/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 2004-2012 Emulex. All rights reserved.
* Use is subject to license terms.
*/
#include <emlxs.h>
/* Timer period in seconds */
#ifdef DHCHAP_SUPPORT
#endif /* DHCHAP_SUPPORT */
static void emlxs_timer(void *arg);
#ifdef TX_WATCHDOG
#endif /* TX_WATCHDOG */
extern clock_t
{
/* Set thread timeout */
} else {
time = -1;
}
return (time);
} /* emlxs_timeout() */
static void
{
return;
}
/* Only one timer thread is allowed */
return;
}
/* Check if a kill request has been made */
hba->timer_tics = 0;
return;
}
/* Check io_active count (Safety net) */
}
/* Perform standard checks */
/* Restart the timer */
/* If timer is still enabled, restart it */
} else {
}
return;
} /* emlxs_timer() */
extern void
{
uint32_t i;
/* Exit if we are still initializing */
return;
}
/* Check SLI level timeouts */
/* Check event queue */
/* Check heartbeat timer */
/* Check fw update timer */
#ifdef IDLE_TIMER
#endif /* IDLE_TIMER */
/* Check for loopback timeouts */
/* Check for packet timeouts */
if (rc) {
/* Link or adapter is being reset */
return;
}
/* Check for linkup timeout */
/* Check the ports */
for (i = 0; i < MAX_VPORTS; i++) {
continue;
}
/* Check for node gate timeouts */
/* Check for clean address bit delay timeout */
/* Check for tape discovery timeout */
/* Check for UB timeouts */
#ifdef DHCHAP_SUPPORT
/* Check for DHCHAP authentication timeouts */
#endif /* DHCHAP_SUPPORT */
}
/* Check memory pools */
/* Check for IO channel service timeouts */
/* Always do this last */
return;
} /* emlxs_timer_checks() */
extern void
{
return;
}
/* Restart the timer */
hba->timer_flags = 0;
}
} /* emlxs_timer_start() */
extern void
{
return;
}
}
return;
} /* emlxs_timer_stop() */
static uint32_t
{
Q tmo;
Q abort;
return (0);
}
return (0);
}
/*
* We must hold the locks here because we never know when an iocb
* will be removed out from under us
*/
/* Scan the tx queues for each active node on the channel */
/* Get the first node */
while (nlp) {
/* Scan the node's priority tx queue */
while (iocbq) {
/* Check if iocb has timed out */
/* iocb timed out, now deque it */
}
} else {
}
/* Add this iocb to our local */
/* timout queue */
/*
* This way we don't hold the TX_CHANNEL
* lock too long
*/
} else {
}
} else {
}
} /* while (iocbq) */
/* Scan the node's tx queue */
while (iocbq) {
/* Check if iocb has timed out */
/* iocb timed out, now deque it */
}
} else {
}
/* Add this iocb to our local */
/* timout queue */
/*
* This way we don't hold the TX_CHANNEL
* lock too long
*/
} else {
}
} else {
}
} /* while (iocbq) */
} else {
}
} /* while (nlp) */
} /* end of for */
/* Now cleanup the iocb's */
while (iocbq) {
/* Free the IoTag and the bmp */
} else {
(void) emlxs_unregister_pkt(
}
}
} /* end of while */
/* Now complete the transmit timeouts outside the locks */
while (iocbq) {
/* Save the next iocbq for now */
/* Unlink this iocbq */
/* Get the pkt */
if (sbp) {
/* Warning: Some FCT sbp's don't have */
/* fc_packet objects */
"TXQ abort: sbp=%p iotag=%d tmo=%d", sbp,
IOERR_ABORT_TIMEOUT, 1);
} else {
IOERR_LINK_DOWN, 1);
}
}
} /* end of while */
/* Now check the chip */
/* Check the HBA for outstanding IOs */
rc = 0;
continue;
}
/* Check if IO is valid */
"timer_check_pkts: Invalid IO found. iotag=%d",
iotag);
continue;
}
if (rc) {
break;
}
}
}
/* Now put the iocb's on the tx queue */
while (iocbq) {
/* Save the next iocbq for now */
/* Unlink this iocbq */
/* Send this iocbq */
}
/* Now trigger IO channel service to send these abort iocbq */
continue;
}
}
if (rc == 1) {
/* If a link reset or port reset is already requested, exit */
/* Spawn a thread to reset the link */
NULL);
goto exit;
}
} else if (rc == 2) {
/* If a port reset is already requested, exit */
/* Spawn a thread to reset the adapter */
NULL);
goto exit;
}
}
exit:
return (rc);
} /* emlxs_timer_check_pkts() */
static void
{
return;
}
logit = 0;
/* Check for channel timeout now */
/* Check if there is work to do on channel and */
/* the link is still up */
logit = 1;
}
} else {
}
}
if (logit) {
"IO Channel %d cnt=%d,%d",
}
/*
* If IO channel flag is set, request iocb servicing
* here to send any iocb's that may still be queued
*/
}
}
return;
} /* emlxs_timer_check_channels() */
static void
{
uint32_t i;
for (;;) {
/* Check node gate flag for expiration */
found = 0;
/*
* We need to lock, scan, and unlock because we can't hold the
* lock while we call node_open
*/
for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
#ifdef NODE_THROTTLE_SUPPORT
/* Check io_active count (Safety net) */
"timer_check_nodes: did=%06x "
"io_active=0x%x. Reset to zero.",
}
#endif /* NODE_THROTTLE_SUPPORT */
for (channelno = 0;
channelno++) {
/* Check if the node timer is active */
/* and if timer has expired */
(hba->timer_tics >=
/* If so, set the flag and */
/* break out */
found = 1;
break;
}
}
if (nlp->nlp_force_rscn &&
nlp->nlp_force_rscn = 0;
/*
* Generate an RSCN to
* wakeup ULP
*/
(void) emlxs_generate_rscn(port,
}
if (found) {
break;
}
}
if (found) {
break;
}
}
if (!found) {
break;
}
}
} /* emlxs_timer_check_nodes() */
static void
{
return;
}
/* Check the loopback timer for expiration */
return;
}
hba->loopback_tics = 0;
reset = 1;
}
if (reset) {
"LOOPBACK_MODE: Expired. Resetting...");
}
return;
} /* emlxs_timer_check_loopback() */
static void
{
/* Check if all mbox commands from previous activity are processed */
return;
}
}
/* Check the linkup timer for expiration */
linkup = 0;
hba->linkup_timer = 0;
/* Make sure link is still ready */
linkup = 1;
}
}
/* Make the linkup callback */
if (linkup) {
}
return;
} /* emlxs_timer_check_linkup() */
static void
{
int rc;
return;
}
return;
}
/* 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;
}
"Unable to allocate heartbeat mailbox.");
return;
}
}
return;
} /* emlxs_timer_check_heartbeat() */
static void
{
return;
}
return;
}
"To trigger an update, a manual HBA or link reset "
"using emlxadm is required.",
(sizeof (msgbuf)-1));
} else {
"To trigger an update, a manual HBA or link reset "
"using luxadm, fcadm, or emlxadm is required.",
(sizeof (msgbuf)-1));
}
/* Force message to console */
"^%s%d: Firmware update required.\n\t(%s)\n",
/* Set timer for 24 hours */
return;
} /* emlxs_timer_check_fw_update() */
static void
{
uint32_t i;
int rc;
return;
}
/* Check the discovery timer for expiration */
send_clear_la = 0;
while (hba->discovery_timer &&
send_clear_la = 1;
/* Perform a flush on fcp2 nodes that are still closed */
found = 0;
for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
NLP_CLOSED)) {
found = 1;
break;
}
}
if (found) {
break;
}
}
if (!found) {
break;
}
"FCP2 device (did=%06x) missing. Flushing...",
}
/* Try to send clear link attention, if needed */
/*
* If state is not FC_LINK_UP, then either the link has gone
* down or a FC_CLEAR_LA has already been issued
*/
} else {
/* Change state and clear discovery timer */
hba->discovery_timer = 0;
/* Prepare and send the CLEAR_LA command */
}
}
}
return;
} /* emlxs_timer_check_discovery() */
static void
{
if (port->clean_address_timer &&
return;
}
port->clean_address_timer = 0;
if (!sbp) {
return;
}
port->clean_address_sbp = 0;
"Clean Address timeout: sid=%x prev=%x RATOV %d",
/* Deferred completion of this pkt until */
/* login is complete */
return;
}
IOERR_NO_RESOURCES, 1);
return;
} /* emlxs_timer_check_clean_address() */
extern void
{
port->clean_address_timer = 0;
if (!sbp) {
return;
}
port->clean_address_sbp = 0;
"Clean Address cancel: sid=%x prev=%x RATOV %d",
IOERR_LINK_DOWN, 1);
} /* emlxs_timer_cancel_clean_address() */
static void
{
uint32_t i;
return;
}
/* Check the unsolicited buffers */
while (ulistp) {
/* Check buffers in this pool */
for (i = 0; i < ulistp->pool_nentries; i++) {
continue;
}
/* If buffer has timed out, print message and */
/* increase timeout */
hba->timer_tics) {
"Stale UB buffer detected (%d mins): "
"buffer=%p (%x,%x,%x,%x)",
/* Increase timeout period */
/* If timeout was 5 mins or less, */
/* increase it to 10 mins */
}
/* If timeout was 10 mins or less, */
/* increase it to 30 mins */
}
/* Otherwise double it. */
else {
}
}
}
}
return;
} /* emlxs_timer_check_ub() */
/* EMLXS_FCTAB_LOCK must be held to call this */
static uint32_t
{
/* Warning: Some FCT sbp's don't have fc_packet objects */
switch (sbp->abort_attempts) {
case 0:
/* Create the abort IOCB */
"chipQ: 1:Aborting. sbp=%p iotag=%d tmo=%d "
"flags=%x",
iocbq =
/* The adapter will make 2 attempts to send ABTS */
/* with 2*ratov timeout each time */
} else {
"chipQ: 1:Closing. sbp=%p iotag=%d tmo=%d "
"flags=%x",
iocbq =
}
/* set the flags */
rc = 0;
break;
case 1:
iocbq =
cp);
rc = 0;
break;
case 2:
"chipQ: 3:Resetting link. sbp=%p iotag=%d", sbp,
rc = 1;
break;
default:
"chipQ: %d:Resetting adapter. sbp=%p iotag=%d",
rc = 2;
break;
}
sbp->abort_attempts++;
if (iocbq) {
} else {
}
}
return (rc);
} /* emlxs_pkt_chip_timeout() */
static void
{
uint32_t i;
return;
}
return;
}
for (i = 0; i < FC_MAX_SEG; i++, seg++) {
}
}
#ifdef SFCT_SUPPORT
{
uint32_t j;
for (i = 0; i < MAX_VPORTS; i++) {
!port->fct_memseg) {
continue;
}
}
}
}
}
#endif /* SFCT_SUPPORT */
return;
} /* emlxs_timer_check_pools() */
#ifdef TX_WATCHDOG
static void
{
Q abort;
iocbq =
} else {
iocbq =
}
/* Find a matching entry */
found = 0;
while (iocbq) {
found = 1;
break;
}
}
if (!found) {
} else {
} else {
}
}
} else {
}
}
}
}
while (iocbq) {
if (pkt) {
}
emlxs_tx_put(iocbq, 0);
} /* end of while */
return;
} /* emlxs_tx_watchdog() */
#endif /* TX_WATCHDOG */
#ifdef DHCHAP_SUPPORT
static void
{
uint32_t i;
for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
if (!ndlp) {
continue;
}
/* Check authentication response timeout */
/* Trigger authresp timeout handler */
}
/* Check reauthentication timeout */
/* Trigger reauth timeout handler */
}
}
return;
} /* emlxs_timer_check_dhchap */
#endif /* DHCHAP_SUPPORT */