Skip to content

Commit 16eaaee

Browse files
suganathprabu0512Somasundaram Krishnasamy
authored andcommitted
scsi: mpt3sas: Handle RDPQ DMA allocation in same 4G region
For INVADER_SERIES, each set of 8 reply queues (0 - 7, 8 - 15,..), and for VENTURA_SERIES, each set of 16 reply queues (0 - 15, 16 - 31,..) need to be within the same 4 GB boundary. Driver uses limitation of VENTURA_SERIES to manage INVADER_SERIES as well. The driver is allocating the DMA able memory for RDPQs accordingly. 1) At driver load, set DMA mask to 64 and allocate memory for RDPQs 2) Check if allocated resources for RDPQ are in the same 4GB range 3) If #2 is true, continue with 64 bit DMA and go to #6 4) If #2 is false, then free all the resources from #1 5) Set DMA mask to 32 and allocate RDPQs 6) Proceed with driver loading and other allocations Link: https://lore.kernel.org/r/1587626596-1044-5-git-send-email-suganath-prabu.subramani@broadcom.com Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Suganath Prabu <suganath-prabu.subramani@broadcom.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> (cherry picked from commit 8012209) Conflicts: drivers/scsi/mpt3sas/mpt3sas_base.h Orabug: 31434583 Signed-off-by: Jack Vogel <jack.vogel@oracle.com> Reviewed-by: John Donnelly <john.p.donnelly@oracle.com> Signed-off-by: Somasundaram Krishnasamy <somasundaram.krishnasamy@oracle.com>
1 parent d1ce1fc commit 16eaaee

2 files changed

Lines changed: 110 additions & 46 deletions

File tree

‎drivers/scsi/mpt3sas/mpt3sas_base.c‎

Lines changed: 106 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -2810,7 +2810,7 @@ _base_config_dma_addressing(struct MPT3SAS_ADAPTER *ioc, struct pci_dev *pdev)
28102810
int dma_mask;
28112811

28122812
if (ioc->is_mcpu_endpoint ||
2813-
sizeof(dma_addr_t) == 4 ||
2813+
sizeof(dma_addr_t) == 4 || ioc->use_32bit_dma ||
28142814
dma_get_required_mask(&pdev->dev) <= 32)
28152815
dma_mask = 32;
28162816
/* Set 63 bit DMA mask for all SAS3 and SAS35 controllers */
@@ -4807,8 +4807,8 @@ _base_release_memory_pools(struct MPT3SAS_ADAPTER *ioc)
48074807
{
48084808
int i = 0;
48094809
int j = 0;
4810+
int dma_alloc_count = 0;
48104811
struct chain_tracker *ct;
4811-
struct reply_post_struct *rps;
48124812

48134813
dexitprintk(ioc, ioc_info(ioc, "%s\n", __func__));
48144814

@@ -4850,29 +4850,34 @@ _base_release_memory_pools(struct MPT3SAS_ADAPTER *ioc)
48504850
}
48514851

