aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2011-06-16 19:59:56 -0400
committerDan Williams <dan.j.williams@intel.com>2011-07-03 07:04:51 -0400
commite9bf709564e90abea25ca7aeae8c3de5cc6468d7 (patch)
treee4569a311fd0181109ad7b265425a74af2a41553 /drivers/scsi
parentddcc7e347a891937be65358b43f40b7f81185f8f (diff)
isci: fix support for arbitrarily large smp requests
Instead of duplicating the smp request buffer reuse the one provided by libsas. This future proofs the driver to support arbitrarily large smp requests, and shrinks the request structure size by ~700 bytes. Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/isci/request.c138
-rw-r--r--drivers/scsi/isci/request.h1
-rw-r--r--drivers/scsi/isci/sas.h11
3 files changed, 65 insertions, 85 deletions
diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c
index 395084955150..1043fed2a40a 100644
--- a/drivers/scsi/isci/request.c
+++ b/drivers/scsi/isci/request.c
@@ -2943,6 +2943,20 @@ static void isci_request_io_request_complete(struct isci_host *isci_host,
2943 dma_unmap_sg(&isci_host->pdev->dev, task->scatter, 2943 dma_unmap_sg(&isci_host->pdev->dev, task->scatter,
2944 request->num_sg_entries, task->data_dir); 2944 request->num_sg_entries, task->data_dir);
2945 break; 2945 break;
2946 case SAS_PROTOCOL_SMP: {
2947 struct scatterlist *sg = &task->smp_task.smp_req;
2948 struct smp_req *smp_req;
2949 void *kaddr;
2950
2951 dma_unmap_sg(&isci_host->pdev->dev, sg, 1, DMA_TO_DEVICE);
2952
2953 /* need to swab it back in case the command buffer is re-used */
2954 kaddr = kmap_atomic(sg_page(sg), KM_IRQ0);
2955 smp_req = kaddr + sg->offset;
2956 sci_swab32_cpy(smp_req, smp_req, sg->length / sizeof(u32));
2957 kunmap_atomic(kaddr, KM_IRQ0);
2958 break;
2959 }
2946 default: 2960 default:
2947 break; 2961 break;
2948 } 2962 }
@@ -3160,7 +3174,7 @@ scic_io_request_construct(struct scic_sds_controller *scic,
3160 else if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) 3174 else if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP))
3161 memset(&sci_req->stp.cmd, 0, sizeof(sci_req->stp.cmd)); 3175 memset(&sci_req->stp.cmd, 0, sizeof(sci_req->stp.cmd));
3162 else if (dev_is_expander(dev)) 3176 else if (dev_is_expander(dev))
3163 memset(&sci_req->smp.cmd, 0, sizeof(sci_req->smp.cmd)); 3177 /* pass */;
3164 else 3178 else
3165 return SCI_FAILURE_UNSUPPORTED_PROTOCOL; 3179 return SCI_FAILURE_UNSUPPORTED_PROTOCOL;
3166 3180
@@ -3236,30 +3250,54 @@ static enum sci_status isci_request_stp_request_construct(
3236 return status; 3250 return status;
3237} 3251}
3238 3252
3239/* 3253static enum sci_status
3240 * This function will fill in the SCU Task Context for a SMP request. The 3254scic_io_request_construct_smp(struct device *dev,
3241 * following important settings are utilized: -# task_type == 3255 struct scic_sds_request *sci_req,
3242 * SCU_TASK_TYPE_SMP. This simply indicates that a normal request type 3256 struct sas_task *task)
3243 * (i.e. non-raw frame) is being utilized to perform task management. -#
3244 * control_frame == 1. This ensures that the proper endianess is set so
3245 * that the bytes are transmitted in the right order for a smp request frame.
3246 * @sci_req: This parameter specifies the smp request object being
3247 * constructed.
3248 *
3249 */
3250static void
3251scu_smp_request_construct_task_context(struct scic_sds_request *sci_req,
3252 ssize_t req_len)
3253{ 3257{
3254 dma_addr_t dma_addr; 3258 struct scatterlist *sg = &task->smp_task.smp_req;
3255 struct scic_sds_remote_device *sci_dev; 3259 struct scic_sds_remote_device *sci_dev;
3256 struct scic_sds_port *sci_port;
3257 struct scu_task_context *task_context; 3260 struct scu_task_context *task_context;
3258 ssize_t word_cnt = sizeof(struct smp_req) / sizeof(u32); 3261 struct scic_sds_port *sci_port;
3262 struct smp_req *smp_req;
3263 void *kaddr;
3264 u8 req_len;
3265 u32 cmd;
3266
3267 kaddr = kmap_atomic(sg_page(sg), KM_IRQ0);
3268 smp_req = kaddr + sg->offset;
3269 /*
3270 * Look at the SMP requests' header fields; for certain SAS 1.x SMP
3271 * functions under SAS 2.0, a zero request length really indicates
3272 * a non-zero default length.
3273 */
3274 if (smp_req->req_len == 0) {
3275 switch (smp_req->func) {
3276 case SMP_DISCOVER:
3277 case SMP_REPORT_PHY_ERR_LOG:
3278 case SMP_REPORT_PHY_SATA:
3279 case SMP_REPORT_ROUTE_INFO:
3280 smp_req->req_len = 2;
3281 break;
3282 case SMP_CONF_ROUTE_INFO:
3283 case SMP_PHY_CONTROL:
3284 case SMP_PHY_TEST_FUNCTION:
3285 smp_req->req_len = 9;
3286 break;
3287 /* Default - zero is a valid default for 2.0. */
3288 }
3289 }
3290 req_len = smp_req->req_len;
3291 sci_swab32_cpy(smp_req, smp_req, sg->length / sizeof(u32));
3292 cmd = *(u32 *) smp_req;
3293 kunmap_atomic(kaddr, KM_IRQ0);
3294
3295 if (!dma_map_sg(dev, sg, 1, DMA_TO_DEVICE))
3296 return SCI_FAILURE;
3297
3298 sci_req->protocol = SCIC_SMP_PROTOCOL;
3259 3299
3260 /* byte swap the smp request. */ 3300 /* byte swap the smp request. */
3261 sci_swab32_cpy(&sci_req->smp.cmd, &sci_req->smp.cmd,
3262 word_cnt);
3263 3301
3264 task_context = scic_sds_request_get_task_context(sci_req); 3302 task_context = scic_sds_request_get_task_context(sci_req);
3265 3303
@@ -3307,7 +3345,7 @@ scu_smp_request_construct_task_context(struct scic_sds_request *sci_req,
3307 * 18h ~ 30h, protocol specific 3345 * 18h ~ 30h, protocol specific
3308 * since commandIU has been build by framework at this point, we just 3346 * since commandIU has been build by framework at this point, we just
3309 * copy the frist DWord from command IU to this location. */ 3347 * copy the frist DWord from command IU to this location. */
3310 memcpy(&task_context->type.smp, &sci_req->smp.cmd, sizeof(u32)); 3348 memcpy(&task_context->type.smp, &cmd, sizeof(u32));
3311 3349
3312 /* 3350 /*
3313 * 40h 3351 * 40h
@@ -3347,48 +3385,12 @@ scu_smp_request_construct_task_context(struct scic_sds_request *sci_req,
3347 * Copy the physical address for the command buffer to the SCU Task 3385 * Copy the physical address for the command buffer to the SCU Task
3348 * Context command buffer should not contain command header. 3386 * Context command buffer should not contain command header.
3349 */ 3387 */
3350 dma_addr = scic_io_request_get_dma_addr(sci_req, 3388 task_context->command_iu_upper = upper_32_bits(sg_dma_address(sg));
3351 ((char *) &sci_req->smp.cmd) + 3389 task_context->command_iu_lower = lower_32_bits(sg_dma_address(sg) + sizeof(u32));
3352 sizeof(u32));
3353
3354 task_context->command_iu_upper = upper_32_bits(dma_addr);
3355 task_context->command_iu_lower = lower_32_bits(dma_addr);
3356 3390
3357 /* SMP response comes as UF, so no need to set response IU address. */ 3391 /* SMP response comes as UF, so no need to set response IU address. */
3358 task_context->response_iu_upper = 0; 3392 task_context->response_iu_upper = 0;
3359 task_context->response_iu_lower = 0; 3393 task_context->response_iu_lower = 0;
3360}
3361
3362static enum sci_status
3363scic_io_request_construct_smp(struct scic_sds_request *sci_req)
3364{
3365 struct smp_req *smp_req = &sci_req->smp.cmd;
3366
3367 sci_req->protocol = SCIC_SMP_PROTOCOL;
3368
3369 /*
3370 * Look at the SMP requests' header fields; for certain SAS 1.x SMP
3371 * functions under SAS 2.0, a zero request length really indicates
3372 * a non-zero default length.
3373 */
3374 if (smp_req->req_len == 0) {
3375 switch (smp_req->func) {
3376 case SMP_DISCOVER:
3377 case SMP_REPORT_PHY_ERR_LOG:
3378 case SMP_REPORT_PHY_SATA:
3379 case SMP_REPORT_ROUTE_INFO:
3380 smp_req->req_len = 2;
3381 break;
3382 case SMP_CONF_ROUTE_INFO:
3383 case SMP_PHY_CONTROL:
3384 case SMP_PHY_TEST_FUNCTION:
3385 smp_req->req_len = 9;
3386 break;
3387 /* Default - zero is a valid default for 2.0. */
3388 }
3389 }
3390
3391 scu_smp_request_construct_task_context(sci_req, smp_req->req_len);
3392 3394
3393 sci_change_state(&sci_req->sm, SCI_REQ_CONSTRUCTED); 3395 sci_change_state(&sci_req->sm, SCI_REQ_CONSTRUCTED);
3394 3396
@@ -3404,24 +3406,12 @@ scic_io_request_construct_smp(struct scic_sds_request *sci_req)
3404 */ 3406 */
3405static enum sci_status isci_smp_request_build(struct isci_request *ireq) 3407static enum sci_status isci_smp_request_build(struct isci_request *ireq)
3406{ 3408{
3407 enum sci_status status = SCI_FAILURE;
3408 struct sas_task *task = isci_request_access_task(ireq); 3409 struct sas_task *task = isci_request_access_task(ireq);
3410 struct device *dev = &ireq->isci_host->pdev->dev;
3409 struct scic_sds_request *sci_req = &ireq->sci; 3411 struct scic_sds_request *sci_req = &ireq->sci;
3412 enum sci_status status = SCI_FAILURE;
3410 3413
3411 dev_dbg(&ireq->isci_host->pdev->dev, 3414 status = scic_io_request_construct_smp(dev, sci_req, task);
3412 "%s: request = %p\n", __func__, ireq);
3413
3414 dev_dbg(&ireq->isci_host->pdev->dev,
3415 "%s: smp_req len = %d\n",
3416 __func__,
3417 task->smp_task.smp_req.length);
3418
3419 /* copy the smp_command to the address; */
3420 sg_copy_to_buffer(&task->smp_task.smp_req, 1,
3421 &sci_req->smp.cmd,
3422 sizeof(struct smp_req));
3423
3424 status = scic_io_request_construct_smp(sci_req);
3425 if (status != SCI_SUCCESS) 3415 if (status != SCI_SUCCESS)
3426 dev_warn(&ireq->isci_host->pdev->dev, 3416 dev_warn(&ireq->isci_host->pdev->dev,
3427 "%s: failed with status = %d\n", 3417 "%s: failed with status = %d\n",
diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h
index 324fb7b3ab42..7c8b59a7c02c 100644
--- a/drivers/scsi/isci/request.h
+++ b/drivers/scsi/isci/request.h
@@ -244,7 +244,6 @@ struct scic_sds_request {
244 } ssp; 244 } ssp;
245 245
246 struct { 246 struct {
247 struct smp_req cmd;
248 struct smp_resp rsp; 247 struct smp_resp rsp;
249 } smp; 248 } smp;
250 249
diff --git a/drivers/scsi/isci/sas.h b/drivers/scsi/isci/sas.h
index 822a8dbd19ca..462b15174d3f 100644
--- a/drivers/scsi/isci/sas.h
+++ b/drivers/scsi/isci/sas.h
@@ -190,8 +190,6 @@ struct smp_req_phycntl {
190 u8 _r_h[3]; /* bytes 37-39 */ 190 u8 _r_h[3]; /* bytes 37-39 */
191} __packed; 191} __packed;
192 192
193#define SMP_REQ_VENDOR_SPECIFIC_MAX_LEN 1016
194
195/* 193/*
196 * struct smp_req - This structure simply unionizes the existing request 194 * struct smp_req - This structure simply unionizes the existing request
197 * structures into a common request type. 195 * structures into a common request type.
@@ -203,14 +201,7 @@ struct smp_req {
203 u8 func; /* byte 1 */ 201 u8 func; /* byte 1 */
204 u8 alloc_resp_len; /* byte 2 */ 202 u8 alloc_resp_len; /* byte 2 */
205 u8 req_len; /* byte 3 */ 203 u8 req_len; /* byte 3 */
206 204 u8 req_data[0];
207 union { /* bytes 4-N */
208 u32 smp_req_gen;
209 struct smp_req_phy_id phy_id;
210 struct smp_req_phycntl phy_cntl;
211 struct smp_req_conf_rtinfo conf_rt_info;
212 u8 vendor[SMP_REQ_VENDOR_SPECIFIC_MAX_LEN];
213 };
214} __packed; 205} __packed;
215 206
216#define SMP_RESP_HDR_SZ 4 207#define SMP_RESP_HDR_SZ 4