diff options
-rw-r--r-- | sys/dev/firewire/firewire.c | 85 | ||||
-rw-r--r-- | sys/dev/firewire/fwohci.c | 40 | ||||
-rw-r--r-- | sys/dev/firewire/fwohci_pci.c | 11 | ||||
-rw-r--r-- | sys/dev/firewire/fwohcivar.h | 8 | ||||
-rw-r--r-- | sys/dev/firewire/sbp.c | 13 |
5 files changed, 88 insertions, 69 deletions
diff --git a/sys/dev/firewire/firewire.c b/sys/dev/firewire/firewire.c index ae0d5d3..8137df6 100644 --- a/sys/dev/firewire/firewire.c +++ b/sys/dev/firewire/firewire.c @@ -430,6 +430,31 @@ firewire_attach(device_t dev) fwdev_makedev(sc); + fc->crom_src_buf = (struct crom_src_buf *)malloc( + sizeof(struct crom_src_buf), + M_FW, M_NOWAIT | M_ZERO); + if (fc->crom_src_buf == NULL) { + device_printf(fc->dev, "%s: Malloc Failure crom src buff\n", __func__); + return ENOMEM; + } + fc->topology_map = (struct fw_topology_map *)malloc( + sizeof(struct fw_topology_map), + M_FW, M_NOWAIT | M_ZERO); + if (fc->topology_map == NULL) { + device_printf(fc->dev, "%s: Malloc Failure topology map\n", __func__); + free(fc->crom_src_buf, M_FW); + return ENOMEM; + } + fc->speed_map = (struct fw_speed_map *)malloc( + sizeof(struct fw_speed_map), + M_FW, M_NOWAIT | M_ZERO); + if (fc->speed_map == NULL) { + device_printf(fc->dev, "%s: Malloc Failure speed map\n", __func__); + free(fc->crom_src_buf, M_FW); + free(fc->topology_map, M_FW); + return ENOMEM; + } + mtx_init(&fc->wait_lock, "fwwait", NULL, MTX_DEF); mtx_init(&fc->tlabel_lock, "fwtlabel", NULL, MTX_DEF); CALLOUT_INIT(&fc->timeout_callout); @@ -451,7 +476,9 @@ firewire_attach(device_t dev) bus_generic_attach(dev); /* bus_reset */ + FW_GLOCK(fc); fw_busreset(fc, FWBUSNOTREADY); + FW_GUNLOCK(fc); fc->ibr(fc); return 0; @@ -642,11 +669,6 @@ fw_init_crom(struct firewire_comm *fc) { struct crom_src *src; - fc->crom_src_buf = (struct crom_src_buf *) - malloc(sizeof(struct crom_src_buf), M_FW, M_WAITOK | M_ZERO); - if (fc->crom_src_buf == NULL) - return; - src = &fc->crom_src_buf->src; bzero(src, sizeof(struct crom_src)); @@ -663,7 +685,7 @@ fw_init_crom(struct firewire_comm *fc) src->businfo.cyc_clk_acc = 100; src->businfo.max_rec = fc->maxrec; src->businfo.max_rom = MAXROM_4; - src->businfo.generation = 1; + src->businfo.generation = 0; src->businfo.link_spd = fc->speed; src->businfo.eui64.hi = fc->eui.hi; @@ -682,9 +704,6 @@ fw_reset_crom(struct firewire_comm *fc) struct crom_src *src; struct crom_chunk *root; - if (fc->crom_src_buf == NULL) - fw_init_crom(fc); - buf = fc->crom_src_buf; src = fc->crom_src; root = fc->crom_root; @@ -715,18 +734,18 @@ fw_busreset(struct firewire_comm *fc, uint32_t new_status) struct firewire_dev_comm *fdc; struct crom_src *src; device_t *devlistp; - void *newrom; int i, devcnt; - switch(fc->status){ - case FWBUSMGRELECT: + FW_GLOCK_ASSERT(fc); + if (fc->status == FWBUSMGRELECT) callout_stop(&fc->bmr_callout); - break; - default: - break; - } + fc->status = new_status; fw_reset_csr(fc); + + if (fc->status == FWBUSNOTREADY) + fw_init_crom(fc); + fw_reset_crom(fc); if (device_get_children(fc->bdev, &devlistp, &devcnt) == 0) { @@ -739,19 +758,19 @@ fw_busreset(struct firewire_comm *fc, uint32_t new_status) free(devlistp, M_TEMP); } - newrom = malloc(CROMSIZE, M_FW, M_NOWAIT | M_ZERO); src = &fc->crom_src_buf->src; - crom_load(src, (uint32_t *)newrom, CROMSIZE); - if (bcmp(newrom, fc->config_rom, CROMSIZE) != 0) { - /* bump generation and reload */ - src->businfo.generation ++; - /* generation must be between 0x2 and 0xF */ - if (src->businfo.generation < 2) - src->businfo.generation ++; - crom_load(src, (uint32_t *)newrom, CROMSIZE); - bcopy(newrom, (void *)fc->config_rom, CROMSIZE); - } - free(newrom, M_FW); + /* + * If the old config rom needs to be overwritten, + * bump the businfo.generation indicator to + * indicate that we need to be reprobed + */ + if (bcmp(src, fc->config_rom, CROMSIZE) != 0) { + /* generation is a 2 bit field */ + /* valid values are only from 0 - 3 */ + src->businfo.generation = 1; + bcopy(src, (void *)fc->config_rom, CROMSIZE); + } else + src->businfo.generation = 0; } /* Call once after reboot */ @@ -807,13 +826,7 @@ void fw_init(struct firewire_comm *fc) fc->ir[i]->maxq = FWMAXQUEUE; fc->it[i]->maxq = FWMAXQUEUE; } -/* Initialize csr registers */ - fc->topology_map = (struct fw_topology_map *)malloc( - sizeof(struct fw_topology_map), - M_FW, M_NOWAIT | M_ZERO); - fc->speed_map = (struct fw_speed_map *)malloc( - sizeof(struct fw_speed_map), - M_FW, M_NOWAIT | M_ZERO); + CSRARC(fc, TOPO_MAP) = 0x3f1 << 16; CSRARC(fc, TOPO_MAP + 4) = 1; CSRARC(fc, SPED_MAP) = 0x3f1 << 16; @@ -1559,7 +1572,7 @@ fw_explore_node(struct fw_device *dfwdev) /* unchanged ? */ if (bcmp(&csr[0], &fwdev->csrrom[0], sizeof(uint32_t) * 5) == 0) { if (firewire_debug) - printf("node%d: crom unchanged\n", node); + device_printf(fc->dev, "node%d: crom unchanged\n", node); return (0); } diff --git a/sys/dev/firewire/fwohci.c b/sys/dev/firewire/fwohci.c index 1c2573b..258ba1b 100644 --- a/sys/dev/firewire/fwohci.c +++ b/sys/dev/firewire/fwohci.c @@ -1003,7 +1003,7 @@ again: if (maxdesc < db_tr->dbcnt) { maxdesc = db_tr->dbcnt; if (firewire_debug) - device_printf(sc->fc.dev, "maxdesc: %d\n", maxdesc); + device_printf(sc->fc.dev, "%s: maxdesc %d\n", __func__, maxdesc); } /* last db */ LAST_DB(db_tr, db); @@ -1842,6 +1842,7 @@ fwohci_intr_core(struct fwohci_softc *sc, uint32_t stat, int count) struct firewire_comm *fc = (struct firewire_comm *)sc; uint32_t node_id, plen; + FW_GLOCK_ASSERT(fc); if ((stat & OHCI_INT_PHY_BUS_R) && (fc->status != FWBUSRESET)) { fc->status = FWBUSRESET; /* Disable bus reset interrupt until sid recv. */ @@ -1884,8 +1885,8 @@ fwohci_intr_core(struct fwohci_softc *sc, uint32_t stat, int count) plen = OREAD(sc, OHCI_SID_CNT); fc->nodeid = node_id & 0x3f; - device_printf(fc->dev, "node_id=0x%08x, gen=%d, ", - node_id, (plen >> 16) & 0xff); + device_printf(fc->dev, "node_id=0x%08x, SelfID Count=%d, ", + fc->nodeid, (plen >> 16) & 0xff); if (!(node_id & OHCI_NODE_VALID)) { printf("Bus reset failure\n"); goto sidout; @@ -1996,9 +1997,11 @@ fwohci_task_busreset(void *arg, int pending) { struct fwohci_softc *sc = (struct fwohci_softc *)arg; + FW_GLOCK(&sc->fc); fw_busreset(&sc->fc, FWBUSRESET); OWRITE(sc, OHCI_CROMHDR, ntohl(sc->fc.config_rom[0])); OWRITE(sc, OHCI_BUS_OPT, ntohl(sc->fc.config_rom[2])); + FW_GUNLOCK(&sc->fc); } static void @@ -2010,6 +2013,10 @@ fwohci_task_sid(void *arg, int pending) int i, plen; + /* + * We really should have locking + * here. Not sure why it's not + */ plen = OREAD(sc, OHCI_SID_CNT); if (plen & OHCI_SID_ERR) { @@ -2029,14 +2036,13 @@ fwohci_task_sid(void *arg, int pending) } for (i = 0; i < plen / 4; i ++) buf[i] = FWOHCI_DMA_READ(sc->sid_buf[i+1]); -#if 1 /* XXX needed?? */ + /* pending all pre-bus_reset packets */ fwohci_txd(sc, &sc->atrq); fwohci_txd(sc, &sc->atrs); fwohci_arcv(sc, &sc->arrs, -1); fwohci_arcv(sc, &sc->arrq, -1); fw_drain_txq(fc); -#endif fw_sidrcv(fc, buf, plen); free(buf, M_FW); } @@ -2061,6 +2067,7 @@ fwohci_check_stat(struct fwohci_softc *sc) { uint32_t stat, irstat, itstat; + FW_GLOCK_ASSERT(&sc->fc); stat = OREAD(sc, FWOHCI_INTSTAT); if (stat == 0xffffffff) { device_printf(sc->fc.dev, @@ -2090,29 +2097,24 @@ fwohci_check_stat(struct fwohci_softc *sc) return (FILTER_HANDLED); } -int -fwohci_filt(void *arg) -{ - struct fwohci_softc *sc = (struct fwohci_softc *)arg; - - if (!(sc->intmask & OHCI_INT_EN)) { - /* polling mode */ - return (FILTER_STRAY); - } - return (fwohci_check_stat(sc)); -} - void fwohci_intr(void *arg) { - fwohci_filt(arg); + struct fwohci_softc *sc = (struct fwohci_softc *)arg; + + FW_GLOCK(&sc->fc); + fwohci_check_stat(sc); + FW_GUNLOCK(&sc->fc); } void fwohci_poll(struct firewire_comm *fc, int quick, int count) { struct fwohci_softc *sc = (struct fwohci_softc *)fc; + + FW_GLOCK(fc); fwohci_check_stat(sc); + FW_GUNLOCK(fc); } static void @@ -2466,6 +2468,7 @@ fwohci_ibr(struct firewire_comm *fc) device_printf(fc->dev, "Initiate bus reset\n"); sc = (struct fwohci_softc *)fc; + FW_GLOCK(fc); /* * Make sure our cached values from the config rom are * initialised. @@ -2486,6 +2489,7 @@ fwohci_ibr(struct firewire_comm *fc) fun |= FW_PHY_ISBR | FW_PHY_RHB; fun = fwphy_wrdata(sc, FW_PHY_ISBR_REG, fun); #endif + FW_GUNLOCK(fc); } void diff --git a/sys/dev/firewire/fwohci_pci.c b/sys/dev/firewire/fwohci_pci.c index b21bb28..ea46dbc 100644 --- a/sys/dev/firewire/fwohci_pci.c +++ b/sys/dev/firewire/fwohci_pci.c @@ -334,14 +334,11 @@ fwohci_pci_attach(device_t self) return ENXIO; } - err = bus_setup_intr(self, sc->irq_res, - INTR_TYPE_NET | INTR_MPSAFE, -#if FWOHCI_INTFILT - fwohci_filt, NULL, sc, &sc->ih); -#else - NULL, (driver_intr_t *) fwohci_intr, sc, &sc->ih); -#endif + INTR_TYPE_NET | INTR_MPSAFE, + NULL, (driver_intr_t *) fwohci_intr, + sc, &sc->ih); + #if defined(__DragonFly__) || __FreeBSD_version < 500000 /* XXX splcam() should mask this irq for sbp.c*/ err = bus_setup_intr(self, sc->irq_res, INTR_TYPE_CAM, diff --git a/sys/dev/firewire/fwohcivar.h b/sys/dev/firewire/fwohcivar.h index d0ee9f6..7e24ab0 100644 --- a/sys/dev/firewire/fwohcivar.h +++ b/sys/dev/firewire/fwohcivar.h @@ -37,12 +37,6 @@ #include <sys/taskqueue.h> -#if defined(__DragonFly__) || __FreeBSD_version < 700043 -#define FWOHCI_INTFILT 0 -#else -#define FWOHCI_INTFILT 1 -#endif - typedef struct fwohci_softc { struct firewire_comm fc; bus_space_tag_t bst; @@ -84,7 +78,7 @@ typedef struct fwohci_softc { } fwohci_softc_t; void fwohci_intr (void *arg); -int fwohci_filt (void *arg); +void fwohci_filt (void *arg); int fwohci_init (struct fwohci_softc *, device_t); void fwohci_poll (struct firewire_comm *, int, int); void fwohci_reset (struct fwohci_softc *, device_t); diff --git a/sys/dev/firewire/sbp.c b/sys/dev/firewire/sbp.c index b4d89d5..e13ec85 100644 --- a/sys/dev/firewire/sbp.c +++ b/sys/dev/firewire/sbp.c @@ -493,6 +493,7 @@ END_DEBUG /* lost device */ sbp_cam_detach_sdev(sdev); sbp_free_sdev(sdev); + target->luns[lun] = NULL; } } @@ -781,7 +782,9 @@ END_DEBUG SBP_UNLOCK(sbp); } sdev->status = SBP_DEV_RETRY; - sbp_abort_all_ocbs(sdev, CAM_SCSI_BUS_RESET); + sbp_cam_detach_sdev(sdev); + sbp_free_sdev(sdev); + target->luns[i] = NULL; break; case SBP_DEV_PROBE: case SBP_DEV_TOATTACH: @@ -1255,11 +1258,18 @@ END_DEBUG htonl(((sdev->target->sbp->fd.fc->nodeid | FWLOCALBUS )<< 16)); xfer->send.payload[1] = htonl((uint32_t)ocb->bus_addr); + /* + * sbp_xfer_free() will attempt to acquire + * the SBP lock on entrance. Also, this removes + * a LOR between the firewire layer and sbp + */ + SBP_UNLOCK(sdev->target->sbp); if(fw_asyreq(xfer->fc, -1, xfer) != 0){ sbp_xfer_free(xfer); ocb->ccb->ccb_h.status = CAM_REQ_INVALID; xpt_done(ocb->ccb); } + SBP_LOCK(sdev->target->sbp); } static void @@ -2123,6 +2133,7 @@ sbp_free_sdev(struct sbp_dev *sdev) sdev->ocb[i].dmamap); fwdma_free(sdev->target->sbp->fd.fc, &sdev->dma); free(sdev, M_SBP); + sdev = NULL; } static void |