f4c25f72ae71b2154793018989d2193585961234
[mirror/winof/.git] / ulp / opensm / user / opensm / osm_lid_mgr.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  * Abstract:
36  *    Implementation of osm_lid_mgr_t.
37  * This file implements the LID Manager object which is responsible for
38  * assigning LIDs to all ports on the subnet.
39  *
40  * DATA STRUCTURES:
41  *  p_subn->port_lid_tbl : a vector pointing from lid to its port.
42  *  osm db guid2lid domain : a hash from guid to lid (min lid)
43  *  p_subn->port_guid_tbl : a map from guid to discovered port obj.
44  *
45  * ALGORITHM:
46  *
47  * 0. we define a function to obtain the correct port lid:
48  *    __osm_lid_mgr_get_port_lid( p_mgr, port, &min_lid ):
49  *    0.1 if the port info lid matches the guid2lid return 0
50  *    0.2 if the port info has a lid and that range is empty in
51  *        port_lid_tbl - return 0 and update the port_lid_tbl and
52  *        guid2lid
53  *    0.3 else find an empty space in port_lid_tbl,  update the
54  *    port_lid_tbl and guid2lid, return 1 - to flag a change required.
55  *
56  * 1. During initialization:
57  *   1.1 initialize the guid2lid database domain.
58  *   1.2 if reassign_lid is not set:
59  *   1.2.1 read the persistant data for the domain.
60  *   1.2.2 validate no duplicate use of lids and lids are 2^(lmc-1)
61  *
62  * 2. During SM port lid assignment:
63  *   2.1 if reassign_lids is set - make it 2^lmc
64  *   2.2 cleanup all port_lid_tbl and re-fill it according to guid2lid
65  *   2.3 call __osm_lid_mgr_get_port_lid the SM port
66  *   2.4 set the port info
67  *
68  * 3. During all other ports lid assignment:
69  *   3.1 go through all ports in the subnet.
70  *   3.1.1 call __osm_lid_mgr_get_port_min_lid
71  *   3.1.2 if a change required send the port info
72  *   3.2 if any change send the signal PENDING...
73  *
74  * 4. Store the guid2lid
75  *
76  * Environment:
77  *    Linux User Mode
78  *
79  * $Revision: 1.15 $
80  */
81
82 /*
83   Next available error code: 0x403
84 */
85
86 #if HAVE_CONFIG_H
87 #  include <config.h>
88 #endif /* HAVE_CONFIG_H */
89
90 #include <iba/ib_types.h>
91 #include <complib/cl_memory.h>
92 #include <complib/cl_qmap.h>
93 #include <complib/cl_debug.h>
94 #include <opensm/osm_lid_mgr.h>
95 #include <opensm/osm_log.h>
96 #include <opensm/osm_node.h>
97 #include <opensm/osm_helper.h>
98 #include <opensm/osm_msgdef.h>
99 #include <vendor/osm_vendor_api.h>
100 #include <opensm/osm_db_pack.h>
101 #include <stdlib.h>
102
103 /**********************************************************************
104   lid range item of qlist
105  **********************************************************************/
106 typedef struct _osm_lid_mgr_range {
107   cl_list_item_t item;
108   uint16_t min_lid;
109   uint16_t max_lid;
110 } osm_lid_mgr_range_t;
111
112 /**********************************************************************
113  **********************************************************************/
114 void
115 osm_lid_mgr_construct(
116   IN osm_lid_mgr_t* const p_mgr )
117 {
118   cl_memclr( p_mgr, sizeof(*p_mgr) );
119   cl_ptr_vector_construct( &p_mgr->used_lids );
120 }
121
122 /**********************************************************************
123  **********************************************************************/
124 void
125 osm_lid_mgr_destroy(
126   IN osm_lid_mgr_t* const p_mgr )
127 {
128   cl_list_item_t *p_item;
129
130   OSM_LOG_ENTER( p_mgr->p_log, osm_lid_mgr_destroy );
131
132   cl_ptr_vector_destroy( &p_mgr->used_lids );
133   p_item = cl_qlist_remove_head( &p_mgr->free_ranges );
134   while ( p_item != cl_qlist_end( &p_mgr->free_ranges ) )
135   {
136     cl_free((osm_lid_mgr_range_t *)p_item);
137     p_item = cl_qlist_remove_head( &p_mgr->free_ranges );
138   }
139   OSM_LOG_EXIT( p_mgr->p_log );
140 }
141
142 /**********************************************************************
143 Validate the guid to lid data by making sure that under the current
144 LMC we did not get duplicates. If we do flag them as errors and remove
145 the entry.
146 **********************************************************************/
147 void
148 __osm_lid_mgr_validate_db(
149   IN osm_lid_mgr_t* p_mgr)
150 {
151   cl_qlist_t         guids;
152   osm_db_guid_elem_t *p_item;
153   uint16_t           lid;
154   uint16_t           min_lid;
155   uint16_t           max_lid;
156   uint16_t           lmc_mask;
157   boolean_t          lids_ok;
158
159   OSM_LOG_ENTER( p_mgr->p_log, __osm_lid_mgr_validate_db );
160
161   if (p_mgr->p_subn->opt.lmc)
162     lmc_mask = ~((1 << p_mgr->p_subn->opt.lmc) - 1);
163
164   else
165     lmc_mask = 0xffff;
166
167   cl_qlist_init( &guids );
168
169   if (osm_db_guid2lid_guids( p_mgr->p_g2l, &guids ))
170   {
171     osm_log( p_mgr->p_log, OSM_LOG_ERROR,
172              "__osm_lid_mgr_validate_db: ERR 0310: "
173              "could not get guid list.\n");
174     goto Exit;
175   }
176
177   p_item = (osm_db_guid_elem_t*)cl_qlist_remove_head(&guids);
178   while ((cl_list_item_t*)p_item != cl_qlist_end(&guids))
179   {
180     if (osm_db_guid2lid_get( p_mgr->p_g2l, p_item->guid, &min_lid, &max_lid ))
181     {
182       osm_log( p_mgr->p_log, OSM_LOG_ERROR,
183                "__osm_lid_mgr_validate_db: ERR 0311: "
184                "could not get lid for guid:0x%016" PRIx64".\n",
185                p_item->guid
186                );
187     }
188     else
189     {
190       lids_ok = TRUE;
191
192       if ((min_lid > max_lid) || (min_lid == 0) || (p_item->guid == 0) ||
193           (max_lid > p_mgr->p_subn->max_unicast_lid_ho))
194       {
195         osm_log( p_mgr->p_log, OSM_LOG_ERROR,
196                  "__osm_lid_mgr_validate_db: ERR 0312: "
197                  "Illegal LID range [0x%x:0x%x] for guid:0x%016" PRIx64
198                  ".\n",
199                  min_lid, max_lid, p_item->guid
200                  );
201         lids_ok = FALSE;
202       }
203       else if ((min_lid != max_lid) && ((min_lid & lmc_mask) != min_lid))
204       {
205         /* check that if the lids define a range - that range is valid
206            for the current LMC mask */
207         osm_log( p_mgr->p_log, OSM_LOG_ERROR,
208                  "__osm_lid_mgr_validate_db: ERR 0313: " 
209                  "LID range [0x%x:0x%x] for guid:0x%016" PRIx64
210                  " is not aligned acording to mask:0x%04x.\n",
211                  min_lid, max_lid, p_item->guid, lmc_mask
212                  );
213         lids_ok = FALSE;
214       }
215       else
216       {
217         /* check if the lids were not previously assigend */
218         for (lid = min_lid; lid <= max_lid; lid++)
219         {
220           if (( cl_ptr_vector_get_size( &p_mgr->used_lids ) > lid ) &&
221               ( cl_ptr_vector_get( &p_mgr->used_lids, lid ) ) )
222           {
223             osm_log( p_mgr->p_log, OSM_LOG_ERROR,
224                      "__osm_lid_mgr_validate_db: ERR 0314: " 
225                      "0x%04x for guid:0x%016" PRIx64
226                      " was previously used.\n",
227                      lid, p_item->guid
228                      );
229             lids_ok = FALSE;
230           }
231         }
232       }
233
234       if (!lids_ok)
235       {
236         if (osm_db_guid2lid_delete( p_mgr->p_g2l, p_item->guid ))
237           osm_log( p_mgr->p_log, OSM_LOG_ERROR,
238                    "__osm_lid_mgr_validate_db: ERR 0315: " 
239                    "failed to delete entry for guid:0x%016" PRIx64
240                    " .\n",
241                    p_item->guid
242                    );
243       }
244       else
245       {
246         /* mark it was visited */
247         for (lid = min_lid; lid <= max_lid; lid++)
248           cl_ptr_vector_set( &p_mgr->used_lids, lid, (void *)1);
249       }
250     } /* got a lid */
251     p_item = (osm_db_guid_elem_t*)cl_qlist_remove_head(&guids);
252   } /* all guids */
253  Exit:
254   OSM_LOG_EXIT( p_mgr->p_log );
255 }
256
257 /**********************************************************************
258  **********************************************************************/
259 ib_api_status_t
260 osm_lid_mgr_init(
261   IN osm_lid_mgr_t* const p_mgr,
262   IN osm_req_t* const p_req,
263   IN osm_subn_t* const p_subn,
264   IN osm_db_t*  const p_db,
265   IN osm_log_t* const p_log,
266   IN cl_plock_t* const p_lock )
267 {
268   ib_api_status_t status = IB_SUCCESS;
269
270   OSM_LOG_ENTER( p_log, osm_lid_mgr_init );
271
272   CL_ASSERT( p_req );
273   CL_ASSERT( p_subn );
274   CL_ASSERT( p_lock );
275   CL_ASSERT( p_db );
276
277   osm_lid_mgr_construct( p_mgr );
278
279   p_mgr->p_log = p_log;
280   p_mgr->p_subn = p_subn;
281   p_mgr->p_db = p_db;
282   p_mgr->p_lock = p_lock;
283   p_mgr->p_req = p_req;
284
285   /* we initialize and restore the db domain of guid to lid map */
286   p_mgr->p_g2l = osm_db_domain_init(p_mgr->p_db, "guid2lid");
287   if (! p_mgr->p_g2l)
288   {
289     osm_log( p_mgr->p_log, OSM_LOG_ERROR,
290              "osm_lid_mgr_init: ERR 0316: " 
291              "Error initializing Guid-to-Lid persistant database.\n");
292     status = IB_ERROR;
293     goto Exit;
294   }
295
296   cl_ptr_vector_init( &p_mgr->used_lids, 100, 40 );
297   cl_qlist_init( &p_mgr->free_ranges );
298
299   /* we use the stored guid to lid table if not forced to re-assign */
300   if (!p_mgr->p_subn->opt.reassign_lids)
301   {
302     if (osm_db_restore(p_mgr->p_g2l))
303     {
304       osm_log( p_mgr->p_log, OSM_LOG_ERROR,
305                "osm_lid_mgr_init: ERR 0317: " 
306                "Error restoring Guid-to-Lid persistant database.\n");
307       status = IB_ERROR;
308       goto Exit;
309     }
310
311     /* we need to make sure we did not get duplicates with
312        current lmc */
313     __osm_lid_mgr_validate_db(p_mgr);
314   }
315
316 Exit:
317   OSM_LOG_EXIT( p_mgr->p_log );
318   return( status );
319 }
320
321 /**********************************************************************
322  initialize the manager for a new sweep:
323  scans the known persistent assignment and port_lid_tbl
324  re-calculate all empty ranges.
325  cleanup invalid port_lid_tbl entries
326 **********************************************************************/
327 int
328 __osm_lid_mgr_init_sweep(
329   IN osm_lid_mgr_t* const p_mgr )
330 {
331
332   cl_ptr_vector_t     *p_discovered_vec = &p_mgr->p_subn->port_lid_tbl;
333   cl_ptr_vector_t     *p_persistent_vec = &p_mgr->used_lids;
334   uint16_t             max_defined_lid;
335   uint16_t             max_persistent_lid;
336   uint16_t             max_discovered_lid;
337   uint16_t             lid, l;
338   uint16_t             disc_min_lid;
339   uint16_t             disc_max_lid;
340   uint16_t             db_min_lid;
341   uint16_t             db_max_lid;
342   int                  status = 0;
343   cl_list_item_t      *p_item;
344   boolean_t            is_free;
345   osm_lid_mgr_range_t *p_range = NULL;
346   osm_port_t          *p_port;
347   cl_qmap_t           *p_port_guid_tbl;
348   uint8_t              lmc_num_lids = (uint8_t)(1 << p_mgr->p_subn->opt.lmc);
349   
350   OSM_LOG_ENTER( p_mgr->p_log, __osm_lid_mgr_init_sweep );
351
352   /* if we came out of standby we need to discard any previous guid 2 lid
353      info we might had */
354   if ( p_mgr->p_subn->coming_out_of_standby == TRUE )
355   {
356     osm_db_clear( p_mgr->p_g2l );
357     for (lid = 0; lid < cl_ptr_vector_get_size(&p_mgr->used_lids); lid++)
358       cl_ptr_vector_set(&p_mgr->used_lids, lid, NULL);
359   }
360
361   /* we need to cleanup the empty ranges list */
362   p_item = cl_qlist_remove_head( &p_mgr->free_ranges );
363   while ( p_item != cl_qlist_end( &p_mgr->free_ranges ) )
364   {
365     cl_free( (osm_lid_mgr_range_t *)p_item );
366     p_item = cl_qlist_remove_head( &p_mgr->free_ranges );
367   }
368
369   /* first clean up the port_by_lid_tbl */
370   for (lid = 0; lid < cl_ptr_vector_get_size(p_discovered_vec); lid++)
371     cl_ptr_vector_set(p_discovered_vec, lid, NULL);
372
373   /* we if are on the first sweep and in re-assign lids mode 
374      we should ignore all the available info and simply define one 
375      hufe empty range */
376   if ((p_mgr->p_subn->first_time_master_sweep == TRUE) &&
377       (p_mgr->p_subn->opt.reassign_lids == TRUE ))
378   {
379     osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
380              "__osm_lid_mgr_init_sweep: "
381              "Skipping all lids - as we are reassigning them.\n");
382     p_range =
383       (osm_lid_mgr_range_t *)cl_malloc(sizeof(osm_lid_mgr_range_t));
384     p_range->min_lid = 1;
385     goto AfterScanningLids;
386   }
387
388   /* go over all discvered ports and mark their entries */
389   p_port_guid_tbl = &p_mgr->p_subn->port_guid_tbl;
390
391   for( p_port = (osm_port_t*)cl_qmap_head( p_port_guid_tbl );
392        p_port != (osm_port_t*)cl_qmap_end( p_port_guid_tbl );
393        p_port = (osm_port_t*)cl_qmap_next( &p_port->map_item ) )
394   {
395     osm_port_get_lid_range_ho(p_port, &disc_min_lid, &disc_max_lid);
396     for (lid = disc_min_lid; lid <= disc_max_lid; lid++)
397       cl_ptr_vector_set(p_discovered_vec, lid, p_port );
398   }
399
400   /* 
401      Our task is to find free lid ranges.
402      A lid can be used if
403      1. a persistent assignment exists
404      2. the lid is used by a discovered port that does not have a persistent 
405         assignment.
406      
407      scan through all lid values of both the persistent table and
408      discovered table. 
409      If the lid has an assigned port in the discovered table:
410      * make sure the lid matches the persistent table, or 
411      * there is no other persistent assignment for that lid.
412      * else cleanup the port_by_lid_tbl, mark this as empty range.
413      Else if the lid does not have an entry in the persistent table
414      mark it as free.
415   */
416
417   /* find the range of lids to scan */
418   max_discovered_lid = (uint16_t)cl_ptr_vector_get_size(p_discovered_vec);
419   max_persistent_lid = (uint16_t)cl_ptr_vector_get_size(p_persistent_vec);
420
421   /* but the vectors have one extra entry for lid=0 */
422   if (max_discovered_lid) max_discovered_lid--;
423   if (max_persistent_lid) max_persistent_lid--;
424
425   if (max_persistent_lid > max_discovered_lid)
426     max_defined_lid = max_persistent_lid;
427   else
428     max_defined_lid = max_discovered_lid;
429
430   for (lid = 1; lid <= max_defined_lid ; lid++)
431   {
432     is_free = TRUE;
433     /* first check to see if the lid is used by a persistent assignment */
434     if ((lid < max_persistent_lid) && cl_ptr_vector_get(p_persistent_vec, lid))
435     {
436       osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
437                "__osm_lid_mgr_init_sweep: "
438                "0x%04x is not free as its mapped by the persistent db.\n",
439                lid);
440       is_free = FALSE;
441     }
442
443     /* check the discovered port if there is one */
444     if ((lid < max_discovered_lid) &&
445         (p_port = (osm_port_t *)cl_ptr_vector_get(p_discovered_vec, lid)))
446     {
447       /* get the lid range of that port  - but we know how many lids we 
448          are about to assign to it */
449       osm_port_get_lid_range_ho(p_port, &disc_min_lid, &disc_max_lid);
450       if ( osm_node_get_type( osm_port_get_parent_node( p_port ) ) !=
451            IB_NODE_TYPE_SWITCH)
452         disc_max_lid = disc_min_lid + lmc_num_lids - 1;
453
454       /* qualify the guid of the port is not persistently mapped to 
455          another range */
456       if (!osm_db_guid2lid_get( p_mgr->p_g2l,
457                                 cl_ntoh64(osm_port_get_guid(p_port)),
458                                 &db_min_lid, &db_max_lid))
459       {
460         /* ok there is an asignment - is it the same ? */
461         if ((disc_min_lid == db_min_lid) && (disc_max_lid == db_max_lid))
462         {
463           osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
464                    "__osm_lid_mgr_init_sweep: "
465                    "[0x%04x,0x%04x] is not free as it was discovered "
466                    " and mapped by the persistent db.\n",
467                    disc_min_lid, disc_max_lid);
468           is_free = FALSE;
469         }
470         else
471         {
472           osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
473                    "__osm_lid_mgr_init_sweep: "
474                    "[0x%04x,0x%04x] is free as it was discovered"
475                    " but mapped to range: [0x%x:0x%x] by the persistent db.\n",
476                    disc_min_lid, disc_max_lid, db_min_lid, db_max_lid);
477           for (l = disc_min_lid; l <= disc_max_lid; l++)
478             cl_ptr_vector_set(p_discovered_vec, l, NULL);
479         }
480       }
481       else
482       {
483         osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
484                  "__osm_lid_mgr_init_sweep: "
485                  "0x%04x is not free as it was discovered"
486                  " and there is no persistent db entry for it.\n",
487                  lid);
488         is_free = FALSE;
489       }
490
491       /* if there is more then one lid on that port - and the discovered port
492          is going to retain its lids advance to the max lid */
493       if (is_free == FALSE)
494       {
495         lid = disc_max_lid;
496       }
497     }
498
499     if (is_free)
500     {
501       if (p_range)
502       {
503         p_range->max_lid = lid;
504       }
505       else
506       {
507         p_range =
508           (osm_lid_mgr_range_t *)cl_malloc(sizeof(osm_lid_mgr_range_t));
509         p_range->min_lid = lid;
510         p_range->max_lid = lid;
511       }
512     }
513     else
514     {
515       /* this lid is used so we need to finalize the previous free range */
516       if (p_range)
517       {
518         cl_qlist_insert_tail( &p_mgr->free_ranges, &p_range->item );
519         osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
520                  "__osm_lid_mgr_init_sweep: "
521                  "new free lid range [0x%x:0x%x]\n",
522                  p_range->min_lid, p_range->max_lid);
523         p_range = NULL;
524       }
525     }
526   }
527
528  AfterScanningLids:
529   /* after scanning all known lids we need to extend the last range 
530      to the max allowed lid */
531   if (!p_range)
532   {
533     p_range =
534       (osm_lid_mgr_range_t *)cl_malloc(sizeof(osm_lid_mgr_range_t));
535     p_range->min_lid = 1;
536   }
537   p_range->max_lid = p_mgr->p_subn->max_unicast_lid_ho - 1;
538   cl_qlist_insert_tail( &p_mgr->free_ranges, &p_range->item );
539   osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
540            "__osm_lid_mgr_init_sweep: "
541            "final free lid range [0x%x:0x%x]\n",
542            p_range->min_lid, p_range->max_lid);
543
544   OSM_LOG_EXIT( p_mgr->p_log );
545   return status;
546 }
547
548 /**********************************************************************
549  check if the given range of lids is free 
550 **********************************************************************/
551 static boolean_t
552 __osm_lid_mgr_is_range_not_persistent(
553   IN osm_lid_mgr_t* const p_mgr,
554   IN const uint16_t lid,
555   IN const uint16_t num_lids )
556 {
557   uint16_t        i;
558   cl_status_t     status;
559   osm_port_t     *p_port;
560   const uint8_t   start_lid = (uint8_t)(1 << p_mgr->p_subn->opt.lmc);
561   const cl_ptr_vector_t* const p_tbl = &p_mgr->used_lids;
562
563   if( lid < start_lid )
564     return( FALSE );
565
566   for( i = lid; i < lid + num_lids; i++ )
567   {
568     status = cl_ptr_vector_at( p_tbl, i, (void*)&p_port );
569     if( status == CL_SUCCESS )
570     {
571       if(p_port != NULL)
572         return( FALSE );
573     }
574     else
575     {
576       /*
577         We are out of range in the array.
578         Consider all further entries "free".
579       */
580       return( TRUE );
581     }
582   }
583
584   return( TRUE );
585 }
586
587 /**********************************************************************
588 find a free lid range
589 **********************************************************************/
590 static void
591 __osm_lid_mgr_find_free_lid_range(
592   IN osm_lid_mgr_t* const p_mgr,
593   IN const uint8_t num_lids,
594   OUT uint16_t* const p_min_lid,
595   OUT uint16_t* const p_max_lid )
596 {
597   uint16_t             lid;
598   cl_list_item_t      *p_item;
599   cl_list_item_t      *p_next_item;
600   osm_lid_mgr_range_t *p_range = NULL;
601   uint8_t              lmc_num_lids;
602   uint16_t             lmc_mask;
603
604
605   osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
606            "__osm_lid_mgr_find_free_lid_range: "
607            "LMC = %u, number LIDs = %u.\n",
608            p_mgr->p_subn->opt.lmc, num_lids );
609
610   lmc_num_lids = (1 << p_mgr->p_subn->opt.lmc );
611   if (p_mgr->p_subn->opt.lmc)
612     lmc_mask = ~((1 << p_mgr->p_subn->opt.lmc) - 1);
613   else
614     lmc_mask = 0xffff;
615
616   /*
617     Search the list of free lid ranges for a range which is big enough
618   */
619   p_item = cl_qlist_head( &p_mgr->free_ranges );
620   while( p_item != cl_qlist_end( &p_mgr->free_ranges ) )
621   {
622     p_next_item = cl_qlist_next( p_item );
623     p_range = (osm_lid_mgr_range_t *)p_item;
624
625     lid = p_range->min_lid;
626
627     /* if we require more then one lid we must align to LMC */
628     if (num_lids > 1)
629     {
630       if ((lid & lmc_mask) != lid)
631         lid = (lid + lmc_num_lids) & lmc_mask;
632     }
633
634     /* but we can be out of the range */
635     if (lid + num_lids - 1 <= p_range->max_lid)
636     {
637       /* ok let us use that range */
638       if (lid + num_lids - 1 == p_range->max_lid)
639       {
640         /* we consumed the entire range */
641         cl_qlist_remove_item( &p_mgr->free_ranges, p_item );
642       }
643       else
644       {
645         /* only update the available range */
646         p_range->min_lid = lid + num_lids;
647       }
648
649       *p_min_lid = lid;
650       *p_max_lid = (uint16_t)(lid + num_lids - 1);
651       return;
652     }
653     p_item = p_next_item;
654   }
655
656   /*
657     Couldn't find a free range of lids.
658   */
659   *p_min_lid = *p_max_lid = 0;
660   /* if we run out of lids - give an error and abort! */
661   osm_log( p_mgr->p_log, OSM_LOG_ERROR,
662            "__osm_lid_mgr_find_free_lid_range: ERR 0307: "
663            "OPENSM RAN OUT OF LIDS!!!\n");
664   CL_ASSERT( 0 );
665 }
666
667 /**********************************************************************
668  **********************************************************************/
669 void
670  __osm_lid_mgr_cleanup_discovered_port_lid_range(
671    IN osm_lid_mgr_t* p_mgr,
672    IN osm_port_t *p_port )
673 {
674   cl_ptr_vector_t *p_discovered_vec = &p_mgr->p_subn->port_lid_tbl;
675   uint16_t         lid, min_lid, max_lid;
676   uint16_t         max_tbl_lid = (uint16_t)(cl_ptr_vector_get_size( p_discovered_vec ));
677
678   osm_port_get_lid_range_ho(p_port, &min_lid, &max_lid);
679   for (lid = min_lid; lid <= max_lid; lid++)
680   {
681     if ((lid < max_tbl_lid ) &&
682         (p_port == (osm_port_t*)cl_ptr_vector_get(p_discovered_vec, lid)))
683       cl_ptr_vector_set(p_discovered_vec, lid, NULL );
684   }
685 }
686
687 /**********************************************************************
688  0.1 if the port info lid matches the guid2lid return 0
689  0.2 if the port info has a lid and that range is empty in
690      port_lid_tbl - return 0 and update the port_lid_tbl and
691      guid2lid
692  0.3 else find an empty space in port_lid_tbl,  update the
693  port_lid_tbl and guid2lid, return 1 - to flag a change required.
694 **********************************************************************/
695 int
696 __osm_lid_mgr_get_port_lid(
697   IN osm_lid_mgr_t* const p_mgr,
698   IN osm_port_t * const p_port,
699   OUT uint16_t* const p_min_lid,
700   OUT uint16_t* const p_max_lid)
701 {
702   uint16_t lid, min_lid, max_lid;
703   uint64_t guid;
704   uint8_t  num_lids = (1 << p_mgr->p_subn->opt.lmc);
705   int      lid_changed = 0;
706   uint16_t lmc_mask;
707
708   OSM_LOG_ENTER( p_mgr->p_log, __osm_lid_mgr_get_port_lid );
709
710   if (p_mgr->p_subn->opt.lmc)
711     lmc_mask = ~((1 << p_mgr->p_subn->opt.lmc) - 1);
712   else
713     lmc_mask = 0xffff;
714
715   /* get the lid from the guid2lid */
716   guid = cl_ntoh64( osm_port_get_guid( p_port ) );
717
718   /* if the port is a switch then we only need one lid */
719   if( osm_node_get_type( osm_port_get_parent_node( p_port ) ) ==
720       IB_NODE_TYPE_SWITCH )
721     num_lids = 1;
722
723   /* if the port matches the guid2lid */
724   if (!osm_db_guid2lid_get( p_mgr->p_g2l, guid, &min_lid, &max_lid))
725   {
726     *p_min_lid = min_lid;
727     *p_max_lid = min_lid + num_lids - 1;
728     if (min_lid == cl_ntoh16(osm_port_get_base_lid(p_port)))
729     {
730       osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
731                "__osm_lid_mgr_get_port_lid: "
732                "0x%016" PRIx64" matches its known lid:0x%04x\n",
733                guid, min_lid);
734       goto Exit;
735     }
736     else
737     {
738       osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
739                "__osm_lid_mgr_get_port_lid: "
740                "0x%016" PRIx64
741                " with lid:0x%04x does not matches its known lid:0x%04x\n",
742                guid, cl_ntoh16(osm_port_get_base_lid(p_port)), min_lid);
743       __osm_lid_mgr_cleanup_discovered_port_lid_range( p_mgr, p_port );
744       /* we still need to send the setting to the target port */
745       lid_changed = 1;
746       goto Exit;
747     }
748   }
749   else
750   {
751     osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
752              "__osm_lid_mgr_get_port_lid: "
753              "0x%016" PRIx64" has no persistent lid assigned.\n",
754              guid);
755   }
756
757   /* if the port info carries a lid it must be lmc aligned and not mapped
758      by the pesistent storage  */
759   min_lid = cl_ntoh16(osm_port_get_base_lid(p_port));
760   
761   /* we want to ignore the discovered lid if we are also on first sweep of
762      re-assign lids flow */
763   if (min_lid &&
764       ! ((p_mgr->p_subn->first_time_master_sweep == TRUE) &&
765          (p_mgr->p_subn->opt.reassign_lids == TRUE )))
766   {
767     /* make sure lid is valid */
768     if ((num_lids == 1) || ((min_lid & lmc_mask) == min_lid))
769     {
770       /* is it free */
771       if (__osm_lid_mgr_is_range_not_persistent(p_mgr, min_lid, num_lids))
772       {
773         *p_min_lid = min_lid;
774         *p_max_lid = min_lid + num_lids - 1;
775         osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
776                  "__osm_lid_mgr_get_port_lid: "
777                  "0x%016" PRIx64" lid range:[0x%x-0x%x] is free\n",
778                  guid, *p_min_lid, *p_max_lid);
779         goto NewLidSet;
780       }
781       else
782       {
783         osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
784                  "__osm_lid_mgr_get_port_lid: "
785                  "0x%016" PRIx64
786                  " existing lid range:[0x%x:0x%x] is not free.\n",
787                  guid, min_lid, min_lid + num_lids - 1);
788       }
789     }
790     else
791     {
792       osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
793                "__osm_lid_mgr_get_port_lid: "
794                "0x%016" PRIx64
795                " existing lid range:[0x%x:0x%x] is not lmc aligned.\n",
796                guid, min_lid, min_lid + num_lids - 1);
797     }
798   }
799
800   /* first cleanup the existing discovered lid range */
801   __osm_lid_mgr_cleanup_discovered_port_lid_range( p_mgr, p_port );
802
803   /* find an empty space */
804   __osm_lid_mgr_find_free_lid_range(p_mgr, num_lids, p_min_lid, p_max_lid);
805   osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
806            "__osm_lid_mgr_get_port_lid: "
807            "0x%016" PRIx64" assigned a new lid range:[0x%x-0x%x]\n",
808            guid, *p_min_lid, *p_max_lid);
809   lid_changed = 1;
810
811  NewLidSet:
812   /* update the guid2lid db and used_lids */
813   osm_db_guid2lid_set(p_mgr->p_g2l, guid, *p_min_lid, *p_max_lid);
814   for (lid = *p_min_lid; lid <= *p_max_lid; lid++)
815     cl_ptr_vector_set(&p_mgr->used_lids, lid, (void*)1);
816
817  Exit:
818   /* make sure the assigned lids are marked in port_lid_tbl */
819   for (lid = *p_min_lid; lid <= *p_max_lid; lid++)
820     cl_ptr_vector_set(&p_mgr->p_subn->port_lid_tbl, lid, p_port);
821
822   OSM_LOG_EXIT( p_mgr->p_log );
823   return lid_changed;
824 }
825
826 /**********************************************************************
827  **********************************************************************/
828 static boolean_t
829 __osm_lid_mgr_set_physp_pi(
830   IN osm_lid_mgr_t *       const p_mgr,
831   IN osm_physp_t*          const p_physp,
832   IN ib_net16_t               const lid )
833 {
834   uint8_t               payload[IB_SMP_DATA_SIZE];
835   ib_port_info_t*       p_pi = (ib_port_info_t*)payload;
836   const ib_port_info_t* p_old_pi;
837   osm_madw_context_t    context;
838   osm_node_t*           p_node;
839   ib_api_status_t       status;
840   uint8_t               mtu;
841   uint8_t               op_vls;
842   uint8_t               port_num;
843   boolean_t             send_set = FALSE;
844
845   OSM_LOG_ENTER( p_mgr->p_log, __osm_lid_mgr_set_physp_pi );
846
847   /*
848     Don't bother doing anything if this Physical Port is not valid.
849     This allows simplified code in the caller.
850   */
851   if( p_physp == NULL )
852     goto Exit;
853
854   if( !osm_physp_is_valid( p_physp ) )
855     goto Exit;
856
857   port_num = osm_physp_get_port_num( p_physp );
858   p_node = osm_physp_get_node_ptr( p_physp );
859
860   if( (osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH) &&
861       (port_num != 0) )
862   {
863     /*
864       Switches ports that are not 0 - should not be set with the
865       following attributes set later (during NO_CHANGE state in link mgr).
866     */
867     if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
868     {
869       osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
870                "__osm_lid_mgr_set_physp_pi: "
871                "Skipping switch port %u, GUID = 0x%016" PRIx64 ".\n",
872                port_num,
873                cl_ntoh64( osm_physp_get_port_guid( p_physp ) ) );
874     }
875     goto Exit;
876   }
877
878   p_old_pi = osm_physp_get_port_info_ptr( p_physp );
879
880   /*
881     First, copy existing parameters from the PortInfo attribute we
882     already have for this node.
883
884     Second, update with default values that we know must be set for
885     every Physical Port and the LID and set the neighbor MTU field
886     appropriately.
887
888     Third, send the SMP to this physical port.
889   */
890
891   cl_memclr( payload, IB_SMP_DATA_SIZE );
892
893   /* Correction by FUJITSU */
894   if( port_num != 0 )
895   {
896     cl_memcpy( payload, p_old_pi, sizeof(ib_port_info_t) );
897   }
898
899   /*
900     Correction following a bug injected by the previous
901     FUJITSU line:
902
903     Should never write back a value that is bigger then 3 in
904     the PortPhysicalState field - so can not simply copy!
905
906     Actually we want to write there:
907     port physical state - no change,
908     link down default state = polling
909     port state - no change
910   */
911   /* these values can be set only for hca ports, so if we are
912      on a switch node - set these values to zero */
913   if ( osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH )
914     p_pi->state_info2 = 0x0;
915   else
916   {
917     p_pi->state_info2 = 0x02;
918     /* Check to see if the value we are setting is different than
919        the value in the port_info. If it is - turn on send_set flag */
920     if ( ib_port_info_get_link_down_def_state(p_pi) !=
921          ib_port_info_get_link_down_def_state(p_old_pi) )
922       send_set = TRUE;
923   }
924
925   ib_port_info_set_port_state( p_pi, IB_LINK_NO_CHANGE );
926
927   p_pi->m_key = p_mgr->p_subn->opt.m_key;
928   /* Check to see if the value we are setting is different than
929      the value in the port_info. If it is - turn on send_set flag */
930   if (cl_memcmp( &p_pi->m_key, &p_old_pi->m_key, sizeof(p_pi->m_key) ))
931     send_set = TRUE;
932
933   p_pi->subnet_prefix = p_mgr->p_subn->opt.subnet_prefix;
934   /* Check to see if the value we are setting is different than
935      the value in the port_info. If it is - turn on send_set flag */
936   if (cl_memcmp( &p_pi->subnet_prefix, &p_old_pi->subnet_prefix,
937                  sizeof(p_pi->subnet_prefix) ))
938     send_set = TRUE;
939
940   p_pi->base_lid = lid;
941   /* Check to see if the value we are setting is different than
942      the value in the port_info. If it is - turn on send_set flag */
943   if (cl_memcmp( &p_pi->base_lid, &p_old_pi->base_lid,
944                  sizeof(p_pi->base_lid) ))
945     send_set = TRUE;
946
947   /* we are updating the ports with our local sm_base_lid */
948   p_pi->master_sm_base_lid = p_mgr->p_subn->sm_base_lid;
949   /* Check to see if the value we are setting is different than
950      the value in the port_info. If it is - turn on send_set flag */
951   if (cl_memcmp( &p_pi->master_sm_base_lid, &p_old_pi->master_sm_base_lid,
952                  sizeof(p_pi->master_sm_base_lid) ))
953     send_set = TRUE;
954
955   p_pi->m_key_lease_period = p_mgr->p_subn->opt.m_key_lease_period;
956   /* Check to see if the value we are setting is different than
957      the value in the port_info. If it is - turn on send_set flag */
958   if (cl_memcmp( &p_pi->m_key_lease_period, &p_old_pi->m_key_lease_period,
959                  sizeof(p_pi->m_key_lease_period) ))
960     send_set = TRUE;
961
962   /*
963     we want to set the timeout for both the switch port 0
964     and the HCA ports
965   */
966   ib_port_info_set_timeout( p_pi, p_mgr->p_subn->opt.subnet_timeout );
967   /* Check to see if the value we are setting is different than
968      the value in the port_info. If it is - turn on send_set flag */
969   if (ib_port_info_get_timeout( p_pi ) != ib_port_info_get_timeout( p_old_pi ))
970     send_set = TRUE;
971
972   if( port_num != 0 )
973   {
974     /*
975       HCA's don't have a port 0, and for switch port 0,
976       the state bits are ignored.
977       This is not the switch management port
978     */
979     p_pi->link_width_enabled = p_old_pi->link_width_supported;
980     /* Check to see if the value we are setting is different than
981        the value in the port_info. If it is - turn on send_set flag */
982     if (cl_memcmp( &p_pi->link_width_enabled, &p_old_pi->link_width_enabled,
983                    sizeof(p_pi->link_width_enabled) ))
984       send_set = TRUE;
985
986     /* M_KeyProtectBits are always zero */
987     p_pi->mkey_lmc = p_mgr->p_subn->opt.lmc;
988     /* Check to see if the value we are setting is different than
989        the value in the port_info. If it is - turn on send_set flag */
990     if (cl_memcmp( &p_pi->mkey_lmc, &p_old_pi->mkey_lmc, sizeof(p_pi->mkey_lmc) ))
991       send_set = TRUE;
992
993     /* calc new op_vls and mtu */
994     op_vls = osm_physp_calc_link_op_vls(
995       p_mgr->p_log, p_mgr->p_subn, p_physp );
996     mtu =  osm_physp_calc_link_mtu(p_mgr->p_log, p_physp );
997
998     ib_port_info_set_neighbor_mtu( p_pi, mtu );
999
1000     if ( ib_port_info_get_neighbor_mtu(p_pi) !=
1001          ib_port_info_get_neighbor_mtu(p_old_pi) )
1002       send_set = TRUE;
1003
1004     ib_port_info_set_op_vls( p_pi, op_vls );
1005     if ( ib_port_info_get_op_vls(p_pi) !=
1006          ib_port_info_get_op_vls(p_old_pi) )
1007       send_set = TRUE;
1008
1009     /*
1010       Several timeout mechanisms:
1011     */
1012     ib_port_info_set_phy_and_overrun_err_thd(
1013       p_pi,
1014       p_mgr->p_subn->opt.local_phy_errors_threshold,
1015       p_mgr->p_subn->opt.overrun_errors_threshold);
1016
1017     if (cl_memcmp( &p_pi->error_threshold, &p_old_pi->error_threshold,
1018                    sizeof(p_pi->error_threshold) ))
1019       send_set = TRUE;
1020
1021     /*
1022       TO DO -
1023       If the subnet is being reconfigured, should we force the link
1024       to the INIT state?
1025
1026       To reset the port state machine we can send PortInfo.State = DOWN.
1027       (see: 7.2.7 p161 lines:10-19.)
1028     */
1029     if ( (mtu != ib_port_info_get_mtu_cap( p_old_pi )) ||
1030          (op_vls !=  ib_port_info_get_op_vls(p_old_pi)))
1031     {
1032       if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
1033       {
1034         osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
1035                  "__osm_lid_mgr_set_physp_pi: "
1036                  "Sending Link Down due to op_vls or mtu change. MTU:%u,%u VL_CAP:%u,%u \n",
1037                  mtu, ib_port_info_get_mtu_cap( p_old_pi ),
1038                  op_vls, ib_port_info_get_op_vls(p_old_pi)
1039                  );
1040       }
1041       ib_port_info_set_port_state( p_pi, IB_LINK_DOWN );
1042       if ( ib_port_info_get_port_state(p_pi) !=
1043            ib_port_info_get_port_state(p_old_pi) )
1044         send_set = TRUE;
1045     }
1046   }
1047   else
1048   {
1049     /*
1050       For Port 0 - NeighborMTU is relevant only for Enh. SP0.
1051       In this case we'll set the MTU according to the mtu_cap
1052     */
1053     ib_port_info_set_neighbor_mtu( p_pi, ib_port_info_get_mtu_cap( p_old_pi ) );
1054     if ( ib_port_info_get_neighbor_mtu(p_pi) !=
1055          ib_port_info_get_neighbor_mtu(p_old_pi) )
1056       send_set = TRUE;
1057
1058     osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
1059              "__osm_lid_mgr_set_physp_pi: "
1060              "Updating neighbor_mtu on sw. port 0 to:%u\n",
1061              ib_port_info_get_neighbor_mtu( p_pi ) );
1062   }
1063
1064   context.pi_context.node_guid = osm_node_get_node_guid( p_node );
1065   context.pi_context.port_guid = osm_physp_get_port_guid( p_physp );
1066   context.pi_context.set_method = TRUE;
1067   context.pi_context.update_master_sm_base_lid = FALSE;
1068   context.pi_context.ignore_errors = FALSE;
1069   context.pi_context.light_sweep = FALSE;
1070
1071   /*
1072     We need to set the cli_rereg bit when we are in first_time_master_sweep for
1073     ports supporting the ClientReregistration Vol1 (v1.2) p811 14.4.11
1074   */
1075   if ( ( p_mgr->p_subn->first_time_master_sweep == TRUE ) &&
1076        ( (p_old_pi->capability_mask & IB_PORT_CAP_HAS_CLIENT_REREG) != 0 ) )
1077     ib_port_info_set_client_rereg( p_pi, 1 );
1078
1079   /* We need to send the PortInfoSet request with the new sm_lid
1080      in the following cases:
1081      1. There is a change in the values (send_set == TRUE)
1082      2. first_time_master_sweep flag on the subnet is TRUE. This means the
1083      SM just became master, and it then needs to send at PortInfoSet to
1084      every port.
1085      3. got_set_resp on the physical port is FALSE. This means we haven't seen
1086      this port before - need to send Set of PortInfo to it.
1087   */
1088   if (send_set || p_mgr->p_subn->first_time_master_sweep == TRUE ||
1089       p_physp->got_set_resp == FALSE)
1090   {
1091
1092     p_mgr->send_set_reqs = TRUE;
1093     status = osm_req_set( p_mgr->p_req,
1094                           osm_physp_get_dr_path_ptr( p_physp ),
1095                           payload,
1096                           IB_MAD_ATTR_PORT_INFO,
1097                           cl_hton32(osm_physp_get_port_num( p_physp )),
1098                           CL_DISP_MSGID_NONE,
1099                           &context );
1100   }
1101
1102  Exit:
1103   OSM_LOG_EXIT( p_mgr->p_log );
1104   return (send_set || p_mgr->p_subn->first_time_master_sweep == TRUE ||
1105           p_physp->got_set_resp == FALSE);
1106 }
1107
1108 /**********************************************************************
1109  Processes our own node
1110  Lock must already be held.
1111 **********************************************************************/
1112 static boolean_t
1113 __osm_lid_mgr_process_our_sm_node(
1114   IN osm_lid_mgr_t* const p_mgr )
1115 {
1116   osm_port_t     *p_port;
1117   uint16_t        min_lid_ho;
1118   uint16_t        max_lid_ho;
1119   osm_physp_t    *p_physp;
1120   boolean_t       res = TRUE;
1121
1122   OSM_LOG_ENTER( p_mgr->p_log, __osm_lid_mgr_process_our_sm_node );
1123
1124   /*
1125     Acquire our own port object.
1126   */
1127   p_port = (osm_port_t*)cl_qmap_get( &p_mgr->p_subn->port_guid_tbl,
1128                                      p_mgr->p_subn->sm_port_guid );
1129
1130   if( p_port == (osm_port_t*)cl_qmap_end( &p_mgr->p_subn->port_guid_tbl ) )
1131   {
1132     osm_log( p_mgr->p_log, OSM_LOG_ERROR,
1133              "__osm_lid_mgr_process_our_sm_node: ERR 0308: "
1134              "Can't acquire SM's Port object, GUID = 0x%016" PRIx64 ".\n",
1135              cl_ntoh64( p_mgr->p_subn->sm_port_guid ) );
1136     res = FALSE;
1137     goto Exit;
1138   }
1139
1140   /*
1141     Determine the LID this SM will use for its own port.
1142     Be careful.  With an LMC > 0, the bottom of the LID range becomes
1143     unusable, since port hardware will mask off least significant bits,
1144     leaving a LID of 0 (invalid).  Therefore, make sure that we always
1145     configure the SM with a LID that has non-zero bits, even after
1146     LMC masking by hardware.
1147   */
1148   __osm_lid_mgr_get_port_lid(p_mgr, p_port, &min_lid_ho, &max_lid_ho);
1149   osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
1150            "__osm_lid_mgr_process_our_sm_node: "
1151            "Current base LID is 0x%X.\n", min_lid_ho );
1152   /*
1153     Update subnet object.
1154   */
1155   p_mgr->p_subn->master_sm_base_lid = cl_hton16( min_lid_ho );
1156   p_mgr->p_subn->sm_base_lid = cl_hton16( min_lid_ho );
1157
1158   if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
1159   {
1160     osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
1161              "__osm_lid_mgr_process_our_sm_node: "
1162              "Assigning SM's port 0x%016" PRIx64
1163              "\n\t\t\t\tto LID range [0x%X,0x%X].\n",
1164              cl_ntoh64( osm_port_get_guid( p_port ) ),
1165              min_lid_ho, max_lid_ho );
1166   }
1167
1168   /*
1169     Set the PortInfo the Physical Port associated
1170     with this Port.
1171   */
1172   p_physp = osm_port_get_default_phys_ptr( p_port );
1173
1174   __osm_lid_mgr_set_physp_pi( p_mgr, p_physp, cl_hton16( min_lid_ho ) );
1175
1176  Exit:
1177   OSM_LOG_EXIT( p_mgr->p_log );
1178   return res;
1179 }
1180
1181 /**********************************************************************
1182  **********************************************************************/
1183 osm_signal_t
1184 osm_lid_mgr_process_sm(
1185   IN osm_lid_mgr_t*        const p_mgr )
1186 {
1187   osm_signal_t          signal = OSM_SIGNAL_DONE_PENDING;
1188
1189   OSM_LOG_ENTER( p_mgr->p_log, osm_lid_mgr_process_sm );
1190
1191   CL_ASSERT( p_mgr->p_subn->sm_port_guid );
1192
1193   CL_PLOCK_EXCL_ACQUIRE( p_mgr->p_lock );
1194
1195   /* initialize the port_lid_tbl and empty ranges list following the
1196      persistant db */
1197   __osm_lid_mgr_init_sweep( p_mgr );
1198
1199   if (p_mgr->p_subn->opt.pfn_ui_pre_lid_assign)
1200   {
1201     osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
1202              "osm_lid_mgr_process_sm: "
1203              "Invoking UI function pfn_ui_pre_lid_assign\n");
1204     p_mgr->p_subn->opt.pfn_ui_pre_lid_assign(
1205       p_mgr->p_subn->opt.ui_pre_lid_assign_ctx);
1206   }
1207
1208   /* Set the send_set_reqs of the p_mgr to FALSE, and
1209      we'll see if any set requests were sent. If not -
1210      can signal OSM_SIGNAL_DONE */
1211   p_mgr->send_set_reqs = FALSE;
1212   if ( __osm_lid_mgr_process_our_sm_node( p_mgr ) == FALSE )
1213     /* The initialization failed */
1214     signal = OSM_SIGNAL_DONE;
1215
1216   if ( p_mgr->send_set_reqs == FALSE )
1217     signal = OSM_SIGNAL_DONE;
1218
1219   CL_PLOCK_RELEASE( p_mgr->p_lock );
1220
1221   OSM_LOG_EXIT( p_mgr->p_log );
1222   return( signal );
1223 }
1224
1225 /**********************************************************************
1226  1 go through all ports in the subnet.
1227  1.1 call __osm_lid_mgr_get_port_min_lid
1228  1.2 if a change is required send the port info
1229  2 if any change send the signal PENDING...
1230 **********************************************************************/
1231 osm_signal_t
1232 osm_lid_mgr_process_subnet(
1233   IN osm_lid_mgr_t*        const p_mgr )
1234 {
1235   osm_signal_t    signal;
1236   cl_qmap_t      *p_port_guid_tbl;
1237   osm_port_t     *p_port;
1238   ib_net64_t      port_guid;
1239   uint16_t        min_lid_ho, max_lid_ho;
1240   osm_physp_t    *p_physp;
1241   int             lid_changed;
1242
1243   OSM_LOG_ENTER( p_mgr->p_log, osm_lid_mgr_process_subnet );
1244
1245   CL_ASSERT( p_mgr );
1246
1247   CL_PLOCK_EXCL_ACQUIRE( p_mgr->p_lock );
1248
1249   CL_ASSERT( p_mgr->p_subn->sm_port_guid );
1250
1251   /* Set the send_set_reqs of the p_mgr to FALSE, and
1252      we'll see if any set requests were sent. If not -
1253      can signal OSM_SIGNAL_DONE */
1254   p_mgr->send_set_reqs = FALSE;
1255
1256   p_port_guid_tbl = &p_mgr->p_subn->port_guid_tbl;
1257
1258   for( p_port = (osm_port_t*)cl_qmap_head( p_port_guid_tbl );
1259        p_port != (osm_port_t*)cl_qmap_end( p_port_guid_tbl );
1260        p_port = (osm_port_t*)cl_qmap_next( &p_port->map_item ) )
1261   {
1262     port_guid = osm_port_get_guid( p_port );
1263
1264     /*
1265       Our own port is a special case in that we want to
1266       assign a LID to ourselves first, since we have to
1267       advertise that LID value to the other ports.
1268
1269       For that reason, our node is treated separately and
1270       we will not add it to any of these lists.
1271     */
1272     if( port_guid == p_mgr->p_subn->sm_port_guid )
1273     {
1274       osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
1275                "osm_lid_mgr_process_subnet: "
1276                "Skipping our own port 0x%016" PRIx64 ".\n",
1277                cl_ntoh64( port_guid ) );
1278     }
1279     else
1280     {
1281       /*
1282         get the port lid range - we need to send it on first active sweep or
1283         if there was a change (the result of the __osm_lid_mgr_get_port_lid)
1284       */
1285       lid_changed =
1286         __osm_lid_mgr_get_port_lid(p_mgr, p_port, &min_lid_ho, &max_lid_ho);
1287
1288       /* we can call the function to update the port info as it known to 
1289          look for any field change and will only send an updated if required */
1290       osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
1291                "osm_lid_mgr_process_subnet: "
1292                "Assigned port 0x%016" PRIx64
1293                ", LID [0x%X,0x%X]\n", cl_ntoh64( port_guid ),
1294                min_lid_ho, max_lid_ho );
1295       
1296       p_physp = osm_port_get_default_phys_ptr( p_port );
1297       /* the proc returns the fact it sent a set port info */
1298       if (__osm_lid_mgr_set_physp_pi( p_mgr, p_physp, cl_hton16( min_lid_ho )))
1299         p_mgr->send_set_reqs = TRUE;
1300         
1301     }
1302   } /* all ports */
1303
1304   /* store the guid to lid table in persistant db */
1305   osm_db_store( p_mgr->p_g2l );
1306
1307   if ( p_mgr->send_set_reqs == FALSE )
1308     signal = OSM_SIGNAL_DONE;
1309   else
1310     signal = OSM_SIGNAL_DONE_PENDING;
1311
1312   CL_PLOCK_RELEASE( p_mgr->p_lock );
1313
1314   OSM_LOG_EXIT( p_mgr->p_log );
1315   return( signal );
1316 }