scsi: mpt3sas: Additional diagnostic buffer query interface
When a host trace buffer is released, applications never know for what reason the buffer is released. Add a new IOCTL MPT3ADDNLDIAGQUERY to provide the trigger information due to which the diag buffer is released. Link: https://lore.kernel.org/r/20210204033724.1345-2-suganath-prabu.subramani@broadcom.com Signed-off-by: Suganath Prabu S <suganath-prabu.subramani@broadcom.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
Родитель
664f0dce20
Коммит
688c1a0a13
|
@ -8191,8 +8191,11 @@ mpt3sas_base_hard_reset_handler(struct MPT3SAS_ADAPTER *ioc,
|
||||||
ioc_state = mpt3sas_base_get_iocstate(ioc, 0);
|
ioc_state = mpt3sas_base_get_iocstate(ioc, 0);
|
||||||
if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT ||
|
if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT ||
|
||||||
(ioc_state & MPI2_IOC_STATE_MASK) ==
|
(ioc_state & MPI2_IOC_STATE_MASK) ==
|
||||||
MPI2_IOC_STATE_COREDUMP)
|
MPI2_IOC_STATE_COREDUMP) {
|
||||||
is_fault = 1;
|
is_fault = 1;
|
||||||
|
ioc->htb_rel.trigger_info_dwords[1] =
|
||||||
|
(ioc_state & MPI2_DOORBELL_DATA_MASK);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_base_pre_reset_handler(ioc);
|
_base_pre_reset_handler(ioc);
|
||||||
mpt3sas_wait_for_commands_to_complete(ioc);
|
mpt3sas_wait_for_commands_to_complete(ioc);
|
||||||
|
|
|
@ -1073,6 +1073,50 @@ struct hba_port {
|
||||||
|
|
||||||
#define MULTIPATH_DISABLED_PORT_ID 0xFF
|
#define MULTIPATH_DISABLED_PORT_ID 0xFF
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct htb_rel_query - diagnostic buffer release reason
|
||||||
|
* @unique_id - unique id associated with this buffer.
|
||||||
|
* @buffer_rel_condition - Release condition ioctl/sysfs/reset
|
||||||
|
* @reserved
|
||||||
|
* @trigger_type - Master/Event/scsi/MPI
|
||||||
|
* @trigger_info_dwords - Data Correspondig to trigger type
|
||||||
|
*/
|
||||||
|
struct htb_rel_query {
|
||||||
|
u16 buffer_rel_condition;
|
||||||
|
u16 reserved;
|
||||||
|
u32 trigger_type;
|
||||||
|
u32 trigger_info_dwords[2];
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Buffer_rel_condition bit fields */
|
||||||
|
|
||||||
|
/* Bit 0 - Diag Buffer not Released */
|
||||||
|
#define MPT3_DIAG_BUFFER_NOT_RELEASED (0x00)
|
||||||
|
/* Bit 0 - Diag Buffer Released */
|
||||||
|
#define MPT3_DIAG_BUFFER_RELEASED (0x01)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Bit 1 - Diag Buffer Released by IOCTL,
|
||||||
|
* This bit is valid only if Bit 0 is one
|
||||||
|
*/
|
||||||
|
#define MPT3_DIAG_BUFFER_REL_IOCTL (0x02 | MPT3_DIAG_BUFFER_RELEASED)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Bit 2 - Diag Buffer Released by Trigger,
|
||||||
|
* This bit is valid only if Bit 0 is one
|
||||||
|
*/
|
||||||
|
#define MPT3_DIAG_BUFFER_REL_TRIGGER (0x04 | MPT3_DIAG_BUFFER_RELEASED)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Bit 3 - Diag Buffer Released by SysFs,
|
||||||
|
* This bit is valid only if Bit 0 is one
|
||||||
|
*/
|
||||||
|
#define MPT3_DIAG_BUFFER_REL_SYSFS (0x08 | MPT3_DIAG_BUFFER_RELEASED)
|
||||||
|
|
||||||
|
/* DIAG RESET Master trigger flags */
|
||||||
|
#define MPT_DIAG_RESET_ISSUED_BY_DRIVER 0x00000000
|
||||||
|
#define MPT_DIAG_RESET_ISSUED_BY_USER 0x00000001
|
||||||
|
|
||||||
typedef void (*MPT3SAS_FLUSH_RUNNING_CMDS)(struct MPT3SAS_ADAPTER *ioc);
|
typedef void (*MPT3SAS_FLUSH_RUNNING_CMDS)(struct MPT3SAS_ADAPTER *ioc);
|
||||||
/**
|
/**
|
||||||
* struct MPT3SAS_ADAPTER - per adapter struct
|
* struct MPT3SAS_ADAPTER - per adapter struct
|
||||||
|
@ -1530,6 +1574,8 @@ struct MPT3SAS_ADAPTER {
|
||||||
u32 diagnostic_flags[MPI2_DIAG_BUF_TYPE_COUNT];
|
u32 diagnostic_flags[MPI2_DIAG_BUF_TYPE_COUNT];
|
||||||
u32 ring_buffer_offset;
|
u32 ring_buffer_offset;
|
||||||
u32 ring_buffer_sz;
|
u32 ring_buffer_sz;
|
||||||
|
struct htb_rel_query htb_rel;
|
||||||
|
u8 reset_from_user;
|
||||||
u8 is_warpdrive;
|
u8 is_warpdrive;
|
||||||
u8 is_mcpu_endpoint;
|
u8 is_mcpu_endpoint;
|
||||||
u8 hide_ir_msg;
|
u8 hide_ir_msg;
|
||||||
|
@ -1566,6 +1612,7 @@ struct mpt3sas_debugfs_buffer {
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MPT_DRV_SUPPORT_BITMAP_MEMMOVE 0x00000001
|
#define MPT_DRV_SUPPORT_BITMAP_MEMMOVE 0x00000001
|
||||||
|
#define MPT_DRV_SUPPORT_BITMAP_ADDNLQUERY 0x00000002
|
||||||
|
|
||||||
typedef u8 (*MPT_CALLBACK)(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
|
typedef u8 (*MPT_CALLBACK)(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
|
||||||
u32 reply);
|
u32 reply);
|
||||||
|
|
|
@ -479,6 +479,8 @@ void mpt3sas_ctl_pre_reset_handler(struct MPT3SAS_ADAPTER *ioc)
|
||||||
ioc_info(ioc,
|
ioc_info(ioc,
|
||||||
"%s: Releasing the trace buffer due to adapter reset.",
|
"%s: Releasing the trace buffer due to adapter reset.",
|
||||||
__func__);
|
__func__);
|
||||||
|
ioc->htb_rel.buffer_rel_condition =
|
||||||
|
MPT3_DIAG_BUFFER_REL_TRIGGER;
|
||||||
mpt3sas_send_diag_release(ioc, i, &issue_reset);
|
mpt3sas_send_diag_release(ioc, i, &issue_reset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1334,6 +1336,7 @@ _ctl_do_reset(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
|
||||||
dctlprintk(ioc, ioc_info(ioc, "%s: enter\n",
|
dctlprintk(ioc, ioc_info(ioc, "%s: enter\n",
|
||||||
__func__));
|
__func__));
|
||||||
|
|
||||||
|
ioc->reset_from_user = 1;
|
||||||
retval = mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
|
retval = mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
|
||||||
ioc_info(ioc,
|
ioc_info(ioc,
|
||||||
"Ioctl: host reset: %s\n", ((!retval) ? "SUCCESS" : "FAILED"));
|
"Ioctl: host reset: %s\n", ((!retval) ? "SUCCESS" : "FAILED"));
|
||||||
|
@ -1687,6 +1690,9 @@ _ctl_diag_register_2(struct MPT3SAS_ADAPTER *ioc,
|
||||||
request_data = ioc->diag_buffer[buffer_type];
|
request_data = ioc->diag_buffer[buffer_type];
|
||||||
request_data_sz = diag_register->requested_buffer_size;
|
request_data_sz = diag_register->requested_buffer_size;
|
||||||
ioc->unique_id[buffer_type] = diag_register->unique_id;
|
ioc->unique_id[buffer_type] = diag_register->unique_id;
|
||||||
|
/* Reset ioc variables used for additional query commands */
|
||||||
|
ioc->reset_from_user = 0;
|
||||||
|
memset(&ioc->htb_rel, 0, sizeof(struct htb_rel_query));
|
||||||
ioc->diag_buffer_status[buffer_type] &=
|
ioc->diag_buffer_status[buffer_type] &=
|
||||||
MPT3_DIAG_BUFFER_IS_DRIVER_ALLOCATED;
|
MPT3_DIAG_BUFFER_IS_DRIVER_ALLOCATED;
|
||||||
memcpy(ioc->product_specific[buffer_type],
|
memcpy(ioc->product_specific[buffer_type],
|
||||||
|
@ -2469,7 +2475,61 @@ _ctl_diag_read_buffer(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* _ctl_addnl_diag_query - query relevant info associated with diag buffers
|
||||||
|
* @ioc: per adapter object
|
||||||
|
* @arg: user space buffer containing ioctl content
|
||||||
|
*
|
||||||
|
* The application will send only unique_id. Driver will
|
||||||
|
* inspect unique_id first, if valid, fill the details related to cause
|
||||||
|
* for diag buffer release.
|
||||||
|
*/
|
||||||
|
static long
|
||||||
|
_ctl_addnl_diag_query(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
|
||||||
|
{
|
||||||
|
struct mpt3_addnl_diag_query karg;
|
||||||
|
u32 buffer_type = 0;
|
||||||
|
|
||||||
|
if (copy_from_user(&karg, arg, sizeof(karg))) {
|
||||||
|
pr_err("%s: failure at %s:%d/%s()!\n",
|
||||||
|
ioc->name, __FILE__, __LINE__, __func__);
|
||||||
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
dctlprintk(ioc, ioc_info(ioc, "%s\n", __func__));
|
||||||
|
if (karg.unique_id == 0) {
|
||||||
|
ioc_err(ioc, "%s: unique_id is(0x%08x)\n",
|
||||||
|
__func__, karg.unique_id);
|
||||||
|
return -EPERM;
|
||||||
|
}
|
||||||
|
buffer_type = _ctl_diag_get_bufftype(ioc, karg.unique_id);
|
||||||
|
if (buffer_type == MPT3_DIAG_UID_NOT_FOUND) {
|
||||||
|
ioc_err(ioc, "%s: buffer with unique_id(0x%08x) not found\n",
|
||||||
|
__func__, karg.unique_id);
|
||||||
|
return -EPERM;
|
||||||
|
}
|
||||||
|
memset(&karg.buffer_rel_condition, 0, sizeof(struct htb_rel_query));
|
||||||
|
if ((ioc->diag_buffer_status[buffer_type] &
|
||||||
|
MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) {
|
||||||
|
ioc_info(ioc, "%s: buffer_type(0x%02x) is not registered\n",
|
||||||
|
__func__, buffer_type);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if ((ioc->diag_buffer_status[buffer_type] &
|
||||||
|
MPT3_DIAG_BUFFER_IS_RELEASED) == 0) {
|
||||||
|
ioc_err(ioc, "%s: buffer_type(0x%02x) is not released\n",
|
||||||
|
__func__, buffer_type);
|
||||||
|
return -EPERM;
|
||||||
|
}
|
||||||
|
memcpy(&karg.buffer_rel_condition, &ioc->htb_rel,
|
||||||
|
sizeof(struct htb_rel_query));
|
||||||
|
out:
|
||||||
|
if (copy_to_user(arg, &karg, sizeof(struct mpt3_addnl_diag_query))) {
|
||||||
|
ioc_err(ioc, "%s: unable to write mpt3_addnl_diag_query data @ %p\n",
|
||||||
|
__func__, arg);
|
||||||
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_COMPAT
|
#ifdef CONFIG_COMPAT
|
||||||
/**
|
/**
|
||||||
|
@ -2533,7 +2593,7 @@ _ctl_ioctl_main(struct file *file, unsigned int cmd, void __user *arg,
|
||||||
struct MPT3SAS_ADAPTER *ioc;
|
struct MPT3SAS_ADAPTER *ioc;
|
||||||
struct mpt3_ioctl_header ioctl_header;
|
struct mpt3_ioctl_header ioctl_header;
|
||||||
enum block_state state;
|
enum block_state state;
|
||||||
long ret = -EINVAL;
|
long ret = -ENOIOCTLCMD;
|
||||||
|
|
||||||
/* get IOCTL header */
|
/* get IOCTL header */
|
||||||
if (copy_from_user(&ioctl_header, (char __user *)arg,
|
if (copy_from_user(&ioctl_header, (char __user *)arg,
|
||||||
|
@ -2643,6 +2703,10 @@ _ctl_ioctl_main(struct file *file, unsigned int cmd, void __user *arg,
|
||||||
if (_IOC_SIZE(cmd) == sizeof(struct mpt3_diag_read_buffer))
|
if (_IOC_SIZE(cmd) == sizeof(struct mpt3_diag_read_buffer))
|
||||||
ret = _ctl_diag_read_buffer(ioc, arg);
|
ret = _ctl_diag_read_buffer(ioc, arg);
|
||||||
break;
|
break;
|
||||||
|
case MPT3ADDNLDIAGQUERY:
|
||||||
|
if (_IOC_SIZE(cmd) == sizeof(struct mpt3_addnl_diag_query))
|
||||||
|
ret = _ctl_addnl_diag_query(ioc, arg);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
dctlprintk(ioc,
|
dctlprintk(ioc,
|
||||||
ioc_info(ioc, "unsupported ioctl opcode(0x%08x)\n",
|
ioc_info(ioc, "unsupported ioctl opcode(0x%08x)\n",
|
||||||
|
@ -3425,6 +3489,7 @@ host_trace_buffer_enable_store(struct device *cdev,
|
||||||
MPT3_DIAG_BUFFER_IS_RELEASED))
|
MPT3_DIAG_BUFFER_IS_RELEASED))
|
||||||
goto out;
|
goto out;
|
||||||
ioc_info(ioc, "releasing host trace buffer\n");
|
ioc_info(ioc, "releasing host trace buffer\n");
|
||||||
|
ioc->htb_rel.buffer_rel_condition = MPT3_DIAG_BUFFER_REL_SYSFS;
|
||||||
mpt3sas_send_diag_release(ioc, MPI2_DIAG_BUF_TYPE_TRACE,
|
mpt3sas_send_diag_release(ioc, MPI2_DIAG_BUF_TYPE_TRACE,
|
||||||
&issue_reset);
|
&issue_reset);
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,6 +94,8 @@
|
||||||
struct mpt3_diag_query)
|
struct mpt3_diag_query)
|
||||||
#define MPT3DIAGREADBUFFER _IOWR(MPT3_MAGIC_NUMBER, 30, \
|
#define MPT3DIAGREADBUFFER _IOWR(MPT3_MAGIC_NUMBER, 30, \
|
||||||
struct mpt3_diag_read_buffer)
|
struct mpt3_diag_read_buffer)
|
||||||
|
#define MPT3ADDNLDIAGQUERY _IOWR(MPT3_MAGIC_NUMBER, 32, \
|
||||||
|
struct mpt3_addnl_diag_query)
|
||||||
|
|
||||||
/* Trace Buffer default UniqueId */
|
/* Trace Buffer default UniqueId */
|
||||||
#define MPT2DIAGBUFFUNIQUEID (0x07075900)
|
#define MPT2DIAGBUFFUNIQUEID (0x07075900)
|
||||||
|
@ -430,4 +432,24 @@ struct mpt3_diag_read_buffer {
|
||||||
uint32_t diagnostic_data[1];
|
uint32_t diagnostic_data[1];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct mpt3_addnl_diag_query - diagnostic buffer release reason
|
||||||
|
* @hdr - generic header
|
||||||
|
* @unique_id - unique id associated with this buffer.
|
||||||
|
* @buffer_rel_condition - Release condition ioctl/sysfs/reset
|
||||||
|
* @reserved1
|
||||||
|
* @trigger_type - Master/Event/scsi/MPI
|
||||||
|
* @trigger_info_dwords - Data Correspondig to trigger type
|
||||||
|
* @reserved2
|
||||||
|
*/
|
||||||
|
struct mpt3_addnl_diag_query {
|
||||||
|
struct mpt3_ioctl_header hdr;
|
||||||
|
uint32_t unique_id;
|
||||||
|
uint16_t buffer_rel_condition;
|
||||||
|
uint16_t reserved1;
|
||||||
|
uint32_t trigger_type;
|
||||||
|
uint32_t trigger_info_dwords[2];
|
||||||
|
uint32_t reserved2[2];
|
||||||
|
};
|
||||||
|
|
||||||
#endif /* MPT3SAS_CTL_H_INCLUDED */
|
#endif /* MPT3SAS_CTL_H_INCLUDED */
|
||||||
|
|
|
@ -11947,6 +11947,8 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||||
* Enable MEMORY MOVE support flag.
|
* Enable MEMORY MOVE support flag.
|
||||||
*/
|
*/
|
||||||
ioc->drv_support_bitmap |= MPT_DRV_SUPPORT_BITMAP_MEMMOVE;
|
ioc->drv_support_bitmap |= MPT_DRV_SUPPORT_BITMAP_MEMMOVE;
|
||||||
|
/* Enable ADDITIONAL QUERY support flag. */
|
||||||
|
ioc->drv_support_bitmap |= MPT_DRV_SUPPORT_BITMAP_ADDNLQUERY;
|
||||||
|
|
||||||
ioc->enable_sdev_max_qd = enable_sdev_max_qd;
|
ioc->enable_sdev_max_qd = enable_sdev_max_qd;
|
||||||
|
|
||||||
|
|
|
@ -132,6 +132,35 @@ mpt3sas_process_trigger_data(struct MPT3SAS_ADAPTER *ioc,
|
||||||
&issue_reset);
|
&issue_reset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ioc->htb_rel.buffer_rel_condition = MPT3_DIAG_BUFFER_REL_TRIGGER;
|
||||||
|
if (event_data) {
|
||||||
|
ioc->htb_rel.trigger_type = event_data->trigger_type;
|
||||||
|
switch (event_data->trigger_type) {
|
||||||
|
case MPT3SAS_TRIGGER_SCSI:
|
||||||
|
memcpy(&ioc->htb_rel.trigger_info_dwords,
|
||||||
|
&event_data->u.scsi,
|
||||||
|
sizeof(struct SL_WH_SCSI_TRIGGER_T));
|
||||||
|
break;
|
||||||
|
case MPT3SAS_TRIGGER_MPI:
|
||||||
|
memcpy(&ioc->htb_rel.trigger_info_dwords,
|
||||||
|
&event_data->u.mpi,
|
||||||
|
sizeof(struct SL_WH_MPI_TRIGGER_T));
|
||||||
|
break;
|
||||||
|
case MPT3SAS_TRIGGER_MASTER:
|
||||||
|
ioc->htb_rel.trigger_info_dwords[0] =
|
||||||
|
event_data->u.master.MasterData;
|
||||||
|
break;
|
||||||
|
case MPT3SAS_TRIGGER_EVENT:
|
||||||
|
memcpy(&ioc->htb_rel.trigger_info_dwords,
|
||||||
|
&event_data->u.event,
|
||||||
|
sizeof(struct SL_WH_EVENT_TRIGGER_T));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ioc_err(ioc, "%d - Is not a valid Trigger type\n",
|
||||||
|
event_data->trigger_type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
_mpt3sas_raise_sigio(ioc, event_data);
|
_mpt3sas_raise_sigio(ioc, event_data);
|
||||||
|
|
||||||
dTriggerDiagPrintk(ioc, ioc_info(ioc, "%s: exit\n",
|
dTriggerDiagPrintk(ioc, ioc_info(ioc, "%s: exit\n",
|
||||||
|
@ -201,9 +230,14 @@ mpt3sas_trigger_master(struct MPT3SAS_ADAPTER *ioc, u32 trigger_bitmask)
|
||||||
event_data.u.master.MasterData = trigger_bitmask;
|
event_data.u.master.MasterData = trigger_bitmask;
|
||||||
|
|
||||||
if (trigger_bitmask & MASTER_TRIGGER_FW_FAULT ||
|
if (trigger_bitmask & MASTER_TRIGGER_FW_FAULT ||
|
||||||
trigger_bitmask & MASTER_TRIGGER_ADAPTER_RESET)
|
trigger_bitmask & MASTER_TRIGGER_ADAPTER_RESET) {
|
||||||
|
ioc->htb_rel.trigger_type = MPT3SAS_TRIGGER_MASTER;
|
||||||
|
ioc->htb_rel.trigger_info_dwords[0] = trigger_bitmask;
|
||||||
|
if (ioc->reset_from_user)
|
||||||
|
ioc->htb_rel.trigger_info_dwords[1] =
|
||||||
|
MPT_DIAG_RESET_ISSUED_BY_USER;
|
||||||
_mpt3sas_raise_sigio(ioc, &event_data);
|
_mpt3sas_raise_sigio(ioc, &event_data);
|
||||||
else
|
} else
|
||||||
mpt3sas_send_trigger_data_event(ioc, &event_data);
|
mpt3sas_send_trigger_data_event(ioc, &event_data);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
|
Загрузка…
Ссылка в новой задаче