Skip to content

Commit 95bfc6d

Browse files
jsmart-ghmartinkpetersen
authored andcommitted
scsi: lpfc: Make FW logging dynamically configurable
Currently, the FW logging facility is a load/boot time parameter which requires the driver to be unloaded/reloaded or the system rebooted in order to change its configuration. Convert the logging facility to allow dynamic enablement and configuration. Specifically: - Convert the feature so that it can be enabled dynamically via an attribute. Additionally, the size of the buffer can be configured dynamically. - Add locks around states that now may be changing. - Tie the feature into debugfs so that the logs can be read at any time. Link: https://lore.kernel.org/r/20191018211832.7917-12-jsmart2021@gmail.com Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com> Signed-off-by: James Smart <jsmart2021@gmail.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
1 parent 8156d37 commit 95bfc6d

File tree

5 files changed

+204
-10
lines changed

5 files changed

+204
-10
lines changed

drivers/scsi/lpfc/lpfc.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -605,6 +605,12 @@ struct lpfc_epd_pool {
605605
spinlock_t lock; /* lock for expedite pool */
606606
};
607607

608+
enum ras_state {
609+
INACTIVE,
610+
REG_INPROGRESS,
611+
ACTIVE
612+
};
613+
608614
struct lpfc_ras_fwlog {
609615
uint8_t *fwlog_buff;
610616
uint32_t fw_buffcount; /* Buffer size posted to FW */
@@ -621,7 +627,7 @@ struct lpfc_ras_fwlog {
621627
bool ras_enabled; /* Ras Enabled for the function */
622628
#define LPFC_RAS_DISABLE_LOGGING 0x00
623629
#define LPFC_RAS_ENABLE_LOGGING 0x01
624-
bool ras_active; /* RAS logging running state */
630+
enum ras_state state; /* RAS logging running state */
625631
};
626632

627633
struct lpfc_hba {
@@ -1053,6 +1059,7 @@ struct lpfc_hba {
10531059
#ifdef LPFC_HDWQ_LOCK_STAT
10541060
struct dentry *debug_lockstat;
10551061
#endif
1062+
struct dentry *debug_ras_log;
10561063
atomic_t nvmeio_trc_cnt;
10571064
uint32_t nvmeio_trc_size;
10581065
uint32_t nvmeio_trc_output_idx;

drivers/scsi/lpfc/lpfc_attr.c

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5932,7 +5932,53 @@ LPFC_ATTR_RW(enable_mds_diags, 0, 0, 1, "Enable MDS Diagnostics");
59325932
* [1-4] = Multiple of 1/4th Mb of host memory for FW logging
59335933
* Value range [0..4]. Default value is 0
59345934
*/
5935-
LPFC_ATTR_RW(ras_fwlog_buffsize, 0, 0, 4, "Host memory for FW logging");
5935+
LPFC_ATTR(ras_fwlog_buffsize, 0, 0, 4, "Host memory for FW logging");
5936+
lpfc_param_show(ras_fwlog_buffsize);
5937+
5938+
static ssize_t
5939+
lpfc_ras_fwlog_buffsize_set(struct lpfc_hba *phba, uint val)
5940+
{
5941+
int ret = 0;
5942+
enum ras_state state;
5943+
5944+
if (!lpfc_rangecheck(val, 0, 4))
5945+
return -EINVAL;
5946+
5947+
if (phba->cfg_ras_fwlog_buffsize == val)
5948+
return 0;
5949+
5950+
if (phba->cfg_ras_fwlog_func == PCI_FUNC(phba->pcidev->devfn))
5951+
return -EINVAL;
5952+
5953+
spin_lock_irq(&phba->hbalock);
5954+
state = phba->ras_fwlog.state;
5955+
spin_unlock_irq(&phba->hbalock);
5956+
5957+
if (state == REG_INPROGRESS) {
5958+
lpfc_printf_log(phba, KERN_ERR, LOG_SLI, "6147 RAS Logging "
5959+
"registration is in progress\n");
5960+
return -EBUSY;
5961+
}
5962+
5963+
/* For disable logging: stop the logs and free the DMA.
5964+
* For ras_fwlog_buffsize size change we still need to free and
5965+
* reallocate the DMA in lpfc_sli4_ras_fwlog_init.
5966+
*/
5967+
phba->cfg_ras_fwlog_buffsize = val;
5968+
if (state == ACTIVE) {
5969+
lpfc_ras_stop_fwlog(phba);
5970+
lpfc_sli4_ras_dma_free(phba);
5971+
}
5972+
5973+
lpfc_sli4_ras_init(phba);
5974+
if (phba->ras_fwlog.ras_enabled)
5975+
ret = lpfc_sli4_ras_fwlog_init(phba, phba->cfg_ras_fwlog_level,
5976+
LPFC_RAS_ENABLE_LOGGING);
5977+
return ret;
5978+
}
5979+
5980+
lpfc_param_store(ras_fwlog_buffsize);
5981+
static DEVICE_ATTR_RW(lpfc_ras_fwlog_buffsize);
59365982

59375983
/*
59385984
* lpfc_ras_fwlog_level: Firmware logging verbosity level

drivers/scsi/lpfc/lpfc_bsg.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5435,10 +5435,12 @@ lpfc_bsg_get_ras_config(struct bsg_job *job)
54355435
bsg_reply->reply_data.vendor_reply.vendor_rsp;
54365436

54375437
/* Current logging state */
5438-
if (ras_fwlog->ras_active == true)
5438+
spin_lock_irq(&phba->hbalock);
5439+
if (ras_fwlog->state == ACTIVE)
54395440
ras_reply->state = LPFC_RASLOG_STATE_RUNNING;
54405441
else
54415442
ras_reply->state = LPFC_RASLOG_STATE_STOPPED;
5443+
spin_unlock_irq(&phba->hbalock);
54425444

54435445
ras_reply->log_level = phba->ras_fwlog.fw_loglevel;
54445446
ras_reply->log_buff_sz = phba->cfg_ras_fwlog_buffsize;
@@ -5495,10 +5497,13 @@ lpfc_bsg_set_ras_config(struct bsg_job *job)
54955497

54965498
if (action == LPFC_RASACTION_STOP_LOGGING) {
54975499
/* Check if already disabled */
5498-
if (ras_fwlog->ras_active == false) {
5500+
spin_lock_irq(&phba->hbalock);
5501+
if (ras_fwlog->state != ACTIVE) {
5502+
spin_unlock_irq(&phba->hbalock);
54995503
rc = -ESRCH;
55005504
goto ras_job_error;
55015505
}
5506+
spin_unlock_irq(&phba->hbalock);
55025507

55035508
/* Disable logging */
55045509
lpfc_ras_stop_fwlog(phba);
@@ -5509,8 +5514,10 @@ lpfc_bsg_set_ras_config(struct bsg_job *job)
55095514
* FW-logging with new log-level. Return status
55105515
* "Logging already Running" to caller.
55115516
**/
5512-
if (ras_fwlog->ras_active)
5517+
spin_lock_irq(&phba->hbalock);
5518+
if (ras_fwlog->state != INACTIVE)
55135519
action_status = -EINPROGRESS;
5520+
spin_unlock_irq(&phba->hbalock);
55145521

55155522
/* Enable logging */
55165523
rc = lpfc_sli4_ras_fwlog_init(phba, log_level,
@@ -5626,10 +5633,13 @@ lpfc_bsg_get_ras_fwlog(struct bsg_job *job)
56265633
goto ras_job_error;
56275634

56285635
/* Logging to be stopped before reading */
5629-
if (ras_fwlog->ras_active == true) {
5636+
spin_lock_irq(&phba->hbalock);
5637+
if (ras_fwlog->state == ACTIVE) {
5638+
spin_unlock_irq(&phba->hbalock);
56305639
rc = -EINPROGRESS;
56315640
goto ras_job_error;
56325641
}
5642+
spin_unlock_irq(&phba->hbalock);
56335643

56345644
if (job->request_len <
56355645
sizeof(struct fc_bsg_request) +

drivers/scsi/lpfc/lpfc_debugfs.c

Lines changed: 116 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2078,6 +2078,96 @@ lpfc_debugfs_lockstat_write(struct file *file, const char __user *buf,
20782078
}
20792079
#endif
20802080

2081+
int
2082+
lpfc_debugfs_ras_log_data(struct lpfc_hba *phba, char *buffer, int size)
2083+
{
2084+
int copied = 0;
2085+
struct lpfc_dmabuf *dmabuf, *next;
2086+
2087+
spin_lock_irq(&phba->hbalock);
2088+
if (phba->ras_fwlog.state != ACTIVE) {
2089+
spin_unlock_irq(&phba->hbalock);
2090+
return -EINVAL;
2091+
}
2092+
spin_unlock_irq(&phba->hbalock);
2093+
2094+
list_for_each_entry_safe(dmabuf, next,
2095+
&phba->ras_fwlog.fwlog_buff_list, list) {
2096+
memcpy(buffer + copied, dmabuf->virt, LPFC_RAS_MAX_ENTRY_SIZE);
2097+
copied += LPFC_RAS_MAX_ENTRY_SIZE;
2098+
if (size > copied)
2099+
break;
2100+
}
2101+
return copied;
2102+
}
2103+
2104+
static int
2105+
lpfc_debugfs_ras_log_release(struct inode *inode, struct file *file)
2106+
{
2107+
struct lpfc_debug *debug = file->private_data;
2108+
2109+
vfree(debug->buffer);
2110+
kfree(debug);
2111+
2112+
return 0;
2113+
}
2114+
2115+
/**
2116+
* lpfc_debugfs_ras_log_open - Open the RAS log debugfs buffer
2117+
* @inode: The inode pointer that contains a vport pointer.
2118+
* @file: The file pointer to attach the log output.
2119+
*
2120+
* Description:
2121+
* This routine is the entry point for the debugfs open file operation. It gets
2122+
* the vport from the i_private field in @inode, allocates the necessary buffer
2123+
* for the log, fills the buffer from the in-memory log for this vport, and then
2124+
* returns a pointer to that log in the private_data field in @file.
2125+
*
2126+
* Returns:
2127+
* This function returns zero if successful. On error it will return a negative
2128+
* error value.
2129+
**/
2130+
static int
2131+
lpfc_debugfs_ras_log_open(struct inode *inode, struct file *file)
2132+
{
2133+
struct lpfc_hba *phba = inode->i_private;
2134+
struct lpfc_debug *debug;
2135+
int size;
2136+
int rc = -ENOMEM;
2137+
2138+
spin_lock_irq(&phba->hbalock);
2139+
if (phba->ras_fwlog.state != ACTIVE) {
2140+
spin_unlock_irq(&phba->hbalock);
2141+
rc = -EINVAL;
2142+
goto out;
2143+
}
2144+
spin_unlock_irq(&phba->hbalock);
2145+
debug = kmalloc(sizeof(*debug), GFP_KERNEL);
2146+
if (!debug)
2147+
goto out;
2148+
2149+
size = LPFC_RAS_MIN_BUFF_POST_SIZE * phba->cfg_ras_fwlog_buffsize;
2150+
debug->buffer = vmalloc(size);
2151+
if (!debug->buffer)
2152+
goto free_debug;
2153+
2154+
debug->len = lpfc_debugfs_ras_log_data(phba, debug->buffer, size);
2155+
if (debug->len < 0) {
2156+
rc = -EINVAL;
2157+
goto free_buffer;
2158+
}
2159+
file->private_data = debug;
2160+
2161+
return 0;
2162+
2163+
free_buffer:
2164+
vfree(debug->buffer);
2165+
free_debug:
2166+
kfree(debug);
2167+
out:
2168+
return rc;
2169+
}
2170+
20812171
/**
20822172
* lpfc_debugfs_dumpHBASlim_open - Open the Dump HBA SLIM debugfs buffer
20832173
* @inode: The inode pointer that contains a vport pointer.
@@ -5286,6 +5376,16 @@ static const struct file_operations lpfc_debugfs_op_lockstat = {
52865376
};
52875377
#endif
52885378

5379+
#undef lpfc_debugfs_ras_log
5380+
static const struct file_operations lpfc_debugfs_ras_log = {
5381+
.owner = THIS_MODULE,
5382+
.open = lpfc_debugfs_ras_log_open,
5383+
.llseek = lpfc_debugfs_lseek,
5384+
.read = lpfc_debugfs_read,
5385+
.release = lpfc_debugfs_ras_log_release,
5386+
};
5387+
#endif
5388+
52895389
#undef lpfc_debugfs_op_dumpHBASlim
52905390
static const struct file_operations lpfc_debugfs_op_dumpHBASlim = {
52915391
.owner = THIS_MODULE,
@@ -5457,7 +5557,6 @@ static const struct file_operations lpfc_idiag_op_extAcc = {
54575557
.release = lpfc_idiag_cmd_release,
54585558
};
54595559

5460-
#endif
54615560

54625561
/* lpfc_idiag_mbxacc_dump_bsg_mbox - idiag debugfs dump bsg mailbox command
54635562
* @phba: Pointer to HBA context object.
@@ -5707,6 +5806,19 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
57075806
goto debug_failed;
57085807
}
57095808

5809+
/* RAS log */
5810+
snprintf(name, sizeof(name), "ras_log");
5811+
phba->debug_ras_log =
5812+
debugfs_create_file(name, 0644,
5813+
phba->hba_debugfs_root,
5814+
phba, &lpfc_debugfs_ras_log);
5815+
if (!phba->debug_ras_log) {
5816+
lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
5817+
"6148 Cannot create debugfs"
5818+
" ras_log\n");
5819+
goto debug_failed;
5820+
}
5821+
57105822
/* Setup hbqinfo */
57115823
snprintf(name, sizeof(name), "hbqinfo");
57125824
phba->debug_hbqinfo =
@@ -6117,6 +6229,9 @@ lpfc_debugfs_terminate(struct lpfc_vport *vport)
61176229
debugfs_remove(phba->debug_hbqinfo); /* hbqinfo */
61186230
phba->debug_hbqinfo = NULL;
61196231

6232+
debugfs_remove(phba->debug_ras_log);
6233+
phba->debug_ras_log = NULL;
6234+
61206235
#ifdef LPFC_HDWQ_LOCK_STAT
61216236
debugfs_remove(phba->debug_lockstat); /* lockstat */
61226237
phba->debug_lockstat = NULL;

drivers/scsi/lpfc/lpfc_sli.c

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6219,11 +6219,16 @@ lpfc_ras_stop_fwlog(struct lpfc_hba *phba)
62196219
{
62206220
struct lpfc_ras_fwlog *ras_fwlog = &phba->ras_fwlog;
62216221

6222-
ras_fwlog->ras_active = false;
6222+
spin_lock_irq(&phba->hbalock);
6223+
ras_fwlog->state = INACTIVE;
6224+
spin_unlock_irq(&phba->hbalock);
62236225

62246226
/* Disable FW logging to host memory */
62256227
writel(LPFC_CTL_PDEV_CTL_DDL_RAS,
62266228
phba->sli4_hba.conf_regs_memmap_p + LPFC_CTL_PDEV_CTL_OFFSET);
6229+
6230+
/* Wait 10ms for firmware to stop using DMA buffer */
6231+
usleep_range(10 * 1000, 20 * 1000);
62276232
}
62286233

62296234
/**
@@ -6259,7 +6264,9 @@ lpfc_sli4_ras_dma_free(struct lpfc_hba *phba)
62596264
ras_fwlog->lwpd.virt = NULL;
62606265
}
62616266

6262-
ras_fwlog->ras_active = false;
6267+
spin_lock_irq(&phba->hbalock);
6268+
ras_fwlog->state = INACTIVE;
6269+
spin_unlock_irq(&phba->hbalock);
62636270
}
62646271

62656272
/**
@@ -6361,7 +6368,9 @@ lpfc_sli4_ras_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
63616368
goto disable_ras;
63626369
}
63636370

6364-
ras_fwlog->ras_active = true;
6371+
spin_lock_irq(&phba->hbalock);
6372+
ras_fwlog->state = ACTIVE;
6373+
spin_unlock_irq(&phba->hbalock);
63656374
mempool_free(pmb, phba->mbox_mem_pool);
63666375

63676376
return;
@@ -6393,6 +6402,10 @@ lpfc_sli4_ras_fwlog_init(struct lpfc_hba *phba,
63936402
uint32_t len = 0, fwlog_buffsize, fwlog_entry_count;
63946403
int rc = 0;
63956404

6405+
spin_lock_irq(&phba->hbalock);
6406+
ras_fwlog->state = INACTIVE;
6407+
spin_unlock_irq(&phba->hbalock);
6408+
63966409
fwlog_buffsize = (LPFC_RAS_MIN_BUFF_POST_SIZE *
63976410
phba->cfg_ras_fwlog_buffsize);
63986411
fwlog_entry_count = (fwlog_buffsize/LPFC_RAS_MAX_ENTRY_SIZE);
@@ -6452,6 +6465,9 @@ lpfc_sli4_ras_fwlog_init(struct lpfc_hba *phba,
64526465
mbx_fwlog->u.request.lwpd.addr_lo = putPaddrLow(ras_fwlog->lwpd.phys);
64536466
mbx_fwlog->u.request.lwpd.addr_hi = putPaddrHigh(ras_fwlog->lwpd.phys);
64546467

6468+
spin_lock_irq(&phba->hbalock);
6469+
ras_fwlog->state = REG_INPROGRESS;
6470+
spin_unlock_irq(&phba->hbalock);
64556471
mbox->vport = phba->pport;
64566472
mbox->mbox_cmpl = lpfc_sli4_ras_mbox_cmpl;
64576473

0 commit comments

Comments
 (0)