diff options
author | Christoph Hellwig <hch@lst.de> | 2017-02-17 07:59:39 -0500 |
---|---|---|
committer | Jens Axboe <axboe@fb.com> | 2017-02-17 14:41:47 -0500 |
commit | 4f1244c8298606b8fae64b4d78b820ae6b896e3c (patch) | |
tree | 81fbf9080d730ca328572847be75fa4e05e4268e | |
parent | f5b37b7c23915af93081a8711e0a0f0219063756 (diff) |
block/sed-opal: allocate struct opal_dev dynamically
Insted of bloating the containing structure with it all the time this
allocates struct opal_dev dynamically. Additionally this allows moving
the definition of struct opal_dev into sed-opal.c. For this a new
private data field is added to it that is passed to the send/receive
callback. After that a lot of internals can be made private as well.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Tested-by: Scott Bauer <scott.bauer@intel.com>
Reviewed-by: Scott Bauer <scott.bauer@intel.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
-rw-r--r-- | block/opal_proto.h | 23 | ||||
-rw-r--r-- | block/sed-opal.c | 101 | ||||
-rw-r--r-- | drivers/nvme/host/core.c | 9 | ||||
-rw-r--r-- | drivers/nvme/host/nvme.h | 14 | ||||
-rw-r--r-- | drivers/nvme/host/pci.c | 8 | ||||
-rw-r--r-- | include/linux/sed-opal.h | 116 |
6 files changed, 131 insertions, 140 deletions
diff --git a/block/opal_proto.h b/block/opal_proto.h index af9abc56c157..f40c9acf8895 100644 --- a/block/opal_proto.h +++ b/block/opal_proto.h | |||
@@ -19,6 +19,29 @@ | |||
19 | #ifndef _OPAL_PROTO_H | 19 | #ifndef _OPAL_PROTO_H |
20 | #define _OPAL_PROTO_H | 20 | #define _OPAL_PROTO_H |
21 | 21 | ||
22 | /* | ||
23 | * These constant values come from: | ||
24 | * SPC-4 section | ||
25 | * 6.30 SECURITY PROTOCOL IN command / table 265. | ||
26 | */ | ||
27 | enum { | ||
28 | TCG_SECP_00 = 0, | ||
29 | TCG_SECP_01, | ||
30 | }; | ||
31 | |||
32 | /* | ||
33 | * Token defs derived from: | ||
34 | * TCG_Storage_Architecture_Core_Spec_v2.01_r1.00 | ||
35 | * 3.2.2 Data Stream Encoding | ||
36 | */ | ||
37 | enum opal_response_token { | ||
38 | OPAL_DTA_TOKENID_BYTESTRING = 0xe0, | ||
39 | OPAL_DTA_TOKENID_SINT = 0xe1, | ||
40 | OPAL_DTA_TOKENID_UINT = 0xe2, | ||
41 | OPAL_DTA_TOKENID_TOKEN = 0xe3, /* actual token is returned */ | ||
42 | OPAL_DTA_TOKENID_INVALID = 0X0 | ||
43 | }; | ||
44 | |||
22 | #define DTAERROR_NO_METHOD_STATUS 0x89 | 45 | #define DTAERROR_NO_METHOD_STATUS 0x89 |
23 | #define GENERIC_HOST_SESSION_NUM 0x41 | 46 | #define GENERIC_HOST_SESSION_NUM 0x41 |
24 | 47 | ||
diff --git a/block/sed-opal.c b/block/sed-opal.c index bcdd5b6d02e8..d1c52ba4d62d 100644 --- a/block/sed-opal.c +++ b/block/sed-opal.c | |||
@@ -31,6 +31,77 @@ | |||
31 | 31 | ||
32 | #include "opal_proto.h" | 32 | #include "opal_proto.h" |
33 | 33 | ||
34 | #define IO_BUFFER_LENGTH 2048 | ||
35 | #define MAX_TOKS 64 | ||
36 | |||
37 | typedef int (*opal_step)(struct opal_dev *dev); | ||
38 | |||
39 | enum opal_atom_width { | ||
40 | OPAL_WIDTH_TINY, | ||
41 | OPAL_WIDTH_SHORT, | ||
42 | OPAL_WIDTH_MEDIUM, | ||
43 | OPAL_WIDTH_LONG, | ||
44 | OPAL_WIDTH_TOKEN | ||
45 | }; | ||
46 | |||
47 | /* | ||
48 | * On the parsed response, we don't store again the toks that are already | ||
49 | * stored in the response buffer. Instead, for each token, we just store a | ||
50 | * pointer to the position in the buffer where the token starts, and the size | ||
51 | * of the token in bytes. | ||
52 | */ | ||
53 | struct opal_resp_tok { | ||
54 | const u8 *pos; | ||
55 | size_t len; | ||
56 | enum opal_response_token type; | ||
57 | enum opal_atom_width width; | ||
58 | union { | ||
59 | u64 u; | ||
60 | s64 s; | ||
61 | } stored; | ||
62 | }; | ||
63 | |||
64 | /* | ||
65 | * From the response header it's not possible to know how many tokens there are | ||
66 | * on the payload. So we hardcode that the maximum will be MAX_TOKS, and later | ||
67 | * if we start dealing with messages that have more than that, we can increase | ||
68 | * this number. This is done to avoid having to make two passes through the | ||
69 | * response, the first one counting how many tokens we have and the second one | ||
70 | * actually storing the positions. | ||
71 | */ | ||
72 | struct parsed_resp { | ||
73 | int num; | ||
74 | struct opal_resp_tok toks[MAX_TOKS]; | ||
75 | }; | ||
76 | |||
77 | struct opal_dev { | ||
78 | bool supported; | ||
79 | |||
80 | void *data; | ||
81 | sec_send_recv *send_recv; | ||
82 | |||
83 | const opal_step *funcs; | ||
84 | void **func_data; | ||
85 | int state; | ||
86 | struct mutex dev_lock; | ||
87 | u16 comid; | ||
88 | u32 hsn; | ||
89 | u32 tsn; | ||
90 | u64 align; | ||
91 | u64 lowest_lba; | ||
92 | |||
93 | size_t pos; | ||
94 | u8 cmd[IO_BUFFER_LENGTH]; | ||
95 | u8 resp[IO_BUFFER_LENGTH]; | ||
96 | |||
97 | struct parsed_resp parsed; | ||
98 | size_t prev_d_len; | ||
99 | void *prev_data; | ||
100 | |||
101 | struct list_head unlk_lst; | ||
102 | }; | ||
103 | |||
104 | |||
34 | static const u8 opaluid[][OPAL_UID_LENGTH] = { | 105 | static const u8 opaluid[][OPAL_UID_LENGTH] = { |
35 | /* users */ | 106 | /* users */ |
36 | [OPAL_SMUID_UID] = | 107 | [OPAL_SMUID_UID] = |
@@ -243,14 +314,14 @@ static u16 get_comid_v200(const void *data) | |||
243 | 314 | ||
244 | static int opal_send_cmd(struct opal_dev *dev) | 315 | static int opal_send_cmd(struct opal_dev *dev) |
245 | { | 316 | { |
246 | return dev->send_recv(dev, dev->comid, TCG_SECP_01, | 317 | return dev->send_recv(dev->data, dev->comid, TCG_SECP_01, |
247 | dev->cmd, IO_BUFFER_LENGTH, | 318 | dev->cmd, IO_BUFFER_LENGTH, |
248 | true); | 319 | true); |
249 | } | 320 | } |
250 | 321 | ||
251 | static int opal_recv_cmd(struct opal_dev *dev) | 322 | static int opal_recv_cmd(struct opal_dev *dev) |
252 | { | 323 | { |
253 | return dev->send_recv(dev, dev->comid, TCG_SECP_01, | 324 | return dev->send_recv(dev->data, dev->comid, TCG_SECP_01, |
254 | dev->resp, IO_BUFFER_LENGTH, | 325 | dev->resp, IO_BUFFER_LENGTH, |
255 | false); | 326 | false); |
256 | } | 327 | } |
@@ -1943,16 +2014,24 @@ static int check_opal_support(struct opal_dev *dev) | |||
1943 | return ret; | 2014 | return ret; |
1944 | } | 2015 | } |
1945 | 2016 | ||
1946 | void init_opal_dev(struct opal_dev *opal_dev, sec_send_recv *send_recv) | 2017 | struct opal_dev *init_opal_dev(void *data, sec_send_recv *send_recv) |
1947 | { | 2018 | { |
1948 | if (opal_dev->initialized) | 2019 | struct opal_dev *dev; |
1949 | return; | 2020 | |
1950 | INIT_LIST_HEAD(&opal_dev->unlk_lst); | 2021 | dev = kmalloc(sizeof(*dev), GFP_KERNEL); |
1951 | mutex_init(&opal_dev->dev_lock); | 2022 | if (!dev) |
1952 | opal_dev->send_recv = send_recv; | 2023 | return NULL; |
1953 | if (check_opal_support(opal_dev) < 0) | 2024 | |
2025 | INIT_LIST_HEAD(&dev->unlk_lst); | ||
2026 | mutex_init(&dev->dev_lock); | ||
2027 | dev->data = data; | ||
2028 | dev->send_recv = send_recv; | ||
2029 | if (check_opal_support(dev) != 0) { | ||
1954 | pr_debug("Opal is not supported on this device\n"); | 2030 | pr_debug("Opal is not supported on this device\n"); |
1955 | opal_dev->initialized = true; | 2031 | kfree(dev); |
2032 | return NULL; | ||
2033 | } | ||
2034 | return dev; | ||
1956 | } | 2035 | } |
1957 | EXPORT_SYMBOL(init_opal_dev); | 2036 | EXPORT_SYMBOL(init_opal_dev); |
1958 | 2037 | ||
@@ -2351,6 +2430,8 @@ int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *arg) | |||
2351 | 2430 | ||
2352 | if (!capable(CAP_SYS_ADMIN)) | 2431 | if (!capable(CAP_SYS_ADMIN)) |
2353 | return -EACCES; | 2432 | return -EACCES; |
2433 | if (!dev) | ||
2434 | return -ENOTSUPP; | ||
2354 | if (!dev->supported) { | 2435 | if (!dev->supported) { |
2355 | pr_err("Not supported\n"); | 2436 | pr_err("Not supported\n"); |
2356 | return -ENOTSUPP; | 2437 | return -ENOTSUPP; |
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index b92a79281611..f6b56a12457a 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c | |||
@@ -789,7 +789,7 @@ static int nvme_ioctl(struct block_device *bdev, fmode_t mode, | |||
789 | return nvme_nvm_ioctl(ns, cmd, arg); | 789 | return nvme_nvm_ioctl(ns, cmd, arg); |
790 | #endif | 790 | #endif |
791 | if (is_sed_ioctl(cmd)) | 791 | if (is_sed_ioctl(cmd)) |
792 | return sed_ioctl(&ns->ctrl->opal_dev, cmd, | 792 | return sed_ioctl(ns->ctrl->opal_dev, cmd, |
793 | (void __user *) arg); | 793 | (void __user *) arg); |
794 | return -ENOTTY; | 794 | return -ENOTTY; |
795 | } | 795 | } |
@@ -1059,18 +1059,17 @@ static const struct pr_ops nvme_pr_ops = { | |||
1059 | }; | 1059 | }; |
1060 | 1060 | ||
1061 | #ifdef CONFIG_BLK_SED_OPAL | 1061 | #ifdef CONFIG_BLK_SED_OPAL |
1062 | int nvme_sec_submit(struct opal_dev *dev, u16 spsp, u8 secp, | 1062 | int nvme_sec_submit(void *data, u16 spsp, u8 secp, void *buffer, size_t len, |
1063 | void *buffer, size_t len, bool send) | 1063 | bool send) |
1064 | { | 1064 | { |
1065 | struct nvme_ctrl *ctrl = data; | ||
1065 | struct nvme_command cmd; | 1066 | struct nvme_command cmd; |
1066 | struct nvme_ctrl *ctrl = NULL; | ||
1067 | 1067 | ||
1068 | memset(&cmd, 0, sizeof(cmd)); | 1068 | memset(&cmd, 0, sizeof(cmd)); |
1069 | if (send) | 1069 | if (send) |
1070 | cmd.common.opcode = nvme_admin_security_send; | 1070 | cmd.common.opcode = nvme_admin_security_send; |
1071 | else | 1071 | else |
1072 | cmd.common.opcode = nvme_admin_security_recv; | 1072 | cmd.common.opcode = nvme_admin_security_recv; |
1073 | ctrl = container_of(dev, struct nvme_ctrl, opal_dev); | ||
1074 | cmd.common.nsid = 0; | 1073 | cmd.common.nsid = 0; |
1075 | cmd.common.cdw10[0] = cpu_to_le32(((u32)secp) << 24 | ((u32)spsp) << 8); | 1074 | cmd.common.cdw10[0] = cpu_to_le32(((u32)secp) << 24 | ((u32)spsp) << 8); |
1076 | cmd.common.cdw10[1] = cpu_to_le32(len); | 1075 | cmd.common.cdw10[1] = cpu_to_le32(len); |
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h index 1aa353a848e3..fd94c94ccbcb 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h | |||
@@ -126,7 +126,7 @@ struct nvme_ctrl { | |||
126 | struct list_head node; | 126 | struct list_head node; |
127 | struct ida ns_ida; | 127 | struct ida ns_ida; |
128 | 128 | ||
129 | struct opal_dev opal_dev; | 129 | struct opal_dev *opal_dev; |
130 | 130 | ||
131 | char name[12]; | 131 | char name[12]; |
132 | char serial[20]; | 132 | char serial[20]; |
@@ -278,16 +278,8 @@ int nvme_init_identify(struct nvme_ctrl *ctrl); | |||
278 | void nvme_queue_scan(struct nvme_ctrl *ctrl); | 278 | void nvme_queue_scan(struct nvme_ctrl *ctrl); |
279 | void nvme_remove_namespaces(struct nvme_ctrl *ctrl); | 279 | void nvme_remove_namespaces(struct nvme_ctrl *ctrl); |
280 | 280 | ||
281 | #ifdef CONFIG_BLK_SED_OPAL | 281 | int nvme_sec_submit(void *data, u16 spsp, u8 secp, void *buffer, size_t len, |
282 | int nvme_sec_submit(struct opal_dev *dev, u16 spsp, u8 secp, | 282 | bool send); |
283 | void *buffer, size_t len, bool send); | ||
284 | #else | ||
285 | static inline int nvme_sec_submit(struct opal_dev *dev, u16 spsp, u8 secp, | ||
286 | void *buffer, size_t len, bool send) | ||
287 | { | ||
288 | return 0; | ||
289 | } | ||
290 | #endif /* CONFIG_BLK_DEV_SED_OPAL */ | ||
291 | 283 | ||
292 | #define NVME_NR_AERS 1 | 284 | #define NVME_NR_AERS 1 |
293 | void nvme_complete_async_event(struct nvme_ctrl *ctrl, __le16 status, | 285 | void nvme_complete_async_event(struct nvme_ctrl *ctrl, __le16 status, |
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index f08e86e73dda..50b070528c50 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c | |||
@@ -1742,6 +1742,7 @@ static void nvme_pci_free_ctrl(struct nvme_ctrl *ctrl) | |||
1742 | if (dev->ctrl.admin_q) | 1742 | if (dev->ctrl.admin_q) |
1743 | blk_put_queue(dev->ctrl.admin_q); | 1743 | blk_put_queue(dev->ctrl.admin_q); |
1744 | kfree(dev->queues); | 1744 | kfree(dev->queues); |
1745 | kfree(dev->ctrl.opal_dev); | ||
1745 | kfree(dev); | 1746 | kfree(dev); |
1746 | } | 1747 | } |
1747 | 1748 | ||
@@ -1791,10 +1792,13 @@ static void nvme_reset_work(struct work_struct *work) | |||
1791 | if (result) | 1792 | if (result) |
1792 | goto out; | 1793 | goto out; |
1793 | 1794 | ||
1794 | init_opal_dev(&dev->ctrl.opal_dev, &nvme_sec_submit); | 1795 | if (!dev->ctrl.opal_dev) { |
1796 | dev->ctrl.opal_dev = | ||
1797 | init_opal_dev(&dev->ctrl, &nvme_sec_submit); | ||
1798 | } | ||
1795 | 1799 | ||
1796 | if (was_suspend) | 1800 | if (was_suspend) |
1797 | opal_unlock_from_suspend(&dev->ctrl.opal_dev); | 1801 | opal_unlock_from_suspend(dev->ctrl.opal_dev); |
1798 | 1802 | ||
1799 | result = nvme_setup_io_queues(dev); | 1803 | result = nvme_setup_io_queues(dev); |
1800 | if (result) | 1804 | if (result) |
diff --git a/include/linux/sed-opal.h b/include/linux/sed-opal.h index 205d520ea688..deee23d012e7 100644 --- a/include/linux/sed-opal.h +++ b/include/linux/sed-opal.h | |||
@@ -21,117 +21,14 @@ | |||
21 | #include <uapi/linux/sed-opal.h> | 21 | #include <uapi/linux/sed-opal.h> |
22 | #include <linux/kernel.h> | 22 | #include <linux/kernel.h> |
23 | 23 | ||
24 | /* | ||
25 | * These constant values come from: | ||
26 | * SPC-4 section | ||
27 | * 6.30 SECURITY PROTOCOL IN command / table 265. | ||
28 | */ | ||
29 | enum { | ||
30 | TCG_SECP_00 = 0, | ||
31 | TCG_SECP_01, | ||
32 | }; | ||
33 | struct opal_dev; | 24 | struct opal_dev; |
34 | 25 | ||
35 | #define IO_BUFFER_LENGTH 2048 | 26 | typedef int (sec_send_recv)(void *data, u16 spsp, u8 secp, void *buffer, |
36 | #define MAX_TOKS 64 | 27 | size_t len, bool send); |
37 | |||
38 | typedef int (*opal_step)(struct opal_dev *dev); | ||
39 | typedef int (sec_send_recv)(struct opal_dev *ctx, u16 spsp, u8 secp, | ||
40 | void *buffer, size_t len, bool send); | ||
41 | |||
42 | |||
43 | enum opal_atom_width { | ||
44 | OPAL_WIDTH_TINY, | ||
45 | OPAL_WIDTH_SHORT, | ||
46 | OPAL_WIDTH_MEDIUM, | ||
47 | OPAL_WIDTH_LONG, | ||
48 | OPAL_WIDTH_TOKEN | ||
49 | }; | ||
50 | |||
51 | /* | ||
52 | * Token defs derived from: | ||
53 | * TCG_Storage_Architecture_Core_Spec_v2.01_r1.00 | ||
54 | * 3.2.2 Data Stream Encoding | ||
55 | */ | ||
56 | enum opal_response_token { | ||
57 | OPAL_DTA_TOKENID_BYTESTRING = 0xe0, | ||
58 | OPAL_DTA_TOKENID_SINT = 0xe1, | ||
59 | OPAL_DTA_TOKENID_UINT = 0xe2, | ||
60 | OPAL_DTA_TOKENID_TOKEN = 0xe3, /* actual token is returned */ | ||
61 | OPAL_DTA_TOKENID_INVALID = 0X0 | ||
62 | }; | ||
63 | |||
64 | /* | ||
65 | * On the parsed response, we don't store again the toks that are already | ||
66 | * stored in the response buffer. Instead, for each token, we just store a | ||
67 | * pointer to the position in the buffer where the token starts, and the size | ||
68 | * of the token in bytes. | ||
69 | */ | ||
70 | struct opal_resp_tok { | ||
71 | const u8 *pos; | ||
72 | size_t len; | ||
73 | enum opal_response_token type; | ||
74 | enum opal_atom_width width; | ||
75 | union { | ||
76 | u64 u; | ||
77 | s64 s; | ||
78 | } stored; | ||
79 | }; | ||
80 | |||
81 | /* | ||
82 | * From the response header it's not possible to know how many tokens there are | ||
83 | * on the payload. So we hardcode that the maximum will be MAX_TOKS, and later | ||
84 | * if we start dealing with messages that have more than that, we can increase | ||
85 | * this number. This is done to avoid having to make two passes through the | ||
86 | * response, the first one counting how many tokens we have and the second one | ||
87 | * actually storing the positions. | ||
88 | */ | ||
89 | struct parsed_resp { | ||
90 | int num; | ||
91 | struct opal_resp_tok toks[MAX_TOKS]; | ||
92 | }; | ||
93 | |||
94 | /** | ||
95 | * struct opal_dev - The structure representing a OPAL enabled SED. | ||
96 | * @supported: Whether or not OPAL is supported on this controller. | ||
97 | * @send_recv: The combined sec_send/sec_recv function pointer. | ||
98 | * @opal_step: A series of opal methods that are necessary to complete a command. | ||
99 | * @func_data: An array of parameters for the opal methods above. | ||
100 | * @state: Describes the current opal_step we're working on. | ||
101 | * @dev_lock: Locks the entire opal_dev structure. | ||
102 | * @parsed: Parsed response from controller. | ||
103 | * @prev_data: Data returned from a method to the controller. | ||
104 | * @unlk_lst: A list of Locking ranges to unlock on this device during a resume. | ||
105 | */ | ||
106 | struct opal_dev { | ||
107 | bool initialized; | ||
108 | bool supported; | ||
109 | sec_send_recv *send_recv; | ||
110 | |||
111 | const opal_step *funcs; | ||
112 | void **func_data; | ||
113 | int state; | ||
114 | struct mutex dev_lock; | ||
115 | u16 comid; | ||
116 | u32 hsn; | ||
117 | u32 tsn; | ||
118 | u64 align; | ||
119 | u64 lowest_lba; | ||
120 | |||
121 | size_t pos; | ||
122 | u8 cmd[IO_BUFFER_LENGTH]; | ||
123 | u8 resp[IO_BUFFER_LENGTH]; | ||
124 | |||
125 | struct parsed_resp parsed; | ||
126 | size_t prev_d_len; | ||
127 | void *prev_data; | ||
128 | |||
129 | struct list_head unlk_lst; | ||
130 | }; | ||
131 | 28 | ||
132 | #ifdef CONFIG_BLK_SED_OPAL | 29 | #ifdef CONFIG_BLK_SED_OPAL |
133 | bool opal_unlock_from_suspend(struct opal_dev *dev); | 30 | bool opal_unlock_from_suspend(struct opal_dev *dev); |
134 | void init_opal_dev(struct opal_dev *opal_dev, sec_send_recv *send_recv); | 31 | struct opal_dev *init_opal_dev(void *data, sec_send_recv *send_recv); |
135 | int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *ioctl_ptr); | 32 | int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *ioctl_ptr); |
136 | 33 | ||
137 | static inline bool is_sed_ioctl(unsigned int cmd) | 34 | static inline bool is_sed_ioctl(unsigned int cmd) |
@@ -168,11 +65,6 @@ static inline bool opal_unlock_from_suspend(struct opal_dev *dev) | |||
168 | { | 65 | { |
169 | return false; | 66 | return false; |
170 | } | 67 | } |
171 | static inline void init_opal_dev(struct opal_dev *opal_dev, | 68 | #define init_opal_dev(data, send_recv) NULL |
172 | sec_send_recv *send_recv) | ||
173 | { | ||
174 | opal_dev->supported = false; | ||
175 | opal_dev->initialized = true; | ||
176 | } | ||
177 | #endif /* CONFIG_BLK_SED_OPAL */ | 69 | #endif /* CONFIG_BLK_SED_OPAL */ |
178 | #endif /* LINUX_OPAL_H */ | 70 | #endif /* LINUX_OPAL_H */ |