diff options
author | jimharris <jimharris@FreeBSD.org> | 2012-03-28 18:38:13 +0000 |
---|---|---|
committer | jimharris <jimharris@FreeBSD.org> | 2012-03-28 18:38:13 +0000 |
commit | a95c98845608b765a2471a2465314c453fbca532 (patch) | |
tree | 3e398e4e0a8c998e9d64632d942f2c24112732f0 /sys/dev | |
parent | ad499681b46e0279b2fdf8d21139f73989104ef9 (diff) | |
download | FreeBSD-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.h | 8 | ||||
-rw-r--r-- | sys/dev/isci/isci_controller.c | 13 | ||||
-rw-r--r-- | sys/dev/isci/isci_domain.c | 20 |
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 |