Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6:
  [SCSI] a100u2w: fix bitmap lookup routine
  [SCSI] fix media change events for polled devices
  [SCSI] sd, sr: do not emit change event at device add
  [SCSI] mpt fusion: Power Management fixes for MPT SAS PCI-E controllers
  [SCSI] gdth: Allocate sense_buffer to prevent NULL pointer dereference
  [SCSI] arcmsr: fix iounmap error for Type B adapter
  [SCSI] isd200: Allocate sense_buffer for hacked up scsi_cmnd
  [SCSI] fix bsg queue oops with iscsi logout
  [SCSI] Fix dependency problems in SCSI drivers
  [SCSI] advansys: Fix bug in AdvLoadMicrocode
This commit is contained in:
Linus Torvalds 2008-03-20 10:20:07 -07:00
commit d67e91117d
12 changed files with 200 additions and 137 deletions

View File

@ -1430,6 +1430,98 @@ mpt_get_product_name(u16 vendor, u16 device, u8 revision, char *prod_name)
sprintf(prod_name, "%s", product_str);
}
/**
* mpt_mapresources - map in memory mapped io
* @ioc: Pointer to pointer to IOC adapter
*
**/
static int
mpt_mapresources(MPT_ADAPTER *ioc)
{
u8 __iomem *mem;
int ii;
unsigned long mem_phys;
unsigned long port;
u32 msize;
u32 psize;
u8 revision;
int r = -ENODEV;
struct pci_dev *pdev;
pdev = ioc->pcidev;
ioc->bars = pci_select_bars(pdev, IORESOURCE_MEM);
if (pci_enable_device_mem(pdev)) {
printk(MYIOC_s_ERR_FMT "pci_enable_device_mem() "
"failed\n", ioc->name);
return r;
}
if (pci_request_selected_regions(pdev, ioc->bars, "mpt")) {
printk(MYIOC_s_ERR_FMT "pci_request_selected_regions() with "
"MEM failed\n", ioc->name);
return r;
}
pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)
&& !pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK)) {
dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n",
ioc->name));
} else if (!pci_set_dma_mask(pdev, DMA_32BIT_MASK)
&& !pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) {
dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
": 32 BIT PCI BUS DMA ADDRESSING SUPPORTED\n",
ioc->name));
} else {
printk(MYIOC_s_WARN_FMT "no suitable DMA mask for %s\n",
ioc->name, pci_name(pdev));
pci_release_selected_regions(pdev, ioc->bars);
return r;
}
mem_phys = msize = 0;
port = psize = 0;
for (ii = 0; ii < DEVICE_COUNT_RESOURCE; ii++) {
if (pci_resource_flags(pdev, ii) & PCI_BASE_ADDRESS_SPACE_IO) {
if (psize)
continue;
/* Get I/O space! */
port = pci_resource_start(pdev, ii);
psize = pci_resource_len(pdev, ii);
} else {
if (msize)
continue;
/* Get memmap */
mem_phys = pci_resource_start(pdev, ii);
msize = pci_resource_len(pdev, ii);
}
}
ioc->mem_size = msize;
mem = NULL;
/* Get logical ptr for PciMem0 space */
/*mem = ioremap(mem_phys, msize);*/
mem = ioremap(mem_phys, msize);
if (mem == NULL) {
printk(MYIOC_s_ERR_FMT ": ERROR - Unable to map adapter"
" memory!\n", ioc->name);
return -EINVAL;
}
ioc->memmap = mem;
dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "mem = %p, mem_phys = %lx\n",
ioc->name, mem, mem_phys));
ioc->mem_phys = mem_phys;
ioc->chip = (SYSIF_REGS __iomem *)mem;
/* Save Port IO values in case we need to do downloadboot */
ioc->pio_mem_phys = port;
ioc->pio_chip = (SYSIF_REGS __iomem *)port;
return 0;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/**
* mpt_attach - Install a PCI intelligent MPT adapter.
@ -1452,13 +1544,6 @@ int
mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
{
MPT_ADAPTER *ioc;
u8 __iomem *mem;
u8 __iomem *pmem;
unsigned long mem_phys;
unsigned long port;
u32 msize;
u32 psize;
int ii;
u8 cb_idx;
int r = -ENODEV;
u8 revision;
@ -1468,52 +1553,32 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
struct proc_dir_entry *dent, *ent;
#endif
if (mpt_debug_level)
printk(KERN_INFO MYNAM ": mpt_debug_level=%xh\n", mpt_debug_level);
ioc = kzalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC);
if (ioc == NULL) {
printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n");
return -ENOMEM;
}
ioc->debug_level = mpt_debug_level;
ioc->id = mpt_ids++;
sprintf(ioc->name, "ioc%d", ioc->id);
ioc->bars = pci_select_bars(pdev, IORESOURCE_MEM);
if (pci_enable_device_mem(pdev)) {
printk(MYIOC_s_ERR_FMT "pci_enable_device_mem() "
"failed\n", ioc->name);
kfree(ioc);
return r;
}
if (pci_request_selected_regions(pdev, ioc->bars, "mpt")) {
printk(MYIOC_s_ERR_FMT "pci_request_selected_regions() with "
"MEM failed\n", ioc->name);
kfree(ioc);
return r;
}
/*
* set initial debug level
* (refer to mptdebug.h)
*
*/
ioc->debug_level = mpt_debug_level;
if (mpt_debug_level)
printk(KERN_INFO "mpt_debug_level=%xh\n", mpt_debug_level);
dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": mpt_adapter_install\n", ioc->name));
if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
dprintk(ioc, printk(MYIOC_s_INFO_FMT
": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n", ioc->name));
} else if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
printk(MYIOC_s_WARN_FMT ": 32 BIT PCI BUS DMA ADDRESSING NOT SUPPORTED\n",
ioc->name);
ioc->pcidev = pdev;
if (mpt_mapresources(ioc)) {
kfree(ioc);
return r;
}
if (!pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK)) {
dprintk(ioc, printk(MYIOC_s_INFO_FMT
": Using 64 bit consistent mask\n", ioc->name));
} else {
dprintk(ioc, printk(MYIOC_s_INFO_FMT
": Not using 64 bit consistent mask\n", ioc->name));
}
ioc->alloc_total = sizeof(MPT_ADAPTER);
ioc->req_sz = MPT_DEFAULT_FRAME_SIZE; /* avoid div by zero! */
ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
@ -1551,48 +1616,9 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
/* Find lookup slot. */
INIT_LIST_HEAD(&ioc->list);
mem_phys = msize = 0;
port = psize = 0;
for (ii=0; ii < DEVICE_COUNT_RESOURCE; ii++) {
if (pci_resource_flags(pdev, ii) & PCI_BASE_ADDRESS_SPACE_IO) {
if (psize)
continue;
/* Get I/O space! */
port = pci_resource_start(pdev, ii);
psize = pci_resource_len(pdev,ii);
} else {
if (msize)
continue;
/* Get memmap */
mem_phys = pci_resource_start(pdev, ii);
msize = pci_resource_len(pdev,ii);
}
}
ioc->mem_size = msize;
mem = NULL;
/* Get logical ptr for PciMem0 space */
/*mem = ioremap(mem_phys, msize);*/
mem = ioremap(mem_phys, msize);
if (mem == NULL) {
printk(MYIOC_s_ERR_FMT "Unable to map adapter memory!\n", ioc->name);
kfree(ioc);
return -EINVAL;
}
ioc->memmap = mem;
dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "mem = %p, mem_phys = %lx\n", ioc->name, mem, mem_phys));
dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "facts @ %p, pfacts[0] @ %p\n",
ioc->name, &ioc->facts, &ioc->pfacts[0]));
ioc->mem_phys = mem_phys;
ioc->chip = (SYSIF_REGS __iomem *)mem;
/* Save Port IO values in case we need to do downloadboot */
ioc->pio_mem_phys = port;
pmem = (u8 __iomem *)port;
ioc->pio_chip = (SYSIF_REGS __iomem *)pmem;
pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
mpt_get_product_name(pdev->vendor, pdev->device, revision, ioc->prod_name);
@ -1688,7 +1714,9 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
list_del(&ioc->list);
if (ioc->alt_ioc)
ioc->alt_ioc->alt_ioc = NULL;
iounmap(mem);
iounmap(ioc->memmap);
if (r != -5)
pci_release_selected_regions(pdev, ioc->bars);
kfree(ioc);
pci_set_drvdata(pdev, NULL);
return r;
@ -1784,13 +1812,10 @@ mpt_suspend(struct pci_dev *pdev, pm_message_t state)
u32 device_state;
MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
device_state=pci_choose_state(pdev, state);
printk(MYIOC_s_INFO_FMT
"pci-suspend: pdev=0x%p, slot=%s, Entering operating state [D%d]\n",
ioc->name, pdev, pci_name(pdev), device_state);
pci_save_state(pdev);
device_state = pci_choose_state(pdev, state);
printk(MYIOC_s_INFO_FMT "pci-suspend: pdev=0x%p, slot=%s, Entering "
"operating state [D%d]\n", ioc->name, pdev, pci_name(pdev),
device_state);
/* put ioc into READY_STATE */
if(SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, CAN_SLEEP)) {
@ -1805,10 +1830,14 @@ mpt_suspend(struct pci_dev *pdev, pm_message_t state)
/* Clear any lingering interrupt */
CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
free_irq(ioc->pci_irq, ioc);
if (mpt_msi_enable)
pci_disable_msi(ioc->pcidev);
ioc->pci_irq = -1;
pci_save_state(pdev);
pci_disable_device(pdev);
pci_release_selected_regions(pdev, ioc->bars);
pci_set_power_state(pdev, device_state);
return 0;
}
@ -1823,48 +1852,54 @@ mpt_resume(struct pci_dev *pdev)
MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
u32 device_state = pdev->current_state;
int recovery_state;
int err;
printk(MYIOC_s_INFO_FMT
"pci-resume: pdev=0x%p, slot=%s, Previous operating state [D%d]\n",
ioc->name, pdev, pci_name(pdev), device_state);
printk(MYIOC_s_INFO_FMT "pci-resume: pdev=0x%p, slot=%s, Previous "
"operating state [D%d]\n", ioc->name, pdev, pci_name(pdev),
device_state);
pci_set_power_state(pdev, 0);
pci_set_power_state(pdev, PCI_D0);
pci_enable_wake(pdev, PCI_D0, 0);
pci_restore_state(pdev);
if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT) {
ioc->bars = pci_select_bars(ioc->pcidev, IORESOURCE_MEM |
IORESOURCE_IO);
if (pci_enable_device(pdev))
return 0;
} else {
ioc->bars = pci_select_bars(pdev, IORESOURCE_MEM);
if (pci_enable_device_mem(pdev))
return 0;
ioc->pcidev = pdev;
err = mpt_mapresources(ioc);
if (err)
return err;
printk(MYIOC_s_INFO_FMT "pci-resume: ioc-state=0x%x,doorbell=0x%x\n",
ioc->name, (mpt_GetIocState(ioc, 1) >> MPI_IOC_STATE_SHIFT),
CHIPREG_READ32(&ioc->chip->Doorbell));
/*
* Errata workaround for SAS pci express:
* Upon returning to the D0 state, the contents of the doorbell will be
* stale data, and this will incorrectly signal to the host driver that
* the firmware is ready to process mpt commands. The workaround is
* to issue a diagnostic reset.
*/
if (ioc->bus_type == SAS && (pdev->device ==
MPI_MANUFACTPAGE_DEVID_SAS1068E || pdev->device ==
MPI_MANUFACTPAGE_DEVID_SAS1064E)) {
if (KickStart(ioc, 1, CAN_SLEEP) < 0) {
printk(MYIOC_s_WARN_FMT "pci-resume: Cannot recover\n",
ioc->name);
goto out;
}
}
if (pci_request_selected_regions(pdev, ioc->bars, "mpt"))
return 0;
/* enable interrupts */
CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
ioc->active = 1;
printk(MYIOC_s_INFO_FMT
"pci-resume: ioc-state=0x%x,doorbell=0x%x\n",
ioc->name,
(mpt_GetIocState(ioc, 1) >> MPI_IOC_STATE_SHIFT),
CHIPREG_READ32(&ioc->chip->Doorbell));
/* bring ioc to operational state */
if ((recovery_state = mpt_do_ioc_recovery(ioc,
MPT_HOSTEVENT_IOC_RECOVER, CAN_SLEEP)) != 0) {
printk(MYIOC_s_INFO_FMT "Sending mpt_do_ioc_recovery\n", ioc->name);
recovery_state = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP,
CAN_SLEEP);
if (recovery_state != 0)
printk(MYIOC_s_WARN_FMT "pci-resume: Cannot recover, "
"error:[%x]\n", ioc->name, recovery_state);
else
printk(MYIOC_s_INFO_FMT
"pci-resume: Cannot recover, error:[%x]\n",
ioc->name, recovery_state);
} else {
printk(MYIOC_s_INFO_FMT
"pci-resume: success\n", ioc->name);
}
"pci-resume: success\n", ioc->name);
out:
return 0;
}
#endif
@ -1903,6 +1938,7 @@ mpt_signal_reset(u8 index, MPT_ADAPTER *ioc, int reset_phase)
* -3 if READY but PrimeIOCFifos Failed
* -4 if READY but IOCInit Failed
* -5 if failed to enable_device and/or request_selected_regions
* -6 if failed to upload firmware
*/
static int
mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
@ -2097,7 +2133,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
} else {
printk(MYIOC_s_WARN_FMT
"firmware upload failure!\n", ioc->name);
ret = -5;
ret = -6;
}
}
}

