[PATCH OLK-6.6] scsi: leapraid: update driver to v2.00.01.10
LeapIO inclusion category: feature bugzilla: https://atomgit.com/openeuler/kernel/issues/9946 ------------------------------------------ leapraid driver changes from v2.00.01.02 to v2.00.01.10. This update includes: - AI-assisted code inspection rollout and follow-up bug fixes - Clang, Sparse, and Smatch issue cleanup - recovery-wait and nested hard-reset stabilization - SCSI EH, task-management, and AER recovery fixes - timeout, IOC-fault, and I/O diagnostic improvements - MSI-X/IRQ affinity and sparse-CPU mapping fixes - SAS topology, event bitmap, and VPHY handling fixes - async-event and SMP payload validation hardening - ioctl and passthrough bounds-checking cleanup - adapter-removal and firmware-event race fixes - firmware-log mmap lifetime and reference-count fixes - active-command teardown and IRQ synchronization - probe rollback and host-memory cleanup hardening - config-page stack usage reduction - SMART polling and NCQ sysfs alignment - drive matching and adapter metadata cleanup Signed-off-by: haodongdong <doubled@leap-io.com> --- drivers/scsi/leapraid/leapraid.h | 37 +- drivers/scsi/leapraid/leapraid_app.c | 169 ++- drivers/scsi/leapraid/leapraid_func.c | 1126 +++++++------------- drivers/scsi/leapraid/leapraid_func.h | 130 +-- drivers/scsi/leapraid/leapraid_os.c | 276 ++--- drivers/scsi/leapraid/leapraid_transport.c | 40 +- 6 files changed, 693 insertions(+), 1085 deletions(-) diff --git a/drivers/scsi/leapraid/leapraid.h b/drivers/scsi/leapraid/leapraid.h index 2a99417143ad..c2d28359be5b 100644 --- a/drivers/scsi/leapraid/leapraid.h +++ b/drivers/scsi/leapraid/leapraid.h @@ -27,8 +27,6 @@ /* Maximum number of retries waiting for doorbell to become operational. */ #define LEAPRAID_DB_WAIT_OP_SHORT 10 #define LEAPRAID_DB_WAIT_OP_LONG 200 -/* Sleep interval (in seconds) between doorbell polls. */ -#define LEAPRAID_DB_POLL_INTERVAL_S 1 /* Maximum number of retries waiting for host to end recovery. */ #define LEAPRAID_WAIT_SHOST_RECOVERY 400 @@ -43,7 +41,6 @@ /* The number of debug register. */ #define LEAPRAID_DEBUGLOG_SZ_MAX 16 -#define LEAPRAID_DEBUGLOG_DWORDS_PER_LINE 4 /* Reply post host register definitions. */ #define REP_POST_HOST_IDX_REG_CNT 16 @@ -180,8 +177,6 @@ #define LEAPRAID_CFG_PAGE_NUM_DEV0 0x0 /* SAS device page 0 flags. */ -#define LEAPRAID_SAS_DEV_P0_FLG_FP_CAP 0x2000 -#define LEAPRAID_SAS_DEV_P0_FLG_SATA_SMART 0x0040 #define LEAPRAID_SAS_DEV_P0_FLG_ENC_LEVEL_VALID 0x0002 #define LEAPRAID_SAS_DEV_P0_FLG_DEV_PRESENT 0x0001 #define LEAPRAID_SAS_DEV_P0_CON_NAME_LEN 4 @@ -207,15 +202,9 @@ /* Physical disk page number. */ #define LEAPRAID_CFG_PAGE_NUM_PD0 0x0 -/* Adapter page number. */ -#define LEAPRAID_CFG_PAGE_NUM_ADAPTER1 0x1 - #define LEAPRAID_CFG_UNIT_SIZE 4 /* Raid volume type and state. */ -#define LEAPRAID_VOL_STATE_MISSING 0x00 -#define LEAPRAID_VOL_STATE_FAILED 0x01 -#define LEAPRAID_VOL_STATE_INITIALIZING 0x02 #define LEAPRAID_VOL_STATE_ONLINE 0x03 #define LEAPRAID_VOL_STATE_DEGRADED 0x04 #define LEAPRAID_VOL_STATE_OPTIMAL 0x05 @@ -231,10 +220,6 @@ #define LEAPRAID_RAIDCFG_P0_EFLG_HOT_SPARE_ELEMENT 0x0002 #define LEAPRAID_RAIDCFG_P0_EFLG_OCE_ELEMENT 0x0003 -/* Raid action. */ -#define LEAPRAID_RAID_ACT_SYSTEM_SHUTDOWN_INITIATED 0x20 -#define LEAPRAID_RAID_ACT_PHYSDISK_HIDDEN 0x24 - /* SAS negotiated link rates. */ #define LEAPRAID_SAS_NEG_LINK_RATE_MASK_PHYSICAL 0x0F #define LEAPRAID_SAS_NEG_LINK_RATE_UNKNOWN_LINK_RATE 0x00 @@ -290,8 +275,6 @@ #define LEAPRAID_TM_MSGFLAGS_LINK_RESET 0x00 #define LEAPRAID_TM_RSP_INVALID_FRAME 0x02 -#define LEAPRAID_TM_RSP_TM_SUCCEEDED 0x08 -#define LEAPRAID_TM_RSP_IO_QUEUED_ON_ADAPTER 0x80 /* SCSI enclosure processor request defines. */ #define LEAPRAID_SEP_REQ_ACT_WRITE_STATUS 0x00 @@ -301,8 +284,6 @@ /* The capabilities of the adapter. */ #define LEAPRAID_ADAPTER_FEATURES_CAP_ATOMIC_REQ 0x00080000 -#define LEAPRAID_ADAPTER_FEATURES_CAP_RDPQ_ARRAY_CAPABLE 0x00040000 -#define LEAPRAID_ADAPTER_FEATURES_CAP_EVENT_REPLAY 0x00002000 #define LEAPRAID_ADAPTER_FEATURES_CAP_INTEGRATED_RAID 0x00001000 /* Event code definitions for the firmware. */ @@ -338,10 +319,6 @@ #define LEAPRAID_EVT_SAS_TOPO_RC_TARG_ADDED 0x01 #define LEAPRAID_EVT_SAS_TOPO_RC_TARG_NOT_RESPONDING 0x02 -/* SAS discovery event defines. */ -#define LEAPRAID_EVT_SAS_DISC_RC_STARTED 0x01 -#define LEAPRAID_EVT_SAS_DISC_RC_COMPLETED 0x02 - /* Enclosure device status change event. */ #define LEAPRAID_EVT_SAS_ENCL_RC_ADDED 0x01 #define LEAPRAID_EVT_SAS_ENCL_RC_NOT_RESPONDING 0x02 @@ -543,7 +520,7 @@ struct leapraid_sge_simple_union { union { __le32 addr32; __le64 addr64; - } u; + } __packed __aligned(4) u; } __packed __aligned(4); /** @@ -562,7 +539,7 @@ struct leapraid_sge_chain_union { union { __le32 addr32; __le64 addr64; - } u; + } __packed __aligned(4) u; } __packed __aligned(4); /** @@ -1672,7 +1649,7 @@ struct leapraid_adapter_features_req { * @r9: Reserved. */ struct leapraid_adapter_features_rep { - u16 msg_ver; + __le16 msg_ver; u8 msg_len; u8 func; u16 header_ver; @@ -1686,7 +1663,7 @@ struct leapraid_adapter_features_rep { u8 r4; u8 max_msix_vectors; __le16 req_slot; - u8 r5[2]; + __le16 product_id; __le32 adapter_caps; __le32 fw_version; __le16 sas_wide_max_qdepth; @@ -1871,7 +1848,7 @@ struct leapraid_evt_sas_topo_phy_entry { * @exp_dev_hdl: Expander device handle. * @num_phys: Number of PHYs in this entry. * @r1: Reserved. - * @entry_num: Entry index. + * @entry_num: Number of PHY elements. * @start_phy_num: Start PHY number. * @exp_status: Expander status. * @physical_port: Physical port number. @@ -1909,7 +1886,7 @@ struct leapraid_evt_data_sas_enc_dev_status_change { __le16 num_slots; __le16 start_slot; __le32 phy_bits; -}; +} __packed __aligned(4); /** * struct leapraid_io_unit_ctrl_req - I/O unit control request @@ -1933,7 +1910,7 @@ struct leapraid_io_unit_ctrl_req { u8 r1; u8 chain_offset; u8 func; - u16 dev_hdl; + __le16 dev_hdl; u8 adapter_para; u8 msg_flag; u8 r2[6]; diff --git a/drivers/scsi/leapraid/leapraid_app.c b/drivers/scsi/leapraid/leapraid_app.c index 25ec57c2ce4b..c4d4aace8112 100644 --- a/drivers/scsi/leapraid/leapraid_app.c +++ b/drivers/scsi/leapraid/leapraid_app.c @@ -134,13 +134,59 @@ struct leapraid_ioctl_command { u8 mf[]; }; -static struct leapraid_adapter *leapraid_ctl_lookup_adapter(int adapter_id) +static int leapraid_ctl_validate_sge_offset(struct leapraid_adapter *adapter, + const struct leapraid_req *req, + u32 offset_bytes, + size_t h2c_size, + size_t c2h_size) +{ + size_t sge_bytes; + + switch (req->func) { + case LEAPRAID_FUNC_SCSIIO: + case LEAPRAID_FUNC_SCSIIO_RAID_PASSTHROUGH: + case LEAPRAID_FUNC_SMP_PASSTHROUGH: + case LEAPRAID_FUNC_SCSIIO_SATA_PASSTHROUGH: + case LEAPRAID_FUNC_FW_DOWNLOAD: + case LEAPRAID_FUNC_FW_UPLOAD: + sge_bytes = LEAPRAID_IEEE_SGE64_ENTRY_SIZE; + break; + default: + sge_bytes = adapter->adapter_attr.use_32_dma_mask ? + sizeof(struct leapraid_sge_simple32) : + sizeof(struct leapraid_sge_simple64); + break; + } + + if (h2c_size && c2h_size) + sge_bytes *= 2; + + if (offset_bytes > LEAPRAID_REQUEST_SIZE - sge_bytes) { + dev_err(&adapter->pdev->dev, + "%s: Invalid offset_bytes=%u for func=0x%x\n", + __func__, offset_bytes, req->func); + return -EINVAL; + } + + return 0; +} + +static struct leapraid_adapter *leapraid_ctl_lookup_adapter(int adapter_id, + bool track_mmap) { struct leapraid_adapter *adapter; + struct Scsi_Host *shost; spin_lock(&leapraid_adapter_lock); list_for_each_entry(adapter, &leapraid_adapter_list, list) { if (adapter->adapter_attr.id == adapter_id) { + if (READ_ONCE(adapter->access_ctrl.host_removing)) + break; + shost = adapter->shost; + if (!shost || !scsi_host_get(shost)) + break; + if (track_mmap) + atomic_inc(&adapter->fw_log_desc.mmap_refcnt); spin_unlock(&leapraid_adapter_lock); return adapter; } @@ -150,6 +196,12 @@ static struct leapraid_adapter *leapraid_ctl_lookup_adapter(int adapter_id) return NULL; } +static void leapraid_ctl_put_adapter(struct leapraid_adapter *adapter) +{ + if (adapter && adapter->shost) + scsi_host_put(adapter->shost); +} + static void leapraid_ctl_scsiio_cmd(struct leapraid_adapter *adapter, void *ctl_sp_mpi_req, u16 taskid, @@ -245,6 +297,7 @@ static int leapraid_ctl_do_command(struct leapraid_adapter *adapter, unsigned long timeout; u16 dev_hdl = LEAPRAID_INVALID_DEV_HANDLE; bool issue_reset = false; + u32 data_sge_offset_bytes; u32 sz; int rc; @@ -257,9 +310,17 @@ static int leapraid_ctl_do_command(struct leapraid_adapter *adapter, if (!leap_mpi_req) return -ENOMEM; - if (karg->data_sge_offset > (UINT_MAX / LEAPRAID_SGE_OFFSET_SIZE) || - karg->data_sge_offset * LEAPRAID_SGE_OFFSET_SIZE > - LEAPRAID_REQUEST_SIZE) { + if (karg->data_sge_offset > (UINT_MAX / LEAPRAID_SGE_OFFSET_SIZE)) { + dev_err(&adapter->pdev->dev, + "%s: Invalid data_sge_offset=%u\n", + __func__, karg->data_sge_offset); + rc = -EINVAL; + goto out_cleanup; + } + + data_sge_offset_bytes = karg->data_sge_offset * + LEAPRAID_SGE_OFFSET_SIZE; + if (data_sge_offset_bytes > LEAPRAID_REQUEST_SIZE) { dev_err(&adapter->pdev->dev, "%s: Invalid data_sge_offset=%u\n", __func__, karg->data_sge_offset); @@ -267,8 +328,7 @@ static int leapraid_ctl_do_command(struct leapraid_adapter *adapter, goto out_cleanup; } - if (copy_from_user(leap_mpi_req, mf, - karg->data_sge_offset * LEAPRAID_SGE_OFFSET_SIZE)) { + if (copy_from_user(leap_mpi_req, mf, data_sge_offset_bytes)) { dev_err(&adapter->pdev->dev, "%s: Failed to copy request message from user\n", __func__); @@ -276,16 +336,21 @@ static int leapraid_ctl_do_command(struct leapraid_adapter *adapter, goto out_cleanup; } + h2c_size = karg->h2c_size; + c2h_size = karg->c2h_size; + rc = leapraid_ctl_validate_sge_offset(adapter, leap_mpi_req, + data_sge_offset_bytes, + h2c_size, c2h_size); + if (rc) + goto out_cleanup; + taskid = adapter->driver_cmds.ctl_cmd.taskid; adapter->driver_cmds.ctl_cmd.status = LEAPRAID_CMD_PENDING; - memset(&adapter->driver_cmds.ctl_cmd.reply, 0, - LEAPRAID_REPLY_SIZE); + memset(&adapter->driver_cmds.ctl_cmd.reply, 0, LEAPRAID_REPLY_SIZE); ctl_sp_mpi_req = leapraid_get_task_desc(adapter, taskid); memset(ctl_sp_mpi_req, 0, LEAPRAID_REQUEST_SIZE); - memcpy(ctl_sp_mpi_req, - leap_mpi_req, - karg->data_sge_offset * LEAPRAID_SGE_OFFSET_SIZE); + memcpy(ctl_sp_mpi_req, leap_mpi_req, data_sge_offset_bytes); if (ctl_sp_mpi_req->func == LEAPRAID_FUNC_SCSIIO || ctl_sp_mpi_req->func == LEAPRAID_FUNC_SCSIIO_RAID_PASSTHROUGH || @@ -305,8 +370,6 @@ static int leapraid_ctl_do_command(struct leapraid_adapter *adapter, goto out_cleanup; } - h2c_size = karg->h2c_size; - c2h_size = karg->c2h_size; if (h2c_size) { h2c = dma_alloc_coherent(&adapter->pdev->dev, h2c_size, &h2c_dma_addr, GFP_KERNEL); @@ -331,8 +394,7 @@ static int leapraid_ctl_do_command(struct leapraid_adapter *adapter, } } - psge = (void *)ctl_sp_mpi_req + (karg->data_sge_offset * - LEAPRAID_SGE_OFFSET_SIZE); + psge = (void *)ctl_sp_mpi_req + data_sge_offset_bytes; init_completion(&adapter->driver_cmds.ctl_cmd.done); switch (ctl_sp_mpi_req->func) { @@ -388,6 +450,7 @@ static int leapraid_ctl_do_command(struct leapraid_adapter *adapter, dev_err(&adapter->pdev->dev, "%s: ctl_cmd timeout, status=0x%x\n", __func__, adapter->driver_cmds.ctl_cmd.status); + leapraid_log_req_context(adapter, taskid, ctl_sp_mpi_req); } if ((leap_mpi_req->func == LEAPRAID_FUNC_SMP_PASSTHROUGH || @@ -517,7 +580,7 @@ static int leapraid_ctl_ioctl_main(struct file *file, unsigned int cmd, void __user *arg) { struct leapraid_ioctl_header ioctl_header; - struct leapraid_adapter *adapter; + struct leapraid_adapter *adapter = NULL; struct leapraid_ioctl_command __user *uarg; struct leapraid_ioctl_command karg; int rc = -ENOIOCTLCMD; @@ -529,7 +592,7 @@ static int leapraid_ctl_ioctl_main(struct file *file, unsigned int cmd, return -EFAULT; } - adapter = leapraid_ctl_lookup_adapter(ioctl_header.adapter_id); + adapter = leapraid_ctl_lookup_adapter(ioctl_header.adapter_id, false); if (!adapter) return -EFAULT; @@ -538,7 +601,8 @@ static int leapraid_ctl_ioctl_main(struct file *file, unsigned int cmd, "%s: Failed, thermal_alert=%d\n", __func__, atomic_read(&adapter->overheat_desc.thermal_alert)); - return -EFAULT; + rc = -EFAULT; + goto out_put; } mutex_lock(&adapter->access_ctrl.pci_access_lock); @@ -590,7 +654,7 @@ static int leapraid_ctl_ioctl_main(struct file *file, unsigned int cmd, break; } - if (karg.hdr.adapter_id != ioctl_header.adapter_id) { + if (karg.hdr.adapter_id != ioctl_header.adapter_id) { rc = -EINVAL; break; } @@ -618,46 +682,78 @@ static int leapraid_ctl_ioctl_main(struct file *file, unsigned int cmd, unlock: mutex_unlock(&adapter->access_ctrl.pci_access_lock); +out_put: + leapraid_ctl_put_adapter(adapter); return rc; } -static long bad_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - return -ENOTTY; -} - static long leapraid_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { return leapraid_ctl_ioctl_main(file, cmd, (void __user *)arg); } +static void leapraid_fw_mmap_open(struct vm_area_struct *vma) +{ + struct leapraid_adapter *adapter = vma->vm_private_data; + + if (!adapter) + return; + + get_device(&adapter->shost->shost_gendev); + atomic_inc(&adapter->fw_log_desc.mmap_refcnt); +} + +static void leapraid_fw_mmap_close(struct vm_area_struct *vma) +{ + struct leapraid_adapter *adapter = vma->vm_private_data; + + if (!adapter) + return; + + if (atomic_dec_and_test(&adapter->fw_log_desc.mmap_refcnt)) + wake_up(&adapter->fw_log_desc.mmap_waitq); + leapraid_ctl_put_adapter(adapter); +} + +static const struct vm_operations_struct leapraid_fw_mmap_vm_ops = { + .open = leapraid_fw_mmap_open, + .close = leapraid_fw_mmap_close, +}; + static int leapraid_fw_mmap(struct file *filp, struct vm_area_struct *vma) { - struct leapraid_adapter *adapter; + struct leapraid_adapter *adapter = NULL; /* Userspace passes the adapter ID via vma->vm_pgoff. */ u32 adapter_id = vma->vm_pgoff; unsigned long length; - int rc; + int rc = -EINVAL; length = vma->vm_end - vma->vm_start; - adapter = leapraid_ctl_lookup_adapter(adapter_id); + adapter = leapraid_ctl_lookup_adapter(adapter_id, true); if (!adapter) { pr_err("%s: No adapter found!\n", __func__); return -EINVAL; } + if (READ_ONCE(adapter->access_ctrl.host_removing)) { + rc = -EAGAIN; + goto out_put; + } + if (length > (LEAPRAID_SYS_LOG_BUF_SIZE + LEAPRAID_SYS_LOG_BUF_RESERVE)) { dev_err(&adapter->pdev->dev, "Requested mapping size is too large!\n"); - return -EINVAL; + rc = -EINVAL; + goto out_put; } if (!adapter->fw_log_desc.fw_log_buffer) { dev_err(&adapter->pdev->dev, "No log buffer!\n"); - return -EINVAL; + rc = -EINVAL; + goto out_put; } vma->vm_pgoff = 0; @@ -669,17 +765,26 @@ static int leapraid_fw_mmap(struct file *filp, struct vm_area_struct *vma) if (rc) { dev_err(&adapter->pdev->dev, "Failed to map memory to user space!\n"); - return rc; + goto out_put; } - return 0; + vma->vm_private_data = adapter; + vma->vm_ops = &leapraid_fw_mmap_vm_ops; + leapraid_fw_mmap_open(vma); + + rc = 0; +out_put: + if (adapter && + atomic_dec_and_test(&adapter->fw_log_desc.mmap_refcnt)) + wake_up(&adapter->fw_log_desc.mmap_waitq); + leapraid_ctl_put_adapter(adapter); + return rc; } static const struct file_operations leapraid_ctl_fops = { .owner = THIS_MODULE, .unlocked_ioctl = leapraid_ctl_ioctl, .mmap = leapraid_fw_mmap, - .compat_ioctl = bad_ioctl, }; static struct miscdevice leapraid_ctl_dev = { diff --git a/drivers/scsi/leapraid/leapraid_func.c b/drivers/scsi/leapraid/leapraid_func.c index f2574feb2514..32683f205d10 100644 --- a/drivers/scsi/leapraid/leapraid_func.c +++ b/drivers/scsi/leapraid/leapraid_func.c @@ -8,21 +8,6 @@ #include "leapraid_func.h" -static int msix_disable; -module_param(msix_disable, int, 0444); -MODULE_PARM_DESC(msix_disable, - "disable msix routed interrupts (default=0)"); - -static int smart_poll; -module_param(smart_poll, int, 0444); -MODULE_PARM_DESC(smart_poll, - "check SATA drive health via SMART polling: (default=0)"); - -static int interrupt_mode; -module_param(interrupt_mode, int, 0444); -MODULE_PARM_DESC(interrupt_mode, - "intr mode: 0 is MSI-X, 1 is MSI, 2 is legacy. (default=0)"); - static int poll_queues; module_param(poll_queues, int, 0444); MODULE_PARM_DESC(poll_queues, @@ -42,45 +27,23 @@ static void leapraid_ublk_io_dev(struct leapraid_adapter *adapter, static void leapraid_clear_cached_boot_dev(struct leapraid_adapter *adapter, void *dev, u32 chnl); static int leapraid_make_adapter_available(struct leapraid_adapter *adapter); +static void leapraid_sync_irqs_for_cleanup(struct leapraid_adapter *adapter); static int leapraid_fw_log_init(struct leapraid_adapter *adapter); static bool leapraid_should_skip_poll_work(struct leapraid_adapter *adapter); static int leapraid_make_adapter_ready(struct leapraid_adapter *adapter, enum reset_type type); -static void leapraid_debug_log_info(struct leapraid_adapter *adapter) +static noinline bool leapraid_shost_in_recovery(struct Scsi_Host *shost) { - struct leapraid_reg_base __iomem *iomem_base = adapter->iomem_base; - u32 debug_log[LEAPRAID_DEBUGLOG_SZ_MAX]; - bool changed = false; - int i; + enum scsi_host_state state; - if (leapraid_should_skip_poll_work(adapter)) - return; - - for (i = 0; i < LEAPRAID_DEBUGLOG_SZ_MAX; i++) { - debug_log[i] = leapraid_readl(&iomem_base->debug_log[i]); - if (debug_log[i] != adapter->fw_log_desc.pre_debug_log[i]) - changed = true; - } - - if (!changed) - return; - - memcpy(adapter->fw_log_desc.pre_debug_log, - debug_log, - sizeof(debug_log)); - - for (i = 0; i < LEAPRAID_DEBUGLOG_SZ_MAX; - i += LEAPRAID_DEBUGLOG_DWORDS_PER_LINE) - dev_warn(&adapter->pdev->dev, - "debug_log[%d-%d]: 0x%08x 0x%08x 0x%08x 0x%08x\n", - i, - i + LEAPRAID_DEBUGLOG_DWORDS_PER_LINE - 1, - debug_log[i], - debug_log[i + 1], - debug_log[i + 2], - debug_log[i + 3]); + state = READ_ONCE(shost->shost_state); + return state == SHOST_RECOVERY || + state == SHOST_CANCEL_RECOVERY || + state == SHOST_DEL_RECOVERY || + shost->tmf_in_progress; } + static inline bool leapraid_is_end_dev(u32 dev_type) { return (dev_type & LEAPRAID_DEVTYP_END_DEV) && @@ -171,7 +134,6 @@ static void leapraid_overheat_suspend(struct leapraid_adapter *adapter) pdev = adapter->pdev; shost = pci_get_drvdata(pdev); - if (!shost) { dev_warn(&pdev->dev, "Overheat suspend failed, invalid host or adapter\n"); @@ -361,6 +323,12 @@ int leapraid_check_adapter_is_op(struct leapraid_adapter *adapter, int wait, int wait_count; for (wait_count = wait; wait_count > 0; wait_count--) { + if (READ_ONCE(adapter->access_ctrl.host_removing)) { + dev_warn(&adapter->pdev->dev, + "%s: Host is removing\n", caller); + return -EFAULT; + } + if (leapraid_pci_removed(adapter)) { dev_warn(&adapter->pdev->dev, "%s: PCI device removed\n", __func__); @@ -499,11 +467,9 @@ static bool leapraid_is_fixed_taskid(struct leapraid_adapter *adapter, struct leapraid_driver_cmds *driver_cmds = &adapter->driver_cmds; return (taskid == driver_cmds->ctl_cmd.taskid || - taskid == driver_cmds->driver_scsiio_cmd.taskid || taskid == driver_cmds->tm_cmd.hp_taskid || taskid == driver_cmds->ctl_cmd.hp_taskid || taskid == driver_cmds->scan_dev_cmd.inter_taskid || - taskid == driver_cmds->timestamp_sync_cmd.inter_taskid || taskid == driver_cmds->transport_cmd.inter_taskid || taskid == driver_cmds->cfg_op_cmd.inter_taskid || taskid == driver_cmds->enc_cmd.inter_taskid || @@ -606,6 +572,8 @@ void leapraid_clean_active_scsi_cmds(struct leapraid_adapter *adapter) void *task_desc; u16 taskid; + leapraid_sync_irqs_for_cleanup(adapter); + for (taskid = 1; taskid <= adapter->shost->can_queue; taskid++) { scmd = leapraid_get_scmd_from_taskid(adapter, taskid); if (!scmd) @@ -643,8 +611,6 @@ static void leapraid_clean_active_driver_cmds(struct leapraid_adapter *adapter) struct leapraid_driver_cmds *driver_cmds; driver_cmds = &adapter->driver_cmds; - leapraid_clean_active_driver_cmd(&driver_cmds->timestamp_sync_cmd); - leapraid_clean_active_driver_cmd(&driver_cmds->driver_scsiio_cmd); leapraid_clean_active_driver_cmd(&driver_cmds->tm_cmd); leapraid_clean_active_driver_cmd(&driver_cmds->transport_cmd); leapraid_clean_active_driver_cmd(&driver_cmds->enc_cmd); @@ -1912,16 +1878,6 @@ static const char *leapraid_sas_op_name(u8 op) } } -static const char *leapraid_io_param_name(u8 adapter_param) -{ - switch (adapter_param) { - case LEAPRAID_SET_PARAMETER_SYNC_TIMESTAMP: - return "SYNC_TIMESTAMP"; - default: - return "UNKNOWN"; - } -} - static const char *leapraid_tm_type_name(u8 task_type) { switch (task_type) { @@ -1948,7 +1904,7 @@ static const char *leapraid_tm_type_name(u8 task_type) } } -void leapraid_log_req_context(struct leapraid_adapter *adapter, +void leapraid_log_req_context(struct leapraid_adapter *adapter, u16 smid, const void *req_data) { const struct leapraid_req *req = req_data; @@ -1961,8 +1917,8 @@ void leapraid_log_req_context(struct leapraid_adapter *adapter, const struct leapraid_cfg_req *cfg_req = req_data; dev_err(&adapter->pdev->dev, - "cfg-req: func=0x%02x(%s) act=0x%02x(%s)\n", - req->func, leapraid_func_name(req->func), + "cfg-req: smid=%u func=0x%02x(%s) action=0x%02x(%s)\n", + smid, req->func, leapraid_func_name(req->func), cfg_req->action, leapraid_cfg_action_name(cfg_req->action)); dev_err(&adapter->pdev->dev, @@ -1984,12 +1940,12 @@ void leapraid_log_req_context(struct leapraid_adapter *adapter, const struct leapraid_scsi_tm_req *tm_req = req_data; dev_err(&adapter->pdev->dev, - "scsi_tm: func=0x%02x(%s) task=0x%02x(%s)\n", - req->func, leapraid_func_name(req->func), + "scsi_tm:: smid=%u func=0x%02x(%s) task=0x%02x(%s)\n", + smid, req->func, leapraid_func_name(req->func), tm_req->task_type, leapraid_tm_type_name(tm_req->task_type)); dev_err(&adapter->pdev->dev, - "scsi_tm: dev_hdl=0x%04x task_mid=%u\n", + "scsi_tm:: dev_hdl=0x%04x task_mid=%u\n", le16_to_cpu(tm_req->dev_hdl), le16_to_cpu(tm_req->task_mid)); break; @@ -1998,8 +1954,8 @@ void leapraid_log_req_context(struct leapraid_adapter *adapter, const struct leapraid_sep_req *sep_req = req_data; dev_err(&adapter->pdev->dev, - "sep: func=0x%02x(%s) act=0x%02x(%s)\n", - req->func, leapraid_func_name(req->func), + "sep: smid=%u func=0x%02x(%s) action=0x%02x(%s)\n", + smid, req->func, leapraid_func_name(req->func), sep_req->act, leapraid_sep_action_name(sep_req->act)); dev_err(&adapter->pdev->dev, @@ -2013,32 +1969,34 @@ void leapraid_log_req_context(struct leapraid_adapter *adapter, const struct leapraid_io_unit_ctrl_req *io_req = req_data; dev_err(&adapter->pdev->dev, - "timestamp sync: func=0x%02x(%s) op=0x%02x(%s)\n", - req->func, leapraid_func_name(req->func), + "ctl_cmd: smid=%u func=0x%02x(%s) action=0x%02x(%s)\n", + smid, req->func, leapraid_func_name(req->func), io_req->op, leapraid_sas_op_name(io_req->op)); dev_err(&adapter->pdev->dev, - "timestamp sync: dev_hdl=0x%04x param=0x%02x(%s)\n", + "ctl_cmd: dev_hdl=0x%04x param=0x%02x\n", le16_to_cpu(io_req->dev_hdl), - io_req->adapter_para, - leapraid_io_param_name(io_req->adapter_para)); + io_req->adapter_para); break; } case LEAPRAID_FUNC_SMP_PASSTHROUGH: { const struct leapraid_smp_passthrough_req *smp_req = req_data; dev_err(&adapter->pdev->dev, - "transport: func=0x%02x(%s) port=%u req_len=%u\n", - req->func, leapraid_func_name(req->func), + "smp_cmd: smid=%u func=0x%02x(%s) action=0x%02x\n", + smid, req->func, leapraid_func_name(req->func), + smp_req->passthrough_flg); + dev_err(&adapter->pdev->dev, + "smp_cmd: port=%u req_len=%u\n", smp_req->physical_port, le16_to_cpu(smp_req->req_data_len)); - dev_err(&adapter->pdev->dev, "transport: sas_addr=0x%016llx\n", + dev_err(&adapter->pdev->dev, "smp_cmd: sas_addr=0x%016llx\n", (unsigned long long)le64_to_cpu(smp_req->sas_address)); break; } default: dev_err(&adapter->pdev->dev, - "%s: func=0x%02x(%s)\n", - __func__, req->func, leapraid_func_name(req->func)); + "cmd: smid=%u func=0x%02x(%s)\n", + smid, req->func, leapraid_func_name(req->func)); break; } } @@ -2049,19 +2007,18 @@ static void leapraid_build_and_fire_cfg_req( struct leapraid_cfg_rep *leap_mpi_cfgp_rep) { struct leapraid_cfg_req *local_leap_cfg_req; + u16 smid; memset(leap_mpi_cfgp_rep, 0, sizeof(struct leapraid_cfg_rep)); memset(&adapter->driver_cmds.cfg_op_cmd.reply, 0, sizeof(struct leapraid_cfg_rep)); adapter->driver_cmds.cfg_op_cmd.status = LEAPRAID_CMD_PENDING; - local_leap_cfg_req = leapraid_get_task_desc( - adapter, - adapter->driver_cmds.cfg_op_cmd.inter_taskid); + smid = adapter->driver_cmds.cfg_op_cmd.inter_taskid; + local_leap_cfg_req = leapraid_get_task_desc(adapter, smid); memcpy(local_leap_cfg_req, leap_mpi_cfgp_req, sizeof(struct leapraid_cfg_req)); init_completion(&adapter->driver_cmds.cfg_op_cmd.done); - leapraid_fire_task(adapter, - adapter->driver_cmds.cfg_op_cmd.inter_taskid); + leapraid_fire_task(adapter, smid); wait_for_completion_timeout(&adapter->driver_cmds.cfg_op_cmd.done, LEAPRAID_CFG_OP_TIMEOUT * HZ); } @@ -2074,11 +2031,13 @@ static int leapraid_req_cfg_func(struct leapraid_adapter *adapter, { u32 adapter_status = UINT_MAX; bool issue_reset = false; + u16 smid; u8 retry_cnt; int rc; retry_cnt = 0; mutex_lock(&adapter->driver_cmds.cfg_op_cmd.mutex); + smid = adapter->driver_cmds.cfg_op_cmd.inter_taskid; retry: if (retry_cnt) { if (retry_cnt > LEAPRAID_CFG_REQ_RETRY_TIMES) { @@ -2115,14 +2074,16 @@ static int leapraid_req_cfg_func(struct leapraid_adapter *adapter, adapter->access_ctrl.shost_recovering ? "shost recovery" : "pcie recovery", adapter->driver_cmds.cfg_op_cmd.status); - leapraid_log_req_context(adapter, leap_mpi_cfgp_req); + leapraid_log_req_context(adapter, smid, + leap_mpi_cfgp_req); issue_reset = false; rc = -EFAULT; } else { dev_err(&adapter->pdev->dev, "cfg-req: timeout, status=0x%x, reset\n", adapter->driver_cmds.cfg_op_cmd.status); - leapraid_log_req_context(adapter, leap_mpi_cfgp_req); + leapraid_log_req_context(adapter, smid, + leap_mpi_cfgp_req); issue_reset = true; } @@ -2162,7 +2123,7 @@ static int leapraid_req_cfg_func(struct leapraid_adapter *adapter, mutex_unlock(&adapter->driver_cmds.cfg_op_cmd.mutex); if (issue_reset) { if (adapter->scan_dev_desc.first_scan_dev_fired) { - dev_info(&adapter->pdev->dev, + dev_warn(&adapter->pdev->dev, "%s:%d cfg-req: Failure, issuing reset\n", __func__, __LINE__); leapraid_hard_reset_handler(adapter, FULL_RESET); @@ -2433,14 +2394,12 @@ static int leapraid_cfg_find_vol_in_page( u16 phys_hdl; phys_hdl = le16_to_cpu(elem->phys_disk_dev_hdl); - if (phys_hdl == pd_hdl) { *vol_hdl = le16_to_cpu(elem->vol_dev_hdl); return 0; } break; } - case LEAPRAID_RAIDCFG_P0_EFLG_HOT_SPARE_ELEMENT: *vol_hdl = 0; return 0; @@ -2607,7 +2566,6 @@ static int leapraid_cfg_get_number_pds(struct leapraid_adapter *adapter, cfgp2.handle = hdl; rc = leapraid_op_config_page(adapter, &raidvol_p0, cfgp1, cfgp2, GET_RAID_VOLUME_PG0); - if (!rc) *num_pds = raidvol_p0.num_phys_disks; @@ -2821,61 +2779,6 @@ void leapraid_fw_log_start(struct leapraid_adapter *adapter) spin_unlock_irqrestore(&adapter->reset_desc.adapter_reset_lock, flags); } -static void leapraid_timestamp_sync(struct leapraid_adapter *adapter) -{ - struct leapraid_io_unit_ctrl_req *io_unit_ctrl_req; - ktime_t current_time; - bool issue_reset = false; - u64 time_stamp; - - mutex_lock(&adapter->driver_cmds.timestamp_sync_cmd.mutex); - adapter->driver_cmds.timestamp_sync_cmd.status = LEAPRAID_CMD_PENDING; - io_unit_ctrl_req = - leapraid_get_task_desc( - adapter, - adapter->driver_cmds.timestamp_sync_cmd.inter_taskid); - memset(io_unit_ctrl_req, 0, sizeof(struct leapraid_io_unit_ctrl_req)); - io_unit_ctrl_req->func = LEAPRAID_FUNC_SAS_IO_UNIT_CTRL; - io_unit_ctrl_req->op = LEAPRAID_SAS_OP_SET_PARAMETER; - io_unit_ctrl_req->adapter_para = LEAPRAID_SET_PARAMETER_SYNC_TIMESTAMP; - - current_time = ktime_get_real(); - time_stamp = ktime_to_ms(current_time); - - io_unit_ctrl_req->adapter_para_value = - cpu_to_le32(time_stamp & 0xFFFFFFFF); - io_unit_ctrl_req->adapter_para_value2 = - cpu_to_le32(time_stamp >> 32); - init_completion(&adapter->driver_cmds.timestamp_sync_cmd.done); - leapraid_fire_task( - adapter, - adapter->driver_cmds.timestamp_sync_cmd.inter_taskid); - leapraid_debug_log_info(adapter); - wait_for_completion_timeout(&adapter->driver_cmds - .timestamp_sync_cmd.done, - LEAPRAID_TIMESTAMP_SYNC_CMD_TIMEOUT * HZ); - if (!(adapter->driver_cmds.timestamp_sync_cmd.status & - LEAPRAID_CMD_DONE)) { - dev_err(&adapter->pdev->dev, - "%s: timestamp sync timeout, status=0x%x\n", - __func__, - adapter->driver_cmds.timestamp_sync_cmd.status); - leapraid_log_req_context(adapter, io_unit_ctrl_req); - issue_reset = - leapraid_check_reset( - adapter->driver_cmds.timestamp_sync_cmd.status); - } - - if (issue_reset) { - dev_info(&adapter->pdev->dev, "%s:%d: call hard_reset\n", - __func__, __LINE__); - leapraid_hard_reset_handler(adapter, FULL_RESET); - } - - adapter->driver_cmds.timestamp_sync_cmd.status = LEAPRAID_CMD_NOT_USED; - mutex_unlock(&adapter->driver_cmds.timestamp_sync_cmd.mutex); -} - static void leapraid_check_scheduled_fault_work(struct work_struct *work) { struct leapraid_adapter *adapter; @@ -2891,21 +2794,16 @@ static void leapraid_check_scheduled_fault_work(struct work_struct *work) adapter_state = leapraid_get_adapter_state(adapter); if (adapter_state != LEAPRAID_DB_OPERATIONAL) { - dev_info(&adapter->pdev->dev, "%s:%d: call hard_reset\n", - __func__, __LINE__); + dev_info(&adapter->pdev->dev, "%s:%d: call hard_reset 0x%x\n", + __func__, __LINE__, adapter_state); rc = leapraid_hard_reset_handler(adapter, FULL_RESET); - dev_warn(&adapter->pdev->dev, "%s: Hard reset %s\n", - __func__, rc == 0 ? "success" : "failed"); - adapter_state = leapraid_get_adapter_state(adapter); - if (rc && adapter_state != LEAPRAID_DB_OPERATIONAL) + if (rc && adapter_state != LEAPRAID_DB_OPERATIONAL) { + dev_err(&adapter->pdev->dev, + "%s: Hard reset failed, state=0x%x rc=%d\n", + __func__, adapter_state, rc); return; - } - - if (++adapter->timestamp_sync_cnt >= - LEAPRAID_TIMESTAMP_SYNC_INTERVAL) { - adapter->timestamp_sync_cnt = 0; - leapraid_timestamp_sync(adapter); + } } scheduled_timer: @@ -2925,7 +2823,6 @@ void leapraid_check_scheduled_fault_start(struct leapraid_adapter *adapter) if (adapter->reset_desc.fault_reset_wq) return; - adapter->timestamp_sync_cnt = 0; INIT_DELAYED_WORK(&adapter->reset_desc.fault_reset_work, leapraid_check_scheduled_fault_work); snprintf(adapter->reset_desc.fault_reset_wq_name, @@ -2968,308 +2865,6 @@ void leapraid_check_scheduled_fault_stop(struct leapraid_adapter *adapter) destroy_workqueue(wq); } -static bool leapraid_ready_for_scsi_io(struct leapraid_adapter *adapter, - u16 hdl) -{ - if (adapter->access_ctrl.pcie_recovering || - adapter->access_ctrl.shost_recovering) { - dev_err(&adapter->pdev->dev, - "%s: Failed, pcie_recovering=%d shost_recovering=%d\n", - __func__, - adapter->access_ctrl.pcie_recovering, - adapter->access_ctrl.shost_recovering); - return false; - } - - if (leapraid_check_adapter_is_op(adapter, LEAPRAID_DB_WAIT_OP_SHORT, - __func__)) - return false; - - if (hdl == LEAPRAID_INVALID_DEV_HANDLE) { - dev_err(&adapter->pdev->dev, - "%s: Device handle is invalid\n", __func__); - return false; - } - - return true; -} - -static int leapraid_dispatch_scsi_io(struct leapraid_adapter *adapter, - struct leapraid_scsi_cmd_desc *cmd_desc) -{ - struct scsi_device *sdev; - struct scsi_device *target_sdev = NULL; - struct leapraid_sdev_priv *sdev_priv; - struct scsi_cmnd *scmd; - void *dma_buffer = NULL; - dma_addr_t dma_addr; - bool issue_reset = false; - int rc; - - if (WARN_ON(!adapter->driver_cmds.internal_scmd)) - return -EINVAL; - - if (!leapraid_ready_for_scsi_io(adapter, cmd_desc->hdl)) - return -EINVAL; - - mutex_lock(&adapter->driver_cmds.driver_scsiio_cmd.mutex); - if (adapter->driver_cmds.driver_scsiio_cmd.status != - LEAPRAID_CMD_NOT_USED) { - dev_err(&adapter->pdev->dev, - "%s: scsiio cmd busy\n", __func__); - rc = -EAGAIN; - goto out_cleanup; - } - adapter->driver_cmds.driver_scsiio_cmd.status = LEAPRAID_CMD_PENDING; - - shost_for_each_device(sdev, adapter->shost) { - sdev_priv = sdev->hostdata; - - if (sdev_priv->starget_priv->hdl == cmd_desc->hdl && - sdev_priv->lun == cmd_desc->lun) { - target_sdev = sdev; - break; - } - } - - if (!target_sdev) { - dev_warn(&adapter->pdev->dev, - "%s: Device not found\n", __func__); - rc = -ENXIO; - goto out_cleanup; - } - - if (cmd_desc->data_length) { - dma_buffer = dma_alloc_coherent(&adapter->pdev->dev, - cmd_desc->data_length, - &dma_addr, GFP_ATOMIC); - if (!dma_buffer) { - rc = -ENOMEM; - goto out_cleanup; - } - if (cmd_desc->dir == DMA_TO_DEVICE) - memcpy(dma_buffer, cmd_desc->data_buffer, - cmd_desc->data_length); - } - - scmd = adapter->driver_cmds.internal_scmd; - scmd->device = target_sdev; - scmd->cmd_len = cmd_desc->cdb_length; - memcpy(scmd->cmnd, cmd_desc->cdb, cmd_desc->cdb_length); - scmd->sc_data_direction = cmd_desc->dir; - scmd->sdb.length = cmd_desc->data_length; - scmd->sdb.table.nents = 1; - scmd->sdb.table.orig_nents = 1; - sg_init_one(scmd->sdb.table.sgl, dma_buffer, cmd_desc->data_length); - init_completion(&adapter->driver_cmds.driver_scsiio_cmd.done); - if (leapraid_queuecommand(adapter->shost, scmd)) { - adapter->driver_cmds.driver_scsiio_cmd.status &= - ~LEAPRAID_CMD_PENDING; - complete(&adapter->driver_cmds.driver_scsiio_cmd.done); - dev_err(&adapter->pdev->dev, - "%s: queuecommand failed\n", __func__); - rc = -EINVAL; - goto out_cleanup; - } - - wait_for_completion_timeout(&adapter->driver_cmds - .driver_scsiio_cmd.done, - cmd_desc->time_out * HZ); - - if (!(adapter->driver_cmds.driver_scsiio_cmd.status & - LEAPRAID_CMD_DONE)) { - issue_reset = - leapraid_check_reset( - adapter->driver_cmds.driver_scsiio_cmd.status); - rc = -ENODATA; - goto reset; - } - - rc = adapter->driver_cmds.internal_scmd->result; - if (!rc && cmd_desc->dir == DMA_FROM_DEVICE) - memcpy(cmd_desc->data_buffer, dma_buffer, - cmd_desc->data_length); - -reset: - if (issue_reset) { - rc = -ENODATA; - dev_err(&adapter->pdev->dev, "fire tgt reset: hdl=0x%04x\n", - cmd_desc->hdl); - leapraid_issue_locked_tm( - adapter, cmd_desc->hdl, 0, 0, 0, - LEAPRAID_TM_TASKTYPE_TARGET_RESET, - adapter->driver_cmds.driver_scsiio_cmd.taskid, - LEAPRAID_TM_MSGFLAGS_LINK_RESET); - } -out_cleanup: - if (target_sdev) - scsi_device_put(target_sdev); - - if (dma_buffer) - dma_free_coherent(&adapter->pdev->dev, - cmd_desc->data_length, - dma_buffer, - dma_addr); - - adapter->driver_cmds.driver_scsiio_cmd.status = LEAPRAID_CMD_NOT_USED; - mutex_unlock(&adapter->driver_cmds.driver_scsiio_cmd.mutex); - return rc; -} - -static int leapraid_dispatch_logsense(struct leapraid_adapter *adapter, - u16 hdl, u32 lun) -{ - struct leapraid_scsi_cmd_desc *desc; - char *buf; - int rc; - - desc = kzalloc(sizeof(*desc), GFP_KERNEL); - if (!desc) - return -ENOMEM; - - desc->hdl = hdl; - desc->lun = lun; - desc->data_length = LEAPRAID_LOGSENSE_DATA_LENGTH; - desc->dir = DMA_FROM_DEVICE; - desc->cdb_length = LEAPRAID_LOGSENSE_CDB_LENGTH; - desc->cdb[0] = LOG_SENSE; - desc->cdb[2] = LEAPRAID_LOGSENSE_CDB_CODE; - desc->cdb[8] = desc->data_length; - desc->raid_member = 0; - desc->time_out = LEAPRAID_LOGSENSE_TIMEOUT; - - desc->data_buffer = kzalloc(desc->data_length, GFP_KERNEL); - if (!desc->data_buffer) { - kfree(desc); - return -ENOMEM; - } - - rc = leapraid_dispatch_scsi_io(adapter, desc); - buf = desc->data_buffer; - - if (!rc && buf[8] == LEAPRAID_LOGSENSE_SMART_CODE) - leapraid_smart_fault_detect(adapter, hdl); - - kfree(desc->data_buffer); - kfree(desc); - - return rc; -} - -static bool leapraid_smart_poll_check(struct leapraid_adapter *adapter, - struct leapraid_sdev_priv *sdev_priv, - u32 reset_flg) -{ - struct leapraid_sas_dev *sas_dev; - - if (!sdev_priv || !sdev_priv->starget_priv->card_port) - return false; - - sas_dev = leapraid_get_sas_dev_by_addr( - adapter, - sdev_priv->starget_priv->sas_address, - sdev_priv->starget_priv->card_port); - if (!sas_dev || !sas_dev->support_smart) - goto out_fail; - - if (reset_flg) - sas_dev->led_on = 0; - else if (sas_dev->led_on) - goto out_fail; - - if (sdev_priv->starget_priv->flg & LEAPRAID_TGT_FLG_RAID_MEMBER || - sdev_priv->starget_priv->flg & LEAPRAID_TGT_FLG_VOLUME || - sdev_priv->block) - goto out_fail; - - leapraid_sdev_put(sas_dev); - return true; - -out_fail: - if (sas_dev) - leapraid_sdev_put(sas_dev); - return false; -} - -static void leapraid_sata_smart_poll_work(struct work_struct *work) -{ - struct leapraid_adapter *adapter = - container_of(work, struct leapraid_adapter, - smart_poll_desc.smart_poll_work.work); - struct scsi_device *sdev; - struct leapraid_sdev_priv *sdev_priv; - bool reset_flg = false; - - if (leapraid_should_skip_poll_work(adapter)) - goto scheduled_timer; - - if (leapraid_check_adapter_is_op(adapter, LEAPRAID_DB_WAIT_OP_SHORT, - __func__)) - goto scheduled_timer; - - if (adapter->reset_desc.last_reset_cnt < adapter->reset_desc.reset_cnt) - reset_flg = true; - - adapter->reset_desc.last_reset_cnt = adapter->reset_desc.reset_cnt; - - shost_for_each_device(sdev, adapter->shost) { - sdev_priv = sdev->hostdata; - if (leapraid_smart_poll_check(adapter, sdev_priv, reset_flg)) - leapraid_dispatch_logsense(adapter, - sdev_priv->starget_priv->hdl, - sdev_priv->lun); - } - -scheduled_timer: - if (adapter->smart_poll_desc.smart_poll_wq) - queue_delayed_work( - adapter->smart_poll_desc.smart_poll_wq, - &adapter->smart_poll_desc.smart_poll_work, - msecs_to_jiffies(LEAPRAID_SMART_POLLING_INTERVAL)); -} - -void leapraid_smart_polling_start(struct leapraid_adapter *adapter) -{ - if (adapter->smart_poll_desc.smart_poll_wq || !smart_poll) - return; - - INIT_DELAYED_WORK(&adapter->smart_poll_desc.smart_poll_work, - leapraid_sata_smart_poll_work); - - snprintf(adapter->smart_poll_desc.smart_poll_wq_name, - sizeof(adapter->smart_poll_desc.smart_poll_wq_name), - "poll_%s%u_smart_poll", - LEAPRAID_DRIVER_NAME, - adapter->adapter_attr.id); - adapter->smart_poll_desc.smart_poll_wq = - create_singlethread_workqueue( - adapter->smart_poll_desc.smart_poll_wq_name); - if (!adapter->smart_poll_desc.smart_poll_wq) - return; - queue_delayed_work(adapter->smart_poll_desc.smart_poll_wq, - &adapter->smart_poll_desc.smart_poll_work, - msecs_to_jiffies(LEAPRAID_SMART_POLLING_INTERVAL)); -} - -void leapraid_smart_polling_stop(struct leapraid_adapter *adapter) -{ - struct workqueue_struct *wq; - struct leapraid_smart_poll_desc *desc; - - desc = &adapter->smart_poll_desc; - if (!desc->smart_poll_wq) - return; - - wq = desc->smart_poll_wq; - desc->smart_poll_wq = NULL; - - if (wq) { - if (!cancel_delayed_work_sync(&desc->smart_poll_work)) - flush_workqueue(wq); - destroy_workqueue(wq); - } -} - static void leapraid_overheat_work(struct work_struct *work) { struct leapraid_overheat_desc *desc; @@ -3304,13 +2899,11 @@ static void leapraid_overheat_work(struct work_struct *work) adapter->scan_dev_desc.scan_start = 0; adapter->scan_dev_desc.wait_scan_dev_done = 0; adapter->scan_dev_desc.driver_loading = 0; - wake_up(&adapter->access_ctrl.recovery_waitq); wake_up(&adapter->access_ctrl.shost_recover_wq); wake_up(&adapter->scan_dev_desc.wait_driver_loading); leapraid_mask_int(adapter); - leapraid_smart_polling_stop(adapter); leapraid_check_scheduled_fault_stop(adapter); leapraid_fw_log_stop(adapter); leapraid_mq_polling_pause(adapter); @@ -3393,10 +2986,10 @@ static struct leapraid_fw_evt_work *leapraid_alloc_fw_evt_work(void) { struct leapraid_fw_evt_work *fw_evt = kzalloc(sizeof(*fw_evt), GFP_ATOMIC); - if (!fw_evt) - return NULL; - kref_init(&fw_evt->refcnt); + if (fw_evt) + kref_init(&fw_evt->refcnt); + return fw_evt; } @@ -3413,10 +3006,14 @@ static void leapraid_fw_evt_add(struct leapraid_adapter *adapter, { unsigned long flags; - if (!adapter->fw_evt_s.fw_evt_thread) + spin_lock_irqsave(&adapter->fw_evt_s.fw_evt_lock, flags); + if (adapter->access_ctrl.host_removing || + adapter->access_ctrl.pcie_recovering || + !adapter->fw_evt_s.fw_evt_thread) { + spin_unlock_irqrestore(&adapter->fw_evt_s.fw_evt_lock, flags); return; + } - spin_lock_irqsave(&adapter->fw_evt_s.fw_evt_lock, flags); leapraid_fw_evt_get(fw_evt); INIT_LIST_HEAD(&fw_evt->list); list_add_tail(&fw_evt->list, &adapter->fw_evt_s.fw_evt_list); @@ -3467,7 +3064,6 @@ void leapraid_clean_active_fw_evt(struct leapraid_adapter *adapter) return; adapter->fw_evt_s.fw_evt_cleanup = 1; - wake_up(&adapter->access_ctrl.recovery_waitq); if (adapter->access_ctrl.shost_recovering && adapter->fw_evt_s.cur_evt) adapter->fw_evt_s.cur_evt->ignore = 1; @@ -3742,8 +3338,6 @@ static struct leapraid_sas_dev *leapraid_init_sas_dev( sas_dev->dev_name = le64_to_cpu(sas_dev_pg0->dev_name); sas_dev->port_connection = sas_dev_pg0->max_port_connections; sas_dev->slot = sas_dev->enc_hdl ? le16_to_cpu(sas_dev_pg0->slot) : 0; - sas_dev->support_smart = (le16_to_cpu(sas_dev_pg0->flg) & - LEAPRAID_SAS_DEV_P0_FLG_SATA_SMART); if (le16_to_cpu(sas_dev_pg0->flg) & LEAPRAID_SAS_DEV_P0_FLG_ENC_LEVEL_VALID) { sas_dev->enc_level = sas_dev_pg0->enc_level; @@ -3991,11 +3585,11 @@ static int leapraid_refresh_card_phy(struct leapraid_adapter *adapter, return 0; if (le32_to_cpu(phy_pg0.phy_info) & - LEAPRAID_SAS_PHYINFO_VPHY && - !leapraid_alloc_vphy(adapter, port_id, i)) - return -EINVAL; - - card->card_phy[i].vphy = 1; + LEAPRAID_SAS_PHYINFO_VPHY) { + if (!leapraid_alloc_vphy(adapter, port_id, i)) + return -ENOMEM; + card->card_phy[i].vphy = 1; + } } card->card_phy[i].hdl = card->hdl; @@ -4382,7 +3976,7 @@ void leapraid_exp_rm(struct leapraid_adapter *adapter, u64 sas_addr, leapraid_exp_node_rm(adapter, topo_node_exp); } -static int leapraid_internal_sas_topo_chg_evt( +static void leapraid_internal_sas_topo_chg_evt( struct leapraid_adapter *adapter, struct leapraid_card_port *card_port, struct leapraid_topo_node *topo_node_exp, @@ -4399,11 +3993,11 @@ static int leapraid_internal_sas_topo_chg_evt( evt_data = fw_evt->evt_data; for (i = 0; i < evt_data->entry_num; i++) { if (fw_evt->ignore) - return 0; + return; if (adapter->access_ctrl.host_removing || adapter->access_ctrl.pcie_recovering) - return 0; + return; phy_number = evt_data->start_phy_num + i; if (phy_number >= max_phys) @@ -4441,12 +4035,10 @@ static int leapraid_internal_sas_topo_chg_evt( if (evt_data->exp_status == LEAPRAID_EVT_SAS_TOPO_ES_NOT_RESPONDING && topo_node_exp) leapraid_exp_rm(adapter, sas_addr, card_port); - - return 0; } -static int leapraid_sas_topo_chg_evt(struct leapraid_adapter *adapter, - struct leapraid_fw_evt_work *fw_evt) +static void leapraid_sas_topo_chg_evt(struct leapraid_adapter *adapter, + struct leapraid_fw_evt_work *fw_evt) { struct leapraid_topo_node *topo_node_exp; struct leapraid_card_port *card_port; @@ -4459,13 +4051,13 @@ static int leapraid_sas_topo_chg_evt(struct leapraid_adapter *adapter, if (adapter->access_ctrl.shost_recovering || adapter->access_ctrl.host_removing || adapter->access_ctrl.pcie_recovering) - return 0; + return; evt_data = fw_evt->evt_data; leapraid_sas_host_add(adapter, adapter->dev_topo.card.phys_num > 0); if (fw_evt->ignore) - return 0; + return; phdl = le16_to_cpu(evt_data->exp_dev_hdl); card_port = leapraid_get_port_by_id(adapter, @@ -4473,7 +4065,7 @@ static int leapraid_sas_topo_chg_evt(struct leapraid_adapter *adapter, false); if (evt_data->exp_status == LEAPRAID_EVT_SAS_TOPO_ES_ADDED && leapraid_exp_add(adapter, phdl) != 0) - return 0; + return; spin_lock_irqsave(&adapter->dev_topo.topo_node_lock, flags); topo_node_exp = leapraid_exp_find_by_hdl(adapter, phdl); @@ -4487,13 +4079,13 @@ static int leapraid_sas_topo_chg_evt(struct leapraid_adapter *adapter, } else { spin_unlock_irqrestore(&adapter->dev_topo.topo_node_lock, flags); - return 0; + return; } spin_unlock_irqrestore(&adapter->dev_topo.topo_node_lock, flags); - return leapraid_internal_sas_topo_chg_evt(adapter, card_port, - topo_node_exp, fw_evt, - sas_addr, max_phys); + leapraid_internal_sas_topo_chg_evt(adapter, card_port, + topo_node_exp, fw_evt, + sas_addr, max_phys); } static void leapraid_reprobe_lun(struct scsi_device *sdev, void *no_uld_attach) @@ -4603,7 +4195,6 @@ static void leapraid_sas_pd_hide( } spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags); if (starget) { - dev_info(&adapter->pdev->dev, "hide sas_dev, hdl=0x%x\n", hdl); starget_for_each_device(starget, (void *)LEAPRAID_NO_ULD_ATTACH_FLAG, leapraid_reprobe_lun); @@ -4623,7 +4214,6 @@ static void leapraid_sas_pd_expose( u16 hdl; hdl = le16_to_cpu(evt_data->phys_disk_dev_hdl); - if (!hdl || hdl > adapter->adapter_attr.features.max_dev_handle) { dev_warn(&adapter->pdev->dev, "%s: Invalid device handle\n", __func__); @@ -4652,10 +4242,8 @@ static void leapraid_sas_pd_expose( spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags); if (starget) { - dev_info(&adapter->pdev->dev, - "expose sas_dev, hdl=0x%x\n", hdl); starget_for_each_device(starget, - LEAPRAID_ULD_ATTACH_FLAG, + NULL, leapraid_reprobe_lun); } @@ -4986,7 +4574,7 @@ static void leapraid_remove_unresp_sas_end_dev( leapraid_sdev_put(sas_dev); } - dev_info(&adapter->pdev->dev, + dev_warn(&adapter->pdev->dev, "Unresponsive SAS end devices removed\n"); } @@ -5011,7 +4599,7 @@ static void leapraid_remove_unresp_raid_volumes( leapraid_sas_volume_delete_by_ptr(adapter, raid_volume); } - dev_info(&adapter->pdev->dev, + dev_warn(&adapter->pdev->dev, "Unresponsive RAID volumes removed\n"); } @@ -5035,7 +4623,7 @@ static void leapraid_remove_unresp_sas_exp(struct leapraid_adapter *adapter) &head, list) leapraid_exp_node_rm(adapter, topo_node_exp); - dev_info(&adapter->pdev->dev, + dev_warn(&adapter->pdev->dev, "Unresponsive SAS expanders removed\n"); } @@ -5153,8 +4741,6 @@ static void leapraid_scan_exp_after_reset(struct leapraid_adapter *adapter) u16 hdl; u8 port_id; - dev_info(&adapter->pdev->dev, "Begin scanning expanders\n"); - cfgp1.form = LEAPRAID_SAS_CFG_PGAD_GET_NEXT_LOOP; for (hdl = 0xFFFF, cfgp2.handle = hdl; !leapraid_op_config_page(adapter, &exp_p0, cfgp1, cfgp2, @@ -5185,8 +4771,6 @@ static void leapraid_scan_exp_after_reset(struct leapraid_adapter *adapter) exp_p0.sas_address)); } } - - dev_info(&adapter->pdev->dev, "Expanders scan complete\n"); } static void leapraid_scan_phy_disks_after_reset( @@ -5203,8 +4787,6 @@ static void leapraid_scan_phy_disks_after_reset( u16 hdl, parent_hdl; u64 sas_addr; - dev_info(&adapter->pdev->dev, "Begin scanning phys disk\n"); - cfgp1.form = LEAPRAID_SAS_CFG_PGAD_GET_NEXT_LOOP; for (phys_disk_num = 0xFF, cfgp2.form_specific = phys_disk_num; !leapraid_op_config_page(adapter, &raidpd_p0, @@ -5253,8 +4835,6 @@ static void leapraid_scan_phy_disks_after_reset( } } } - - dev_info(&adapter->pdev->dev, "PHYs disk scan complete\n"); } static void leapraid_scan_vol_after_reset(struct leapraid_adapter *adapter) @@ -5279,7 +4859,6 @@ static void leapraid_scan_vol_after_reset(struct leapraid_adapter *adapter) return; } - dev_info(&adapter->pdev->dev, "Begin scanning volumes\n"); cfgp1.form = LEAPRAID_SAS_CFG_PGAD_GET_NEXT_LOOP; for (hdl = 0xFFFF, cfgp2.handle = hdl; !leapraid_op_config_page(adapter, vol_p1, cfgp1, @@ -5316,8 +4895,6 @@ static void leapraid_scan_vol_after_reset(struct leapraid_adapter *adapter) kfree(vol_p0); kfree(vol_p1); - - dev_info(&adapter->pdev->dev, "Volumes scan complete\n"); } static void leapraid_scan_sas_dev_after_reset(struct leapraid_adapter *adapter) @@ -5330,9 +4907,6 @@ static void leapraid_scan_sas_dev_after_reset(struct leapraid_adapter *adapter) u64 sas_address; u8 port_id; - dev_info(&adapter->pdev->dev, - "Begin scanning SAS end devices\n"); - cfgp1.form = LEAPRAID_SAS_CFG_PGAD_GET_NEXT_LOOP; for (hdl = 0xFFFF, cfgp2.handle = hdl; !leapraid_op_config_page(adapter, &sas_dev_p0, cfgp1, cfgp2, @@ -5382,14 +4956,10 @@ static void leapraid_scan_sas_dev_after_reset(struct leapraid_adapter *adapter) sas_dev_p0.sas_address)); } } - - dev_info(&adapter->pdev->dev, "SAS end devices scan complete\n"); } static void leapraid_scan_all_dev_after_reset(struct leapraid_adapter *adapter) { - dev_info(&adapter->pdev->dev, "Begin scanning devices\n"); - leapraid_sas_host_add(adapter, adapter->dev_topo.card.phys_num > 0); leapraid_scan_exp_after_reset(adapter); if (adapter->adapter_attr.raid_support) { @@ -5397,8 +4967,6 @@ static void leapraid_scan_all_dev_after_reset(struct leapraid_adapter *adapter) leapraid_scan_vol_after_reset(adapter); } leapraid_scan_sas_dev_after_reset(adapter); - - dev_info(&adapter->pdev->dev, "Devices scan complete\n"); } static void leapraid_hardreset_async_logic(struct leapraid_adapter *adapter) @@ -5426,6 +4994,7 @@ static int leapraid_send_enc_cmd(struct leapraid_adapter *adapter, void *req; bool reset_flg = false; int rc; + u16 smid; mutex_lock(&adapter->driver_cmds.enc_cmd.mutex); rc = leapraid_check_adapter_is_op(adapter, LEAPRAID_DB_WAIT_OP_SHORT, @@ -5434,21 +5003,19 @@ static int leapraid_send_enc_cmd(struct leapraid_adapter *adapter, goto unlock; adapter->driver_cmds.enc_cmd.status = LEAPRAID_CMD_PENDING; - req = leapraid_get_task_desc( - adapter, - adapter->driver_cmds.enc_cmd.inter_taskid); + smid = adapter->driver_cmds.enc_cmd.inter_taskid; + req = leapraid_get_task_desc(adapter, smid); memset(req, 0, LEAPRAID_REQUEST_SIZE); memcpy(req, sep_req, sizeof(struct leapraid_sep_req)); init_completion(&adapter->driver_cmds.enc_cmd.done); - leapraid_fire_task(adapter, - adapter->driver_cmds.enc_cmd.inter_taskid); + leapraid_fire_task(adapter, smid); wait_for_completion_timeout(&adapter->driver_cmds.enc_cmd.done, LEAPRAID_ENC_CMD_TIMEOUT * HZ); if (!(adapter->driver_cmds.enc_cmd.status & LEAPRAID_CMD_DONE)) { dev_err(&adapter->pdev->dev, "%s: SEP command timeout, status=0x%x\n", __func__, adapter->driver_cmds.enc_cmd.status); - leapraid_log_req_context(adapter, sep_req); + leapraid_log_req_context(adapter, smid, sep_req); reset_flg = leapraid_check_reset( adapter->driver_cmds.enc_cmd.status); @@ -5512,10 +5079,10 @@ static int leapraid_wait_adapter_recovery(struct leapraid_adapter *adapter) { unsigned long flags; - while (scsi_host_in_recovery(adapter->shost) || - adapter->access_ctrl.shost_recovering) { - if (adapter->access_ctrl.host_removing || - adapter->fw_evt_s.fw_evt_cleanup) { + while (leapraid_shost_in_recovery(adapter->shost) || + READ_ONCE(adapter->access_ctrl.shost_recovering)) { + if (READ_ONCE(adapter->access_ctrl.host_removing) || + READ_ONCE(adapter->fw_evt_s.fw_evt_cleanup)) { spin_lock_irqsave( &adapter->reset_desc.adapter_reset_lock, flags); @@ -5535,12 +5102,13 @@ static int leapraid_wait_adapter_recovery(struct leapraid_adapter *adapter) return -EFAULT; } - wait_event_timeout(adapter->access_ctrl.recovery_waitq, - !adapter->access_ctrl.shost_recovering || - adapter->access_ctrl.host_removing || - adapter->fw_evt_s.fw_evt_cleanup, - msecs_to_jiffies(1000)); + wait_event_timeout( + adapter->access_ctrl.recovery_waitq, + (!leapraid_shost_in_recovery(adapter->shost) && + !READ_ONCE(adapter->access_ctrl.shost_recovering)), + msecs_to_jiffies(1000)); } + return 0; } @@ -5625,7 +5193,6 @@ static void leapraid_sas_dev_stat_chg_evt( leapraid_get_port_by_id(adapter, event_data->physical_port, false)); - if (!sas_dev || !sas_dev->starget) goto out_unlock; @@ -5755,6 +5322,80 @@ static void leapraid_check_topo_del_evts( leapraid_topo_del_evts_process_exp_status(adapter, evt_data); } +static bool leapraid_async_evt_validate( + struct leapraid_adapter *adapter, + struct leapraid_evt_notify_rep *event_notify_rep) +{ + size_t msg_len; + size_t evt_sz; + size_t evt_avail; + u16 evt; + + msg_len = event_notify_rep->msg_len * sizeof(u32); + if (msg_len > LEAPRAID_REPLY_SIZE || + msg_len < offsetof(struct leapraid_evt_notify_rep, evt_data)) { + dev_warn(&adapter->pdev->dev, + "%s: Invalid async event msg_len=%zu\n", + __func__, msg_len); + return false; + } + + evt_sz = le16_to_cpu(event_notify_rep->evt_data_len) * sizeof(u32); + evt_avail = msg_len - + offsetof(struct leapraid_evt_notify_rep, evt_data); + if (evt_sz > evt_avail) { + dev_warn(&adapter->pdev->dev, + "%s: Invalid async event evt_data_len=%zu\n", + __func__, evt_sz); + return false; + } + + evt = le16_to_cpu(event_notify_rep->evt); + switch (evt) { + case LEAPRAID_EVT_SAS_DEV_STATUS_CHANGE: + if (evt_sz < + sizeof(struct leapraid_evt_data_sas_dev_status_change)) + goto invalid_evt_sz; + break; + case LEAPRAID_EVT_IR_CHANGE: + if (evt_sz < sizeof(struct leapraid_evt_data_ir_change)) + goto invalid_evt_sz; + break; + case LEAPRAID_EVT_SAS_TOPO_CHANGE_LIST: + { + struct leapraid_evt_data_sas_topo_change_list *evt_data = + (void *)event_notify_rep->evt_data; + size_t hdr_sz; + + hdr_sz = + offsetof(struct leapraid_evt_data_sas_topo_change_list, + phy); + if (evt_sz < hdr_sz) + goto invalid_evt_sz; + + if (evt_data->entry_num > + (evt_sz - hdr_sz) / sizeof(evt_data->phy[0])) + goto invalid_evt_sz; + break; + } + case LEAPRAID_EVT_SAS_ENCL_DEV_STATUS_CHANGE: + if (evt_sz < + sizeof(struct leapraid_evt_data_sas_enc_dev_status_change)) + goto invalid_evt_sz; + break; + default: + break; + } + + return true; + +invalid_evt_sz: + dev_warn(&adapter->pdev->dev, + "%s: Invalid async event size=%zu for evt=0x%x\n", + __func__, evt_sz, evt); + return false; +} + static bool leapraid_async_process_evt( struct leapraid_adapter *adapter, struct leapraid_evt_notify_rep *event_notify_rep) @@ -5762,6 +5403,10 @@ static bool leapraid_async_process_evt( u16 evt = le16_to_cpu(event_notify_rep->evt); bool exit_flag = false; + if (adapter->access_ctrl.host_removing || + adapter->access_ctrl.pcie_recovering) + return true; + switch (evt) { case LEAPRAID_EVT_SAS_DEV_STATUS_CHANGE: leapraid_sas_dev_stat_chg_evt( @@ -5824,13 +5469,17 @@ static void leapraid_async_evt_cb(struct leapraid_adapter *adapter, { struct leapraid_evt_notify_rep *evt_notify_rep; - if (adapter->access_ctrl.pcie_recovering) + if (adapter->access_ctrl.host_removing || + adapter->access_ctrl.pcie_recovering) return; evt_notify_rep = leapraid_get_reply_vaddr(adapter, rep_paddr); if (unlikely(!evt_notify_rep)) return; + if (!leapraid_async_evt_validate(adapter, evt_notify_rep)) + return; + if (leapraid_async_process_evt(adapter, evt_notify_rep)) return; @@ -5895,9 +5544,9 @@ static void leapraid_scan_dev_complete(struct leapraid_adapter *adapter) leapraid_fw_evt_put(fw_evt); } -static u8 leapraid_handle_scan_cb(struct leapraid_adapter *adapter, - struct leapraid_driver_cmd *cmd, - struct leapraid_rep *rep) +static void leapraid_handle_scan_cb(struct leapraid_adapter *adapter, + struct leapraid_driver_cmd *cmd, + struct leapraid_rep *rep) { u16 status; @@ -5905,21 +5554,18 @@ static u8 leapraid_handle_scan_cb(struct leapraid_adapter *adapter, status = le16_to_cpu(rep->adapter_status) & LEAPRAID_ADAPTER_STATUS_MASK; - if (status != LEAPRAID_ADAPTER_STATUS_SUCCESS) adapter->scan_dev_desc.scan_dev_failed = 1; if (!cmd->async_scan_dev) { complete(&cmd->done); - return 1; + return; } if (status == LEAPRAID_ADAPTER_STATUS_SUCCESS) leapraid_scan_dev_complete(adapter); else adapter->scan_dev_desc.scan_start_failed = status; - - return 1; } static void leapraid_handle_ctl_cb(struct leapraid_adapter *adapter, @@ -5933,7 +5579,6 @@ static void leapraid_handle_ctl_cb(struct leapraid_adapter *adapter, return; scsiio_reply = (struct leapraid_scsiio_rep *)rep; - if (!(scsiio_reply->scsi_state & LEAPRAID_SCSI_STATE_AUTOSENSE_VALID)) return; @@ -5976,10 +5621,11 @@ static bool leapraid_driver_cmds_done(struct leapraid_adapter *adapter, memcpy(&_sp_cmd->reply, leap_mpi_rep, reply_len); _sp_cmd->status |= LEAPRAID_CMD_REPLY_VALID; - if (_sp_cmd->cb_idx == LEAPRAID_SCAN_DEV_CB_IDX) - return leapraid_handle_scan_cb(adapter, - _sp_cmd, - leap_mpi_rep); + if (_sp_cmd->cb_idx == LEAPRAID_SCAN_DEV_CB_IDX) { + leapraid_handle_scan_cb(adapter, _sp_cmd, + leap_mpi_rep); + return true; + } if (_sp_cmd->cb_idx == LEAPRAID_CTL_CB_IDX) leapraid_handle_ctl_cb(adapter, leap_mpi_rep, taskid); @@ -5994,8 +5640,9 @@ static bool leapraid_driver_cmds_done(struct leapraid_adapter *adapter, static void leapraid_complete_task(struct leapraid_adapter *adapter, u16 taskid, u8 msix_idx, u32 rep) { - if (taskid <= adapter->shost->can_queue || - taskid == adapter->driver_cmds.driver_scsiio_cmd.taskid) { + bool scsiio_task = taskid <= adapter->shost->can_queue; + + if (scsiio_task) { if (leapraid_scsiio_done(adapter, taskid, msix_idx, rep)) leapraid_free_taskid(adapter, taskid); return; @@ -6175,6 +5822,22 @@ void leapraid_sync_irqs(struct leapraid_adapter *adapter, bool poll) } } +static void leapraid_sync_irqs_for_cleanup(struct leapraid_adapter *adapter) +{ + struct leapraid_notification_desc *desc = &adapter->notification_desc; + struct leapraid_int_rq *int_rq; + unsigned int i; + + if (!adapter->mask_int && leapraid_pci_active(adapter)) + leapraid_mask_int(adapter); + + for (i = 0; i < desc->int_rqs_allocated; i++) { + int_rq = &desc->int_rqs[i]; + synchronize_irq(pci_irq_vector(adapter->pdev, + int_rq->rq.msix_idx)); + } +} + void leapraid_mq_polling_pause(struct leapraid_adapter *adapter) { struct leapraid_notification_desc *desc; @@ -6245,7 +5908,6 @@ static int leapraid_host_diag_reset(struct leapraid_adapter *adapter) { u32 host_diag; - dev_info(&adapter->pdev->dev, "Entering host diag reset!\n"); pci_cfg_access_lock(adapter->pdev); mutex_lock(&adapter->reset_desc.host_diag_mutex); @@ -6269,14 +5931,13 @@ static int leapraid_host_diag_reset(struct leapraid_adapter *adapter) goto out_failed; pci_cfg_access_unlock(adapter->pdev); - dev_info(&adapter->pdev->dev, "Host diag success!\n"); return 0; out_cleanup: mutex_unlock(&adapter->reset_desc.host_diag_mutex); out_failed: pci_cfg_access_unlock(adapter->pdev); - dev_info(&adapter->pdev->dev, "Host diag failed!\n"); + dev_err(&adapter->pdev->dev, "Host diag failed\n"); return -EFAULT; } @@ -6791,11 +6452,8 @@ static void leapraid_search_resp_sas_dev(struct leapraid_adapter *adapter) struct leapraid_sas_dev_p0 sas_dev_p0; u32 device_info; - dev_info(&adapter->pdev->dev, - "Begin searching for SAS end devices\n"); - if (list_empty(&adapter->dev_topo.sas_dev_list)) - goto exit_search; + return; cfgp1.form = LEAPRAID_SAS_CFG_PGAD_GET_NEXT_LOOP; for (cfgp2.handle = 0xFFFF; @@ -6808,9 +6466,6 @@ static void leapraid_search_resp_sas_dev(struct leapraid_adapter *adapter) leapraid_mark_resp_sas_dev(adapter, &sas_dev_p0); } -exit_search: - dev_info(&adapter->pdev->dev, - "SAS end devices searching complete\n"); } static void leapraid_mark_resp_raid_volume(struct leapraid_adapter *adapter, @@ -6879,14 +6534,11 @@ static void leapraid_search_resp_raid_volume(struct leapraid_adapter *adapter) if (!adapter->adapter_attr.raid_support) return; - dev_info(&adapter->pdev->dev, - "Begin searching for RAID volumes\n"); - spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags); is_empty = list_empty(&adapter->dev_topo.raid_volume_list); spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags); if (is_empty) - goto exit_search; + return; cfgp1.form = LEAPRAID_SAS_CFG_PGAD_GET_NEXT_LOOP; for (hdl = 0xFFFF, cfgp2.handle = hdl; @@ -6924,9 +6576,6 @@ static void leapraid_search_resp_raid_volume(struct leapraid_adapter *adapter) else set_bit(hdl, adapter->dev_topo.pd_hdls); } -exit_search: - dev_info(&adapter->pdev->dev, - "RAID volumes searching complete\n"); } static void leapraid_mark_resp_exp(struct leapraid_adapter *adapter, @@ -6987,10 +6636,8 @@ static void leapraid_search_resp_exp(struct leapraid_adapter *adapter) u16 hdl; u8 port; - dev_dbg(&adapter->pdev->dev, - "Begin searching for expanders\n"); if (list_empty(&adapter->dev_topo.exp_list)) - goto exit_search; + return; cfgp1.form = LEAPRAID_SAS_CFG_PGAD_GET_NEXT_LOOP; for (hdl = 0xFFFF, cfgp2.handle = hdl; @@ -7008,9 +6655,6 @@ static void leapraid_search_resp_exp(struct leapraid_adapter *adapter) LEAPRAID_DISABLE_MP_PORT_ID); leapraid_mark_resp_exp(adapter, &exp_p0); } -exit_search: - dev_dbg(&adapter->pdev->dev, - "Expander searching complete\n"); } void leapraid_wait_cmds_done(struct leapraid_adapter *adapter) @@ -7057,6 +6701,15 @@ int leapraid_hard_reset_handler(struct leapraid_adapter *adapter, mutex_lock(&adapter->reset_desc.adapter_reset_mutex); + if (adapter->access_ctrl.shost_recover_async) { + rc = adapter->reset_desc.adapter_reset_results; + dev_info(&adapter->pdev->dev, + "Skip nested hard reset, async evt running, rc=%d\n", + rc); + mutex_unlock(&adapter->reset_desc.adapter_reset_mutex); + return rc; + } + if (!leapraid_pci_active(adapter)) { if (leapraid_pci_removed(adapter)) { dev_info(&adapter->pdev->dev, @@ -7099,7 +6752,6 @@ int leapraid_hard_reset_handler(struct leapraid_adapter *adapter, dev_err(&adapter->pdev->dev, "Previous device scan failed or driver loading\n"); adapter->access_ctrl.host_removing = 1; - wake_up(&adapter->access_ctrl.recovery_waitq); rc = -EFAULT; goto out_cleanup; } @@ -7120,8 +6772,8 @@ int leapraid_hard_reset_handler(struct leapraid_adapter *adapter, leapraid_hardreset_barrier(adapter); } out_cleanup: - dev_info(&adapter->pdev->dev, "Hard reset %s\n", - rc == 0 ? "SUCCESS" : "FAILED"); + if (rc) + dev_err(&adapter->pdev->dev, "Hard reset failed\n"); spin_lock_irqsave(&adapter->reset_desc.adapter_reset_lock, flags); adapter->reset_desc.adapter_reset_results = rc; @@ -7253,9 +6905,17 @@ static int leapraid_get_adapter_features(struct leapraid_adapter *adapter) fw_major, fw_minor, fw_build, fw_release, adapter->adapter_attr.features.fw_version); - if (fw_major < 2) { - dev_err(&adapter->pdev->dev, - "Unsupported firmware major version, requires >= 2\n"); + adapter->adapter_attr.features.msg_ver = + le16_to_cpu(leap_mpi_rep.msg_ver); + adapter->adapter_attr.features.product_id = + le16_to_cpu(leap_mpi_rep.product_id); + dev_info(&adapter->pdev->dev, + "message version: 0x%x, product id 0x%x\n", + adapter->adapter_attr.features.msg_ver, + adapter->adapter_attr.features.product_id); + + if (adapter->adapter_attr.features.msg_ver < 0x1000) { + dev_err(&adapter->pdev->dev, "Device not supported\n"); return -EFAULT; } adapter->shost->max_id = LEAPRAID_INVALID_INITIAL_VALUE; @@ -7340,13 +7000,16 @@ static void leapraid_cpus_on_irq(struct leapraid_adapter *adapter) index++) { int_rq = &adapter->notification_desc.int_rqs[index]; - if (cpu >= nr_cpus) + if (cpu >= adapter->notification_desc.msix_cpu_map_sz) break; this_group = base_group + (index < (nr_cpus % total_msix) ? 1 : 0); for (i = 0 ; i < this_group ; i++) { + if (cpu >= adapter->notification_desc.msix_cpu_map_sz) + break; + adapter->notification_desc.msix_cpu_map[cpu] = int_rq->rq.msix_idx; cpu = cpumask_next(cpu, cpu_online_mask); @@ -7358,8 +7021,8 @@ static void leapraid_map_msix_to_cpu(struct leapraid_adapter *adapter) { struct leapraid_int_rq *int_rq; const cpumask_t *affinity_mask; + int cpu; u32 i; - u16 cpu; if (!adapter->adapter_attr.rq_cnt) return; @@ -7377,16 +7040,29 @@ static void leapraid_map_msix_to_cpu(struct leapraid_adapter *adapter) for_each_cpu_and(cpu, affinity_mask, cpu_online_mask) { if (cpu >= adapter->notification_desc.msix_cpu_map_sz) - break; + continue; adapter->notification_desc.msix_cpu_map[cpu] = int_rq->rq.msix_idx; } } + return; out_apply_irq_affinity: leapraid_cpus_on_irq(adapter); } +static int leapraid_alloc_msix_cpu_map(struct leapraid_adapter *adapter) +{ + adapter->notification_desc.msix_cpu_map_sz = nr_cpu_ids; + adapter->notification_desc.msix_cpu_map = + kzalloc(adapter->notification_desc.msix_cpu_map_sz, + GFP_KERNEL); + if (!adapter->notification_desc.msix_cpu_map) + return -ENOMEM; + + return 0; +} + static void leapraid_configure_reply_queue_affinity( struct leapraid_adapter *adapter) { @@ -7436,16 +7112,16 @@ static void leapraid_free_irq(struct leapraid_adapter *adapter) static int leapraid_setup_irqs(struct leapraid_adapter *adapter) { + int irq_mode = adapter->notification_desc.irq_mode; unsigned int i; int rc = 0; - if (interrupt_mode == LEAPRAID_INTERRUPT_MODE_MSIX) { + if (irq_mode == LEAPRAID_INTERRUPT_MODE_MSIX) { rc = pci_alloc_irq_vectors_affinity( adapter->pdev, adapter->notification_desc.iopoll_qdex, adapter->notification_desc.iopoll_qdex, PCI_IRQ_MSIX | PCI_IRQ_AFFINITY, NULL); - if (rc < 0) { dev_err(&adapter->pdev->dev, "%d MSI/MSIX vectors allocated failed!\n", @@ -7454,20 +7130,18 @@ static int leapraid_setup_irqs(struct leapraid_adapter *adapter) } adapter->notification_desc.irq_vectors_allocated = 1; - adapter->notification_desc.irq_mode = - LEAPRAID_INTERRUPT_MODE_MSIX; } for (i = 0; i < adapter->notification_desc.iopoll_qdex; i++) { adapter->notification_desc.int_rqs[i].rq.adapter = adapter; adapter->notification_desc.int_rqs[i].rq.msix_idx = i; atomic_set(&adapter->notification_desc.int_rqs[i].rq.busy, 0); - if (interrupt_mode == LEAPRAID_INTERRUPT_MODE_MSIX) + if (irq_mode == LEAPRAID_INTERRUPT_MODE_MSIX) snprintf(adapter->notification_desc.int_rqs[i].rq.name, LEAPRAID_NAME_LENGTH, "%s%u-MSIx%u", LEAPRAID_DRIVER_NAME, adapter->adapter_attr.id, i); - else if (interrupt_mode == LEAPRAID_INTERRUPT_MODE_MSI) + else if (irq_mode == LEAPRAID_INTERRUPT_MODE_MSI) snprintf(adapter->notification_desc.int_rqs[i].rq.name, LEAPRAID_NAME_LENGTH, "%s%u-MSI%u", LEAPRAID_DRIVER_NAME, @@ -7478,7 +7152,6 @@ static int leapraid_setup_irqs(struct leapraid_adapter *adapter) IRQF_SHARED, adapter->notification_desc.int_rqs[i].rq.name, &adapter->notification_desc.int_rqs[i].rq); - if (rc) { dev_err(&adapter->pdev->dev, "MSI/MSIx: request_irq %s failed!\n", @@ -7538,12 +7211,9 @@ static int leapraid_set_legacy_int(struct leapraid_adapter *adapter) { int rc; - adapter->notification_desc.msix_cpu_map_sz = num_online_cpus(); - adapter->notification_desc.msix_cpu_map = - kzalloc(adapter->notification_desc.msix_cpu_map_sz, - GFP_KERNEL); - if (!adapter->notification_desc.msix_cpu_map) - return -ENOMEM; + rc = leapraid_alloc_msix_cpu_map(adapter); + if (rc) + return rc; adapter->adapter_attr.rq_cnt = 1; adapter->notification_desc.iopoll_qdex = @@ -7560,9 +7230,7 @@ static int leapraid_set_legacy_int(struct leapraid_adapter *adapter) if (!adapter->notification_desc.int_rqs) return -ENOMEM; - rc = leapraid_setup_legacy_int(adapter); - - return rc; + return leapraid_setup_legacy_int(adapter); } static int leapraid_set_msix(struct leapraid_adapter *adapter) @@ -7571,14 +7239,11 @@ static int leapraid_set_msix(struct leapraid_adapter *adapter) unsigned int i; int rc, msix_cnt; - if (msix_disable == 1) - goto apply_legacy_int; - msix_cnt = pci_msix_vec_count(adapter->pdev); if (msix_cnt <= 0 || adapter->adapter_attr.features.max_msix_vectors == 0) { dev_info(&adapter->pdev->dev, "MSIX unsupported!\n"); - goto apply_legacy_int; + return -EOPNOTSUPP; } msix_cnt = min_t(int, msix_cnt, @@ -7648,31 +7313,20 @@ static int leapraid_set_msix(struct leapraid_adapter *adapter) 0); } - adapter->notification_desc.msix_cpu_map_sz = - num_online_cpus(); - adapter->notification_desc.msix_cpu_map = - kzalloc(adapter->notification_desc.msix_cpu_map_sz, - GFP_KERNEL); - if (!adapter->notification_desc.msix_cpu_map) - return -ENOMEM; - - memset(adapter->notification_desc.msix_cpu_map, 0, - adapter->notification_desc.msix_cpu_map_sz); + rc = leapraid_alloc_msix_cpu_map(adapter); + if (rc) + return rc; + adapter->notification_desc.irq_mode = LEAPRAID_INTERRUPT_MODE_MSIX; adapter->notification_desc.msix_enable = 1; rc = leapraid_setup_irqs(adapter); if (rc) { leapraid_free_irq(adapter); adapter->notification_desc.msix_enable = 0; - goto apply_legacy_int; + return rc; } return 0; - -apply_legacy_int: - rc = leapraid_set_legacy_int(adapter); - - return rc; } static int leapraid_set_msi(struct leapraid_adapter *adapter) @@ -7681,14 +7335,11 @@ static int leapraid_set_msi(struct leapraid_adapter *adapter) unsigned int i; int rc, msi_cnt; - if (msix_disable == 1) - goto apply_legacy_int; - msi_cnt = pci_msi_vec_count(adapter->pdev); if (msi_cnt <= 0 || adapter->adapter_attr.features.max_msix_vectors == 0) { dev_info(&adapter->pdev->dev, "MSI unsupported!\n"); - goto apply_legacy_int; + return -EOPNOTSUPP; } msi_cnt = min_t(int, msi_cnt, @@ -7738,10 +7389,9 @@ static int leapraid_set_msi(struct leapraid_adapter *adapter) "%d MSI vectors allocated failed!\n", adapter->notification_desc.iopoll_qdex); leapraid_free_irq(adapter); - goto apply_legacy_int; + return rc; } adapter->notification_desc.irq_vectors_allocated = 1; - adapter->notification_desc.irq_mode = LEAPRAID_INTERRUPT_MODE_MSI; if (rc != adapter->notification_desc.iopoll_qdex) { adapter->notification_desc.iopoll_qdex = rc; adapter->adapter_attr.rq_cnt = @@ -7781,51 +7431,46 @@ static int leapraid_set_msi(struct leapraid_adapter *adapter) 0); } - adapter->notification_desc.msix_cpu_map_sz = num_online_cpus(); - adapter->notification_desc.msix_cpu_map = - kzalloc(adapter->notification_desc.msix_cpu_map_sz, - GFP_KERNEL); - if (!adapter->notification_desc.msix_cpu_map) - return -ENOMEM; - memset(adapter->notification_desc.msix_cpu_map, 0, - adapter->notification_desc.msix_cpu_map_sz); + rc = leapraid_alloc_msix_cpu_map(adapter); + if (rc) + return rc; + adapter->notification_desc.irq_mode = LEAPRAID_INTERRUPT_MODE_MSI; adapter->notification_desc.msix_enable = 1; rc = leapraid_setup_irqs(adapter); if (rc) { leapraid_free_irq(adapter); adapter->notification_desc.msix_enable = 0; - goto apply_legacy_int; + return rc; } return 0; - -apply_legacy_int: - rc = leapraid_set_legacy_int(adapter); - - return rc; } -static int leapraid_set_notification(struct leapraid_adapter *adapter) +static int leapraid_set_notification_auto(struct leapraid_adapter *adapter) { - int rc = 0; + int rc; - if (interrupt_mode == LEAPRAID_INTERRUPT_MODE_MSIX) { - rc = leapraid_set_msix(adapter); - if (rc) - dev_err(&adapter->pdev->dev, - "%s: Enable MSI-X irq failed!\n", __func__); - } else if (interrupt_mode == LEAPRAID_INTERRUPT_MODE_MSI) { - rc = leapraid_set_msi(adapter); - if (rc) - dev_err(&adapter->pdev->dev, - "%s: Enable MSI irq failed!\n", __func__); - } else if (interrupt_mode == LEAPRAID_INTERRUPT_MODE_LEGACY) { - rc = leapraid_set_legacy_int(adapter); - if (rc) - dev_err(&adapter->pdev->dev, - "%s: Enable legacy irq failed!\n", __func__); - } + rc = leapraid_set_msix(adapter); + if (!rc) + return 0; + + leapraid_free_irq(adapter); + dev_info(&adapter->pdev->dev, + "MSI-X setup failed (%d), trying MSI\n", rc); + + rc = leapraid_set_msi(adapter); + if (!rc) + return 0; + + leapraid_free_irq(adapter); + dev_info(&adapter->pdev->dev, + "MSI setup failed (%d), back to legacy INTx\n", rc); + + rc = leapraid_set_legacy_int(adapter); + if (rc) + dev_err(&adapter->pdev->dev, + "%s: Enable legacy irq failed!\n", __func__); return rc; } @@ -7852,7 +7497,7 @@ int leapraid_set_pcie_and_notification(struct leapraid_adapter *adapter) goto out_fail; } - rc = leapraid_set_notification(adapter); + rc = leapraid_set_notification_auto(adapter); if (rc) goto out_fail; @@ -7886,18 +7531,16 @@ static int leapraid_adapter_unit_reset(struct leapraid_adapter *adapter) { int rc = 0; - dev_info(&adapter->pdev->dev, "fire unit reset\n"); writel(LEAPRAID_FUNC_ADAPTER_UNIT_RESET << LEAPRAID_DB_FUNC_SHIFT, &adapter->iomem_base->db); if (leapraid_db_wait_ack_and_clear_int(adapter)) rc = -EFAULT; if (!leapraid_wait_adapter_ready(adapter)) { - dev_info(&adapter->pdev->dev, "unit reset: FAILED\n"); + dev_err(&adapter->pdev->dev, "unit reset failed\n"); return -EFAULT; } - dev_info(&adapter->pdev->dev, "unit reset: SUCCESS\n"); return rc; } @@ -7905,7 +7548,6 @@ static int leapraid_make_adapter_ready(struct leapraid_adapter *adapter, enum reset_type type) { u32 db; - int rc; int count; if (!leapraid_pci_active(adapter)) @@ -7944,8 +7586,7 @@ static int leapraid_make_adapter_ready(struct leapraid_adapter *adapter, return 0; full_reset: - rc = leapraid_host_diag_reset(adapter); - return rc; + return leapraid_host_diag_reset(adapter); } static void leapraid_fw_log_exit(struct leapraid_adapter *adapter) @@ -7954,6 +7595,8 @@ static void leapraid_fw_log_exit(struct leapraid_adapter *adapter) return; if (adapter->fw_log_desc.fw_log_buffer) { + wait_event(adapter->fw_log_desc.mmap_waitq, + !atomic_read(&adapter->fw_log_desc.mmap_refcnt)); dma_free_coherent(&adapter->pdev->dev, (LEAPRAID_SYS_LOG_BUF_SIZE + LEAPRAID_SYS_LOG_BUF_RESERVE), @@ -8085,16 +7728,22 @@ static void leapraid_free_host_memory(struct leapraid_adapter *adapter) adapter->mem_desc.rep_desc_q_arr = NULL; } - for (i = 0; i < adapter->adapter_attr.rep_desc_q_seg_cnt; i++) + for (i = 0; i < adapter->adapter_attr.rep_desc_q_seg_cnt; i++) { + struct leapraid_mem_desc *mem_desc = + &adapter->mem_desc; kfree(adapter->mem_desc.rep_desc_seg_maint[i] .rep_desc_maint); + mem_desc->rep_desc_seg_maint[i].rep_desc_maint = NULL; + } kfree(adapter->mem_desc.rep_desc_seg_maint); + adapter->mem_desc.rep_desc_seg_maint = NULL; } kfree(adapter->mem_desc.taskid_to_uniq_tag); adapter->mem_desc.taskid_to_uniq_tag = NULL; dma_pool_destroy(adapter->mem_desc.sg_chain_pool); + adapter->mem_desc.sg_chain_pool = NULL; } static inline bool leapraid_is_in_same_4g_seg(dma_addr_t start, u32 size) @@ -8116,15 +7765,13 @@ int leapraid_internal_init_cmd_priv(struct leapraid_adapter *adapter, return 0; } -int leapraid_internal_exit_cmd_priv(struct leapraid_adapter *adapter, - struct leapraid_io_req_tracker *io_tracker) +void leapraid_internal_exit_cmd_priv(struct leapraid_adapter *adapter, + struct leapraid_io_req_tracker *io_tracker) { if (io_tracker && io_tracker->chain) dma_pool_free(adapter->mem_desc.sg_chain_pool, io_tracker->chain, io_tracker->chain_dma); - - return 0; } static int leapraid_request_host_memory(struct leapraid_adapter *adapter) @@ -8170,12 +7817,9 @@ static int leapraid_request_host_memory(struct leapraid_adapter *adapter) adapter->dynamic_task_desc.inter_cmd_qd; /* SCSI host can queue. */ adapter->shost->can_queue = adapter->adapter_attr.io_qd - - LEAPRAID_TASKID_OFFSET_SCSIIO_CMD; + LEAPRAID_TASKID_OFFSET_CTRL_CMD; adapter->driver_cmds.ctl_cmd.taskid = adapter->shost->can_queue + LEAPRAID_TASKID_OFFSET_CTRL_CMD; - adapter->driver_cmds.driver_scsiio_cmd.taskid = - adapter->shost->can_queue + - LEAPRAID_TASKID_OFFSET_SCSIIO_CMD; /* Allocate task descriptor. */ try_again: @@ -8203,7 +7847,6 @@ static int leapraid_request_host_memory(struct leapraid_adapter *adapter) return -ENOMEM; /* Allocate I/O tracker to SCSI I/O. */ - adapter->mem_desc.taskid_to_uniq_tag = kcalloc(adapter->shost->can_queue, sizeof(u16), GFP_KERNEL); if (!adapter->mem_desc.taskid_to_uniq_tag) @@ -8230,9 +7873,6 @@ static int leapraid_request_host_memory(struct leapraid_adapter *adapter) adapter->driver_cmds.transport_cmd.inter_taskid = adapter->dynamic_task_desc.inter_taskid + LEAPRAID_TASKID_OFFSET_TRANSPORT_CMD; - adapter->driver_cmds.timestamp_sync_cmd.inter_taskid = - adapter->dynamic_task_desc.inter_taskid + - LEAPRAID_TASKID_OFFSET_TIMESTAMP_SYNC_CMD; adapter->driver_cmds.enc_cmd.inter_taskid = adapter->dynamic_task_desc.inter_taskid + LEAPRAID_TASKID_OFFSET_ENC_CMD; @@ -8292,8 +7932,11 @@ static int leapraid_request_host_memory(struct leapraid_adapter *adapter) LEAPRAID_REPLY_SIZE, &adapter->mem_desc.rep_msg_dma, GFP_KERNEL); - if (!adapter->mem_desc.rep_msg) - return -ENOMEM; + if (!adapter->mem_desc.rep_msg) { + rc = -ENOMEM; + goto out_fail; + } + if (!leapraid_is_in_same_4g_seg(adapter->mem_desc.rep_msg_dma, adapter->adapter_attr.rep_msg_qd * LEAPRAID_REPLY_SIZE)) { @@ -8405,9 +8048,10 @@ static int leapraid_alloc_dev_topo_bitmaps(struct leapraid_adapter *adapter) { u16 pd_hdls_sz; - pd_hdls_sz = adapter->adapter_attr.features.max_dev_handle / - LEAPRAID_BITS_PER_BYTE; - pd_hdls_sz++; + pd_hdls_sz = + BITS_TO_LONGS( + adapter->adapter_attr.features.max_dev_handle + 1) * + sizeof(unsigned long); adapter->dev_topo.pd_hdls_sz = pd_hdls_sz; adapter->dev_topo.pd_hdls = @@ -8431,9 +8075,6 @@ static void leapraid_free_dev_topo_bitmaps(struct leapraid_adapter *adapter) static int leapraid_init_driver_cmds(struct leapraid_adapter *adapter) { - u32 buffer_size; - void *buffer; - INIT_LIST_HEAD(&adapter->driver_cmds.special_cmd_list); adapter->driver_cmds.scan_dev_cmd.status = LEAPRAID_CMD_NOT_USED; @@ -8453,45 +8094,6 @@ static int leapraid_init_driver_cmds(struct leapraid_adapter *adapter) list_add_tail(&adapter->driver_cmds.transport_cmd.list, &adapter->driver_cmds.special_cmd_list); - adapter->driver_cmds.timestamp_sync_cmd.status = LEAPRAID_CMD_NOT_USED; - adapter->driver_cmds.timestamp_sync_cmd.cb_idx = - LEAPRAID_TIMESTAMP_SYNC_CB_IDX; - mutex_init(&adapter->driver_cmds.timestamp_sync_cmd.mutex); - list_add_tail(&adapter->driver_cmds.timestamp_sync_cmd.list, - &adapter->driver_cmds.special_cmd_list); - - adapter->driver_cmds.raid_action_cmd.status = LEAPRAID_CMD_NOT_USED; - adapter->driver_cmds.raid_action_cmd.cb_idx = - LEAPRAID_RAID_ACTION_CB_IDX; - mutex_init(&adapter->driver_cmds.raid_action_cmd.mutex); - list_add_tail(&adapter->driver_cmds.raid_action_cmd.list, - &adapter->driver_cmds.special_cmd_list); - - adapter->driver_cmds.driver_scsiio_cmd.status = LEAPRAID_CMD_NOT_USED; - adapter->driver_cmds.driver_scsiio_cmd.cb_idx = - LEAPRAID_DRIVER_SCSIIO_CB_IDX; - mutex_init(&adapter->driver_cmds.driver_scsiio_cmd.mutex); - list_add_tail(&adapter->driver_cmds.driver_scsiio_cmd.list, - &adapter->driver_cmds.special_cmd_list); - - buffer_size = sizeof(struct scsi_cmnd) + - sizeof(struct leapraid_io_req_tracker) + - SCSI_SENSE_BUFFERSIZE + - sizeof(struct scatterlist); - buffer = kzalloc(buffer_size, GFP_KERNEL); - if (!buffer) - return -ENOMEM; - - adapter->driver_cmds.internal_scmd = buffer; - buffer = (u8 *)buffer + sizeof(struct scsi_cmnd) + - sizeof(struct leapraid_io_req_tracker); - adapter->driver_cmds.internal_scmd->sense_buffer = - (unsigned char *)buffer; - buffer = (u8 *)buffer + SCSI_SENSE_BUFFERSIZE; - adapter->driver_cmds.internal_scmd->sdb.table.sgl = - (struct scatterlist *)buffer; - buffer = (u8 *)buffer + sizeof(struct scatterlist); - adapter->driver_cmds.enc_cmd.status = LEAPRAID_CMD_NOT_USED; adapter->driver_cmds.enc_cmd.cb_idx = LEAPRAID_ENC_CB_IDX; mutex_init(&adapter->driver_cmds.enc_cmd.mutex); @@ -8635,7 +8237,6 @@ static int leapraid_send_adapter_init(struct leapraid_adapter *adapter) rc = -EIO; } - adapter->timestamp_sync_cnt = 0; return rc; } @@ -8643,48 +8244,52 @@ static int leapraid_cfg_pages(struct leapraid_adapter *adapter) { union cfg_param_1 cfgp1 = {0}; union cfg_param_2 cfgp2 = {0}; - struct leapraid_manufacturing_p0 manufacturing_page0; - struct leapraid_bios_page3 bios_page3; - struct leapraid_bios_page2 bios_page2; + union { + struct leapraid_manufacturing_p0 manufacturing_page0; + struct leapraid_bios_page3 bios_page3; + struct leapraid_bios_page2 bios_page2; + } cfg_page; int rc; - rc = leapraid_op_config_page(adapter, &bios_page3, cfgp1, + rc = leapraid_op_config_page(adapter, &cfg_page.bios_page3, cfgp1, cfgp2, GET_BIOS_PG3); if (rc) return rc; - rc = leapraid_op_config_page(adapter, &bios_page2, cfgp1, - cfgp2, GET_BIOS_PG2); - if (rc) - return rc; + adapter->adapter_attr.bios_version = + le32_to_cpu(cfg_page.bios_page3.bios_version); - rc = leapraid_op_config_page(adapter, &manufacturing_page0, cfgp1, - cfgp2, GET_MANUFACTURING_PG0); + rc = leapraid_op_config_page(adapter, &cfg_page.bios_page2, cfgp1, + cfgp2, GET_BIOS_PG2); if (rc) return rc; - adapter->adapter_attr.bios_version = - le32_to_cpu(bios_page3.bios_version); - snprintf(adapter->adapter_attr.board_name, - sizeof(adapter->adapter_attr.board_name), - "%.*s", - (int)sizeof(manufacturing_page0.board_name), - manufacturing_page0.board_name); adapter->boot_devs.requested_boot_dev.form = - bios_page2.requested_boot_dev_form; + cfg_page.bios_page2.requested_boot_dev_form; memcpy(adapter->boot_devs.requested_boot_dev.pg_dev, - &bios_page2.requested_boot_dev, + &cfg_page.bios_page2.requested_boot_dev, LEAPRAID_BOOT_DEV_SIZE); adapter->boot_devs.requested_alt_boot_dev.form = - bios_page2.requested_alt_boot_dev_form; + cfg_page.bios_page2.requested_alt_boot_dev_form; memcpy(adapter->boot_devs.requested_alt_boot_dev.pg_dev, - &bios_page2.requested_alt_boot_dev, + &cfg_page.bios_page2.requested_alt_boot_dev, LEAPRAID_BOOT_DEV_SIZE); adapter->boot_devs.current_boot_dev.form = - bios_page2.current_boot_dev_form; + cfg_page.bios_page2.current_boot_dev_form; memcpy(adapter->boot_devs.current_boot_dev.pg_dev, - &bios_page2.current_boot_dev, + &cfg_page.bios_page2.current_boot_dev, LEAPRAID_BOOT_DEV_SIZE); + + rc = leapraid_op_config_page(adapter, &cfg_page.manufacturing_page0, + cfgp1, cfgp2, GET_MANUFACTURING_PG0); + if (rc) + return rc; + + snprintf(adapter->adapter_attr.board_name, + sizeof(adapter->adapter_attr.board_name), + "%.*s", + (int)sizeof(cfg_page.manufacturing_page0.board_name), + cfg_page.manufacturing_page0.board_name); return rc; } @@ -8793,8 +8398,6 @@ int leapraid_scan_dev(struct leapraid_adapter *adapter, bool async_scan_dev) out_cleanup: adapter->driver_cmds.scan_dev_cmd.status = LEAPRAID_CMD_NOT_USED; - dev_info(&adapter->pdev->dev, - "Device scan %s\n", rc == 0 ? "SUCCESS" : "FAILED"); return rc; } @@ -8936,11 +8539,7 @@ static int leapraid_make_adapter_available(struct leapraid_adapter *adapter) return 0; } - rc = leapraid_scan_dev(adapter, false); - if (rc) - return rc; - - return rc; + return leapraid_scan_dev(adapter, false); } int leapraid_ctrl_init(struct leapraid_adapter *adapter) @@ -8948,6 +8547,12 @@ int leapraid_ctrl_init(struct leapraid_adapter *adapter) u32 cap; int rc; + rc = leapraid_init_driver_cmds(adapter); + if (rc) { + dev_err(&adapter->pdev->dev, "Init driver cmds failure\n"); + goto out_free; + } + rc = leapraid_set_pcie_and_notification(adapter); if (rc) goto out_free; @@ -8981,12 +8586,6 @@ int leapraid_ctrl_init(struct leapraid_adapter *adapter) goto out_free; } - rc = leapraid_init_driver_cmds(adapter); - if (rc) { - dev_err(&adapter->pdev->dev, "Init driver cmds failure\n"); - goto out_free; - } - leapraid_init_event_mask(adapter); rc = leapraid_make_adapter_available(adapter); @@ -9006,9 +8605,7 @@ int leapraid_ctrl_init(struct leapraid_adapter *adapter) out_free: adapter->access_ctrl.host_removing = 1; - wake_up(&adapter->access_ctrl.recovery_waitq); leapraid_fw_log_exit(adapter); - leapraid_free_internal_scsi_cmd(adapter); leapraid_disable_controller(adapter); leapraid_free_host_memory(adapter); leapraid_free_dev_topo_bitmaps(adapter); @@ -9022,18 +8619,9 @@ void leapraid_remove_ctrl(struct leapraid_adapter *adapter) leapraid_check_scheduled_fault_stop(adapter); leapraid_fw_log_stop(adapter); leapraid_fw_log_exit(adapter); - leapraid_free_internal_scsi_cmd(adapter); leapraid_disable_controller(adapter); leapraid_free_host_memory(adapter); leapraid_free_dev_topo_bitmaps(adapter); leapraid_free_enc_list(adapter); pci_set_drvdata(adapter->pdev, NULL); } - -void leapraid_free_internal_scsi_cmd(struct leapraid_adapter *adapter) -{ - mutex_lock(&adapter->driver_cmds.driver_scsiio_cmd.mutex); - kfree(adapter->driver_cmds.internal_scmd); - adapter->driver_cmds.internal_scmd = NULL; - mutex_unlock(&adapter->driver_cmds.driver_scsiio_cmd.mutex); -} diff --git a/drivers/scsi/leapraid/leapraid_func.h b/drivers/scsi/leapraid/leapraid_func.h index df61bc2e994a..b4dce7e4b355 100644 --- a/drivers/scsi/leapraid/leapraid_func.h +++ b/drivers/scsi/leapraid/leapraid_func.h @@ -51,11 +51,11 @@ #define LEAPRAID_BOARD_NAME_LENGTH 17 #define LEAPRAID_AUTHOR "LeapIO Inc." #define LEAPRAID_DESCRIPTION "LeapRAID Driver" -#define LEAPRAID_DRIVER_VERSION "2.00.01.02" +#define LEAPRAID_DRIVER_VERSION "2.00.01.10" #define LEAPRAID_MAJOR_VERSION 2 -#define LEAPRAID_MINOR_VERSION 00 -#define LEAPRAID_BUILD_VERSION 01 -#define LEAPRAID_RELEASE_VERSION 02 +#define LEAPRAID_MINOR_VERSION 0 +#define LEAPRAID_BUILD_VERSION 1 +#define LEAPRAID_RELEASE_VERSION 10 #define LEAPRAID_MSG_VERSION 0x1021 #define LEAPRAID_HEADER_VERSION 0x0000 @@ -77,7 +77,6 @@ #define LEAPRAID_SG_DEPTH LEAPRAID_MAX_PHYS_SEGMENTS /* Firmware and config page operations. */ -#define LEAPRAID_SET_PARAMETER_SYNC_TIMESTAMP 0x81 #define LEAPRAID_CFG_REQ_RETRY_TIMES 2 /* Hardware access helpers. */ @@ -88,8 +87,6 @@ /* Polling intervals. */ #define LEAPRAID_PCIE_LOG_POLLING_INTERVAL 1 #define LEAPRAID_FAULT_POLLING_INTERVAL 1000 -#define LEAPRAID_TIMESTAMP_SYNC_INTERVAL 900 -#define LEAPRAID_SMART_POLLING_INTERVAL (300 * 1000) /* Init mask. */ #define LEAPRAID_RESET_IRQ_MASK 0x40000000 @@ -103,7 +100,6 @@ /* Target probe flag. */ #define LEAPRAID_NO_ULD_ATTACH_FLAG 1 -#define LEAPRAID_ULD_ATTACH_FLAG 0 /* SCSI device and queue limits. */ #define LEAPRAID_MAX_SECTORS 2048 @@ -127,7 +123,6 @@ /* SMP (Serial Management Protocol). */ #define LEAPRAID_SMP_PT_FLAG_SGL_PTR 0x80 -#define LEAPRAID_SMP_FN_REPORT_PHY_ERR_LOG 0x91 #define LEAPRAID_SMP_FRAME_HEADER_SIZE 4 #define LEAPRAID_SCSI_HOST_SHIFT 16 #define LEAPRAID_SCSI_DRIVER_SHIFT 24 @@ -171,13 +166,9 @@ /* Basic constants and limits. */ #define LEAPRAID_BUSY_LIMIT 1 -#define LEAPRAID_INDEX_FIRST 0 -#define LEAPRAID_BITS_PER_BYTE 8 #define LEAPRAID_INVALID_HOST_DIAG_VAL 0xFFFFFFFF /* Retry/Sleep configuration. */ -#define LEAPRAID_WRITE_SEQUENCE_OFFSET 0x4 -#define LEAPRAID_WRSEQ_KEY_VALUE_MASK 0xF #define LEAPRAID_WRSEQ_FLUSH_KEY_VALUE 0x0 #define LEAPRAID_WRSEQ_1ST_KEY_VALUE 0xF #define LEAPRAID_WRSEQ_2ND_KEY_VALUE 0x4 @@ -187,7 +178,6 @@ #define LEAPRAID_WRSEQ_6TH_KEY_VALUE 0xD #define LEAPRAID_UNLOCK_RETRY_LIMIT 20 #define LEAPRAID_UNLOCK_SLEEP_MS 100 -#define LEAPRAID_MSLEEP_SHORT_MS 50 #define LEAPRAID_MSLEEP_NORMAL_MS 100 #define LEAPRAID_MSLEEP_EXTRA_LONG_MS 500 #define LEAPRAID_IO_POLL_DELAY_US 500 @@ -198,17 +188,14 @@ #define LEAPRAID_INVALID_DEV_HANDLE 0xFFFF /* Commands queue depth. */ -#define LEAPRAID_COALESCING_DEPTH_MAX 256 #define LEAPRAID_DEFAULT_CMD_QD_OFFSET 64 #define LEAPRAID_REPLY_QD_ALIGNMENT 16 /* Task ID offset. */ #define LEAPRAID_TASKID_OFFSET_CTRL_CMD 1 -#define LEAPRAID_TASKID_OFFSET_SCSIIO_CMD 2 #define LEAPRAID_TASKID_OFFSET_CFG_OP_CMD 1 #define LEAPRAID_TASKID_OFFSET_TRANSPORT_CMD 2 -#define LEAPRAID_TASKID_OFFSET_TIMESTAMP_SYNC_CMD 3 -#define LEAPRAID_TASKID_OFFSET_ENC_CMD 4 -#define LEAPRAID_TASKID_OFFSET_NOTIFY_EVENT_CMD 5 +#define LEAPRAID_TASKID_OFFSET_ENC_CMD 3 +#define LEAPRAID_TASKID_OFFSET_NOTIFY_EVENT_CMD 4 /* Task ID offset for high-priority. */ #define LEAPRAID_HP_TASKID_OFFSET_CTL_CMD 0 @@ -223,21 +210,12 @@ #define LEAPRAID_CFG_OP_TIMEOUT LEAPRAID_UNIFIED_TIMEOUT #define LEAPRAID_CTL_CMD_TIMEOUT LEAPRAID_UNIFIED_TIMEOUT #define LEAPRAID_SCAN_DEV_CMD_TIMEOUT 300 -#define LEAPRAID_TIMESTAMP_SYNC_CMD_TIMEOUT LEAPRAID_UNIFIED_TIMEOUT -#define LEAPRAID_RAID_ACTION_CMD_TIMEOUT LEAPRAID_UNIFIED_TIMEOUT #define LEAPRAID_ENC_CMD_TIMEOUT LEAPRAID_UNIFIED_TIMEOUT #define LEAPRAID_IO_CMD_TIMEOUT LEAPRAID_UNIFIED_TIMEOUT #define LEAPRAID_NOTIFY_EVENT_CMD_TIMEOUT LEAPRAID_UNIFIED_TIMEOUT #define LEAPRAID_TM_CMD_TIMEOUT LEAPRAID_UNIFIED_TIMEOUT #define LEAPRAID_TRANSPORT_CMD_TIMEOUT LEAPRAID_UNIFIED_TIMEOUT -/* Logsense command definitions. */ -#define LEAPRAID_LOGSENSE_DATA_LENGTH 16 -#define LEAPRAID_LOGSENSE_CDB_LENGTH 10 -#define LEAPRAID_LOGSENSE_CDB_CODE 0x6F -#define LEAPRAID_LOGSENSE_TIMEOUT LEAPRAID_UNIFIED_TIMEOUT -#define LEAPRAID_LOGSENSE_SMART_CODE 0x5D - /* Host DMA cap. */ #define DMA_32_BITS 32 #define DMA_64_BITS 64 @@ -284,6 +262,8 @@ struct leapraid_adapter_features { u8 max_volumes; u16 max_dev_handle; u16 min_dev_handle; + u16 msg_ver; + u16 product_id; }; /** @@ -424,7 +404,7 @@ struct leapraid_mem_desc { }; /* internal cmd description */ -#define LEAPRAID_FIXED_INTER_CMDS 6 +#define LEAPRAID_FIXED_INTER_CMDS 5 #define LEAPRAID_FIXED_HP_CMDS 2 #define LEAPRAID_CMD_NOT_USED 0x8000 @@ -439,9 +419,6 @@ struct leapraid_mem_desc { * @LEAPRAID_SCAN_DEV_CB_IDX: Scan device callback index. * @LEAPRAID_CONFIG_CB_IDX: Configuration callback index. * @LEAPRAID_TRANSPORT_CB_IDX: Transport callback index. - * @LEAPRAID_TIMESTAMP_SYNC_CB_IDX: Timestamp sync callback index. - * @LEAPRAID_RAID_ACTION_CB_IDX: RAID action callback index. - * @LEAPRAID_DRIVER_SCSIIO_CB_IDX: Driver SCSI I/O callback index. * @LEAPRAID_SAS_CTRL_CB_IDX: SAS controller callback index. * @LEAPRAID_ENC_CB_IDX: Encryption callback index. * @LEAPRAID_NOTIFY_EVENT_CB_IDX: Notify event callback index. @@ -452,14 +429,11 @@ enum LEAPRAID_CB_INDEX { LEAPRAID_SCAN_DEV_CB_IDX = 0x1, LEAPRAID_CONFIG_CB_IDX = 0x2, LEAPRAID_TRANSPORT_CB_IDX = 0x3, - LEAPRAID_TIMESTAMP_SYNC_CB_IDX = 0x4, - LEAPRAID_RAID_ACTION_CB_IDX = 0x5, - LEAPRAID_DRIVER_SCSIIO_CB_IDX = 0x6, - LEAPRAID_SAS_CTRL_CB_IDX = 0x7, - LEAPRAID_ENC_CB_IDX = 0x8, - LEAPRAID_NOTIFY_EVENT_CB_IDX = 0x9, - LEAPRAID_CTL_CB_IDX = 0xA, - LEAPRAID_TM_CB_IDX = 0xB, + LEAPRAID_SAS_CTRL_CB_IDX = 0x5, + LEAPRAID_ENC_CB_IDX = 0x6, + LEAPRAID_NOTIFY_EVENT_CB_IDX = 0x7, + LEAPRAID_CTL_CB_IDX = 0x8, + LEAPRAID_TM_CB_IDX = 0x9, LEAPRAID_NUM_CB_IDXS }; @@ -522,28 +496,20 @@ struct leapraid_driver_cmd { * @scan_dev_cmd: Command used for asynchronous device scan operations. * @cfg_op_cmd: Command for configuration operations. * @transport_cmd: Command for transport-level operations. - * @timestamp_sync_cmd: Command for synchronizing timestamp with firmware. - * @raid_action_cmd: Command for RAID-related management or action requests. - * @driver_scsiio_cmd: Command used for internal SCSI I/O processing. * @enc_cmd: Command for enclosure management operations. * @notify_event_cmd: Command for asynchronous event notification handling. * @ctl_cmd: Command for generic control or maintenance operations. * @tm_cmd: Task management command. - * @internal_scmd: Pointer to internal SCSI command used by the driver. */ struct leapraid_driver_cmds { struct list_head special_cmd_list; struct leapraid_driver_cmd scan_dev_cmd; struct leapraid_driver_cmd cfg_op_cmd; struct leapraid_driver_cmd transport_cmd; - struct leapraid_driver_cmd timestamp_sync_cmd; - struct leapraid_driver_cmd raid_action_cmd; - struct leapraid_driver_cmd driver_scsiio_cmd; struct leapraid_driver_cmd enc_cmd; struct leapraid_driver_cmd notify_event_cmd; struct leapraid_driver_cmd ctl_cmd; struct leapraid_driver_cmd tm_cmd; - struct scsi_cmnd *internal_scmd; }; /** @@ -599,6 +565,7 @@ struct leapraid_fw_evt_work { * @leapraid_evt_masks: Array of event masks for filtering firmware events. */ struct leapraid_fw_evt_struct { + u32 leapraid_evt_masks[4]; char fw_evt_name[48]; struct workqueue_struct *fw_evt_thread; spinlock_t fw_evt_lock; /* protects firmware event */ @@ -606,7 +573,6 @@ struct leapraid_fw_evt_struct { struct leapraid_fw_evt_work *cur_evt; struct task_struct *cur_evt_task; u8 fw_evt_cleanup; - u32 leapraid_evt_masks[4]; }; /** @@ -660,8 +626,8 @@ struct leapraid_blk_mq_poll_rq { * @msix_enable: Flag indicating MSI-X is enabled. * @irq_vectors_allocated: Flag indicating PCI IRQ vectors are allocated. * @irq_mode: Actual interrupt mode used for allocated PCI IRQ vectors. - * @msix_cpu_map: CPU map for MSI-X interrupts. - * @msix_cpu_map_sz: Size of the MSI-X CPU map. + * @msix_cpu_map: CPU-ID indexed MSI-X queue map. + * @msix_cpu_map_sz: Number of CPU-ID slots allocated in @msix_cpu_map. * @int_rqs: Array of interrupt request queues. * @int_rqs_allocated: Count of allocated interrupt request queues. * @blk_mq_poll_rqs: Array of blk-mq polling requests. @@ -708,7 +674,6 @@ struct leapraid_overheat_desc { * @pending_io_cnt: Count of pending I/O operations. * @reset_wait_queue: Wait queue for reset operations. * @reset_cnt: Counter for reset operations. - * @last_reset_cnt: Last observed adapter reset counter. */ struct leapraid_reset_desc { struct workqueue_struct *fault_reset_wq; @@ -722,7 +687,6 @@ struct leapraid_reset_desc { int pending_io_cnt; wait_queue_head_t reset_wait_queue; u32 reset_cnt; - u32 last_reset_cnt; }; /** @@ -776,7 +740,8 @@ struct leapraid_access_ctrl { * @fw_log_work: Delayed work structure for firmware log. * @open_pcie_trace: Flag indicating if PCIe tracing is open. * @fw_log_init_flag: Flag indicating if firmware log is initialized. - * @pre_debug_log: Last DebugLog register snapshot for change detection. + * @mmap_refcnt: Number of active user VMAs on fw_log_buffer. + * @mmap_waitq: Waitqueue for fw_log_buffer VMA teardown. */ struct leapraid_fw_log_desc { u8 *fw_log_buffer; @@ -786,7 +751,8 @@ struct leapraid_fw_log_desc { struct delayed_work fw_log_work; int open_pcie_trace; int fw_log_init_flag; - u32 pre_debug_log[LEAPRAID_DEBUGLOG_SZ_MAX]; + atomic_t mmap_refcnt; + wait_queue_head_t mmap_waitq; }; #define LEAPRAID_CARD_PORT_FLG_DIRTY 0x01 @@ -939,19 +905,6 @@ struct leapraid_boot_devs { struct leapraid_boot_dev current_boot_dev; }; -/** - * struct leapraid_smart_poll_desc - SMART polling descriptor - * - * @smart_poll_wq: Workqueue for SMART polling tasks. - * @smart_poll_work: Delayed work for SMART polling operations. - * @smart_poll_wq_name: Workqueue name string. - */ -struct leapraid_smart_poll_desc { - struct workqueue_struct *smart_poll_wq; - struct delayed_work smart_poll_work; - char smart_poll_wq_name[48]; -}; - /** * struct leapraid_adapter - Main LeapRAID adapter structure * @@ -961,7 +914,6 @@ struct leapraid_smart_poll_desc { * @iomem_base: I/O memory mapped base address. * @rep_msg_host_idx: Host index for reply messages. * @mask_int: Interrupt masking flag. - * @timestamp_sync_cnt: Timestamp synchronization counter. * @adapter_attr: Adapter attributes. * @mem_desc: Memory descriptor. * @driver_cmds: Driver commands. @@ -974,7 +926,6 @@ struct leapraid_smart_poll_desc { * @fw_log_desc: Firmware log descriptor. * @dev_topo: Device topology. * @boot_devs: Boot devices. - * @smart_poll_desc: SMART polling descriptor. * @overheat_desc: Overheat processing descriptor. */ struct leapraid_adapter { @@ -984,7 +935,6 @@ struct leapraid_adapter { struct leapraid_reg_base __iomem *iomem_base; u32 rep_msg_host_idx; u8 mask_int; - u32 timestamp_sync_cnt; struct leapraid_adapter_attr adapter_attr; struct leapraid_mem_desc mem_desc; @@ -998,7 +948,6 @@ struct leapraid_adapter { struct leapraid_fw_log_desc fw_log_desc; struct leapraid_dev_topo dev_topo; struct leapraid_boot_devs boot_devs; - struct leapraid_smart_poll_desc smart_poll_desc; struct leapraid_overheat_desc overheat_desc; }; @@ -1116,6 +1065,7 @@ struct leapraid_starget_priv { * @starget_priv: Associated target private data. * @lun: Logical Unit Number. * @flg: Flags. + * @ncq_prio_enable: Enables NCQ command priority for RT I/O. * @block: Block flag. * @deleted: Deletion flag. * @sep: SEP flag. @@ -1124,7 +1074,7 @@ struct leapraid_sdev_priv { struct leapraid_starget_priv *starget_priv; unsigned int lun; u32 flg; - u8 ncq; + u8 ncq_prio_enable; u8 block; u8 deleted; u8 sep; @@ -1157,7 +1107,6 @@ struct leapraid_sdev_priv { * @enc_level: Enclosure level. * @port_connection: Port connection. * @connector_name: Connector name. - * @support_smart: SMART support flag. */ struct leapraid_sas_dev { struct list_head list; @@ -1184,7 +1133,6 @@ struct leapraid_sas_dev { u8 enc_level; u8 port_connection; u8 connector_name[LEAPRAID_SAS_DEV_P0_CON_NAME_LEN + 1]; - u8 support_smart; }; static inline void leapraid_sdev_free(struct kref *ref) @@ -1362,31 +1310,6 @@ struct leapraid_rep_manu_reply { u8 vendor_specific[8]; }; -/** - * struct leapraid_scsi_cmd_desc - SCSI command descriptor - * - * @hdl: Device handle. - * @lun: Logical Unit Number. - * @raid_member: RAID member flag. - * @dir: DMA data direction. - * @data_length: Data transfer length. - * @data_buffer: Data buffer pointer. - * @cdb_length: CDB length. - * @cdb: Command Descriptor Block. - * @time_out: Timeout. - */ -struct leapraid_scsi_cmd_desc { - u16 hdl; - u32 lun; - u8 raid_member; - enum dma_data_direction dir; - u32 data_length; - void *data_buffer; - u8 cdb_length; - u8 cdb[32]; - u8 time_out; -}; - extern struct list_head leapraid_adapter_list; extern spinlock_t leapraid_adapter_lock; extern char driver_name[LEAPRAID_NAME_LENGTH]; @@ -1446,7 +1369,7 @@ int leapraid_get_volume_cap(struct leapraid_adapter *adapter, int leapraid_internal_init_cmd_priv( struct leapraid_adapter *adapter, struct leapraid_io_req_tracker *io_tracker); -int leapraid_internal_exit_cmd_priv( +void leapraid_internal_exit_cmd_priv( struct leapraid_adapter *adapter, struct leapraid_io_req_tracker *io_tracker); void leapraid_clean_active_fw_evt(struct leapraid_adapter *adapter); @@ -1517,7 +1440,7 @@ int leapraid_op_config_page(struct leapraid_adapter *adapter, void *cfgp, union cfg_param_1 cfgp1, union cfg_param_2 cfgp2, enum config_page_action cfg_op); -void leapraid_log_req_context(struct leapraid_adapter *adapter, +void leapraid_log_req_context(struct leapraid_adapter *adapter, u16 smid, const void *req_data); int leapraid_change_queue_depth(struct scsi_device *sdev, int qdepth); @@ -1557,10 +1480,7 @@ void leapraid_transport_attach_phy_to_port( u64 sas_address, struct leapraid_card_port *card_port); int leapraid_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmd); -void leapraid_smart_polling_start(struct leapraid_adapter *adapter); -void leapraid_smart_polling_stop(struct leapraid_adapter *adapter); void leapraid_overheat_cleanup(struct leapraid_adapter *adapter); void leapraid_smart_fault_detect(struct leapraid_adapter *adapter, u16 hdl); -void leapraid_free_internal_scsi_cmd(struct leapraid_adapter *adapter); #endif /* LEAPRAID_FUNC_H_INCLUDED */ diff --git a/drivers/scsi/leapraid/leapraid_os.c b/drivers/scsi/leapraid/leapraid_os.c index c60c5d80c7b3..6a9f97e4c63a 100644 --- a/drivers/scsi/leapraid/leapraid_os.c +++ b/drivers/scsi/leapraid/leapraid_os.c @@ -125,13 +125,6 @@ static int leapraid_tm_cmd_map_status(struct leapraid_adapter *adapter, } } - if (taskid_task == adapter->driver_cmds.driver_scsiio_cmd.taskid && - (adapter->driver_cmds.driver_scsiio_cmd.status & - LEAPRAID_CMD_DONE || - adapter->driver_cmds.driver_scsiio_cmd.status & - LEAPRAID_CMD_NOT_USED)) - rc = SUCCESS; - if (taskid_task == adapter->driver_cmds.ctl_cmd.hp_taskid && (adapter->driver_cmds.ctl_cmd.status & LEAPRAID_CMD_DONE || @@ -157,9 +150,8 @@ static int leapraid_tm_post_processing(struct leapraid_adapter *adapter, leapraid_sync_irqs(adapter, true); leapraid_unmask_int(adapter); - rc = leapraid_tm_cmd_map_status(adapter, channel, id, lun, type, - taskid_task); - return rc; + return leapraid_tm_cmd_map_status(adapter, channel, id, lun, type, + taskid_task); } static void leapraid_build_tm_req(struct leapraid_scsi_tm_req *scsi_tm_req, @@ -185,6 +177,7 @@ int leapraid_issue_tm(struct leapraid_adapter *adapter, u16 hdl, uint channel, struct leapraid_scsiio_req *scsiio_req; struct leapraid_io_req_tracker *io_req_tracker = NULL; u16 msix_task; + u16 taskid; bool issue_reset = false; u32 db; int rc; @@ -239,16 +232,15 @@ int leapraid_issue_tm(struct leapraid_adapter *adapter, u16 hdl, uint channel, msix_task = io_req_tracker->msix_io; else msix_task = 0; - leapraid_fire_hpr_task(adapter, - adapter->driver_cmds.tm_cmd.hp_taskid, - msix_task); + taskid = adapter->driver_cmds.tm_cmd.hp_taskid; + leapraid_fire_hpr_task(adapter, taskid, msix_task); wait_for_completion_timeout(&adapter->driver_cmds.tm_cmd.done, LEAPRAID_TM_CMD_TIMEOUT * HZ); if (!(adapter->driver_cmds.tm_cmd.status & LEAPRAID_CMD_DONE)) { dev_err(&adapter->pdev->dev, "%s: TM cmd timeout, status=0x%x\n", __func__, adapter->driver_cmds.tm_cmd.status); - leapraid_log_req_context(adapter, scsi_tm_req); + leapraid_log_req_context(adapter, taskid, scsi_tm_req); issue_reset = leapraid_check_reset( adapter->driver_cmds.tm_cmd.status); @@ -508,11 +500,11 @@ static void leapraid_scsiio_done_dispatch( if (!scmd->result) return; - scsi_print_command(scmd); - dev_warn(&adapter->pdev->dev, - "SCSI I/O: hdl=0x%x, status: 0x%x, 0x%x, 0x%x\n", - le16_to_cpu(scsiio_rep->dev_hdl), adapter_status, - scsi_status, scsi_state); + dev_dbg(&adapter->pdev->dev, + "SCSI I/O: CDB=%*ph, hdl=0x%x, status: 0x%x, 0x%x, 0x%x\n", + scmd->cmd_len, scmd->cmnd, + le16_to_cpu(scsiio_rep->dev_hdl), adapter_status, + scsi_status, scsi_state); if (scsi_state & LEAPRAID_SCSI_STATE_AUTOSENSE_VALID) { struct scsi_sense_hdr sshdr; @@ -521,13 +513,13 @@ static void leapraid_scsiio_done_dispatch( le32_to_cpu(scsiio_rep->sense_count)); if (scsi_normalize_sense(scmd->sense_buffer, sz, &sshdr)) - dev_warn(&adapter->pdev->dev, - "Sense: key=0x%x asc=0x%x ascq=0x%x\n", - sshdr.sense_key, sshdr.asc, - sshdr.ascq); + dev_dbg(&adapter->pdev->dev, + "Sense: key=0x%x asc=0x%x ascq=0x%x\n", + sshdr.sense_key, sshdr.asc, + sshdr.ascq); else - dev_warn(&adapter->pdev->dev, - "Sense: Invalid sense data\n"); + dev_dbg(&adapter->pdev->dev, + "Sense: Invalid sense data\n"); } } @@ -539,10 +531,7 @@ bool leapraid_scsiio_done(struct leapraid_adapter *adapter, u16 taskid, struct scsi_cmnd *scmd; u32 response_code = 0; - if (likely(taskid != adapter->driver_cmds.driver_scsiio_cmd.taskid)) - scmd = leapraid_get_scmd_from_taskid(adapter, taskid); - else - scmd = adapter->driver_cmds.internal_scmd; + scmd = leapraid_get_scmd_from_taskid(adapter, taskid); if (!scmd) return true; @@ -569,13 +558,6 @@ bool leapraid_scsiio_done(struct leapraid_adapter *adapter, u16 taskid, out_scsiio_done: scsi_dma_unmap(scmd); - if (unlikely(taskid == - adapter->driver_cmds.driver_scsiio_cmd.taskid)) { - adapter->driver_cmds.driver_scsiio_cmd.status = - LEAPRAID_CMD_DONE; - complete(&adapter->driver_cmds.driver_scsiio_cmd.done); - return false; - } leapraid_free_taskid(adapter, taskid); scsi_done(scmd); return false; @@ -644,7 +626,6 @@ static void leapraid_probe_sas(struct leapraid_adapter *adapter) sas_dev->hdl, sas_dev->parent_sas_addr, sas_dev->card_port); - if (!added) goto remove_dev; @@ -781,7 +762,6 @@ void leapraid_scan_dev_done(struct leapraid_adapter *adapter) leapraid_fw_log_start(adapter); adapter->scan_dev_desc.driver_loading = 0; wake_up(&adapter->scan_dev_desc.wait_driver_loading); - leapraid_smart_polling_start(adapter); } static const struct pci_device_id leapraid_pci_table[] = { @@ -805,10 +785,7 @@ static inline bool leapraid_is_scmd_permitted(struct leapraid_adapter *adapter, return false; opcode = scmd->cmnd[0]; - if (opcode == SYNCHRONIZE_CACHE || opcode == START_STOP) - return true; - - return false; + return opcode == SYNCHRONIZE_CACHE || opcode == START_STOP; } return true; } @@ -857,10 +834,7 @@ static bool leapraid_should_queuecommand(struct leapraid_adapter *adapter, no_connect: scmd->result = DID_NO_CONNECT << LEAPRAID_SCSI_HOST_SHIFT; scsiio_done: - if (likely(scmd != adapter->driver_cmds.internal_scmd)) - scsi_done(scmd); - else - *rc = LEAPRAID_OPERATION_FAILED; + scsi_done(scmd); return false; } @@ -884,7 +858,7 @@ static u32 build_scsiio_req_control(struct scsi_cmnd *scmd, control |= LEAPRAID_SCSIIO_CTRL_SIMPLEQ; - if (sdev_priv->ncq && + if (sdev_priv->ncq_prio_enable && (IOPRIO_PRIO_CLASS(req_get_ioprio(scsi_cmd_to_rq(scmd))) == IOPRIO_CLASS_RT)) control |= LEAPRAID_SCSIIO_CTRL_CMDPRI; @@ -914,10 +888,7 @@ int leapraid_queuecommand(struct Scsi_Host *shost, hdl = starget_priv->hdl; control = build_scsiio_req_control(scmd, sdev_priv); - if (unlikely(scmd == adapter->driver_cmds.internal_scmd)) - taskid = adapter->driver_cmds.driver_scsiio_cmd.taskid; - else - taskid = leapraid_alloc_scsiio_taskid(adapter, scmd); + taskid = leapraid_alloc_scsiio_taskid(adapter, scmd); scsiio_req = leapraid_get_task_desc(adapter, taskid); scsiio_req->func = LEAPRAID_FUNC_SCSIIO; @@ -1101,13 +1072,15 @@ static int leapraid_error_handler(struct scsi_cmnd *scmd, out_eh_done: if (type == LEAPRAID_TM_TASKTYPE_ABORT_TASK) { - dev_info(&adapter->pdev->dev, - "EH ABORT result: %s, scmd=0x%p\n", - rc == SUCCESS ? "success" : "failed", scmd); + if (rc != SUCCESS) + dev_err(&adapter->pdev->dev, + "EH ABORT result: failed, scmd=0x%p\n", + scmd); } else { - dev_info(&adapter->pdev->dev, - "EH %s result: %s, scmd=0x%p\n", - str, rc == SUCCESS ? "success" : "failed", scmd); + if (rc != SUCCESS) + dev_err(&adapter->pdev->dev, + "EH %s result: failed, scmd=0x%p\n", + str, scmd); if (sas_dev) leapraid_sdev_put(sas_dev); } @@ -1161,8 +1134,10 @@ static int leapraid_eh_host_reset_handler(struct scsi_cmnd *scmd) rc = SUCCESS; out_host_reset_done: - dev_info(&adapter->pdev->dev, "EH HOST RESET result: %s, scmd=0x%p\n", - rc == SUCCESS ? "success" : "failed", scmd); + if (rc != SUCCESS) + dev_err(&adapter->pdev->dev, + "EH HOST RESET result: failed, scmd=0x%p\n", + scmd); return rc; } @@ -1227,7 +1202,7 @@ static int leapraid_slave_alloc(struct scsi_device *sdev) return 0; } -static int leapraid_slave_cfg_volume(struct scsi_device *sdev) +static bool leapraid_slave_cfg_volume(struct scsi_device *sdev) { struct Scsi_Host *shost = sdev->host; struct leapraid_adapter *adapter = shost_priv(shost); @@ -1276,10 +1251,10 @@ static int leapraid_slave_cfg_volume(struct scsi_device *sdev) return 0; } -static int leapraid_slave_configure_extra(struct scsi_device *sdev, - struct leapraid_sas_dev **psas_dev, - u16 vol_hdl, u64 volume_wwid, - bool *is_target_ssp, int *qd) +static bool leapraid_slave_configure_extra(struct scsi_device *sdev, + struct leapraid_sas_dev **psas_dev, + u16 vol_hdl, u64 volume_wwid, + bool *is_target_ssp, int *qd) { struct leapraid_sas_dev *sas_dev; struct leapraid_sdev_priv *sdev_priv; @@ -1586,11 +1561,9 @@ static bool leapraid_scan_check_status(struct leapraid_adapter *adapter, wake_up(&adapter->scan_dev_desc.wait_driver_loading); adapter->scan_dev_desc.wait_scan_dev_done = 0; adapter->access_ctrl.host_removing = 1; - wake_up(&adapter->access_ctrl.recovery_waitq); return true; } - dev_info(&adapter->pdev->dev, "Device scan: SUCCESS\n"); adapter->driver_cmds.scan_dev_cmd.status = LEAPRAID_CMD_NOT_USED; leapraid_scan_dev_done(adapter); return true; @@ -1861,12 +1834,11 @@ static struct attribute *leapraid_shost_attrs[] = { ATTRIBUTE_GROUPS(leapraid_shost); -static ssize_t sas_address_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t sas_device_handle_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct scsi_device *sdev = to_scsi_device(dev); struct leapraid_sdev_priv *sas_device_priv_data = sdev->hostdata; - u64 sas_address; if (!sas_device_priv_data || !sas_device_priv_data->starget_priv) { dev_err(&sdev->sdev_gendev, @@ -1874,29 +1846,45 @@ static ssize_t sas_address_show(struct device *dev, return -EINVAL; } - sas_address = sas_device_priv_data->starget_priv->sas_address; - - return sysfs_emit(buf, "0x%016llx\n", (unsigned long long)sas_address); + return sysfs_emit(buf, "0x%04x\n", + sas_device_priv_data->starget_priv->hdl); } -static ssize_t sas_device_handle_show(struct device *dev, - struct device_attribute *attr, char *buf) +static int leapraid_ncq_prio_supported(struct scsi_device *sdev, + bool *supported) +{ + struct scsi_vpd *vpd_pg89; + + *supported = false; + rcu_read_lock(); + vpd_pg89 = rcu_dereference(sdev->vpd_pg89); + if (vpd_pg89 && vpd_pg89->len >= LEAPRAID_VPD_PG89_MIN_LEN) + *supported = + (vpd_pg89->data[LEAPRAID_VPD_PG89_NCQ_BYTE_IDX] >> + LEAPRAID_VPD_PG89_NCQ_BIT_SHIFT) & + LEAPRAID_VPD_PG89_NCQ_BIT_MASK; + rcu_read_unlock(); + + return 0; +} +static ssize_t sas_ncq_prio_supported_show(struct device *dev, + struct device_attribute *attr, + char *buf) { struct scsi_device *sdev = to_scsi_device(dev); - struct leapraid_sdev_priv *sas_device_priv_data = sdev->hostdata; + bool supported; + int rc; - if (!sas_device_priv_data || !sas_device_priv_data->starget_priv) { - dev_err(&sdev->sdev_gendev, - "%s: Invalid sdev_priv or starget_priv\n", __func__); - return -EINVAL; - } + rc = leapraid_ncq_prio_supported(sdev, &supported); + if (rc) + return rc; - return sysfs_emit(buf, "0x%04x\n", - sas_device_priv_data->starget_priv->hdl); + return sysfs_emit(buf, "%d\n", supported); } -static ssize_t sas_ncq_show(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t sas_ncq_prio_enable_show(struct device *dev, + struct device_attribute *attr, + char *buf) { struct scsi_device *sdev = to_scsi_device(dev); struct leapraid_sdev_priv *sas_device_priv_data = sdev->hostdata; @@ -1907,18 +1895,18 @@ static ssize_t sas_ncq_show(struct device *dev, struct device_attribute *attr, return -EINVAL; } - return sysfs_emit(buf, "%d\n", sas_device_priv_data->ncq); + return sysfs_emit(buf, "%d\n", sas_device_priv_data->ncq_prio_enable); } -static ssize_t sas_ncq_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t sas_ncq_prio_enable_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { struct scsi_device *sdev = to_scsi_device(dev); struct leapraid_sdev_priv *sas_device_priv_data = sdev->hostdata; - struct scsi_vpd *vpd_pg89; - int ncq_op; - bool ncq_supported; + bool supported; + int rc; + bool enable; if (!sas_device_priv_data) { dev_err(&sdev->sdev_gendev, @@ -1926,45 +1914,66 @@ static ssize_t sas_ncq_store(struct device *dev, return -EINVAL; } - if (kstrtoint(buf, 0, &ncq_op)) - return -EINVAL; - - if (ncq_op != 0 && ncq_op != 1) { - dev_err(&sdev->sdev_gendev, - "%s: Invalid NCQ value %d (only 0/1 allowed)\n", - __func__, ncq_op); + if (kstrtobool(buf, &enable)) return -EINVAL; - } - rcu_read_lock(); - vpd_pg89 = rcu_dereference(sdev->vpd_pg89); - if (!vpd_pg89 || vpd_pg89->len < LEAPRAID_VPD_PG89_MIN_LEN) { - rcu_read_unlock(); + rc = leapraid_ncq_prio_supported(sdev, &supported); + if (rc) + return rc; + if (!supported) return -EINVAL; - } - ncq_supported = (vpd_pg89->data[LEAPRAID_VPD_PG89_NCQ_BYTE_IDX] >> - LEAPRAID_VPD_PG89_NCQ_BIT_SHIFT) & - LEAPRAID_VPD_PG89_NCQ_BIT_MASK; - rcu_read_unlock(); - if (ncq_supported) - sas_device_priv_data->ncq = ncq_op; + sas_device_priv_data->ncq_prio_enable = enable; return count; } -static DEVICE_ATTR_RO(sas_address); static DEVICE_ATTR_RO(sas_device_handle); +static DEVICE_ATTR_RO(sas_ncq_prio_supported); +static DEVICE_ATTR_RW(sas_ncq_prio_enable); -static DEVICE_ATTR_RW(sas_ncq); +static bool leapraid_sdev_is_sata(struct scsi_device *sdev) +{ + struct scsi_target *starget = sdev->sdev_target; + struct leapraid_starget_priv *starget_priv = starget->hostdata; + struct leapraid_sas_dev *sas_dev; + + if (!starget_priv) + return false; + + sas_dev = starget_priv->sas_dev; + return sas_dev && (sas_dev->dev_info & LEAPRAID_DEVTYP_SATA_DEV); +} static struct attribute *leapraid_sdev_attrs[] = { - &dev_attr_sas_address.attr, &dev_attr_sas_device_handle.attr, - &dev_attr_sas_ncq.attr, + &dev_attr_sas_ncq_prio_supported.attr, + &dev_attr_sas_ncq_prio_enable.attr, NULL, }; -ATTRIBUTE_GROUPS(leapraid_sdev); +static umode_t leapraid_sdev_attr_is_visible(struct kobject *kobj, + struct attribute *attr, int i) +{ + struct device *dev = kobj_to_dev(kobj); + struct scsi_device *sdev = to_scsi_device(dev); + + if (attr == &dev_attr_sas_ncq_prio_supported.attr || + attr == &dev_attr_sas_ncq_prio_enable.attr) + if (!leapraid_sdev_is_sata(sdev)) + return 0; + + return attr->mode; +} + +static const struct attribute_group leapraid_sdev_attr_group = { + .attrs = leapraid_sdev_attrs, + .is_visible = leapraid_sdev_attr_is_visible, +}; + +static const struct attribute_group *leapraid_sdev_groups[] = { + &leapraid_sdev_attr_group, + NULL, +}; static struct scsi_host_template leapraid_driver_template = { .module = THIS_MODULE, @@ -2053,13 +2062,12 @@ static int leapraid_probe(struct pci_dev *pdev, const struct pci_device_id *id) adapter = shost_priv(shost); INIT_LIST_HEAD(&adapter->list); - spin_lock(&leapraid_adapter_lock); - list_add_tail(&adapter->list, &leapraid_adapter_list); - spin_unlock(&leapraid_adapter_lock); adapter->shost = shost; adapter->pdev = pdev; adapter->fw_log_desc.open_pcie_trace = open_pcie_trace; + atomic_set(&adapter->fw_log_desc.mmap_refcnt, 0); + init_waitqueue_head(&adapter->fw_log_desc.mmap_waitq); leapraid_lock_init(adapter); leapraid_list_init(adapter); snprintf(adapter->adapter_attr.name, LEAPRAID_NAME_LENGTH, "%s%d", @@ -2111,6 +2119,10 @@ static int leapraid_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto scsi_add_shost_fail; } + spin_lock(&leapraid_adapter_lock); + list_add_tail(&adapter->list, &leapraid_adapter_list); + spin_unlock(&leapraid_adapter_lock); + scsi_scan_host(shost); return 0; @@ -2120,9 +2132,6 @@ static int leapraid_probe(struct pci_dev *pdev, const struct pci_device_id *id) leapraid_overheat_cleanup(adapter); destroy_workqueue(adapter->fw_evt_s.fw_evt_thread); evt_wq_fail: - spin_lock(&leapraid_adapter_lock); - list_del(&adapter->list); - spin_unlock(&leapraid_adapter_lock); scsi_host_put(shost); return rc; } @@ -2205,13 +2214,13 @@ static void leapraid_remove(struct pci_dev *pdev) wait_event(adapter->scan_dev_desc.wait_driver_loading, !atomic_read(&adapter->overheat_desc.thermal_alert)); - adapter->access_ctrl.host_removing = 1; - wake_up(&adapter->access_ctrl.recovery_waitq); + WRITE_ONCE(adapter->access_ctrl.host_removing, 1); + spin_lock(&leapraid_adapter_lock); + list_del(&adapter->list); + spin_unlock(&leapraid_adapter_lock); leapraid_wait_cmds_done(adapter); - leapraid_smart_polling_stop(adapter); - if (leapraid_pci_removed(adapter)) { leapraid_mq_polling_pause(adapter); leapraid_clean_active_scsi_cmds(adapter); @@ -2228,9 +2237,6 @@ static void leapraid_remove(struct pci_dev *pdev) sas_remove_host(shost); leapraid_cleanup_lists(adapter); leapraid_remove_ctrl(adapter); - spin_lock(&leapraid_adapter_lock); - list_del(&adapter->list); - spin_unlock(&leapraid_adapter_lock); scsi_host_put(shost); } @@ -2247,7 +2253,6 @@ static void leapraid_shutdown(struct pci_dev *pdev) } adapter->access_ctrl.host_removing = 1; - wake_up(&adapter->access_ctrl.recovery_waitq); leapraid_wait_cmds_done(adapter); leapraid_clean_active_fw_evt(adapter); leapraid_overheat_cleanup(adapter); @@ -2283,7 +2288,6 @@ static pci_ers_result_t leapraid_pci_error_detected(struct pci_dev *pdev, adapter->access_ctrl.pcie_recovering = 1; scsi_block_requests(adapter->shost); leapraid_overheat_cleanup(adapter); - leapraid_smart_polling_stop(adapter); leapraid_check_scheduled_fault_stop(adapter); leapraid_fw_log_stop(adapter); leapraid_disable_controller(adapter); @@ -2291,7 +2295,6 @@ static pci_ers_result_t leapraid_pci_error_detected(struct pci_dev *pdev, case pci_channel_io_perm_failure: adapter->access_ctrl.pcie_recovering = 1; leapraid_overheat_cleanup(adapter); - leapraid_smart_polling_stop(adapter); leapraid_check_scheduled_fault_stop(adapter); leapraid_fw_log_stop(adapter); leapraid_mq_polling_pause(adapter); @@ -2334,7 +2337,6 @@ static pci_ers_result_t leapraid_pci_slot_reset(struct pci_dev *pdev) dev_err(&pdev->dev, "%s PCI error slot reset\n", adapter->adapter_attr.name); - adapter->access_ctrl.pcie_recovering = 0; adapter->pdev = pdev; pci_restore_state(pdev); if (leapraid_set_pcie_and_notification(adapter)) { @@ -2344,13 +2346,15 @@ static pci_ers_result_t leapraid_pci_slot_reset(struct pci_dev *pdev) return PCI_ERS_RESULT_DISCONNECT; } + adapter->access_ctrl.pcie_recovering = 0; dev_info(&pdev->dev, "%s: Hard reset triggered by PCI slot reset\n", adapter->adapter_attr.name); dev_info(&adapter->pdev->dev, "%s: %d: call hard_reset\n", __func__, __LINE__); rc = leapraid_hard_reset_handler(adapter, FULL_RESET); - dev_info(&pdev->dev, "%s hard reset: %s\n", - adapter->adapter_attr.name, rc == 0 ? "success" : "failed"); + if (rc) + dev_err(&pdev->dev, "%s hard reset: failed\n", + adapter->adapter_attr.name); return rc == 0 ? PCI_ERS_RESULT_RECOVERED : PCI_ERS_RESULT_DISCONNECT; @@ -2367,11 +2371,11 @@ static void leapraid_pci_resume(struct pci_dev *pdev) } dev_err(&pdev->dev, "PCI error resume!\n"); + pci_aer_clear_nonfatal_status(pdev); leapraid_check_scheduled_fault_start(adapter); leapraid_fw_log_start(adapter); scsi_unblock_requests(adapter->shost); - leapraid_smart_polling_start(adapter); } MODULE_DEVICE_TABLE(pci, leapraid_pci_table); @@ -2396,7 +2400,6 @@ static int leapraid_suspend(struct pci_dev *pdev, pm_message_t state) } leapraid_overheat_cleanup(adapter); - leapraid_smart_polling_stop(adapter); leapraid_check_scheduled_fault_stop(adapter); leapraid_fw_log_stop(adapter); scsi_block_requests(shost); @@ -2452,7 +2455,6 @@ static int leapraid_resume(struct pci_dev *pdev) scsi_unblock_requests(shost); leapraid_check_scheduled_fault_start(adapter); leapraid_fw_log_start(adapter); - leapraid_smart_polling_start(adapter); return 0; } #endif /* CONFIG_PM */ diff --git a/drivers/scsi/leapraid/leapraid_transport.c b/drivers/scsi/leapraid/leapraid_transport.c index 738bc55df416..379029685e16 100644 --- a/drivers/scsi/leapraid/leapraid_transport.c +++ b/drivers/scsi/leapraid/leapraid_transport.c @@ -298,6 +298,7 @@ static int leapraid_transport_exp_report_manu(struct leapraid_adapter *adapter, dma_addr_t c2h_dma_addr; bool issue_reset = false; void *data_out = NULL; + u16 inter_taskid; size_t c2h_size; size_t h2c_size; void *psge; @@ -338,10 +339,8 @@ static int leapraid_transport_exp_report_manu(struct leapraid_adapter *adapter, rep_manu_request->allocated_response_length = 0; rep_manu_request->request_length = 0; - smp_passthrough_req = - leapraid_get_task_desc( - adapter, - adapter->driver_cmds.transport_cmd.inter_taskid); + inter_taskid = adapter->driver_cmds.transport_cmd.inter_taskid; + smp_passthrough_req = leapraid_get_task_desc(adapter, inter_taskid); memset(smp_passthrough_req, 0, sizeof(struct leapraid_smp_passthrough_req)); smp_passthrough_req->func = LEAPRAID_FUNC_SMP_PASSTHROUGH; @@ -354,8 +353,7 @@ static int leapraid_transport_exp_report_manu(struct leapraid_adapter *adapter, c2h_dma_addr, c2h_size); init_completion(&adapter->driver_cmds.transport_cmd.done); - leapraid_fire_task(adapter, - adapter->driver_cmds.transport_cmd.inter_taskid); + leapraid_fire_task(adapter, inter_taskid); wait_for_completion_timeout(&adapter->driver_cmds.transport_cmd.done, LEAPRAID_TRANSPORT_CMD_TIMEOUT * HZ); if (!(adapter->driver_cmds.transport_cmd.status & LEAPRAID_CMD_DONE)) { @@ -363,7 +361,8 @@ static int leapraid_transport_exp_report_manu(struct leapraid_adapter *adapter, dev_err(&adapter->pdev->dev, "%s: SMP passthrough timeout, st=0x%x\n", __func__, adapter->driver_cmds.transport_cmd.status); - leapraid_log_req_context(adapter, smp_passthrough_req); + leapraid_log_req_context(adapter, inter_taskid, + smp_passthrough_req); if (!(adapter->driver_cmds.transport_cmd.status & LEAPRAID_CMD_RESET)) issue_reset = true; @@ -1249,20 +1248,21 @@ static void leapraid_build_smp_task(struct leapraid_adapter *adapter, static int leapraid_send_smp_req(struct leapraid_adapter *adapter) { const struct leapraid_smp_passthrough_req *smp_passthrough_req; + u16 inter_taskid; dev_dbg(&adapter->pdev->dev, "%s: Sending smp request\n", __func__); - smp_passthrough_req = leapraid_get_task_desc( - adapter, adapter->driver_cmds.transport_cmd.inter_taskid); + inter_taskid = adapter->driver_cmds.transport_cmd.inter_taskid; + smp_passthrough_req = leapraid_get_task_desc(adapter, inter_taskid); init_completion(&adapter->driver_cmds.transport_cmd.done); - leapraid_fire_task(adapter, - adapter->driver_cmds.transport_cmd.inter_taskid); + leapraid_fire_task(adapter, inter_taskid); wait_for_completion_timeout(&adapter->driver_cmds.transport_cmd.done, LEAPRAID_TRANSPORT_CMD_TIMEOUT * HZ); if (!(adapter->driver_cmds.transport_cmd.status & LEAPRAID_CMD_DONE)) { dev_err(&adapter->pdev->dev, "%s: timeout, st=0x%x\n", __func__, adapter->driver_cmds.transport_cmd.status); - leapraid_log_req_context(adapter, smp_passthrough_req); + leapraid_log_req_context(adapter, inter_taskid, + smp_passthrough_req); if (!(adapter->driver_cmds.transport_cmd.status & LEAPRAID_CMD_RESET)) { dev_dbg(&adapter->pdev->dev, @@ -1343,6 +1343,14 @@ static void leapraid_transport_smp_handler(struct bsg_job *job, if (rc) goto release_lock; + if (h2c_size < LEAPRAID_SMP_FRAME_HEADER_SIZE) { + dev_err(&adapter->pdev->dev, + "%s: Invalid SMP request payload size=%zu\n", + __func__, h2c_size); + rc = -EINVAL; + goto free_req_buf; + } + if (addr_out) sg_copy_to_buffer(job->request_payload.sg_list, job->request_payload.sg_cnt, addr_out, @@ -1353,6 +1361,14 @@ static void leapraid_transport_smp_handler(struct bsg_job *job, if (rc) goto free_req_buf; + if (c2h_size < LEAPRAID_SMP_FRAME_HEADER_SIZE) { + dev_err(&adapter->pdev->dev, + "%s: Invalid SMP reply payload size=%zu\n", + __func__, c2h_size); + rc = -EINVAL; + goto free_rep_buf; + } + rc = leapraid_check_adapter_is_op(adapter, LEAPRAID_DB_WAIT_OP_SHORT, __func__); if (rc) -- 2.25.1
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://atomgit.com/openeuler/kernel/merge_requests/27457 邮件列表地址:https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/JSS... FeedBack: The patch(es) which you have sent to kernel@openeuler.org mailing list has been converted to a pull request successfully! Pull request link: https://atomgit.com/openeuler/kernel/merge_requests/27457 Mailing list address: https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/JSS...
participants (2)
-
haodongdong -
patchwork bot