Commit 688c1a0a authored by Suganath Prabu S's avatar Suganath Prabu S Committed by Martin K. Petersen
Browse files

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: default avatarSuganath Prabu S <suganath-prabu.subramani@broadcom.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 664f0dce
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -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);
+47 −0
Original line number Diff line number Diff line
@@ -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);
+66 −1
Original line number Diff line number Diff line
@@ -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);
	}
+22 −0
Original line number Diff line number Diff line
@@ -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 */
+2 −0
Original line number Diff line number Diff line
@@ -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;

Loading