From 54b5e3a4bfa3452bc10cd4da672099ccc46b8c09 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 28 Sep 2011 18:35:27 -0700 Subject: [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: Reported-by: Derick Marks Tested-by: Derick Marks Signed-off-by: Dan Williams Signed-off-by: James Bottomley --- drivers/scsi/isci/request.c | 49 ++++++++++++++++++--------------------------- 1 file changed, 20 insertions(+), 29 deletions(-) (limited to 'drivers/scsi/isci/request.c') 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, return SCI_SUCCESS; case SCI_REQ_SMP_WAIT_RESP: { - struct smp_resp *rsp_hdr = &ireq->smp.rsp; - void *frame_header; + struct sas_task *task = isci_request_access_task(ireq); + struct scatterlist *sg = &task->smp_task.smp_resp; + void *frame_header, *kaddr; + u8 *rsp; sci_unsolicited_frame_control_get_header(&ihost->uf_control, - frame_index, - &frame_header); - - /* byte swap the header. */ - word_cnt = SMP_RESP_HDR_SZ / sizeof(u32); - sci_swab32_cpy(rsp_hdr, frame_header, word_cnt); + frame_index, + &frame_header); + kaddr = kmap_atomic(sg_page(sg), KM_IRQ0); + rsp = kaddr + sg->offset; + sci_swab32_cpy(rsp, frame_header, 1); - if (rsp_hdr->frame_type == SMP_RESPONSE) { + if (rsp[0] == SMP_RESPONSE) { void *smp_resp; sci_unsolicited_frame_control_get_buffer(&ihost->uf_control, - frame_index, - &smp_resp); + frame_index, + &smp_resp); - word_cnt = (sizeof(struct smp_resp) - SMP_RESP_HDR_SZ) / - sizeof(u32); - - sci_swab32_cpy(((u8 *) rsp_hdr) + SMP_RESP_HDR_SZ, - smp_resp, word_cnt); + word_cnt = (sg->length/4)-1; + if (word_cnt > 0) + word_cnt = min_t(unsigned int, word_cnt, + SCU_UNSOLICITED_FRAME_BUFFER_SIZE/4); + sci_swab32_cpy(rsp + 4, smp_resp, word_cnt); ireq->scu_status = SCU_TASK_DONE_GOOD; ireq->sci_status = SCI_SUCCESS; @@ -1528,12 +1529,13 @@ sci_io_request_frame_handler(struct isci_request *ireq, __func__, ireq, frame_index, - rsp_hdr->frame_type); + rsp[0]); ireq->scu_status = SCU_TASK_DONE_SMP_FRM_TYPE_ERR; ireq->sci_status = SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR; sci_change_state(&ireq->sm, SCI_REQ_COMPLETED); } + kunmap_atomic(kaddr, KM_IRQ0); sci_controller_release_frame(ihost, frame_index); @@ -2603,18 +2605,7 @@ static void isci_request_io_request_complete(struct isci_host *ihost, status = SAM_STAT_GOOD; set_bit(IREQ_COMPLETE_IN_TARGET, &request->flags); - if (task->task_proto == SAS_PROTOCOL_SMP) { - void *rsp = &request->smp.rsp; - - dev_dbg(&ihost->pdev->dev, - "%s: SMP protocol completion\n", - __func__); - - sg_copy_from_buffer( - &task->smp_task.smp_resp, 1, - rsp, sizeof(struct smp_resp)); - } else if (completion_status - == SCI_IO_SUCCESS_IO_DONE_EARLY) { + if (completion_status == SCI_IO_SUCCESS_IO_DONE_EARLY) { /* This was an SSP / STP / SATA transfer. * There is a possibility that less data than -- cgit v1.2.3-55-g7522