diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-28 21:09:34 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-28 21:09:34 -0400 |
commit | 561d9e8185883a8d0788cb15090873d4f13323f5 (patch) | |
tree | 7fd14e77967c9858ddb906686916156b506feae7 | |
parent | 6c504ecf506705a6575541b28824e13090bd223b (diff) | |
parent | e1be09808e030d57bb743618eb41e2bc31dd464c (diff) |
Merge tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull SCSI fixes from James Bottomley:
"This is five bug fixes, two of which fix long standing problems
causing crashes (sd and mvsas). The remaining three are hung (isci
race) or lost (qla2xxx, isci) devices"
* tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi:
[SCSI] isci: fix breakage caused by >16byte CDB patch
[SCSI] mvsas: Fix kernel panic on tile due to unaligned data access
[SCSI] sd: fix crash when UA received on DIF enabled device
[SCSI] qla2xxx: Properly set the tagging for commands.
[SCSI] isci: Fix a race condition in the SSP task management path
-rw-r--r-- | drivers/scsi/isci/request.c | 2 | ||||
-rw-r--r-- | drivers/scsi/isci/task.c | 9 | ||||
-rw-r--r-- | drivers/scsi/mvsas/mv_sas.c | 11 | ||||
-rw-r--r-- | drivers/scsi/mvsas/mv_sas.h | 1 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_iocb.c | 11 | ||||
-rw-r--r-- | drivers/scsi/sd.c | 22 |
6 files changed, 32 insertions, 24 deletions
diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 7b082157eb79..99d2930b18c8 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c | |||
@@ -185,7 +185,7 @@ static void sci_io_request_build_ssp_command_iu(struct isci_request *ireq) | |||
185 | cmd_iu->_r_c = 0; | 185 | cmd_iu->_r_c = 0; |
186 | 186 | ||
187 | sci_swab32_cpy(&cmd_iu->cdb, task->ssp_task.cmd->cmnd, | 187 | sci_swab32_cpy(&cmd_iu->cdb, task->ssp_task.cmd->cmnd, |
188 | task->ssp_task.cmd->cmd_len / sizeof(u32)); | 188 | (task->ssp_task.cmd->cmd_len+3) / sizeof(u32)); |
189 | } | 189 | } |
190 | 190 | ||
191 | static void sci_task_request_build_ssp_task_iu(struct isci_request *ireq) | 191 | static void sci_task_request_build_ssp_task_iu(struct isci_request *ireq) |
diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index 9bb020ac089c..0d30ca849e8f 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c | |||
@@ -491,6 +491,7 @@ int isci_task_abort_task(struct sas_task *task) | |||
491 | struct isci_tmf tmf; | 491 | struct isci_tmf tmf; |
492 | int ret = TMF_RESP_FUNC_FAILED; | 492 | int ret = TMF_RESP_FUNC_FAILED; |
493 | unsigned long flags; | 493 | unsigned long flags; |
494 | int target_done_already = 0; | ||
494 | 495 | ||
495 | /* Get the isci_request reference from the task. Note that | 496 | /* Get the isci_request reference from the task. Note that |
496 | * this check does not depend on the pending request list | 497 | * this check does not depend on the pending request list |
@@ -505,9 +506,11 @@ int isci_task_abort_task(struct sas_task *task) | |||
505 | /* If task is already done, the request isn't valid */ | 506 | /* If task is already done, the request isn't valid */ |
506 | if (!(task->task_state_flags & SAS_TASK_STATE_DONE) && | 507 | if (!(task->task_state_flags & SAS_TASK_STATE_DONE) && |
507 | (task->task_state_flags & SAS_TASK_AT_INITIATOR) && | 508 | (task->task_state_flags & SAS_TASK_AT_INITIATOR) && |
508 | old_request) | 509 | old_request) { |
509 | idev = isci_get_device(task->dev->lldd_dev); | 510 | idev = isci_get_device(task->dev->lldd_dev); |
510 | 511 | target_done_already = test_bit(IREQ_COMPLETE_IN_TARGET, | |
512 | &old_request->flags); | ||
513 | } | ||
511 | spin_unlock(&task->task_state_lock); | 514 | spin_unlock(&task->task_state_lock); |
512 | spin_unlock_irqrestore(&ihost->scic_lock, flags); | 515 | spin_unlock_irqrestore(&ihost->scic_lock, flags); |
513 | 516 | ||
@@ -561,7 +564,7 @@ int isci_task_abort_task(struct sas_task *task) | |||
561 | 564 | ||
562 | if (task->task_proto == SAS_PROTOCOL_SMP || | 565 | if (task->task_proto == SAS_PROTOCOL_SMP || |
563 | sas_protocol_ata(task->task_proto) || | 566 | sas_protocol_ata(task->task_proto) || |
564 | test_bit(IREQ_COMPLETE_IN_TARGET, &old_request->flags) || | 567 | target_done_already || |
565 | test_bit(IDEV_GONE, &idev->flags)) { | 568 | test_bit(IDEV_GONE, &idev->flags)) { |
566 | 569 | ||
567 | spin_unlock_irqrestore(&ihost->scic_lock, flags); | 570 | spin_unlock_irqrestore(&ihost->scic_lock, flags); |
diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c index f14665a6293d..6b1b4e91e53f 100644 --- a/drivers/scsi/mvsas/mv_sas.c +++ b/drivers/scsi/mvsas/mv_sas.c | |||
@@ -1857,11 +1857,16 @@ int mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc, u32 flags) | |||
1857 | goto out; | 1857 | goto out; |
1858 | } | 1858 | } |
1859 | 1859 | ||
1860 | /* error info record present */ | 1860 | /* |
1861 | if (unlikely((rx_desc & RXQ_ERR) && (*(u64 *) slot->response))) { | 1861 | * error info record present; slot->response is 32 bit aligned but may |
1862 | * not be 64 bit aligned, so check for zero in two 32 bit reads | ||
1863 | */ | ||
1864 | if (unlikely((rx_desc & RXQ_ERR) | ||
1865 | && (*((u32 *)slot->response) | ||
1866 | || *(((u32 *)slot->response) + 1)))) { | ||
1862 | mv_dprintk("port %d slot %d rx_desc %X has error info" | 1867 | mv_dprintk("port %d slot %d rx_desc %X has error info" |
1863 | "%016llX.\n", slot->port->sas_port.id, slot_idx, | 1868 | "%016llX.\n", slot->port->sas_port.id, slot_idx, |
1864 | rx_desc, (u64)(*(u64 *)slot->response)); | 1869 | rx_desc, get_unaligned_le64(slot->response)); |
1865 | tstat->stat = mvs_slot_err(mvi, task, slot_idx); | 1870 | tstat->stat = mvs_slot_err(mvi, task, slot_idx); |
1866 | tstat->resp = SAS_TASK_COMPLETE; | 1871 | tstat->resp = SAS_TASK_COMPLETE; |
1867 | goto out; | 1872 | goto out; |
diff --git a/drivers/scsi/mvsas/mv_sas.h b/drivers/scsi/mvsas/mv_sas.h index 60e2fb7f2dca..d6b19dc80bee 100644 --- a/drivers/scsi/mvsas/mv_sas.h +++ b/drivers/scsi/mvsas/mv_sas.h | |||
@@ -39,6 +39,7 @@ | |||
39 | #include <linux/irq.h> | 39 | #include <linux/irq.h> |
40 | #include <linux/slab.h> | 40 | #include <linux/slab.h> |
41 | #include <linux/vmalloc.h> | 41 | #include <linux/vmalloc.h> |
42 | #include <asm/unaligned.h> | ||
42 | #include <scsi/libsas.h> | 43 | #include <scsi/libsas.h> |
43 | #include <scsi/scsi.h> | 44 | #include <scsi/scsi.h> |
44 | #include <scsi/scsi_tcq.h> | 45 | #include <scsi/scsi_tcq.h> |
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 42ef481db942..ef0a5481b9dd 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c | |||
@@ -419,6 +419,8 @@ qla2x00_start_scsi(srb_t *sp) | |||
419 | __constant_cpu_to_le16(CF_SIMPLE_TAG); | 419 | __constant_cpu_to_le16(CF_SIMPLE_TAG); |
420 | break; | 420 | break; |
421 | } | 421 | } |
422 | } else { | ||
423 | cmd_pkt->control_flags = __constant_cpu_to_le16(CF_SIMPLE_TAG); | ||
422 | } | 424 | } |
423 | 425 | ||
424 | /* Load SCSI command packet. */ | 426 | /* Load SCSI command packet. */ |
@@ -1307,11 +1309,11 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, | |||
1307 | fcp_cmnd->task_attribute = TSK_ORDERED; | 1309 | fcp_cmnd->task_attribute = TSK_ORDERED; |
1308 | break; | 1310 | break; |
1309 | default: | 1311 | default: |
1310 | fcp_cmnd->task_attribute = 0; | 1312 | fcp_cmnd->task_attribute = TSK_SIMPLE; |
1311 | break; | 1313 | break; |
1312 | } | 1314 | } |
1313 | } else { | 1315 | } else { |
1314 | fcp_cmnd->task_attribute = 0; | 1316 | fcp_cmnd->task_attribute = TSK_SIMPLE; |
1315 | } | 1317 | } |
1316 | 1318 | ||
1317 | cmd_pkt->fcp_rsp_dseg_len = 0; /* Let response come in status iocb */ | 1319 | cmd_pkt->fcp_rsp_dseg_len = 0; /* Let response come in status iocb */ |
@@ -1525,7 +1527,12 @@ qla24xx_start_scsi(srb_t *sp) | |||
1525 | case ORDERED_QUEUE_TAG: | 1527 | case ORDERED_QUEUE_TAG: |
1526 | cmd_pkt->task = TSK_ORDERED; | 1528 | cmd_pkt->task = TSK_ORDERED; |
1527 | break; | 1529 | break; |
1530 | default: | ||
1531 | cmd_pkt->task = TSK_SIMPLE; | ||
1532 | break; | ||
1528 | } | 1533 | } |
1534 | } else { | ||
1535 | cmd_pkt->task = TSK_SIMPLE; | ||
1529 | } | 1536 | } |
1530 | 1537 | ||
1531 | /* Load SCSI command packet. */ | 1538 | /* Load SCSI command packet. */ |
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 80f39b8b0223..86fcf2c313ad 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
@@ -838,10 +838,17 @@ static int scsi_setup_flush_cmnd(struct scsi_device *sdp, struct request *rq) | |||
838 | 838 | ||
839 | static void sd_unprep_fn(struct request_queue *q, struct request *rq) | 839 | static void sd_unprep_fn(struct request_queue *q, struct request *rq) |
840 | { | 840 | { |
841 | struct scsi_cmnd *SCpnt = rq->special; | ||
842 | |||
841 | if (rq->cmd_flags & REQ_DISCARD) { | 843 | if (rq->cmd_flags & REQ_DISCARD) { |
842 | free_page((unsigned long)rq->buffer); | 844 | free_page((unsigned long)rq->buffer); |
843 | rq->buffer = NULL; | 845 | rq->buffer = NULL; |
844 | } | 846 | } |
847 | if (SCpnt->cmnd != rq->cmd) { | ||
848 | mempool_free(SCpnt->cmnd, sd_cdb_pool); | ||
849 | SCpnt->cmnd = NULL; | ||
850 | SCpnt->cmd_len = 0; | ||
851 | } | ||
845 | } | 852 | } |
846 | 853 | ||
847 | /** | 854 | /** |
@@ -1720,21 +1727,6 @@ static int sd_done(struct scsi_cmnd *SCpnt) | |||
1720 | if (rq_data_dir(SCpnt->request) == READ && scsi_prot_sg_count(SCpnt)) | 1727 | if (rq_data_dir(SCpnt->request) == READ && scsi_prot_sg_count(SCpnt)) |
1721 | sd_dif_complete(SCpnt, good_bytes); | 1728 | sd_dif_complete(SCpnt, good_bytes); |
1722 | 1729 | ||
1723 | if (scsi_host_dif_capable(sdkp->device->host, sdkp->protection_type) | ||
1724 | == SD_DIF_TYPE2_PROTECTION && SCpnt->cmnd != SCpnt->request->cmd) { | ||
1725 | |||
1726 | /* We have to print a failed command here as the | ||
1727 | * extended CDB gets freed before scsi_io_completion() | ||
1728 | * is called. | ||
1729 | */ | ||
1730 | if (result) | ||
1731 | scsi_print_command(SCpnt); | ||
1732 | |||
1733 | mempool_free(SCpnt->cmnd, sd_cdb_pool); | ||
1734 | SCpnt->cmnd = NULL; | ||
1735 | SCpnt->cmd_len = 0; | ||
1736 | } | ||
1737 | |||
1738 | return good_bytes; | 1730 | return good_bytes; |
1739 | } | 1731 | } |
1740 | 1732 | ||