View File

@ -1170,6 +1170,10 @@ mptscsih_shutdown(struct pci_dev *pdev)
int
mptscsih_suspend(struct pci_dev *pdev, pm_message_t state)
{
MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
scsi_block_requests(ioc->sh);
flush_scheduled_work();
mptscsih_shutdown(pdev);
return mpt_suspend(pdev,state);
}
@ -1183,7 +1187,12 @@ mptscsih_suspend(struct pci_dev *pdev, pm_message_t state)
int
mptscsih_resume(struct pci_dev *pdev)
{
return mpt_resume(pdev);
MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
int rc;
rc = mpt_resume(pdev);
scsi_unblock_requests(ioc->sh);
return rc;
}
#endif

View File

@ -325,7 +325,7 @@ menuconfig SCSI_LOWLEVEL
depends on SCSI!=n
default y
if SCSI_LOWLEVEL
if SCSI_LOWLEVEL && SCSI
config ISCSI_TCP
tristate "iSCSI Initiator over TCP/IP"

View File

@ -674,12 +674,13 @@ static struct orc_scb *__orc_alloc_scb(struct orc_host * host)
for (index = 0; index < 32; index++) {
if ((host->allocation_map[channel][i] >> index) & 0x01) {
host->allocation_map[channel][i] &= ~(1 << index);
break;
idx = index + 32 * i;
/*
* Translate the index to a structure instance
*/
return host->scb_virt + idx;
}
}
idx = index + 32 * i;
/* Translate the index to a structure instance */
return (struct orc_scb *) ((unsigned long) host->scb_virt + (idx * sizeof(struct orc_scb)));
}
return NULL;
}

