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 | |
| 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')
| -rw-r--r-- | drivers/scsi/isci/host.c | 70 | ||||
| -rw-r--r-- | drivers/scsi/isci/host.h | 11 | ||||
| -rw-r--r-- | drivers/scsi/isci/remote_device.c | 9 | ||||
| -rw-r--r-- | drivers/scsi/isci/request.c | 89 | ||||
| -rw-r--r-- | drivers/scsi/isci/request.h | 26 | ||||
| -rw-r--r-- | drivers/scsi/isci/task.c | 19 |
6 files changed, 85 insertions, 139 deletions
diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index c99fab53dd0c..0884ae3253e5 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c | |||
| @@ -255,14 +255,14 @@ static bool scic_sds_controller_error_isr(struct scic_sds_controller *scic) | |||
| 255 | static void scic_sds_controller_task_completion(struct scic_sds_controller *scic, | 255 | static void scic_sds_controller_task_completion(struct scic_sds_controller *scic, |
| 256 | u32 completion_entry) | 256 | u32 completion_entry) |
| 257 | { | 257 | { |
| 258 | u32 index; | 258 | u32 index = SCU_GET_COMPLETION_INDEX(completion_entry); |
| 259 | struct scic_sds_request *sci_req; | 259 | struct isci_host *ihost = scic_to_ihost(scic); |
| 260 | 260 | struct isci_request *ireq = ihost->reqs[index]; | |
| 261 | index = SCU_GET_COMPLETION_INDEX(completion_entry); | 261 | struct scic_sds_request *sci_req = &ireq->sci; |
| 262 | sci_req = scic->io_request_table[index]; | ||
| 263 | 262 | ||
| 264 | /* Make sure that we really want to process this IO request */ | 263 | /* Make sure that we really want to process this IO request */ |
| 265 | if (sci_req && sci_req->io_tag != SCI_CONTROLLER_INVALID_IO_TAG && | 264 | if (test_bit(IREQ_ACTIVE, &ireq->flags) && |
| 265 | sci_req->io_tag != SCI_CONTROLLER_INVALID_IO_TAG && | ||
| 266 | ISCI_TAG_SEQ(sci_req->io_tag) == scic->io_request_sequence[index]) | 266 | ISCI_TAG_SEQ(sci_req->io_tag) == scic->io_request_sequence[index]) |
| 267 | /* Yep this is a valid io request pass it along to the io request handler */ | 267 | /* Yep this is a valid io request pass it along to the io request handler */ |
| 268 | scic_sds_io_request_tc_completion(sci_req, completion_entry); | 268 | scic_sds_io_request_tc_completion(sci_req, completion_entry); |
| @@ -280,7 +280,7 @@ static void scic_sds_controller_sdma_completion(struct scic_sds_controller *scic | |||
| 280 | switch (scu_get_command_request_type(completion_entry)) { | 280 | switch (scu_get_command_request_type(completion_entry)) { |
| 281 | case SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC: | 281 | case SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC: |
| 282 | case SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_TC: | 282 | case SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_TC: |
| 283 | io_request = scic->io_request_table[index]; | 283 | io_request = &scic_to_ihost(scic)->reqs[index]->sci; |
| 284 | dev_warn(scic_to_dev(scic), | 284 | dev_warn(scic_to_dev(scic), |
| 285 | "%s: SCIC SDS Completion type SDMA %x for io request " | 285 | "%s: SCIC SDS Completion type SDMA %x for io request " |
| 286 | "%p\n", | 286 | "%p\n", |
| @@ -418,7 +418,7 @@ static void scic_sds_controller_event_completion(struct scic_sds_controller *sci | |||
| 418 | break; | 418 | break; |
| 419 | 419 | ||
| 420 | case SCU_EVENT_TYPE_TRANSPORT_ERROR: | 420 | case SCU_EVENT_TYPE_TRANSPORT_ERROR: |
| 421 | io_request = scic->io_request_table[index]; | 421 | io_request = &ihost->reqs[index]->sci; |
| 422 | scic_sds_io_request_event_handler(io_request, completion_entry); | 422 | scic_sds_io_request_event_handler(io_request, completion_entry); |
| 423 | break; | 423 | break; |
| 424 | 424 | ||
| @@ -426,7 +426,7 @@ static void scic_sds_controller_event_completion(struct scic_sds_controller *sci | |||
| 426 | switch (scu_get_event_specifier(completion_entry)) { | 426 | switch (scu_get_event_specifier(completion_entry)) { |
| 427 | case SCU_EVENT_SPECIFIC_SMP_RESPONSE_NO_PE: | 427 | case SCU_EVENT_SPECIFIC_SMP_RESPONSE_NO_PE: |
| 428 | case SCU_EVENT_SPECIFIC_TASK_TIMEOUT: | 428 | case SCU_EVENT_SPECIFIC_TASK_TIMEOUT: |
| 429 | io_request = scic->io_request_table[index]; | 429 | io_request = &ihost->reqs[index]->sci; |
| 430 | if (io_request != NULL) | 430 | if (io_request != NULL) |
| 431 | scic_sds_io_request_event_handler(io_request, completion_entry); | 431 | scic_sds_io_request_event_handler(io_request, completion_entry); |
| 432 | else | 432 | else |
| @@ -1187,9 +1187,6 @@ static void isci_host_completion_routine(unsigned long data) | |||
| 1187 | spin_lock_irq(&isci_host->scic_lock); | 1187 | spin_lock_irq(&isci_host->scic_lock); |
| 1188 | isci_free_tag(isci_host, request->sci.io_tag); | 1188 | isci_free_tag(isci_host, request->sci.io_tag); |
| 1189 | spin_unlock_irq(&isci_host->scic_lock); | 1189 | spin_unlock_irq(&isci_host->scic_lock); |
| 1190 | |||
| 1191 | /* Free the request object. */ | ||
| 1192 | isci_request_free(isci_host, request); | ||
| 1193 | } | 1190 | } |
| 1194 | list_for_each_entry_safe(request, next_request, &errored_request_list, | 1191 | list_for_each_entry_safe(request, next_request, &errored_request_list, |
| 1195 | completed_node) { | 1192 | completed_node) { |
| @@ -1227,9 +1224,6 @@ static void isci_host_completion_routine(unsigned long data) | |||
| 1227 | list_del_init(&request->dev_node); | 1224 | list_del_init(&request->dev_node); |
| 1228 | isci_free_tag(isci_host, request->sci.io_tag); | 1225 | isci_free_tag(isci_host, request->sci.io_tag); |
| 1229 | spin_unlock_irq(&isci_host->scic_lock); | 1226 | spin_unlock_irq(&isci_host->scic_lock); |
| 1230 | |||
| 1231 | /* Free the request object. */ | ||
| 1232 | isci_request_free(isci_host, request); | ||
| 1233 | } | 1227 | } |
| 1234 | } | 1228 | } |
| 1235 | 1229 | ||
| @@ -2469,13 +2463,6 @@ int isci_host_init(struct isci_host *isci_host) | |||
| 2469 | if (err) | 2463 | if (err) |
| 2470 | return err; | 2464 | return err; |
| 2471 | 2465 | ||
| 2472 | isci_host->dma_pool = dmam_pool_create(DRV_NAME, &isci_host->pdev->dev, | ||
| 2473 | sizeof(struct isci_request), | ||
| 2474 | SLAB_HWCACHE_ALIGN, 0); | ||
| 2475 | |||
| 2476 | if (!isci_host->dma_pool) | ||
| 2477 | return -ENOMEM; | ||
| 2478 | |||
| 2479 | for (i = 0; i < SCI_MAX_PORTS; i++) | 2466 | for (i = 0; i < SCI_MAX_PORTS; i++) |
| 2480 | isci_port_init(&isci_host->ports[i], isci_host, i); | 2467 | isci_port_init(&isci_host->ports[i], isci_host, i); |
| 2481 | 2468 | ||
| @@ -2489,6 +2476,25 @@ int isci_host_init(struct isci_host *isci_host) | |||
| 2489 | INIT_LIST_HEAD(&idev->node); | 2476 | INIT_LIST_HEAD(&idev->node); |
| 2490 | } | 2477 | } |
| 2491 | 2478 | ||
| 2479 | for (i = 0; i < SCI_MAX_IO_REQUESTS; i++) { | ||
| 2480 | struct isci_request *ireq; | ||
| 2481 | dma_addr_t dma; | ||
| 2482 | |||
| 2483 | ireq = dmam_alloc_coherent(&isci_host->pdev->dev, | ||
| 2484 | sizeof(struct isci_request), &dma, | ||
| 2485 | GFP_KERNEL); | ||
| 2486 | if (!ireq) | ||
| 2487 | return -ENOMEM; | ||
| 2488 | |||
| 2489 | ireq->sci.tc = &isci_host->sci.task_context_table[i]; | ||
| 2490 | ireq->sci.owning_controller = &isci_host->sci; | ||
| 2491 | spin_lock_init(&ireq->state_lock); | ||
| 2492 | ireq->request_daddr = dma; | ||
| 2493 | ireq->isci_host = isci_host; | ||
| 2494 | |||
| 2495 | isci_host->reqs[i] = ireq; | ||
| 2496 | } | ||
| 2497 | |||
| 2492 | return 0; | 2498 | return 0; |
| 2493 | } | 2499 | } |
| 2494 | 2500 | ||
| @@ -2602,12 +2608,13 @@ struct scic_sds_request *scic_request_by_tag(struct scic_sds_controller *scic, u | |||
| 2602 | task_index = ISCI_TAG_TCI(io_tag); | 2608 | task_index = ISCI_TAG_TCI(io_tag); |
| 2603 | 2609 | ||
| 2604 | if (task_index < scic->task_context_entries) { | 2610 | if (task_index < scic->task_context_entries) { |
| 2605 | if (scic->io_request_table[task_index] != NULL) { | 2611 | struct isci_request *ireq = scic_to_ihost(scic)->reqs[task_index]; |
| 2612 | |||
| 2613 | if (test_bit(IREQ_ACTIVE, &ireq->flags)) { | ||
| 2606 | task_sequence = ISCI_TAG_SEQ(io_tag); | 2614 | task_sequence = ISCI_TAG_SEQ(io_tag); |
| 2607 | 2615 | ||
| 2608 | if (task_sequence == scic->io_request_sequence[task_index]) { | 2616 | if (task_sequence == scic->io_request_sequence[task_index]) |
| 2609 | return scic->io_request_table[task_index]; | 2617 | return &ireq->sci; |
| 2610 | } | ||
| 2611 | } | 2618 | } |
| 2612 | } | 2619 | } |
| 2613 | 2620 | ||
| @@ -2820,7 +2827,7 @@ enum sci_status scic_controller_start_io(struct scic_sds_controller *scic, | |||
| 2820 | if (status != SCI_SUCCESS) | 2827 | if (status != SCI_SUCCESS) |
| 2821 | return status; | 2828 | return status; |
| 2822 | 2829 | ||
| 2823 | scic->io_request_table[ISCI_TAG_TCI(req->io_tag)] = req; | 2830 | set_bit(IREQ_ACTIVE, &sci_req_to_ireq(req)->flags); |
| 2824 | scic_sds_controller_post_request(scic, scic_sds_request_get_post_context(req)); | 2831 | scic_sds_controller_post_request(scic, scic_sds_request_get_post_context(req)); |
| 2825 | return SCI_SUCCESS; | 2832 | return SCI_SUCCESS; |
| 2826 | } | 2833 | } |
| @@ -2897,7 +2904,7 @@ enum sci_status scic_controller_complete_io( | |||
| 2897 | return status; | 2904 | return status; |
| 2898 | 2905 | ||
| 2899 | index = ISCI_TAG_TCI(request->io_tag); | 2906 | index = ISCI_TAG_TCI(request->io_tag); |
| 2900 | scic->io_request_table[index] = NULL; | 2907 | clear_bit(IREQ_ACTIVE, &sci_req_to_ireq(request)->flags); |
| 2901 | return SCI_SUCCESS; | 2908 | return SCI_SUCCESS; |
| 2902 | default: | 2909 | default: |
| 2903 | dev_warn(scic_to_dev(scic), "invalid state to complete I/O"); | 2910 | dev_warn(scic_to_dev(scic), "invalid state to complete I/O"); |
| @@ -2915,7 +2922,7 @@ enum sci_status scic_controller_continue_io(struct scic_sds_request *sci_req) | |||
| 2915 | return SCI_FAILURE_INVALID_STATE; | 2922 | return SCI_FAILURE_INVALID_STATE; |
| 2916 | } | 2923 | } |
| 2917 | 2924 | ||
| 2918 | scic->io_request_table[ISCI_TAG_TCI(sci_req->io_tag)] = sci_req; | 2925 | set_bit(IREQ_ACTIVE, &sci_req_to_ireq(sci_req)->flags); |
| 2919 | scic_sds_controller_post_request(scic, scic_sds_request_get_post_context(sci_req)); | 2926 | scic_sds_controller_post_request(scic, scic_sds_request_get_post_context(sci_req)); |
| 2920 | return SCI_SUCCESS; | 2927 | return SCI_SUCCESS; |
| 2921 | } | 2928 | } |
| @@ -2934,6 +2941,7 @@ enum sci_task_status scic_controller_start_task( | |||
| 2934 | struct scic_sds_remote_device *rdev, | 2941 | struct scic_sds_remote_device *rdev, |
| 2935 | struct scic_sds_request *req) | 2942 | struct scic_sds_request *req) |
| 2936 | { | 2943 | { |
| 2944 | struct isci_request *ireq = sci_req_to_ireq(req); | ||
| 2937 | enum sci_status status; | 2945 | enum sci_status status; |
| 2938 | 2946 | ||
| 2939 | if (scic->sm.current_state_id != SCIC_READY) { | 2947 | if (scic->sm.current_state_id != SCIC_READY) { |
| @@ -2947,7 +2955,7 @@ enum sci_task_status scic_controller_start_task( | |||
| 2947 | status = scic_sds_remote_device_start_task(scic, rdev, req); | 2955 | status = scic_sds_remote_device_start_task(scic, rdev, req); |
| 2948 | switch (status) { | 2956 | switch (status) { |
| 2949 | case SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS: | 2957 | case SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS: |
| 2950 | scic->io_request_table[ISCI_TAG_TCI(req->io_tag)] = req; | 2958 | set_bit(IREQ_ACTIVE, &ireq->flags); |
| 2951 | 2959 | ||
| 2952 | /* | 2960 | /* |
| 2953 | * We will let framework know this task request started successfully, | 2961 | * We will let framework know this task request started successfully, |
| @@ -2956,7 +2964,7 @@ enum sci_task_status scic_controller_start_task( | |||
| 2956 | */ | 2964 | */ |
| 2957 | return SCI_SUCCESS; | 2965 | return SCI_SUCCESS; |
| 2958 | case SCI_SUCCESS: | 2966 | case SCI_SUCCESS: |
| 2959 | scic->io_request_table[ISCI_TAG_TCI(req->io_tag)] = req; | 2967 | set_bit(IREQ_ACTIVE, &ireq->flags); |
| 2960 | 2968 | ||
| 2961 | scic_sds_controller_post_request(scic, | 2969 | scic_sds_controller_post_request(scic, |
| 2962 | scic_sds_request_get_post_context(req)); | 2970 | scic_sds_request_get_post_context(req)); |
diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index d8164f5d7988..446fade19b3a 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h | |||
| @@ -166,14 +166,6 @@ struct scic_sds_controller { | |||
| 166 | struct scic_sds_remote_device *device_table[SCI_MAX_REMOTE_DEVICES]; | 166 | struct scic_sds_remote_device *device_table[SCI_MAX_REMOTE_DEVICES]; |
| 167 | 167 | ||
| 168 | /** | 168 | /** |
| 169 | * This field is the array of IO request objects that are currently active for | ||
| 170 | * this controller object. This table is used as a fast lookup of the io | ||
| 171 | * request object that need to handle completion queue notifications. The | ||
| 172 | * table is TCi based. | ||
| 173 | */ | ||
| 174 | struct scic_sds_request *io_request_table[SCI_MAX_IO_REQUESTS]; | ||
| 175 | |||
| 176 | /** | ||
| 177 | * This field is the free RNi data structure | 169 | * This field is the free RNi data structure |
| 178 | */ | 170 | */ |
| 179 | struct scic_remote_node_table available_remote_nodes; | 171 | struct scic_remote_node_table available_remote_nodes; |
| @@ -298,7 +290,6 @@ struct isci_host { | |||
| 298 | union scic_oem_parameters oem_parameters; | 290 | union scic_oem_parameters oem_parameters; |
| 299 | 291 | ||
| 300 | int id; /* unique within a given pci device */ | 292 | int id; /* unique within a given pci device */ |
| 301 | struct dma_pool *dma_pool; | ||
| 302 | struct isci_phy phys[SCI_MAX_PHYS]; | 293 | struct isci_phy phys[SCI_MAX_PHYS]; |
| 303 | struct isci_port ports[SCI_MAX_PORTS + 1]; /* includes dummy port */ | 294 | struct isci_port ports[SCI_MAX_PORTS + 1]; /* includes dummy port */ |
| 304 | struct sas_ha_struct sas_ha; | 295 | struct sas_ha_struct sas_ha; |
| @@ -315,7 +306,7 @@ struct isci_host { | |||
| 315 | struct list_head requests_to_complete; | 306 | struct list_head requests_to_complete; |
| 316 | struct list_head requests_to_errorback; | 307 | struct list_head requests_to_errorback; |
| 317 | spinlock_t scic_lock; | 308 | spinlock_t scic_lock; |
| 318 | 309 | struct isci_request *reqs[SCI_MAX_IO_REQUESTS]; | |
| 319 | struct isci_remote_device devices[SCI_MAX_REMOTE_DEVICES]; | 310 | struct isci_remote_device devices[SCI_MAX_REMOTE_DEVICES]; |
| 320 | }; | 311 | }; |
| 321 | 312 | ||
diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index c5ce0f0f3645..5a86bb1e96df 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c | |||
| @@ -136,16 +136,19 @@ static void rnc_destruct_done(void *_dev) | |||
| 136 | static enum sci_status scic_sds_remote_device_terminate_requests(struct scic_sds_remote_device *sci_dev) | 136 | static enum sci_status scic_sds_remote_device_terminate_requests(struct scic_sds_remote_device *sci_dev) |
| 137 | { | 137 | { |
| 138 | struct scic_sds_controller *scic = sci_dev->owning_port->owning_controller; | 138 | struct scic_sds_controller *scic = sci_dev->owning_port->owning_controller; |
| 139 | struct isci_host *ihost = scic_to_ihost(scic); | ||
| 139 | u32 i, request_count = sci_dev->started_request_count; | 140 | u32 i, request_count = sci_dev->started_request_count; |
| 140 | enum sci_status status = SCI_SUCCESS; | 141 | enum sci_status status = SCI_SUCCESS; |
| 141 | 142 | ||
| 142 | for (i = 0; i < SCI_MAX_IO_REQUESTS && i < request_count; i++) { | 143 | for (i = 0; i < SCI_MAX_IO_REQUESTS && i < request_count; i++) { |
| 143 | struct scic_sds_request *sci_req; | 144 | struct isci_request *ireq = ihost->reqs[i]; |
| 145 | struct scic_sds_request *sci_req = &ireq->sci; | ||
| 144 | enum sci_status s; | 146 | enum sci_status s; |
| 145 | 147 | ||
| 146 | sci_req = scic->io_request_table[i]; | 148 | if (!test_bit(IREQ_ACTIVE, &ireq->flags) || |
| 147 | if (!sci_req || sci_req->target_device != sci_dev) | 149 | sci_req->target_device != sci_dev) |
| 148 | continue; | 150 | continue; |
| 151 | |||
| 149 | s = scic_controller_terminate_request(scic, sci_dev, sci_req); | 152 | s = scic_controller_terminate_request(scic, sci_dev, sci_req); |
| 150 | if (s != SCI_SUCCESS) | 153 | if (s != SCI_SUCCESS) |
| 151 | status = s; | 154 | status = s; |
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 | } |
diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h index f440e421ea0e..7628decbd535 100644 --- a/drivers/scsi/isci/request.h +++ b/drivers/scsi/isci/request.h | |||
| @@ -257,6 +257,7 @@ struct isci_request { | |||
| 257 | #define IREQ_COMPLETE_IN_TARGET 0 | 257 | #define IREQ_COMPLETE_IN_TARGET 0 |
| 258 | #define IREQ_TERMINATED 1 | 258 | #define IREQ_TERMINATED 1 |
| 259 | #define IREQ_TMF 2 | 259 | #define IREQ_TMF 2 |
| 260 | #define IREQ_ACTIVE 3 | ||
| 260 | unsigned long flags; | 261 | unsigned long flags; |
| 261 | 262 | ||
| 262 | union ttype_ptr_union { | 263 | union ttype_ptr_union { |
| @@ -590,33 +591,16 @@ isci_request_change_started_to_aborted(struct isci_request *isci_request, | |||
| 590 | completion_ptr, | 591 | completion_ptr, |
| 591 | aborted); | 592 | aborted); |
| 592 | } | 593 | } |
| 593 | /** | ||
| 594 | * isci_request_free() - This function frees the request object. | ||
| 595 | * @isci_host: This parameter specifies the ISCI host object | ||
| 596 | * @isci_request: This parameter points to the isci_request object | ||
| 597 | * | ||
| 598 | */ | ||
| 599 | static inline void isci_request_free(struct isci_host *isci_host, | ||
| 600 | struct isci_request *isci_request) | ||
| 601 | { | ||
| 602 | if (!isci_request) | ||
| 603 | return; | ||
| 604 | |||
| 605 | /* release the dma memory if we fail. */ | ||
| 606 | dma_pool_free(isci_host->dma_pool, | ||
| 607 | isci_request, | ||
| 608 | isci_request->request_daddr); | ||
| 609 | } | ||
| 610 | 594 | ||
| 611 | #define isci_request_access_task(req) ((req)->ttype_ptr.io_task_ptr) | 595 | #define isci_request_access_task(req) ((req)->ttype_ptr.io_task_ptr) |
| 612 | 596 | ||
| 613 | #define isci_request_access_tmf(req) ((req)->ttype_ptr.tmf_task_ptr) | 597 | #define isci_request_access_tmf(req) ((req)->ttype_ptr.tmf_task_ptr) |
| 614 | 598 | ||
| 615 | struct isci_request *isci_request_alloc_tmf(struct isci_host *ihost, | 599 | struct isci_request *isci_tmf_request_from_tag(struct isci_host *ihost, |
| 616 | struct isci_tmf *isci_tmf, | 600 | struct isci_tmf *isci_tmf, |
| 617 | gfp_t gfp_flags); | 601 | u16 tag); |
| 618 | int isci_request_execute(struct isci_host *ihost, struct isci_remote_device *idev, | 602 | int isci_request_execute(struct isci_host *ihost, struct isci_remote_device *idev, |
| 619 | struct sas_task *task, u16 tag, gfp_t gfp_flags); | 603 | struct sas_task *task, u16 tag); |
| 620 | void isci_terminate_pending_requests(struct isci_host *ihost, | 604 | void isci_terminate_pending_requests(struct isci_host *ihost, |
| 621 | struct isci_remote_device *idev); | 605 | struct isci_remote_device *idev); |
| 622 | enum sci_status | 606 | enum sci_status |
diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index d1a46710f4a7..d2dba8354899 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c | |||
| @@ -203,7 +203,7 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) | |||
| 203 | spin_unlock_irqrestore(&task->task_state_lock, flags); | 203 | spin_unlock_irqrestore(&task->task_state_lock, flags); |
| 204 | 204 | ||
| 205 | /* build and send the request. */ | 205 | /* build and send the request. */ |
| 206 | status = isci_request_execute(ihost, idev, task, tag, gfp_flags); | 206 | status = isci_request_execute(ihost, idev, task, tag); |
| 207 | 207 | ||
| 208 | if (status != SCI_SUCCESS) { | 208 | if (status != SCI_SUCCESS) { |
| 209 | 209 | ||
| @@ -252,7 +252,7 @@ static struct isci_request *isci_task_request_build(struct isci_host *ihost, | |||
| 252 | dev = idev->domain_dev; | 252 | dev = idev->domain_dev; |
| 253 | 253 | ||
| 254 | /* do common allocation and init of request object. */ | 254 | /* do common allocation and init of request object. */ |
| 255 | ireq = isci_request_alloc_tmf(ihost, isci_tmf, GFP_ATOMIC); | 255 | ireq = isci_tmf_request_from_tag(ihost, isci_tmf, tag); |
| 256 | if (!ireq) | 256 | if (!ireq) |
| 257 | return NULL; | 257 | return NULL; |
| 258 | 258 | ||
| @@ -266,7 +266,7 @@ static struct isci_request *isci_task_request_build(struct isci_host *ihost, | |||
| 266 | "status = 0x%x\n", | 266 | "status = 0x%x\n", |
| 267 | __func__, | 267 | __func__, |
| 268 | status); | 268 | status); |
| 269 | goto errout; | 269 | return NULL; |
| 270 | } | 270 | } |
| 271 | 271 | ||
| 272 | /* XXX convert to get this from task->tproto like other drivers */ | 272 | /* XXX convert to get this from task->tproto like other drivers */ |
| @@ -274,7 +274,7 @@ static struct isci_request *isci_task_request_build(struct isci_host *ihost, | |||
| 274 | isci_tmf->proto = SAS_PROTOCOL_SSP; | 274 | isci_tmf->proto = SAS_PROTOCOL_SSP; |
| 275 | status = scic_task_request_construct_ssp(&ireq->sci); | 275 | status = scic_task_request_construct_ssp(&ireq->sci); |
| 276 | if (status != SCI_SUCCESS) | 276 | if (status != SCI_SUCCESS) |
| 277 | goto errout; | 277 | return NULL; |
| 278 | } | 278 | } |
| 279 | 279 | ||
| 280 | if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) { | 280 | if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) { |
| @@ -282,12 +282,9 @@ static struct isci_request *isci_task_request_build(struct isci_host *ihost, | |||
| 282 | status = isci_sata_management_task_request_build(ireq); | 282 | status = isci_sata_management_task_request_build(ireq); |
| 283 | 283 | ||
| 284 | if (status != SCI_SUCCESS) | 284 | if (status != SCI_SUCCESS) |
| 285 | goto errout; | 285 | return NULL; |
| 286 | } | 286 | } |
| 287 | return ireq; | 287 | return ireq; |
| 288 | errout: | ||
| 289 | isci_request_free(ihost, ireq); | ||
| 290 | return NULL; | ||
| 291 | } | 288 | } |
| 292 | 289 | ||
| 293 | int isci_task_execute_tmf(struct isci_host *ihost, | 290 | int isci_task_execute_tmf(struct isci_host *ihost, |
| @@ -349,7 +346,7 @@ int isci_task_execute_tmf(struct isci_host *ihost, | |||
| 349 | status, | 346 | status, |
| 350 | ireq); | 347 | ireq); |
| 351 | spin_unlock_irqrestore(&ihost->scic_lock, flags); | 348 | spin_unlock_irqrestore(&ihost->scic_lock, flags); |
| 352 | goto err_ireq; | 349 | goto err_tci; |
| 353 | } | 350 | } |
| 354 | 351 | ||
| 355 | if (tmf->cb_state_func != NULL) | 352 | if (tmf->cb_state_func != NULL) |
| @@ -401,8 +398,6 @@ int isci_task_execute_tmf(struct isci_host *ihost, | |||
| 401 | 398 | ||
| 402 | return ret; | 399 | return ret; |
| 403 | 400 | ||
| 404 | err_ireq: | ||
| 405 | isci_request_free(ihost, ireq); | ||
| 406 | err_tci: | 401 | err_tci: |
| 407 | spin_lock_irqsave(&ihost->scic_lock, flags); | 402 | spin_lock_irqsave(&ihost->scic_lock, flags); |
| 408 | isci_tci_free(ihost, ISCI_TAG_TCI(tag)); | 403 | isci_tci_free(ihost, ISCI_TAG_TCI(tag)); |
| @@ -516,8 +511,6 @@ static void isci_request_cleanup_completed_loiterer( | |||
| 516 | spin_lock_irqsave(&isci_host->scic_lock, flags); | 511 | spin_lock_irqsave(&isci_host->scic_lock, flags); |
| 517 | list_del_init(&isci_request->dev_node); | 512 | list_del_init(&isci_request->dev_node); |
| 518 | spin_unlock_irqrestore(&isci_host->scic_lock, flags); | 513 | spin_unlock_irqrestore(&isci_host->scic_lock, flags); |
| 519 | |||
| 520 | isci_request_free(isci_host, isci_request); | ||
| 521 | } | 514 | } |
| 522 | } | 515 | } |
| 523 | 516 | ||
