#include <emlxs.h>
EMLXS_MSG_DEF(EMLXS_NODE_C);
static void emlxs_node_add(emlxs_port_t *, NODELIST *);
static int emlxs_node_match_did(emlxs_port_t *, NODELIST *, uint32_t);
extern void
emlxs_node_close(emlxs_port_t *port, NODELIST *ndlp, uint32_t channelno,
int32_t timeout)
{
emlxs_hba_t *hba = HBA;
emlxs_config_t *cfg = &CFG;
CHANNEL *cp;
NODELIST *prev;
uint32_t offline = 0;
mutex_enter(&EMLXS_TX_CHANNEL_LOCK);
if (!ndlp || !ndlp->nlp_active) {
mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
return;
}
if (timeout == -1) {
if (cfg[CFG_OFFLINE_TIMEOUT].current) {
timeout = cfg[CFG_OFFLINE_TIMEOUT].current;
offline = 1;
} else {
timeout = 0;
}
}
if (channelno == hba->channel_ip) {
ndlp->nlp_Xri = 0;
}
if (ndlp->nlp_flag[channelno] & NLP_CLOSED) {
if (ndlp->nlp_flag[channelno] & NLP_OFFLINE) {
mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
return;
}
if (offline) {
ndlp->nlp_tics[channelno] = hba->timer_tics + timeout;
ndlp->nlp_flag[channelno] |= NLP_OFFLINE;
mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_closed_msg,
"node=%p did=%06x channel=%d. offline=%d update.",
ndlp, ndlp->nlp_DID, channelno, timeout);
} else if (timeout) {
ndlp->nlp_tics[channelno] = hba->timer_tics + timeout;
mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_closed_msg,
"node=%p did=%06x channel=%d. timeout=%d update.",
ndlp, ndlp->nlp_DID, channelno, timeout);
} else {
mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
}
return;
}
ndlp->nlp_flag[channelno] |= NLP_CLOSED;
if (offline) {
ndlp->nlp_tics[channelno] = hba->timer_tics + timeout;
ndlp->nlp_flag[channelno] |= NLP_OFFLINE;
EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_closed_msg,
"node=%p did=%06x channel=%d. offline=%d set.",
ndlp, ndlp->nlp_DID, channelno, timeout);
} else if (timeout) {
ndlp->nlp_tics[channelno] = hba->timer_tics + timeout;
EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_closed_msg,
"node=%p did=%06x channel=%d. timeout=%d set.",
ndlp, ndlp->nlp_DID, channelno, timeout);
} else {
EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_closed_msg,
"node=%p did=%06x channel=%d.",
ndlp, ndlp->nlp_DID, channelno);
}
if (ndlp->nlp_next[channelno]) {
cp = &hba->chan[channelno];
if (cp->nodeq.q_first == (void *)ndlp &&
cp->nodeq.q_last == (void *)ndlp) {
cp->nodeq.q_last = NULL;
cp->nodeq.q_first = NULL;
cp->nodeq.q_cnt = 0;
} else if (cp->nodeq.q_first == (void *)ndlp) {
cp->nodeq.q_first = ndlp->nlp_next[channelno];
((NODELIST *)cp->nodeq.q_last)->nlp_next[channelno] =
cp->nodeq.q_first;
cp->nodeq.q_cnt--;
} else {
prev = ndlp;
while (prev->nlp_next[channelno] != ndlp) {
prev = prev->nlp_next[channelno];
}
prev->nlp_next[channelno] = ndlp->nlp_next[channelno];
if (cp->nodeq.q_last == (void *)ndlp) {
cp->nodeq.q_last = (void *)prev;
}
cp->nodeq.q_cnt--;
}
ndlp->nlp_next[channelno] = NULL;
}
mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
return;
}
extern void
emlxs_node_timeout(emlxs_port_t *port, NODELIST *ndlp, uint32_t channelno)
{
emlxs_hba_t *hba = HBA;
mutex_enter(&EMLXS_TX_CHANNEL_LOCK);
if (!ndlp || !ndlp->nlp_active) {
mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
return;
}
if (!(ndlp->nlp_flag[channelno] & NLP_OFFLINE)) {
mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_timeout_msg,
"node=%p did=%06x channel=%d Opening.", ndlp, ndlp->nlp_DID,
channelno);
emlxs_node_open(port, ndlp, channelno);
return;
}
ndlp->nlp_tics[channelno] = 0;
mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_timeout_msg,
"node=%p did=%06x channel=%d. Flushing.", ndlp, ndlp->nlp_DID,
channelno);
(void) emlxs_tx_node_flush(port, ndlp, &hba->chan[channelno], 0, 0);
(void) emlxs_chipq_node_flush(port, &hba->chan[channelno], ndlp, 0);
return;
}
extern void
emlxs_node_open(emlxs_port_t *port, NODELIST *ndlp, uint32_t channelno)
{
emlxs_hba_t *hba = HBA;
CHANNEL *cp;
uint32_t found;
NODELIST *nlp;
MAILBOXQ *mbox;
uint32_t i;
int rc;
mutex_enter(&EMLXS_TX_CHANNEL_LOCK);
if (!ndlp || !ndlp->nlp_active) {
mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
return;
}
if (!(ndlp->nlp_flag[channelno] & NLP_CLOSED)) {
mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
return;
}
ndlp->nlp_flag[channelno] &= ~(NLP_CLOSED|NLP_OFFLINE);
ndlp->nlp_tics[channelno] = 0;
if ((ndlp->nlp_ptx[channelno].q_first ||
ndlp->nlp_tx[channelno].q_first) && !ndlp->nlp_next[channelno]) {
cp = &hba->chan[channelno];
if (cp->nodeq.q_first) {
((NODELIST *)cp->nodeq.q_last)->nlp_next[channelno] =
(uint8_t *)ndlp;
ndlp->nlp_next[channelno] = cp->nodeq.q_first;
if (!ndlp->nlp_base) {
cp->nodeq.q_last = (uint8_t *)ndlp;
} else {
cp->nodeq.q_first = (uint8_t *)ndlp;
}
cp->nodeq.q_cnt++;
} else {
cp->nodeq.q_first = (uint8_t *)ndlp;
cp->nodeq.q_last = (uint8_t *)ndlp;
ndlp->nlp_next[channelno] = ndlp;
cp->nodeq.q_cnt = 1;
}
}
mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_opened_msg,
"node=%p did=%06x rpi=%d channel=%d", ndlp, ndlp->nlp_DID,
ndlp->nlp_Rpi, channelno);
if ((hba->state == FC_LINK_UP) && (channelno == hba->channel_fcp)) {
if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
goto done;
}
found = 0;
rw_enter(&port->node_rwlock, RW_READER);
for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
nlp = port->node_table[i];
while (nlp != NULL) {
if ((nlp->nlp_fcp_info & NLP_FCP_2_DEVICE) &&
(nlp->nlp_flag[hba->channel_fcp] &
NLP_CLOSED)) {
found = 1;
break;
}
nlp = nlp->nlp_list_next;
}
if (found) {
break;
}
}
rw_exit(&port->node_rwlock);
if (!found) {
if ((mbox = (MAILBOXQ *)emlxs_mem_get(hba,
MEM_MBOX))) {
mutex_enter(&EMLXS_PORT_LOCK);
if (hba->state != FC_LINK_UP) {
mutex_exit(&EMLXS_PORT_LOCK);
emlxs_mem_put(hba, MEM_MBOX,
(void *)mbox);
goto done;
}
EMLXS_STATE_CHANGE_LOCKED(hba, FC_CLEAR_LA);
hba->discovery_timer = 0;
mutex_exit(&EMLXS_PORT_LOCK);
emlxs_mb_clear_la(hba, mbox);
rc = EMLXS_SLI_ISSUE_MBOX_CMD(hba,
mbox, MBX_NOWAIT, 0);
if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) {
emlxs_mem_put(hba, MEM_MBOX,
(void *)mbox);
}
} else {
emlxs_node_close(port, ndlp, channelno, 5);
return;
}
}
}
done:
mutex_enter(&EMLXS_PKT_LOCK);
cv_broadcast(&EMLXS_PKT_CV);
mutex_exit(&EMLXS_PKT_LOCK);
return;
}
static int
emlxs_node_match_did(emlxs_port_t *port, NODELIST *ndlp, uint32_t did)
{
D_ID mydid;
D_ID odid;
D_ID ndid;
if (ndlp->nlp_DID == did)
return (1);
mydid.un.word = port->did;
if ((mydid.un.b.domain == 0) && (mydid.un.b.area == 0)) {
goto out;
}
ndid.un.word = did;
odid.un.word = ndlp->nlp_DID;
if (ndid.un.b.id == odid.un.b.id) {
if ((mydid.un.b.domain == ndid.un.b.domain) &&
(mydid.un.b.area == ndid.un.b.area)) {
ndid.un.word = ndlp->nlp_DID;
odid.un.word = did;
if ((ndid.un.b.domain == 0) && (ndid.un.b.area == 0)) {
return (1);
}
goto out;
}
ndid.un.word = ndlp->nlp_DID;
if ((mydid.un.b.domain == ndid.un.b.domain) &&
(mydid.un.b.area == ndid.un.b.area)) {
odid.un.word = ndlp->nlp_DID;
ndid.un.word = did;
if ((ndid.un.b.domain == 0) && (ndid.un.b.area == 0)) {
return (1);
}
}
}
out:
return (0);
}
extern NODELIST *
emlxs_node_find_mac(emlxs_port_t *port, uint8_t *mac)
{
NODELIST *nlp;
uint32_t i;
rw_enter(&port->node_rwlock, RW_READER);
for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
nlp = port->node_table[i];
while (nlp != NULL) {
if ((nlp->nlp_portname.IEEE[0] == mac[0])) {
if ((nlp->nlp_DID != BCAST_DID) &&
((nlp->nlp_DID & FABRIC_DID_MASK) ==
FABRIC_DID_MASK)) {
nlp = (NODELIST *)nlp->nlp_list_next;
continue;
}
if ((nlp->nlp_portname.IEEE[1] == mac[1]) &&
(nlp->nlp_portname.IEEE[2] == mac[2]) &&
(nlp->nlp_portname.IEEE[3] == mac[3]) &&
(nlp->nlp_portname.IEEE[4] == mac[4]) &&
(nlp->nlp_portname.IEEE[5] == mac[5])) {
rw_exit(&port->node_rwlock);
return (nlp);
}
}
nlp = (NODELIST *)nlp->nlp_list_next;
}
}
rw_exit(&port->node_rwlock);
EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_not_found_msg,
"find: MAC=%02x%02x%02x%02x%02x%02x", mac[0], mac[1], mac[2],
mac[3], mac[4], mac[5]);
return (NULL);
}
extern NODELIST *
emlxs_node_find_did(emlxs_port_t *port, uint32_t did, uint32_t lock)
{
emlxs_hba_t *hba = HBA;
NODELIST *nlp;
uint32_t hash;
if ((did == 0) && (!(hba->flag & FC_LOOPBACK_MODE))) {
return ((NODELIST *)0);
}
if (did & 0xff000000) {
return ((NODELIST *)0);
}
if (did == BCAST_DID) {
return (&port->node_base);
}
#ifdef MENLO_SUPPORT
if (did == EMLXS_MENLO_DID) {
return (&port->node_base);
}
#endif
if (did == port->did && !(hba->flag & FC_LOOPBACK_MODE)) {
return (&port->node_base);
}
if ((did == SCR_DID)) {
did = FABRIC_DID;
}
if (lock) {
rw_enter(&port->node_rwlock, RW_READER);
}
hash = EMLXS_DID_HASH(did);
nlp = port->node_table[hash];
while (nlp != NULL) {
if (nlp->nlp_DID == did) {
if (lock) {
rw_exit(&port->node_rwlock);
}
return (nlp);
}
else if (emlxs_node_match_did(port, nlp, did)) {
if (lock) {
rw_exit(&port->node_rwlock);
}
return (nlp);
}
nlp = (NODELIST *)nlp->nlp_list_next;
}
if (lock) {
rw_exit(&port->node_rwlock);
}
EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_not_found_msg, "find: did=%x",
did);
return ((NODELIST *)0);
}
extern NODELIST *
emlxs_node_find_rpi(emlxs_port_t *port, uint32_t rpi)
{
NODELIST *nlp;
uint32_t i;
rw_enter(&port->node_rwlock, RW_READER);
for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
nlp = port->node_table[i];
while (nlp != NULL) {
if (nlp->nlp_Rpi == rpi) {
rw_exit(&port->node_rwlock);
return (nlp);
}
nlp = (NODELIST *)nlp->nlp_list_next;
}
}
rw_exit(&port->node_rwlock);
EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_not_found_msg, "find: rpi=%d",
rpi);
return ((NODELIST *)0);
}
extern NODELIST *
emlxs_node_find_wwpn(emlxs_port_t *port, uint8_t *wwpn, uint32_t lock)
{
NODELIST *nlp;
uint32_t i;
uint32_t j;
uint8_t *bptr1;
uint8_t *bptr2;
if (lock) {
rw_enter(&port->node_rwlock, RW_READER);
}
for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
nlp = port->node_table[i];
while (nlp != NULL) {
bptr1 = (uint8_t *)&nlp->nlp_portname;
bptr1 += 7;
bptr2 = (uint8_t *)wwpn;
bptr2 += 7;
for (j = 0; j < 8; j++) {
if (*bptr1-- != *bptr2--) {
break;
}
}
if (j == 8) {
if (lock) {
rw_exit(&port->node_rwlock);
}
return (nlp);
}
nlp = (NODELIST *)nlp->nlp_list_next;
}
}
if (lock) {
rw_exit(&port->node_rwlock);
}
EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_not_found_msg,
"find: wwpn=%02x%02x%02x%02x%02x%02x%02x%02x", wwpn[0], wwpn[1],
wwpn[2], wwpn[3], wwpn[4], wwpn[5], wwpn[6], wwpn[7]);
return ((NODELIST *)0);
}
extern NODELIST *
emlxs_node_find_index(emlxs_port_t *port, uint32_t index,
uint32_t nports_only)
{
NODELIST *nlp;
uint32_t i;
uint32_t count;
rw_enter(&port->node_rwlock, RW_READER);
if (index > port->node_count - 1) {
rw_exit(&port->node_rwlock);
return (NULL);
}
count = 0;
for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
nlp = port->node_table[i];
while (nlp != NULL) {
if (nports_only &&
(nlp->nlp_DID & 0xFFF000) == 0xFFF000) {
nlp = (NODELIST *)nlp->nlp_list_next;
continue;
}
if (count == index) {
rw_exit(&port->node_rwlock);
return (nlp);
}
nlp = (NODELIST *)nlp->nlp_list_next;
count++;
}
}
rw_exit(&port->node_rwlock);
EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_not_found_msg, "find: index=%d",
index);
return ((NODELIST *)0);
}
extern uint32_t
emlxs_nport_count(emlxs_port_t *port)
{
NODELIST *nlp;
uint32_t i;
uint32_t nport_count = 0;
rw_enter(&port->node_rwlock, RW_READER);
for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
nlp = port->node_table[i];
while (nlp != NULL) {
if ((nlp->nlp_DID & 0xFFF000) != 0xFFF000) {
nport_count++;
}
nlp = (NODELIST *)nlp->nlp_list_next;
}
}
rw_exit(&port->node_rwlock);
return (nport_count);
}
extern void
emlxs_node_destroy_all(emlxs_port_t *port)
{
emlxs_hba_t *hba = HBA;
NODELIST *next;
NODELIST *ndlp;
RPIobj_t *rpip;
uint8_t *wwn;
uint32_t i;
rw_enter(&port->node_rwlock, RW_WRITER);
for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
ndlp = port->node_table[i];
port->node_table[i] = 0;
while (ndlp != NULL) {
next = ndlp->nlp_list_next;
ndlp->nlp_list_next = NULL;
ndlp->nlp_list_prev = NULL;
ndlp->nlp_active = 0;
if (port->node_count) {
port->node_count--;
}
wwn = (uint8_t *)&ndlp->nlp_portname;
EMLXS_MSGF(EMLXS_CONTEXT,
&emlxs_node_destroy_msg, "did=%06x "
"rpi=%d wwpn=%02x%02x%02x%02x%02x%02x%02x%02x "
"count=%d", ndlp->nlp_DID, ndlp->nlp_Rpi, wwn[0],
wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6],
wwn[7], port->node_count);
(void) emlxs_tx_node_flush(port, ndlp, 0, 0, 0);
if (ndlp->rpip) {
rpip = ndlp->rpip;
ndlp->rpip = NULL;
rpip->node = NULL;
(void) emlxs_rpi_free_notify(port, rpip);
}
emlxs_mem_put(hba, MEM_NLP, (void *)ndlp);
ndlp = next;
}
}
port->node_count = 0;
rw_exit(&port->node_rwlock);
mutex_enter(&EMLXS_PORT_LOCK);
port->node_base.nlp_list_next = NULL;
port->node_base.nlp_list_prev = NULL;
port->node_base.nlp_active = 1;
mutex_exit(&EMLXS_PORT_LOCK);
(void) emlxs_tx_node_flush(port, &port->node_base, 0, 1, 0);
(void) emlxs_chipq_node_flush(port, 0, &port->node_base, 0);
return;
}
extern NODELIST *
emlxs_node_create(emlxs_port_t *port, uint32_t did, uint32_t rpi, SERV_PARM *sp)
{
emlxs_hba_t *hba = HBA;
NODELIST *ndlp, *ndlp_wwn;
uint8_t *wwn;
emlxs_vvl_fmt_t vvl;
RPIobj_t *rpip;
rw_enter(&port->node_rwlock, RW_WRITER);
ndlp = emlxs_node_find_did(port, did, 0);
ndlp_wwn = emlxs_node_find_wwpn(port, (uint8_t *)&sp->portName, 0);
if (ndlp_wwn && (ndlp != ndlp_wwn)) {
bzero((uint8_t *)&ndlp_wwn->nlp_nodename, sizeof (NAME_TYPE));
bzero((uint8_t *)&ndlp_wwn->nlp_portname, sizeof (NAME_TYPE));
}
if (ndlp) {
ndlp->nlp_Rpi = (uint16_t)rpi;
ndlp->nlp_DID = did;
bcopy((uint8_t *)sp, (uint8_t *)&ndlp->sparm,
sizeof (SERV_PARM));
bcopy((uint8_t *)&sp->nodeName,
(uint8_t *)&ndlp->nlp_nodename,
sizeof (NAME_TYPE));
bcopy((uint8_t *)&sp->portName,
(uint8_t *)&ndlp->nlp_portname,
sizeof (NAME_TYPE));
if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
rpip = emlxs_rpi_find(port, rpi);
if (rpip) {
rpip->node = ndlp;
ndlp->rpip = rpip;
} else {
ndlp->rpip = NULL;
EMLXS_MSGF(EMLXS_CONTEXT,
&emlxs_node_create_msg,
"Unable to find RPI. did=%x rpi=%d",
did, rpi);
}
} else {
ndlp->rpip = NULL;
}
wwn = (uint8_t *)&ndlp->nlp_portname;
EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_update_msg,
"node=%p did=%06x rpi=%d "
"wwpn=%02x%02x%02x%02x%02x%02x%02x%02x",
ndlp, ndlp->nlp_DID, ndlp->nlp_Rpi, wwn[0],
wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], wwn[7]);
goto done;
}
ndlp = (NODELIST *)emlxs_mem_get(hba, MEM_NLP);
if (ndlp) {
ndlp->nlp_Rpi = (uint16_t)rpi;
ndlp->nlp_DID = did;
bcopy((uint8_t *)sp, (uint8_t *)&ndlp->sparm,
sizeof (SERV_PARM));
bcopy((uint8_t *)&sp->nodeName,
(uint8_t *)&ndlp->nlp_nodename,
sizeof (NAME_TYPE));
bcopy((uint8_t *)&sp->portName,
(uint8_t *)&ndlp->nlp_portname,
sizeof (NAME_TYPE));
ndlp->nlp_active = 1;
ndlp->nlp_flag[hba->channel_ct] |= NLP_CLOSED;
ndlp->nlp_flag[hba->channel_els] |= NLP_CLOSED;
ndlp->nlp_flag[hba->channel_fcp] |= NLP_CLOSED;
ndlp->nlp_flag[hba->channel_ip] |= NLP_CLOSED;
if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
rpip = emlxs_rpi_find(port, rpi);
if (rpip) {
rpip->node = ndlp;
ndlp->rpip = rpip;
} else {
ndlp->rpip = NULL;
EMLXS_MSGF(EMLXS_CONTEXT,
&emlxs_node_create_msg,
"Unable to find RPI. did=%x rpi=%d",
did, rpi);
}
} else {
ndlp->rpip = NULL;
}
#ifdef NODE_THROTTLE_SUPPORT
emlxs_node_throttle_set(port, ndlp);
#endif
emlxs_node_add(port, ndlp);
goto done;
}
rw_exit(&port->node_rwlock);
wwn = (uint8_t *)&sp->portName;
EMLXS_MSGF(EMLXS_CONTEXT,
&emlxs_node_create_failed_msg,
"Unable to allocate node. did=%06x "
"wwpn=%02x%02x%02x%02x%02x%02x%02x%02x",
did, wwn[0], wwn[1], wwn[2],
wwn[3], wwn[4], wwn[5], wwn[6], wwn[7]);
return (NULL);
done:
rw_exit(&port->node_rwlock);
if (sp->VALID_VENDOR_VERSION) {
bcopy((caddr_t *)&sp->vendorVersion[0],
(caddr_t *)&vvl, sizeof (emlxs_vvl_fmt_t));
vvl.un0.word0 = LE_SWAP32(vvl.un0.word0);
vvl.un1.word1 = LE_SWAP32(vvl.un1.word1);
if ((vvl.un0.w0.oui == 0x0000C9) &&
(vvl.un1.w1.vport)) {
ndlp->nlp_fcp_info |= NLP_EMLX_VPORT;
}
}
emlxs_node_open(port, ndlp, hba->channel_ct);
emlxs_node_open(port, ndlp, hba->channel_els);
emlxs_node_open(port, ndlp, hba->channel_ip);
emlxs_node_open(port, ndlp, hba->channel_fcp);
EMLXS_SET_DFC_STATE(ndlp, NODE_LOGIN);
return (ndlp);
}
static void
emlxs_node_add(emlxs_port_t *port, NODELIST *ndlp)
{
NODELIST *np;
uint8_t *wwn;
uint32_t hash;
hash = EMLXS_DID_HASH(ndlp->nlp_DID);
np = port->node_table[hash];
port->node_table[hash] = ndlp;
if (!np) {
ndlp->nlp_list_next = NULL;
} else {
ndlp->nlp_list_next = np;
}
port->node_count++;
wwn = (uint8_t *)&ndlp->nlp_portname;
EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_msg,
"node=%p did=%06x rpi=%d wwpn=%02x%02x%02x%02x%02x%02x%02x%02x "
"count=%d", ndlp, ndlp->nlp_DID, ndlp->nlp_Rpi, wwn[0], wwn[1],
wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], wwn[7], port->node_count);
return;
}
extern void
emlxs_node_rm(emlxs_port_t *port, NODELIST *ndlp)
{
emlxs_hba_t *hba = HBA;
NODELIST *np;
NODELIST *prevp;
RPIobj_t *rpip;
uint8_t *wwn;
uint32_t hash;
rw_enter(&port->node_rwlock, RW_WRITER);
hash = EMLXS_DID_HASH(ndlp->nlp_DID);
np = port->node_table[hash];
prevp = NULL;
while (np != NULL) {
if (np->nlp_DID == ndlp->nlp_DID) {
if (prevp == NULL) {
port->node_table[hash] = np->nlp_list_next;
} else {
prevp->nlp_list_next = np->nlp_list_next;
}
if (port->node_count) {
port->node_count--;
}
wwn = (uint8_t *)&ndlp->nlp_portname;
EMLXS_MSGF(EMLXS_CONTEXT,
&emlxs_node_destroy_msg, "did=%06x "
"rpi=%d wwpn=%02x%02x%02x%02x%02x%02x%02x%02x "
"count=%d", ndlp->nlp_DID, ndlp->nlp_Rpi, wwn[0],
wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6],
wwn[7], port->node_count);
(void) emlxs_tx_node_flush(port, ndlp, 0, 1, 0);
ndlp->nlp_active = 0;
if (ndlp->rpip) {
rpip = ndlp->rpip;
ndlp->rpip = NULL;
rpip->node = NULL;
(void) emlxs_rpi_free_notify(port, rpip);
}
emlxs_mem_put(hba, MEM_NLP, (void *)ndlp);
break;
}
prevp = np;
np = np->nlp_list_next;
}
rw_exit(&port->node_rwlock);
return;
}
extern void
emlxs_node_throttle_set(emlxs_port_t *port, NODELIST *ndlp)
{
emlxs_hba_t *hba = HBA;
emlxs_config_t *cfg = &CFG;
char prop[64];
char buf1[32];
uint32_t throttle;
throttle = (ndlp->nlp_fcp_info & NLP_FCP_TGT_DEVICE)?
cfg[CFG_TGT_DEPTH].current:0;
(void) snprintf(prop, sizeof (prop), "w%s-depth",
emlxs_wwn_xlate(buf1, sizeof (buf1),
(uint8_t *)&ndlp->nlp_portname));
throttle = (uint32_t)ddi_prop_get_int(DDI_DEV_T_ANY,
(void *)hba->dip, DDI_PROP_DONTPASS, prop, throttle);
(void) snprintf(prop, sizeof (prop), "%s%d-w%s-depth", DRIVER_NAME,
hba->ddiinst, emlxs_wwn_xlate(buf1, sizeof (buf1),
(uint8_t *)&ndlp->nlp_portname));
throttle = (uint32_t)ddi_prop_get_int(DDI_DEV_T_ANY,
(void *)hba->dip, DDI_PROP_DONTPASS, prop, throttle);
throttle = MIN(throttle, MAX_NODE_THROTTLE);
ndlp->io_throttle = throttle;
return;
}