aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBoaz Harrosh <bharrosh@panasas.com>2009-01-25 10:13:38 -0500
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2009-03-12 13:58:08 -0400
commit1b9dce94c8a24a3f1a01fcdf688f2d903b32acdf (patch)
treec0e17494a5eb8f8701d3674afff26b91ccf593b3
parentc6572c983726fe3f3bb5f07e9afe3a9b8e402d1b (diff)
[SCSI] libosd: OSDv2 auto detection
Auto detect an OSDv2 or OSDv1 target at run time. Note how none of the OSD API calls change. The tests do not know what device version it is. This test now passes against both the IBM-OSD-SIM OSD1 target as well as OSC's OSD2 target. Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> Reviewed-by: Benny Halevy <bhalevy@panasas.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
-rw-r--r--drivers/scsi/osd/osd_initiator.c125
-rw-r--r--drivers/scsi/osd/osd_uld.c5
-rw-r--r--include/scsi/osd_initiator.h3
3 files changed, 133 insertions, 0 deletions
diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index 86a76cccfebd..f6340c2ceb25 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -41,6 +41,7 @@
41 41
42#include <scsi/osd_initiator.h> 42#include <scsi/osd_initiator.h>
43#include <scsi/osd_sec.h> 43#include <scsi/osd_sec.h>
44#include <scsi/osd_attributes.h>
44#include <scsi/scsi_device.h> 45#include <scsi/scsi_device.h>
45 46
46#include "osd_debug.h" 47#include "osd_debug.h"
@@ -63,6 +64,130 @@ static inline void build_test(void)
63 BUILD_BUG_ON(sizeof(struct osdv1_cdb) != OSDv1_TOTAL_CDB_LEN); 64 BUILD_BUG_ON(sizeof(struct osdv1_cdb) != OSDv1_TOTAL_CDB_LEN);
64} 65}
65 66
67static const char *_osd_ver_desc(struct osd_request *or)
68{
69 return osd_req_is_ver1(or) ? "OSD1" : "OSD2";
70}
71
72#define ATTR_DEF_RI(id, len) ATTR_DEF(OSD_APAGE_ROOT_INFORMATION, id, len)
73
74static int _osd_print_system_info(struct osd_dev *od, void *caps)
75{
76 struct osd_request *or;
77 struct osd_attr get_attrs[] = {
78 ATTR_DEF_RI(OSD_ATTR_RI_VENDOR_IDENTIFICATION, 8),
79 ATTR_DEF_RI(OSD_ATTR_RI_PRODUCT_IDENTIFICATION, 16),
80 ATTR_DEF_RI(OSD_ATTR_RI_PRODUCT_MODEL, 32),
81 ATTR_DEF_RI(OSD_ATTR_RI_PRODUCT_REVISION_LEVEL, 4),
82 ATTR_DEF_RI(OSD_ATTR_RI_PRODUCT_SERIAL_NUMBER, 64 /*variable*/),
83 ATTR_DEF_RI(OSD_ATTR_RI_OSD_NAME, 64 /*variable*/),
84 ATTR_DEF_RI(OSD_ATTR_RI_TOTAL_CAPACITY, 8),
85 ATTR_DEF_RI(OSD_ATTR_RI_USED_CAPACITY, 8),
86 ATTR_DEF_RI(OSD_ATTR_RI_NUMBER_OF_PARTITIONS, 8),
87 ATTR_DEF_RI(OSD_ATTR_RI_CLOCK, 6),
88 /* IBM-OSD-SIM Has a bug with this one put it last */
89 ATTR_DEF_RI(OSD_ATTR_RI_OSD_SYSTEM_ID, 20),
90 };
91 void *iter = NULL, *pFirst;
92 int nelem = ARRAY_SIZE(get_attrs), a = 0;
93 int ret;
94
95 or = osd_start_request(od, GFP_KERNEL);
96 if (!or)
97 return -ENOMEM;
98
99 /* get attrs */
100 osd_req_get_attributes(or, &osd_root_object);
101 osd_req_add_get_attr_list(or, get_attrs, ARRAY_SIZE(get_attrs));
102
103 ret = osd_finalize_request(or, 0, caps, NULL);
104 if (ret)
105 goto out;
106
107 ret = osd_execute_request(or);
108 if (ret) {
109 OSD_ERR("Failed to detect %s => %d\n", _osd_ver_desc(or), ret);
110 goto out;
111 }
112
113 osd_req_decode_get_attr_list(or, get_attrs, &nelem, &iter);
114
115 OSD_INFO("Detected %s device\n",
116 _osd_ver_desc(or));
117
118 pFirst = get_attrs[a++].val_ptr;
119 OSD_INFO("OSD_ATTR_RI_VENDOR_IDENTIFICATION [%s]\n",
120 (char *)pFirst);
121
122 pFirst = get_attrs[a++].val_ptr;
123 OSD_INFO("OSD_ATTR_RI_PRODUCT_IDENTIFICATION [%s]\n",
124 (char *)pFirst);
125
126 pFirst = get_attrs[a++].val_ptr;
127 OSD_INFO("OSD_ATTR_RI_PRODUCT_MODEL [%s]\n",
128 (char *)pFirst);
129
130 pFirst = get_attrs[a++].val_ptr;
131 OSD_INFO("OSD_ATTR_RI_PRODUCT_REVISION_LEVEL [%u]\n",
132 get_unaligned_be32(pFirst));
133
134 pFirst = get_attrs[a++].val_ptr;
135 OSD_INFO("OSD_ATTR_RI_PRODUCT_SERIAL_NUMBER [%s]\n",
136 (char *)pFirst);
137
138 pFirst = get_attrs[a].val_ptr;
139 OSD_INFO("OSD_ATTR_RI_OSD_NAME [%s]\n", (char *)pFirst);
140 a++;
141
142 pFirst = get_attrs[a++].val_ptr;
143 OSD_INFO("OSD_ATTR_RI_TOTAL_CAPACITY [0x%llx]\n",
144 _LLU(get_unaligned_be64(pFirst)));
145
146 pFirst = get_attrs[a++].val_ptr;
147 OSD_INFO("OSD_ATTR_RI_USED_CAPACITY [0x%llx]\n",
148 _LLU(get_unaligned_be64(pFirst)));
149
150 pFirst = get_attrs[a++].val_ptr;
151 OSD_INFO("OSD_ATTR_RI_NUMBER_OF_PARTITIONS [%llu]\n",
152 _LLU(get_unaligned_be64(pFirst)));
153
154 /* FIXME: Where are the time utilities */
155 pFirst = get_attrs[a++].val_ptr;
156 OSD_INFO("OSD_ATTR_RI_CLOCK [0x%02x%02x%02x%02x%02x%02x]\n",
157 ((char *)pFirst)[0], ((char *)pFirst)[1],
158 ((char *)pFirst)[2], ((char *)pFirst)[3],
159 ((char *)pFirst)[4], ((char *)pFirst)[5]);
160
161 if (a < nelem) { /* IBM-OSD-SIM bug, Might not have it */
162 unsigned len = get_attrs[a].len;
163 char sid_dump[32*4 + 2]; /* 2nibbles+space+ASCII */
164
165 hex_dump_to_buffer(get_attrs[a].val_ptr, len, 32, 1,
166 sid_dump, sizeof(sid_dump), true);
167 OSD_INFO("OSD_ATTR_RI_OSD_SYSTEM_ID(%d) [%s]\n", len, sid_dump);
168 a++;
169 }
170out:
171 osd_end_request(or);
172 return ret;
173}
174
175int osd_auto_detect_ver(struct osd_dev *od, void *caps)
176{
177 int ret;
178
179 /* Auto-detect the osd version */
180 ret = _osd_print_system_info(od, caps);
181 if (ret) {
182 osd_dev_set_ver(od, OSD_VER1);
183 OSD_DEBUG("converting to OSD1\n");
184 ret = _osd_print_system_info(od, caps);
185 }
186
187 return ret;
188}
189EXPORT_SYMBOL(osd_auto_detect_ver);
190
66static unsigned _osd_req_cdb_len(struct osd_request *or) 191static unsigned _osd_req_cdb_len(struct osd_request *or)
67{ 192{
68 return osd_req_is_ver1(or) ? OSDv1_TOTAL_CDB_LEN : OSD_TOTAL_CDB_LEN; 193 return osd_req_is_ver1(or) ? OSDv1_TOTAL_CDB_LEN : OSD_TOTAL_CDB_LEN;
diff --git a/drivers/scsi/osd/osd_uld.c b/drivers/scsi/osd/osd_uld.c
index cd4ca7cd9f75..f8b1a749958b 100644
--- a/drivers/scsi/osd/osd_uld.c
+++ b/drivers/scsi/osd/osd_uld.c
@@ -243,6 +243,7 @@ EXPORT_SYMBOL(osduld_put_device);
243static int __detect_osd(struct osd_uld_device *oud) 243static int __detect_osd(struct osd_uld_device *oud)
244{ 244{
245 struct scsi_device *scsi_device = oud->od.scsi_device; 245 struct scsi_device *scsi_device = oud->od.scsi_device;
246 char caps[OSD_CAP_LEN];
246 int error; 247 int error;
247 248
248 /* sending a test_unit_ready as first command seems to be needed 249 /* sending a test_unit_ready as first command seems to be needed
@@ -254,6 +255,10 @@ static int __detect_osd(struct osd_uld_device *oud)
254 if (error) 255 if (error)
255 OSD_ERR("warning: scsi_test_unit_ready failed\n"); 256 OSD_ERR("warning: scsi_test_unit_ready failed\n");
256 257
258 osd_sec_init_nosec_doall_caps(caps, &osd_root_object, false, true);
259 if (osd_auto_detect_ver(&oud->od, caps))
260 return -ENODEV;
261
257 return 0; 262 return 0;
258} 263}
259 264
diff --git a/include/scsi/osd_initiator.h b/include/scsi/osd_initiator.h
index 8482777416d8..24edeae48936 100644
--- a/include/scsi/osd_initiator.h
+++ b/include/scsi/osd_initiator.h
@@ -67,6 +67,9 @@ void osduld_unregister_test(unsigned ioctl);
67void osd_dev_init(struct osd_dev *od, struct scsi_device *scsi_device); 67void osd_dev_init(struct osd_dev *od, struct scsi_device *scsi_device);
68void osd_dev_fini(struct osd_dev *od); 68void osd_dev_fini(struct osd_dev *od);
69 69
70/* some hi level device operations */
71int osd_auto_detect_ver(struct osd_dev *od, void *caps); /* GFP_KERNEL */
72
70/* we might want to use function vector in the future */ 73/* we might want to use function vector in the future */
71static inline void osd_dev_set_ver(struct osd_dev *od, enum osd_std_version v) 74static inline void osd_dev_set_ver(struct osd_dev *od, enum osd_std_version v)
72{ 75{