diff options
Diffstat (limited to 'drivers/scsi/mpt2sas/mpt2sas_base.c')
-rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_base.c | 87 |
1 files changed, 70 insertions, 17 deletions
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index 0e30827d44e7..c8f39f8c6fed 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c @@ -65,7 +65,6 @@ static MPT_CALLBACK mpt_callbacks[MPT_MAX_CALLBACKS]; #define FAULT_POLLING_INTERVAL 1000 /* in milliseconds */ -#define MPT2SAS_MAX_REQUEST_QUEUE 600 /* maximum controller queue depth */ static int max_queue_depth = -1; module_param(max_queue_depth, int, 0); @@ -1497,6 +1496,7 @@ mpt2sas_base_free_smid(struct MPT2SAS_ADAPTER *ioc, u16 smid) { unsigned long flags; int i; + struct chain_tracker *chain_req, *next; spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); if (smid >= ioc->hi_priority_smid) { @@ -1519,6 +1519,14 @@ mpt2sas_base_free_smid(struct MPT2SAS_ADAPTER *ioc, u16 smid) /* scsiio queue */ i = smid - 1; + if (!list_empty(&ioc->scsi_lookup[i].chain_list)) { + list_for_each_entry_safe(chain_req, next, + &ioc->scsi_lookup[i].chain_list, tracker_list) { + list_del_init(&chain_req->tracker_list); + list_add_tail(&chain_req->tracker_list, + &ioc->free_chain_list); + } + } ioc->scsi_lookup[i].cb_idx = 0xFF; ioc->scsi_lookup[i].scmd = NULL; list_add_tail(&ioc->scsi_lookup[i].tracker_list, @@ -1968,6 +1976,8 @@ _base_static_config_pages(struct MPT2SAS_ADAPTER *ioc) static void _base_release_memory_pools(struct MPT2SAS_ADAPTER *ioc) { + int i; + dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__)); @@ -2032,6 +2042,20 @@ _base_release_memory_pools(struct MPT2SAS_ADAPTER *ioc) } kfree(ioc->hpr_lookup); kfree(ioc->internal_lookup); + if (ioc->chain_lookup) { + for (i = 0; i < ioc->chain_depth; i++) { + if (ioc->chain_lookup[i].chain_buffer) + pci_pool_free(ioc->chain_dma_pool, + ioc->chain_lookup[i].chain_buffer, + ioc->chain_lookup[i].chain_buffer_dma); + } + if (ioc->chain_dma_pool) + pci_pool_destroy(ioc->chain_dma_pool); + } + if (ioc->chain_lookup) { + free_pages((ulong)ioc->chain_lookup, ioc->chain_pages); + ioc->chain_lookup = NULL; + } } @@ -2053,6 +2077,7 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) u32 sz, total_sz; u32 retry_sz; u16 max_request_credit; + int i; dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__)); @@ -2070,14 +2095,11 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) } /* command line tunables for max controller queue depth */ - if (max_queue_depth != -1) { + if (max_queue_depth != -1) max_request_credit = (max_queue_depth < facts->RequestCredit) ? max_queue_depth : facts->RequestCredit; - } else { - max_request_credit = (facts->RequestCredit > - MPT2SAS_MAX_REQUEST_QUEUE) ? MPT2SAS_MAX_REQUEST_QUEUE : - facts->RequestCredit; - } + else + max_request_credit = facts->RequestCredit; ioc->hba_queue_depth = max_request_credit; ioc->hi_priority_depth = facts->HighPriorityCredit; @@ -2183,7 +2205,7 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) * "frame for smid=0 */ ioc->chain_depth = ioc->chains_needed_per_io * ioc->scsiio_depth; - sz = ((ioc->scsiio_depth + 1 + ioc->chain_depth) * ioc->request_sz); + sz = ((ioc->scsiio_depth + 1) * ioc->request_sz); /* hi-priority queue */ sz += (ioc->hi_priority_depth * ioc->request_sz); @@ -2224,19 +2246,11 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) ioc->internal_dma = ioc->hi_priority_dma + (ioc->hi_priority_depth * ioc->request_sz); - ioc->chain = ioc->internal + (ioc->internal_depth * - ioc->request_sz); - ioc->chain_dma = ioc->internal_dma + (ioc->internal_depth * - ioc->request_sz); dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "request pool(0x%p): " "depth(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name, ioc->request, ioc->hba_queue_depth, ioc->request_sz, (ioc->hba_queue_depth * ioc->request_sz)/1024)); - dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "chain pool(0x%p): depth" - "(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name, ioc->chain, - ioc->chain_depth, ioc->request_sz, ((ioc->chain_depth * - ioc->request_sz))/1024)); dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "request pool: dma(0x%llx)\n", ioc->name, (unsigned long long) ioc->request_dma)); total_sz += sz; @@ -2255,6 +2269,38 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) "depth(%d)\n", ioc->name, ioc->request, ioc->scsiio_depth)); + /* loop till the allocation succeeds */ + do { + sz = ioc->chain_depth * sizeof(struct chain_tracker); + ioc->chain_pages = get_order(sz); + ioc->chain_lookup = (struct chain_tracker *)__get_free_pages( + GFP_KERNEL, ioc->chain_pages); + if (ioc->chain_lookup == NULL) + ioc->chain_depth -= 100; + } while (ioc->chain_lookup == NULL); + ioc->chain_dma_pool = pci_pool_create("chain pool", ioc->pdev, + ioc->request_sz, 16, 0); + if (!ioc->chain_dma_pool) { + printk(MPT2SAS_ERR_FMT "chain_dma_pool: pci_pool_create " + "failed\n", ioc->name); + goto out; + } + for (i = 0; i < ioc->chain_depth; i++) { + ioc->chain_lookup[i].chain_buffer = pci_pool_alloc( + ioc->chain_dma_pool , GFP_KERNEL, + &ioc->chain_lookup[i].chain_buffer_dma); + if (!ioc->chain_lookup[i].chain_buffer) { + ioc->chain_depth = i; + goto chain_done; + } + total_sz += ioc->request_sz; + } +chain_done: + dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "chain pool depth" + "(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name, + ioc->chain_depth, ioc->request_sz, ((ioc->chain_depth * + ioc->request_sz))/1024)); + /* initialize hi-priority queue smid's */ ioc->hpr_lookup = kcalloc(ioc->hi_priority_depth, sizeof(struct request_tracker), GFP_KERNEL); @@ -2404,7 +2450,6 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) return 0; out: - _base_release_memory_pools(ioc); return -ENOMEM; } @@ -3587,6 +3632,7 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) INIT_LIST_HEAD(&ioc->free_list); smid = 1; for (i = 0; i < ioc->scsiio_depth; i++, smid++) { + INIT_LIST_HEAD(&ioc->scsi_lookup[i].chain_list); ioc->scsi_lookup[i].cb_idx = 0xFF; ioc->scsi_lookup[i].smid = smid; ioc->scsi_lookup[i].scmd = NULL; @@ -3613,6 +3659,13 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) list_add_tail(&ioc->internal_lookup[i].tracker_list, &ioc->internal_free_list); } + + /* chain pool */ + INIT_LIST_HEAD(&ioc->free_chain_list); + for (i = 0; i < ioc->chain_depth; i++) + list_add_tail(&ioc->chain_lookup[i].tracker_list, + &ioc->free_chain_list); + spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); /* initialize Reply Free Queue */ |