[SCSI] mpt2sas: Create a pool of chain buffer instead of dedicated per IOs
Create a pool of chain buffers, instead of dedicated per IO: This enahancment is to address memory allocation failure when asking for more than 2300 IOs per host. There is just not enough contiquious DMA physical memory to make one single allocation to hold both message frames and chain buffers when asking for more than 2300 request. In order to address this problem we will have to allocate memory for each chain buffer in a seperate individual memory allocation, placing each chain element of 128 bytes onto a pool of available chains, which can be shared amoung all request. Signed-off-by: Kashyap Desai <kashyap.desai@lsi.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
This commit is contained in:
committed by
James Bottomley
parent
6cb8ef573f
commit
35f805b52c
@ -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 */
|
||||
|
Reference in New Issue
Block a user