diff options
author | Dan Williams <dan.j.williams@intel.com> | 2011-06-17 17:18:39 -0400 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2011-07-03 07:04:51 -0400 |
commit | db0562509800a2d4cb5cb14a66413c30484f165c (patch) | |
tree | d05cc34b78a8f2a6b9024b8d45e5e8e50786ee64 /drivers/scsi/isci/request.c | |
parent | 38d8879baeb61b6946052739e7c03fa79b3a57f0 (diff) |
isci: preallocate requests
the dma_pool interface is optimized for object_size << page_size which
is not the case with isci_request objects and the dma_pool routines show
up in the top of the profile.
The old io_request_table which tracked whether tci slots were in-flight
or not is replaced with an IREQ_ACTIVE flag per request.
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'drivers/scsi/isci/request.c')
-rw-r--r-- | drivers/scsi/isci/request.c | 89 |
1 files changed, 28 insertions, 61 deletions
diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 27376ba22483..3c7ed4e61b4a 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c | |||
@@ -3017,13 +3017,10 @@ static const struct sci_base_state scic_sds_request_state_table[] = { | |||
3017 | static void | 3017 | static void |
3018 | scic_sds_general_request_construct(struct scic_sds_controller *scic, | 3018 | scic_sds_general_request_construct(struct scic_sds_controller *scic, |
3019 | struct scic_sds_remote_device *sci_dev, | 3019 | struct scic_sds_remote_device *sci_dev, |
3020 | u16 io_tag, | ||
3021 | struct scic_sds_request *sci_req) | 3020 | struct scic_sds_request *sci_req) |
3022 | { | 3021 | { |
3023 | sci_init_sm(&sci_req->sm, scic_sds_request_state_table, SCI_REQ_INIT); | 3022 | sci_init_sm(&sci_req->sm, scic_sds_request_state_table, SCI_REQ_INIT); |
3024 | 3023 | ||
3025 | sci_req->io_tag = io_tag; | ||
3026 | sci_req->owning_controller = scic; | ||
3027 | sci_req->target_device = sci_dev; | 3024 | sci_req->target_device = sci_dev; |
3028 | sci_req->protocol = SCIC_NO_PROTOCOL; | 3025 | sci_req->protocol = SCIC_NO_PROTOCOL; |
3029 | sci_req->saved_rx_frame_index = SCU_INVALID_FRAME_INDEX; | 3026 | sci_req->saved_rx_frame_index = SCU_INVALID_FRAME_INDEX; |
@@ -3031,20 +3028,18 @@ scic_sds_general_request_construct(struct scic_sds_controller *scic, | |||
3031 | sci_req->sci_status = SCI_SUCCESS; | 3028 | sci_req->sci_status = SCI_SUCCESS; |
3032 | sci_req->scu_status = 0; | 3029 | sci_req->scu_status = 0; |
3033 | sci_req->post_context = 0xFFFFFFFF; | 3030 | sci_req->post_context = 0xFFFFFFFF; |
3034 | sci_req->tc = &scic->task_context_table[ISCI_TAG_TCI(io_tag)]; | ||
3035 | WARN_ONCE(io_tag == SCI_CONTROLLER_INVALID_IO_TAG, "straggling invalid tag usage\n"); | ||
3036 | } | 3031 | } |
3037 | 3032 | ||
3038 | static enum sci_status | 3033 | static enum sci_status |
3039 | scic_io_request_construct(struct scic_sds_controller *scic, | 3034 | scic_io_request_construct(struct scic_sds_controller *scic, |
3040 | struct scic_sds_remote_device *sci_dev, | 3035 | struct scic_sds_remote_device *sci_dev, |
3041 | u16 io_tag, struct scic_sds_request *sci_req) | 3036 | struct scic_sds_request *sci_req) |
3042 | { | 3037 | { |
3043 | struct domain_device *dev = sci_dev_to_domain(sci_dev); | 3038 | struct domain_device *dev = sci_dev_to_domain(sci_dev); |
3044 | enum sci_status status = SCI_SUCCESS; | 3039 | enum sci_status status = SCI_SUCCESS; |
3045 | 3040 | ||
3046 | /* Build the common part of the request */ | 3041 | /* Build the common part of the request */ |
3047 | scic_sds_general_request_construct(scic, sci_dev, io_tag, sci_req); | 3042 | scic_sds_general_request_construct(scic, sci_dev, sci_req); |
3048 | 3043 | ||
3049 | if (sci_dev->rnc.remote_node_index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) | 3044 | if (sci_dev->rnc.remote_node_index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) |
3050 | return SCI_FAILURE_INVALID_REMOTE_DEVICE; | 3045 | return SCI_FAILURE_INVALID_REMOTE_DEVICE; |
@@ -3071,7 +3066,7 @@ enum sci_status scic_task_request_construct(struct scic_sds_controller *scic, | |||
3071 | enum sci_status status = SCI_SUCCESS; | 3066 | enum sci_status status = SCI_SUCCESS; |
3072 | 3067 | ||
3073 | /* Build the common part of the request */ | 3068 | /* Build the common part of the request */ |
3074 | scic_sds_general_request_construct(scic, sci_dev, io_tag, sci_req); | 3069 | scic_sds_general_request_construct(scic, sci_dev, sci_req); |
3075 | 3070 | ||
3076 | if (dev->dev_type == SAS_END_DEV || | 3071 | if (dev->dev_type == SAS_END_DEV || |
3077 | dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) { | 3072 | dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) { |
@@ -3291,8 +3286,7 @@ static enum sci_status isci_smp_request_build(struct isci_request *ireq) | |||
3291 | */ | 3286 | */ |
3292 | static enum sci_status isci_io_request_build(struct isci_host *isci_host, | 3287 | static enum sci_status isci_io_request_build(struct isci_host *isci_host, |
3293 | struct isci_request *request, | 3288 | struct isci_request *request, |
3294 | struct isci_remote_device *isci_device, | 3289 | struct isci_remote_device *isci_device) |
3295 | u16 tag) | ||
3296 | { | 3290 | { |
3297 | enum sci_status status = SCI_SUCCESS; | 3291 | enum sci_status status = SCI_SUCCESS; |
3298 | struct sas_task *task = isci_request_access_task(request); | 3292 | struct sas_task *task = isci_request_access_task(request); |
@@ -3325,11 +3319,8 @@ static enum sci_status isci_io_request_build(struct isci_host *isci_host, | |||
3325 | return SCI_FAILURE_INSUFFICIENT_RESOURCES; | 3319 | return SCI_FAILURE_INSUFFICIENT_RESOURCES; |
3326 | } | 3320 | } |
3327 | 3321 | ||
3328 | /* build the common request object. For now, | ||
3329 | * we will let the core allocate the IO tag. | ||
3330 | */ | ||
3331 | status = scic_io_request_construct(&isci_host->sci, sci_device, | 3322 | status = scic_io_request_construct(&isci_host->sci, sci_device, |
3332 | tag, &request->sci); | 3323 | &request->sci); |
3333 | 3324 | ||
3334 | if (status != SCI_SUCCESS) { | 3325 | if (status != SCI_SUCCESS) { |
3335 | dev_warn(&isci_host->pdev->dev, | 3326 | dev_warn(&isci_host->pdev->dev, |
@@ -3359,65 +3350,51 @@ static enum sci_status isci_io_request_build(struct isci_host *isci_host, | |||
3359 | return SCI_SUCCESS; | 3350 | return SCI_SUCCESS; |
3360 | } | 3351 | } |
3361 | 3352 | ||
3362 | static struct isci_request *isci_request_alloc_core(struct isci_host *ihost, | 3353 | static struct isci_request *isci_request_from_tag(struct isci_host *ihost, u16 tag) |
3363 | gfp_t gfp_flags) | ||
3364 | { | 3354 | { |
3365 | dma_addr_t handle; | ||
3366 | struct isci_request *ireq; | 3355 | struct isci_request *ireq; |
3367 | 3356 | ||
3368 | ireq = dma_pool_alloc(ihost->dma_pool, gfp_flags, &handle); | 3357 | ireq = ihost->reqs[ISCI_TAG_TCI(tag)]; |
3369 | if (!ireq) { | 3358 | ireq->sci.io_tag = tag; |
3370 | dev_warn(&ihost->pdev->dev, | ||
3371 | "%s: dma_pool_alloc returned NULL\n", __func__); | ||
3372 | return NULL; | ||
3373 | } | ||
3374 | |||
3375 | /* initialize the request object. */ | ||
3376 | spin_lock_init(&ireq->state_lock); | ||
3377 | ireq->request_daddr = handle; | ||
3378 | ireq->isci_host = ihost; | ||
3379 | ireq->io_request_completion = NULL; | 3359 | ireq->io_request_completion = NULL; |
3380 | ireq->flags = 0; | 3360 | ireq->flags = 0; |
3381 | ireq->num_sg_entries = 0; | 3361 | ireq->num_sg_entries = 0; |
3382 | INIT_LIST_HEAD(&ireq->completed_node); | 3362 | INIT_LIST_HEAD(&ireq->completed_node); |
3383 | INIT_LIST_HEAD(&ireq->dev_node); | 3363 | INIT_LIST_HEAD(&ireq->dev_node); |
3384 | |||
3385 | isci_request_change_state(ireq, allocated); | 3364 | isci_request_change_state(ireq, allocated); |
3386 | 3365 | ||
3387 | return ireq; | 3366 | return ireq; |
3388 | } | 3367 | } |
3389 | 3368 | ||
3390 | static struct isci_request *isci_request_alloc_io(struct isci_host *ihost, | 3369 | static struct isci_request *isci_io_request_from_tag(struct isci_host *ihost, |
3391 | struct sas_task *task, | 3370 | struct sas_task *task, |
3392 | gfp_t gfp_flags) | 3371 | u16 tag) |
3393 | { | 3372 | { |
3394 | struct isci_request *ireq; | 3373 | struct isci_request *ireq; |
3395 | 3374 | ||
3396 | ireq = isci_request_alloc_core(ihost, gfp_flags); | 3375 | ireq = isci_request_from_tag(ihost, tag); |
3397 | if (ireq) { | 3376 | ireq->ttype_ptr.io_task_ptr = task; |
3398 | ireq->ttype_ptr.io_task_ptr = task; | 3377 | ireq->ttype = io_task; |
3399 | ireq->ttype = io_task; | 3378 | task->lldd_task = ireq; |
3400 | task->lldd_task = ireq; | 3379 | |
3401 | } | ||
3402 | return ireq; | 3380 | return ireq; |
3403 | } | 3381 | } |
3404 | 3382 | ||
3405 | struct isci_request *isci_request_alloc_tmf(struct isci_host *ihost, | 3383 | struct isci_request *isci_tmf_request_from_tag(struct isci_host *ihost, |
3406 | struct isci_tmf *isci_tmf, | 3384 | struct isci_tmf *isci_tmf, |
3407 | gfp_t gfp_flags) | 3385 | u16 tag) |
3408 | { | 3386 | { |
3409 | struct isci_request *ireq; | 3387 | struct isci_request *ireq; |
3410 | 3388 | ||
3411 | ireq = isci_request_alloc_core(ihost, gfp_flags); | 3389 | ireq = isci_request_from_tag(ihost, tag); |
3412 | if (ireq) { | 3390 | ireq->ttype_ptr.tmf_task_ptr = isci_tmf; |
3413 | ireq->ttype_ptr.tmf_task_ptr = isci_tmf; | 3391 | ireq->ttype = tmf_task; |
3414 | ireq->ttype = tmf_task; | 3392 | |
3415 | } | ||
3416 | return ireq; | 3393 | return ireq; |
3417 | } | 3394 | } |
3418 | 3395 | ||
3419 | int isci_request_execute(struct isci_host *ihost, struct isci_remote_device *idev, | 3396 | int isci_request_execute(struct isci_host *ihost, struct isci_remote_device *idev, |
3420 | struct sas_task *task, u16 tag, gfp_t gfp_flags) | 3397 | struct sas_task *task, u16 tag) |
3421 | { | 3398 | { |
3422 | enum sci_status status = SCI_FAILURE_UNSUPPORTED_PROTOCOL; | 3399 | enum sci_status status = SCI_FAILURE_UNSUPPORTED_PROTOCOL; |
3423 | struct isci_request *ireq; | 3400 | struct isci_request *ireq; |
@@ -3425,17 +3402,15 @@ int isci_request_execute(struct isci_host *ihost, struct isci_remote_device *ide | |||
3425 | int ret = 0; | 3402 | int ret = 0; |
3426 | 3403 | ||
3427 | /* do common allocation and init of request object. */ | 3404 | /* do common allocation and init of request object. */ |
3428 | ireq = isci_request_alloc_io(ihost, task, gfp_flags); | 3405 | ireq = isci_io_request_from_tag(ihost, task, tag); |
3429 | if (!ireq) | ||
3430 | goto out; | ||
3431 | 3406 | ||
3432 | status = isci_io_request_build(ihost, ireq, idev, tag); | 3407 | status = isci_io_request_build(ihost, ireq, idev); |
3433 | if (status != SCI_SUCCESS) { | 3408 | if (status != SCI_SUCCESS) { |
3434 | dev_warn(&ihost->pdev->dev, | 3409 | dev_warn(&ihost->pdev->dev, |
3435 | "%s: request_construct failed - status = 0x%x\n", | 3410 | "%s: request_construct failed - status = 0x%x\n", |
3436 | __func__, | 3411 | __func__, |
3437 | status); | 3412 | status); |
3438 | goto out; | 3413 | return status; |
3439 | } | 3414 | } |
3440 | 3415 | ||
3441 | spin_lock_irqsave(&ihost->scic_lock, flags); | 3416 | spin_lock_irqsave(&ihost->scic_lock, flags); |
@@ -3468,7 +3443,7 @@ int isci_request_execute(struct isci_host *ihost, struct isci_remote_device *ide | |||
3468 | "%s: failed request start (0x%x)\n", | 3443 | "%s: failed request start (0x%x)\n", |
3469 | __func__, status); | 3444 | __func__, status); |
3470 | spin_unlock_irqrestore(&ihost->scic_lock, flags); | 3445 | spin_unlock_irqrestore(&ihost->scic_lock, flags); |
3471 | goto out; | 3446 | return status; |
3472 | } | 3447 | } |
3473 | 3448 | ||
3474 | /* Either I/O started OK, or the core has signaled that | 3449 | /* Either I/O started OK, or the core has signaled that |
@@ -3518,13 +3493,5 @@ int isci_request_execute(struct isci_host *ihost, struct isci_remote_device *ide | |||
3518 | status = SCI_SUCCESS; | 3493 | status = SCI_SUCCESS; |
3519 | } | 3494 | } |
3520 | 3495 | ||
3521 | out: | ||
3522 | if (status != SCI_SUCCESS) { | ||
3523 | /* release dma memory on failure. */ | ||
3524 | isci_request_free(ihost, ireq); | ||
3525 | ireq = NULL; | ||
3526 | ret = SCI_FAILURE; | ||
3527 | } | ||
3528 | |||
3529 | return ret; | 3496 | return ret; |
3530 | } | 3497 | } |