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 /block/sed-opal.c | |
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>
Diffstat (limited to 'block/sed-opal.c')
-rw-r--r-- | block/sed-opal.c | 101 |
1 files changed, 91 insertions, 10 deletions
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; |