diff options
author | Ishai Rabinovitz <ishai@mellanox.co.il> | 2006-10-04 09:28:56 -0400 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2006-10-10 15:49:05 -0400 |
commit | 01cb9bcbd34b7ba768a7f05375faf43becdb8a60 (patch) | |
tree | 58eeaa0d602c3f858fced07e53ca4c44041c5a45 /drivers/infiniband/ulp | |
parent | 9b0af401aae336975e620fccdd294bb763424f3f (diff) |
IB/srp: Enable multiple connections to the same target
Enable multiple concurrent connections to the same SRP target:
1) Use port GUID instead of node GUID in the initiator port
identifier. This allows connections to be made from multiple HCA
ports at the same time.
2) Let the user specify the identifier extention when adding the
device. This allows userspace to make multiple connections even
from the same port, if it wants too.
Without this, only one connection can be made from any given HCA, even
if it has multiple ports, because we don't use multi-channel mode, so
targets will only allow one connection from a given initiator port ID.
Signed-off-by: Ishai Rabinovitz <ishai@mellanox.co.il>
Signed-off-by: Michael S. Tsirkin <mst@mellanox.co.il>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband/ulp')
-rw-r--r-- | drivers/infiniband/ulp/srp/ib_srp.c | 26 | ||||
-rw-r--r-- | drivers/infiniband/ulp/srp/ib_srp.h | 2 |
2 files changed, 18 insertions, 10 deletions
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index f1b7a0f2beed..4b09147f438f 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c | |||
@@ -343,29 +343,32 @@ static int srp_send_req(struct srp_target_port *target) | |||
343 | */ | 343 | */ |
344 | if (target->io_class == SRP_REV10_IB_IO_CLASS) { | 344 | if (target->io_class == SRP_REV10_IB_IO_CLASS) { |
345 | memcpy(req->priv.initiator_port_id, | 345 | memcpy(req->priv.initiator_port_id, |
346 | target->srp_host->initiator_port_id + 8, 8); | 346 | &target->path.sgid.global.interface_id, 8); |
347 | memcpy(req->priv.initiator_port_id + 8, | 347 | memcpy(req->priv.initiator_port_id + 8, |
348 | target->srp_host->initiator_port_id, 8); | 348 | &target->initiator_ext, 8); |
349 | memcpy(req->priv.target_port_id, &target->ioc_guid, 8); | 349 | memcpy(req->priv.target_port_id, &target->ioc_guid, 8); |
350 | memcpy(req->priv.target_port_id + 8, &target->id_ext, 8); | 350 | memcpy(req->priv.target_port_id + 8, &target->id_ext, 8); |
351 | } else { | 351 | } else { |
352 | memcpy(req->priv.initiator_port_id, | 352 | memcpy(req->priv.initiator_port_id, |
353 | target->srp_host->initiator_port_id, 16); | 353 | &target->initiator_ext, 8); |
354 | memcpy(req->priv.initiator_port_id + 8, | ||
355 | &target->path.sgid.global.interface_id, 8); | ||
354 | memcpy(req->priv.target_port_id, &target->id_ext, 8); | 356 | memcpy(req->priv.target_port_id, &target->id_ext, 8); |
355 | memcpy(req->priv.target_port_id + 8, &target->ioc_guid, 8); | 357 | memcpy(req->priv.target_port_id + 8, &target->ioc_guid, 8); |
356 | } | 358 | } |
357 | 359 | ||
358 | /* | 360 | /* |
359 | * Topspin/Cisco SRP targets will reject our login unless we | 361 | * Topspin/Cisco SRP targets will reject our login unless we |
360 | * zero out the first 8 bytes of our initiator port ID. The | 362 | * zero out the first 8 bytes of our initiator port ID and set |
361 | * second 8 bytes must be our local node GUID, but we always | 363 | * the second 8 bytes to the local node GUID. |
362 | * use that anyway. | ||
363 | */ | 364 | */ |
364 | if (topspin_workarounds && !memcmp(&target->ioc_guid, topspin_oui, 3)) { | 365 | if (topspin_workarounds && !memcmp(&target->ioc_guid, topspin_oui, 3)) { |
365 | printk(KERN_DEBUG PFX "Topspin/Cisco initiator port ID workaround " | 366 | printk(KERN_DEBUG PFX "Topspin/Cisco initiator port ID workaround " |
366 | "activated for target GUID %016llx\n", | 367 | "activated for target GUID %016llx\n", |
367 | (unsigned long long) be64_to_cpu(target->ioc_guid)); | 368 | (unsigned long long) be64_to_cpu(target->ioc_guid)); |
368 | memset(req->priv.initiator_port_id, 0, 8); | 369 | memset(req->priv.initiator_port_id, 0, 8); |
370 | memcpy(req->priv.initiator_port_id + 8, | ||
371 | &target->srp_host->dev->dev->node_guid, 8); | ||
369 | } | 372 | } |
370 | 373 | ||
371 | status = ib_send_cm_req(target->cm_id, &req->param); | 374 | status = ib_send_cm_req(target->cm_id, &req->param); |
@@ -1553,6 +1556,7 @@ enum { | |||
1553 | SRP_OPT_MAX_SECT = 1 << 5, | 1556 | SRP_OPT_MAX_SECT = 1 << 5, |
1554 | SRP_OPT_MAX_CMD_PER_LUN = 1 << 6, | 1557 | SRP_OPT_MAX_CMD_PER_LUN = 1 << 6, |
1555 | SRP_OPT_IO_CLASS = 1 << 7, | 1558 | SRP_OPT_IO_CLASS = 1 << 7, |
1559 | SRP_OPT_INITIATOR_EXT = 1 << 8, | ||
1556 | SRP_OPT_ALL = (SRP_OPT_ID_EXT | | 1560 | SRP_OPT_ALL = (SRP_OPT_ID_EXT | |
1557 | SRP_OPT_IOC_GUID | | 1561 | SRP_OPT_IOC_GUID | |
1558 | SRP_OPT_DGID | | 1562 | SRP_OPT_DGID | |
@@ -1569,6 +1573,7 @@ static match_table_t srp_opt_tokens = { | |||
1569 | { SRP_OPT_MAX_SECT, "max_sect=%d" }, | 1573 | { SRP_OPT_MAX_SECT, "max_sect=%d" }, |
1570 | { SRP_OPT_MAX_CMD_PER_LUN, "max_cmd_per_lun=%d" }, | 1574 | { SRP_OPT_MAX_CMD_PER_LUN, "max_cmd_per_lun=%d" }, |
1571 | { SRP_OPT_IO_CLASS, "io_class=%x" }, | 1575 | { SRP_OPT_IO_CLASS, "io_class=%x" }, |
1576 | { SRP_OPT_INITIATOR_EXT, "initiator_ext=%s" }, | ||
1572 | { SRP_OPT_ERR, NULL } | 1577 | { SRP_OPT_ERR, NULL } |
1573 | }; | 1578 | }; |
1574 | 1579 | ||
@@ -1668,6 +1673,12 @@ static int srp_parse_options(const char *buf, struct srp_target_port *target) | |||
1668 | target->io_class = token; | 1673 | target->io_class = token; |
1669 | break; | 1674 | break; |
1670 | 1675 | ||
1676 | case SRP_OPT_INITIATOR_EXT: | ||
1677 | p = match_strdup(args); | ||
1678 | target->initiator_ext = cpu_to_be64(simple_strtoull(p, NULL, 16)); | ||
1679 | kfree(p); | ||
1680 | break; | ||
1681 | |||
1671 | default: | 1682 | default: |
1672 | printk(KERN_WARNING PFX "unknown parameter or missing value " | 1683 | printk(KERN_WARNING PFX "unknown parameter or missing value " |
1673 | "'%s' in target creation request\n", p); | 1684 | "'%s' in target creation request\n", p); |
@@ -1814,9 +1825,6 @@ static struct srp_host *srp_add_port(struct srp_device *device, u8 port) | |||
1814 | host->dev = device; | 1825 | host->dev = device; |
1815 | host->port = port; | 1826 | host->port = port; |
1816 | 1827 | ||
1817 | host->initiator_port_id[7] = port; | ||
1818 | memcpy(host->initiator_port_id + 8, &device->dev->node_guid, 8); | ||
1819 | |||
1820 | host->class_dev.class = &srp_class; | 1828 | host->class_dev.class = &srp_class; |
1821 | host->class_dev.dev = device->dev->dma_device; | 1829 | host->class_dev.dev = device->dev->dma_device; |
1822 | snprintf(host->class_dev.class_id, BUS_ID_SIZE, "srp-%s-%d", | 1830 | snprintf(host->class_dev.class_id, BUS_ID_SIZE, "srp-%s-%d", |
diff --git a/drivers/infiniband/ulp/srp/ib_srp.h b/drivers/infiniband/ulp/srp/ib_srp.h index 5b581fb8eb0d..d4e35ef51374 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.h +++ b/drivers/infiniband/ulp/srp/ib_srp.h | |||
@@ -91,7 +91,6 @@ struct srp_device { | |||
91 | }; | 91 | }; |
92 | 92 | ||
93 | struct srp_host { | 93 | struct srp_host { |
94 | u8 initiator_port_id[16]; | ||
95 | struct srp_device *dev; | 94 | struct srp_device *dev; |
96 | u8 port; | 95 | u8 port; |
97 | struct class_device class_dev; | 96 | struct class_device class_dev; |
@@ -122,6 +121,7 @@ struct srp_target_port { | |||
122 | __be64 id_ext; | 121 | __be64 id_ext; |
123 | __be64 ioc_guid; | 122 | __be64 ioc_guid; |
124 | __be64 service_id; | 123 | __be64 service_id; |
124 | __be64 initiator_ext; | ||
125 | u16 io_class; | 125 | u16 io_class; |
126 | struct srp_host *srp_host; | 126 | struct srp_host *srp_host; |
127 | struct Scsi_Host *scsi_host; | 127 | struct Scsi_Host *scsi_host; |