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. 2482527734SSukumar Swaminathan * Use is subject to license terms. 25fcf3ce44SJohn Forte */ 26fcf3ce44SJohn Forte 2782527734SSukumar 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 */ 3582527734SSukumar Swaminathan /* Timeout not -1 will apply the timeout */ 36fcf3ce44SJohn Forte extern void 3782527734SSukumar 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; 4282527734SSukumar Swaminathan CHANNEL *cp; 43fcf3ce44SJohn Forte NODELIST *prev; 44291a2b48SSukumar Swaminathan uint32_t offline = 0; 45fcf3ce44SJohn Forte 4682527734SSukumar Swaminathan 4782527734SSukumar Swaminathan /* If node is on a channel service queue, then remove it */ 4882527734SSukumar Swaminathan mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 49fcf3ce44SJohn Forte 50fcf3ce44SJohn Forte /* Return if node destroyed */ 51fcf3ce44SJohn Forte if (!ndlp || !ndlp->nlp_active) { 5282527734SSukumar 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 6782527734SSukumar 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 */ 7382527734SSukumar Swaminathan if (ndlp->nlp_flag[channelno] & NLP_CLOSED) { 7482527734SSukumar Swaminathan if (ndlp->nlp_flag[channelno] & NLP_OFFLINE) { 7582527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 76291a2b48SSukumar Swaminathan return; 77291a2b48SSukumar Swaminathan } 78291a2b48SSukumar Swaminathan 79291a2b48SSukumar Swaminathan if (offline) { 8082527734SSukumar Swaminathan ndlp->nlp_tics[channelno] = hba->timer_tics + timeout; 8182527734SSukumar Swaminathan ndlp->nlp_flag[channelno] |= NLP_OFFLINE; 8282527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 83291a2b48SSukumar Swaminathan 84291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_closed_msg, 85*fe199829SSukumar Swaminathan "node=%p did=%06x channel=%d. offline=%d update.", 8682527734SSukumar Swaminathan ndlp, ndlp->nlp_DID, channelno, timeout); 87291a2b48SSukumar Swaminathan 88291a2b48SSukumar Swaminathan } else if (timeout) { 8982527734SSukumar Swaminathan ndlp->nlp_tics[channelno] = hba->timer_tics + timeout; 9082527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 91291a2b48SSukumar Swaminathan 92291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_closed_msg, 93*fe199829SSukumar Swaminathan "node=%p did=%06x channel=%d. timeout=%d update.", 9482527734SSukumar Swaminathan ndlp, ndlp->nlp_DID, channelno, timeout); 95291a2b48SSukumar Swaminathan } else { 9682527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 97fcf3ce44SJohn Forte } 98fcf3ce44SJohn Forte 99fcf3ce44SJohn Forte return; 100fcf3ce44SJohn Forte } 101291a2b48SSukumar Swaminathan 102fcf3ce44SJohn Forte /* Set the node closed */ 10382527734SSukumar Swaminathan ndlp->nlp_flag[channelno] |= NLP_CLOSED; 104fcf3ce44SJohn Forte 105291a2b48SSukumar Swaminathan if (offline) { 10682527734SSukumar Swaminathan ndlp->nlp_tics[channelno] = hba->timer_tics + timeout; 10782527734SSukumar Swaminathan ndlp->nlp_flag[channelno] |= NLP_OFFLINE; 108291a2b48SSukumar Swaminathan 109*fe199829SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_closed_msg, 110*fe199829SSukumar Swaminathan "node=%p did=%06x channel=%d. offline=%d set.", 111*fe199829SSukumar Swaminathan ndlp, ndlp->nlp_DID, channelno, timeout); 112*fe199829SSukumar Swaminathan 113291a2b48SSukumar Swaminathan } else if (timeout) { 11482527734SSukumar Swaminathan ndlp->nlp_tics[channelno] = hba->timer_tics + timeout; 115*fe199829SSukumar Swaminathan 116*fe199829SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_closed_msg, 117*fe199829SSukumar Swaminathan "node=%p did=%06x channel=%d. timeout=%d set.", 118*fe199829SSukumar Swaminathan ndlp, ndlp->nlp_DID, channelno, timeout); 119*fe199829SSukumar Swaminathan } else { 120*fe199829SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_closed_msg, 121*fe199829SSukumar Swaminathan "node=%p did=%06x channel=%d.", 122*fe199829SSukumar Swaminathan ndlp, ndlp->nlp_DID, channelno); 123fcf3ce44SJohn Forte } 124fcf3ce44SJohn Forte 12582527734SSukumar Swaminathan 12682527734SSukumar Swaminathan /* 12782527734SSukumar Swaminathan * ndlp->nlp_next[] and cp->nodeq list have to be updated 12882527734SSukumar Swaminathan * simulaneously 12982527734SSukumar Swaminathan */ 13082527734SSukumar Swaminathan if (ndlp->nlp_next[channelno]) { 13182527734SSukumar Swaminathan /* Remove node from channel queue */ 13282527734SSukumar Swaminathan cp = &hba->chan[channelno]; 133fcf3ce44SJohn Forte 134fcf3ce44SJohn Forte /* If this is the only node on list */ 13582527734SSukumar Swaminathan if (cp->nodeq.q_first == (void *)ndlp && 13682527734SSukumar Swaminathan cp->nodeq.q_last == (void *)ndlp) { 13782527734SSukumar Swaminathan cp->nodeq.q_last = NULL; 13882527734SSukumar Swaminathan cp->nodeq.q_first = NULL; 13982527734SSukumar Swaminathan cp->nodeq.q_cnt = 0; 14082527734SSukumar Swaminathan } else if (cp->nodeq.q_first == (void *)ndlp) { 14182527734SSukumar Swaminathan cp->nodeq.q_first = ndlp->nlp_next[channelno]; 14282527734SSukumar Swaminathan ((NODELIST *)cp->nodeq.q_last)->nlp_next[channelno] = 14382527734SSukumar Swaminathan cp->nodeq.q_first; 14482527734SSukumar Swaminathan cp->nodeq.q_cnt--; 145fcf3ce44SJohn Forte } else { /* This is a little more difficult */ 146291a2b48SSukumar Swaminathan 14782527734SSukumar Swaminathan /* Find the previous node in circular channel queue */ 148fcf3ce44SJohn Forte prev = ndlp; 14982527734SSukumar Swaminathan while (prev->nlp_next[channelno] != ndlp) { 15082527734SSukumar Swaminathan prev = prev->nlp_next[channelno]; 151fcf3ce44SJohn Forte } 152fcf3ce44SJohn Forte 15382527734SSukumar Swaminathan prev->nlp_next[channelno] = ndlp->nlp_next[channelno]; 154fcf3ce44SJohn Forte 15582527734SSukumar Swaminathan if (cp->nodeq.q_last == (void *)ndlp) { 15682527734SSukumar Swaminathan cp->nodeq.q_last = (void *)prev; 157fcf3ce44SJohn Forte } 15882527734SSukumar Swaminathan cp->nodeq.q_cnt--; 159fcf3ce44SJohn Forte 160fcf3ce44SJohn Forte } 161fcf3ce44SJohn Forte 162fcf3ce44SJohn Forte /* Clear node */ 16382527734SSukumar Swaminathan ndlp->nlp_next[channelno] = NULL; 164fcf3ce44SJohn Forte } 165291a2b48SSukumar Swaminathan 16682527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 167728bdc9bSSukumar Swaminathan 168291a2b48SSukumar Swaminathan return; 169291a2b48SSukumar Swaminathan 17082527734SSukumar Swaminathan } /* emlxs_node_close() */ 171291a2b48SSukumar Swaminathan 172291a2b48SSukumar Swaminathan 173291a2b48SSukumar Swaminathan /* Called by emlxs_timer_check_nodes() */ 174291a2b48SSukumar Swaminathan extern void 17582527734SSukumar Swaminathan emlxs_node_timeout(emlxs_port_t *port, NODELIST *ndlp, uint32_t channelno) 176291a2b48SSukumar Swaminathan { 177291a2b48SSukumar Swaminathan emlxs_hba_t *hba = HBA; 178291a2b48SSukumar Swaminathan 17982527734SSukumar Swaminathan /* If node needs servicing, then add it to the channel queues */ 18082527734SSukumar Swaminathan mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 181291a2b48SSukumar Swaminathan 182291a2b48SSukumar Swaminathan /* Return if node destroyed */ 183291a2b48SSukumar Swaminathan if (!ndlp || !ndlp->nlp_active) { 18482527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 185291a2b48SSukumar Swaminathan return; 186291a2b48SSukumar Swaminathan } 187291a2b48SSukumar Swaminathan 188291a2b48SSukumar Swaminathan /* Open the node if not offline */ 18982527734SSukumar Swaminathan if (!(ndlp->nlp_flag[channelno] & NLP_OFFLINE)) { 19082527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 191291a2b48SSukumar Swaminathan 192291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_timeout_msg, 19382527734SSukumar Swaminathan "node=%p did=%06x channel=%d Opening.", ndlp, ndlp->nlp_DID, 19482527734SSukumar Swaminathan channelno); 195291a2b48SSukumar Swaminathan 19682527734SSukumar Swaminathan emlxs_node_open(port, ndlp, channelno); 197291a2b48SSukumar Swaminathan return; 198728bdc9bSSukumar Swaminathan } 199fcf3ce44SJohn Forte 200291a2b48SSukumar Swaminathan /* OFFLINE TIMEOUT OCCURRED! */ 201291a2b48SSukumar Swaminathan 202291a2b48SSukumar Swaminathan /* Clear the timer */ 20382527734SSukumar Swaminathan ndlp->nlp_tics[channelno] = 0; 204291a2b48SSukumar Swaminathan 20582527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 206291a2b48SSukumar Swaminathan 207291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_timeout_msg, 208291a2b48SSukumar Swaminathan "node=%p did=%06x %s. Flushing.", ndlp, ndlp->nlp_DID, 20982527734SSukumar Swaminathan channelno); 210291a2b48SSukumar Swaminathan 21182527734SSukumar Swaminathan /* Flush tx queue for this channel */ 21282527734SSukumar Swaminathan (void) emlxs_tx_node_flush(port, ndlp, &hba->chan[channelno], 0, 0); 213291a2b48SSukumar Swaminathan 21482527734SSukumar Swaminathan /* Flush chip queue for this channel */ 21582527734SSukumar Swaminathan (void) emlxs_chipq_node_flush(port, &hba->chan[channelno], ndlp, 0); 216291a2b48SSukumar Swaminathan 217fcf3ce44SJohn Forte return; 218fcf3ce44SJohn Forte 21982527734SSukumar Swaminathan } /* emlxs_node_timeout() */ 220fcf3ce44SJohn Forte 221fcf3ce44SJohn Forte 222fcf3ce44SJohn Forte extern void 22382527734SSukumar Swaminathan emlxs_node_open(emlxs_port_t *port, NODELIST *ndlp, uint32_t channelno) 224fcf3ce44SJohn Forte { 225fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 22682527734SSukumar Swaminathan CHANNEL *cp; 227fcf3ce44SJohn Forte uint32_t found; 228fcf3ce44SJohn Forte NODELIST *nlp; 229fcf3ce44SJohn Forte MAILBOXQ *mbox; 230fcf3ce44SJohn Forte uint32_t i; 23182527734SSukumar Swaminathan int rc; 232fcf3ce44SJohn Forte 23382527734SSukumar Swaminathan /* If node needs servicing, then add it to the channel queues */ 23482527734SSukumar Swaminathan mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 235fcf3ce44SJohn Forte 236fcf3ce44SJohn Forte /* Return if node destroyed */ 237fcf3ce44SJohn Forte if (!ndlp || !ndlp->nlp_active) { 23882527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 239fcf3ce44SJohn Forte 240fcf3ce44SJohn Forte return; 241fcf3ce44SJohn Forte } 242291a2b48SSukumar Swaminathan 243fcf3ce44SJohn Forte /* Return if node already open */ 24482527734SSukumar Swaminathan if (!(ndlp->nlp_flag[channelno] & NLP_CLOSED)) { 24582527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 246fcf3ce44SJohn Forte 247fcf3ce44SJohn Forte return; 248fcf3ce44SJohn Forte } 249fcf3ce44SJohn Forte 250291a2b48SSukumar Swaminathan /* Set the node open (not closed) */ 25182527734SSukumar Swaminathan ndlp->nlp_flag[channelno] &= ~(NLP_CLOSED|NLP_OFFLINE); 252fcf3ce44SJohn Forte 253fcf3ce44SJohn Forte /* Clear the timer */ 25482527734SSukumar Swaminathan ndlp->nlp_tics[channelno] = 0; 255fcf3ce44SJohn Forte 256fcf3ce44SJohn Forte /* 257291a2b48SSukumar Swaminathan * If the ptx or the tx queue needs servicing and 25882527734SSukumar Swaminathan * the node is not already on the channel queue 259fcf3ce44SJohn Forte */ 26082527734SSukumar Swaminathan if ((ndlp->nlp_ptx[channelno].q_first || 26182527734SSukumar Swaminathan ndlp->nlp_tx[channelno].q_first) && !ndlp->nlp_next[channelno]) { 26282527734SSukumar Swaminathan cp = &hba->chan[channelno]; 263fcf3ce44SJohn Forte 26482527734SSukumar Swaminathan /* If so, then add it to the channel queue */ 26582527734SSukumar Swaminathan if (cp->nodeq.q_first) { 26682527734SSukumar Swaminathan ((NODELIST *)cp->nodeq.q_last)->nlp_next[channelno] = 267fcf3ce44SJohn Forte (uint8_t *)ndlp; 26882527734SSukumar Swaminathan ndlp->nlp_next[channelno] = cp->nodeq.q_first; 269fcf3ce44SJohn Forte 270291a2b48SSukumar Swaminathan /* If this is not the base node then */ 271291a2b48SSukumar Swaminathan /* add it to the tail */ 272fcf3ce44SJohn Forte if (!ndlp->nlp_base) { 27382527734SSukumar Swaminathan cp->nodeq.q_last = (uint8_t *)ndlp; 274fcf3ce44SJohn Forte } else { /* Otherwise, add it to the head */ 275291a2b48SSukumar Swaminathan 276fcf3ce44SJohn Forte /* The command node always gets priority */ 27782527734SSukumar Swaminathan cp->nodeq.q_first = (uint8_t *)ndlp; 278fcf3ce44SJohn Forte } 279fcf3ce44SJohn Forte 28082527734SSukumar Swaminathan cp->nodeq.q_cnt++; 281fcf3ce44SJohn Forte } else { 28282527734SSukumar Swaminathan cp->nodeq.q_first = (uint8_t *)ndlp; 28382527734SSukumar Swaminathan cp->nodeq.q_last = (uint8_t *)ndlp; 28482527734SSukumar Swaminathan ndlp->nlp_next[channelno] = ndlp; 28582527734SSukumar Swaminathan cp->nodeq.q_cnt = 1; 286fcf3ce44SJohn Forte } 287fcf3ce44SJohn Forte } 288291a2b48SSukumar Swaminathan 28982527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 290fcf3ce44SJohn Forte 291291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_opened_msg, 29282527734SSukumar Swaminathan "node=%p did=%06x channel=%d", ndlp, ndlp->nlp_DID, channelno); 293728bdc9bSSukumar Swaminathan 294fcf3ce44SJohn Forte /* If link attention needs to be cleared */ 29582527734SSukumar Swaminathan if ((hba->state == FC_LINK_UP) && (channelno == hba->channel_fcp)) { 29682527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 29782527734SSukumar Swaminathan /* re Think this code path. For SLI4 channel fcp == els */ 29882527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 29982527734SSukumar Swaminathan "ADD CODE to RESUME RPIs node=%p did=%06x chan=%d", 30082527734SSukumar Swaminathan ndlp, ndlp->nlp_DID, channelno); 30182527734SSukumar Swaminathan 30282527734SSukumar Swaminathan goto done; 30382527734SSukumar Swaminathan } 304fcf3ce44SJohn Forte 305fcf3ce44SJohn Forte /* Scan to see if any FCP2 devices are still closed */ 306fcf3ce44SJohn Forte found = 0; 307fcf3ce44SJohn Forte rw_enter(&port->node_rwlock, RW_READER); 308fcf3ce44SJohn Forte for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { 309fcf3ce44SJohn Forte nlp = port->node_table[i]; 310fcf3ce44SJohn Forte while (nlp != NULL) { 311fcf3ce44SJohn Forte if ((nlp->nlp_fcp_info & NLP_FCP_2_DEVICE) && 31282527734SSukumar Swaminathan (nlp->nlp_flag[hba->channel_fcp] & 31382527734SSukumar Swaminathan NLP_CLOSED)) { 314fcf3ce44SJohn Forte found = 1; 315fcf3ce44SJohn Forte break; 316291a2b48SSukumar Swaminathan 317fcf3ce44SJohn Forte } 318fcf3ce44SJohn Forte nlp = nlp->nlp_list_next; 319fcf3ce44SJohn Forte } 320fcf3ce44SJohn Forte 321fcf3ce44SJohn Forte if (found) { 322fcf3ce44SJohn Forte break; 323fcf3ce44SJohn Forte } 324fcf3ce44SJohn Forte } 325fcf3ce44SJohn Forte 326fcf3ce44SJohn Forte rw_exit(&port->node_rwlock); 327fcf3ce44SJohn Forte 328fcf3ce44SJohn Forte if (!found) { 329fcf3ce44SJohn Forte /* Clear link attention */ 330291a2b48SSukumar Swaminathan if ((mbox = (MAILBOXQ *)emlxs_mem_get(hba, 33182527734SSukumar Swaminathan MEM_MBOX, 1))) { 332fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 333fcf3ce44SJohn Forte 334fcf3ce44SJohn Forte /* 335291a2b48SSukumar Swaminathan * If state is not FC_LINK_UP, then either the 336291a2b48SSukumar Swaminathan * link has gone down or a FC_CLEAR_LA has 337291a2b48SSukumar Swaminathan * already been issued 338fcf3ce44SJohn Forte */ 339fcf3ce44SJohn Forte if (hba->state != FC_LINK_UP) { 340fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 341fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_MBOX, 342fcf3ce44SJohn Forte (uint8_t *)mbox); 343fcf3ce44SJohn Forte goto done; 344fcf3ce44SJohn Forte } 345291a2b48SSukumar Swaminathan 34682527734SSukumar Swaminathan EMLXS_STATE_CHANGE_LOCKED(hba, FC_CLEAR_LA); 347fcf3ce44SJohn Forte hba->discovery_timer = 0; 348fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 349fcf3ce44SJohn Forte 35082527734SSukumar Swaminathan emlxs_mb_clear_la(hba, mbox); 351fcf3ce44SJohn Forte 35282527734SSukumar Swaminathan rc = EMLXS_SLI_ISSUE_MBOX_CMD(hba, 35382527734SSukumar Swaminathan mbox, MBX_NOWAIT, 0); 35482527734SSukumar Swaminathan if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) { 355fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_MBOX, 356fcf3ce44SJohn Forte (uint8_t *)mbox); 357fcf3ce44SJohn Forte } 358fcf3ce44SJohn Forte } else { 359291a2b48SSukumar Swaminathan /* Close the node and try again */ 360291a2b48SSukumar Swaminathan /* in a few seconds */ 36182527734SSukumar Swaminathan emlxs_node_close(port, ndlp, channelno, 5); 362fcf3ce44SJohn Forte return; 363fcf3ce44SJohn Forte } 364fcf3ce44SJohn Forte } 365fcf3ce44SJohn Forte } 366291a2b48SSukumar Swaminathan 367fcf3ce44SJohn Forte done: 368fcf3ce44SJohn Forte 369fcf3ce44SJohn Forte /* Wake any sleeping threads */ 370fcf3ce44SJohn Forte mutex_enter(&EMLXS_PKT_LOCK); 371fcf3ce44SJohn Forte cv_broadcast(&EMLXS_PKT_CV); 372fcf3ce44SJohn Forte mutex_exit(&EMLXS_PKT_LOCK); 373fcf3ce44SJohn Forte 374fcf3ce44SJohn Forte return; 375fcf3ce44SJohn Forte 37682527734SSukumar Swaminathan } /* emlxs_node_open() */ 377fcf3ce44SJohn Forte 378fcf3ce44SJohn Forte 379fcf3ce44SJohn Forte static int 380fcf3ce44SJohn Forte emlxs_node_match_did(emlxs_port_t *port, NODELIST *ndlp, uint32_t did) 381fcf3ce44SJohn Forte { 382fcf3ce44SJohn Forte D_ID mydid; 383fcf3ce44SJohn Forte D_ID odid; 384fcf3ce44SJohn Forte D_ID ndid; 385fcf3ce44SJohn Forte 386291a2b48SSukumar Swaminathan if (ndlp->nlp_DID == did) 387fcf3ce44SJohn Forte return (1); 388fcf3ce44SJohn Forte 389fcf3ce44SJohn Forte /* 390fcf3ce44SJohn Forte * Next check for area/domain == 0 match 391fcf3ce44SJohn Forte */ 392fcf3ce44SJohn Forte mydid.un.word = port->did; 393fcf3ce44SJohn Forte if ((mydid.un.b.domain == 0) && (mydid.un.b.area == 0)) { 394fcf3ce44SJohn Forte goto out; 395fcf3ce44SJohn Forte } 396291a2b48SSukumar Swaminathan 397fcf3ce44SJohn Forte ndid.un.word = did; 398fcf3ce44SJohn Forte odid.un.word = ndlp->nlp_DID; 399fcf3ce44SJohn Forte if (ndid.un.b.id == odid.un.b.id) { 400fcf3ce44SJohn Forte if ((mydid.un.b.domain == ndid.un.b.domain) && 401fcf3ce44SJohn Forte (mydid.un.b.area == ndid.un.b.area)) { 402fcf3ce44SJohn Forte ndid.un.word = ndlp->nlp_DID; 403fcf3ce44SJohn Forte odid.un.word = did; 404291a2b48SSukumar Swaminathan if ((ndid.un.b.domain == 0) && (ndid.un.b.area == 0)) { 405fcf3ce44SJohn Forte return (1); 406fcf3ce44SJohn Forte } 407fcf3ce44SJohn Forte goto out; 408fcf3ce44SJohn Forte } 409291a2b48SSukumar Swaminathan 410fcf3ce44SJohn Forte ndid.un.word = ndlp->nlp_DID; 411fcf3ce44SJohn Forte if ((mydid.un.b.domain == ndid.un.b.domain) && 412fcf3ce44SJohn Forte (mydid.un.b.area == ndid.un.b.area)) { 413fcf3ce44SJohn Forte odid.un.word = ndlp->nlp_DID; 414fcf3ce44SJohn Forte ndid.un.word = did; 415291a2b48SSukumar Swaminathan if ((ndid.un.b.domain == 0) && (ndid.un.b.area == 0)) { 416fcf3ce44SJohn Forte return (1); 417fcf3ce44SJohn Forte } 418fcf3ce44SJohn Forte } 419fcf3ce44SJohn Forte } 420291a2b48SSukumar Swaminathan 421fcf3ce44SJohn Forte out: 422fcf3ce44SJohn Forte 423fcf3ce44SJohn Forte return (0); 424fcf3ce44SJohn Forte 42582527734SSukumar Swaminathan } /* End emlxs_node_match_did */ 426fcf3ce44SJohn Forte 427fcf3ce44SJohn Forte 428fcf3ce44SJohn Forte 429fcf3ce44SJohn Forte extern NODELIST * 430fcf3ce44SJohn Forte emlxs_node_find_mac(emlxs_port_t *port, uint8_t *mac) 431fcf3ce44SJohn Forte { 432fcf3ce44SJohn Forte NODELIST *nlp; 433fcf3ce44SJohn Forte uint32_t i; 434fcf3ce44SJohn Forte 435fcf3ce44SJohn Forte rw_enter(&port->node_rwlock, RW_READER); 436fcf3ce44SJohn Forte for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { 437fcf3ce44SJohn Forte nlp = port->node_table[i]; 438fcf3ce44SJohn Forte while (nlp != NULL) { 439fcf3ce44SJohn Forte /* 440291a2b48SSukumar Swaminathan * If portname matches mac address, 441291a2b48SSukumar Swaminathan * return NODELIST entry 442fcf3ce44SJohn Forte */ 443fcf3ce44SJohn Forte if ((nlp->nlp_portname.IEEE[0] == mac[0])) { 44482527734SSukumar Swaminathan if ((nlp->nlp_DID != BCAST_DID) && 44582527734SSukumar Swaminathan ((nlp->nlp_DID & FABRIC_DID_MASK) == 44682527734SSukumar Swaminathan FABRIC_DID_MASK)) { 447291a2b48SSukumar Swaminathan nlp = (NODELIST *)nlp->nlp_list_next; 448fcf3ce44SJohn Forte continue; 449fcf3ce44SJohn Forte } 450291a2b48SSukumar Swaminathan 451fcf3ce44SJohn Forte if ((nlp->nlp_portname.IEEE[1] == mac[1]) && 452fcf3ce44SJohn Forte (nlp->nlp_portname.IEEE[2] == mac[2]) && 453fcf3ce44SJohn Forte (nlp->nlp_portname.IEEE[3] == mac[3]) && 454fcf3ce44SJohn Forte (nlp->nlp_portname.IEEE[4] == mac[4]) && 455fcf3ce44SJohn Forte (nlp->nlp_portname.IEEE[5] == mac[5])) { 456fcf3ce44SJohn Forte rw_exit(&port->node_rwlock); 457fcf3ce44SJohn Forte return (nlp); 458fcf3ce44SJohn Forte } 459291a2b48SSukumar Swaminathan 460fcf3ce44SJohn Forte } 461291a2b48SSukumar Swaminathan 462291a2b48SSukumar Swaminathan nlp = (NODELIST *)nlp->nlp_list_next; 463fcf3ce44SJohn Forte } 464fcf3ce44SJohn Forte } 465fcf3ce44SJohn Forte rw_exit(&port->node_rwlock); 466fcf3ce44SJohn Forte 467fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_not_found_msg, 468291a2b48SSukumar Swaminathan "find: MAC=%02x%02x%02x%02x%02x%02x", mac[0], mac[1], mac[2], 469291a2b48SSukumar Swaminathan mac[3], mac[4], mac[5]); 470fcf3ce44SJohn Forte 471fcf3ce44SJohn Forte return (NULL); 472fcf3ce44SJohn Forte 47382527734SSukumar Swaminathan } /* emlxs_node_find_mac() */ 474fcf3ce44SJohn Forte 475fcf3ce44SJohn Forte 476fcf3ce44SJohn Forte extern NODELIST * 477fcf3ce44SJohn Forte emlxs_node_find_did(emlxs_port_t *port, uint32_t did) 478fcf3ce44SJohn Forte { 479fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 480fcf3ce44SJohn Forte NODELIST *nlp; 481fcf3ce44SJohn Forte uint32_t hash; 482fcf3ce44SJohn Forte 483fcf3ce44SJohn Forte /* Check for invalid node ids */ 484291a2b48SSukumar Swaminathan if ((did == 0) && (!(hba->flag & FC_LOOPBACK_MODE))) { 485291a2b48SSukumar Swaminathan return ((NODELIST *)0); 486291a2b48SSukumar Swaminathan } 487291a2b48SSukumar Swaminathan 488291a2b48SSukumar Swaminathan if (did & 0xff000000) { 489291a2b48SSukumar Swaminathan return ((NODELIST *)0); 490fcf3ce44SJohn Forte } 491291a2b48SSukumar Swaminathan 492fcf3ce44SJohn Forte /* Check for bcast node */ 49382527734SSukumar Swaminathan if (did == BCAST_DID) { 494fcf3ce44SJohn Forte /* Use the base node here */ 495fcf3ce44SJohn Forte return (&port->node_base); 496fcf3ce44SJohn Forte } 497fcf3ce44SJohn Forte #ifdef MENLO_SUPPORT 498fcf3ce44SJohn Forte /* Check for menlo node */ 499fcf3ce44SJohn Forte if (did == EMLXS_MENLO_DID) { 500fcf3ce44SJohn Forte /* Use the base node here */ 501fcf3ce44SJohn Forte return (&port->node_base); 502fcf3ce44SJohn Forte } 503291a2b48SSukumar Swaminathan #endif /* MENLO_SUPPORT */ 504fcf3ce44SJohn Forte 505fcf3ce44SJohn Forte /* Check for host node */ 506fcf3ce44SJohn Forte if (did == port->did && !(hba->flag & FC_LOOPBACK_MODE)) { 507fcf3ce44SJohn Forte /* Use the base node here */ 508fcf3ce44SJohn Forte return (&port->node_base); 509fcf3ce44SJohn Forte } 510291a2b48SSukumar Swaminathan 511fcf3ce44SJohn Forte /* 51282527734SSukumar Swaminathan * Convert well known fabric addresses to the FABRIC_DID, 513291a2b48SSukumar Swaminathan * since we don't login to some of them 514fcf3ce44SJohn Forte */ 515fcf3ce44SJohn Forte if ((did == SCR_DID)) { 51682527734SSukumar Swaminathan did = FABRIC_DID; 517fcf3ce44SJohn Forte } 518291a2b48SSukumar Swaminathan 519fcf3ce44SJohn Forte rw_enter(&port->node_rwlock, RW_READER); 520fcf3ce44SJohn Forte hash = EMLXS_DID_HASH(did); 521fcf3ce44SJohn Forte nlp = port->node_table[hash]; 522fcf3ce44SJohn Forte while (nlp != NULL) { 523fcf3ce44SJohn Forte /* Check for obvious match */ 524fcf3ce44SJohn Forte if (nlp->nlp_DID == did) { 525fcf3ce44SJohn Forte rw_exit(&port->node_rwlock); 526fcf3ce44SJohn Forte return (nlp); 527fcf3ce44SJohn Forte } 528291a2b48SSukumar Swaminathan 529fcf3ce44SJohn Forte /* Check for detailed match */ 530fcf3ce44SJohn Forte else if (emlxs_node_match_did(port, nlp, did)) { 531fcf3ce44SJohn Forte rw_exit(&port->node_rwlock); 532fcf3ce44SJohn Forte return (nlp); 533fcf3ce44SJohn Forte } 534291a2b48SSukumar Swaminathan 535291a2b48SSukumar Swaminathan nlp = (NODELIST *)nlp->nlp_list_next; 536fcf3ce44SJohn Forte } 537fcf3ce44SJohn Forte rw_exit(&port->node_rwlock); 538fcf3ce44SJohn Forte 539291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_not_found_msg, "find: did=%x", 540291a2b48SSukumar Swaminathan did); 541fcf3ce44SJohn Forte 542fcf3ce44SJohn Forte /* no match found */ 543291a2b48SSukumar Swaminathan return ((NODELIST *)0); 544fcf3ce44SJohn Forte 54582527734SSukumar Swaminathan } /* emlxs_node_find_did() */ 546fcf3ce44SJohn Forte 547fcf3ce44SJohn Forte 548fcf3ce44SJohn Forte extern NODELIST * 549fcf3ce44SJohn Forte emlxs_node_find_rpi(emlxs_port_t *port, uint32_t rpi) 550fcf3ce44SJohn Forte { 551fcf3ce44SJohn Forte NODELIST *nlp; 552fcf3ce44SJohn Forte uint32_t i; 553fcf3ce44SJohn Forte 554fcf3ce44SJohn Forte rw_enter(&port->node_rwlock, RW_READER); 555fcf3ce44SJohn Forte for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { 556fcf3ce44SJohn Forte nlp = port->node_table[i]; 557fcf3ce44SJohn Forte while (nlp != NULL) { 558fcf3ce44SJohn Forte if (nlp->nlp_Rpi == rpi) { 559fcf3ce44SJohn Forte rw_exit(&port->node_rwlock); 560fcf3ce44SJohn Forte return (nlp); 561fcf3ce44SJohn Forte } 562291a2b48SSukumar Swaminathan 563291a2b48SSukumar Swaminathan nlp = (NODELIST *)nlp->nlp_list_next; 564fcf3ce44SJohn Forte } 565fcf3ce44SJohn Forte } 566fcf3ce44SJohn Forte rw_exit(&port->node_rwlock); 567fcf3ce44SJohn Forte 568291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_not_found_msg, "find: rpi=%x", 569291a2b48SSukumar Swaminathan rpi); 570fcf3ce44SJohn Forte 571fcf3ce44SJohn Forte /* no match found */ 572291a2b48SSukumar Swaminathan return ((NODELIST *)0); 573fcf3ce44SJohn Forte 57482527734SSukumar Swaminathan } /* emlxs_node_find_rpi() */ 575fcf3ce44SJohn Forte 576fcf3ce44SJohn Forte 577fcf3ce44SJohn Forte extern NODELIST * 578fcf3ce44SJohn Forte emlxs_node_find_wwpn(emlxs_port_t *port, uint8_t *wwpn) 579fcf3ce44SJohn Forte { 580fcf3ce44SJohn Forte NODELIST *nlp; 581fcf3ce44SJohn Forte uint32_t i; 582fcf3ce44SJohn Forte uint32_t j; 583fcf3ce44SJohn Forte uint8_t *bptr1; 584fcf3ce44SJohn Forte uint8_t *bptr2; 585fcf3ce44SJohn Forte 586fcf3ce44SJohn Forte rw_enter(&port->node_rwlock, RW_READER); 587fcf3ce44SJohn Forte for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { 588fcf3ce44SJohn Forte nlp = port->node_table[i]; 589fcf3ce44SJohn Forte while (nlp != NULL) { 590fcf3ce44SJohn Forte bptr1 = (uint8_t *)&nlp->nlp_portname; 591fcf3ce44SJohn Forte bptr1 += 7; 592fcf3ce44SJohn Forte bptr2 = (uint8_t *)wwpn; 593fcf3ce44SJohn Forte bptr2 += 7; 594fcf3ce44SJohn Forte 595fcf3ce44SJohn Forte for (j = 0; j < 8; j++) { 596fcf3ce44SJohn Forte if (*bptr1-- != *bptr2--) { 597fcf3ce44SJohn Forte break; 598fcf3ce44SJohn Forte } 599fcf3ce44SJohn Forte } 600fcf3ce44SJohn Forte 601fcf3ce44SJohn Forte if (j == 8) { 602fcf3ce44SJohn Forte rw_exit(&port->node_rwlock); 603fcf3ce44SJohn Forte return (nlp); 604fcf3ce44SJohn Forte } 605291a2b48SSukumar Swaminathan 606291a2b48SSukumar Swaminathan nlp = (NODELIST *)nlp->nlp_list_next; 607fcf3ce44SJohn Forte } 608fcf3ce44SJohn Forte } 609fcf3ce44SJohn Forte rw_exit(&port->node_rwlock); 610fcf3ce44SJohn Forte 611fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_not_found_msg, 612291a2b48SSukumar Swaminathan "find: wwpn=%02x%02x%02x%02x%02x%02x%02x%02x", wwpn[0], wwpn[1], 613291a2b48SSukumar Swaminathan wwpn[2], wwpn[3], wwpn[4], wwpn[5], wwpn[6], wwpn[7]); 614fcf3ce44SJohn Forte 615fcf3ce44SJohn Forte /* no match found */ 616291a2b48SSukumar Swaminathan return ((NODELIST *)0); 617fcf3ce44SJohn Forte 61882527734SSukumar Swaminathan } /* emlxs_node_find_wwpn() */ 619fcf3ce44SJohn Forte 620fcf3ce44SJohn Forte 621fcf3ce44SJohn Forte extern NODELIST * 622291a2b48SSukumar Swaminathan emlxs_node_find_index(emlxs_port_t *port, uint32_t index, 623291a2b48SSukumar Swaminathan uint32_t nports_only) 624fcf3ce44SJohn Forte { 625fcf3ce44SJohn Forte NODELIST *nlp; 626fcf3ce44SJohn Forte uint32_t i; 627fcf3ce44SJohn Forte uint32_t count; 628fcf3ce44SJohn Forte 629fcf3ce44SJohn Forte rw_enter(&port->node_rwlock, RW_READER); 630fcf3ce44SJohn Forte 631fcf3ce44SJohn Forte if (index > port->node_count - 1) { 632fcf3ce44SJohn Forte rw_exit(&port->node_rwlock); 633fcf3ce44SJohn Forte return (NULL); 634fcf3ce44SJohn Forte } 635291a2b48SSukumar Swaminathan 636fcf3ce44SJohn Forte count = 0; 637fcf3ce44SJohn Forte for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { 638fcf3ce44SJohn Forte nlp = port->node_table[i]; 639fcf3ce44SJohn Forte while (nlp != NULL) { 640fcf3ce44SJohn Forte /* Skip fabric ports if requested */ 641291a2b48SSukumar Swaminathan if (nports_only && 642291a2b48SSukumar Swaminathan (nlp->nlp_DID & 0xFFF000) == 0xFFF000) { 643291a2b48SSukumar Swaminathan nlp = (NODELIST *)nlp->nlp_list_next; 644fcf3ce44SJohn Forte continue; 645fcf3ce44SJohn Forte } 646291a2b48SSukumar Swaminathan 647fcf3ce44SJohn Forte if (count == index) { 648fcf3ce44SJohn Forte rw_exit(&port->node_rwlock); 649fcf3ce44SJohn Forte return (nlp); 650fcf3ce44SJohn Forte } 651291a2b48SSukumar Swaminathan 652291a2b48SSukumar Swaminathan nlp = (NODELIST *)nlp->nlp_list_next; 653fcf3ce44SJohn Forte count++; 654fcf3ce44SJohn Forte } 655fcf3ce44SJohn Forte } 656fcf3ce44SJohn Forte rw_exit(&port->node_rwlock); 657fcf3ce44SJohn Forte 658291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_not_found_msg, "find: index=%d", 659291a2b48SSukumar Swaminathan index); 660fcf3ce44SJohn Forte 661fcf3ce44SJohn Forte /* no match found */ 662291a2b48SSukumar Swaminathan return ((NODELIST *)0); 663fcf3ce44SJohn Forte 66482527734SSukumar Swaminathan } /* emlxs_node_find_wwpn() */ 665fcf3ce44SJohn Forte 666fcf3ce44SJohn Forte 667fcf3ce44SJohn Forte extern uint32_t 668fcf3ce44SJohn Forte emlxs_nport_count(emlxs_port_t *port) 669fcf3ce44SJohn Forte { 670fcf3ce44SJohn Forte NODELIST *nlp; 671fcf3ce44SJohn Forte uint32_t i; 672fcf3ce44SJohn Forte uint32_t nport_count = 0; 673fcf3ce44SJohn Forte 674fcf3ce44SJohn Forte rw_enter(&port->node_rwlock, RW_READER); 675fcf3ce44SJohn Forte for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { 676fcf3ce44SJohn Forte nlp = port->node_table[i]; 677fcf3ce44SJohn Forte while (nlp != NULL) { 678fcf3ce44SJohn Forte if ((nlp->nlp_DID & 0xFFF000) != 0xFFF000) { 679fcf3ce44SJohn Forte nport_count++; 680fcf3ce44SJohn Forte } 681291a2b48SSukumar Swaminathan 682291a2b48SSukumar Swaminathan nlp = (NODELIST *)nlp->nlp_list_next; 683fcf3ce44SJohn Forte } 684fcf3ce44SJohn Forte } 685fcf3ce44SJohn Forte rw_exit(&port->node_rwlock); 686fcf3ce44SJohn Forte 687fcf3ce44SJohn Forte return (nport_count); 688fcf3ce44SJohn Forte 68982527734SSukumar Swaminathan } /* emlxs_nport_count() */ 690fcf3ce44SJohn Forte 691fcf3ce44SJohn Forte 692fcf3ce44SJohn Forte 693fcf3ce44SJohn Forte extern void 694fcf3ce44SJohn Forte emlxs_node_destroy_all(emlxs_port_t *port) 695fcf3ce44SJohn Forte { 696fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 697fcf3ce44SJohn Forte NODELIST *next; 698fcf3ce44SJohn Forte NODELIST *ndlp; 69982527734SSukumar Swaminathan RPIobj_t *rp; 700fcf3ce44SJohn Forte uint8_t *wwn; 701fcf3ce44SJohn Forte uint32_t i; 702fcf3ce44SJohn Forte 703fcf3ce44SJohn Forte /* Flush and free the nodes */ 704fcf3ce44SJohn Forte rw_enter(&port->node_rwlock, RW_WRITER); 705fcf3ce44SJohn Forte for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { 706fcf3ce44SJohn Forte ndlp = port->node_table[i]; 707fcf3ce44SJohn Forte port->node_table[i] = 0; 708fcf3ce44SJohn Forte while (ndlp != NULL) { 709fcf3ce44SJohn Forte next = ndlp->nlp_list_next; 710fcf3ce44SJohn Forte ndlp->nlp_list_next = NULL; 711fcf3ce44SJohn Forte ndlp->nlp_list_prev = NULL; 712fcf3ce44SJohn Forte ndlp->nlp_active = 0; 713fcf3ce44SJohn Forte 714fcf3ce44SJohn Forte if (port->node_count) { 715fcf3ce44SJohn Forte port->node_count--; 716fcf3ce44SJohn Forte } 717291a2b48SSukumar Swaminathan 718fcf3ce44SJohn Forte wwn = (uint8_t *)&ndlp->nlp_portname; 719291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 720291a2b48SSukumar Swaminathan &emlxs_node_destroy_msg, "did=%06x " 721291a2b48SSukumar Swaminathan "rpi=%x wwpn=%02x%02x%02x%02x%02x%02x%02x%02x " 722291a2b48SSukumar Swaminathan "count=%d", ndlp->nlp_DID, ndlp->nlp_Rpi, wwn[0], 723291a2b48SSukumar Swaminathan wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], 724291a2b48SSukumar Swaminathan wwn[7], port->node_count); 725fcf3ce44SJohn Forte 726fcf3ce44SJohn Forte (void) emlxs_tx_node_flush(port, ndlp, 0, 0, 0); 727fcf3ce44SJohn Forte 72882527734SSukumar Swaminathan /* Break Node/RPI binding */ 72982527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 73082527734SSukumar Swaminathan rp = EMLXS_NODE_TO_RPI(hba, ndlp); 73182527734SSukumar Swaminathan ndlp->RPIp = NULL; 73282527734SSukumar Swaminathan 73382527734SSukumar Swaminathan if (rp) { 73482527734SSukumar Swaminathan rp->node = NULL; 73582527734SSukumar Swaminathan (void) emlxs_sli4_free_rpi(hba, rp); 73682527734SSukumar Swaminathan } 73782527734SSukumar Swaminathan } 73882527734SSukumar Swaminathan 739fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_NLP, (uint8_t *)ndlp); 740fcf3ce44SJohn Forte 741fcf3ce44SJohn Forte ndlp = next; 742fcf3ce44SJohn Forte } 743fcf3ce44SJohn Forte } 744fcf3ce44SJohn Forte port->node_count = 0; 745fcf3ce44SJohn Forte rw_exit(&port->node_rwlock); 746fcf3ce44SJohn Forte 747fcf3ce44SJohn Forte /* Clean the base node */ 748fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 749fcf3ce44SJohn Forte port->node_base.nlp_list_next = NULL; 750fcf3ce44SJohn Forte port->node_base.nlp_list_prev = NULL; 751fcf3ce44SJohn Forte port->node_base.nlp_active = 1; 752fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 753fcf3ce44SJohn Forte 754fcf3ce44SJohn Forte /* Flush the base node */ 755fcf3ce44SJohn Forte (void) emlxs_tx_node_flush(port, &port->node_base, 0, 1, 0); 756fcf3ce44SJohn Forte (void) emlxs_chipq_node_flush(port, 0, &port->node_base, 0); 757fcf3ce44SJohn Forte 758fcf3ce44SJohn Forte return; 759fcf3ce44SJohn Forte 76082527734SSukumar Swaminathan } /* emlxs_node_destroy_all() */ 761fcf3ce44SJohn Forte 762fcf3ce44SJohn Forte 763fcf3ce44SJohn Forte extern void 764fcf3ce44SJohn Forte emlxs_node_add(emlxs_port_t *port, NODELIST *ndlp) 765fcf3ce44SJohn Forte { 76682527734SSukumar Swaminathan emlxs_hba_t *hba = HBA; 767fcf3ce44SJohn Forte NODELIST *np; 768fcf3ce44SJohn Forte uint8_t *wwn; 769fcf3ce44SJohn Forte uint32_t hash; 77082527734SSukumar Swaminathan RPIobj_t *rp; 771fcf3ce44SJohn Forte 772fcf3ce44SJohn Forte rw_enter(&port->node_rwlock, RW_WRITER); 773fcf3ce44SJohn Forte hash = EMLXS_DID_HASH(ndlp->nlp_DID); 774fcf3ce44SJohn Forte np = port->node_table[hash]; 775fcf3ce44SJohn Forte 776fcf3ce44SJohn Forte /* 777fcf3ce44SJohn Forte * Insert node pointer to the head 778fcf3ce44SJohn Forte */ 779fcf3ce44SJohn Forte port->node_table[hash] = ndlp; 780fcf3ce44SJohn Forte if (!np) { 781fcf3ce44SJohn Forte ndlp->nlp_list_next = NULL; 782fcf3ce44SJohn Forte } else { 783fcf3ce44SJohn Forte ndlp->nlp_list_next = np; 784fcf3ce44SJohn Forte } 785fcf3ce44SJohn Forte port->node_count++; 786fcf3ce44SJohn Forte 787fcf3ce44SJohn Forte wwn = (uint8_t *)&ndlp->nlp_portname; 788fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_msg, 789291a2b48SSukumar Swaminathan "node=%p did=%06x rpi=%x wwpn=%02x%02x%02x%02x%02x%02x%02x%02x " 790291a2b48SSukumar Swaminathan "count=%d", ndlp, ndlp->nlp_DID, ndlp->nlp_Rpi, wwn[0], wwn[1], 791291a2b48SSukumar Swaminathan wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], wwn[7], port->node_count); 792fcf3ce44SJohn Forte 79382527734SSukumar Swaminathan /* Add Node/RPI binding */ 79482527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 79582527734SSukumar Swaminathan rp = emlxs_sli4_find_rpi(hba, ndlp->nlp_Rpi); 79682527734SSukumar Swaminathan 79782527734SSukumar Swaminathan if (rp) { 79882527734SSukumar Swaminathan rp->node = ndlp; 79982527734SSukumar Swaminathan ndlp->RPIp = rp; 80082527734SSukumar Swaminathan } else { 80182527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_msg, 80282527734SSukumar Swaminathan "Unable to find RPI! did=%x rpi=%x", 80382527734SSukumar Swaminathan ndlp->nlp_DID, ndlp->nlp_Rpi); 80482527734SSukumar Swaminathan } 80582527734SSukumar Swaminathan } 80682527734SSukumar Swaminathan 807fcf3ce44SJohn Forte rw_exit(&port->node_rwlock); 808fcf3ce44SJohn Forte 809fcf3ce44SJohn Forte return; 810fcf3ce44SJohn Forte 81182527734SSukumar Swaminathan } /* emlxs_node_add() */ 812fcf3ce44SJohn Forte 813fcf3ce44SJohn Forte 814fcf3ce44SJohn Forte extern void 815fcf3ce44SJohn Forte emlxs_node_rm(emlxs_port_t *port, NODELIST *ndlp) 816fcf3ce44SJohn Forte { 817fcf3ce44SJohn Forte emlxs_hba_t *hba = HBA; 818fcf3ce44SJohn Forte NODELIST *np; 819fcf3ce44SJohn Forte NODELIST *prevp; 82082527734SSukumar Swaminathan RPIobj_t *rp; 821fcf3ce44SJohn Forte uint8_t *wwn; 822fcf3ce44SJohn Forte uint32_t hash; 823fcf3ce44SJohn Forte 824fcf3ce44SJohn Forte rw_enter(&port->node_rwlock, RW_WRITER); 825fcf3ce44SJohn Forte hash = EMLXS_DID_HASH(ndlp->nlp_DID); 826fcf3ce44SJohn Forte np = port->node_table[hash]; 827fcf3ce44SJohn Forte prevp = NULL; 828fcf3ce44SJohn Forte while (np != NULL) { 829fcf3ce44SJohn Forte if (np->nlp_DID == ndlp->nlp_DID) { 830fcf3ce44SJohn Forte if (prevp == NULL) { 831fcf3ce44SJohn Forte port->node_table[hash] = np->nlp_list_next; 832fcf3ce44SJohn Forte } else { 833fcf3ce44SJohn Forte prevp->nlp_list_next = np->nlp_list_next; 834fcf3ce44SJohn Forte } 835fcf3ce44SJohn Forte 836fcf3ce44SJohn Forte if (port->node_count) { 837fcf3ce44SJohn Forte port->node_count--; 838fcf3ce44SJohn Forte } 839291a2b48SSukumar Swaminathan 840fcf3ce44SJohn Forte wwn = (uint8_t *)&ndlp->nlp_portname; 841291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 842291a2b48SSukumar Swaminathan &emlxs_node_destroy_msg, "did=%06x " 843291a2b48SSukumar Swaminathan "rpi=%x wwpn=%02x%02x%02x%02x%02x%02x%02x%02x " 844291a2b48SSukumar Swaminathan "count=%d", ndlp->nlp_DID, ndlp->nlp_Rpi, wwn[0], 845291a2b48SSukumar Swaminathan wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], 846291a2b48SSukumar Swaminathan wwn[7], port->node_count); 847fcf3ce44SJohn Forte 848fcf3ce44SJohn Forte (void) emlxs_tx_node_flush(port, ndlp, 0, 1, 0); 849fcf3ce44SJohn Forte 850fcf3ce44SJohn Forte ndlp->nlp_active = 0; 85182527734SSukumar Swaminathan 85282527734SSukumar Swaminathan /* Break Node/RPI binding */ 85382527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 85482527734SSukumar Swaminathan rp = EMLXS_NODE_TO_RPI(hba, ndlp); 85582527734SSukumar Swaminathan ndlp->RPIp = NULL; 85682527734SSukumar Swaminathan 85782527734SSukumar Swaminathan if (rp) { 85882527734SSukumar Swaminathan rp->node = NULL; 85982527734SSukumar Swaminathan (void) emlxs_sli4_free_rpi(hba, rp); 86082527734SSukumar Swaminathan } 86182527734SSukumar Swaminathan } 86282527734SSukumar Swaminathan 863fcf3ce44SJohn Forte (void) emlxs_mem_put(hba, MEM_NLP, (uint8_t *)ndlp); 864fcf3ce44SJohn Forte 865fcf3ce44SJohn Forte break; 866fcf3ce44SJohn Forte } 867fcf3ce44SJohn Forte prevp = np; 868fcf3ce44SJohn Forte np = np->nlp_list_next; 869fcf3ce44SJohn Forte } 870fcf3ce44SJohn Forte rw_exit(&port->node_rwlock); 871fcf3ce44SJohn Forte 872fcf3ce44SJohn Forte return; 873fcf3ce44SJohn Forte 87482527734SSukumar Swaminathan } /* emlxs_node_rm() */ 875