upload tizen1.0 source
[kernel/linux-2.6.36.git] / drivers / scsi / osd / osd_initiator.c
1 /*
2  * osd_initiator - Main body of the osd initiator library.
3  *
4  * Note: The file does not contain the advanced security functionality which
5  * is only needed by the security_manager's initiators.
6  *
7  * Copyright (C) 2008 Panasas Inc.  All rights reserved.
8  *
9  * Authors:
10  *   Boaz Harrosh <bharrosh@panasas.com>
11  *   Benny Halevy <bhalevy@panasas.com>
12  *
13  * This program is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License version 2
15  *
16  * Redistribution and use in source and binary forms, with or without
17  * modification, are permitted provided that the following conditions
18  * are met:
19  *
20  *  1. Redistributions of source code must retain the above copyright
21  *     notice, this list of conditions and the following disclaimer.
22  *  2. Redistributions in binary form must reproduce the above copyright
23  *     notice, this list of conditions and the following disclaimer in the
24  *     documentation and/or other materials provided with the distribution.
25  *  3. Neither the name of the Panasas company nor the names of its
26  *     contributors may be used to endorse or promote products derived
27  *     from this software without specific prior written permission.
28  *
29  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
30  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
31  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
32  * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
33  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
34  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
35  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
36  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
37  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
38  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
39  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40  */
41
42 #include <linux/slab.h>
43
44 #include <scsi/osd_initiator.h>
45 #include <scsi/osd_sec.h>
46 #include <scsi/osd_attributes.h>
47 #include <scsi/osd_sense.h>
48
49 #include <scsi/scsi_device.h>
50
51 #include "osd_debug.h"
52
53 #ifndef __unused
54 #    define __unused                    __attribute__((unused))
55 #endif
56
57 enum { OSD_REQ_RETRIES = 1 };
58
59 MODULE_AUTHOR("Boaz Harrosh <bharrosh@panasas.com>");
60 MODULE_DESCRIPTION("open-osd initiator library libosd.ko");
61 MODULE_LICENSE("GPL");
62
63 static inline void build_test(void)
64 {
65         /* structures were not packed */
66         BUILD_BUG_ON(sizeof(struct osd_capability) != OSD_CAP_LEN);
67         BUILD_BUG_ON(sizeof(struct osdv2_cdb) != OSD_TOTAL_CDB_LEN);
68         BUILD_BUG_ON(sizeof(struct osdv1_cdb) != OSDv1_TOTAL_CDB_LEN);
69 }
70
71 static const char *_osd_ver_desc(struct osd_request *or)
72 {
73         return osd_req_is_ver1(or) ? "OSD1" : "OSD2";
74 }
75
76 #define ATTR_DEF_RI(id, len) ATTR_DEF(OSD_APAGE_ROOT_INFORMATION, id, len)
77
78 static int _osd_get_print_system_info(struct osd_dev *od,
79         void *caps, struct osd_dev_info *odi)
80 {
81         struct osd_request *or;
82         struct osd_attr get_attrs[] = {
83                 ATTR_DEF_RI(OSD_ATTR_RI_VENDOR_IDENTIFICATION, 8),
84                 ATTR_DEF_RI(OSD_ATTR_RI_PRODUCT_IDENTIFICATION, 16),
85                 ATTR_DEF_RI(OSD_ATTR_RI_PRODUCT_MODEL, 32),
86                 ATTR_DEF_RI(OSD_ATTR_RI_PRODUCT_REVISION_LEVEL, 4),
87                 ATTR_DEF_RI(OSD_ATTR_RI_PRODUCT_SERIAL_NUMBER, 64 /*variable*/),
88                 ATTR_DEF_RI(OSD_ATTR_RI_OSD_NAME, 64 /*variable*/),
89                 ATTR_DEF_RI(OSD_ATTR_RI_TOTAL_CAPACITY, 8),
90                 ATTR_DEF_RI(OSD_ATTR_RI_USED_CAPACITY, 8),
91                 ATTR_DEF_RI(OSD_ATTR_RI_NUMBER_OF_PARTITIONS, 8),
92                 ATTR_DEF_RI(OSD_ATTR_RI_CLOCK, 6),
93                 /* IBM-OSD-SIM Has a bug with this one put it last */
94                 ATTR_DEF_RI(OSD_ATTR_RI_OSD_SYSTEM_ID, 20),
95         };
96         void *iter = NULL, *pFirst;
97         int nelem = ARRAY_SIZE(get_attrs), a = 0;
98         int ret;
99
100         or = osd_start_request(od, GFP_KERNEL);
101         if (!or)
102                 return -ENOMEM;
103
104         /* get attrs */
105         osd_req_get_attributes(or, &osd_root_object);
106         osd_req_add_get_attr_list(or, get_attrs, ARRAY_SIZE(get_attrs));
107
108         ret = osd_finalize_request(or, 0, caps, NULL);
109         if (ret)
110                 goto out;
111
112         ret = osd_execute_request(or);
113         if (ret) {
114                 OSD_ERR("Failed to detect %s => %d\n", _osd_ver_desc(or), ret);
115                 goto out;
116         }
117
118         osd_req_decode_get_attr_list(or, get_attrs, &nelem, &iter);
119
120         OSD_INFO("Detected %s device\n",
121                 _osd_ver_desc(or));
122
123         pFirst = get_attrs[a++].val_ptr;
124         OSD_INFO("VENDOR_IDENTIFICATION  [%s]\n",
125                 (char *)pFirst);
126
127         pFirst = get_attrs[a++].val_ptr;
128         OSD_INFO("PRODUCT_IDENTIFICATION [%s]\n",
129                 (char *)pFirst);
130
131         pFirst = get_attrs[a++].val_ptr;
132         OSD_INFO("PRODUCT_MODEL          [%s]\n",
133                 (char *)pFirst);
134
135         pFirst = get_attrs[a++].val_ptr;
136         OSD_INFO("PRODUCT_REVISION_LEVEL [%u]\n",
137                 pFirst ? get_unaligned_be32(pFirst) : ~0U);
138
139         pFirst = get_attrs[a++].val_ptr;
140         OSD_INFO("PRODUCT_SERIAL_NUMBER  [%s]\n",
141                 (char *)pFirst);
142
143         odi->osdname_len = get_attrs[a].len;
144         /* Avoid NULL for memcmp optimization 0-length is good enough */
145         odi->osdname = kzalloc(odi->osdname_len + 1, GFP_KERNEL);
146         if (odi->osdname_len)
147                 memcpy(odi->osdname, get_attrs[a].val_ptr, odi->osdname_len);
148         OSD_INFO("OSD_NAME               [%s]\n", odi->osdname);
149         a++;
150
151         pFirst = get_attrs[a++].val_ptr;
152         OSD_INFO("TOTAL_CAPACITY         [0x%llx]\n",
153                 pFirst ? _LLU(get_unaligned_be64(pFirst)) : ~0ULL);
154
155         pFirst = get_attrs[a++].val_ptr;
156         OSD_INFO("USED_CAPACITY          [0x%llx]\n",
157                 pFirst ? _LLU(get_unaligned_be64(pFirst)) : ~0ULL);
158
159         pFirst = get_attrs[a++].val_ptr;
160         OSD_INFO("NUMBER_OF_PARTITIONS   [%llu]\n",
161                 pFirst ? _LLU(get_unaligned_be64(pFirst)) : ~0ULL);
162
163         if (a >= nelem)
164                 goto out;
165
166         /* FIXME: Where are the time utilities */
167         pFirst = get_attrs[a++].val_ptr;
168         OSD_INFO("CLOCK                  [0x%02x%02x%02x%02x%02x%02x]\n",
169                 ((char *)pFirst)[0], ((char *)pFirst)[1],
170                 ((char *)pFirst)[2], ((char *)pFirst)[3],
171                 ((char *)pFirst)[4], ((char *)pFirst)[5]);
172
173         if (a < nelem) { /* IBM-OSD-SIM bug, Might not have it */
174                 unsigned len = get_attrs[a].len;
175                 char sid_dump[32*4 + 2]; /* 2nibbles+space+ASCII */
176
177                 hex_dump_to_buffer(get_attrs[a].val_ptr, len, 32, 1,
178                                    sid_dump, sizeof(sid_dump), true);
179                 OSD_INFO("OSD_SYSTEM_ID(%d)\n"
180                          "        [%s]\n", len, sid_dump);
181
182                 if (unlikely(len > sizeof(odi->systemid))) {
183                         OSD_ERR("OSD Target error: OSD_SYSTEM_ID too long(%d). "
184                                 "device idetification might not work\n", len);
185                         len = sizeof(odi->systemid);
186                 }
187                 odi->systemid_len = len;
188                 memcpy(odi->systemid, get_attrs[a].val_ptr, len);
189                 a++;
190         }
191 out:
192         osd_end_request(or);
193         return ret;
194 }
195
196 int osd_auto_detect_ver(struct osd_dev *od,
197         void *caps, struct osd_dev_info *odi)
198 {
199         int ret;
200
201         /* Auto-detect the osd version */
202         ret = _osd_get_print_system_info(od, caps, odi);
203         if (ret) {
204                 osd_dev_set_ver(od, OSD_VER1);
205                 OSD_DEBUG("converting to OSD1\n");
206                 ret = _osd_get_print_system_info(od, caps, odi);
207         }
208
209         return ret;
210 }
211 EXPORT_SYMBOL(osd_auto_detect_ver);
212
213 static unsigned _osd_req_cdb_len(struct osd_request *or)
214 {
215         return osd_req_is_ver1(or) ? OSDv1_TOTAL_CDB_LEN : OSD_TOTAL_CDB_LEN;
216 }
217
218 static unsigned _osd_req_alist_elem_size(struct osd_request *or, unsigned len)
219 {
220         return osd_req_is_ver1(or) ?
221                 osdv1_attr_list_elem_size(len) :
222                 osdv2_attr_list_elem_size(len);
223 }
224
225 static void _osd_req_alist_elem_encode(struct osd_request *or,
226         void *attr_last, const struct osd_attr *oa)
227 {
228         if (osd_req_is_ver1(or)) {
229                 struct osdv1_attributes_list_element *attr = attr_last;
230
231                 attr->attr_page = cpu_to_be32(oa->attr_page);
232                 attr->attr_id = cpu_to_be32(oa->attr_id);
233                 attr->attr_bytes = cpu_to_be16(oa->len);
234                 memcpy(attr->attr_val, oa->val_ptr, oa->len);
235         } else {
236                 struct osdv2_attributes_list_element *attr = attr_last;
237
238                 attr->attr_page = cpu_to_be32(oa->attr_page);
239                 attr->attr_id = cpu_to_be32(oa->attr_id);
240                 attr->attr_bytes = cpu_to_be16(oa->len);
241                 memcpy(attr->attr_val, oa->val_ptr, oa->len);
242         }
243 }
244
245 static int _osd_req_alist_elem_decode(struct osd_request *or,
246         void *cur_p, struct osd_attr *oa, unsigned max_bytes)
247 {
248         unsigned inc;
249         if (osd_req_is_ver1(or)) {
250                 struct osdv1_attributes_list_element *attr = cur_p;
251
252                 if (max_bytes < sizeof(*attr))
253                         return -1;
254
255                 oa->len = be16_to_cpu(attr->attr_bytes);
256                 inc = _osd_req_alist_elem_size(or, oa->len);
257                 if (inc > max_bytes)
258                         return -1;
259
260                 oa->attr_page = be32_to_cpu(attr->attr_page);
261                 oa->attr_id = be32_to_cpu(attr->attr_id);
262
263                 /* OSD1: On empty attributes we return a pointer to 2 bytes
264                  * of zeros. This keeps similar behaviour with OSD2.
265                  * (See below)
266                  */
267                 oa->val_ptr = likely(oa->len) ? attr->attr_val :
268                                                 (u8 *)&attr->attr_bytes;
269         } else {
270                 struct osdv2_attributes_list_element *attr = cur_p;
271
272                 if (max_bytes < sizeof(*attr))
273                         return -1;
274
275                 oa->len = be16_to_cpu(attr->attr_bytes);
276                 inc = _osd_req_alist_elem_size(or, oa->len);
277                 if (inc > max_bytes)
278                         return -1;
279
280                 oa->attr_page = be32_to_cpu(attr->attr_page);
281                 oa->attr_id = be32_to_cpu(attr->attr_id);
282
283                 /* OSD2: For convenience, on empty attributes, we return 8 bytes
284                  * of zeros here. This keeps the same behaviour with OSD2r04,
285                  * and is nice with null terminating ASCII fields.
286                  * oa->val_ptr == NULL marks the end-of-list, or error.
287                  */
288                 oa->val_ptr = likely(oa->len) ? attr->attr_val : attr->reserved;
289         }
290         return inc;
291 }
292
293 static unsigned _osd_req_alist_size(struct osd_request *or, void *list_head)
294 {
295         return osd_req_is_ver1(or) ?
296                 osdv1_list_size(list_head) :
297                 osdv2_list_size(list_head);
298 }
299
300 static unsigned _osd_req_sizeof_alist_header(struct osd_request *or)
301 {
302         return osd_req_is_ver1(or) ?
303                 sizeof(struct osdv1_attributes_list_header) :
304                 sizeof(struct osdv2_attributes_list_header);
305 }
306
307 static void _osd_req_set_alist_type(struct osd_request *or,
308         void *list, int list_type)
309 {
310         if (osd_req_is_ver1(or)) {
311                 struct osdv1_attributes_list_header *attr_list = list;
312
313                 memset(attr_list, 0, sizeof(*attr_list));
314                 attr_list->type = list_type;
315         } else {
316                 struct osdv2_attributes_list_header *attr_list = list;
317
318                 memset(attr_list, 0, sizeof(*attr_list));
319                 attr_list->type = list_type;
320         }
321 }
322
323 static bool _osd_req_is_alist_type(struct osd_request *or,
324         void *list, int list_type)
325 {
326         if (!list)
327                 return false;
328
329         if (osd_req_is_ver1(or)) {
330                 struct osdv1_attributes_list_header *attr_list = list;
331
332                 return attr_list->type == list_type;
333         } else {
334                 struct osdv2_attributes_list_header *attr_list = list;
335
336                 return attr_list->type == list_type;
337         }
338 }
339
340 /* This is for List-objects not Attributes-Lists */
341 static void _osd_req_encode_olist(struct osd_request *or,
342         struct osd_obj_id_list *list)
343 {
344         struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
345
346         if (osd_req_is_ver1(or)) {
347                 cdbh->v1.list_identifier = list->list_identifier;
348                 cdbh->v1.start_address = list->continuation_id;
349         } else {
350                 cdbh->v2.list_identifier = list->list_identifier;
351                 cdbh->v2.start_address = list->continuation_id;
352         }
353 }
354
355 static osd_cdb_offset osd_req_encode_offset(struct osd_request *or,
356         u64 offset, unsigned *padding)
357 {
358         return __osd_encode_offset(offset, padding,
359                         osd_req_is_ver1(or) ?
360                                 OSDv1_OFFSET_MIN_SHIFT : OSD_OFFSET_MIN_SHIFT,
361                         OSD_OFFSET_MAX_SHIFT);
362 }
363
364 static struct osd_security_parameters *
365 _osd_req_sec_params(struct osd_request *or)
366 {
367         struct osd_cdb *ocdb = &or->cdb;
368
369         if (osd_req_is_ver1(or))
370                 return (struct osd_security_parameters *)&ocdb->v1.sec_params;
371         else
372                 return (struct osd_security_parameters *)&ocdb->v2.sec_params;
373 }
374
375 void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_device)
376 {
377         memset(osdd, 0, sizeof(*osdd));
378         osdd->scsi_device = scsi_device;
379         osdd->def_timeout = BLK_DEFAULT_SG_TIMEOUT;
380 #ifdef OSD_VER1_SUPPORT
381         osdd->version = OSD_VER2;
382 #endif
383         /* TODO: Allocate pools for osd_request attributes ... */
384 }
385 EXPORT_SYMBOL(osd_dev_init);
386
387 void osd_dev_fini(struct osd_dev *osdd)
388 {
389         /* TODO: De-allocate pools */
390
391         osdd->scsi_device = NULL;
392 }
393 EXPORT_SYMBOL(osd_dev_fini);
394
395 static struct osd_request *_osd_request_alloc(gfp_t gfp)
396 {
397         struct osd_request *or;
398
399         /* TODO: Use mempool with one saved request */
400         or = kzalloc(sizeof(*or), gfp);
401         return or;
402 }
403
404 static void _osd_request_free(struct osd_request *or)
405 {
406         kfree(or);
407 }
408
409 struct osd_request *osd_start_request(struct osd_dev *dev, gfp_t gfp)
410 {
411         struct osd_request *or;
412
413         or = _osd_request_alloc(gfp);
414         if (!or)
415                 return NULL;
416
417         or->osd_dev = dev;
418         or->alloc_flags = gfp;
419         or->timeout = dev->def_timeout;
420         or->retries = OSD_REQ_RETRIES;
421
422         return or;
423 }
424 EXPORT_SYMBOL(osd_start_request);
425
426 static void _osd_free_seg(struct osd_request *or __unused,
427         struct _osd_req_data_segment *seg)
428 {
429         if (!seg->buff || !seg->alloc_size)
430                 return;
431
432         kfree(seg->buff);
433         seg->buff = NULL;
434         seg->alloc_size = 0;
435 }
436
437 static void _put_request(struct request *rq)
438 {
439         /*
440          * If osd_finalize_request() was called but the request was not
441          * executed through the block layer, then we must release BIOs.
442          * TODO: Keep error code in or->async_error. Need to audit all
443          *       code paths.
444          */
445         if (unlikely(rq->bio))
446                 blk_end_request(rq, -ENOMEM, blk_rq_bytes(rq));
447         else
448                 blk_put_request(rq);
449 }
450
451 void osd_end_request(struct osd_request *or)
452 {
453         struct request *rq = or->request;
454
455         _osd_free_seg(or, &or->set_attr);
456         _osd_free_seg(or, &or->enc_get_attr);
457         _osd_free_seg(or, &or->get_attr);
458
459         if (rq) {
460                 if (rq->next_rq) {
461                         _put_request(rq->next_rq);
462                         rq->next_rq = NULL;
463                 }
464
465                 _put_request(rq);
466         }
467         _osd_request_free(or);
468 }
469 EXPORT_SYMBOL(osd_end_request);
470
471 static void _set_error_resid(struct osd_request *or, struct request *req,
472                              int error)
473 {
474         or->async_error = error;
475         or->req_errors = req->errors ? : error;
476         or->sense_len = req->sense_len;
477         if (or->out.req)
478                 or->out.residual = or->out.req->resid_len;
479         if (or->in.req)
480                 or->in.residual = or->in.req->resid_len;
481 }
482
483 int osd_execute_request(struct osd_request *or)
484 {
485         int error = blk_execute_rq(or->request->q, NULL, or->request, 0);
486
487         _set_error_resid(or, or->request, error);
488         return error;
489 }
490 EXPORT_SYMBOL(osd_execute_request);
491
492 static void osd_request_async_done(struct request *req, int error)
493 {
494         struct osd_request *or = req->end_io_data;
495
496         _set_error_resid(or, req, error);
497         if (req->next_rq) {
498                 __blk_put_request(req->q, req->next_rq);
499                 req->next_rq = NULL;
500         }
501
502         __blk_put_request(req->q, req);
503         or->request = NULL;
504         or->in.req = NULL;
505         or->out.req = NULL;
506
507         if (or->async_done)
508                 or->async_done(or, or->async_private);
509         else
510                 osd_end_request(or);
511 }
512
513 int osd_execute_request_async(struct osd_request *or,
514         osd_req_done_fn *done, void *private)
515 {
516         or->request->end_io_data = or;
517         or->async_private = private;
518         or->async_done = done;
519
520         blk_execute_rq_nowait(or->request->q, NULL, or->request, 0,
521                               osd_request_async_done);
522         return 0;
523 }
524 EXPORT_SYMBOL(osd_execute_request_async);
525
526 u8 sg_out_pad_buffer[1 << OSDv1_OFFSET_MIN_SHIFT];
527 u8 sg_in_pad_buffer[1 << OSDv1_OFFSET_MIN_SHIFT];
528
529 static int _osd_realloc_seg(struct osd_request *or,
530         struct _osd_req_data_segment *seg, unsigned max_bytes)
531 {
532         void *buff;
533
534         if (seg->alloc_size >= max_bytes)
535                 return 0;
536
537         buff = krealloc(seg->buff, max_bytes, or->alloc_flags);
538         if (!buff) {
539                 OSD_ERR("Failed to Realloc %d-bytes was-%d\n", max_bytes,
540                         seg->alloc_size);
541                 return -ENOMEM;
542         }
543
544         memset(buff + seg->alloc_size, 0, max_bytes - seg->alloc_size);
545         seg->buff = buff;
546         seg->alloc_size = max_bytes;
547         return 0;
548 }
549
550 static int _alloc_set_attr_list(struct osd_request *or,
551         const struct osd_attr *oa, unsigned nelem, unsigned add_bytes)
552 {
553         unsigned total_bytes = add_bytes;
554
555         for (; nelem; --nelem, ++oa)
556                 total_bytes += _osd_req_alist_elem_size(or, oa->len);
557
558         OSD_DEBUG("total_bytes=%d\n", total_bytes);
559         return _osd_realloc_seg(or, &or->set_attr, total_bytes);
560 }
561
562 static int _alloc_get_attr_desc(struct osd_request *or, unsigned max_bytes)
563 {
564         OSD_DEBUG("total_bytes=%d\n", max_bytes);
565         return _osd_realloc_seg(or, &or->enc_get_attr, max_bytes);
566 }
567
568 static int _alloc_get_attr_list(struct osd_request *or)
569 {
570         OSD_DEBUG("total_bytes=%d\n", or->get_attr.total_bytes);
571         return _osd_realloc_seg(or, &or->get_attr, or->get_attr.total_bytes);
572 }
573
574 /*
575  * Common to all OSD commands
576  */
577
578 static void _osdv1_req_encode_common(struct osd_request *or,
579         __be16 act, const struct osd_obj_id *obj, u64 offset, u64 len)
580 {
581         struct osdv1_cdb *ocdb = &or->cdb.v1;
582
583         /*
584          * For speed, the commands
585          *      OSD_ACT_PERFORM_SCSI_COMMAND    , V1 0x8F7E, V2 0x8F7C
586          *      OSD_ACT_SCSI_TASK_MANAGEMENT    , V1 0x8F7F, V2 0x8F7D
587          * are not supported here. Should pass zero and set after the call
588          */
589         act &= cpu_to_be16(~0x0080); /* V1 action code */
590
591         OSD_DEBUG("OSDv1 execute opcode 0x%x\n", be16_to_cpu(act));
592
593         ocdb->h.varlen_cdb.opcode = VARIABLE_LENGTH_CMD;
594         ocdb->h.varlen_cdb.additional_cdb_length = OSD_ADDITIONAL_CDB_LENGTH;
595         ocdb->h.varlen_cdb.service_action = act;
596
597         ocdb->h.partition = cpu_to_be64(obj->partition);
598         ocdb->h.object = cpu_to_be64(obj->id);
599         ocdb->h.v1.length = cpu_to_be64(len);
600         ocdb->h.v1.start_address = cpu_to_be64(offset);
601 }
602
603 static void _osdv2_req_encode_common(struct osd_request *or,
604          __be16 act, const struct osd_obj_id *obj, u64 offset, u64 len)
605 {
606         struct osdv2_cdb *ocdb = &or->cdb.v2;
607
608         OSD_DEBUG("OSDv2 execute opcode 0x%x\n", be16_to_cpu(act));
609
610         ocdb->h.varlen_cdb.opcode = VARIABLE_LENGTH_CMD;
611         ocdb->h.varlen_cdb.additional_cdb_length = OSD_ADDITIONAL_CDB_LENGTH;
612         ocdb->h.varlen_cdb.service_action = act;
613
614         ocdb->h.partition = cpu_to_be64(obj->partition);
615         ocdb->h.object = cpu_to_be64(obj->id);
616         ocdb->h.v2.length = cpu_to_be64(len);
617         ocdb->h.v2.start_address = cpu_to_be64(offset);
618 }
619
620 static void _osd_req_encode_common(struct osd_request *or,
621         __be16 act, const struct osd_obj_id *obj, u64 offset, u64 len)
622 {
623         if (osd_req_is_ver1(or))
624                 _osdv1_req_encode_common(or, act, obj, offset, len);
625         else
626                 _osdv2_req_encode_common(or, act, obj, offset, len);
627 }
628
629 /*
630  * Device commands
631  */
632 /*TODO: void osd_req_set_master_seed_xchg(struct osd_request *, ...); */
633 /*TODO: void osd_req_set_master_key(struct osd_request *, ...); */
634
635 void osd_req_format(struct osd_request *or, u64 tot_capacity)
636 {
637         _osd_req_encode_common(or, OSD_ACT_FORMAT_OSD, &osd_root_object, 0,
638                                 tot_capacity);
639 }
640 EXPORT_SYMBOL(osd_req_format);
641
642 int osd_req_list_dev_partitions(struct osd_request *or,
643         osd_id initial_id, struct osd_obj_id_list *list, unsigned nelem)
644 {
645         return osd_req_list_partition_objects(or, 0, initial_id, list, nelem);
646 }
647 EXPORT_SYMBOL(osd_req_list_dev_partitions);
648
649 static void _osd_req_encode_flush(struct osd_request *or,
650         enum osd_options_flush_scope_values op)
651 {
652         struct osd_cdb_head *ocdb = osd_cdb_head(&or->cdb);
653
654         ocdb->command_specific_options = op;
655 }
656
657 void osd_req_flush_obsd(struct osd_request *or,
658         enum osd_options_flush_scope_values op)
659 {
660         _osd_req_encode_common(or, OSD_ACT_FLUSH_OSD, &osd_root_object, 0, 0);
661         _osd_req_encode_flush(or, op);
662 }
663 EXPORT_SYMBOL(osd_req_flush_obsd);
664
665 /*TODO: void osd_req_perform_scsi_command(struct osd_request *,
666         const u8 *cdb, ...); */
667 /*TODO: void osd_req_task_management(struct osd_request *, ...); */
668
669 /*
670  * Partition commands
671  */
672 static void _osd_req_encode_partition(struct osd_request *or,
673         __be16 act, osd_id partition)
674 {
675         struct osd_obj_id par = {
676                 .partition = partition,
677                 .id = 0,
678         };
679
680         _osd_req_encode_common(or, act, &par, 0, 0);
681 }
682
683 void osd_req_create_partition(struct osd_request *or, osd_id partition)
684 {
685         _osd_req_encode_partition(or, OSD_ACT_CREATE_PARTITION, partition);
686 }
687 EXPORT_SYMBOL(osd_req_create_partition);
688
689 void osd_req_remove_partition(struct osd_request *or, osd_id partition)
690 {
691         _osd_req_encode_partition(or, OSD_ACT_REMOVE_PARTITION, partition);
692 }
693 EXPORT_SYMBOL(osd_req_remove_partition);
694
695 /*TODO: void osd_req_set_partition_key(struct osd_request *,
696         osd_id partition, u8 new_key_id[OSD_CRYPTO_KEYID_SIZE],
697         u8 seed[OSD_CRYPTO_SEED_SIZE]); */
698
699 static int _osd_req_list_objects(struct osd_request *or,
700         __be16 action, const struct osd_obj_id *obj, osd_id initial_id,
701         struct osd_obj_id_list *list, unsigned nelem)
702 {
703         struct request_queue *q = osd_request_queue(or->osd_dev);
704         u64 len = nelem * sizeof(osd_id) + sizeof(*list);
705         struct bio *bio;
706
707         _osd_req_encode_common(or, action, obj, (u64)initial_id, len);
708
709         if (list->list_identifier)
710                 _osd_req_encode_olist(or, list);
711
712         WARN_ON(or->in.bio);
713         bio = bio_map_kern(q, list, len, or->alloc_flags);
714         if (IS_ERR(bio)) {
715                 OSD_ERR("!!! Failed to allocate list_objects BIO\n");
716                 return PTR_ERR(bio);
717         }
718
719         bio->bi_rw &= ~REQ_WRITE;
720         or->in.bio = bio;
721         or->in.total_bytes = bio->bi_size;
722         return 0;
723 }
724
725 int osd_req_list_partition_collections(struct osd_request *or,
726         osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
727         unsigned nelem)
728 {
729         struct osd_obj_id par = {
730                 .partition = partition,
731                 .id = 0,
732         };
733
734         return osd_req_list_collection_objects(or, &par, initial_id, list,
735                                                nelem);
736 }
737 EXPORT_SYMBOL(osd_req_list_partition_collections);
738
739 int osd_req_list_partition_objects(struct osd_request *or,
740         osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
741         unsigned nelem)
742 {
743         struct osd_obj_id par = {
744                 .partition = partition,
745                 .id = 0,
746         };
747
748         return _osd_req_list_objects(or, OSD_ACT_LIST, &par, initial_id, list,
749                                      nelem);
750 }
751 EXPORT_SYMBOL(osd_req_list_partition_objects);
752
753 void osd_req_flush_partition(struct osd_request *or,
754         osd_id partition, enum osd_options_flush_scope_values op)
755 {
756         _osd_req_encode_partition(or, OSD_ACT_FLUSH_PARTITION, partition);
757         _osd_req_encode_flush(or, op);
758 }
759 EXPORT_SYMBOL(osd_req_flush_partition);
760
761 /*
762  * Collection commands
763  */
764 /*TODO: void osd_req_create_collection(struct osd_request *,
765         const struct osd_obj_id *); */
766 /*TODO: void osd_req_remove_collection(struct osd_request *,
767         const struct osd_obj_id *); */
768
769 int osd_req_list_collection_objects(struct osd_request *or,
770         const struct osd_obj_id *obj, osd_id initial_id,
771         struct osd_obj_id_list *list, unsigned nelem)
772 {
773         return _osd_req_list_objects(or, OSD_ACT_LIST_COLLECTION, obj,
774                                      initial_id, list, nelem);
775 }
776 EXPORT_SYMBOL(osd_req_list_collection_objects);
777
778 /*TODO: void query(struct osd_request *, ...); V2 */
779
780 void osd_req_flush_collection(struct osd_request *or,
781         const struct osd_obj_id *obj, enum osd_options_flush_scope_values op)
782 {
783         _osd_req_encode_common(or, OSD_ACT_FLUSH_PARTITION, obj, 0, 0);
784         _osd_req_encode_flush(or, op);
785 }
786 EXPORT_SYMBOL(osd_req_flush_collection);
787
788 /*TODO: void get_member_attrs(struct osd_request *, ...); V2 */
789 /*TODO: void set_member_attrs(struct osd_request *, ...); V2 */
790
791 /*
792  * Object commands
793  */
794 void osd_req_create_object(struct osd_request *or, struct osd_obj_id *obj)
795 {
796         _osd_req_encode_common(or, OSD_ACT_CREATE, obj, 0, 0);
797 }
798 EXPORT_SYMBOL(osd_req_create_object);
799
800 void osd_req_remove_object(struct osd_request *or, struct osd_obj_id *obj)
801 {
802         _osd_req_encode_common(or, OSD_ACT_REMOVE, obj, 0, 0);
803 }
804 EXPORT_SYMBOL(osd_req_remove_object);
805
806
807 /*TODO: void osd_req_create_multi(struct osd_request *or,
808         struct osd_obj_id *first, struct osd_obj_id_list *list, unsigned nelem);
809 */
810
811 void osd_req_write(struct osd_request *or,
812         const struct osd_obj_id *obj, u64 offset,
813         struct bio *bio, u64 len)
814 {
815         _osd_req_encode_common(or, OSD_ACT_WRITE, obj, offset, len);
816         WARN_ON(or->out.bio || or->out.total_bytes);
817         WARN_ON(0 == (bio->bi_rw & REQ_WRITE));
818         or->out.bio = bio;
819         or->out.total_bytes = len;
820 }
821 EXPORT_SYMBOL(osd_req_write);
822
823 int osd_req_write_kern(struct osd_request *or,
824         const struct osd_obj_id *obj, u64 offset, void* buff, u64 len)
825 {
826         struct request_queue *req_q = osd_request_queue(or->osd_dev);
827         struct bio *bio = bio_map_kern(req_q, buff, len, GFP_KERNEL);
828
829         if (IS_ERR(bio))
830                 return PTR_ERR(bio);
831
832         bio->bi_rw |= REQ_WRITE; /* FIXME: bio_set_dir() */
833         osd_req_write(or, obj, offset, bio, len);
834         return 0;
835 }
836 EXPORT_SYMBOL(osd_req_write_kern);
837
838 /*TODO: void osd_req_append(struct osd_request *,
839         const struct osd_obj_id *, struct bio *data_out); */
840 /*TODO: void osd_req_create_write(struct osd_request *,
841         const struct osd_obj_id *, struct bio *data_out, u64 offset); */
842 /*TODO: void osd_req_clear(struct osd_request *,
843         const struct osd_obj_id *, u64 offset, u64 len); */
844 /*TODO: void osd_req_punch(struct osd_request *,
845         const struct osd_obj_id *, u64 offset, u64 len); V2 */
846
847 void osd_req_flush_object(struct osd_request *or,
848         const struct osd_obj_id *obj, enum osd_options_flush_scope_values op,
849         /*V2*/ u64 offset, /*V2*/ u64 len)
850 {
851         if (unlikely(osd_req_is_ver1(or) && (offset || len))) {
852                 OSD_DEBUG("OSD Ver1 flush on specific range ignored\n");
853                 offset = 0;
854                 len = 0;
855         }
856
857         _osd_req_encode_common(or, OSD_ACT_FLUSH, obj, offset, len);
858         _osd_req_encode_flush(or, op);
859 }
860 EXPORT_SYMBOL(osd_req_flush_object);
861
862 void osd_req_read(struct osd_request *or,
863         const struct osd_obj_id *obj, u64 offset,
864         struct bio *bio, u64 len)
865 {
866         _osd_req_encode_common(or, OSD_ACT_READ, obj, offset, len);
867         WARN_ON(or->in.bio || or->in.total_bytes);
868         WARN_ON(bio->bi_rw & REQ_WRITE);
869         or->in.bio = bio;
870         or->in.total_bytes = len;
871 }
872 EXPORT_SYMBOL(osd_req_read);
873
874 int osd_req_read_kern(struct osd_request *or,
875         const struct osd_obj_id *obj, u64 offset, void* buff, u64 len)
876 {
877         struct request_queue *req_q = osd_request_queue(or->osd_dev);
878         struct bio *bio = bio_map_kern(req_q, buff, len, GFP_KERNEL);
879
880         if (IS_ERR(bio))
881                 return PTR_ERR(bio);
882
883         osd_req_read(or, obj, offset, bio, len);
884         return 0;
885 }
886 EXPORT_SYMBOL(osd_req_read_kern);
887
888 void osd_req_get_attributes(struct osd_request *or,
889         const struct osd_obj_id *obj)
890 {
891         _osd_req_encode_common(or, OSD_ACT_GET_ATTRIBUTES, obj, 0, 0);
892 }
893 EXPORT_SYMBOL(osd_req_get_attributes);
894
895 void osd_req_set_attributes(struct osd_request *or,
896         const struct osd_obj_id *obj)
897 {
898         _osd_req_encode_common(or, OSD_ACT_SET_ATTRIBUTES, obj, 0, 0);
899 }
900 EXPORT_SYMBOL(osd_req_set_attributes);
901
902 /*
903  * Attributes List-mode
904  */
905
906 int osd_req_add_set_attr_list(struct osd_request *or,
907         const struct osd_attr *oa, unsigned nelem)
908 {
909         unsigned total_bytes = or->set_attr.total_bytes;
910         void *attr_last;
911         int ret;
912
913         if (or->attributes_mode &&
914             or->attributes_mode != OSD_CDB_GET_SET_ATTR_LISTS) {
915                 WARN_ON(1);
916                 return -EINVAL;
917         }
918         or->attributes_mode = OSD_CDB_GET_SET_ATTR_LISTS;
919
920         if (!total_bytes) { /* first-time: allocate and put list header */
921                 total_bytes = _osd_req_sizeof_alist_header(or);
922                 ret = _alloc_set_attr_list(or, oa, nelem, total_bytes);
923                 if (ret)
924                         return ret;
925                 _osd_req_set_alist_type(or, or->set_attr.buff,
926                                         OSD_ATTR_LIST_SET_RETRIEVE);
927         }
928         attr_last = or->set_attr.buff + total_bytes;
929
930         for (; nelem; --nelem) {
931                 unsigned elem_size = _osd_req_alist_elem_size(or, oa->len);
932
933                 total_bytes += elem_size;
934                 if (unlikely(or->set_attr.alloc_size < total_bytes)) {
935                         or->set_attr.total_bytes = total_bytes - elem_size;
936                         ret = _alloc_set_attr_list(or, oa, nelem, total_bytes);
937                         if (ret)
938                                 return ret;
939                         attr_last =
940                                 or->set_attr.buff + or->set_attr.total_bytes;
941                 }
942
943                 _osd_req_alist_elem_encode(or, attr_last, oa);
944
945                 attr_last += elem_size;
946                 ++oa;
947         }
948
949         or->set_attr.total_bytes = total_bytes;
950         return 0;
951 }
952 EXPORT_SYMBOL(osd_req_add_set_attr_list);
953
954 static int _req_append_segment(struct osd_request *or,
955         unsigned padding, struct _osd_req_data_segment *seg,
956         struct _osd_req_data_segment *last_seg, struct _osd_io_info *io)
957 {
958         void *pad_buff;
959         int ret;
960
961         if (padding) {
962                 /* check if we can just add it to last buffer */
963                 if (last_seg &&
964                     (padding <= last_seg->alloc_size - last_seg->total_bytes))
965                         pad_buff = last_seg->buff + last_seg->total_bytes;
966                 else
967                         pad_buff = io->pad_buff;
968
969                 ret = blk_rq_map_kern(io->req->q, io->req, pad_buff, padding,
970                                        or->alloc_flags);
971                 if (ret)
972                         return ret;
973                 io->total_bytes += padding;
974         }
975
976         ret = blk_rq_map_kern(io->req->q, io->req, seg->buff, seg->total_bytes,
977                                or->alloc_flags);
978         if (ret)
979                 return ret;
980
981         io->total_bytes += seg->total_bytes;
982         OSD_DEBUG("padding=%d buff=%p total_bytes=%d\n", padding, seg->buff,
983                   seg->total_bytes);
984         return 0;
985 }
986
987 static int _osd_req_finalize_set_attr_list(struct osd_request *or)
988 {
989         struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
990         unsigned padding;
991         int ret;
992
993         if (!or->set_attr.total_bytes) {
994                 cdbh->attrs_list.set_attr_offset = OSD_OFFSET_UNUSED;
995                 return 0;
996         }
997
998         cdbh->attrs_list.set_attr_bytes = cpu_to_be32(or->set_attr.total_bytes);
999         cdbh->attrs_list.set_attr_offset =
1000                 osd_req_encode_offset(or, or->out.total_bytes, &padding);
1001
1002         ret = _req_append_segment(or, padding, &or->set_attr,
1003                                   or->out.last_seg, &or->out);
1004         if (ret)
1005                 return ret;
1006
1007         or->out.last_seg = &or->set_attr;
1008         return 0;
1009 }
1010
1011 int osd_req_add_get_attr_list(struct osd_request *or,
1012         const struct osd_attr *oa, unsigned nelem)
1013 {
1014         unsigned total_bytes = or->enc_get_attr.total_bytes;
1015         void *attr_last;
1016         int ret;
1017
1018         if (or->attributes_mode &&
1019             or->attributes_mode != OSD_CDB_GET_SET_ATTR_LISTS) {
1020                 WARN_ON(1);
1021                 return -EINVAL;
1022         }
1023         or->attributes_mode = OSD_CDB_GET_SET_ATTR_LISTS;
1024
1025         /* first time calc data-in list header size */
1026         if (!or->get_attr.total_bytes)
1027                 or->get_attr.total_bytes = _osd_req_sizeof_alist_header(or);
1028
1029         /* calc data-out info */
1030         if (!total_bytes) { /* first-time: allocate and put list header */
1031                 unsigned max_bytes;
1032
1033                 total_bytes = _osd_req_sizeof_alist_header(or);
1034                 max_bytes = total_bytes +
1035                         nelem * sizeof(struct osd_attributes_list_attrid);
1036                 ret = _alloc_get_attr_desc(or, max_bytes);
1037                 if (ret)
1038                         return ret;
1039
1040                 _osd_req_set_alist_type(or, or->enc_get_attr.buff,
1041                                         OSD_ATTR_LIST_GET);
1042         }
1043         attr_last = or->enc_get_attr.buff + total_bytes;
1044
1045         for (; nelem; --nelem) {
1046                 struct osd_attributes_list_attrid *attrid;
1047                 const unsigned cur_size = sizeof(*attrid);
1048
1049                 total_bytes += cur_size;
1050                 if (unlikely(or->enc_get_attr.alloc_size < total_bytes)) {
1051                         or->enc_get_attr.total_bytes = total_bytes - cur_size;
1052                         ret = _alloc_get_attr_desc(or,
1053                                         total_bytes + nelem * sizeof(*attrid));
1054                         if (ret)
1055                                 return ret;
1056                         attr_last = or->enc_get_attr.buff +
1057                                 or->enc_get_attr.total_bytes;
1058                 }
1059
1060                 attrid = attr_last;
1061                 attrid->attr_page = cpu_to_be32(oa->attr_page);
1062                 attrid->attr_id = cpu_to_be32(oa->attr_id);
1063
1064                 attr_last += cur_size;
1065
1066                 /* calc data-in size */
1067                 or->get_attr.total_bytes +=
1068                         _osd_req_alist_elem_size(or, oa->len);
1069                 ++oa;
1070         }
1071
1072         or->enc_get_attr.total_bytes = total_bytes;
1073
1074         OSD_DEBUG(
1075                "get_attr.total_bytes=%u(%u) enc_get_attr.total_bytes=%u(%Zu)\n",
1076                or->get_attr.total_bytes,
1077                or->get_attr.total_bytes - _osd_req_sizeof_alist_header(or),
1078                or->enc_get_attr.total_bytes,
1079                (or->enc_get_attr.total_bytes - _osd_req_sizeof_alist_header(or))
1080                         / sizeof(struct osd_attributes_list_attrid));
1081
1082         return 0;
1083 }
1084 EXPORT_SYMBOL(osd_req_add_get_attr_list);
1085
1086 static int _osd_req_finalize_get_attr_list(struct osd_request *or)
1087 {
1088         struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
1089         unsigned out_padding;
1090         unsigned in_padding;
1091         int ret;
1092
1093         if (!or->enc_get_attr.total_bytes) {
1094                 cdbh->attrs_list.get_attr_desc_offset = OSD_OFFSET_UNUSED;
1095                 cdbh->attrs_list.get_attr_offset = OSD_OFFSET_UNUSED;
1096                 return 0;
1097         }
1098
1099         ret = _alloc_get_attr_list(or);
1100         if (ret)
1101                 return ret;
1102
1103         /* The out-going buffer info update */
1104         OSD_DEBUG("out-going\n");
1105         cdbh->attrs_list.get_attr_desc_bytes =
1106                 cpu_to_be32(or->enc_get_attr.total_bytes);
1107
1108         cdbh->attrs_list.get_attr_desc_offset =
1109                 osd_req_encode_offset(or, or->out.total_bytes, &out_padding);
1110
1111         ret = _req_append_segment(or, out_padding, &or->enc_get_attr,
1112                                   or->out.last_seg, &or->out);
1113         if (ret)
1114                 return ret;
1115         or->out.last_seg = &or->enc_get_attr;
1116
1117         /* The incoming buffer info update */
1118         OSD_DEBUG("in-coming\n");
1119         cdbh->attrs_list.get_attr_alloc_length =
1120                 cpu_to_be32(or->get_attr.total_bytes);
1121
1122         cdbh->attrs_list.get_attr_offset =
1123                 osd_req_encode_offset(or, or->in.total_bytes, &in_padding);
1124
1125         ret = _req_append_segment(or, in_padding, &or->get_attr, NULL,
1126                                   &or->in);
1127         if (ret)
1128                 return ret;
1129         or->in.last_seg = &or->get_attr;
1130
1131         return 0;
1132 }
1133
1134 int osd_req_decode_get_attr_list(struct osd_request *or,
1135         struct osd_attr *oa, int *nelem, void **iterator)
1136 {
1137         unsigned cur_bytes, returned_bytes;
1138         int n;
1139         const unsigned sizeof_attr_list = _osd_req_sizeof_alist_header(or);
1140         void *cur_p;
1141
1142         if (!_osd_req_is_alist_type(or, or->get_attr.buff,
1143                                     OSD_ATTR_LIST_SET_RETRIEVE)) {
1144                 oa->attr_page = 0;
1145                 oa->attr_id = 0;
1146                 oa->val_ptr = NULL;
1147                 oa->len = 0;
1148                 *iterator = NULL;
1149                 return 0;
1150         }
1151
1152         if (*iterator) {
1153                 BUG_ON((*iterator < or->get_attr.buff) ||
1154                      (or->get_attr.buff + or->get_attr.alloc_size < *iterator));
1155                 cur_p = *iterator;
1156                 cur_bytes = (*iterator - or->get_attr.buff) - sizeof_attr_list;
1157                 returned_bytes = or->get_attr.total_bytes;
1158         } else { /* first time decode the list header */
1159                 cur_bytes = sizeof_attr_list;
1160                 returned_bytes = _osd_req_alist_size(or, or->get_attr.buff) +
1161                                         sizeof_attr_list;
1162
1163                 cur_p = or->get_attr.buff + sizeof_attr_list;
1164
1165                 if (returned_bytes > or->get_attr.alloc_size) {
1166                         OSD_DEBUG("target report: space was not big enough! "
1167                                   "Allocate=%u Needed=%u\n",
1168                                   or->get_attr.alloc_size,
1169                                   returned_bytes + sizeof_attr_list);
1170
1171                         returned_bytes =
1172                                 or->get_attr.alloc_size - sizeof_attr_list;
1173                 }
1174                 or->get_attr.total_bytes = returned_bytes;
1175         }
1176
1177         for (n = 0; (n < *nelem) && (cur_bytes < returned_bytes); ++n) {
1178                 int inc = _osd_req_alist_elem_decode(or, cur_p, oa,
1179                                                  returned_bytes - cur_bytes);
1180
1181                 if (inc < 0) {
1182                         OSD_ERR("BAD FOOD from target. list not valid!"
1183                                 "c=%d r=%d n=%d\n",
1184                                 cur_bytes, returned_bytes, n);
1185                         oa->val_ptr = NULL;
1186                         cur_bytes = returned_bytes; /* break the caller loop */
1187                         break;
1188                 }
1189
1190                 cur_bytes += inc;
1191                 cur_p += inc;
1192                 ++oa;
1193         }
1194
1195         *iterator = (returned_bytes - cur_bytes) ? cur_p : NULL;
1196         *nelem = n;
1197         return returned_bytes - cur_bytes;
1198 }
1199 EXPORT_SYMBOL(osd_req_decode_get_attr_list);
1200
1201 /*
1202  * Attributes Page-mode
1203  */
1204
1205 int osd_req_add_get_attr_page(struct osd_request *or,
1206         u32 page_id, void *attar_page, unsigned max_page_len,
1207         const struct osd_attr *set_one_attr)
1208 {
1209         struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
1210
1211         if (or->attributes_mode &&
1212             or->attributes_mode != OSD_CDB_GET_ATTR_PAGE_SET_ONE) {
1213                 WARN_ON(1);
1214                 return -EINVAL;
1215         }
1216         or->attributes_mode = OSD_CDB_GET_ATTR_PAGE_SET_ONE;
1217
1218         or->get_attr.buff = attar_page;
1219         or->get_attr.total_bytes = max_page_len;
1220
1221         or->set_attr.buff = set_one_attr->val_ptr;
1222         or->set_attr.total_bytes = set_one_attr->len;
1223
1224         cdbh->attrs_page.get_attr_page = cpu_to_be32(page_id);
1225         cdbh->attrs_page.get_attr_alloc_length = cpu_to_be32(max_page_len);
1226         /* ocdb->attrs_page.get_attr_offset; */
1227
1228         cdbh->attrs_page.set_attr_page = cpu_to_be32(set_one_attr->attr_page);
1229         cdbh->attrs_page.set_attr_id = cpu_to_be32(set_one_attr->attr_id);
1230         cdbh->attrs_page.set_attr_length = cpu_to_be32(set_one_attr->len);
1231         /* ocdb->attrs_page.set_attr_offset; */
1232         return 0;
1233 }
1234 EXPORT_SYMBOL(osd_req_add_get_attr_page);
1235
1236 static int _osd_req_finalize_attr_page(struct osd_request *or)
1237 {
1238         struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
1239         unsigned in_padding, out_padding;
1240         int ret;
1241
1242         /* returned page */
1243         cdbh->attrs_page.get_attr_offset =
1244                 osd_req_encode_offset(or, or->in.total_bytes, &in_padding);
1245
1246         ret = _req_append_segment(or, in_padding, &or->get_attr, NULL,
1247                                   &or->in);
1248         if (ret)
1249                 return ret;
1250
1251         /* set one value */
1252         cdbh->attrs_page.set_attr_offset =
1253                 osd_req_encode_offset(or, or->out.total_bytes, &out_padding);
1254
1255         ret = _req_append_segment(or, out_padding, &or->enc_get_attr, NULL,
1256                                   &or->out);
1257         return ret;
1258 }
1259
1260 static inline void osd_sec_parms_set_out_offset(bool is_v1,
1261         struct osd_security_parameters *sec_parms, osd_cdb_offset offset)
1262 {
1263         if (is_v1)
1264                 sec_parms->v1.data_out_integrity_check_offset = offset;
1265         else
1266                 sec_parms->v2.data_out_integrity_check_offset = offset;
1267 }
1268
1269 static inline void osd_sec_parms_set_in_offset(bool is_v1,
1270         struct osd_security_parameters *sec_parms, osd_cdb_offset offset)
1271 {
1272         if (is_v1)
1273                 sec_parms->v1.data_in_integrity_check_offset = offset;
1274         else
1275                 sec_parms->v2.data_in_integrity_check_offset = offset;
1276 }
1277
1278 static int _osd_req_finalize_data_integrity(struct osd_request *or,
1279         bool has_in, bool has_out, u64 out_data_bytes, const u8 *cap_key)
1280 {
1281         struct osd_security_parameters *sec_parms = _osd_req_sec_params(or);
1282         int ret;
1283
1284         if (!osd_is_sec_alldata(sec_parms))
1285                 return 0;
1286
1287         if (has_out) {
1288                 struct _osd_req_data_segment seg = {
1289                         .buff = &or->out_data_integ,
1290                         .total_bytes = sizeof(or->out_data_integ),
1291                 };
1292                 unsigned pad;
1293
1294                 or->out_data_integ.data_bytes = cpu_to_be64(out_data_bytes);
1295                 or->out_data_integ.set_attributes_bytes = cpu_to_be64(
1296                         or->set_attr.total_bytes);
1297                 or->out_data_integ.get_attributes_bytes = cpu_to_be64(
1298                         or->enc_get_attr.total_bytes);
1299
1300                 osd_sec_parms_set_out_offset(osd_req_is_ver1(or), sec_parms,
1301                         osd_req_encode_offset(or, or->out.total_bytes, &pad));
1302
1303                 ret = _req_append_segment(or, pad, &seg, or->out.last_seg,
1304                                           &or->out);
1305                 if (ret)
1306                         return ret;
1307                 or->out.last_seg = NULL;
1308
1309                 /* they are now all chained to request sign them all together */
1310                 osd_sec_sign_data(&or->out_data_integ, or->out.req->bio,
1311                                   cap_key);
1312         }
1313
1314         if (has_in) {
1315                 struct _osd_req_data_segment seg = {
1316                         .buff = &or->in_data_integ,
1317                         .total_bytes = sizeof(or->in_data_integ),
1318                 };
1319                 unsigned pad;
1320
1321                 osd_sec_parms_set_in_offset(osd_req_is_ver1(or), sec_parms,
1322                         osd_req_encode_offset(or, or->in.total_bytes, &pad));
1323
1324                 ret = _req_append_segment(or, pad, &seg, or->in.last_seg,
1325                                           &or->in);
1326                 if (ret)
1327                         return ret;
1328
1329                 or->in.last_seg = NULL;
1330         }
1331
1332         return 0;
1333 }
1334
1335 /*
1336  * osd_finalize_request and helpers
1337  */
1338 static struct request *_make_request(struct request_queue *q, bool has_write,
1339                               struct _osd_io_info *oii, gfp_t flags)
1340 {
1341         if (oii->bio)
1342                 return blk_make_request(q, oii->bio, flags);
1343         else {
1344                 struct request *req;
1345
1346                 req = blk_get_request(q, has_write ? WRITE : READ, flags);
1347                 if (unlikely(!req))
1348                         return ERR_PTR(-ENOMEM);
1349
1350                 return req;
1351         }
1352 }
1353
1354 static int _init_blk_request(struct osd_request *or,
1355         bool has_in, bool has_out)
1356 {
1357         gfp_t flags = or->alloc_flags;
1358         struct scsi_device *scsi_device = or->osd_dev->scsi_device;
1359         struct request_queue *q = scsi_device->request_queue;
1360         struct request *req;
1361         int ret;
1362
1363         req = _make_request(q, has_out, has_out ? &or->out : &or->in, flags);
1364         if (IS_ERR(req)) {
1365                 ret = PTR_ERR(req);
1366                 goto out;
1367         }
1368
1369         or->request = req;
1370         req->cmd_type = REQ_TYPE_BLOCK_PC;
1371         req->cmd_flags |= REQ_QUIET;
1372
1373         req->timeout = or->timeout;
1374         req->retries = or->retries;
1375         req->sense = or->sense;
1376         req->sense_len = 0;
1377
1378         if (has_out) {
1379                 or->out.req = req;
1380                 if (has_in) {
1381                         /* allocate bidi request */
1382                         req = _make_request(q, false, &or->in, flags);
1383                         if (IS_ERR(req)) {
1384                                 OSD_DEBUG("blk_get_request for bidi failed\n");
1385                                 ret = PTR_ERR(req);
1386                                 goto out;
1387                         }
1388                         req->cmd_type = REQ_TYPE_BLOCK_PC;
1389                         or->in.req = or->request->next_rq = req;
1390                 }
1391         } else if (has_in)
1392                 or->in.req = req;
1393
1394         ret = 0;
1395 out:
1396         OSD_DEBUG("or=%p has_in=%d has_out=%d => %d, %p\n",
1397                         or, has_in, has_out, ret, or->request);
1398         return ret;
1399 }
1400
1401 int osd_finalize_request(struct osd_request *or,
1402         u8 options, const void *cap, const u8 *cap_key)
1403 {
1404         struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
1405         bool has_in, has_out;
1406         u64 out_data_bytes = or->out.total_bytes;
1407         int ret;
1408
1409         if (options & OSD_REQ_FUA)
1410                 cdbh->options |= OSD_CDB_FUA;
1411
1412         if (options & OSD_REQ_DPO)
1413                 cdbh->options |= OSD_CDB_DPO;
1414
1415         if (options & OSD_REQ_BYPASS_TIMESTAMPS)
1416                 cdbh->timestamp_control = OSD_CDB_BYPASS_TIMESTAMPS;
1417
1418         osd_set_caps(&or->cdb, cap);
1419
1420         has_in = or->in.bio || or->get_attr.total_bytes;
1421         has_out = or->out.bio || or->set_attr.total_bytes ||
1422                 or->enc_get_attr.total_bytes;
1423
1424         ret = _init_blk_request(or, has_in, has_out);
1425         if (ret) {
1426                 OSD_DEBUG("_init_blk_request failed\n");
1427                 return ret;
1428         }
1429
1430         or->out.pad_buff = sg_out_pad_buffer;
1431         or->in.pad_buff = sg_in_pad_buffer;
1432
1433         if (!or->attributes_mode)
1434                 or->attributes_mode = OSD_CDB_GET_SET_ATTR_LISTS;
1435         cdbh->command_specific_options |= or->attributes_mode;
1436         if (or->attributes_mode == OSD_CDB_GET_ATTR_PAGE_SET_ONE) {
1437                 ret = _osd_req_finalize_attr_page(or);
1438                 if (ret) {
1439                         OSD_DEBUG("_osd_req_finalize_attr_page failed\n");
1440                         return ret;
1441                 }
1442         } else {
1443                 /* TODO: I think that for the GET_ATTR command these 2 should
1444                  * be reversed to keep them in execution order (for embeded
1445                  * targets with low memory footprint)
1446                  */
1447                 ret = _osd_req_finalize_set_attr_list(or);
1448                 if (ret) {
1449                         OSD_DEBUG("_osd_req_finalize_set_attr_list failed\n");
1450                         return ret;
1451                 }
1452
1453                 ret = _osd_req_finalize_get_attr_list(or);
1454                 if (ret) {
1455                         OSD_DEBUG("_osd_req_finalize_get_attr_list failed\n");
1456                         return ret;
1457                 }
1458         }
1459
1460         ret = _osd_req_finalize_data_integrity(or, has_in, has_out,
1461                                                out_data_bytes, cap_key);
1462         if (ret)
1463                 return ret;
1464
1465         osd_sec_sign_cdb(&or->cdb, cap_key);
1466
1467         or->request->cmd = or->cdb.buff;
1468         or->request->cmd_len = _osd_req_cdb_len(or);
1469
1470         return 0;
1471 }
1472 EXPORT_SYMBOL(osd_finalize_request);
1473
1474 static bool _is_osd_security_code(int code)
1475 {
1476         return  (code == osd_security_audit_value_frozen) ||
1477                 (code == osd_security_working_key_frozen) ||
1478                 (code == osd_nonce_not_unique) ||
1479                 (code == osd_nonce_timestamp_out_of_range) ||
1480                 (code == osd_invalid_dataout_buffer_integrity_check_value);
1481 }
1482
1483 #define OSD_SENSE_PRINT1(fmt, a...) \
1484         do { \
1485                 if (__cur_sense_need_output) \
1486                         OSD_ERR(fmt, ##a); \
1487         } while (0)
1488
1489 #define OSD_SENSE_PRINT2(fmt, a...) OSD_SENSE_PRINT1("    " fmt, ##a)
1490
1491 int osd_req_decode_sense_full(struct osd_request *or,
1492         struct osd_sense_info *osi, bool silent,
1493         struct osd_obj_id *bad_obj_list __unused, int max_obj __unused,
1494         struct osd_attr *bad_attr_list, int max_attr)
1495 {
1496         int sense_len, original_sense_len;
1497         struct osd_sense_info local_osi;
1498         struct scsi_sense_descriptor_based *ssdb;
1499         void *cur_descriptor;
1500 #if (CONFIG_SCSI_OSD_DPRINT_SENSE == 0)
1501         const bool __cur_sense_need_output = false;
1502 #else
1503         bool __cur_sense_need_output = !silent;
1504 #endif
1505         int ret;
1506
1507         if (likely(!or->req_errors))
1508                 return 0;
1509
1510         osi = osi ? : &local_osi;
1511         memset(osi, 0, sizeof(*osi));
1512
1513         ssdb = (typeof(ssdb))or->sense;
1514         sense_len = or->sense_len;
1515         if ((sense_len < (int)sizeof(*ssdb) || !ssdb->sense_key)) {
1516                 OSD_ERR("Block-layer returned error(0x%x) but "
1517                         "sense_len(%u) || key(%d) is empty\n",
1518                         or->req_errors, sense_len, ssdb->sense_key);
1519                 goto analyze;
1520         }
1521
1522         if ((ssdb->response_code != 0x72) && (ssdb->response_code != 0x73)) {
1523                 OSD_ERR("Unrecognized scsi sense: rcode=%x length=%d\n",
1524                         ssdb->response_code, sense_len);
1525                 goto analyze;
1526         }
1527
1528         osi->key = ssdb->sense_key;
1529         osi->additional_code = be16_to_cpu(ssdb->additional_sense_code);
1530         original_sense_len = ssdb->additional_sense_length + 8;
1531
1532 #if (CONFIG_SCSI_OSD_DPRINT_SENSE == 1)
1533         if (__cur_sense_need_output)
1534                 __cur_sense_need_output = (osi->key > scsi_sk_recovered_error);
1535 #endif
1536         OSD_SENSE_PRINT1("Main Sense information key=0x%x length(%d, %d) "
1537                         "additional_code=0x%x async_error=%d errors=0x%x\n",
1538                         osi->key, original_sense_len, sense_len,
1539                         osi->additional_code, or->async_error,
1540                         or->req_errors);
1541
1542         if (original_sense_len < sense_len)
1543                 sense_len = original_sense_len;
1544
1545         cur_descriptor = ssdb->ssd;
1546         sense_len -= sizeof(*ssdb);
1547         while (sense_len > 0) {
1548                 struct scsi_sense_descriptor *ssd = cur_descriptor;
1549                 int cur_len = ssd->additional_length + 2;
1550
1551                 sense_len -= cur_len;
1552
1553                 if (sense_len < 0)
1554                         break; /* sense was truncated */
1555
1556                 switch (ssd->descriptor_type) {
1557                 case scsi_sense_information:
1558                 case scsi_sense_command_specific_information:
1559                 {
1560                         struct scsi_sense_command_specific_data_descriptor
1561                                 *sscd = cur_descriptor;
1562
1563                         osi->command_info =
1564                                 get_unaligned_be64(&sscd->information) ;
1565                         OSD_SENSE_PRINT2(
1566                                 "command_specific_information 0x%llx \n",
1567                                 _LLU(osi->command_info));
1568                         break;
1569                 }
1570                 case scsi_sense_key_specific:
1571                 {
1572                         struct scsi_sense_key_specific_data_descriptor
1573                                 *ssks = cur_descriptor;
1574
1575                         osi->sense_info = get_unaligned_be16(&ssks->value);
1576                         OSD_SENSE_PRINT2(
1577                                 "sense_key_specific_information %u"
1578                                 "sksv_cd_bpv_bp (0x%x)\n",
1579                                 osi->sense_info, ssks->sksv_cd_bpv_bp);
1580                         break;
1581                 }
1582                 case osd_sense_object_identification:
1583                 { /*FIXME: Keep first not last, Store in array*/
1584                         struct osd_sense_identification_data_descriptor
1585                                 *osidd = cur_descriptor;
1586
1587                         osi->not_initiated_command_functions =
1588                                 le32_to_cpu(osidd->not_initiated_functions);
1589                         osi->completed_command_functions =
1590                                 le32_to_cpu(osidd->completed_functions);
1591                         osi->obj.partition = be64_to_cpu(osidd->partition_id);
1592                         osi->obj.id = be64_to_cpu(osidd->object_id);
1593                         OSD_SENSE_PRINT2(
1594                                 "object_identification pid=0x%llx oid=0x%llx\n",
1595                                 _LLU(osi->obj.partition), _LLU(osi->obj.id));
1596                         OSD_SENSE_PRINT2(
1597                                 "not_initiated_bits(%x) "
1598                                 "completed_command_bits(%x)\n",
1599                                 osi->not_initiated_command_functions,
1600                                 osi->completed_command_functions);
1601                         break;
1602                 }
1603                 case osd_sense_response_integrity_check:
1604                 {
1605                         struct osd_sense_response_integrity_check_descriptor
1606                                 *osricd = cur_descriptor;
1607                         const unsigned len =
1608                                           sizeof(osricd->integrity_check_value);
1609                         char key_dump[len*4 + 2]; /* 2nibbles+space+ASCII */
1610
1611                         hex_dump_to_buffer(osricd->integrity_check_value, len,
1612                                        32, 1, key_dump, sizeof(key_dump), true);
1613                         OSD_SENSE_PRINT2("response_integrity [%s]\n", key_dump);
1614                 }
1615                 case osd_sense_attribute_identification:
1616                 {
1617                         struct osd_sense_attributes_data_descriptor
1618                                 *osadd = cur_descriptor;
1619                         unsigned len = min(cur_len, sense_len);
1620                         struct osd_sense_attr *pattr = osadd->sense_attrs;
1621
1622                         while (len >= sizeof(*pattr)) {
1623                                 u32 attr_page = be32_to_cpu(pattr->attr_page);
1624                                 u32 attr_id = be32_to_cpu(pattr->attr_id);
1625
1626                                 if (!osi->attr.attr_page) {
1627                                         osi->attr.attr_page = attr_page;
1628                                         osi->attr.attr_id = attr_id;
1629                                 }
1630
1631                                 if (bad_attr_list && max_attr) {
1632                                         bad_attr_list->attr_page = attr_page;
1633                                         bad_attr_list->attr_id = attr_id;
1634                                         bad_attr_list++;
1635                                         max_attr--;
1636                                 }
1637
1638                                 len -= sizeof(*pattr);
1639                                 OSD_SENSE_PRINT2(
1640                                         "osd_sense_attribute_identification"
1641                                         "attr_page=0x%x attr_id=0x%x\n",
1642                                         attr_page, attr_id);
1643                         }
1644                 }
1645                 /*These are not legal for OSD*/
1646                 case scsi_sense_field_replaceable_unit:
1647                         OSD_SENSE_PRINT2("scsi_sense_field_replaceable_unit\n");
1648                         break;
1649                 case scsi_sense_stream_commands:
1650                         OSD_SENSE_PRINT2("scsi_sense_stream_commands\n");
1651                         break;
1652                 case scsi_sense_block_commands:
1653                         OSD_SENSE_PRINT2("scsi_sense_block_commands\n");
1654                         break;
1655                 case scsi_sense_ata_return:
1656                         OSD_SENSE_PRINT2("scsi_sense_ata_return\n");
1657                         break;
1658                 default:
1659                         if (ssd->descriptor_type <= scsi_sense_Reserved_last)
1660                                 OSD_SENSE_PRINT2(
1661                                         "scsi_sense Reserved descriptor (0x%x)",
1662                                         ssd->descriptor_type);
1663                         else
1664                                 OSD_SENSE_PRINT2(
1665                                         "scsi_sense Vendor descriptor (0x%x)",
1666                                         ssd->descriptor_type);
1667                 }
1668
1669                 cur_descriptor += cur_len;
1670         }
1671
1672 analyze:
1673         if (!osi->key) {
1674                 /* scsi sense is Empty, the request was never issued to target
1675                  * linux return code might tell us what happened.
1676                  */
1677                 if (or->async_error == -ENOMEM)
1678                         osi->osd_err_pri = OSD_ERR_PRI_RESOURCE;
1679                 else
1680                         osi->osd_err_pri = OSD_ERR_PRI_UNREACHABLE;
1681                 ret = or->async_error;
1682         } else if (osi->key <= scsi_sk_recovered_error) {
1683                 osi->osd_err_pri = 0;
1684                 ret = 0;
1685         } else if (osi->additional_code == scsi_invalid_field_in_cdb) {
1686                 if (osi->cdb_field_offset == OSD_CFO_STARTING_BYTE) {
1687                         osi->osd_err_pri = OSD_ERR_PRI_CLEAR_PAGES;
1688                         ret = -EFAULT; /* caller should recover from this */
1689                 } else if (osi->cdb_field_offset == OSD_CFO_OBJECT_ID) {
1690                         osi->osd_err_pri = OSD_ERR_PRI_NOT_FOUND;
1691                         ret = -ENOENT;
1692                 } else if (osi->cdb_field_offset == OSD_CFO_PERMISSIONS) {
1693                         osi->osd_err_pri = OSD_ERR_PRI_NO_ACCESS;
1694                         ret = -EACCES;
1695                 } else {
1696                         osi->osd_err_pri = OSD_ERR_PRI_BAD_CRED;
1697                         ret = -EINVAL;
1698                 }
1699         } else if (osi->additional_code == osd_quota_error) {
1700                 osi->osd_err_pri = OSD_ERR_PRI_NO_SPACE;
1701                 ret = -ENOSPC;
1702         } else if (_is_osd_security_code(osi->additional_code)) {
1703                 osi->osd_err_pri = OSD_ERR_PRI_BAD_CRED;
1704                 ret = -EINVAL;
1705         } else {
1706                 osi->osd_err_pri = OSD_ERR_PRI_EIO;
1707                 ret = -EIO;
1708         }
1709
1710         if (!or->out.residual)
1711                 or->out.residual = or->out.total_bytes;
1712         if (!or->in.residual)
1713                 or->in.residual = or->in.total_bytes;
1714
1715         return ret;
1716 }
1717 EXPORT_SYMBOL(osd_req_decode_sense_full);
1718
1719 /*
1720  * Implementation of osd_sec.h API
1721  * TODO: Move to a separate osd_sec.c file at a later stage.
1722  */
1723
1724 enum { OSD_SEC_CAP_V1_ALL_CAPS =
1725         OSD_SEC_CAP_APPEND | OSD_SEC_CAP_OBJ_MGMT | OSD_SEC_CAP_REMOVE   |
1726         OSD_SEC_CAP_CREATE | OSD_SEC_CAP_SET_ATTR | OSD_SEC_CAP_GET_ATTR |
1727         OSD_SEC_CAP_WRITE  | OSD_SEC_CAP_READ     | OSD_SEC_CAP_POL_SEC  |
1728         OSD_SEC_CAP_GLOBAL | OSD_SEC_CAP_DEV_MGMT
1729 };
1730
1731 enum { OSD_SEC_CAP_V2_ALL_CAPS =
1732         OSD_SEC_CAP_V1_ALL_CAPS | OSD_SEC_CAP_QUERY | OSD_SEC_CAP_M_OBJECT
1733 };
1734
1735 void osd_sec_init_nosec_doall_caps(void *caps,
1736         const struct osd_obj_id *obj, bool is_collection, const bool is_v1)
1737 {
1738         struct osd_capability *cap = caps;
1739         u8 type;
1740         u8 descriptor_type;
1741
1742         if (likely(obj->id)) {
1743                 if (unlikely(is_collection)) {
1744                         type = OSD_SEC_OBJ_COLLECTION;
1745                         descriptor_type = is_v1 ? OSD_SEC_OBJ_DESC_OBJ :
1746                                                   OSD_SEC_OBJ_DESC_COL;
1747                 } else {
1748                         type = OSD_SEC_OBJ_USER;
1749                         descriptor_type = OSD_SEC_OBJ_DESC_OBJ;
1750                 }
1751                 WARN_ON(!obj->partition);
1752         } else {
1753                 type = obj->partition ? OSD_SEC_OBJ_PARTITION :
1754                                         OSD_SEC_OBJ_ROOT;
1755                 descriptor_type = OSD_SEC_OBJ_DESC_PAR;
1756         }
1757
1758         memset(cap, 0, sizeof(*cap));
1759
1760         cap->h.format = OSD_SEC_CAP_FORMAT_VER1;
1761         cap->h.integrity_algorithm__key_version = 0; /* MAKE_BYTE(0, 0); */
1762         cap->h.security_method = OSD_SEC_NOSEC;
1763 /*      cap->expiration_time;
1764         cap->AUDIT[30-10];
1765         cap->discriminator[42-30];
1766         cap->object_created_time; */
1767         cap->h.object_type = type;
1768         osd_sec_set_caps(&cap->h, OSD_SEC_CAP_V1_ALL_CAPS);
1769         cap->h.object_descriptor_type = descriptor_type;
1770         cap->od.obj_desc.policy_access_tag = 0;
1771         cap->od.obj_desc.allowed_partition_id = cpu_to_be64(obj->partition);
1772         cap->od.obj_desc.allowed_object_id = cpu_to_be64(obj->id);
1773 }
1774 EXPORT_SYMBOL(osd_sec_init_nosec_doall_caps);
1775
1776 /* FIXME: Extract version from caps pointer.
1777  *        Also Pete's target only supports caps from OSDv1 for now
1778  */
1779 void osd_set_caps(struct osd_cdb *cdb, const void *caps)
1780 {
1781         bool is_ver1 = true;
1782         /* NOTE: They start at same address */
1783         memcpy(&cdb->v1.caps, caps, is_ver1 ? OSDv1_CAP_LEN : OSD_CAP_LEN);
1784 }
1785
1786 bool osd_is_sec_alldata(struct osd_security_parameters *sec_parms __unused)
1787 {
1788         return false;
1789 }
1790
1791 void osd_sec_sign_cdb(struct osd_cdb *ocdb __unused, const u8 *cap_key __unused)
1792 {
1793 }
1794
1795 void osd_sec_sign_data(void *data_integ __unused,
1796                        struct bio *bio __unused, const u8 *cap_key __unused)
1797 {
1798 }
1799
1800 /*
1801  * Declared in osd_protocol.h
1802  * 4.12.5 Data-In and Data-Out buffer offsets
1803  * byte offset = mantissa * (2^(exponent+8))
1804  * Returns the smallest allowed encoded offset that contains given @offset
1805  * The actual encoded offset returned is @offset + *@padding.
1806  */
1807 osd_cdb_offset __osd_encode_offset(
1808         u64 offset, unsigned *padding, int min_shift, int max_shift)
1809 {
1810         u64 try_offset = -1, mod, align;
1811         osd_cdb_offset be32_offset;
1812         int shift;
1813
1814         *padding = 0;
1815         if (!offset)
1816                 return 0;
1817
1818         for (shift = min_shift; shift < max_shift; ++shift) {
1819                 try_offset = offset >> shift;
1820                 if (try_offset < (1 << OSD_OFFSET_MAX_BITS))
1821                         break;
1822         }
1823
1824         BUG_ON(shift == max_shift);
1825
1826         align = 1 << shift;
1827         mod = offset & (align - 1);
1828         if (mod) {
1829                 *padding = align - mod;
1830                 try_offset += 1;
1831         }
1832
1833         try_offset |= ((shift - 8) & 0xf) << 28;
1834         be32_offset = cpu_to_be32((u32)try_offset);
1835
1836         OSD_DEBUG("offset=%llu mantissa=%llu exp=%d encoded=%x pad=%d\n",
1837                  _LLU(offset), _LLU(try_offset & 0x0FFFFFFF), shift,
1838                  be32_offset, *padding);
1839         return be32_offset;
1840 }