[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>
This commit is contained in:
parent
6fbc769219
commit
54b5e3a4bf
4 changed files with 21 additions and 35 deletions
|
@ -97,7 +97,7 @@
|
||||||
#define SCU_MAX_COMPLETION_QUEUE_SHIFT (ilog2(SCU_MAX_COMPLETION_QUEUE_ENTRIES))
|
#define SCU_MAX_COMPLETION_QUEUE_SHIFT (ilog2(SCU_MAX_COMPLETION_QUEUE_ENTRIES))
|
||||||
|
|
||||||
#define SCU_ABSOLUTE_MAX_UNSOLICITED_FRAMES (4096)
|
#define SCU_ABSOLUTE_MAX_UNSOLICITED_FRAMES (4096)
|
||||||
#define SCU_UNSOLICITED_FRAME_BUFFER_SIZE (1024)
|
#define SCU_UNSOLICITED_FRAME_BUFFER_SIZE (1024U)
|
||||||
#define SCU_INVALID_FRAME_INDEX (0xFFFF)
|
#define SCU_INVALID_FRAME_INDEX (0xFFFF)
|
||||||
|
|
||||||
#define SCU_IO_REQUEST_MAX_SGE_SIZE (0x00FFFFFF)
|
#define SCU_IO_REQUEST_MAX_SGE_SIZE (0x00FFFFFF)
|
||||||
|
|
|
@ -1490,29 +1490,30 @@ sci_io_request_frame_handler(struct isci_request *ireq,
|
||||||
return SCI_SUCCESS;
|
return SCI_SUCCESS;
|
||||||
|
|
||||||
case SCI_REQ_SMP_WAIT_RESP: {
|
case SCI_REQ_SMP_WAIT_RESP: {
|
||||||
struct smp_resp *rsp_hdr = &ireq->smp.rsp;
|
struct sas_task *task = isci_request_access_task(ireq);
|
||||||
void *frame_header;
|
struct scatterlist *sg = &task->smp_task.smp_resp;
|
||||||
|
void *frame_header, *kaddr;
|
||||||
|
u8 *rsp;
|
||||||
|
|
||||||
sci_unsolicited_frame_control_get_header(&ihost->uf_control,
|
sci_unsolicited_frame_control_get_header(&ihost->uf_control,
|
||||||
frame_index,
|
frame_index,
|
||||||
&frame_header);
|
&frame_header);
|
||||||
|
kaddr = kmap_atomic(sg_page(sg), KM_IRQ0);
|
||||||
|
rsp = kaddr + sg->offset;
|
||||||
|
sci_swab32_cpy(rsp, frame_header, 1);
|
||||||
|
|
||||||
/* byte swap the header. */
|
if (rsp[0] == SMP_RESPONSE) {
|
||||||
word_cnt = SMP_RESP_HDR_SZ / sizeof(u32);
|
|
||||||
sci_swab32_cpy(rsp_hdr, frame_header, word_cnt);
|
|
||||||
|
|
||||||
if (rsp_hdr->frame_type == SMP_RESPONSE) {
|
|
||||||
void *smp_resp;
|
void *smp_resp;
|
||||||
|
|
||||||
sci_unsolicited_frame_control_get_buffer(&ihost->uf_control,
|
sci_unsolicited_frame_control_get_buffer(&ihost->uf_control,
|
||||||
frame_index,
|
frame_index,
|
||||||
&smp_resp);
|
&smp_resp);
|
||||||
|
|
||||||
word_cnt = (sizeof(struct smp_resp) - SMP_RESP_HDR_SZ) /
|
word_cnt = (sg->length/4)-1;
|
||||||
sizeof(u32);
|
if (word_cnt > 0)
|
||||||
|
word_cnt = min_t(unsigned int, word_cnt,
|
||||||
sci_swab32_cpy(((u8 *) rsp_hdr) + SMP_RESP_HDR_SZ,
|
SCU_UNSOLICITED_FRAME_BUFFER_SIZE/4);
|
||||||
smp_resp, word_cnt);
|
sci_swab32_cpy(rsp + 4, smp_resp, word_cnt);
|
||||||
|
|
||||||
ireq->scu_status = SCU_TASK_DONE_GOOD;
|
ireq->scu_status = SCU_TASK_DONE_GOOD;
|
||||||
ireq->sci_status = SCI_SUCCESS;
|
ireq->sci_status = SCI_SUCCESS;
|
||||||
|
@ -1528,12 +1529,13 @@ sci_io_request_frame_handler(struct isci_request *ireq,
|
||||||
__func__,
|
__func__,
|
||||||
ireq,
|
ireq,
|
||||||
frame_index,
|
frame_index,
|
||||||
rsp_hdr->frame_type);
|
rsp[0]);
|
||||||
|
|
||||||
ireq->scu_status = SCU_TASK_DONE_SMP_FRM_TYPE_ERR;
|
ireq->scu_status = SCU_TASK_DONE_SMP_FRM_TYPE_ERR;
|
||||||
ireq->sci_status = SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR;
|
ireq->sci_status = SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR;
|
||||||
sci_change_state(&ireq->sm, SCI_REQ_COMPLETED);
|
sci_change_state(&ireq->sm, SCI_REQ_COMPLETED);
|
||||||
}
|
}
|
||||||
|
kunmap_atomic(kaddr, KM_IRQ0);
|
||||||
|
|
||||||
sci_controller_release_frame(ihost, frame_index);
|
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;
|
status = SAM_STAT_GOOD;
|
||||||
set_bit(IREQ_COMPLETE_IN_TARGET, &request->flags);
|
set_bit(IREQ_COMPLETE_IN_TARGET, &request->flags);
|
||||||
|
|
||||||
if (task->task_proto == SAS_PROTOCOL_SMP) {
|
if (completion_status == SCI_IO_SUCCESS_IO_DONE_EARLY) {
|
||||||
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) {
|
|
||||||
|
|
||||||
/* This was an SSP / STP / SATA transfer.
|
/* This was an SSP / STP / SATA transfer.
|
||||||
* There is a possibility that less data than
|
* There is a possibility that less data than
|
||||||
|
|
|
@ -173,9 +173,6 @@ struct isci_request {
|
||||||
u8 rsp_buf[SSP_RESP_IU_MAX_SIZE];
|
u8 rsp_buf[SSP_RESP_IU_MAX_SIZE];
|
||||||
};
|
};
|
||||||
} ssp;
|
} ssp;
|
||||||
struct {
|
|
||||||
struct smp_resp rsp;
|
|
||||||
} smp;
|
|
||||||
struct {
|
struct {
|
||||||
struct isci_stp_request req;
|
struct isci_stp_request req;
|
||||||
struct host_to_dev_fis cmd;
|
struct host_to_dev_fis cmd;
|
||||||
|
|
|
@ -204,8 +204,6 @@ struct smp_req {
|
||||||
u8 req_data[0];
|
u8 req_data[0];
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
#define SMP_RESP_HDR_SZ 4
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* struct sci_sas_address - This structure depicts how a SAS address is
|
* struct sci_sas_address - This structure depicts how a SAS address is
|
||||||
* represented by SCI.
|
* represented by SCI.
|
||||||
|
|
Loading…
Add table
Reference in a new issue