View File

@ -6439,7 +6439,7 @@ static int AdvLoadMicrocode(AdvPortAddr iop_base, unsigned char *buf, int size,
i += 2;
len += 2;
} else {
unsigned char off = buf[i] * 2;
unsigned int off = buf[i] * 2;
unsigned short word = (buf[off + 1] << 8) | buf[off];
AdvWriteWordAutoIncLram(iop_base, word);
len += 2;

View File

@ -341,13 +341,13 @@ struct MessageUnit_B
uint32_t done_qbuffer[ARCMSR_MAX_HBB_POSTQUEUE];
uint32_t postq_index;
uint32_t doneq_index;
uint32_t __iomem *drv2iop_doorbell_reg;
uint32_t __iomem *drv2iop_doorbell_mask_reg;
uint32_t __iomem *iop2drv_doorbell_reg;
uint32_t __iomem *iop2drv_doorbell_mask_reg;
uint32_t __iomem *msgcode_rwbuffer_reg;
uint32_t __iomem *ioctl_wbuffer_reg;
uint32_t __iomem *ioctl_rbuffer_reg;
void __iomem *drv2iop_doorbell_reg;
void __iomem *drv2iop_doorbell_mask_reg;
void __iomem *iop2drv_doorbell_reg;
void __iomem *iop2drv_doorbell_mask_reg;
void __iomem *msgcode_rwbuffer_reg;
void __iomem *ioctl_wbuffer_reg;
void __iomem *ioctl_rbuffer_reg;
};
/*

View File

@ -493,6 +493,12 @@ int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd, char *cmnd,
if (!scp)
return -ENOMEM;
scp->sense_buffer = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL);
if (!scp->sense_buffer) {
kfree(scp);
return -ENOMEM;
}
scp->device = sdev;
memset(&cmndinfo, 0, sizeof(cmndinfo));
@ -513,6 +519,7 @@ int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd, char *cmnd,
rval = cmndinfo.status;
if (info)
*info = cmndinfo.info;
kfree(scp->sense_buffer);
kfree(scp);
return rval;
}

View File

@ -2162,10 +2162,15 @@ void sdev_evt_send(struct scsi_device *sdev, struct scsi_event *evt)
{
unsigned long flags;
#if 0
/* FIXME: currently this check eliminates all media change events
* for polled devices. Need to update to discriminate between AN
* and polled events */
if (!test_bit(evt->evt_type, sdev->supported_events)) {
kfree(evt);
return;
}
#endif
spin_lock_irqsave(&sdev->list_lock, flags);
list_add_tail(&evt->node, &sdev->event_list);

