aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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