diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-02-03 22:26:39 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-02-03 22:26:39 +0300 |
commit | ce35a81a71f405031ed6fd0d454d3aaa55dc8ed2 (patch) | |
tree | ba67cda811c798970ed89786f2e4a60618cb0975 | |
parent | 259886a7c4e4eb0089181e800d1f477cb3786875 (diff) | |
parent | 017f2e37ae19ccd28e5edd965741fc374194c5dd (diff) | |
download | linux-ce35a81a71f405031ed6fd0d454d3aaa55dc8ed2.tar.xz |
Merge master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6:
[SCSI] sd: udev accessing an uninitialized scsi_disk field results in a crash
[SCSI] st: A MTIOCTOP/MTWEOF within the early warning will cause the file number to be incorrect
[SCSI] qla4xxx: bug fixes
[SCSI] Fix scsi_add_device() for async scanning
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_def.h | 1 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_glbl.h | 1 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_init.c | 18 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_isr.c | 4 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_mbx.c | 35 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_os.c | 64 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_version.h | 2 | ||||
-rw-r--r-- | drivers/scsi/scsi_scan.c | 6 | ||||
-rw-r--r-- | drivers/scsi/sd.c | 20 | ||||
-rw-r--r-- | drivers/scsi/st.c | 19 |
10 files changed, 100 insertions, 70 deletions
diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h index 4249e52a5592..6f4cf2dd2f4a 100644 --- a/drivers/scsi/qla4xxx/ql4_def.h +++ b/drivers/scsi/qla4xxx/ql4_def.h @@ -418,7 +418,6 @@ struct scsi_qla_host { * concurrently. */ struct mutex mbox_sem; - wait_queue_head_t mailbox_wait_queue; /* temporary mailbox status registers */ volatile uint8_t mbox_status_count; diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h index 2122967bbf0b..e021eb5db2b2 100644 --- a/drivers/scsi/qla4xxx/ql4_glbl.h +++ b/drivers/scsi/qla4xxx/ql4_glbl.h @@ -76,4 +76,5 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host * ha, extern int ql4xextended_error_logging; extern int ql4xdiscoverywait; extern int ql4xdontresethba; +extern int ql4_mod_unload; #endif /* _QLA4x_GBL_H */ diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c index cc210f297a78..b907b06d72ab 100644 --- a/drivers/scsi/qla4xxx/ql4_init.c +++ b/drivers/scsi/qla4xxx/ql4_init.c @@ -958,25 +958,25 @@ static int qla4xxx_start_firmware_from_flash(struct scsi_qla_host *ha) return status; } -int ql4xxx_lock_drvr_wait(struct scsi_qla_host *a) +int ql4xxx_lock_drvr_wait(struct scsi_qla_host *ha) { -#define QL4_LOCK_DRVR_WAIT 300 -#define QL4_LOCK_DRVR_SLEEP 100 +#define QL4_LOCK_DRVR_WAIT 30 +#define QL4_LOCK_DRVR_SLEEP 1 int drvr_wait = QL4_LOCK_DRVR_WAIT; while (drvr_wait) { - if (ql4xxx_lock_drvr(a) == 0) { - msleep(QL4_LOCK_DRVR_SLEEP); + if (ql4xxx_lock_drvr(ha) == 0) { + ssleep(QL4_LOCK_DRVR_SLEEP); if (drvr_wait) { DEBUG2(printk("scsi%ld: %s: Waiting for " - "Global Init Semaphore...n", - a->host_no, - __func__)); + "Global Init Semaphore(%d)...n", + ha->host_no, + __func__, drvr_wait)); } drvr_wait -= QL4_LOCK_DRVR_SLEEP; } else { DEBUG2(printk("scsi%ld: %s: Global Init Semaphore " - "acquired.n", a->host_no, __func__)); + "acquired.n", ha->host_no, __func__)); return QLA_SUCCESS; } } diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c index ef975e0dc87f..35b9e36a0e8d 100644 --- a/drivers/scsi/qla4xxx/ql4_isr.c +++ b/drivers/scsi/qla4xxx/ql4_isr.c @@ -433,7 +433,6 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, readl(&ha->reg->mailbox[i]); set_bit(AF_MBOX_COMMAND_DONE, &ha->flags); - wake_up(&ha->mailbox_wait_queue); } } else if (mbox_status >> 12 == MBOX_ASYNC_EVENT_STATUS) { /* Immediately process the AENs that don't require much work. @@ -686,7 +685,8 @@ irqreturn_t qla4xxx_intr_handler(int irq, void *dev_id) &ha->reg->ctrl_status); readl(&ha->reg->ctrl_status); - set_bit(DPC_RESET_HA_INTR, &ha->dpc_flags); + if (!ql4_mod_unload) + set_bit(DPC_RESET_HA_INTR, &ha->dpc_flags); break; } else if (intr_status & INTR_PENDING) { diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c index b721dc5dd711..7f28657eef3f 100644 --- a/drivers/scsi/qla4xxx/ql4_mbx.c +++ b/drivers/scsi/qla4xxx/ql4_mbx.c @@ -29,18 +29,30 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, u_long wait_count; uint32_t intr_status; unsigned long flags = 0; - DECLARE_WAITQUEUE(wait, current); - - mutex_lock(&ha->mbox_sem); - - /* Mailbox code active */ - set_bit(AF_MBOX_COMMAND, &ha->flags); /* Make sure that pointers are valid */ if (!mbx_cmd || !mbx_sts) { DEBUG2(printk("scsi%ld: %s: Invalid mbx_cmd or mbx_sts " "pointer\n", ha->host_no, __func__)); - goto mbox_exit; + return status; + } + /* Mailbox code active */ + wait_count = MBOX_TOV * 100; + + while (wait_count--) { + mutex_lock(&ha->mbox_sem); + if (!test_bit(AF_MBOX_COMMAND, &ha->flags)) { + set_bit(AF_MBOX_COMMAND, &ha->flags); + mutex_unlock(&ha->mbox_sem); + break; + } + mutex_unlock(&ha->mbox_sem); + if (!wait_count) { + DEBUG2(printk("scsi%ld: %s: mbox_sem failed\n", + ha->host_no, __func__)); + return status; + } + msleep(10); } /* To prevent overwriting mailbox registers for a command that has @@ -73,8 +85,6 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, spin_unlock_irqrestore(&ha->hardware_lock, flags); /* Wait for completion */ - set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&ha->mailbox_wait_queue, &wait); /* * If we don't want status, don't wait for the mailbox command to @@ -83,8 +93,6 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, */ if (outCount == 0) { status = QLA_SUCCESS; - set_current_state(TASK_RUNNING); - remove_wait_queue(&ha->mailbox_wait_queue, &wait); goto mbox_exit; } /* Wait for command to complete */ @@ -108,8 +116,6 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, spin_unlock_irqrestore(&ha->hardware_lock, flags); msleep(10); } - set_current_state(TASK_RUNNING); - remove_wait_queue(&ha->mailbox_wait_queue, &wait); /* Check for mailbox timeout. */ if (!test_bit(AF_MBOX_COMMAND_DONE, &ha->flags)) { @@ -155,9 +161,10 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, spin_unlock_irqrestore(&ha->hardware_lock, flags); mbox_exit: + mutex_lock(&ha->mbox_sem); clear_bit(AF_MBOX_COMMAND, &ha->flags); - clear_bit(AF_MBOX_COMMAND_DONE, &ha->flags); mutex_unlock(&ha->mbox_sem); + clear_bit(AF_MBOX_COMMAND_DONE, &ha->flags); return status; } diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 9ef693c8809a..81fb7bd44f01 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -40,6 +40,8 @@ MODULE_PARM_DESC(ql4xextended_error_logging, "Option to enable extended error logging, " "Default is 0 - no logging, 1 - debug logging"); +int ql4_mod_unload = 0; + /* * SCSI host template entry points */ @@ -422,6 +424,9 @@ static int qla4xxx_queuecommand(struct scsi_cmnd *cmd, goto qc_host_busy; } + if (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) + goto qc_host_busy; + spin_unlock_irq(ha->host->host_lock); srb = qla4xxx_get_new_srb(ha, ddb_entry, cmd, done); @@ -707,16 +712,12 @@ static int qla4xxx_cmd_wait(struct scsi_qla_host *ha) return stat; } -/** - * qla4xxx_soft_reset - performs soft reset. - * @ha: Pointer to host adapter structure. - **/ -int qla4xxx_soft_reset(struct scsi_qla_host *ha) +static void qla4xxx_hw_reset(struct scsi_qla_host *ha) { - uint32_t max_wait_time; - unsigned long flags = 0; - int status = QLA_ERROR; uint32_t ctrl_status; + unsigned long flags = 0; + + DEBUG2(printk(KERN_ERR "scsi%ld: %s\n", ha->host_no, __func__)); spin_lock_irqsave(&ha->hardware_lock, flags); @@ -733,6 +734,20 @@ int qla4xxx_soft_reset(struct scsi_qla_host *ha) readl(&ha->reg->ctrl_status); spin_unlock_irqrestore(&ha->hardware_lock, flags); +} + +/** + * qla4xxx_soft_reset - performs soft reset. + * @ha: Pointer to host adapter structure. + **/ +int qla4xxx_soft_reset(struct scsi_qla_host *ha) +{ + uint32_t max_wait_time; + unsigned long flags = 0; + int status = QLA_ERROR; + uint32_t ctrl_status; + + qla4xxx_hw_reset(ha); /* Wait until the Network Reset Intr bit is cleared */ max_wait_time = RESET_INTR_TOV; @@ -966,10 +981,12 @@ static void qla4xxx_do_dpc(struct work_struct *work) struct scsi_qla_host *ha = container_of(work, struct scsi_qla_host, dpc_work); struct ddb_entry *ddb_entry, *dtemp; + int status = QLA_ERROR; DEBUG2(printk("scsi%ld: %s: DPC handler waking up." - "flags = 0x%08lx, dpc_flags = 0x%08lx\n", - ha->host_no, __func__, ha->flags, ha->dpc_flags)); + "flags = 0x%08lx, dpc_flags = 0x%08lx ctrl_stat = 0x%08x\n", + ha->host_no, __func__, ha->flags, ha->dpc_flags, + readw(&ha->reg->ctrl_status))); /* Initialization not yet finished. Don't do anything yet. */ if (!test_bit(AF_INIT_DONE, &ha->flags)) @@ -983,31 +1000,28 @@ static void qla4xxx_do_dpc(struct work_struct *work) test_bit(DPC_RESET_HA, &ha->dpc_flags)) qla4xxx_recover_adapter(ha, PRESERVE_DDB_LIST); - if (test_and_clear_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) { + if (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) { uint8_t wait_time = RESET_INTR_TOV; - unsigned long flags = 0; - - qla4xxx_flush_active_srbs(ha); - spin_lock_irqsave(&ha->hardware_lock, flags); while ((readw(&ha->reg->ctrl_status) & (CSR_SOFT_RESET | CSR_FORCE_SOFT_RESET)) != 0) { if (--wait_time == 0) break; - - spin_unlock_irqrestore(&ha->hardware_lock, - flags); - msleep(1000); - - spin_lock_irqsave(&ha->hardware_lock, flags); } - spin_unlock_irqrestore(&ha->hardware_lock, flags); - if (wait_time == 0) DEBUG2(printk("scsi%ld: %s: SR|FSR " "bit not cleared-- resetting\n", ha->host_no, __func__)); + qla4xxx_flush_active_srbs(ha); + if (ql4xxx_lock_drvr_wait(ha) == QLA_SUCCESS) { + qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS); + status = qla4xxx_initialize_adapter(ha, + PRESERVE_DDB_LIST); + } + clear_bit(DPC_RESET_HA_INTR, &ha->dpc_flags); + if (status == QLA_SUCCESS) + qla4xxx_enable_intrs(ha); } } @@ -1062,7 +1076,7 @@ static void qla4xxx_free_adapter(struct scsi_qla_host *ha) /* Issue Soft Reset to put firmware in unknown state */ if (ql4xxx_lock_drvr_wait(ha) == QLA_SUCCESS) - qla4xxx_soft_reset(ha); + qla4xxx_hw_reset(ha); /* Remove timer thread, if present */ if (ha->timer_active) @@ -1198,7 +1212,6 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, INIT_LIST_HEAD(&ha->free_srb_q); mutex_init(&ha->mbox_sem); - init_waitqueue_head(&ha->mailbox_wait_queue); spin_lock_init(&ha->hardware_lock); @@ -1665,6 +1678,7 @@ no_srp_cache: static void __exit qla4xxx_module_exit(void) { + ql4_mod_unload = 1; pci_unregister_driver(&qla4xxx_pci_driver); iscsi_unregister_transport(&qla4xxx_iscsi_transport); kmem_cache_destroy(srb_cachep); diff --git a/drivers/scsi/qla4xxx/ql4_version.h b/drivers/scsi/qla4xxx/ql4_version.h index 454e19c8ad68..e5183a697d1f 100644 --- a/drivers/scsi/qla4xxx/ql4_version.h +++ b/drivers/scsi/qla4xxx/ql4_version.h @@ -5,4 +5,4 @@ * See LICENSE.qla4xxx for copyright and licensing details. */ -#define QLA4XXX_DRIVER_VERSION "5.00.07-k" +#define QLA4XXX_DRIVER_VERSION "5.00.07-k1" diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index b83d03c4deef..96b7cbd746a8 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -1453,6 +1453,12 @@ struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel, struct device *parent = &shost->shost_gendev; struct scsi_target *starget; + if (strncmp(scsi_scan_type, "none", 4) == 0) + return ERR_PTR(-ENODEV); + + if (!shost->async_scan) + scsi_complete_async_scans(); + starget = scsi_alloc_target(parent, channel, id); if (!starget) return ERR_PTR(-ENOMEM); diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 978bfc1e0c6a..b781a90d6699 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1647,16 +1647,6 @@ static int sd_probe(struct device *dev) if (error) goto out_put; - class_device_initialize(&sdkp->cdev); - sdkp->cdev.dev = &sdp->sdev_gendev; - sdkp->cdev.class = &sd_disk_class; - strncpy(sdkp->cdev.class_id, sdp->sdev_gendev.bus_id, BUS_ID_SIZE); - - if (class_device_add(&sdkp->cdev)) - goto out_put; - - get_device(&sdp->sdev_gendev); - sdkp->device = sdp; sdkp->driver = &sd_template; sdkp->disk = gd; @@ -1670,6 +1660,16 @@ static int sd_probe(struct device *dev) sdp->timeout = SD_MOD_TIMEOUT; } + class_device_initialize(&sdkp->cdev); + sdkp->cdev.dev = &sdp->sdev_gendev; + sdkp->cdev.class = &sd_disk_class; + strncpy(sdkp->cdev.class_id, sdp->sdev_gendev.bus_id, BUS_ID_SIZE); + + if (class_device_add(&sdkp->cdev)) + goto out_put; + + get_device(&sdp->sdev_gendev); + gd->major = sd_major((index & 0xf0) >> 4); gd->first_minor = ((index & 0xf) << 4) | (index & 0xfff00); gd->minors = 16; diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index e016e0906e1a..488ec7948a57 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -2816,15 +2816,18 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon if (cmd_in == MTWEOF && cmdstatp->have_sense && - (cmdstatp->flags & SENSE_EOM) && - (cmdstatp->sense_hdr.sense_key == NO_SENSE || - cmdstatp->sense_hdr.sense_key == RECOVERED_ERROR) && - undone == 0) { - ioctl_result = 0; /* EOF written successfully at EOM */ - if (fileno >= 0) - fileno++; + (cmdstatp->flags & SENSE_EOM)) { + if (cmdstatp->sense_hdr.sense_key == NO_SENSE || + cmdstatp->sense_hdr.sense_key == RECOVERED_ERROR) { + ioctl_result = 0; /* EOF(s) written successfully at EOM */ + STps->eof = ST_NOEOF; + } else { /* Writing EOF(s) failed */ + if (fileno >= 0) + fileno -= undone; + if (undone < arg) + STps->eof = ST_NOEOF; + } STps->drv_file = fileno; - STps->eof = ST_NOEOF; } else if ((cmd_in == MTFSF) || (cmd_in == MTFSFM)) { if (fileno >= 0) STps->drv_file = fileno - undone; |