Deleted Added
full compact
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 ---