Mercurial > illumos > illumos-gate
changeset 4024:3e0ae05d7190
6513951 Service Entry update not notified when both IOU ChangeID and IOC ServiceEntry has changed
author | pramodbg |
---|---|
date | Thu, 12 Apr 2007 23:27:05 -0700 |
parents | 2a35fc2ee7d3 |
children | d8be2f0444ab |
files | usr/src/uts/common/io/ib/mgt/ibdm/ibdm.c usr/src/uts/common/sys/ib/mgt/ibdm/ibdm_impl.h |
diffstat | 2 files changed, 156 insertions(+), 27 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/uts/common/io/ib/mgt/ibdm/ibdm.c Thu Apr 12 20:04:29 2007 -0700 +++ b/usr/src/uts/common/io/ib/mgt/ibdm/ibdm.c Thu Apr 12 23:27:05 2007 -0700 @@ -45,7 +45,7 @@ #include <sys/modctl.h> /* Function Prototype declarations */ -static int ibdm_free_iou_info(ibdm_dp_gidinfo_t *); +static int ibdm_free_iou_info(ibdm_dp_gidinfo_t *, ibdm_iou_info_t **); static int ibdm_fini(void); static int ibdm_init(void); static int ibdm_get_reachable_ports(ibdm_port_attr_t *, @@ -139,6 +139,9 @@ static void ibdm_delete_gidinfo(ibdm_dp_gidinfo_t *); static void ibdm_fill_srv_attr_mod(ib_mad_hdr_t *, ibdm_timeout_cb_args_t *); static void ibdm_bump_transactionID(ibdm_dp_gidinfo_t *); +static ibdm_ioc_info_t *ibdm_handle_prev_iou(); +static int ibdm_serv_cmp(ibdm_srvents_info_t *, ibdm_srvents_info_t *, + int); int ibdm_dft_timeout = IBDM_DFT_TIMEOUT; int ibdm_dft_retry_cnt = IBDM_DFT_NRETRIES; @@ -288,26 +291,27 @@ static int -ibdm_free_iou_info(ibdm_dp_gidinfo_t *gid_info) +ibdm_free_iou_info(ibdm_dp_gidinfo_t *gid_info, ibdm_iou_info_t **ioup) { int ii, k, niocs; size_t size; ibdm_gid_t *delete, *head; timeout_id_t timeout_id; ibdm_ioc_info_t *ioc; + ibdm_iou_info_t *gl_iou = *ioup; ASSERT(mutex_owned(&gid_info->gl_mutex)); - if (gid_info->gl_iou == NULL) { + if (gl_iou == NULL) { IBTF_DPRINTF_L4("ibdm", "\tibdm_free_iou_info: No IOU"); return (0); } - niocs = gid_info->gl_iou->iou_info.iou_num_ctrl_slots; + niocs = gl_iou->iou_info.iou_num_ctrl_slots; IBTF_DPRINTF_L4("ibdm", "\tfree_iou_info: gid_info = %p, niocs %d", gid_info, niocs); for (ii = 0; ii < niocs; ii++) { - ioc = IBDM_GIDINFO2IOCINFO(gid_info, ii); + ioc = (ibdm_ioc_info_t *)&gl_iou->iou_ioc_info[ii]; /* handle the case where an ioc_timeout_id is scheduled */ if (ioc->ioc_timeout_id) { @@ -360,7 +364,7 @@ } } - /* delete GID list */ + /* delete GID list in IOC */ head = ioc->ioc_gid_list; while (head) { IBTF_DPRINTF_L4("ibdm", "\tibdm_free_iou_info: " @@ -382,8 +386,8 @@ IBTF_DPRINTF_L4("ibdm", "\tibdm_free_iou_info: deleting IOU & IOC"); size = sizeof (ibdm_iou_info_t) + niocs * sizeof (ibdm_ioc_info_t); - kmem_free(gid_info->gl_iou, size); - gid_info->gl_iou = NULL; + kmem_free(gl_iou, size); + *ioup = NULL; return (0); } @@ -436,7 +440,7 @@ gid_info = ibdm.ibdm_dp_gidlist_head; while (gid_info) { mutex_enter(&gid_info->gl_mutex); - (void) ibdm_free_iou_info(gid_info); + (void) ibdm_free_iou_info(gid_info, &gid_info->gl_iou); mutex_exit(&gid_info->gl_mutex); ibdm_delete_glhca_list(gid_info); @@ -1306,7 +1310,24 @@ gid_info); } } - } + } else if (ibdm.ibdm_prev_iou) { + ibdm_ioc_info_t *ioc_list; + + /* + * Get the list of IOCs which have changed. + * If any IOCs have changed, Notify IBNexus + */ + ibdm.ibdm_prev_iou = 0; + ioc_list = ibdm_handle_prev_iou(); + if (ioc_list) { + if (ibdm.ibdm_ibnex_callback != NULL) { + (*ibdm.ibdm_ibnex_callback)( + (void *)ioc_list, + IBDM_EVENT_IOC_PROP_UPDATE); + } + } + } + ibdm_dump_sweep_fabric_timestamp(1); ibdm.ibdm_busy &= ~IBDM_BUSY; @@ -2156,20 +2177,26 @@ */ if (gid_info->gl_iou) { giou_info = &gid_info->gl_iou->iou_info; - if (iou_info->iou_changeid == giou_info->iou_changeid) { + if (b2h16(iou_info->iou_changeid) == + giou_info->iou_changeid) { IBTF_DPRINTF_L3("ibdm", "\thandle_iounitinfo: no IOCs changed"); gid_info->gl_state = IBDM_GID_PROBING_COMPLETE; mutex_exit(&gid_info->gl_mutex); return; } - if (ibdm_free_iou_info(gid_info)) { - IBTF_DPRINTF_L3("ibdm", - "\thandle_iounitinfo: failed to cleanup resources"); - gid_info->gl_state = IBDM_GID_PROBING_COMPLETE; - mutex_exit(&gid_info->gl_mutex); - return; - } + + /* + * Store the iou info as prev_iou to be used after + * sweep is done. + */ + ASSERT(gid_info->gl_prev_iou == NULL); + IBTF_DPRINTF_L4(ibdm_string, + "\thandle_iounitinfo: setting gl_prev_iou %p", + gid_info->gl_prev_iou); + gid_info->gl_prev_iou = gid_info->gl_iou; + ibdm.ibdm_prev_iou = 1; + gid_info->gl_iou = NULL; } size = sizeof (ibdm_iou_info_t) + num_iocs * sizeof (ibdm_ioc_info_t); @@ -5378,7 +5405,7 @@ mutex_enter(&ibdm.ibdm_mutex); if (gid_info->gl_iou != NULL && gid_info->gl_ngids == 0) { mutex_enter(&gid_info->gl_mutex); - (void) ibdm_free_iou_info(gid_info); + (void) ibdm_free_iou_info(gid_info, &gid_info->gl_iou); mutex_exit(&gid_info->gl_mutex); } if (gid_info->gl_prev != NULL) @@ -5468,11 +5495,10 @@ cur_gid_list = gidinfo->gl_gid; cur_nportgids = gidinfo->gl_ngids; - /* - * Service entry names and IDs are not compared currently. - * This may require change. - */ - if (ioc->ioc_prev_serv_cnt != ioc->ioc_profile.ioc_service_entries) + if (ioc->ioc_prev_serv_cnt != + ioc->ioc_profile.ioc_service_entries || + ibdm_serv_cmp(&ioc->ioc_serv[0], &ioc->ioc_prev_serv[0], + ioc->ioc_prev_serv_cnt)) ioc->ioc_info_updated.ib_srv_prop_updated = 1; if (ioc->ioc_prev_nportgids != cur_nportgids || @@ -5726,7 +5752,7 @@ mutex_enter(&ibdm.ibdm_mutex); if (gid_info->gl_iou != NULL && gid_info->gl_ngids == 0) { mutex_enter(&gid_info->gl_mutex); - (void) ibdm_free_iou_info(gid_info); + (void) ibdm_free_iou_info(gid_info, &gid_info->gl_iou); mutex_exit(&gid_info->gl_mutex); } tmp = gid_info->gl_next; @@ -6168,7 +6194,7 @@ mutex_enter(&ibdm.ibdm_mutex); if (gidinfo->gl_iou != NULL && gidinfo->gl_ngids == 0) { mutex_enter(&gidinfo->gl_mutex); - (void) ibdm_free_iou_info(gidinfo); + (void) ibdm_free_iou_info(gidinfo, &gidinfo->gl_iou); mutex_exit(&gidinfo->gl_mutex); } @@ -6233,6 +6259,105 @@ } } +/* + * gl_prev_iou is set for *non-reprobe* sweeep requests, which + * detected that ChangeID in IOU info has changed. The service + * entry also may have changed. Check if service entry in IOC + * has changed wrt the prev iou, if so notify to IB Nexus. + */ +static ibdm_ioc_info_t * +ibdm_handle_prev_iou() +{ + ibdm_dp_gidinfo_t *gid_info; + ibdm_ioc_info_t *ioc_list_head = NULL, *ioc_list; + ibdm_ioc_info_t *prev_ioc, *ioc; + int ii, jj, niocs, prev_niocs; + + ASSERT(MUTEX_HELD(&ibdm.ibdm_mutex)); + + IBTF_DPRINTF_L4(ibdm_string, "\thandle_prev_iou enter"); + for (gid_info = ibdm.ibdm_dp_gidlist_head; gid_info; + gid_info = gid_info->gl_next) { + if (gid_info->gl_prev_iou == NULL) + continue; + + IBTF_DPRINTF_L4(ibdm_string, "\thandle_prev_iou gid %p", + gid_info); + niocs = gid_info->gl_iou->iou_info.iou_num_ctrl_slots; + prev_niocs = + gid_info->gl_prev_iou->iou_info.iou_num_ctrl_slots; + for (ii = 0; ii < niocs; ii++) { + ioc = IBDM_GIDINFO2IOCINFO(gid_info, ii); + + /* Find matching IOC */ + for (jj = 0; jj < prev_niocs; jj++) { + prev_ioc = (ibdm_ioc_info_t *) + &gid_info->gl_prev_iou->iou_ioc_info[jj]; + if (prev_ioc->ioc_profile.ioc_guid == + ioc->ioc_profile.ioc_guid) + break; + } + if (jj == prev_niocs) + prev_ioc = NULL; + if (ioc == NULL || prev_ioc == NULL) + continue; + if ((ioc->ioc_profile.ioc_service_entries != + prev_ioc->ioc_profile.ioc_service_entries) || + ibdm_serv_cmp(&ioc->ioc_serv[0], + &prev_ioc->ioc_serv[0], + ioc->ioc_profile.ioc_service_entries) != 0) { + IBTF_DPRINTF_L4(ibdm_string, + "/thandle_prev_iou modified IOC: " + "current ioc %p, old ioc %p", + ioc, prev_ioc); + ioc_list = ibdm_dup_ioc_info(ioc, gid_info); + ioc_list->ioc_info_updated.ib_prop_updated + = 0; + ioc_list->ioc_info_updated.ib_srv_prop_updated + = 1; + + if (ioc_list_head == NULL) + ioc_list_head = ioc_list; + else { + ioc_list_head->ioc_next = ioc_list; + ioc_list_head = ioc_list; + } + } + } + + mutex_enter(&gid_info->gl_mutex); + (void) ibdm_free_iou_info(gid_info, &gid_info->gl_prev_iou); + mutex_exit(&gid_info->gl_mutex); + } + IBTF_DPRINTF_L4(ibdm_string, "\thandle_prev_iouret %p", + ioc_list_head); + return (ioc_list_head); +} + +/* + * Compares two service entries lists, returns 0 if same, returns 1 + * if no match. + */ +static int +ibdm_serv_cmp(ibdm_srvents_info_t *serv1, ibdm_srvents_info_t *serv2, + int nserv) +{ + int ii; + + IBTF_DPRINTF_L4(ibdm_string, "\tserv_cmp: enter"); + for (ii = 0; ii < nserv; ii++, serv1++, serv2++) { + if (serv1->se_attr.srv_id != serv2->se_attr.srv_id || + bcmp(serv1->se_attr.srv_name, + serv2->se_attr.srv_name, + IB_DM_MAX_SVC_NAME_LEN) != 0) { + IBTF_DPRINTF_L4(ibdm_string, "\tserv_cmp: ret 1"); + return (1); + } + } + IBTF_DPRINTF_L4(ibdm_string, "\tserv_cmp: ret 0"); + return (0); +} + /* For debugging purpose only */ #ifdef DEBUG void
--- a/usr/src/uts/common/sys/ib/mgt/ibdm/ibdm_impl.h Thu Apr 12 20:04:29 2007 -0700 +++ b/usr/src/uts/common/sys/ib/mgt/ibdm/ibdm_impl.h Thu Apr 12 23:27:05 2007 -0700 @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -196,6 +196,7 @@ int gl_disconnected; uint64_t gl_min_transactionID; uint64_t gl_max_transactionID; + ibdm_iou_info_t *gl_prev_iou; } ibdm_dp_gidinfo_t; _NOTE(MUTEX_PROTECTS_DATA(ibdm_dp_gidinfo_s::gl_mutex, ibdm_dp_gidinfo_s::{gl_state gl_timeout_id gl_pending_cmds})) @@ -241,6 +242,9 @@ * the arrival/removal of HCA and IOC's */ ibdm_callback_t ibdm_ibnex_callback; + + /* Flag indicating - prev_iou during sweep */ + int ibdm_prev_iou; } ibdm_t; _NOTE(MUTEX_PROTECTS_DATA(ibdm_s::ibdm_mutex, ibdm_s::{ibdm_ibt_clnt_hdl ibdm_busy ibdm_state}))