Skip to content

Commit cd96fe6

Browse files
Luojiaxing1991martinkpetersen
authored andcommitted
scsi: hisi_sas: Add trace FIFO debugfs support
The controller provides trace FIFO DFX tool to assist link fault debugging and link optimization. This tool can be helpful when debugging link faults without SAS analyzers. Each PHY has an independent trace FIFO interface. The user can configure the trace FIFO tool of one PHY by using the following six interfaces: signal_sel: select signal group applies to different scenarios. 0x0: linkrate negotiation 0x1: Host 12G TX train 0x2: Disk 12G TX train 0x3: SAS PHY CTRL DFX 0 0x4: SAS PHY CTRL DFX 1 0x5: SAS PCS DFX other: linkrate negotiation dump_mask: The masked hardware status bit will not be updated. dump_mode: determines how to dump data after trigger signal is generated. 0x0: dump forever 0x1: dump 32 data after trigger signal is generated 0x2: no more dump after trigger signal is generated trigger_mode: determines the trigger mode, level or edge. 0x0: dump when trigger signal changed 0x1: dump when trigger signal's level equal to trigger_level 0x2: dump when trigger signal's level different from trigger_level trigger_level: determines the trigger level. trigger_msk: mask trigger signal The user can get 32-byte values from hardware by reading the rd_data. These values consitute the status record of the hardware at different time points. Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Luo Jiaxing <[email protected]> Signed-off-by: John Garry <[email protected]> Signed-off-by: Martin K. Petersen <[email protected]>
1 parent 6834ec8 commit cd96fe6

File tree

2 files changed

+266
-0
lines changed

2 files changed

+266
-0
lines changed

drivers/scsi/hisi_sas/hisi_sas.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444

4545
#define HISI_SAS_IOST_ITCT_CACHE_NUM 64
4646
#define HISI_SAS_IOST_ITCT_CACHE_DW_SZ 10
47+
#define HISI_SAS_FIFO_DATA_DW_SIZE 32
4748

4849
#define HISI_SAS_STATUS_BUF_SZ (sizeof(struct hisi_sas_status_buffer))
4950
#define HISI_SAS_COMMAND_TABLE_SZ (sizeof(union hisi_sas_command_table))
@@ -154,6 +155,16 @@ enum hisi_sas_phy_event {
154155
HISI_PHYES_NUM,
155156
};
156157

