diff options
-rw-r--r-- | drivers/scsi/osd/osd_initiator.c | 94 | ||||
-rw-r--r-- | include/scsi/osd_initiator.h | 39 | ||||
-rw-r--r-- | include/scsi/osd_protocol.h | 90 |
3 files changed, 205 insertions, 18 deletions
diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c index 3fd021a57e59..86a76cccfebd 100644 --- a/drivers/scsi/osd/osd_initiator.c +++ b/drivers/scsi/osd/osd_initiator.c | |||
@@ -59,36 +59,50 @@ static inline void build_test(void) | |||
59 | { | 59 | { |
60 | /* structures were not packed */ | 60 | /* structures were not packed */ |
61 | BUILD_BUG_ON(sizeof(struct osd_capability) != OSD_CAP_LEN); | 61 | BUILD_BUG_ON(sizeof(struct osd_capability) != OSD_CAP_LEN); |
62 | BUILD_BUG_ON(sizeof(struct osdv2_cdb) != OSD_TOTAL_CDB_LEN); | ||
62 | BUILD_BUG_ON(sizeof(struct osdv1_cdb) != OSDv1_TOTAL_CDB_LEN); | 63 | BUILD_BUG_ON(sizeof(struct osdv1_cdb) != OSDv1_TOTAL_CDB_LEN); |
63 | } | 64 | } |
64 | 65 | ||
65 | static unsigned _osd_req_cdb_len(struct osd_request *or) | 66 | static unsigned _osd_req_cdb_len(struct osd_request *or) |
66 | { | 67 | { |
67 | return OSDv1_TOTAL_CDB_LEN; | 68 | return osd_req_is_ver1(or) ? OSDv1_TOTAL_CDB_LEN : OSD_TOTAL_CDB_LEN; |
68 | } | 69 | } |
69 | 70 | ||
70 | static unsigned _osd_req_alist_elem_size(struct osd_request *or, unsigned len) | 71 | static unsigned _osd_req_alist_elem_size(struct osd_request *or, unsigned len) |
71 | { | 72 | { |
72 | return osdv1_attr_list_elem_size(len); | 73 | return osd_req_is_ver1(or) ? |
74 | osdv1_attr_list_elem_size(len) : | ||
75 | osdv2_attr_list_elem_size(len); | ||
73 | } | 76 | } |
74 | 77 | ||
75 | static unsigned _osd_req_alist_size(struct osd_request *or, void *list_head) | 78 | static unsigned _osd_req_alist_size(struct osd_request *or, void *list_head) |
76 | { | 79 | { |
77 | return osdv1_list_size(list_head); | 80 | return osd_req_is_ver1(or) ? |
81 | osdv1_list_size(list_head) : | ||
82 | osdv2_list_size(list_head); | ||
78 | } | 83 | } |
79 | 84 | ||
80 | static unsigned _osd_req_sizeof_alist_header(struct osd_request *or) | 85 | static unsigned _osd_req_sizeof_alist_header(struct osd_request *or) |
81 | { | 86 | { |
82 | return sizeof(struct osdv1_attributes_list_header); | 87 | return osd_req_is_ver1(or) ? |
88 | sizeof(struct osdv1_attributes_list_header) : | ||
89 | sizeof(struct osdv2_attributes_list_header); | ||
83 | } | 90 | } |
84 | 91 | ||
85 | static void _osd_req_set_alist_type(struct osd_request *or, | 92 | static void _osd_req_set_alist_type(struct osd_request *or, |
86 | void *list, int list_type) | 93 | void *list, int list_type) |
87 | { | 94 | { |
88 | struct osdv1_attributes_list_header *attr_list = list; | 95 | if (osd_req_is_ver1(or)) { |
96 | struct osdv1_attributes_list_header *attr_list = list; | ||
97 | |||
98 | memset(attr_list, 0, sizeof(*attr_list)); | ||
99 | attr_list->type = list_type; | ||
100 | } else { | ||
101 | struct osdv2_attributes_list_header *attr_list = list; | ||
89 | 102 | ||
90 | memset(attr_list, 0, sizeof(*attr_list)); | 103 | memset(attr_list, 0, sizeof(*attr_list)); |
91 | attr_list->type = list_type; | 104 | attr_list->type = list_type; |
105 | } | ||
92 | } | 106 | } |
93 | 107 | ||
94 | static bool _osd_req_is_alist_type(struct osd_request *or, | 108 | static bool _osd_req_is_alist_type(struct osd_request *or, |
@@ -97,10 +111,14 @@ static bool _osd_req_is_alist_type(struct osd_request *or, | |||
97 | if (!list) | 111 | if (!list) |
98 | return false; | 112 | return false; |
99 | 113 | ||
100 | if (1) { | 114 | if (osd_req_is_ver1(or)) { |
101 | struct osdv1_attributes_list_header *attr_list = list; | 115 | struct osdv1_attributes_list_header *attr_list = list; |
102 | 116 | ||
103 | return attr_list->type == list_type; | 117 | return attr_list->type == list_type; |
118 | } else { | ||
119 | struct osdv2_attributes_list_header *attr_list = list; | ||
120 | |||
121 | return attr_list->type == list_type; | ||
104 | } | 122 | } |
105 | } | 123 | } |
106 | 124 | ||
@@ -110,15 +128,22 @@ static void _osd_req_encode_olist(struct osd_request *or, | |||
110 | { | 128 | { |
111 | struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb); | 129 | struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb); |
112 | 130 | ||
113 | cdbh->v1.list_identifier = list->list_identifier; | 131 | if (osd_req_is_ver1(or)) { |
114 | cdbh->v1.start_address = list->continuation_id; | 132 | cdbh->v1.list_identifier = list->list_identifier; |
133 | cdbh->v1.start_address = list->continuation_id; | ||
134 | } else { | ||
135 | cdbh->v2.list_identifier = list->list_identifier; | ||
136 | cdbh->v2.start_address = list->continuation_id; | ||
137 | } | ||
115 | } | 138 | } |
116 | 139 | ||
117 | static osd_cdb_offset osd_req_encode_offset(struct osd_request *or, | 140 | static osd_cdb_offset osd_req_encode_offset(struct osd_request *or, |
118 | u64 offset, unsigned *padding) | 141 | u64 offset, unsigned *padding) |
119 | { | 142 | { |
120 | return __osd_encode_offset(offset, padding, | 143 | return __osd_encode_offset(offset, padding, |
121 | OSDv1_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT); | 144 | osd_req_is_ver1(or) ? |
145 | OSDv1_OFFSET_MIN_SHIFT : OSD_OFFSET_MIN_SHIFT, | ||
146 | OSD_OFFSET_MAX_SHIFT); | ||
122 | } | 147 | } |
123 | 148 | ||
124 | static struct osd_security_parameters * | 149 | static struct osd_security_parameters * |
@@ -126,7 +151,10 @@ _osd_req_sec_params(struct osd_request *or) | |||
126 | { | 151 | { |
127 | struct osd_cdb *ocdb = &or->cdb; | 152 | struct osd_cdb *ocdb = &or->cdb; |
128 | 153 | ||
129 | return &ocdb->v1.sec_params; | 154 | if (osd_req_is_ver1(or)) |
155 | return &ocdb->v1.sec_params; | ||
156 | else | ||
157 | return &ocdb->v2.sec_params; | ||
130 | } | 158 | } |
131 | 159 | ||
132 | void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_device) | 160 | void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_device) |
@@ -134,6 +162,9 @@ void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_device) | |||
134 | memset(osdd, 0, sizeof(*osdd)); | 162 | memset(osdd, 0, sizeof(*osdd)); |
135 | osdd->scsi_device = scsi_device; | 163 | osdd->scsi_device = scsi_device; |
136 | osdd->def_timeout = BLK_DEFAULT_SG_TIMEOUT; | 164 | osdd->def_timeout = BLK_DEFAULT_SG_TIMEOUT; |
165 | #ifdef OSD_VER1_SUPPORT | ||
166 | osdd->version = OSD_VER2; | ||
167 | #endif | ||
137 | /* TODO: Allocate pools for osd_request attributes ... */ | 168 | /* TODO: Allocate pools for osd_request attributes ... */ |
138 | } | 169 | } |
139 | EXPORT_SYMBOL(osd_dev_init); | 170 | EXPORT_SYMBOL(osd_dev_init); |
@@ -334,10 +365,30 @@ static void _osdv1_req_encode_common(struct osd_request *or, | |||
334 | ocdb->h.v1.start_address = cpu_to_be64(offset); | 365 | ocdb->h.v1.start_address = cpu_to_be64(offset); |
335 | } | 366 | } |
336 | 367 | ||
368 | static void _osdv2_req_encode_common(struct osd_request *or, | ||
369 | __be16 act, const struct osd_obj_id *obj, u64 offset, u64 len) | ||
370 | { | ||
371 | struct osdv2_cdb *ocdb = &or->cdb.v2; | ||
372 | |||
373 | OSD_DEBUG("OSDv2 execute opcode 0x%x\n", be16_to_cpu(act)); | ||
374 | |||
375 | ocdb->h.varlen_cdb.opcode = VARIABLE_LENGTH_CMD; | ||
376 | ocdb->h.varlen_cdb.additional_cdb_length = OSD_ADDITIONAL_CDB_LENGTH; | ||
377 | ocdb->h.varlen_cdb.service_action = act; | ||
378 | |||
379 | ocdb->h.partition = cpu_to_be64(obj->partition); | ||
380 | ocdb->h.object = cpu_to_be64(obj->id); | ||
381 | ocdb->h.v2.length = cpu_to_be64(len); | ||
382 | ocdb->h.v2.start_address = cpu_to_be64(offset); | ||
383 | } | ||
384 | |||
337 | static void _osd_req_encode_common(struct osd_request *or, | 385 | static void _osd_req_encode_common(struct osd_request *or, |
338 | __be16 act, const struct osd_obj_id *obj, u64 offset, u64 len) | 386 | __be16 act, const struct osd_obj_id *obj, u64 offset, u64 len) |
339 | { | 387 | { |
340 | _osdv1_req_encode_common(or, act, obj, offset, len); | 388 | if (osd_req_is_ver1(or)) |
389 | _osdv1_req_encode_common(or, act, obj, offset, len); | ||
390 | else | ||
391 | _osdv2_req_encode_common(or, act, obj, offset, len); | ||
341 | } | 392 | } |
342 | 393 | ||
343 | /* | 394 | /* |
@@ -546,6 +597,12 @@ void osd_req_flush_object(struct osd_request *or, | |||
546 | const struct osd_obj_id *obj, enum osd_options_flush_scope_values op, | 597 | const struct osd_obj_id *obj, enum osd_options_flush_scope_values op, |
547 | /*V2*/ u64 offset, /*V2*/ u64 len) | 598 | /*V2*/ u64 offset, /*V2*/ u64 len) |
548 | { | 599 | { |
600 | if (unlikely(osd_req_is_ver1(or) && (offset || len))) { | ||
601 | OSD_DEBUG("OSD Ver1 flush on specific range ignored\n"); | ||
602 | offset = 0; | ||
603 | len = 0; | ||
604 | } | ||
605 | |||
549 | _osd_req_encode_common(or, OSD_ACT_FLUSH, obj, offset, len); | 606 | _osd_req_encode_common(or, OSD_ACT_FLUSH, obj, offset, len); |
550 | _osd_req_encode_flush(or, op); | 607 | _osd_req_encode_flush(or, op); |
551 | } | 608 | } |
@@ -1169,6 +1226,10 @@ enum { OSD_SEC_CAP_V1_ALL_CAPS = | |||
1169 | OSD_SEC_CAP_GLOBAL | OSD_SEC_CAP_DEV_MGMT | 1226 | OSD_SEC_CAP_GLOBAL | OSD_SEC_CAP_DEV_MGMT |
1170 | }; | 1227 | }; |
1171 | 1228 | ||
1229 | enum { OSD_SEC_CAP_V2_ALL_CAPS = | ||
1230 | OSD_SEC_CAP_V1_ALL_CAPS | OSD_SEC_CAP_QUERY | OSD_SEC_CAP_M_OBJECT | ||
1231 | }; | ||
1232 | |||
1172 | void osd_sec_init_nosec_doall_caps(void *caps, | 1233 | void osd_sec_init_nosec_doall_caps(void *caps, |
1173 | const struct osd_obj_id *obj, bool is_collection, const bool is_v1) | 1234 | const struct osd_obj_id *obj, bool is_collection, const bool is_v1) |
1174 | { | 1235 | { |
@@ -1210,9 +1271,14 @@ void osd_sec_init_nosec_doall_caps(void *caps, | |||
1210 | } | 1271 | } |
1211 | EXPORT_SYMBOL(osd_sec_init_nosec_doall_caps); | 1272 | EXPORT_SYMBOL(osd_sec_init_nosec_doall_caps); |
1212 | 1273 | ||
1274 | /* FIXME: Extract version from caps pointer. | ||
1275 | * Also Pete's target only supports caps from OSDv1 for now | ||
1276 | */ | ||
1213 | void osd_set_caps(struct osd_cdb *cdb, const void *caps) | 1277 | void osd_set_caps(struct osd_cdb *cdb, const void *caps) |
1214 | { | 1278 | { |
1215 | memcpy(&cdb->v1.caps, caps, OSDv1_CAP_LEN); | 1279 | bool is_ver1 = true; |
1280 | /* NOTE: They start at same address */ | ||
1281 | memcpy(&cdb->v1.caps, caps, is_ver1 ? OSDv1_CAP_LEN : OSD_CAP_LEN); | ||
1216 | } | 1282 | } |
1217 | 1283 | ||
1218 | bool osd_is_sec_alldata(struct osd_security_parameters *sec_parms __unused) | 1284 | bool osd_is_sec_alldata(struct osd_security_parameters *sec_parms __unused) |
diff --git a/include/scsi/osd_initiator.h b/include/scsi/osd_initiator.h index e84dc7aa5e34..8482777416d8 100644 --- a/include/scsi/osd_initiator.h +++ b/include/scsi/osd_initiator.h | |||
@@ -21,6 +21,23 @@ | |||
21 | 21 | ||
22 | /* Note: "NI" in comments below means "Not Implemented yet" */ | 22 | /* Note: "NI" in comments below means "Not Implemented yet" */ |
23 | 23 | ||
24 | /* Configure of code: | ||
25 | * #undef if you *don't* want OSD v1 support in runtime. | ||
26 | * If #defined the initiator will dynamically configure to encode OSD v1 | ||
27 | * CDB's if the target is detected to be OSD v1 only. | ||
28 | * OSD v2 only commands, options, and attributes will be ignored if target | ||
29 | * is v1 only. | ||
30 | * If #defined will result in bigger/slower code (OK Slower maybe not) | ||
31 | * Q: Should this be CONFIG_SCSI_OSD_VER1_SUPPORT and set from Kconfig? | ||
32 | */ | ||
33 | #define OSD_VER1_SUPPORT y | ||
34 | |||
35 | enum osd_std_version { | ||
36 | OSD_VER_NONE = 0, | ||
37 | OSD_VER1 = 1, | ||
38 | OSD_VER2 = 2, | ||
39 | }; | ||
40 | |||
24 | /* | 41 | /* |
25 | * Object-based Storage Device. | 42 | * Object-based Storage Device. |
26 | * This object represents an OSD device. | 43 | * This object represents an OSD device. |
@@ -31,6 +48,10 @@ | |||
31 | struct osd_dev { | 48 | struct osd_dev { |
32 | struct scsi_device *scsi_device; | 49 | struct scsi_device *scsi_device; |
33 | unsigned def_timeout; | 50 | unsigned def_timeout; |
51 | |||
52 | #ifdef OSD_VER1_SUPPORT | ||
53 | enum osd_std_version version; | ||
54 | #endif | ||
34 | }; | 55 | }; |
35 | 56 | ||
36 | /* Retrieve/return osd_dev(s) for use by Kernel clients */ | 57 | /* Retrieve/return osd_dev(s) for use by Kernel clients */ |
@@ -46,6 +67,14 @@ void osduld_unregister_test(unsigned ioctl); | |||
46 | void osd_dev_init(struct osd_dev *od, struct scsi_device *scsi_device); | 67 | void osd_dev_init(struct osd_dev *od, struct scsi_device *scsi_device); |
47 | void osd_dev_fini(struct osd_dev *od); | 68 | void osd_dev_fini(struct osd_dev *od); |
48 | 69 | ||
70 | /* we might want to use function vector in the future */ | ||
71 | static inline void osd_dev_set_ver(struct osd_dev *od, enum osd_std_version v) | ||
72 | { | ||
73 | #ifdef OSD_VER1_SUPPORT | ||
74 | od->version = v; | ||
75 | #endif | ||
76 | } | ||
77 | |||
49 | struct osd_request; | 78 | struct osd_request; |
50 | typedef void (osd_req_done_fn)(struct osd_request *or, void *private); | 79 | typedef void (osd_req_done_fn)(struct osd_request *or, void *private); |
51 | 80 | ||
@@ -82,6 +111,16 @@ struct osd_request { | |||
82 | int async_error; | 111 | int async_error; |
83 | }; | 112 | }; |
84 | 113 | ||
114 | /* OSD Version control */ | ||
115 | static inline bool osd_req_is_ver1(struct osd_request *or) | ||
116 | { | ||
117 | #ifdef OSD_VER1_SUPPORT | ||
118 | return or->osd_dev->version == OSD_VER1; | ||
119 | #else | ||
120 | return false; | ||
121 | #endif | ||
122 | } | ||
123 | |||
85 | /* | 124 | /* |
86 | * How to use the osd library: | 125 | * How to use the osd library: |
87 | * | 126 | * |
diff --git a/include/scsi/osd_protocol.h b/include/scsi/osd_protocol.h index ce1a8771ea71..cd3cbf764650 100644 --- a/include/scsi/osd_protocol.h +++ b/include/scsi/osd_protocol.h | |||
@@ -25,12 +25,16 @@ enum { | |||
25 | OSDv1_TOTAL_CDB_LEN = OSDv1_ADDITIONAL_CDB_LENGTH + 8, | 25 | OSDv1_TOTAL_CDB_LEN = OSDv1_ADDITIONAL_CDB_LENGTH + 8, |
26 | OSDv1_CAP_LEN = 80, | 26 | OSDv1_CAP_LEN = 80, |
27 | /* Latest supported version */ | 27 | /* Latest supported version */ |
28 | OSD_ADDITIONAL_CDB_LENGTH = OSDv1_ADDITIONAL_CDB_LENGTH, | 28 | /* OSD_ADDITIONAL_CDB_LENGTH = 216,*/ |
29 | OSD_TOTAL_CDB_LEN = OSDv1_TOTAL_CDB_LEN, | 29 | OSD_ADDITIONAL_CDB_LENGTH = |
30 | OSD_CAP_LEN = OSDv1_CAP_LEN, | 30 | OSDv1_ADDITIONAL_CDB_LENGTH, /* FIXME: Pete rev-001 sup */ |
31 | OSD_TOTAL_CDB_LEN = OSD_ADDITIONAL_CDB_LENGTH + 8, | ||
32 | /* OSD_CAP_LEN = 104,*/ | ||
33 | OSD_CAP_LEN = OSDv1_CAP_LEN,/* FIXME: Pete rev-001 sup */ | ||
31 | 34 | ||
32 | OSD_SYSTEMID_LEN = 20, | 35 | OSD_SYSTEMID_LEN = 20, |
33 | OSD_CRYPTO_KEYID_SIZE = 20, | 36 | OSD_CRYPTO_KEYID_SIZE = 20, |
37 | /*FIXME: OSDv2_CRYPTO_KEYID_SIZE = 32,*/ | ||
34 | OSD_CRYPTO_SEED_SIZE = 4, | 38 | OSD_CRYPTO_SEED_SIZE = 4, |
35 | OSD_CRYPTO_NONCE_SIZE = 12, | 39 | OSD_CRYPTO_NONCE_SIZE = 12, |
36 | OSD_MAX_SENSE_LEN = 252, /* from SPC-3 */ | 40 | OSD_MAX_SENSE_LEN = 252, /* from SPC-3 */ |
@@ -108,6 +112,7 @@ enum { | |||
108 | OSD_OFFSET_MAX_BITS = 28, | 112 | OSD_OFFSET_MAX_BITS = 28, |
109 | 113 | ||
110 | OSDv1_OFFSET_MIN_SHIFT = 8, | 114 | OSDv1_OFFSET_MIN_SHIFT = 8, |
115 | OSD_OFFSET_MIN_SHIFT = 3, | ||
111 | OSD_OFFSET_MAX_SHIFT = 16, | 116 | OSD_OFFSET_MAX_SHIFT = 16, |
112 | }; | 117 | }; |
113 | 118 | ||
@@ -129,6 +134,16 @@ static inline osd_cdb_offset osd_encode_offset_v1(u64 offset, unsigned *padding) | |||
129 | OSDv1_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT); | 134 | OSDv1_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT); |
130 | } | 135 | } |
131 | 136 | ||
137 | /* Minimum 8 bytes alignment | ||
138 | * Same as v1 but since exponent can be signed than a less than | ||
139 | * 256 alignment can be reached with small offsets (<2GB) | ||
140 | */ | ||
141 | static inline osd_cdb_offset osd_encode_offset_v2(u64 offset, unsigned *padding) | ||
142 | { | ||
143 | return __osd_encode_offset(offset, padding, | ||
144 | OSD_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT); | ||
145 | } | ||
146 | |||
132 | /* osd2r03: 5.2.1 Overview */ | 147 | /* osd2r03: 5.2.1 Overview */ |
133 | struct osd_cdb_head { | 148 | struct osd_cdb_head { |
134 | struct scsi_varlen_cdb_hdr varlen_cdb; | 149 | struct scsi_varlen_cdb_hdr varlen_cdb; |
@@ -144,6 +159,13 @@ struct osd_cdb_head { | |||
144 | /*36*/ __be64 length; | 159 | /*36*/ __be64 length; |
145 | /*44*/ __be64 start_address; | 160 | /*44*/ __be64 start_address; |
146 | } __packed v1; | 161 | } __packed v1; |
162 | |||
163 | struct __osdv2_cdb_addr_len { | ||
164 | /* called allocation_length in some commands */ | ||
165 | /*32*/ __be64 length; | ||
166 | /*40*/ __be64 start_address; | ||
167 | /*48*/ __be32 list_identifier;/* Rarely used */ | ||
168 | } __packed v2; | ||
147 | }; | 169 | }; |
148 | /*52*/ union { /* selected attributes mode Page/List/Single */ | 170 | /*52*/ union { /* selected attributes mode Page/List/Single */ |
149 | struct osd_attributes_page_mode { | 171 | struct osd_attributes_page_mode { |
@@ -182,6 +204,7 @@ struct osd_cdb_head { | |||
182 | /*80*/ | 204 | /*80*/ |
183 | 205 | ||
184 | /*160 v1*/ | 206 | /*160 v1*/ |
207 | /*184 v2*/ | ||
185 | struct osd_security_parameters { | 208 | struct osd_security_parameters { |
186 | /*160*/u8 integrity_check_value[OSD_CRYPTO_KEYID_SIZE]; | 209 | /*160*/u8 integrity_check_value[OSD_CRYPTO_KEYID_SIZE]; |
187 | /*180*/u8 request_nonce[OSD_CRYPTO_NONCE_SIZE]; | 210 | /*180*/u8 request_nonce[OSD_CRYPTO_NONCE_SIZE]; |
@@ -189,6 +212,9 @@ struct osd_security_parameters { | |||
189 | /*196*/osd_cdb_offset data_out_integrity_check_offset; | 212 | /*196*/osd_cdb_offset data_out_integrity_check_offset; |
190 | } __packed; | 213 | } __packed; |
191 | /*200 v1*/ | 214 | /*200 v1*/ |
215 | /*224 v2*/ | ||
216 | |||
217 | /* FIXME: osdv2_security_parameters */ | ||
192 | 218 | ||
193 | struct osdv1_cdb { | 219 | struct osdv1_cdb { |
194 | struct osd_cdb_head h; | 220 | struct osd_cdb_head h; |
@@ -196,9 +222,17 @@ struct osdv1_cdb { | |||
196 | struct osd_security_parameters sec_params; | 222 | struct osd_security_parameters sec_params; |
197 | } __packed; | 223 | } __packed; |
198 | 224 | ||
225 | struct osdv2_cdb { | ||
226 | struct osd_cdb_head h; | ||
227 | u8 caps[OSD_CAP_LEN]; | ||
228 | struct osd_security_parameters sec_params; | ||
229 | /* FIXME: osdv2_security_parameters */ | ||
230 | } __packed; | ||
231 | |||
199 | struct osd_cdb { | 232 | struct osd_cdb { |
200 | union { | 233 | union { |
201 | struct osdv1_cdb v1; | 234 | struct osdv1_cdb v1; |
235 | struct osdv2_cdb v2; | ||
202 | u8 buff[OSD_TOTAL_CDB_LEN]; | 236 | u8 buff[OSD_TOTAL_CDB_LEN]; |
203 | }; | 237 | }; |
204 | } __packed; | 238 | } __packed; |
@@ -269,6 +303,7 @@ struct osd_attributes_list_attrid { | |||
269 | /* | 303 | /* |
270 | * osd2r03: 7.1.3.3 List entry format for retrieved attributes and | 304 | * osd2r03: 7.1.3.3 List entry format for retrieved attributes and |
271 | * for setting attributes | 305 | * for setting attributes |
306 | * NOTE: v2 is 8-bytes aligned, v1 is not aligned. | ||
272 | */ | 307 | */ |
273 | struct osd_attributes_list_element { | 308 | struct osd_attributes_list_element { |
274 | __be32 attr_page; | 309 | __be32 attr_page; |
@@ -279,6 +314,7 @@ struct osd_attributes_list_element { | |||
279 | 314 | ||
280 | enum { | 315 | enum { |
281 | OSDv1_ATTRIBUTES_ELEM_ALIGN = 1, | 316 | OSDv1_ATTRIBUTES_ELEM_ALIGN = 1, |
317 | OSD_ATTRIBUTES_ELEM_ALIGN = 8, | ||
282 | }; | 318 | }; |
283 | 319 | ||
284 | enum { | 320 | enum { |
@@ -292,6 +328,12 @@ static inline unsigned osdv1_attr_list_elem_size(unsigned len) | |||
292 | OSDv1_ATTRIBUTES_ELEM_ALIGN); | 328 | OSDv1_ATTRIBUTES_ELEM_ALIGN); |
293 | } | 329 | } |
294 | 330 | ||
331 | static inline unsigned osdv2_attr_list_elem_size(unsigned len) | ||
332 | { | ||
333 | return ALIGN(len + sizeof(struct osd_attributes_list_element), | ||
334 | OSD_ATTRIBUTES_ELEM_ALIGN); | ||
335 | } | ||
336 | |||
295 | /* | 337 | /* |
296 | * osd2r03: 7.1.3 OSD attributes lists (Table 184) — List type values | 338 | * osd2r03: 7.1.3 OSD attributes lists (Table 184) — List type values |
297 | */ | 339 | */ |
@@ -326,6 +368,21 @@ static inline unsigned osdv1_list_size(struct osdv1_attributes_list_header *h) | |||
326 | return be16_to_cpu(h->list_bytes); | 368 | return be16_to_cpu(h->list_bytes); |
327 | } | 369 | } |
328 | 370 | ||
371 | struct osdv2_attributes_list_header { | ||
372 | u8 type; /* lower 4-bits only */ | ||
373 | u8 pad[3]; | ||
374 | /*4*/ __be32 list_bytes; /* Initiator shall set to zero. Only set by target */ | ||
375 | /* | ||
376 | * type=9 followed by struct osd_attributes_list_element's | ||
377 | * type=E followed by struct osd_attributes_list_multi_header's | ||
378 | */ | ||
379 | } __packed; | ||
380 | |||
381 | static inline unsigned osdv2_list_size(struct osdv2_attributes_list_header *h) | ||
382 | { | ||
383 | return be32_to_cpu(h->list_bytes); | ||
384 | } | ||
385 | |||
329 | /* (osd-r10 6.13) | 386 | /* (osd-r10 6.13) |
330 | * osd2r03: 6.15 LIST (Table 79) LIST command parameter data. | 387 | * osd2r03: 6.15 LIST (Table 79) LIST command parameter data. |
331 | * for root_lstchg below | 388 | * for root_lstchg below |
@@ -469,11 +526,36 @@ struct osdv1_cap_object_descriptor { | |||
469 | } __packed; | 526 | } __packed; |
470 | /*80 v1*/ | 527 | /*80 v1*/ |
471 | 528 | ||
472 | struct osd_capability { | 529 | /*56 v2*/ |
530 | struct osd_cap_object_descriptor { | ||
531 | union { | ||
532 | struct { | ||
533 | /*56*/ __be32 allowed_attributes_access; | ||
534 | /*60*/ __be32 policy_access_tag; | ||
535 | /*64*/ __be16 boot_epoch; | ||
536 | /*66*/ u8 reserved[6]; | ||
537 | /*72*/ __be64 allowed_partition_id; | ||
538 | /*80*/ __be64 allowed_object_id; | ||
539 | /*88*/ __be64 allowed_range_length; | ||
540 | /*96*/ __be64 allowed_range_start; | ||
541 | } __packed obj_desc; | ||
542 | |||
543 | /*56*/ u8 object_descriptor[48]; | ||
544 | }; | ||
545 | } __packed; | ||
546 | /*104 v2*/ | ||
547 | |||
548 | struct osdv1_capability { | ||
473 | struct osd_capability_head h; | 549 | struct osd_capability_head h; |
474 | struct osdv1_cap_object_descriptor od; | 550 | struct osdv1_cap_object_descriptor od; |
475 | } __packed; | 551 | } __packed; |
476 | 552 | ||
553 | struct osd_capability { | ||
554 | struct osd_capability_head h; | ||
555 | /* struct osd_cap_object_descriptor od;*/ | ||
556 | struct osdv1_cap_object_descriptor od; /* FIXME: Pete rev-001 sup */ | ||
557 | } __packed; | ||
558 | |||
477 | /** | 559 | /** |
478 | * osd_sec_set_caps - set cap-bits into the capabilities header | 560 | * osd_sec_set_caps - set cap-bits into the capabilities header |
479 | * | 561 | * |