isp_freebsd.c (291209) | isp_freebsd.c (291365) |
---|---|
1/*- 2 * Copyright (c) 1997-2009 by Matthew Jacob 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 14 unchanged lines hidden (view full) --- 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27/* 28 * Platform (FreeBSD) dependent common attachment code for Qlogic adapters. 29 */ 30#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 1997-2009 by Matthew Jacob 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 14 unchanged lines hidden (view full) --- 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27/* 28 * Platform (FreeBSD) dependent common attachment code for Qlogic adapters. 29 */ 30#include <sys/cdefs.h> |
31__FBSDID("$FreeBSD: head/sys/dev/isp/isp_freebsd.c 291209 2015-11-23 15:49:50Z mav $"); | 31__FBSDID("$FreeBSD: head/sys/dev/isp/isp_freebsd.c 291365 2015-11-26 13:04:58Z mav $"); |
32 33#include <dev/isp/isp_freebsd.h> 34#include <sys/unistd.h> 35#include <sys/kthread.h> 36#include <sys/conf.h> 37#include <sys/module.h> 38#include <sys/ioccom.h> 39#include <dev/isp/isp_ioctl.h> --- 5 unchanged lines hidden (view full) --- 45#define THREAD_CREATE kthread_create 46#else 47#define THREAD_CREATE kproc_create 48#endif 49 50MODULE_VERSION(isp, 1); 51MODULE_DEPEND(isp, cam, 1, 1, 1); 52int isp_announced = 0; | 32 33#include <dev/isp/isp_freebsd.h> 34#include <sys/unistd.h> 35#include <sys/kthread.h> 36#include <sys/conf.h> 37#include <sys/module.h> 38#include <sys/ioccom.h> 39#include <dev/isp/isp_ioctl.h> --- 5 unchanged lines hidden (view full) --- 45#define THREAD_CREATE kthread_create 46#else 47#define THREAD_CREATE kproc_create 48#endif 49 50MODULE_VERSION(isp, 1); 51MODULE_DEPEND(isp, cam, 1, 1, 1); 52int isp_announced = 0; |
53int isp_fabric_hysteresis = 5; | |
54int isp_loop_down_limit = 60; /* default loop down limit */ 55int isp_quickboot_time = 7; /* don't wait more than N secs for loop up */ 56int isp_gone_device_time = 30; /* grace time before reporting device lost */ 57static const char prom3[] = "Chan %d [%u] PortID 0x%06x Departed because of %s"; 58 | 53int isp_loop_down_limit = 60; /* default loop down limit */ 54int isp_quickboot_time = 7; /* don't wait more than N secs for loop up */ 55int isp_gone_device_time = 30; /* grace time before reporting device lost */ 56static const char prom3[] = "Chan %d [%u] PortID 0x%06x Departed because of %s"; 57 |
59static void isp_freeze_loopdown(ispsoftc_t *, int, char *); | 58static void isp_freeze_loopdown(ispsoftc_t *, int); 59static void isp_loop_changed(ispsoftc_t *isp, int chan); |
60static d_ioctl_t ispioctl; 61static void isp_intr_enable(void *); 62static void isp_cam_async(void *, uint32_t, struct cam_path *, void *); 63static void isp_poll(struct cam_sim *); 64static timeout_t isp_watchdog; 65static timeout_t isp_gdt; 66static task_fn_t isp_gdt_task; 67static timeout_t isp_ldt; --- 95 unchanged lines hidden (view full) --- 163 char name[16]; 164 165 ISP_LOCK(isp); 166 fc->sim = sim; 167 fc->path = path; 168 fc->isp = isp; 169 fc->ready = 1; 170 | 60static d_ioctl_t ispioctl; 61static void isp_intr_enable(void *); 62static void isp_cam_async(void *, uint32_t, struct cam_path *, void *); 63static void isp_poll(struct cam_sim *); 64static timeout_t isp_watchdog; 65static timeout_t isp_gdt; 66static task_fn_t isp_gdt_task; 67static timeout_t isp_ldt; --- 95 unchanged lines hidden (view full) --- 163 char name[16]; 164 165 ISP_LOCK(isp); 166 fc->sim = sim; 167 fc->path = path; 168 fc->isp = isp; 169 fc->ready = 1; 170 |
171 callout_init_mtx(&fc->ldt, &isp->isp_osinfo.lock, 0); | |
172 callout_init_mtx(&fc->gdt, &isp->isp_osinfo.lock, 0); | 171 callout_init_mtx(&fc->gdt, &isp->isp_osinfo.lock, 0); |
173 TASK_INIT(&fc->ltask, 1, isp_ldt_task, fc); | |
174 TASK_INIT(&fc->gtask, 1, isp_gdt_task, fc); | 172 TASK_INIT(&fc->gtask, 1, isp_gdt_task, fc); |
175 176 /* 177 * We start by being "loop down" if we have an initiator role 178 */ 179 if (fcp->role & ISP_ROLE_INITIATOR) { 180 isp_freeze_loopdown(isp, chan, "isp_attach"); 181 callout_reset(&fc->ldt, isp_quickboot_time * hz, isp_ldt, fc); 182 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, "Starting Initial Loop Down Timer @ %lu", (unsigned long) time_uptime); 183 } | 173 isp_loop_changed(isp, chan); |
184 ISP_UNLOCK(isp); 185 if (THREAD_CREATE(isp_kthread, fc, &fc->kproc, 0, 0, "%s: fc_thrd%d", device_get_nameunit(isp->isp_osinfo.dev), chan)) { 186 xpt_free_path(fc->path); 187 ISP_LOCK(isp); | 174 ISP_UNLOCK(isp); 175 if (THREAD_CREATE(isp_kthread, fc, &fc->kproc, 0, 0, "%s: fc_thrd%d", device_get_nameunit(isp->isp_osinfo.dev), chan)) { 176 xpt_free_path(fc->path); 177 ISP_LOCK(isp); |
188 if (callout_active(&fc->ldt)) 189 callout_stop(&fc->ldt); | |
190 xpt_bus_deregister(cam_sim_path(fc->sim)); 191 ISP_UNLOCK(isp); 192 cam_sim_free(fc->sim, FALSE); 193 return (ENOMEM); 194 } 195 fc->num_threads += 1; 196 if (chan > 0) { 197 snprintf(name, sizeof(name), "chan%d", chan); --- 174 unchanged lines hidden (view full) --- 372 if (isp->isp_osinfo.devq != NULL) { 373 cam_simq_free(isp->isp_osinfo.devq); 374 isp->isp_osinfo.devq = NULL; 375 } 376 return (0); 377} 378 379static void | 178 xpt_bus_deregister(cam_sim_path(fc->sim)); 179 ISP_UNLOCK(isp); 180 cam_sim_free(fc->sim, FALSE); 181 return (ENOMEM); 182 } 183 fc->num_threads += 1; 184 if (chan > 0) { 185 snprintf(name, sizeof(name), "chan%d", chan); --- 174 unchanged lines hidden (view full) --- 360 if (isp->isp_osinfo.devq != NULL) { 361 cam_simq_free(isp->isp_osinfo.devq); 362 isp->isp_osinfo.devq = NULL; 363 } 364 return (0); 365} 366 367static void |
380isp_freeze_loopdown(ispsoftc_t *isp, int chan, char *msg) | 368isp_freeze_loopdown(ispsoftc_t *isp, int chan) |
381{ 382 if (IS_FC(isp)) { 383 struct isp_fc *fc = ISP_FC_PC(isp, chan); 384 if (fc->simqfrozen == 0) { 385 isp_prt(isp, ISP_LOGDEBUG0, | 369{ 370 if (IS_FC(isp)) { 371 struct isp_fc *fc = ISP_FC_PC(isp, chan); 372 if (fc->simqfrozen == 0) { 373 isp_prt(isp, ISP_LOGDEBUG0, |
386 "Chan %d %s -- freeze simq (loopdown)", chan, msg); | 374 "Chan %d Freeze simq (loopdown)", chan); |
387 fc->simqfrozen = SIMQFRZ_LOOPDOWN; 388#if __FreeBSD_version >= 1000039 389 xpt_hold_boot(); 390#endif 391 xpt_freeze_simq(fc->sim, 1); 392 } else { 393 isp_prt(isp, ISP_LOGDEBUG0, | 375 fc->simqfrozen = SIMQFRZ_LOOPDOWN; 376#if __FreeBSD_version >= 1000039 377 xpt_hold_boot(); 378#endif 379 xpt_freeze_simq(fc->sim, 1); 380 } else { 381 isp_prt(isp, ISP_LOGDEBUG0, |
394 "Chan %d %s -- mark frozen (loopdown)", chan, msg); | 382 "Chan %d Mark simq frozen (loopdown)", chan); |
395 fc->simqfrozen |= SIMQFRZ_LOOPDOWN; 396 } 397 } 398} 399 400static void 401isp_unfreeze_loopdown(ispsoftc_t *isp, int chan) 402{ 403 if (IS_FC(isp)) { 404 struct isp_fc *fc = ISP_FC_PC(isp, chan); 405 int wasfrozen = fc->simqfrozen & SIMQFRZ_LOOPDOWN; 406 fc->simqfrozen &= ~SIMQFRZ_LOOPDOWN; 407 if (wasfrozen && fc->simqfrozen == 0) { | 383 fc->simqfrozen |= SIMQFRZ_LOOPDOWN; 384 } 385 } 386} 387 388static void 389isp_unfreeze_loopdown(ispsoftc_t *isp, int chan) 390{ 391 if (IS_FC(isp)) { 392 struct isp_fc *fc = ISP_FC_PC(isp, chan); 393 int wasfrozen = fc->simqfrozen & SIMQFRZ_LOOPDOWN; 394 fc->simqfrozen &= ~SIMQFRZ_LOOPDOWN; 395 if (wasfrozen && fc->simqfrozen == 0) { |
408 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, "%s: Chan %d releasing simq", __func__, chan); | 396 isp_prt(isp, ISP_LOGDEBUG0, 397 "Chan %d Release simq", chan); |
409 xpt_release_simq(fc->sim, 1); 410#if __FreeBSD_version >= 1000039 411 xpt_release_boot(); 412#endif 413 } 414 } 415} 416 --- 59 unchanged lines hidden (view full) --- 476 case ISP_RESCAN: 477 if (IS_FC(isp)) { 478 chan = *(int *)addr; 479 if (chan < 0 || chan >= isp->isp_nchan) { 480 retval = -ENXIO; 481 break; 482 } 483 ISP_LOCK(isp); | 398 xpt_release_simq(fc->sim, 1); 399#if __FreeBSD_version >= 1000039 400 xpt_release_boot(); 401#endif 402 } 403 } 404} 405 --- 59 unchanged lines hidden (view full) --- 465 case ISP_RESCAN: 466 if (IS_FC(isp)) { 467 chan = *(int *)addr; 468 if (chan < 0 || chan >= isp->isp_nchan) { 469 retval = -ENXIO; 470 break; 471 } 472 ISP_LOCK(isp); |
484 if (isp_fc_runstate(isp, chan, 5 * 1000000)) { | 473 if (isp_fc_runstate(isp, chan, 5 * 1000000) != LOOP_READY) { |
485 retval = EIO; 486 } else { 487 retval = 0; 488 } 489 ISP_UNLOCK(isp); 490 } 491 break; 492 --- 2772 unchanged lines hidden (view full) --- 3265 callout_deactivate(&fc->gdt); 3266 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Stopping Gone Device Timer @ %lu", chan, (unsigned long) time_uptime); 3267 } 3268 } 3269 ISP_UNLOCK(isp); 3270} 3271 3272/* | 474 retval = EIO; 475 } else { 476 retval = 0; 477 } 478 ISP_UNLOCK(isp); 479 } 480 break; 481 --- 2772 unchanged lines hidden (view full) --- 3254 callout_deactivate(&fc->gdt); 3255 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Stopping Gone Device Timer @ %lu", chan, (unsigned long) time_uptime); 3256 } 3257 } 3258 ISP_UNLOCK(isp); 3259} 3260 3261/* |
3273 * Loop Down Timer Function- when loop goes down, a timer is started and 3274 * and after it expires we come here and take all probational devices that 3275 * the OS knows about and the tell the OS that they've gone away. 3276 * | 3262 * When loop goes down we remember the time and freeze CAM command queue. 3263 * During some time period we are trying to reprobe the loop. But if we 3264 * fail, we tell the OS that devices have gone away and drop the freeze. 3265 * |
3277 * We don't clear the devices out of our port database because, when loop 3278 * come back up, we have to do some actual cleanup with the chip at that 3279 * point (implicit PLOGO, e.g., to get the chip's port database state right). 3280 */ 3281static void | 3266 * We don't clear the devices out of our port database because, when loop 3267 * come back up, we have to do some actual cleanup with the chip at that 3268 * point (implicit PLOGO, e.g., to get the chip's port database state right). 3269 */ 3270static void |
3282isp_ldt(void *arg) | 3271isp_loop_changed(ispsoftc_t *isp, int chan) |
3283{ | 3272{ |
3284 struct isp_fc *fc = arg; 3285 taskqueue_enqueue(taskqueue_thread, &fc->ltask); | 3273 fcparam *fcp = FCPARAM(isp, chan); 3274 struct isp_fc *fc = ISP_FC_PC(isp, chan); 3275 3276 if (fc->loop_down_time) 3277 return; 3278 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, "Chan %d Loop changed", chan); 3279 if (fcp->role & ISP_ROLE_INITIATOR) 3280 isp_freeze_loopdown(isp, chan); 3281 fc->loop_dead = 0; 3282 fc->loop_down_time = time_uptime; 3283 wakeup(fc); |
3286} 3287 3288static void | 3284} 3285 3286static void |
3289isp_ldt_task(void *arg, int pending) | 3287isp_loop_up(ispsoftc_t *isp, int chan) |
3290{ | 3288{ |
3291 struct isp_fc *fc = arg; 3292 ispsoftc_t *isp = fc->isp; 3293 int chan = fc - isp->isp_osinfo.pc.fc; | 3289 struct isp_fc *fc = ISP_FC_PC(isp, chan); 3290 3291 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, "Chan %d Loop is up", chan); 3292 fc->loop_seen_once = 1; 3293 fc->loop_dead = 0; 3294 fc->loop_down_time = 0; 3295 isp_unfreeze_loopdown(isp, chan); 3296} 3297 3298static void 3299isp_loop_dead(ispsoftc_t *isp, int chan) 3300{ 3301 fcparam *fcp = FCPARAM(isp, chan); 3302 struct isp_fc *fc = ISP_FC_PC(isp, chan); |
3294 fcportdb_t *lp; 3295 struct ac_contract ac; 3296 struct ac_device_changed *adc; 3297 int dbidx, i; 3298 | 3303 fcportdb_t *lp; 3304 struct ac_contract ac; 3305 struct ac_device_changed *adc; 3306 int dbidx, i; 3307 |
3299 ISP_LOCK(isp); 3300 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, "Chan %d Loop Down Timer expired @ %lu", chan, (unsigned long) time_uptime); 3301 callout_deactivate(&fc->ldt); | 3308 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, "Chan %d Loop is dead", chan); |
3302 3303 /* 3304 * Notify to the OS all targets who we now consider have departed. 3305 */ 3306 for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) { | 3309 3310 /* 3311 * Notify to the OS all targets who we now consider have departed. 3312 */ 3313 for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) { |
3307 lp = &FCPARAM(isp, chan)->portdb[dbidx]; | 3314 lp = &fcp->portdb[dbidx]; |
3308 3309 if (lp->state == FC_PORTDB_STATE_NIL) 3310 continue; 3311 3312 /* 3313 * XXX: CLEAN UP AND COMPLETE ANY PENDING COMMANDS FIRST! 3314 */ 3315 for (i = 0; i < isp->isp_maxcmds; i++) { --- 26 unchanged lines hidden (view full) --- 3342 adc->port = lp->portid; 3343 adc->target = dbidx; 3344 adc->arrived = 0; 3345 xpt_async(AC_CONTRACT, fc->path, &ac); 3346 } 3347 } 3348 3349 isp_unfreeze_loopdown(isp, chan); | 3315 3316 if (lp->state == FC_PORTDB_STATE_NIL) 3317 continue; 3318 3319 /* 3320 * XXX: CLEAN UP AND COMPLETE ANY PENDING COMMANDS FIRST! 3321 */ 3322 for (i = 0; i < isp->isp_maxcmds; i++) { --- 26 unchanged lines hidden (view full) --- 3349 adc->port = lp->portid; 3350 adc->target = dbidx; 3351 adc->arrived = 0; 3352 xpt_async(AC_CONTRACT, fc->path, &ac); 3353 } 3354 } 3355 3356 isp_unfreeze_loopdown(isp, chan); |
3350 /* 3351 * The loop down timer has expired. Wake up the kthread 3352 * to notice that fact (or make it false). 3353 */ | |
3354 fc->loop_dead = 1; | 3357 fc->loop_dead = 1; |
3355 fc->loop_down_time = fc->loop_down_limit+1; 3356 wakeup(fc); 3357 ISP_UNLOCK(isp); | 3358 fc->loop_down_time = 0; |
3358} 3359 3360static void 3361isp_kthread(void *arg) 3362{ 3363 struct isp_fc *fc = arg; 3364 ispsoftc_t *isp = fc->isp; 3365 int chan = fc - isp->isp_osinfo.pc.fc; | 3359} 3360 3361static void 3362isp_kthread(void *arg) 3363{ 3364 struct isp_fc *fc = arg; 3365 ispsoftc_t *isp = fc->isp; 3366 int chan = fc - isp->isp_osinfo.pc.fc; |
3366 int slp = 0; | 3367 int slp = 0, d; 3368 int lb, lim; |
3367 3368 mtx_lock(&isp->isp_osinfo.lock); 3369 3370 while (isp->isp_osinfo.is_exiting == 0) { | 3369 3370 mtx_lock(&isp->isp_osinfo.lock); 3371 3372 while (isp->isp_osinfo.is_exiting == 0) { |
3371 int lb, lim; 3372 3373 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, "%s: Chan %d checking FC state", __func__, chan); | 3373 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, 3374 "Chan %d Checking FC state", chan); |
3374 lb = isp_fc_runstate(isp, chan, 250000); | 3375 lb = isp_fc_runstate(isp, chan, 250000); |
3376 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, 3377 "Chan %d FC got to %s state", chan, 3378 isp_fc_loop_statename(lb)); |
|
3375 3376 /* 3377 * Our action is different based upon whether we're supporting 3378 * Initiator mode or not. If we are, we might freeze the simq 3379 * when loop is down and set all sorts of different delays to 3380 * check again. 3381 * 3382 * If not, we simply just wait for loop to come up. 3383 */ | 3379 3380 /* 3381 * Our action is different based upon whether we're supporting 3382 * Initiator mode or not. If we are, we might freeze the simq 3383 * when loop is down and set all sorts of different delays to 3384 * check again. 3385 * 3386 * If not, we simply just wait for loop to come up. 3387 */ |
3384 if (lb && (FCPARAM(isp, chan)->role & ISP_ROLE_INITIATOR)) { | 3388 if (lb == LOOP_READY || lb < 0) { 3389 slp = 0; 3390 } else { |
3385 /* | 3391 /* |
3386 * Increment loop down time by the last sleep interval 3387 */ 3388 fc->loop_down_time += slp; 3389 3390 if (lb < 0) { 3391 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, "%s: Chan %d FC loop not up (down count %d)", __func__, chan, fc->loop_down_time); 3392 } else { 3393 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, "%s: Chan %d FC got to %d (down count %d)", __func__, chan, lb, fc->loop_down_time); 3394 } 3395 3396 /* | |
3397 * If we've never seen loop up and we've waited longer 3398 * than quickboot time, or we've seen loop up but we've 3399 * waited longer than loop_down_limit, give up and go 3400 * to sleep until loop comes up. 3401 */ | 3392 * If we've never seen loop up and we've waited longer 3393 * than quickboot time, or we've seen loop up but we've 3394 * waited longer than loop_down_limit, give up and go 3395 * to sleep until loop comes up. 3396 */ |
3402 if (FCPARAM(isp, chan)->loop_seen_once == 0) { | 3397 if (fc->loop_seen_once == 0) |
3403 lim = isp_quickboot_time; | 3398 lim = isp_quickboot_time; |
3404 } else { | 3399 else |
3405 lim = fc->loop_down_limit; | 3400 lim = fc->loop_down_limit; |
3406 } 3407 if (fc->loop_down_time >= lim) { 3408 isp_freeze_loopdown(isp, chan, "loop limit hit"); | 3401 d = time_uptime - fc->loop_down_time; 3402 if (d >= lim) |
3409 slp = 0; | 3403 slp = 0; |
3410 } else if (fc->loop_down_time < 10) { | 3404 else if (d < 10) |
3411 slp = 1; | 3405 slp = 1; |
3412 } else if (fc->loop_down_time < 30) { | 3406 else if (d < 30) |
3413 slp = 5; | 3407 slp = 5; |
3414 } else if (fc->loop_down_time < 60) { | 3408 else if (d < 60) |
3415 slp = 10; | 3409 slp = 10; |
3416 } else if (fc->loop_down_time < 120) { | 3410 else if (d < 120) |
3417 slp = 20; | 3411 slp = 20; |
3418 } else { | 3412 else |
3419 slp = 30; | 3413 slp = 30; |
3420 } | 3414 } |
3421 | 3415 |
3422 } else if (lb) { 3423 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, "%s: Chan %d FC Loop Down", __func__, chan); 3424 fc->loop_down_time += slp; 3425 if (fc->loop_down_time > 300) 3426 slp = 0; | 3416 if (slp == 0) { 3417 if (lb == LOOP_READY) 3418 isp_loop_up(isp, chan); |
3427 else | 3419 else |
3428 slp = 60; 3429 } else { 3430 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, "%s: Chan %d FC state OK", __func__, chan); 3431 fc->loop_down_time = 0; 3432 slp = 0; | 3420 isp_loop_dead(isp, chan); |
3433 } 3434 | 3421 } 3422 |
3435 3436 /* 3437 * If this is past the first loop up or the loop is dead and if we'd frozen the simq, unfreeze it 3438 * now so that CAM can start sending us commands. 3439 * 3440 * If the FC state isn't okay yet, they'll hit that in isp_start which will freeze the queue again 3441 * or kill the commands, as appropriate. 3442 */ 3443 3444 if (FCPARAM(isp, chan)->loop_seen_once || fc->loop_dead) { 3445 isp_unfreeze_loopdown(isp, chan); 3446 } 3447 3448 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, "%s: Chan %d sleep time %d", __func__, chan, slp); 3449 | 3423 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, 3424 "Chan %d sleep for %d seconds", chan, slp); |
3450 msleep(fc, &isp->isp_osinfo.lock, PRIBIO, "ispf", slp * hz); | 3425 msleep(fc, &isp->isp_osinfo.lock, PRIBIO, "ispf", slp * hz); |
3451 3452 /* 3453 * If slp is zero, we're waking up for the first time after 3454 * things have been okay. In this case, we set a deferral state 3455 * for all commands and delay hysteresis seconds before starting 3456 * the FC state evaluation. This gives the loop/fabric a chance 3457 * to settle. 3458 */ 3459 if (slp == 0 && fc->hysteresis) { 3460 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, "%s: Chan %d sleep hysteresis ticks %d", __func__, chan, fc->hysteresis * hz); 3461 mtx_unlock(&isp->isp_osinfo.lock); 3462 pause("ispt", fc->hysteresis * hz); 3463 mtx_lock(&isp->isp_osinfo.lock); 3464 } | |
3465 } 3466 fc->num_threads -= 1; 3467 mtx_unlock(&isp->isp_osinfo.lock); 3468 kthread_exit(); 3469} 3470 3471static void 3472isp_action(struct cam_sim *sim, union ccb *ccb) 3473{ | 3426 } 3427 fc->num_threads -= 1; 3428 mtx_unlock(&isp->isp_osinfo.lock); 3429 kthread_exit(); 3430} 3431 3432static void 3433isp_action(struct cam_sim *sim, union ccb *ccb) 3434{ |
3474 int bus, tgt, ts, error, lim; | 3435 int bus, tgt, ts, error; |
3475 ispsoftc_t *isp; 3476 struct ccb_trans_settings *cts; 3477 3478 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("isp_action\n")); 3479 3480 isp = (ispsoftc_t *)cam_sim_softc(sim); 3481 mtx_assert(&isp->isp_lock, MA_OWNED); 3482 isp_prt(isp, ISP_LOGDEBUG2, "isp_action code %x", ccb->ccb_h.func_code); --- 47 unchanged lines hidden (view full) --- 3530 if (ts == CAM_TIME_DEFAULT) { 3531 ts = 60*1000; 3532 } 3533 ts = isp_mstohz(ts); 3534 callout_reset(&PISP_PCMD(ccb)->wdog, ts, isp_watchdog, ccb); 3535 break; 3536 case CMD_RQLATER: 3537 /* | 3436 ispsoftc_t *isp; 3437 struct ccb_trans_settings *cts; 3438 3439 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("isp_action\n")); 3440 3441 isp = (ispsoftc_t *)cam_sim_softc(sim); 3442 mtx_assert(&isp->isp_lock, MA_OWNED); 3443 isp_prt(isp, ISP_LOGDEBUG2, "isp_action code %x", ccb->ccb_h.func_code); --- 47 unchanged lines hidden (view full) --- 3491 if (ts == CAM_TIME_DEFAULT) { 3492 ts = 60*1000; 3493 } 3494 ts = isp_mstohz(ts); 3495 callout_reset(&PISP_PCMD(ccb)->wdog, ts, isp_watchdog, ccb); 3496 break; 3497 case CMD_RQLATER: 3498 /* |
3538 * We get this result for FC devices if the loop state isn't ready yet 3539 * or if the device in question has gone zombie on us. 3540 * 3541 * If we've never seen Loop UP at all, we requeue this request and wait 3542 * for the initial loop up delay to expire. | 3499 * We get this result if the loop isn't ready 3500 * or if the device in question has gone zombie. |
3543 */ | 3501 */ |
3544 lim = ISP_FC_PC(isp, bus)->loop_down_limit; 3545 if (FCPARAM(isp, bus)->loop_seen_once == 0 || ISP_FC_PC(isp, bus)->loop_down_time >= lim) { 3546 if (FCPARAM(isp, bus)->loop_seen_once == 0) { 3547 isp_prt(isp, ISP_LOGDEBUG0, 3548 "%d.%jx loop not seen yet @ %lu", 3549 XS_TGT(ccb), (uintmax_t)XS_LUN(ccb), 3550 (unsigned long) time_uptime); 3551 } else { 3552 isp_prt(isp, ISP_LOGDEBUG0, 3553 "%d.%jx downtime (%d) > lim (%d)", 3554 XS_TGT(ccb), (uintmax_t)XS_LUN(ccb), 3555 ISP_FC_PC(isp, bus)->loop_down_time, 3556 lim); 3557 } | 3502 if (ISP_FC_PC(isp, bus)->loop_dead) { 3503 isp_prt(isp, ISP_LOGDEBUG0, 3504 "%d.%jx loop is dead", 3505 XS_TGT(ccb), (uintmax_t)XS_LUN(ccb)); |
3558 ccb->ccb_h.status = CAM_SEL_TIMEOUT; 3559 isp_done((struct ccb_scsiio *) ccb); 3560 break; 3561 } 3562 isp_prt(isp, ISP_LOGDEBUG0, "%d.%jx retry later", 3563 XS_TGT(ccb), (uintmax_t)XS_LUN(ccb)); 3564 cam_freeze_devq(ccb->ccb_h.path); 3565 cam_release_devq(ccb->ccb_h.path, RELSIM_RELEASE_AFTER_TIMEOUT, 0, 1000, 0); --- 689 unchanged lines hidden (view full) --- 4255 if (msg == NULL) 4256 msg = "LIP Received"; 4257 /* FALLTHROUGH */ 4258 case ISPASYNC_LOOP_RESET: 4259 if (msg == NULL) 4260 msg = "LOOP Reset"; 4261 /* FALLTHROUGH */ 4262 case ISPASYNC_LOOP_DOWN: | 3506 ccb->ccb_h.status = CAM_SEL_TIMEOUT; 3507 isp_done((struct ccb_scsiio *) ccb); 3508 break; 3509 } 3510 isp_prt(isp, ISP_LOGDEBUG0, "%d.%jx retry later", 3511 XS_TGT(ccb), (uintmax_t)XS_LUN(ccb)); 3512 cam_freeze_devq(ccb->ccb_h.path); 3513 cam_release_devq(ccb->ccb_h.path, RELSIM_RELEASE_AFTER_TIMEOUT, 0, 1000, 0); --- 689 unchanged lines hidden (view full) --- 4203 if (msg == NULL) 4204 msg = "LIP Received"; 4205 /* FALLTHROUGH */ 4206 case ISPASYNC_LOOP_RESET: 4207 if (msg == NULL) 4208 msg = "LOOP Reset"; 4209 /* FALLTHROUGH */ 4210 case ISPASYNC_LOOP_DOWN: |
4263 { | |
4264 if (msg == NULL) 4265 msg = "LOOP Down"; 4266 va_start(ap, cmd); 4267 bus = va_arg(ap, int); 4268 va_end(ap); | 4211 if (msg == NULL) 4212 msg = "LOOP Down"; 4213 va_start(ap, cmd); 4214 bus = va_arg(ap, int); 4215 va_end(ap); |
4269 4270 FCPARAM(isp, bus)->isp_linkstate = 0; 4271 4272 fc = ISP_FC_PC(isp, bus); 4273 if (cmd == ISPASYNC_LOOP_DOWN && fc->ready) { 4274 /* 4275 * We don't do any simq freezing if we are only in target mode 4276 */ 4277 if (FCPARAM(isp, bus)->role & ISP_ROLE_INITIATOR) { 4278 if (fc->path) { 4279 isp_freeze_loopdown(isp, bus, msg); 4280 } 4281 } 4282 if (!callout_active(&fc->ldt)) { 4283 callout_reset(&fc->ldt, fc->loop_down_limit * hz, isp_ldt, fc); 4284 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, "Starting Loop Down Timer @ %lu", (unsigned long) time_uptime); 4285 } 4286 } | |
4287 isp_fcp_reset_crn(isp, bus, /*tgt*/0, /*tgt_set*/ 0); | 4216 isp_fcp_reset_crn(isp, bus, /*tgt*/0, /*tgt_set*/ 0); |
4288 4289 isp_prt(isp, ISP_LOGINFO, "Chan %d: %s", bus, msg); | 4217 isp_loop_changed(isp, bus); 4218 isp_prt(isp, ISP_LOGINFO, "Chan %d %s", bus, msg); |
4290 break; | 4219 break; |
4291 } | |
4292 case ISPASYNC_LOOP_UP: 4293 va_start(ap, cmd); 4294 bus = va_arg(ap, int); 4295 va_end(ap); | 4220 case ISPASYNC_LOOP_UP: 4221 va_start(ap, cmd); 4222 bus = va_arg(ap, int); 4223 va_end(ap); |
4296 fc = ISP_FC_PC(isp, bus); 4297 /* 4298 * Now we just note that Loop has come up. We don't 4299 * actually do anything because we're waiting for a 4300 * Change Notify before activating the FC cleanup 4301 * thread to look at the state of the loop again. 4302 */ 4303 FCPARAM(isp, bus)->isp_linkstate = 1; 4304 fc->loop_dead = 0; 4305 fc->loop_down_time = 0; | 4224 isp_loop_changed(isp, bus); |
4306 isp_prt(isp, ISP_LOGINFO, "Chan %d Loop UP", bus); 4307 break; 4308 case ISPASYNC_DEV_ARRIVED: 4309 va_start(ap, cmd); 4310 bus = va_arg(ap, int); 4311 lp = va_arg(ap, fcportdb_t *); 4312 va_end(ap); 4313 fc = ISP_FC_PC(isp, bus); --- 116 unchanged lines hidden (view full) --- 4430 } else if (evt == ISPASYNC_CHANGE_SNS) { 4431 msg = "Name Server Database Changed"; 4432 isp_prt(isp, ISP_LOGINFO, "Chan %d %s (PortID 0x%06x)", 4433 bus, msg, portid); 4434 } else { 4435 msg = "Other Change Notify"; 4436 isp_prt(isp, ISP_LOGINFO, "Chan %d %s", bus, msg); 4437 } | 4225 isp_prt(isp, ISP_LOGINFO, "Chan %d Loop UP", bus); 4226 break; 4227 case ISPASYNC_DEV_ARRIVED: 4228 va_start(ap, cmd); 4229 bus = va_arg(ap, int); 4230 lp = va_arg(ap, fcportdb_t *); 4231 va_end(ap); 4232 fc = ISP_FC_PC(isp, bus); --- 116 unchanged lines hidden (view full) --- 4349 } else if (evt == ISPASYNC_CHANGE_SNS) { 4350 msg = "Name Server Database Changed"; 4351 isp_prt(isp, ISP_LOGINFO, "Chan %d %s (PortID 0x%06x)", 4352 bus, msg, portid); 4353 } else { 4354 msg = "Other Change Notify"; 4355 isp_prt(isp, ISP_LOGINFO, "Chan %d %s", bus, msg); 4356 } |
4438 4439 /* 4440 * If the loop down timer is running, cancel it. 4441 */ 4442 if (fc->ready && callout_active(&fc->ldt)) { 4443 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, "Stopping Loop Down Timer @ %lu", (unsigned long) time_uptime); 4444 callout_stop(&fc->ldt); 4445 } 4446 if (FCPARAM(isp, bus)->role & ISP_ROLE_INITIATOR) { 4447 isp_freeze_loopdown(isp, bus, msg); 4448 } 4449 wakeup(fc); | 4357 isp_loop_changed(isp, bus); |
4450 break; 4451 } 4452#ifdef ISP_TARGET_MODE 4453 case ISPASYNC_TARGET_NOTIFY: 4454 { 4455 isp_notify_t *notify; 4456 va_start(ap, cmd); 4457 notify = va_arg(ap, isp_notify_t *); --- 558 unchanged lines hidden --- | 4358 break; 4359 } 4360#ifdef ISP_TARGET_MODE 4361 case ISPASYNC_TARGET_NOTIFY: 4362 { 4363 isp_notify_t *notify; 4364 va_start(ap, cmd); 4365 notify = va_arg(ap, isp_notify_t *); --- 558 unchanged lines hidden --- |