Exemplo n.º 1
0
static void
emlxs_timer_check_heartbeat(emlxs_hba_t *hba)
{
    emlxs_port_t *port = &PPORT;
    MAILBOXQ *mbq;
    emlxs_config_t *cfg = &CFG;
    int rc;

    if (!cfg[CFG_HEARTBEAT_ENABLE].current) {
        return;
    }

    if (hba->timer_tics < hba->heartbeat_timer) {
        return;
    }

    hba->heartbeat_timer = hba->timer_tics + 5;

    /* Return if adapter interrupts have occurred */
    if (hba->heartbeat_flag) {
        hba->heartbeat_flag = 0;
        return;
    }
    /* No adapter interrupts have occured for 5 seconds now */

    /* Return if mailbox is busy */
    /* This means the mailbox timer routine is watching for problems */
    if (hba->mbox_timer) {
        return;
    }

    /* Return if heartbeat is still outstanding */
    if (hba->heartbeat_active) {
        return;
    }

    if ((mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1)) == 0) {
        EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
                   "Unable to allocate heartbeat mailbox.");
        return;
    }

    emlxs_mb_heartbeat(hba, mbq);
    hba->heartbeat_active = 1;

    rc =  EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
    if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) {
        (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq);
    }

    return;

} /* emlxs_timer_check_heartbeat() */
Exemplo n.º 2
0
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;

	/* If node needs servicing, then add it to the channel queues */
	mutex_enter(&EMLXS_TX_CHANNEL_LOCK);

	/* Return if node destroyed */
	if (!ndlp || !ndlp->nlp_active) {
		mutex_exit(&EMLXS_TX_CHANNEL_LOCK);

		return;
	}

	/* Return if node already open */
	if (!(ndlp->nlp_flag[channelno] & NLP_CLOSED)) {
		mutex_exit(&EMLXS_TX_CHANNEL_LOCK);

		return;
	}

	/* Set the node open (not closed) */
	ndlp->nlp_flag[channelno] &= ~(NLP_CLOSED|NLP_OFFLINE);

	/* Clear the timer */
	ndlp->nlp_tics[channelno] = 0;

	/*
	 * If the ptx or the tx queue needs servicing and
	 * the node is not already on the channel queue
	 */
	if ((ndlp->nlp_ptx[channelno].q_first ||
	    ndlp->nlp_tx[channelno].q_first) && !ndlp->nlp_next[channelno]) {
		cp = &hba->chan[channelno];

		/* If so, then add it to the channel queue */
		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 this is not the base node then */
			/* add it to the tail */
			if (!ndlp->nlp_base) {
				cp->nodeq.q_last = (uint8_t *)ndlp;
			} else {	/* Otherwise, add it to the head */

				/* The command node always gets priority */
				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 channel=%d", ndlp, ndlp->nlp_DID, channelno);

	/* If link attention needs to be cleared */
	if ((hba->state == FC_LINK_UP) && (channelno == hba->channel_fcp)) {
		if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
		/* re Think this code path. For SLI4 channel fcp == els */
			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
			    "ADD CODE to RESUME RPIs node=%p did=%06x chan=%d",
			    ndlp, ndlp->nlp_DID, channelno);

			goto done;
		}

		/* Scan to see if any FCP2 devices are still closed */
		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) {
			/* Clear link attention */
			if ((mbox = (MAILBOXQ *)emlxs_mem_get(hba,
			    MEM_MBOX, 1))) {
				mutex_enter(&EMLXS_PORT_LOCK);

				/*
				 * If state is not FC_LINK_UP, then either the
				 * link has gone down or a FC_CLEAR_LA has
				 * already been issued
				 */
				if (hba->state != FC_LINK_UP) {
					mutex_exit(&EMLXS_PORT_LOCK);
					(void) emlxs_mem_put(hba, MEM_MBOX,
					    (uint8_t *)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)) {
					(void) emlxs_mem_put(hba, MEM_MBOX,
					    (uint8_t *)mbox);
				}
			} else {
				/* Close the node and try again */
				/* in a few seconds */
				emlxs_node_close(port, ndlp, channelno, 5);
				return;
			}
		}
	}

done:

	/* Wake any sleeping threads */
	mutex_enter(&EMLXS_PKT_LOCK);
	cv_broadcast(&EMLXS_PKT_CV);
	mutex_exit(&EMLXS_PKT_LOCK);

	return;

} /* emlxs_node_open() */
Exemplo n.º 3
0
static void
emlxs_timer_check_discovery(emlxs_port_t *port)
{
    emlxs_hba_t *hba = HBA;
    emlxs_config_t *cfg = &CFG;
    int32_t send_clear_la;
    uint32_t found;
    uint32_t i;
    NODELIST *nlp;
    MAILBOXQ *mbox;
    int rc;

    if (!cfg[CFG_TIMEOUT_ENABLE].current) {
        return;
    }

    /* Check the discovery timer for expiration */
    send_clear_la = 0;
    mutex_enter(&EMLXS_PORT_LOCK);
    while (hba->discovery_timer &&
            (hba->timer_tics >= hba->discovery_timer) &&
            (hba->state == FC_LINK_UP)) {
        send_clear_la = 1;

        /* Perform a flush on fcp2 nodes that are still closed */
        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) {
            break;
        }

        EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_missing_msg,
                   "FCP2 device (did=%06x) missing. Flushing...",
                   nlp->nlp_DID);

        mutex_exit(&EMLXS_PORT_LOCK);

        (void) emlxs_mb_unreg_did(port, nlp->nlp_DID, NULL, NULL, NULL);

        mutex_enter(&EMLXS_PORT_LOCK);

    }
    mutex_exit(&EMLXS_PORT_LOCK);

    /* Try to send clear link attention, if needed */
    if ((send_clear_la == 1) &&
            (mbox = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) {
        mutex_enter(&EMLXS_PORT_LOCK);

        /*
         * If state is not FC_LINK_UP, then either the link has gone
         * down or a FC_CLEAR_LA has already been issued
         */
        if (hba->state != FC_LINK_UP) {
            mutex_exit(&EMLXS_PORT_LOCK);
            (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbox);
        } else {
            /* Change state and clear discovery timer */
            EMLXS_STATE_CHANGE_LOCKED(hba, FC_CLEAR_LA);

            hba->discovery_timer = 0;

            mutex_exit(&EMLXS_PORT_LOCK);

            /* Prepare and send the CLEAR_LA command */
            emlxs_mb_clear_la(hba, mbox);

            rc = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_NOWAIT, 0);
            if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) {
                (void) emlxs_mem_put(hba, MEM_MBOX,
                                     (uint8_t *)mbox);
            }
        }
    }

    return;

} /* emlxs_timer_check_discovery()  */