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:
Matthew R. Ochs 2017-06-21 21:15:42 -05:00 committed by Martin K. Petersen
parent cf24302790
commit d6e32f530d
4 changed files with 168 additions and 5 deletions

View File

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

View File

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

View File

@ -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,
}; };
/** /**

View File

@ -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 */