From a98e58e54fbd0c80b6a46a7cac6e231eed3b3efa Mon Sep 17 00:00:00 2001 From: Scott Bauer Date: Fri, 3 Feb 2017 12:50:32 -0700 Subject: nvme: Add Support for Opal: Unlock from S3 & Opal Allocation/Ioctls This patch implements the necessary logic to unlock an Opal enabled device coming back from an S3. The patch also implements the SED/Opal allocation necessary to support the opal ioctls. Signed-off-by: Scott Bauer Signed-off-by: Jens Axboe --- drivers/nvme/host/core.c | 25 +++++++++++++++++++++++++ drivers/nvme/host/nvme.h | 14 ++++++++++++++ drivers/nvme/host/pci.c | 7 +++++++ 3 files changed, 46 insertions(+) (limited to 'drivers/nvme') diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index 037ee999e759..26ae4afd3737 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -788,6 +788,8 @@ static int nvme_ioctl(struct block_device *bdev, fmode_t mode, if (ns->ndev) return nvme_nvm_ioctl(ns, cmd, arg); #endif + if (is_sed_ioctl(cmd)) + return sed_ioctl(&ns->ctrl->opal_dev, cmd, arg); return -ENOTTY; } } @@ -1055,6 +1057,29 @@ static const struct pr_ops nvme_pr_ops = { .pr_clear = nvme_pr_clear, }; +#ifdef CONFIG_BLK_SED_OPAL +int nvme_sec_submit(struct opal_dev *dev, u16 spsp, u8 secp, + void *buffer, size_t len, bool send) +{ + struct nvme_command cmd; + struct nvme_ctrl *ctrl = NULL; + + memset(&cmd, 0, sizeof(cmd)); + if (send) + cmd.common.opcode = nvme_admin_security_send; + else + cmd.common.opcode = nvme_admin_security_recv; + ctrl = container_of(dev, struct nvme_ctrl, opal_dev); + cmd.common.nsid = 0; + cmd.common.cdw10[0] = cpu_to_le32(((u32)secp) << 24 | ((u32)spsp) << 8); + cmd.common.cdw10[1] = cpu_to_le32(len); + + return __nvme_submit_sync_cmd(ctrl->admin_q, &cmd, NULL, buffer, len, + ADMIN_TIMEOUT, NVME_QID_ANY, 1, 0); +} +EXPORT_SYMBOL_GPL(nvme_sec_submit); +#endif /* CONFIG_BLK_SED_OPAL */ + static const struct block_device_operations nvme_fops = { .owner = THIS_MODULE, .ioctl = nvme_ioctl, diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h index 330713c4abdb..1aa353a848e3 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h @@ -19,6 +19,7 @@ #include #include #include +#include enum { /* @@ -125,6 +126,8 @@ struct nvme_ctrl { struct list_head node; struct ida ns_ida; + struct opal_dev opal_dev; + char name[12]; char serial[20]; char model[40]; @@ -275,6 +278,17 @@ int nvme_init_identify(struct nvme_ctrl *ctrl); void nvme_queue_scan(struct nvme_ctrl *ctrl); void nvme_remove_namespaces(struct nvme_ctrl *ctrl); +#ifdef CONFIG_BLK_SED_OPAL +int nvme_sec_submit(struct opal_dev *dev, u16 spsp, u8 secp, + void *buffer, size_t len, bool send); +#else +static inline int nvme_sec_submit(struct opal_dev *dev, u16 spsp, u8 secp, + void *buffer, size_t len, bool send) +{ + return 0; +} +#endif /* CONFIG_BLK_DEV_SED_OPAL */ + #define NVME_NR_AERS 1 void nvme_complete_async_event(struct nvme_ctrl *ctrl, __le16 status, union nvme_result *res); diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index 06875bc1ba80..f08e86e73dda 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -43,6 +43,7 @@ #include #include #include +#include #include "nvme.h" @@ -1757,6 +1758,7 @@ static void nvme_remove_dead_ctrl(struct nvme_dev *dev, int status) static void nvme_reset_work(struct work_struct *work) { struct nvme_dev *dev = container_of(work, struct nvme_dev, reset_work); + bool was_suspend = !!(dev->ctrl.ctrl_config & NVME_CC_SHN_NORMAL); int result = -ENODEV; if (WARN_ON(dev->ctrl.state == NVME_CTRL_RESETTING)) @@ -1789,6 +1791,11 @@ static void nvme_reset_work(struct work_struct *work) if (result) goto out; + init_opal_dev(&dev->ctrl.opal_dev, &nvme_sec_submit); + + if (was_suspend) + opal_unlock_from_suspend(&dev->ctrl.opal_dev); + result = nvme_setup_io_queues(dev); if (result) goto out; -- cgit v1.2.3