OpenSM: Clear port number in attribute modifier for P_KeyTable when not switch
[mirror/winof/.git] / ulp / opensm / user / opensm / osm_port_info_rcv.c
1 /*
2  * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
3  * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
4  * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
5  *
6  * This software is available to you under the OpenIB.org BSD license
7  * below:
8  *
9  *     Redistribution and use in source and binary forms, with or
10  *     without modification, are permitted provided that the following
11  *     conditions are met:
12  *
13  *      - Redistributions of source code must retain the above
14  *        copyright notice, this list of conditions and the following
15  *        disclaimer.
16  *
17  *      - Redistributions in binary form must reproduce the above
18  *        copyright notice, this list of conditions and the following
19  *        disclaimer in the documentation and/or other materials
20  *        provided with the distribution.
21  *
22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
26  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
27  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
28  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29  * SOFTWARE.
30  *
31  * $Id$
32  */
33
34
35 /*
36  * Abstract:
37  *    Implementation of osm_pi_rcv_t.
38  * This object represents the PortInfo Receiver object.
39  * This object is part of the opensm family of objects.
40  *
41  * Environment:
42  *    Linux User Mode
43  *
44  * $Revision: 1.8 $
45  */
46
47 #if HAVE_CONFIG_H
48 #  include <config.h>
49 #endif /* HAVE_CONFIG_H */
50
51 #include <iba/ib_types.h>
52 #include <complib/cl_memory.h>
53 #include <complib/cl_qmap.h>
54 #include <complib/cl_passivelock.h>
55 #include <complib/cl_debug.h>
56 #include <opensm/osm_port_info_rcv.h>
57 #include <opensm/osm_node_info_rcv.h>
58 #include <opensm/osm_req.h>
59 #include <opensm/osm_madw.h>
60 #include <opensm/osm_log.h>
61 #include <opensm/osm_node.h>
62 #include <opensm/osm_subnet.h>
63 #include <opensm/osm_mad_pool.h>
64 #include <opensm/osm_msgdef.h>
65 #include <opensm/osm_helper.h>
66 #include <vendor/osm_vendor_api.h>
67 #include <opensm/osm_pkey.h>
68 #include <opensm/osm_remote_sm.h>
69
70 /**********************************************************************
71  **********************************************************************/
72 static void
73 __osm_pi_rcv_set_sm(
74   IN const osm_pi_rcv_t* const p_rcv,
75   IN osm_physp_t* const p_physp )
76 {
77   osm_bind_handle_t h_bind;
78   osm_dr_path_t *p_dr_path;
79
80   OSM_LOG_ENTER( p_rcv->p_log, __osm_pi_rcv_set_sm );
81
82   if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
83   {
84     osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
85              "__osm_pi_rcv_set_sm: "
86              "Setting 'IS_SM' bit in port attributes.\n" );
87   }
88
89   p_dr_path = osm_physp_get_dr_path_ptr( p_physp );
90   h_bind = osm_dr_path_get_bind_handle( p_dr_path );
91   /*
92     The 'IS_SM' bit isn't already set, so set it.
93   */
94   osm_vendor_set_sm( h_bind, TRUE );
95
96   OSM_LOG_EXIT( p_rcv->p_log );
97 }
98
99 /**********************************************************************
100  **********************************************************************/
101 static void
102 __osm_pi_rcv_process_endport(
103   IN const osm_pi_rcv_t* const p_rcv,
104   IN osm_physp_t* const p_physp,
105   IN const ib_port_info_t* const p_pi )
106 {
107   osm_madw_context_t context;
108   ib_api_status_t    status;
109   ib_net64_t         port_guid;
110   uint8_t            rate, mtu;
111   cl_qmap_t*         p_sm_tbl;
112   osm_remote_sm_t*   p_sm;
113
114   OSM_LOG_ENTER( p_rcv->p_log, __osm_pi_rcv_process_endport );
115
116   port_guid = osm_physp_get_port_guid( p_physp );
117
118   /* HACK should we track extended port 0 too? */
119   if (osm_physp_get_port_num( p_physp ) != 0)
120   {
121     /* track the minimal endport MTU and rate */
122     mtu = ib_port_info_get_mtu_cap(p_pi);
123     if (mtu < p_rcv->p_subn->min_ca_mtu)
124     {
125       osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
126                "__osm_pi_rcv_process_endport: "
127                "Setting endport minimal MTU to:%u defined by port:0x%" 
128                PRIx64 ".\n",
129                mtu,
130                cl_ntoh64( port_guid ) );
131       p_rcv->p_subn->min_ca_mtu = mtu;
132     }
133     
134     rate = ib_port_info_compute_rate( p_pi );
135     if (rate < p_rcv->p_subn->min_ca_rate)
136     {
137       osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
138                "__osm_pi_rcv_process_endport: "
139                "Setting endport minimal rate to:%u defined by port:0x%" 
140                PRIx64 ".\n",
141                rate,
142                cl_ntoh64( port_guid ) );
143       p_rcv->p_subn->min_ca_rate = rate;
144     }
145   }
146
147   if( port_guid == p_rcv->p_subn->sm_port_guid )
148   {
149     /*
150       We received the PortInfo for our own port.
151     */
152     if( !(p_pi->capability_mask & IB_PORT_CAP_IS_SM ) )
153     {
154       /*
155         Set the IS_SM bit to indicate our port hosts an SM.
156       */
157       __osm_pi_rcv_set_sm( p_rcv, p_physp );
158     }
159   }
160   else
161   {
162     /*
163        Before querying the SM - we want to make sure we clean its state, so
164        if the querying fails we recognize that this SM is not active.
165     */
166     p_sm_tbl = &p_rcv->p_subn->sm_guid_tbl;
167     p_sm = (osm_remote_sm_t*)cl_qmap_get( p_sm_tbl, port_guid );
168     if( p_sm != (osm_remote_sm_t*)cl_qmap_end( p_sm_tbl ) )
169     {
170       /* clean it up */
171       p_sm->smi.pri_state = 0xF0 & p_sm->smi.pri_state;
172     }
173
174     if( p_pi->capability_mask & IB_PORT_CAP_IS_SM )
175     {
176       if( p_rcv->p_subn->opt.ignore_other_sm )
177       {
178         osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
179                  "__osm_pi_rcv_process_endport: "
180                  "Ignoring SM on port 0x%" PRIx64 ".\n",
181                  cl_ntoh64( port_guid ) );
182       }
183       else
184       {
185         if( osm_log_is_active( p_rcv->p_log, OSM_LOG_VERBOSE ) )
186         {
187           osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
188                    "__osm_pi_rcv_process_endport: "
189                    "Detected another SM.  Requesting SMInfo."
190                    "\n\t\t\t\tPort 0x%" PRIx64 ".\n",
191                    cl_ntoh64( port_guid ) );
192         }
193
194         /*
195           This port indicates it's an SM, and it's not our own port.
196           Acquire the SMInfo Attribute.
197         */
198         cl_memclr( &context, sizeof(context) );
199         context.smi_context.set_method = FALSE;
200         status = osm_req_get( p_rcv->p_req,
201                               osm_physp_get_dr_path_ptr( p_physp ),
202                               IB_MAD_ATTR_SM_INFO,
203                               0,
204                               CL_DISP_MSGID_NONE,
205                               &context );
206
207         if( status != IB_SUCCESS )
208         {
209           osm_log( p_rcv->p_log, OSM_LOG_ERROR,
210                    "__osm_pi_rcv_process_endport: ERR 0F05: "
211                    "Failure requesting SMInfo (%s).\n",
212                    ib_get_err_str( status ) );
213         }
214       }
215     }
216   }
217
218   OSM_LOG_EXIT( p_rcv->p_log );
219 }
220
221 /**********************************************************************
222  The plock must be held before calling this function.
223 **********************************************************************/
224 static void
225 __osm_pi_rcv_process_switch_port(
226   IN const osm_pi_rcv_t* const p_rcv,
227   IN osm_node_t* const p_node,
228   IN osm_physp_t* const p_physp,
229   IN const ib_port_info_t* const p_pi )
230 {
231   ib_api_status_t status = IB_SUCCESS;
232   osm_madw_context_t context;
233   osm_physp_t *p_remote_physp;
234   osm_node_t *p_remote_node;
235   uint8_t port_num;
236   uint8_t remote_port_num;
237   osm_dr_path_t path;
238
239   OSM_LOG_ENTER( p_rcv->p_log, __osm_pi_rcv_process_switch_port );
240
241   /*
242     Check the state of the physical port.
243     If there appears to be something on the other end of the wire,
244     then ask for NodeInfo.  Ignore the switch management port.
245   */
246   port_num = osm_physp_get_port_num( p_physp );
247   /* if in_sweep_hop_0 is TRUE, then this means the SM in on the switch,
248      and we got switchInfo of our local switch. Do not continue
249      probing through the switch. */
250   if( port_num != 0 && p_rcv->p_subn->in_sweep_hop_0 == FALSE)
251   {
252     switch( ib_port_info_get_port_state( p_pi ) )
253     {
254     case IB_LINK_DOWN:
255       p_remote_physp = osm_physp_get_remote( p_physp );
256       if( p_remote_physp && osm_physp_is_valid( p_remote_physp ) )
257       {
258         p_remote_node = osm_physp_get_node_ptr( p_remote_physp );
259         remote_port_num = osm_physp_get_port_num( p_remote_physp );
260
261         osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
262                  "__osm_pi_rcv_process_switch_port: "
263                  "Unlinking local node 0x%" PRIx64 ", port 0x%X"
264                  "\n\t\t\t\tand remote node 0x%" PRIx64
265                  ", port 0x%X.\n",
266                  cl_ntoh64( osm_node_get_node_guid( p_node ) ),
267                  port_num,
268                  cl_ntoh64( osm_node_get_node_guid( p_remote_node ) ),
269                  remote_port_num );
270
271         osm_node_unlink( p_node, (uint8_t)port_num,
272                          p_remote_node, (uint8_t)remote_port_num );
273
274       }
275       break;
276
277     case IB_LINK_INIT:
278     case IB_LINK_ARMED:
279     case IB_LINK_ACTIVE:
280       /*
281         To avoid looping forever, only probe the port if it
282         is NOT the port that responded to the SMP.
283
284         Request node info from the other end of this link:
285         1) Copy the current path from the parent node.
286         2) Extend the path to the next hop thru this port.
287         3) Request node info with the new path
288         
289       */
290       if( p_pi->local_port_num != osm_physp_get_port_num( p_physp ) )
291       {
292         path = *osm_physp_get_dr_path_ptr( p_physp );
293
294         osm_dr_path_extend( &path,
295                             osm_physp_get_port_num( p_physp ) );
296
297         context.ni_context.node_guid =
298           osm_node_get_node_guid( p_node );
299         context.ni_context.port_num =
300           osm_physp_get_port_num( p_physp );
301
302         status = osm_req_get( p_rcv->p_req,
303                               &path,
304                               IB_MAD_ATTR_NODE_INFO,
305                               0,
306                               CL_DISP_MSGID_NONE,
307                               &context );
308
309         if( status != IB_SUCCESS )
310         {
311           osm_log( p_rcv->p_log, OSM_LOG_ERROR,
312                    "__osm_pi_rcv_process_switch_port: ERR 0F02: "
313                    "Failure initiating NodeInfo request (%s).\n",
314                    ib_get_err_str(status));
315         }
316       }
317       else
318       {
319         if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
320         {
321           osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
322                    "__osm_pi_rcv_process_switch_port: "
323                    "Skipping SMP responder port 0x%X.\n",
324                    p_pi->local_port_num );
325         }
326       }
327       break;
328
329     default:
330       osm_log( p_rcv->p_log, OSM_LOG_ERROR,
331                "__osm_pi_rcv_process_switch_port: ERR 0F03: "
332                "Unknown link state = %u, port = 0x%X.\n",
333                osm_physp_get_port_state( p_physp ),
334                p_pi->local_port_num );
335       break;
336     }
337   }
338
339   /*
340     Update the PortInfo attribute.
341   */
342   osm_physp_set_port_info( p_physp, p_pi );
343
344   if (port_num == 0)
345   {
346     /* This is a management port 0 */
347                 __osm_pi_rcv_process_endport(p_rcv, p_physp, p_pi);
348   }
349
350   OSM_LOG_EXIT( p_rcv->p_log );
351 }
352
353 /**********************************************************************
354  **********************************************************************/
355 static void
356 __osm_pi_rcv_process_ca_port(
357   IN const osm_pi_rcv_t* const p_rcv,
358   IN osm_node_t* const p_node,
359   IN osm_physp_t* const p_physp,
360   IN const ib_port_info_t* const p_pi )
361 {
362   OSM_LOG_ENTER( p_rcv->p_log, __osm_pi_rcv_process_ca_port );
363
364   UNUSED_PARAM( p_node );
365
366   osm_physp_set_port_info( p_physp, p_pi );
367
368   __osm_pi_rcv_process_endport(p_rcv, p_physp, p_pi);
369
370   OSM_LOG_EXIT( p_rcv->p_log );
371 }
372
373 /**********************************************************************
374  **********************************************************************/
375 static void
376 __osm_pi_rcv_process_router_port(
377   IN const osm_pi_rcv_t* const p_rcv,
378   IN osm_node_t* const p_node,
379   IN osm_physp_t* const p_physp,
380   IN const ib_port_info_t* const p_pi )
381 {
382   OSM_LOG_ENTER( p_rcv->p_log, __osm_pi_rcv_process_router_port );
383
384   UNUSED_PARAM( p_node );
385
386   /*
387     Update the PortInfo attribute.
388   */
389   osm_physp_set_port_info( p_physp, p_pi );
390
391   OSM_LOG_EXIT( p_rcv->p_log );
392 }
393
394 /**********************************************************************
395  **********************************************************************/
396 void osm_pkey_get_tables(
397   IN osm_log_t         *p_log,
398   IN osm_req_t         *p_req,
399   IN osm_subn_t* const  p_subn,
400   IN osm_node_t* const  p_node,
401   IN osm_physp_t* const p_physp ) {
402
403   osm_madw_context_t context;
404   ib_api_status_t status;
405   osm_dr_path_t path;
406   uint8_t  port_num;
407   uint16_t block_num, max_blocks;
408   uint32_t attr_mod_ho;
409   osm_switch_t* p_switch;
410
411   OSM_LOG_ENTER( p_log, osm_physp_has_pkey );
412
413   path = *osm_physp_get_dr_path_ptr( p_physp );
414
415   context.pkey_context.node_guid =
416     osm_node_get_node_guid( p_node );
417   context.pkey_context.port_guid =
418     osm_physp_get_port_guid( p_physp );
419   context.pkey_context.set_method = FALSE;
420
421   port_num = p_physp->port_num;
422
423   if (osm_node_get_type( p_node ) != IB_NODE_TYPE_SWITCH ||
424       port_num == 0 )
425   {
426     /* The maximum blocks is defined on the node info partition cap for CA, routers and
427        switch management ports. */
428     max_blocks = (cl_ntoh16(p_node->node_info.partition_cap)+IB_NUM_PKEY_ELEMENTS_IN_BLOCK -1)
429       / IB_NUM_PKEY_ELEMENTS_IN_BLOCK ;
430   }
431   else
432   {
433     /* This is a switch, and not a management port. The maximum blocks is defined
434        in the switch info partition enforcement cap. */
435     p_switch = osm_get_switch_by_guid(p_subn, p_node->node_info.node_guid);
436
437     if (! p_switch)
438     {
439       osm_log( p_log, OSM_LOG_ERROR,
440                "osm_physp_has_pkey: ERR 4A02: "
441                "Cannot find switch by guid: %" PRIx64 "\n",
442                cl_ntoh64(p_node->node_info.node_guid) );
443       goto Exit;
444     }
445     max_blocks = (cl_ntoh16(p_switch->switch_info.enforce_cap)+IB_NUM_PKEY_ELEMENTS_IN_BLOCK -1)
446       / IB_NUM_PKEY_ELEMENTS_IN_BLOCK ;
447   }
448
449   for (block_num = 0 ; block_num < max_blocks  ; block_num++)
450   {
451     if (osm_node_get_type( p_node ) != IB_NODE_TYPE_SWITCH)
452       attr_mod_ho = block_num;
453     else
454       attr_mod_ho = block_num | (port_num << 16);
455     status = osm_req_get( p_req,
456                           &path,
457                           IB_MAD_ATTR_P_KEY_TABLE,
458                           cl_hton32(attr_mod_ho),
459                           CL_DISP_MSGID_NONE,
460                           &context );
461
462     if( status != IB_SUCCESS )
463     {
464       osm_log( p_log, OSM_LOG_ERROR,
465                "osm_physp_has_pkey: ERR 4A03: "
466                "Failure initiating PkeyTable request (%s).\n",
467                ib_get_err_str(status));
468       goto Exit;
469     }
470   }
471
472  Exit:
473   OSM_LOG_EXIT( p_log );
474 }
475
476 /**********************************************************************
477  **********************************************************************/
478 void
479 __osm_pi_rcv_get_pkey_slvl_vla_tables(
480   IN const osm_pi_rcv_t* const p_rcv,
481   IN osm_node_t* const p_node,
482   IN osm_physp_t* const p_physp )
483 {
484   OSM_LOG_ENTER( p_rcv->p_log, __osm_pi_rcv_get_pkey_slvl_vla_tables );
485
486   osm_pkey_get_tables( p_rcv->p_log, p_rcv->p_req, p_rcv->p_subn,
487                        p_node, p_physp );
488
489   OSM_LOG_EXIT( p_rcv->p_log );
490 }
491
492 /**********************************************************************
493  **********************************************************************/
494 void
495 osm_pi_rcv_construct(
496   IN osm_pi_rcv_t* const p_rcv )
497 {
498   cl_memclr( p_rcv, sizeof(*p_rcv) );
499 }
500
501 /**********************************************************************
502  **********************************************************************/
503 void
504 osm_pi_rcv_destroy(
505   IN osm_pi_rcv_t* const p_rcv )
506 {
507   OSM_LOG_ENTER( p_rcv->p_log, osm_pi_rcv_destroy );
508
509   CL_ASSERT( p_rcv );
510   OSM_LOG_EXIT( p_rcv->p_log );
511 }
512
513 /**********************************************************************
514  **********************************************************************/
515 ib_api_status_t
516 osm_pi_rcv_init(
517   IN osm_pi_rcv_t* const p_rcv,
518   IN osm_req_t* const p_req,
519   IN osm_subn_t* const p_subn,
520   IN osm_log_t* const p_log,
521   IN osm_state_mgr_t* const p_state_mgr,
522   IN cl_plock_t* const p_lock )
523 {
524   ib_api_status_t status = IB_SUCCESS;
525   OSM_LOG_ENTER( p_log, osm_pi_rcv_init );
526
527   osm_pi_rcv_construct( p_rcv );
528
529   p_rcv->p_log = p_log;
530   p_rcv->p_subn = p_subn;
531   p_rcv->p_lock = p_lock;
532   p_rcv->p_req = p_req;
533   p_rcv->p_state_mgr = p_state_mgr;
534
535   OSM_LOG_EXIT( p_log );
536   return( status );
537 }
538
539 /**********************************************************************
540  **********************************************************************/
541 void
542 osm_pi_rcv_process_set(
543   IN const osm_pi_rcv_t* const p_rcv,
544   IN osm_port_t* const p_port,
545   IN const uint8_t port_num,
546   IN osm_madw_t* const p_madw )
547 {
548   osm_physp_t *p_physp;
549   osm_node_t *p_node;
550   ib_net64_t port_guid;
551   ib_smp_t *p_smp;
552   ib_port_info_t *p_pi;
553   osm_pi_context_t *p_context;
554
555   OSM_LOG_ENTER( p_rcv->p_log, osm_pi_rcv_process_set );
556
557   p_context = osm_madw_get_pi_context_ptr( p_madw );
558
559   p_physp = osm_port_get_phys_ptr( p_port, port_num );
560   CL_ASSERT( p_physp );
561   CL_ASSERT( osm_physp_is_valid( p_physp ) );
562
563   port_guid = osm_physp_get_port_guid( p_physp );
564   p_node = osm_port_get_parent_node( p_port );
565   CL_ASSERT( p_node );
566
567   p_smp = osm_madw_get_smp_ptr( p_madw );
568   p_pi = (ib_port_info_t*)ib_smp_get_payload_ptr( p_smp );
569
570   /* check for error */
571   if (!p_context->ignore_errors && (cl_ntoh16(p_smp->status) & 0x7fff))
572   {
573     osm_log( p_rcv->p_log, OSM_LOG_ERROR,
574              "osm_pi_rcv_process_set: ERR 0F10: "
575              "Received Error Status for SetResp()\n");
576     osm_dump_port_info(
577       p_rcv->p_log,
578       osm_node_get_node_guid( p_node ),
579       port_guid,
580       port_num,
581       p_pi,
582       OSM_LOG_ERROR);
583   }
584
585   if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
586   {
587     osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
588              "osm_pi_rcv_process_set: "
589              "Received logical SetResp() for GUID = 0x%" PRIx64
590              ", port num = %u"
591              "\n\t\t\t\tfor parent node GUID = 0x%" PRIx64
592              " TID = 0x%" PRIx64 ".\n",
593              cl_ntoh64( port_guid ),
594              port_num,
595              cl_ntoh64( osm_node_get_node_guid( p_node ) ),
596              cl_ntoh64( p_smp->trans_id ) );
597   }
598
599   osm_physp_set_port_info( p_physp, p_pi );
600
601   /* We got a PortInfoSetResp - set the got_set_resp flag to TRUE */
602   p_physp->got_set_resp = TRUE;
603
604   OSM_LOG_EXIT( p_rcv->p_log );
605 }
606
607 /**********************************************************************
608  **********************************************************************/
609 void
610 osm_pi_rcv_process(
611   IN const osm_pi_rcv_t* const p_rcv,
612   IN osm_madw_t* const p_madw )
613 {
614   cl_qmap_t *p_guid_tbl;
615   ib_port_info_t *p_pi;
616   ib_smp_t *p_smp;
617   osm_port_t *p_port;
618   osm_physp_t *p_physp;
619   osm_dr_path_t *p_dr_path;
620   osm_node_t *p_node;
621   osm_pi_context_t *p_context;
622   ib_net64_t port_guid;
623   ib_net64_t node_guid;
624   uint8_t port_num;
625
626   OSM_LOG_ENTER( p_rcv->p_log, osm_pi_rcv_process );
627
628   CL_ASSERT( p_rcv );
629   CL_ASSERT( p_madw );
630
631   p_smp = osm_madw_get_smp_ptr( p_madw );
632   p_context = osm_madw_get_pi_context_ptr( p_madw );
633   p_pi = (ib_port_info_t*)ib_smp_get_payload_ptr( p_smp );
634   port_num = (uint8_t)cl_ntoh32( p_smp->attr_mod );
635
636   port_guid = p_context->port_guid;
637   node_guid = p_context->node_guid;
638
639   CL_ASSERT( p_smp->attr_id == IB_MAD_ATTR_PORT_INFO );
640
641   osm_dump_port_info(
642     p_rcv->p_log, node_guid, port_guid, port_num, p_pi, OSM_LOG_DEBUG);
643
644   /* 
645      we might get a response during a light sweep looking for a change in 
646      the status of a remote port that did not respond in earlier sweeps.
647      So if the context of the Get was light_sweep - we do not need to 
648      do anything with the response - just flag that we need a heavy sweep
649   */
650   if (p_context->light_sweep == TRUE) 
651   {
652     osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
653              "osm_pi_rcv_process: "
654              "Got light sweep response from remote port of parent node GUID = 0x%" PRIx64
655              " port = %u, Commencing heavy sweep.\n",
656              cl_ntoh64( node_guid ),
657              cl_ntoh64( port_guid ) );
658     osm_state_mgr_process( p_rcv->p_state_mgr,
659                            OSM_SIGNAL_CHANGE_DETECTED );
660     goto Exit;
661   }
662   
663   p_guid_tbl = &p_rcv->p_subn->port_guid_tbl;
664   CL_PLOCK_EXCL_ACQUIRE( p_rcv->p_lock );
665   p_port = (osm_port_t*)cl_qmap_get( p_guid_tbl, port_guid );
666
667   if( p_port == (osm_port_t*)cl_qmap_end( p_guid_tbl) )
668   {
669     CL_PLOCK_RELEASE( p_rcv->p_lock );
670     osm_log( p_rcv->p_log, OSM_LOG_ERROR,
671              "osm_pi_rcv_process: ERR 0F06: "
672              "No Port object for port with GUID = 0x%" PRIx64
673              "\n\t\t\t\tfor parent node GUID = 0x%" PRIx64
674              ", TID = 0x%" PRIx64 ".\n",
675              cl_ntoh64( port_guid ),
676              cl_ntoh64( node_guid ),
677              cl_ntoh64( p_smp->trans_id ) );
678     goto Exit;
679   }
680
681   /*
682     If we were setting the PortInfo, then receiving
683     this attribute was not part of sweeping the subent.
684     In this case, just update the PortInfo attribute.
685
686     In an unfortunate blunder, the IB spec defines the
687     return method for Set() as a GetResp().  Thus, we can't
688     use the method (what would have been SetResp()) to determine
689     our course of action.  So, we have to carry this extra
690     boolean around to determine if we were doing Get() or Set().
691   */
692   if( p_context->set_method )
693   {
694     osm_pi_rcv_process_set( p_rcv, p_port, port_num, p_madw );
695   }
696   else
697   {
698     osm_port_discovery_count_inc( p_port );
699
700     /*
701       This PortInfo arrived because we did a Get() method,
702       most likely due to a subnet sweep in progress.
703     */
704     if( osm_log_is_active( p_rcv->p_log, OSM_LOG_VERBOSE ) )
705     {
706       osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
707                "osm_pi_rcv_process: "
708                "Discovered port num %u with GUID = 0x%" PRIx64
709                " for parent node GUID = 0x%" PRIx64
710                ", TID = 0x%" PRIx64 ".\n",
711                port_num,
712                cl_ntoh64( port_guid ),
713                cl_ntoh64( node_guid ),
714                cl_ntoh64( p_smp->trans_id ) );
715     }
716
717     p_node = osm_port_get_parent_node( p_port );
718     p_physp = osm_node_get_physp_ptr( p_node, port_num );
719
720     CL_ASSERT( p_node );
721     CL_ASSERT( p_physp );
722
723     /*
724       Determine if we encountered a new Physical Port.
725       If so, initialize the new Physical Port  then
726       continue processing as normal.
727     */
728     if( !osm_physp_is_valid( p_physp ) )
729     {
730       if( osm_log_is_active( p_rcv->p_log, OSM_LOG_VERBOSE ) )
731       {
732         osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
733                  "osm_pi_rcv_process: "
734                  "Initializing port number 0x%X.\n",
735                  port_num );
736       }
737
738       osm_physp_init( p_physp,
739                       port_guid,
740                       port_num,
741                       p_node,
742                       osm_madw_get_bind_handle( p_madw ),
743                       p_smp->hop_count,
744                       p_smp->initial_path );
745
746       osm_port_add_new_physp( p_port, port_num );
747     }
748     else
749     {
750       /*
751         Update the directed route path to this port
752         in case the old path is no longer usable.
753       */
754       p_dr_path = osm_physp_get_dr_path_ptr( p_physp );
755       osm_dr_path_init( p_dr_path,
756                         osm_madw_get_bind_handle( p_madw ),
757                         p_smp->hop_count, p_smp->initial_path );
758     }
759
760     osm_dump_port_info( p_rcv->p_log,
761                         node_guid, port_guid, port_num, p_pi,
762                         OSM_LOG_DEBUG );
763
764     /*
765       Check if the update_sm_base_lid in the context is on TRUE.
766       If it is - then update the master_sm_base_lid of the variable
767       in the subnet.
768     */
769     if (p_context->update_master_sm_base_lid == TRUE)
770     {
771       osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
772                "osm_pi_rcv_process: "
773                "update_master_sm is TRUE. "
774                "Updating master_sm_base_lid to:%u\n",
775                p_pi->master_sm_base_lid );
776
777       p_rcv->p_subn->master_sm_base_lid = p_pi->master_sm_base_lid;
778     }
779
780     switch( osm_node_get_type( p_node ) )
781     {
782     case IB_NODE_TYPE_CA:
783       __osm_pi_rcv_process_ca_port( p_rcv,
784                                     p_node, p_physp, p_pi );
785       break;
786     case IB_NODE_TYPE_ROUTER:
787       __osm_pi_rcv_process_router_port( p_rcv,
788                                         p_node, p_physp, p_pi );
789       break;
790     case IB_NODE_TYPE_SWITCH:
791       __osm_pi_rcv_process_switch_port( p_rcv,
792                                         p_node, p_physp, p_pi );
793       break;
794     default:
795       osm_log( p_rcv->p_log, OSM_LOG_ERROR,
796                "osm_pi_rcv_process: ERR 0F07: "
797                "Unknown node type %u with GUID = 0x%" PRIx64 ".\n",
798                osm_node_get_type( p_node ),
799                cl_ntoh64( node_guid ) );
800       break;
801     }
802
803     /*
804       Get the tables on the physp.
805     */
806     __osm_pi_rcv_get_pkey_slvl_vla_tables( p_rcv, p_node, p_physp );
807
808   }
809
810   CL_PLOCK_RELEASE( p_rcv->p_lock );
811
812  Exit:
813   /*
814     Release the lock before jumping here!!
815   */
816   OSM_LOG_EXIT( p_rcv->p_log );
817 }