diff options
Diffstat (limited to 'drivers/scsi/osd')
-rw-r--r-- | drivers/scsi/osd/osd_initiator.c | 94 |
1 files changed, 80 insertions, 14 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) |