!143 [next-6.6] kunpeng:Backport some bugfixes for hisi_sas

Merge pull request !143 from chenyi/linux-6.6/next-cy-dev
This commit is contained in:
chinaljp030 2024-05-08 06:39:25 +00:00 committed by Gitee
commit 7722165753
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
4 changed files with 108 additions and 97 deletions

View File

@ -343,7 +343,7 @@ struct hisi_sas_hw {
u8 reg_index, u8 reg_count, u8 *write_data);
void (*wait_cmds_complete_timeout)(struct hisi_hba *hisi_hba,
int delay_ms, int timeout_ms);
void (*debugfs_snapshot_regs)(struct hisi_hba *hisi_hba);
int (*debugfs_snapshot_regs)(struct hisi_hba *hisi_hba);
int complete_hdr_size;
const struct scsi_host_template *sht;
};
@ -451,7 +451,6 @@ struct hisi_hba {
const struct hisi_sas_hw *hw; /* Low level hw interface */
unsigned long sata_dev_bitmap[BITS_TO_LONGS(HISI_SAS_MAX_DEVICES)];
struct work_struct rst_work;
struct work_struct debugfs_work;
u32 phy_state;
u32 intr_coal_ticks; /* Time of interrupt coalesce in us */
u32 intr_coal_count; /* Interrupt count to coalesce */

View File

@ -1507,6 +1507,11 @@ void hisi_sas_controller_reset_prepare(struct hisi_hba *hisi_hba)
scsi_block_requests(shost);
hisi_hba->hw->wait_cmds_complete_timeout(hisi_hba, 100, 5000);
/*
* hisi_hba->timer is only used for v1/v2 hw, and check hw->sht
* which is also only used for v1/v2 hw to skip it for v3 hw
*/
if (hisi_hba->hw->sht)
del_timer_sync(&hisi_hba->timer);
set_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags);
@ -1573,7 +1578,7 @@ static int hisi_sas_controller_prereset(struct hisi_hba *hisi_hba)
return -EPERM;
}
if (hisi_sas_debugfs_enable && hisi_hba->debugfs_itct[0].itct)
if (hisi_sas_debugfs_enable)
hisi_hba->hw->debugfs_snapshot_regs(hisi_hba);
return 0;
@ -1791,8 +1796,10 @@ static int hisi_sas_debug_I_T_nexus_reset(struct domain_device *device)
if (dev_is_sata(device)) {
struct ata_link *link = &device->sata_dev.ap->link;
unsigned long deadline = ata_deadline(jiffies,
HISI_SAS_WAIT_PHYUP_TIMEOUT / HZ * 1000);
rc = ata_wait_after_reset(link, HISI_SAS_WAIT_PHYUP_TIMEOUT,
rc = ata_wait_after_reset(link, deadline,
smp_ata_check_ready_type);
} else {
msleep(2000);
@ -1818,33 +1825,14 @@ static int hisi_sas_I_T_nexus_reset(struct domain_device *device)
}
hisi_sas_dereg_device(hisi_hba, device);
rc = hisi_sas_debug_I_T_nexus_reset(device);
if (rc == TMF_RESP_FUNC_COMPLETE && dev_is_sata(device)) {
struct sas_phy *local_phy;
if (dev_is_sata(device)) {
rc = hisi_sas_softreset_ata_disk(device);
switch (rc) {
case -ECOMM:
rc = -ENODEV;
break;
case TMF_RESP_FUNC_FAILED:
case -EMSGSIZE:
case -EIO:
local_phy = sas_get_local_phy(device);
rc = sas_phy_enable(local_phy, 0);
if (!rc) {
local_phy->enabled = 0;
dev_err(dev, "Disabled local phy of ATA disk %016llx due to softreset fail (%d)\n",
if (rc == TMF_RESP_FUNC_FAILED)
dev_err(dev, "ata disk %016llx reset (%d)\n",
SAS_ADDR(device->sas_addr), rc);
rc = -ENODEV;
}
sas_put_local_phy(local_phy);
break;
default:
break;
}
}
rc = hisi_sas_debug_I_T_nexus_reset(device);
if ((rc == TMF_RESP_FUNC_COMPLETE) || (rc == -ENODEV))
hisi_sas_release_task(hisi_hba, device);
@ -1961,8 +1949,20 @@ static bool hisi_sas_internal_abort_timeout(struct sas_task *task,
struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
struct hisi_sas_internal_abort_data *timeout = data;
if (hisi_sas_debugfs_enable && hisi_hba->debugfs_itct[0].itct)
queue_work(hisi_hba->wq, &hisi_hba->debugfs_work);
if (hisi_sas_debugfs_enable) {
/*
* If timeout occurs in device gone scenario, to avoid
* circular dependency like:
* hisi_sas_dev_gone() -> down() -> ... ->
* hisi_sas_internal_abort_timeout() -> down().
*/
if (!timeout->rst_ha_timeout)
down(&hisi_hba->sem);
hisi_hba->hw->debugfs_snapshot_regs(hisi_hba);
if (!timeout->rst_ha_timeout)
up(&hisi_hba->sem);
}
if (task->task_state_flags & SAS_TASK_STATE_DONE) {
pr_err("Internal abort: timeout %016llx\n",
@ -2614,6 +2614,7 @@ static __exit void hisi_sas_exit(void)
{
sas_release_transport(hisi_sas_stt);
if (hisi_sas_debugfs_enable)
debugfs_remove(hisi_sas_debugfs_dir);
}

View File

@ -558,8 +558,7 @@ static int experimental_iopoll_q_cnt;
module_param(experimental_iopoll_q_cnt, int, 0444);
MODULE_PARM_DESC(experimental_iopoll_q_cnt, "number of queues to be used as poll mode, def=0");
static void debugfs_work_handler_v3_hw(struct work_struct *work);
static void debugfs_snapshot_regs_v3_hw(struct hisi_hba *hisi_hba);
static int debugfs_snapshot_regs_v3_hw(struct hisi_hba *hisi_hba);
static u32 hisi_sas_read32(struct hisi_hba *hisi_hba, u32 off)
{
@ -2245,7 +2244,15 @@ slot_err_v3_hw(struct hisi_hba *hisi_hba, struct sas_task *task,
case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP:
if ((dw0 & CMPLT_HDR_RSPNS_XFRD_MSK) &&
(sipc_rx_err_type & RX_FIS_STATUS_ERR_MSK)) {
if (task->ata_task.use_ncq) {
struct domain_device *device = task->dev;
struct hisi_sas_device *sas_dev =
device->lldd_dev;
sas_dev->dev_status = HISI_SAS_DEV_NCQ_ERR;
slot->abort = 1;
} else {
ts->stat = SAS_PROTO_RESPONSE;
}
} else if (dma_rx_err_type & RX_DATA_LEN_UNDERFLOW_MSK) {
ts->residual = trans_tx_fail_type;
ts->stat = SAS_DATA_UNDERRUN;
@ -2909,7 +2916,8 @@ static int slave_configure_v3_hw(struct scsi_device *sdev)
return 0;
if (!device_link_add(&sdev->sdev_gendev, dev,
DL_FLAG_PM_RUNTIME | DL_FLAG_RPM_ACTIVE)) {
DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME |
DL_FLAG_RPM_ACTIVE)) {
if (pm_runtime_enabled(dev)) {
dev_info(dev, "add device link failed, disable runtime PM for the host\n");
pm_runtime_disable(dev);
@ -2919,6 +2927,15 @@ static int slave_configure_v3_hw(struct scsi_device *sdev)
return 0;
}
static void slave_destroy_v3_hw(struct scsi_device *sdev)
{
struct Scsi_Host *shost = dev_to_shost(&sdev->sdev_gendev);
struct hisi_hba *hisi_hba = shost_priv(shost);
struct device *dev = hisi_hba->dev;
device_link_remove(&sdev->sdev_gendev, dev);
}
static struct attribute *host_v3_hw_attrs[] = {
&dev_attr_phy_event_threshold.attr,
&dev_attr_intr_conv_v3_hw.attr,
@ -3335,6 +3352,7 @@ static const struct scsi_host_template sht_v3_hw = {
.eh_device_reset_handler = sas_eh_device_reset_handler,
.eh_target_reset_handler = sas_eh_target_reset_handler,
.slave_alloc = hisi_sas_slave_alloc,
.slave_destroy = slave_destroy_v3_hw,
.target_destroy = sas_target_destroy,
.ioctl = sas_ioctl,
#ifdef CONFIG_COMPAT
@ -3388,7 +3406,6 @@ hisi_sas_shost_alloc_pci(struct pci_dev *pdev)
hisi_hba = shost_priv(shost);
INIT_WORK(&hisi_hba->rst_work, hisi_sas_rst_work_handler);
INIT_WORK(&hisi_hba->debugfs_work, debugfs_work_handler_v3_hw);
hisi_hba->hw = &hisi_sas_v3_hw;
hisi_hba->pci_dev = pdev;
hisi_hba->dev = dev;
@ -3860,37 +3877,6 @@ static void debugfs_create_files_v3_hw(struct hisi_hba *hisi_hba)
&debugfs_ras_v3_hw_fops);
}
static void debugfs_snapshot_regs_v3_hw(struct hisi_hba *hisi_hba)
{
int debugfs_dump_index = hisi_hba->debugfs_dump_index;
struct device *dev = hisi_hba->dev;
u64 timestamp = local_clock();
if (debugfs_dump_index >= hisi_sas_debugfs_dump_count) {
dev_warn(dev, "dump count exceeded!\n");
return;
}
do_div(timestamp, NSEC_PER_MSEC);
hisi_hba->debugfs_timestamp[debugfs_dump_index] = timestamp;
debugfs_snapshot_prepare_v3_hw(hisi_hba);
debugfs_snapshot_global_reg_v3_hw(hisi_hba);
debugfs_snapshot_port_reg_v3_hw(hisi_hba);
debugfs_snapshot_axi_reg_v3_hw(hisi_hba);
debugfs_snapshot_ras_reg_v3_hw(hisi_hba);
debugfs_snapshot_cq_reg_v3_hw(hisi_hba);
debugfs_snapshot_dq_reg_v3_hw(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++;
}
static ssize_t debugfs_trigger_dump_v3_hw_write(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
@ -3898,9 +3884,6 @@ static ssize_t debugfs_trigger_dump_v3_hw_write(struct file *file,
struct hisi_hba *hisi_hba = file->f_inode->i_private;
char buf[8];
if (hisi_hba->debugfs_dump_index >= hisi_sas_debugfs_dump_count)
return -EFAULT;
if (count > 8)
return -EFAULT;
@ -3910,7 +3893,12 @@ static ssize_t debugfs_trigger_dump_v3_hw_write(struct file *file,
if (buf[0] != '1')
return -EFAULT;
queue_work(hisi_hba->wq, &hisi_hba->debugfs_work);
down(&hisi_hba->sem);
if (debugfs_snapshot_regs_v3_hw(hisi_hba)) {
up(&hisi_hba->sem);
return -EFAULT;
}
up(&hisi_hba->sem);
return count;
}
@ -4661,14 +4649,6 @@ static void debugfs_fifo_init_v3_hw(struct hisi_hba *hisi_hba)
}
}
static void debugfs_work_handler_v3_hw(struct work_struct *work)
{
struct hisi_hba *hisi_hba =
container_of(work, struct hisi_hba, debugfs_work);
debugfs_snapshot_regs_v3_hw(hisi_hba);
}
static void debugfs_release_v3_hw(struct hisi_hba *hisi_hba, int dump_index)
{
struct device *dev = hisi_hba->dev;
@ -4703,7 +4683,7 @@ static int debugfs_alloc_v3_hw(struct hisi_hba *hisi_hba, int dump_index)
{
const struct hisi_sas_hw *hw = hisi_hba->hw;
struct device *dev = hisi_hba->dev;
int p, c, d, r, i;
int p, c, d, r;
size_t sz;
for (r = 0; r < DEBUGFS_REGS_NUM; r++) {
@ -4783,11 +4763,48 @@ static int debugfs_alloc_v3_hw(struct hisi_hba *hisi_hba, int dump_index)
return 0;
fail:
for (i = 0; i < hisi_sas_debugfs_dump_count; i++)
debugfs_release_v3_hw(hisi_hba, i);
debugfs_release_v3_hw(hisi_hba, dump_index);
return -ENOMEM;
}
static int debugfs_snapshot_regs_v3_hw(struct hisi_hba *hisi_hba)
{
int debugfs_dump_index = hisi_hba->debugfs_dump_index;
struct device *dev = hisi_hba->dev;
u64 timestamp = local_clock();
if (debugfs_dump_index >= hisi_sas_debugfs_dump_count) {
dev_warn(dev, "dump count exceeded!\n");
return -EINVAL;
}
if (debugfs_alloc_v3_hw(hisi_hba, debugfs_dump_index)) {
dev_warn(dev, "failed to alloc memory\n");
return -ENOMEM;
}
do_div(timestamp, NSEC_PER_MSEC);
hisi_hba->debugfs_timestamp[debugfs_dump_index] = timestamp;
debugfs_snapshot_prepare_v3_hw(hisi_hba);
debugfs_snapshot_global_reg_v3_hw(hisi_hba);
debugfs_snapshot_port_reg_v3_hw(hisi_hba);
debugfs_snapshot_axi_reg_v3_hw(hisi_hba);
debugfs_snapshot_ras_reg_v3_hw(hisi_hba);
debugfs_snapshot_cq_reg_v3_hw(hisi_hba);
debugfs_snapshot_dq_reg_v3_hw(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++;
return 0;
}
static void debugfs_phy_down_cnt_init_v3_hw(struct hisi_hba *hisi_hba)
{
struct dentry *dir = debugfs_create_dir("phy_down_cnt",
@ -4874,7 +4891,6 @@ static void debugfs_exit_v3_hw(struct hisi_hba *hisi_hba)
static void debugfs_init_v3_hw(struct hisi_hba *hisi_hba)
{
struct device *dev = hisi_hba->dev;
int i;
hisi_hba->debugfs_dir = debugfs_create_dir(dev_name(dev),
hisi_sas_debugfs_dir);
@ -4891,14 +4907,6 @@ static void debugfs_init_v3_hw(struct hisi_hba *hisi_hba)
debugfs_phy_down_cnt_init_v3_hw(hisi_hba);
debugfs_fifo_init_v3_hw(hisi_hba);
for (i = 0; i < hisi_sas_debugfs_dump_count; i++) {
if (debugfs_alloc_v3_hw(hisi_hba, i)) {
debugfs_exit_v3_hw(hisi_hba);
dev_dbg(dev, "failed to init debugfs!\n");
break;
}
}
}
static int
@ -5032,6 +5040,7 @@ err_out_unregister_ha:
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);
@ -5064,7 +5073,6 @@ static void hisi_sas_v3_remove(struct pci_dev *pdev)
struct Scsi_Host *shost = sha->shost;
pm_runtime_get_noresume(dev);
del_timer_sync(&hisi_hba->timer);
sas_unregister_ha(sha);
flush_workqueue(hisi_hba->wq);
@ -5072,7 +5080,9 @@ 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);
}
@ -5163,7 +5173,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;

View File

@ -135,7 +135,7 @@ static int smp_execute_task(struct domain_device *dev, void *req, int req_size,
static inline void *alloc_smp_req(int size)
{
u8 *p = kzalloc(size, GFP_KERNEL);
u8 *p = kzalloc(ALIGN(size, ARCH_DMA_MINALIGN), GFP_KERNEL);
if (p)
p[0] = SMP_REQUEST;
return p;