158+
struct hisi_sas_debugfs_fifo {
159+
u32 signal_sel;
160+
u32 dump_msk;
161+
u32 dump_mode;
162+
u32 trigger;
163+
u32 trigger_msk;
164+
u32 trigger_mode;
165+
u32 rd_data[HISI_SAS_FIFO_DATA_DW_SIZE];
166+
};
167+
157168
struct hisi_sas_phy {
158169
struct work_struct works[HISI_PHYES_NUM];
159170
struct hisi_hba *hisi_hba;
@@ -175,6 +186,9 @@ struct hisi_sas_phy {
175186
enum sas_linkrate maximum_linkrate;
176187
int enable;
177188
atomic_t down_cnt;
189+
190+
/* Trace FIFO */
191+
struct hisi_sas_debugfs_fifo fifo;
178192
};
179193

180194
struct hisi_sas_port {
@@ -474,6 +488,7 @@ struct hisi_hba {
474488
struct dentry *debugfs_dir;
475489
struct dentry *debugfs_dump_dentry;
476490
struct dentry *debugfs_bist_dentry;
491+
struct dentry *debugfs_fifo_dentry;
477492
};
478493

479494
/* Generic HW DMA host memory structures */

drivers/scsi/hisi_sas/hisi_sas_v3_hw.c

Lines changed: 251 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,19 @@
303303
#define ERR_CNT_INVLD_DW (PORT_BASE + 0x390)
304304
#define ERR_CNT_CODE_ERR (PORT_BASE + 0x394)
305305
#define ERR_CNT_DISP_ERR (PORT_BASE + 0x398)
306+
#define DFX_FIFO_CTRL (PORT_BASE + 0x3a0)
307+
#define DFX_FIFO_CTRL_TRIGGER_MODE_OFF 0
308+
#define DFX_FIFO_CTRL_TRIGGER_MODE_MSK (0x7 << DFX_FIFO_CTRL_TRIGGER_MODE_OFF)
309+
#define DFX_FIFO_CTRL_DUMP_MODE_OFF 3
310+
#define DFX_FIFO_CTRL_DUMP_MODE_MSK (0x7 << DFX_FIFO_CTRL_DUMP_MODE_OFF)
311+
#define DFX_FIFO_CTRL_SIGNAL_SEL_OFF 6
312+
#define DFX_FIFO_CTRL_SIGNAL_SEL_MSK (0xF << DFX_FIFO_CTRL_SIGNAL_SEL_OFF)
313+
#define DFX_FIFO_CTRL_DUMP_DISABLE_OFF 10
314+
#define DFX_FIFO_CTRL_DUMP_DISABLE_MSK (0x1 << DFX_FIFO_CTRL_DUMP_DISABLE_OFF)
315+
#define DFX_FIFO_TRIGGER (PORT_BASE + 0x3a4)
316+
#define DFX_FIFO_TRIGGER_MSK (PORT_BASE + 0x3a8)
317+
#define DFX_FIFO_DUMP_MSK (PORT_BASE + 0x3aC)
318+
#define DFX_FIFO_RD_DATA (PORT_BASE + 0x3b0)
306319

307320
#define DEFAULT_ITCT_HW 2048 /* reset value, not reprogrammed */
308321
#if (HISI_SAS_MAX_DEVICES > DEFAULT_ITCT_HW)
@@ -4153,6 +4166,243 @@ static const struct file_operations debugfs_phy_down_cnt_v3_hw_fops = {
41534166
.owner = THIS_MODULE,
41544167
};
41554168

4169+
enum fifo_dump_mode_v3_hw {
4170+
FIFO_DUMP_FORVER = (1U << 0),
4171+
FIFO_DUMP_AFTER_TRIGGER = (1U << 1),
4172+
FIFO_DUMP_UNTILL_TRIGGER = (1U << 2),
4173+
};
4174+
4175+
enum fifo_trigger_mode_v3_hw {
4176+
FIFO_TRIGGER_EDGE = (1U << 0),
4177+
FIFO_TRIGGER_SAME_LEVEL = (1U << 1),
4178+
FIFO_TRIGGER_DIFF_LEVEL = (1U << 2),
4179+
};
4180+
4181+
static int debugfs_is_fifo_config_valid_v3_hw(struct hisi_sas_phy *phy)
4182+
{
4183+
struct hisi_hba *hisi_hba = phy->hisi_hba;
4184+
4185+
if (phy->fifo.signal_sel > 0xf) {
4186+
dev_info(hisi_hba->dev, "Invalid signal select: %u\n",
4187+
phy->fifo.signal_sel);
4188+
return -EINVAL;
4189+
}
4190+
4191+
switch (phy->fifo.dump_mode) {
4192+
case FIFO_DUMP_FORVER:
4193+
case FIFO_DUMP_AFTER_TRIGGER:
4194+
case FIFO_DUMP_UNTILL_TRIGGER:
4195+
break;
4196+
default:
4197+
dev_info(hisi_hba->dev, "Invalid dump mode: %u\n",
4198+
phy->fifo.dump_mode);
4199+
return -EINVAL;
4200+
}
4201+
4202+
/* when FIFO_DUMP_FORVER, no need to check trigger_mode */
4203+
if (phy->fifo.dump_mode == FIFO_DUMP_FORVER)
4204+
return 0;
4205+
4206+
switch (phy->fifo.trigger_mode) {
4207+
case FIFO_TRIGGER_EDGE:
4208+
case FIFO_TRIGGER_SAME_LEVEL:
4209+
case FIFO_TRIGGER_DIFF_LEVEL:
4210+
break;
4211+
default:
4212+
dev_info(hisi_hba->dev, "Invalid trigger mode: %u\n",
4213+
phy->fifo.trigger_mode);
4214+
return -EINVAL;
4215+
}
4216+
return 0;
4217+
}
4218+
4219+
static int debugfs_update_fifo_config_v3_hw(struct hisi_sas_phy *phy)
4220+
{
4221+
u32 trigger_mode = phy->fifo.trigger_mode;
4222+
u32 signal_sel = phy->fifo.signal_sel;
4223+
u32 dump_mode = phy->fifo.dump_mode;
4224+
struct hisi_hba *hisi_hba = phy->hisi_hba;
4225+
int phy_no = phy->sas_phy.id;
4226+
u32 reg_val;
4227+
int res;
4228+
4229+
/* Check the validity of trace FIFO configuration */
4230+
res = debugfs_is_fifo_config_valid_v3_hw(phy);
4231+
if (res)
4232+
return res;
4233+
4234+
reg_val = hisi_sas_phy_read32(hisi_hba, phy_no, DFX_FIFO_CTRL);
4235+
/* Disable trace FIFO before update configuration */
4236+
reg_val |= DFX_FIFO_CTRL_DUMP_DISABLE_MSK;
4237+
4238+
/* Update trace FIFO configuration */
4239+
reg_val &= ~(DFX_FIFO_CTRL_DUMP_MODE_MSK |
4240+
DFX_FIFO_CTRL_SIGNAL_SEL_MSK |
4241+
DFX_FIFO_CTRL_TRIGGER_MODE_MSK);
4242+
4243+
reg_val |= ((trigger_mode << DFX_FIFO_CTRL_TRIGGER_MODE_OFF) |
4244+
(dump_mode << DFX_FIFO_CTRL_DUMP_MODE_OFF) |
4245+
(signal_sel << DFX_FIFO_CTRL_SIGNAL_SEL_OFF));
4246+
hisi_sas_phy_write32(hisi_hba, phy_no, DFX_FIFO_CTRL, reg_val);
4247+
4248+
hisi_sas_phy_write32(hisi_hba, phy_no, DFX_FIFO_DUMP_MSK,
4249+
phy->fifo.dump_msk);
4250+
4251+
hisi_sas_phy_write32(hisi_hba, phy_no, DFX_FIFO_TRIGGER,
4252+
phy->fifo.trigger);
4253+
4254+
hisi_sas_phy_write32(hisi_hba, phy_no, DFX_FIFO_TRIGGER_MSK,
4255+
phy->fifo.trigger_msk);
4256+
4257+
/* Enable trace FIFO after updated configuration */
4258+
reg_val = hisi_sas_phy_read32(hisi_hba, phy_no, DFX_FIFO_CTRL);
4259+
reg_val &= ~DFX_FIFO_CTRL_DUMP_DISABLE_MSK;
4260+
hisi_sas_phy_write32(hisi_hba, phy_no, DFX_FIFO_CTRL, reg_val);
4261+
4262+
return 0;
4263+
}
4264+
4265+
static ssize_t debugfs_fifo_update_cfg_v3_hw_write(struct file *filp,
4266+
const char __user *buf,
4267+
size_t count, loff_t *ppos)
4268+
{
4269+
struct hisi_sas_phy *phy = filp->private_data;
4270+
bool update;
4271+
int val;
4272+
4273+
val = kstrtobool_from_user(buf, count, &update);
4274+
if (val)
4275+
return val;
4276+
4277+
if (update != 1)
4278+
return -EINVAL;
4279+
4280+
val = debugfs_update_fifo_config_v3_hw(phy);
4281+
if (val)
4282+
return val;
4283+
4284+
return count;
4285+
}
4286+
4287+
static const struct file_operations debugfs_fifo_update_cfg_v3_hw_fops = {
4288+
.open = simple_open,
4289+
.write = debugfs_fifo_update_cfg_v3_hw_write,
4290+
.owner = THIS_MODULE,
4291+
};
4292+
4293+
static void debugfs_read_fifo_data_v3_hw(struct hisi_sas_phy *phy)
4294+
{
4295+
struct hisi_hba *hisi_hba = phy->hisi_hba;
4296+
u32 *buf = phy->fifo.rd_data;
4297+
int phy_no = phy->sas_phy.id;
4298+
u32 val;
4299+
int i;
4300+
4301+
memset(buf, 0, sizeof(phy->fifo.rd_data));
4302+
4303+
/* Disable trace FIFO before read data */
4304+
val = hisi_sas_phy_read32(hisi_hba, phy_no, DFX_FIFO_CTRL);
4305+
val |= DFX_FIFO_CTRL_DUMP_DISABLE_MSK;
4306+
hisi_sas_phy_write32(hisi_hba, phy_no, DFX_FIFO_CTRL, val);
4307+
4308+
for (i = 0; i < HISI_SAS_FIFO_DATA_DW_SIZE; i++) {
4309+
val = hisi_sas_phy_read32(hisi_hba, phy_no,
4310+
DFX_FIFO_RD_DATA);
4311+
buf[i] = val;
4312+
}
4313+
4314+
/* Enable trace FIFO after read data */
4315+
val = hisi_sas_phy_read32(hisi_hba, phy_no, DFX_FIFO_CTRL);
4316+
val &= ~DFX_FIFO_CTRL_DUMP_DISABLE_MSK;
4317+
hisi_sas_phy_write32(hisi_hba, phy_no, DFX_FIFO_CTRL, val);
4318+
}
4319+
4320+
static int debugfs_fifo_data_v3_hw_show(struct seq_file *s, void *p)
4321+
{
4322+
struct hisi_sas_phy *phy = s->private;
4323+
4324+
debugfs_read_fifo_data_v3_hw(phy);
4325+
4326+
debugfs_show_row_32_v3_hw(s, 0, HISI_SAS_FIFO_DATA_DW_SIZE * 4,
4327+
phy->fifo.rd_data);
4328+
4329+
return 0;
4330+
}
4331+
DEFINE_SHOW_ATTRIBUTE(debugfs_fifo_data_v3_hw);
4332+
4333+
static void debugfs_fifo_init_v3_hw(struct hisi_hba *hisi_hba)
4334+
{
4335+
int phy_no;
4336+
4337+
hisi_hba->debugfs_fifo_dentry =
4338+
debugfs_create_dir("fifo", hisi_hba->debugfs_dir);
4339+
4340+
for (phy_no = 0; phy_no < hisi_hba->n_phy; phy_no++) {
4341+
struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
4342+
struct dentry *port_dentry;
4343+
char name[256];
4344+
u32 val;
4345+
4346+
/* get default configuration for trace FIFO */
4347+
val = hisi_sas_phy_read32(hisi_hba, phy_no, DFX_FIFO_CTRL);
4348+
val &= DFX_FIFO_CTRL_DUMP_MODE_MSK;
4349+
val >>= DFX_FIFO_CTRL_DUMP_MODE_OFF;
4350+
phy->fifo.dump_mode = val;
4351+
4352+
val = hisi_sas_phy_read32(hisi_hba, phy_no, DFX_FIFO_CTRL);
4353+
val &= DFX_FIFO_CTRL_TRIGGER_MODE_MSK;
4354+
val >>= DFX_FIFO_CTRL_TRIGGER_MODE_OFF;
4355+
phy->fifo.trigger_mode = val;
4356+
4357+
val = hisi_sas_phy_read32(hisi_hba, phy_no, DFX_FIFO_CTRL);
4358+
val &= DFX_FIFO_CTRL_SIGNAL_SEL_MSK;
4359+
val >>= DFX_FIFO_CTRL_SIGNAL_SEL_OFF;
4360+
phy->fifo.signal_sel = val;
4361+
4362+
val = hisi_sas_phy_read32(hisi_hba, phy_no, DFX_FIFO_DUMP_MSK);
4363+
phy->fifo.dump_msk = val;
4364+
4365+
val = hisi_sas_phy_read32(hisi_hba, phy_no, DFX_FIFO_TRIGGER);
4366+
phy->fifo.trigger = val;
4367+
val = hisi_sas_phy_read32(hisi_hba, phy_no, DFX_FIFO_TRIGGER_MSK);
4368+
phy->fifo.trigger_msk = val;
4369+
4370+
snprintf(name, 256, "%d", phy_no);
4371+
port_dentry = debugfs_create_dir(name,
4372+
hisi_hba->debugfs_fifo_dentry);
4373+
4374+
debugfs_create_file("update_config", 0200, port_dentry, phy,
4375+
&debugfs_fifo_update_cfg_v3_hw_fops);
4376+
4377+
debugfs_create_file("signal_sel", 0600, port_dentry,
4378+
&phy->fifo.signal_sel,
4379+
&debugfs_v3_hw_fops);
4380+
4381+
debugfs_create_file("dump_msk", 0600, port_dentry,
4382+
&phy->fifo.dump_msk,
4383+
&debugfs_v3_hw_fops);
4384+
4385+
debugfs_create_file("dump_mode", 0600, port_dentry,
4386+
&phy->fifo.dump_mode,
4387+
&debugfs_v3_hw_fops);
4388+
4389+
debugfs_create_file("trigger_mode", 0600, port_dentry,
4390+
&phy->fifo.trigger_mode,
4391+
&debugfs_v3_hw_fops);
4392+
4393+
debugfs_create_file("trigger", 0600, port_dentry,
4394+
&phy->fifo.trigger,
4395+
&debugfs_v3_hw_fops);
4396+
4397+
debugfs_create_file("trigger_msk", 0600, port_dentry,
4398+
&phy->fifo.trigger_msk,
4399+
&debugfs_v3_hw_fops);
4400+
4401+
debugfs_create_file("fifo_data", 0400, port_dentry, phy,
4402+
&debugfs_fifo_data_v3_hw_fops);
4403+
}
4404+
}
4405+
41564406
static void debugfs_work_handler_v3_hw(struct work_struct *work)
41574407
{
41584408
struct hisi_hba *hisi_hba =
@@ -4388,6 +4638,7 @@ static void debugfs_init_v3_hw(struct hisi_hba *hisi_hba)
43884638
debugfs_create_dir("dump", hisi_hba->debugfs_dir);
43894639

43904640
debugfs_phy_down_cnt_init_v3_hw(hisi_hba);
4641+
debugfs_fifo_init_v3_hw(hisi_hba);
43914642

43924643
for (i = 0; i < hisi_sas_debugfs_dump_count; i++) {
43934644
if (debugfs_alloc_v3_hw(hisi_hba, i)) {

0 commit comments

Comments
 (0)