Skip to content

Commit ef010eb

Browse files
suganathprabu0512jfvogel
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) Orabug: 31741029 Signed-off-by: Jack Vogel <jack.vogel@oracle.com> Reviewed-by: John Donnelly <john.p.donnelly@oracle.com>
1 parent 499140d commit ef010eb

2 files changed

Lines changed: 109 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

@@ -4950,36 +4955,75 @@ mpt3sas_check_same_4gb_region(long reply_pool_start_address, u32 pool_sz)
49504955
static int
49514956
base_alloc_rdpq_dma_pool(struct MPT3SAS_ADAPTER *ioc, int sz)
49524957
{
4953-
int i;
4958+
int i = 0;
4959+
u32 dma_alloc_count = 0;
4960+
int reply_post_free_sz = ioc->reply_post_queue_depth *
4961+
sizeof(Mpi2DefaultReplyDescriptor_t);
49544962
int count = ioc->rdpq_array_enable ? ioc->reply_queue_count : 1;
49554963

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

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

@@ -4997,10 +5041,12 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc)
49975041
u16 chains_needed_per_io;
49985042
u32 sz, total_sz, reply_post_free_sz, reply_post_free_array_sz;
49995043
u32 retry_sz;
5044+
u32 rdpq_sz = 0;
50005045
u16 max_request_credit, nvme_blocks_needed;
50015046
unsigned short sg_tablesize;
50025047
u16 sge_size;
50035048
int i, j;
5049+
int ret = 0;
50045050
struct chain_tracker *ct;
50055051

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

@@ -5173,7 +5233,6 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc)
51735233
ioc_info(ioc, "scsi host: can_queue depth (%d)\n",
51745234
ioc->shost->can_queue));
51755235

5176-
51775236
/* contiguous pool for request and chains, 16 byte align, one extra "
51785237
* "frame for smid=0
51795238
*/
@@ -7143,6 +7202,7 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc)
71437202
ioc->smp_affinity_enable = smp_affinity_enable;
71447203

71457204
ioc->rdpq_array_enable_assigned = 0;
7205+
ioc->use_32bit_dma = 0;
71467206
if (ioc->is_aero_ioc)
71477207
ioc->base_readl = &_base_readl_aero;
71487208
else

‎drivers/scsi/mpt3sas/mpt3sas_base.h‎

Lines changed: 3 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
@@ -1252,6 +1254,7 @@ struct MPT3SAS_ADAPTER {
12521254
u8 high_iops_queues;
12531255
u32 drv_support_bitmap;
12541256
bool enable_sdev_max_qd;
1257+
bool use_32bit_dma;
12551258

12561259
/* internal commands, callback index */
12571260
u8 scsi_io_cb_idx;

0 commit comments

Comments
 (0)