diff options
-rw-r--r-- | drivers/scsi/isci/request.c | 138 | ||||
-rw-r--r-- | drivers/scsi/isci/request.h | 1 | ||||
-rw-r--r-- | drivers/scsi/isci/sas.h | 11 |
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 | /* | 3253 | static enum sci_status |
3240 | * This function will fill in the SCU Task Context for a SMP request. The | 3254 | scic_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 | */ | ||
3250 | static void | ||
3251 | scu_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 | |||
3362 | static enum sci_status | ||
3363 | scic_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 | */ |
3405 | static enum sci_status isci_smp_request_build(struct isci_request *ireq) | 3407 | static 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 |