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:
Suganath Prabu S 2021-02-04 09:07:23 +05:30 committed by Martin K. Petersen
parent 664f0dce20
commit 688c1a0a13
6 changed files with 177 additions and 4 deletions

View file

@ -8191,8 +8191,11 @@ mpt3sas_base_hard_reset_handler(struct MPT3SAS_ADAPTER *ioc,
ioc_state = mpt3sas_base_get_iocstate(ioc, 0);
if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT ||
(ioc_state & MPI2_IOC_STATE_MASK) ==
MPI2_IOC_STATE_COREDUMP)
MPI2_IOC_STATE_COREDUMP) {
is_fault = 1;
ioc->htb_rel.trigger_info_dwords[1] =
(ioc_state & MPI2_DOORBELL_DATA_MASK);
}
}
_base_pre_reset_handler(ioc);
mpt3sas_wait_for_commands_to_complete(ioc);

View file

@ -1073,6 +1073,50 @@ struct hba_port {
#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);
/**
* struct MPT3SAS_ADAPTER - per adapter struct
@ -1530,6 +1574,8 @@ struct MPT3SAS_ADAPTER {
u32 diagnostic_flags[MPI2_DIAG_BUF_TYPE_COUNT];
u32 ring_buffer_offset;
u32 ring_buffer_sz;
struct htb_rel_query htb_rel;
u8 reset_from_user;
u8 is_warpdrive;
u8 is_mcpu_endpoint;
u8 hide_ir_msg;
@ -1566,6 +1612,7 @@ struct mpt3sas_debugfs_buffer {
};
#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,
u32 reply);

View file

@ -479,6 +479,8 @@ void mpt3sas_ctl_pre_reset_handler(struct MPT3SAS_ADAPTER *ioc)
ioc_info(ioc,
"%s: Releasing the trace buffer due to adapter reset.",
__func__);
ioc->htb_rel.buffer_rel_condition =
MPT3_DIAG_BUFFER_REL_TRIGGER;
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",
__func__));
ioc->reset_from_user = 1;
retval = mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
ioc_info(ioc,
"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_sz = diag_register->requested_buffer_size;
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] &=
MPT3_DIAG_BUFFER_IS_DRIVER_ALLOCATED;
memcpy(ioc->product_specific[buffer_type],
@ -2469,7 +2475,61 @@ _ctl_diag_read_buffer(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
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
/**
@ -2533,7 +2593,7 @@ _ctl_ioctl_main(struct file *file, unsigned int cmd, void __user *arg,
struct MPT3SAS_ADAPTER *ioc;
struct mpt3_ioctl_header ioctl_header;
enum block_state state;
long ret = -EINVAL;
long ret = -ENOIOCTLCMD;
/* get IOCTL header */
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))
ret = _ctl_diag_read_buffer(ioc, arg);
break;
case MPT3ADDNLDIAGQUERY:
if (_IOC_SIZE(cmd) == sizeof(struct mpt3_addnl_diag_query))
ret = _ctl_addnl_diag_query(ioc, arg);
break;
default:
dctlprintk(ioc,
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))
goto out;
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,
&issue_reset);
}

View file

@ -94,6 +94,8 @@
struct mpt3_diag_query)
#define MPT3DIAGREADBUFFER _IOWR(MPT3_MAGIC_NUMBER, 30, \
struct mpt3_diag_read_buffer)
#define MPT3ADDNLDIAGQUERY _IOWR(MPT3_MAGIC_NUMBER, 32, \
struct mpt3_addnl_diag_query)
/* Trace Buffer default UniqueId */
#define MPT2DIAGBUFFUNIQUEID (0x07075900)
@ -430,4 +432,24 @@ struct mpt3_diag_read_buffer {
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 */

View file

@ -11947,6 +11947,8 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
* Enable MEMORY MOVE support flag.
*/
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;

View file

@ -132,6 +132,35 @@ mpt3sas_process_trigger_data(struct MPT3SAS_ADAPTER *ioc,
&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);
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;
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);
else
} else
mpt3sas_send_trigger_data_event(ioc, &event_data);
out: