git-svn-id: svn://openib.tc.cornell.edu/gen1/trunk@588 ad392aa1-c5ef-ae45-8dd8-e69d62...
authorsleybo <sleybo@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Wed, 7 Feb 2007 13:32:45 +0000 (13:32 +0000)
committersleybo <sleybo@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Wed, 7 Feb 2007 13:32:45 +0000 (13:32 +0000)
core/al/kernel/al_smi.c
core/al/kernel/al_smi.h

index ca4adb8..a2fc5f3 100644 (file)
@@ -121,7 +121,7 @@ loopback_mad(
        IN                              al_mad_wr_t* const                      p_mad_wr );\r
 \r
 static ib_api_status_t\r
-process_subn_mad(\r
+__process_subn_mad(\r
        IN                              spl_qp_svc_t*                           p_spl_qp_svc,\r
        IN                              al_mad_wr_t* const                      p_mad_wr );\r
 \r
@@ -552,7 +552,8 @@ create_spl_qp_svc(
        /* Initialize the send and receive queues. */\r
        cl_qlist_init( &p_spl_qp_svc->send_queue );\r
        cl_qlist_init( &p_spl_qp_svc->recv_queue );\r
-\r
+       cl_spinlock_init(&p_spl_qp_svc->cache_lock);\r
+       \r
 #if defined( CL_USE_MUTEX )\r
        /* Initialize async callbacks and flags for send/receive processing. */\r
        p_spl_qp_svc->send_async_queued = FALSE;\r
@@ -1388,8 +1389,8 @@ local_mad_send(
                case IB_MCLASS_SUBN_DIR:\r
                case IB_MCLASS_SUBN_LID:\r
                        //DO not use the cache in order to force Mkey  check\r
-                       //status = process_subn_mad( p_spl_qp_svc, p_mad_wr );\r
-                       status = IB_NOT_DONE;\r
+                       status = __process_subn_mad( p_spl_qp_svc, p_mad_wr );\r
+                       //status = IB_NOT_DONE;\r
                        break;\r
 \r
                default:\r
@@ -1540,8 +1541,129 @@ loopback_mad(
 }\r
 \r
 \r
+static void\r
+__update_guid_info(\r
+       IN                              spl_qp_cache_t* const                   p_cache,\r
+       IN              const   ib_smp_t* const                         p_mad )\r
+{\r
+       uint32_t                        idx;\r
+\r
+       /* Get the table selector from the attribute */\r
+       idx = cl_ntoh32( p_mad->attr_mod );\r
+\r
+       /*\r
+        * We only get successful MADs here, so invalid settings\r
+        * shouldn't happen.\r
+        */\r
+       CL_ASSERT( idx <= 31 );\r
+\r
+       cl_memcpy( &p_cache->guid_block[idx].tbl,\r
+               ib_smp_get_payload_ptr( p_mad ),\r
+               sizeof(ib_guid_info_t) );\r
+       p_cache->guid_block[idx].valid = TRUE;\r
+}\r
+\r
+\r
+static  void\r
+__update_pkey_table(\r
+       IN                              spl_qp_cache_t* const                   p_cache,\r
+       IN              const   ib_smp_t* const                         p_mad )\r
+{\r
+       uint16_t                        idx;\r
+\r
+       /* Get the table selector from the attribute */\r
+       idx = ((uint16_t)cl_ntoh32( p_mad->attr_mod ));\r
+\r
+       CL_ASSERT( idx <= 2047 );\r
+\r
+       cl_memcpy( &p_cache->pkey_tbl[idx].tbl,\r
+               ib_smp_get_payload_ptr( p_mad ),\r
+               sizeof(ib_pkey_table_info_t) );\r
+       p_cache->pkey_tbl[idx].valid = TRUE;\r
+}\r
+\r
+\r
+static void\r
+__update_sl_vl_table(\r
+       IN                              spl_qp_cache_t* const                   p_cache,\r
+       IN              const   ib_smp_t* const                         p_mad )\r
+{\r
+       cl_memcpy( &p_cache->sl_vl.tbl,\r
+               ib_smp_get_payload_ptr( p_mad ),\r
+               sizeof(ib_slvl_table_t) );\r
+       p_cache->sl_vl.valid = TRUE;\r
+}\r
+\r
+\r
+static void\r
+__update_vl_arb_table(\r
+       IN                              spl_qp_cache_t* const                   p_cache,\r
+       IN              const   ib_smp_t* const                         p_mad )\r
+{\r
+       uint16_t                        idx;\r
+\r
+       /* Get the table selector from the attribute */\r
+       idx = ((uint16_t)(cl_ntoh32( p_mad->attr_mod ) >> 16)) - 1;\r
+\r
+       CL_ASSERT( idx <= 3 );\r
+\r
+       cl_memcpy( &p_cache->vl_arb[idx].tbl,\r
+               ib_smp_get_payload_ptr( p_mad ),\r
+               sizeof(ib_vl_arb_table_t) );\r
+       p_cache->vl_arb[idx].valid = TRUE;\r
+}\r
+\r
+\r
+\r
+void\r
+spl_qp_svc_update_cache(\r
+       IN                              spl_qp_svc_t                            *p_spl_qp_svc,\r
+       IN                              ib_smp_t                                        *p_mad )\r
+{\r
+\r
+\r
+\r
+       CL_ASSERT( p_spl_qp_svc );\r
+       CL_ASSERT( p_mad );\r
+       CL_ASSERT( p_mad->mgmt_class == IB_MCLASS_SUBN_DIR ||\r
+                                p_mad->mgmt_class == IB_MCLASS_SUBN_LID);\r
+       CL_ASSERT(!p_mad->status);\r
+\r
+       cl_spinlock_acquire(&p_spl_qp_svc->cache_lock);\r
+       \r
+       switch( p_mad->attr_id )\r
+       {\r
+       case IB_MAD_ATTR_GUID_INFO:\r
+               __update_guid_info(\r
+                       &p_spl_qp_svc->cache, p_mad );\r
+               break;\r
+\r
+       case IB_MAD_ATTR_P_KEY_TABLE:\r
+               __update_pkey_table(\r
+                       &p_spl_qp_svc->cache, p_mad );\r
+               break;\r
+\r
+       case IB_MAD_ATTR_SLVL_TABLE:\r
+               __update_sl_vl_table(\r
+                       &p_spl_qp_svc->cache, p_mad );\r
+               break;\r
+\r
+       case IB_MAD_ATTR_VL_ARBITRATION:\r
+               __update_vl_arb_table(\r
+                       &p_spl_qp_svc->cache, p_mad );\r
+               break;\r
+\r
+       default:\r
+               break;\r
+       }\r
+       \r
+       cl_spinlock_release(&p_spl_qp_svc->cache_lock);\r
+}\r
+\r
+\r
+\r
 static ib_api_status_t\r
-process_node_info(\r
+__process_node_info(\r
        IN                              spl_qp_svc_t*                           p_spl_qp_svc,\r
        IN                              al_mad_wr_t* const                      p_mad_wr )\r
 {\r
@@ -1596,8 +1718,7 @@ process_node_info(
                p_node_info->class_version = 1;\r
                p_node_info->node_type = IB_NODE_TYPE_CA;\r
                p_node_info->num_ports = p_ca_attr->num_ports;\r
-               /* TODO: Get some unique identifier for the system */\r
-               p_node_info->sys_guid = p_ca_attr->ca_guid;\r
+               p_node_info->sys_guid = p_ca_attr->system_image_guid;\r
                p_node_info->node_guid = p_ca_attr->ca_guid;\r
                p_node_info->port_guid = p_port_attr->port_guid;\r
                p_node_info->partition_cap = cl_hton16( p_port_attr->num_pkeys );\r
@@ -1616,7 +1737,7 @@ process_node_info(
 \r
 \r
 static ib_api_status_t\r
-process_node_desc(\r
+__process_node_desc(\r
        IN                              spl_qp_svc_t*                           p_spl_qp_svc,\r
        IN                              al_mad_wr_t* const                      p_mad_wr )\r
 {\r
@@ -1662,12 +1783,341 @@ process_node_desc(
        return status;\r
 }\r
 \r
+static ib_api_status_t\r
+__process_guid_info(\r
+       IN                              spl_qp_svc_t*                           p_spl_qp_svc,\r
+       IN                              al_mad_wr_t* const                      p_mad_wr )\r
+{\r
+       \r
+       ib_mad_t                                *p_mad;\r
+       ib_mad_element_t                *p_mad_resp;\r
+       ib_smp_t                                *p_smp;\r
+       ib_guid_info_t                  *p_guid_info;\r
+       uint16_t                                idx;\r
+       ib_api_status_t         status;\r
+\r
+\r
+       /* Initialize a pointers to the MAD work request and outbound MAD. */\r
+       p_mad = get_mad_hdr_from_wr( p_mad_wr );\r
+\r
+       /* Get the table selector from the attribute */\r
+       idx = ((uint16_t)cl_ntoh32( p_mad->attr_mod ));\r
+       \r
+       /*\r
+        * TODO : Setup the response to fail the MAD instead of sending\r
+        * it down to the HCA.\r
+        */\r
+       if( idx > 31 )\r
+       {\r
+               AL_EXIT( AL_DBG_SMI );\r
+               return IB_NOT_DONE;\r
+       }\r
+       if( !p_spl_qp_svc->cache.guid_block[idx].valid )\r
+       {\r
+               AL_EXIT( AL_DBG_SMI );\r
+               return IB_NOT_DONE;\r
+       }\r
+\r
+       /*\r
+        * If a SET, see if the set is identical to the cache,\r
+        * in which case it's a no-op.\r
+        */\r
+       if( p_mad->method == IB_MAD_METHOD_SET )\r
+       {\r
+               if( cl_memcmp( ib_smp_get_payload_ptr( (ib_smp_t*)p_mad ),\r
+                       &p_spl_qp_svc->cache.guid_block[idx].tbl, sizeof(ib_pkey_table_info_t) ) )\r
+               {\r
+                       /* The set is requesting a change. */\r
+                       return IB_NOT_DONE;\r
+               }\r
+       }\r
+       \r
+       /* Get a MAD element from the pool for the response. */\r
+       status = get_resp_mad( p_spl_qp_svc, p_mad_wr, &p_mad_resp );\r
+       if( status == IB_SUCCESS )\r
+       {\r
+               p_smp = (ib_smp_t*)p_mad_resp->p_mad_buf;\r
+\r
+               /* Setup the response mad. */\r
+               cl_memcpy( p_smp, p_mad, MAD_BLOCK_SIZE );\r
+               p_smp->method = (IB_MAD_METHOD_RESP_MASK | IB_MAD_METHOD_GET);\r
+               if( p_smp->mgmt_class == IB_MCLASS_SUBN_DIR )\r
+                       p_smp->status = IB_SMP_DIRECTION;\r
+               else\r
+                       p_smp->status = 0;\r
+\r
+               p_guid_info = (ib_guid_info_t*)ib_smp_get_payload_ptr( p_smp );\r
+\r
+               // TODO: do we need lock on the cache ?????\r
+\r
+               \r
+               /* Copy the cached data. */\r
+               cl_memcpy( p_guid_info,\r
+                       &p_spl_qp_svc->cache.guid_block[idx].tbl, sizeof(ib_guid_info_t) );\r
+\r
+               status = complete_local_mad( p_spl_qp_svc, p_mad_wr, p_mad_resp );\r
+       }\r
+\r
+       AL_EXIT( AL_DBG_SMI );\r
+       return status;\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+__process_pkey_table(\r
+       IN                              spl_qp_svc_t*                           p_spl_qp_svc,\r
+       IN                              al_mad_wr_t* const                      p_mad_wr )\r
+{\r
+\r
+       ib_mad_t                                *p_mad;\r
+       ib_mad_element_t                *p_mad_resp;\r
+       ib_smp_t                                *p_smp;\r
+       ib_pkey_table_info_t    *p_pkey_table_info;\r
+       uint16_t                                idx;\r
+       ib_api_status_t         status;\r
+\r
+       AL_ENTER( AL_DBG_SMI );\r
+\r
+       CL_ASSERT( p_spl_qp_svc );\r
+       CL_ASSERT( p_mad_wr );\r
+\r
+       /* Initialize a pointers to the MAD work request and outbound MAD. */\r
+       p_mad = get_mad_hdr_from_wr( p_mad_wr );\r
+\r
+       /* Get the table selector from the attribute */\r
+       idx = ((uint16_t)cl_ntoh32( p_mad->attr_mod ));\r
+       \r
+       /*\r
+        * TODO : Setup the response to fail the MAD instead of sending\r
+        * it down to the HCA.\r
+        */\r
+       if( idx > 2047 )\r
+       {\r
+               AL_EXIT( AL_DBG_SMI );\r
+               return IB_NOT_DONE;\r
+       }\r
+\r
+\r
+       if( !p_spl_qp_svc->cache.pkey_tbl[idx].valid )\r
+       {\r
+               AL_EXIT( AL_DBG_SMI );\r
+               return IB_NOT_DONE;\r
+       }\r
+\r
+       /*\r
+        * If a SET, see if the set is identical to the cache,\r
+        * in which case it's a no-op.\r
+        */\r
+       if( p_mad->method == IB_MAD_METHOD_SET )\r
+       {\r
+               if( cl_memcmp( ib_smp_get_payload_ptr( (ib_smp_t*)p_mad ),\r
+                       &p_spl_qp_svc->cache.pkey_tbl[idx].tbl, sizeof(ib_pkey_table_info_t) ) )\r
+               {\r
+                       /* The set is requesting a change. */\r
+                       AL_EXIT( AL_DBG_SMI );\r
+                       return IB_NOT_DONE;\r
+               }\r
+       }\r
+       \r
+       /* Get a MAD element from the pool for the response. */\r
+       status = get_resp_mad( p_spl_qp_svc, p_mad_wr, &p_mad_resp );\r
+       if( status == IB_SUCCESS )\r
+       {\r
+               p_smp = (ib_smp_t*)p_mad_resp->p_mad_buf;\r
+\r
+               /* Setup the response mad. */\r
+               cl_memcpy( p_smp, p_mad, MAD_BLOCK_SIZE );\r
+               p_smp->method = (IB_MAD_METHOD_RESP_MASK | IB_MAD_METHOD_GET);\r
+               if( p_smp->mgmt_class == IB_MCLASS_SUBN_DIR )\r
+                       p_smp->status = IB_SMP_DIRECTION;\r
+               else\r
+                       p_smp->status = 0;\r
+\r
+               p_pkey_table_info = (ib_pkey_table_info_t*)ib_smp_get_payload_ptr( p_smp );\r
+\r
+               // TODO: do we need lock on the cache ?????\r
+\r
+               \r
+               /* Copy the cached data. */\r
+               cl_memcpy( p_pkey_table_info,\r
+                       &p_spl_qp_svc->cache.pkey_tbl[idx].tbl, sizeof(ib_pkey_table_info_t) );\r
+\r
+               status = complete_local_mad( p_spl_qp_svc, p_mad_wr, p_mad_resp );\r
+       }\r
+\r
+       AL_EXIT( AL_DBG_SMI );\r
+       return status;\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+__process_slvl_table(\r
+       IN                              spl_qp_svc_t*                           p_spl_qp_svc,\r
+       IN                              al_mad_wr_t* const                      p_mad_wr )\r
+{\r
+\r
+\r
+       ib_mad_t                                *p_mad;\r
+       ib_mad_element_t                *p_mad_resp;\r
+       ib_smp_t                                *p_smp;\r
+       ib_slvl_table_t                 *p_slvl_table;\r
+       ib_api_status_t         status;\r
+\r
+       AL_ENTER( AL_DBG_SMI );\r
+\r
+       CL_ASSERT( p_spl_qp_svc );\r
+       CL_ASSERT( p_mad_wr );\r
+\r
+       /* Initialize a pointers to the MAD work request and outbound MAD. */\r
+       p_mad = get_mad_hdr_from_wr( p_mad_wr );\r
+\r
+       if( !p_spl_qp_svc->cache.sl_vl.valid )\r
+       {\r
+               AL_EXIT( AL_DBG_SMI );\r
+               return IB_NOT_DONE;\r
+       }\r
+\r
+       /*\r
+        * If a SET, see if the set is identical to the cache,\r
+        * in which case it's a no-op.\r
+        */\r
+       if( p_mad->method == IB_MAD_METHOD_SET )\r
+       {\r
+               if( cl_memcmp( ib_smp_get_payload_ptr( (ib_smp_t*)p_mad ),\r
+                       &p_spl_qp_svc->cache.sl_vl.tbl, sizeof(ib_slvl_table_t) ) )\r
+               {\r
+                       /* The set is requesting a change. */\r
+                       AL_EXIT( AL_DBG_SMI );\r
+                       return IB_NOT_DONE;\r
+               }\r
+       }\r
+       \r
+       /* Get a MAD element from the pool for the response. */\r
+       status = get_resp_mad( p_spl_qp_svc, p_mad_wr, &p_mad_resp );\r
+       if( status == IB_SUCCESS )\r
+       {\r
+               p_smp = (ib_smp_t*)p_mad_resp->p_mad_buf;\r
+\r
+               /* Setup the response mad. */\r
+               cl_memcpy( p_smp, p_mad, MAD_BLOCK_SIZE );\r
+               p_smp->method = (IB_MAD_METHOD_RESP_MASK | IB_MAD_METHOD_GET);\r
+               if( p_smp->mgmt_class == IB_MCLASS_SUBN_DIR )\r
+                       p_smp->status = IB_SMP_DIRECTION;\r
+               else\r
+                       p_smp->status = 0;\r
+\r
+               p_slvl_table = (ib_slvl_table_t*)ib_smp_get_payload_ptr( p_smp );\r
+\r
+               // TODO: do we need lock on the cache ?????\r
+\r
+               \r
+               /* Copy the cached data. */\r
+               cl_memcpy( p_slvl_table,\r
+                       &p_spl_qp_svc->cache.sl_vl.tbl, sizeof(ib_slvl_table_t) );\r
+\r
+               status = complete_local_mad( p_spl_qp_svc, p_mad_wr, p_mad_resp );\r
+       }\r
+\r
+       AL_EXIT( AL_DBG_SMI );\r
+       return status;\r
+}\r
+\r
+\r
+\r
+static ib_api_status_t\r
+__process_vl_arb_table(\r
+       IN                              spl_qp_svc_t*                           p_spl_qp_svc,\r
+       IN                              al_mad_wr_t* const                      p_mad_wr )\r
+{\r
+\r
+       ib_mad_t                                *p_mad;\r
+       ib_mad_element_t                *p_mad_resp;\r
+       ib_smp_t                                *p_smp;\r
+       ib_vl_arb_table_t               *p_vl_arb_table;\r
+       uint16_t                                idx;\r
+       ib_api_status_t         status;\r
+\r
+       AL_ENTER( AL_DBG_SMI );\r
+\r
+       CL_ASSERT( p_spl_qp_svc );\r
+       CL_ASSERT( p_mad_wr );\r
+\r
+       /* Initialize a pointers to the MAD work request and outbound MAD. */\r
+       p_mad = get_mad_hdr_from_wr( p_mad_wr );\r
+\r
+       /* Get the table selector from the attribute */\r
+       idx = ((uint16_t)(cl_ntoh32( p_mad->attr_mod ) >> 16)) - 1;\r
+       \r
+       /*\r
+        * TODO : Setup the response to fail the MAD instead of sending\r
+        * it down to the HCA.\r
+        */\r
+       if( idx > 3 )\r
+       {\r
+               AL_EXIT( AL_DBG_SMI );\r
+               return IB_NOT_DONE;\r
+       }\r
+\r
+\r
+       if( !p_spl_qp_svc->cache.vl_arb[idx].valid )\r
+       {\r
+               AL_EXIT( AL_DBG_SMI );\r
+               return IB_NOT_DONE;\r
+       }\r
+\r
+       /*\r
+        * If a SET, see if the set is identical to the cache,\r
+        * in which case it's a no-op.\r
+        */\r
+       if( p_mad->method == IB_MAD_METHOD_SET )\r
+       {\r
+               if( cl_memcmp( ib_smp_get_payload_ptr( (ib_smp_t*)p_mad ),\r
+                       &p_spl_qp_svc->cache.vl_arb[idx].tbl, sizeof(ib_vl_arb_table_t) ) )\r
+               {\r
+                       /* The set is requesting a change. */\r
+                       AL_EXIT( AL_DBG_SMI );\r
+                       return IB_NOT_DONE;\r
+               }\r
+       }\r
+       \r
+       /* Get a MAD element from the pool for the response. */\r
+       status = get_resp_mad( p_spl_qp_svc, p_mad_wr, &p_mad_resp );\r
+       if( status == IB_SUCCESS )\r
+       {\r
+               p_smp = (ib_smp_t*)p_mad_resp->p_mad_buf;\r
+\r
+               /* Setup the response mad. */\r
+               cl_memcpy( p_smp, p_mad, MAD_BLOCK_SIZE );\r
+               p_smp->method = (IB_MAD_METHOD_RESP_MASK | IB_MAD_METHOD_GET);\r
+               if( p_smp->mgmt_class == IB_MCLASS_SUBN_DIR )\r
+                       p_smp->status = IB_SMP_DIRECTION;\r
+               else\r
+                       p_smp->status = 0;\r
+\r
+               p_vl_arb_table = (ib_vl_arb_table_t*)ib_smp_get_payload_ptr( p_smp );\r
+\r
+               // TODO: do we need lock on the cache ?????\r
+\r
+               \r
+               /* Copy the cached data. */\r
+               cl_memcpy( p_vl_arb_table,\r
+                       &p_spl_qp_svc->cache.pkey_tbl[idx].tbl, sizeof(ib_vl_arb_table_t) );\r
+\r
+               status = complete_local_mad( p_spl_qp_svc, p_mad_wr, p_mad_resp );\r
+       }\r
+\r
+       AL_EXIT( AL_DBG_SMI );\r
+       return status;\r
+}\r
+\r
+\r
+\r
 \r
 /*\r
  * Process subnet administration MADs using cached data if possible.\r
  */\r
 static ib_api_status_t\r
-process_subn_mad(\r
+__process_subn_mad(\r
        IN                              spl_qp_svc_t*                           p_spl_qp_svc,\r
        IN                              al_mad_wr_t* const                      p_mad_wr )\r
 {\r
@@ -1684,21 +2134,63 @@ process_subn_mad(
        CL_ASSERT( p_smp->mgmt_class == IB_MCLASS_SUBN_DIR ||\r
                p_smp->mgmt_class == IB_MCLASS_SUBN_LID );\r
 \r
+       /* simple m-key check */\r
+       if( p_spl_qp_svc->m_key && p_smp->m_key == p_spl_qp_svc->m_key )\r
+       {\r
+               if(!p_spl_qp_svc->cache_en )\r
+               {\r
+                       p_spl_qp_svc->cache_en = TRUE;\r
+                       AL_EXIT( AL_DBG_SMI );\r
+                       return IB_NOT_DONE;\r
+               }\r
+       }\r
+       else\r
+       {\r
+               AL_PRINT(TRACE_LEVEL_WARNING, AL_DBG_SMI, ("Mkey check failed \n"));\r
+               AL_PRINT(TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("Mkey check SMP= 0x%x:%x  SVC = 0x%x:%x \n",\r
+                                                                       ((uint32_t*)&p_smp->m_key)[0],((uint32_t*)&p_smp->m_key)[1],\r
+                                                                       ((uint32_t*)&p_spl_qp_svc->m_key)[0],((uint32_t*)&p_spl_qp_svc->m_key)[1]));\r
+\r
+               p_spl_qp_svc->cache_en = FALSE;\r
+               AL_EXIT( AL_DBG_SMI );\r
+               return IB_NOT_DONE;\r
+       }\r
+\r
+       cl_spinlock_acquire(&p_spl_qp_svc->cache_lock);\r
+       \r
        switch( p_smp->attr_id )\r
        {\r
        case IB_MAD_ATTR_NODE_INFO:\r
-               status = process_node_info( p_spl_qp_svc, p_mad_wr );\r
+               status = __process_node_info( p_spl_qp_svc, p_mad_wr );\r
                break;\r
 \r
        case IB_MAD_ATTR_NODE_DESC:\r
-               status = process_node_desc( p_spl_qp_svc, p_mad_wr );\r
+               status = __process_node_desc( p_spl_qp_svc, p_mad_wr );\r
+               break;\r
+\r
+       case IB_MAD_ATTR_GUID_INFO:\r
+               status = __process_guid_info( p_spl_qp_svc, p_mad_wr );\r
                break;\r
 \r
+       case IB_MAD_ATTR_P_KEY_TABLE:\r
+               status = __process_pkey_table( p_spl_qp_svc, p_mad_wr );\r
+               break;\r
+               \r
+       case IB_MAD_ATTR_SLVL_TABLE:\r
+               status = __process_slvl_table( p_spl_qp_svc, p_mad_wr );\r
+               break;\r
+               \r
+       case IB_MAD_ATTR_VL_ARBITRATION:\r
+               status = __process_vl_arb_table( p_spl_qp_svc, p_mad_wr );\r
+               break;\r
+               \r
        default:\r
                status = IB_NOT_DONE;\r
                break;\r
        }\r
 \r
+       cl_spinlock_release(&p_spl_qp_svc->cache_lock);\r
+\r
        AL_EXIT( AL_DBG_SMI );\r
        return status;\r
 }\r
@@ -1707,7 +2199,7 @@ process_subn_mad(
 /*\r
  * Process a local MAD send work request.\r
  */\r
-ib_api_status_t\r
+static ib_api_status_t\r
 fwd_local_mad(\r
        IN                              spl_qp_svc_t*                           p_spl_qp_svc,\r
        IN                              al_mad_wr_t* const                      p_mad_wr )\r
@@ -1814,25 +2306,25 @@ fwd_local_mad(
                 */\r
                if( smp_is_set )\r
                {\r
-                       ib_port_info_t*         p_port_info = NULL;\r
+                       ib_smp_t*               p_smp_response = NULL;\r
 \r
                        switch( p_mad_response_buf->mgmt_class )\r
                        {\r
                        case IB_MCLASS_SUBN_DIR:\r
-                               if( ( p_smp->attr_id == IB_MAD_ATTR_PORT_INFO ) &&\r
-                                       ( ib_smp_get_status( p_smp ) == IB_SA_MAD_STATUS_SUCCESS ) )\r
+                               if( ib_smp_get_status( p_smp ) == IB_SA_MAD_STATUS_SUCCESS ) \r
                                {\r
-                                       p_port_info =\r
-                                               (ib_port_info_t*)ib_smp_get_payload_ptr( p_smp );\r
+                                       p_smp_response = p_smp;\r
+                                       //p_port_info =\r
+                                       //      (ib_port_info_t*)ib_smp_get_payload_ptr( p_smp );\r
                                }\r
                                break;\r
 \r
                        case IB_MCLASS_SUBN_LID:\r
-                               if( ( p_mad_response_buf->attr_id == IB_MAD_ATTR_PORT_INFO ) &&\r
-                                       ( p_mad_response_buf->status == IB_SA_MAD_STATUS_SUCCESS ) )\r
+                               if( p_mad_response_buf->status == IB_SA_MAD_STATUS_SUCCESS )\r
                                {\r
-                                       p_port_info =\r
-                                               (ib_port_info_t*)ib_smp_get_payload_ptr((ib_smp_t*)p_mad_response_buf);\r
+                                       p_smp_response = (ib_smp_t*)p_mad_response_buf;\r
+                                       //p_port_info =\r
+                                       //      (ib_port_info_t*)ib_smp_get_payload_ptr((ib_smp_t*)p_mad_response_buf);\r
                                }\r
                                break;\r
 \r
@@ -1840,21 +2332,39 @@ fwd_local_mad(
                                break;\r
                        }\r
 \r
-                       if( p_port_info )\r
-                       { \r
-                               p_spl_qp_svc->base_lid = p_port_info->base_lid;\r
-                               p_spl_qp_svc->lmc = ib_port_info_get_lmc( p_port_info );\r
-                               p_spl_qp_svc->sm_lid = p_port_info->master_sm_base_lid;\r
-                               p_spl_qp_svc->sm_sl = ib_port_info_get_sm_sl( p_port_info );\r
-\r
-                               if (p_port_info->subnet_timeout & 0x80)\r
+                       if( p_smp_response )\r
+                       {\r
+                               switch( p_smp_response->attr_id )\r
                                {\r
-                                       AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_PNP,\r
-                                               ("Client reregister event, setting sm_lid to 0.\n"));\r
-                                       ci_ca_lock_attr(p_spl_qp_svc->obj.p_ci_ca);\r
-                                       p_spl_qp_svc->obj.p_ci_ca->p_pnp_attr->\r
-                                               p_port_attr->sm_lid= 0;\r
-                                       ci_ca_unlock_attr(p_spl_qp_svc->obj.p_ci_ca);\r
+                                       case IB_MAD_ATTR_PORT_INFO:\r
+                                               {\r
+                                                       ib_port_info_t          *p_port_info =\r
+                                                               (ib_port_info_t*)ib_smp_get_payload_ptr(p_smp_response);\r
+                                                       p_spl_qp_svc->base_lid = p_port_info->base_lid;\r
+                                                       p_spl_qp_svc->lmc = ib_port_info_get_lmc( p_port_info );\r
+                                                       p_spl_qp_svc->sm_lid = p_port_info->master_sm_base_lid;\r
+                                                       p_spl_qp_svc->sm_sl = ib_port_info_get_sm_sl( p_port_info );\r
+                                                       if(p_port_info->m_key)\r
+                                                               p_spl_qp_svc->m_key = p_port_info->m_key;\r
+                                                       if (p_port_info->subnet_timeout & 0x80)\r
+                                                       {\r
+                                                               AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_PNP,\r
+                                                                       ("Client reregister event, setting sm_lid to 0.\n"));\r
+                                                               ci_ca_lock_attr(p_spl_qp_svc->obj.p_ci_ca);\r
+                                                               p_spl_qp_svc->obj.p_ci_ca->p_pnp_attr->\r
+                                                                       p_port_attr->sm_lid= 0;\r
+                                                               ci_ca_unlock_attr(p_spl_qp_svc->obj.p_ci_ca);\r
+                                                       }\r
+                                               }\r
+                                               break;\r
+                                       case IB_MAD_ATTR_P_KEY_TABLE:\r
+                                       case IB_MAD_ATTR_GUID_INFO:\r
+                                       case IB_MAD_ATTR_SLVL_TABLE:\r
+                                       case IB_MAD_ATTR_VL_ARBITRATION:\r
+                                               spl_qp_svc_update_cache( p_spl_qp_svc, p_smp_response);\r
+                                               break;\r
+                                       default :\r
+                                               break;\r
                                }\r
                        }\r
                }\r
index e9f452d..883d970 100644 (file)
@@ -66,23 +66,71 @@ typedef enum _spl_qp_svc_state
 \r
 }      spl_qp_svc_state_t;\r
 \r
+/*\r
+ * Attribute cache for port info saved to expedite local MAD processing.\r
+ * Note that the cache accounts for the worst case GID and PKEY table size\r
+ * but is allocated from paged pool, so it's nothing to worry about.\r
+ */\r
+\r
+typedef struct _guid_block\r
+{\r
+       boolean_t                               valid;\r
+       ib_guid_info_t                  tbl;\r
+\r
+}      guid_block_t;\r
+\r
+\r
+typedef struct _pkey_block\r
+{\r
+       boolean_t                               valid;\r
+       ib_pkey_table_info_t    tbl;\r
+\r
+}      pkey_block_t;\r
+\r
+typedef struct _sl_vl_cache\r
+{\r
+       boolean_t                               valid;\r
+       ib_slvl_table_t                 tbl;\r
+\r
+}      sl_vl_cache_t;\r
+\r
+typedef struct _vl_arb_block\r
+{\r
+       boolean_t                               valid;\r
+       ib_vl_arb_table_t               tbl;\r
+\r
+}      vl_arb_block_t;\r
+\r
+typedef struct _attr_cache\r
+{\r
+       guid_block_t            guid_block[32];\r
+       pkey_block_t            pkey_tbl[2048];\r
+       sl_vl_cache_t           sl_vl;\r
+       vl_arb_block_t  vl_arb[4];\r
+\r
+}      spl_qp_cache_t;\r
 \r
 \r
 /* Per port special QP service */\r
 typedef struct _spl_qp_svc\r
 {\r
-       al_obj_t                                        obj;            /* Child of spl_qp_agent_t */\r
+       al_obj_t                                                obj;            /* Child of spl_qp_agent_t */\r
        cl_map_item_t                           map_item;       /* Item on SMI/GSI list */\r
 \r
        net64_t                                         port_guid;\r
        uint8_t                                         port_num;\r
        ib_net16_t                                      base_lid;\r
        uint8_t                                         lmc;\r
-\r
+       \r
        ib_net16_t                                      sm_lid;\r
        uint8_t                                         sm_sl;\r
+       ib_net64_t                                      m_key;\r
 \r
-       al_mad_disp_handle_t            h_mad_disp;\r
+       spl_qp_cache_t                          cache;\r
+       cl_spinlock_t                                   cache_lock;\r
+       boolean_t                                       cache_en;\r
+       \r
+       al_mad_disp_handle_t                    h_mad_disp;\r
        ib_cq_handle_t                          h_send_cq;\r
        ib_cq_handle_t                          h_recv_cq;\r
        ib_qp_handle_t                          h_qp;\r