aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/osd
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/osd')
-rw-r--r--drivers/scsi/osd/osd_initiator.c94
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
65static unsigned _osd_req_cdb_len(struct osd_request *or) 66static 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
70static unsigned _osd_req_alist_elem_size(struct osd_request *or, unsigned len) 71static 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
75static unsigned _osd_req_alist_size(struct osd_request *or, void *list_head) 78static 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
80static unsigned _osd_req_sizeof_alist_header(struct osd_request *or) 85static 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
85static void _osd_req_set_alist_type(struct osd_request *or, 92static 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
94static bool _osd_req_is_alist_type(struct osd_request *or, 108static 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
117static osd_cdb_offset osd_req_encode_offset(struct osd_request *or, 140static 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
124static struct osd_security_parameters * 149static 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
132void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_device) 160void 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}
139EXPORT_SYMBOL(osd_dev_init); 170EXPORT_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
368static 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
337static void _osd_req_encode_common(struct osd_request *or, 385static 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
1229enum { OSD_SEC_CAP_V2_ALL_CAPS =
1230 OSD_SEC_CAP_V1_ALL_CAPS | OSD_SEC_CAP_QUERY | OSD_SEC_CAP_M_OBJECT
1231};
1232
1172void osd_sec_init_nosec_doall_caps(void *caps, 1233void 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}
1211EXPORT_SYMBOL(osd_sec_init_nosec_doall_caps); 1272EXPORT_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 */
1213void osd_set_caps(struct osd_cdb *cdb, const void *caps) 1277void 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
1218bool osd_is_sec_alldata(struct osd_security_parameters *sec_parms __unused) 1284bool osd_is_sec_alldata(struct osd_security_parameters *sec_parms __unused)