Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+65 -85
+64 -74
drivers/scsi/isci/request.c
··· 2943 2943 dma_unmap_sg(&isci_host->pdev->dev, task->scatter, 2944 2944 request->num_sg_entries, task->data_dir); 2945 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 2960 default: 2947 2961 break; 2948 2962 } ··· 3174 3160 else if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) 3175 3161 memset(&sci_req->stp.cmd, 0, sizeof(sci_req->stp.cmd)); 3176 3162 else if (dev_is_expander(dev)) 3177 - memset(&sci_req->smp.cmd, 0, sizeof(sci_req->smp.cmd)); 3163 + /* pass */; 3178 3164 else 3179 3165 return SCI_FAILURE_UNSUPPORTED_PROTOCOL; 3180 3166 ··· 3250 3236 return status; 3251 3237 } 3252 3238 3253 - /* 3254 - * This function will fill in the SCU Task Context for a SMP request. The 3255 - * following important settings are utilized: -# task_type == 3256 - * SCU_TASK_TYPE_SMP. This simply indicates that a normal request type 3257 - * (i.e. non-raw frame) is being utilized to perform task management. -# 3258 - * control_frame == 1. This ensures that the proper endianess is set so 3259 - * that the bytes are transmitted in the right order for a smp request frame. 3260 - * @sci_req: This parameter specifies the smp request object being 3261 - * constructed. 3262 - * 3263 - */ 3264 - static void 3265 - scu_smp_request_construct_task_context(struct scic_sds_request *sci_req, 3266 - ssize_t req_len) 3239 + static enum sci_status 3240 + scic_io_request_construct_smp(struct device *dev, 3241 + struct scic_sds_request *sci_req, 3242 + struct sas_task *task) 3267 3243 { 3268 - dma_addr_t dma_addr; 3244 + struct scatterlist *sg = &task->smp_task.smp_req; 3269 3245 struct scic_sds_remote_device *sci_dev; 3270 - struct scic_sds_port *sci_port; 3271 3246 struct scu_task_context *task_context; 3272 - ssize_t word_cnt = sizeof(struct smp_req) / sizeof(u32); 3247 + struct scic_sds_port *sci_port; 3248 + struct smp_req *smp_req; 3249 + void *kaddr; 3250 + u8 req_len; 3251 + u32 cmd; 3252 + 3253 + kaddr = kmap_atomic(sg_page(sg), KM_IRQ0); 3254 + smp_req = kaddr + sg->offset; 3255 + /* 3256 + * Look at the SMP requests' header fields; for certain SAS 1.x SMP 3257 + * functions under SAS 2.0, a zero request length really indicates 3258 + * a non-zero default length. 3259 + */ 3260 + if (smp_req->req_len == 0) { 3261 + switch (smp_req->func) { 3262 + case SMP_DISCOVER: 3263 + case SMP_REPORT_PHY_ERR_LOG: 3264 + case SMP_REPORT_PHY_SATA: 3265 + case SMP_REPORT_ROUTE_INFO: 3266 + smp_req->req_len = 2; 3267 + break; 3268 + case SMP_CONF_ROUTE_INFO: 3269 + case SMP_PHY_CONTROL: 3270 + case SMP_PHY_TEST_FUNCTION: 3271 + smp_req->req_len = 9; 3272 + break; 3273 + /* Default - zero is a valid default for 2.0. */ 3274 + } 3275 + } 3276 + req_len = smp_req->req_len; 3277 + sci_swab32_cpy(smp_req, smp_req, sg->length / sizeof(u32)); 3278 + cmd = *(u32 *) smp_req; 3279 + kunmap_atomic(kaddr, KM_IRQ0); 3280 + 3281 + if (!dma_map_sg(dev, sg, 1, DMA_TO_DEVICE)) 3282 + return SCI_FAILURE; 3283 + 3284 + sci_req->protocol = SCIC_SMP_PROTOCOL; 3273 3285 3274 3286 /* byte swap the smp request. */ 3275 - sci_swab32_cpy(&sci_req->smp.cmd, &sci_req->smp.cmd, 3276 - word_cnt); 3277 3287 3278 3288 task_context = scic_sds_request_get_task_context(sci_req); 3279 3289 ··· 3345 3307 * 18h ~ 30h, protocol specific 3346 3308 * since commandIU has been build by framework at this point, we just 3347 3309 * copy the frist DWord from command IU to this location. */ 3348 - memcpy(&task_context->type.smp, &sci_req->smp.cmd, sizeof(u32)); 3310 + memcpy(&task_context->type.smp, &cmd, sizeof(u32)); 3349 3311 3350 3312 /* 3351 3313 * 40h ··· 3385 3347 * Copy the physical address for the command buffer to the SCU Task 3386 3348 * Context command buffer should not contain command header. 3387 3349 */ 3388 - dma_addr = scic_io_request_get_dma_addr(sci_req, 3389 - ((char *) &sci_req->smp.cmd) + 3390 - sizeof(u32)); 3391 - 3392 - task_context->command_iu_upper = upper_32_bits(dma_addr); 3393 - task_context->command_iu_lower = lower_32_bits(dma_addr); 3350 + task_context->command_iu_upper = upper_32_bits(sg_dma_address(sg)); 3351 + task_context->command_iu_lower = lower_32_bits(sg_dma_address(sg) + sizeof(u32)); 3394 3352 3395 3353 /* SMP response comes as UF, so no need to set response IU address. */ 3396 3354 task_context->response_iu_upper = 0; 3397 3355 task_context->response_iu_lower = 0; 3398 - } 3399 - 3400 - static enum sci_status 3401 - scic_io_request_construct_smp(struct scic_sds_request *sci_req) 3402 - { 3403 - struct smp_req *smp_req = &sci_req->smp.cmd; 3404 - 3405 - sci_req->protocol = SCIC_SMP_PROTOCOL; 3406 - 3407 - /* 3408 - * Look at the SMP requests' header fields; for certain SAS 1.x SMP 3409 - * functions under SAS 2.0, a zero request length really indicates 3410 - * a non-zero default length. 3411 - */ 3412 - if (smp_req->req_len == 0) { 3413 - switch (smp_req->func) { 3414 - case SMP_DISCOVER: 3415 - case SMP_REPORT_PHY_ERR_LOG: 3416 - case SMP_REPORT_PHY_SATA: 3417 - case SMP_REPORT_ROUTE_INFO: 3418 - smp_req->req_len = 2; 3419 - break; 3420 - case SMP_CONF_ROUTE_INFO: 3421 - case SMP_PHY_CONTROL: 3422 - case SMP_PHY_TEST_FUNCTION: 3423 - smp_req->req_len = 9; 3424 - break; 3425 - /* Default - zero is a valid default for 2.0. */ 3426 - } 3427 - } 3428 - 3429 - scu_smp_request_construct_task_context(sci_req, smp_req->req_len); 3430 3356 3431 3357 sci_change_state(&sci_req->sm, SCI_REQ_CONSTRUCTED); 3432 3358 ··· 3406 3404 */ 3407 3405 static enum sci_status isci_smp_request_build(struct isci_request *ireq) 3408 3406 { 3409 - enum sci_status status = SCI_FAILURE; 3410 3407 struct sas_task *task = isci_request_access_task(ireq); 3408 + struct device *dev = &ireq->isci_host->pdev->dev; 3411 3409 struct scic_sds_request *sci_req = &ireq->sci; 3410 + enum sci_status status = SCI_FAILURE; 3412 3411 3413 - dev_dbg(&ireq->isci_host->pdev->dev, 3414 - "%s: request = %p\n", __func__, ireq); 3415 - 3416 - dev_dbg(&ireq->isci_host->pdev->dev, 3417 - "%s: smp_req len = %d\n", 3418 - __func__, 3419 - task->smp_task.smp_req.length); 3420 - 3421 - /* copy the smp_command to the address; */ 3422 - sg_copy_to_buffer(&task->smp_task.smp_req, 1, 3423 - &sci_req->smp.cmd, 3424 - sizeof(struct smp_req)); 3425 - 3426 - status = scic_io_request_construct_smp(sci_req); 3412 + status = scic_io_request_construct_smp(dev, sci_req, task); 3427 3413 if (status != SCI_SUCCESS) 3428 3414 dev_warn(&ireq->isci_host->pdev->dev, 3429 3415 "%s: failed with status = %d\n",
-1
drivers/scsi/isci/request.h
··· 244 244 } ssp; 245 245 246 246 struct { 247 - struct smp_req cmd; 248 247 struct smp_resp rsp; 249 248 } smp; 250 249
+1 -10
drivers/scsi/isci/sas.h
··· 190 190 u8 _r_h[3]; /* bytes 37-39 */ 191 191 } __packed; 192 192 193 - #define SMP_REQ_VENDOR_SPECIFIC_MAX_LEN 1016 194 - 195 193 /* 196 194 * struct smp_req - This structure simply unionizes the existing request 197 195 * structures into a common request type. ··· 201 203 u8 func; /* byte 1 */ 202 204 u8 alloc_resp_len; /* byte 2 */ 203 205 u8 req_len; /* byte 3 */ 204 - 205 - union { /* bytes 4-N */ 206 - u32 smp_req_gen; 207 - struct smp_req_phy_id phy_id; 208 - struct smp_req_phycntl phy_cntl; 209 - struct smp_req_conf_rtinfo conf_rt_info; 210 - u8 vendor[SMP_REQ_VENDOR_SPECIFIC_MAX_LEN]; 211 - }; 206 + u8 req_data[0]; 212 207 } __packed; 213 208 214 209 #define SMP_RESP_HDR_SZ 4