48524852
if (ioc->reply_post) {
4853-
do {
4854-
rps = &ioc->reply_post[i];
4855-
if (rps->reply_post_free) {
4856-
dma_pool_free(
4857-
ioc->reply_post_free_dma_pool,
4858-
rps->reply_post_free,
4859-
rps->reply_post_free_dma);
4860-
dexitprintk(ioc,
4861-
ioc_info(ioc, "reply_post_free_pool(0x%p): free\n",
4862-
rps->reply_post_free));
4863-
rps->reply_post_free = NULL;
4853+
dma_alloc_count = DIV_ROUND_UP(ioc->reply_queue_count,
4854+
RDPQ_MAX_INDEX_IN_ONE_CHUNK);
4855+
for (i = 0; i < ioc->reply_queue_count; i++) {
4856+
if (i % RDPQ_MAX_INDEX_IN_ONE_CHUNK == 0
4857+
&& dma_alloc_count) {
4858+
if (ioc->reply_post[i].reply_post_free) {
4859+
dma_pool_free(
4860+
ioc->reply_post_free_dma_pool,
4861+
ioc->reply_post[i].reply_post_free,
4862+
ioc->reply_post[i].reply_post_free_dma);
4863+
dexitprintk(ioc, ioc_info(ioc,
4864+
"reply_post_free_pool(0x%p): free\n",
4865+
ioc->reply_post[i].reply_post_free));
4866+
ioc->reply_post[i].reply_post_free =
4867+
NULL;
4868+
}
4869+
--dma_alloc_count;
48644870
}
4865-
} while (ioc->rdpq_array_enable &&
4866-
(++i < ioc->reply_queue_count));
4871+
}
4872+
dma_pool_destroy(ioc->reply_post_free_dma_pool);
48674873
if (ioc->reply_post_free_array &&
48684874
ioc->rdpq_array_enable) {
48694875
dma_pool_free(ioc->reply_post_free_array_dma_pool,
4870-
ioc->reply_post_free_array,
4871-
ioc->reply_post_free_array_dma);
4876+
ioc->reply_post_free_array,
4877+
ioc->reply_post_free_array_dma);
48724878
ioc->reply_post_free_array = NULL;
48734879
}
48744880
dma_pool_destroy(ioc->reply_post_free_array_dma_pool);
4875-
dma_pool_destroy(ioc->reply_post_free_dma_pool);
48764881
kfree(ioc->reply_post);
48774882
}
48784883

