summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--block/opal_proto.h20
-rw-r--r--block/sed-opal.c47
-rw-r--r--include/linux/sed-opal.h1
-rw-r--r--include/uapi/linux/sed-opal.h1
4 files changed, 69 insertions, 0 deletions
diff --git a/block/opal_proto.h b/block/opal_proto.h
index d138785b8198..7c24247aa186 100644
--- a/block/opal_proto.h
+++ b/block/opal_proto.h
@@ -19,6 +19,7 @@
enum {
TCG_SECP_00 = 0,
TCG_SECP_01,
+ TCG_SECP_02,
};
/*
@@ -273,6 +274,25 @@ struct opal_header {
struct opal_data_subpacket subpkt;
};
+/*
+ * TCG_Storage_Architecture_Core_Spec_v2.01_r1.00
+ * Section: 3.3.4.7.5 STACK_RESET
+ */
+#define OPAL_STACK_RESET 0x0002
+
+struct opal_stack_reset {
+ u8 extendedComID[4];
+ __be32 request_code;
+};
+
+struct opal_stack_reset_response {
+ u8 extendedComID[4];
+ __be32 request_code;
+ u8 reserved0[2];
+ __be16 data_length;
+ __be32 response;
+};
+
#define FC_TPER 0x0001
#define FC_LOCKING 0x0002
#define FC_GEOMETRY 0x0003
diff --git a/block/sed-opal.c b/block/sed-opal.c
index c34d19e91201..79b290d9458a 100644
--- a/block/sed-opal.c
+++ b/block/sed-opal.c
@@ -3545,6 +3545,50 @@ static int opal_get_sum_ranges(struct opal_dev *dev, struct opal_sum_ranges *opa
return ret;
}
+static int opal_stack_reset(struct opal_dev *dev)
+{
+ struct opal_stack_reset *req;
+ struct opal_stack_reset_response *resp;
+ int ret;
+
+ mutex_lock(&dev->dev_lock);
+
+ memset(dev->cmd, 0, IO_BUFFER_LENGTH);
+ req = (struct opal_stack_reset *)dev->cmd;
+ req->extendedComID[0] = dev->comid >> 8;
+ req->extendedComID[1] = dev->comid & 0xFF;
+ req->request_code = cpu_to_be32(OPAL_STACK_RESET);
+
+ ret = dev->send_recv(dev->data, dev->comid, TCG_SECP_02,
+ dev->cmd, IO_BUFFER_LENGTH, true);
+ if (ret) {
+ pr_debug("Error sending stack reset: %d\n", ret);
+ goto out;
+ }
+
+ memset(dev->resp, 0, IO_BUFFER_LENGTH);
+ ret = dev->send_recv(dev->data, dev->comid, TCG_SECP_02,
+ dev->resp, IO_BUFFER_LENGTH, false);
+ if (ret) {
+ pr_debug("Error receiving stack reset response: %d\n", ret);
+ goto out;
+ }
+
+ resp = (struct opal_stack_reset_response *)dev->resp;
+ if (be16_to_cpu(resp->data_length) != 4) {
+ pr_debug("Stack reset pending\n");
+ ret = -EBUSY;
+ goto out;
+ }
+ if (be32_to_cpu(resp->response) != 0) {
+ pr_debug("Stack reset failed: %u\n", be32_to_cpu(resp->response));
+ ret = -EIO;
+ }
+out:
+ mutex_unlock(&dev->dev_lock);
+ return ret;
+}
+
int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *arg)
{
void *p;
@@ -3642,6 +3686,9 @@ int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *arg)
case IOC_OPAL_GET_SUM_STATUS:
ret = opal_get_sum_ranges(dev, p, arg);
break;
+ case IOC_OPAL_STACK_RESET:
+ ret = opal_stack_reset(dev);
+ break;
default:
break;
diff --git a/include/linux/sed-opal.h b/include/linux/sed-opal.h
index aa006edb612b..0630430cc01a 100644
--- a/include/linux/sed-opal.h
+++ b/include/linux/sed-opal.h
@@ -57,6 +57,7 @@ static inline bool is_sed_ioctl(unsigned int cmd)
case IOC_OPAL_LR_SET_START_LEN:
case IOC_OPAL_ENABLE_DISABLE_LR:
case IOC_OPAL_GET_SUM_STATUS:
+ case IOC_OPAL_STACK_RESET:
return true;
}
return false;
diff --git a/include/uapi/linux/sed-opal.h b/include/uapi/linux/sed-opal.h
index 9830298ec51c..ef4d3be6ca7f 100644
--- a/include/uapi/linux/sed-opal.h
+++ b/include/uapi/linux/sed-opal.h
@@ -245,5 +245,6 @@ struct opal_revert_lsp {
#define IOC_OPAL_LR_SET_START_LEN _IOW('p', 243, struct opal_user_lr_setup)
#define IOC_OPAL_ENABLE_DISABLE_LR _IOW('p', 244, struct opal_user_lr_setup)
#define IOC_OPAL_GET_SUM_STATUS _IOW('p', 245, struct opal_sum_ranges)
+#define IOC_OPAL_STACK_RESET _IO('p', 246)
#endif /* _UAPI_SED_OPAL_H */