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 /*
23fcf3ce44SJohn Forte  * Copyright 2008 Emulex.  All rights reserved.
24fcf3ce44SJohn Forte  * Use is subject to License terms.
25fcf3ce44SJohn Forte  */
26fcf3ce44SJohn Forte 
27fcf3ce44SJohn Forte 
28fcf3ce44SJohn Forte #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 #ifdef DFC_SUPPORT
39fcf3ce44SJohn Forte static void emlxs_timer_check_loopback(emlxs_hba_t *hba);
40fcf3ce44SJohn Forte #endif	/* DFC_SUPPORT */
41fcf3ce44SJohn Forte 
42fcf3ce44SJohn Forte #ifdef DHCHAP_SUPPORT
43fcf3ce44SJohn Forte static void emlxs_timer_check_dhchap(emlxs_port_t *port);
44fcf3ce44SJohn Forte #endif	/* DHCHAP_SUPPORT */
45fcf3ce44SJohn Forte 
46fcf3ce44SJohn Forte static void emlxs_timer(void *arg);
47fcf3ce44SJohn Forte static void emlxs_timer_check_heartbeat(emlxs_hba_t *hba);
48fcf3ce44SJohn Forte static uint32_t emlxs_timer_check_pkts(emlxs_hba_t *hba, uint8_t *flag);
49fcf3ce44SJohn Forte static void emlxs_timer_check_nodes(emlxs_port_t *port, uint8_t *flag);
50fcf3ce44SJohn Forte static void emlxs_timer_check_linkup(emlxs_hba_t *hba);
51fcf3ce44SJohn Forte static void emlxs_timer_check_mbox(emlxs_hba_t *hba);
52fcf3ce44SJohn Forte static void emlxs_timer_check_discovery(emlxs_port_t *port);
53fcf3ce44SJohn Forte static void emlxs_timer_check_ub(emlxs_port_t *port);
54fcf3ce44SJohn Forte static void emlxs_timer_check_rings(emlxs_hba_t *hba, uint8_t *flag);
55fcf3ce44SJohn Forte static uint32_t emlxs_pkt_chip_timeout(emlxs_port_t *port,
56fcf3ce44SJohn Forte 	emlxs_buf_t *sbp, Q *abortq, uint8_t *flag);
57fcf3ce44SJohn Forte 
58fcf3ce44SJohn Forte #ifdef TX_WATCHDOG
59fcf3ce44SJohn Forte static void emlxs_tx_watchdog(emlxs_hba_t *hba);
60fcf3ce44SJohn Forte #endif	/* TX_WATCHDOG */
61fcf3ce44SJohn Forte 
62fcf3ce44SJohn Forte extern clock_t
63fcf3ce44SJohn Forte emlxs_timeout(emlxs_hba_t *hba, uint32_t timeout)
64fcf3ce44SJohn Forte {
65fcf3ce44SJohn Forte 	emlxs_config_t *cfg = &CFG;
66fcf3ce44SJohn Forte 	clock_t time;
67fcf3ce44SJohn Forte 
68fcf3ce44SJohn Forte 	/* Set thread timeout */
69fcf3ce44SJohn Forte 	if (cfg[CFG_TIMEOUT_ENABLE].current) {
70fcf3ce44SJohn Forte 		(void) drv_getparm(LBOLT, &time);
71fcf3ce44SJohn Forte 		time += (timeout * drv_usectohz(1000000));
72fcf3ce44SJohn Forte 	} else {
73fcf3ce44SJohn Forte 		time = -1;
74fcf3ce44SJohn Forte 	}
75fcf3ce44SJohn Forte 
76fcf3ce44SJohn Forte 	return (time);
77fcf3ce44SJohn Forte 
78fcf3ce44SJohn Forte } /* emlxs_timeout() */
79fcf3ce44SJohn Forte 
80fcf3ce44SJohn Forte 
81fcf3ce44SJohn Forte static void
82fcf3ce44SJohn Forte emlxs_timer(void *arg)
83fcf3ce44SJohn Forte {
84fcf3ce44SJohn Forte 	emlxs_hba_t *hba = (emlxs_hba_t *)arg;
85fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
86fcf3ce44SJohn Forte 	uint8_t flag[MAX_RINGS];
87fcf3ce44SJohn Forte 	uint32_t i;
88fcf3ce44SJohn Forte 	uint32_t rc;
89fcf3ce44SJohn Forte 
90fcf3ce44SJohn Forte 	if (!hba->timer_id) {
91fcf3ce44SJohn Forte 		return;
92fcf3ce44SJohn Forte 	}
93fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_TIMER_LOCK);
94fcf3ce44SJohn Forte 
95fcf3ce44SJohn Forte 	/* Only one timer thread is allowed */
96fcf3ce44SJohn Forte 	if (hba->timer_flags & EMLXS_TIMER_BUSY) {
97fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_TIMER_LOCK);
98fcf3ce44SJohn Forte 		return;
99fcf3ce44SJohn Forte 	}
100fcf3ce44SJohn Forte 	/* Check if a kill request has been made */
101fcf3ce44SJohn Forte 	if (hba->timer_flags & EMLXS_TIMER_KILL) {
102fcf3ce44SJohn Forte 		hba->timer_id = 0;
103fcf3ce44SJohn Forte 		hba->timer_flags |= EMLXS_TIMER_ENDED;
104fcf3ce44SJohn Forte 
105fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_TIMER_LOCK);
106fcf3ce44SJohn Forte 		return;
107fcf3ce44SJohn Forte 	}
108fcf3ce44SJohn Forte 	hba->timer_flags |= (EMLXS_TIMER_BUSY | EMLXS_TIMER_STARTED);
109fcf3ce44SJohn Forte 	hba->timer_tics = DRV_TIME;
110fcf3ce44SJohn Forte 
111fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_TIMER_LOCK);
112fcf3ce44SJohn Forte 
113fcf3ce44SJohn Forte 	/* Exit if we are still initializing */
114fcf3ce44SJohn Forte 	if (hba->state < FC_LINK_DOWN) {
115fcf3ce44SJohn Forte 		goto done;
116fcf3ce44SJohn Forte 	}
117fcf3ce44SJohn Forte 	bzero((void *) flag, sizeof (flag));
118fcf3ce44SJohn Forte 
119fcf3ce44SJohn Forte 	/* Check for mailbox timeout */
120fcf3ce44SJohn Forte 	emlxs_timer_check_mbox(hba);
121fcf3ce44SJohn Forte 
122fcf3ce44SJohn Forte 	/* Check heartbeat timer */
123fcf3ce44SJohn Forte 	emlxs_timer_check_heartbeat(hba);
124fcf3ce44SJohn Forte 
125fcf3ce44SJohn Forte #ifdef IDLE_TIMER
126fcf3ce44SJohn Forte 	emlxs_pm_idle_timer(hba);
127fcf3ce44SJohn Forte #endif	/* IDLE_TIMER */
128fcf3ce44SJohn Forte 
129fcf3ce44SJohn Forte #ifdef DFC_SUPPORT
130fcf3ce44SJohn Forte 	/* Check for loopback timeouts */
131fcf3ce44SJohn Forte 	emlxs_timer_check_loopback(hba);
132fcf3ce44SJohn Forte #endif	/* DFC_SUPPORT */
133fcf3ce44SJohn Forte 
134fcf3ce44SJohn Forte 	/* Check for packet timeouts */
135fcf3ce44SJohn Forte 	rc = emlxs_timer_check_pkts(hba, flag);
136fcf3ce44SJohn Forte 
137fcf3ce44SJohn Forte 	if (rc) {
138fcf3ce44SJohn Forte 		/* Link or adapter is being reset */
139fcf3ce44SJohn Forte 		goto done;
140fcf3ce44SJohn Forte 	}
141fcf3ce44SJohn Forte 	/* Check for linkup timeout */
142fcf3ce44SJohn Forte 	emlxs_timer_check_linkup(hba);
143fcf3ce44SJohn Forte 
144fcf3ce44SJohn Forte 	/* Check the ports */
145fcf3ce44SJohn Forte 	for (i = 0; i < MAX_VPORTS; i++) {
146fcf3ce44SJohn Forte 		port = &VPORT(i);
147fcf3ce44SJohn Forte 
148fcf3ce44SJohn Forte 		if (!(port->flag & EMLXS_PORT_BOUND)) {
149fcf3ce44SJohn Forte 			continue;
150fcf3ce44SJohn Forte 		}
151fcf3ce44SJohn Forte 		/* Check for node gate timeouts */
152fcf3ce44SJohn Forte 		emlxs_timer_check_nodes(port, flag);
153fcf3ce44SJohn Forte 
154fcf3ce44SJohn Forte 		/* Check for tape discovery timeout */
155fcf3ce44SJohn Forte 		emlxs_timer_check_discovery(port);
156fcf3ce44SJohn Forte 
157fcf3ce44SJohn Forte 		/* Check for UB timeouts */
158fcf3ce44SJohn Forte 		emlxs_timer_check_ub(port);
159fcf3ce44SJohn Forte 
160fcf3ce44SJohn Forte #ifdef DHCHAP_SUPPORT
161fcf3ce44SJohn Forte 		/* Check for DHCHAP authentication timeouts */
162fcf3ce44SJohn Forte 		emlxs_timer_check_dhchap(port);
163fcf3ce44SJohn Forte #endif	/* DHCHAP_SUPPORT */
164fcf3ce44SJohn Forte 
165fcf3ce44SJohn Forte 	}
166fcf3ce44SJohn Forte 
167fcf3ce44SJohn Forte 	/* Check for ring service timeouts */
168fcf3ce44SJohn Forte 	/* Always do this last */
169fcf3ce44SJohn Forte 	emlxs_timer_check_rings(hba, flag);
170fcf3ce44SJohn Forte 
171fcf3ce44SJohn Forte done:
172fcf3ce44SJohn Forte 
173fcf3ce44SJohn Forte 	/* Restart the timer */
174fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_TIMER_LOCK);
175fcf3ce44SJohn Forte 
176fcf3ce44SJohn Forte 	hba->timer_flags &= ~EMLXS_TIMER_BUSY;
177fcf3ce44SJohn Forte 
178fcf3ce44SJohn Forte 	/* If timer is still enabled, restart it */
179fcf3ce44SJohn Forte 	if (!(hba->timer_flags & EMLXS_TIMER_KILL)) {
180fcf3ce44SJohn Forte 		hba->timer_id = timeout(emlxs_timer, (void *) hba,
181fcf3ce44SJohn Forte 		    (EMLXS_TIMER_PERIOD * drv_usectohz(1000000)));
182fcf3ce44SJohn Forte 	} else {
183fcf3ce44SJohn Forte 		hba->timer_id = 0;
184fcf3ce44SJohn Forte 		hba->timer_flags |= EMLXS_TIMER_ENDED;
185fcf3ce44SJohn Forte 	}
186fcf3ce44SJohn Forte 
187fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_TIMER_LOCK);
188fcf3ce44SJohn Forte 
189fcf3ce44SJohn Forte 	return;
190fcf3ce44SJohn Forte 
191fcf3ce44SJohn Forte } /* emlxs_timer() */
192fcf3ce44SJohn Forte 
193fcf3ce44SJohn Forte 
194fcf3ce44SJohn Forte extern void
195fcf3ce44SJohn Forte emlxs_timer_start(emlxs_hba_t *hba)
196fcf3ce44SJohn Forte {
197fcf3ce44SJohn Forte 	if (hba->timer_id) {
198fcf3ce44SJohn Forte 		return;
199fcf3ce44SJohn Forte 	}
200fcf3ce44SJohn Forte 	/* Restart the timer */
201fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_TIMER_LOCK);
202fcf3ce44SJohn Forte 	if (!hba->timer_id) {
203fcf3ce44SJohn Forte 		hba->timer_flags = 0;
204fcf3ce44SJohn Forte 		hba->timer_id = timeout(emlxs_timer, (void *)hba,
205fcf3ce44SJohn Forte 		    drv_usectohz(1000000));
206fcf3ce44SJohn Forte 	}
207fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_TIMER_LOCK);
208fcf3ce44SJohn Forte 
209fcf3ce44SJohn Forte } /* emlxs_timer_start() */
210fcf3ce44SJohn Forte 
211fcf3ce44SJohn Forte 
212fcf3ce44SJohn Forte extern void
213fcf3ce44SJohn Forte emlxs_timer_stop(emlxs_hba_t *hba)
214fcf3ce44SJohn Forte {
215fcf3ce44SJohn Forte 	if (!hba->timer_id) {
216fcf3ce44SJohn Forte 		return;
217fcf3ce44SJohn Forte 	}
218fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_TIMER_LOCK);
219fcf3ce44SJohn Forte 	hba->timer_flags |= EMLXS_TIMER_KILL;
220fcf3ce44SJohn Forte 
221fcf3ce44SJohn Forte 	while (hba->timer_id) {
222fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_TIMER_LOCK);
223fcf3ce44SJohn Forte 		delay(drv_usectohz(500000));
224fcf3ce44SJohn Forte 		mutex_enter(&EMLXS_TIMER_LOCK);
225fcf3ce44SJohn Forte 	}
226fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_TIMER_LOCK);
227fcf3ce44SJohn Forte 
228fcf3ce44SJohn Forte 	return;
229fcf3ce44SJohn Forte 
230fcf3ce44SJohn Forte } /* emlxs_timer_stop() */
231fcf3ce44SJohn Forte 
232fcf3ce44SJohn Forte 
233fcf3ce44SJohn Forte static uint32_t
234fcf3ce44SJohn Forte emlxs_timer_check_pkts(emlxs_hba_t *hba, uint8_t *flag)
235fcf3ce44SJohn Forte {
236fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
237fcf3ce44SJohn Forte 	/* emlxs_port_t *vport; */
238fcf3ce44SJohn Forte 	emlxs_config_t *cfg = &CFG;
239fcf3ce44SJohn Forte 	Q tmo;
240fcf3ce44SJohn Forte 	int32_t ringno;
241fcf3ce44SJohn Forte 	RING *rp;
242fcf3ce44SJohn Forte 	NODELIST *nlp;
243fcf3ce44SJohn Forte 	IOCBQ *prev;
244fcf3ce44SJohn Forte 	IOCBQ *next;
245fcf3ce44SJohn Forte 	IOCB *iocb;
246fcf3ce44SJohn Forte 	IOCBQ *iocbq;
247fcf3ce44SJohn Forte 	emlxs_buf_t *sbp;
248fcf3ce44SJohn Forte 	fc_packet_t *pkt;
249fcf3ce44SJohn Forte 	Q abort;
250fcf3ce44SJohn Forte 	uint32_t iotag;
251fcf3ce44SJohn Forte 	uint32_t rc;
252fcf3ce44SJohn Forte 
253fcf3ce44SJohn Forte 	if (!cfg[CFG_TIMEOUT_ENABLE].current) {
254fcf3ce44SJohn Forte 		return (0);
255fcf3ce44SJohn Forte 	}
256fcf3ce44SJohn Forte 	if (hba->pkt_timer > hba->timer_tics) {
257fcf3ce44SJohn Forte 		return (0);
258fcf3ce44SJohn Forte 	}
259fcf3ce44SJohn Forte 	hba->pkt_timer = hba->timer_tics + EMLXS_PKT_PERIOD;
260fcf3ce44SJohn Forte 
261fcf3ce44SJohn Forte 
262fcf3ce44SJohn Forte 	bzero((void *) &tmo, sizeof (Q));
263fcf3ce44SJohn Forte 
264fcf3ce44SJohn Forte 	/*
265fcf3ce44SJohn Forte 	 * We must hold the locks here because we never know when an iocb
266fcf3ce44SJohn Forte 	 * will be removed out from under us
267fcf3ce44SJohn Forte 	 */
268fcf3ce44SJohn Forte 
269fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_RINGTX_LOCK);
270fcf3ce44SJohn Forte 
271fcf3ce44SJohn Forte 	for (ringno = 0; ringno < hba->ring_count; ringno++) {
272fcf3ce44SJohn Forte 		rp = &hba->ring[ringno];
273fcf3ce44SJohn Forte 
274fcf3ce44SJohn Forte 		/* Scan the tx queues for each active node on the ring */
275fcf3ce44SJohn Forte 
276fcf3ce44SJohn Forte 		/* Get the first node */
277fcf3ce44SJohn Forte 		nlp = (NODELIST *)rp->nodeq.q_first;
278fcf3ce44SJohn Forte 
279fcf3ce44SJohn Forte 		while (nlp) {
280fcf3ce44SJohn Forte 			/* Scan the node's priority tx queue */
281fcf3ce44SJohn Forte 			prev = NULL;
282fcf3ce44SJohn Forte 			iocbq = (IOCBQ *)nlp->nlp_ptx[ringno].q_first;
283fcf3ce44SJohn Forte 
284fcf3ce44SJohn Forte 			while (iocbq) {
285fcf3ce44SJohn Forte 				next = (IOCBQ *)iocbq->next;
286fcf3ce44SJohn Forte 				iocb = &iocbq->iocb;
287fcf3ce44SJohn Forte 				sbp = (emlxs_buf_t *)iocbq->sbp;
288fcf3ce44SJohn Forte 
289fcf3ce44SJohn Forte 				/* Check if iocb has timed out */
290fcf3ce44SJohn Forte 				if (sbp && hba->timer_tics >= sbp->ticks) {
291fcf3ce44SJohn Forte 					/* iocb timed out, now deque it */
292fcf3ce44SJohn Forte 					if (next == NULL) {
293fcf3ce44SJohn Forte 						nlp->nlp_ptx[ringno].q_last =
294fcf3ce44SJohn Forte 						    (uint8_t *)prev;
295fcf3ce44SJohn Forte 					}
296fcf3ce44SJohn Forte 					if (prev == NULL) {
297fcf3ce44SJohn Forte 						nlp->nlp_ptx[ringno].q_first =
298fcf3ce44SJohn Forte 						    (uint8_t *)next;
299fcf3ce44SJohn Forte 					} else {
300fcf3ce44SJohn Forte 						prev->next = next;
301fcf3ce44SJohn Forte 					}
302fcf3ce44SJohn Forte 
303fcf3ce44SJohn Forte 					iocbq->next = NULL;
304fcf3ce44SJohn Forte 					nlp->nlp_ptx[ringno].q_cnt--;
305fcf3ce44SJohn Forte 
306fcf3ce44SJohn Forte 					/*
307fcf3ce44SJohn Forte 					 * Add this iocb to our local timout
308fcf3ce44SJohn Forte 					 * Q
309fcf3ce44SJohn Forte 					 */
310fcf3ce44SJohn Forte 
311fcf3ce44SJohn Forte 					/*
312fcf3ce44SJohn Forte 					 * This way we don't hold the RINGTX
313fcf3ce44SJohn Forte 					 * lock too long
314fcf3ce44SJohn Forte 					 */
315fcf3ce44SJohn Forte 
316fcf3ce44SJohn Forte 					if (tmo.q_first) {
317fcf3ce44SJohn Forte 						((IOCBQ *)tmo.q_last)->next =
318fcf3ce44SJohn Forte 						    iocbq;
319fcf3ce44SJohn Forte 						tmo.q_last = (uint8_t *)iocbq;
320fcf3ce44SJohn Forte 						tmo.q_cnt++;
321fcf3ce44SJohn Forte 					} else {
322fcf3ce44SJohn Forte 						tmo.q_first = (uint8_t *)iocbq;
323fcf3ce44SJohn Forte 						tmo.q_last = (uint8_t *)iocbq;
324fcf3ce44SJohn Forte 						tmo.q_cnt = 1;
325fcf3ce44SJohn Forte 					}
326fcf3ce44SJohn Forte 					iocbq->next = NULL;
327fcf3ce44SJohn Forte 
328fcf3ce44SJohn Forte 				} else {
329fcf3ce44SJohn Forte 					prev = iocbq;
330fcf3ce44SJohn Forte 				}
331fcf3ce44SJohn Forte 
332fcf3ce44SJohn Forte 				iocbq = next;
333fcf3ce44SJohn Forte 
334fcf3ce44SJohn Forte 			}	/* while (iocbq) */
335fcf3ce44SJohn Forte 
336fcf3ce44SJohn Forte 
337fcf3ce44SJohn Forte 			/* Scan the node's tx queue */
338fcf3ce44SJohn Forte 			prev = NULL;
339fcf3ce44SJohn Forte 			iocbq = (IOCBQ *)nlp->nlp_tx[ringno].q_first;
340fcf3ce44SJohn Forte 
341fcf3ce44SJohn Forte 			while (iocbq) {
342fcf3ce44SJohn Forte 				next = (IOCBQ *)iocbq->next;
343fcf3ce44SJohn Forte 				iocb = &iocbq->iocb;
344fcf3ce44SJohn Forte 				sbp = (emlxs_buf_t *)iocbq->sbp;
345fcf3ce44SJohn Forte 
346fcf3ce44SJohn Forte 				/* Check if iocb has timed out */
347fcf3ce44SJohn Forte 				if (sbp && hba->timer_tics >= sbp->ticks) {
348fcf3ce44SJohn Forte 					/* iocb timed out, now deque it */
349fcf3ce44SJohn Forte 					if (next == NULL) {
350fcf3ce44SJohn Forte 						nlp->nlp_tx[ringno].q_last =
351fcf3ce44SJohn Forte 						    (uint8_t *)prev;
352fcf3ce44SJohn Forte 					}
353fcf3ce44SJohn Forte 					if (prev == NULL) {
354fcf3ce44SJohn Forte 						nlp->nlp_tx[ringno].q_first =
355fcf3ce44SJohn Forte 						    (uint8_t *)next;
356fcf3ce44SJohn Forte 					} else {
357fcf3ce44SJohn Forte 						prev->next = next;
358fcf3ce44SJohn Forte 					}
359fcf3ce44SJohn Forte 
360fcf3ce44SJohn Forte 					iocbq->next = NULL;
361fcf3ce44SJohn Forte 					nlp->nlp_tx[ringno].q_cnt--;
362fcf3ce44SJohn Forte 
363fcf3ce44SJohn Forte 					/*
364fcf3ce44SJohn Forte 					 * Add this iocb to our local timout
365fcf3ce44SJohn Forte 					 * Q
366fcf3ce44SJohn Forte 					 */
367fcf3ce44SJohn Forte 
368fcf3ce44SJohn Forte 					/*
369fcf3ce44SJohn Forte 					 * This way we don't hold the RINGTX
370fcf3ce44SJohn Forte 					 * lock too long
371fcf3ce44SJohn Forte 					 */
372fcf3ce44SJohn Forte 
373fcf3ce44SJohn Forte 					/*
374fcf3ce44SJohn Forte 					 * EMLXS_MSGF(EMLXS_CONTEXT,
375fcf3ce44SJohn Forte 					 * &emlxs_pkt_timeout_msg, "TXQ
376fcf3ce44SJohn Forte 					 * abort: Removing iotag=%x qcnt=%d
377fcf3ce44SJohn Forte 					 * pqcnt=%d", sbp->iotag,
378fcf3ce44SJohn Forte 					 * nlp->nlp_tx[ringno].q_cnt,
379fcf3ce44SJohn Forte 					 * nlp->nlp_ptx[ringno].q_cnt);
380fcf3ce44SJohn Forte 					 */
381fcf3ce44SJohn Forte 
382fcf3ce44SJohn Forte 					if (tmo.q_first) {
383fcf3ce44SJohn Forte 						((IOCBQ *)tmo.q_last)->next =
384fcf3ce44SJohn Forte 						    iocbq;
385fcf3ce44SJohn Forte 						tmo.q_last = (uint8_t *)iocbq;
386fcf3ce44SJohn Forte 						tmo.q_cnt++;
387fcf3ce44SJohn Forte 					} else {
388fcf3ce44SJohn Forte 						tmo.q_first = (uint8_t *)iocbq;
389fcf3ce44SJohn Forte 						tmo.q_last = (uint8_t *)iocbq;
390fcf3ce44SJohn Forte 						tmo.q_cnt = 1;
391fcf3ce44SJohn Forte 					}
392fcf3ce44SJohn Forte 					iocbq->next = NULL;
393fcf3ce44SJohn Forte 
394fcf3ce44SJohn Forte 				} else {
395fcf3ce44SJohn Forte 					prev = iocbq;
396fcf3ce44SJohn Forte 				}
397fcf3ce44SJohn Forte 
398fcf3ce44SJohn Forte 				iocbq = next;
399fcf3ce44SJohn Forte 
400fcf3ce44SJohn Forte 			}	/* while (iocbq) */
401fcf3ce44SJohn Forte 
402fcf3ce44SJohn Forte 			if (nlp == (NODELIST *) rp->nodeq.q_last) {
403fcf3ce44SJohn Forte 				nlp = NULL;
404fcf3ce44SJohn Forte 			} else {
405fcf3ce44SJohn Forte 				nlp = nlp->nlp_next[ringno];
406fcf3ce44SJohn Forte 			}
407fcf3ce44SJohn Forte 
408fcf3ce44SJohn Forte 		}	/* while(nlp) */
409fcf3ce44SJohn Forte 
410fcf3ce44SJohn Forte 	}	/* end of for */
411fcf3ce44SJohn Forte 
412fcf3ce44SJohn Forte 	/* Now cleanup the iocb's */
413fcf3ce44SJohn Forte 	iocbq = (IOCBQ *)tmo.q_first;
414fcf3ce44SJohn Forte 	while (iocbq) {
415fcf3ce44SJohn Forte 		/* Free the IoTag and the bmp */
416fcf3ce44SJohn Forte 		iocb = &iocbq->iocb;
417fcf3ce44SJohn Forte 		sbp = emlxs_unregister_pkt(iocbq->ring, iocb->ulpIoTag, 0);
418fcf3ce44SJohn Forte 		ringno = ((RING *)iocbq->ring)->ringno;
419fcf3ce44SJohn Forte 
420fcf3ce44SJohn Forte 		if (sbp && (sbp != STALE_PACKET)) {
421fcf3ce44SJohn Forte 			mutex_enter(&sbp->mtx);
422fcf3ce44SJohn Forte 			if (sbp->pkt_flags & PACKET_IN_TXQ) {
423fcf3ce44SJohn Forte 				sbp->pkt_flags &= ~PACKET_IN_TXQ;
424fcf3ce44SJohn Forte 				hba->ring_tx_count[ringno]--;
425fcf3ce44SJohn Forte 			}
426fcf3ce44SJohn Forte 			sbp->pkt_flags |= PACKET_IN_TIMEOUT;
427fcf3ce44SJohn Forte 			mutex_exit(&sbp->mtx);
428fcf3ce44SJohn Forte 		}
429fcf3ce44SJohn Forte 		iocbq = (IOCBQ *)iocbq->next;
430fcf3ce44SJohn Forte 
431fcf3ce44SJohn Forte 	}	/* end of while */
432fcf3ce44SJohn Forte 
433fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_RINGTX_LOCK);
434fcf3ce44SJohn Forte 
435fcf3ce44SJohn Forte 	/* Now complete the transmit timeouts outside the locks */
436fcf3ce44SJohn Forte 	iocbq = (IOCBQ *)tmo.q_first;
437fcf3ce44SJohn Forte 	while (iocbq) {
438fcf3ce44SJohn Forte 		/* Save the next iocbq for now */
439fcf3ce44SJohn Forte 		next = (IOCBQ *)iocbq->next;
440fcf3ce44SJohn Forte 
441fcf3ce44SJohn Forte 		/* Unlink this iocbq */
442fcf3ce44SJohn Forte 		iocbq->next = NULL;
443fcf3ce44SJohn Forte 
444fcf3ce44SJohn Forte 		/* Get the pkt */
445fcf3ce44SJohn Forte 		sbp = (emlxs_buf_t *)iocbq->sbp;
446fcf3ce44SJohn Forte 
447fcf3ce44SJohn Forte 		if (sbp) {
448fcf3ce44SJohn Forte 			/*
449fcf3ce44SJohn Forte 			 * Warning: Some FCT sbp's don't have fc_packet
450fcf3ce44SJohn Forte 			 * objects
451fcf3ce44SJohn Forte 			 */
452fcf3ce44SJohn Forte 			pkt = PRIV2PKT(sbp);
453fcf3ce44SJohn Forte 
454fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_timeout_msg,
455fcf3ce44SJohn Forte 			    "TXQ abort: sbp=%p iotag=%x tmo=%d", sbp,
456fcf3ce44SJohn Forte 			    sbp->iotag, (pkt) ? pkt->pkt_timeout : 0);
457fcf3ce44SJohn Forte 
458fcf3ce44SJohn Forte 			if (hba->state >= FC_LINK_UP) {
459fcf3ce44SJohn Forte 				emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT,
460fcf3ce44SJohn Forte 				    IOERR_ABORT_TIMEOUT, 1);
461fcf3ce44SJohn Forte 			} else {
462fcf3ce44SJohn Forte 				emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT,
463fcf3ce44SJohn Forte 				    IOERR_LINK_DOWN, 1);
464fcf3ce44SJohn Forte 			}
465fcf3ce44SJohn Forte 		}
466fcf3ce44SJohn Forte 		iocbq = next;
467fcf3ce44SJohn Forte 
468fcf3ce44SJohn Forte 	}	/* end of while */
469fcf3ce44SJohn Forte 
470fcf3ce44SJohn Forte 
471fcf3ce44SJohn Forte 
472fcf3ce44SJohn Forte 	/* Now check the chip */
473fcf3ce44SJohn Forte 	bzero((void *) &abort, sizeof (Q));
474fcf3ce44SJohn Forte 
475fcf3ce44SJohn Forte 	/* Check the rings */
476fcf3ce44SJohn Forte 	rc = 0;
477fcf3ce44SJohn Forte 	for (ringno = 0; ringno < hba->ring_count; ringno++) {
478fcf3ce44SJohn Forte 		rp = &hba->ring[ringno];
479fcf3ce44SJohn Forte 
480fcf3ce44SJohn Forte 		mutex_enter(&EMLXS_FCTAB_LOCK(ringno));
481fcf3ce44SJohn Forte 		for (iotag = 1; iotag < rp->max_iotag; iotag++) {
482fcf3ce44SJohn Forte 			sbp = rp->fc_table[iotag];
483fcf3ce44SJohn Forte 			if (sbp && (sbp != STALE_PACKET) &&
484fcf3ce44SJohn Forte 			    (sbp->pkt_flags & PACKET_IN_CHIPQ) &&
485fcf3ce44SJohn Forte 			    (hba->timer_tics >= sbp->ticks)) {
486fcf3ce44SJohn Forte 				rc = emlxs_pkt_chip_timeout(sbp->iocbq.port,
487fcf3ce44SJohn Forte 				    sbp, &abort, flag);
488fcf3ce44SJohn Forte 
489fcf3ce44SJohn Forte 				if (rc) {
490fcf3ce44SJohn Forte 					break;
491fcf3ce44SJohn Forte 				}
492fcf3ce44SJohn Forte 			}
493fcf3ce44SJohn Forte 		}
494fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_FCTAB_LOCK(ringno));
495fcf3ce44SJohn Forte 
496fcf3ce44SJohn Forte 		if (rc) {
497fcf3ce44SJohn Forte 			break;
498fcf3ce44SJohn Forte 		}
499fcf3ce44SJohn Forte 	}
500fcf3ce44SJohn Forte 
501fcf3ce44SJohn Forte 	/* Now put the iocb's on the tx queue */
502fcf3ce44SJohn Forte 	iocbq = (IOCBQ *)abort.q_first;
503fcf3ce44SJohn Forte 	while (iocbq) {
504fcf3ce44SJohn Forte 		/* Save the next iocbq for now */
505fcf3ce44SJohn Forte 		next = (IOCBQ *)iocbq->next;
506fcf3ce44SJohn Forte 
507fcf3ce44SJohn Forte 		/* Unlink this iocbq */
508fcf3ce44SJohn Forte 		iocbq->next = NULL;
509fcf3ce44SJohn Forte 
510fcf3ce44SJohn Forte 		/* Send this iocbq */
511fcf3ce44SJohn Forte 		emlxs_tx_put(iocbq, 1);
512fcf3ce44SJohn Forte 
513fcf3ce44SJohn Forte 		iocbq = next;
514fcf3ce44SJohn Forte 	}
515fcf3ce44SJohn Forte 
516fcf3ce44SJohn Forte 	if (rc == 1) {
517fcf3ce44SJohn Forte 		/* Spawn a thread to reset the link */
518fcf3ce44SJohn Forte 		(void) thread_create(NULL, 0, emlxs_reset_link_thread,
519fcf3ce44SJohn Forte 		    (char *)hba, 0, &p0, TS_RUN, v.v_maxsyspri - 2);
520fcf3ce44SJohn Forte 	} else if (rc == 2) {
521fcf3ce44SJohn Forte 		/* Spawn a thread to reset the adapter */
522fcf3ce44SJohn Forte 		(void) thread_create(NULL, 0, emlxs_restart_thread,
523fcf3ce44SJohn Forte 		    (char *)hba, 0, &p0, TS_RUN, v.v_maxsyspri - 2);
524fcf3ce44SJohn Forte 	}
525fcf3ce44SJohn Forte 	return (rc);
526fcf3ce44SJohn Forte 
527fcf3ce44SJohn Forte } /* emlxs_timer_check_pkts() */
528fcf3ce44SJohn Forte 
529fcf3ce44SJohn Forte 
530fcf3ce44SJohn Forte 
531fcf3ce44SJohn Forte static void
532fcf3ce44SJohn Forte emlxs_timer_check_rings(emlxs_hba_t *hba, uint8_t *flag)
533fcf3ce44SJohn Forte {
534fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
535fcf3ce44SJohn Forte 	emlxs_config_t *cfg = &CFG;
536fcf3ce44SJohn Forte 	int32_t ringno;
537fcf3ce44SJohn Forte 	RING *rp;
538*728bdc9bSSukumar Swaminathan 	uint32_t logit = 0;
539fcf3ce44SJohn Forte 
540fcf3ce44SJohn Forte 	if (!cfg[CFG_TIMEOUT_ENABLE].current) {
541fcf3ce44SJohn Forte 		return;
542fcf3ce44SJohn Forte 	}
543fcf3ce44SJohn Forte 	for (ringno = 0; ringno < hba->ring_count; ringno++) {
544fcf3ce44SJohn Forte 		rp = &hba->ring[ringno];
545fcf3ce44SJohn Forte 
546fcf3ce44SJohn Forte 		/* Check for ring timeout now */
547fcf3ce44SJohn Forte 		mutex_enter(&EMLXS_RINGTX_LOCK);
548fcf3ce44SJohn Forte 		if (rp->timeout && (hba->timer_tics >= rp->timeout)) {
549fcf3ce44SJohn Forte 			/* Check if there is still work to do on the ring and */
550fcf3ce44SJohn Forte 			/* the link is still up */
551fcf3ce44SJohn Forte 			if (rp->nodeq.q_first) {
552fcf3ce44SJohn Forte 				flag[ringno] = 1;
553fcf3ce44SJohn Forte 				rp->timeout = hba->timer_tics + 10;
554fcf3ce44SJohn Forte 
555fcf3ce44SJohn Forte 				if (hba->state >= FC_LINK_UP) {
556*728bdc9bSSukumar Swaminathan 					logit = 1;
557fcf3ce44SJohn Forte 				}
558fcf3ce44SJohn Forte 			} else {
559fcf3ce44SJohn Forte 				rp->timeout = 0;
560fcf3ce44SJohn Forte 			}
561fcf3ce44SJohn Forte 		}
562fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_RINGTX_LOCK);
563fcf3ce44SJohn Forte 
564*728bdc9bSSukumar Swaminathan 		if (logit) {
565*728bdc9bSSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT,
566*728bdc9bSSukumar Swaminathan 			    &emlxs_ring_watchdog_msg,
567*728bdc9bSSukumar Swaminathan 			    "%s host=%d port=%d cnt=%d,%d",
568*728bdc9bSSukumar Swaminathan 			    emlxs_ring_xlate(ringno),
569*728bdc9bSSukumar Swaminathan 			    rp->fc_cmdidx, rp->fc_port_cmdidx,
570*728bdc9bSSukumar Swaminathan 			    hba->ring_tx_count[ringno],
571*728bdc9bSSukumar Swaminathan 			    hba->io_count[ringno]);
572*728bdc9bSSukumar Swaminathan 		}
573*728bdc9bSSukumar Swaminathan 
574fcf3ce44SJohn Forte 		/*
575fcf3ce44SJohn Forte 		 * If ring flag is set, request iocb servicing here to send
576fcf3ce44SJohn Forte 		 * any iocb's that may still be queued
577fcf3ce44SJohn Forte 		 */
578fcf3ce44SJohn Forte 		if (flag[ringno]) {
579fcf3ce44SJohn Forte 			emlxs_issue_iocb_cmd(hba, rp, 0);
580fcf3ce44SJohn Forte 		}
581fcf3ce44SJohn Forte 	}
582fcf3ce44SJohn Forte 
583fcf3ce44SJohn Forte 	return;
584fcf3ce44SJohn Forte 
585fcf3ce44SJohn Forte } /* emlxs_timer_check_rings() */
586fcf3ce44SJohn Forte 
587fcf3ce44SJohn Forte 
588fcf3ce44SJohn Forte static void
589fcf3ce44SJohn Forte emlxs_timer_check_nodes(emlxs_port_t *port, uint8_t *flag)
590fcf3ce44SJohn Forte {
591fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
592fcf3ce44SJohn Forte 	uint32_t found;
593fcf3ce44SJohn Forte 	uint32_t i;
594fcf3ce44SJohn Forte 	NODELIST *nlp;
595fcf3ce44SJohn Forte 	int32_t ringno;
596fcf3ce44SJohn Forte 
597fcf3ce44SJohn Forte 	for (;;) {
598fcf3ce44SJohn Forte 		/* Check node gate flag for expiration */
599fcf3ce44SJohn Forte 		found = 0;
600fcf3ce44SJohn Forte 
601fcf3ce44SJohn Forte 		/*
602fcf3ce44SJohn Forte 		 * We need to lock, scan, and unlock because we can't hold
603fcf3ce44SJohn Forte 		 * the lock while we call node_open
604fcf3ce44SJohn Forte 		 */
605fcf3ce44SJohn Forte 		rw_enter(&port->node_rwlock, RW_READER);
606fcf3ce44SJohn Forte 		for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
607fcf3ce44SJohn Forte 			nlp = port->node_table[i];
608fcf3ce44SJohn Forte 			while (nlp != NULL) {
609fcf3ce44SJohn Forte 				for (ringno = 0;
610fcf3ce44SJohn Forte 				    ringno < hba->ring_count;
611fcf3ce44SJohn Forte 				    ringno++) {
612fcf3ce44SJohn Forte 					/*
613fcf3ce44SJohn Forte 					 * Check if the node timer is active
614fcf3ce44SJohn Forte 					 * and if timer has expired
615fcf3ce44SJohn Forte 					 */
616fcf3ce44SJohn Forte 					if ((nlp->nlp_flag[ringno] &
617fcf3ce44SJohn Forte 					    NLP_TIMER) &&
618fcf3ce44SJohn Forte 					    nlp->nlp_tics[ringno] &&
619fcf3ce44SJohn Forte 					    (hba->timer_tics >=
620fcf3ce44SJohn Forte 					    nlp->nlp_tics[ringno])) {
621fcf3ce44SJohn Forte 						/*
622fcf3ce44SJohn Forte 						 * If so, set the flag and
623fcf3ce44SJohn Forte 						 * break out
624fcf3ce44SJohn Forte 						 */
625fcf3ce44SJohn Forte 						found = 1;
626fcf3ce44SJohn Forte 						flag[ringno] = 1;
627fcf3ce44SJohn Forte 						break;
628fcf3ce44SJohn Forte 					}
629fcf3ce44SJohn Forte 				}
630fcf3ce44SJohn Forte 
631fcf3ce44SJohn Forte 				if (found) {
632fcf3ce44SJohn Forte 					break;
633fcf3ce44SJohn Forte 				}
634fcf3ce44SJohn Forte 				nlp = nlp->nlp_list_next;
635fcf3ce44SJohn Forte 			}
636fcf3ce44SJohn Forte 
637fcf3ce44SJohn Forte 			if (found) {
638fcf3ce44SJohn Forte 				break;
639fcf3ce44SJohn Forte 			}
640fcf3ce44SJohn Forte 		}
641fcf3ce44SJohn Forte 		rw_exit(&port->node_rwlock);
642fcf3ce44SJohn Forte 
643fcf3ce44SJohn Forte 		if (!found) {
644fcf3ce44SJohn Forte 			break;
645fcf3ce44SJohn Forte 		}
646fcf3ce44SJohn Forte 		emlxs_node_open(port, nlp, ringno);
647fcf3ce44SJohn Forte 	}
648fcf3ce44SJohn Forte 
649fcf3ce44SJohn Forte } /* emlxs_timer_check_nodes() */
650fcf3ce44SJohn Forte 
651fcf3ce44SJohn Forte 
652fcf3ce44SJohn Forte #ifdef DFC_SUPPORT
653fcf3ce44SJohn Forte static void
654fcf3ce44SJohn Forte emlxs_timer_check_loopback(emlxs_hba_t *hba)
655fcf3ce44SJohn Forte {
656fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
657fcf3ce44SJohn Forte 	emlxs_config_t *cfg = &CFG;
658fcf3ce44SJohn Forte 	int32_t reset = 0;
659fcf3ce44SJohn Forte 
660fcf3ce44SJohn Forte 	if (!cfg[CFG_TIMEOUT_ENABLE].current) {
661fcf3ce44SJohn Forte 		return;
662fcf3ce44SJohn Forte 	}
663fcf3ce44SJohn Forte 	/* Check the loopback timer for expiration */
664fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_PORT_LOCK);
665fcf3ce44SJohn Forte 
666fcf3ce44SJohn Forte 	if (!hba->loopback_tics ||
667fcf3ce44SJohn Forte 	    (hba->timer_tics < hba->loopback_tics)) {
668fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_PORT_LOCK);
669fcf3ce44SJohn Forte 		return;
670fcf3ce44SJohn Forte 	}
671fcf3ce44SJohn Forte 	hba->loopback_tics = 0;
672fcf3ce44SJohn Forte 
673fcf3ce44SJohn Forte 	if (hba->flag & FC_LOOPBACK_MODE) {
674fcf3ce44SJohn Forte 		reset = 1;
675fcf3ce44SJohn Forte 	}
676fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_PORT_LOCK);
677fcf3ce44SJohn Forte 
678fcf3ce44SJohn Forte 	if (reset) {
679fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
680fcf3ce44SJohn Forte 		    "LOOPBACK_MODE: Expired. Resetting...");
681fcf3ce44SJohn Forte 		(void) emlxs_reset(port, FC_FCA_LINK_RESET);
682fcf3ce44SJohn Forte 	}
683fcf3ce44SJohn Forte 	return;
684fcf3ce44SJohn Forte 
685fcf3ce44SJohn Forte } /* emlxs_timer_check_loopback() */
686fcf3ce44SJohn Forte #endif	/* DFC_SUPPORT  */
687fcf3ce44SJohn Forte 
688fcf3ce44SJohn Forte 
689fcf3ce44SJohn Forte static void
690fcf3ce44SJohn Forte emlxs_timer_check_linkup(emlxs_hba_t *hba)
691fcf3ce44SJohn Forte {
692fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
693fcf3ce44SJohn Forte 	uint32_t linkup;
694fcf3ce44SJohn Forte 
695fcf3ce44SJohn Forte 	/* Check the linkup timer for expiration */
696fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_PORT_LOCK);
697fcf3ce44SJohn Forte 	linkup = 0;
698fcf3ce44SJohn Forte 	if (hba->linkup_timer && (hba->timer_tics >= hba->linkup_timer)) {
699fcf3ce44SJohn Forte 		hba->linkup_timer = 0;
700fcf3ce44SJohn Forte 
701fcf3ce44SJohn Forte 		/* Make sure link is still ready */
702fcf3ce44SJohn Forte 		if (hba->state >= FC_LINK_UP) {
703fcf3ce44SJohn Forte 			linkup = 1;
704fcf3ce44SJohn Forte 		}
705fcf3ce44SJohn Forte 	}
706fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_PORT_LOCK);
707fcf3ce44SJohn Forte 
708fcf3ce44SJohn Forte 	/* Make the linkup callback */
709fcf3ce44SJohn Forte 	if (linkup) {
710fcf3ce44SJohn Forte 		emlxs_port_online(port);
711fcf3ce44SJohn Forte 	}
712fcf3ce44SJohn Forte 	return;
713fcf3ce44SJohn Forte 
714fcf3ce44SJohn Forte } /* emlxs_timer_check_linkup() */
715fcf3ce44SJohn Forte 
716fcf3ce44SJohn Forte 
717fcf3ce44SJohn Forte static void
718fcf3ce44SJohn Forte emlxs_timer_check_heartbeat(emlxs_hba_t *hba)
719fcf3ce44SJohn Forte {
720fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
721fcf3ce44SJohn Forte 	MAILBOX *mb;
722fcf3ce44SJohn Forte 	emlxs_config_t *cfg = &CFG;
723fcf3ce44SJohn Forte 
724fcf3ce44SJohn Forte 	if (!cfg[CFG_HEARTBEAT_ENABLE].current) {
725fcf3ce44SJohn Forte 		return;
726fcf3ce44SJohn Forte 	}
727fcf3ce44SJohn Forte 	if (hba->timer_tics < hba->heartbeat_timer) {
728fcf3ce44SJohn Forte 		return;
729fcf3ce44SJohn Forte 	}
730fcf3ce44SJohn Forte 	hba->heartbeat_timer = hba->timer_tics + 5;
731fcf3ce44SJohn Forte 
732fcf3ce44SJohn Forte 	/* Return if adapter interrupts have occurred */
733fcf3ce44SJohn Forte 	if (hba->heartbeat_flag) {
734fcf3ce44SJohn Forte 		hba->heartbeat_flag = 0;
735fcf3ce44SJohn Forte 		return;
736fcf3ce44SJohn Forte 	}
737fcf3ce44SJohn Forte 	/* No adapter interrupts have occured for 5 seconds now */
738fcf3ce44SJohn Forte 
739fcf3ce44SJohn Forte 	/* Return if mailbox is busy */
740fcf3ce44SJohn Forte 	/* This means the mailbox timer routine is watching for problems */
741fcf3ce44SJohn Forte 	if (hba->mbox_timer) {
742fcf3ce44SJohn Forte 		return;
743fcf3ce44SJohn Forte 	}
744fcf3ce44SJohn Forte 	/* Return if heartbeat is still outstanding */
745fcf3ce44SJohn Forte 	if (hba->heartbeat_active) {
746fcf3ce44SJohn Forte 		return;
747fcf3ce44SJohn Forte 	}
748fcf3ce44SJohn Forte 	if ((mb = (MAILBOX *) emlxs_mem_get(hba, MEM_MBOX | MEM_PRI)) == 0) {
749fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
750fcf3ce44SJohn Forte 		    "Unable to allocate heartbeat mailbox.");
751fcf3ce44SJohn Forte 		return;
752fcf3ce44SJohn Forte 	}
753fcf3ce44SJohn Forte 	emlxs_mb_heartbeat(hba, mb);
754fcf3ce44SJohn Forte 	hba->heartbeat_active = 1;
755fcf3ce44SJohn Forte 
756fcf3ce44SJohn Forte 	if (emlxs_mb_issue_cmd(hba, mb, MBX_NOWAIT, 0) != MBX_BUSY) {
757fcf3ce44SJohn Forte 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mb);
758fcf3ce44SJohn Forte 	}
759fcf3ce44SJohn Forte 	return;
760fcf3ce44SJohn Forte 
761fcf3ce44SJohn Forte } /* emlxs_timer_check_heartbeat() */
762fcf3ce44SJohn Forte 
763fcf3ce44SJohn Forte 
764fcf3ce44SJohn Forte 
765fcf3ce44SJohn Forte static void
766fcf3ce44SJohn Forte emlxs_timer_check_mbox(emlxs_hba_t *hba)
767fcf3ce44SJohn Forte {
768fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
769fcf3ce44SJohn Forte 	emlxs_config_t *cfg = &CFG;
770fcf3ce44SJohn Forte 	MAILBOX *mb;
771fcf3ce44SJohn Forte 	uint32_t word0;
772fcf3ce44SJohn Forte 	uint32_t offset;
773fcf3ce44SJohn Forte 	uint32_t ha_copy = 0;
774fcf3ce44SJohn Forte 
775fcf3ce44SJohn Forte 	if (!cfg[CFG_TIMEOUT_ENABLE].current) {
776fcf3ce44SJohn Forte 		return;
777fcf3ce44SJohn Forte 	}
778fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_PORT_LOCK);
779fcf3ce44SJohn Forte 
780fcf3ce44SJohn Forte 	/* Return if timer hasn't expired */
781fcf3ce44SJohn Forte 	if (!hba->mbox_timer || (hba->timer_tics < hba->mbox_timer)) {
782fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_PORT_LOCK);
783fcf3ce44SJohn Forte 		return;
784fcf3ce44SJohn Forte 	}
785fcf3ce44SJohn Forte 	hba->mbox_timer = 0;
786fcf3ce44SJohn Forte 
787fcf3ce44SJohn Forte 	/* Mailbox timed out, first check for error attention */
788fcf3ce44SJohn Forte 	ha_copy = READ_CSR_REG(hba, FC_HA_REG(hba, hba->csr_addr));
789fcf3ce44SJohn Forte 
790fcf3ce44SJohn Forte 	if (ha_copy & HA_ERATT) {
791fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_PORT_LOCK);
792fcf3ce44SJohn Forte 		emlxs_handle_ff_error(hba);
793fcf3ce44SJohn Forte 		return;
794fcf3ce44SJohn Forte 	}
795fcf3ce44SJohn Forte 	if (hba->mbox_queue_flag) {
796fcf3ce44SJohn Forte 		/* Get first word of mailbox */
797fcf3ce44SJohn Forte 		if (hba->flag & FC_SLIM2_MODE) {
798fcf3ce44SJohn Forte 			mb = FC_SLIM2_MAILBOX(hba);
799fcf3ce44SJohn Forte 			offset = (off_t)((uint64_t)(unsigned long)mb -
800fcf3ce44SJohn Forte 			    (uint64_t)(unsigned long)hba->slim2.virt);
801fcf3ce44SJohn Forte 
802fcf3ce44SJohn Forte 			emlxs_mpdata_sync(hba->slim2.dma_handle,
803fcf3ce44SJohn Forte 			    offset, sizeof (uint32_t), DDI_DMA_SYNC_FORKERNEL);
804fcf3ce44SJohn Forte 			word0 = *((volatile uint32_t *) mb);
805fcf3ce44SJohn Forte 			word0 = PCIMEM_LONG(word0);
806fcf3ce44SJohn Forte 		} else {
807fcf3ce44SJohn Forte 			mb = FC_SLIM1_MAILBOX(hba);
808fcf3ce44SJohn Forte 			word0 = READ_SLIM_ADDR(hba, ((volatile uint32_t *)mb));
809fcf3ce44SJohn Forte 		}
810fcf3ce44SJohn Forte 
811fcf3ce44SJohn Forte 		mb = (MAILBOX *) & word0;
812fcf3ce44SJohn Forte 
813fcf3ce44SJohn Forte 		/* Check if mailbox has actually completed */
814fcf3ce44SJohn Forte 		if (mb->mbxOwner == OWN_HOST) {
815fcf3ce44SJohn Forte 			/*
816fcf3ce44SJohn Forte 			 * Read host attention register to determine
817fcf3ce44SJohn Forte 			 * interrupt source
818fcf3ce44SJohn Forte 			 */
819fcf3ce44SJohn Forte 			uint32_t ha_copy = READ_CSR_REG(hba,
820fcf3ce44SJohn Forte 			    FC_HA_REG(hba, hba->csr_addr));
821fcf3ce44SJohn Forte 
822fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg,
823fcf3ce44SJohn Forte 			    "Mailbox attention missed: %s."
824fcf3ce44SJohn Forte 			    "Forcing event. hc = %x ha = %x",
825fcf3ce44SJohn Forte 			    emlxs_mb_cmd_xlate(mb->mbxCommand),
826fcf3ce44SJohn Forte 			    hba->hc_copy, ha_copy);
827fcf3ce44SJohn Forte 
828fcf3ce44SJohn Forte 			mutex_exit(&EMLXS_PORT_LOCK);
829fcf3ce44SJohn Forte 
830fcf3ce44SJohn Forte 			(void) emlxs_handle_mb_event(hba);
831fcf3ce44SJohn Forte 
832fcf3ce44SJohn Forte 			return;
833fcf3ce44SJohn Forte 		}
834fcf3ce44SJohn Forte 		if (hba->mbox_mbq) {
835fcf3ce44SJohn Forte 			mb = (MAILBOX *)hba->mbox_mbq;
836fcf3ce44SJohn Forte 		}
837fcf3ce44SJohn Forte 	}
838fcf3ce44SJohn Forte 	switch (hba->mbox_queue_flag) {
839fcf3ce44SJohn Forte 	case MBX_NOWAIT:
840fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_hardware_error_msg,
841fcf3ce44SJohn Forte 		    "Mailbox Timeout: %s: Nowait.",
842fcf3ce44SJohn Forte 		    emlxs_mb_cmd_xlate(mb->mbxCommand));
843fcf3ce44SJohn Forte 		break;
844fcf3ce44SJohn Forte 
845fcf3ce44SJohn Forte 	case MBX_SLEEP:
846fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_hardware_error_msg,
847fcf3ce44SJohn Forte 		    "Mailbox Timeout: %s: mb=%p Sleep.",
848fcf3ce44SJohn Forte 		    emlxs_mb_cmd_xlate(mb->mbxCommand), mb);
849fcf3ce44SJohn Forte 		break;
850fcf3ce44SJohn Forte 
851fcf3ce44SJohn Forte 	case MBX_POLL:
852fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_hardware_error_msg,
853fcf3ce44SJohn Forte 		    "Mailbox Timeout: %s: mb=%p Polled.",
854fcf3ce44SJohn Forte 		    emlxs_mb_cmd_xlate(mb->mbxCommand), mb);
855fcf3ce44SJohn Forte 		break;
856fcf3ce44SJohn Forte 
857fcf3ce44SJohn Forte 	default:
858fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_hardware_error_msg,
859fcf3ce44SJohn Forte 		    "Mailbox Timeout.");
860fcf3ce44SJohn Forte 		break;
861fcf3ce44SJohn Forte 	}
862fcf3ce44SJohn Forte 
863fcf3ce44SJohn Forte 	hba->flag |= FC_MBOX_TIMEOUT;
864fcf3ce44SJohn Forte 	emlxs_ffstate_change_locked(hba, FC_ERROR);
865fcf3ce44SJohn Forte 
866fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_PORT_LOCK);
867fcf3ce44SJohn Forte 
868fcf3ce44SJohn Forte 	/* Perform mailbox cleanup */
869fcf3ce44SJohn Forte 	/* This will wake any sleeping or polling threads */
870fcf3ce44SJohn Forte 	emlxs_mb_fini(hba, NULL, MBX_TIMEOUT);
871fcf3ce44SJohn Forte 
872fcf3ce44SJohn Forte 	/* Trigger adapter shutdown */
873fcf3ce44SJohn Forte 	(void) thread_create(NULL, 0, emlxs_shutdown_thread, (char *)hba, 0,
874fcf3ce44SJohn Forte 	    &p0, TS_RUN, v.v_maxsyspri - 2);
875fcf3ce44SJohn Forte 
876fcf3ce44SJohn Forte 	return;
877fcf3ce44SJohn Forte 
878fcf3ce44SJohn Forte } /* emlxs_timer_check_mbox() */
879fcf3ce44SJohn Forte 
880fcf3ce44SJohn Forte 
881fcf3ce44SJohn Forte 
882fcf3ce44SJohn Forte static void
883fcf3ce44SJohn Forte emlxs_timer_check_discovery(emlxs_port_t *port)
884fcf3ce44SJohn Forte {
885fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
886fcf3ce44SJohn Forte 	emlxs_config_t *cfg = &CFG;
887fcf3ce44SJohn Forte 	int32_t send_clear_la;
888fcf3ce44SJohn Forte 	uint32_t found;
889fcf3ce44SJohn Forte 	uint32_t i;
890fcf3ce44SJohn Forte 	NODELIST *nlp;
891fcf3ce44SJohn Forte 	MAILBOXQ *mbox;
892fcf3ce44SJohn Forte 
893fcf3ce44SJohn Forte 	if (!cfg[CFG_TIMEOUT_ENABLE].current) {
894fcf3ce44SJohn Forte 		return;
895fcf3ce44SJohn Forte 	}
896fcf3ce44SJohn Forte 	/* Check the discovery timer for expiration */
897fcf3ce44SJohn Forte 	send_clear_la = 0;
898fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_PORT_LOCK);
899fcf3ce44SJohn Forte 	while (hba->discovery_timer &&
900fcf3ce44SJohn Forte 	    (hba->timer_tics >= hba->discovery_timer) &&
901fcf3ce44SJohn Forte 	    (hba->state == FC_LINK_UP)) {
902fcf3ce44SJohn Forte 		send_clear_la = 1;
903fcf3ce44SJohn Forte 
904fcf3ce44SJohn Forte 		/* Perform a flush on fcp2 nodes that are still closed */
905fcf3ce44SJohn Forte 		found = 0;
906fcf3ce44SJohn Forte 		rw_enter(&port->node_rwlock, RW_READER);
907fcf3ce44SJohn Forte 		for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
908fcf3ce44SJohn Forte 			nlp = port->node_table[i];
909fcf3ce44SJohn Forte 			while (nlp != NULL) {
910fcf3ce44SJohn Forte 				if ((nlp->nlp_fcp_info & NLP_FCP_2_DEVICE) &&
911fcf3ce44SJohn Forte 				    (nlp->nlp_flag[FC_FCP_RING] &
912fcf3ce44SJohn Forte 				    NLP_CLOSED)) {
913fcf3ce44SJohn Forte 					found = 1;
914fcf3ce44SJohn Forte 					break;
915fcf3ce44SJohn Forte 
916fcf3ce44SJohn Forte 				}
917fcf3ce44SJohn Forte 				nlp = nlp->nlp_list_next;
918fcf3ce44SJohn Forte 			}
919fcf3ce44SJohn Forte 
920fcf3ce44SJohn Forte 			if (found) {
921fcf3ce44SJohn Forte 				break;
922fcf3ce44SJohn Forte 			}
923fcf3ce44SJohn Forte 		}
924fcf3ce44SJohn Forte 		rw_exit(&port->node_rwlock);
925fcf3ce44SJohn Forte 
926fcf3ce44SJohn Forte 		if (!found) {
927fcf3ce44SJohn Forte 			break;
928fcf3ce44SJohn Forte 		}
929fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_missing_msg,
930fcf3ce44SJohn Forte 		    "FCP2 device (did=%06x) missing. Flushing...",
931fcf3ce44SJohn Forte 		    nlp->nlp_DID);
932fcf3ce44SJohn Forte 
933fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_PORT_LOCK);
934fcf3ce44SJohn Forte 
935fcf3ce44SJohn Forte 		(void) emlxs_mb_unreg_did(port, nlp->nlp_DID, NULL, NULL, NULL);
936fcf3ce44SJohn Forte 
937fcf3ce44SJohn Forte 		mutex_enter(&EMLXS_PORT_LOCK);
938fcf3ce44SJohn Forte 
939fcf3ce44SJohn Forte 	}
940fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_PORT_LOCK);
941fcf3ce44SJohn Forte 
942fcf3ce44SJohn Forte 	/* Try to send clear link attention, if needed */
943fcf3ce44SJohn Forte 	if ((send_clear_la == 1) &&
944fcf3ce44SJohn Forte 	    (mbox = (MAILBOXQ *) emlxs_mem_get(hba, MEM_MBOX | MEM_PRI))) {
945fcf3ce44SJohn Forte 		mutex_enter(&EMLXS_PORT_LOCK);
946fcf3ce44SJohn Forte 
947fcf3ce44SJohn Forte 		/*
948fcf3ce44SJohn Forte 		 * If state is not FC_LINK_UP, then either the link has gone
949fcf3ce44SJohn Forte 		 * down or a FC_CLEAR_LA has already been issued
950fcf3ce44SJohn Forte 		 */
951fcf3ce44SJohn Forte 		if (hba->state != FC_LINK_UP) {
952fcf3ce44SJohn Forte 			mutex_exit(&EMLXS_PORT_LOCK);
953fcf3ce44SJohn Forte 			(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbox);
954fcf3ce44SJohn Forte 		} else {
955fcf3ce44SJohn Forte 			/* Change state and clear discovery timer */
956fcf3ce44SJohn Forte 			emlxs_ffstate_change_locked(hba, FC_CLEAR_LA);
957fcf3ce44SJohn Forte 
958fcf3ce44SJohn Forte 			hba->discovery_timer = 0;
959fcf3ce44SJohn Forte 
960fcf3ce44SJohn Forte 			mutex_exit(&EMLXS_PORT_LOCK);
961fcf3ce44SJohn Forte 
962fcf3ce44SJohn Forte 			/* Prepare and send the CLEAR_LA command */
963fcf3ce44SJohn Forte 			emlxs_mb_clear_la(hba, (MAILBOX *)mbox);
964fcf3ce44SJohn Forte 
965fcf3ce44SJohn Forte 			if (emlxs_mb_issue_cmd(hba, (MAILBOX *)mbox,
966fcf3ce44SJohn Forte 			    MBX_NOWAIT, 0) != MBX_BUSY) {
967fcf3ce44SJohn Forte 				(void) emlxs_mem_put(hba, MEM_MBOX,
968fcf3ce44SJohn Forte 				    (uint8_t *)mbox);
969fcf3ce44SJohn Forte 			}
970fcf3ce44SJohn Forte 		}
971fcf3ce44SJohn Forte 	}
972fcf3ce44SJohn Forte 	return;
973fcf3ce44SJohn Forte 
974fcf3ce44SJohn Forte } /* emlxs_timer_check_discovery()  */
975fcf3ce44SJohn Forte 
976fcf3ce44SJohn Forte 
977fcf3ce44SJohn Forte static void
978fcf3ce44SJohn Forte emlxs_timer_check_ub(emlxs_port_t *port)
979fcf3ce44SJohn Forte {
980fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
981fcf3ce44SJohn Forte 	emlxs_unsol_buf_t *ulistp;
982fcf3ce44SJohn Forte 	fc_unsol_buf_t *ubp;
983fcf3ce44SJohn Forte 	emlxs_ub_priv_t *ub_priv;
984fcf3ce44SJohn Forte 	uint32_t i;
985fcf3ce44SJohn Forte 
986fcf3ce44SJohn Forte 	if (port->ub_timer > hba->timer_tics) {
987fcf3ce44SJohn Forte 		return;
988fcf3ce44SJohn Forte 	}
989fcf3ce44SJohn Forte 	port->ub_timer = hba->timer_tics + EMLXS_UB_PERIOD;
990fcf3ce44SJohn Forte 
991fcf3ce44SJohn Forte 	/* Check the unsolicited buffers */
992fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_UB_LOCK);
993fcf3ce44SJohn Forte 
994fcf3ce44SJohn Forte 	ulistp = port->ub_pool;
995fcf3ce44SJohn Forte 	while (ulistp) {
996fcf3ce44SJohn Forte 		/* Check buffers in this pool */
997fcf3ce44SJohn Forte 		for (i = 0; i < ulistp->pool_nentries; i++) {
998fcf3ce44SJohn Forte 			ubp = (fc_unsol_buf_t *)&ulistp->fc_ubufs[i];
999fcf3ce44SJohn Forte 			ub_priv = ubp->ub_fca_private;
1000fcf3ce44SJohn Forte 
1001fcf3ce44SJohn Forte 			if (!(ub_priv->flags & EMLXS_UB_IN_USE)) {
1002fcf3ce44SJohn Forte 				continue;
1003fcf3ce44SJohn Forte 			}
1004fcf3ce44SJohn Forte 			/*
1005fcf3ce44SJohn Forte 			 * If buffer has timed out, print message and
1006fcf3ce44SJohn Forte 			 * increase timeout
1007fcf3ce44SJohn Forte 			 */
1008fcf3ce44SJohn Forte 			if ((ub_priv->time + ub_priv->timeout) <=
1009fcf3ce44SJohn Forte 			    hba->timer_tics) {
1010fcf3ce44SJohn Forte 				ub_priv->flags |= EMLXS_UB_TIMEOUT;
1011fcf3ce44SJohn Forte 
1012fcf3ce44SJohn Forte 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
1013fcf3ce44SJohn Forte 				    "Stale UB buffer detected (%d mins): "
1014fcf3ce44SJohn Forte 				    "buffer = %p (%x,%x,%x,%x)",
1015fcf3ce44SJohn Forte 				    (ub_priv->timeout / 60),
1016fcf3ce44SJohn Forte 				    ubp, ubp->ub_frame.type,
1017fcf3ce44SJohn Forte 				    ubp->ub_frame.s_id,
1018fcf3ce44SJohn Forte 				    ubp->ub_frame.ox_id,
1019fcf3ce44SJohn Forte 				    ubp->ub_frame.rx_id);
1020fcf3ce44SJohn Forte 
1021fcf3ce44SJohn Forte 				/* Increase timeout period */
1022fcf3ce44SJohn Forte 
1023fcf3ce44SJohn Forte 				/*
1024fcf3ce44SJohn Forte 				 * If timeout was 5 mins or less, increase it
1025fcf3ce44SJohn Forte 				 * to 10 mins
1026fcf3ce44SJohn Forte 				 */
1027fcf3ce44SJohn Forte 				if (ub_priv->timeout <= (5 * 60)) {
1028fcf3ce44SJohn Forte 					ub_priv->timeout = (10 * 60);
1029fcf3ce44SJohn Forte 				}
1030fcf3ce44SJohn Forte 				/*
1031fcf3ce44SJohn Forte 				 * If timeout was 10 mins or less, increase
1032fcf3ce44SJohn Forte 				 * it to 30 mins
1033fcf3ce44SJohn Forte 				 */
1034fcf3ce44SJohn Forte 				else if (ub_priv->timeout <= (10 * 60)) {
1035fcf3ce44SJohn Forte 					ub_priv->timeout = (30 * 60);
1036fcf3ce44SJohn Forte 				}
1037fcf3ce44SJohn Forte 				/* Otherwise double it. */
1038fcf3ce44SJohn Forte 				else {
1039fcf3ce44SJohn Forte 					ub_priv->timeout *= 2;
1040fcf3ce44SJohn Forte 				}
1041fcf3ce44SJohn Forte 			}
1042fcf3ce44SJohn Forte 		}
1043fcf3ce44SJohn Forte 
1044fcf3ce44SJohn Forte 		ulistp = ulistp->pool_next;
1045fcf3ce44SJohn Forte 	}
1046fcf3ce44SJohn Forte 
1047fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_UB_LOCK);
1048fcf3ce44SJohn Forte 
1049fcf3ce44SJohn Forte 	return;
1050fcf3ce44SJohn Forte 
1051fcf3ce44SJohn Forte } /* emlxs_timer_check_ub()  */
1052fcf3ce44SJohn Forte 
1053fcf3ce44SJohn Forte 
1054fcf3ce44SJohn Forte /* EMLXS_FCTAB_LOCK must be held to call this */
1055fcf3ce44SJohn Forte static uint32_t
1056fcf3ce44SJohn Forte emlxs_pkt_chip_timeout(emlxs_port_t *port, emlxs_buf_t *sbp,
1057fcf3ce44SJohn Forte 	Q *abortq, uint8_t *flag)
1058fcf3ce44SJohn Forte {
1059fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
1060fcf3ce44SJohn Forte 	RING *rp = (RING *) sbp->ring;
1061fcf3ce44SJohn Forte 	IOCBQ *iocbq = NULL;
1062fcf3ce44SJohn Forte 	fc_packet_t *pkt;
1063fcf3ce44SJohn Forte 	uint32_t rc = 0;
1064fcf3ce44SJohn Forte 
1065fcf3ce44SJohn Forte 	mutex_enter(&sbp->mtx);
1066fcf3ce44SJohn Forte 
1067fcf3ce44SJohn Forte 	/* Warning: Some FCT sbp's don't have fc_packet objects */
1068fcf3ce44SJohn Forte 	pkt = PRIV2PKT(sbp);
1069fcf3ce44SJohn Forte 
1070fcf3ce44SJohn Forte 	switch (sbp->abort_attempts) {
1071fcf3ce44SJohn Forte 	case 0:
1072fcf3ce44SJohn Forte 
1073fcf3ce44SJohn Forte 		/* Create the abort IOCB */
1074fcf3ce44SJohn Forte 		if (hba->state >= FC_LINK_UP) {
1075fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_timeout_msg,
1076fcf3ce44SJohn Forte 			    "chipQ: 1:Aborting. sbp=%p iotag=%x tmo=%d",
1077fcf3ce44SJohn Forte 			    sbp, sbp->iotag, (pkt) ? pkt->pkt_timeout : 0);
1078fcf3ce44SJohn Forte 
1079fcf3ce44SJohn Forte 			iocbq = emlxs_create_abort_xri_cn(port, sbp->node,
1080fcf3ce44SJohn Forte 			    sbp->iotag, rp, sbp->class, ABORT_TYPE_ABTS);
1081fcf3ce44SJohn Forte 
1082fcf3ce44SJohn Forte 			/*
1083fcf3ce44SJohn Forte 			 * The adapter will make 2 attempts to send ABTS with
1084fcf3ce44SJohn Forte 			 * 2*ratov timeout each time
1085fcf3ce44SJohn Forte 			 */
1086fcf3ce44SJohn Forte 			sbp->ticks = hba->timer_tics + (4 * hba->fc_ratov) + 10;
1087fcf3ce44SJohn Forte 		} else {
1088fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_timeout_msg,
1089fcf3ce44SJohn Forte 			    "chipQ: 1:Closing. sbp=%p iotag=%x tmo=%d",
1090fcf3ce44SJohn Forte 			    sbp, sbp->iotag, (pkt) ? pkt->pkt_timeout : 0);
1091fcf3ce44SJohn Forte 
1092fcf3ce44SJohn Forte 			iocbq = emlxs_create_close_xri_cn(port, sbp->node,
1093fcf3ce44SJohn Forte 			    sbp->iotag, rp);
1094fcf3ce44SJohn Forte 
1095fcf3ce44SJohn Forte 			sbp->ticks = hba->timer_tics + 30;
1096fcf3ce44SJohn Forte 		}
1097fcf3ce44SJohn Forte 
1098fcf3ce44SJohn Forte 		/* set the flags */
1099fcf3ce44SJohn Forte 		sbp->pkt_flags |= (PACKET_IN_TIMEOUT | PACKET_XRI_CLOSED);
1100fcf3ce44SJohn Forte 
1101fcf3ce44SJohn Forte 		flag[rp->ringno] = 1;
1102fcf3ce44SJohn Forte 		rc = 0;
1103fcf3ce44SJohn Forte 
1104fcf3ce44SJohn Forte 		break;
1105fcf3ce44SJohn Forte 
1106fcf3ce44SJohn Forte 	case 1:
1107fcf3ce44SJohn Forte 
1108fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_timeout_msg,
1109fcf3ce44SJohn Forte 		    "chipQ: 2:Closing. sbp=%p iotag=%x",
1110fcf3ce44SJohn Forte 		    sbp, sbp->iotag);
1111fcf3ce44SJohn Forte 
1112fcf3ce44SJohn Forte 		iocbq = emlxs_create_close_xri_cn(port, sbp->node,
1113fcf3ce44SJohn Forte 		    sbp->iotag, rp);
1114fcf3ce44SJohn Forte 
1115fcf3ce44SJohn Forte 		sbp->ticks = hba->timer_tics + 30;
1116fcf3ce44SJohn Forte 
1117fcf3ce44SJohn Forte 		flag[rp->ringno] = 1;
1118fcf3ce44SJohn Forte 		rc = 0;
1119fcf3ce44SJohn Forte 
1120fcf3ce44SJohn Forte 		break;
1121fcf3ce44SJohn Forte 
1122fcf3ce44SJohn Forte 	case 2:
1123fcf3ce44SJohn Forte 
1124fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_timeout_msg,
1125fcf3ce44SJohn Forte 		    "chipQ: 3:Resetting link. sbp=%p iotag=%x",
1126fcf3ce44SJohn Forte 		    sbp, sbp->iotag);
1127fcf3ce44SJohn Forte 
1128fcf3ce44SJohn Forte 		sbp->ticks = hba->timer_tics + 60;
1129fcf3ce44SJohn Forte 		rc = 1;
1130fcf3ce44SJohn Forte 
1131fcf3ce44SJohn Forte 		break;
1132fcf3ce44SJohn Forte 
1133fcf3ce44SJohn Forte 	default:
1134fcf3ce44SJohn Forte 
1135fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_timeout_msg,
1136fcf3ce44SJohn Forte 		    "chipQ: %d:Resetting adapter. sbp=%p iotag=%x",
1137fcf3ce44SJohn Forte 		    sbp->abort_attempts, sbp, sbp->iotag);
1138fcf3ce44SJohn Forte 
1139fcf3ce44SJohn Forte 		sbp->ticks = hba->timer_tics + 60;
1140fcf3ce44SJohn Forte 		rc = 2;
1141fcf3ce44SJohn Forte 
1142fcf3ce44SJohn Forte 		break;
1143fcf3ce44SJohn Forte 	}
1144fcf3ce44SJohn Forte 
1145fcf3ce44SJohn Forte 	sbp->abort_attempts++;
1146fcf3ce44SJohn Forte 	mutex_exit(&sbp->mtx);
1147fcf3ce44SJohn Forte 
1148fcf3ce44SJohn Forte 	if (iocbq) {
1149fcf3ce44SJohn Forte 		if (abortq->q_first) {
1150fcf3ce44SJohn Forte 			((IOCBQ *) abortq->q_last)->next = iocbq;
1151fcf3ce44SJohn Forte 			abortq->q_last = (uint8_t *)iocbq;
1152fcf3ce44SJohn Forte 			abortq->q_cnt++;
1153fcf3ce44SJohn Forte 		} else {
1154fcf3ce44SJohn Forte 			abortq->q_first = (uint8_t *)iocbq;
1155fcf3ce44SJohn Forte 			abortq->q_last = (uint8_t *)iocbq;
1156fcf3ce44SJohn Forte 			abortq->q_cnt = 1;
1157fcf3ce44SJohn Forte 		}
1158fcf3ce44SJohn Forte 		iocbq->next = NULL;
1159fcf3ce44SJohn Forte 	}
1160fcf3ce44SJohn Forte 	return (rc);
1161fcf3ce44SJohn Forte 
1162fcf3ce44SJohn Forte } /* emlxs_pkt_chip_timeout() */
1163fcf3ce44SJohn Forte 
1164fcf3ce44SJohn Forte 
1165fcf3ce44SJohn Forte #ifdef TX_WATCHDOG
1166fcf3ce44SJohn Forte 
1167fcf3ce44SJohn Forte static void
1168fcf3ce44SJohn Forte emlxs_tx_watchdog(emlxs_hba_t *hba)
1169fcf3ce44SJohn Forte {
1170fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
1171fcf3ce44SJohn Forte 	NODELIST *nlp;
1172fcf3ce44SJohn Forte 	uint32_t ringno;
1173fcf3ce44SJohn Forte 	RING *rp;
1174fcf3ce44SJohn Forte 	IOCBQ *next;
1175fcf3ce44SJohn Forte 	IOCBQ *iocbq;
1176fcf3ce44SJohn Forte 	IOCB *iocb;
1177fcf3ce44SJohn Forte 	uint32_t found;
1178fcf3ce44SJohn Forte 	MATCHMAP *bmp;
1179fcf3ce44SJohn Forte 	Q abort;
1180fcf3ce44SJohn Forte 	uint32_t iotag;
1181fcf3ce44SJohn Forte 	emlxs_buf_t *sbp;
1182fcf3ce44SJohn Forte 	fc_packet_t *pkt = NULL;
1183fcf3ce44SJohn Forte 	uint32_t cmd;
1184fcf3ce44SJohn Forte 	uint32_t did;
1185fcf3ce44SJohn Forte 
1186fcf3ce44SJohn Forte 	bzero((void *) &abort, sizeof (Q));
1187fcf3ce44SJohn Forte 
1188fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_RINGTX_LOCK);
1189fcf3ce44SJohn Forte 
1190fcf3ce44SJohn Forte 	for (ringno = 0; ringno < hba->ring_count; ringno++) {
1191fcf3ce44SJohn Forte 		rp = &hba->ring[ringno];
1192fcf3ce44SJohn Forte 
1193fcf3ce44SJohn Forte 		mutex_enter(&EMLXS_FCTAB_LOCK(ringno));
1194fcf3ce44SJohn Forte 		for (iotag = 1; iotag < rp->max_iotag; iotag++) {
1195fcf3ce44SJohn Forte 			sbp = rp->fc_table[iotag];
1196fcf3ce44SJohn Forte 			if (sbp && (sbp != STALE_PACKET) &&
1197fcf3ce44SJohn Forte 			    (sbp->pkt_flags & PACKET_IN_TXQ)) {
1198fcf3ce44SJohn Forte 				nlp = sbp->node;
1199fcf3ce44SJohn Forte 				iocbq = &sbp->iocbq;
1200fcf3ce44SJohn Forte 
1201fcf3ce44SJohn Forte 				if (iocbq->flag & IOCB_PRIORITY) {
1202fcf3ce44SJohn Forte 					iocbq = (IOCBQ *)
1203fcf3ce44SJohn Forte 					    nlp->nlp_ptx[ringno].q_first;
1204fcf3ce44SJohn Forte 				} else {
1205fcf3ce44SJohn Forte 					iocbq = (IOCBQ *)
1206fcf3ce44SJohn Forte 					    nlp->nlp_tx[ringno].q_first;
1207fcf3ce44SJohn Forte 				}
1208fcf3ce44SJohn Forte 
1209fcf3ce44SJohn Forte 				/* Find a matching entry */
1210fcf3ce44SJohn Forte 				found = 0;
1211fcf3ce44SJohn Forte 				while (iocbq) {
1212fcf3ce44SJohn Forte 					if (iocbq == &sbp->iocbq) {
1213fcf3ce44SJohn Forte 						found = 1;
1214fcf3ce44SJohn Forte 						break;
1215fcf3ce44SJohn Forte 					}
1216fcf3ce44SJohn Forte 					iocbq = (IOCBQ *) iocbq->next;
1217fcf3ce44SJohn Forte 				}
1218fcf3ce44SJohn Forte 
1219fcf3ce44SJohn Forte 				if (!found) {
1220fcf3ce44SJohn Forte 					if (!(sbp->pkt_flags & PACKET_STALE)) {
1221fcf3ce44SJohn Forte 						mutex_enter(&sbp->mtx);
1222fcf3ce44SJohn Forte 						sbp->pkt_flags |= PACKET_STALE;
1223fcf3ce44SJohn Forte 						mutex_exit(&sbp->mtx);
1224fcf3ce44SJohn Forte 					} else {
1225fcf3ce44SJohn Forte 						if (abort.q_first == 0) {
1226fcf3ce44SJohn Forte 							abort.q_first =
1227fcf3ce44SJohn Forte 							    &sbp->iocbq;
1228fcf3ce44SJohn Forte 							abort.q_last =
1229fcf3ce44SJohn Forte 							    &sbp->iocbq;
1230fcf3ce44SJohn Forte 						} else {
1231fcf3ce44SJohn Forte 							((IOCBQ *)
1232fcf3ce44SJohn Forte 							    abort.q_last)->next=
1233fcf3ce44SJohn Forte 							    &sbp->iocbq;
1234fcf3ce44SJohn Forte 						}
1235fcf3ce44SJohn Forte 
1236fcf3ce44SJohn Forte 						abort.q_cnt++;
1237fcf3ce44SJohn Forte 					}
1238fcf3ce44SJohn Forte 
1239fcf3ce44SJohn Forte 				} else {
1240fcf3ce44SJohn Forte 					if ((sbp->pkt_flags & PACKET_STALE)) {
1241fcf3ce44SJohn Forte 						mutex_enter(&sbp->mtx);
1242fcf3ce44SJohn Forte 						sbp->pkt_flags &= ~PACKET_STALE;
1243fcf3ce44SJohn Forte 						mutex_exit(&sbp->mtx);
1244fcf3ce44SJohn Forte 					}
1245fcf3ce44SJohn Forte 				}
1246fcf3ce44SJohn Forte 			}
1247fcf3ce44SJohn Forte 		}
1248fcf3ce44SJohn Forte 		mutex_exit(&EMLXS_FCTAB_LOCK(ringno));
1249fcf3ce44SJohn Forte 	}
1250fcf3ce44SJohn Forte 
1251fcf3ce44SJohn Forte 	iocbq = (IOCBQ *) abort.q_first;
1252fcf3ce44SJohn Forte 	while (iocbq) {
1253fcf3ce44SJohn Forte 		next = (IOCBQ *) iocbq->next;
1254fcf3ce44SJohn Forte 		iocbq->next = NULL;
1255fcf3ce44SJohn Forte 		sbp = (emlxs_buf_t *)iocbq->sbp;
1256fcf3ce44SJohn Forte 
1257fcf3ce44SJohn Forte 		pkt = PRIV2PKT(sbp);
1258fcf3ce44SJohn Forte 		if (pkt) {
1259fcf3ce44SJohn Forte 			did = SWAP_DATA24_LO(pkt->pkt_cmd_fhdr.d_id);
1260fcf3ce44SJohn Forte 			cmd = *((uint32_t *)pkt->pkt_cmd);
1261fcf3ce44SJohn Forte 			cmd = SWAP_DATA32(cmd);
1262fcf3ce44SJohn Forte 		}
1263fcf3ce44SJohn Forte 
1264fcf3ce44SJohn Forte 
1265fcf3ce44SJohn Forte 		emlxs_tx_put(iocbq, 0);
1266fcf3ce44SJohn Forte 
1267fcf3ce44SJohn Forte 		iocbq = next;
1268fcf3ce44SJohn Forte 
1269fcf3ce44SJohn Forte 	}	/* end of while */
1270fcf3ce44SJohn Forte 
1271fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_RINGTX_LOCK);
1272fcf3ce44SJohn Forte 
1273fcf3ce44SJohn Forte 	return;
1274fcf3ce44SJohn Forte 
1275fcf3ce44SJohn Forte } /* emlxs_tx_watchdog() */
1276fcf3ce44SJohn Forte 
1277fcf3ce44SJohn Forte #endif	/* TX_WATCHDOG */
1278fcf3ce44SJohn Forte 
1279fcf3ce44SJohn Forte 
1280fcf3ce44SJohn Forte #ifdef DHCHAP_SUPPORT
1281fcf3ce44SJohn Forte 
1282fcf3ce44SJohn Forte static void
1283fcf3ce44SJohn Forte emlxs_timer_check_dhchap(emlxs_port_t *port)
1284fcf3ce44SJohn Forte {
1285fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
1286fcf3ce44SJohn Forte 	uint32_t i;
1287fcf3ce44SJohn Forte 	NODELIST *ndlp = NULL;
1288fcf3ce44SJohn Forte 
1289fcf3ce44SJohn Forte 	for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
1290fcf3ce44SJohn Forte 		ndlp = port->node_table[i];
1291fcf3ce44SJohn Forte 
1292fcf3ce44SJohn Forte 		if (!ndlp) {
1293fcf3ce44SJohn Forte 			continue;
1294fcf3ce44SJohn Forte 		}
1295fcf3ce44SJohn Forte 		/* Check authentication response timeout */
1296fcf3ce44SJohn Forte 		if (ndlp->node_dhc.nlp_authrsp_tmo &&
1297fcf3ce44SJohn Forte 		    (hba->timer_tics >= ndlp->node_dhc.nlp_authrsp_tmo)) {
1298fcf3ce44SJohn Forte 			/* Trigger authresp timeout handler */
1299fcf3ce44SJohn Forte 			(void) emlxs_dhc_authrsp_timeout(port, ndlp, NULL);
1300fcf3ce44SJohn Forte 		}
1301fcf3ce44SJohn Forte 		/* Check reauthentication timeout */
1302fcf3ce44SJohn Forte 		if (ndlp->node_dhc.nlp_reauth_tmo &&
1303fcf3ce44SJohn Forte 		    (hba->timer_tics >= ndlp->node_dhc.nlp_reauth_tmo)) {
1304fcf3ce44SJohn Forte 			/* Trigger reauth timeout handler */
1305fcf3ce44SJohn Forte 			emlxs_dhc_reauth_timeout(port, NULL, ndlp);
1306fcf3ce44SJohn Forte 		}
1307fcf3ce44SJohn Forte 	}
1308fcf3ce44SJohn Forte 	return;
1309fcf3ce44SJohn Forte 
1310fcf3ce44SJohn Forte } /* emlxs_timer_check_dhchap */
1311fcf3ce44SJohn Forte 
1312fcf3ce44SJohn Forte #endif	/* DHCHAP_SUPPORT */
1313