diff options
author | Ramachandra K <rkuchimanchi@silverstorm.com> | 2006-06-17 23:37:38 -0400 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2006-06-17 23:37:38 -0400 |
commit | 0c0450db31481aa01a04e7faecc93ee6841972d6 (patch) | |
tree | c7a1ed2896345d022011831f8a9aaa21e8d8ff00 /drivers/infiniband/ulp | |
parent | 73c0996b1ca60338fa50e42acfcebd32b7636a8b (diff) |
IB/srp: Support SRP rev. 10 targets
There has been a change in the format of port identifiers between
revision 10 of the SRP specification and the current revision 16A.
Revision 10 specifies port identifier format as
lower 8 bytes : GUID upper 8 bytes : Extension
Whereas revision 16A specifies it as
lower 8 bytes : Extension upper 8 bytes : GUID
There are older targets (e.g. SilverStorm Virtual Fibre Channel
Bridge) which conform to revision 10 of the SRP specification.
The I/O class of revision 10 is 0xFF00 and the I/O class of revision
16A is 0x0100.
For supporting older targets, this patch:
1) Adds a new optional target creation parameter "io_class". Default
value of io_class is 0x0100 (i.e. revision 16A)
2) Uses the correct port identifier format for targets with IO class
of 0xFF00 (i.e. conforming to revision 10)
Signed-off-by: Ramachandra K <rkuchimanchi@silverstorm.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband/ulp')
-rw-r--r-- | drivers/infiniband/ulp/srp/ib_srp.c | 44 | ||||
-rw-r--r-- | drivers/infiniband/ulp/srp/ib_srp.h | 1 |
2 files changed, 42 insertions, 3 deletions
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index f1401e1f2f97..e7fa8b680cb6 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c | |||
@@ -321,7 +321,29 @@ static int srp_send_req(struct srp_target_port *target) | |||
321 | req->priv.req_it_iu_len = cpu_to_be32(srp_max_iu_len); | 321 | req->priv.req_it_iu_len = cpu_to_be32(srp_max_iu_len); |
322 | req->priv.req_buf_fmt = cpu_to_be16(SRP_BUF_FORMAT_DIRECT | | 322 | req->priv.req_buf_fmt = cpu_to_be16(SRP_BUF_FORMAT_DIRECT | |
323 | SRP_BUF_FORMAT_INDIRECT); | 323 | SRP_BUF_FORMAT_INDIRECT); |
324 | memcpy(req->priv.initiator_port_id, target->srp_host->initiator_port_id, 16); | 324 | /* |
325 | * In the published SRP specification (draft rev. 16a), the | ||
326 | * port identifier format is 8 bytes of ID extension followed | ||
327 | * by 8 bytes of GUID. Older drafts put the two halves in the | ||
328 | * opposite order, so that the GUID comes first. | ||
329 | * | ||
330 | * Targets conforming to these obsolete drafts can be | ||
331 | * recognized by the I/O Class they report. | ||
332 | */ | ||
333 | if (target->io_class == SRP_REV10_IB_IO_CLASS) { | ||
334 | memcpy(req->priv.initiator_port_id, | ||
335 | target->srp_host->initiator_port_id + 8, 8); | ||
336 | memcpy(req->priv.initiator_port_id + 8, | ||
337 | target->srp_host->initiator_port_id, 8); | ||
338 | memcpy(req->priv.target_port_id, &target->ioc_guid, 8); | ||
339 | memcpy(req->priv.target_port_id + 8, &target->id_ext, 8); | ||
340 | } else { | ||
341 | memcpy(req->priv.initiator_port_id, | ||
342 | target->srp_host->initiator_port_id, 16); | ||
343 | memcpy(req->priv.target_port_id, &target->id_ext, 8); | ||
344 | memcpy(req->priv.target_port_id + 8, &target->ioc_guid, 8); | ||
345 | } | ||
346 | |||
325 | /* | 347 | /* |
326 | * Topspin/Cisco SRP targets will reject our login unless we | 348 | * Topspin/Cisco SRP targets will reject our login unless we |
327 | * zero out the first 8 bytes of our initiator port ID. The | 349 | * zero out the first 8 bytes of our initiator port ID. The |
@@ -334,8 +356,6 @@ static int srp_send_req(struct srp_target_port *target) | |||
334 | (unsigned long long) be64_to_cpu(target->ioc_guid)); | 356 | (unsigned long long) be64_to_cpu(target->ioc_guid)); |
335 | memset(req->priv.initiator_port_id, 0, 8); | 357 | memset(req->priv.initiator_port_id, 0, 8); |
336 | } | 358 | } |
337 | memcpy(req->priv.target_port_id, &target->id_ext, 8); | ||
338 | memcpy(req->priv.target_port_id + 8, &target->ioc_guid, 8); | ||
339 | 359 | ||
340 | status = ib_send_cm_req(target->cm_id, &req->param); | 360 | status = ib_send_cm_req(target->cm_id, &req->param); |
341 | 361 | ||
@@ -1511,6 +1531,7 @@ enum { | |||
1511 | SRP_OPT_SERVICE_ID = 1 << 4, | 1531 | SRP_OPT_SERVICE_ID = 1 << 4, |
1512 | SRP_OPT_MAX_SECT = 1 << 5, | 1532 | SRP_OPT_MAX_SECT = 1 << 5, |
1513 | SRP_OPT_MAX_CMD_PER_LUN = 1 << 6, | 1533 | SRP_OPT_MAX_CMD_PER_LUN = 1 << 6, |
1534 | SRP_OPT_IO_CLASS = 1 << 7, | ||
1514 | SRP_OPT_ALL = (SRP_OPT_ID_EXT | | 1535 | SRP_OPT_ALL = (SRP_OPT_ID_EXT | |
1515 | SRP_OPT_IOC_GUID | | 1536 | SRP_OPT_IOC_GUID | |
1516 | SRP_OPT_DGID | | 1537 | SRP_OPT_DGID | |
@@ -1526,6 +1547,7 @@ static match_table_t srp_opt_tokens = { | |||
1526 | { SRP_OPT_SERVICE_ID, "service_id=%s" }, | 1547 | { SRP_OPT_SERVICE_ID, "service_id=%s" }, |
1527 | { SRP_OPT_MAX_SECT, "max_sect=%d" }, | 1548 | { SRP_OPT_MAX_SECT, "max_sect=%d" }, |
1528 | { SRP_OPT_MAX_CMD_PER_LUN, "max_cmd_per_lun=%d" }, | 1549 | { SRP_OPT_MAX_CMD_PER_LUN, "max_cmd_per_lun=%d" }, |
1550 | { SRP_OPT_IO_CLASS, "io_class=%x" }, | ||
1529 | { SRP_OPT_ERR, NULL } | 1551 | { SRP_OPT_ERR, NULL } |
1530 | }; | 1552 | }; |
1531 | 1553 | ||
@@ -1610,6 +1632,21 @@ static int srp_parse_options(const char *buf, struct srp_target_port *target) | |||
1610 | target->scsi_host->cmd_per_lun = min(token, SRP_SQ_SIZE); | 1632 | target->scsi_host->cmd_per_lun = min(token, SRP_SQ_SIZE); |
1611 | break; | 1633 | break; |
1612 | 1634 | ||
1635 | case SRP_OPT_IO_CLASS: | ||
1636 | if (match_hex(args, &token)) { | ||
1637 | printk(KERN_WARNING PFX "bad IO class parameter '%s' \n", p); | ||
1638 | goto out; | ||
1639 | } | ||
1640 | if (token != SRP_REV10_IB_IO_CLASS && | ||
1641 | token != SRP_REV16A_IB_IO_CLASS) { | ||
1642 | printk(KERN_WARNING PFX "unknown IO class parameter value" | ||
1643 | " %x specified (use %x or %x).\n", | ||
1644 | token, SRP_REV10_IB_IO_CLASS, SRP_REV16A_IB_IO_CLASS); | ||
1645 | goto out; | ||
1646 | } | ||
1647 | target->io_class = token; | ||
1648 | break; | ||
1649 | |||
1613 | default: | 1650 | default: |
1614 | printk(KERN_WARNING PFX "unknown parameter or missing value " | 1651 | printk(KERN_WARNING PFX "unknown parameter or missing value " |
1615 | "'%s' in target creation request\n", p); | 1652 | "'%s' in target creation request\n", p); |
@@ -1652,6 +1689,7 @@ static ssize_t srp_create_target(struct class_device *class_dev, | |||
1652 | target = host_to_target(target_host); | 1689 | target = host_to_target(target_host); |
1653 | memset(target, 0, sizeof *target); | 1690 | memset(target, 0, sizeof *target); |
1654 | 1691 | ||
1692 | target->io_class = SRP_REV16A_IB_IO_CLASS; | ||
1655 | target->scsi_host = target_host; | 1693 | target->scsi_host = target_host; |
1656 | target->srp_host = host; | 1694 | target->srp_host = host; |
1657 | 1695 | ||
diff --git a/drivers/infiniband/ulp/srp/ib_srp.h b/drivers/infiniband/ulp/srp/ib_srp.h index ad45e4856e1c..5b581fb8eb0d 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.h +++ b/drivers/infiniband/ulp/srp/ib_srp.h | |||
@@ -122,6 +122,7 @@ struct srp_target_port { | |||
122 | __be64 id_ext; | 122 | __be64 id_ext; |
123 | __be64 ioc_guid; | 123 | __be64 ioc_guid; |
124 | __be64 service_id; | 124 | __be64 service_id; |
125 | u16 io_class; | ||
125 | struct srp_host *srp_host; | 126 | struct srp_host *srp_host; |
126 | struct Scsi_Host *scsi_host; | 127 | struct Scsi_Host *scsi_host; |
127 | char target_name[32]; | 128 | char target_name[32]; |