@@ -4948,36 +4953,75 @@ mpt3sas_check_same_4gb_region(long reply_pool_start_address, u32 pool_sz)
49484953
static int
49494954
base_alloc_rdpq_dma_pool(struct MPT3SAS_ADAPTER *ioc, int sz)
49504955
{
4951-
int i;
4956+
int i = 0;
4957+
u32 dma_alloc_count = 0;
4958+
int reply_post_free_sz = ioc->reply_post_queue_depth *
4959+
sizeof(Mpi2DefaultReplyDescriptor_t);
49524960
int count = ioc->rdpq_array_enable ? ioc->reply_queue_count : 1;
49534961

49544962
ioc->reply_post = kcalloc(count, sizeof(struct reply_post_struct),
49554963
GFP_KERNEL);
49564964
if (!ioc->reply_post)
49574965
return -ENOMEM;
4966+
/*
4967+
* For INVADER_SERIES each set of 8 reply queues(0-7, 8-15, ..) and
4968+
* VENTURA_SERIES each set of 16 reply queues(0-15, 16-31, ..) should
4969+
* be within 4GB boundary i.e reply queues in a set must have same
4970+
* upper 32-bits in their memory address. so here driver is allocating
4971+
* the DMA'able memory for reply queues according.
4972+
* Driver uses limitation of
4973+
* VENTURA_SERIES to manage INVADER_SERIES as well.
4974+
*/
4975+
dma_alloc_count = DIV_ROUND_UP(ioc->reply_queue_count,
4976+
RDPQ_MAX_INDEX_IN_ONE_CHUNK);
49584977
ioc->reply_post_free_dma_pool =
4959-
dma_pool_create("reply_post_free pool",
4960-
&ioc->pdev->dev, sz, 16, 0);
4978+
dma_pool_create("reply_post_free pool",
4979+
&ioc->pdev->dev, sz, 16, 0);
49614980
if (!ioc->reply_post_free_dma_pool)
49624981
return -ENOMEM;
4963-
i = 0;
4964-
do {
4965-
ioc->reply_post[i].reply_post_free =
4966-
dma_pool_zalloc(ioc->reply_post_free_dma_pool,
4967-
GFP_KERNEL,
4968-
&ioc->reply_post[i].reply_post_free_dma);
4969-
if (!ioc->reply_post[i].reply_post_free)
4970-
return -ENOMEM;
4971-
dinitprintk(ioc,
4972-
ioc_info(ioc, "reply post free pool (0x%p): depth(%d),"
4973-
"element_size(%d), pool_size(%d kB)\n",
4974-
ioc->reply_post[i].reply_post_free,
4975-
ioc->reply_post_queue_depth, 8, sz / 1024));
4976-
dinitprintk(ioc,
4977-
ioc_info(ioc, "reply_post_free_dma = (0x%llx)\n",
4978-
(u64)ioc->reply_post[i].reply_post_free_dma));
4982+
for (i = 0; i < ioc->reply_queue_count; i++) {
4983+
if ((i % RDPQ_MAX_INDEX_IN_ONE_CHUNK == 0) && dma_alloc_count) {
4984+
ioc->reply_post[i].reply_post_free =
4985+
dma_pool_alloc(ioc->reply_post_free_dma_pool,
4986+
GFP_KERNEL,
4987+
&ioc->reply_post[i].reply_post_free_dma);
4988+
if (!ioc->reply_post[i].reply_post_free)
4989+
return -ENOMEM;
4990+
/*
4991+
* Each set of RDPQ pool must satisfy 4gb boundary
4992+
* restriction.
4993+
* 1) Check if allocated resources for RDPQ pool are in
4994+
* the same 4GB range.
4995+
* 2) If #1 is true, continue with 64 bit DMA.
4996+
* 3) If #1 is false, return 1. which means free all the
4997+
* resources and set DMA mask to 32 and allocate.
4998+
*/
4999+
if (!mpt3sas_check_same_4gb_region(
5000+
(long)ioc->reply_post[i].reply_post_free, sz)) {
5001+
dinitprintk(ioc,
5002+
ioc_err(ioc, "bad Replypost free pool(0x%p)"
5003+
"reply_post_free_dma = (0x%llx)\n",
5004+
ioc->reply_post[i].reply_post_free,
5005+
(unsigned long long)
5006+
ioc->reply_post[i].reply_post_free_dma));
5007+
return -EAGAIN;
5008+
}
5009+
memset(ioc->reply_post[i].reply_post_free, 0,
5010+
RDPQ_MAX_INDEX_IN_ONE_CHUNK *
5011+
reply_post_free_sz);
5012+
dma_alloc_count--;
49795013

4980-
} while (ioc->rdpq_array_enable && ++i < ioc->reply_queue_count);
5014+
} else {
5015+
ioc->reply_post[i].reply_post_free =
5016+
(Mpi2ReplyDescriptorsUnion_t *)
5017+
((long)ioc->reply_post[i-1].reply_post_free
5018+
+ reply_post_free_sz);
5019+
ioc->reply_post[i].reply_post_free_dma =
5020+
(dma_addr_t)
5021+
(ioc->reply_post[i-1].reply_post_free_dma +
5022+
reply_post_free_sz);
5023+
}
5024+
}
49815025
return 0;
49825026
}
49835027

@@ -4995,10 +5039,12 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc)
49955039
u16 chains_needed_per_io;
49965040
u32 sz, total_sz, reply_post_free_sz, reply_post_free_array_sz;
49975041
u32 retry_sz;
5042+
u32 rdpq_sz = 0;
49985043
u16 max_request_credit, nvme_blocks_needed;
49995044
unsigned short sg_tablesize;
50005045
u16 sge_size;
50015046
int i, j;
5047+
int ret = 0;
50025048
struct chain_tracker *ct;
50035049

