aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/osd/osd_initiator.c579
-rw-r--r--include/scsi/osd_attributes.h327
2 files changed, 906 insertions, 0 deletions
diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index 0e6d906f1113..b982d767bf99 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -45,6 +45,10 @@
45 45
46#include "osd_debug.h" 46#include "osd_debug.h"
47 47
48#ifndef __unused
49# define __unused __attribute__((unused))
50#endif
51
48enum { OSD_REQ_RETRIES = 1 }; 52enum { OSD_REQ_RETRIES = 1 };
49 53
50MODULE_AUTHOR("Boaz Harrosh <bharrosh@panasas.com>"); 54MODULE_AUTHOR("Boaz Harrosh <bharrosh@panasas.com>");
@@ -63,6 +67,50 @@ static unsigned _osd_req_cdb_len(struct osd_request *or)
63 return OSDv1_TOTAL_CDB_LEN; 67 return OSDv1_TOTAL_CDB_LEN;
64} 68}
65 69
70static unsigned _osd_req_alist_elem_size(struct osd_request *or, unsigned len)
71{
72 return osdv1_attr_list_elem_size(len);
73}
74
75static unsigned _osd_req_alist_size(struct osd_request *or, void *list_head)
76{
77 return osdv1_list_size(list_head);
78}
79
80static unsigned _osd_req_sizeof_alist_header(struct osd_request *or)
81{
82 return sizeof(struct osdv1_attributes_list_header);
83}
84
85static void _osd_req_set_alist_type(struct osd_request *or,
86 void *list, int list_type)
87{
88 struct osdv1_attributes_list_header *attr_list = list;
89
90 memset(attr_list, 0, sizeof(*attr_list));
91 attr_list->type = list_type;
92}
93
94static bool _osd_req_is_alist_type(struct osd_request *or,
95 void *list, int list_type)
96{
97 if (!list)
98 return false;
99
100 if (1) {
101 struct osdv1_attributes_list_header *attr_list = list;
102
103 return attr_list->type == list_type;
104 }
105}
106
107static osd_cdb_offset osd_req_encode_offset(struct osd_request *or,
108 u64 offset, unsigned *padding)
109{
110 return __osd_encode_offset(offset, padding,
111 OSDv1_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT);
112}
113
66void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_device) 114void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_device)
67{ 115{
68 memset(osdd, 0, sizeof(*osdd)); 116 memset(osdd, 0, sizeof(*osdd));
@@ -125,10 +173,25 @@ static void _abort_unexecuted_bios(struct request *rq)
125 } 173 }
126} 174}
127 175
176static void _osd_free_seg(struct osd_request *or __unused,
177 struct _osd_req_data_segment *seg)
178{
179 if (!seg->buff || !seg->alloc_size)
180 return;
181
182 kfree(seg->buff);
183 seg->buff = NULL;
184 seg->alloc_size = 0;
185}
186
128void osd_end_request(struct osd_request *or) 187void osd_end_request(struct osd_request *or)
129{ 188{
130 struct request *rq = or->request; 189 struct request *rq = or->request;
131 190
191 _osd_free_seg(or, &or->set_attr);
192 _osd_free_seg(or, &or->enc_get_attr);
193 _osd_free_seg(or, &or->get_attr);
194
132 if (rq) { 195 if (rq) {
133 if (rq->next_rq) { 196 if (rq->next_rq) {
134 _abort_unexecuted_bios(rq->next_rq); 197 _abort_unexecuted_bios(rq->next_rq);
@@ -176,6 +239,54 @@ int osd_execute_request_async(struct osd_request *or,
176} 239}
177EXPORT_SYMBOL(osd_execute_request_async); 240EXPORT_SYMBOL(osd_execute_request_async);
178 241
242u8 sg_out_pad_buffer[1 << OSDv1_OFFSET_MIN_SHIFT];
243u8 sg_in_pad_buffer[1 << OSDv1_OFFSET_MIN_SHIFT];
244
245static int _osd_realloc_seg(struct osd_request *or,
246 struct _osd_req_data_segment *seg, unsigned max_bytes)
247{
248 void *buff;
249
250 if (seg->alloc_size >= max_bytes)
251 return 0;
252
253 buff = krealloc(seg->buff, max_bytes, or->alloc_flags);
254 if (!buff) {
255 OSD_ERR("Failed to Realloc %d-bytes was-%d\n", max_bytes,
256 seg->alloc_size);
257 return -ENOMEM;
258 }
259
260 memset(buff + seg->alloc_size, 0, max_bytes - seg->alloc_size);
261 seg->buff = buff;
262 seg->alloc_size = max_bytes;
263 return 0;
264}
265
266static int _alloc_set_attr_list(struct osd_request *or,
267 const struct osd_attr *oa, unsigned nelem, unsigned add_bytes)
268{
269 unsigned total_bytes = add_bytes;
270
271 for (; nelem; --nelem, ++oa)
272 total_bytes += _osd_req_alist_elem_size(or, oa->len);
273
274 OSD_DEBUG("total_bytes=%d\n", total_bytes);
275 return _osd_realloc_seg(or, &or->set_attr, total_bytes);
276}
277
278static int _alloc_get_attr_desc(struct osd_request *or, unsigned max_bytes)
279{
280 OSD_DEBUG("total_bytes=%d\n", max_bytes);
281 return _osd_realloc_seg(or, &or->enc_get_attr, max_bytes);
282}
283
284static int _alloc_get_attr_list(struct osd_request *or)
285{
286 OSD_DEBUG("total_bytes=%d\n", or->get_attr.total_bytes);
287 return _osd_realloc_seg(or, &or->get_attr, or->get_attr.total_bytes);
288}
289
179/* 290/*
180 * Common to all OSD commands 291 * Common to all OSD commands
181 */ 292 */
@@ -284,6 +395,410 @@ void osd_req_read(struct osd_request *or,
284} 395}
285EXPORT_SYMBOL(osd_req_read); 396EXPORT_SYMBOL(osd_req_read);
286 397
398void osd_req_get_attributes(struct osd_request *or,
399 const struct osd_obj_id *obj)
400{
401 _osd_req_encode_common(or, OSD_ACT_GET_ATTRIBUTES, obj, 0, 0);
402}
403EXPORT_SYMBOL(osd_req_get_attributes);
404
405void osd_req_set_attributes(struct osd_request *or,
406 const struct osd_obj_id *obj)
407{
408 _osd_req_encode_common(or, OSD_ACT_SET_ATTRIBUTES, obj, 0, 0);
409}
410EXPORT_SYMBOL(osd_req_set_attributes);
411
412/*
413 * Attributes List-mode
414 */
415
416int osd_req_add_set_attr_list(struct osd_request *or,
417 const struct osd_attr *oa, unsigned nelem)
418{
419 unsigned total_bytes = or->set_attr.total_bytes;
420 void *attr_last;
421 int ret;
422
423 if (or->attributes_mode &&
424 or->attributes_mode != OSD_CDB_GET_SET_ATTR_LISTS) {
425 WARN_ON(1);
426 return -EINVAL;
427 }
428 or->attributes_mode = OSD_CDB_GET_SET_ATTR_LISTS;
429
430 if (!total_bytes) { /* first-time: allocate and put list header */
431 total_bytes = _osd_req_sizeof_alist_header(or);
432 ret = _alloc_set_attr_list(or, oa, nelem, total_bytes);
433 if (ret)
434 return ret;
435 _osd_req_set_alist_type(or, or->set_attr.buff,
436 OSD_ATTR_LIST_SET_RETRIEVE);
437 }
438 attr_last = or->set_attr.buff + total_bytes;
439
440 for (; nelem; --nelem) {
441 struct osd_attributes_list_element *attr;
442 unsigned elem_size = _osd_req_alist_elem_size(or, oa->len);
443
444 total_bytes += elem_size;
445 if (unlikely(or->set_attr.alloc_size < total_bytes)) {
446 or->set_attr.total_bytes = total_bytes - elem_size;
447 ret = _alloc_set_attr_list(or, oa, nelem, total_bytes);
448 if (ret)
449 return ret;
450 attr_last =
451 or->set_attr.buff + or->set_attr.total_bytes;
452 }
453
454 attr = attr_last;
455 attr->attr_page = cpu_to_be32(oa->attr_page);
456 attr->attr_id = cpu_to_be32(oa->attr_id);
457 attr->attr_bytes = cpu_to_be16(oa->len);
458 memcpy(attr->attr_val, oa->val_ptr, oa->len);
459
460 attr_last += elem_size;
461 ++oa;
462 }
463
464 or->set_attr.total_bytes = total_bytes;
465 return 0;
466}
467EXPORT_SYMBOL(osd_req_add_set_attr_list);
468
469static int _append_map_kern(struct request *req,
470 void *buff, unsigned len, gfp_t flags)
471{
472 struct bio *bio;
473 int ret;
474
475 bio = bio_map_kern(req->q, buff, len, flags);
476 if (IS_ERR(bio)) {
477 OSD_ERR("Failed bio_map_kern(%p, %d) => %ld\n", buff, len,
478 PTR_ERR(bio));
479 return PTR_ERR(bio);
480 }
481 ret = blk_rq_append_bio(req->q, req, bio);
482 if (ret) {
483 OSD_ERR("Failed blk_rq_append_bio(%p) => %d\n", bio, ret);
484 bio_put(bio);
485 }
486 return ret;
487}
488
489static int _req_append_segment(struct osd_request *or,
490 unsigned padding, struct _osd_req_data_segment *seg,
491 struct _osd_req_data_segment *last_seg, struct _osd_io_info *io)
492{
493 void *pad_buff;
494 int ret;
495
496 if (padding) {
497 /* check if we can just add it to last buffer */
498 if (last_seg &&
499 (padding <= last_seg->alloc_size - last_seg->total_bytes))
500 pad_buff = last_seg->buff + last_seg->total_bytes;
501 else
502 pad_buff = io->pad_buff;
503
504 ret = _append_map_kern(io->req, pad_buff, padding,
505 or->alloc_flags);
506 if (ret)
507 return ret;
508 io->total_bytes += padding;
509 }
510
511 ret = _append_map_kern(io->req, seg->buff, seg->total_bytes,
512 or->alloc_flags);
513 if (ret)
514 return ret;
515
516 io->total_bytes += seg->total_bytes;
517 OSD_DEBUG("padding=%d buff=%p total_bytes=%d\n", padding, seg->buff,
518 seg->total_bytes);
519 return 0;
520}
521
522static int _osd_req_finalize_set_attr_list(struct osd_request *or)
523{
524 struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
525 unsigned padding;
526 int ret;
527
528 if (!or->set_attr.total_bytes) {
529 cdbh->attrs_list.set_attr_offset = OSD_OFFSET_UNUSED;
530 return 0;
531 }
532
533 cdbh->attrs_list.set_attr_bytes = cpu_to_be32(or->set_attr.total_bytes);
534 cdbh->attrs_list.set_attr_offset =
535 osd_req_encode_offset(or, or->out.total_bytes, &padding);
536
537 ret = _req_append_segment(or, padding, &or->set_attr,
538 or->out.last_seg, &or->out);
539 if (ret)
540 return ret;
541
542 or->out.last_seg = &or->set_attr;
543 return 0;
544}
545
546int osd_req_add_get_attr_list(struct osd_request *or,
547 const struct osd_attr *oa, unsigned nelem)
548{
549 unsigned total_bytes = or->enc_get_attr.total_bytes;
550 void *attr_last;
551 int ret;
552
553 if (or->attributes_mode &&
554 or->attributes_mode != OSD_CDB_GET_SET_ATTR_LISTS) {
555 WARN_ON(1);
556 return -EINVAL;
557 }
558 or->attributes_mode = OSD_CDB_GET_SET_ATTR_LISTS;
559
560 /* first time calc data-in list header size */
561 if (!or->get_attr.total_bytes)
562 or->get_attr.total_bytes = _osd_req_sizeof_alist_header(or);
563
564 /* calc data-out info */
565 if (!total_bytes) { /* first-time: allocate and put list header */
566 unsigned max_bytes;
567
568 total_bytes = _osd_req_sizeof_alist_header(or);
569 max_bytes = total_bytes +
570 nelem * sizeof(struct osd_attributes_list_attrid);
571 ret = _alloc_get_attr_desc(or, max_bytes);
572 if (ret)
573 return ret;
574
575 _osd_req_set_alist_type(or, or->enc_get_attr.buff,
576 OSD_ATTR_LIST_GET);
577 }
578 attr_last = or->enc_get_attr.buff + total_bytes;
579
580 for (; nelem; --nelem) {
581 struct osd_attributes_list_attrid *attrid;
582 const unsigned cur_size = sizeof(*attrid);
583
584 total_bytes += cur_size;
585 if (unlikely(or->enc_get_attr.alloc_size < total_bytes)) {
586 or->enc_get_attr.total_bytes = total_bytes - cur_size;
587 ret = _alloc_get_attr_desc(or,
588 total_bytes + nelem * sizeof(*attrid));
589 if (ret)
590 return ret;
591 attr_last = or->enc_get_attr.buff +
592 or->enc_get_attr.total_bytes;
593 }
594
595 attrid = attr_last;
596 attrid->attr_page = cpu_to_be32(oa->attr_page);
597 attrid->attr_id = cpu_to_be32(oa->attr_id);
598
599 attr_last += cur_size;
600
601 /* calc data-in size */
602 or->get_attr.total_bytes +=
603 _osd_req_alist_elem_size(or, oa->len);
604 ++oa;
605 }
606
607 or->enc_get_attr.total_bytes = total_bytes;
608
609 OSD_DEBUG(
610 "get_attr.total_bytes=%u(%u) enc_get_attr.total_bytes=%u(%Zu)\n",
611 or->get_attr.total_bytes,
612 or->get_attr.total_bytes - _osd_req_sizeof_alist_header(or),
613 or->enc_get_attr.total_bytes,
614 (or->enc_get_attr.total_bytes - _osd_req_sizeof_alist_header(or))
615 / sizeof(struct osd_attributes_list_attrid));
616
617 return 0;
618}
619EXPORT_SYMBOL(osd_req_add_get_attr_list);
620
621static int _osd_req_finalize_get_attr_list(struct osd_request *or)
622{
623 struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
624 unsigned out_padding;
625 unsigned in_padding;
626 int ret;
627
628 if (!or->enc_get_attr.total_bytes) {
629 cdbh->attrs_list.get_attr_desc_offset = OSD_OFFSET_UNUSED;
630 cdbh->attrs_list.get_attr_offset = OSD_OFFSET_UNUSED;
631 return 0;
632 }
633
634 ret = _alloc_get_attr_list(or);
635 if (ret)
636 return ret;
637
638 /* The out-going buffer info update */
639 OSD_DEBUG("out-going\n");
640 cdbh->attrs_list.get_attr_desc_bytes =
641 cpu_to_be32(or->enc_get_attr.total_bytes);
642
643 cdbh->attrs_list.get_attr_desc_offset =
644 osd_req_encode_offset(or, or->out.total_bytes, &out_padding);
645
646 ret = _req_append_segment(or, out_padding, &or->enc_get_attr,
647 or->out.last_seg, &or->out);
648 if (ret)
649 return ret;
650 or->out.last_seg = &or->enc_get_attr;
651
652 /* The incoming buffer info update */
653 OSD_DEBUG("in-coming\n");
654 cdbh->attrs_list.get_attr_alloc_length =
655 cpu_to_be32(or->get_attr.total_bytes);
656
657 cdbh->attrs_list.get_attr_offset =
658 osd_req_encode_offset(or, or->in.total_bytes, &in_padding);
659
660 ret = _req_append_segment(or, in_padding, &or->get_attr, NULL,
661 &or->in);
662 if (ret)
663 return ret;
664 or->in.last_seg = &or->get_attr;
665
666 return 0;
667}
668
669int osd_req_decode_get_attr_list(struct osd_request *or,
670 struct osd_attr *oa, int *nelem, void **iterator)
671{
672 unsigned cur_bytes, returned_bytes;
673 int n;
674 const unsigned sizeof_attr_list = _osd_req_sizeof_alist_header(or);
675 void *cur_p;
676
677 if (!_osd_req_is_alist_type(or, or->get_attr.buff,
678 OSD_ATTR_LIST_SET_RETRIEVE)) {
679 oa->attr_page = 0;
680 oa->attr_id = 0;
681 oa->val_ptr = NULL;
682 oa->len = 0;
683 *iterator = NULL;
684 return 0;
685 }
686
687 if (*iterator) {
688 BUG_ON((*iterator < or->get_attr.buff) ||
689 (or->get_attr.buff + or->get_attr.alloc_size < *iterator));
690 cur_p = *iterator;
691 cur_bytes = (*iterator - or->get_attr.buff) - sizeof_attr_list;
692 returned_bytes = or->get_attr.total_bytes;
693 } else { /* first time decode the list header */
694 cur_bytes = sizeof_attr_list;
695 returned_bytes = _osd_req_alist_size(or, or->get_attr.buff) +
696 sizeof_attr_list;
697
698 cur_p = or->get_attr.buff + sizeof_attr_list;
699
700 if (returned_bytes > or->get_attr.alloc_size) {
701 OSD_DEBUG("target report: space was not big enough! "
702 "Allocate=%u Needed=%u\n",
703 or->get_attr.alloc_size,
704 returned_bytes + sizeof_attr_list);
705
706 returned_bytes =
707 or->get_attr.alloc_size - sizeof_attr_list;
708 }
709 or->get_attr.total_bytes = returned_bytes;
710 }
711
712 for (n = 0; (n < *nelem) && (cur_bytes < returned_bytes); ++n) {
713 struct osd_attributes_list_element *attr = cur_p;
714 unsigned inc;
715
716 oa->len = be16_to_cpu(attr->attr_bytes);
717 inc = _osd_req_alist_elem_size(or, oa->len);
718 OSD_DEBUG("oa->len=%d inc=%d cur_bytes=%d\n",
719 oa->len, inc, cur_bytes);
720 cur_bytes += inc;
721 if (cur_bytes > returned_bytes) {
722 OSD_ERR("BAD FOOD from target. list not valid!"
723 "c=%d r=%d n=%d\n",
724 cur_bytes, returned_bytes, n);
725 oa->val_ptr = NULL;
726 break;
727 }
728
729 oa->attr_page = be32_to_cpu(attr->attr_page);
730 oa->attr_id = be32_to_cpu(attr->attr_id);
731 oa->val_ptr = attr->attr_val;
732
733 cur_p += inc;
734 ++oa;
735 }
736
737 *iterator = (returned_bytes - cur_bytes) ? cur_p : NULL;
738 *nelem = n;
739 return returned_bytes - cur_bytes;
740}
741EXPORT_SYMBOL(osd_req_decode_get_attr_list);
742
743/*
744 * Attributes Page-mode
745 */
746
747int osd_req_add_get_attr_page(struct osd_request *or,
748 u32 page_id, void *attar_page, unsigned max_page_len,
749 const struct osd_attr *set_one_attr)
750{
751 struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
752
753 if (or->attributes_mode &&
754 or->attributes_mode != OSD_CDB_GET_ATTR_PAGE_SET_ONE) {
755 WARN_ON(1);
756 return -EINVAL;
757 }
758 or->attributes_mode = OSD_CDB_GET_ATTR_PAGE_SET_ONE;
759
760 or->get_attr.buff = attar_page;
761 or->get_attr.total_bytes = max_page_len;
762
763 or->set_attr.buff = set_one_attr->val_ptr;
764 or->set_attr.total_bytes = set_one_attr->len;
765
766 cdbh->attrs_page.get_attr_page = cpu_to_be32(page_id);
767 cdbh->attrs_page.get_attr_alloc_length = cpu_to_be32(max_page_len);
768 /* ocdb->attrs_page.get_attr_offset; */
769
770 cdbh->attrs_page.set_attr_page = cpu_to_be32(set_one_attr->attr_page);
771 cdbh->attrs_page.set_attr_id = cpu_to_be32(set_one_attr->attr_id);
772 cdbh->attrs_page.set_attr_length = cpu_to_be32(set_one_attr->len);
773 /* ocdb->attrs_page.set_attr_offset; */
774 return 0;
775}
776EXPORT_SYMBOL(osd_req_add_get_attr_page);
777
778static int _osd_req_finalize_attr_page(struct osd_request *or)
779{
780 struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
781 unsigned in_padding, out_padding;
782 int ret;
783
784 /* returned page */
785 cdbh->attrs_page.get_attr_offset =
786 osd_req_encode_offset(or, or->in.total_bytes, &in_padding);
787
788 ret = _req_append_segment(or, in_padding, &or->get_attr, NULL,
789 &or->in);
790 if (ret)
791 return ret;
792
793 /* set one value */
794 cdbh->attrs_page.set_attr_offset =
795 osd_req_encode_offset(or, or->out.total_bytes, &out_padding);
796
797 ret = _req_append_segment(or, out_padding, &or->enc_get_attr, NULL,
798 &or->out);
799 return ret;
800}
801
287/* 802/*
288 * osd_finalize_request and helpers 803 * osd_finalize_request and helpers
289 */ 804 */
@@ -378,9 +893,31 @@ int osd_finalize_request(struct osd_request *or,
378 _LLU(or->in.total_bytes), or->in.req->data_len); 893 _LLU(or->in.total_bytes), or->in.req->data_len);
379 } 894 }
380 895
896 or->out.pad_buff = sg_out_pad_buffer;
897 or->in.pad_buff = sg_in_pad_buffer;
898
381 if (!or->attributes_mode) 899 if (!or->attributes_mode)
382 or->attributes_mode = OSD_CDB_GET_SET_ATTR_LISTS; 900 or->attributes_mode = OSD_CDB_GET_SET_ATTR_LISTS;
383 cdbh->command_specific_options |= or->attributes_mode; 901 cdbh->command_specific_options |= or->attributes_mode;
902 if (or->attributes_mode == OSD_CDB_GET_ATTR_PAGE_SET_ONE) {
903 ret = _osd_req_finalize_attr_page(or);
904 } else {
905 /* TODO: I think that for the GET_ATTR command these 2 should
906 * be reversed to keep them in execution order (for embeded
907 * targets with low memory footprint)
908 */
909 ret = _osd_req_finalize_set_attr_list(or);
910 if (ret) {
911 OSD_DEBUG("_osd_req_finalize_set_attr_list failed\n");
912 return ret;
913 }
914
915 ret = _osd_req_finalize_get_attr_list(or);
916 if (ret) {
917 OSD_DEBUG("_osd_req_finalize_get_attr_list failed\n");
918 return ret;
919 }
920 }
384 921
385 or->request->cmd = or->cdb.buff; 922 or->request->cmd = or->cdb.buff;
386 or->request->cmd_len = _osd_req_cdb_len(or); 923 or->request->cmd_len = _osd_req_cdb_len(or);
@@ -446,3 +983,45 @@ void osd_set_caps(struct osd_cdb *cdb, const void *caps)
446{ 983{
447 memcpy(&cdb->v1.caps, caps, OSDv1_CAP_LEN); 984 memcpy(&cdb->v1.caps, caps, OSDv1_CAP_LEN);
448} 985}
986
987/*
988 * Declared in osd_protocol.h
989 * 4.12.5 Data-In and Data-Out buffer offsets
990 * byte offset = mantissa * (2^(exponent+8))
991 * Returns the smallest allowed encoded offset that contains given @offset
992 * The actual encoded offset returned is @offset + *@padding.
993 */
994osd_cdb_offset __osd_encode_offset(
995 u64 offset, unsigned *padding, int min_shift, int max_shift)
996{
997 u64 try_offset = -1, mod, align;
998 osd_cdb_offset be32_offset;
999 int shift;
1000
1001 *padding = 0;
1002 if (!offset)
1003 return 0;
1004
1005 for (shift = min_shift; shift < max_shift; ++shift) {
1006 try_offset = offset >> shift;
1007 if (try_offset < (1 << OSD_OFFSET_MAX_BITS))
1008 break;
1009 }
1010
1011 BUG_ON(shift == max_shift);
1012
1013 align = 1 << shift;
1014 mod = offset & (align - 1);
1015 if (mod) {
1016 *padding = align - mod;
1017 try_offset += 1;
1018 }
1019
1020 try_offset |= ((shift - 8) & 0xf) << 28;
1021 be32_offset = cpu_to_be32((u32)try_offset);
1022
1023 OSD_DEBUG("offset=%llu mantissa=%llu exp=%d encoded=%x pad=%d\n",
1024 _LLU(offset), _LLU(try_offset & 0x0FFFFFFF), shift,
1025 be32_offset, *padding);
1026 return be32_offset;
1027}
diff --git a/include/scsi/osd_attributes.h b/include/scsi/osd_attributes.h
new file mode 100644
index 000000000000..f888a6fda073
--- /dev/null
+++ b/include/scsi/osd_attributes.h
@@ -0,0 +1,327 @@
1#ifndef __OSD_ATTRIBUTES_H__
2#define __OSD_ATTRIBUTES_H__
3
4#include "osd_protocol.h"
5
6/*
7 * Contains types and constants that define attribute pages and attribute
8 * numbers and their data types.
9 */
10
11#define ATTR_SET(pg, id, l, ptr) \
12 { .attr_page = pg, .attr_id = id, .len = l, .val_ptr = ptr }
13
14#define ATTR_DEF(pg, id, l) ATTR_SET(pg, id, l, NULL)
15
16/* osd-r10 4.7.3 Attributes pages */
17enum {
18 OSD_APAGE_OBJECT_FIRST = 0x0,
19 OSD_APAGE_OBJECT_DIRECTORY = 0,
20 OSD_APAGE_OBJECT_INFORMATION = 1,
21 OSD_APAGE_OBJECT_QUOTAS = 2,
22 OSD_APAGE_OBJECT_TIMESTAMP = 3,
23 OSD_APAGE_OBJECT_COLLECTIONS = 4,
24 OSD_APAGE_OBJECT_SECURITY = 5,
25 OSD_APAGE_OBJECT_LAST = 0x2fffffff,
26
27 OSD_APAGE_PARTITION_FIRST = 0x30000000,
28 OSD_APAGE_PARTITION_DIRECTORY = OSD_APAGE_PARTITION_FIRST + 0,
29 OSD_APAGE_PARTITION_INFORMATION = OSD_APAGE_PARTITION_FIRST + 1,
30 OSD_APAGE_PARTITION_QUOTAS = OSD_APAGE_PARTITION_FIRST + 2,
31 OSD_APAGE_PARTITION_TIMESTAMP = OSD_APAGE_PARTITION_FIRST + 3,
32 OSD_APAGE_PARTITION_SECURITY = OSD_APAGE_PARTITION_FIRST + 5,
33 OSD_APAGE_PARTITION_LAST = 0x5FFFFFFF,
34
35 OSD_APAGE_COLLECTION_FIRST = 0x60000000,
36 OSD_APAGE_COLLECTION_DIRECTORY = OSD_APAGE_COLLECTION_FIRST + 0,
37 OSD_APAGE_COLLECTION_INFORMATION = OSD_APAGE_COLLECTION_FIRST + 1,
38 OSD_APAGE_COLLECTION_TIMESTAMP = OSD_APAGE_COLLECTION_FIRST + 3,
39 OSD_APAGE_COLLECTION_SECURITY = OSD_APAGE_COLLECTION_FIRST + 5,
40 OSD_APAGE_COLLECTION_LAST = 0x8FFFFFFF,
41
42 OSD_APAGE_ROOT_FIRST = 0x90000000,
43 OSD_APAGE_ROOT_DIRECTORY = OSD_APAGE_ROOT_FIRST + 0,
44 OSD_APAGE_ROOT_INFORMATION = OSD_APAGE_ROOT_FIRST + 1,
45 OSD_APAGE_ROOT_QUOTAS = OSD_APAGE_ROOT_FIRST + 2,
46 OSD_APAGE_ROOT_TIMESTAMP = OSD_APAGE_ROOT_FIRST + 3,
47 OSD_APAGE_ROOT_SECURITY = OSD_APAGE_ROOT_FIRST + 5,
48 OSD_APAGE_ROOT_LAST = 0xBFFFFFFF,
49
50 OSD_APAGE_RESERVED_TYPE_FIRST = 0xC0000000,
51 OSD_APAGE_RESERVED_TYPE_LAST = 0xEFFFFFFF,
52
53 OSD_APAGE_COMMON_FIRST = 0xF0000000,
54 OSD_APAGE_COMMON_LAST = 0xFFFFFFFE,
55
56 OSD_APAGE_REQUEST_ALL = 0xFFFFFFFF,
57};
58
59/* subcategories of attr pages within each range above */
60enum {
61 OSD_APAGE_STD_FIRST = 0x0,
62 OSD_APAGE_STD_DIRECTORY = 0,
63 OSD_APAGE_STD_INFORMATION = 1,
64 OSD_APAGE_STD_QUOTAS = 2,
65 OSD_APAGE_STD_TIMESTAMP = 3,
66 OSD_APAGE_STD_COLLECTIONS = 4,
67 OSD_APAGE_STD_POLICY_SECURITY = 5,
68 OSD_APAGE_STD_LAST = 0x0000007F,
69
70 OSD_APAGE_RESERVED_FIRST = 0x00000080,
71 OSD_APAGE_RESERVED_LAST = 0x00007FFF,
72
73 OSD_APAGE_OTHER_STD_FIRST = 0x00008000,
74 OSD_APAGE_OTHER_STD_LAST = 0x0000EFFF,
75
76 OSD_APAGE_PUBLIC_FIRST = 0x0000F000,
77 OSD_APAGE_PUBLIC_LAST = 0x0000FFFF,
78
79 OSD_APAGE_APP_DEFINED_FIRST = 0x00010000,
80 OSD_APAGE_APP_DEFINED_LAST = 0x1FFFFFFF,
81
82 OSD_APAGE_VENDOR_SPECIFIC_FIRST = 0x20000000,
83 OSD_APAGE_VENDOR_SPECIFIC_LAST = 0x2FFFFFFF,
84};
85
86enum {
87 OSD_ATTR_PAGE_IDENTIFICATION = 0, /* in all pages 40 bytes */
88};
89
90struct page_identification {
91 u8 vendor_identification[8];
92 u8 page_identification[32];
93} __packed;
94
95struct osd_attr_page_header {
96 __be32 page_number;
97 __be32 page_length;
98} __packed;
99
100/* 7.1.2.8 Root Information attributes page (OSD_APAGE_ROOT_INFORMATION) */
101enum {
102 OSD_ATTR_RI_OSD_SYSTEM_ID = 0x3, /* 20 */
103 OSD_ATTR_RI_VENDOR_IDENTIFICATION = 0x4, /* 8 */
104 OSD_ATTR_RI_PRODUCT_IDENTIFICATION = 0x5, /* 16 */
105 OSD_ATTR_RI_PRODUCT_MODEL = 0x6, /* 32 */
106 OSD_ATTR_RI_PRODUCT_REVISION_LEVEL = 0x7, /* 4 */
107 OSD_ATTR_RI_PRODUCT_SERIAL_NUMBER = 0x8, /* variable */
108 OSD_ATTR_RI_OSD_NAME = 0x9, /* variable */
109 OSD_ATTR_RI_TOTAL_CAPACITY = 0x80, /* 8 */
110 OSD_ATTR_RI_USED_CAPACITY = 0x81, /* 8 */
111 OSD_ATTR_RI_NUMBER_OF_PARTITIONS = 0xC0, /* 8 */
112 OSD_ATTR_RI_CLOCK = 0x100, /* 6 */
113};
114/* Root_Information_attributes_page does not have a get_page structure */
115
116/* 7.1.2.9 Partition Information attributes page
117 * (OSD_APAGE_PARTITION_INFORMATION)
118 */
119enum {
120 OSD_ATTR_PI_PARTITION_ID = 0x1, /* 8 */
121 OSD_ATTR_PI_USERNAME = 0x9, /* variable */
122 OSD_ATTR_PI_USED_CAPACITY = 0x81, /* 8 */
123 OSD_ATTR_PI_NUMBER_OF_OBJECTS = 0xC1, /* 8 */
124};
125/* Partition Information attributes page does not have a get_page structure */
126
127/* 7.1.2.10 Collection Information attributes page
128 * (OSD_APAGE_COLLECTION_INFORMATION)
129 */
130enum {
131 OSD_ATTR_CI_PARTITION_ID = 0x1, /* 8 */
132 OSD_ATTR_CI_COLLECTION_OBJECT_ID = 0x2, /* 8 */
133 OSD_ATTR_CI_USERNAME = 0x9, /* variable */
134 OSD_ATTR_CI_USED_CAPACITY = 0x81, /* 8 */
135};
136/* Collection Information attributes page does not have a get_page structure */
137
138/* 7.1.2.11 User Object Information attributes page
139 * (OSD_APAGE_OBJECT_INFORMATION)
140 */
141enum {
142 OSD_ATTR_OI_PARTITION_ID = 0x1, /* 8 */
143 OSD_ATTR_OI_OBJECT_ID = 0x2, /* 8 */
144 OSD_ATTR_OI_USERNAME = 0x9, /* variable */
145 OSD_ATTR_OI_USED_CAPACITY = 0x81, /* 8 */
146 OSD_ATTR_OI_LOGICAL_LENGTH = 0x82, /* 8 */
147};
148/* Object Information attributes page does not have a get_page structure */
149
150/* 7.1.2.12 Root Quotas attributes page (OSD_APAGE_ROOT_QUOTAS) */
151enum {
152 OSD_ATTR_RQ_DEFAULT_MAXIMUM_USER_OBJECT_LENGTH = 0x1, /* 8 */
153 OSD_ATTR_RQ_PARTITION_CAPACITY_QUOTA = 0x10001, /* 8 */
154 OSD_ATTR_RQ_PARTITION_OBJECT_COUNT = 0x10002, /* 8 */
155 OSD_ATTR_RQ_PARTITION_COLLECTIONS_PER_USER_OBJECT = 0x10081, /* 4 */
156 OSD_ATTR_RQ_PARTITION_COUNT = 0x20002, /* 8 */
157};
158
159struct Root_Quotas_attributes_page {
160 struct osd_attr_page_header hdr; /* id=R+2, size=0x24 */
161 __be64 default_maximum_user_object_length;
162 __be64 partition_capacity_quota;
163 __be64 partition_object_count;
164 __be64 partition_collections_per_user_object;
165 __be64 partition_count;
166} __packed;
167
168/* 7.1.2.13 Partition Quotas attributes page (OSD_APAGE_PARTITION_QUOTAS)*/
169enum {
170 OSD_ATTR_PQ_DEFAULT_MAXIMUM_USER_OBJECT_LENGTH = 0x1, /* 8 */
171 OSD_ATTR_PQ_CAPACITY_QUOTA = 0x10001, /* 8 */
172 OSD_ATTR_PQ_OBJECT_COUNT = 0x10002, /* 8 */
173 OSD_ATTR_PQ_COLLECTIONS_PER_USER_OBJECT = 0x10081, /* 4 */
174};
175
176struct Partition_Quotas_attributes_page {
177 struct osd_attr_page_header hdr; /* id=P+2, size=0x1C */
178 __be64 default_maximum_user_object_length;
179 __be64 capacity_quota;
180 __be64 object_count;
181 __be64 collections_per_user_object;
182} __packed;
183
184/* 7.1.2.14 User Object Quotas attributes page (OSD_APAGE_OBJECT_QUOTAS) */
185enum {
186 OSD_ATTR_OQ_MAXIMUM_LENGTH = 0x1, /* 8 */
187};
188
189struct Object_Quotas_attributes_page {
190 struct osd_attr_page_header hdr; /* id=U+2, size=0x8 */
191 __be64 maximum_length;
192} __packed;
193
194/* 7.1.2.15 Root Timestamps attributes page (OSD_APAGE_ROOT_TIMESTAMP) */
195enum {
196 OSD_ATTR_RT_ATTRIBUTES_ACCESSED_TIME = 0x2, /* 6 */
197 OSD_ATTR_RT_ATTRIBUTES_MODIFIED_TIME = 0x3, /* 6 */
198 OSD_ATTR_RT_TIMESTAMP_BYPASS = 0xFFFFFFFE, /* 1 */
199};
200
201struct root_timestamps_attributes_page {
202 struct osd_attr_page_header hdr; /* id=R+3, size=0xD */
203 struct osd_timestamp attributes_accessed_time;
204 struct osd_timestamp attributes_modified_time;
205 u8 timestamp_bypass;
206} __packed;
207
208/* 7.1.2.16 Partition Timestamps attributes page
209 * (OSD_APAGE_PARTITION_TIMESTAMP)
210 */
211enum {
212 OSD_ATTR_PT_CREATED_TIME = 0x1, /* 6 */
213 OSD_ATTR_PT_ATTRIBUTES_ACCESSED_TIME = 0x2, /* 6 */
214 OSD_ATTR_PT_ATTRIBUTES_MODIFIED_TIME = 0x3, /* 6 */
215 OSD_ATTR_PT_DATA_ACCESSED_TIME = 0x4, /* 6 */
216 OSD_ATTR_PT_DATA_MODIFIED_TIME = 0x5, /* 6 */
217 OSD_ATTR_PT_TIMESTAMP_BYPASS = 0xFFFFFFFE, /* 1 */
218};
219
220struct partition_timestamps_attributes_page {
221 struct osd_attr_page_header hdr; /* id=P+3, size=0x1F */
222 struct osd_timestamp created_time;
223 struct osd_timestamp attributes_accessed_time;
224 struct osd_timestamp attributes_modified_time;
225 struct osd_timestamp data_accessed_time;
226 struct osd_timestamp data_modified_time;
227 u8 timestamp_bypass;
228} __packed;
229
230/* 7.1.2.17/18 Collection/Object Timestamps attributes page
231 * (OSD_APAGE_COLLECTION_TIMESTAMP/OSD_APAGE_OBJECT_TIMESTAMP)
232 */
233enum {
234 OSD_ATTR_OT_CREATED_TIME = 0x1, /* 6 */
235 OSD_ATTR_OT_ATTRIBUTES_ACCESSED_TIME = 0x2, /* 6 */
236 OSD_ATTR_OT_ATTRIBUTES_MODIFIED_TIME = 0x3, /* 6 */
237 OSD_ATTR_OT_DATA_ACCESSED_TIME = 0x4, /* 6 */
238 OSD_ATTR_OT_DATA_MODIFIED_TIME = 0x5, /* 6 */
239};
240
241/* same for collection */
242struct object_timestamps_attributes_page {
243 struct osd_attr_page_header hdr; /* id=C+3/3, size=0x1E */
244 struct osd_timestamp created_time;
245 struct osd_timestamp attributes_accessed_time;
246 struct osd_timestamp attributes_modified_time;
247 struct osd_timestamp data_accessed_time;
248 struct osd_timestamp data_modified_time;
249} __packed;
250
251/* 7.1.2.19 Collections attributes page */
252/* TBD */
253
254/* 7.1.2.20 Root Policy/Security attributes page (OSD_APAGE_ROOT_SECURITY) */
255enum {
256 OSD_ATTR_RS_DEFAULT_SECURITY_METHOD = 0x1, /* 1 */
257 OSD_ATTR_RS_OLDEST_VALID_NONCE_LIMIT = 0x2, /* 6 */
258 OSD_ATTR_RS_NEWEST_VALID_NONCE_LIMIT = 0x3, /* 6 */
259 OSD_ATTR_RS_PARTITION_DEFAULT_SECURITY_METHOD = 0x6, /* 1 */
260 OSD_ATTR_RS_SUPPORTED_SECURITY_METHODS = 0x7, /* 2 */
261 OSD_ATTR_RS_ADJUSTABLE_CLOCK = 0x9, /* 6 */
262 OSD_ATTR_RS_MASTER_KEY_IDENTIFIER = 0x7FFD, /* 0 or 7 */
263 OSD_ATTR_RS_ROOT_KEY_IDENTIFIER = 0x7FFE, /* 0 or 7 */
264 OSD_ATTR_RS_SUPPORTED_INTEGRITY_ALGORITHM_0 = 0x80000000,/* 1,(x16)*/
265 OSD_ATTR_RS_SUPPORTED_DH_GROUP_0 = 0x80000010,/* 1,(x16)*/
266};
267
268struct root_security_attributes_page {
269 struct osd_attr_page_header hdr; /* id=R+5, size=0x3F */
270 u8 default_security_method;
271 u8 partition_default_security_method;
272 __be16 supported_security_methods;
273 u8 mki_valid_rki_valid;
274 struct osd_timestamp oldest_valid_nonce_limit;
275 struct osd_timestamp newest_valid_nonce_limit;
276 struct osd_timestamp adjustable_clock;
277 u8 master_key_identifier[32-25];
278 u8 root_key_identifier[39-32];
279 u8 supported_integrity_algorithm[16];
280 u8 supported_dh_group[16];
281} __packed;
282
283/* 7.1.2.21 Partition Policy/Security attributes page
284 * (OSD_APAGE_PARTITION_SECURITY)
285 */
286enum {
287 OSD_ATTR_PS_DEFAULT_SECURITY_METHOD = 0x1, /* 1 */
288 OSD_ATTR_PS_OLDEST_VALID_NONCE = 0x2, /* 6 */
289 OSD_ATTR_PS_NEWEST_VALID_NONCE = 0x3, /* 6 */
290 OSD_ATTR_PS_REQUEST_NONCE_LIST_DEPTH = 0x4, /* 2 */
291 OSD_ATTR_PS_FROZEN_WORKING_KEY_BIT_MASK = 0x5, /* 2 */
292 OSD_ATTR_PS_PARTITION_KEY_IDENTIFIER = 0x7FFF, /* 0 or 7 */
293 OSD_ATTR_PS_WORKING_KEY_IDENTIFIER_FIRST = 0x8000, /* 0 or 7 */
294 OSD_ATTR_PS_WORKING_KEY_IDENTIFIER_LAST = 0x800F, /* 0 or 7 */
295 OSD_ATTR_PS_POLICY_ACCESS_TAG = 0x40000001, /* 4 */
296 OSD_ATTR_PS_USER_OBJECT_POLICY_ACCESS_TAG = 0x40000002, /* 4 */
297};
298
299struct partition_security_attributes_page {
300 struct osd_attr_page_header hdr; /* id=p+5, size=0x8f */
301 u8 reserved[3];
302 u8 default_security_method;
303 struct osd_timestamp oldest_valid_nonce;
304 struct osd_timestamp newest_valid_nonce;
305 __be16 request_nonce_list_depth;
306 __be16 frozen_working_key_bit_mask;
307 __be32 policy_access_tag;
308 __be32 user_object_policy_access_tag;
309 u8 pki_valid;
310 __be16 wki_00_0f_vld;
311 struct osd_key_identifier partition_key_identifier;
312 struct osd_key_identifier working_key_identifiers[16];
313} __packed;
314
315/* 7.1.2.22/23 Collection/Object Policy-Security attributes page
316 * (OSD_APAGE_COLLECTION_SECURITY/OSD_APAGE_OBJECT_SECURITY)
317 */
318enum {
319 OSD_ATTR_OS_POLICY_ACCESS_TAG = 0x40000001, /* 4 */
320};
321
322struct object_security_attributes_page {
323 struct osd_attr_page_header hdr; /* id=C+5/5, size=4 */
324 __be32 policy_access_tag;
325} __packed;
326
327#endif /*ndef __OSD_ATTRIBUTES_H__*/