scsi: cxlflash: Introduce host ioctl support
As staging for supporting various host management functions, add a host ioctl infrastructure to filter ioctl commands and perform operations that are common for all host ioctls. Also update the cxlflash documentation to create a new section for documenting host ioctls. Signed-off-by: Matthew R. Ochs <mrochs@linux.vnet.ibm.com> Signed-off-by: Uma Krishnan <ukrishn@linux.vnet.ibm.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
parent
cf24302790
commit
d6e32f530d
|
@ -326,7 +326,7 @@ Code Seq#(hex) Include File Comments
|
||||||
0xB5 00-0F uapi/linux/rpmsg.h <mailto:linux-remoteproc@vger.kernel.org>
|
0xB5 00-0F uapi/linux/rpmsg.h <mailto:linux-remoteproc@vger.kernel.org>
|
||||||
0xC0 00-0F linux/usb/iowarrior.h
|
0xC0 00-0F linux/usb/iowarrior.h
|
||||||
0xCA 00-0F uapi/misc/cxl.h
|
0xCA 00-0F uapi/misc/cxl.h
|
||||||
0xCA 80-8F uapi/scsi/cxlflash_ioctl.h
|
0xCA 80-BF uapi/scsi/cxlflash_ioctl.h
|
||||||
0xCB 00-1F CBM serial IEC bus in development:
|
0xCB 00-1F CBM serial IEC bus in development:
|
||||||
<mailto:michael.klein@puffin.lb.shuttle.de>
|
<mailto:michael.klein@puffin.lb.shuttle.de>
|
||||||
0xCD 01 linux/reiserfs_fs.h
|
0xCD 01 linux/reiserfs_fs.h
|
||||||
|
|
|
@ -124,8 +124,8 @@ Block library API
|
||||||
http://github.com/open-power/capiflash
|
http://github.com/open-power/capiflash
|
||||||
|
|
||||||
|
|
||||||
CXL Flash Driver IOCTLs
|
CXL Flash Driver LUN IOCTLs
|
||||||
=======================
|
===========================
|
||||||
|
|
||||||
Users, such as the block library, that wish to interface with a flash
|
Users, such as the block library, that wish to interface with a flash
|
||||||
device (LUN) via user space access need to use the services provided
|
device (LUN) via user space access need to use the services provided
|
||||||
|
@ -367,3 +367,18 @@ DK_CXLFLASH_MANAGE_LUN
|
||||||
exclusive user space access (superpipe). In case a LUN is visible
|
exclusive user space access (superpipe). In case a LUN is visible
|
||||||
across multiple ports and adapters, this ioctl is used to uniquely
|
across multiple ports and adapters, this ioctl is used to uniquely
|
||||||
identify each LUN by its World Wide Node Name (WWNN).
|
identify each LUN by its World Wide Node Name (WWNN).
|
||||||
|
|
||||||
|
|
||||||
|
CXL Flash Driver Host IOCTLs
|
||||||
|
============================
|
||||||
|
|
||||||
|
Each host adapter instance that is supported by the cxlflash driver
|
||||||
|
has a special character device associated with it to enable a set of
|
||||||
|
host management function. These character devices are hosted in a
|
||||||
|
class dedicated for cxlflash and can be accessed via /dev/cxlflash/*.
|
||||||
|
|
||||||
|
Applications can be written to perform various functions using the
|
||||||
|
host ioctl APIs below.
|
||||||
|
|
||||||
|
The structure definitions for these IOCTLs are available in:
|
||||||
|
uapi/scsi/cxlflash_ioctl.h
|
||||||
|
|
|
@ -2693,7 +2693,14 @@ static ssize_t lun_mode_store(struct device *dev,
|
||||||
static ssize_t ioctl_version_show(struct device *dev,
|
static ssize_t ioctl_version_show(struct device *dev,
|
||||||
struct device_attribute *attr, char *buf)
|
struct device_attribute *attr, char *buf)
|
||||||
{
|
{
|
||||||
return scnprintf(buf, PAGE_SIZE, "%u\n", DK_CXLFLASH_VERSION_0);
|
ssize_t bytes = 0;
|
||||||
|
|
||||||
|
bytes = scnprintf(buf, PAGE_SIZE,
|
||||||
|
"disk: %u\n", DK_CXLFLASH_VERSION_0);
|
||||||
|
bytes += scnprintf(buf + bytes, PAGE_SIZE - bytes,
|
||||||
|
"host: %u\n", HT_CXLFLASH_VERSION_0);
|
||||||
|
|
||||||
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3211,12 +3218,124 @@ static int cxlflash_chr_open(struct inode *inode, struct file *file)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* decode_hioctl() - translates encoded host ioctl to easily identifiable string
|
||||||
|
* @cmd: The host ioctl command to decode.
|
||||||
|
*
|
||||||
|
* Return: A string identifying the decoded host ioctl.
|
||||||
|
*/
|
||||||
|
static char *decode_hioctl(int cmd)
|
||||||
|
{
|
||||||
|
switch (cmd) {
|
||||||
|
default:
|
||||||
|
return "UNKNOWN";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "UNKNOWN";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cxlflash_chr_ioctl() - character device IOCTL handler
|
||||||
|
* @file: File pointer for this device.
|
||||||
|
* @cmd: IOCTL command.
|
||||||
|
* @arg: Userspace ioctl data structure.
|
||||||
|
*
|
||||||
|
* A read/write semaphore is used to implement a 'drain' of currently
|
||||||
|
* running ioctls. The read semaphore is taken at the beginning of each
|
||||||
|
* ioctl thread and released upon concluding execution. Additionally the
|
||||||
|
* semaphore should be released and then reacquired in any ioctl execution
|
||||||
|
* path which will wait for an event to occur that is outside the scope of
|
||||||
|
* the ioctl (i.e. an adapter reset). To drain the ioctls currently running,
|
||||||
|
* a thread simply needs to acquire the write semaphore.
|
||||||
|
*
|
||||||
|
* Return: 0 on success, -errno on failure
|
||||||
|
*/
|
||||||
|
static long cxlflash_chr_ioctl(struct file *file, unsigned int cmd,
|
||||||
|
unsigned long arg)
|
||||||
|
{
|
||||||
|
typedef int (*hioctl) (struct cxlflash_cfg *, void *);
|
||||||
|
|
||||||
|
struct cxlflash_cfg *cfg = file->private_data;
|
||||||
|
struct device *dev = &cfg->dev->dev;
|
||||||
|
char buf[sizeof(union cxlflash_ht_ioctls)];
|
||||||
|
void __user *uarg = (void __user *)arg;
|
||||||
|
struct ht_cxlflash_hdr *hdr;
|
||||||
|
size_t size = 0;
|
||||||
|
bool known_ioctl = false;
|
||||||
|
int idx = 0;
|
||||||
|
int rc = 0;
|
||||||
|
hioctl do_ioctl = NULL;
|
||||||
|
|
||||||
|
static const struct {
|
||||||
|
size_t size;
|
||||||
|
hioctl ioctl;
|
||||||
|
} ioctl_tbl[] = { /* NOTE: order matters here */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Hold read semaphore so we can drain if needed */
|
||||||
|
down_read(&cfg->ioctl_rwsem);
|
||||||
|
|
||||||
|
dev_dbg(dev, "%s: cmd=%u idx=%d tbl_size=%lu\n",
|
||||||
|
__func__, cmd, idx, sizeof(ioctl_tbl));
|
||||||
|
|
||||||
|
switch (cmd) {
|
||||||
|
default:
|
||||||
|
rc = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unlikely(copy_from_user(&buf, uarg, size))) {
|
||||||
|
dev_err(dev, "%s: copy_from_user() fail "
|
||||||
|
"size=%lu cmd=%d (%s) uarg=%p\n",
|
||||||
|
__func__, size, cmd, decode_hioctl(cmd), uarg);
|
||||||
|
rc = -EFAULT;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
hdr = (struct ht_cxlflash_hdr *)&buf;
|
||||||
|
if (hdr->version != HT_CXLFLASH_VERSION_0) {
|
||||||
|
dev_dbg(dev, "%s: Version %u not supported for %s\n",
|
||||||
|
__func__, hdr->version, decode_hioctl(cmd));
|
||||||
|
rc = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hdr->rsvd[0] || hdr->rsvd[1] || hdr->return_flags) {
|
||||||
|
dev_dbg(dev, "%s: Reserved/rflags populated\n", __func__);
|
||||||
|
rc = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = do_ioctl(cfg, (void *)&buf);
|
||||||
|
if (likely(!rc))
|
||||||
|
if (unlikely(copy_to_user(uarg, &buf, size))) {
|
||||||
|
dev_err(dev, "%s: copy_to_user() fail "
|
||||||
|
"size=%lu cmd=%d (%s) uarg=%p\n",
|
||||||
|
__func__, size, cmd, decode_hioctl(cmd), uarg);
|
||||||
|
rc = -EFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fall through to exit */
|
||||||
|
|
||||||
|
out:
|
||||||
|
up_read(&cfg->ioctl_rwsem);
|
||||||
|
if (unlikely(rc && known_ioctl))
|
||||||
|
dev_err(dev, "%s: ioctl %s (%08X) returned rc=%d\n",
|
||||||
|
__func__, decode_hioctl(cmd), cmd, rc);
|
||||||
|
else
|
||||||
|
dev_dbg(dev, "%s: ioctl %s (%08X) returned rc=%d\n",
|
||||||
|
__func__, decode_hioctl(cmd), cmd, rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Character device file operations
|
* Character device file operations
|
||||||
*/
|
*/
|
||||||
static const struct file_operations cxlflash_chr_fops = {
|
static const struct file_operations cxlflash_chr_fops = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.open = cxlflash_chr_open,
|
.open = cxlflash_chr_open,
|
||||||
|
.unlocked_ioctl = cxlflash_chr_ioctl,
|
||||||
|
.compat_ioctl = cxlflash_chr_ioctl,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -31,7 +31,7 @@ struct dk_cxlflash_hdr {
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return flag definitions available to all ioctls
|
* Return flag definitions available to all superpipe ioctls
|
||||||
*
|
*
|
||||||
* Similar to the input flags, these are grown from the bottom-up with the
|
* Similar to the input flags, these are grown from the bottom-up with the
|
||||||
* intention that ioctl-specific return flag definitions would grow from the
|
* intention that ioctl-specific return flag definitions would grow from the
|
||||||
|
@ -180,6 +180,10 @@ union cxlflash_ioctls {
|
||||||
#define CXL_MAGIC 0xCA
|
#define CXL_MAGIC 0xCA
|
||||||
#define CXL_IOWR(_n, _s) _IOWR(CXL_MAGIC, _n, struct _s)
|
#define CXL_IOWR(_n, _s) _IOWR(CXL_MAGIC, _n, struct _s)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CXL Flash superpipe ioctls start at base of the reserved CXL_MAGIC
|
||||||
|
* region (0x80) and grow upwards.
|
||||||
|
*/
|
||||||
#define DK_CXLFLASH_ATTACH CXL_IOWR(0x80, dk_cxlflash_attach)
|
#define DK_CXLFLASH_ATTACH CXL_IOWR(0x80, dk_cxlflash_attach)
|
||||||
#define DK_CXLFLASH_USER_DIRECT CXL_IOWR(0x81, dk_cxlflash_udirect)
|
#define DK_CXLFLASH_USER_DIRECT CXL_IOWR(0x81, dk_cxlflash_udirect)
|
||||||
#define DK_CXLFLASH_RELEASE CXL_IOWR(0x82, dk_cxlflash_release)
|
#define DK_CXLFLASH_RELEASE CXL_IOWR(0x82, dk_cxlflash_release)
|
||||||
|
@ -191,4 +195,29 @@ union cxlflash_ioctls {
|
||||||
#define DK_CXLFLASH_VLUN_RESIZE CXL_IOWR(0x88, dk_cxlflash_resize)
|
#define DK_CXLFLASH_VLUN_RESIZE CXL_IOWR(0x88, dk_cxlflash_resize)
|
||||||
#define DK_CXLFLASH_VLUN_CLONE CXL_IOWR(0x89, dk_cxlflash_clone)
|
#define DK_CXLFLASH_VLUN_CLONE CXL_IOWR(0x89, dk_cxlflash_clone)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Structure and flag definitions CXL Flash host ioctls
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define HT_CXLFLASH_VERSION_0 0
|
||||||
|
|
||||||
|
struct ht_cxlflash_hdr {
|
||||||
|
__u16 version; /* Version data */
|
||||||
|
__u16 subcmd; /* Sub-command */
|
||||||
|
__u16 rsvd[2]; /* Reserved for future use */
|
||||||
|
__u64 flags; /* Input flags */
|
||||||
|
__u64 return_flags; /* Returned flags */
|
||||||
|
};
|
||||||
|
|
||||||
|
union cxlflash_ht_ioctls {
|
||||||
|
};
|
||||||
|
|
||||||
|
#define MAX_HT_CXLFLASH_IOCTL_SZ (sizeof(union cxlflash_ht_ioctls))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CXL Flash host ioctls start at the top of the reserved CXL_MAGIC
|
||||||
|
* region (0xBF) and grow downwards.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
#endif /* ifndef _CXLFLASH_IOCTL_H */
|
#endif /* ifndef _CXLFLASH_IOCTL_H */
|
||||||
|
|
Loading…
Reference in New Issue