diff options
author | Kashyap, Desai <kashyap.desai@lsi.com> | 2010-11-12 18:04:06 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-12-21 13:24:04 -0500 |
commit | 35f805b52c94f8e6cb22907ef32517132a15cb96 (patch) | |
tree | eb26ec6db8b4093d5659eb0f351b1dbc228c5359 /drivers/scsi/mpt2sas/mpt2sas_base.c | |
parent | 6cb8ef573fd4c2bd72248f492fe336133660148d (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/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 @@ | |||
65 | static MPT_CALLBACK mpt_callbacks[MPT_MAX_CALLBACKS]; | 65 | 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 | #define MPT2SAS_MAX_REQUEST_QUEUE 600 /* maximum controller queue depth */ | ||
69 | 68 | ||
70 | static int max_queue_depth = -1; | 69 | static int max_queue_depth = -1; |
71 | module_param(max_queue_depth, int, 0); | 70 | module_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) | |||
1968 | static void | 1976 | static 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 | } | ||
2298 | chain_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 */ |