summaryrefslogtreecommitdiff
path: root/drivers/scsi/libsas/sas_host_smp.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/libsas/sas_host_smp.c')
-rw-r--r--drivers/scsi/libsas/sas_host_smp.c106
1 files changed, 40 insertions, 66 deletions
diff --git a/drivers/scsi/libsas/sas_host_smp.c b/drivers/scsi/libsas/sas_host_smp.c
index 45cbbc44f4d7..9ead93df3a6e 100644
--- a/drivers/scsi/libsas/sas_host_smp.c
+++ b/drivers/scsi/libsas/sas_host_smp.c
@@ -225,47 +225,36 @@ static void sas_phy_control(struct sas_ha_struct *sas_ha, u8 phy_id,
resp_data[2] = SMP_RESP_FUNC_ACC;
}
-int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req,
- struct request *rsp)
+void sas_smp_host_handler(struct bsg_job *job, struct Scsi_Host *shost)
{
- u8 *req_data = NULL, *resp_data = NULL, *buf;
struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(shost);
+ u8 *req_data, *resp_data;
+ unsigned int reslen = 0;
int error = -EINVAL;
/* eight is the minimum size for request and response frames */
- if (blk_rq_bytes(req) < 8 || blk_rq_bytes(rsp) < 8)
+ if (job->request_payload.payload_len < 8 ||
+ job->reply_payload.payload_len < 8)
goto out;
- if (bio_offset(req->bio) + blk_rq_bytes(req) > PAGE_SIZE ||
- bio_offset(rsp->bio) + blk_rq_bytes(rsp) > PAGE_SIZE) {
- shost_printk(KERN_ERR, shost,
- "SMP request/response frame crosses page boundary");
+ error = -ENOMEM;
+ req_data = kzalloc(job->request_payload.payload_len, GFP_KERNEL);
+ if (!req_data)
goto out;
- }
-
- req_data = kzalloc(blk_rq_bytes(req), GFP_KERNEL);
+ sg_copy_to_buffer(job->request_payload.sg_list,
+ job->request_payload.sg_cnt, req_data,
+ job->request_payload.payload_len);
/* make sure frame can always be built ... we copy
* back only the requested length */
- resp_data = kzalloc(max(blk_rq_bytes(rsp), 128U), GFP_KERNEL);
-
- if (!req_data || !resp_data) {
- error = -ENOMEM;
- goto out;
- }
-
- local_irq_disable();
- buf = kmap_atomic(bio_page(req->bio));
- memcpy(req_data, buf, blk_rq_bytes(req));
- kunmap_atomic(buf - bio_offset(req->bio));
- local_irq_enable();
+ resp_data = kzalloc(max(job->reply_payload.payload_len, 128U),
+ GFP_KERNEL);
+ if (!resp_data)
+ goto out_free_req;
+ error = -EINVAL;
if (req_data[0] != SMP_REQUEST)
- goto out;
-
- /* always succeeds ... even if we can't process the request
- * the result is in the response frame */
- error = 0;
+ goto out_free_resp;
/* set up default don't know response */
resp_data[0] = SMP_RESPONSE;
@@ -274,20 +263,18 @@ int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req,
switch (req_data[1]) {
case SMP_REPORT_GENERAL:
- scsi_req(req)->resid_len -= 8;
- scsi_req(rsp)->resid_len -= 32;
resp_data[2] = SMP_RESP_FUNC_ACC;
resp_data[9] = sas_ha->num_phys;
+ reslen = 32;
break;
case SMP_REPORT_MANUF_INFO:
- scsi_req(req)->resid_len -= 8;
- scsi_req(rsp)->resid_len -= 64;
resp_data[2] = SMP_RESP_FUNC_ACC;
memcpy(resp_data + 12, shost->hostt->name,
SAS_EXPANDER_VENDOR_ID_LEN);
memcpy(resp_data + 20, "libsas virt phy",
SAS_EXPANDER_PRODUCT_ID_LEN);
+ reslen = 64;
break;
case SMP_READ_GPIO_REG:
@@ -295,14 +282,10 @@ int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req,
break;
case SMP_DISCOVER:
- scsi_req(req)->resid_len -= 16;
- if ((int)scsi_req(req)->resid_len < 0) {
- scsi_req(req)->resid_len = 0;
- error = -EINVAL;
- goto out;
- }
- scsi_req(rsp)->resid_len -= 56;
+ if (job->request_payload.payload_len < 16)
+ goto out_free_resp;
sas_host_smp_discover(sas_ha, resp_data, req_data[9]);
+ reslen = 56;
break;
case SMP_REPORT_PHY_ERR_LOG:
@@ -311,14 +294,10 @@ int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req,
break;
case SMP_REPORT_PHY_SATA:
- scsi_req(req)->resid_len -= 16;
- if ((int)scsi_req(req)->resid_len < 0) {
- scsi_req(req)->resid_len = 0;
- error = -EINVAL;
- goto out;
- }
- scsi_req(rsp)->resid_len -= 60;
+ if (job->request_payload.payload_len < 16)
+ goto out_free_resp;
sas_report_phy_sata(sas_ha, resp_data, req_data[9]);
+ reslen = 60;
break;
case SMP_REPORT_ROUTE_INFO:
@@ -330,16 +309,15 @@ int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req,
const int base_frame_size = 11;
int to_write = req_data[4];
- if (blk_rq_bytes(req) < base_frame_size + to_write * 4 ||
- scsi_req(req)->resid_len < base_frame_size + to_write * 4) {
+ if (job->request_payload.payload_len <
+ base_frame_size + to_write * 4) {
resp_data[2] = SMP_RESP_INV_FRM_LEN;
break;
}
to_write = sas_host_smp_write_gpio(sas_ha, resp_data, req_data[2],
req_data[3], to_write, &req_data[8]);
- scsi_req(req)->resid_len -= base_frame_size + to_write * 4;
- scsi_req(rsp)->resid_len -= 8;
+ reslen = 8;
break;
}
@@ -348,16 +326,12 @@ int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req,
break;
case SMP_PHY_CONTROL:
- scsi_req(req)->resid_len -= 44;
- if ((int)scsi_req(req)->resid_len < 0) {
- scsi_req(req)->resid_len = 0;
- error = -EINVAL;
- goto out;
- }
- scsi_req(rsp)->resid_len -= 8;
+ if (job->request_payload.payload_len < 44)
+ goto out_free_resp;
sas_phy_control(sas_ha, req_data[9], req_data[10],
req_data[32] >> 4, req_data[33] >> 4,
resp_data);
+ reslen = 8;
break;
case SMP_PHY_TEST_FUNCTION:
@@ -369,15 +343,15 @@ int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req,
break;
}
- local_irq_disable();
- buf = kmap_atomic(bio_page(rsp->bio));
- memcpy(buf, resp_data, blk_rq_bytes(rsp));
- flush_kernel_dcache_page(bio_page(rsp->bio));
- kunmap_atomic(buf - bio_offset(rsp->bio));
- local_irq_enable();
+ sg_copy_from_buffer(job->reply_payload.sg_list,
+ job->reply_payload.sg_cnt, resp_data,
+ job->reply_payload.payload_len);
- out:
- kfree(req_data);
+ error = 0;
+out_free_resp:
kfree(resp_data);
- return error;
+out_free_req:
+ kfree(req_data);
+out:
+ bsg_job_done(job, error, reslen);
}