View File

@ -294,6 +294,7 @@ static void scsi_device_dev_release_usercontext(struct work_struct *work)
}
if (sdev->request_queue) {
bsg_unregister_queue(sdev->request_queue);
sdev->request_queue->queuedata = NULL;
/* user context needed to free queue */
scsi_free_queue(sdev->request_queue);
@ -857,7 +858,6 @@ void __scsi_remove_device(struct scsi_device *sdev)
if (scsi_device_set_state(sdev, SDEV_CANCEL) != 0)
return;
bsg_unregister_queue(sdev->request_queue);
class_device_unregister(&sdev->sdev_classdev);
transport_remove_device(dev);
device_del(dev);

View File

@ -1654,6 +1654,7 @@ static int sd_probe(struct device *dev)
sdkp->disk = gd;
sdkp->index = index;
sdkp->openers = 0;
sdkp->previous_state = 1;
if (!sdp->timeout) {
if (sdp->type != TYPE_MOD)

View File

@ -623,6 +623,7 @@ static int sr_probe(struct device *dev)
cd->disk = disk;
cd->capacity = 0x1fffff;
cd->device->changed = 1; /* force recheck CD type */
cd->previous_state = 1;
cd->use = 1;
cd->readcd_known = 0;
cd->readcd_cdda = 0;

View File

@ -1469,6 +1469,7 @@ static void isd200_free_info_ptrs(void *info_)
if (info) {
kfree(info->id);
kfree(info->RegsBuf);
kfree(info->srb.sense_buffer);
}
}
@ -1494,7 +1495,9 @@ static int isd200_init_info(struct us_data *us)
kzalloc(sizeof(struct hd_driveid), GFP_KERNEL);
info->RegsBuf = (unsigned char *)
kmalloc(sizeof(info->ATARegs), GFP_KERNEL);
if (!info->id || !info->RegsBuf) {
info->srb.sense_buffer =
kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL);
if (!info->id || !info->RegsBuf || !info->srb.sense_buffer) {
isd200_free_info_ptrs(info);
kfree(info);
retStatus = ISD200_ERROR;