Module Name: src Committed By: cegger Date: Sat Aug 14 10:39:36 UTC 2010
Modified Files: src/sys/dev/ieee1394: sbp.c Log Message: Fix sbp attach/detach. When plugging a firewire webcam, sbp attaches. sbpattach() calls sbp_alloc_target(). In sbp_alloc_target, crom_search_key() fails and sbp_alloc_target() returns NULL. Move mutex and list initializations up in sbpattach() and in sbp_alloc_target() so that destroyal of them through sbpdetach() does not cause LOCKDEBUG panics when unplugging the firewire webcam. To generate a diff of this commit: cvs rdiff -u -r1.32 -r1.33 src/sys/dev/ieee1394/sbp.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/ieee1394/sbp.c diff -u src/sys/dev/ieee1394/sbp.c:1.32 src/sys/dev/ieee1394/sbp.c:1.33 --- src/sys/dev/ieee1394/sbp.c:1.32 Sun May 23 18:56:59 2010 +++ src/sys/dev/ieee1394/sbp.c Sat Aug 14 10:39:33 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: sbp.c,v 1.32 2010/05/23 18:56:59 christos Exp $ */ +/* $NetBSD: sbp.c,v 1.33 2010/08/14 10:39:33 cegger Exp $ */ /*- * Copyright (c) 2003 Hidetoshi Shimokawa * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa @@ -37,7 +37,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: sbp.c,v 1.32 2010/05/23 18:56:59 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sbp.c,v 1.33 2010/08/14 10:39:33 cegger Exp $"); #include <sys/param.h> @@ -495,6 +495,12 @@ sc->sc_target.fwdev = NULL; sc->sc_target.luns = NULL; + /* Initialize mutexes and lists before we can error out + * to prevent crashes on detach + */ + mutex_init(&sc->sc_fwb.fwb_mtx, MUTEX_DEFAULT, IPL_VM); + STAILQ_INIT(&sc->sc_fwb.xferlist); + if (sbp_alloc_target(sc, fwa->fwdev) == NULL) return; @@ -525,9 +531,7 @@ dv_unit = device_unit(sc->sc_fd.dev); sc->sc_fwb.start = SBP_DEV2ADDR(dv_unit, 0); sc->sc_fwb.end = SBP_DEV2ADDR(dv_unit, -1); - mutex_init(&sc->sc_fwb.fwb_mtx, MUTEX_DEFAULT, IPL_VM); /* pre-allocate xfer */ - STAILQ_INIT(&sc->sc_fwb.xferlist); fw_xferlist_add(&sc->sc_fwb.xferlist, M_SBP, /*send*/ 0, /*recv*/ SBP_RECV_LEN, SBP_NUM_OCB / 2, fc, (void *)sc, sbp_recv); @@ -550,7 +554,7 @@ sbp_scsipi_detach_target(&sc->sc_target); - if (SBP_FWDEV_ALIVE(sc->sc_target.fwdev)) { + if (sc->sc_target.fwdev && SBP_FWDEV_ALIVE(sc->sc_target.fwdev)) { sbp_logout_all(sc); /* XXX wait for logout completion */ @@ -566,6 +570,7 @@ mutex_destroy(&sc->sc_fwb.fwb_mtx); mutex_destroy(&sc->sc_mtx); + cv_destroy(&sc->sc_cv); return 0; } @@ -841,6 +846,18 @@ target->sbp = sc; target->fwdev = fwdev; target->target_id = 0; + target->mgm_ocb_cur = NULL; +SBP_DEBUG(1) + printf("target: mgm_port: %x\n", target->mgm_lo); +END_DEBUG + STAILQ_INIT(&target->xferlist); + target->n_xfer = 0; + STAILQ_INIT(&target->mgm_ocb_queue); + callout_init(&target->mgm_ocb_timeout, CALLOUT_MPSAFE); + + target->luns = NULL; + target->num_lun = 0; + /* XXX we may want to reload mgm port after each bus reset */ /* XXX there might be multiple management agents */ crom_init_context(&cc, target->fwdev->csrrom); @@ -850,19 +867,10 @@ target->fwdev = NULL; return NULL; } + target->mgm_hi = 0xffff; target->mgm_lo = 0xf0000000 | (reg->val << 2); - target->mgm_ocb_cur = NULL; -SBP_DEBUG(1) - printf("target: mgm_port: %x\n", target->mgm_lo); -END_DEBUG - STAILQ_INIT(&target->xferlist); - target->n_xfer = 0; - STAILQ_INIT(&target->mgm_ocb_queue); - callout_init(&target->mgm_ocb_timeout, CALLOUT_MPSAFE); - target->luns = NULL; - target->num_lun = 0; return target; } @@ -2023,7 +2031,7 @@ printf("sbp_logout_all\n"); END_DEBUG target = &sbp->sc_target; - if (target->luns != NULL) + if (target->luns != NULL) { for (i = 0; i < target->num_lun; i++) { sdev = target->luns[i]; if (sdev == NULL) @@ -2033,6 +2041,7 @@ sdev->status <= SBP_DEV_ATTACHED) sbp_mgm_orb(sdev, ORB_FUN_LGO, NULL); } + } return 0; }