summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authorjimharris <jimharris@FreeBSD.org>2012-03-28 18:38:13 +0000
committerjimharris <jimharris@FreeBSD.org>2012-03-28 18:38:13 +0000
commita95c98845608b765a2471a2465314c453fbca532 (patch)
tree3e398e4e0a8c998e9d64632d942f2c24112732f0 /sys/dev
parentad499681b46e0279b2fdf8d21139f73989104ef9 (diff)
downloadFreeBSD-src-a95c98845608b765a2471a2465314c453fbca532.zip
FreeBSD-src-a95c98845608b765a2471a2465314c453fbca532.tar.gz
Ensure consistent target IDs for direct-attached devices.
Sponsored by: Intel Reported by: sbruno, <rpokala at panasas dot com> Tested by: <rpokala at panasas dot com> Reviewed by: scottl Approved by: scottl MFC after: 3 days
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/isci/isci.h8
-rw-r--r--sys/dev/isci/isci_controller.c13
-rw-r--r--sys/dev/isci/isci_domain.c20
3 files changed, 32 insertions, 9 deletions
diff --git a/sys/dev/isci/isci.h b/sys/dev/isci/isci.h
index 70ba16a..50f0236 100644
--- a/sys/dev/isci/isci.h
+++ b/sys/dev/isci/isci.h
@@ -89,10 +89,10 @@ struct ISCI_REMOTE_DEVICE {
};
struct ISCI_DOMAIN {
- struct ISCI_CONTROLLER *controller;
- SCI_DOMAIN_HANDLE_T sci_object;
- uint8_t index;
-
+ struct ISCI_CONTROLLER *controller;
+ SCI_DOMAIN_HANDLE_T sci_object;
+ uint8_t index;
+ struct ISCI_REMOTE_DEVICE *da_remote_device;
};
struct ISCI_MEMORY
diff --git a/sys/dev/isci/isci_controller.c b/sys/dev/isci/isci_controller.c
index 38d91ac..8511400 100644
--- a/sys/dev/isci/isci_controller.c
+++ b/sys/dev/isci/isci_controller.c
@@ -430,7 +430,18 @@ int isci_controller_allocate_memory(struct ISCI_CONTROLLER *controller)
remote_device->frozen_lun_mask = 0;
sci_fast_list_element_init(remote_device,
&remote_device->pending_device_reset_element);
- sci_pool_put(controller->remote_device_pool, remote_device);
+
+ /*
+ * For the first SCI_MAX_DOMAINS device objects, do not put
+ * them in the pool, rather assign them to each domain. This
+ * ensures that any device attached directly to port "i" will
+ * always get CAM target id "i".
+ */
+ if (i < SCI_MAX_DOMAINS)
+ controller->domain[i].da_remote_device = remote_device;
+ else
+ sci_pool_put(controller->remote_device_pool,
+ remote_device);
remote_device_memory_ptr += remote_device_size;
}
diff --git a/sys/dev/isci/isci_domain.c b/sys/dev/isci/isci_domain.c
index 1f79dfd..834c1c2 100644
--- a/sys/dev/isci/isci_domain.c
+++ b/sys/dev/isci/isci_domain.c
@@ -202,10 +202,14 @@ scif_cb_domain_da_device_added(SCI_CONTROLLER_HANDLE_T controller,
struct ISCI_REMOTE_DEVICE *remote_device;
struct ISCI_DOMAIN *isci_domain =
(struct ISCI_DOMAIN *)sci_object_get_association(domain);
- struct ISCI_CONTROLLER *isci_controller =
- (struct ISCI_CONTROLLER *)sci_object_get_association(controller);
- sci_pool_get(isci_controller->remote_device_pool, remote_device);
+ /*
+ * For direct-attached devices, do not pull the device object from
+ * the pool. Rather, use the one stored in the domain object which
+ * will ensure that we always get consistent target ids for direct
+ * attached devices.
+ */
+ remote_device = isci_domain->da_remote_device;
scif_remote_device_construct(domain,
(uint8_t*)remote_device + sizeof(struct ISCI_REMOTE_DEVICE),
@@ -287,6 +291,8 @@ scif_cb_domain_device_removed(SCI_CONTROLLER_HANDLE_T controller,
{
struct ISCI_REMOTE_DEVICE *isci_remote_device =
(struct ISCI_REMOTE_DEVICE *)sci_object_get_association(remote_device);
+ struct ISCI_DOMAIN *isci_domain =
+ (struct ISCI_DOMAIN *)sci_object_get_association(domain);
struct ISCI_CONTROLLER *isci_controller =
(struct ISCI_CONTROLLER *)sci_object_get_association(controller);
uint32_t path = cam_sim_path(isci_controller->sim);
@@ -301,7 +307,13 @@ scif_cb_domain_device_removed(SCI_CONTROLLER_HANDLE_T controller,
scif_remote_device_destruct(remote_device);
- sci_pool_put(isci_controller->remote_device_pool, isci_remote_device);
+ /*
+ * Only put the remote device back into the pool if it was an
+ * expander-attached device.
+ */
+ if (isci_remote_device != isci_domain->da_remote_device)
+ sci_pool_put(isci_controller->remote_device_pool,
+ isci_remote_device);
}
void
OpenPOWER on IntegriCloud