[RFC PATCH 5/5] fsi/scom: Major overhaul

Eddie James eajames at linux.vnet.ibm.com
Thu Jun 14 00:57:05 AEST 2018



On 06/12/2018 12:19 AM, Benjamin Herrenschmidt wrote:
> This was too hard to split ... this adds a number of features
> to the SCOM user interface:
>
>   - Support for indirect SCOMs
>
>   - read()/write() interface now handle errors and retries
>
>   - New ioctl() "raw" interface for use by debuggers
>
> Signed-off-by: Benjamin Herrenschmidt <benh at kernel.crashing.org>
> ---
>   drivers/fsi/fsi-scom.c   | 424 ++++++++++++++++++++++++++++++++++++---
>   include/uapi/linux/fsi.h |  56 ++++++
>   2 files changed, 450 insertions(+), 30 deletions(-)
>   create mode 100644 include/uapi/linux/fsi.h
>
> diff --git a/drivers/fsi/fsi-scom.c b/drivers/fsi/fsi-scom.c
> index e98573ecdae1..39c74351f1bf 100644
> --- a/drivers/fsi/fsi-scom.c
> +++ b/drivers/fsi/fsi-scom.c
> @@ -24,6 +24,8 @@
>   #include <linux/list.h>
>   #include <linux/idr.h>

> +
> +static int scom_reset(struct scom_device *scom, void __user *argp)
> +{
> +	uint32_t flags, dummy = -1;
> +	int rc = 0;
> +
> +	if (get_user(flags, (__u32 __user *)argp))
> +		return -EFAULT;
> +	if (flags & SCOM_RESET_PIB)
> +		rc = fsi_device_write(scom->fsi_dev, SCOM_PIB_RESET_REG, &dummy,
> +				      sizeof(uint32_t));

I realize this is a user requested flag but I believe the BMC is never 
supposed to issue this type of reset, due to the possibility of breaking 
stuff on the host side. Not sure if it should even be available?

Otherwise, looks good!
Thanks,
Eddie

> +	if (!rc && (flags & (SCOM_RESET_PIB | SCOM_RESET_INTF)))
> +		rc = fsi_device_write(scom->fsi_dev, SCOM_FSI2PIB_RESET_REG, &dummy,
> +				      sizeof(uint32_t));
> +	return rc;
> +}
> +
> +static int scom_check(struct scom_device *scom, void __user *argp)
> +{
> +	/* Still need to find out how to get "protected" */
> +	return put_user(SCOM_CHECK_SUPPORTED, (__u32 __user *)argp);
> +}
> +
> +static long scom_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
> +{
> +	struct miscdevice *mdev = file->private_data;
> +	struct scom_device *scom = to_scom_dev(mdev);
> +	void __user *argp = (void __user *)arg;
> +	int rc = -ENOTTY;
> +
> +	mutex_lock(&scom->lock);
> +	switch(cmd) {
> +	case FSI_SCOM_CHECK:
> +		rc = scom_check(scom, argp);
> +		break;
> +	case FSI_SCOM_READ:
> +		rc = scom_raw_read(scom, argp);
> +		break;
> +	case FSI_SCOM_WRITE:
> +		rc = scom_raw_write(scom, argp);
> +		break;
> +	case FSI_SCOM_RESET:
> +		rc = scom_reset(scom, argp);
> +		break;
> +	}
> +	mutex_unlock(&scom->lock);
> +	return rc;
> +}
> +
>   static const struct file_operations scom_fops = {
> -	.owner	= THIS_MODULE,
> -	.llseek	= scom_llseek,
> -	.read	= scom_read,
> -	.write	= scom_write,
> +	.owner		= THIS_MODULE,
> +	.llseek		= scom_llseek,
> +	.read		= scom_read,
> +	.write		= scom_write,
> +	.unlocked_ioctl	= scom_ioctl,
>   };
>
>   static int scom_probe(struct device *dev)
> diff --git a/include/uapi/linux/fsi.h b/include/uapi/linux/fsi.h
> new file mode 100644
> index 000000000000..6008d93f2e48
> --- /dev/null
> +++ b/include/uapi/linux/fsi.h
> @@ -0,0 +1,56 @@
> +#ifndef _UAPI_LINUX_FSI_H
> +#define _UAPI_LINUX_FSI_H
> +
> +#include <linux/ioctl.h>
> +
> +/*
> + * /dev/scom "raw" ioctl interface
> + *
> + * The driver supports a high level "read/write" interface which
> + * handles retries and converts the status to Linux error codes,
> + * however low level tools an debugger need to access the "raw"
> + * HW status information and interpret it themselves, so this
> + * ioctl interface is also provided for their use case.
> + */
> +
> +/* Structure for SCOM read/write */
> +struct scom_access {
> +	__u64	addr;		/* SCOM address, supports indirect */
> +	__u64	data;		/* SCOM data (in for write, out for read) */
> +	__u64	mask;		/* Data mask for writes */
> +	__u32	intf_errors;	/* Interface error flags */
> +#define SCOM_INTF_ERR_PARITY		0x00000001 /* Parity error */
> +#define SCOM_INTF_ERR_PROTECTION	0x00000002 /* Blocked by secure boot */
> +#define SCOM_INTF_ERR_ABORT		0x00000004 /* PIB reset during access */
> +#define SCOM_INTF_ERR_UNKNOWN		0x80000000 /* Unknown error */
> +	/*
> +	 * Note: Any other bit set in intf_errors need to be considered as an
> +	 * error. Future implementations may define new error conditions. The
> +	 * pib_status below is only valid if intf_errors is 0.
> +	 */
> +	__u8	pib_status;	/* 3-bit PIB status */
> +#define SCOM_PIB_SUCCESS	0	/* Access successful */
> +#define SCOM_PIB_BLOCKED	1	/* PIB blocked, pls retry */
> +#define SCOM_PIB_OFFLINE	2	/* Chiplet offline */
> +#define SCOM_PIB_PARTIAL	3	/* Partial good */
> +#define SCOM_PIB_BAD_ADDR	4	/* Invalid address */
> +#define SCOM_PIB_CLK_ERR	5	/* Clock error */
> +#define SCOM_PIB_PARITY_ERR	6	/* Parity error on the PIB bus */
> +#define SCOM_PIB_TIMEOUT	7	/* Bus timeout */
> +	__u8	pad;
> +};
> +
> +/* Flags for SCOM check */
> +#define SCOM_CHECK_SUPPORTED	0x00000001	/* Interface supported */
> +#define SCOM_CHECK_PROTECTED	0x00000002	/* Interface blocked by secure boot */
> +
> +/* Flags for SCOM reset */
> +#define SCOM_RESET_INTF		0x00000001	/* Reset interface */
> +#define SCOM_RESET_PIB		0x00000002	/* Reset PIB */
> +
> +#define FSI_SCOM_CHECK	_IOR('s', 0x00, __u32)
> +#define FSI_SCOM_READ	_IOWR('s', 0x01, struct scom_access)
> +#define FSI_SCOM_WRITE	_IOWR('s', 0x02, struct scom_access)
> +#define FSI_SCOM_RESET	_IOW('s', 0x03, __u32)
> +
> +#endif /* _UAPI_LINUX_FSI_H */



More information about the openbmc mailing list