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  *
88f23e9faSHans Rosenfeld  * You can obtain a copy of the license at
98f23e9faSHans Rosenfeld  * http://www.opensource.org/licenses/cddl1.txt.
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 /*
238f23e9faSHans Rosenfeld  * Copyright (c) 2004-2012 Emulex. All rights reserved.
2482527734SSukumar Swaminathan  * Use is subject to license terms.
25fcf3ce44SJohn Forte  */
26fcf3ce44SJohn Forte 
2793c20f26SSukumar Swaminathan #include <emlxs.h>
28fcf3ce44SJohn Forte 
29fcf3ce44SJohn Forte /* Timer period in seconds */
30fcf3ce44SJohn Forte #define	EMLXS_TIMER_PERIOD		1	/* secs */
31fcf3ce44SJohn Forte #define	EMLXS_PKT_PERIOD		5	/* secs */
32fcf3ce44SJohn Forte #define	EMLXS_UB_PERIOD			60	/* secs */
33fcf3ce44SJohn Forte 
34fcf3ce44SJohn Forte EMLXS_MSG_DEF(EMLXS_CLOCK_C);
35fcf3ce44SJohn Forte 
36fcf3ce44SJohn Forte 
37fcf3ce44SJohn Forte static void emlxs_timer_check_loopback(emlxs_hba_t *hba);
38fcf3ce44SJohn Forte 
39fcf3ce44SJohn Forte #ifdef DHCHAP_SUPPORT
40fcf3ce44SJohn Forte static void emlxs_timer_check_dhchap(emlxs_port_t *port);
41291a2b48SSukumar Swaminathan #endif /* DHCHAP_SUPPORT */
42291a2b48SSukumar Swaminathan 
438f23e9faSHans Rosenfeld static void	emlxs_timer_check_pools(emlxs_hba_t *hba);
44291a2b48SSukumar Swaminathan static void	emlxs_timer(void *arg);
456a573d82SSukumar Swaminathan static void	emlxs_timer_check_fw_update(emlxs_hba_t *hba);
46291a2b48SSukumar Swaminathan static void	emlxs_timer_check_heartbeat(emlxs_hba_t *hba);
47291a2b48SSukumar Swaminathan static uint32_t	emlxs_timer_check_pkts(emlxs_hba_t *hba, uint8_t *flag);
48291a2b48SSukumar Swaminathan static void	emlxs_timer_check_nodes(emlxs_port_t *port, uint8_t *flag);
49291a2b48SSukumar Swaminathan static void	emlxs_timer_check_linkup(emlxs_hba_t *hba);
50291a2b48SSukumar Swaminathan static void	emlxs_timer_check_discovery(emlxs_port_t *port);
518f23e9faSHans Rosenfeld static void	emlxs_timer_check_clean_address(emlxs_port_t *port);
52291a2b48SSukumar Swaminathan static void	emlxs_timer_check_ub(emlxs_port_t *port);
5382527734SSukumar Swaminathan static void	emlxs_timer_check_channels(emlxs_hba_t *hba, uint8_t *flag);
54291a2b48SSukumar Swaminathan static uint32_t	emlxs_pkt_chip_timeout(emlxs_port_t *port, emlxs_buf_t *sbp,
55291a2b48SSukumar Swaminathan 			Q *abortq, uint8_t *flag);
56fcf3ce44SJohn Forte 
57fcf3ce44SJohn Forte #ifdef TX_WATCHDOG
58291a2b48SSukumar Swaminathan static void	emlxs_tx_watchdog(emlxs_hba_t *hba);
59291a2b48SSukumar Swaminathan #endif /* TX_WATCHDOG */
60fcf3ce44SJohn Forte 
61fcf3ce44SJohn Forte extern clock_t
emlxs_timeout(emlxs_hba_t * hba,uint32_t timeout)62fcf3ce44SJohn Forte emlxs_timeout(emlxs_hba_t *hba, uint32_t timeout)
63fcf3ce44SJohn Forte {
64fcf3ce44SJohn Forte 	emlxs_config_t *cfg = &CFG;
65fcf3ce44SJohn Forte 	clock_t time;
66fcf3ce44SJohn Forte 
67fcf3ce44SJohn Forte 	/* Set thread timeout */
68fcf3ce44SJohn Forte 	if (cfg[CFG_TIMEOUT_ENABLE].current) {
69fcf3ce44SJohn Forte 		(void) drv_getparm(LBOLT, &time);
70fcf3ce44SJohn Forte 		time += (timeout * drv_usectohz(1000000));
71fcf3ce44SJohn Forte 	} else {
72fcf3ce44SJohn Forte 		time = -1;
73fcf3ce44SJohn Forte 	}
74fcf3ce44SJohn Forte 
75fcf3ce44SJohn Forte 	return (time);
76fcf3ce44SJohn Forte 
7782527734SSukumar Swaminathan } /* emlxs_timeout() */
78fcf3ce44SJohn Forte 
79fcf3ce44SJohn Forte 
80fcf3ce44SJohn Forte static void
emlxs_timer(void * arg)81fcf3ce44SJohn Forte emlxs_timer(void *arg)
82fcf3ce44SJohn Forte {
83fcf3ce44SJohn Forte 	emlxs_hba_t *hba = (emlxs_hba_t *)arg;
848f23e9faSHans Rosenfeld 	emlxs_port_t *port = &PPORT;
85fcf3ce44SJohn Forte 
86fcf3ce44SJohn Forte 	if (!hba->timer_id) {
87fcf3ce44SJohn Forte 		return;
88fcf3ce44SJohn Forte 	}
89291a2b48SSukumar Swaminathan 
90fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_TIMER_LOCK);
91fcf3ce44SJohn Forte 
92fcf3ce44SJohn Forte 	/* Only one timer thread is allowed */
93fcf3ce44SJohn Forte 	if (hba->timer_flags & EMLXS_TIMER_BUSY) {
94fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_TIMER_LOCK);
95fcf3ce44SJohn Forte 		return;
96fcf3ce44SJohn Forte 	}
97291a2b48SSukumar Swaminathan 
98fcf3ce44SJohn Forte 	/* Check if a kill request has been made */
99fcf3ce44SJohn Forte 	if (hba->timer_flags & EMLXS_TIMER_KILL) {
100fcf3ce44SJohn Forte 		hba->timer_id = 0;
1018f23e9faSHans Rosenfeld 		hba->timer_tics = 0;
102fcf3ce44SJohn Forte 		hba->timer_flags |= EMLXS_TIMER_ENDED;
103fcf3ce44SJohn Forte 
104fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_TIMER_LOCK);
105fcf3ce44SJohn Forte 		return;
106fcf3ce44SJohn Forte 	}
107291a2b48SSukumar Swaminathan 
108fcf3ce44SJohn Forte 	hba->timer_flags |= (EMLXS_TIMER_BUSY | EMLXS_TIMER_STARTED);
109fcf3ce44SJohn Forte 	hba->timer_tics = DRV_TIME;
110fcf3ce44SJohn Forte 
1118f23e9faSHans Rosenfeld 	/* Check io_active count (Safety net) */
1128f23e9faSHans Rosenfeld 	if (hba->io_active & 0x80000000) {
1138f23e9faSHans Rosenfeld 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_debug_msg,
1148f23e9faSHans Rosenfeld 		    "Timer: io_active=0x%x. Reset to zero.", hba->io_active);
1158f23e9faSHans Rosenfeld 		hba->io_active = 0;
1168f23e9faSHans Rosenfeld 	}
1178f23e9faSHans Rosenfeld 
118fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_TIMER_LOCK);
119fcf3ce44SJohn Forte 
120a9800bebSGarrett D'Amore 	EMLXS_SLI_POLL_ERRATT(hba);
121a9800bebSGarrett D'Amore 
122291a2b48SSukumar Swaminathan 	/* Perform standard checks */
123291a2b48SSukumar Swaminathan 	emlxs_timer_checks(hba);
124291a2b48SSukumar Swaminathan 
125291a2b48SSukumar Swaminathan 	/* Restart the timer */
126291a2b48SSukumar Swaminathan 	mutex_enter(&EMLXS_TIMER_LOCK);
127291a2b48SSukumar Swaminathan 
128291a2b48SSukumar Swaminathan 	hba->timer_flags &= ~EMLXS_TIMER_BUSY;
129291a2b48SSukumar Swaminathan 
130291a2b48SSukumar Swaminathan 	/* If timer is still enabled, restart it */
131291a2b48SSukumar Swaminathan 	if (!(hba->timer_flags & EMLXS_TIMER_KILL)) {
132291a2b48SSukumar Swaminathan 		hba->timer_id =
133291a2b48SSukumar Swaminathan 		    timeout(emlxs_timer, (void *)hba,
134291a2b48SSukumar Swaminathan 		    (EMLXS_TIMER_PERIOD * drv_usectohz(1000000)));
135291a2b48SSukumar Swaminathan 	} else {
136291a2b48SSukumar Swaminathan 		hba->timer_id = 0;
137291a2b48SSukumar Swaminathan 		hba->timer_flags |= EMLXS_TIMER_ENDED;
138291a2b48SSukumar Swaminathan 	}
139291a2b48SSukumar Swaminathan 
140291a2b48SSukumar Swaminathan 	mutex_exit(&EMLXS_TIMER_LOCK);
141291a2b48SSukumar Swaminathan 
142291a2b48SSukumar Swaminathan 	return;
143291a2b48SSukumar Swaminathan 
14482527734SSukumar Swaminathan } /* emlxs_timer() */
145291a2b48SSukumar Swaminathan 
146291a2b48SSukumar Swaminathan 
147291a2b48SSukumar Swaminathan extern void
emlxs_timer_checks(emlxs_hba_t * hba)148291a2b48SSukumar Swaminathan emlxs_timer_checks(emlxs_hba_t *hba)
149291a2b48SSukumar Swaminathan {
150291a2b48SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
15182527734SSukumar Swaminathan 	uint8_t flag[MAX_CHANNEL];
152291a2b48SSukumar Swaminathan 	uint32_t i;
153291a2b48SSukumar Swaminathan 	uint32_t rc;
154291a2b48SSukumar Swaminathan 
155fcf3ce44SJohn Forte 	/* Exit if we are still initializing */
156fcf3ce44SJohn Forte 	if (hba->state < FC_LINK_DOWN) {
157291a2b48SSukumar Swaminathan 		return;
158fcf3ce44SJohn Forte 	}
159291a2b48SSukumar Swaminathan 
160291a2b48SSukumar Swaminathan 	bzero((void *)flag, sizeof (flag));
161fcf3ce44SJohn Forte 
16282527734SSukumar Swaminathan 	/* Check SLI level timeouts */
16382527734SSukumar Swaminathan 	EMLXS_SLI_TIMER(hba);
16482527734SSukumar Swaminathan 
16582527734SSukumar Swaminathan 	/* Check event queue */
16682527734SSukumar Swaminathan 	emlxs_timer_check_events(hba);
167fcf3ce44SJohn Forte 
168fcf3ce44SJohn Forte 	/* Check heartbeat timer */
169fcf3ce44SJohn Forte 	emlxs_timer_check_heartbeat(hba);
170fcf3ce44SJohn Forte 
1716a573d82SSukumar Swaminathan 	/* Check fw update timer */
1726a573d82SSukumar Swaminathan 	emlxs_timer_check_fw_update(hba);
1736a573d82SSukumar Swaminathan 
174fcf3ce44SJohn Forte #ifdef IDLE_TIMER
175fcf3ce44SJohn Forte 	emlxs_pm_idle_timer(hba);
176291a2b48SSukumar Swaminathan #endif /* IDLE_TIMER */
177fcf3ce44SJohn Forte 
178fcf3ce44SJohn Forte 	/* Check for loopback timeouts */
179fcf3ce44SJohn Forte 	emlxs_timer_check_loopback(hba);
180fcf3ce44SJohn Forte 
181fcf3ce44SJohn Forte 	/* Check for packet timeouts */
182fcf3ce44SJohn Forte 	rc = emlxs_timer_check_pkts(hba, flag);
183fcf3ce44SJohn Forte 
184fcf3ce44SJohn Forte 	if (rc) {
185fcf3ce44SJohn Forte 		/* Link or adapter is being reset */
186291a2b48SSukumar Swaminathan 		return;
187fcf3ce44SJohn Forte 	}
188291a2b48SSukumar Swaminathan 
189fcf3ce44SJohn Forte 	/* Check for linkup timeout */
190fcf3ce44SJohn Forte 	emlxs_timer_check_linkup(hba);
191fcf3ce44SJohn Forte 
192fcf3ce44SJohn Forte 	/* Check the ports */
193fcf3ce44SJohn Forte 	for (i = 0; i < MAX_VPORTS; i++) {
194fcf3ce44SJohn Forte 		port = &VPORT(i);
195fcf3ce44SJohn Forte 
196fcf3ce44SJohn Forte 		if (!(port->flag & EMLXS_PORT_BOUND)) {
197fcf3ce44SJohn Forte 			continue;
198fcf3ce44SJohn Forte 		}
199291a2b48SSukumar Swaminathan 
200fcf3ce44SJohn Forte 		/* Check for node gate timeouts */
201fcf3ce44SJohn Forte 		emlxs_timer_check_nodes(port, flag);
202fcf3ce44SJohn Forte 
2038f23e9faSHans Rosenfeld 		/* Check for clean address bit delay timeout */
2048f23e9faSHans Rosenfeld 		emlxs_timer_check_clean_address(port);
2058f23e9faSHans Rosenfeld 
206fcf3ce44SJohn Forte 		/* Check for tape discovery timeout */
207fcf3ce44SJohn Forte 		emlxs_timer_check_discovery(port);
208fcf3ce44SJohn Forte 
209fcf3ce44SJohn Forte 		/* Check for UB timeouts */
210fcf3ce44SJohn Forte 		emlxs_timer_check_ub(port);
211fcf3ce44SJohn Forte 
212fcf3ce44SJohn Forte #ifdef DHCHAP_SUPPORT
213fcf3ce44SJohn Forte 		/* Check for DHCHAP authentication timeouts */
214fcf3ce44SJohn Forte 		emlxs_timer_check_dhchap(port);
215291a2b48SSukumar Swaminathan #endif /* DHCHAP_SUPPORT */
216fcf3ce44SJohn Forte 
217fcf3ce44SJohn Forte 	}
218fcf3ce44SJohn Forte 
2198f23e9faSHans Rosenfeld 	/* Check memory pools */
2208f23e9faSHans Rosenfeld 	emlxs_timer_check_pools(hba);
2218f23e9faSHans Rosenfeld 
22282527734SSukumar Swaminathan 	/* Check for IO channel service timeouts */
223fcf3ce44SJohn Forte 	/* Always do this last */
22482527734SSukumar Swaminathan 	emlxs_timer_check_channels(hba, flag);
225fcf3ce44SJohn Forte 
226fcf3ce44SJohn Forte 	return;
227fcf3ce44SJohn Forte 
22882527734SSukumar Swaminathan } /* emlxs_timer_checks() */
229fcf3ce44SJohn Forte 
230fcf3ce44SJohn Forte 
231fcf3ce44SJohn Forte extern void
emlxs_timer_start(emlxs_hba_t * hba)232fcf3ce44SJohn Forte emlxs_timer_start(emlxs_hba_t *hba)
233fcf3ce44SJohn Forte {
234fcf3ce44SJohn Forte 	if (hba->timer_id) {
235fcf3ce44SJohn Forte 		return;
236fcf3ce44SJohn Forte 	}
237291a2b48SSukumar Swaminathan 
238fcf3ce44SJohn Forte 	/* Restart the timer */
239fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_TIMER_LOCK);
240fcf3ce44SJohn Forte 	if (!hba->timer_id) {
241fcf3ce44SJohn Forte 		hba->timer_flags = 0;
242291a2b48SSukumar Swaminathan 		hba->timer_id =
243291a2b48SSukumar Swaminathan 		    timeout(emlxs_timer, (void *)hba, drv_usectohz(1000000));
244fcf3ce44SJohn Forte 	}
245fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_TIMER_LOCK);
246fcf3ce44SJohn Forte 
24782527734SSukumar Swaminathan } /* emlxs_timer_start() */
248fcf3ce44SJohn Forte 
249fcf3ce44SJohn Forte 
250fcf3ce44SJohn Forte extern void
emlxs_timer_stop(emlxs_hba_t * hba)251fcf3ce44SJohn Forte emlxs_timer_stop(emlxs_hba_t *hba)
252fcf3ce44SJohn Forte {
253fcf3ce44SJohn Forte 	if (!hba->timer_id) {
254fcf3ce44SJohn Forte 		return;
255fcf3ce44SJohn Forte 	}
256291a2b48SSukumar Swaminathan 
257fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_TIMER_LOCK);
258fcf3ce44SJohn Forte 	hba->timer_flags |= EMLXS_TIMER_KILL;
259fcf3ce44SJohn Forte 
260fcf3ce44SJohn Forte 	while (hba->timer_id) {
261fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_TIMER_LOCK);
262fcf3ce44SJohn Forte 		delay(drv_usectohz(500000));
263fcf3ce44SJohn Forte 		mutex_enter(&EMLXS_TIMER_LOCK);
264fcf3ce44SJohn Forte 	}
265fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_TIMER_LOCK);
266fcf3ce44SJohn Forte 
267fcf3ce44SJohn Forte 	return;
268fcf3ce44SJohn Forte 
26982527734SSukumar Swaminathan } /* emlxs_timer_stop() */
270fcf3ce44SJohn Forte 
271fcf3ce44SJohn Forte 
272fcf3ce44SJohn Forte static uint32_t
emlxs_timer_check_pkts(emlxs_hba_t * hba,uint8_t * flag)273fcf3ce44SJohn Forte emlxs_timer_check_pkts(emlxs_hba_t *hba, uint8_t *flag)
274fcf3ce44SJohn Forte {
275fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
276fcf3ce44SJohn Forte 	emlxs_config_t *cfg = &CFG;
277fcf3ce44SJohn Forte 	Q tmo;
27882527734SSukumar Swaminathan 	int32_t channelno;
27982527734SSukumar Swaminathan 	CHANNEL *cp;
280fcf3ce44SJohn Forte 	NODELIST *nlp;
281fcf3ce44SJohn Forte 	IOCBQ *prev;
282fcf3ce44SJohn Forte 	IOCBQ *next;
283fcf3ce44SJohn Forte 	IOCB *iocb;
284fcf3ce44SJohn Forte 	IOCBQ *iocbq;
285fcf3ce44SJohn Forte 	emlxs_buf_t *sbp;
286fcf3ce44SJohn Forte 	fc_packet_t *pkt;
287fcf3ce44SJohn Forte 	Q abort;
288fcf3ce44SJohn Forte 	uint32_t iotag;
289fcf3ce44SJohn Forte 	uint32_t rc;
290fcf3ce44SJohn Forte 
291fcf3ce44SJohn Forte 	if (!cfg[CFG_TIMEOUT_ENABLE].current) {
292fcf3ce44SJohn Forte 		return (0);
293fcf3ce44SJohn Forte 	}
294291a2b48SSukumar Swaminathan 
295fcf3ce44SJohn Forte 	if (hba->pkt_timer > hba->timer_tics) {
296fcf3ce44SJohn Forte 		return (0);
297fcf3ce44SJohn Forte 	}
298291a2b48SSukumar Swaminathan 
299fcf3ce44SJohn Forte 	hba->pkt_timer = hba->timer_tics + EMLXS_PKT_PERIOD;
300fcf3ce44SJohn Forte 
301fcf3ce44SJohn Forte 
302291a2b48SSukumar Swaminathan 	bzero((void *)&tmo, sizeof (Q));
303fcf3ce44SJohn Forte 
304fcf3ce44SJohn Forte 	/*
305fcf3ce44SJohn Forte 	 * We must hold the locks here because we never know when an iocb
306fcf3ce44SJohn Forte 	 * will be removed out from under us
307fcf3ce44SJohn Forte 	 */
308fcf3ce44SJohn Forte 
30982527734SSukumar Swaminathan 	mutex_enter(&EMLXS_TX_CHANNEL_LOCK);
310fcf3ce44SJohn Forte 
31182527734SSukumar Swaminathan 	for (channelno = 0; channelno < hba->chan_count; channelno++) {
31282527734SSukumar Swaminathan 		cp = &hba->chan[channelno];
313fcf3ce44SJohn Forte 
31482527734SSukumar Swaminathan 		/* Scan the tx queues for each active node on the channel */
315fcf3ce44SJohn Forte 
316fcf3ce44SJohn Forte 		/* Get the first node */
31782527734SSukumar Swaminathan 		nlp = (NODELIST *)cp->nodeq.q_first;
318fcf3ce44SJohn Forte 
319fcf3ce44SJohn Forte 		while (nlp) {
320fcf3ce44SJohn Forte 			/* Scan the node's priority tx queue */
321fcf3ce44SJohn Forte 			prev = NULL;
32282527734SSukumar Swaminathan 			iocbq = (IOCBQ *)nlp->nlp_ptx[channelno].q_first;
323fcf3ce44SJohn Forte 
324fcf3ce44SJohn Forte 			while (iocbq) {
325fcf3ce44SJohn Forte 				next = (IOCBQ *)iocbq->next;
326fcf3ce44SJohn Forte 				iocb = &iocbq->iocb;
327fcf3ce44SJohn Forte 				sbp = (emlxs_buf_t *)iocbq->sbp;
328fcf3ce44SJohn Forte 
329fcf3ce44SJohn Forte 				/* Check if iocb has timed out */
330fcf3ce44SJohn Forte 				if (sbp && hba->timer_tics >= sbp->ticks) {
331fcf3ce44SJohn Forte 					/* iocb timed out, now deque it */
332fcf3ce44SJohn Forte 					if (next == NULL) {
33382527734SSukumar Swaminathan 						nlp->nlp_ptx[channelno].q_last =
334fcf3ce44SJohn Forte 						    (uint8_t *)prev;
335fcf3ce44SJohn Forte 					}
336291a2b48SSukumar Swaminathan 
337fcf3ce44SJohn Forte 					if (prev == NULL) {
33882527734SSukumar Swaminathan 						nlp->nlp_ptx[channelno].
33982527734SSukumar Swaminathan 						    q_first = (uint8_t *)next;
340fcf3ce44SJohn Forte 					} else {
341fcf3ce44SJohn Forte 						prev->next = next;
342fcf3ce44SJohn Forte 					}
343fcf3ce44SJohn Forte 
344fcf3ce44SJohn Forte 					iocbq->next = NULL;
34582527734SSukumar Swaminathan 					nlp->nlp_ptx[channelno].q_cnt--;
346fcf3ce44SJohn Forte 
347291a2b48SSukumar Swaminathan 					/* Add this iocb to our local */
348291a2b48SSukumar Swaminathan 					/* timout queue */
349fcf3ce44SJohn Forte 
350fcf3ce44SJohn Forte 					/*
35182527734SSukumar Swaminathan 					 * This way we don't hold the TX_CHANNEL
352fcf3ce44SJohn Forte 					 * lock too long
353fcf3ce44SJohn Forte 					 */
354fcf3ce44SJohn Forte 
355fcf3ce44SJohn Forte 					if (tmo.q_first) {
356fcf3ce44SJohn Forte 						((IOCBQ *)tmo.q_last)->next =
357fcf3ce44SJohn Forte 						    iocbq;
358291a2b48SSukumar Swaminathan 						tmo.q_last =
359291a2b48SSukumar Swaminathan 						    (uint8_t *)iocbq;
360fcf3ce44SJohn Forte 						tmo.q_cnt++;
361fcf3ce44SJohn Forte 					} else {
362291a2b48SSukumar Swaminathan 						tmo.q_first =
363291a2b48SSukumar Swaminathan 						    (uint8_t *)iocbq;
364291a2b48SSukumar Swaminathan 						tmo.q_last =
365291a2b48SSukumar Swaminathan 						    (uint8_t *)iocbq;
366fcf3ce44SJohn Forte 						tmo.q_cnt = 1;
367fcf3ce44SJohn Forte 					}
368fcf3ce44SJohn Forte 					iocbq->next = NULL;
369fcf3ce44SJohn Forte 
370fcf3ce44SJohn Forte 				} else {
371fcf3ce44SJohn Forte 					prev = iocbq;
372fcf3ce44SJohn Forte 				}
373fcf3ce44SJohn Forte 
374fcf3ce44SJohn Forte 				iocbq = next;
375fcf3ce44SJohn Forte 
376fcf3ce44SJohn Forte 			}	/* while (iocbq) */
377fcf3ce44SJohn Forte 
378fcf3ce44SJohn Forte 
379fcf3ce44SJohn Forte 			/* Scan the node's tx queue */
380fcf3ce44SJohn Forte 			prev = NULL;
38182527734SSukumar Swaminathan 			iocbq = (IOCBQ *)nlp->nlp_tx[channelno].q_first;
382fcf3ce44SJohn Forte 
383fcf3ce44SJohn Forte 			while (iocbq) {
384fcf3ce44SJohn Forte 				next = (IOCBQ *)iocbq->next;
385fcf3ce44SJohn Forte 				iocb = &iocbq->iocb;
386fcf3ce44SJohn Forte 				sbp = (emlxs_buf_t *)iocbq->sbp;
387fcf3ce44SJohn Forte 
388fcf3ce44SJohn Forte 				/* Check if iocb has timed out */
389fcf3ce44SJohn Forte 				if (sbp && hba->timer_tics >= sbp->ticks) {
390fcf3ce44SJohn Forte 					/* iocb timed out, now deque it */
391fcf3ce44SJohn Forte 					if (next == NULL) {
39282527734SSukumar Swaminathan 						nlp->nlp_tx[channelno].q_last =
393fcf3ce44SJohn Forte 						    (uint8_t *)prev;
394fcf3ce44SJohn Forte 					}
395291a2b48SSukumar Swaminathan 
396fcf3ce44SJohn Forte 					if (prev == NULL) {
39782527734SSukumar Swaminathan 						nlp->nlp_tx[channelno].q_first =
398fcf3ce44SJohn Forte 						    (uint8_t *)next;
399fcf3ce44SJohn Forte 					} else {
400fcf3ce44SJohn Forte 						prev->next = next;
401fcf3ce44SJohn Forte 					}
402fcf3ce44SJohn Forte 
403fcf3ce44SJohn Forte 					iocbq->next = NULL;
40482527734SSukumar Swaminathan 					nlp->nlp_tx[channelno].q_cnt--;
405fcf3ce44SJohn Forte 
406291a2b48SSukumar Swaminathan 					/* Add this iocb to our local */
407291a2b48SSukumar Swaminathan 					/* timout queue */
408fcf3ce44SJohn Forte 
409fcf3ce44SJohn Forte 					/*
41082527734SSukumar Swaminathan 					 * This way we don't hold the TX_CHANNEL
411fcf3ce44SJohn Forte 					 * lock too long
412fcf3ce44SJohn Forte 					 */
413fcf3ce44SJohn Forte 
414fcf3ce44SJohn Forte 					if (tmo.q_first) {
415fcf3ce44SJohn Forte 						((IOCBQ *)tmo.q_last)->next =
416fcf3ce44SJohn Forte 						    iocbq;
417291a2b48SSukumar Swaminathan 						tmo.q_last =
418291a2b48SSukumar Swaminathan 						    (uint8_t *)iocbq;
419fcf3ce44SJohn Forte 						tmo.q_cnt++;
420fcf3ce44SJohn Forte 					} else {
421291a2b48SSukumar Swaminathan 						tmo.q_first =
422291a2b48SSukumar Swaminathan 						    (uint8_t *)iocbq;
423291a2b48SSukumar Swaminathan 						tmo.q_last =
424291a2b48SSukumar Swaminathan 						    (uint8_t *)iocbq;
425fcf3ce44SJohn Forte 						tmo.q_cnt = 1;
426fcf3ce44SJohn Forte 					}
427fcf3ce44SJohn Forte 					iocbq->next = NULL;
428fcf3ce44SJohn Forte 
429fcf3ce44SJohn Forte 				} else {
430fcf3ce44SJohn Forte 					prev = iocbq;
431fcf3ce44SJohn Forte 				}
432fcf3ce44SJohn Forte 
433fcf3ce44SJohn Forte 				iocbq = next;
434fcf3ce44SJohn Forte 
435fcf3ce44SJohn Forte 			}	/* while (iocbq) */
436fcf3ce44SJohn Forte 
43782527734SSukumar Swaminathan 			if (nlp == (NODELIST *)cp->nodeq.q_last) {
438fcf3ce44SJohn Forte 				nlp = NULL;
439fcf3ce44SJohn Forte 			} else {
44082527734SSukumar Swaminathan 				nlp = nlp->nlp_next[channelno];
441fcf3ce44SJohn Forte 			}
442fcf3ce44SJohn Forte 
44382527734SSukumar Swaminathan 		}	/* while (nlp) */
444fcf3ce44SJohn Forte 
445fcf3ce44SJohn Forte 	}	/* end of for */
446fcf3ce44SJohn Forte 
447fcf3ce44SJohn Forte 	/* Now cleanup the iocb's */
448fcf3ce44SJohn Forte 	iocbq = (IOCBQ *)tmo.q_first;
449fcf3ce44SJohn Forte 	while (iocbq) {
450fcf3ce44SJohn Forte 		/* Free the IoTag and the bmp */
451fcf3ce44SJohn Forte 		iocb = &iocbq->iocb;
45282527734SSukumar Swaminathan 		channelno = ((CHANNEL *)iocbq->channel)->channelno;
45382527734SSukumar Swaminathan 		sbp = iocbq->sbp;
454fcf3ce44SJohn Forte 		if (sbp && (sbp != STALE_PACKET)) {
45582527734SSukumar Swaminathan 			if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
4568f23e9faSHans Rosenfeld 				emlxs_sli4_free_xri(port, sbp, sbp->xrip, 1);
45782527734SSukumar Swaminathan 			} else {
45882527734SSukumar Swaminathan 				(void) emlxs_unregister_pkt(
45982527734SSukumar Swaminathan 				    (CHANNEL *)iocbq->channel,
46082527734SSukumar Swaminathan 				    iocb->ULPIOTAG, 0);
461fcf3ce44SJohn Forte 			}
46282527734SSukumar Swaminathan 
46382527734SSukumar Swaminathan 			mutex_enter(&sbp->mtx);
464fcf3ce44SJohn Forte 			sbp->pkt_flags |= PACKET_IN_TIMEOUT;
465fcf3ce44SJohn Forte 			mutex_exit(&sbp->mtx);
466fcf3ce44SJohn Forte 		}
467291a2b48SSukumar Swaminathan 
468fcf3ce44SJohn Forte 		iocbq = (IOCBQ *)iocbq->next;
469fcf3ce44SJohn Forte 
470fcf3ce44SJohn Forte 	}	/* end of while */
471fcf3ce44SJohn Forte 
47282527734SSukumar Swaminathan 	mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
473fcf3ce44SJohn Forte 
474fcf3ce44SJohn Forte 	/* Now complete the transmit timeouts outside the locks */
475fcf3ce44SJohn Forte 	iocbq = (IOCBQ *)tmo.q_first;
476fcf3ce44SJohn Forte 	while (iocbq) {
477fcf3ce44SJohn Forte 		/* Save the next iocbq for now */
478fcf3ce44SJohn Forte 		next = (IOCBQ *)iocbq->next;
479fcf3ce44SJohn Forte 
480fcf3ce44SJohn Forte 		/* Unlink this iocbq */
481fcf3ce44SJohn Forte 		iocbq->next = NULL;
482fcf3ce44SJohn Forte 
483fcf3ce44SJohn Forte 		/* Get the pkt */
484fcf3ce44SJohn Forte 		sbp = (emlxs_buf_t *)iocbq->sbp;
485fcf3ce44SJohn Forte 
486fcf3ce44SJohn Forte 		if (sbp) {
487291a2b48SSukumar Swaminathan 			/* Warning: Some FCT sbp's don't have */
488291a2b48SSukumar Swaminathan 			/* fc_packet objects */
489fcf3ce44SJohn Forte 			pkt = PRIV2PKT(sbp);
490fcf3ce44SJohn Forte 
491fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_timeout_msg,
4928f23e9faSHans Rosenfeld 			    "TXQ abort: sbp=%p iotag=%d tmo=%d", sbp,
493fcf3ce44SJohn Forte 			    sbp->iotag, (pkt) ? pkt->pkt_timeout : 0);
494fcf3ce44SJohn Forte 
495fcf3ce44SJohn Forte 			if (hba->state >= FC_LINK_UP) {
496fcf3ce44SJohn Forte 				emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT,
497fcf3ce44SJohn Forte 				    IOERR_ABORT_TIMEOUT, 1);
498fcf3ce44SJohn Forte 			} else {
499fcf3ce44SJohn Forte 				emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT,
500fcf3ce44SJohn Forte 				    IOERR_LINK_DOWN, 1);
501fcf3ce44SJohn Forte 			}
502291a2b48SSukumar Swaminathan 
503fcf3ce44SJohn Forte 		}
504291a2b48SSukumar Swaminathan 
505fcf3ce44SJohn Forte 		iocbq = next;
506fcf3ce44SJohn Forte 
507fcf3ce44SJohn Forte 	}	/* end of while */
508fcf3ce44SJohn Forte 
509fcf3ce44SJohn Forte 
510fcf3ce44SJohn Forte 
511fcf3ce44SJohn Forte 	/* Now check the chip */
512291a2b48SSukumar Swaminathan 	bzero((void *)&abort, sizeof (Q));
513fcf3ce44SJohn Forte 
51482527734SSukumar Swaminathan 	/* Check the HBA for outstanding IOs */
515fcf3ce44SJohn Forte 	rc = 0;
51682527734SSukumar Swaminathan 	mutex_enter(&EMLXS_FCTAB_LOCK);
51782527734SSukumar Swaminathan 	for (iotag = 1; iotag < hba->max_iotag; iotag++) {
51882527734SSukumar Swaminathan 		sbp = hba->fc_table[iotag];
519a9800bebSGarrett D'Amore 
5208f23e9faSHans Rosenfeld 		if (!sbp || sbp == STALE_PACKET) {
521a9800bebSGarrett D'Amore 			continue;
522a9800bebSGarrett D'Amore 		}
523*e2d1a434SCarsten Grzemba 		/* if channel not set we can not send a abort iocbq */
524*e2d1a434SCarsten Grzemba 		if (sbp->channel == NULL) {
525*e2d1a434SCarsten Grzemba 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_err_msg,
526*e2d1a434SCarsten Grzemba 			    "timer_check_pkts: Invalid IO found. iotag=%d, "
527*e2d1a434SCarsten Grzemba 			    "no channel set", iotag);
528*e2d1a434SCarsten Grzemba 			continue;
529*e2d1a434SCarsten Grzemba 		}
530a9800bebSGarrett D'Amore 
531a9800bebSGarrett D'Amore 		/* Check if IO is valid */
532a9800bebSGarrett D'Amore 		if (!(sbp->pkt_flags & PACKET_VALID) ||
533a9800bebSGarrett D'Amore 		    (sbp->pkt_flags & (PACKET_ULP_OWNED|
534a9800bebSGarrett D'Amore 		    PACKET_COMPLETED|PACKET_IN_COMPLETION))) {
535a9800bebSGarrett D'Amore 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_debug_msg,
5368f23e9faSHans Rosenfeld 			    "timer_check_pkts: Invalid IO found. iotag=%d",
537a9800bebSGarrett D'Amore 			    iotag);
538a9800bebSGarrett D'Amore 
539a9800bebSGarrett D'Amore 			hba->fc_table[iotag] = STALE_PACKET;
540a9800bebSGarrett D'Amore 			hba->io_count--;
541a9800bebSGarrett D'Amore 			continue;
542a9800bebSGarrett D'Amore 		}
543a9800bebSGarrett D'Amore 
544a9800bebSGarrett D'Amore 		if ((sbp->pkt_flags & PACKET_IN_CHIPQ) &&
54582527734SSukumar Swaminathan 		    (hba->timer_tics >= sbp->ticks)) {
54682527734SSukumar Swaminathan 			rc = emlxs_pkt_chip_timeout(sbp->iocbq.port,
54782527734SSukumar Swaminathan 			    sbp, &abort, flag);
54882527734SSukumar Swaminathan 
54982527734SSukumar Swaminathan 			if (rc) {
55082527734SSukumar Swaminathan 				break;
551fcf3ce44SJohn Forte 			}
552fcf3ce44SJohn Forte 		}
553fcf3ce44SJohn Forte 	}
55482527734SSukumar Swaminathan 	mutex_exit(&EMLXS_FCTAB_LOCK);
555fcf3ce44SJohn Forte 
556fcf3ce44SJohn Forte 	/* Now put the iocb's on the tx queue */
557fcf3ce44SJohn Forte 	iocbq = (IOCBQ *)abort.q_first;
558fcf3ce44SJohn Forte 	while (iocbq) {
559fcf3ce44SJohn Forte 		/* Save the next iocbq for now */
560fcf3ce44SJohn Forte 		next = (IOCBQ *)iocbq->next;
561fcf3ce44SJohn Forte 
562fcf3ce44SJohn Forte 		/* Unlink this iocbq */
563fcf3ce44SJohn Forte 		iocbq->next = NULL;
564fcf3ce44SJohn Forte 
565fcf3ce44SJohn Forte 		/* Send this iocbq */
566fcf3ce44SJohn Forte 		emlxs_tx_put(iocbq, 1);
567fcf3ce44SJohn Forte 
568fcf3ce44SJohn Forte 		iocbq = next;
569fcf3ce44SJohn Forte 	}
570fcf3ce44SJohn Forte 
57182527734SSukumar Swaminathan 	/* Now trigger IO channel service to send these abort iocbq */
57282527734SSukumar Swaminathan 	for (channelno = 0; channelno < hba->chan_count; channelno++) {
57382527734SSukumar Swaminathan 		if (!flag[channelno]) {
57482527734SSukumar Swaminathan 			continue;
57582527734SSukumar Swaminathan 		}
57682527734SSukumar Swaminathan 		cp = &hba->chan[channelno];
57782527734SSukumar Swaminathan 
57882527734SSukumar Swaminathan 		EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, 0);
57982527734SSukumar Swaminathan 	}
58082527734SSukumar Swaminathan 
581fcf3ce44SJohn Forte 	if (rc == 1) {
5828f23e9faSHans Rosenfeld 		mutex_enter(&EMLXS_PORT_LOCK);
5838f23e9faSHans Rosenfeld 		/* If a link reset or port reset is already requested, exit */
5848f23e9faSHans Rosenfeld 		if (!(hba->reset_request & (FC_LINK_RESET | FC_PORT_RESET))) {
5858f23e9faSHans Rosenfeld 			hba->reset_request |= FC_LINK_RESET;
5868f23e9faSHans Rosenfeld 			mutex_exit(&EMLXS_PORT_LOCK);
5878f23e9faSHans Rosenfeld 			/* Spawn a thread to reset the link */
5888f23e9faSHans Rosenfeld 			emlxs_thread_spawn(hba, emlxs_reset_link_thread, NULL,
5898f23e9faSHans Rosenfeld 			    NULL);
5908f23e9faSHans Rosenfeld 			goto exit;
5918f23e9faSHans Rosenfeld 		}
5928f23e9faSHans Rosenfeld 		mutex_exit(&EMLXS_PORT_LOCK);
593fcf3ce44SJohn Forte 	} else if (rc == 2) {
5948f23e9faSHans Rosenfeld 		mutex_enter(&EMLXS_PORT_LOCK);
5958f23e9faSHans Rosenfeld 		/* If a port reset is already requested, exit */
5968f23e9faSHans Rosenfeld 		if (!(hba->reset_request & FC_PORT_RESET)) {
5978f23e9faSHans Rosenfeld 			hba->reset_request |= FC_PORT_RESET;
5988f23e9faSHans Rosenfeld 			mutex_exit(&EMLXS_PORT_LOCK);
5998f23e9faSHans Rosenfeld 			/* Spawn a thread to reset the adapter */
6008f23e9faSHans Rosenfeld 			emlxs_thread_spawn(hba, emlxs_restart_thread, NULL,
6018f23e9faSHans Rosenfeld 			    NULL);
6028f23e9faSHans Rosenfeld 			goto exit;
6038f23e9faSHans Rosenfeld 		}
6048f23e9faSHans Rosenfeld 		mutex_exit(&EMLXS_PORT_LOCK);
605fcf3ce44SJohn Forte 	}
606291a2b48SSukumar Swaminathan 
6078f23e9faSHans Rosenfeld exit:
608fcf3ce44SJohn Forte 	return (rc);
609fcf3ce44SJohn Forte 
61082527734SSukumar Swaminathan } /* emlxs_timer_check_pkts() */
611fcf3ce44SJohn Forte 
612fcf3ce44SJohn Forte 
613fcf3ce44SJohn Forte static void
emlxs_timer_check_channels(emlxs_hba_t * hba,uint8_t * flag)61482527734SSukumar Swaminathan emlxs_timer_check_channels(emlxs_hba_t *hba, uint8_t *flag)
615fcf3ce44SJohn Forte {
616fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
617fcf3ce44SJohn Forte 	emlxs_config_t *cfg = &CFG;
61882527734SSukumar Swaminathan 	int32_t channelno;
61982527734SSukumar Swaminathan 	CHANNEL *cp;
62082527734SSukumar Swaminathan 	uint32_t logit;
621fcf3ce44SJohn Forte 
622fcf3ce44SJohn Forte 	if (!cfg[CFG_TIMEOUT_ENABLE].current) {
623fcf3ce44SJohn Forte 		return;
624fcf3ce44SJohn Forte 	}
625291a2b48SSukumar Swaminathan 
62682527734SSukumar Swaminathan 	for (channelno = 0; channelno < hba->chan_count; channelno++) {
62782527734SSukumar Swaminathan 		cp = &hba->chan[channelno];
62882527734SSukumar Swaminathan 
62982527734SSukumar Swaminathan 		logit = 0;
630fcf3ce44SJohn Forte 
63182527734SSukumar Swaminathan 		/* Check for channel timeout now */
63282527734SSukumar Swaminathan 		mutex_enter(&EMLXS_TX_CHANNEL_LOCK);
63382527734SSukumar Swaminathan 		if (cp->timeout && (hba->timer_tics >= cp->timeout)) {
63482527734SSukumar Swaminathan 			/* Check if there is work to do on channel and */
635fcf3ce44SJohn Forte 			/* the link is still up */
63682527734SSukumar Swaminathan 			if (cp->nodeq.q_first) {
63782527734SSukumar Swaminathan 				flag[channelno] = 1;
63882527734SSukumar Swaminathan 				cp->timeout = hba->timer_tics + 10;
639fcf3ce44SJohn Forte 
640fcf3ce44SJohn Forte 				if (hba->state >= FC_LINK_UP) {
641728bdc9bSSukumar Swaminathan 					logit = 1;
642fcf3ce44SJohn Forte 				}
643fcf3ce44SJohn Forte 			} else {
64482527734SSukumar Swaminathan 				cp->timeout = 0;
645fcf3ce44SJohn Forte 			}
646fcf3ce44SJohn Forte 		}
64782527734SSukumar Swaminathan 		mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
648fcf3ce44SJohn Forte 
649728bdc9bSSukumar Swaminathan 		if (logit) {
650728bdc9bSSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT,
65182527734SSukumar Swaminathan 			    &emlxs_chan_watchdog_msg,
65282527734SSukumar Swaminathan 			    "IO Channel %d cnt=%d,%d",
65382527734SSukumar Swaminathan 			    channelno,
65482527734SSukumar Swaminathan 			    hba->channel_tx_count,
65582527734SSukumar Swaminathan 			    hba->io_count);
656728bdc9bSSukumar Swaminathan 		}
657728bdc9bSSukumar Swaminathan 
658fcf3ce44SJohn Forte 		/*
65982527734SSukumar Swaminathan 		 * If IO channel flag is set, request iocb servicing
66082527734SSukumar Swaminathan 		 * here to send any iocb's that may still be queued
661fcf3ce44SJohn Forte 		 */
66282527734SSukumar Swaminathan 		if (flag[channelno]) {
66382527734SSukumar Swaminathan 			EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, 0);
664fcf3ce44SJohn Forte 		}
665fcf3ce44SJohn Forte 	}
666fcf3ce44SJohn Forte 
667fcf3ce44SJohn Forte 	return;
668fcf3ce44SJohn Forte 
66982527734SSukumar Swaminathan } /* emlxs_timer_check_channels() */
670fcf3ce44SJohn Forte 
671fcf3ce44SJohn Forte 
672fcf3ce44SJohn Forte static void
emlxs_timer_check_nodes(emlxs_port_t * port,uint8_t * flag)673fcf3ce44SJohn Forte emlxs_timer_check_nodes(emlxs_port_t *port, uint8_t *flag)
674fcf3ce44SJohn Forte {
675fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
676fcf3ce44SJohn Forte 	uint32_t found;
677fcf3ce44SJohn Forte 	uint32_t i;
678fcf3ce44SJohn Forte 	NODELIST *nlp;
67982527734SSukumar Swaminathan 	int32_t channelno;
680fcf3ce44SJohn Forte 
681fcf3ce44SJohn Forte 	for (;;) {
682fcf3ce44SJohn Forte 		/* Check node gate flag for expiration */
683fcf3ce44SJohn Forte 		found = 0;
684fcf3ce44SJohn Forte 
685fcf3ce44SJohn Forte 		/*
686291a2b48SSukumar Swaminathan 		 * We need to lock, scan, and unlock because we can't hold the
687291a2b48SSukumar Swaminathan 		 * lock while we call node_open
688fcf3ce44SJohn Forte 		 */
689fcf3ce44SJohn Forte 		rw_enter(&port->node_rwlock, RW_READER);
690fcf3ce44SJohn Forte 		for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
691fcf3ce44SJohn Forte 			nlp = port->node_table[i];
692fcf3ce44SJohn Forte 			while (nlp != NULL) {
6938f23e9faSHans Rosenfeld #ifdef NODE_THROTTLE_SUPPORT
6948f23e9faSHans Rosenfeld 				/* Check io_active count (Safety net) */
6958f23e9faSHans Rosenfeld 				if (nlp->io_active & 0x80000000) {
6968f23e9faSHans Rosenfeld 					EMLXS_MSGF(EMLXS_CONTEXT,
6978f23e9faSHans Rosenfeld 					    &emlxs_sli_debug_msg,
6988f23e9faSHans Rosenfeld 					    "timer_check_nodes: did=%06x "
6998f23e9faSHans Rosenfeld 					    "io_active=0x%x. Reset to zero.",
7008f23e9faSHans Rosenfeld 					    nlp->nlp_DID, nlp->io_active);
7018f23e9faSHans Rosenfeld 
7028f23e9faSHans Rosenfeld 					nlp->io_active = 0;
7038f23e9faSHans Rosenfeld 				}
7048f23e9faSHans Rosenfeld #endif /* NODE_THROTTLE_SUPPORT */
7058f23e9faSHans Rosenfeld 
70682527734SSukumar Swaminathan 				for (channelno = 0;
70782527734SSukumar Swaminathan 				    channelno < hba->chan_count;
70882527734SSukumar Swaminathan 				    channelno++) {
709291a2b48SSukumar Swaminathan 					/* Check if the node timer is active */
710291a2b48SSukumar Swaminathan 					/* and if timer has expired */
71182527734SSukumar Swaminathan 					if (nlp->nlp_tics[channelno] &&
712fcf3ce44SJohn Forte 					    (hba->timer_tics >=
71382527734SSukumar Swaminathan 					    nlp->nlp_tics[channelno])) {
714291a2b48SSukumar Swaminathan 						/* If so, set the flag and */
715291a2b48SSukumar Swaminathan 						/* break out */
716fcf3ce44SJohn Forte 						found = 1;
71782527734SSukumar Swaminathan 						flag[channelno] = 1;
718fcf3ce44SJohn Forte 						break;
719fcf3ce44SJohn Forte 					}
720fcf3ce44SJohn Forte 				}
721fcf3ce44SJohn Forte 
72282527734SSukumar Swaminathan 				if (nlp->nlp_force_rscn &&
72382527734SSukumar Swaminathan 				    (hba->timer_tics >= nlp->nlp_force_rscn)) {
72482527734SSukumar Swaminathan 					nlp->nlp_force_rscn = 0;
72582527734SSukumar Swaminathan 					/*
72682527734SSukumar Swaminathan 					 * Generate an RSCN to
72782527734SSukumar Swaminathan 					 * wakeup ULP
72882527734SSukumar Swaminathan 					 */
72982527734SSukumar Swaminathan 					(void) emlxs_generate_rscn(port,
73082527734SSukumar Swaminathan 					    nlp->nlp_DID);
73182527734SSukumar Swaminathan 				}
73282527734SSukumar Swaminathan 
733fcf3ce44SJohn Forte 				if (found) {
734fcf3ce44SJohn Forte 					break;
735fcf3ce44SJohn Forte 				}
736291a2b48SSukumar Swaminathan 
737fcf3ce44SJohn Forte 				nlp = nlp->nlp_list_next;
738fcf3ce44SJohn Forte 			}
739fcf3ce44SJohn Forte 
740fcf3ce44SJohn Forte 			if (found) {
741fcf3ce44SJohn Forte 				break;
742fcf3ce44SJohn Forte 			}
743291a2b48SSukumar Swaminathan 
744fcf3ce44SJohn Forte 		}
745fcf3ce44SJohn Forte 		rw_exit(&port->node_rwlock);
746fcf3ce44SJohn Forte 
747fcf3ce44SJohn Forte 		if (!found) {
748fcf3ce44SJohn Forte 			break;
749fcf3ce44SJohn Forte 		}
750291a2b48SSukumar Swaminathan 
75182527734SSukumar Swaminathan 		emlxs_node_timeout(port, nlp, channelno);
752fcf3ce44SJohn Forte 	}
753fcf3ce44SJohn Forte 
75482527734SSukumar Swaminathan } /* emlxs_timer_check_nodes() */
755fcf3ce44SJohn Forte 
756fcf3ce44SJohn Forte 
757fcf3ce44SJohn Forte static void
emlxs_timer_check_loopback(emlxs_hba_t * hba)758fcf3ce44SJohn Forte emlxs_timer_check_loopback(emlxs_hba_t *hba)
759fcf3ce44SJohn Forte {
760fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
761fcf3ce44SJohn Forte 	emlxs_config_t *cfg = &CFG;
762fcf3ce44SJohn Forte 	int32_t reset = 0;
763fcf3ce44SJohn Forte 
764fcf3ce44SJohn Forte 	if (!cfg[CFG_TIMEOUT_ENABLE].current) {
765fcf3ce44SJohn Forte 		return;
766fcf3ce44SJohn Forte 	}
767291a2b48SSukumar Swaminathan 
768fcf3ce44SJohn Forte 	/* Check the loopback timer for expiration */
769fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_PORT_LOCK);
770fcf3ce44SJohn Forte 
771291a2b48SSukumar Swaminathan 	if (!hba->loopback_tics || (hba->timer_tics < hba->loopback_tics)) {
772fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_PORT_LOCK);
773fcf3ce44SJohn Forte 		return;
774fcf3ce44SJohn Forte 	}
775291a2b48SSukumar Swaminathan 
776fcf3ce44SJohn Forte 	hba->loopback_tics = 0;
777fcf3ce44SJohn Forte 
778fcf3ce44SJohn Forte 	if (hba->flag & FC_LOOPBACK_MODE) {
779fcf3ce44SJohn Forte 		reset = 1;
780fcf3ce44SJohn Forte 	}
781291a2b48SSukumar Swaminathan 
782fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_PORT_LOCK);
783fcf3ce44SJohn Forte 
784fcf3ce44SJohn Forte 	if (reset) {
785fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
786fcf3ce44SJohn Forte 		    "LOOPBACK_MODE: Expired. Resetting...");
787fcf3ce44SJohn Forte 		(void) emlxs_reset(port, FC_FCA_LINK_RESET);
788fcf3ce44SJohn Forte 	}
789291a2b48SSukumar Swaminathan 
790fcf3ce44SJohn Forte 	return;
791fcf3ce44SJohn Forte 
79282527734SSukumar Swaminathan } /* emlxs_timer_check_loopback() */
793fcf3ce44SJohn Forte 
794fcf3ce44SJohn Forte 
795fcf3ce44SJohn Forte static void
emlxs_timer_check_linkup(emlxs_hba_t * hba)796fcf3ce44SJohn Forte emlxs_timer_check_linkup(emlxs_hba_t *hba)
797fcf3ce44SJohn Forte {
798fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
799fcf3ce44SJohn Forte 	uint32_t linkup;
800fcf3ce44SJohn Forte 
80182527734SSukumar Swaminathan 	/* Check if all mbox commands from previous activity are processed */
80282527734SSukumar Swaminathan 	if (hba->model_info.sli_mask & EMLXS_SLI4_MASK) {
80382527734SSukumar Swaminathan 		mutex_enter(&EMLXS_MBOX_LOCK);
80482527734SSukumar Swaminathan 		if (hba->mbox_queue.q_first) {
80582527734SSukumar Swaminathan 			mutex_exit(&EMLXS_MBOX_LOCK);
80682527734SSukumar Swaminathan 			return;
80782527734SSukumar Swaminathan 		}
80882527734SSukumar Swaminathan 		mutex_exit(&EMLXS_MBOX_LOCK);
80982527734SSukumar Swaminathan 	}
81082527734SSukumar Swaminathan 
811fcf3ce44SJohn Forte 	/* Check the linkup timer for expiration */
812fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_PORT_LOCK);
813fcf3ce44SJohn Forte 	linkup = 0;
814fcf3ce44SJohn Forte 	if (hba->linkup_timer && (hba->timer_tics >= hba->linkup_timer)) {
815fcf3ce44SJohn Forte 		hba->linkup_timer = 0;
816fcf3ce44SJohn Forte 
817fcf3ce44SJohn Forte 		/* Make sure link is still ready */
818fcf3ce44SJohn Forte 		if (hba->state >= FC_LINK_UP) {
819fcf3ce44SJohn Forte 			linkup = 1;
820fcf3ce44SJohn Forte 		}
821fcf3ce44SJohn Forte 	}
822fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_PORT_LOCK);
823fcf3ce44SJohn Forte 
824fcf3ce44SJohn Forte 	/* Make the linkup callback */
825fcf3ce44SJohn Forte 	if (linkup) {
826fcf3ce44SJohn Forte 		emlxs_port_online(port);
827fcf3ce44SJohn Forte 	}
828fcf3ce44SJohn Forte 	return;
829fcf3ce44SJohn Forte 
83082527734SSukumar Swaminathan } /* emlxs_timer_check_linkup() */
831fcf3ce44SJohn Forte 
832fcf3ce44SJohn Forte 
833fcf3ce44SJohn Forte static void
emlxs_timer_check_heartbeat(emlxs_hba_t * hba)834fcf3ce44SJohn Forte emlxs_timer_check_heartbeat(emlxs_hba_t *hba)
835fcf3ce44SJohn Forte {
836fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
83782527734SSukumar Swaminathan 	MAILBOXQ *mbq;
838fcf3ce44SJohn Forte 	emlxs_config_t *cfg = &CFG;
83982527734SSukumar Swaminathan 	int rc;
840fcf3ce44SJohn Forte 
841fcf3ce44SJohn Forte 	if (!cfg[CFG_HEARTBEAT_ENABLE].current) {
842fcf3ce44SJohn Forte 		return;
843fcf3ce44SJohn Forte 	}
844291a2b48SSukumar Swaminathan 
845fcf3ce44SJohn Forte 	if (hba->timer_tics < hba->heartbeat_timer) {
846fcf3ce44SJohn Forte 		return;
847fcf3ce44SJohn Forte 	}
848291a2b48SSukumar Swaminathan 
849fcf3ce44SJohn Forte 	hba->heartbeat_timer = hba->timer_tics + 5;
850fcf3ce44SJohn Forte 
851fcf3ce44SJohn Forte 	/* Return if adapter interrupts have occurred */
852fcf3ce44SJohn Forte 	if (hba->heartbeat_flag) {
853fcf3ce44SJohn Forte 		hba->heartbeat_flag = 0;
854fcf3ce44SJohn Forte 		return;
855fcf3ce44SJohn Forte 	}
856fcf3ce44SJohn Forte 	/* No adapter interrupts have occured for 5 seconds now */
857fcf3ce44SJohn Forte 
858fcf3ce44SJohn Forte 	/* Return if mailbox is busy */
859fcf3ce44SJohn Forte 	/* This means the mailbox timer routine is watching for problems */
860fcf3ce44SJohn Forte 	if (hba->mbox_timer) {
861fcf3ce44SJohn Forte 		return;
862fcf3ce44SJohn Forte 	}
863291a2b48SSukumar Swaminathan 
864fcf3ce44SJohn Forte 	/* Return if heartbeat is still outstanding */
865fcf3ce44SJohn Forte 	if (hba->heartbeat_active) {
866fcf3ce44SJohn Forte 		return;
867fcf3ce44SJohn Forte 	}
868291a2b48SSukumar Swaminathan 
8698f23e9faSHans Rosenfeld 	if ((mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX)) == 0) {
870fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
871fcf3ce44SJohn Forte 		    "Unable to allocate heartbeat mailbox.");
872fcf3ce44SJohn Forte 		return;
873fcf3ce44SJohn Forte 	}
874291a2b48SSukumar Swaminathan 
87582527734SSukumar Swaminathan 	emlxs_mb_heartbeat(hba, mbq);
876fcf3ce44SJohn Forte 	hba->heartbeat_active = 1;
877fcf3ce44SJohn Forte 
87882527734SSukumar Swaminathan 	rc =  EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
87982527734SSukumar Swaminathan 	if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) {
880a9800bebSGarrett D'Amore 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
881fcf3ce44SJohn Forte 	}
882fcf3ce44SJohn Forte 
883fcf3ce44SJohn Forte 	return;
884fcf3ce44SJohn Forte 
88582527734SSukumar Swaminathan } /* emlxs_timer_check_heartbeat() */
886fcf3ce44SJohn Forte 
887fcf3ce44SJohn Forte 
8886a573d82SSukumar Swaminathan static void
emlxs_timer_check_fw_update(emlxs_hba_t * hba)8896a573d82SSukumar Swaminathan emlxs_timer_check_fw_update(emlxs_hba_t *hba)
8906a573d82SSukumar Swaminathan {
8916a573d82SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
8928f23e9faSHans Rosenfeld 	char msgbuf[128];
8936a573d82SSukumar Swaminathan 
8946a573d82SSukumar Swaminathan 	if (!(hba->fw_flag & FW_UPDATE_NEEDED)) {
8956a573d82SSukumar Swaminathan 		hba->fw_timer = 0;
8966a573d82SSukumar Swaminathan 		return;
8976a573d82SSukumar Swaminathan 	}
8986a573d82SSukumar Swaminathan 
8996a573d82SSukumar Swaminathan 	if (hba->timer_tics < hba->fw_timer) {
9006a573d82SSukumar Swaminathan 		return;
9016a573d82SSukumar Swaminathan 	}
9026a573d82SSukumar Swaminathan 
9038f23e9faSHans Rosenfeld 	if (port->mode == MODE_TARGET) {
9048f23e9faSHans Rosenfeld 		(void) strncpy(msgbuf,
9058f23e9faSHans Rosenfeld 		    "To trigger an update, a manual HBA or link reset "
9068f23e9faSHans Rosenfeld 		    "using emlxadm is required.",
9078f23e9faSHans Rosenfeld 		    (sizeof (msgbuf)-1));
908a9800bebSGarrett D'Amore 	} else {
9098f23e9faSHans Rosenfeld 		(void) strncpy(msgbuf,
9108f23e9faSHans Rosenfeld 		    "To trigger an update, a manual HBA or link reset "
9118f23e9faSHans Rosenfeld 		    "using luxadm, fcadm, or emlxadm is required.",
9128f23e9faSHans Rosenfeld 		    (sizeof (msgbuf)-1));
913a9800bebSGarrett D'Amore 	}
9146a573d82SSukumar Swaminathan 
9158f23e9faSHans Rosenfeld 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_update_msg, msgbuf);
9168f23e9faSHans Rosenfeld 
9178f23e9faSHans Rosenfeld 	/* Force message to console */
9188f23e9faSHans Rosenfeld 	cmn_err(CE_WARN,
9198f23e9faSHans Rosenfeld 	    "^%s%d: Firmware update required.\n\t(%s)\n",
9208f23e9faSHans Rosenfeld 	    DRIVER_NAME, hba->ddiinst, msgbuf);
9218f23e9faSHans Rosenfeld 
9226a573d82SSukumar Swaminathan 	/* Set timer for 24 hours */
9236a573d82SSukumar Swaminathan 	hba->fw_timer = hba->timer_tics + (60 * 60 * 24);
9246a573d82SSukumar Swaminathan 
9256a573d82SSukumar Swaminathan 	return;
9266a573d82SSukumar Swaminathan 
9276a573d82SSukumar Swaminathan } /* emlxs_timer_check_fw_update() */
9286a573d82SSukumar Swaminathan 
9296a573d82SSukumar Swaminathan 
930fcf3ce44SJohn Forte static void
emlxs_timer_check_discovery(emlxs_port_t * port)931fcf3ce44SJohn Forte emlxs_timer_check_discovery(emlxs_port_t *port)
932fcf3ce44SJohn Forte {
933fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
934fcf3ce44SJohn Forte 	emlxs_config_t *cfg = &CFG;
935fcf3ce44SJohn Forte 	int32_t send_clear_la;
936fcf3ce44SJohn Forte 	uint32_t found;
937fcf3ce44SJohn Forte 	uint32_t i;
938fcf3ce44SJohn Forte 	NODELIST *nlp;
939fcf3ce44SJohn Forte 	MAILBOXQ *mbox;
94082527734SSukumar Swaminathan 	int rc;
941fcf3ce44SJohn Forte 
942fcf3ce44SJohn Forte 	if (!cfg[CFG_TIMEOUT_ENABLE].current) {
943fcf3ce44SJohn Forte 		return;
944fcf3ce44SJohn Forte 	}
945291a2b48SSukumar Swaminathan 
946fcf3ce44SJohn Forte 	/* Check the discovery timer for expiration */
947fcf3ce44SJohn Forte 	send_clear_la = 0;
948fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_PORT_LOCK);
949fcf3ce44SJohn Forte 	while (hba->discovery_timer &&
950fcf3ce44SJohn Forte 	    (hba->timer_tics >= hba->discovery_timer) &&
951fcf3ce44SJohn Forte 	    (hba->state == FC_LINK_UP)) {
952fcf3ce44SJohn Forte 		send_clear_la = 1;
953fcf3ce44SJohn Forte 
954fcf3ce44SJohn Forte 		/* Perform a flush on fcp2 nodes that are still closed */
955fcf3ce44SJohn Forte 		found = 0;
956fcf3ce44SJohn Forte 		rw_enter(&port->node_rwlock, RW_READER);
957fcf3ce44SJohn Forte 		for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
958fcf3ce44SJohn Forte 			nlp = port->node_table[i];
959fcf3ce44SJohn Forte 			while (nlp != NULL) {
960fcf3ce44SJohn Forte 				if ((nlp->nlp_fcp_info & NLP_FCP_2_DEVICE) &&
96182527734SSukumar Swaminathan 				    (nlp->nlp_flag[hba->channel_fcp] &
96282527734SSukumar Swaminathan 				    NLP_CLOSED)) {
963fcf3ce44SJohn Forte 					found = 1;
964fcf3ce44SJohn Forte 					break;
965fcf3ce44SJohn Forte 
966fcf3ce44SJohn Forte 				}
967fcf3ce44SJohn Forte 				nlp = nlp->nlp_list_next;
968fcf3ce44SJohn Forte 			}
969fcf3ce44SJohn Forte 
970fcf3ce44SJohn Forte 			if (found) {
971fcf3ce44SJohn Forte 				break;
972fcf3ce44SJohn Forte 			}
973fcf3ce44SJohn Forte 		}
974fcf3ce44SJohn Forte 		rw_exit(&port->node_rwlock);
975fcf3ce44SJohn Forte 
976fcf3ce44SJohn Forte 		if (!found) {
977fcf3ce44SJohn Forte 			break;
978fcf3ce44SJohn Forte 		}
979291a2b48SSukumar Swaminathan 
980fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_missing_msg,
981fcf3ce44SJohn Forte 		    "FCP2 device (did=%06x) missing. Flushing...",
982fcf3ce44SJohn Forte 		    nlp->nlp_DID);
983fcf3ce44SJohn Forte 
984fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_PORT_LOCK);
985fcf3ce44SJohn Forte 
9868f23e9faSHans Rosenfeld 		(void) EMLXS_SLI_UNREG_NODE(port, nlp, NULL, NULL, NULL);
987fcf3ce44SJohn Forte 
988fcf3ce44SJohn Forte 		mutex_enter(&EMLXS_PORT_LOCK);
989fcf3ce44SJohn Forte 
990fcf3ce44SJohn Forte 	}
991fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_PORT_LOCK);
992fcf3ce44SJohn Forte 
993fcf3ce44SJohn Forte 	/* Try to send clear link attention, if needed */
994fe199829SSukumar Swaminathan 	if ((hba->sli_mode < EMLXS_HBA_SLI4_MODE) && (send_clear_la == 1) &&
9958f23e9faSHans Rosenfeld 	    (mbox = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) {
996fcf3ce44SJohn Forte 		mutex_enter(&EMLXS_PORT_LOCK);
997fcf3ce44SJohn Forte 
998fcf3ce44SJohn Forte 		/*
999fcf3ce44SJohn Forte 		 * If state is not FC_LINK_UP, then either the link has gone
1000fcf3ce44SJohn Forte 		 * down or a FC_CLEAR_LA has already been issued
1001fcf3ce44SJohn Forte 		 */
1002fcf3ce44SJohn Forte 		if (hba->state != FC_LINK_UP) {
1003fcf3ce44SJohn Forte 			mutex_exit(&EMLXS_PORT_LOCK);
1004a9800bebSGarrett D'Amore 			emlxs_mem_put(hba, MEM_MBOX, (void *)mbox);
1005fcf3ce44SJohn Forte 		} else {
1006fcf3ce44SJohn Forte 			/* Change state and clear discovery timer */
100782527734SSukumar Swaminathan 			EMLXS_STATE_CHANGE_LOCKED(hba, FC_CLEAR_LA);
1008fcf3ce44SJohn Forte 
1009fcf3ce44SJohn Forte 			hba->discovery_timer = 0;
1010fcf3ce44SJohn Forte 
1011fcf3ce44SJohn Forte 			mutex_exit(&EMLXS_PORT_LOCK);
1012fcf3ce44SJohn Forte 
1013fcf3ce44SJohn Forte 			/* Prepare and send the CLEAR_LA command */
101482527734SSukumar Swaminathan 			emlxs_mb_clear_la(hba, mbox);
1015fcf3ce44SJohn Forte 
101682527734SSukumar Swaminathan 			rc = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_NOWAIT, 0);
101782527734SSukumar Swaminathan 			if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) {
1018a9800bebSGarrett D'Amore 				emlxs_mem_put(hba, MEM_MBOX, (void *)mbox);
1019fcf3ce44SJohn Forte 			}
1020fcf3ce44SJohn Forte 		}
1021fcf3ce44SJohn Forte 	}
1022291a2b48SSukumar Swaminathan 
1023fcf3ce44SJohn Forte 	return;
1024fcf3ce44SJohn Forte 
102582527734SSukumar Swaminathan } /* emlxs_timer_check_discovery()  */
1026fcf3ce44SJohn Forte 
1027fcf3ce44SJohn Forte 
10288f23e9faSHans Rosenfeld static void
emlxs_timer_check_clean_address(emlxs_port_t * port)10298f23e9faSHans Rosenfeld emlxs_timer_check_clean_address(emlxs_port_t *port)
10308f23e9faSHans Rosenfeld {
10318f23e9faSHans Rosenfeld 	emlxs_hba_t *hba = HBA;
10328f23e9faSHans Rosenfeld 	emlxs_buf_t *sbp;
10338f23e9faSHans Rosenfeld 
10348f23e9faSHans Rosenfeld 	if (port->clean_address_timer &&
10358f23e9faSHans Rosenfeld 	    (hba->timer_tics < port->clean_address_timer)) {
10368f23e9faSHans Rosenfeld 		return;
10378f23e9faSHans Rosenfeld 	}
10388f23e9faSHans Rosenfeld 	port->clean_address_timer = 0;
10398f23e9faSHans Rosenfeld 
10408f23e9faSHans Rosenfeld 	sbp = port->clean_address_sbp;
10418f23e9faSHans Rosenfeld 	if (!sbp) {
10428f23e9faSHans Rosenfeld 		return;
10438f23e9faSHans Rosenfeld 	}
10448f23e9faSHans Rosenfeld 	port->clean_address_sbp = 0;
10458f23e9faSHans Rosenfeld 
10468f23e9faSHans Rosenfeld 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_els_completion_msg,
10478f23e9faSHans Rosenfeld 	    "Clean Address timeout: sid=%x prev=%x RATOV %d",
10488f23e9faSHans Rosenfeld 	    port->did, port->prev_did, hba->fc_ratov);
10498f23e9faSHans Rosenfeld 
10508f23e9faSHans Rosenfeld 	if (EMLXS_SLI_REG_DID(port, FABRIC_DID, &port->fabric_sparam,
10518f23e9faSHans Rosenfeld 	    sbp, NULL, NULL) == 0) {
10528f23e9faSHans Rosenfeld 		/* Deferred completion of this pkt until */
10538f23e9faSHans Rosenfeld 		/* login is complete */
10548f23e9faSHans Rosenfeld 		return;
10558f23e9faSHans Rosenfeld 	}
10568f23e9faSHans Rosenfeld 
10578f23e9faSHans Rosenfeld 	emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT,
10588f23e9faSHans Rosenfeld 	    IOERR_NO_RESOURCES, 1);
10598f23e9faSHans Rosenfeld 
10608f23e9faSHans Rosenfeld 	return;
10618f23e9faSHans Rosenfeld 
10628f23e9faSHans Rosenfeld } /* emlxs_timer_check_clean_address()  */
10638f23e9faSHans Rosenfeld 
10648f23e9faSHans Rosenfeld extern void
emlxs_timer_cancel_clean_address(emlxs_port_t * port)10658f23e9faSHans Rosenfeld emlxs_timer_cancel_clean_address(emlxs_port_t *port)
10668f23e9faSHans Rosenfeld {
10678f23e9faSHans Rosenfeld 	emlxs_hba_t *hba = HBA;
10688f23e9faSHans Rosenfeld 	emlxs_buf_t *sbp;
10698f23e9faSHans Rosenfeld 
10708f23e9faSHans Rosenfeld 	port->clean_address_timer = 0;
10718f23e9faSHans Rosenfeld 	sbp = port->clean_address_sbp;
10728f23e9faSHans Rosenfeld 	if (!sbp) {
10738f23e9faSHans Rosenfeld 		return;
10748f23e9faSHans Rosenfeld 	}
10758f23e9faSHans Rosenfeld 	port->clean_address_sbp = 0;
10768f23e9faSHans Rosenfeld 
10778f23e9faSHans Rosenfeld 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_els_completion_msg,
10788f23e9faSHans Rosenfeld 	    "Clean Address cancel: sid=%x prev=%x RATOV %d",
10798f23e9faSHans Rosenfeld 	    port->did, port->prev_did, hba->fc_ratov);
10808f23e9faSHans Rosenfeld 
10818f23e9faSHans Rosenfeld 	emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT,
10828f23e9faSHans Rosenfeld 	    IOERR_LINK_DOWN, 1);
10838f23e9faSHans Rosenfeld 
10848f23e9faSHans Rosenfeld } /* emlxs_timer_cancel_clean_address() */
10858f23e9faSHans Rosenfeld 
1086fcf3ce44SJohn Forte static void
emlxs_timer_check_ub(emlxs_port_t * port)1087fcf3ce44SJohn Forte emlxs_timer_check_ub(emlxs_port_t *port)
1088fcf3ce44SJohn Forte {
1089fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
1090fcf3ce44SJohn Forte 	emlxs_unsol_buf_t *ulistp;
1091fcf3ce44SJohn Forte 	fc_unsol_buf_t *ubp;
1092fcf3ce44SJohn Forte 	emlxs_ub_priv_t *ub_priv;
1093fcf3ce44SJohn Forte 	uint32_t i;
1094fcf3ce44SJohn Forte 
1095fcf3ce44SJohn Forte 	if (port->ub_timer > hba->timer_tics) {
1096fcf3ce44SJohn Forte 		return;
1097fcf3ce44SJohn Forte 	}
1098291a2b48SSukumar Swaminathan 
1099fcf3ce44SJohn Forte 	port->ub_timer = hba->timer_tics + EMLXS_UB_PERIOD;
1100fcf3ce44SJohn Forte 
1101fcf3ce44SJohn Forte 	/* Check the unsolicited buffers */
1102fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_UB_LOCK);
1103fcf3ce44SJohn Forte 
1104fcf3ce44SJohn Forte 	ulistp = port->ub_pool;
1105fcf3ce44SJohn Forte 	while (ulistp) {
1106fcf3ce44SJohn Forte 		/* Check buffers in this pool */
1107fcf3ce44SJohn Forte 		for (i = 0; i < ulistp->pool_nentries; i++) {
1108fcf3ce44SJohn Forte 			ubp = (fc_unsol_buf_t *)&ulistp->fc_ubufs[i];
1109fcf3ce44SJohn Forte 			ub_priv = ubp->ub_fca_private;
1110fcf3ce44SJohn Forte 
1111fcf3ce44SJohn Forte 			if (!(ub_priv->flags & EMLXS_UB_IN_USE)) {
1112fcf3ce44SJohn Forte 				continue;
1113fcf3ce44SJohn Forte 			}
1114291a2b48SSukumar Swaminathan 
1115291a2b48SSukumar Swaminathan 			/* If buffer has timed out, print message and */
1116291a2b48SSukumar Swaminathan 			/* increase timeout */
1117fcf3ce44SJohn Forte 			if ((ub_priv->time + ub_priv->timeout) <=
1118fcf3ce44SJohn Forte 			    hba->timer_tics) {
1119fcf3ce44SJohn Forte 				ub_priv->flags |= EMLXS_UB_TIMEOUT;
1120fcf3ce44SJohn Forte 
1121291a2b48SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
1122291a2b48SSukumar Swaminathan 				    &emlxs_sfs_debug_msg,
1123fcf3ce44SJohn Forte 				    "Stale UB buffer detected (%d mins): "
1124291a2b48SSukumar Swaminathan 				    "buffer=%p (%x,%x,%x,%x)",
1125291a2b48SSukumar Swaminathan 				    (ub_priv->timeout / 60), ubp,
1126291a2b48SSukumar Swaminathan 				    ubp->ub_frame.type, ubp->ub_frame.s_id,
1127291a2b48SSukumar Swaminathan 				    ubp->ub_frame.ox_id, ubp->ub_frame.rx_id);
1128fcf3ce44SJohn Forte 
1129fcf3ce44SJohn Forte 				/* Increase timeout period */
1130fcf3ce44SJohn Forte 
1131291a2b48SSukumar Swaminathan 				/* If timeout was 5 mins or less, */
1132291a2b48SSukumar Swaminathan 				/* increase it to 10 mins */
1133fcf3ce44SJohn Forte 				if (ub_priv->timeout <= (5 * 60)) {
1134fcf3ce44SJohn Forte 					ub_priv->timeout = (10 * 60);
1135fcf3ce44SJohn Forte 				}
1136291a2b48SSukumar Swaminathan 				/* If timeout was 10 mins or less, */
1137291a2b48SSukumar Swaminathan 				/* increase it to 30 mins */
1138fcf3ce44SJohn Forte 				else if (ub_priv->timeout <= (10 * 60)) {
1139fcf3ce44SJohn Forte 					ub_priv->timeout = (30 * 60);
1140fcf3ce44SJohn Forte 				}
1141fcf3ce44SJohn Forte 				/* Otherwise double it. */
1142fcf3ce44SJohn Forte 				else {
1143fcf3ce44SJohn Forte 					ub_priv->timeout *= 2;
1144fcf3ce44SJohn Forte 				}
1145fcf3ce44SJohn Forte 			}
1146fcf3ce44SJohn Forte 		}
1147fcf3ce44SJohn Forte 
1148fcf3ce44SJohn Forte 		ulistp = ulistp->pool_next;
1149fcf3ce44SJohn Forte 	}
1150fcf3ce44SJohn Forte 
1151fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_UB_LOCK);
1152fcf3ce44SJohn Forte 
1153fcf3ce44SJohn Forte 	return;
1154fcf3ce44SJohn Forte 
115582527734SSukumar Swaminathan } /* emlxs_timer_check_ub()  */
1156fcf3ce44SJohn Forte 
1157fcf3ce44SJohn Forte 
1158fcf3ce44SJohn Forte /* EMLXS_FCTAB_LOCK must be held to call this */
1159fcf3ce44SJohn Forte static uint32_t
emlxs_pkt_chip_timeout(emlxs_port_t * port,emlxs_buf_t * sbp,Q * abortq,uint8_t * flag)1160291a2b48SSukumar Swaminathan emlxs_pkt_chip_timeout(emlxs_port_t *port, emlxs_buf_t *sbp, Q *abortq,
1161291a2b48SSukumar Swaminathan     uint8_t *flag)
1162fcf3ce44SJohn Forte {
1163fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
116482527734SSukumar Swaminathan 	CHANNEL *cp = (CHANNEL *)sbp->channel;
1165fcf3ce44SJohn Forte 	IOCBQ *iocbq = NULL;
1166fcf3ce44SJohn Forte 	fc_packet_t *pkt;
1167fcf3ce44SJohn Forte 	uint32_t rc = 0;
1168fcf3ce44SJohn Forte 
1169fcf3ce44SJohn Forte 	mutex_enter(&sbp->mtx);
1170fcf3ce44SJohn Forte 
1171fcf3ce44SJohn Forte 	/* Warning: Some FCT sbp's don't have fc_packet objects */
1172fcf3ce44SJohn Forte 	pkt = PRIV2PKT(sbp);
1173fcf3ce44SJohn Forte 
1174fcf3ce44SJohn Forte 	switch (sbp->abort_attempts) {
1175fcf3ce44SJohn Forte 	case 0:
1176fcf3ce44SJohn Forte 
1177fcf3ce44SJohn Forte 		/* Create the abort IOCB */
1178fcf3ce44SJohn Forte 		if (hba->state >= FC_LINK_UP) {
1179fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_timeout_msg,
11808f23e9faSHans Rosenfeld 			    "chipQ: 1:Aborting. sbp=%p iotag=%d tmo=%d "
1181a9800bebSGarrett D'Amore 			    "flags=%x",
1182291a2b48SSukumar Swaminathan 			    sbp, sbp->iotag,
1183291a2b48SSukumar Swaminathan 			    (pkt) ? pkt->pkt_timeout : 0, sbp->pkt_flags);
1184fcf3ce44SJohn Forte 
1185291a2b48SSukumar Swaminathan 			iocbq =
1186291a2b48SSukumar Swaminathan 			    emlxs_create_abort_xri_cn(port, sbp->node,
118782527734SSukumar Swaminathan 			    sbp->iotag, cp, sbp->class, ABORT_TYPE_ABTS);
1188fcf3ce44SJohn Forte 
1189291a2b48SSukumar Swaminathan 			/* The adapter will make 2 attempts to send ABTS */
1190291a2b48SSukumar Swaminathan 			/* with 2*ratov timeout each time */
1191291a2b48SSukumar Swaminathan 			sbp->ticks =
1192291a2b48SSukumar Swaminathan 			    hba->timer_tics + (4 * hba->fc_ratov) + 10;
1193fcf3ce44SJohn Forte 		} else {
1194fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_timeout_msg,
11958f23e9faSHans Rosenfeld 			    "chipQ: 1:Closing. sbp=%p iotag=%d tmo=%d "
1196a9800bebSGarrett D'Amore 			    "flags=%x",
1197291a2b48SSukumar Swaminathan 			    sbp, sbp->iotag,
1198291a2b48SSukumar Swaminathan 			    (pkt) ? pkt->pkt_timeout : 0, sbp->pkt_flags);
1199fcf3ce44SJohn Forte 
1200291a2b48SSukumar Swaminathan 			iocbq =
1201291a2b48SSukumar Swaminathan 			    emlxs_create_close_xri_cn(port, sbp->node,
120282527734SSukumar Swaminathan 			    sbp->iotag, cp);
1203fcf3ce44SJohn Forte 
1204fcf3ce44SJohn Forte 			sbp->ticks = hba->timer_tics + 30;
1205fcf3ce44SJohn Forte 		}
1206fcf3ce44SJohn Forte 
1207fcf3ce44SJohn Forte 		/* set the flags */
1208fcf3ce44SJohn Forte 		sbp->pkt_flags |= (PACKET_IN_TIMEOUT | PACKET_XRI_CLOSED);
1209fcf3ce44SJohn Forte 
121082527734SSukumar Swaminathan 		flag[cp->channelno] = 1;
1211fcf3ce44SJohn Forte 		rc = 0;
1212fcf3ce44SJohn Forte 
1213fcf3ce44SJohn Forte 		break;
1214fcf3ce44SJohn Forte 
1215fcf3ce44SJohn Forte 	case 1:
1216fcf3ce44SJohn Forte 
1217fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_timeout_msg,
12188f23e9faSHans Rosenfeld 		    "chipQ: 2:Closing. sbp=%p iotag=%d", sbp, sbp->iotag);
1219fcf3ce44SJohn Forte 
1220291a2b48SSukumar Swaminathan 		iocbq =
1221291a2b48SSukumar Swaminathan 		    emlxs_create_close_xri_cn(port, sbp->node, sbp->iotag,
122282527734SSukumar Swaminathan 		    cp);
1223fcf3ce44SJohn Forte 
1224fcf3ce44SJohn Forte 		sbp->ticks = hba->timer_tics + 30;
1225fcf3ce44SJohn Forte 
122682527734SSukumar Swaminathan 		flag[cp->channelno] = 1;
1227fcf3ce44SJohn Forte 		rc = 0;
1228fcf3ce44SJohn Forte 
1229fcf3ce44SJohn Forte 		break;
1230fcf3ce44SJohn Forte 
1231fcf3ce44SJohn Forte 	case 2:
1232fcf3ce44SJohn Forte 
1233fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_timeout_msg,
12348f23e9faSHans Rosenfeld 		    "chipQ: 3:Resetting link. sbp=%p iotag=%d", sbp,
1235291a2b48SSukumar Swaminathan 		    sbp->iotag);
1236fcf3ce44SJohn Forte 
1237fcf3ce44SJohn Forte 		sbp->ticks = hba->timer_tics + 60;
1238fcf3ce44SJohn Forte 		rc = 1;
1239fcf3ce44SJohn Forte 
1240fcf3ce44SJohn Forte 		break;
1241fcf3ce44SJohn Forte 
1242fcf3ce44SJohn Forte 	default:
1243fcf3ce44SJohn Forte 
1244fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_timeout_msg,
12458f23e9faSHans Rosenfeld 		    "chipQ: %d:Resetting adapter. sbp=%p iotag=%d",
1246fcf3ce44SJohn Forte 		    sbp->abort_attempts, sbp, sbp->iotag);
1247fcf3ce44SJohn Forte 
1248fcf3ce44SJohn Forte 		sbp->ticks = hba->timer_tics + 60;
1249fcf3ce44SJohn Forte 		rc = 2;
1250fcf3ce44SJohn Forte 
1251fcf3ce44SJohn Forte 		break;
1252fcf3ce44SJohn Forte 	}
1253fcf3ce44SJohn Forte 
1254fcf3ce44SJohn Forte 	sbp->abort_attempts++;
1255fcf3ce44SJohn Forte 	mutex_exit(&sbp->mtx);
1256fcf3ce44SJohn Forte 
1257fcf3ce44SJohn Forte 	if (iocbq) {
1258fcf3ce44SJohn Forte 		if (abortq->q_first) {
1259291a2b48SSukumar Swaminathan 			((IOCBQ *)abortq->q_last)->next = iocbq;
1260fcf3ce44SJohn Forte 			abortq->q_last = (uint8_t *)iocbq;
1261fcf3ce44SJohn Forte 			abortq->q_cnt++;
1262fcf3ce44SJohn Forte 		} else {
1263fcf3ce44SJohn Forte 			abortq->q_first = (uint8_t *)iocbq;
1264fcf3ce44SJohn Forte 			abortq->q_last = (uint8_t *)iocbq;
1265fcf3ce44SJohn Forte 			abortq->q_cnt = 1;
1266fcf3ce44SJohn Forte 		}
1267fcf3ce44SJohn Forte 		iocbq->next = NULL;
1268fcf3ce44SJohn Forte 	}
1269291a2b48SSukumar Swaminathan 
1270fcf3ce44SJohn Forte 	return (rc);
1271fcf3ce44SJohn Forte 
127282527734SSukumar Swaminathan } /* emlxs_pkt_chip_timeout() */
1273fcf3ce44SJohn Forte 
1274fcf3ce44SJohn Forte 
12758f23e9faSHans Rosenfeld static void
emlxs_timer_check_pools(emlxs_hba_t * hba)12768f23e9faSHans Rosenfeld emlxs_timer_check_pools(emlxs_hba_t *hba)
12778f23e9faSHans Rosenfeld {
12788f23e9faSHans Rosenfeld 	uint32_t i;
12798f23e9faSHans Rosenfeld 	MEMSEG *seg;
12808f23e9faSHans Rosenfeld 	emlxs_config_t *cfg = &CFG;
12818f23e9faSHans Rosenfeld 
12828f23e9faSHans Rosenfeld 	if (cfg[CFG_MEM_DYNAMIC].current == 0) {
12838f23e9faSHans Rosenfeld 		return;
12848f23e9faSHans Rosenfeld 	}
12858f23e9faSHans Rosenfeld 
12868f23e9faSHans Rosenfeld 	if (hba->mem_timer > hba->timer_tics) {
12878f23e9faSHans Rosenfeld 		return;
12888f23e9faSHans Rosenfeld 	}
12898f23e9faSHans Rosenfeld 
12908f23e9faSHans Rosenfeld 	hba->mem_timer = hba->timer_tics + cfg[CFG_MEM_DYNAMIC].current;
12918f23e9faSHans Rosenfeld 
12928f23e9faSHans Rosenfeld 	seg = hba->memseg;
12938f23e9faSHans Rosenfeld 	for (i = 0; i < FC_MAX_SEG; i++, seg++) {
12948f23e9faSHans Rosenfeld 		if (seg->fc_memflag & FC_MEMSEG_DYNAMIC) {
12958f23e9faSHans Rosenfeld 			emlxs_mem_pool_clean(hba, seg);
12968f23e9faSHans Rosenfeld 		}
12978f23e9faSHans Rosenfeld 	}
12988f23e9faSHans Rosenfeld 
12998f23e9faSHans Rosenfeld #ifdef SFCT_SUPPORT
13008f23e9faSHans Rosenfeld {
13018f23e9faSHans Rosenfeld 	uint32_t j;
13028f23e9faSHans Rosenfeld 	emlxs_port_t *port;
13038f23e9faSHans Rosenfeld 
13048f23e9faSHans Rosenfeld 	for (i = 0; i < MAX_VPORTS; i++) {
13058f23e9faSHans Rosenfeld 		port = &VPORT(i);
13068f23e9faSHans Rosenfeld 
13078f23e9faSHans Rosenfeld 		if (!(port->flag & EMLXS_PORT_BOUND) ||
13088f23e9faSHans Rosenfeld 		    !(port->flag & EMLXS_TGT_ENABLED) ||
13098f23e9faSHans Rosenfeld 		    !port->fct_memseg) {
13108f23e9faSHans Rosenfeld 			continue;
13118f23e9faSHans Rosenfeld 		}
13128f23e9faSHans Rosenfeld 
13138f23e9faSHans Rosenfeld 		seg = port->fct_memseg;
13148f23e9faSHans Rosenfeld 		for (j = 0; j < port->fct_memseg_cnt; j++, seg++) {
13158f23e9faSHans Rosenfeld 			if (seg->fc_memflag & FC_MEMSEG_DYNAMIC) {
13168f23e9faSHans Rosenfeld 				emlxs_mem_pool_clean(hba, seg);
13178f23e9faSHans Rosenfeld 			}
13188f23e9faSHans Rosenfeld 		}
13198f23e9faSHans Rosenfeld 	}
13208f23e9faSHans Rosenfeld }
13218f23e9faSHans Rosenfeld #endif /* SFCT_SUPPORT */
13228f23e9faSHans Rosenfeld 
13238f23e9faSHans Rosenfeld 	return;
13248f23e9faSHans Rosenfeld 
13258f23e9faSHans Rosenfeld } /* emlxs_timer_check_pools() */
13268f23e9faSHans Rosenfeld 
13278f23e9faSHans Rosenfeld 
1328fcf3ce44SJohn Forte #ifdef TX_WATCHDOG
1329fcf3ce44SJohn Forte 
1330fcf3ce44SJohn Forte static void
emlxs_tx_watchdog(emlxs_hba_t * hba)1331fcf3ce44SJohn Forte emlxs_tx_watchdog(emlxs_hba_t *hba)
1332fcf3ce44SJohn Forte {
1333fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
1334fcf3ce44SJohn Forte 	NODELIST *nlp;
133582527734SSukumar Swaminathan 	uint32_t channelno;
133682527734SSukumar Swaminathan 	CHANNEL *cp;
1337fcf3ce44SJohn Forte 	IOCBQ *next;
1338fcf3ce44SJohn Forte 	IOCBQ *iocbq;
1339fcf3ce44SJohn Forte 	IOCB *iocb;
1340fcf3ce44SJohn Forte 	uint32_t found;
1341fcf3ce44SJohn Forte 	MATCHMAP *bmp;
1342fcf3ce44SJohn Forte 	Q abort;
1343fcf3ce44SJohn Forte 	uint32_t iotag;
1344fcf3ce44SJohn Forte 	emlxs_buf_t *sbp;
1345fcf3ce44SJohn Forte 	fc_packet_t *pkt = NULL;
1346fcf3ce44SJohn Forte 	uint32_t cmd;
1347fcf3ce44SJohn Forte 	uint32_t did;
1348fcf3ce44SJohn Forte 
1349291a2b48SSukumar Swaminathan 	bzero((void *)&abort, sizeof (Q));
1350fcf3ce44SJohn Forte 
135182527734SSukumar Swaminathan 	mutex_enter(&EMLXS_TX_CHANNEL_LOCK);
135282527734SSukumar Swaminathan 
135382527734SSukumar Swaminathan 	mutex_enter(&EMLXS_FCTAB_LOCK);
135482527734SSukumar Swaminathan 	for (iotag = 1; iotag < hba->max_iotag; iotag++) {
135582527734SSukumar Swaminathan 		sbp = hba->fc_table[iotag];
135682527734SSukumar Swaminathan 		if (sbp && (sbp != STALE_PACKET) &&
135782527734SSukumar Swaminathan 		    (sbp->pkt_flags & PACKET_IN_TXQ)) {
135882527734SSukumar Swaminathan 			nlp = sbp->node;
135982527734SSukumar Swaminathan 			iocbq = &sbp->iocbq;
136082527734SSukumar Swaminathan 
136182527734SSukumar Swaminathan 			channelno = (CHANNEL *)(sbp->channel)->channelno;
136282527734SSukumar Swaminathan 			if (iocbq->flag & IOCB_PRIORITY) {
136382527734SSukumar Swaminathan 				iocbq =
136482527734SSukumar Swaminathan 				    (IOCBQ *)nlp->nlp_ptx[channelno].
136582527734SSukumar Swaminathan 				    q_first;
136682527734SSukumar Swaminathan 			} else {
136782527734SSukumar Swaminathan 				iocbq =
136882527734SSukumar Swaminathan 				    (IOCBQ *)nlp->nlp_tx[channelno].
136982527734SSukumar Swaminathan 				    q_first;
137082527734SSukumar Swaminathan 			}
1371fcf3ce44SJohn Forte 
137282527734SSukumar Swaminathan 			/* Find a matching entry */
137382527734SSukumar Swaminathan 			found = 0;
137482527734SSukumar Swaminathan 			while (iocbq) {
137582527734SSukumar Swaminathan 				if (iocbq == &sbp->iocbq) {
137682527734SSukumar Swaminathan 					found = 1;
137782527734SSukumar Swaminathan 					break;
137882527734SSukumar Swaminathan 				}
1379fcf3ce44SJohn Forte 
138082527734SSukumar Swaminathan 				iocbq = (IOCBQ *)iocbq->next;
138182527734SSukumar Swaminathan 			}
1382fcf3ce44SJohn Forte 
138382527734SSukumar Swaminathan 			if (!found) {
138482527734SSukumar Swaminathan 				if (!(sbp->pkt_flags & PACKET_STALE)) {
138582527734SSukumar Swaminathan 					mutex_enter(&sbp->mtx);
138682527734SSukumar Swaminathan 					sbp->pkt_flags |=
138782527734SSukumar Swaminathan 					    PACKET_STALE;
138882527734SSukumar Swaminathan 					mutex_exit(&sbp->mtx);
1389fcf3ce44SJohn Forte 				} else {
139082527734SSukumar Swaminathan 					if (abort.q_first == 0) {
139182527734SSukumar Swaminathan 						abort.q_first =
139282527734SSukumar Swaminathan 						    &sbp->iocbq;
139382527734SSukumar Swaminathan 					} else {
139482527734SSukumar Swaminathan 						((IOCBQ *)abort.
139582527734SSukumar Swaminathan 						    q_last)->next =
139682527734SSukumar Swaminathan 						    &sbp->iocbq;
1397fcf3ce44SJohn Forte 					}
1398291a2b48SSukumar Swaminathan 
139982527734SSukumar Swaminathan 					abort.q_last = &sbp->iocbq;
140082527734SSukumar Swaminathan 					abort.q_cnt++;
1401fcf3ce44SJohn Forte 				}
1402fcf3ce44SJohn Forte 
140382527734SSukumar Swaminathan 			} else {
140482527734SSukumar Swaminathan 				if ((sbp->pkt_flags & PACKET_STALE)) {
140582527734SSukumar Swaminathan 					mutex_enter(&sbp->mtx);
140682527734SSukumar Swaminathan 					sbp->pkt_flags &=
140782527734SSukumar Swaminathan 					    ~PACKET_STALE;
140882527734SSukumar Swaminathan 					mutex_exit(&sbp->mtx);
1409fcf3ce44SJohn Forte 				}
1410fcf3ce44SJohn Forte 			}
1411fcf3ce44SJohn Forte 		}
1412fcf3ce44SJohn Forte 	}
141382527734SSukumar Swaminathan 	mutex_exit(&EMLXS_FCTAB_LOCK);
1414fcf3ce44SJohn Forte 
1415291a2b48SSukumar Swaminathan 	iocbq = (IOCBQ *)abort.q_first;
1416fcf3ce44SJohn Forte 	while (iocbq) {
1417291a2b48SSukumar Swaminathan 		next = (IOCBQ *)iocbq->next;
1418fcf3ce44SJohn Forte 		iocbq->next = NULL;
1419fcf3ce44SJohn Forte 		sbp = (emlxs_buf_t *)iocbq->sbp;
1420fcf3ce44SJohn Forte 
1421fcf3ce44SJohn Forte 		pkt = PRIV2PKT(sbp);
1422fcf3ce44SJohn Forte 		if (pkt) {
142382527734SSukumar Swaminathan 			did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
1424fcf3ce44SJohn Forte 			cmd = *((uint32_t *)pkt->pkt_cmd);
142582527734SSukumar Swaminathan 			cmd = LE_SWAP32(cmd);
1426fcf3ce44SJohn Forte 		}
1427fcf3ce44SJohn Forte 
1428fcf3ce44SJohn Forte 
1429fcf3ce44SJohn Forte 		emlxs_tx_put(iocbq, 0);
1430fcf3ce44SJohn Forte 
1431fcf3ce44SJohn Forte 		iocbq = next;
1432fcf3ce44SJohn Forte 
1433fcf3ce44SJohn Forte 	}	/* end of while */
1434fcf3ce44SJohn Forte 
143582527734SSukumar Swaminathan 	mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
1436fcf3ce44SJohn Forte 
1437fcf3ce44SJohn Forte 	return;
1438fcf3ce44SJohn Forte 
143982527734SSukumar Swaminathan } /* emlxs_tx_watchdog() */
1440fcf3ce44SJohn Forte 
1441291a2b48SSukumar Swaminathan #endif /* TX_WATCHDOG */
1442fcf3ce44SJohn Forte 
1443fcf3ce44SJohn Forte 
1444fcf3ce44SJohn Forte #ifdef DHCHAP_SUPPORT
1445fcf3ce44SJohn Forte 
1446fcf3ce44SJohn Forte static void
emlxs_timer_check_dhchap(emlxs_port_t * port)1447fcf3ce44SJohn Forte emlxs_timer_check_dhchap(emlxs_port_t *port)
1448fcf3ce44SJohn Forte {
1449fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
1450fcf3ce44SJohn Forte 	uint32_t i;
1451fcf3ce44SJohn Forte 	NODELIST *ndlp = NULL;
1452fcf3ce44SJohn Forte 
1453fcf3ce44SJohn Forte 	for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
1454fcf3ce44SJohn Forte 		ndlp = port->node_table[i];
1455fcf3ce44SJohn Forte 
1456fcf3ce44SJohn Forte 		if (!ndlp) {
1457fcf3ce44SJohn Forte 			continue;
1458fcf3ce44SJohn Forte 		}
1459291a2b48SSukumar Swaminathan 
1460fcf3ce44SJohn Forte 		/* Check authentication response timeout */
1461fcf3ce44SJohn Forte 		if (ndlp->node_dhc.nlp_authrsp_tmo &&
1462fcf3ce44SJohn Forte 		    (hba->timer_tics >= ndlp->node_dhc.nlp_authrsp_tmo)) {
1463fcf3ce44SJohn Forte 			/* Trigger authresp timeout handler */
1464fcf3ce44SJohn Forte 			(void) emlxs_dhc_authrsp_timeout(port, ndlp, NULL);
1465fcf3ce44SJohn Forte 		}
1466291a2b48SSukumar Swaminathan 
1467fcf3ce44SJohn Forte 		/* Check reauthentication timeout */
1468fcf3ce44SJohn Forte 		if (ndlp->node_dhc.nlp_reauth_tmo &&
1469fcf3ce44SJohn Forte 		    (hba->timer_tics >= ndlp->node_dhc.nlp_reauth_tmo)) {
1470fcf3ce44SJohn Forte 			/* Trigger reauth timeout handler */
1471fcf3ce44SJohn Forte 			emlxs_dhc_reauth_timeout(port, NULL, ndlp);
1472fcf3ce44SJohn Forte 		}
1473fcf3ce44SJohn Forte 	}
1474fcf3ce44SJohn Forte 	return;
1475fcf3ce44SJohn Forte 
147682527734SSukumar Swaminathan } /* emlxs_timer_check_dhchap */
1477fcf3ce44SJohn Forte 
1478291a2b48SSukumar Swaminathan #endif /* DHCHAP_SUPPORT */
1479