Merge patch series "scsi: hisi_sas: Some fixes for hisi_sas"

Yihang Li <liyihang9@huawei.com> says:

This series contains some fixes including:

 - Adjust priority of registering and exiting debugfs for security;
 - Create trigger_dump at the end of the debugfs initialization;
 - Add firmware information check;
 - Enable all PHYs that are not disabled by user during controller reset;
 - Reset PHY again if phyup timeout;
 - Check usage count only when the runtime PM status is RPM_SUSPENDING;
 - Add cond_resched() for no forced preemption model;
 - Default enable interrupt coalescing;
 - Update disk locked timeout to 7 seconds;
 - Add time interval between two H2D FIS following soft reset spec;
 - Update v3 hw STP_LINK_TIMER setting;
 - Create all dump files during debugfs initialization;
 - Add latest_dump for the debugfs dump;

Link: https://lore.kernel.org/r/20241008021822.2617339-1-liyihang9@huawei.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
Martin K. Petersen 2024-10-15 22:34:14 -04:00
commit a3517717c3
5 changed files with 206 additions and 53 deletions

View File

@ -307,6 +307,7 @@ enum {
struct hisi_sas_hw {
int (*hw_init)(struct hisi_hba *hisi_hba);
int (*fw_info_check)(struct hisi_hba *hisi_hba);
int (*interrupt_preinit)(struct hisi_hba *hisi_hba);
void (*setup_itct)(struct hisi_hba *hisi_hba,
struct hisi_sas_device *device);

View File

@ -1321,6 +1321,7 @@ static int hisi_sas_softreset_ata_disk(struct domain_device *device)
}
if (rc == TMF_RESP_FUNC_COMPLETE) {
usleep_range(900, 1000);
ata_for_each_link(link, ap, EDGE) {
int pmp = sata_srst_pmp(link);
@ -1384,6 +1385,7 @@ static void hisi_sas_refresh_port_id(struct hisi_hba *hisi_hba)
static void hisi_sas_rescan_topology(struct hisi_hba *hisi_hba, u32 state)
{
u32 new_state = hisi_hba->hw->get_phys_state(hisi_hba);
struct asd_sas_port *_sas_port = NULL;
int phy_no;
@ -1397,7 +1399,7 @@ static void hisi_sas_rescan_topology(struct hisi_hba *hisi_hba, u32 state)
continue;
/* Report PHY state change to libsas */
if (state & BIT(phy_no)) {
if (new_state & BIT(phy_no)) {
if (do_port_check && sas_port && sas_port->port_dev) {
struct domain_device *dev = sas_port->port_dev;
@ -1410,6 +1412,16 @@ static void hisi_sas_rescan_topology(struct hisi_hba *hisi_hba, u32 state)
}
} else {
hisi_sas_phy_down(hisi_hba, phy_no, 0, GFP_KERNEL);
/*
* The new_state is not ready but old_state is ready,
* the two possible causes:
* 1. The connected device is removed
* 2. Device exists but phyup timed out
*/
if (state & BIT(phy_no))
hisi_sas_notify_phy_event(phy,
HISI_PHYE_LINK_RESET);
}
}
}
@ -1545,10 +1557,16 @@ void hisi_sas_controller_reset_done(struct hisi_hba *hisi_hba)
/* Init and wait for PHYs to come up and all libsas event finished. */
for (phy_no = 0; phy_no < hisi_hba->n_phy; phy_no++) {
struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
struct asd_sas_phy *sas_phy = &phy->sas_phy;
if (!(hisi_hba->phy_state & BIT(phy_no)))
if (!sas_phy->phy->enabled)
continue;
if (!(hisi_hba->phy_state & BIT(phy_no))) {
hisi_sas_phy_enable(hisi_hba, phy_no, 1);
continue;
}
async_schedule_domain(hisi_sas_async_init_wait_phyup,
phy, &async);
}
@ -2450,6 +2468,11 @@ static struct Scsi_Host *hisi_sas_shost_alloc(struct platform_device *pdev,
if (hisi_sas_get_fw_info(hisi_hba) < 0)
goto err_out;
if (hisi_hba->hw->fw_info_check) {
if (hisi_hba->hw->fw_info_check(hisi_hba))
goto err_out;
}
error = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
if (error) {
dev_err(dev, "No usable DMA addressing method\n");
@ -2630,10 +2653,10 @@ static __init int hisi_sas_init(void)
static __exit void hisi_sas_exit(void)
{
sas_release_transport(hisi_sas_stt);
if (hisi_sas_debugfs_enable)
debugfs_remove(hisi_sas_debugfs_dir);
sas_release_transport(hisi_sas_stt);
}
module_init(hisi_sas_init);

View File

@ -1734,6 +1734,23 @@ static struct attribute *host_v1_hw_attrs[] = {
ATTRIBUTE_GROUPS(host_v1_hw);
static int check_fw_info_v1_hw(struct hisi_hba *hisi_hba)
{
struct device *dev = hisi_hba->dev;
if (hisi_hba->n_phy < 0 || hisi_hba->n_phy > 9) {
dev_err(dev, "invalid phy number from FW\n");
return -EINVAL;
}
if (hisi_hba->queue_count < 0 || hisi_hba->queue_count > 32) {
dev_err(dev, "invalid queue count from FW\n");
return -EINVAL;
}
return 0;
}
static const struct scsi_host_template sht_v1_hw = {
LIBSAS_SHT_BASE_NO_SLAVE_INIT
.device_configure = hisi_sas_device_configure,
@ -1747,6 +1764,7 @@ static const struct scsi_host_template sht_v1_hw = {
static const struct hisi_sas_hw hisi_sas_v1_hw = {
.hw_init = hisi_sas_v1_init,
.fw_info_check = check_fw_info_v1_hw,
.setup_itct = setup_itct_v1_hw,
.sl_notify_ssp = sl_notify_ssp_v1_hw,
.clear_itct = clear_itct_v1_hw,

View File

@ -3566,6 +3566,23 @@ static void map_queues_v2_hw(struct Scsi_Host *shost)
}
}
static int check_fw_info_v2_hw(struct hisi_hba *hisi_hba)
{
struct device *dev = hisi_hba->dev;
if (hisi_hba->n_phy < 0 || hisi_hba->n_phy > 9) {
dev_err(dev, "invalid phy number from FW\n");
return -EINVAL;
}
if (hisi_hba->queue_count < 0 || hisi_hba->queue_count > 16) {
dev_err(dev, "invalid queue count from FW\n");
return -EINVAL;
}
return 0;
}
static const struct scsi_host_template sht_v2_hw = {
LIBSAS_SHT_BASE_NO_SLAVE_INIT
.device_configure = hisi_sas_device_configure,
@ -3582,6 +3599,7 @@ static const struct scsi_host_template sht_v2_hw = {
static const struct hisi_sas_hw hisi_sas_v2_hw = {
.hw_init = hisi_sas_v2_init,
.fw_info_check = check_fw_info_v2_hw,
.interrupt_preinit = hisi_sas_v2_interrupt_preinit,
.setup_itct = setup_itct_v2_hw,
.slot_index_alloc = slot_index_alloc_quirk_v2_hw,

View File

@ -43,6 +43,7 @@
#define CQ_INT_CONVERGE_EN 0xb0
#define CFG_AGING_TIME 0xbc
#define HGC_DFX_CFG2 0xc0
#define CFG_ICT_TIMER_STEP_TRSH 0xc8
#define CFG_ABT_SET_QUERY_IPTT 0xd4
#define CFG_SET_ABORTED_IPTT_OFF 0
#define CFG_SET_ABORTED_IPTT_MSK (0xfff << CFG_SET_ABORTED_IPTT_OFF)
@ -638,9 +639,12 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba)
hisi_sas_write32(hisi_hba, TRANS_LOCK_ICT_TIME, 0x4A817C80);
hisi_sas_write32(hisi_hba, HGC_SAS_TXFAIL_RETRY_CTRL, 0x108);
hisi_sas_write32(hisi_hba, CFG_AGING_TIME, 0x1);
hisi_sas_write32(hisi_hba, INT_COAL_EN, 0x1);
hisi_sas_write32(hisi_hba, OQ_INT_COAL_TIME, 0x1);
hisi_sas_write32(hisi_hba, OQ_INT_COAL_CNT, 0x1);
hisi_sas_write32(hisi_hba, CFG_ICT_TIMER_STEP_TRSH, 0xf4240);
hisi_sas_write32(hisi_hba, INT_COAL_EN, 0x3);
/* configure the interrupt coalescing timeout period 10us */
hisi_sas_write32(hisi_hba, OQ_INT_COAL_TIME, 0xa);
/* configure the count of CQ entries 10 */
hisi_sas_write32(hisi_hba, OQ_INT_COAL_CNT, 0xa);
hisi_sas_write32(hisi_hba, CQ_INT_CONVERGE_EN,
hisi_sas_intr_conv);
hisi_sas_write32(hisi_hba, OQ_INT_SRC, 0xffff);
@ -682,7 +686,7 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba)
hisi_sas_phy_write32(hisi_hba, i, PHY_CTRL_RDY_MSK, 0x0);
hisi_sas_phy_write32(hisi_hba, i, PHYCTRL_DWS_RESET_MSK, 0x0);
hisi_sas_phy_write32(hisi_hba, i, PHYCTRL_OOB_RESTART_MSK, 0x1);
hisi_sas_phy_write32(hisi_hba, i, STP_LINK_TIMER, 0x7f7a120);
hisi_sas_phy_write32(hisi_hba, i, STP_LINK_TIMER, 0x7ffffff);
hisi_sas_phy_write32(hisi_hba, i, CON_CFG_DRIVER, 0x2a0a01);
hisi_sas_phy_write32(hisi_hba, i, SAS_EC_INT_COAL_TIME,
0x30f4240);
@ -2493,6 +2497,7 @@ static int complete_v3_hw(struct hisi_sas_cq *cq)
/* update rd_point */
cq->rd_point = rd_point;
hisi_sas_write32(hisi_hba, COMPL_Q_0_RD_PTR + (0x14 * queue), rd_point);
cond_resched();
return completed;
}
@ -2796,14 +2801,15 @@ static void config_intr_coal_v3_hw(struct hisi_hba *hisi_hba)
{
/* config those registers between enable and disable PHYs */
hisi_sas_stop_phys(hisi_hba);
hisi_sas_write32(hisi_hba, INT_COAL_EN, 0x3);
if (hisi_hba->intr_coal_ticks == 0 ||
hisi_hba->intr_coal_count == 0) {
hisi_sas_write32(hisi_hba, INT_COAL_EN, 0x1);
hisi_sas_write32(hisi_hba, OQ_INT_COAL_TIME, 0x1);
hisi_sas_write32(hisi_hba, OQ_INT_COAL_CNT, 0x1);
/* configure the interrupt coalescing timeout period 10us */
hisi_sas_write32(hisi_hba, OQ_INT_COAL_TIME, 0xa);
/* configure the count of CQ entries 10 */
hisi_sas_write32(hisi_hba, OQ_INT_COAL_CNT, 0xa);
} else {
hisi_sas_write32(hisi_hba, INT_COAL_EN, 0x3);
hisi_sas_write32(hisi_hba, OQ_INT_COAL_TIME,
hisi_hba->intr_coal_ticks);
hisi_sas_write32(hisi_hba, OQ_INT_COAL_CNT,
@ -3371,6 +3377,23 @@ static const struct hisi_sas_hw hisi_sas_v3_hw = {
.debugfs_snapshot_regs = debugfs_snapshot_regs_v3_hw,
};
static int check_fw_info_v3_hw(struct hisi_hba *hisi_hba)
{
struct device *dev = hisi_hba->dev;
if (hisi_hba->n_phy < 0 || hisi_hba->n_phy > 8) {
dev_err(dev, "invalid phy number from FW\n");
return -EINVAL;
}
if (hisi_hba->queue_count < 0 || hisi_hba->queue_count > 16) {
dev_err(dev, "invalid queue count from FW\n");
return -EINVAL;
}
return 0;
}
static struct Scsi_Host *
hisi_sas_shost_alloc_pci(struct pci_dev *pdev)
{
@ -3401,6 +3424,9 @@ hisi_sas_shost_alloc_pci(struct pci_dev *pdev)
if (hisi_sas_get_fw_info(hisi_hba) < 0)
goto err_out;
if (check_fw_info_v3_hw(hisi_hba) < 0)
goto err_out;
if (experimental_iopoll_q_cnt < 0 ||
experimental_iopoll_q_cnt >= hisi_hba->queue_count)
dev_err(dev, "iopoll queue count %d cannot exceed or equal 16, using default 0\n",
@ -3550,6 +3576,11 @@ debugfs_to_reg_name_v3_hw(int off, int base_off,
return NULL;
}
static bool debugfs_dump_is_generated_v3_hw(void *p)
{
return p ? true : false;
}
static void debugfs_print_reg_v3_hw(u32 *regs_val, struct seq_file *s,
const struct hisi_sas_debugfs_reg *reg)
{
@ -3575,6 +3606,9 @@ static int debugfs_global_v3_hw_show(struct seq_file *s, void *p)
{
struct hisi_sas_debugfs_regs *global = s->private;
if (!debugfs_dump_is_generated_v3_hw(global->data))
return -EPERM;
debugfs_print_reg_v3_hw(global->data, s,
&debugfs_global_reg);
@ -3586,6 +3620,9 @@ static int debugfs_axi_v3_hw_show(struct seq_file *s, void *p)
{
struct hisi_sas_debugfs_regs *axi = s->private;
if (!debugfs_dump_is_generated_v3_hw(axi->data))
return -EPERM;
debugfs_print_reg_v3_hw(axi->data, s,
&debugfs_axi_reg);
@ -3597,6 +3634,9 @@ static int debugfs_ras_v3_hw_show(struct seq_file *s, void *p)
{
struct hisi_sas_debugfs_regs *ras = s->private;
if (!debugfs_dump_is_generated_v3_hw(ras->data))
return -EPERM;
debugfs_print_reg_v3_hw(ras->data, s,
&debugfs_ras_reg);
@ -3609,6 +3649,9 @@ static int debugfs_port_v3_hw_show(struct seq_file *s, void *p)
struct hisi_sas_debugfs_port *port = s->private;
const struct hisi_sas_debugfs_reg *reg_port = &debugfs_port_reg;
if (!debugfs_dump_is_generated_v3_hw(port->data))
return -EPERM;
debugfs_print_reg_v3_hw(port->data, s, reg_port);
return 0;
@ -3664,6 +3707,9 @@ static int debugfs_cq_v3_hw_show(struct seq_file *s, void *p)
struct hisi_sas_debugfs_cq *debugfs_cq = s->private;
int slot;
if (!debugfs_dump_is_generated_v3_hw(debugfs_cq->complete_hdr))
return -EPERM;
for (slot = 0; slot < HISI_SAS_QUEUE_SLOTS; slot++)
debugfs_cq_show_slot_v3_hw(s, slot, debugfs_cq);
@ -3685,8 +3731,12 @@ static void debugfs_dq_show_slot_v3_hw(struct seq_file *s, int slot,
static int debugfs_dq_v3_hw_show(struct seq_file *s, void *p)
{
struct hisi_sas_debugfs_dq *debugfs_dq = s->private;
int slot;
if (!debugfs_dump_is_generated_v3_hw(debugfs_dq->hdr))
return -EPERM;
for (slot = 0; slot < HISI_SAS_QUEUE_SLOTS; slot++)
debugfs_dq_show_slot_v3_hw(s, slot, s->private);
@ -3700,6 +3750,9 @@ static int debugfs_iost_v3_hw_show(struct seq_file *s, void *p)
struct hisi_sas_iost *iost = debugfs_iost->iost;
int i, max_command_entries = HISI_SAS_MAX_COMMANDS;
if (!debugfs_dump_is_generated_v3_hw(iost))
return -EPERM;
for (i = 0; i < max_command_entries; i++, iost++) {
__le64 *data = &iost->qw0;
@ -3719,6 +3772,9 @@ static int debugfs_iost_cache_v3_hw_show(struct seq_file *s, void *p)
int i, tab_idx;
__le64 *iost;
if (!debugfs_dump_is_generated_v3_hw(iost_cache))
return -EPERM;
for (i = 0; i < HISI_SAS_IOST_ITCT_CACHE_NUM; i++, iost_cache++) {
/*
* Data struct of IOST cache:
@ -3742,6 +3798,9 @@ static int debugfs_itct_v3_hw_show(struct seq_file *s, void *p)
struct hisi_sas_debugfs_itct *debugfs_itct = s->private;
struct hisi_sas_itct *itct = debugfs_itct->itct;
if (!debugfs_dump_is_generated_v3_hw(itct))
return -EPERM;
for (i = 0; i < HISI_SAS_MAX_ITCT_ENTRIES; i++, itct++) {
__le64 *data = &itct->qw0;
@ -3761,6 +3820,9 @@ static int debugfs_itct_cache_v3_hw_show(struct seq_file *s, void *p)
int i, tab_idx;
__le64 *itct;
if (!debugfs_dump_is_generated_v3_hw(itct_cache))
return -EPERM;
for (i = 0; i < HISI_SAS_IOST_ITCT_CACHE_NUM; i++, itct_cache++) {
/*
* Data struct of ITCT cache:
@ -3778,10 +3840,9 @@ static int debugfs_itct_cache_v3_hw_show(struct seq_file *s, void *p)
}
DEFINE_SHOW_ATTRIBUTE(debugfs_itct_cache_v3_hw);
static void debugfs_create_files_v3_hw(struct hisi_hba *hisi_hba)
static void debugfs_create_files_v3_hw(struct hisi_hba *hisi_hba, int index)
{
u64 *debugfs_timestamp;
int dump_index = hisi_hba->debugfs_dump_index;
struct dentry *dump_dentry;
struct dentry *dentry;
char name[256];
@ -3789,17 +3850,17 @@ static void debugfs_create_files_v3_hw(struct hisi_hba *hisi_hba)
int c;
int d;
snprintf(name, 256, "%d", dump_index);
snprintf(name, 256, "%d", index);
dump_dentry = debugfs_create_dir(name, hisi_hba->debugfs_dump_dentry);
debugfs_timestamp = &hisi_hba->debugfs_timestamp[dump_index];
debugfs_timestamp = &hisi_hba->debugfs_timestamp[index];
debugfs_create_u64("timestamp", 0400, dump_dentry,
debugfs_timestamp);
debugfs_create_file("global", 0400, dump_dentry,
&hisi_hba->debugfs_regs[dump_index][DEBUGFS_GLOBAL],
&hisi_hba->debugfs_regs[index][DEBUGFS_GLOBAL],
&debugfs_global_v3_hw_fops);
/* Create port dir and files */
@ -3808,7 +3869,7 @@ static void debugfs_create_files_v3_hw(struct hisi_hba *hisi_hba)
snprintf(name, 256, "%d", p);
debugfs_create_file(name, 0400, dentry,
&hisi_hba->debugfs_port_reg[dump_index][p],
&hisi_hba->debugfs_port_reg[index][p],
&debugfs_port_v3_hw_fops);
}
@ -3818,7 +3879,7 @@ static void debugfs_create_files_v3_hw(struct hisi_hba *hisi_hba)
snprintf(name, 256, "%d", c);
debugfs_create_file(name, 0400, dentry,
&hisi_hba->debugfs_cq[dump_index][c],
&hisi_hba->debugfs_cq[index][c],
&debugfs_cq_v3_hw_fops);
}
@ -3828,32 +3889,32 @@ static void debugfs_create_files_v3_hw(struct hisi_hba *hisi_hba)
snprintf(name, 256, "%d", d);
debugfs_create_file(name, 0400, dentry,
&hisi_hba->debugfs_dq[dump_index][d],
&hisi_hba->debugfs_dq[index][d],
&debugfs_dq_v3_hw_fops);
}
debugfs_create_file("iost", 0400, dump_dentry,
&hisi_hba->debugfs_iost[dump_index],
&hisi_hba->debugfs_iost[index],
&debugfs_iost_v3_hw_fops);
debugfs_create_file("iost_cache", 0400, dump_dentry,
&hisi_hba->debugfs_iost_cache[dump_index],
&hisi_hba->debugfs_iost_cache[index],
&debugfs_iost_cache_v3_hw_fops);
debugfs_create_file("itct", 0400, dump_dentry,
&hisi_hba->debugfs_itct[dump_index],
&hisi_hba->debugfs_itct[index],
&debugfs_itct_v3_hw_fops);
debugfs_create_file("itct_cache", 0400, dump_dentry,
&hisi_hba->debugfs_itct_cache[dump_index],
&hisi_hba->debugfs_itct_cache[index],
&debugfs_itct_cache_v3_hw_fops);
debugfs_create_file("axi", 0400, dump_dentry,
&hisi_hba->debugfs_regs[dump_index][DEBUGFS_AXI],
&hisi_hba->debugfs_regs[index][DEBUGFS_AXI],
&debugfs_axi_v3_hw_fops);
debugfs_create_file("ras", 0400, dump_dentry,
&hisi_hba->debugfs_regs[dump_index][DEBUGFS_RAS],
&hisi_hba->debugfs_regs[index][DEBUGFS_RAS],
&debugfs_ras_v3_hw_fops);
}
@ -4516,22 +4577,34 @@ static void debugfs_release_v3_hw(struct hisi_hba *hisi_hba, int dump_index)
int i;
devm_kfree(dev, hisi_hba->debugfs_iost_cache[dump_index].cache);
hisi_hba->debugfs_iost_cache[dump_index].cache = NULL;
devm_kfree(dev, hisi_hba->debugfs_itct_cache[dump_index].cache);
hisi_hba->debugfs_itct_cache[dump_index].cache = NULL;
devm_kfree(dev, hisi_hba->debugfs_iost[dump_index].iost);
hisi_hba->debugfs_iost[dump_index].iost = NULL;
devm_kfree(dev, hisi_hba->debugfs_itct[dump_index].itct);
hisi_hba->debugfs_itct[dump_index].itct = NULL;
for (i = 0; i < hisi_hba->queue_count; i++)
for (i = 0; i < hisi_hba->queue_count; i++) {
devm_kfree(dev, hisi_hba->debugfs_dq[dump_index][i].hdr);
hisi_hba->debugfs_dq[dump_index][i].hdr = NULL;
}
for (i = 0; i < hisi_hba->queue_count; i++)
for (i = 0; i < hisi_hba->queue_count; i++) {
devm_kfree(dev,
hisi_hba->debugfs_cq[dump_index][i].complete_hdr);
hisi_hba->debugfs_cq[dump_index][i].complete_hdr = NULL;
}
for (i = 0; i < DEBUGFS_REGS_NUM; i++)
for (i = 0; i < DEBUGFS_REGS_NUM; i++) {
devm_kfree(dev, hisi_hba->debugfs_regs[dump_index][i].data);
hisi_hba->debugfs_regs[dump_index][i].data = NULL;
}
for (i = 0; i < hisi_hba->n_phy; i++)
for (i = 0; i < hisi_hba->n_phy; i++) {
devm_kfree(dev, hisi_hba->debugfs_port_reg[dump_index][i].data);
hisi_hba->debugfs_port_reg[dump_index][i].data = NULL;
}
}
static const struct hisi_sas_debugfs_reg *debugfs_reg_array_v3_hw[DEBUGFS_REGS_NUM] = {
@ -4658,8 +4731,6 @@ static int debugfs_snapshot_regs_v3_hw(struct hisi_hba *hisi_hba)
debugfs_snapshot_itct_reg_v3_hw(hisi_hba);
debugfs_snapshot_iost_reg_v3_hw(hisi_hba);
debugfs_create_files_v3_hw(hisi_hba);
debugfs_snapshot_restore_v3_hw(hisi_hba);
hisi_hba->debugfs_dump_index++;
@ -4743,6 +4814,34 @@ static void debugfs_bist_init_v3_hw(struct hisi_hba *hisi_hba)
hisi_hba->debugfs_bist_linkrate = SAS_LINK_RATE_1_5_GBPS;
}
static int debugfs_dump_index_v3_hw_show(struct seq_file *s, void *p)
{
int *debugfs_dump_index = s->private;
if (*debugfs_dump_index > 0)
seq_printf(s, "%d\n", *debugfs_dump_index - 1);
else
seq_puts(s, "dump not triggered\n");
return 0;
}
DEFINE_SHOW_ATTRIBUTE(debugfs_dump_index_v3_hw);
static void debugfs_dump_init_v3_hw(struct hisi_hba *hisi_hba)
{
int i;
hisi_hba->debugfs_dump_dentry =
debugfs_create_dir("dump", hisi_hba->debugfs_dir);
debugfs_create_file("latest_dump", 0400, hisi_hba->debugfs_dump_dentry,
&hisi_hba->debugfs_dump_index,
&debugfs_dump_index_v3_hw_fops);
for (i = 0; i < hisi_sas_debugfs_dump_count; i++)
debugfs_create_files_v3_hw(hisi_hba, i);
}
static void debugfs_exit_v3_hw(struct hisi_hba *hisi_hba)
{
debugfs_remove_recursive(hisi_hba->debugfs_dir);
@ -4755,19 +4854,17 @@ static void debugfs_init_v3_hw(struct hisi_hba *hisi_hba)
hisi_hba->debugfs_dir = debugfs_create_dir(dev_name(dev),
hisi_sas_debugfs_dir);
/* create bist structures */
debugfs_bist_init_v3_hw(hisi_hba);
debugfs_dump_init_v3_hw(hisi_hba);
debugfs_phy_down_cnt_init_v3_hw(hisi_hba);
debugfs_fifo_init_v3_hw(hisi_hba);
debugfs_create_file("trigger_dump", 0200,
hisi_hba->debugfs_dir,
hisi_hba,
&debugfs_trigger_dump_v3_hw_fops);
/* create bist structures */
debugfs_bist_init_v3_hw(hisi_hba);
hisi_hba->debugfs_dump_dentry =
debugfs_create_dir("dump", hisi_hba->debugfs_dir);
debugfs_phy_down_cnt_init_v3_hw(hisi_hba);
debugfs_fifo_init_v3_hw(hisi_hba);
}
static int
@ -4860,16 +4957,13 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id)
SHOST_DIX_GUARD_CRC);
}
if (hisi_sas_debugfs_enable)
debugfs_init_v3_hw(hisi_hba);
rc = interrupt_preinit_v3_hw(hisi_hba);
if (rc)
goto err_out_undo_debugfs;
goto err_out_free_host;
rc = scsi_add_host(shost, dev);
if (rc)
goto err_out_undo_debugfs;
goto err_out_free_host;
rc = sas_register_ha(sha);
if (rc)
@ -4880,6 +4974,8 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto err_out_unregister_ha;
scsi_scan_host(shost);
if (hisi_sas_debugfs_enable)
debugfs_init_v3_hw(hisi_hba);
pm_runtime_set_autosuspend_delay(dev, 5000);
pm_runtime_use_autosuspend(dev);
@ -4900,9 +4996,6 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id)
sas_unregister_ha(sha);
err_out_remove_host:
scsi_remove_host(shost);
err_out_undo_debugfs:
if (hisi_sas_debugfs_enable)
debugfs_exit_v3_hw(hisi_hba);
err_out_free_host:
hisi_sas_free(hisi_hba);
scsi_host_put(shost);
@ -4934,6 +5027,8 @@ static void hisi_sas_v3_remove(struct pci_dev *pdev)
struct Scsi_Host *shost = sha->shost;
pm_runtime_get_noresume(dev);
if (hisi_sas_debugfs_enable)
debugfs_exit_v3_hw(hisi_hba);
sas_unregister_ha(sha);
flush_workqueue(hisi_hba->wq);
@ -4941,9 +5036,6 @@ static void hisi_sas_v3_remove(struct pci_dev *pdev)
hisi_sas_v3_destroy_irqs(pdev, hisi_hba);
hisi_sas_free(hisi_hba);
if (hisi_sas_debugfs_enable)
debugfs_exit_v3_hw(hisi_hba);
scsi_host_put(shost);
}
@ -5034,7 +5126,8 @@ static int _suspend_v3_hw(struct device *device)
interrupt_disable_v3_hw(hisi_hba);
#ifdef CONFIG_PM
if (atomic_read(&device->power.usage_count)) {
if ((device->power.runtime_status == RPM_SUSPENDING) &&
atomic_read(&device->power.usage_count)) {
dev_err(dev, "PM suspend: host status cannot be suspended\n");
rc = -EBUSY;
goto err_out;