aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorKashyap, Desai <kashyap.desai@lsi.com>2010-11-12 18:04:06 -0500
committerJames Bottomley <James.Bottomley@suse.de>2010-12-21 13:24:04 -0500
commit35f805b52c94f8e6cb22907ef32517132a15cb96 (patch)
treeeb26ec6db8b4093d5659eb0f351b1dbc228c5359 /drivers/scsi
parent6cb8ef573fd4c2bd72248f492fe336133660148d (diff)
[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>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.c87
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.h19
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_scsih.c56
3 files changed, 119 insertions, 43 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 @@
65static MPT_CALLBACK mpt_callbacks[MPT_MAX_CALLBACKS]; 65static 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#define MPT2SAS_MAX_REQUEST_QUEUE 600 /* maximum controller queue depth */
69 68
70static int max_queue_depth = -1; 69static int max_queue_depth = -1;
71module_param(max_queue_depth, int, 0); 70module_param(max_queue_depth, int, 0);
@@ -1497,6 +1496,7 @@ mpt2sas_base_free_smid(struct MPT2SAS_ADAPTER *ioc, u16 smid)
1497{ 1496{
1498 unsigned long flags; 1497 unsigned long flags;
1499 int i; 1498 int i;
1499 struct chain_tracker *chain_req, *next;
1500 1500
1501 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); 1501 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
1502 if (smid >= ioc->hi_priority_smid) { 1502 if (smid >= ioc->hi_priority_smid) {
@@ -1519,6 +1519,14 @@ mpt2sas_base_free_smid(struct MPT2SAS_ADAPTER *ioc, u16 smid)
1519 1519
1520 /* scsiio queue */ 1520 /* scsiio queue */
1521 i = smid - 1; 1521 i = smid - 1;
1522 if (!list_empty(&ioc->scsi_lookup[i].chain_list)) {
1523 list_for_each_entry_safe(chain_req, next,
1524 &ioc->scsi_lookup[i].chain_list, tracker_list) {
1525 list_del_init(&chain_req->tracker_list);
1526 list_add_tail(&chain_req->tracker_list,
1527 &ioc->free_chain_list);
1528 }
1529 }
1522 ioc->scsi_lookup[i].cb_idx = 0xFF; 1530 ioc->scsi_lookup[i].cb_idx = 0xFF;
1523 ioc->scsi_lookup[i].scmd = NULL; 1531 ioc->scsi_lookup[i].scmd = NULL;
1524 list_add_tail(&ioc->scsi_lookup[i].tracker_list, 1532 list_add_tail(&ioc->scsi_lookup[i].tracker_list,
@@ -1968,6 +1976,8 @@ _base_static_config_pages(struct MPT2SAS_ADAPTER *ioc)
1968static void 1976static void
1969_base_release_memory_pools(struct MPT2SAS_ADAPTER *ioc) 1977_base_release_memory_pools(struct MPT2SAS_ADAPTER *ioc)
1970{ 1978{
1979 int i;
1980
1971 dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, 1981 dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
1972 __func__)); 1982 __func__));
1973 1983
@@ -2032,6 +2042,20 @@ _base_release_memory_pools(struct MPT2SAS_ADAPTER *ioc)
2032 } 2042 }
2033 kfree(ioc->hpr_lookup); 2043 kfree(ioc->hpr_lookup);
2034 kfree(ioc->internal_lookup); 2044 kfree(ioc->internal_lookup);
2045 if (ioc->chain_lookup) {
2046 for (i = 0; i < ioc->chain_depth; i++) {
2047 if (ioc->chain_lookup[i].chain_buffer)
2048 pci_pool_free(ioc->chain_dma_pool,
2049 ioc->chain_lookup[i].chain_buffer,
2050 ioc->chain_lookup[i].chain_buffer_dma);
2051 }
2052 if (ioc->chain_dma_pool)
2053 pci_pool_destroy(ioc->chain_dma_pool);
2054 }
2055 if (ioc->chain_lookup) {
2056 free_pages((ulong)ioc->chain_lookup, ioc->chain_pages);
2057 ioc->chain_lookup = NULL;
2058 }
2035} 2059}
2036 2060
2037 2061
@@ -2053,6 +2077,7 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
2053 u32 sz, total_sz; 2077 u32 sz, total_sz;
2054 u32 retry_sz; 2078 u32 retry_sz;
2055 u16 max_request_credit; 2079 u16 max_request_credit;
2080 int i;
2056 2081
2057 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, 2082 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
2058 __func__)); 2083 __func__));
@@ -2070,14 +2095,11 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
2070 } 2095 }
2071 2096
2072 /* command line tunables for max controller queue depth */ 2097 /* command line tunables for max controller queue depth */
2073 if (max_queue_depth != -1) { 2098 if (max_queue_depth != -1)
2074 max_request_credit = (max_queue_depth < facts->RequestCredit) 2099 max_request_credit = (max_queue_depth < facts->RequestCredit)
2075 ? max_queue_depth : facts->RequestCredit; 2100 ? max_queue_depth : facts->RequestCredit;
2076 } else { 2101 else
2077 max_request_credit = (facts->RequestCredit > 2102 max_request_credit = facts->RequestCredit;
2078 MPT2SAS_MAX_REQUEST_QUEUE) ? MPT2SAS_MAX_REQUEST_QUEUE :
2079 facts->RequestCredit;
2080 }
2081 2103
2082 ioc->hba_queue_depth = max_request_credit; 2104 ioc->hba_queue_depth = max_request_credit;
2083 ioc->hi_priority_depth = facts->HighPriorityCredit; 2105 ioc->hi_priority_depth = facts->HighPriorityCredit;
@@ -2183,7 +2205,7 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
2183 * "frame for smid=0 2205 * "frame for smid=0
2184 */ 2206 */
2185 ioc->chain_depth = ioc->chains_needed_per_io * ioc->scsiio_depth; 2207 ioc->chain_depth = ioc->chains_needed_per_io * ioc->scsiio_depth;
2186 sz = ((ioc->scsiio_depth + 1 + ioc->chain_depth) * ioc->request_sz); 2208 sz = ((ioc->scsiio_depth + 1) * ioc->request_sz);
2187 2209
2188 /* hi-priority queue */ 2210 /* hi-priority queue */
2189 sz += (ioc->hi_priority_depth * ioc->request_sz); 2211 sz += (ioc->hi_priority_depth * ioc->request_sz);
@@ -2224,19 +2246,11 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
2224 ioc->internal_dma = ioc->hi_priority_dma + (ioc->hi_priority_depth * 2246 ioc->internal_dma = ioc->hi_priority_dma + (ioc->hi_priority_depth *
2225 ioc->request_sz); 2247 ioc->request_sz);
2226 2248
2227 ioc->chain = ioc->internal + (ioc->internal_depth *
2228 ioc->request_sz);
2229 ioc->chain_dma = ioc->internal_dma + (ioc->internal_depth *
2230 ioc->request_sz);
2231 2249
2232 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "request pool(0x%p): " 2250 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "request pool(0x%p): "
2233 "depth(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name, 2251 "depth(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name,
2234 ioc->request, ioc->hba_queue_depth, ioc->request_sz, 2252 ioc->request, ioc->hba_queue_depth, ioc->request_sz,
2235 (ioc->hba_queue_depth * ioc->request_sz)/1024)); 2253 (ioc->hba_queue_depth * ioc->request_sz)/1024));
2236 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "chain pool(0x%p): depth"
2237 "(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name, ioc->chain,
2238 ioc->chain_depth, ioc->request_sz, ((ioc->chain_depth *
2239 ioc->request_sz))/1024));
2240 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "request pool: dma(0x%llx)\n", 2254 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "request pool: dma(0x%llx)\n",
2241 ioc->name, (unsigned long long) ioc->request_dma)); 2255 ioc->name, (unsigned long long) ioc->request_dma));
2242 total_sz += sz; 2256 total_sz += sz;
@@ -2255,6 +2269,38 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
2255 "depth(%d)\n", ioc->name, ioc->request, 2269 "depth(%d)\n", ioc->name, ioc->request,
2256 ioc->scsiio_depth)); 2270 ioc->scsiio_depth));
2257 2271
2272 /* loop till the allocation succeeds */
2273 do {
2274 sz = ioc->chain_depth * sizeof(struct chain_tracker);
2275 ioc->chain_pages = get_order(sz);
2276 ioc->chain_lookup = (struct chain_tracker *)__get_free_pages(
2277 GFP_KERNEL, ioc->chain_pages);
2278 if (ioc->chain_lookup == NULL)
2279 ioc->chain_depth -= 100;
2280 } while (ioc->chain_lookup == NULL);
2281 ioc->chain_dma_pool = pci_pool_create("chain pool", ioc->pdev,
2282 ioc->request_sz, 16, 0);
2283 if (!ioc->chain_dma_pool) {
2284 printk(MPT2SAS_ERR_FMT "chain_dma_pool: pci_pool_create "
2285 "failed\n", ioc->name);
2286 goto out;
2287 }
2288 for (i = 0; i < ioc->chain_depth; i++) {
2289 ioc->chain_lookup[i].chain_buffer = pci_pool_alloc(
2290 ioc->chain_dma_pool , GFP_KERNEL,
2291 &ioc->chain_lookup[i].chain_buffer_dma);
2292 if (!ioc->chain_lookup[i].chain_buffer) {
2293 ioc->chain_depth = i;
2294 goto chain_done;
2295 }
2296 total_sz += ioc->request_sz;
2297 }
2298chain_done:
2299 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "chain pool depth"
2300 "(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name,
2301 ioc->chain_depth, ioc->request_sz, ((ioc->chain_depth *
2302 ioc->request_sz))/1024));
2303
2258 /* initialize hi-priority queue smid's */ 2304 /* initialize hi-priority queue smid's */
2259 ioc->hpr_lookup = kcalloc(ioc->hi_priority_depth, 2305 ioc->hpr_lookup = kcalloc(ioc->hi_priority_depth,
2260 sizeof(struct request_tracker), GFP_KERNEL); 2306 sizeof(struct request_tracker), GFP_KERNEL);
@@ -2404,7 +2450,6 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
2404 return 0; 2450 return 0;
2405 2451
2406 out: 2452 out:
2407 _base_release_memory_pools(ioc);
2408 return -ENOMEM; 2453 return -ENOMEM;
2409} 2454}
2410 2455
@@ -3587,6 +3632,7 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
3587 INIT_LIST_HEAD(&ioc->free_list); 3632 INIT_LIST_HEAD(&ioc->free_list);
3588 smid = 1; 3633 smid = 1;
3589 for (i = 0; i < ioc->scsiio_depth; i++, smid++) { 3634 for (i = 0; i < ioc->scsiio_depth; i++, smid++) {
3635 INIT_LIST_HEAD(&ioc->scsi_lookup[i].chain_list);
3590 ioc->scsi_lookup[i].cb_idx = 0xFF; 3636 ioc->scsi_lookup[i].cb_idx = 0xFF;
3591 ioc->scsi_lookup[i].smid = smid; 3637 ioc->scsi_lookup[i].smid = smid;
3592 ioc->scsi_lookup[i].scmd = NULL; 3638 ioc->scsi_lookup[i].scmd = NULL;
@@ -3613,6 +3659,13 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
3613 list_add_tail(&ioc->internal_lookup[i].tracker_list, 3659 list_add_tail(&ioc->internal_lookup[i].tracker_list,
3614 &ioc->internal_free_list); 3660 &ioc->internal_free_list);
3615 } 3661 }
3662
3663 /* chain pool */
3664 INIT_LIST_HEAD(&ioc->free_chain_list);
3665 for (i = 0; i < ioc->chain_depth; i++)
3666 list_add_tail(&ioc->chain_lookup[i].tracker_list,
3667 &ioc->free_chain_list);
3668
3616 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); 3669 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
3617 3670
3618 /* initialize Reply Free Queue */ 3671 /* initialize Reply Free Queue */
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h
index 63f7a196f42d..edf1a028db6c 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.h
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.h
@@ -419,6 +419,18 @@ enum reset_type {
419}; 419};
420 420
421/** 421/**
422 * struct chain_tracker - firmware chain tracker
423 * @chain_buffer: chain buffer
424 * @chain_buffer_dma: physical address
425 * @tracker_list: list of free request (ioc->free_chain_list)
426 */
427struct chain_tracker {
428 void *chain_buffer;
429 dma_addr_t chain_buffer_dma;
430 struct list_head tracker_list;
431};
432
433/**
422 * struct request_tracker - firmware request tracker 434 * struct request_tracker - firmware request tracker
423 * @smid: system message id 435 * @smid: system message id
424 * @scmd: scsi request pointer 436 * @scmd: scsi request pointer
@@ -430,6 +442,7 @@ struct request_tracker {
430 u16 smid; 442 u16 smid;
431 struct scsi_cmnd *scmd; 443 struct scsi_cmnd *scmd;
432 u8 cb_idx; 444 u8 cb_idx;
445 struct list_head chain_list;
433 struct list_head tracker_list; 446 struct list_head tracker_list;
434}; 447};
435 448
@@ -704,8 +717,10 @@ struct MPT2SAS_ADAPTER {
704 wait_queue_head_t reset_wq; 717 wait_queue_head_t reset_wq;
705 718
706 /* chain */ 719 /* chain */
707 u8 *chain; 720 struct chain_tracker *chain_lookup;
708 dma_addr_t chain_dma; 721 struct list_head free_chain_list;
722 struct dma_pool *chain_dma_pool;
723 ulong chain_pages;
709 u16 max_sges_in_main_message; 724 u16 max_sges_in_main_message;
710 u16 max_sges_in_chain_message; 725 u16 max_sges_in_chain_message;
711 u16 chains_needed_per_io; 726 u16 chains_needed_per_io;
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
index 5af5781d9464..3e9c78aa4ccb 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
@@ -931,31 +931,32 @@ _scsih_scsi_lookup_find_by_lun(struct MPT2SAS_ADAPTER *ioc, int id,
931} 931}
932 932
933/** 933/**
934 * _scsih_get_chain_buffer_dma - obtain block of chains (dma address) 934 * _scsih_get_chain_buffer_tracker - obtain chain tracker
935 * @ioc: per adapter object 935 * @ioc: per adapter object
936 * @smid: system request message index 936 * @smid: smid associated to an IO request
937 * 937 *
938 * Returns phys pointer to chain buffer. 938 * Returns chain tracker(from ioc->free_chain_list)
939 */ 939 */
940static dma_addr_t 940static struct chain_tracker *
941_scsih_get_chain_buffer_dma(struct MPT2SAS_ADAPTER *ioc, u16 smid) 941_scsih_get_chain_buffer_tracker(struct MPT2SAS_ADAPTER *ioc, u16 smid)
942{ 942{
943 return ioc->chain_dma + ((smid - 1) * (ioc->request_sz * 943 struct chain_tracker *chain_req;
944 ioc->chains_needed_per_io)); 944 unsigned long flags;
945}
946 945
947/** 946 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
948 * _scsih_get_chain_buffer - obtain block of chains assigned to a mf request 947 if (list_empty(&ioc->free_chain_list)) {
949 * @ioc: per adapter object 948 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
950 * @smid: system request message index 949 printk(MPT2SAS_WARN_FMT "chain buffers not available\n",
951 * 950 ioc->name);
952 * Returns virt pointer to chain buffer. 951 return NULL;
953 */ 952 }
954static void * 953 chain_req = list_entry(ioc->free_chain_list.next,
955_scsih_get_chain_buffer(struct MPT2SAS_ADAPTER *ioc, u16 smid) 954 struct chain_tracker, tracker_list);
956{ 955 list_del_init(&chain_req->tracker_list);
957 return (void *)(ioc->chain + ((smid - 1) * (ioc->request_sz * 956 list_add_tail(&chain_req->tracker_list,
958 ioc->chains_needed_per_io))); 957 &ioc->scsi_lookup[smid - 1].chain_list);
958 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
959 return chain_req;
959} 960}
960 961
961/** 962/**
@@ -986,6 +987,7 @@ _scsih_build_scatter_gather(struct MPT2SAS_ADAPTER *ioc,
986 u32 sgl_flags; 987 u32 sgl_flags;
987 u32 sgl_flags_last_element; 988 u32 sgl_flags_last_element;
988 u32 sgl_flags_end_buffer; 989 u32 sgl_flags_end_buffer;
990 struct chain_tracker *chain_req;
989 991
990 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); 992 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
991 993
@@ -1033,8 +1035,11 @@ _scsih_build_scatter_gather(struct MPT2SAS_ADAPTER *ioc,
1033 1035
1034 /* initializing the chain flags and pointers */ 1036 /* initializing the chain flags and pointers */
1035 chain_flags = MPI2_SGE_FLAGS_CHAIN_ELEMENT << MPI2_SGE_FLAGS_SHIFT; 1037 chain_flags = MPI2_SGE_FLAGS_CHAIN_ELEMENT << MPI2_SGE_FLAGS_SHIFT;
1036 chain = _scsih_get_chain_buffer(ioc, smid); 1038 chain_req = _scsih_get_chain_buffer_tracker(ioc, smid);
1037 chain_dma = _scsih_get_chain_buffer_dma(ioc, smid); 1039 if (!chain_req)
1040 return -1;
1041 chain = chain_req->chain_buffer;
1042 chain_dma = chain_req->chain_buffer_dma;
1038 do { 1043 do {
1039 sges_in_segment = (sges_left <= 1044 sges_in_segment = (sges_left <=
1040 ioc->max_sges_in_chain_message) ? sges_left : 1045 ioc->max_sges_in_chain_message) ? sges_left :
@@ -1070,8 +1075,11 @@ _scsih_build_scatter_gather(struct MPT2SAS_ADAPTER *ioc,
1070 sges_in_segment--; 1075 sges_in_segment--;
1071 } 1076 }
1072 1077
1073 chain_dma += ioc->request_sz; 1078 chain_req = _scsih_get_chain_buffer_tracker(ioc, smid);
1074 chain += ioc->request_sz; 1079 if (!chain_req)
1080 return -1;
1081 chain = chain_req->chain_buffer;
1082 chain_dma = chain_req->chain_buffer_dma;
1075 } while (1); 1083 } while (1);
1076 1084
1077 1085