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