Commit 93204b78 authored by Chaitra P B's avatar Chaitra P B Committed by Martin K. Petersen

scsi: mpt3sas: Lockless access for chain buffers.

Introduces Chain lookup table/tracker and implements accessing chain
buffer using smid.  Removed link list based access of chain buffer which
requires lock and allocated as many chains needed.
Signed-off-by: default avatarChaitra P B <chaitra.basappa@broadcom.com>
Signed-off-by: default avatarSuganath Prabu S <suganath-prabu.subramani@broadcom.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent cd33223b
...@@ -297,12 +297,15 @@ static void * ...@@ -297,12 +297,15 @@ static void *
_base_get_chain_buffer_dma_to_chain_buffer(struct MPT3SAS_ADAPTER *ioc, _base_get_chain_buffer_dma_to_chain_buffer(struct MPT3SAS_ADAPTER *ioc,
dma_addr_t chain_buffer_dma) dma_addr_t chain_buffer_dma)
{ {
u16 index; u16 index, j;
struct chain_tracker *ct;
for (index = 0; index < ioc->chain_depth; index++) { for (index = 0; index < ioc->scsiio_depth; index++) {
if (ioc->chain_lookup[index].chain_buffer_dma == for (j = 0; j < ioc->chains_needed_per_io; j++) {
chain_buffer_dma) ct = &ioc->chain_lookup[index].chains_per_smid[j];
return ioc->chain_lookup[index].chain_buffer; if (ct && ct->chain_buffer_dma == chain_buffer_dma)
return ct->chain_buffer;
}
} }
pr_info(MPT3SAS_FMT pr_info(MPT3SAS_FMT
"Provided chain_buffer_dma address is not in the lookup list\n", "Provided chain_buffer_dma address is not in the lookup list\n",
...@@ -1679,7 +1682,8 @@ _base_add_sg_single_64(void *paddr, u32 flags_length, dma_addr_t dma_addr) ...@@ -1679,7 +1682,8 @@ _base_add_sg_single_64(void *paddr, u32 flags_length, dma_addr_t dma_addr)
* @ioc: per adapter object * @ioc: per adapter object
* @scmd: SCSI commands of the IO request * @scmd: SCSI commands of the IO request
* *
* Returns chain tracker(from ioc->free_chain_list) * Returns chain tracker from chain_lookup table using key as
* smid and smid's chain_offset.
*/ */
static struct chain_tracker * static struct chain_tracker *
_base_get_chain_buffer_tracker(struct MPT3SAS_ADAPTER *ioc, _base_get_chain_buffer_tracker(struct MPT3SAS_ADAPTER *ioc,
...@@ -1687,20 +1691,15 @@ _base_get_chain_buffer_tracker(struct MPT3SAS_ADAPTER *ioc, ...@@ -1687,20 +1691,15 @@ _base_get_chain_buffer_tracker(struct MPT3SAS_ADAPTER *ioc,
{ {
struct chain_tracker *chain_req; struct chain_tracker *chain_req;
struct scsiio_tracker *st = scsi_cmd_priv(scmd); struct scsiio_tracker *st = scsi_cmd_priv(scmd);
unsigned long flags; u16 smid = st->smid;
u8 chain_offset =
atomic_read(&ioc->chain_lookup[smid - 1].chain_offset);
spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); if (chain_offset == ioc->chains_needed_per_io)
if (list_empty(&ioc->free_chain_list)) {
spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
dfailprintk(ioc, pr_warn(MPT3SAS_FMT
"chain buffers not available\n", ioc->name));
return NULL; return NULL;
}
chain_req = list_entry(ioc->free_chain_list.next, chain_req = &ioc->chain_lookup[smid - 1].chains_per_smid[chain_offset];
struct chain_tracker, tracker_list); atomic_inc(&ioc->chain_lookup[smid - 1].chain_offset);
list_del_init(&chain_req->tracker_list);
list_add_tail(&chain_req->tracker_list, &st->chain_list);
spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
return chain_req; return chain_req;
} }
...@@ -3281,13 +3280,7 @@ void mpt3sas_base_clear_st(struct MPT3SAS_ADAPTER *ioc, ...@@ -3281,13 +3280,7 @@ void mpt3sas_base_clear_st(struct MPT3SAS_ADAPTER *ioc,
return; return;
st->cb_idx = 0xFF; st->cb_idx = 0xFF;
st->direct_io = 0; st->direct_io = 0;
if (!list_empty(&st->chain_list)) { atomic_set(&ioc->chain_lookup[st->smid - 1].chain_offset, 0);
unsigned long flags;
spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
list_splice_init(&st->chain_list, &ioc->free_chain_list);
spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
}
} }
/** /**
...@@ -4105,6 +4098,8 @@ static void ...@@ -4105,6 +4098,8 @@ static void
_base_release_memory_pools(struct MPT3SAS_ADAPTER *ioc) _base_release_memory_pools(struct MPT3SAS_ADAPTER *ioc)
{ {
int i = 0; int i = 0;
int j = 0;
struct chain_tracker *ct;
struct reply_post_struct *rps; struct reply_post_struct *rps;
dexitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, dexitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
...@@ -4195,14 +4190,18 @@ _base_release_memory_pools(struct MPT3SAS_ADAPTER *ioc) ...@@ -4195,14 +4190,18 @@ _base_release_memory_pools(struct MPT3SAS_ADAPTER *ioc)
kfree(ioc->hpr_lookup); kfree(ioc->hpr_lookup);
kfree(ioc->internal_lookup); kfree(ioc->internal_lookup);
if (ioc->chain_lookup) { if (ioc->chain_lookup) {
for (i = 0; i < ioc->chain_depth; i++) { for (i = 0; i < ioc->scsiio_depth; i++) {
if (ioc->chain_lookup[i].chain_buffer) for (j = 0; j < ioc->chains_needed_per_io; j++) {
ct = &ioc->chain_lookup[i].chains_per_smid[j];
if (ct && ct->chain_buffer)
dma_pool_free(ioc->chain_dma_pool, dma_pool_free(ioc->chain_dma_pool,
ioc->chain_lookup[i].chain_buffer, ct->chain_buffer,
ioc->chain_lookup[i].chain_buffer_dma); ct->chain_buffer_dma);
}
kfree(ioc->chain_lookup[i].chains_per_smid);
} }
dma_pool_destroy(ioc->chain_dma_pool); dma_pool_destroy(ioc->chain_dma_pool);
free_pages((ulong)ioc->chain_lookup, ioc->chain_pages); kfree(ioc->chain_lookup);
ioc->chain_lookup = NULL; ioc->chain_lookup = NULL;
} }
} }
...@@ -4224,7 +4223,8 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc) ...@@ -4224,7 +4223,8 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc)
u16 max_request_credit, nvme_blocks_needed; u16 max_request_credit, nvme_blocks_needed;
unsigned short sg_tablesize; unsigned short sg_tablesize;
u16 sge_size; u16 sge_size;
int i; int i, j;
struct chain_tracker *ct;
dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
__func__)); __func__));
...@@ -4505,15 +4505,24 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc) ...@@ -4505,15 +4505,24 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc)
ioc->name, ioc->request, ioc->scsiio_depth)); ioc->name, ioc->request, ioc->scsiio_depth));
ioc->chain_depth = min_t(u32, ioc->chain_depth, MAX_CHAIN_DEPTH); ioc->chain_depth = min_t(u32, ioc->chain_depth, MAX_CHAIN_DEPTH);
sz = ioc->chain_depth * sizeof(struct chain_tracker); sz = ioc->scsiio_depth * sizeof(struct chain_lookup);
ioc->chain_pages = get_order(sz); ioc->chain_lookup = kzalloc(sz, GFP_KERNEL);
ioc->chain_lookup = (struct chain_tracker *)__get_free_pages(
GFP_KERNEL, ioc->chain_pages);
if (!ioc->chain_lookup) { if (!ioc->chain_lookup) {
pr_err(MPT3SAS_FMT "chain_lookup: __get_free_pages failed\n", pr_err(MPT3SAS_FMT "chain_lookup: __get_free_pages "
ioc->name); "failed\n", ioc->name);
goto out;
}
sz = ioc->chains_needed_per_io * sizeof(struct chain_tracker);
for (i = 0; i < ioc->scsiio_depth; i++) {
ioc->chain_lookup[i].chains_per_smid = kzalloc(sz, GFP_KERNEL);
if (!ioc->chain_lookup[i].chains_per_smid) {
pr_err(MPT3SAS_FMT "chain_lookup: "
" kzalloc failed\n", ioc->name);
goto out; goto out;
} }
}
ioc->chain_dma_pool = dma_pool_create("chain pool", &ioc->pdev->dev, ioc->chain_dma_pool = dma_pool_create("chain pool", &ioc->pdev->dev,
ioc->chain_segment_sz, 16, 0); ioc->chain_segment_sz, 16, 0);
if (!ioc->chain_dma_pool) { if (!ioc->chain_dma_pool) {
...@@ -4521,17 +4530,21 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc) ...@@ -4521,17 +4530,21 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc)
ioc->name); ioc->name);
goto out; goto out;
} }
for (i = 0; i < ioc->chain_depth; i++) { for (i = 0; i < ioc->scsiio_depth; i++) {
ioc->chain_lookup[i].chain_buffer = dma_pool_alloc( for (j = 0; j < ioc->chains_needed_per_io; j++) {
ct = &ioc->chain_lookup[i].chains_per_smid[j];
ct->chain_buffer = dma_pool_alloc(
ioc->chain_dma_pool , GFP_KERNEL, ioc->chain_dma_pool , GFP_KERNEL,
&ioc->chain_lookup[i].chain_buffer_dma); &ct->chain_buffer_dma);
if (!ioc->chain_lookup[i].chain_buffer) { if (!ct->chain_buffer) {
ioc->chain_depth = i; pr_err(MPT3SAS_FMT "chain_lookup: "
goto chain_done; " pci_pool_alloc failed\n", ioc->name);
goto out;
}
} }
total_sz += ioc->chain_segment_sz; total_sz += ioc->chain_segment_sz;
} }
chain_done:
dinitprintk(ioc, pr_info(MPT3SAS_FMT dinitprintk(ioc, pr_info(MPT3SAS_FMT
"chain pool depth(%d), frame_size(%d), pool_size(%d kB)\n", "chain pool depth(%d), frame_size(%d), pool_size(%d kB)\n",
ioc->name, ioc->chain_depth, ioc->chain_segment_sz, ioc->name, ioc->chain_depth, ioc->chain_segment_sz,
...@@ -6179,12 +6192,6 @@ _base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc) ...@@ -6179,12 +6192,6 @@ _base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc)
&ioc->internal_free_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); spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
/* initialize Reply Free Queue */ /* initialize Reply Free Queue */
......
...@@ -770,7 +770,11 @@ struct pcie_sg_list { ...@@ -770,7 +770,11 @@ struct pcie_sg_list {
struct chain_tracker { struct chain_tracker {
void *chain_buffer; void *chain_buffer;
dma_addr_t chain_buffer_dma; dma_addr_t chain_buffer_dma;
struct list_head tracker_list; };
struct chain_lookup {
struct chain_tracker *chains_per_smid;
atomic_t chain_offset;
}; };
/** /**
...@@ -1261,7 +1265,7 @@ struct MPT3SAS_ADAPTER { ...@@ -1261,7 +1265,7 @@ struct MPT3SAS_ADAPTER {
u32 page_size; u32 page_size;
/* chain */ /* chain */
struct chain_tracker *chain_lookup; struct chain_lookup *chain_lookup;
struct list_head free_chain_list; struct list_head free_chain_list;
struct dma_pool *chain_dma_pool; struct dma_pool *chain_dma_pool;
ulong chain_pages; ulong chain_pages;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment