!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:
commit
7722165753
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue