1fcf3ce44SJohn Forte /*
2fcf3ce44SJohn Forte  * CDDL HEADER START
3fcf3ce44SJohn Forte  *
4fcf3ce44SJohn Forte  * The contents of this file are subject to the terms of the
5fcf3ce44SJohn Forte  * Common Development and Distribution License (the "License").
6fcf3ce44SJohn Forte  * You may not use this file except in compliance with the License.
7fcf3ce44SJohn Forte  *
8fcf3ce44SJohn Forte  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fcf3ce44SJohn Forte  * or http://www.opensolaris.org/os/licensing.
10fcf3ce44SJohn Forte  * See the License for the specific language governing permissions
11fcf3ce44SJohn Forte  * and limitations under the License.
12fcf3ce44SJohn Forte  *
13fcf3ce44SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
14fcf3ce44SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fcf3ce44SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
16fcf3ce44SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
17fcf3ce44SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
18fcf3ce44SJohn Forte  *
19fcf3ce44SJohn Forte  * CDDL HEADER END
20fcf3ce44SJohn Forte  */
21fcf3ce44SJohn Forte 
22fcf3ce44SJohn Forte /*
23bce54adfSSukumar Swaminathan  * Copyright 2010 Emulex.  All rights reserved.
2482527734SSukumar Swaminathan  * Use is subject to license terms.
25fcf3ce44SJohn Forte  */
26fcf3ce44SJohn Forte 
2782527734SSukumar Swaminathan 
2893c20f26SSukumar Swaminathan #include <emlxs.h>
29fcf3ce44SJohn Forte 
30fcf3ce44SJohn Forte /* Timer period in seconds */
31fcf3ce44SJohn Forte #define	EMLXS_TIMER_PERIOD		1	/* secs */
32fcf3ce44SJohn Forte #define	EMLXS_PKT_PERIOD		5	/* secs */
33fcf3ce44SJohn Forte #define	EMLXS_UB_PERIOD			60	/* secs */
34fcf3ce44SJohn Forte 
35fcf3ce44SJohn Forte EMLXS_MSG_DEF(EMLXS_CLOCK_C);
36fcf3ce44SJohn Forte 
37fcf3ce44SJohn Forte 
38fcf3ce44SJohn Forte static void emlxs_timer_check_loopback(emlxs_hba_t *hba);
39fcf3ce44SJohn Forte 
40fcf3ce44SJohn Forte #ifdef DHCHAP_SUPPORT
41fcf3ce44SJohn Forte static void emlxs_timer_check_dhchap(emlxs_port_t *port);
42291a2b48SSukumar Swaminathan #endif /* DHCHAP_SUPPORT */
43291a2b48SSukumar Swaminathan 
44291a2b48SSukumar Swaminathan static void	emlxs_timer(void *arg);
45*6a573d82SSukumar 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);
51291a2b48SSukumar Swaminathan static void	emlxs_timer_check_ub(emlxs_port_t *port);
5282527734SSukumar Swaminathan static void	emlxs_timer_check_channels(emlxs_hba_t *hba, uint8_t *flag);
53291a2b48SSukumar Swaminathan static uint32_t	emlxs_pkt_chip_timeout(emlxs_port_t *port, emlxs_buf_t *sbp,
54291a2b48SSukumar Swaminathan 			Q *abortq, uint8_t *flag);
55fcf3ce44SJohn Forte 
56fcf3ce44SJohn Forte #ifdef TX_WATCHDOG
57291a2b48SSukumar Swaminathan static void	emlxs_tx_watchdog(emlxs_hba_t *hba);
58291a2b48SSukumar Swaminathan #endif /* TX_WATCHDOG */
59fcf3ce44SJohn Forte 
60fcf3ce44SJohn Forte extern clock_t
61fcf3ce44SJohn Forte emlxs_timeout(emlxs_hba_t *hba, uint32_t timeout)
62fcf3ce44SJohn Forte {
63fcf3ce44SJohn Forte 	emlxs_config_t *cfg = &CFG;
64fcf3ce44SJohn Forte 	clock_t time;
65fcf3ce44SJohn Forte 
66fcf3ce44SJohn Forte 	/* Set thread timeout */
67fcf3ce44SJohn Forte 	if (cfg[CFG_TIMEOUT_ENABLE].current) {
68fcf3ce44SJohn Forte 		(void) drv_getparm(LBOLT, &time);
69fcf3ce44SJohn Forte 		time += (timeout * drv_usectohz(1000000));
70fcf3ce44SJohn Forte 	} else {
71fcf3ce44SJohn Forte 		time = -1;
72fcf3ce44SJohn Forte 	}
73fcf3ce44SJohn Forte 
74fcf3ce44SJohn Forte 	return (time);
75fcf3ce44SJohn Forte 
7682527734SSukumar Swaminathan } /* emlxs_timeout() */
77fcf3ce44SJohn Forte 
78fcf3ce44SJohn Forte 
79fcf3ce44SJohn Forte static void
80fcf3ce44SJohn Forte emlxs_timer(void *arg)
81fcf3ce44SJohn Forte {
82fcf3ce44SJohn Forte 	emlxs_hba_t *hba = (emlxs_hba_t *)arg;
83fcf3ce44SJohn Forte 
84fcf3ce44SJohn Forte 	if (!hba->timer_id) {
85fcf3ce44SJohn Forte 		return;
86fcf3ce44SJohn Forte 	}
87291a2b48SSukumar Swaminathan 
88fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_TIMER_LOCK);
89fcf3ce44SJohn Forte 
9082527734SSukumar Swaminathan 	EMLXS_SLI_POLL_ERRATT(hba);
9182527734SSukumar Swaminathan 
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;
101fcf3ce44SJohn Forte 		hba->timer_flags |= EMLXS_TIMER_ENDED;
102fcf3ce44SJohn Forte 
103fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_TIMER_LOCK);
104fcf3ce44SJohn Forte 		return;
105fcf3ce44SJohn Forte 	}
106291a2b48SSukumar Swaminathan 
107fcf3ce44SJohn Forte 	hba->timer_flags |= (EMLXS_TIMER_BUSY | EMLXS_TIMER_STARTED);
108fcf3ce44SJohn Forte 	hba->timer_tics = DRV_TIME;
109fcf3ce44SJohn Forte 
110fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_TIMER_LOCK);
111fcf3ce44SJohn Forte 
112291a2b48SSukumar Swaminathan 	/* Perform standard checks */
113291a2b48SSukumar Swaminathan 	emlxs_timer_checks(hba);
114291a2b48SSukumar Swaminathan 
115291a2b48SSukumar Swaminathan 	/* Restart the timer */
116291a2b48SSukumar Swaminathan 	mutex_enter(&EMLXS_TIMER_LOCK);
117291a2b48SSukumar Swaminathan 
118291a2b48SSukumar Swaminathan 	hba->timer_flags &= ~EMLXS_TIMER_BUSY;
119291a2b48SSukumar Swaminathan 
120291a2b48SSukumar Swaminathan 	/* If timer is still enabled, restart it */
121291a2b48SSukumar Swaminathan 	if (!(hba->timer_flags & EMLXS_TIMER_KILL)) {
122291a2b48SSukumar Swaminathan 		hba->timer_id =
123291a2b48SSukumar Swaminathan 		    timeout(emlxs_timer, (void *)hba,
124291a2b48SSukumar Swaminathan 		    (EMLXS_TIMER_PERIOD * drv_usectohz(1000000)));
125291a2b48SSukumar Swaminathan 	} else {
126291a2b48SSukumar Swaminathan 		hba->timer_id = 0;
127291a2b48SSukumar Swaminathan 		hba->timer_flags |= EMLXS_TIMER_ENDED;
128291a2b48SSukumar Swaminathan 	}
129291a2b48SSukumar Swaminathan 
130291a2b48SSukumar Swaminathan 	mutex_exit(&EMLXS_TIMER_LOCK);
131291a2b48SSukumar Swaminathan 
132291a2b48SSukumar Swaminathan 	return;
133291a2b48SSukumar Swaminathan 
13482527734SSukumar Swaminathan } /* emlxs_timer() */
135291a2b48SSukumar Swaminathan 
136291a2b48SSukumar Swaminathan 
137291a2b48SSukumar Swaminathan extern void
138291a2b48SSukumar Swaminathan emlxs_timer_checks(emlxs_hba_t *hba)
139291a2b48SSukumar Swaminathan {
140291a2b48SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
14182527734SSukumar Swaminathan 	uint8_t flag[MAX_CHANNEL];
142291a2b48SSukumar Swaminathan 	uint32_t i;
143291a2b48SSukumar Swaminathan 	uint32_t rc;
144291a2b48SSukumar Swaminathan 
145fcf3ce44SJohn Forte 	/* Exit if we are still initializing */
146fcf3ce44SJohn Forte 	if (hba->state < FC_LINK_DOWN) {
147291a2b48SSukumar Swaminathan 		return;
148fcf3ce44SJohn Forte 	}
149291a2b48SSukumar Swaminathan 
150291a2b48SSukumar Swaminathan 	bzero((void *)flag, sizeof (flag));
151fcf3ce44SJohn Forte 
15282527734SSukumar Swaminathan 	/* Check SLI level timeouts */
15382527734SSukumar Swaminathan 	EMLXS_SLI_TIMER(hba);
15482527734SSukumar Swaminathan 
15582527734SSukumar Swaminathan 	/* Check event queue */
15682527734SSukumar Swaminathan 	emlxs_timer_check_events(hba);
157fcf3ce44SJohn Forte 
158fcf3ce44SJohn Forte 	/* Check heartbeat timer */
159fcf3ce44SJohn Forte 	emlxs_timer_check_heartbeat(hba);
160fcf3ce44SJohn Forte 
161*6a573d82SSukumar Swaminathan 	/* Check fw update timer */
162*6a573d82SSukumar Swaminathan 	emlxs_timer_check_fw_update(hba);
163*6a573d82SSukumar Swaminathan 
164fcf3ce44SJohn Forte #ifdef IDLE_TIMER
165fcf3ce44SJohn Forte 	emlxs_pm_idle_timer(hba);
166291a2b48SSukumar Swaminathan #endif /* IDLE_TIMER */
167fcf3ce44SJohn Forte 
168fcf3ce44SJohn Forte 	/* Check for loopback timeouts */
169fcf3ce44SJohn Forte 	emlxs_timer_check_loopback(hba);
170fcf3ce44SJohn Forte 
171fcf3ce44SJohn Forte 	/* Check for packet timeouts */
172fcf3ce44SJohn Forte 	rc = emlxs_timer_check_pkts(hba, flag);
173fcf3ce44SJohn Forte 
174fcf3ce44SJohn Forte 	if (rc) {
175fcf3ce44SJohn Forte 		/* Link or adapter is being reset */
176291a2b48SSukumar Swaminathan 		return;
177fcf3ce44SJohn Forte 	}
178291a2b48SSukumar Swaminathan 
179fcf3ce44SJohn Forte 	/* Check for linkup timeout */
180fcf3ce44SJohn Forte 	emlxs_timer_check_linkup(hba);
181fcf3ce44SJohn Forte 
182fcf3ce44SJohn Forte 	/* Check the ports */
183fcf3ce44SJohn Forte 	for (i = 0; i < MAX_VPORTS; i++) {
184fcf3ce44SJohn Forte 		port = &VPORT(i);
185fcf3ce44SJohn Forte 
186fcf3ce44SJohn Forte 		if (!(port->flag & EMLXS_PORT_BOUND)) {
187fcf3ce44SJohn Forte 			continue;
188fcf3ce44SJohn Forte 		}
189291a2b48SSukumar Swaminathan 
190fcf3ce44SJohn Forte 		/* Check for node gate timeouts */
191fcf3ce44SJohn Forte 		emlxs_timer_check_nodes(port, flag);
192fcf3ce44SJohn Forte 
193fcf3ce44SJohn Forte 		/* Check for tape discovery timeout */
194fcf3ce44SJohn Forte 		emlxs_timer_check_discovery(port);
195fcf3ce44SJohn Forte 
196fcf3ce44SJohn Forte 		/* Check for UB timeouts */
197fcf3ce44SJohn Forte 		emlxs_timer_check_ub(port);
198fcf3ce44SJohn Forte 
199fcf3ce44SJohn Forte #ifdef DHCHAP_SUPPORT
200fcf3ce44SJohn Forte 		/* Check for DHCHAP authentication timeouts */
201fcf3ce44SJohn Forte 		emlxs_timer_check_dhchap(port);
202291a2b48SSukumar Swaminathan #endif /* DHCHAP_SUPPORT */
203fcf3ce44SJohn Forte 
204fcf3ce44SJohn Forte 	}
205fcf3ce44SJohn Forte 
20682527734SSukumar Swaminathan 	/* Check for IO channel service timeouts */
207fcf3ce44SJohn Forte 	/* Always do this last */
20882527734SSukumar Swaminathan 	emlxs_timer_check_channels(hba, flag);
209fcf3ce44SJohn Forte 
210fcf3ce44SJohn Forte 	return;
211fcf3ce44SJohn Forte 
21282527734SSukumar Swaminathan } /* emlxs_timer_checks() */
213fcf3ce44SJohn Forte 
214fcf3ce44SJohn Forte 
215fcf3ce44SJohn Forte extern void
216fcf3ce44SJohn Forte emlxs_timer_start(emlxs_hba_t *hba)
217fcf3ce44SJohn Forte {
218fcf3ce44SJohn Forte 	if (hba->timer_id) {
219fcf3ce44SJohn Forte 		return;
220fcf3ce44SJohn Forte 	}
221291a2b48SSukumar Swaminathan 
222fcf3ce44SJohn Forte 	/* Restart the timer */
223fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_TIMER_LOCK);
224fcf3ce44SJohn Forte 	if (!hba->timer_id) {
225fcf3ce44SJohn Forte 		hba->timer_flags = 0;
226291a2b48SSukumar Swaminathan 		hba->timer_id =
227291a2b48SSukumar Swaminathan 		    timeout(emlxs_timer, (void *)hba, drv_usectohz(1000000));
228fcf3ce44SJohn Forte 	}
229fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_TIMER_LOCK);
230fcf3ce44SJohn Forte 
23182527734SSukumar Swaminathan } /* emlxs_timer_start() */
232fcf3ce44SJohn Forte 
233fcf3ce44SJohn Forte 
234fcf3ce44SJohn Forte extern void
235fcf3ce44SJohn Forte emlxs_timer_stop(emlxs_hba_t *hba)
236fcf3ce44SJohn Forte {
237fcf3ce44SJohn Forte 	if (!hba->timer_id) {
238fcf3ce44SJohn Forte 		return;
239fcf3ce44SJohn Forte 	}
240291a2b48SSukumar Swaminathan 
241fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_TIMER_LOCK);
242fcf3ce44SJohn Forte 	hba->timer_flags |= EMLXS_TIMER_KILL;
243fcf3ce44SJohn Forte 
244fcf3ce44SJohn Forte 	while (hba->timer_id) {
245fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_TIMER_LOCK);
246fcf3ce44SJohn Forte 		delay(drv_usectohz(500000));
247fcf3ce44SJohn Forte 		mutex_enter(&EMLXS_TIMER_LOCK);
248fcf3ce44SJohn Forte 	}
249fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_TIMER_LOCK);
250fcf3ce44SJohn Forte 
251fcf3ce44SJohn Forte 	return;
252fcf3ce44SJohn Forte 
25382527734SSukumar Swaminathan } /* emlxs_timer_stop() */
254fcf3ce44SJohn Forte 
255fcf3ce44SJohn Forte 
256fcf3ce44SJohn Forte static uint32_t
257fcf3ce44SJohn Forte emlxs_timer_check_pkts(emlxs_hba_t *hba, uint8_t *flag)
258fcf3ce44SJohn Forte {
259fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
260fcf3ce44SJohn Forte 	emlxs_config_t *cfg = &CFG;
261fcf3ce44SJohn Forte 	Q tmo;
26282527734SSukumar Swaminathan 	int32_t channelno;
26382527734SSukumar Swaminathan 	CHANNEL *cp;
264fcf3ce44SJohn Forte 	NODELIST *nlp;
265fcf3ce44SJohn Forte 	IOCBQ *prev;
266fcf3ce44SJohn Forte 	IOCBQ *next;
267fcf3ce44SJohn Forte 	IOCB *iocb;
268fcf3ce44SJohn Forte 	IOCBQ *iocbq;
269fcf3ce44SJohn Forte 	emlxs_buf_t *sbp;
270fcf3ce44SJohn Forte 	fc_packet_t *pkt;
271fcf3ce44SJohn Forte 	Q abort;
272fcf3ce44SJohn Forte 	uint32_t iotag;
273fcf3ce44SJohn Forte 	uint32_t rc;
274fcf3ce44SJohn Forte 
275fcf3ce44SJohn Forte 	if (!cfg[CFG_TIMEOUT_ENABLE].current) {
276fcf3ce44SJohn Forte 		return (0);
277fcf3ce44SJohn Forte 	}
278291a2b48SSukumar Swaminathan 
279fcf3ce44SJohn Forte 	if (hba->pkt_timer > hba->timer_tics) {
280fcf3ce44SJohn Forte 		return (0);
281fcf3ce44SJohn Forte 	}
282291a2b48SSukumar Swaminathan 
283fcf3ce44SJohn Forte 	hba->pkt_timer = hba->timer_tics + EMLXS_PKT_PERIOD;
284fcf3ce44SJohn Forte 
285fcf3ce44SJohn Forte 
286291a2b48SSukumar Swaminathan 	bzero((void *)&tmo, sizeof (Q));
287fcf3ce44SJohn Forte 
288fcf3ce44SJohn Forte 	/*
289fcf3ce44SJohn Forte 	 * We must hold the locks here because we never know when an iocb
290fcf3ce44SJohn Forte 	 * will be removed out from under us
291fcf3ce44SJohn Forte 	 */
292fcf3ce44SJohn Forte 
29382527734SSukumar Swaminathan 	mutex_enter(&EMLXS_TX_CHANNEL_LOCK);
294fcf3ce44SJohn Forte 
29582527734SSukumar Swaminathan 	for (channelno = 0; channelno < hba->chan_count; channelno++) {
29682527734SSukumar Swaminathan 		cp = &hba->chan[channelno];
297fcf3ce44SJohn Forte 
29882527734SSukumar Swaminathan 		/* Scan the tx queues for each active node on the channel */
299fcf3ce44SJohn Forte 
300fcf3ce44SJohn Forte 		/* Get the first node */
30182527734SSukumar Swaminathan 		nlp = (NODELIST *)cp->nodeq.q_first;
302fcf3ce44SJohn Forte 
303fcf3ce44SJohn Forte 		while (nlp) {
304fcf3ce44SJohn Forte 			/* Scan the node's priority tx queue */
305fcf3ce44SJohn Forte 			prev = NULL;
30682527734SSukumar Swaminathan 			iocbq = (IOCBQ *)nlp->nlp_ptx[channelno].q_first;
307fcf3ce44SJohn Forte 
308fcf3ce44SJohn Forte 			while (iocbq) {
309fcf3ce44SJohn Forte 				next = (IOCBQ *)iocbq->next;
310fcf3ce44SJohn Forte 				iocb = &iocbq->iocb;
311fcf3ce44SJohn Forte 				sbp = (emlxs_buf_t *)iocbq->sbp;
312fcf3ce44SJohn Forte 
313fcf3ce44SJohn Forte 				/* Check if iocb has timed out */
314fcf3ce44SJohn Forte 				if (sbp && hba->timer_tics >= sbp->ticks) {
315fcf3ce44SJohn Forte 					/* iocb timed out, now deque it */
316fcf3ce44SJohn Forte 					if (next == NULL) {
31782527734SSukumar Swaminathan 						nlp->nlp_ptx[channelno].q_last =
318fcf3ce44SJohn Forte 						    (uint8_t *)prev;
319fcf3ce44SJohn Forte 					}
320291a2b48SSukumar Swaminathan 
321fcf3ce44SJohn Forte 					if (prev == NULL) {
32282527734SSukumar Swaminathan 						nlp->nlp_ptx[channelno].
32382527734SSukumar Swaminathan 						    q_first = (uint8_t *)next;
324fcf3ce44SJohn Forte 					} else {
325fcf3ce44SJohn Forte 						prev->next = next;
326fcf3ce44SJohn Forte 					}
327fcf3ce44SJohn Forte 
328fcf3ce44SJohn Forte 					iocbq->next = NULL;
32982527734SSukumar Swaminathan 					nlp->nlp_ptx[channelno].q_cnt--;
330fcf3ce44SJohn Forte 
331291a2b48SSukumar Swaminathan 					/* Add this iocb to our local */
332291a2b48SSukumar Swaminathan 					/* timout queue */
333fcf3ce44SJohn Forte 
334fcf3ce44SJohn Forte 					/*
33582527734SSukumar Swaminathan 					 * This way we don't hold the TX_CHANNEL
336fcf3ce44SJohn Forte 					 * lock too long
337fcf3ce44SJohn Forte 					 */
338fcf3ce44SJohn Forte 
339fcf3ce44SJohn Forte 					if (tmo.q_first) {
340fcf3ce44SJohn Forte 						((IOCBQ *)tmo.q_last)->next =
341fcf3ce44SJohn Forte 						    iocbq;
342291a2b48SSukumar Swaminathan 						tmo.q_last =
343291a2b48SSukumar Swaminathan 						    (uint8_t *)iocbq;
344fcf3ce44SJohn Forte 						tmo.q_cnt++;
345fcf3ce44SJohn Forte 					} else {
346291a2b48SSukumar Swaminathan 						tmo.q_first =
347291a2b48SSukumar Swaminathan 						    (uint8_t *)iocbq;
348291a2b48SSukumar Swaminathan 						tmo.q_last =
349291a2b48SSukumar Swaminathan 						    (uint8_t *)iocbq;
350fcf3ce44SJohn Forte 						tmo.q_cnt = 1;
351fcf3ce44SJohn Forte 					}
352fcf3ce44SJohn Forte 					iocbq->next = NULL;
353fcf3ce44SJohn Forte 
354fcf3ce44SJohn Forte 				} else {
355fcf3ce44SJohn Forte 					prev = iocbq;
356fcf3ce44SJohn Forte 				}
357fcf3ce44SJohn Forte 
358fcf3ce44SJohn Forte 				iocbq = next;
359fcf3ce44SJohn Forte 
360fcf3ce44SJohn Forte 			}	/* while (iocbq) */
361fcf3ce44SJohn Forte 
362fcf3ce44SJohn Forte 
363fcf3ce44SJohn Forte 			/* Scan the node's tx queue */
364fcf3ce44SJohn Forte 			prev = NULL;
36582527734SSukumar Swaminathan 			iocbq = (IOCBQ *)nlp->nlp_tx[channelno].q_first;
366fcf3ce44SJohn Forte 
367fcf3ce44SJohn Forte 			while (iocbq) {
368fcf3ce44SJohn Forte 				next = (IOCBQ *)iocbq->next;
369fcf3ce44SJohn Forte 				iocb = &iocbq->iocb;
370fcf3ce44SJohn Forte 				sbp = (emlxs_buf_t *)iocbq->sbp;
371fcf3ce44SJohn Forte 
372fcf3ce44SJohn Forte 				/* Check if iocb has timed out */
373fcf3ce44SJohn Forte 				if (sbp && hba->timer_tics >= sbp->ticks) {
374fcf3ce44SJohn Forte 					/* iocb timed out, now deque it */
375fcf3ce44SJohn Forte 					if (next == NULL) {
37682527734SSukumar Swaminathan 						nlp->nlp_tx[channelno].q_last =
377fcf3ce44SJohn Forte 						    (uint8_t *)prev;
378fcf3ce44SJohn Forte 					}
379291a2b48SSukumar Swaminathan 
380fcf3ce44SJohn Forte 					if (prev == NULL) {
38182527734SSukumar Swaminathan 						nlp->nlp_tx[channelno].q_first =
382fcf3ce44SJohn Forte 						    (uint8_t *)next;
383fcf3ce44SJohn Forte 					} else {
384fcf3ce44SJohn Forte 						prev->next = next;
385fcf3ce44SJohn Forte 					}
386fcf3ce44SJohn Forte 
387fcf3ce44SJohn Forte 					iocbq->next = NULL;
38882527734SSukumar Swaminathan 					nlp->nlp_tx[channelno].q_cnt--;
389fcf3ce44SJohn Forte 
390291a2b48SSukumar Swaminathan 					/* Add this iocb to our local */
391291a2b48SSukumar Swaminathan 					/* timout queue */
392fcf3ce44SJohn Forte 
393fcf3ce44SJohn Forte 					/*
39482527734SSukumar Swaminathan 					 * This way we don't hold the TX_CHANNEL
395fcf3ce44SJohn Forte 					 * lock too long
396fcf3ce44SJohn Forte 					 */
397fcf3ce44SJohn Forte 
398fcf3ce44SJohn Forte 					if (tmo.q_first) {
399fcf3ce44SJohn Forte 						((IOCBQ *)tmo.q_last)->next =
400fcf3ce44SJohn Forte 						    iocbq;
401291a2b48SSukumar Swaminathan 						tmo.q_last =
402291a2b48SSukumar Swaminathan 						    (uint8_t *)iocbq;
403fcf3ce44SJohn Forte 						tmo.q_cnt++;
404fcf3ce44SJohn Forte 					} else {
405291a2b48SSukumar Swaminathan 						tmo.q_first =
406291a2b48SSukumar Swaminathan 						    (uint8_t *)iocbq;
407291a2b48SSukumar Swaminathan 						tmo.q_last =
408291a2b48SSukumar Swaminathan 						    (uint8_t *)iocbq;
409fcf3ce44SJohn Forte 						tmo.q_cnt = 1;
410fcf3ce44SJohn Forte 					}
411fcf3ce44SJohn Forte 					iocbq->next = NULL;
412fcf3ce44SJohn Forte 
413fcf3ce44SJohn Forte 				} else {
414fcf3ce44SJohn Forte 					prev = iocbq;
415fcf3ce44SJohn Forte 				}
416fcf3ce44SJohn Forte 
417fcf3ce44SJohn Forte 				iocbq = next;
418fcf3ce44SJohn Forte 
419fcf3ce44SJohn Forte 			}	/* while (iocbq) */
420fcf3ce44SJohn Forte 
42182527734SSukumar Swaminathan 			if (nlp == (NODELIST *)cp->nodeq.q_last) {
422fcf3ce44SJohn Forte 				nlp = NULL;
423fcf3ce44SJohn Forte 			} else {
42482527734SSukumar Swaminathan 				nlp = nlp->nlp_next[channelno];
425fcf3ce44SJohn Forte 			}
426fcf3ce44SJohn Forte 
42782527734SSukumar Swaminathan 		}	/* while (nlp) */
428fcf3ce44SJohn Forte 
429fcf3ce44SJohn Forte 	}	/* end of for */
430fcf3ce44SJohn Forte 
431fcf3ce44SJohn Forte 	/* Now cleanup the iocb's */
432fcf3ce44SJohn Forte 	iocbq = (IOCBQ *)tmo.q_first;
433fcf3ce44SJohn Forte 	while (iocbq) {
434fcf3ce44SJohn Forte 		/* Free the IoTag and the bmp */
435fcf3ce44SJohn Forte 		iocb = &iocbq->iocb;
43682527734SSukumar Swaminathan 		channelno = ((CHANNEL *)iocbq->channel)->channelno;
43782527734SSukumar Swaminathan 		sbp = iocbq->sbp;
438fcf3ce44SJohn Forte 		if (sbp && (sbp != STALE_PACKET)) {
43982527734SSukumar Swaminathan 			if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
44082527734SSukumar Swaminathan 				hba->fc_table[sbp->iotag] = NULL;
44182527734SSukumar Swaminathan 				emlxs_sli4_free_xri(hba, sbp, sbp->xp);
44282527734SSukumar Swaminathan 			} else {
44382527734SSukumar Swaminathan 				(void) emlxs_unregister_pkt(
44482527734SSukumar Swaminathan 				    (CHANNEL *)iocbq->channel,
44582527734SSukumar Swaminathan 				    iocb->ULPIOTAG, 0);
446fcf3ce44SJohn Forte 			}
44782527734SSukumar Swaminathan 
44882527734SSukumar Swaminathan 			mutex_enter(&sbp->mtx);
449fcf3ce44SJohn Forte 			sbp->pkt_flags |= PACKET_IN_TIMEOUT;
450fcf3ce44SJohn Forte 			mutex_exit(&sbp->mtx);
451fcf3ce44SJohn Forte 		}
452291a2b48SSukumar Swaminathan 
453fcf3ce44SJohn Forte 		iocbq = (IOCBQ *)iocbq->next;
454fcf3ce44SJohn Forte 
455fcf3ce44SJohn Forte 	}	/* end of while */
456fcf3ce44SJohn Forte 
45782527734SSukumar Swaminathan 	mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
458fcf3ce44SJohn Forte 
459fcf3ce44SJohn Forte 	/* Now complete the transmit timeouts outside the locks */
460fcf3ce44SJohn Forte 	iocbq = (IOCBQ *)tmo.q_first;
461fcf3ce44SJohn Forte 	while (iocbq) {
462fcf3ce44SJohn Forte 		/* Save the next iocbq for now */
463fcf3ce44SJohn Forte 		next = (IOCBQ *)iocbq->next;
464fcf3ce44SJohn Forte 
465fcf3ce44SJohn Forte 		/* Unlink this iocbq */
466fcf3ce44SJohn Forte 		iocbq->next = NULL;
467fcf3ce44SJohn Forte 
468fcf3ce44SJohn Forte 		/* Get the pkt */
469fcf3ce44SJohn Forte 		sbp = (emlxs_buf_t *)iocbq->sbp;
470fcf3ce44SJohn Forte 
471fcf3ce44SJohn Forte 		if (sbp) {
472291a2b48SSukumar Swaminathan 			/* Warning: Some FCT sbp's don't have */
473291a2b48SSukumar Swaminathan 			/* fc_packet objects */
474fcf3ce44SJohn Forte 			pkt = PRIV2PKT(sbp);
475fcf3ce44SJohn Forte 
476fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_timeout_msg,
477fcf3ce44SJohn Forte 			    "TXQ abort: sbp=%p iotag=%x tmo=%d", sbp,
478fcf3ce44SJohn Forte 			    sbp->iotag, (pkt) ? pkt->pkt_timeout : 0);
479fcf3ce44SJohn Forte 
480fcf3ce44SJohn Forte 			if (hba->state >= FC_LINK_UP) {
481fcf3ce44SJohn Forte 				emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT,
482fcf3ce44SJohn Forte 				    IOERR_ABORT_TIMEOUT, 1);
483fcf3ce44SJohn Forte 			} else {
484fcf3ce44SJohn Forte 				emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT,
485fcf3ce44SJohn Forte 				    IOERR_LINK_DOWN, 1);
486fcf3ce44SJohn Forte 			}
487291a2b48SSukumar Swaminathan 
488fcf3ce44SJohn Forte 		}
489291a2b48SSukumar Swaminathan 
490fcf3ce44SJohn Forte 		iocbq = next;
491fcf3ce44SJohn Forte 
492fcf3ce44SJohn Forte 	}	/* end of while */
493fcf3ce44SJohn Forte 
494fcf3ce44SJohn Forte 
495fcf3ce44SJohn Forte 
496fcf3ce44SJohn Forte 	/* Now check the chip */
497291a2b48SSukumar Swaminathan 	bzero((void *)&abort, sizeof (Q));
498fcf3ce44SJohn Forte 
49982527734SSukumar Swaminathan 	/* Check the HBA for outstanding IOs */
500fcf3ce44SJohn Forte 	rc = 0;
50182527734SSukumar Swaminathan 	mutex_enter(&EMLXS_FCTAB_LOCK);
50282527734SSukumar Swaminathan 	for (iotag = 1; iotag < hba->max_iotag; iotag++) {
50382527734SSukumar Swaminathan 		sbp = hba->fc_table[iotag];
50482527734SSukumar Swaminathan 		if (sbp && (sbp != STALE_PACKET) &&
50582527734SSukumar Swaminathan 		    (sbp->pkt_flags & PACKET_IN_CHIPQ) &&
50682527734SSukumar Swaminathan 		    (hba->timer_tics >= sbp->ticks)) {
50782527734SSukumar Swaminathan 			rc = emlxs_pkt_chip_timeout(sbp->iocbq.port,
50882527734SSukumar Swaminathan 			    sbp, &abort, flag);
50982527734SSukumar Swaminathan 
51082527734SSukumar Swaminathan 			if (rc) {
51182527734SSukumar Swaminathan 				break;
512fcf3ce44SJohn Forte 			}
513fcf3ce44SJohn Forte 		}
514fcf3ce44SJohn Forte 	}
51582527734SSukumar Swaminathan 	mutex_exit(&EMLXS_FCTAB_LOCK);
516fcf3ce44SJohn Forte 
517fcf3ce44SJohn Forte 	/* Now put the iocb's on the tx queue */
518fcf3ce44SJohn Forte 	iocbq = (IOCBQ *)abort.q_first;
519fcf3ce44SJohn Forte 	while (iocbq) {
520fcf3ce44SJohn Forte 		/* Save the next iocbq for now */
521fcf3ce44SJohn Forte 		next = (IOCBQ *)iocbq->next;
522fcf3ce44SJohn Forte 
523fcf3ce44SJohn Forte 		/* Unlink this iocbq */
524fcf3ce44SJohn Forte 		iocbq->next = NULL;
525fcf3ce44SJohn Forte 
526fcf3ce44SJohn Forte 		/* Send this iocbq */
527fcf3ce44SJohn Forte 		emlxs_tx_put(iocbq, 1);
528fcf3ce44SJohn Forte 
529fcf3ce44SJohn Forte 		iocbq = next;
530fcf3ce44SJohn Forte 	}
531fcf3ce44SJohn Forte 
53282527734SSukumar Swaminathan 	/* Now trigger IO channel service to send these abort iocbq */
53382527734SSukumar Swaminathan 	for (channelno = 0; channelno < hba->chan_count; channelno++) {
53482527734SSukumar Swaminathan 		if (!flag[channelno]) {
53582527734SSukumar Swaminathan 			continue;
53682527734SSukumar Swaminathan 		}
53782527734SSukumar Swaminathan 		cp = &hba->chan[channelno];
53882527734SSukumar Swaminathan 
53982527734SSukumar Swaminathan 		EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, 0);
54082527734SSukumar Swaminathan 	}
54182527734SSukumar Swaminathan 
542fcf3ce44SJohn Forte 	if (rc == 1) {
543fcf3ce44SJohn Forte 		/* Spawn a thread to reset the link */
544bb63f56eSSukumar Swaminathan 		emlxs_thread_spawn(hba, emlxs_reset_link_thread, NULL, NULL);
545fcf3ce44SJohn Forte 	} else if (rc == 2) {
546fcf3ce44SJohn Forte 		/* Spawn a thread to reset the adapter */
547bb63f56eSSukumar Swaminathan 		emlxs_thread_spawn(hba, emlxs_restart_thread, NULL, NULL);
548fcf3ce44SJohn Forte 	}
549291a2b48SSukumar Swaminathan 
550fcf3ce44SJohn Forte 	return (rc);
551fcf3ce44SJohn Forte 
55282527734SSukumar Swaminathan } /* emlxs_timer_check_pkts() */
553fcf3ce44SJohn Forte 
554fcf3ce44SJohn Forte 
555fcf3ce44SJohn Forte static void
55682527734SSukumar Swaminathan emlxs_timer_check_channels(emlxs_hba_t *hba, uint8_t *flag)
557fcf3ce44SJohn Forte {
558fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
559fcf3ce44SJohn Forte 	emlxs_config_t *cfg = &CFG;
56082527734SSukumar Swaminathan 	int32_t channelno;
56182527734SSukumar Swaminathan 	CHANNEL *cp;
56282527734SSukumar Swaminathan 	uint32_t logit;
563fcf3ce44SJohn Forte 
564fcf3ce44SJohn Forte 	if (!cfg[CFG_TIMEOUT_ENABLE].current) {
565fcf3ce44SJohn Forte 		return;
566fcf3ce44SJohn Forte 	}
567291a2b48SSukumar Swaminathan 
56882527734SSukumar Swaminathan 	for (channelno = 0; channelno < hba->chan_count; channelno++) {
56982527734SSukumar Swaminathan 		cp = &hba->chan[channelno];
57082527734SSukumar Swaminathan 
57182527734SSukumar Swaminathan 		logit = 0;
572fcf3ce44SJohn Forte 
57382527734SSukumar Swaminathan 		/* Check for channel timeout now */
57482527734SSukumar Swaminathan 		mutex_enter(&EMLXS_TX_CHANNEL_LOCK);
57582527734SSukumar Swaminathan 		if (cp->timeout && (hba->timer_tics >= cp->timeout)) {
57682527734SSukumar Swaminathan 			/* Check if there is work to do on channel and */
577fcf3ce44SJohn Forte 			/* the link is still up */
57882527734SSukumar Swaminathan 			if (cp->nodeq.q_first) {
57982527734SSukumar Swaminathan 				flag[channelno] = 1;
58082527734SSukumar Swaminathan 				cp->timeout = hba->timer_tics + 10;
581fcf3ce44SJohn Forte 
582fcf3ce44SJohn Forte 				if (hba->state >= FC_LINK_UP) {
583728bdc9bSSukumar Swaminathan 					logit = 1;
584fcf3ce44SJohn Forte 				}
585fcf3ce44SJohn Forte 			} else {
58682527734SSukumar Swaminathan 				cp->timeout = 0;
587fcf3ce44SJohn Forte 			}
588fcf3ce44SJohn Forte 		}
58982527734SSukumar Swaminathan 		mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
590fcf3ce44SJohn Forte 
591728bdc9bSSukumar Swaminathan 		if (logit) {
592728bdc9bSSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT,
59382527734SSukumar Swaminathan 			    &emlxs_chan_watchdog_msg,
59482527734SSukumar Swaminathan 			    "IO Channel %d cnt=%d,%d",
59582527734SSukumar Swaminathan 			    channelno,
59682527734SSukumar Swaminathan 			    hba->channel_tx_count,
59782527734SSukumar Swaminathan 			    hba->io_count);
598728bdc9bSSukumar Swaminathan 		}
599728bdc9bSSukumar Swaminathan 
600fcf3ce44SJohn Forte 		/*
60182527734SSukumar Swaminathan 		 * If IO channel flag is set, request iocb servicing
60282527734SSukumar Swaminathan 		 * here to send any iocb's that may still be queued
603fcf3ce44SJohn Forte 		 */
60482527734SSukumar Swaminathan 		if (flag[channelno]) {
60582527734SSukumar Swaminathan 			EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, 0);
606fcf3ce44SJohn Forte 		}
607fcf3ce44SJohn Forte 	}
608fcf3ce44SJohn Forte 
609fcf3ce44SJohn Forte 	return;
610fcf3ce44SJohn Forte 
61182527734SSukumar Swaminathan } /* emlxs_timer_check_channels() */
612fcf3ce44SJohn Forte 
613fcf3ce44SJohn Forte 
614fcf3ce44SJohn Forte static void
615fcf3ce44SJohn Forte emlxs_timer_check_nodes(emlxs_port_t *port, uint8_t *flag)
616fcf3ce44SJohn Forte {
617fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
618fcf3ce44SJohn Forte 	uint32_t found;
619fcf3ce44SJohn Forte 	uint32_t i;
620fcf3ce44SJohn Forte 	NODELIST *nlp;
62182527734SSukumar Swaminathan 	int32_t channelno;
622fcf3ce44SJohn Forte 
623fcf3ce44SJohn Forte 	for (;;) {
624fcf3ce44SJohn Forte 		/* Check node gate flag for expiration */
625fcf3ce44SJohn Forte 		found = 0;
626fcf3ce44SJohn Forte 
627fcf3ce44SJohn Forte 		/*
628291a2b48SSukumar Swaminathan 		 * We need to lock, scan, and unlock because we can't hold the
629291a2b48SSukumar Swaminathan 		 * lock while we call node_open
630fcf3ce44SJohn Forte 		 */
631fcf3ce44SJohn Forte 		rw_enter(&port->node_rwlock, RW_READER);
632fcf3ce44SJohn Forte 		for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
633fcf3ce44SJohn Forte 			nlp = port->node_table[i];
634fcf3ce44SJohn Forte 			while (nlp != NULL) {
63582527734SSukumar Swaminathan 				for (channelno = 0;
63682527734SSukumar Swaminathan 				    channelno < hba->chan_count;
63782527734SSukumar Swaminathan 				    channelno++) {
638291a2b48SSukumar Swaminathan 					/* Check if the node timer is active */
639291a2b48SSukumar Swaminathan 					/* and if timer has expired */
64082527734SSukumar Swaminathan 					if (nlp->nlp_tics[channelno] &&
641fcf3ce44SJohn Forte 					    (hba->timer_tics >=
64282527734SSukumar Swaminathan 					    nlp->nlp_tics[channelno])) {
643291a2b48SSukumar Swaminathan 						/* If so, set the flag and */
644291a2b48SSukumar Swaminathan 						/* break out */
645fcf3ce44SJohn Forte 						found = 1;
64682527734SSukumar Swaminathan 						flag[channelno] = 1;
647fcf3ce44SJohn Forte 						break;
648fcf3ce44SJohn Forte 					}
649fcf3ce44SJohn Forte 				}
650fcf3ce44SJohn Forte 
65182527734SSukumar Swaminathan 				if (nlp->nlp_force_rscn &&
65282527734SSukumar Swaminathan 				    (hba->timer_tics >= nlp->nlp_force_rscn)) {
65382527734SSukumar Swaminathan 					nlp->nlp_force_rscn = 0;
65482527734SSukumar Swaminathan 					/*
65582527734SSukumar Swaminathan 					 * Generate an RSCN to
65682527734SSukumar Swaminathan 					 * wakeup ULP
65782527734SSukumar Swaminathan 					 */
65882527734SSukumar Swaminathan 					(void) emlxs_generate_rscn(port,
65982527734SSukumar Swaminathan 					    nlp->nlp_DID);
66082527734SSukumar Swaminathan 				}
66182527734SSukumar Swaminathan 
662fcf3ce44SJohn Forte 				if (found) {
663fcf3ce44SJohn Forte 					break;
664fcf3ce44SJohn Forte 				}
665291a2b48SSukumar Swaminathan 
666fcf3ce44SJohn Forte 				nlp = nlp->nlp_list_next;
667fcf3ce44SJohn Forte 			}
668fcf3ce44SJohn Forte 
669fcf3ce44SJohn Forte 			if (found) {
670fcf3ce44SJohn Forte 				break;
671fcf3ce44SJohn Forte 			}
672291a2b48SSukumar Swaminathan 
673fcf3ce44SJohn Forte 		}
674fcf3ce44SJohn Forte 		rw_exit(&port->node_rwlock);
675fcf3ce44SJohn Forte 
676fcf3ce44SJohn Forte 		if (!found) {
677fcf3ce44SJohn Forte 			break;
678fcf3ce44SJohn Forte 		}
679291a2b48SSukumar Swaminathan 
68082527734SSukumar Swaminathan 		emlxs_node_timeout(port, nlp, channelno);
681fcf3ce44SJohn Forte 	}
682fcf3ce44SJohn Forte 
68382527734SSukumar Swaminathan } /* emlxs_timer_check_nodes() */
684fcf3ce44SJohn Forte 
685fcf3ce44SJohn Forte 
686fcf3ce44SJohn Forte static void
687fcf3ce44SJohn Forte emlxs_timer_check_loopback(emlxs_hba_t *hba)
688fcf3ce44SJohn Forte {
689fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
690fcf3ce44SJohn Forte 	emlxs_config_t *cfg = &CFG;
691fcf3ce44SJohn Forte 	int32_t reset = 0;
692fcf3ce44SJohn Forte 
693fcf3ce44SJohn Forte 	if (!cfg[CFG_TIMEOUT_ENABLE].current) {
694fcf3ce44SJohn Forte 		return;
695fcf3ce44SJohn Forte 	}
696291a2b48SSukumar Swaminathan 
697fcf3ce44SJohn Forte 	/* Check the loopback timer for expiration */
698fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_PORT_LOCK);
699fcf3ce44SJohn Forte 
700291a2b48SSukumar Swaminathan 	if (!hba->loopback_tics || (hba->timer_tics < hba->loopback_tics)) {
701fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_PORT_LOCK);
702fcf3ce44SJohn Forte 		return;
703fcf3ce44SJohn Forte 	}
704291a2b48SSukumar Swaminathan 
705fcf3ce44SJohn Forte 	hba->loopback_tics = 0;
706fcf3ce44SJohn Forte 
707fcf3ce44SJohn Forte 	if (hba->flag & FC_LOOPBACK_MODE) {
708fcf3ce44SJohn Forte 		reset = 1;
709fcf3ce44SJohn Forte 	}
710291a2b48SSukumar Swaminathan 
711fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_PORT_LOCK);
712fcf3ce44SJohn Forte 
713fcf3ce44SJohn Forte 	if (reset) {
714fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
715fcf3ce44SJohn Forte 		    "LOOPBACK_MODE: Expired. Resetting...");
716fcf3ce44SJohn Forte 		(void) emlxs_reset(port, FC_FCA_LINK_RESET);
717fcf3ce44SJohn Forte 	}
718291a2b48SSukumar Swaminathan 
719fcf3ce44SJohn Forte 	return;
720fcf3ce44SJohn Forte 
72182527734SSukumar Swaminathan } /* emlxs_timer_check_loopback() */
722fcf3ce44SJohn Forte 
723fcf3ce44SJohn Forte 
724fcf3ce44SJohn Forte static void
725fcf3ce44SJohn Forte emlxs_timer_check_linkup(emlxs_hba_t *hba)
726fcf3ce44SJohn Forte {
727fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
728fcf3ce44SJohn Forte 	uint32_t linkup;
729fcf3ce44SJohn Forte 
73082527734SSukumar Swaminathan 	/* Check if all mbox commands from previous activity are processed */
73182527734SSukumar Swaminathan 	if (hba->model_info.sli_mask & EMLXS_SLI4_MASK) {
73282527734SSukumar Swaminathan 		mutex_enter(&EMLXS_MBOX_LOCK);
73382527734SSukumar Swaminathan 		if (hba->mbox_queue.q_first) {
73482527734SSukumar Swaminathan 			mutex_exit(&EMLXS_MBOX_LOCK);
73582527734SSukumar Swaminathan 			return;
73682527734SSukumar Swaminathan 		}
73782527734SSukumar Swaminathan 		mutex_exit(&EMLXS_MBOX_LOCK);
73882527734SSukumar Swaminathan 	}
73982527734SSukumar Swaminathan 
740fcf3ce44SJohn Forte 	/* Check the linkup timer for expiration */
741fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_PORT_LOCK);
742fcf3ce44SJohn Forte 	linkup = 0;
743fcf3ce44SJohn Forte 	if (hba->linkup_timer && (hba->timer_tics >= hba->linkup_timer)) {
744fcf3ce44SJohn Forte 		hba->linkup_timer = 0;
745fcf3ce44SJohn Forte 
746fcf3ce44SJohn Forte 		/* Make sure link is still ready */
747fcf3ce44SJohn Forte 		if (hba->state >= FC_LINK_UP) {
748fcf3ce44SJohn Forte 			linkup = 1;
749fcf3ce44SJohn Forte 		}
750fcf3ce44SJohn Forte 	}
751fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_PORT_LOCK);
752fcf3ce44SJohn Forte 
753fcf3ce44SJohn Forte 	/* Make the linkup callback */
754fcf3ce44SJohn Forte 	if (linkup) {
755fcf3ce44SJohn Forte 		emlxs_port_online(port);
756fcf3ce44SJohn Forte 	}
757fcf3ce44SJohn Forte 	return;
758fcf3ce44SJohn Forte 
75982527734SSukumar Swaminathan } /* emlxs_timer_check_linkup() */
760fcf3ce44SJohn Forte 
761fcf3ce44SJohn Forte 
762fcf3ce44SJohn Forte static void
763fcf3ce44SJohn Forte emlxs_timer_check_heartbeat(emlxs_hba_t *hba)
764fcf3ce44SJohn Forte {
765fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
76682527734SSukumar Swaminathan 	MAILBOXQ *mbq;
767fcf3ce44SJohn Forte 	emlxs_config_t *cfg = &CFG;
76882527734SSukumar Swaminathan 	int rc;
769fcf3ce44SJohn Forte 
770fcf3ce44SJohn Forte 	if (!cfg[CFG_HEARTBEAT_ENABLE].current) {
771fcf3ce44SJohn Forte 		return;
772fcf3ce44SJohn Forte 	}
773291a2b48SSukumar Swaminathan 
774fcf3ce44SJohn Forte 	if (hba->timer_tics < hba->heartbeat_timer) {
775fcf3ce44SJohn Forte 		return;
776fcf3ce44SJohn Forte 	}
777291a2b48SSukumar Swaminathan 
778fcf3ce44SJohn Forte 	hba->heartbeat_timer = hba->timer_tics + 5;
779fcf3ce44SJohn Forte 
780fcf3ce44SJohn Forte 	/* Return if adapter interrupts have occurred */
781fcf3ce44SJohn Forte 	if (hba->heartbeat_flag) {
782fcf3ce44SJohn Forte 		hba->heartbeat_flag = 0;
783fcf3ce44SJohn Forte 		return;
784fcf3ce44SJohn Forte 	}
785fcf3ce44SJohn Forte 	/* No adapter interrupts have occured for 5 seconds now */
786fcf3ce44SJohn Forte 
787fcf3ce44SJohn Forte 	/* Return if mailbox is busy */
788fcf3ce44SJohn Forte 	/* This means the mailbox timer routine is watching for problems */
789fcf3ce44SJohn Forte 	if (hba->mbox_timer) {
790fcf3ce44SJohn Forte 		return;
791fcf3ce44SJohn Forte 	}
792291a2b48SSukumar Swaminathan 
793fcf3ce44SJohn Forte 	/* Return if heartbeat is still outstanding */
794fcf3ce44SJohn Forte 	if (hba->heartbeat_active) {
795fcf3ce44SJohn Forte 		return;
796fcf3ce44SJohn Forte 	}
797291a2b48SSukumar Swaminathan 
79882527734SSukumar Swaminathan 	if ((mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1)) == 0) {
799fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
800fcf3ce44SJohn Forte 		    "Unable to allocate heartbeat mailbox.");
801fcf3ce44SJohn Forte 		return;
802fcf3ce44SJohn Forte 	}
803291a2b48SSukumar Swaminathan 
80482527734SSukumar Swaminathan 	emlxs_mb_heartbeat(hba, mbq);
805fcf3ce44SJohn Forte 	hba->heartbeat_active = 1;
806fcf3ce44SJohn Forte 
80782527734SSukumar Swaminathan 	rc =  EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
80882527734SSukumar Swaminathan 	if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) {
80982527734SSukumar Swaminathan 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq);
810fcf3ce44SJohn Forte 	}
811fcf3ce44SJohn Forte 
812fcf3ce44SJohn Forte 	return;
813fcf3ce44SJohn Forte 
81482527734SSukumar Swaminathan } /* emlxs_timer_check_heartbeat() */
815fcf3ce44SJohn Forte 
816fcf3ce44SJohn Forte 
817*6a573d82SSukumar Swaminathan static void
818*6a573d82SSukumar Swaminathan emlxs_timer_check_fw_update(emlxs_hba_t *hba)
819*6a573d82SSukumar Swaminathan {
820*6a573d82SSukumar Swaminathan 	emlxs_port_t *port = &PPORT;
821*6a573d82SSukumar Swaminathan 
822*6a573d82SSukumar Swaminathan 	if (!(hba->fw_flag & FW_UPDATE_NEEDED)) {
823*6a573d82SSukumar Swaminathan 		hba->fw_timer = 0;
824*6a573d82SSukumar Swaminathan 		return;
825*6a573d82SSukumar Swaminathan 	}
826*6a573d82SSukumar Swaminathan 
827*6a573d82SSukumar Swaminathan 	if (hba->timer_tics < hba->fw_timer) {
828*6a573d82SSukumar Swaminathan 		return;
829*6a573d82SSukumar Swaminathan 	}
830*6a573d82SSukumar Swaminathan 
831*6a573d82SSukumar Swaminathan 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_update_msg,
832*6a573d82SSukumar Swaminathan 	"A manual HBA reset or link reset (using luxadm or fcadm) "
833*6a573d82SSukumar Swaminathan 	"is required.");
834*6a573d82SSukumar Swaminathan 
835*6a573d82SSukumar Swaminathan 	/* Set timer for 24 hours */
836*6a573d82SSukumar Swaminathan 	hba->fw_timer = hba->timer_tics + (60 * 60 * 24);
837*6a573d82SSukumar Swaminathan 
838*6a573d82SSukumar Swaminathan 	return;
839*6a573d82SSukumar Swaminathan 
840*6a573d82SSukumar Swaminathan } /* emlxs_timer_check_fw_update() */
841*6a573d82SSukumar Swaminathan 
842*6a573d82SSukumar Swaminathan 
843fcf3ce44SJohn Forte static void
844fcf3ce44SJohn Forte emlxs_timer_check_discovery(emlxs_port_t *port)
845fcf3ce44SJohn Forte {
846fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
847fcf3ce44SJohn Forte 	emlxs_config_t *cfg = &CFG;
848fcf3ce44SJohn Forte 	int32_t send_clear_la;
849fcf3ce44SJohn Forte 	uint32_t found;
850fcf3ce44SJohn Forte 	uint32_t i;
851fcf3ce44SJohn Forte 	NODELIST *nlp;
852fcf3ce44SJohn Forte 	MAILBOXQ *mbox;
85382527734SSukumar Swaminathan 	int rc;
854fcf3ce44SJohn Forte 
855fcf3ce44SJohn Forte 	if (!cfg[CFG_TIMEOUT_ENABLE].current) {
856fcf3ce44SJohn Forte 		return;
857fcf3ce44SJohn Forte 	}
858291a2b48SSukumar Swaminathan 
859fcf3ce44SJohn Forte 	/* Check the discovery timer for expiration */
860fcf3ce44SJohn Forte 	send_clear_la = 0;
861fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_PORT_LOCK);
862fcf3ce44SJohn Forte 	while (hba->discovery_timer &&
863fcf3ce44SJohn Forte 	    (hba->timer_tics >= hba->discovery_timer) &&
864fcf3ce44SJohn Forte 	    (hba->state == FC_LINK_UP)) {
865fcf3ce44SJohn Forte 		send_clear_la = 1;
866fcf3ce44SJohn Forte 
867fcf3ce44SJohn Forte 		/* Perform a flush on fcp2 nodes that are still closed */
868fcf3ce44SJohn Forte 		found = 0;
869fcf3ce44SJohn Forte 		rw_enter(&port->node_rwlock, RW_READER);
870fcf3ce44SJohn Forte 		for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
871fcf3ce44SJohn Forte 			nlp = port->node_table[i];
872fcf3ce44SJohn Forte 			while (nlp != NULL) {
873fcf3ce44SJohn Forte 				if ((nlp->nlp_fcp_info & NLP_FCP_2_DEVICE) &&
87482527734SSukumar Swaminathan 				    (nlp->nlp_flag[hba->channel_fcp] &
87582527734SSukumar Swaminathan 				    NLP_CLOSED)) {
876fcf3ce44SJohn Forte 					found = 1;
877fcf3ce44SJohn Forte 					break;
878fcf3ce44SJohn Forte 
879fcf3ce44SJohn Forte 				}
880fcf3ce44SJohn Forte 				nlp = nlp->nlp_list_next;
881fcf3ce44SJohn Forte 			}
882fcf3ce44SJohn Forte 
883fcf3ce44SJohn Forte 			if (found) {
884fcf3ce44SJohn Forte 				break;
885fcf3ce44SJohn Forte 			}
886fcf3ce44SJohn Forte 		}
887fcf3ce44SJohn Forte 		rw_exit(&port->node_rwlock);
888fcf3ce44SJohn Forte 
889fcf3ce44SJohn Forte 		if (!found) {
890fcf3ce44SJohn Forte 			break;
891fcf3ce44SJohn Forte 		}
892291a2b48SSukumar Swaminathan 
893fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_missing_msg,
894fcf3ce44SJohn Forte 		    "FCP2 device (did=%06x) missing. Flushing...",
895fcf3ce44SJohn Forte 		    nlp->nlp_DID);
896fcf3ce44SJohn Forte 
897fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_PORT_LOCK);
898fcf3ce44SJohn Forte 
899fcf3ce44SJohn Forte 		(void) emlxs_mb_unreg_did(port, nlp->nlp_DID, NULL, NULL, NULL);
900fcf3ce44SJohn Forte 
901fcf3ce44SJohn Forte 		mutex_enter(&EMLXS_PORT_LOCK);
902fcf3ce44SJohn Forte 
903fcf3ce44SJohn Forte 	}
904fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_PORT_LOCK);
905fcf3ce44SJohn Forte 
906fcf3ce44SJohn Forte 	/* Try to send clear link attention, if needed */
907fe199829SSukumar Swaminathan 	if ((hba->sli_mode < EMLXS_HBA_SLI4_MODE) && (send_clear_la == 1) &&
90882527734SSukumar Swaminathan 	    (mbox = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) {
909fcf3ce44SJohn Forte 		mutex_enter(&EMLXS_PORT_LOCK);
910fcf3ce44SJohn Forte 
911fcf3ce44SJohn Forte 		/*
912fcf3ce44SJohn Forte 		 * If state is not FC_LINK_UP, then either the link has gone
913fcf3ce44SJohn Forte 		 * down or a FC_CLEAR_LA has already been issued
914fcf3ce44SJohn Forte 		 */
915fcf3ce44SJohn Forte 		if (hba->state != FC_LINK_UP) {
916fcf3ce44SJohn Forte 			mutex_exit(&EMLXS_PORT_LOCK);
917fcf3ce44SJohn Forte 			(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbox);
918fcf3ce44SJohn Forte 		} else {
919fcf3ce44SJohn Forte 			/* Change state and clear discovery timer */
92082527734SSukumar Swaminathan 			EMLXS_STATE_CHANGE_LOCKED(hba, FC_CLEAR_LA);
921fcf3ce44SJohn Forte 
922fcf3ce44SJohn Forte 			hba->discovery_timer = 0;
923fcf3ce44SJohn Forte 
924fcf3ce44SJohn Forte 			mutex_exit(&EMLXS_PORT_LOCK);
925fcf3ce44SJohn Forte 
926fcf3ce44SJohn Forte 			/* Prepare and send the CLEAR_LA command */
92782527734SSukumar Swaminathan 			emlxs_mb_clear_la(hba, mbox);
928fcf3ce44SJohn Forte 
92982527734SSukumar Swaminathan 			rc = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_NOWAIT, 0);
93082527734SSukumar Swaminathan 			if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) {
931fcf3ce44SJohn Forte 				(void) emlxs_mem_put(hba, MEM_MBOX,
932fcf3ce44SJohn Forte 				    (uint8_t *)mbox);
933fcf3ce44SJohn Forte 			}
934fcf3ce44SJohn Forte 		}
935fcf3ce44SJohn Forte 	}
936291a2b48SSukumar Swaminathan 
937fcf3ce44SJohn Forte 	return;
938fcf3ce44SJohn Forte 
93982527734SSukumar Swaminathan } /* emlxs_timer_check_discovery()  */
940fcf3ce44SJohn Forte 
941fcf3ce44SJohn Forte 
942fcf3ce44SJohn Forte static void
943fcf3ce44SJohn Forte emlxs_timer_check_ub(emlxs_port_t *port)
944fcf3ce44SJohn Forte {
945fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
946fcf3ce44SJohn Forte 	emlxs_unsol_buf_t *ulistp;
947fcf3ce44SJohn Forte 	fc_unsol_buf_t *ubp;
948fcf3ce44SJohn Forte 	emlxs_ub_priv_t *ub_priv;
949fcf3ce44SJohn Forte 	uint32_t i;
950fcf3ce44SJohn Forte 
951fcf3ce44SJohn Forte 	if (port->ub_timer > hba->timer_tics) {
952fcf3ce44SJohn Forte 		return;
953fcf3ce44SJohn Forte 	}
954291a2b48SSukumar Swaminathan 
955fcf3ce44SJohn Forte 	port->ub_timer = hba->timer_tics + EMLXS_UB_PERIOD;
956fcf3ce44SJohn Forte 
957fcf3ce44SJohn Forte 	/* Check the unsolicited buffers */
958fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_UB_LOCK);
959fcf3ce44SJohn Forte 
960fcf3ce44SJohn Forte 	ulistp = port->ub_pool;
961fcf3ce44SJohn Forte 	while (ulistp) {
962fcf3ce44SJohn Forte 		/* Check buffers in this pool */
963fcf3ce44SJohn Forte 		for (i = 0; i < ulistp->pool_nentries; i++) {
964fcf3ce44SJohn Forte 			ubp = (fc_unsol_buf_t *)&ulistp->fc_ubufs[i];
965fcf3ce44SJohn Forte 			ub_priv = ubp->ub_fca_private;
966fcf3ce44SJohn Forte 
967fcf3ce44SJohn Forte 			if (!(ub_priv->flags & EMLXS_UB_IN_USE)) {
968fcf3ce44SJohn Forte 				continue;
969fcf3ce44SJohn Forte 			}
970291a2b48SSukumar Swaminathan 
971291a2b48SSukumar Swaminathan 			/* If buffer has timed out, print message and */
972291a2b48SSukumar Swaminathan 			/* increase timeout */
973fcf3ce44SJohn Forte 			if ((ub_priv->time + ub_priv->timeout) <=
974fcf3ce44SJohn Forte 			    hba->timer_tics) {
975fcf3ce44SJohn Forte 				ub_priv->flags |= EMLXS_UB_TIMEOUT;
976fcf3ce44SJohn Forte 
977291a2b48SSukumar Swaminathan 				EMLXS_MSGF(EMLXS_CONTEXT,
978291a2b48SSukumar Swaminathan 				    &emlxs_sfs_debug_msg,
979fcf3ce44SJohn Forte 				    "Stale UB buffer detected (%d mins): "
980291a2b48SSukumar Swaminathan 				    "buffer=%p (%x,%x,%x,%x)",
981291a2b48SSukumar Swaminathan 				    (ub_priv->timeout / 60), ubp,
982291a2b48SSukumar Swaminathan 				    ubp->ub_frame.type, ubp->ub_frame.s_id,
983291a2b48SSukumar Swaminathan 				    ubp->ub_frame.ox_id, ubp->ub_frame.rx_id);
984fcf3ce44SJohn Forte 
985fcf3ce44SJohn Forte 				/* Increase timeout period */
986fcf3ce44SJohn Forte 
987291a2b48SSukumar Swaminathan 				/* If timeout was 5 mins or less, */
988291a2b48SSukumar Swaminathan 				/* increase it to 10 mins */
989fcf3ce44SJohn Forte 				if (ub_priv->timeout <= (5 * 60)) {
990fcf3ce44SJohn Forte 					ub_priv->timeout = (10 * 60);
991fcf3ce44SJohn Forte 				}
992291a2b48SSukumar Swaminathan 				/* If timeout was 10 mins or less, */
993291a2b48SSukumar Swaminathan 				/* increase it to 30 mins */
994fcf3ce44SJohn Forte 				else if (ub_priv->timeout <= (10 * 60)) {
995fcf3ce44SJohn Forte 					ub_priv->timeout = (30 * 60);
996fcf3ce44SJohn Forte 				}
997fcf3ce44SJohn Forte 				/* Otherwise double it. */
998fcf3ce44SJohn Forte 				else {
999fcf3ce44SJohn Forte 					ub_priv->timeout *= 2;
1000fcf3ce44SJohn Forte 				}
1001fcf3ce44SJohn Forte 			}
1002fcf3ce44SJohn Forte 		}
1003fcf3ce44SJohn Forte 
1004fcf3ce44SJohn Forte 		ulistp = ulistp->pool_next;
1005fcf3ce44SJohn Forte 	}
1006fcf3ce44SJohn Forte 
1007fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_UB_LOCK);
1008fcf3ce44SJohn Forte 
1009fcf3ce44SJohn Forte 	return;
1010fcf3ce44SJohn Forte 
101182527734SSukumar Swaminathan } /* emlxs_timer_check_ub()  */
1012fcf3ce44SJohn Forte 
1013fcf3ce44SJohn Forte 
1014fcf3ce44SJohn Forte /* EMLXS_FCTAB_LOCK must be held to call this */
1015fcf3ce44SJohn Forte static uint32_t
1016291a2b48SSukumar Swaminathan emlxs_pkt_chip_timeout(emlxs_port_t *port, emlxs_buf_t *sbp, Q *abortq,
1017291a2b48SSukumar Swaminathan     uint8_t *flag)
1018fcf3ce44SJohn Forte {
1019fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
102082527734SSukumar Swaminathan 	CHANNEL *cp = (CHANNEL *)sbp->channel;
1021fcf3ce44SJohn Forte 	IOCBQ *iocbq = NULL;
1022fcf3ce44SJohn Forte 	fc_packet_t *pkt;
1023fcf3ce44SJohn Forte 	uint32_t rc = 0;
1024fcf3ce44SJohn Forte 
1025fcf3ce44SJohn Forte 	mutex_enter(&sbp->mtx);
1026fcf3ce44SJohn Forte 
1027fcf3ce44SJohn Forte 	/* Warning: Some FCT sbp's don't have fc_packet objects */
1028fcf3ce44SJohn Forte 	pkt = PRIV2PKT(sbp);
1029fcf3ce44SJohn Forte 
1030fcf3ce44SJohn Forte 	switch (sbp->abort_attempts) {
1031fcf3ce44SJohn Forte 	case 0:
1032fcf3ce44SJohn Forte 
1033fcf3ce44SJohn Forte 		/* Create the abort IOCB */
1034fcf3ce44SJohn Forte 		if (hba->state >= FC_LINK_UP) {
1035fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_timeout_msg,
1036291a2b48SSukumar Swaminathan 			    "chipQ:1:Aborting. sbp=%p iotag=%x tmo=%d flags=%x",
1037291a2b48SSukumar Swaminathan 			    sbp, sbp->iotag,
1038291a2b48SSukumar Swaminathan 			    (pkt) ? pkt->pkt_timeout : 0, sbp->pkt_flags);
1039fcf3ce44SJohn Forte 
1040291a2b48SSukumar Swaminathan 			iocbq =
1041291a2b48SSukumar Swaminathan 			    emlxs_create_abort_xri_cn(port, sbp->node,
104282527734SSukumar Swaminathan 			    sbp->iotag, cp, sbp->class, ABORT_TYPE_ABTS);
1043fcf3ce44SJohn Forte 
1044291a2b48SSukumar Swaminathan 			/* The adapter will make 2 attempts to send ABTS */
1045291a2b48SSukumar Swaminathan 			/* with 2*ratov timeout each time */
1046291a2b48SSukumar Swaminathan 			sbp->ticks =
1047291a2b48SSukumar Swaminathan 			    hba->timer_tics + (4 * hba->fc_ratov) + 10;
1048fcf3ce44SJohn Forte 		} else {
1049fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_timeout_msg,
1050291a2b48SSukumar Swaminathan 			    "chipQ:1:Closing. sbp=%p iotag=%x tmo=%d flags=%x",
1051291a2b48SSukumar Swaminathan 			    sbp, sbp->iotag,
1052291a2b48SSukumar Swaminathan 			    (pkt) ? pkt->pkt_timeout : 0, sbp->pkt_flags);
1053fcf3ce44SJohn Forte 
1054291a2b48SSukumar Swaminathan 			iocbq =
1055291a2b48SSukumar Swaminathan 			    emlxs_create_close_xri_cn(port, sbp->node,
105682527734SSukumar Swaminathan 			    sbp->iotag, cp);
1057fcf3ce44SJohn Forte 
1058fcf3ce44SJohn Forte 			sbp->ticks = hba->timer_tics + 30;
1059fcf3ce44SJohn Forte 		}
1060fcf3ce44SJohn Forte 
1061fcf3ce44SJohn Forte 		/* set the flags */
1062fcf3ce44SJohn Forte 		sbp->pkt_flags |= (PACKET_IN_TIMEOUT | PACKET_XRI_CLOSED);
1063fcf3ce44SJohn Forte 
106482527734SSukumar Swaminathan 		flag[cp->channelno] = 1;
1065fcf3ce44SJohn Forte 		rc = 0;
1066fcf3ce44SJohn Forte 
1067fcf3ce44SJohn Forte 		break;
1068fcf3ce44SJohn Forte 
1069fcf3ce44SJohn Forte 	case 1:
1070fcf3ce44SJohn Forte 
1071fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_timeout_msg,
1072291a2b48SSukumar Swaminathan 		    "chipQ: 2:Closing. sbp=%p iotag=%x", sbp, sbp->iotag);
1073fcf3ce44SJohn Forte 
1074291a2b48SSukumar Swaminathan 		iocbq =
1075291a2b48SSukumar Swaminathan 		    emlxs_create_close_xri_cn(port, sbp->node, sbp->iotag,
107682527734SSukumar Swaminathan 		    cp);
1077fcf3ce44SJohn Forte 
1078fcf3ce44SJohn Forte 		sbp->ticks = hba->timer_tics + 30;
1079fcf3ce44SJohn Forte 
108082527734SSukumar Swaminathan 		flag[cp->channelno] = 1;
1081fcf3ce44SJohn Forte 		rc = 0;
1082fcf3ce44SJohn Forte 
1083fcf3ce44SJohn Forte 		break;
1084fcf3ce44SJohn Forte 
1085fcf3ce44SJohn Forte 	case 2:
1086fcf3ce44SJohn Forte 
1087fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_timeout_msg,
1088291a2b48SSukumar Swaminathan 		    "chipQ: 3:Resetting link. sbp=%p iotag=%x", sbp,
1089291a2b48SSukumar Swaminathan 		    sbp->iotag);
1090fcf3ce44SJohn Forte 
1091fcf3ce44SJohn Forte 		sbp->ticks = hba->timer_tics + 60;
1092fcf3ce44SJohn Forte 		rc = 1;
1093fcf3ce44SJohn Forte 
1094fcf3ce44SJohn Forte 		break;
1095fcf3ce44SJohn Forte 
1096fcf3ce44SJohn Forte 	default:
1097fcf3ce44SJohn Forte 
1098fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_timeout_msg,
1099fcf3ce44SJohn Forte 		    "chipQ: %d:Resetting adapter. sbp=%p iotag=%x",
1100fcf3ce44SJohn Forte 		    sbp->abort_attempts, sbp, sbp->iotag);
1101fcf3ce44SJohn Forte 
1102fcf3ce44SJohn Forte 		sbp->ticks = hba->timer_tics + 60;
1103fcf3ce44SJohn Forte 		rc = 2;
1104fcf3ce44SJohn Forte 
1105fcf3ce44SJohn Forte 		break;
1106fcf3ce44SJohn Forte 	}
1107fcf3ce44SJohn Forte 
1108fcf3ce44SJohn Forte 	sbp->abort_attempts++;
1109fcf3ce44SJohn Forte 	mutex_exit(&sbp->mtx);
1110fcf3ce44SJohn Forte 
1111fcf3ce44SJohn Forte 	if (iocbq) {
1112fcf3ce44SJohn Forte 		if (abortq->q_first) {
1113291a2b48SSukumar Swaminathan 			((IOCBQ *)abortq->q_last)->next = iocbq;
1114fcf3ce44SJohn Forte 			abortq->q_last = (uint8_t *)iocbq;
1115fcf3ce44SJohn Forte 			abortq->q_cnt++;
1116fcf3ce44SJohn Forte 		} else {
1117fcf3ce44SJohn Forte 			abortq->q_first = (uint8_t *)iocbq;
1118fcf3ce44SJohn Forte 			abortq->q_last = (uint8_t *)iocbq;
1119fcf3ce44SJohn Forte 			abortq->q_cnt = 1;
1120fcf3ce44SJohn Forte 		}
1121fcf3ce44SJohn Forte 		iocbq->next = NULL;
1122fcf3ce44SJohn Forte 	}
1123291a2b48SSukumar Swaminathan 
1124fcf3ce44SJohn Forte 	return (rc);
1125fcf3ce44SJohn Forte 
112682527734SSukumar Swaminathan } /* emlxs_pkt_chip_timeout() */
1127fcf3ce44SJohn Forte 
1128fcf3ce44SJohn Forte 
1129fcf3ce44SJohn Forte #ifdef TX_WATCHDOG
1130fcf3ce44SJohn Forte 
1131fcf3ce44SJohn Forte static void
1132fcf3ce44SJohn Forte emlxs_tx_watchdog(emlxs_hba_t *hba)
1133fcf3ce44SJohn Forte {
1134fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
1135fcf3ce44SJohn Forte 	NODELIST *nlp;
113682527734SSukumar Swaminathan 	uint32_t channelno;
113782527734SSukumar Swaminathan 	CHANNEL *cp;
1138fcf3ce44SJohn Forte 	IOCBQ *next;
1139fcf3ce44SJohn Forte 	IOCBQ *iocbq;
1140fcf3ce44SJohn Forte 	IOCB *iocb;
1141fcf3ce44SJohn Forte 	uint32_t found;
1142fcf3ce44SJohn Forte 	MATCHMAP *bmp;
1143fcf3ce44SJohn Forte 	Q abort;
1144fcf3ce44SJohn Forte 	uint32_t iotag;
1145fcf3ce44SJohn Forte 	emlxs_buf_t *sbp;
1146fcf3ce44SJohn Forte 	fc_packet_t *pkt = NULL;
1147fcf3ce44SJohn Forte 	uint32_t cmd;
1148fcf3ce44SJohn Forte 	uint32_t did;
1149fcf3ce44SJohn Forte 
1150291a2b48SSukumar Swaminathan 	bzero((void *)&abort, sizeof (Q));
1151fcf3ce44SJohn Forte 
115282527734SSukumar Swaminathan 	mutex_enter(&EMLXS_TX_CHANNEL_LOCK);
115382527734SSukumar Swaminathan 
115482527734SSukumar Swaminathan 	mutex_enter(&EMLXS_FCTAB_LOCK);
115582527734SSukumar Swaminathan 	for (iotag = 1; iotag < hba->max_iotag; iotag++) {
115682527734SSukumar Swaminathan 		sbp = hba->fc_table[iotag];
115782527734SSukumar Swaminathan 		if (sbp && (sbp != STALE_PACKET) &&
115882527734SSukumar Swaminathan 		    (sbp->pkt_flags & PACKET_IN_TXQ)) {
115982527734SSukumar Swaminathan 			nlp = sbp->node;
116082527734SSukumar Swaminathan 			iocbq = &sbp->iocbq;
116182527734SSukumar Swaminathan 
116282527734SSukumar Swaminathan 			channelno = (CHANNEL *)(sbp->channel)->channelno;
116382527734SSukumar Swaminathan 			if (iocbq->flag & IOCB_PRIORITY) {
116482527734SSukumar Swaminathan 				iocbq =
116582527734SSukumar Swaminathan 				    (IOCBQ *)nlp->nlp_ptx[channelno].
116682527734SSukumar Swaminathan 				    q_first;
116782527734SSukumar Swaminathan 			} else {
116882527734SSukumar Swaminathan 				iocbq =
116982527734SSukumar Swaminathan 				    (IOCBQ *)nlp->nlp_tx[channelno].
117082527734SSukumar Swaminathan 				    q_first;
117182527734SSukumar Swaminathan 			}
1172fcf3ce44SJohn Forte 
117382527734SSukumar Swaminathan 			/* Find a matching entry */
117482527734SSukumar Swaminathan 			found = 0;
117582527734SSukumar Swaminathan 			while (iocbq) {
117682527734SSukumar Swaminathan 				if (iocbq == &sbp->iocbq) {
117782527734SSukumar Swaminathan 					found = 1;
117882527734SSukumar Swaminathan 					break;
117982527734SSukumar Swaminathan 				}
1180fcf3ce44SJohn Forte 
118182527734SSukumar Swaminathan 				iocbq = (IOCBQ *)iocbq->next;
118282527734SSukumar Swaminathan 			}
1183fcf3ce44SJohn Forte 
118482527734SSukumar Swaminathan 			if (!found) {
118582527734SSukumar Swaminathan 				if (!(sbp->pkt_flags & PACKET_STALE)) {
118682527734SSukumar Swaminathan 					mutex_enter(&sbp->mtx);
118782527734SSukumar Swaminathan 					sbp->pkt_flags |=
118882527734SSukumar Swaminathan 					    PACKET_STALE;
118982527734SSukumar Swaminathan 					mutex_exit(&sbp->mtx);
1190fcf3ce44SJohn Forte 				} else {
119182527734SSukumar Swaminathan 					if (abort.q_first == 0) {
119282527734SSukumar Swaminathan 						abort.q_first =
119382527734SSukumar Swaminathan 						    &sbp->iocbq;
119482527734SSukumar Swaminathan 					} else {
119582527734SSukumar Swaminathan 						((IOCBQ *)abort.
119682527734SSukumar Swaminathan 						    q_last)->next =
119782527734SSukumar Swaminathan 						    &sbp->iocbq;
1198fcf3ce44SJohn Forte 					}
1199291a2b48SSukumar Swaminathan 
120082527734SSukumar Swaminathan 					abort.q_last = &sbp->iocbq;
120182527734SSukumar Swaminathan 					abort.q_cnt++;
1202fcf3ce44SJohn Forte 				}
1203fcf3ce44SJohn Forte 
120482527734SSukumar Swaminathan 			} else {
120582527734SSukumar Swaminathan 				if ((sbp->pkt_flags & PACKET_STALE)) {
120682527734SSukumar Swaminathan 					mutex_enter(&sbp->mtx);
120782527734SSukumar Swaminathan 					sbp->pkt_flags &=
120882527734SSukumar Swaminathan 					    ~PACKET_STALE;
120982527734SSukumar Swaminathan 					mutex_exit(&sbp->mtx);
1210fcf3ce44SJohn Forte 				}
1211fcf3ce44SJohn Forte 			}
1212fcf3ce44SJohn Forte 		}
1213fcf3ce44SJohn Forte 	}
121482527734SSukumar Swaminathan 	mutex_exit(&EMLXS_FCTAB_LOCK);
1215fcf3ce44SJohn Forte 
1216291a2b48SSukumar Swaminathan 	iocbq = (IOCBQ *)abort.q_first;
1217fcf3ce44SJohn Forte 	while (iocbq) {
1218291a2b48SSukumar Swaminathan 		next = (IOCBQ *)iocbq->next;
1219fcf3ce44SJohn Forte 		iocbq->next = NULL;
1220fcf3ce44SJohn Forte 		sbp = (emlxs_buf_t *)iocbq->sbp;
1221fcf3ce44SJohn Forte 
1222fcf3ce44SJohn Forte 		pkt = PRIV2PKT(sbp);
1223fcf3ce44SJohn Forte 		if (pkt) {
122482527734SSukumar Swaminathan 			did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id);
1225fcf3ce44SJohn Forte 			cmd = *((uint32_t *)pkt->pkt_cmd);
122682527734SSukumar Swaminathan 			cmd = LE_SWAP32(cmd);
1227fcf3ce44SJohn Forte 		}
1228fcf3ce44SJohn Forte 
1229fcf3ce44SJohn Forte 
1230fcf3ce44SJohn Forte 		emlxs_tx_put(iocbq, 0);
1231fcf3ce44SJohn Forte 
1232fcf3ce44SJohn Forte 		iocbq = next;
1233fcf3ce44SJohn Forte 
1234fcf3ce44SJohn Forte 	}	/* end of while */
1235fcf3ce44SJohn Forte 
123682527734SSukumar Swaminathan 	mutex_exit(&EMLXS_TX_CHANNEL_LOCK);
1237fcf3ce44SJohn Forte 
1238fcf3ce44SJohn Forte 	return;
1239fcf3ce44SJohn Forte 
124082527734SSukumar Swaminathan } /* emlxs_tx_watchdog() */
1241fcf3ce44SJohn Forte 
1242291a2b48SSukumar Swaminathan #endif /* TX_WATCHDOG */
1243fcf3ce44SJohn Forte 
1244fcf3ce44SJohn Forte 
1245fcf3ce44SJohn Forte #ifdef DHCHAP_SUPPORT
1246fcf3ce44SJohn Forte 
1247fcf3ce44SJohn Forte static void
1248fcf3ce44SJohn Forte emlxs_timer_check_dhchap(emlxs_port_t *port)
1249fcf3ce44SJohn Forte {
1250fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
1251fcf3ce44SJohn Forte 	uint32_t i;
1252fcf3ce44SJohn Forte 	NODELIST *ndlp = NULL;
1253fcf3ce44SJohn Forte 
1254fcf3ce44SJohn Forte 	for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
1255fcf3ce44SJohn Forte 		ndlp = port->node_table[i];
1256fcf3ce44SJohn Forte 
1257fcf3ce44SJohn Forte 		if (!ndlp) {
1258fcf3ce44SJohn Forte 			continue;
1259fcf3ce44SJohn Forte 		}
1260291a2b48SSukumar Swaminathan 
1261fcf3ce44SJohn Forte 		/* Check authentication response timeout */
1262fcf3ce44SJohn Forte 		if (ndlp->node_dhc.nlp_authrsp_tmo &&
1263fcf3ce44SJohn Forte 		    (hba->timer_tics >= ndlp->node_dhc.nlp_authrsp_tmo)) {
1264fcf3ce44SJohn Forte 			/* Trigger authresp timeout handler */
1265fcf3ce44SJohn Forte 			(void) emlxs_dhc_authrsp_timeout(port, ndlp, NULL);
1266fcf3ce44SJohn Forte 		}
1267291a2b48SSukumar Swaminathan 
1268fcf3ce44SJohn Forte 		/* Check reauthentication timeout */
1269fcf3ce44SJohn Forte 		if (ndlp->node_dhc.nlp_reauth_tmo &&
1270fcf3ce44SJohn Forte 		    (hba->timer_tics >= ndlp->node_dhc.nlp_reauth_tmo)) {
1271fcf3ce44SJohn Forte 			/* Trigger reauth timeout handler */
1272fcf3ce44SJohn Forte 			emlxs_dhc_reauth_timeout(port, NULL, ndlp);
1273fcf3ce44SJohn Forte 		}
1274fcf3ce44SJohn Forte 	}
1275fcf3ce44SJohn Forte 	return;
1276fcf3ce44SJohn Forte 
127782527734SSukumar Swaminathan } /* emlxs_timer_check_dhchap */
1278fcf3ce44SJohn Forte 
1279291a2b48SSukumar Swaminathan #endif /* DHCHAP_SUPPORT */
1280