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