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

Eddie James eajames at linux.vnet.ibm.com
Fri Jun 15 00:12:25 AEST 2018



On 06/13/2018 06:00 PM, Benjamin Herrenschmidt wrote:
> On Wed, 2018-06-13 at 09:57 -0500, Eddie James wrote:
>> 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?
> It's for use by cronus or similar low level system debuggers.
>
> Cheers,
> Ben.

Cool, thanks.

Reviewed-by: Eddie James <eajames at linux.vnet.ibm.com>

>
>> 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