aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authornagalakshmi.nandigama@lsi.com <nagalakshmi.nandigama@lsi.com>2011-11-30 21:23:08 -0500
committerJames Bottomley <JBottomley@Parallels.com>2011-12-15 01:57:39 -0500
commitaff132d95ffe14eca96cab90597cdd010b457af7 (patch)
tree652c0f0babc3c70fd6f91962318ff96e5bd0034d /drivers/scsi
parent4da7af9494b2f98a1503a2634059300c3e4615e6 (diff)
[SCSI] mpt2sas : Fix for memory allocation error for large host credits
The amount of memory required for tracking chain buffers is rather large, and when the host credit count is big, memory allocation failure occurs inside __get_free_pages. The fix is to limit the number of chains to 100,000. In addition, the number of host credits is limited to 30,000 IOs. However this limitation can be overridden this using the command line option max_queue_depth. The algorithm for calculating the reply_post_queue_depth is changed so that it is equal to (reply_free_queue_depth + 16), previously it was (reply_free_queue_depth * 2). Signed-off-by: Nagalakshmi Nandigama <nagalakshmi.nandigama@lsi.com> Cc: stable@kernel.org Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.c83
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_scsih.c4
2 files changed, 29 insertions, 58 deletions
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c
index c0526878a337..961b11ea8c04 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.c
@@ -66,6 +66,8 @@ static MPT_CALLBACK mpt_callbacks[MPT_MAX_CALLBACKS];
66 66
67#define FAULT_POLLING_INTERVAL 1000 /* in milliseconds */ 67#define FAULT_POLLING_INTERVAL 1000 /* in milliseconds */
68 68
69#define MAX_HBA_QUEUE_DEPTH 30000
70#define MAX_CHAIN_DEPTH 100000
69static int max_queue_depth = -1; 71static int max_queue_depth = -1;
70module_param(max_queue_depth, int, 0); 72module_param(max_queue_depth, int, 0);
71MODULE_PARM_DESC(max_queue_depth, " max controller queue depth "); 73MODULE_PARM_DESC(max_queue_depth, " max controller queue depth ");
@@ -2390,8 +2392,6 @@ _base_release_memory_pools(struct MPT2SAS_ADAPTER *ioc)
2390 } 2392 }
2391 if (ioc->chain_dma_pool) 2393 if (ioc->chain_dma_pool)
2392 pci_pool_destroy(ioc->chain_dma_pool); 2394 pci_pool_destroy(ioc->chain_dma_pool);
2393 }
2394 if (ioc->chain_lookup) {
2395 free_pages((ulong)ioc->chain_lookup, ioc->chain_pages); 2395 free_pages((ulong)ioc->chain_lookup, ioc->chain_pages);
2396 ioc->chain_lookup = NULL; 2396 ioc->chain_lookup = NULL;
2397 } 2397 }
@@ -2409,9 +2409,7 @@ static int
2409_base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) 2409_base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
2410{ 2410{
2411 struct mpt2sas_facts *facts; 2411 struct mpt2sas_facts *facts;
2412 u32 queue_size, queue_diff;
2413 u16 max_sge_elements; 2412 u16 max_sge_elements;
2414 u16 num_of_reply_frames;
2415 u16 chains_needed_per_io; 2413 u16 chains_needed_per_io;
2416 u32 sz, total_sz, reply_post_free_sz; 2414 u32 sz, total_sz, reply_post_free_sz;
2417 u32 retry_sz; 2415 u32 retry_sz;
@@ -2438,7 +2436,8 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
2438 max_request_credit = (max_queue_depth < facts->RequestCredit) 2436 max_request_credit = (max_queue_depth < facts->RequestCredit)
2439 ? max_queue_depth : facts->RequestCredit; 2437 ? max_queue_depth : facts->RequestCredit;
2440 else 2438 else
2441 max_request_credit = facts->RequestCredit; 2439 max_request_credit = min_t(u16, facts->RequestCredit,
2440 MAX_HBA_QUEUE_DEPTH);
2442 2441
2443 ioc->hba_queue_depth = max_request_credit; 2442 ioc->hba_queue_depth = max_request_credit;
2444 ioc->hi_priority_depth = facts->HighPriorityCredit; 2443 ioc->hi_priority_depth = facts->HighPriorityCredit;
@@ -2479,50 +2478,25 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
2479 } 2478 }
2480 ioc->chains_needed_per_io = chains_needed_per_io; 2479 ioc->chains_needed_per_io = chains_needed_per_io;
2481 2480
2482 /* reply free queue sizing - taking into account for events */ 2481 /* reply free queue sizing - taking into account for 64 FW events */
2483 num_of_reply_frames = ioc->hba_queue_depth + 32; 2482 ioc->reply_free_queue_depth = ioc->hba_queue_depth + 64;
2484
2485 /* number of replies frames can't be a multiple of 16 */
2486 /* decrease number of reply frames by 1 */
2487 if (!(num_of_reply_frames % 16))
2488 num_of_reply_frames--;
2489
2490 /* calculate number of reply free queue entries
2491 * (must be multiple of 16)
2492 */
2493
2494 /* (we know reply_free_queue_depth is not a multiple of 16) */
2495 queue_size = num_of_reply_frames;
2496 queue_size += 16 - (queue_size % 16);
2497 ioc->reply_free_queue_depth = queue_size;
2498
2499 /* reply descriptor post queue sizing */
2500 /* this size should be the number of request frames + number of reply
2501 * frames
2502 */
2503
2504 queue_size = ioc->hba_queue_depth + num_of_reply_frames + 1;
2505 /* round up to 16 byte boundary */
2506 if (queue_size % 16)
2507 queue_size += 16 - (queue_size % 16);
2508
2509 /* check against IOC maximum reply post queue depth */
2510 if (queue_size > facts->MaxReplyDescriptorPostQueueDepth) {
2511 queue_diff = queue_size -
2512 facts->MaxReplyDescriptorPostQueueDepth;
2513 2483
2514 /* round queue_diff up to multiple of 16 */ 2484 /* align the reply post queue on the next 16 count boundary */
2515 if (queue_diff % 16) 2485 if (!ioc->reply_free_queue_depth % 16)
2516 queue_diff += 16 - (queue_diff % 16); 2486 ioc->reply_post_queue_depth = ioc->reply_free_queue_depth + 16;
2517 2487 else
2518 /* adjust hba_queue_depth, reply_free_queue_depth, 2488 ioc->reply_post_queue_depth = ioc->reply_free_queue_depth +
2519 * and queue_size 2489 32 - (ioc->reply_free_queue_depth % 16);
2520 */ 2490 if (ioc->reply_post_queue_depth >
2521 ioc->hba_queue_depth -= (queue_diff / 2); 2491 facts->MaxReplyDescriptorPostQueueDepth) {
2522 ioc->reply_free_queue_depth -= (queue_diff / 2); 2492 ioc->reply_post_queue_depth = min_t(u16,
2523 queue_size = facts->MaxReplyDescriptorPostQueueDepth; 2493 (facts->MaxReplyDescriptorPostQueueDepth -
2494 (facts->MaxReplyDescriptorPostQueueDepth % 16)),
2495 (ioc->hba_queue_depth - (ioc->hba_queue_depth % 16)));
2496 ioc->reply_free_queue_depth = ioc->reply_post_queue_depth - 16;
2497 ioc->hba_queue_depth = ioc->reply_free_queue_depth - 64;
2524 } 2498 }
2525 ioc->reply_post_queue_depth = queue_size; 2499
2526 2500
2527 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "scatter gather: " 2501 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "scatter gather: "
2528 "sge_in_main_msg(%d), sge_per_chain(%d), sge_per_io(%d), " 2502 "sge_in_main_msg(%d), sge_per_chain(%d), sge_per_io(%d), "
@@ -2608,15 +2582,12 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
2608 "depth(%d)\n", ioc->name, ioc->request, 2582 "depth(%d)\n", ioc->name, ioc->request,
2609 ioc->scsiio_depth)); 2583 ioc->scsiio_depth));
2610 2584
2611 /* loop till the allocation succeeds */ 2585 ioc->chain_depth = min_t(u32, ioc->chain_depth, MAX_CHAIN_DEPTH);
2612 do { 2586 sz = ioc->chain_depth * sizeof(struct chain_tracker);
2613 sz = ioc->chain_depth * sizeof(struct chain_tracker); 2587 ioc->chain_pages = get_order(sz);
2614 ioc->chain_pages = get_order(sz); 2588
2615 ioc->chain_lookup = (struct chain_tracker *)__get_free_pages( 2589 ioc->chain_lookup = (struct chain_tracker *)__get_free_pages(
2616 GFP_KERNEL, ioc->chain_pages); 2590 GFP_KERNEL, ioc->chain_pages);
2617 if (ioc->chain_lookup == NULL)
2618 ioc->chain_depth -= 100;
2619 } while (ioc->chain_lookup == NULL);
2620 ioc->chain_dma_pool = pci_pool_create("chain pool", ioc->pdev, 2591 ioc->chain_dma_pool = pci_pool_create("chain pool", ioc->pdev,
2621 ioc->request_sz, 16, 0); 2592 ioc->request_sz, 16, 0);
2622 if (!ioc->chain_dma_pool) { 2593 if (!ioc->chain_dma_pool) {
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
index fd1ba744b423..8cd4ebb9349f 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
@@ -1011,8 +1011,8 @@ _scsih_get_chain_buffer_tracker(struct MPT2SAS_ADAPTER *ioc, u16 smid)
1011 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); 1011 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
1012 if (list_empty(&ioc->free_chain_list)) { 1012 if (list_empty(&ioc->free_chain_list)) {
1013 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); 1013 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1014 printk(MPT2SAS_WARN_FMT "chain buffers not available\n", 1014 dfailprintk(ioc, printk(MPT2SAS_WARN_FMT "chain buffers not "
1015 ioc->name); 1015 "available\n", ioc->name));
1016 return NULL; 1016 return NULL;
1017 } 1017 }
1018 chain_req = list_entry(ioc->free_chain_list.next, 1018 chain_req = list_entry(ioc->free_chain_list.next,