1fcf3ce44SJohn Forte /* 2fcf3ce44SJohn Forte * CDDL HEADER START 3fcf3ce44SJohn Forte * 4fcf3ce44SJohn Forte * The contents of this file are subject to the terms of the 5fcf3ce44SJohn Forte * Common Development and Distribution License (the "License"). 6fcf3ce44SJohn Forte * You may not use this file except in compliance with the License. 7fcf3ce44SJohn Forte * 8fcf3ce44SJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9fcf3ce44SJohn Forte * or http://www.opensolaris.org/os/licensing. 10fcf3ce44SJohn Forte * See the License for the specific language governing permissions 11fcf3ce44SJohn Forte * and limitations under the License. 12fcf3ce44SJohn Forte * 13fcf3ce44SJohn Forte * When distributing Covered Code, include this CDDL HEADER in each 14fcf3ce44SJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15fcf3ce44SJohn Forte * If applicable, add the following below this CDDL HEADER, with the 16fcf3ce44SJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying 17fcf3ce44SJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner] 18fcf3ce44SJohn Forte * 19fcf3ce44SJohn Forte * CDDL HEADER END 20fcf3ce44SJohn Forte */ 21fcf3ce44SJohn Forte 22fcf3ce44SJohn Forte /* 23291a2b48SSukumar Swaminathan * Copyright 2009 Emulex. All rights reserved. 24*82527734SSukumar Swaminathan * Use is subject to license terms. 25fcf3ce44SJohn Forte */ 26fcf3ce44SJohn Forte 27*82527734SSukumar Swaminathan 28291a2b48SSukumar Swaminathan #include <emlxs.h> 29fcf3ce44SJohn Forte 30fcf3ce44SJohn Forte 31fcf3ce44SJohn Forte /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */ 32fcf3ce44SJohn Forte EMLXS_MSG_DEF(EMLXS_NODE_C); 33fcf3ce44SJohn Forte 34291a2b48SSukumar Swaminathan /* Timeout == -1 will enable the offline timer */ 35*82527734SSukumar Swaminathan /* Timeout not -1 will apply the timeout */ 36fcf3ce44SJohn Forte extern void 37*82527734SSukumar Swaminathan emlxs_node_close(emlxs_port_t *port, NODELIST *ndlp, uint32_t channelno, 38291a2b48SSukumar Swaminathan int32_t timeout) 39fcf3ce44SJohn Forte { 40fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 41291a2b48SSukumar Swaminathan emlxs_config_t *cfg = &CFG; 42*82527734SSukumar Swaminathan CHANNEL *cp; 43fcf3ce44SJohn Forte NODELIST *prev; 44291a2b48SSukumar Swaminathan uint32_t offline = 0; 45fcf3ce44SJohn Forte 46*82527734SSukumar Swaminathan 47*82527734SSukumar Swaminathan /* If node is on a channel service queue, then remove it */ 48*82527734SSukumar Swaminathan mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 49fcf3ce44SJohn Forte 50fcf3ce44SJohn Forte /* Return if node destroyed */ 51fcf3ce44SJohn Forte if (!ndlp || !ndlp->nlp_active) { 52*82527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 53fcf3ce44SJohn Forte 54fcf3ce44SJohn Forte return; 55fcf3ce44SJohn Forte } 56291a2b48SSukumar Swaminathan 57291a2b48SSukumar Swaminathan /* Check offline support */ 58291a2b48SSukumar Swaminathan if (timeout == -1) { 59291a2b48SSukumar Swaminathan if (cfg[CFG_OFFLINE_TIMEOUT].current) { 60291a2b48SSukumar Swaminathan timeout = cfg[CFG_OFFLINE_TIMEOUT].current; 61291a2b48SSukumar Swaminathan offline = 1; 62291a2b48SSukumar Swaminathan } else { 63291a2b48SSukumar Swaminathan timeout = 0; 64291a2b48SSukumar Swaminathan } 65291a2b48SSukumar Swaminathan } 66291a2b48SSukumar Swaminathan 67*82527734SSukumar Swaminathan if (channelno == hba->channel_ip) { 68fcf3ce44SJohn Forte /* Clear IP XRI */ 69fcf3ce44SJohn Forte ndlp->nlp_Xri = 0; 70fcf3ce44SJohn Forte } 71291a2b48SSukumar Swaminathan 72fcf3ce44SJohn Forte /* Check if node is already closed */ 73*82527734SSukumar Swaminathan if (ndlp->nlp_flag[channelno] & NLP_CLOSED) { 74*82527734SSukumar Swaminathan if (ndlp->nlp_flag[channelno] & NLP_OFFLINE) { 75*82527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 76291a2b48SSukumar Swaminathan return; 77291a2b48SSukumar Swaminathan } 78291a2b48SSukumar Swaminathan 79291a2b48SSukumar Swaminathan if (offline) { 80*82527734SSukumar Swaminathan ndlp->nlp_tics[channelno] = hba->timer_tics + timeout; 81*82527734SSukumar Swaminathan ndlp->nlp_flag[channelno] |= NLP_OFFLINE; 82*82527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 83291a2b48SSukumar Swaminathan 84291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_closed_msg, 85*82527734SSukumar Swaminathan "node=%p did=%06x channel=%d. offline=%d set.", 86*82527734SSukumar Swaminathan ndlp, ndlp->nlp_DID, channelno, timeout); 87291a2b48SSukumar Swaminathan 88291a2b48SSukumar Swaminathan } else if (timeout) { 89*82527734SSukumar Swaminathan ndlp->nlp_tics[channelno] = hba->timer_tics + timeout; 90*82527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 91291a2b48SSukumar Swaminathan 92291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_closed_msg, 93*82527734SSukumar Swaminathan "node=%p did=%06x channel=%d. timeout=%d set.", 94*82527734SSukumar Swaminathan ndlp, ndlp->nlp_DID, channelno, timeout); 95291a2b48SSukumar Swaminathan } else { 96*82527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 97fcf3ce44SJohn Forte } 98fcf3ce44SJohn Forte 99fcf3ce44SJohn Forte return; 100fcf3ce44SJohn Forte } 101291a2b48SSukumar Swaminathan 102fcf3ce44SJohn Forte /* Set the node closed */ 103*82527734SSukumar Swaminathan ndlp->nlp_flag[channelno] |= NLP_CLOSED; 104fcf3ce44SJohn Forte 105291a2b48SSukumar Swaminathan if (offline) { 106*82527734SSukumar Swaminathan ndlp->nlp_tics[channelno] = hba->timer_tics + timeout; 107*82527734SSukumar Swaminathan ndlp->nlp_flag[channelno] |= NLP_OFFLINE; 108291a2b48SSukumar Swaminathan 109291a2b48SSukumar Swaminathan } else if (timeout) { 110*82527734SSukumar Swaminathan ndlp->nlp_tics[channelno] = hba->timer_tics + timeout; 111fcf3ce44SJohn Forte } 112fcf3ce44SJohn Forte 113*82527734SSukumar Swaminathan 114*82527734SSukumar Swaminathan /* 115*82527734SSukumar Swaminathan * ndlp->nlp_next[] and cp->nodeq list have to be updated 116*82527734SSukumar Swaminathan * simulaneously 117*82527734SSukumar Swaminathan */ 118*82527734SSukumar Swaminathan if (ndlp->nlp_next[channelno]) { 119*82527734SSukumar Swaminathan /* Remove node from channel queue */ 120*82527734SSukumar Swaminathan cp = &hba->chan[channelno]; 121fcf3ce44SJohn Forte 122fcf3ce44SJohn Forte /* If this is the only node on list */ 123*82527734SSukumar Swaminathan if (cp->nodeq.q_first == (void *)ndlp && 124*82527734SSukumar Swaminathan cp->nodeq.q_last == (void *)ndlp) { 125*82527734SSukumar Swaminathan cp->nodeq.q_last = NULL; 126*82527734SSukumar Swaminathan cp->nodeq.q_first = NULL; 127*82527734SSukumar Swaminathan cp->nodeq.q_cnt = 0; 128*82527734SSukumar Swaminathan } else if (cp->nodeq.q_first == (void *)ndlp) { 129*82527734SSukumar Swaminathan cp->nodeq.q_first = ndlp->nlp_next[channelno]; 130*82527734SSukumar Swaminathan ((NODELIST *)cp->nodeq.q_last)->nlp_next[channelno] = 131*82527734SSukumar Swaminathan cp->nodeq.q_first; 132*82527734SSukumar Swaminathan cp->nodeq.q_cnt--; 133fcf3ce44SJohn Forte } else { /* This is a little more difficult */ 134291a2b48SSukumar Swaminathan 135*82527734SSukumar Swaminathan /* Find the previous node in circular channel queue */ 136fcf3ce44SJohn Forte prev = ndlp; 137*82527734SSukumar Swaminathan while (prev->nlp_next[channelno] != ndlp) { 138*82527734SSukumar Swaminathan prev = prev->nlp_next[channelno]; 139fcf3ce44SJohn Forte } 140fcf3ce44SJohn Forte 141*82527734SSukumar Swaminathan prev->nlp_next[channelno] = ndlp->nlp_next[channelno]; 142fcf3ce44SJohn Forte 143*82527734SSukumar Swaminathan if (cp->nodeq.q_last == (void *)ndlp) { 144*82527734SSukumar Swaminathan cp->nodeq.q_last = (void *)prev; 145fcf3ce44SJohn Forte } 146*82527734SSukumar Swaminathan cp->nodeq.q_cnt--; 147fcf3ce44SJohn Forte 148fcf3ce44SJohn Forte } 149fcf3ce44SJohn Forte 150fcf3ce44SJohn Forte /* Clear node */ 151*82527734SSukumar Swaminathan ndlp->nlp_next[channelno] = NULL; 152fcf3ce44SJohn Forte } 153291a2b48SSukumar Swaminathan 154*82527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 155728bdc9bSSukumar Swaminathan 156291a2b48SSukumar Swaminathan return; 157291a2b48SSukumar Swaminathan 158*82527734SSukumar Swaminathan } /* emlxs_node_close() */ 159291a2b48SSukumar Swaminathan 160291a2b48SSukumar Swaminathan 161291a2b48SSukumar Swaminathan /* Called by emlxs_timer_check_nodes() */ 162291a2b48SSukumar Swaminathan extern void 163*82527734SSukumar Swaminathan emlxs_node_timeout(emlxs_port_t *port, NODELIST *ndlp, uint32_t channelno) 164291a2b48SSukumar Swaminathan { 165291a2b48SSukumar Swaminathan emlxs_hba_t *hba = HBA; 166291a2b48SSukumar Swaminathan 167*82527734SSukumar Swaminathan /* If node needs servicing, then add it to the channel queues */ 168*82527734SSukumar Swaminathan mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 169291a2b48SSukumar Swaminathan 170291a2b48SSukumar Swaminathan /* Return if node destroyed */ 171291a2b48SSukumar Swaminathan if (!ndlp || !ndlp->nlp_active) { 172*82527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 173291a2b48SSukumar Swaminathan return; 174291a2b48SSukumar Swaminathan } 175291a2b48SSukumar Swaminathan 176291a2b48SSukumar Swaminathan /* Open the node if not offline */ 177*82527734SSukumar Swaminathan if (!(ndlp->nlp_flag[channelno] & NLP_OFFLINE)) { 178*82527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 179291a2b48SSukumar Swaminathan 180291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_timeout_msg, 181*82527734SSukumar Swaminathan "node=%p did=%06x channel=%d Opening.", ndlp, ndlp->nlp_DID, 182*82527734SSukumar Swaminathan channelno); 183291a2b48SSukumar Swaminathan 184*82527734SSukumar Swaminathan emlxs_node_open(port, ndlp, channelno); 185291a2b48SSukumar Swaminathan return; 186728bdc9bSSukumar Swaminathan } 187fcf3ce44SJohn Forte 188291a2b48SSukumar Swaminathan /* OFFLINE TIMEOUT OCCURRED! */ 189291a2b48SSukumar Swaminathan 190291a2b48SSukumar Swaminathan /* Clear the timer */ 191*82527734SSukumar Swaminathan ndlp->nlp_tics[channelno] = 0; 192291a2b48SSukumar Swaminathan 193*82527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 194291a2b48SSukumar Swaminathan 195291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_timeout_msg, 196291a2b48SSukumar Swaminathan "node=%p did=%06x %s. Flushing.", ndlp, ndlp->nlp_DID, 197*82527734SSukumar Swaminathan channelno); 198291a2b48SSukumar Swaminathan 199*82527734SSukumar Swaminathan /* Flush tx queue for this channel */ 200*82527734SSukumar Swaminathan (void) emlxs_tx_node_flush(port, ndlp, &hba->chan[channelno], 0, 0); 201291a2b48SSukumar Swaminathan 202*82527734SSukumar Swaminathan /* Flush chip queue for this channel */ 203*82527734SSukumar Swaminathan (void) emlxs_chipq_node_flush(port, &hba->chan[channelno], ndlp, 0); 204291a2b48SSukumar Swaminathan 205fcf3ce44SJohn Forte return; 206fcf3ce44SJohn Forte 207*82527734SSukumar Swaminathan } /* emlxs_node_timeout() */ 208fcf3ce44SJohn Forte 209fcf3ce44SJohn Forte 210fcf3ce44SJohn Forte extern void 211*82527734SSukumar Swaminathan emlxs_node_open(emlxs_port_t *port, NODELIST *ndlp, uint32_t channelno) 212fcf3ce44SJohn Forte { 213fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 214*82527734SSukumar Swaminathan CHANNEL *cp; 215fcf3ce44SJohn Forte uint32_t found; 216fcf3ce44SJohn Forte NODELIST *nlp; 217fcf3ce44SJohn Forte MAILBOXQ *mbox; 218fcf3ce44SJohn Forte uint32_t i; 219*82527734SSukumar Swaminathan int rc; 220fcf3ce44SJohn Forte 221*82527734SSukumar Swaminathan /* If node needs servicing, then add it to the channel queues */ 222*82527734SSukumar Swaminathan mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 223fcf3ce44SJohn Forte 224fcf3ce44SJohn Forte /* Return if node destroyed */ 225fcf3ce44SJohn Forte if (!ndlp || !ndlp->nlp_active) { 226*82527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 227fcf3ce44SJohn Forte 228fcf3ce44SJohn Forte return; 229fcf3ce44SJohn Forte } 230291a2b48SSukumar Swaminathan 231fcf3ce44SJohn Forte /* Return if node already open */ 232*82527734SSukumar Swaminathan if (!(ndlp->nlp_flag[channelno] & NLP_CLOSED)) { 233*82527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 234fcf3ce44SJohn Forte 235fcf3ce44SJohn Forte return; 236fcf3ce44SJohn Forte } 237fcf3ce44SJohn Forte 238291a2b48SSukumar Swaminathan /* Set the node open (not closed) */ 239*82527734SSukumar Swaminathan ndlp->nlp_flag[channelno] &= ~(NLP_CLOSED|NLP_OFFLINE); 240fcf3ce44SJohn Forte 241fcf3ce44SJohn Forte /* Clear the timer */ 242*82527734SSukumar Swaminathan ndlp->nlp_tics[channelno] = 0; 243fcf3ce44SJohn Forte 244fcf3ce44SJohn Forte /* 245291a2b48SSukumar Swaminathan * If the ptx or the tx queue needs servicing and 246*82527734SSukumar Swaminathan * the node is not already on the channel queue 247fcf3ce44SJohn Forte */ 248*82527734SSukumar Swaminathan if ((ndlp->nlp_ptx[channelno].q_first || 249*82527734SSukumar Swaminathan ndlp->nlp_tx[channelno].q_first) && !ndlp->nlp_next[channelno]) { 250*82527734SSukumar Swaminathan cp = &hba->chan[channelno]; 251fcf3ce44SJohn Forte 252*82527734SSukumar Swaminathan /* If so, then add it to the channel queue */ 253*82527734SSukumar Swaminathan if (cp->nodeq.q_first) { 254*82527734SSukumar Swaminathan ((NODELIST *)cp->nodeq.q_last)->nlp_next[channelno] = 255fcf3ce44SJohn Forte (uint8_t *)ndlp; 256*82527734SSukumar Swaminathan ndlp->nlp_next[channelno] = cp->nodeq.q_first; 257fcf3ce44SJohn Forte 258291a2b48SSukumar Swaminathan /* If this is not the base node then */ 259291a2b48SSukumar Swaminathan /* add it to the tail */ 260fcf3ce44SJohn Forte if (!ndlp->nlp_base) { 261*82527734SSukumar Swaminathan cp->nodeq.q_last = (uint8_t *)ndlp; 262fcf3ce44SJohn Forte } else { /* Otherwise, add it to the head */ 263291a2b48SSukumar Swaminathan 264fcf3ce44SJohn Forte /* The command node always gets priority */ 265*82527734SSukumar Swaminathan cp->nodeq.q_first = (uint8_t *)ndlp; 266fcf3ce44SJohn Forte } 267fcf3ce44SJohn Forte 268*82527734SSukumar Swaminathan cp->nodeq.q_cnt++; 269fcf3ce44SJohn Forte } else { 270*82527734SSukumar Swaminathan cp->nodeq.q_first = (uint8_t *)ndlp; 271*82527734SSukumar Swaminathan cp->nodeq.q_last = (uint8_t *)ndlp; 272*82527734SSukumar Swaminathan ndlp->nlp_next[channelno] = ndlp; 273*82527734SSukumar Swaminathan cp->nodeq.q_cnt = 1; 274fcf3ce44SJohn Forte } 275fcf3ce44SJohn Forte } 276291a2b48SSukumar Swaminathan 277*82527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 278fcf3ce44SJohn Forte 279291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_opened_msg, 280*82527734SSukumar Swaminathan "node=%p did=%06x channel=%d", ndlp, ndlp->nlp_DID, channelno); 281728bdc9bSSukumar Swaminathan 282fcf3ce44SJohn Forte /* If link attention needs to be cleared */ 283*82527734SSukumar Swaminathan if ((hba->state == FC_LINK_UP) && (channelno == hba->channel_fcp)) { 284*82527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 285*82527734SSukumar Swaminathan /* re Think this code path. For SLI4 channel fcp == els */ 286*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 287*82527734SSukumar Swaminathan "ADD CODE to RESUME RPIs node=%p did=%06x chan=%d", 288*82527734SSukumar Swaminathan ndlp, ndlp->nlp_DID, channelno); 289*82527734SSukumar Swaminathan 290*82527734SSukumar Swaminathan goto done; 291*82527734SSukumar Swaminathan } 292fcf3ce44SJohn Forte 293fcf3ce44SJohn Forte /* Scan to see if any FCP2 devices are still closed */ 294fcf3ce44SJohn Forte found = 0; 295fcf3ce44SJohn Forte rw_enter(&port->node_rwlock, RW_READER); 296fcf3ce44SJohn Forte for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { 297fcf3ce44SJohn Forte nlp = port->node_table[i]; 298fcf3ce44SJohn Forte while (nlp != NULL) { 299fcf3ce44SJohn Forte if ((nlp->nlp_fcp_info & NLP_FCP_2_DEVICE) && 300*82527734SSukumar Swaminathan (nlp->nlp_flag[hba->channel_fcp] & 301*82527734SSukumar Swaminathan NLP_CLOSED)) { 302fcf3ce44SJohn Forte found = 1; 303fcf3ce44SJohn Forte break; 304291a2b48SSukumar Swaminathan 305fcf3ce44SJohn Forte } 306fcf3ce44SJohn Forte nlp = nlp->nlp_list_next; 307fcf3ce44SJohn Forte } 308fcf3ce44SJohn Forte 309fcf3ce44SJohn Forte if (found) { 310fcf3ce44SJohn Forte break; 311fcf3ce44SJohn Forte } 312fcf3ce44SJohn Forte } 313fcf3ce44SJohn Forte 314fcf3ce44SJohn Forte rw_exit(&port->node_rwlock); 315fcf3ce44SJohn Forte 316fcf3ce44SJohn Forte if (!found) { 317fcf3ce44SJohn Forte /* Clear link attention */ 318291a2b48SSukumar Swaminathan if ((mbox = (MAILBOXQ *)emlxs_mem_get(hba, 319*82527734SSukumar Swaminathan MEM_MBOX, 1))) { 320fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 321fcf3ce44SJohn Forte 322fcf3ce44SJohn Forte /* 323291a2b48SSukumar Swaminathan * If state is not FC_LINK_UP, then either the 324291a2b48SSukumar Swaminathan * link has gone down or a FC_CLEAR_LA has 325291a2b48SSukumar Swaminathan * already been issued 326fcf3ce44SJohn Forte */ 327fcf3ce44SJohn Forte if (hba->state != FC_LINK_UP) { 328fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 329fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_MBOX, 330fcf3ce44SJohn Forte (uint8_t *)mbox); 331fcf3ce44SJohn Forte goto done; 332fcf3ce44SJohn Forte } 333291a2b48SSukumar Swaminathan 334*82527734SSukumar Swaminathan EMLXS_STATE_CHANGE_LOCKED(hba, FC_CLEAR_LA); 335fcf3ce44SJohn Forte hba->discovery_timer = 0; 336fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 337fcf3ce44SJohn Forte 338*82527734SSukumar Swaminathan emlxs_mb_clear_la(hba, mbox); 339fcf3ce44SJohn Forte 340*82527734SSukumar Swaminathan rc = EMLXS_SLI_ISSUE_MBOX_CMD(hba, 341*82527734SSukumar Swaminathan mbox, MBX_NOWAIT, 0); 342*82527734SSukumar Swaminathan if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) { 343fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_MBOX, 344fcf3ce44SJohn Forte (uint8_t *)mbox); 345fcf3ce44SJohn Forte } 346fcf3ce44SJohn Forte } else { 347291a2b48SSukumar Swaminathan /* Close the node and try again */ 348291a2b48SSukumar Swaminathan /* in a few seconds */ 349*82527734SSukumar Swaminathan emlxs_node_close(port, ndlp, channelno, 5); 350fcf3ce44SJohn Forte return; 351fcf3ce44SJohn Forte } 352fcf3ce44SJohn Forte } 353fcf3ce44SJohn Forte } 354291a2b48SSukumar Swaminathan 355fcf3ce44SJohn Forte done: 356fcf3ce44SJohn Forte 357fcf3ce44SJohn Forte /* Wake any sleeping threads */ 358fcf3ce44SJohn Forte mutex_enter(&EMLXS_PKT_LOCK); 359fcf3ce44SJohn Forte cv_broadcast(&EMLXS_PKT_CV); 360fcf3ce44SJohn Forte mutex_exit(&EMLXS_PKT_LOCK); 361fcf3ce44SJohn Forte 362fcf3ce44SJohn Forte return; 363fcf3ce44SJohn Forte 364*82527734SSukumar Swaminathan } /* emlxs_node_open() */ 365fcf3ce44SJohn Forte 366fcf3ce44SJohn Forte 367fcf3ce44SJohn Forte static int 368fcf3ce44SJohn Forte emlxs_node_match_did(emlxs_port_t *port, NODELIST *ndlp, uint32_t did) 369fcf3ce44SJohn Forte { 370fcf3ce44SJohn Forte D_ID mydid; 371fcf3ce44SJohn Forte D_ID odid; 372fcf3ce44SJohn Forte D_ID ndid; 373fcf3ce44SJohn Forte 374291a2b48SSukumar Swaminathan if (ndlp->nlp_DID == did) 375fcf3ce44SJohn Forte return (1); 376fcf3ce44SJohn Forte 377fcf3ce44SJohn Forte /* 378fcf3ce44SJohn Forte * Next check for area/domain == 0 match 379fcf3ce44SJohn Forte */ 380fcf3ce44SJohn Forte mydid.un.word = port->did; 381fcf3ce44SJohn Forte if ((mydid.un.b.domain == 0) && (mydid.un.b.area == 0)) { 382fcf3ce44SJohn Forte goto out; 383fcf3ce44SJohn Forte } 384291a2b48SSukumar Swaminathan 385fcf3ce44SJohn Forte ndid.un.word = did; 386fcf3ce44SJohn Forte odid.un.word = ndlp->nlp_DID; 387fcf3ce44SJohn Forte if (ndid.un.b.id == odid.un.b.id) { 388fcf3ce44SJohn Forte if ((mydid.un.b.domain == ndid.un.b.domain) && 389fcf3ce44SJohn Forte (mydid.un.b.area == ndid.un.b.area)) { 390fcf3ce44SJohn Forte ndid.un.word = ndlp->nlp_DID; 391fcf3ce44SJohn Forte odid.un.word = did; 392291a2b48SSukumar Swaminathan if ((ndid.un.b.domain == 0) && (ndid.un.b.area == 0)) { 393fcf3ce44SJohn Forte return (1); 394fcf3ce44SJohn Forte } 395fcf3ce44SJohn Forte goto out; 396fcf3ce44SJohn Forte } 397291a2b48SSukumar Swaminathan 398fcf3ce44SJohn Forte ndid.un.word = ndlp->nlp_DID; 399fcf3ce44SJohn Forte if ((mydid.un.b.domain == ndid.un.b.domain) && 400fcf3ce44SJohn Forte (mydid.un.b.area == ndid.un.b.area)) { 401fcf3ce44SJohn Forte odid.un.word = ndlp->nlp_DID; 402fcf3ce44SJohn Forte ndid.un.word = did; 403291a2b48SSukumar Swaminathan if ((ndid.un.b.domain == 0) && (ndid.un.b.area == 0)) { 404fcf3ce44SJohn Forte return (1); 405fcf3ce44SJohn Forte } 406fcf3ce44SJohn Forte } 407fcf3ce44SJohn Forte } 408291a2b48SSukumar Swaminathan 409fcf3ce44SJohn Forte out: 410fcf3ce44SJohn Forte 411fcf3ce44SJohn Forte return (0); 412fcf3ce44SJohn Forte 413*82527734SSukumar Swaminathan } /* End emlxs_node_match_did */ 414fcf3ce44SJohn Forte 415fcf3ce44SJohn Forte 416fcf3ce44SJohn Forte 417fcf3ce44SJohn Forte extern NODELIST * 418fcf3ce44SJohn Forte emlxs_node_find_mac(emlxs_port_t *port, uint8_t *mac) 419fcf3ce44SJohn Forte { 420fcf3ce44SJohn Forte NODELIST *nlp; 421fcf3ce44SJohn Forte uint32_t i; 422fcf3ce44SJohn Forte 423fcf3ce44SJohn Forte rw_enter(&port->node_rwlock, RW_READER); 424fcf3ce44SJohn Forte for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { 425fcf3ce44SJohn Forte nlp = port->node_table[i]; 426fcf3ce44SJohn Forte while (nlp != NULL) { 427fcf3ce44SJohn Forte /* 428291a2b48SSukumar Swaminathan * If portname matches mac address, 429291a2b48SSukumar Swaminathan * return NODELIST entry 430fcf3ce44SJohn Forte */ 431fcf3ce44SJohn Forte if ((nlp->nlp_portname.IEEE[0] == mac[0])) { 432*82527734SSukumar Swaminathan if ((nlp->nlp_DID != BCAST_DID) && 433*82527734SSukumar Swaminathan ((nlp->nlp_DID & FABRIC_DID_MASK) == 434*82527734SSukumar Swaminathan FABRIC_DID_MASK)) { 435291a2b48SSukumar Swaminathan nlp = (NODELIST *)nlp->nlp_list_next; 436fcf3ce44SJohn Forte continue; 437fcf3ce44SJohn Forte } 438291a2b48SSukumar Swaminathan 439fcf3ce44SJohn Forte if ((nlp->nlp_portname.IEEE[1] == mac[1]) && 440fcf3ce44SJohn Forte (nlp->nlp_portname.IEEE[2] == mac[2]) && 441fcf3ce44SJohn Forte (nlp->nlp_portname.IEEE[3] == mac[3]) && 442fcf3ce44SJohn Forte (nlp->nlp_portname.IEEE[4] == mac[4]) && 443fcf3ce44SJohn Forte (nlp->nlp_portname.IEEE[5] == mac[5])) { 444fcf3ce44SJohn Forte rw_exit(&port->node_rwlock); 445fcf3ce44SJohn Forte return (nlp); 446fcf3ce44SJohn Forte } 447291a2b48SSukumar Swaminathan 448fcf3ce44SJohn Forte } 449291a2b48SSukumar Swaminathan 450291a2b48SSukumar Swaminathan nlp = (NODELIST *)nlp->nlp_list_next; 451fcf3ce44SJohn Forte } 452fcf3ce44SJohn Forte } 453fcf3ce44SJohn Forte rw_exit(&port->node_rwlock); 454fcf3ce44SJohn Forte 455fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_not_found_msg, 456291a2b48SSukumar Swaminathan "find: MAC=%02x%02x%02x%02x%02x%02x", mac[0], mac[1], mac[2], 457291a2b48SSukumar Swaminathan mac[3], mac[4], mac[5]); 458fcf3ce44SJohn Forte 459fcf3ce44SJohn Forte return (NULL); 460fcf3ce44SJohn Forte 461*82527734SSukumar Swaminathan } /* emlxs_node_find_mac() */ 462fcf3ce44SJohn Forte 463fcf3ce44SJohn Forte 464fcf3ce44SJohn Forte extern NODELIST * 465fcf3ce44SJohn Forte emlxs_node_find_did(emlxs_port_t *port, uint32_t did) 466fcf3ce44SJohn Forte { 467fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 468fcf3ce44SJohn Forte NODELIST *nlp; 469fcf3ce44SJohn Forte uint32_t hash; 470fcf3ce44SJohn Forte 471fcf3ce44SJohn Forte /* Check for invalid node ids */ 472291a2b48SSukumar Swaminathan if ((did == 0) && (!(hba->flag & FC_LOOPBACK_MODE))) { 473291a2b48SSukumar Swaminathan return ((NODELIST *)0); 474291a2b48SSukumar Swaminathan } 475291a2b48SSukumar Swaminathan 476291a2b48SSukumar Swaminathan if (did & 0xff000000) { 477291a2b48SSukumar Swaminathan return ((NODELIST *)0); 478fcf3ce44SJohn Forte } 479291a2b48SSukumar Swaminathan 480fcf3ce44SJohn Forte /* Check for bcast node */ 481*82527734SSukumar Swaminathan if (did == BCAST_DID) { 482fcf3ce44SJohn Forte /* Use the base node here */ 483fcf3ce44SJohn Forte return (&port->node_base); 484fcf3ce44SJohn Forte } 485fcf3ce44SJohn Forte #ifdef MENLO_SUPPORT 486fcf3ce44SJohn Forte /* Check for menlo node */ 487fcf3ce44SJohn Forte if (did == EMLXS_MENLO_DID) { 488fcf3ce44SJohn Forte /* Use the base node here */ 489fcf3ce44SJohn Forte return (&port->node_base); 490fcf3ce44SJohn Forte } 491291a2b48SSukumar Swaminathan #endif /* MENLO_SUPPORT */ 492fcf3ce44SJohn Forte 493fcf3ce44SJohn Forte /* Check for host node */ 494fcf3ce44SJohn Forte if (did == port->did && !(hba->flag & FC_LOOPBACK_MODE)) { 495fcf3ce44SJohn Forte /* Use the base node here */ 496fcf3ce44SJohn Forte return (&port->node_base); 497fcf3ce44SJohn Forte } 498291a2b48SSukumar Swaminathan 499fcf3ce44SJohn Forte /* 500*82527734SSukumar Swaminathan * Convert well known fabric addresses to the FABRIC_DID, 501291a2b48SSukumar Swaminathan * since we don't login to some of them 502fcf3ce44SJohn Forte */ 503fcf3ce44SJohn Forte if ((did == SCR_DID)) { 504*82527734SSukumar Swaminathan did = FABRIC_DID; 505fcf3ce44SJohn Forte } 506291a2b48SSukumar Swaminathan 507fcf3ce44SJohn Forte rw_enter(&port->node_rwlock, RW_READER); 508fcf3ce44SJohn Forte hash = EMLXS_DID_HASH(did); 509fcf3ce44SJohn Forte nlp = port->node_table[hash]; 510fcf3ce44SJohn Forte while (nlp != NULL) { 511fcf3ce44SJohn Forte /* Check for obvious match */ 512fcf3ce44SJohn Forte if (nlp->nlp_DID == did) { 513fcf3ce44SJohn Forte rw_exit(&port->node_rwlock); 514fcf3ce44SJohn Forte return (nlp); 515fcf3ce44SJohn Forte } 516291a2b48SSukumar Swaminathan 517fcf3ce44SJohn Forte /* Check for detailed match */ 518fcf3ce44SJohn Forte else if (emlxs_node_match_did(port, nlp, did)) { 519fcf3ce44SJohn Forte rw_exit(&port->node_rwlock); 520fcf3ce44SJohn Forte return (nlp); 521fcf3ce44SJohn Forte } 522291a2b48SSukumar Swaminathan 523291a2b48SSukumar Swaminathan nlp = (NODELIST *)nlp->nlp_list_next; 524fcf3ce44SJohn Forte } 525fcf3ce44SJohn Forte rw_exit(&port->node_rwlock); 526fcf3ce44SJohn Forte 527291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_not_found_msg, "find: did=%x", 528291a2b48SSukumar Swaminathan did); 529fcf3ce44SJohn Forte 530fcf3ce44SJohn Forte /* no match found */ 531291a2b48SSukumar Swaminathan return ((NODELIST *)0); 532fcf3ce44SJohn Forte 533*82527734SSukumar Swaminathan } /* emlxs_node_find_did() */ 534fcf3ce44SJohn Forte 535fcf3ce44SJohn Forte 536fcf3ce44SJohn Forte extern NODELIST * 537fcf3ce44SJohn Forte emlxs_node_find_rpi(emlxs_port_t *port, uint32_t rpi) 538fcf3ce44SJohn Forte { 539fcf3ce44SJohn Forte NODELIST *nlp; 540fcf3ce44SJohn Forte uint32_t i; 541fcf3ce44SJohn Forte 542fcf3ce44SJohn Forte rw_enter(&port->node_rwlock, RW_READER); 543fcf3ce44SJohn Forte for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { 544fcf3ce44SJohn Forte nlp = port->node_table[i]; 545fcf3ce44SJohn Forte while (nlp != NULL) { 546fcf3ce44SJohn Forte if (nlp->nlp_Rpi == rpi) { 547fcf3ce44SJohn Forte rw_exit(&port->node_rwlock); 548fcf3ce44SJohn Forte return (nlp); 549fcf3ce44SJohn Forte } 550291a2b48SSukumar Swaminathan 551291a2b48SSukumar Swaminathan nlp = (NODELIST *)nlp->nlp_list_next; 552fcf3ce44SJohn Forte } 553fcf3ce44SJohn Forte } 554fcf3ce44SJohn Forte rw_exit(&port->node_rwlock); 555fcf3ce44SJohn Forte 556291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_not_found_msg, "find: rpi=%x", 557291a2b48SSukumar Swaminathan rpi); 558fcf3ce44SJohn Forte 559fcf3ce44SJohn Forte /* no match found */ 560291a2b48SSukumar Swaminathan return ((NODELIST *)0); 561fcf3ce44SJohn Forte 562*82527734SSukumar Swaminathan } /* emlxs_node_find_rpi() */ 563fcf3ce44SJohn Forte 564fcf3ce44SJohn Forte 565fcf3ce44SJohn Forte extern NODELIST * 566fcf3ce44SJohn Forte emlxs_node_find_wwpn(emlxs_port_t *port, uint8_t *wwpn) 567fcf3ce44SJohn Forte { 568fcf3ce44SJohn Forte NODELIST *nlp; 569fcf3ce44SJohn Forte uint32_t i; 570fcf3ce44SJohn Forte uint32_t j; 571fcf3ce44SJohn Forte uint8_t *bptr1; 572fcf3ce44SJohn Forte uint8_t *bptr2; 573fcf3ce44SJohn Forte 574fcf3ce44SJohn Forte rw_enter(&port->node_rwlock, RW_READER); 575fcf3ce44SJohn Forte for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { 576fcf3ce44SJohn Forte nlp = port->node_table[i]; 577fcf3ce44SJohn Forte while (nlp != NULL) { 578fcf3ce44SJohn Forte bptr1 = (uint8_t *)&nlp->nlp_portname; 579fcf3ce44SJohn Forte bptr1 += 7; 580fcf3ce44SJohn Forte bptr2 = (uint8_t *)wwpn; 581fcf3ce44SJohn Forte bptr2 += 7; 582fcf3ce44SJohn Forte 583fcf3ce44SJohn Forte for (j = 0; j < 8; j++) { 584fcf3ce44SJohn Forte if (*bptr1-- != *bptr2--) { 585fcf3ce44SJohn Forte break; 586fcf3ce44SJohn Forte } 587fcf3ce44SJohn Forte } 588fcf3ce44SJohn Forte 589fcf3ce44SJohn Forte if (j == 8) { 590fcf3ce44SJohn Forte rw_exit(&port->node_rwlock); 591fcf3ce44SJohn Forte return (nlp); 592fcf3ce44SJohn Forte } 593291a2b48SSukumar Swaminathan 594291a2b48SSukumar Swaminathan nlp = (NODELIST *)nlp->nlp_list_next; 595fcf3ce44SJohn Forte } 596fcf3ce44SJohn Forte } 597fcf3ce44SJohn Forte rw_exit(&port->node_rwlock); 598fcf3ce44SJohn Forte 599fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_not_found_msg, 600291a2b48SSukumar Swaminathan "find: wwpn=%02x%02x%02x%02x%02x%02x%02x%02x", wwpn[0], wwpn[1], 601291a2b48SSukumar Swaminathan wwpn[2], wwpn[3], wwpn[4], wwpn[5], wwpn[6], wwpn[7]); 602fcf3ce44SJohn Forte 603fcf3ce44SJohn Forte /* no match found */ 604291a2b48SSukumar Swaminathan return ((NODELIST *)0); 605fcf3ce44SJohn Forte 606*82527734SSukumar Swaminathan } /* emlxs_node_find_wwpn() */ 607fcf3ce44SJohn Forte 608fcf3ce44SJohn Forte 609fcf3ce44SJohn Forte extern NODELIST * 610291a2b48SSukumar Swaminathan emlxs_node_find_index(emlxs_port_t *port, uint32_t index, 611291a2b48SSukumar Swaminathan uint32_t nports_only) 612fcf3ce44SJohn Forte { 613fcf3ce44SJohn Forte NODELIST *nlp; 614fcf3ce44SJohn Forte uint32_t i; 615fcf3ce44SJohn Forte uint32_t count; 616fcf3ce44SJohn Forte 617fcf3ce44SJohn Forte rw_enter(&port->node_rwlock, RW_READER); 618fcf3ce44SJohn Forte 619fcf3ce44SJohn Forte if (index > port->node_count - 1) { 620fcf3ce44SJohn Forte rw_exit(&port->node_rwlock); 621fcf3ce44SJohn Forte return (NULL); 622fcf3ce44SJohn Forte } 623291a2b48SSukumar Swaminathan 624fcf3ce44SJohn Forte count = 0; 625fcf3ce44SJohn Forte for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { 626fcf3ce44SJohn Forte nlp = port->node_table[i]; 627fcf3ce44SJohn Forte while (nlp != NULL) { 628fcf3ce44SJohn Forte /* Skip fabric ports if requested */ 629291a2b48SSukumar Swaminathan if (nports_only && 630291a2b48SSukumar Swaminathan (nlp->nlp_DID & 0xFFF000) == 0xFFF000) { 631291a2b48SSukumar Swaminathan nlp = (NODELIST *)nlp->nlp_list_next; 632fcf3ce44SJohn Forte continue; 633fcf3ce44SJohn Forte } 634291a2b48SSukumar Swaminathan 635fcf3ce44SJohn Forte if (count == index) { 636fcf3ce44SJohn Forte rw_exit(&port->node_rwlock); 637fcf3ce44SJohn Forte return (nlp); 638fcf3ce44SJohn Forte } 639291a2b48SSukumar Swaminathan 640291a2b48SSukumar Swaminathan nlp = (NODELIST *)nlp->nlp_list_next; 641fcf3ce44SJohn Forte count++; 642fcf3ce44SJohn Forte } 643fcf3ce44SJohn Forte } 644fcf3ce44SJohn Forte rw_exit(&port->node_rwlock); 645fcf3ce44SJohn Forte 646291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_not_found_msg, "find: index=%d", 647291a2b48SSukumar Swaminathan index); 648fcf3ce44SJohn Forte 649fcf3ce44SJohn Forte /* no match found */ 650291a2b48SSukumar Swaminathan return ((NODELIST *)0); 651fcf3ce44SJohn Forte 652*82527734SSukumar Swaminathan } /* emlxs_node_find_wwpn() */ 653fcf3ce44SJohn Forte 654fcf3ce44SJohn Forte 655fcf3ce44SJohn Forte extern uint32_t 656fcf3ce44SJohn Forte emlxs_nport_count(emlxs_port_t *port) 657fcf3ce44SJohn Forte { 658fcf3ce44SJohn Forte NODELIST *nlp; 659fcf3ce44SJohn Forte uint32_t i; 660fcf3ce44SJohn Forte uint32_t nport_count = 0; 661fcf3ce44SJohn Forte 662fcf3ce44SJohn Forte rw_enter(&port->node_rwlock, RW_READER); 663fcf3ce44SJohn Forte for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { 664fcf3ce44SJohn Forte nlp = port->node_table[i]; 665fcf3ce44SJohn Forte while (nlp != NULL) { 666fcf3ce44SJohn Forte if ((nlp->nlp_DID & 0xFFF000) != 0xFFF000) { 667fcf3ce44SJohn Forte nport_count++; 668fcf3ce44SJohn Forte } 669291a2b48SSukumar Swaminathan 670291a2b48SSukumar Swaminathan nlp = (NODELIST *)nlp->nlp_list_next; 671fcf3ce44SJohn Forte } 672fcf3ce44SJohn Forte } 673fcf3ce44SJohn Forte rw_exit(&port->node_rwlock); 674fcf3ce44SJohn Forte 675fcf3ce44SJohn Forte return (nport_count); 676fcf3ce44SJohn Forte 677*82527734SSukumar Swaminathan } /* emlxs_nport_count() */ 678fcf3ce44SJohn Forte 679fcf3ce44SJohn Forte 680fcf3ce44SJohn Forte 681fcf3ce44SJohn Forte extern void 682fcf3ce44SJohn Forte emlxs_node_destroy_all(emlxs_port_t *port) 683fcf3ce44SJohn Forte { 684fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 685fcf3ce44SJohn Forte NODELIST *next; 686fcf3ce44SJohn Forte NODELIST *ndlp; 687*82527734SSukumar Swaminathan RPIobj_t *rp; 688fcf3ce44SJohn Forte uint8_t *wwn; 689fcf3ce44SJohn Forte uint32_t i; 690fcf3ce44SJohn Forte 691fcf3ce44SJohn Forte /* Flush and free the nodes */ 692fcf3ce44SJohn Forte rw_enter(&port->node_rwlock, RW_WRITER); 693fcf3ce44SJohn Forte for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { 694fcf3ce44SJohn Forte ndlp = port->node_table[i]; 695fcf3ce44SJohn Forte port->node_table[i] = 0; 696fcf3ce44SJohn Forte while (ndlp != NULL) { 697fcf3ce44SJohn Forte next = ndlp->nlp_list_next; 698fcf3ce44SJohn Forte ndlp->nlp_list_next = NULL; 699fcf3ce44SJohn Forte ndlp->nlp_list_prev = NULL; 700fcf3ce44SJohn Forte ndlp->nlp_active = 0; 701fcf3ce44SJohn Forte 702fcf3ce44SJohn Forte if (port->node_count) { 703fcf3ce44SJohn Forte port->node_count--; 704fcf3ce44SJohn Forte } 705291a2b48SSukumar Swaminathan 706fcf3ce44SJohn Forte wwn = (uint8_t *)&ndlp->nlp_portname; 707291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 708291a2b48SSukumar Swaminathan &emlxs_node_destroy_msg, "did=%06x " 709291a2b48SSukumar Swaminathan "rpi=%x wwpn=%02x%02x%02x%02x%02x%02x%02x%02x " 710291a2b48SSukumar Swaminathan "count=%d", ndlp->nlp_DID, ndlp->nlp_Rpi, wwn[0], 711291a2b48SSukumar Swaminathan wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], 712291a2b48SSukumar Swaminathan wwn[7], port->node_count); 713fcf3ce44SJohn Forte 714fcf3ce44SJohn Forte (void) emlxs_tx_node_flush(port, ndlp, 0, 0, 0); 715fcf3ce44SJohn Forte 716*82527734SSukumar Swaminathan /* Break Node/RPI binding */ 717*82527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 718*82527734SSukumar Swaminathan rp = EMLXS_NODE_TO_RPI(hba, ndlp); 719*82527734SSukumar Swaminathan ndlp->RPIp = NULL; 720*82527734SSukumar Swaminathan 721*82527734SSukumar Swaminathan if (rp) { 722*82527734SSukumar Swaminathan rp->node = NULL; 723*82527734SSukumar Swaminathan (void) emlxs_sli4_free_rpi(hba, rp); 724*82527734SSukumar Swaminathan } 725*82527734SSukumar Swaminathan } 726*82527734SSukumar Swaminathan 727fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_NLP, (uint8_t *)ndlp); 728fcf3ce44SJohn Forte 729fcf3ce44SJohn Forte ndlp = next; 730fcf3ce44SJohn Forte } 731fcf3ce44SJohn Forte } 732fcf3ce44SJohn Forte port->node_count = 0; 733fcf3ce44SJohn Forte rw_exit(&port->node_rwlock); 734fcf3ce44SJohn Forte 735fcf3ce44SJohn Forte /* Clean the base node */ 736fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 737fcf3ce44SJohn Forte port->node_base.nlp_list_next = NULL; 738fcf3ce44SJohn Forte port->node_base.nlp_list_prev = NULL; 739fcf3ce44SJohn Forte port->node_base.nlp_active = 1; 740fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 741fcf3ce44SJohn Forte 742fcf3ce44SJohn Forte /* Flush the base node */ 743fcf3ce44SJohn Forte (void) emlxs_tx_node_flush(port, &port->node_base, 0, 1, 0); 744fcf3ce44SJohn Forte (void) emlxs_chipq_node_flush(port, 0, &port->node_base, 0); 745fcf3ce44SJohn Forte 746fcf3ce44SJohn Forte return; 747fcf3ce44SJohn Forte 748*82527734SSukumar Swaminathan } /* emlxs_node_destroy_all() */ 749fcf3ce44SJohn Forte 750fcf3ce44SJohn Forte 751fcf3ce44SJohn Forte extern void 752fcf3ce44SJohn Forte emlxs_node_add(emlxs_port_t *port, NODELIST *ndlp) 753fcf3ce44SJohn Forte { 754*82527734SSukumar Swaminathan emlxs_hba_t *hba = HBA; 755fcf3ce44SJohn Forte NODELIST *np; 756fcf3ce44SJohn Forte uint8_t *wwn; 757fcf3ce44SJohn Forte uint32_t hash; 758*82527734SSukumar Swaminathan RPIobj_t *rp; 759fcf3ce44SJohn Forte 760fcf3ce44SJohn Forte rw_enter(&port->node_rwlock, RW_WRITER); 761fcf3ce44SJohn Forte hash = EMLXS_DID_HASH(ndlp->nlp_DID); 762fcf3ce44SJohn Forte np = port->node_table[hash]; 763fcf3ce44SJohn Forte 764fcf3ce44SJohn Forte /* 765fcf3ce44SJohn Forte * Insert node pointer to the head 766fcf3ce44SJohn Forte */ 767fcf3ce44SJohn Forte port->node_table[hash] = ndlp; 768fcf3ce44SJohn Forte if (!np) { 769fcf3ce44SJohn Forte ndlp->nlp_list_next = NULL; 770fcf3ce44SJohn Forte } else { 771fcf3ce44SJohn Forte ndlp->nlp_list_next = np; 772fcf3ce44SJohn Forte } 773fcf3ce44SJohn Forte port->node_count++; 774fcf3ce44SJohn Forte 775fcf3ce44SJohn Forte wwn = (uint8_t *)&ndlp->nlp_portname; 776fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_msg, 777291a2b48SSukumar Swaminathan "node=%p did=%06x rpi=%x wwpn=%02x%02x%02x%02x%02x%02x%02x%02x " 778291a2b48SSukumar Swaminathan "count=%d", ndlp, ndlp->nlp_DID, ndlp->nlp_Rpi, wwn[0], wwn[1], 779291a2b48SSukumar Swaminathan wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], wwn[7], port->node_count); 780fcf3ce44SJohn Forte 781*82527734SSukumar Swaminathan /* Add Node/RPI binding */ 782*82527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 783*82527734SSukumar Swaminathan rp = emlxs_sli4_find_rpi(hba, ndlp->nlp_Rpi); 784*82527734SSukumar Swaminathan 785*82527734SSukumar Swaminathan if (rp) { 786*82527734SSukumar Swaminathan rp->node = ndlp; 787*82527734SSukumar Swaminathan ndlp->RPIp = rp; 788*82527734SSukumar Swaminathan } else { 789*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_msg, 790*82527734SSukumar Swaminathan "Unable to find RPI! did=%x rpi=%x", 791*82527734SSukumar Swaminathan ndlp->nlp_DID, ndlp->nlp_Rpi); 792*82527734SSukumar Swaminathan } 793*82527734SSukumar Swaminathan } 794*82527734SSukumar Swaminathan 795fcf3ce44SJohn Forte rw_exit(&port->node_rwlock); 796fcf3ce44SJohn Forte 797fcf3ce44SJohn Forte return; 798fcf3ce44SJohn Forte 799*82527734SSukumar Swaminathan } /* emlxs_node_add() */ 800fcf3ce44SJohn Forte 801fcf3ce44SJohn Forte 802fcf3ce44SJohn Forte extern void 803fcf3ce44SJohn Forte emlxs_node_rm(emlxs_port_t *port, NODELIST *ndlp) 804fcf3ce44SJohn Forte { 805fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 806fcf3ce44SJohn Forte NODELIST *np; 807fcf3ce44SJohn Forte NODELIST *prevp; 808*82527734SSukumar Swaminathan RPIobj_t *rp; 809fcf3ce44SJohn Forte uint8_t *wwn; 810fcf3ce44SJohn Forte uint32_t hash; 811fcf3ce44SJohn Forte 812fcf3ce44SJohn Forte rw_enter(&port->node_rwlock, RW_WRITER); 813fcf3ce44SJohn Forte hash = EMLXS_DID_HASH(ndlp->nlp_DID); 814fcf3ce44SJohn Forte np = port->node_table[hash]; 815fcf3ce44SJohn Forte prevp = NULL; 816fcf3ce44SJohn Forte while (np != NULL) { 817fcf3ce44SJohn Forte if (np->nlp_DID == ndlp->nlp_DID) { 818fcf3ce44SJohn Forte if (prevp == NULL) { 819fcf3ce44SJohn Forte port->node_table[hash] = np->nlp_list_next; 820fcf3ce44SJohn Forte } else { 821fcf3ce44SJohn Forte prevp->nlp_list_next = np->nlp_list_next; 822fcf3ce44SJohn Forte } 823fcf3ce44SJohn Forte 824fcf3ce44SJohn Forte if (port->node_count) { 825fcf3ce44SJohn Forte port->node_count--; 826fcf3ce44SJohn Forte } 827291a2b48SSukumar Swaminathan 828fcf3ce44SJohn Forte wwn = (uint8_t *)&ndlp->nlp_portname; 829291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 830291a2b48SSukumar Swaminathan &emlxs_node_destroy_msg, "did=%06x " 831291a2b48SSukumar Swaminathan "rpi=%x wwpn=%02x%02x%02x%02x%02x%02x%02x%02x " 832291a2b48SSukumar Swaminathan "count=%d", ndlp->nlp_DID, ndlp->nlp_Rpi, wwn[0], 833291a2b48SSukumar Swaminathan wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], 834291a2b48SSukumar Swaminathan wwn[7], port->node_count); 835fcf3ce44SJohn Forte 836fcf3ce44SJohn Forte (void) emlxs_tx_node_flush(port, ndlp, 0, 1, 0); 837fcf3ce44SJohn Forte 838fcf3ce44SJohn Forte ndlp->nlp_active = 0; 839*82527734SSukumar Swaminathan 840*82527734SSukumar Swaminathan /* Break Node/RPI binding */ 841*82527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 842*82527734SSukumar Swaminathan rp = EMLXS_NODE_TO_RPI(hba, ndlp); 843*82527734SSukumar Swaminathan ndlp->RPIp = NULL; 844*82527734SSukumar Swaminathan 845*82527734SSukumar Swaminathan if (rp) { 846*82527734SSukumar Swaminathan rp->node = NULL; 847*82527734SSukumar Swaminathan (void) emlxs_sli4_free_rpi(hba, rp); 848*82527734SSukumar Swaminathan } 849*82527734SSukumar Swaminathan } 850*82527734SSukumar Swaminathan 851fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_NLP, (uint8_t *)ndlp); 852fcf3ce44SJohn Forte 853fcf3ce44SJohn Forte break; 854fcf3ce44SJohn Forte } 855fcf3ce44SJohn Forte prevp = np; 856fcf3ce44SJohn Forte np = np->nlp_list_next; 857fcf3ce44SJohn Forte } 858fcf3ce44SJohn Forte rw_exit(&port->node_rwlock); 859fcf3ce44SJohn Forte 860fcf3ce44SJohn Forte return; 861fcf3ce44SJohn Forte 862*82527734SSukumar Swaminathan } /* emlxs_node_rm() */ 863