50045050
dinitprintk(ioc, ioc_info(ioc, "%s\n", __func__));
@@ -5152,14 +5198,28 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc)
51525198
/* reply post queue, 16 byte align */
51535199
reply_post_free_sz = ioc->reply_post_queue_depth *
51545200
sizeof(Mpi2DefaultReplyDescriptor_t);
5155-
5156-
sz = reply_post_free_sz;
5201+
rdpq_sz = reply_post_free_sz * RDPQ_MAX_INDEX_IN_ONE_CHUNK;
51575202
if (_base_is_controller_msix_enabled(ioc) && !ioc->rdpq_array_enable)
5158-
sz *= ioc->reply_queue_count;
5159-
if (base_alloc_rdpq_dma_pool(ioc, sz))
5160-
goto out;
5161-
total_sz += sz * (!ioc->rdpq_array_enable ? 1 : ioc->reply_queue_count);
5162-
5203+
rdpq_sz = reply_post_free_sz * ioc->reply_queue_count;
5204+
ret = base_alloc_rdpq_dma_pool(ioc, rdpq_sz);
5205+
if (ret == -EAGAIN) {
5206+
/*
5207+
* Free allocated bad RDPQ memory pools.
5208+
* Change dma coherent mask to 32 bit and reallocate RDPQ
5209+
*/
5210+
_base_release_memory_pools(ioc);
5211+
ioc->use_32bit_dma = true;
5212+
if (_base_config_dma_addressing(ioc, ioc->pdev) != 0) {
5213+
ioc_err(ioc,
5214+
"32 DMA mask failed %s\n", pci_name(ioc->pdev));
5215+
return -ENODEV;
5216+
}
5217+
if (base_alloc_rdpq_dma_pool(ioc, rdpq_sz))
5218+
return -ENOMEM;
5219+
} else if (ret == -ENOMEM)
5220+
return -ENOMEM;
5221+
total_sz = rdpq_sz * (!ioc->rdpq_array_enable ? 1 :
5222+
DIV_ROUND_UP(ioc->reply_queue_count, RDPQ_MAX_INDEX_IN_ONE_CHUNK));
51635223
ioc->scsiio_depth = ioc->hba_queue_depth -
51645224
ioc->hi_priority_depth - ioc->internal_depth;
51655225

@@ -5171,7 +5231,6 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc)
51715231
ioc_info(ioc, "scsi host: can_queue depth (%d)\n",
51725232
ioc->shost->can_queue));
51735233

5174-
51755234
/* contiguous pool for request and chains, 16 byte align, one extra "
51765235
* "frame for smid=0
51775236
*/
@@ -7141,6 +7200,7 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc)
71417200
ioc->smp_affinity_enable = smp_affinity_enable;
71427201

71437202
ioc->rdpq_array_enable_assigned = 0;
7203+
ioc->use_32bit_dma = 0;
71447204
if (ioc->is_aero_ioc)
71457205
ioc->base_readl = &_base_readl_aero;
71467206
else

‎drivers/scsi/mpt3sas/mpt3sas_base.h‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,7 @@ struct mpt3sas_nvme_cmd {
367367
#define MPT3SAS_HIGH_IOPS_REPLY_QUEUES 8
368368
#define MPT3SAS_HIGH_IOPS_BATCH_COUNT 16
369369
#define MPT3SAS_GEN35_MAX_MSIX_QUEUES 128
370+
#define RDPQ_MAX_INDEX_IN_ONE_CHUNK 16
370371

371372
/* OEM Specific Flags will come from OEM specific header files */
372373
struct Mpi2ManufacturingPage10_t {
@@ -1063,6 +1064,7 @@ typedef void (*MPT3SAS_FLUSH_RUNNING_CMDS)(struct MPT3SAS_ADAPTER *ioc);
10631064
* @thresh_hold: Max number of reply descriptors processed
10641065
* before updating Host Index
10651066
* @drv_support_bitmap: driver's supported feature bit map
1067+
* @use_32bit_dma: Flag to use 32 bit consistent dma mask
10661068
* @scsi_io_cb_idx: shost generated commands
10671069
* @tm_cb_idx: task management commands
10681070
* @scsih_cb_idx: scsih internal commands
@@ -1251,6 +1253,8 @@ struct MPT3SAS_ADAPTER {
12511253
u16 thresh_hold;
12521254
u8 high_iops_queues;
12531255
u32 drv_support_bitmap;
1256+
bool enable_sdev_max_qd;
1257+
bool use_32bit_dma;
12541258

12551259
/* internal commands, callback index */
12561260
u8 scsi_io_cb_idx;

0 commit comments

Comments
 (0)