Index: kern/kern_intr.c =================================================================== --- kern/kern_intr.c (revision 239020) +++ kern/kern_intr.c (working copy) @@ -545,17 +545,6 @@ } } - /* Add the new handler to the event in priority order. */ - TAILQ_FOREACH(temp_ih, &ie->ie_handlers, ih_next) { - if (temp_ih->ih_pri > ih->ih_pri) - break; - } - if (temp_ih == NULL) - TAILQ_INSERT_TAIL(&ie->ie_handlers, ih, ih_next); - else - TAILQ_INSERT_BEFORE(temp_ih, ih, ih_next); - intr_event_update(ie); - /* Create a thread if we need one. */ while (ie->ie_thread == NULL && handler != NULL) { if (ie->ie_flags & IE_ADDING_THREAD) @@ -572,6 +561,18 @@ wakeup(ie); } } + + /* Add the new handler to the event in priority order. */ + TAILQ_FOREACH(temp_ih, &ie->ie_handlers, ih_next) { + if (temp_ih->ih_pri > ih->ih_pri) + break; + } + if (temp_ih == NULL) + TAILQ_INSERT_TAIL(&ie->ie_handlers, ih, ih_next); + else + TAILQ_INSERT_BEFORE(temp_ih, ih, ih_next); + intr_event_update(ie); + CTR3(KTR_INTR, "%s: added %s to %s", __func__, ih->ih_name, ie->ie_name); mtx_unlock(&ie->ie_lock); Index: dev/firewire/firewire.c =================================================================== --- dev/firewire/firewire.c (revision 239020) +++ dev/firewire/firewire.c (working copy) @@ -223,7 +223,8 @@ /* XXX allow bus explore packets only after bus rest */ if ((fc->status < FWBUSEXPLORE) && - ((tcode != FWTCODE_RREQQ) || (fp->mode.rreqq.dest_hi != 0xffff) || + ((fc->status < FWBUSINIT) || + (tcode != FWTCODE_RREQQ) || (fp->mode.rreqq.dest_hi != 0xffff) || (fp->mode.rreqq.dest_lo < 0xf0000000) || (fp->mode.rreqq.dest_lo >= 0xf0001000))) { xfer->resp = EAGAIN; @@ -279,7 +280,7 @@ * Wakeup blocked process. */ void -fw_xferwake(struct fw_xfer *xfer) +_fw_xferwake(struct fw_xfer *xfer) { struct mtx *lock = &xfer->fc->wait_lock; @@ -292,7 +293,7 @@ } int -fw_xferwait(struct fw_xfer *xfer) +_fw_xferwait(struct fw_xfer *xfer) { struct mtx *lock = &xfer->fc->wait_lock; int err = 0; @@ -371,7 +372,7 @@ break; device_printf(fc->bdev, "split transaction timeout: " - "tl=0x%x flag=0x%02x\n", i, xfer->flag); + "tl=0x%x xfer %p flag=0x%02x\n", i, xfer, xfer->flag); fw_dump_hdr(&xfer->send.hdr, "send"); xfer->resp = ETIMEDOUT; STAILQ_REMOVE_HEAD(&fc->tlabels[i], tlabel); @@ -383,7 +384,10 @@ fc->timeout(fc); STAILQ_FOREACH_SAFE(xfer, &xfer_timeout, tlabel, txfer) + { + TR3("xfer timeout %p flag %x hand %p", xfer, xfer->flag, xfer->hand); xfer->hand(xfer); + } } #define WATCHDOG_HZ 10 @@ -614,8 +618,10 @@ } mtx_unlock(&fc->tlabel_lock); - STAILQ_FOREACH_SAFE(xfer, &xfer_drain, tlabel, txfer) + STAILQ_FOREACH_SAFE(xfer, &xfer_drain, tlabel, txfer) { + TR1("drain_txq xfer %p", xfer); xfer->hand(xfer); + } } static void @@ -1113,7 +1119,7 @@ * To allocate IEEE1394 XFER structure. */ struct fw_xfer * -fw_xfer_alloc(struct malloc_type *type) +_fw_xfer_alloc(struct malloc_type *type) { struct fw_xfer *xfer; @@ -1127,11 +1133,11 @@ } struct fw_xfer * -fw_xfer_alloc_buf(struct malloc_type *type, int send_len, int recv_len) +_fw_xfer_alloc_buf(struct malloc_type *type, int send_len, int recv_len) { struct fw_xfer *xfer; - xfer = fw_xfer_alloc(type); + xfer = _fw_xfer_alloc(type); if (xfer == NULL) return(NULL); xfer->send.pay_len = send_len; @@ -1159,7 +1165,7 @@ * IEEE1394 XFER post process. */ void -fw_xfer_done(struct fw_xfer *xfer) +_fw_xfer_done(struct fw_xfer *xfer) { if (xfer->hand == NULL) { printf("hand == NULL\n"); @@ -1198,7 +1204,7 @@ * 1. We call fwohci_arcv() before fwohci_txd(). * 2. firewire_watch() is called. */ - printf("fw_xfer_free FWXF_START\n"); + printf("fw_xfer_free %p FWXF_START\n", xfer); #endif } xfer->flag = FWXF_INIT; @@ -1208,7 +1214,7 @@ * To free IEEE1394 XFER structure. */ void -fw_xfer_free_buf( struct fw_xfer* xfer) +_fw_xfer_free_buf( struct fw_xfer* xfer) { if (xfer == NULL) { printf("%s: xfer == NULL\n", __func__); @@ -1225,7 +1231,7 @@ } void -fw_xfer_free( struct fw_xfer* xfer) +_fw_xfer_free( struct fw_xfer* xfer) { if (xfer == NULL) { printf("%s: xfer == NULL\n", __func__); @@ -1242,6 +1248,7 @@ printf("asyreq done flag=0x%02x resp=%d\n", xfer->flag, xfer->resp); #endif + TR1("xfer_asy_callback_free: %p", xfer); fw_xfer_free(xfer); } @@ -1467,7 +1474,7 @@ for (i = 0; i < length; i ++, offset += sizeof(uint32_t)) { xfer = fwmem_read_quad(fwdev, NULL, -1, 0xffff, 0xf0000000 | offset, (void *)&tmp, - fw_xferwake); + _fw_xferwake); if (xfer == NULL) return (-1); fw_xferwait(xfer); @@ -2070,7 +2077,7 @@ /* rb->xfer->hand = fw_xferwake; */ - rb->xfer->hand = fw_xfer_free; + rb->xfer->hand = _fw_xfer_free; if(fw_asyreq(rb->fc, -1, rb->xfer)){ fw_xfer_free(rb->xfer); return; @@ -2089,6 +2096,7 @@ } STAILQ_REMOVE_HEAD(&bind->xferlist, link); fw_rcv_copy(rb); + TR1("fw_rcv xfer %p", rb->xfer); rb->xfer->hand(rb->xfer); return; #if 0 /* shouldn't happen ?? or for GASP */ Index: dev/firewire/firewirereg.h =================================================================== --- dev/firewire/firewirereg.h (revision 239020) +++ dev/firewire/firewirereg.h (working copy) @@ -270,10 +270,10 @@ void fw_sidrcv (struct firewire_comm *, uint32_t *, u_int); void fw_rcv (struct fw_rcv_buf *); void fw_xfer_unload ( struct fw_xfer*); -void fw_xfer_free_buf ( struct fw_xfer*); -void fw_xfer_free ( struct fw_xfer*); -struct fw_xfer *fw_xfer_alloc (struct malloc_type *); -struct fw_xfer *fw_xfer_alloc_buf (struct malloc_type *, int, int); +void _fw_xfer_free_buf ( struct fw_xfer*); +void _fw_xfer_free ( struct fw_xfer*); +struct fw_xfer *_fw_xfer_alloc (struct malloc_type *); +struct fw_xfer *_fw_xfer_alloc_buf (struct malloc_type *, int, int); void fw_init (struct firewire_comm *); int fw_tbuf_update (struct firewire_comm *, int, int); int fw_rbuf_update (struct firewire_comm *, int, int); @@ -286,9 +286,9 @@ void fw_busreset (struct firewire_comm *, uint32_t); uint16_t fw_crc16 (uint32_t *, uint32_t); void fw_xfer_timeout (void *); -void fw_xfer_done (struct fw_xfer *); -void fw_xferwake (struct fw_xfer *); -int fw_xferwait (struct fw_xfer *); +void _fw_xfer_done (struct fw_xfer *); +void _fw_xferwake (struct fw_xfer *); +int _fw_xferwait (struct fw_xfer *); void fw_asy_callback_free (struct fw_xfer *); struct fw_device *fw_noderesolve_nodeid (struct firewire_comm *, int); struct fw_device *fw_noderesolve_eui64 (struct firewire_comm *, struct fw_eui64 *); @@ -303,6 +303,14 @@ extern devclass_t firewire_devclass; extern int firewire_phydma_enable; +#define fw_xfer_free(xfer) do { TR1("xfer free %p", (xfer)); _fw_xfer_free(xfer); } while(0) +#define fw_xfer_free_buf(xfer) do { TR1("xfer free_buf %p", (xfer)); _fw_xfer_free_buf(xfer); } while(0) +#define fw_xfer_done(xfer) do { TR1("xfer done %p", (xfer)); _fw_xfer_done(xfer); } while(0) +#define fw_xfer_alloc(m) ({ struct fw_xfer *__xfer = _fw_xfer_alloc((m)); TR1("xfer alloc %p", __xfer); __xfer;}) +#define fw_xfer_alloc_buf(m, a, b) ({ struct fw_xfer *__xfer = _fw_xfer_alloc_buf((m), (a), (b)); TR1("xfer alloc_buf %p", __xfer); __xfer;}) +#define fw_xferwait(xfer) ({ int __ret; TR1("xfer wait %p begin", (xfer)); __ret = _fw_xferwait((xfer)); TR2("xfer wait %p ret %d", (xfer), __ret); __ret;}) +#define fw_xferwake(xfer) do { TR1("xfer wake %p", (xfer)); _fw_xferwake(xfer); } while(0) + #ifdef __DragonFly__ #define FWPRI PCATCH #else Index: dev/firewire/fwohci.c =================================================================== --- dev/firewire/fwohci.c (revision 239020) +++ dev/firewire/fwohci.c (working copy) @@ -53,6 +53,7 @@ #include #include #include +#include #include @@ -137,7 +138,7 @@ static void fwohci_db_init (struct fwohci_softc *, struct fwohci_dbch *); static void fwohci_db_free (struct fwohci_dbch *); static void fwohci_arcv (struct fwohci_softc *, struct fwohci_dbch *, int); -static void fwohci_txd (struct fwohci_softc *, struct fwohci_dbch *); +void fwohci_txd (struct fwohci_softc *, struct fwohci_dbch *, int flush); static void fwohci_start_atq (struct firewire_comm *); static void fwohci_start_ats (struct firewire_comm *); static void fwohci_start (struct fwohci_softc *, struct fwohci_dbch *); @@ -884,11 +885,11 @@ FW_GLOCK_ASSERT(&sc->fc); - if(&sc->atrq == dbch){ + if (&sc->atrq == dbch) { off = OHCI_ATQOFF; - }else if(&sc->atrs == dbch){ + } else if(&sc->atrs == dbch) { off = OHCI_ATSOFF; - }else{ + } else { return; } @@ -902,11 +903,7 @@ if(xfer == NULL){ goto kick; } -#if 0 - if(dbch->xferq.queued == 0 ){ - device_printf(sc->fc.dev, "TX queue empty\n"); - } -#endif + TR2("fwohci_start xfer %p db_tr %p", xfer, db_tr); STAILQ_REMOVE_HEAD(&dbch->xferq.q, link); db_tr->xfer = xfer; xfer->flag = FWXF_START; @@ -1070,7 +1067,7 @@ } void -fwohci_txd(struct fwohci_softc *sc, struct fwohci_dbch *dbch) +fwohci_txd(struct fwohci_softc *sc, struct fwohci_dbch *dbch, int flush) { int s, ch, err = 0; struct fwohcidb_tr *tr; @@ -1081,13 +1078,14 @@ int packets; struct firewire_comm *fc = (struct firewire_comm *)sc; - if(&sc->atrq == dbch){ + TR2("fwohci_txd and fc status is %d, flush is %d", fc->status, flush); + if (&sc->atrq == dbch) { off = OHCI_ATQOFF; ch = ATRQ_CH; - }else if(&sc->atrs == dbch){ + } else if(&sc->atrs == dbch) { off = OHCI_ATSOFF; ch = ATRS_CH; - }else{ + } else { return; } s = splfw(); @@ -1095,13 +1093,15 @@ packets = 0; fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_POSTREAD); fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_POSTWRITE); - while(dbch->xferq.queued > 0){ + while (dbch->xferq.queued > 0) { LAST_DB(tr, db); status = FWOHCI_DMA_READ(db->db.desc.res) >> OHCI_STATUS_SHIFT; - if(!(status & OHCI_CNTL_DMA_ACTIVE)){ - if (fc->status != FWBUSINIT) + if (!(status & OHCI_CNTL_DMA_ACTIVE)) { + if (fc->status != FWBUSINIT) { /* maybe out of order?? */ + TR1("DMA not complete and fc status is %d", fc->status); goto out; + } } bus_dmamap_sync(dbch->dmat, tr->dma_map, BUS_DMASYNC_POSTWRITE); @@ -1110,7 +1110,7 @@ if (firewire_debug > 1) dump_db(sc, ch); #endif - if(status & OHCI_CNTL_DMA_DEAD) { + if (status & OHCI_CNTL_DMA_DEAD) { /* Stop DMA */ OWRITE(sc, OHCI_DMACTLCLR(off), OHCI_CNTL_DMA_RUN); device_printf(sc->fc.dev, "force reset AT FIFO\n"); @@ -1119,7 +1119,7 @@ OWRITE(sc, OHCI_DMACTLCLR(off), OHCI_CNTL_DMA_RUN); } stat = status & FWOHCIEV_MASK; - switch(stat){ + switch(stat) { case FWOHCIEV_ACKPEND: case FWOHCIEV_ACKCOMPL: err = 0; @@ -1146,8 +1146,7 @@ case FWOHCIEV_ACKDERR: case FWOHCIEV_ACKTERR: default: - device_printf(sc->fc.dev, "txd err=%2x %s\n", - stat, fwohcicode[stat]); + device_printf(sc->fc.dev, "txd err=%2x %s\n", stat, fwohcicode[stat]); err = EINVAL; break; } @@ -1158,26 +1157,30 @@ if (firewire_debug) printf("already rcvd\n"); #endif + TR1("xfer RCVD %p", xfer); fw_xfer_done(xfer); } else { - microtime(&xfer->tv); - xfer->flag = FWXF_SENT; if (err == EBUSY) { xfer->flag = FWXF_BUSY; xfer->resp = err; xfer->recv.pay_len = 0; + TR2("xfer err %p err %d", xfer, err); fw_xfer_done(xfer); } else if (stat != FWOHCIEV_ACKPEND) { - if (stat != FWOHCIEV_ACKCOMPL) - xfer->flag = FWXF_SENTERR; + xfer->flag = (stat != FWOHCIEV_ACKCOMPL) ? FWXF_SENTERR : FWXF_SENT; xfer->resp = err; xfer->recv.pay_len = 0; + TR3("xfer err %p err %d stat %u", xfer, err, stat); fw_xfer_done(xfer); + } else { + microtime(&xfer->tv); + xfer->flag = FWXF_SENT; + TR3("xfer err %p err %d stat %u", xfer, err, stat); } } /* * The watchdog timer takes care of split - * transcation timeout for ACKPEND case. + * transaction timeout for ACKPEND case. */ } else { printf("this shouldn't happen\n"); @@ -1191,7 +1194,7 @@ tr = STAILQ_NEXT(tr, link); dbch->bottom = tr; if (dbch->bottom == dbch->top) { - /* we reaches the end of context program */ + /* we reached the end of context program */ if (firewire_debug && dbch->xferq.queued > 0) printf("queued > 0\n"); break; @@ -1274,7 +1277,7 @@ } #define DB_SIZE(x) (sizeof(struct fwohcidb) * (x)->ndesc) - dbch->am = fwdma_malloc_multiseg(&sc->fc, DB_SIZE(dbch), + dbch->am = fwdma_malloc_multiseg(&sc->fc, sizeof(struct fwohcidb), DB_SIZE(dbch), dbch->ndb, BUS_DMA_WAITOK); if (dbch->am == NULL) { printf("fwohci_db_init: fwdma_malloc_multiseg failed\n"); @@ -1842,26 +1845,36 @@ { struct firewire_comm *fc = (struct firewire_comm *)sc; uint32_t node_id, plen; +#ifdef KTR + int fcstatus = fc->status;; +#endif FW_GLOCK_ASSERT(fc); + TR3("INTR reset %s sid %s status %d", + (stat & OHCI_INT_PHY_BUS_R) ? "yes" : "no", + (stat & OHCI_INT_PHY_SID) ? "yes" : "no", + fcstatus); + if ((stat & OHCI_INT_PHY_BUS_R) && (fc->status != FWBUSRESET)) { fc->status = FWBUSRESET; + TR2("fcstatus %d -> %d", fcstatus, fc->status); /* Disable bus reset interrupt until sid recv. */ OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_PHY_BUS_R); - + device_printf(fc->dev, "%s: BUS reset\n", __func__); OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_CYC_LOST); OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCSRC); - OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN); + OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN); sc->atrq.xferq.flag &= ~FWXFERQ_RUNNING; - OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN); + OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN); sc->atrs.xferq.flag &= ~FWXFERQ_RUNNING; if (!kdb_active) taskqueue_enqueue(sc->fc.taskqueue, &sc->fwohci_task_busreset); } if (stat & OHCI_INT_PHY_SID) { + TR1("SID received, status %d", fc->status); /* Enable bus reset interrupt */ OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_PHY_BUS_R); OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_PHY_BUS_R); @@ -1907,8 +1920,6 @@ OWRITE(sc, OHCI_LNKCTL, OHCI_CNTL_CYCTIMER); } - fc->status = FWBUSINIT; - if (!kdb_active) taskqueue_enqueue(sc->fc.taskqueue, &sc->fwohci_task_sid); } @@ -1924,6 +1935,8 @@ u_int i; struct firewire_comm *fc = (struct firewire_comm *)sc; + TR1("fwohci_intr_dma stat %x start", stat); + if (stat & OHCI_INT_DMA_IR) { irstat = atomic_readandclear_int(&sc->irstat); for(i = 0; i < fc->nisodma ; i++){ @@ -1976,10 +1989,12 @@ } } if (stat & OHCI_INT_DMA_ATRQ) { - fwohci_txd(sc, &(sc->atrq)); + TR0("intr_dma atrq"); + fwohci_txd(sc, &(sc->atrq), 0); } if (stat & OHCI_INT_DMA_ATRS) { - fwohci_txd(sc, &(sc->atrs)); + TR0("intr_dma atrs"); + fwohci_txd(sc, &(sc->atrs), 0); } if (stat & OHCI_INT_PW_ERR) { device_printf(fc->dev, "posted write error\n"); @@ -1990,6 +2005,7 @@ if (stat & OHCI_INT_PHY_INT) { device_printf(fc->dev, "phy int\n"); } + TR1("fwohci_intr_dma stat %x end", stat); return; } @@ -1999,11 +2015,13 @@ { struct fwohci_softc *sc = (struct fwohci_softc *)arg; + TR1("fwohci_task_busreset penging %d start", pending); 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); + TR1("fwohci_task_busreset penging %d end", pending); } static void @@ -2014,6 +2032,7 @@ uint32_t *buf; int i, plen; + TR1("fwohci_task_sid penging %d start", pending); /* * We really should have locking @@ -2039,14 +2058,22 @@ for (i = 0; i < plen / 4; i ++) buf[i] = FWOHCI_DMA_READ(sc->sid_buf[i+1]); + TR2("fcstatus %d -> %d", fc->status, FWBUSINIT); + fc->status = FWBUSINIT; + /* pending all pre-bus_reset packets */ - fwohci_txd(sc, &sc->atrq); - fwohci_txd(sc, &sc->atrs); + TR0("SID_TASK: txd atrq"); + fwohci_txd(sc, &sc->atrq, 1); + TR0("SID_TASK: txd atrs"); + fwohci_txd(sc, &sc->atrs, 1); fwohci_arcv(sc, &sc->arrs, -1); fwohci_arcv(sc, &sc->arrq, -1); + TR0("SID_TASK: drain_txq"); fw_drain_txq(fc); fw_sidrcv(fc, buf, plen); free(buf, M_FW); + + TR1("fwohci_task_sid penging %d end", pending); } static void Index: dev/firewire/fwdev.c =================================================================== --- dev/firewire/fwdev.c (revision 239020) +++ dev/firewire/fwdev.c (working copy) @@ -449,7 +449,7 @@ xfer->fc = d->fc; xfer->sc = NULL; - xfer->hand = fw_xferwake; + xfer->hand = _fw_xferwake; xfer->send.spd = 2 /* XXX */; if ((err = fw_asyreq(xfer->fc, -1, xfer))) @@ -711,7 +711,7 @@ bcopy((char *)fp + tinfo->hdr_len, (void *)xfer->send.payload, pay_len); xfer->send.spd = asyreq->req.sped; - xfer->hand = fw_xferwake; + xfer->hand = _fw_xferwake; if ((err = fw_asyreq(fc, -1, xfer)) != 0) goto out; Index: dev/pci/pcireg.h =================================================================== --- dev/pci/pcireg.h (revision 239020) +++ dev/pci/pcireg.h (working copy) @@ -667,6 +667,16 @@ #define PCIR_EXPRESS_SLOT_STA 0x1a #define PCIR_EXPRESS_ROOT_CTL 0x1c #define PCIR_EXPRESS_ROOT_STA 0x20 +#define PCIR_EXPRESS_DEVICE_CTL2 40 +#define PCIM_EXPRESS_DEVICE_CTL2_ARI 0x20 +#define PCIM_EXPRESS_ID_ORDERED_REQ_EN 0x100 +#define PCIM_EXPRESS_ID_ORDERED_CMP_EN 0x200 +#define PCIM_EXPRESS_LTR_ENABLE 0x400 +#define PCIM_EXPRESS_OBFF_MSGA_ENABLE 0x2000 +#define PCIM_EXPRESS_OBFF_MSGB_ENABLE 0x4000 +#define PCIM_EXPRESS_OBFF_WAKE_ENABLE 0x6000 +#define PCIR_EXPRESS_LINK_CTL2 48 +#define PCIR_EXPRESS_SLOT_CTL2 56 /* MSI-X definitions */ #define PCIR_MSIX_CTRL 0x2 Index: dev/pci/pcivar.h =================================================================== --- dev/pci/pcivar.h (revision 239020) +++ dev/pci/pcivar.h (working copy) @@ -123,6 +123,23 @@ uint64_t ht_msiaddr; /* MSI mapping base address */ }; +struct pcicfg_pcie { + uint16_t pcie_flags; + uint16_t pcie_device_ctl; + uint16_t pcie_link_ctl; + uint16_t pcie_slot_ctl; + uint16_t pcie_root_ctl; + uint16_t pcie_device_ctl2; + uint16_t pcie_link_ctl2; + uint16_t pcie_slot_ctl2; + uint8_t pcie_location; /* Offset of PCI-e capability registers. */ +}; + +struct pcicfg_pcix { + uint16_t pcix_command; + uint8_t pcix_location; /* Offset of PCI-X capability registers. */ +}; + /* config header information common to all header types */ typedef struct pcicfg { struct device *dev; /* device which owns this */ @@ -164,6 +181,8 @@ struct pcicfg_msi msi; /* PCI MSI */ struct pcicfg_msix msix; /* PCI MSI-X */ struct pcicfg_ht ht; /* HyperTransport */ + struct pcicfg_pcie pcie; + struct pcicfg_pcix pcix; } pcicfgregs; /* additional type 1 device config header information (PCI to PCI bridge) */ Index: dev/pci/pci.c =================================================================== --- dev/pci/pci.c (revision 239020) +++ dev/pci/pci.c (working copy) @@ -743,6 +743,7 @@ if ((cfg->hdrtype & PCIM_HDRTYPE) == PCIM_HDRTYPE_BRIDGE) pcix_chipset = 1; + cfg->pcix.pcix_location = ptr; break; case PCIY_EXPRESS: /* PCI-express */ /* @@ -750,6 +751,7 @@ * at least one PCI-express device. */ pcie_chipset = 1; + cfg->pcie.pcie_location = ptr; break; default: break; @@ -4388,6 +4390,50 @@ return (0); } +static void +pci_cfg_restore_pcie(device_t dev, struct pci_devinfo *dinfo) +{ +#define WREG(n, v) pci_write_config(dev, pos + (n), (v), 2) + struct pcicfg_pcie *cfg; + int type, version, pos; + + cfg = &dinfo->cfg.pcie; + pos = cfg->pcie_location; + + version = cfg->pcie_flags & PCIM_EXP_FLAGS_VERSION; + type = cfg->pcie_flags & PCIM_EXP_FLAGS_TYPE; + + WREG(PCIR_EXPRESS_DEVICE_CTL, cfg->pcie_device_ctl); + + if (version > 1 || type == PCIM_EXP_TYPE_ROOT_PORT || + type == PCIM_EXP_TYPE_ENDPOINT || + type == PCIM_EXP_TYPE_LEGACY_ENDPOINT) + WREG(PCIR_EXPRESS_LINK_CTL, cfg->pcie_link_ctl); + + if (version > 1 || (type == PCIM_EXP_TYPE_ROOT_PORT || + (type == PCIM_EXP_TYPE_DOWNSTREAM_PORT && + (cfg->pcie_flags & PCIM_EXP_FLAGS_SLOT)))) + WREG(PCIR_EXPRESS_SLOT_CTL, cfg->pcie_link_ctl); + + if (version > 1 || type == PCIM_EXP_TYPE_ROOT_PORT || + type == PCIM_EXP_TYPE_ROOT_EC) + WREG(PCIR_EXPRESS_ROOT_CTL, cfg->pcie_root_ctl); + + if (version > 1) { + WREG(PCIR_EXPRESS_DEVICE_CTL2, cfg->pcie_device_ctl2); + WREG(PCIR_EXPRESS_LINK_CTL2, cfg->pcie_link_ctl2); + WREG(PCIR_EXPRESS_SLOT_CTL2, cfg->pcie_slot_ctl2); + } +#undef WREG +} + +static void +pci_cfg_restore_pcix(device_t dev, struct pci_devinfo *dinfo) +{ + pci_write_config(dev, dinfo->cfg.pcix.pcix_location + PCIXR_COMMAND, + dinfo->cfg.pcix.pcix_command, 2); +} + void pci_cfg_restore(device_t dev, struct pci_devinfo *dinfo) { @@ -4423,6 +4469,14 @@ pci_write_config(dev, PCIR_PROGIF, dinfo->cfg.progif, 1); pci_write_config(dev, PCIR_REVID, dinfo->cfg.revid, 1); + /* + * Restore extended capabilities for PCI-Express and PCI-X + */ + if (dinfo->cfg.pcie.pcie_location != 0) + pci_cfg_restore_pcie(dev, dinfo); + if (dinfo->cfg.pcix.pcix_location != 0) + pci_cfg_restore_pcix(dev, dinfo); + /* Restore MSI and MSI-X configurations if they are present. */ if (dinfo->cfg.msi.msi_location != 0) pci_resume_msi(dev); @@ -4430,6 +4484,52 @@ pci_resume_msix(dev); } +static void +pci_cfg_save_pcie(device_t dev, struct pci_devinfo *dinfo) +{ +#define RREG(n) pci_read_config(dev, pos + (n), 2) + struct pcicfg_pcie *cfg; + int type, version, pos; + + cfg = &dinfo->cfg.pcie; + pos = cfg->pcie_location; + + cfg->pcie_flags = RREG(PCIR_EXPRESS_FLAGS); + + version = cfg->pcie_flags & PCIM_EXP_FLAGS_VERSION; + type = cfg->pcie_flags & PCIM_EXP_FLAGS_TYPE; + + cfg->pcie_device_ctl = RREG(PCIR_EXPRESS_DEVICE_CTL); + + if (version > 1 || type == PCIM_EXP_TYPE_ROOT_PORT || + type == PCIM_EXP_TYPE_ENDPOINT || + type == PCIM_EXP_TYPE_LEGACY_ENDPOINT) + cfg->pcie_link_ctl = RREG(PCIR_EXPRESS_LINK_CTL); + + if (version > 1 || (type == PCIM_EXP_TYPE_ROOT_PORT || + (type == PCIM_EXP_TYPE_DOWNSTREAM_PORT && + (cfg->pcie_flags & PCIM_EXP_FLAGS_SLOT)))) + cfg->pcie_slot_ctl = RREG(PCIR_EXPRESS_SLOT_CTL); + + if (version > 1 || type == PCIM_EXP_TYPE_ROOT_PORT || + type == PCIM_EXP_TYPE_ROOT_EC) + cfg->pcie_root_ctl = RREG(PCIR_EXPRESS_ROOT_CTL); + + if (version > 1) { + cfg->pcie_device_ctl2 = RREG(PCIR_EXPRESS_DEVICE_CTL2); + cfg->pcie_link_ctl2 = RREG(PCIR_EXPRESS_LINK_CTL2); + cfg->pcie_slot_ctl2 = RREG(PCIR_EXPRESS_SLOT_CTL2); + } +#undef RREG +} + +static void +pci_cfg_save_pcix(device_t dev, struct pci_devinfo *dinfo) +{ + dinfo->cfg.pcix.pcix_command = pci_read_config(dev, + dinfo->cfg.pcix.pcix_location + PCIXR_COMMAND, 2); +} + void pci_cfg_save(device_t dev, struct pci_devinfo *dinfo, int setstate) { @@ -4472,6 +4572,12 @@ dinfo->cfg.progif = pci_read_config(dev, PCIR_PROGIF, 1); dinfo->cfg.revid = pci_read_config(dev, PCIR_REVID, 1); + if (dinfo->cfg.pcie.pcie_location != 0) + pci_cfg_save_pcie(dev, dinfo); + + if (dinfo->cfg.pcix.pcix_location != 0) + pci_cfg_save_pcix(dev, dinfo); + /* * don't set the state for display devices, base peripherals and * memory devices since bad things happen when they are powered down. Index: x86/cpufreq/p4tcc.c =================================================================== --- x86/cpufreq/p4tcc.c (revision 239020) +++ x86/cpufreq/p4tcc.c (working copy) @@ -276,9 +276,9 @@ * what the current mode. */ if (msr & TCC_ENABLE_ONDEMAND) + sc->auto_mode = FALSE; + else sc->auto_mode = TRUE; - else - sc->auto_mode = FALSE; return (0); }