summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/osd
diff options
context:
space:
mode:
authorBoaz Harrosh <bharrosh@panasas.com>2009-01-25 16:13:38 +0100
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2009-03-12 18:58:08 +0100
commit1b9dce94c8a24a3f1a01fcdf688f2d903b32acdf (patch)
treec0e17494a5eb8f8701d3674afff26b91ccf593b3 /drivers/scsi/osd
parent[SCSI] libosd: OSD version 2 Support (diff)
downloadlinux-1b9dce94c8a24a3f1a01fcdf688f2d903b32acdf.tar.xz
linux-1b9dce94c8a24a3f1a01fcdf688f2d903b32acdf.zip
[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>
Diffstat (limited to 'drivers/scsi/osd')
-rw-r--r--drivers/scsi/osd/osd_initiator.c125
-rw-r--r--drivers/scsi/osd/osd_uld.c5
2 files changed, 130 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 @@
#include <scsi/osd_initiator.h>
#include <scsi/osd_sec.h>
+#include <scsi/osd_attributes.h>
#include <scsi/scsi_device.h>
#include "osd_debug.h"
@@ -63,6 +64,130 @@ static inline void build_test(void)
BUILD_BUG_ON(sizeof(struct osdv1_cdb) != OSDv1_TOTAL_CDB_LEN);
}
+static const char *_osd_ver_desc(struct osd_request *or)
+{
+ return osd_req_is_ver1(or) ? "OSD1" : "OSD2";
+}
+
+#define ATTR_DEF_RI(id, len) ATTR_DEF(OSD_APAGE_ROOT_INFORMATION, id, len)
+
+static int _osd_print_system_info(struct osd_dev *od, void *caps)
+{
+ struct osd_request *or;
+ struct osd_attr get_attrs[] = {
+ ATTR_DEF_RI(OSD_ATTR_RI_VENDOR_IDENTIFICATION, 8),
+ ATTR_DEF_RI(OSD_ATTR_RI_PRODUCT_IDENTIFICATION, 16),
+ ATTR_DEF_RI(OSD_ATTR_RI_PRODUCT_MODEL, 32),
+ ATTR_DEF_RI(OSD_ATTR_RI_PRODUCT_REVISION_LEVEL, 4),
+ ATTR_DEF_RI(OSD_ATTR_RI_PRODUCT_SERIAL_NUMBER, 64 /*variable*/),
+ ATTR_DEF_RI(OSD_ATTR_RI_OSD_NAME, 64 /*variable*/),
+ ATTR_DEF_RI(OSD_ATTR_RI_TOTAL_CAPACITY, 8),
+ ATTR_DEF_RI(OSD_ATTR_RI_USED_CAPACITY, 8),
+ ATTR_DEF_RI(OSD_ATTR_RI_NUMBER_OF_PARTITIONS, 8),
+ ATTR_DEF_RI(OSD_ATTR_RI_CLOCK, 6),
+ /* IBM-OSD-SIM Has a bug with this one put it last */
+ ATTR_DEF_RI(OSD_ATTR_RI_OSD_SYSTEM_ID, 20),
+ };
+ void *iter = NULL, *pFirst;
+ int nelem = ARRAY_SIZE(get_attrs), a = 0;
+ int ret;
+
+ or = osd_start_request(od, GFP_KERNEL);
+ if (!or)
+ return -ENOMEM;
+
+ /* get attrs */
+ osd_req_get_attributes(or, &osd_root_object);
+ osd_req_add_get_attr_list(or, get_attrs, ARRAY_SIZE(get_attrs));
+
+ ret = osd_finalize_request(or, 0, caps, NULL);
+ if (ret)
+ goto out;
+
+ ret = osd_execute_request(or);
+ if (ret) {
+ OSD_ERR("Failed to detect %s => %d\n", _osd_ver_desc(or), ret);
+ goto out;
+ }
+
+ osd_req_decode_get_attr_list(or, get_attrs, &nelem, &iter);
+
+ OSD_INFO("Detected %s device\n",
+ _osd_ver_desc(or));
+
+ pFirst = get_attrs[a++].val_ptr;
+ OSD_INFO("OSD_ATTR_RI_VENDOR_IDENTIFICATION [%s]\n",
+ (char *)pFirst);
+
+ pFirst = get_attrs[a++].val_ptr;
+ OSD_INFO("OSD_ATTR_RI_PRODUCT_IDENTIFICATION [%s]\n",
+ (char *)pFirst);
+
+ pFirst = get_attrs[a++].val_ptr;
+ OSD_INFO("OSD_ATTR_RI_PRODUCT_MODEL [%s]\n",
+ (char *)pFirst);
+
+ pFirst = get_attrs[a++].val_ptr;
+ OSD_INFO("OSD_ATTR_RI_PRODUCT_REVISION_LEVEL [%u]\n",
+ get_unaligned_be32(pFirst));
+
+ pFirst = get_attrs[a++].val_ptr;
+ OSD_INFO("OSD_ATTR_RI_PRODUCT_SERIAL_NUMBER [%s]\n",
+ (char *)pFirst);
+
+ pFirst = get_attrs[a].val_ptr;
+ OSD_INFO("OSD_ATTR_RI_OSD_NAME [%s]\n", (char *)pFirst);
+ a++;
+
+ pFirst = get_attrs[a++].val_ptr;
+ OSD_INFO("OSD_ATTR_RI_TOTAL_CAPACITY [0x%llx]\n",
+ _LLU(get_unaligned_be64(pFirst)));
+
+ pFirst = get_attrs[a++].val_ptr;
+ OSD_INFO("OSD_ATTR_RI_USED_CAPACITY [0x%llx]\n",
+ _LLU(get_unaligned_be64(pFirst)));
+
+ pFirst = get_attrs[a++].val_ptr;
+ OSD_INFO("OSD_ATTR_RI_NUMBER_OF_PARTITIONS [%llu]\n",
+ _LLU(get_unaligned_be64(pFirst)));
+
+ /* FIXME: Where are the time utilities */
+ pFirst = get_attrs[a++].val_ptr;
+ OSD_INFO("OSD_ATTR_RI_CLOCK [0x%02x%02x%02x%02x%02x%02x]\n",
+ ((char *)pFirst)[0], ((char *)pFirst)[1],
+ ((char *)pFirst)[2], ((char *)pFirst)[3],
+ ((char *)pFirst)[4], ((char *)pFirst)[5]);
+
+ if (a < nelem) { /* IBM-OSD-SIM bug, Might not have it */
+ unsigned len = get_attrs[a].len;
+ char sid_dump[32*4 + 2]; /* 2nibbles+space+ASCII */
+
+ hex_dump_to_buffer(get_attrs[a].val_ptr, len, 32, 1,
+ sid_dump, sizeof(sid_dump), true);
+ OSD_INFO("OSD_ATTR_RI_OSD_SYSTEM_ID(%d) [%s]\n", len, sid_dump);
+ a++;
+ }
+out:
+ osd_end_request(or);
+ return ret;
+}
+
+int osd_auto_detect_ver(struct osd_dev *od, void *caps)
+{
+ int ret;
+
+ /* Auto-detect the osd version */
+ ret = _osd_print_system_info(od, caps);
+ if (ret) {
+ osd_dev_set_ver(od, OSD_VER1);
+ OSD_DEBUG("converting to OSD1\n");
+ ret = _osd_print_system_info(od, caps);
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL(osd_auto_detect_ver);
+
static unsigned _osd_req_cdb_len(struct osd_request *or)
{
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);
static int __detect_osd(struct osd_uld_device *oud)
{
struct scsi_device *scsi_device = oud->od.scsi_device;
+ char caps[OSD_CAP_LEN];
int error;
/* 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)
if (error)
OSD_ERR("warning: scsi_test_unit_ready failed\n");
+ osd_sec_init_nosec_doall_caps(caps, &osd_root_object, false, true);
+ if (osd_auto_detect_ver(&oud->od, caps))
+ return -ENODEV;
+
return 0;
}