diff options
author | Dan Williams <dan.j.williams@intel.com> | 2011-09-28 21:35:27 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2011-10-02 14:07:17 -0400 |
commit | 54b5e3a4bfa3452bc10cd4da672099ccc46b8c09 (patch) | |
tree | f07de6264a0ffb59845f8dfb62d2f158ba50e012 /drivers | |
parent | 6fbc769219a7a8060ea33f397304f05b1cdf8a00 (diff) |
[SCSI] isci: fix support for large smp requests
Kill the local smp response buffer.
Besides being unnecessary, it is too small (currently truncates
responses to 60 bytes). The mid-layer will have already allocated a
sufficiently sized buffer, just kmap and copy into it directly.
Cc: <stable@kernel.org>
Reported-by: Derick Marks <derick.w.marks@intel.com>
Tested-by: Derick Marks <derick.w.marks@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/isci/isci.h | 2 | ||||
-rw-r--r-- | drivers/scsi/isci/request.c | 49 | ||||
-rw-r--r-- | drivers/scsi/isci/request.h | 3 | ||||
-rw-r--r-- | drivers/scsi/isci/sas.h | 2 |
4 files changed, 21 insertions, 35 deletions
diff --git a/drivers/scsi/isci/isci.h b/drivers/scsi/isci/isci.h index d1de63312e7f..8efeb6b08321 100644 --- a/drivers/scsi/isci/isci.h +++ b/drivers/scsi/isci/isci.h | |||
@@ -97,7 +97,7 @@ | |||
97 | #define SCU_MAX_COMPLETION_QUEUE_SHIFT (ilog2(SCU_MAX_COMPLETION_QUEUE_ENTRIES)) | 97 | #define SCU_MAX_COMPLETION_QUEUE_SHIFT (ilog2(SCU_MAX_COMPLETION_QUEUE_ENTRIES)) |
98 | 98 | ||
99 | #define SCU_ABSOLUTE_MAX_UNSOLICITED_FRAMES (4096) | 99 | #define SCU_ABSOLUTE_MAX_UNSOLICITED_FRAMES (4096) |
100 | #define SCU_UNSOLICITED_FRAME_BUFFER_SIZE (1024) | 100 | #define SCU_UNSOLICITED_FRAME_BUFFER_SIZE (1024U) |
101 | #define SCU_INVALID_FRAME_INDEX (0xFFFF) | 101 | #define SCU_INVALID_FRAME_INDEX (0xFFFF) |
102 | 102 | ||
103 | #define SCU_IO_REQUEST_MAX_SGE_SIZE (0x00FFFFFF) | 103 | #define SCU_IO_REQUEST_MAX_SGE_SIZE (0x00FFFFFF) |
diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index b5d3a8c4d329..225b196800a2 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c | |||
@@ -1490,29 +1490,30 @@ sci_io_request_frame_handler(struct isci_request *ireq, | |||
1490 | return SCI_SUCCESS; | 1490 | return SCI_SUCCESS; |
1491 | 1491 | ||
1492 | case SCI_REQ_SMP_WAIT_RESP: { | 1492 | case SCI_REQ_SMP_WAIT_RESP: { |
1493 | struct smp_resp *rsp_hdr = &ireq->smp.rsp; | 1493 | struct sas_task *task = isci_request_access_task(ireq); |
1494 | void *frame_header; | 1494 | struct scatterlist *sg = &task->smp_task.smp_resp; |
1495 | void *frame_header, *kaddr; | ||
1496 | u8 *rsp; | ||
1495 | 1497 | ||
1496 | sci_unsolicited_frame_control_get_header(&ihost->uf_control, | 1498 | sci_unsolicited_frame_control_get_header(&ihost->uf_control, |
1497 | frame_index, | 1499 | frame_index, |
1498 | &frame_header); | 1500 | &frame_header); |
1499 | 1501 | kaddr = kmap_atomic(sg_page(sg), KM_IRQ0); | |
1500 | /* byte swap the header. */ | 1502 | rsp = kaddr + sg->offset; |
1501 | word_cnt = SMP_RESP_HDR_SZ / sizeof(u32); | 1503 | sci_swab32_cpy(rsp, frame_header, 1); |
1502 | sci_swab32_cpy(rsp_hdr, frame_header, word_cnt); | ||
1503 | 1504 | ||
1504 | if (rsp_hdr->frame_type == SMP_RESPONSE) { | 1505 | if (rsp[0] == SMP_RESPONSE) { |
1505 | void *smp_resp; | 1506 | void *smp_resp; |
1506 | 1507 | ||
1507 | sci_unsolicited_frame_control_get_buffer(&ihost->uf_control, | 1508 | sci_unsolicited_frame_control_get_buffer(&ihost->uf_control, |
1508 | frame_index, | 1509 | frame_index, |
1509 | &smp_resp); | 1510 | &smp_resp); |
1510 | 1511 | ||
1511 | word_cnt = (sizeof(struct smp_resp) - SMP_RESP_HDR_SZ) / | 1512 | word_cnt = (sg->length/4)-1; |
1512 | sizeof(u32); | 1513 | if (word_cnt > 0) |
1513 | 1514 | word_cnt = min_t(unsigned int, word_cnt, | |
1514 | sci_swab32_cpy(((u8 *) rsp_hdr) + SMP_RESP_HDR_SZ, | 1515 | SCU_UNSOLICITED_FRAME_BUFFER_SIZE/4); |
1515 | smp_resp, word_cnt); | 1516 | sci_swab32_cpy(rsp + 4, smp_resp, word_cnt); |
1516 | 1517 | ||
1517 | ireq->scu_status = SCU_TASK_DONE_GOOD; | 1518 | ireq->scu_status = SCU_TASK_DONE_GOOD; |
1518 | ireq->sci_status = SCI_SUCCESS; | 1519 | ireq->sci_status = SCI_SUCCESS; |
@@ -1528,12 +1529,13 @@ sci_io_request_frame_handler(struct isci_request *ireq, | |||
1528 | __func__, | 1529 | __func__, |
1529 | ireq, | 1530 | ireq, |
1530 | frame_index, | 1531 | frame_index, |
1531 | rsp_hdr->frame_type); | 1532 | rsp[0]); |
1532 | 1533 | ||
1533 | ireq->scu_status = SCU_TASK_DONE_SMP_FRM_TYPE_ERR; | 1534 | ireq->scu_status = SCU_TASK_DONE_SMP_FRM_TYPE_ERR; |
1534 | ireq->sci_status = SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR; | 1535 | ireq->sci_status = SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR; |
1535 | sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); | 1536 | sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); |
1536 | } | 1537 | } |
1538 | kunmap_atomic(kaddr, KM_IRQ0); | ||
1537 | 1539 | ||
1538 | sci_controller_release_frame(ihost, frame_index); | 1540 | sci_controller_release_frame(ihost, frame_index); |
1539 | 1541 | ||
@@ -2603,18 +2605,7 @@ static void isci_request_io_request_complete(struct isci_host *ihost, | |||
2603 | status = SAM_STAT_GOOD; | 2605 | status = SAM_STAT_GOOD; |
2604 | set_bit(IREQ_COMPLETE_IN_TARGET, &request->flags); | 2606 | set_bit(IREQ_COMPLETE_IN_TARGET, &request->flags); |
2605 | 2607 | ||
2606 | if (task->task_proto == SAS_PROTOCOL_SMP) { | 2608 | if (completion_status == SCI_IO_SUCCESS_IO_DONE_EARLY) { |
2607 | void *rsp = &request->smp.rsp; | ||
2608 | |||
2609 | dev_dbg(&ihost->pdev->dev, | ||
2610 | "%s: SMP protocol completion\n", | ||
2611 | __func__); | ||
2612 | |||
2613 | sg_copy_from_buffer( | ||
2614 | &task->smp_task.smp_resp, 1, | ||
2615 | rsp, sizeof(struct smp_resp)); | ||
2616 | } else if (completion_status | ||
2617 | == SCI_IO_SUCCESS_IO_DONE_EARLY) { | ||
2618 | 2609 | ||
2619 | /* This was an SSP / STP / SATA transfer. | 2610 | /* This was an SSP / STP / SATA transfer. |
2620 | * There is a possibility that less data than | 2611 | * There is a possibility that less data than |
diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h index 7a1d5a9778eb..58d70b6606ef 100644 --- a/drivers/scsi/isci/request.h +++ b/drivers/scsi/isci/request.h | |||
@@ -174,9 +174,6 @@ struct isci_request { | |||
174 | }; | 174 | }; |
175 | } ssp; | 175 | } ssp; |
176 | struct { | 176 | struct { |
177 | struct smp_resp rsp; | ||
178 | } smp; | ||
179 | struct { | ||
180 | struct isci_stp_request req; | 177 | struct isci_stp_request req; |
181 | struct host_to_dev_fis cmd; | 178 | struct host_to_dev_fis cmd; |
182 | struct dev_to_host_fis rsp; | 179 | struct dev_to_host_fis rsp; |
diff --git a/drivers/scsi/isci/sas.h b/drivers/scsi/isci/sas.h index 462b15174d3f..dc26b4aea99e 100644 --- a/drivers/scsi/isci/sas.h +++ b/drivers/scsi/isci/sas.h | |||
@@ -204,8 +204,6 @@ struct smp_req { | |||
204 | u8 req_data[0]; | 204 | u8 req_data[0]; |
205 | } __packed; | 205 | } __packed; |
206 | 206 | ||
207 | #define SMP_RESP_HDR_SZ 4 | ||
208 | |||
209 | /* | 207 | /* |
210 | * struct sci_sas_address - This structure depicts how a SAS address is | 208 | * struct sci_sas_address - This structure depicts how a SAS address is |
211 | * represented by SCI. | 209 | * represented by SCI. |