Skip to content

Commit 339a7b3

Browse files
Ranjan Kumarmartinkpetersen
authored andcommitted
scsi: mpi3mr: Support for Segmented Hardware Trace buffer
Allocate segmented trace buffer if firmware advertises the capability in IOCfacts. Upon driver load, read the trace buffer size from driver page 1, calculate the required segments for trace buffer, and allocate segmented buffers. Each segment is 4096 bytes in size. While posting driver diagnostic buffer to firmware, advertise that trace buffer is segmented. Signed-off-by: Sumit Saxena <[email protected]> Signed-off-by: Ranjan Kumar <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Martin K. Petersen <[email protected]>
1 parent f08b24d commit 339a7b3

File tree

4 files changed

+150
-13
lines changed

4 files changed

+150
-13
lines changed

drivers/scsi/mpi3mr/mpi/mpi30_tool.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#define MPI3_DIAG_BUFFER_TYPE_FW (0x02)
1010
#define MPI3_DIAG_BUFFER_ACTION_RELEASE (0x01)
1111

12+
#define MPI3_DIAG_BUFFER_POST_MSGFLAGS_SEGMENTED (0x01)
1213
struct mpi3_diag_buffer_post_request {
1314
__le16 host_tag;
1415
u8 ioc_use_only02;

drivers/scsi/mpi3mr/mpi3mr.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -934,6 +934,8 @@ struct trigger_event_data {
934934
* @size: Buffer size
935935
* @addr: Virtual address
936936
* @dma_addr: Buffer DMA address
937+
* @is_segmented: The buffer is segmented or not
938+
* @disabled_after_reset: The buffer is disabled after reset
937939
*/
938940
struct diag_buffer_desc {
939941
u8 type;
@@ -943,6 +945,8 @@ struct diag_buffer_desc {
943945
u32 size;
944946
void *addr;
945947
dma_addr_t dma_addr;
948+
bool is_segmented;
949+
bool disabled_after_reset;
946950
};
947951

948952
/**
@@ -1161,6 +1165,10 @@ struct scmd_priv {
11611165
* @block_on_pci_err: Block IO during PCI error recovery
11621166
* @reply_qfull_count: Occurences of reply queue full avoidance kicking-in
11631167
* @prevent_reply_qfull: Enable reply queue prevention
1168+
* @seg_tb_support: Segmented trace buffer support
1169+
* @num_tb_segs: Number of Segments in Trace buffer
1170+
* @trace_buf_pool: DMA pool for Segmented trace buffer segments
1171+
* @trace_buf: Trace buffer segments memory descriptor
11641172
*/
11651173
struct mpi3mr_ioc {
11661174
struct list_head list;
@@ -1361,6 +1369,11 @@ struct mpi3mr_ioc {
13611369
bool block_on_pci_err;
13621370
atomic_t reply_qfull_count;
13631371
bool prevent_reply_qfull;
1372+
bool seg_tb_support;
1373+
u32 num_tb_segs;
1374+
struct dma_pool *trace_buf_pool;
1375+
struct segments *trace_buf;
1376+
13641377
};
13651378

13661379
/**

drivers/scsi/mpi3mr/mpi3mr_app.c

Lines changed: 95 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,23 +12,98 @@
1212
#include <uapi/scsi/scsi_bsg_mpi3mr.h>
1313

1414
/**
15-
* mpi3mr_alloc_trace_buffer: Allocate trace buffer
15+
* mpi3mr_alloc_trace_buffer: Allocate segmented trace buffer
1616
* @mrioc: Adapter instance reference
1717
* @trace_size: Trace buffer size
1818
*
19-
* Allocate trace buffer
19+
* Allocate either segmented memory pools or contiguous buffer
20+
* based on the controller capability for the host trace
21+
* buffer.
22+
*
2023
* Return: 0 on success, non-zero on failure.
2124
*/
2225
static int mpi3mr_alloc_trace_buffer(struct mpi3mr_ioc *mrioc, u32 trace_size)
2326
{
2427
struct diag_buffer_desc *diag_buffer = &mrioc->diag_buffers[0];
28+
int i, sz;
29+
u64 *diag_buffer_list = NULL;
30+
dma_addr_t diag_buffer_list_dma;
31+
u32 seg_count;
32+
33+
if (mrioc->seg_tb_support) {
34+
seg_count = (trace_size) / MPI3MR_PAGE_SIZE_4K;
35+
trace_size = seg_count * MPI3MR_PAGE_SIZE_4K;
36+
37+
diag_buffer_list = dma_alloc_coherent(&mrioc->pdev->dev,
38+
sizeof(u64) * seg_count,
39+
&diag_buffer_list_dma, GFP_KERNEL);
40+
if (!diag_buffer_list)
41+
return -1;
42+
43+
mrioc->num_tb_segs = seg_count;
44+
45+
sz = sizeof(struct segments) * seg_count;
46+
mrioc->trace_buf = kzalloc(sz, GFP_KERNEL);
47+
if (!mrioc->trace_buf)
48+
goto trace_buf_failed;
49+
50+
mrioc->trace_buf_pool = dma_pool_create("trace_buf pool",
51+
&mrioc->pdev->dev, MPI3MR_PAGE_SIZE_4K, MPI3MR_PAGE_SIZE_4K,
52+
0);
53+
if (!mrioc->trace_buf_pool) {
54+
ioc_err(mrioc, "trace buf pool: dma_pool_create failed\n");
55+
goto trace_buf_pool_failed;
56+
}
2557

26-
diag_buffer->addr = dma_alloc_coherent(&mrioc->pdev->dev,
27-
trace_size, &diag_buffer->dma_addr, GFP_KERNEL);
28-
if (diag_buffer->addr) {
29-
dprint_init(mrioc, "trace diag buffer is allocated successfully\n");
58+
for (i = 0; i < seg_count; i++) {
59+
mrioc->trace_buf[i].segment =
60+
dma_pool_zalloc(mrioc->trace_buf_pool, GFP_KERNEL,
61+
&mrioc->trace_buf[i].segment_dma);
62+
diag_buffer_list[i] =
63+
(u64) mrioc->trace_buf[i].segment_dma;
64+
if (!diag_buffer_list[i])
65+
goto tb_seg_alloc_failed;
66+
}
67+
68+
diag_buffer->addr = diag_buffer_list;
69+
diag_buffer->dma_addr = diag_buffer_list_dma;
70+
diag_buffer->is_segmented = true;
71+
72+
dprint_init(mrioc, "segmented trace diag buffer\n"
73+
"is allocated successfully seg_count:%d\n", seg_count);
3074
return 0;
75+
} else {
76+
diag_buffer->addr = dma_alloc_coherent(&mrioc->pdev->dev,
77+
trace_size, &diag_buffer->dma_addr, GFP_KERNEL);
78+
if (diag_buffer->addr) {
79+
dprint_init(mrioc, "trace diag buffer is allocated successfully\n");
80+
return 0;
81+
}
82+
return -1;
3183
}
84+
85+
tb_seg_alloc_failed:
86+
if (mrioc->trace_buf_pool) {
87+
for (i = 0; i < mrioc->num_tb_segs; i++) {
88+
if (mrioc->trace_buf[i].segment) {
89+
dma_pool_free(mrioc->trace_buf_pool,
90+
mrioc->trace_buf[i].segment,
91+
mrioc->trace_buf[i].segment_dma);
92+
mrioc->trace_buf[i].segment = NULL;
93+
}
94+
mrioc->trace_buf[i].segment = NULL;
95+
}
96+
dma_pool_destroy(mrioc->trace_buf_pool);
97+
mrioc->trace_buf_pool = NULL;
98+
}
99+
trace_buf_pool_failed:
100+
kfree(mrioc->trace_buf);
101+
mrioc->trace_buf = NULL;
102+
trace_buf_failed:
103+
if (diag_buffer_list)
104+
dma_free_coherent(&mrioc->pdev->dev,
105+
sizeof(u64) * mrioc->num_tb_segs,
106+
diag_buffer_list, diag_buffer_list_dma);
32107
return -1;
33108
}
34109

@@ -100,8 +175,9 @@ void mpi3mr_alloc_diag_bufs(struct mpi3mr_ioc *mrioc)
100175
dprint_init(mrioc,
101176
"trying to allocate trace diag buffer of size = %dKB\n",
102177
trace_size / 1024);
103-
if (get_order(trace_size) > MAX_PAGE_ORDER ||
178+
if ((!mrioc->seg_tb_support && (get_order(trace_size) > MAX_PAGE_ORDER)) ||
104179
mpi3mr_alloc_trace_buffer(mrioc, trace_size)) {
180+
105181
retry = true;
106182
trace_size -= trace_dec_size;
107183
dprint_init(mrioc, "trace diag buffer allocation failed\n"
@@ -161,6 +237,12 @@ int mpi3mr_issue_diag_buf_post(struct mpi3mr_ioc *mrioc,
161237
u8 prev_status;
162238
int retval = 0;
163239

240+
if (diag_buffer->disabled_after_reset) {
241+
dprint_bsg_err(mrioc, "%s: skiping diag buffer posting\n"
242+
"as it is disabled after reset\n", __func__);
243+
return -1;
244+
}
245+
164246
memset(&diag_buf_post_req, 0, sizeof(diag_buf_post_req));
165247
mutex_lock(&mrioc->init_cmds.mutex);
166248
if (mrioc->init_cmds.state & MPI3MR_CMD_PENDING) {
@@ -177,8 +259,12 @@ int mpi3mr_issue_diag_buf_post(struct mpi3mr_ioc *mrioc,
177259
diag_buf_post_req.address = le64_to_cpu(diag_buffer->dma_addr);
178260
diag_buf_post_req.length = le32_to_cpu(diag_buffer->size);
179261

180-
dprint_bsg_info(mrioc, "%s: posting diag buffer type %d\n", __func__,
181-
diag_buffer->type);
262+
if (diag_buffer->is_segmented)
263+
diag_buf_post_req.msg_flags |= MPI3_DIAG_BUFFER_POST_MSGFLAGS_SEGMENTED;
264+
265+
dprint_bsg_info(mrioc, "%s: posting diag buffer type %d segmented:%d\n", __func__,
266+
diag_buffer->type, diag_buffer->is_segmented);
267+
182268
prev_status = diag_buffer->status;
183269
diag_buffer->status = MPI3MR_HDB_BUFSTATUS_POSTED_UNPAUSED;
184270
init_completion(&mrioc->init_cmds.done);

drivers/scsi/mpi3mr/mpi3mr_fw.c

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1302,7 +1302,7 @@ static int mpi3mr_issue_and_process_mur(struct mpi3mr_ioc *mrioc,
13021302
(ioc_config & MPI3_SYSIF_IOC_CONFIG_ENABLE_IOC)))
13031303
retval = 0;
13041304

1305-
ioc_info(mrioc, "Base IOC Sts/Config after %s MUR is (0x%x)/(0x%x)\n",
1305+
ioc_info(mrioc, "Base IOC Sts/Config after %s MUR is (0x%08x)/(0x%08x)\n",
13061306
(!retval) ? "successful" : "failed", ioc_status, ioc_config);
13071307
return retval;
13081308
}
@@ -1355,6 +1355,19 @@ mpi3mr_revalidate_factsdata(struct mpi3mr_ioc *mrioc)
13551355
"\tcontroller while sas transport support is enabled at the\n"
13561356
"\tdriver, please reboot the system or reload the driver\n");
13571357

1358+
if (mrioc->seg_tb_support) {
1359+
if (!(mrioc->facts.ioc_capabilities &
1360+
MPI3_IOCFACTS_CAPABILITY_SEG_DIAG_TRACE_SUPPORTED)) {
1361+
ioc_err(mrioc,
1362+
"critical error: previously enabled segmented trace\n"
1363+
" buffer capability is disabled after reset. Please\n"
1364+
" update the firmware or reboot the system or\n"
1365+
" reload the driver to enable trace diag buffer\n");
1366+
mrioc->diag_buffers[0].disabled_after_reset = true;
1367+
} else
1368+
mrioc->diag_buffers[0].disabled_after_reset = false;
1369+
}
1370+
13581371
if (mrioc->facts.max_devhandle > mrioc->dev_handle_bitmap_bits) {
13591372
removepend_bitmap = bitmap_zalloc(mrioc->facts.max_devhandle,
13601373
GFP_KERNEL);
@@ -1717,7 +1730,7 @@ static int mpi3mr_issue_reset(struct mpi3mr_ioc *mrioc, u16 reset_type,
17171730
ioc_config = readl(&mrioc->sysif_regs->ioc_configuration);
17181731
ioc_status = readl(&mrioc->sysif_regs->ioc_status);
17191732
ioc_info(mrioc,
1720-
"ioc_status/ioc_onfig after %s reset is (0x%x)/(0x%x)\n",
1733+
"ioc_status/ioc_config after %s reset is (0x%08x)/(0x%08x)\n",
17211734
(!retval)?"successful":"failed", ioc_status,
17221735
ioc_config);
17231736
if (retval)
@@ -4238,6 +4251,10 @@ int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc)
42384251
if (mrioc->facts.max_req_limit)
42394252
mrioc->prevent_reply_qfull = true;
42404253

4254+
if (mrioc->facts.ioc_capabilities &
4255+
MPI3_IOCFACTS_CAPABILITY_SEG_DIAG_TRACE_SUPPORTED)
4256+
mrioc->seg_tb_support = true;
4257+
42414258
mrioc->reply_sz = mrioc->facts.reply_sz;
42424259

42434260
retval = mpi3mr_check_reset_dma_mask(mrioc);
@@ -4695,7 +4712,7 @@ void mpi3mr_memset_buffers(struct mpi3mr_ioc *mrioc)
46954712
*/
46964713
void mpi3mr_free_mem(struct mpi3mr_ioc *mrioc)
46974714
{
4698-
u16 i;
4715+
u16 i, j;
46994716
struct mpi3mr_intr_info *intr_info;
47004717
struct diag_buffer_desc *diag_buffer;
47014718

@@ -4830,6 +4847,26 @@ void mpi3mr_free_mem(struct mpi3mr_ioc *mrioc)
48304847

48314848
for (i = 0; i < MPI3MR_MAX_NUM_HDB; i++) {
48324849
diag_buffer = &mrioc->diag_buffers[i];
4850+
if ((i == 0) && mrioc->seg_tb_support) {
4851+
if (mrioc->trace_buf_pool) {
4852+
for (j = 0; j < mrioc->num_tb_segs; j++) {
4853+
if (mrioc->trace_buf[j].segment) {
4854+
dma_pool_free(mrioc->trace_buf_pool,
4855+
mrioc->trace_buf[j].segment,
4856+
mrioc->trace_buf[j].segment_dma);
4857+
mrioc->trace_buf[j].segment = NULL;
4858+
}
4859+
4860+
mrioc->trace_buf[j].segment = NULL;
4861+
}
4862+
dma_pool_destroy(mrioc->trace_buf_pool);
4863+
mrioc->trace_buf_pool = NULL;
4864+
}
4865+
4866+
kfree(mrioc->trace_buf);
4867+
mrioc->trace_buf = NULL;
4868+
diag_buffer->size = sizeof(u64) * mrioc->num_tb_segs;
4869+
}
48334870
if (diag_buffer->addr) {
48344871
dma_free_coherent(&mrioc->pdev->dev,
48354872
diag_buffer->size, diag_buffer->addr,
@@ -4907,7 +4944,7 @@ static void mpi3mr_issue_ioc_shutdown(struct mpi3mr_ioc *mrioc)
49074944
}
49084945

49094946
ioc_info(mrioc,
4910-
"Base IOC Sts/Config after %s shutdown is (0x%x)/(0x%x)\n",
4947+
"Base IOC Sts/Config after %s shutdown is (0x%08x)/(0x%08x)\n",
49114948
(!retval) ? "successful" : "failed", ioc_status,
49124949
ioc_config);
49134950
}

0 commit comments

Comments
 (0)