Kernel
Threads by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- 38 participants
- 24725 discussions
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(a)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
2
1
LeapIO inclusion
category: feature
bugzilla: https://atomgit.com/openeuler/kernel/issues/9945
------------------------------------------
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(a)leap-io.com>
---
drivers/scsi/leapraid/leapraid.h | 37 +-
drivers/scsi/leapraid/leapraid_app.c | 169 ++-
drivers/scsi/leapraid/leapraid_func.c | 1130 +++++++-------------
drivers/scsi/leapraid/leapraid_func.h | 130 +--
drivers/scsi/leapraid/leapraid_os.c | 261 +++--
drivers/scsi/leapraid/leapraid_transport.c | 40 +-
6 files changed, 673 insertions(+), 1094 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 01096664d122..edb6530735ab 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 max_msix_vectors = LEAPRAID_INVALID_MSIX_VECTORS;
module_param(max_msix_vectors, int, 0444);
@@ -38,45 +23,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) &&
@@ -167,7 +130,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");
@@ -357,6 +319,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__);
@@ -490,11 +458,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 ||
@@ -591,6 +557,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)
@@ -628,8 +596,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);
@@ -1897,16 +1863,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) {
@@ -1933,7 +1889,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;
@@ -1946,8 +1902,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,
@@ -1969,12 +1925,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;
@@ -1983,8 +1939,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,
@@ -1998,32 +1954,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;
}
}
@@ -2034,19 +1992,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);
}
@@ -2059,11 +2016,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) {
@@ -2100,14 +2059,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;
}
@@ -2147,7 +2108,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);
@@ -2418,14 +2379,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;
@@ -2592,7 +2551,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;
@@ -2806,61 +2764,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;
@@ -2876,21 +2779,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:
@@ -2910,7 +2808,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,
@@ -2953,308 +2850,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;
@@ -3289,13 +2884,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);
@@ -3378,10 +2971,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;
}
@@ -3398,10 +2991,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);
@@ -3452,7 +3049,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;
@@ -3727,8 +3323,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;
@@ -3976,11 +3570,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;
@@ -4367,7 +3961,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,
@@ -4384,11 +3978,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)
@@ -4426,12 +4020,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;
@@ -4444,13 +4036,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,
@@ -4458,7 +4050,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);
@@ -4472,13 +4064,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)
@@ -4588,7 +4180,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);
@@ -4608,7 +4199,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__);
@@ -4637,10 +4227,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);
}
@@ -4971,7 +4559,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");
}
@@ -4996,7 +4584,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");
}
@@ -5020,7 +4608,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");
}
@@ -5138,8 +4726,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,
@@ -5170,8 +4756,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(
@@ -5188,8 +4772,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,
@@ -5238,8 +4820,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)
@@ -5264,7 +4844,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,
@@ -5301,8 +4880,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)
@@ -5315,9 +4892,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,
@@ -5367,14 +4941,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) {
@@ -5382,8 +4952,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)
@@ -5411,6 +4979,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,
@@ -5419,21 +4988,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);
@@ -5497,10 +5064,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);
@@ -5520,12 +5087,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;
}
@@ -5610,7 +5178,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;
@@ -5740,6 +5307,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)
@@ -5747,6 +5388,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(
@@ -5809,13 +5454,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;
@@ -5880,9 +5529,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;
@@ -5890,21 +5539,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,
@@ -5918,7 +5564,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;
@@ -5961,10 +5606,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);
@@ -5979,8 +5625,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;
@@ -6160,6 +5807,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;
@@ -6230,7 +5893,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);
@@ -6254,14 +5916,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;
}
@@ -6776,11 +6437,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;
@@ -6793,9 +6451,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,
@@ -6864,14 +6519,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;
@@ -6909,9 +6561,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,
@@ -6972,10 +6621,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;
@@ -6993,9 +6640,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)
@@ -7042,6 +6686,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,
@@ -7084,7 +6737,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;
}
@@ -7105,8 +6757,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;
@@ -7238,9 +6890,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;
@@ -7327,13 +6987,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);
@@ -7345,8 +7008,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;
@@ -7364,16 +7027,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)
{
@@ -7423,16 +7099,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",
@@ -7441,20 +7117,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,
@@ -7465,7 +7139,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",
@@ -7525,12 +7198,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 =
@@ -7547,9 +7217,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)
@@ -7558,14 +7226,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,
@@ -7628,31 +7293,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)
@@ -7661,14 +7315,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,
@@ -7711,10 +7362,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 =
@@ -7754,51 +7404,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;
}
@@ -7825,7 +7470,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;
@@ -7859,18 +7504,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;
}
@@ -7878,7 +7521,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))
@@ -7917,8 +7559,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)
@@ -7927,6 +7568,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),
@@ -8058,10 +7701,15 @@ 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;
}
if (adapter->mem_desc.io_tracker) {
@@ -8074,6 +7722,7 @@ static void leapraid_free_host_memory(struct leapraid_adapter *adapter)
}
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)
@@ -8095,15 +7744,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)
@@ -8149,12 +7796,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:
@@ -8197,7 +7841,6 @@ static int leapraid_request_host_memory(struct leapraid_adapter *adapter)
goto out_fail;
}
-
adapter->dynamic_task_desc.hp_taskid =
adapter->adapter_attr.io_qd +
LEAPRAID_HP_TASKID_OFFSET_CTL_CMD;
@@ -8219,9 +7862,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;
@@ -8281,8 +7921,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)) {
@@ -8394,9 +8037,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 =
@@ -8420,9 +8064,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;
@@ -8442,49 +8083,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_size += 32;
- 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.internal_scmd->cmnd = buffer;
- adapter->driver_cmds.internal_scmd->host_scribble =
- (unsigned char *)(adapter->driver_cmds.internal_scmd + 1);
-
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);
@@ -8628,7 +8226,6 @@ static int leapraid_send_adapter_init(struct leapraid_adapter *adapter)
rc = -EIO;
}
- adapter->timestamp_sync_cnt = 0;
return rc;
}
@@ -8636,48 +8233,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;
}
@@ -8786,8 +8387,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 +8535,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 +8543,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 +8582,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 +8601,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 +8615,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 359802578586..38a24915f8dd 100644
--- a/drivers/scsi/leapraid/leapraid_func.h
+++ b/drivers/scsi/leapraid/leapraid_func.h
@@ -50,11 +50,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
@@ -76,7 +76,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. */
@@ -87,8 +86,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
@@ -102,7 +99,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
@@ -126,7 +122,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
@@ -170,13 +165,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
@@ -186,7 +177,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
@@ -197,17 +187,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
@@ -222,21 +209,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
@@ -283,6 +261,8 @@ struct leapraid_adapter_features {
u8 max_volumes;
u16 max_dev_handle;
u16 min_dev_handle;
+ u16 msg_ver;
+ u16 product_id;
};
/**
@@ -423,7 +403,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
@@ -438,9 +418,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.
@@ -451,14 +428,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
};
@@ -521,28 +495,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;
};
/**
@@ -598,6 +564,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 */
@@ -605,7 +572,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];
};
/**
@@ -659,8 +625,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.
@@ -707,7 +673,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;
@@ -721,7 +686,6 @@ struct leapraid_reset_desc {
int pending_io_cnt;
wait_queue_head_t reset_wait_queue;
u32 reset_cnt;
- u32 last_reset_cnt;
};
/**
@@ -775,7 +739,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;
@@ -785,7 +750,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
@@ -938,19 +904,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
*
@@ -960,7 +913,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.
@@ -973,7 +925,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 {
@@ -983,7 +934,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;
@@ -997,7 +947,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;
};
@@ -1115,6 +1064,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.
@@ -1123,7 +1073,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;
@@ -1156,7 +1106,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;
@@ -1183,7 +1132,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)
@@ -1361,31 +1309,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];
@@ -1444,7 +1367,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);
@@ -1515,7 +1438,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);
@@ -1555,10 +1478,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 5a6cda0b5ea8..144c859ab25d 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);
@@ -511,11 +503,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;
@@ -524,13 +516,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");
}
}
@@ -542,10 +534,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;
@@ -572,13 +561,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);
scmd->scsi_done(scmd);
return false;
@@ -647,7 +629,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;
@@ -784,7 +765,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[] = {
@@ -808,10 +788,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;
}
@@ -863,10 +840,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))
- scmd->scsi_done(scmd);
- else
- *rc = LEAPRAID_OPERATION_FAILED;
+ scmd->scsi_done(scmd);
return false;
}
@@ -890,7 +864,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(scmd->request)) ==
IOPRIO_CLASS_RT))
control |= LEAPRAID_SCSIIO_CTRL_CMDPRI;
@@ -920,10 +894,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;
@@ -1084,13 +1055,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);
}
@@ -1144,8 +1117,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;
}
@@ -1210,7 +1185,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);
@@ -1259,10 +1234,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;
@@ -1569,11 +1544,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;
@@ -1785,12 +1758,11 @@ static struct device_attribute *leapraid_shost_attrs[] = {
NULL,
};
-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,
@@ -1798,30 +1770,59 @@ static ssize_t sas_address_show(struct device *dev,
return -EINVAL;
}
- sas_address = sas_device_priv_data->starget_priv->sas_address;
-
- return scnprintf(buf, PAGE_SIZE, "0x%016llx\n",
- (unsigned long long)sas_address);
+ return scnprintf(buf, PAGE_SIZE, "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_device *sdev = to_scsi_device(dev);
- struct leapraid_sdev_priv *sas_device_priv_data = sdev->hostdata;
+ unsigned char *vpd_pg89;
+ unsigned int vpd_len;
+ 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;
+ *supported = false;
+ if (!scsi_device_supports_vpd(sdev))
+ return 0;
+
+ vpd_pg89 = kzalloc(LEAPRAID_VPD_PG89_MAX_LEN, GFP_KERNEL);
+ if (!vpd_pg89)
+ return -ENOMEM;
+
+ rc = scsi_get_vpd_page(sdev, LEAPRAID_VPD_PAGE_ATA_INFO,
+ vpd_pg89, LEAPRAID_VPD_PG89_MAX_LEN);
+ if (rc) {
+ kfree(vpd_pg89);
+ return rc;
}
- return scnprintf(buf, PAGE_SIZE, "0x%04x\n",
- sas_device_priv_data->starget_priv->hdl);
+ vpd_len = ((unsigned int)vpd_pg89[2] << 8) | vpd_pg89[3];
+ if (vpd_len + 4 >= LEAPRAID_VPD_PG89_MIN_LEN)
+ *supported =
+ (vpd_pg89[LEAPRAID_VPD_PG89_NCQ_BYTE_IDX] >>
+ LEAPRAID_VPD_PG89_NCQ_BIT_SHIFT) &
+ LEAPRAID_VPD_PG89_NCQ_BIT_MASK;
+ kfree(vpd_pg89);
+ 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);
+ bool supported;
+ int rc;
-static ssize_t sas_ncq_show(struct device *dev, struct device_attribute *attr,
- char *buf)
+ rc = leapraid_ncq_prio_supported(sdev, &supported);
+ if (rc)
+ return rc;
+
+ return scnprintf(buf, PAGE_SIZE, "%d\n", supported);
+}
+
+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;
@@ -1832,18 +1833,19 @@ static ssize_t sas_ncq_show(struct device *dev, struct device_attribute *attr,
return -EINVAL;
}
- return scnprintf(buf, PAGE_SIZE, "%d\n", sas_device_priv_data->ncq);
+ return scnprintf(buf, PAGE_SIZE, "%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;
- unsigned char *vpd_pg89;
- int ncq_op;
- bool ncq_supported;
+ bool supported;
+ int rc;
+ bool enable;
if (!sas_device_priv_data) {
dev_err(&sdev->sdev_gendev,
@@ -1851,45 +1853,27 @@ 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;
- }
-
- vpd_pg89 = kmalloc(LEAPRAID_VPD_PG89_MAX_LEN, GFP_KERNEL);
- if (!vpd_pg89)
- return -ENOMEM;
- if (!scsi_device_supports_vpd(sdev) ||
- scsi_get_vpd_page(sdev, LEAPRAID_VPD_PAGE_ATA_INFO,
- vpd_pg89, LEAPRAID_VPD_PG89_MAX_LEN)) {
- kfree(vpd_pg89);
+ rc = leapraid_ncq_prio_supported(sdev, &supported);
+ if (rc)
+ return rc;
+ if (!supported)
return -EINVAL;
- }
- ncq_supported = (vpd_pg89[LEAPRAID_VPD_PG89_NCQ_BYTE_IDX] >>
- LEAPRAID_VPD_PG89_NCQ_BIT_SHIFT) &
- LEAPRAID_VPD_PG89_NCQ_BIT_MASK;
- kfree(vpd_pg89);
- 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_RW(sas_ncq);
+static DEVICE_ATTR_RO(sas_ncq_prio_supported);
+static DEVICE_ATTR_RW(sas_ncq_prio_enable);
static struct device_attribute *leapraid_sdev_attrs[] = {
- &dev_attr_sas_address,
&dev_attr_sas_device_handle,
- &dev_attr_sas_ncq,
+ &dev_attr_sas_ncq_prio_supported,
+ &dev_attr_sas_ncq_prio_enable,
NULL,
};
@@ -1974,13 +1958,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",
@@ -2021,6 +2004,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;
@@ -2030,9 +2017,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;
}
@@ -2115,13 +2099,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);
@@ -2138,9 +2122,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);
}
@@ -2157,7 +2138,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);
@@ -2193,7 +2173,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);
@@ -2201,7 +2180,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);
@@ -2244,7 +2222,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)) {
@@ -2254,13 +2231,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;
@@ -2277,11 +2256,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);
@@ -2306,7 +2285,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);
flush_scheduled_work();
@@ -2363,7 +2341,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
2
1
bugfix for dpool
Wupeng Ma (5):
dpool: Fix refcount leak when page not in dpagelist
mm/dpool: fix race between fill_pool and page_in_dynamic_pool
dpool: fix compile error for CONFIG_MEMORY_RELIABLE
mm/dpool: allow longterm pin for dpool
mm/dpool: hide dpool related files if not enabled
include/linux/dynamic_pool.h | 29 +++++------------------------
include/linux/mm.h | 36 ++++++++++++++++++++++++++++++++++++
mm/dynamic_pool.c | 31 +++++++++++++++++++++++++------
mm/gup.c | 3 ++-
4 files changed, 68 insertions(+), 31 deletions(-)
--
2.43.0
2
6
[PATCH openEuler-1.0-LTS] ipvlan: inherit needed_headroom and needed_tailroom from phy_dev
by JiangJieHua 11 Sep '26
by JiangJieHua 11 Sep '26
11 Sep '26
From: Eric Dumazet <edumazet(a)google.com>
mainline inclusion
from mainline-v7.2
commit e16e960d55a40d36bd7c2494cc005e757dc9a1ef
category: bugfix
bugzilla: https://atomgit.com/src-openeuler/kernel/issues/18377
CVE: CVE-2026-74744
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?…
--------------------------------
ipvlan devices inherit hard_header_len from phy_dev during ipvlan_init(),
but leave needed_headroom and needed_tailroom set to 0.
When the underlying phy_dev (or stacked lower device) requires extra headroom
or tailroom for headers/trailers (e.g. macsec, ipsec, wireguard, tunnels, or
veth with rx headroom), upper layers calculating packet headroom and tailroom
fail to reserve sufficient space.
This can result in reallocation overhead, skb headroom underflows, or KASAN
slab-use-after-free crashes when dev_hard_header() / ipvlan_hard_header()
prepends header data or when lower devices append tailroom.
Fix this by:
1. Inheriting needed_headroom and needed_tailroom from phy_dev in ipvlan_init().
2. Propagating needed_headroom and needed_tailroom updates to attached ipvlans
in ipvlan_device_event() when receiving NETDEV_FEAT_CHANGE events.
Fixes: 2ad7bf363841 ("ipvlan: Initial check-in of the IPVLAN driver.")
Reported-by: syzbot+1f9fd0f4b601cf88d6e6(a)syzkaller.appspotmail.com
Closes: https://lore.kernel.org/netdev/6a720a21.40259c87.584f4.04bb.GAE@google.com/…
Reported-by: Tangxin Xie <xietangxin(a)h-partners.com>
Closes: https://lore.kernel.org/netdev/CANn89i+1EW-sFNK8xoq98gMbPCeLS7e=+rs9gHfLg5W…
Signed-off-by: Eric Dumazet <edumazet(a)google.com>
Reviewed-by: Hangbin Liu <liuhangbin(a)kylinos.cn>
Link: https://patch.msgid.link/20260806103857.115541-1-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba(a)kernel.org>
Conflicts:
drivers/net/ipvlan/ipvlan_main.c
[Context differences are due to the following patches not being merged:
a4d2113e46c1 ("ipvlan: set hw_enc_features like macvlan")
6df6398f7c8b ("net: add netif_inherit_tso_max()")
00d066a4d4ed ("netdev_features: convert NETIF_F_LLTX to dev->lltx")]
Signed-off-by: JiangJieHua <jiangjiehua1(a)huawei.com>
---
drivers/net/ipvlan/ipvlan_main.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c
index 9057cdf9b2162..ed1a5af42b072 100644
--- a/drivers/net/ipvlan/ipvlan_main.c
+++ b/drivers/net/ipvlan/ipvlan_main.c
@@ -258,6 +258,8 @@ static int ipvlan_init(struct net_device *dev)
dev->gso_max_size = phy_dev->gso_max_size;
dev->gso_max_segs = phy_dev->gso_max_segs;
dev->hard_header_len = phy_dev->hard_header_len;
+ dev->needed_headroom = phy_dev->needed_headroom;
+ dev->needed_tailroom = phy_dev->needed_tailroom;
netdev_lockdep_set_classes(dev);
@@ -899,6 +901,8 @@ static int ipvlan_device_event(struct notifier_block *unused,
list_for_each_entry(ipvlan, &port->ipvlans, pnode) {
ipvlan->dev->gso_max_size = dev->gso_max_size;
ipvlan->dev->gso_max_segs = dev->gso_max_segs;
+ ipvlan->dev->needed_headroom = dev->needed_headroom;
+ ipvlan->dev->needed_tailroom = dev->needed_tailroom;
netdev_update_features(ipvlan->dev);
}
break;
--
2.33.8
2
1
[PATCH openEuler-1.0-LTS] ipvlan: inherit needed_headroom and needed_tailroom from phy_dev
by JiangJieHua 11 Sep '26
by JiangJieHua 11 Sep '26
11 Sep '26
From: Eric Dumazet <edumazet(a)google.com>
mainline inclusion
from mainline-v7.2
commit e16e960d55a40d36bd7c2494cc005e757dc9a1ef
category: bugfix
bugzilla: https://atomgit.com/src-openeuler/kernel/issues/18377
CVE: CVE-2026-74744
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?…
--------------------------------
ipvlan devices inherit hard_header_len from phy_dev during ipvlan_init(),
but leave needed_headroom and needed_tailroom set to 0.
When the underlying phy_dev (or stacked lower device) requires extra headroom
or tailroom for headers/trailers (e.g. macsec, ipsec, wireguard, tunnels, or
veth with rx headroom), upper layers calculating packet headroom and tailroom
fail to reserve sufficient space.
This can result in reallocation overhead, skb headroom underflows, or KASAN
slab-use-after-free crashes when dev_hard_header() / ipvlan_hard_header()
prepends header data or when lower devices append tailroom.
Fix this by:
1. Inheriting needed_headroom and needed_tailroom from phy_dev in ipvlan_init().
2. Propagating needed_headroom and needed_tailroom updates to attached ipvlans
in ipvlan_device_event() when receiving NETDEV_FEAT_CHANGE events.
Fixes: 2ad7bf363841 ("ipvlan: Initial check-in of the IPVLAN driver.")
Reported-by: syzbot+1f9fd0f4b601cf88d6e6(a)syzkaller.appspotmail.com
Closes: https://lore.kernel.org/netdev/6a720a21.40259c87.584f4.04bb.GAE@google.com/…
Reported-by: Tangxin Xie <xietangxin(a)h-partners.com>
Closes: https://lore.kernel.org/netdev/CANn89i+1EW-sFNK8xoq98gMbPCeLS7e=+rs9gHfLg5W…
Signed-off-by: Eric Dumazet <edumazet(a)google.com>
Reviewed-by: Hangbin Liu <liuhangbin(a)kylinos.cn>
Link: https://patch.msgid.link/20260806103857.115541-1-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba(a)kernel.org>
Conflicts:
drivers/net/ipvlan/ipvlan_main.c
[Context differences are due to the following patches not being merged:
a4d2113e46c1 ("ipvlan: set hw_enc_features like macvlan")
6df6398f7c8b ("net: add netif_inherit_tso_max()")
00d066a4d4ed ("netdev_features: convert NETIF_F_LLTX to dev->lltx")]
]
Signed-off-by: JiangJieHua <jiangjiehua1(a)huawei.com>
---
drivers/net/ipvlan/ipvlan_main.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c
index 9057cdf9b2162..ed1a5af42b072 100644
--- a/drivers/net/ipvlan/ipvlan_main.c
+++ b/drivers/net/ipvlan/ipvlan_main.c
@@ -258,6 +258,8 @@ static int ipvlan_init(struct net_device *dev)
dev->gso_max_size = phy_dev->gso_max_size;
dev->gso_max_segs = phy_dev->gso_max_segs;
dev->hard_header_len = phy_dev->hard_header_len;
+ dev->needed_headroom = phy_dev->needed_headroom;
+ dev->needed_tailroom = phy_dev->needed_tailroom;
netdev_lockdep_set_classes(dev);
@@ -899,6 +901,8 @@ static int ipvlan_device_event(struct notifier_block *unused,
list_for_each_entry(ipvlan, &port->ipvlans, pnode) {
ipvlan->dev->gso_max_size = dev->gso_max_size;
ipvlan->dev->gso_max_segs = dev->gso_max_segs;
+ ipvlan->dev->needed_headroom = dev->needed_headroom;
+ ipvlan->dev->needed_tailroom = dev->needed_tailroom;
netdev_update_features(ipvlan->dev);
}
break;
--
2.33.8
2
1
[PATCH openEuler-1.0-LTS] ipv6: mcast: Fix potential UAF in MLD delayed work
by JiangJieHua 11 Sep '26
by JiangJieHua 11 Sep '26
11 Sep '26
From: Eric Dumazet <edumazet(a)google.com>
mainline inclusion
from mainline-v7.2-rc3
commit 9b26518b6896a16b809b1e42986f4ebac7bccc1e
category: bugfix
bugzilla: https://atomgit.com/src-openeuler/kernel/issues/17356
CVE: CVE-2026-72322
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?…
--------------------------------
A race condition exists between device teardown and incoming MLD query
processing, leading to a Use-After-Free in the MLD delayed work.
During device destruction, the primary reference to inet6_dev is dropped,
which can drop its refcount to 0. The actual freeing of inet6_dev memory
is deferred via RCU.
Concurrently, the packet receive path runs under RCU read lock and obtains
the inet6_dev pointer. Because the memory is RCU-protected, CPU-0 can
safely dereference inet6_dev even if its refcount has hit 0.
However, if CPU-0 calls igmp6_event_query() and schedules delayed work, it
attempts to acquire a reference using in6_dev_hold(). This increments the
refcount from 0 to 1, triggering a "refcount_t: addition on 0" warning.
Since the inet6_dev memory is still scheduled to be freed after the RCU
grace period, the device is freed while the work is still scheduled.
When the work runs, it accesses the freed memory, causing a kernel panic.
Fix this by using refcount_inc_not_zero() (via a new helper
in6_dev_hold_safe()) to prevent acquiring a reference if the device is
already being destroyed. If the refcount is 0, we do not schedule the work.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Eric Dumazet <edumazet(a)google.com>
Reviewed-by: Ido Schimmel <idosch(a)nvidia.com>
Link: https://patch.msgid.link/20260705181756.963063-3-edumazet@google.com
Signed-off-by: Paolo Abeni <pabeni(a)redhat.com>
Conflicts:
include/net/addrconf.h
net/ipv6/mcast.c
[Context differences are due to the following patches not being merged:
2d9a93b4902b ("mld: convert from timer to delayed work")
f185de28d9ae ("mld: add new workqueues for process mld events")
81895a65ec63 ("treewide: use prandom_u32_max() when possible, part 1")
8032bf1233a7 ("treewide: use get_random_u32_below() instead of deprecated function")]
Signed-off-by: JiangJieHua <jiangjiehua1(a)huawei.com>
---
include/net/addrconf.h | 5 +++++
net/ipv6/mcast.c | 18 ++++++++++++------
2 files changed, 17 insertions(+), 6 deletions(-)
diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index 10d270f004f0d..26f0a5bc234be 100644
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -425,6 +425,11 @@ static inline void in6_dev_hold(struct inet6_dev *idev)
refcount_inc(&idev->refcnt);
}
+static inline bool in6_dev_hold_safe(struct inet6_dev *idev)
+{
+ return refcount_inc_not_zero(&idev->refcnt);
+}
+
void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp);
static inline void in6_ifa_put(struct inet6_ifaddr *ifp)
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index bb484fe27e137..787800af097a5 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -1037,8 +1037,10 @@ static void mld_gq_start_timer(struct inet6_dev *idev)
unsigned long tv = prandom_u32() % idev->mc_maxdelay;
idev->mc_gq_running = 1;
- if (!mod_timer(&idev->mc_gq_timer, jiffies+tv+2))
- in6_dev_hold(idev);
+ if (in6_dev_hold_safe(idev)) {
+ if (mod_timer(&idev->mc_gq_timer, jiffies+tv+2))
+ in6_dev_put(idev);
+ }
}
static void mld_gq_stop_timer(struct inet6_dev *idev)
@@ -1052,8 +1054,10 @@ static void mld_ifc_start_timer(struct inet6_dev *idev, unsigned long delay)
{
unsigned long tv = prandom_u32() % delay;
- if (!mod_timer(&idev->mc_ifc_timer, jiffies+tv+2))
- in6_dev_hold(idev);
+ if (in6_dev_hold_safe(idev)) {
+ if (mod_timer(&idev->mc_ifc_timer, jiffies+tv+2))
+ in6_dev_put(idev);
+ }
}
static void mld_ifc_stop_timer(struct inet6_dev *idev)
@@ -1067,8 +1071,10 @@ static void mld_dad_start_timer(struct inet6_dev *idev, unsigned long delay)
{
unsigned long tv = prandom_u32() % delay;
- if (!mod_timer(&idev->mc_dad_timer, jiffies+tv+2))
- in6_dev_hold(idev);
+ if (in6_dev_hold_safe(idev)) {
+ if (mod_timer(&idev->mc_dad_timer, jiffies+tv+2))
+ in6_dev_put(idev);
+ }
}
static void mld_dad_stop_timer(struct inet6_dev *idev)
--
2.33.8
2
1
[PATCH OLK-6.6 v4 0/5] cgroup/cpuset: Backport upstream remote partition accounting fixes
by Zhang Qiao 11 Sep '26
by Zhang Qiao 11 Sep '26
11 Sep '26
This series backports a minimal set of upstream cpuset fixes to
openEuler OLK-6.6 so that remote partition operations no longer
trigger list BUG_ON / use-after-free / oops / panic under the
no-hotplug high-concurrency cpuset stress test (fn_warn_repro_008
without CPU online/offline). Verified stable over 50 rounds (KASAN +
CONFIG_DEBUG_LIST): no list corruption, KASAN UAF, BUG, Oops or panic.
Bugzilla: https://atomgit.com/openeuler/kernel/issues/9899
The 5 backports (in mainline order):
1. cgroup/cpuset: Correct invalid remote parition prs
2. cgroup/cpuset: Fix incorrect isolated_cpus update in
update_parent_effective_cpumask()
3. cgroup/cpuset: Fix error handling in remote_partition_disable()
4. cgroup/cpuset: Remove remote_partition_check() & make
update_cpumasks_hier() handle remote partition
5. cpuset: remove global remote_children list
Patches 4 and 5 are the core fix: they route remote partition teardown
through the centralized update_cpumasks_hier() path and drop the global
remote_children linked list that was the source of the list corruption /
UAF. Patches 1-3 are required prerequisites (PERR_ACCESS enum, effective
xcpus accounting, and remote_partition_disable error handling).
Chen Ridong (2):
cgroup/cpuset: Correct invalid remote parition prs
cpuset: remove global remote_children list
Waiman Long (3):
cgroup/cpuset: Fix incorrect isolated_cpus update in
update_parent_effective_cpumask()
cgroup/cpuset: Fix error handling in remote_partition_disable()
cgroup/cpuset: Remove remote_partition_check() & make
update_cpumasks_hier() handle remote partition
kernel/cgroup/cpuset.c | 354 +++++++++++++++++++++++------------------
1 file changed, 203 insertions(+), 151 deletions(-)
--
2.18.0
2
6
[PATCH OLK-6.6 v4 0/5] cgroup/cpuset: Backport upstream remote partition accounting fixes
by Zhang Qiao 11 Sep '26
by Zhang Qiao 11 Sep '26
11 Sep '26
This series backports a minimal set of upstream cpuset fixes to
openEuler OLK-6.6 so that remote partition operations no longer
trigger list BUG_ON / use-after-free / oops / panic under the
no-hotplug high-concurrency cpuset stress test (fn_warn_repro_008
without CPU online/offline). Verified stable over 50 rounds (KASAN +
CONFIG_DEBUG_LIST): no list corruption, KASAN UAF, BUG, Oops or panic.
Bugzilla: https://atomgit.com/openeuler/kernel/issues/9899
The 5 backports (in mainline order):
1. cgroup/cpuset: Correct invalid remote parition prs
2. cgroup/cpuset: Fix incorrect isolated_cpus update in
update_parent_effective_cpumask()
3. cgroup/cpuset: Fix error handling in remote_partition_disable()
4. cgroup/cpuset: Remove remote_partition_check() & make
update_cpumasks_hier() handle remote partition
5. cpuset: remove global remote_children list
Patches 4 and 5 are the core fix: they route remote partition teardown
through the centralized update_cpumasks_hier() path and drop the global
remote_children linked list that was the source of the list corruption /
UAF. Patches 1-3 are required prerequisites (PERR_ACCESS enum, effective
xcpus accounting, and remote_partition_disable error handling).
Chen Ridong (2):
cgroup/cpuset: Correct invalid remote parition prs
cpuset: remove global remote_children list
Waiman Long (3):
cgroup/cpuset: Fix incorrect isolated_cpus update in
update_parent_effective_cpumask()
cgroup/cpuset: Fix error handling in remote_partition_disable()
cgroup/cpuset: Remove remote_partition_check() & make
update_cpumasks_hier() handle remote partition
kernel/cgroup/cpuset.c | 354 +++++++++++++++++++++++------------------
1 file changed, 203 insertions(+), 151 deletions(-)
--
2.18.0
2
6
[PATCH OLK-6.6 v4 0/5] cgroup/cpuset: Backport upstream remote partition accounting fixes
by Zhang Qiao 11 Sep '26
by Zhang Qiao 11 Sep '26
11 Sep '26
This series backports a minimal set of upstream cpuset fixes to
openEuler OLK-6.6 so that remote partition operations no longer
trigger list BUG_ON / use-after-free / oops / panic under the
no-hotplug high-concurrency cpuset stress test (fn_warn_repro_008
without CPU online/offline). Verified stable over 50 rounds (KASAN +
CONFIG_DEBUG_LIST): no list corruption, KASAN UAF, BUG, Oops or panic.
Bugzilla: https://atomgit.com/openeuler/kernel/issues/9899
The 5 backports (in mainline order):
1. cgroup/cpuset: Correct invalid remote parition prs
2. cgroup/cpuset: Fix incorrect isolated_cpus update in
update_parent_effective_cpumask()
3. cgroup/cpuset: Fix error handling in remote_partition_disable()
4. cgroup/cpuset: Remove remote_partition_check() & make
update_cpumasks_hier() handle remote partition
5. cpuset: remove global remote_children list
Patches 4 and 5 are the core fix: they route remote partition teardown
through the centralized update_cpumasks_hier() path and drop the global
remote_children linked list that was the source of the list corruption /
UAF. Patches 1-3 are required prerequisites (PERR_ACCESS enum, effective
xcpus accounting, and remote_partition_disable error handling).
Chen Ridong (2):
cgroup/cpuset: Correct invalid remote parition prs
cpuset: remove global remote_children list
Waiman Long (3):
cgroup/cpuset: Fix incorrect isolated_cpus update in
update_parent_effective_cpumask()
cgroup/cpuset: Fix error handling in remote_partition_disable()
cgroup/cpuset: Remove remote_partition_check() & make
update_cpumasks_hier() handle remote partition
kernel/cgroup/cpuset.c | 354 +++++++++++++++++++++++------------------
1 file changed, 203 insertions(+), 151 deletions(-)
--
2.18.0
2
6
11 Sep '26
From: Chen Ridong <chenridong(a)huawei.com>
mainline inclusion
from mainline-v6.12
commit e55f45b4bafee0ef488e815aa88368444ec5c79c
category: bugfix
bugzilla: https://atomgit.com/openeuler/kernel/issues/9899
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?…
--------------------------------
When enable a remote partition, I found that:
cd /sys/fs/cgroup/
mkdir test
mkdir test/test1
echo +cpuset > cgroup.subtree_control
echo +cpuset > test/cgroup.subtree_control
echo 3 > test/test1/cpuset.cpus
echo root > test/test1/cpuset.cpus.partition
cat test/test1/cpuset.cpus.partition
root invalid (Parent is not a partition root)
The parent of a remote partition could not be a root. This is due to the
emtpy effective_xcpus. It would be better to prompt the message "invalid
cpu list in cpuset.cpus.exclusive".
Signed-off-by: Chen Ridong <chenridong(a)huawei.com>
Reviewed-by: Waiman Long <longman(a)redhat.com>
Signed-off-by: Tejun Heo <tj(a)kernel.org>
Conflicts:
kernel/cgroup/cpuset.c
[
OLK-6.6 does not have the partcmd_enablei command (isolated partition
rework not backported); update_prstate() enables a local partition with
partcmd_enable only. remote_partition_enable() keeps the (cs, tmp)
signature as the upstream new_prs parameter comes from a commit not
backported.
]
Signed-off-by: Zhang Qiao <zhangqiao22(a)huawei.com>
---
kernel/cgroup/cpuset.c | 24 ++++++++++++++----------
1 file changed, 14 insertions(+), 10 deletions(-)
diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index 3823e17157b1..d0fa90510e07 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -84,6 +84,7 @@ enum prs_errcode {
PERR_HOTPLUG,
PERR_CPUSEMPTY,
PERR_HKEEPING,
+ PERR_ACCESS,
};
static const char * const perr_strings[] = {
@@ -95,6 +96,7 @@ static const char * const perr_strings[] = {
[PERR_HOTPLUG] = "No cpu available due to hotplug",
[PERR_CPUSEMPTY] = "cpuset.cpus and cpuset.cpus.exclusive are empty",
[PERR_HKEEPING] = "partition config conflicts with housekeeping setup",
+ [PERR_ACCESS] = "Enable partition not permitted",
};
struct cpuset {
@@ -1686,7 +1688,7 @@ static inline bool is_local_partition(struct cpuset *cs)
* remote_partition_enable - Enable current cpuset as a remote partition root
* @cs: the cpuset to update
* @tmp: temparary masks
- * Return: 1 if successful, 0 if error
+ * Return: 0 if successful, errcode if error
*
* Enable the current cpuset to become a remote partition root taking CPUs
* directly from the top cpuset. cpuset_mutex must be held by the caller.
@@ -1697,7 +1699,7 @@ static int remote_partition_enable(struct cpuset *cs, struct tmpmasks *tmp)
* The user must have sysadmin privilege.
*/
if (!capable(CAP_SYS_ADMIN))
- return 0;
+ return PERR_ACCESS;
/*
* The requested exclusive_cpus must not be allocated to other
@@ -1711,7 +1713,7 @@ static int remote_partition_enable(struct cpuset *cs, struct tmpmasks *tmp)
if (cpumask_empty(tmp->new_cpus) ||
cpumask_intersects(tmp->new_cpus, subpartitions_cpus) ||
cpumask_subset(top_cpuset.effective_cpus, tmp->new_cpus))
- return 0;
+ return PERR_INVCPUS;
spin_lock_irq(&callback_lock);
cpumask_andnot(top_cpuset.effective_cpus,
@@ -1734,7 +1736,7 @@ static int remote_partition_enable(struct cpuset *cs, struct tmpmasks *tmp)
update_tasks_cpumask(&top_cpuset, tmp->new_cpus);
update_sibling_cpumasks(&top_cpuset, NULL, tmp);
- return 1;
+ return 0;
}
/*
@@ -3216,14 +3218,16 @@ static int update_prstate(struct cpuset *cs, int new_prs)
goto out;
}
- err = update_parent_effective_cpumask(cs, partcmd_enable,
- NULL, &tmpmask);
/*
- * If an attempt to become local partition root fails,
- * try to become a remote partition root instead.
+ * If parent is valid partition, enable local partiion.
+ * Otherwise, enable a remote partition.
*/
- if (err && remote_partition_enable(cs, &tmpmask))
- err = 0;
+ if (is_partition_valid(parent)) {
+ err = update_parent_effective_cpumask(cs, partcmd_enable,
+ NULL, &tmpmask);
+ } else {
+ err = remote_partition_enable(cs, &tmpmask);
+ }
} else if (old_prs && new_prs) {
/*
* A change in load balance state only, no change in cpumasks.
--
2.18.0
2
5