/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* #define LDEBUG 1 */ #ifdef LDEBUG #define DPRINTF printk #define printf printk #else #define DPRINTF(x...) #endif module_t *sn_modules[MODULE_MAX]; int nummodules; #define SN00_SERIAL_FUDGE 0x3b1af409d513c2 #define SN0_SERIAL_FUDGE 0x6e static void __init encode_str_serial(const char *src, char *dest) { int i; for (i = 0; i < MAX_SERIAL_NUM_SIZE; i++) { dest[i] = src[MAX_SERIAL_NUM_SIZE/2 + ((i%2) ? ((i/2 * -1) - 1) : (i/2))] + SN0_SERIAL_FUDGE; } } module_t * __init module_lookup(moduleid_t id) { int i; for (i = 0; i < nummodules; i++) if (sn_modules[i]->id == id) { DPRINTF("module_lookup: found m=0x%p\n", sn_modules[i]); return sn_modules[i]; } return NULL; } /* * module_add_node * * The first time a new module number is seen, a module structure is * inserted into the module list in order sorted by module number * and the structure is initialized. * * The node number is added to the list of nodes in the module. */ static module_t * __init module_add_node(geoid_t geoid, cnodeid_t cnodeid) { module_t *m; int i; char buffer[16]; moduleid_t moduleid; slabid_t slab_number; memset(buffer, 0, 16); moduleid = geo_module(geoid); format_module_id(buffer, moduleid, MODULE_FORMAT_BRIEF); DPRINTF("module_add_node: moduleid=%s node=%d\n", buffer, cnodeid); if ((m = module_lookup(moduleid)) == 0) { m = kmalloc(sizeof (module_t), GFP_KERNEL); ASSERT_ALWAYS(m); memset(m, 0 , sizeof(module_t)); for (slab_number = 0; slab_number <= MAX_SLABS; slab_number++) { m->nodes[slab_number] = -1; } m->id = moduleid; spin_lock_init(&m->lock); /* Insert in sorted order by module number */ for (i = nummodules; i > 0 && sn_modules[i - 1]->id > moduleid; i--) sn_modules[i] = sn_modules[i - 1]; sn_modules[i] = m; nummodules++; } /* * Save this information in the correct slab number of the node in the * module. */ slab_number = geo_slab(geoid); DPRINTF("slab number added 0x%x\n", slab_number); if (m->nodes[slab_number] != -1) { printk("module_add_node .. slab previously found\n"); return NULL; } m->nodes[slab_number] = cnodeid; m->geoid[slab_number] = geoid; return m; } static int __init module_probe_snum(module_t *m, nasid_t host_nasid, nasid_t nasid) { lboard_t *board; klmod_serial_num_t *comp; char serial_number[16]; /* * record brick serial number */ board = find_lboard_nasid((lboard_t *) KL_CONFIG_INFO(host_nasid), host_nasid, KLTYPE_SNIA); if (! board || KL_CONFIG_DUPLICATE_BOARD(board)) { return 0; } board_serial_number_get( board, serial_number ); if( serial_number[0] != '\0' ) { encode_str_serial( serial_number, m->snum.snum_str ); m->snum_valid = 1; } board = find_lboard_nasid((lboard_t *) KL_CONFIG_INFO(nasid), nasid, KLTYPE_IOBRICK_XBOW); if (! board || KL_CONFIG_DUPLICATE_BOARD(board)) return 0; comp = GET_SNUM_COMP(board); if (comp) { if (comp->snum.snum_str[0] != '\0') { memcpy(m->sys_snum, comp->snum.snum_str, MAX_SERIAL_NUM_SIZE); m->sys_snum_valid = 1; } } if (m->sys_snum_valid) return 1; else { DPRINTF("Invalid serial number for module %d, " "possible missing or invalid NIC.", m->id); return 0; } } void __init io_module_init(void) { cnodeid_t node; lboard_t *board; nasid_t nasid; int nserial; module_t *m; extern int numionodes; DPRINTF("*******module_init\n"); nserial = 0; /* * First pass just scan for compute node boards KLTYPE_SNIA. * We do not support memoryless compute nodes. */ for (node = 0; node < numnodes; node++) { nasid = cnodeid_to_nasid(node); board = find_lboard_nasid((lboard_t *) KL_CONFIG_INFO(nasid), nasid, KLTYPE_SNIA); ASSERT(board); HWGRAPH_DEBUG(__FILE__, __FUNCTION__, __LINE__, NULL, NULL, "Found Shub lboard 0x%lx nasid 0x%x cnode 0x%x \n", (unsigned long)board, (int)nasid, (int)node); m = module_add_node(board->brd_geoid, node); if (! m->snum_valid && module_probe_snum(m, nasid, nasid)) nserial++; } /* * Second scan, look for headless/memless board hosted by compute nodes. */ for (node = numnodes; node < numionodes; node++) { nasid_t nasid; char serial_number[16]; nasid = cnodeid_to_nasid(node); board = find_lboard_nasid((lboard_t *) KL_CONFIG_INFO(nasid), nasid, KLTYPE_SNIA); ASSERT(board); HWGRAPH_DEBUG(__FILE__, __FUNCTION__, __LINE__, NULL, NULL, "Found headless/memless lboard 0x%lx node %d nasid %d cnode %d\n", (unsigned long)board, node, (int)nasid, (int)node); m = module_add_node(board->brd_geoid, node); /* * Get and initialize the serial number. */ board_serial_number_get( board, serial_number ); if( serial_number[0] != '\0' ) { encode_str_serial( serial_number, m->snum.snum_str ); m->snum_valid = 1; nserial++; } } }