diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2013-11-06 16:20:21 +0100 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2013-11-11 10:08:08 +0100 |
commit | 66659ff1ad6831b0ea7425fa6ecd8a8687523658 (patch) | |
tree | 48e22b475fa8854128e0861a33fed6f78c8094b5 /freebsd/sys/dev | |
parent | Define __GLOBL1() and __GLOBL() (diff) | |
download | rtems-libbsd-66659ff1ad6831b0ea7425fa6ecd8a8687523658.tar.bz2 |
Update to FreeBSD 9.2
Diffstat (limited to 'freebsd/sys/dev')
59 files changed, 2426 insertions, 1750 deletions
diff --git a/freebsd/sys/dev/bce/if_bce.c b/freebsd/sys/dev/bce/if_bce.c index 21ef5dc7..dfae5dcc 100644 --- a/freebsd/sys/dev/bce/if_bce.c +++ b/freebsd/sys/dev/bce/if_bce.c @@ -377,7 +377,8 @@ static void bce_release_resources (struct bce_softc *); /****************************************************************************/ static void bce_fw_cap_init (struct bce_softc *); static int bce_fw_sync (struct bce_softc *, u32); -static void bce_load_rv2p_fw (struct bce_softc *, u32 *, u32, u32); +static void bce_load_rv2p_fw (struct bce_softc *, const u32 *, u32, + u32); static void bce_load_cpu_fw (struct bce_softc *, struct cpu_reg *, struct fw_info *); static void bce_start_cpu (struct bce_softc *, struct cpu_reg *); @@ -400,14 +401,12 @@ static int bce_blockinit (struct bce_softc *); static int bce_init_tx_chain (struct bce_softc *); static void bce_free_tx_chain (struct bce_softc *); -static int bce_get_rx_buf (struct bce_softc *, - struct mbuf *, u16 *, u16 *, u32 *); +static int bce_get_rx_buf (struct bce_softc *, u16, u16, u32 *); static int bce_init_rx_chain (struct bce_softc *); static void bce_fill_rx_chain (struct bce_softc *); static void bce_free_rx_chain (struct bce_softc *); -static int bce_get_pg_buf (struct bce_softc *, - struct mbuf *, u16 *, u16 *); +static int bce_get_pg_buf (struct bce_softc *, u16, u16); static int bce_init_pg_chain (struct bce_softc *); static void bce_fill_pg_chain (struct bce_softc *); static void bce_free_pg_chain (struct bce_softc *); @@ -490,7 +489,7 @@ DRIVER_MODULE(miibus, bce, miibus_driver, miibus_devclass, NULL, NULL); /****************************************************************************/ /* Tunable device values */ /****************************************************************************/ -SYSCTL_NODE(_hw, OID_AUTO, bce, CTLFLAG_RD, 0, "bce driver parameters"); +static SYSCTL_NODE(_hw, OID_AUTO, bce, CTLFLAG_RD, 0, "bce driver parameters"); /* Allowable values are TRUE or FALSE */ static int bce_verbose = TRUE; @@ -501,14 +500,14 @@ SYSCTL_INT(_hw_bce, OID_AUTO, verbose, CTLFLAG_RDTUN, &bce_verbose, 0, /* Allowable values are TRUE or FALSE */ static int bce_tso_enable = TRUE; TUNABLE_INT("hw.bce.tso_enable", &bce_tso_enable); -SYSCTL_UINT(_hw_bce, OID_AUTO, tso_enable, CTLFLAG_RDTUN, &bce_tso_enable, 0, +SYSCTL_INT(_hw_bce, OID_AUTO, tso_enable, CTLFLAG_RDTUN, &bce_tso_enable, 0, "TSO Enable/Disable"); /* Allowable values are 0 (IRQ), 1 (MSI/IRQ), and 2 (MSI-X/MSI/IRQ) */ /* ToDo: Add MSI-X support. */ static int bce_msi_enable = 1; TUNABLE_INT("hw.bce.msi_enable", &bce_msi_enable); -SYSCTL_UINT(_hw_bce, OID_AUTO, msi_enable, CTLFLAG_RDTUN, &bce_msi_enable, 0, +SYSCTL_INT(_hw_bce, OID_AUTO, msi_enable, CTLFLAG_RDTUN, &bce_msi_enable, 0, "MSI-X|MSI|INTx selector"); /* Allowable values are 1, 2, 4, 8. */ @@ -808,13 +807,13 @@ bce_probe_pci_caps(device_t dev, struct bce_softc *sc) DBENTER(BCE_VERBOSE_LOAD); /* Check if PCI-X capability is enabled. */ - if (pci_find_extcap(dev, PCIY_PCIX, ®) == 0) { + if (pci_find_cap(dev, PCIY_PCIX, ®) == 0) { if (reg != 0) sc->bce_cap_flags |= BCE_PCIX_CAPABLE_FLAG; } /* Check if PCIe capability is enabled. */ - if (pci_find_extcap(dev, PCIY_EXPRESS, ®) == 0) { + if (pci_find_cap(dev, PCIY_EXPRESS, ®) == 0) { if (reg != 0) { u16 link_status = pci_read_config(dev, reg + 0x12, 2); DBPRINT(sc, BCE_INFO_LOAD, "PCIe link_status = " @@ -827,13 +826,13 @@ bce_probe_pci_caps(device_t dev, struct bce_softc *sc) } /* Check if MSI capability is enabled. */ - if (pci_find_extcap(dev, PCIY_MSI, ®) == 0) { + if (pci_find_cap(dev, PCIY_MSI, ®) == 0) { if (reg != 0) sc->bce_cap_flags |= BCE_MSI_CAPABLE_FLAG; } /* Check if MSI-X capability is enabled. */ - if (pci_find_extcap(dev, PCIY_MSIX, ®) == 0) { + if (pci_find_cap(dev, PCIY_MSIX, ®) == 0) { if (reg != 0) sc->bce_cap_flags |= BCE_MSIX_CAPABLE_FLAG; } @@ -1021,7 +1020,6 @@ bce_set_tunables(struct bce_softc *sc) sc->bce_tx_ticks = DEFAULT_TX_TICKS; sc->bce_tx_quick_cons_trip = DEFAULT_TX_QUICK_CONS_TRIP; } - } @@ -1334,23 +1332,6 @@ bce_attach(device_t dev) /* Fetch the permanent Ethernet MAC address. */ bce_get_mac_addr(sc); - /* - * Trip points control how many BDs - * should be ready before generating an - * interrupt while ticks control how long - * a BD can sit in the chain before - * generating an interrupt. Set the default - * values for the RX and TX chains. - */ - - /* Not used for L2. */ - sc->bce_comp_prod_trip_int = 0; - sc->bce_comp_prod_trip = 0; - sc->bce_com_ticks_int = 0; - sc->bce_com_ticks = 0; - sc->bce_cmd_ticks_int = 0; - sc->bce_cmd_ticks = 0; - /* Update statistics once every second. */ sc->bce_stats_ticks = 1000000 & 0xffff00; @@ -1465,7 +1446,7 @@ bce_attach(device_t dev) /* MII child bus by attaching the PHY. */ rc = mii_attach(dev, &sc->bce_miibus, ifp, bce_ifmedia_upd, bce_ifmedia_sts, BMSR_DEFCAPMASK, sc->bce_phy_addr, - MII_OFFSET_ANY, MIIF_DOPAUSE | MIIF_FORCEPAUSE); + MII_OFFSET_ANY, MIIF_DOPAUSE); if (rc != 0) { BCE_PRINTF("%s(%d): attaching PHYs failed\n", __FILE__, __LINE__); @@ -1937,7 +1918,6 @@ bce_miibus_read_reg(device_t dev, int phy, int reg) DB_PRINT_PHY_REG(reg, val); return (val & 0xffff); - } @@ -2099,10 +2079,12 @@ bce_miibus_statchg(device_t dev) DBPRINT(sc, BCE_INFO_PHY, "%s(): Enabling RX flow control.\n", __FUNCTION__); BCE_SETBIT(sc, BCE_EMAC_RX_MODE, BCE_EMAC_RX_MODE_FLOW_EN); + sc->bce_flags |= BCE_USING_RX_FLOW_CONTROL; } else { DBPRINT(sc, BCE_INFO_PHY, "%s(): Disabling RX flow control.\n", __FUNCTION__); BCE_CLRBIT(sc, BCE_EMAC_RX_MODE, BCE_EMAC_RX_MODE_FLOW_EN); + sc->bce_flags &= ~BCE_USING_RX_FLOW_CONTROL; } if ((IFM_OPTIONS(media_active) & IFM_ETH_TXPAUSE) != 0) { @@ -3039,7 +3021,6 @@ bce_get_rx_buffer_sizes(struct bce_softc *sc, int mtu) roundup2((MSIZE - MHLEN), 16) - (MSIZE - MHLEN); sc->rx_bd_mbuf_data_len = sc->rx_bd_mbuf_alloc_size - sc->rx_bd_mbuf_align_pad; - sc->pg_bd_mbuf_alloc_size = MCLBYTES; } else { if ((mtu + ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN + ETHER_CRC_LEN) > MCLBYTES) { @@ -3069,7 +3050,6 @@ bce_get_rx_buffer_sizes(struct bce_softc *sc, int mtu) sc->rx_bd_mbuf_align_pad); DBEXIT(BCE_VERBOSE_LOAD); - } /****************************************************************************/ @@ -3486,8 +3466,6 @@ bce_dma_map_addr(void *arg, bus_dma_segment_t *segs, int nseg, int error) } else { *busaddr = segs->ds_addr; } - - return; } @@ -3568,7 +3546,7 @@ bce_dma_alloc(device_t dev) sc->status_block, BCE_STATUS_BLK_SZ, bce_dma_map_addr, &sc->status_block_paddr, BUS_DMA_NOWAIT); - if (error) { + if (error || sc->status_block_paddr == 0) { BCE_PRINTF("%s(%d): Could not map status block " "DMA memory!\n", __FILE__, __LINE__); rc = ENOMEM; @@ -3605,7 +3583,7 @@ bce_dma_alloc(device_t dev) sc->stats_block, BCE_STATS_BLK_SZ, bce_dma_map_addr, &sc->stats_block_paddr, BUS_DMA_NOWAIT); - if(error) { + if (error || sc->stats_block_paddr == 0) { BCE_PRINTF("%s(%d): Could not map statistics block " "DMA memory!\n", __FILE__, __LINE__); rc = ENOMEM; @@ -3657,7 +3635,7 @@ bce_dma_alloc(device_t dev) sc->ctx_block[i], BCM_PAGE_SIZE, bce_dma_map_addr, &sc->ctx_paddr[i], BUS_DMA_NOWAIT); - if (error) { + if (error || sc->ctx_paddr[i] == 0) { BCE_PRINTF("%s(%d): Could not map CTX " "DMA memory!\n", __FILE__, __LINE__); rc = ENOMEM; @@ -3702,7 +3680,7 @@ bce_dma_alloc(device_t dev) BCE_TX_CHAIN_PAGE_SZ, bce_dma_map_addr, &sc->tx_bd_chain_paddr[i], BUS_DMA_NOWAIT); - if (error) { + if (error || sc->tx_bd_chain_paddr[i] == 0) { BCE_PRINTF("%s(%d): Could not map TX descriptor " "chain DMA memory!\n", __FILE__, __LINE__); rc = ENOMEM; @@ -3779,7 +3757,7 @@ bce_dma_alloc(device_t dev) BCE_RX_CHAIN_PAGE_SZ, bce_dma_map_addr, &sc->rx_bd_chain_paddr[i], BUS_DMA_NOWAIT); - if (error) { + if (error || sc->rx_bd_chain_paddr[i] == 0) { BCE_PRINTF("%s(%d): Could not map RX descriptor " "chain DMA memory!\n", __FILE__, __LINE__); rc = ENOMEM; @@ -3795,21 +3773,17 @@ bce_dma_alloc(device_t dev) * Create a DMA tag for RX mbufs. */ if (bce_hdr_split == TRUE) - max_size = max_seg_size = ((sc->rx_bd_mbuf_alloc_size < MCLBYTES) ? + max_size = ((sc->rx_bd_mbuf_alloc_size < MCLBYTES) ? MCLBYTES : sc->rx_bd_mbuf_alloc_size); else - max_size = max_seg_size = MJUM9BYTES; - max_segments = 1; + max_size = MJUM9BYTES; DBPRINT(sc, BCE_INFO_LOAD, "%s(): Creating rx_mbuf_tag " - "(max size = 0x%jX max segments = %d, max segment " - "size = 0x%jX)\n", __FUNCTION__, (uintmax_t) max_size, - max_segments, (uintmax_t) max_seg_size); + "(max size = 0x%jX)\n", __FUNCTION__, (uintmax_t)max_size); if (bus_dma_tag_create(sc->parent_tag, BCE_RX_BUF_ALIGN, BCE_DMA_BOUNDARY, sc->max_bus_addr, BUS_SPACE_MAXADDR, NULL, NULL, - max_size, max_segments, max_seg_size, 0, NULL, NULL, - &sc->rx_mbuf_tag)) { + max_size, 1, max_size, 0, NULL, NULL, &sc->rx_mbuf_tag)) { BCE_PRINTF("%s(%d): Could not allocate RX mbuf DMA tag!\n", __FILE__, __LINE__); rc = ENOMEM; @@ -3860,7 +3834,7 @@ bce_dma_alloc(device_t dev) BCE_PG_CHAIN_PAGE_SZ, bce_dma_map_addr, &sc->pg_bd_chain_paddr[i], BUS_DMA_NOWAIT); - if (error) { + if (error || sc->pg_bd_chain_paddr[i] == 0) { BCE_PRINTF("%s(%d): Could not map page descriptor " "chain DMA memory!\n", __FILE__, __LINE__); rc = ENOMEM; @@ -3875,12 +3849,9 @@ bce_dma_alloc(device_t dev) /* * Create a DMA tag for page mbufs. */ - max_size = max_seg_size = ((sc->pg_bd_mbuf_alloc_size < MCLBYTES) ? - MCLBYTES : sc->pg_bd_mbuf_alloc_size); - if (bus_dma_tag_create(sc->parent_tag, 1, BCE_DMA_BOUNDARY, - sc->max_bus_addr, BUS_SPACE_MAXADDR, NULL, NULL, - max_size, 1, max_seg_size, 0, NULL, NULL, &sc->pg_mbuf_tag)) { + sc->max_bus_addr, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES, + 1, MCLBYTES, 0, NULL, NULL, &sc->pg_mbuf_tag)) { BCE_PRINTF("%s(%d): Could not allocate page mbuf " "DMA tag!\n", __FILE__, __LINE__); rc = ENOMEM; @@ -4030,7 +4001,7 @@ bce_fw_sync_exit: /* Nothing. */ /****************************************************************************/ static void -bce_load_rv2p_fw(struct bce_softc *sc, u32 *rv2p_code, +bce_load_rv2p_fw(struct bce_softc *sc, const u32 *rv2p_code, u32 rv2p_code_len, u32 rv2p_proc) { int i; @@ -5246,24 +5217,28 @@ bce_blockinit(struct bce_softc *sc) REG_WR(sc, BCE_HC_STATISTICS_ADDR_H, BCE_ADDR_HI(sc->stats_block_paddr)); - /* Program various host coalescing parameters. */ + /* + * Program various host coalescing parameters. + * Trip points control how many BDs should be ready before generating + * an interrupt while ticks control how long a BD can sit in the chain + * before generating an interrupt. + */ REG_WR(sc, BCE_HC_TX_QUICK_CONS_TRIP, - (sc->bce_tx_quick_cons_trip_int << 16) | sc->bce_tx_quick_cons_trip); + (sc->bce_tx_quick_cons_trip_int << 16) | + sc->bce_tx_quick_cons_trip); REG_WR(sc, BCE_HC_RX_QUICK_CONS_TRIP, - (sc->bce_rx_quick_cons_trip_int << 16) | sc->bce_rx_quick_cons_trip); - REG_WR(sc, BCE_HC_COMP_PROD_TRIP, - (sc->bce_comp_prod_trip_int << 16) | sc->bce_comp_prod_trip); + (sc->bce_rx_quick_cons_trip_int << 16) | + sc->bce_rx_quick_cons_trip); REG_WR(sc, BCE_HC_TX_TICKS, (sc->bce_tx_ticks_int << 16) | sc->bce_tx_ticks); REG_WR(sc, BCE_HC_RX_TICKS, (sc->bce_rx_ticks_int << 16) | sc->bce_rx_ticks); - REG_WR(sc, BCE_HC_COM_TICKS, - (sc->bce_com_ticks_int << 16) | sc->bce_com_ticks); - REG_WR(sc, BCE_HC_CMD_TICKS, - (sc->bce_cmd_ticks_int << 16) | sc->bce_cmd_ticks); - REG_WR(sc, BCE_HC_STATS_TICKS, - (sc->bce_stats_ticks & 0xffff00)); + REG_WR(sc, BCE_HC_STATS_TICKS, sc->bce_stats_ticks & 0xffff00); REG_WR(sc, BCE_HC_STAT_COLLECT_TICKS, 0xbb8); /* 3ms */ + /* Not used for L2. */ + REG_WR(sc, BCE_HC_COMP_PROD_TRIP, 0); + REG_WR(sc, BCE_HC_COM_TICKS, 0); + REG_WR(sc, BCE_HC_CMD_TICKS, 0); /* Configure the Host Coalescing block. */ val = BCE_HC_CONFIG_RX_TMR_MODE | BCE_HC_CONFIG_TX_TMR_MODE | @@ -5378,29 +5353,27 @@ bce_blockinit_exit: /* 0 for success, positive value for failure. */ /****************************************************************************/ static int -bce_get_rx_buf(struct bce_softc *sc, struct mbuf *m, u16 *prod, - u16 *chain_prod, u32 *prod_bseq) +bce_get_rx_buf(struct bce_softc *sc, u16 prod, u16 chain_prod, u32 *prod_bseq) { - bus_dmamap_t map; - bus_dma_segment_t segs[BCE_MAX_SEGMENTS]; + bus_dma_segment_t segs[1]; struct mbuf *m_new = NULL; struct rx_bd *rxbd; int nsegs, error, rc = 0; #ifdef BCE_DEBUG - u16 debug_chain_prod = *chain_prod; + u16 debug_chain_prod = chain_prod; #endif DBENTER(BCE_EXTREME_RESET | BCE_EXTREME_RECV | BCE_EXTREME_LOAD); /* Make sure the inputs are valid. */ - DBRUNIF((*chain_prod > MAX_RX_BD_ALLOC), + DBRUNIF((chain_prod > MAX_RX_BD_ALLOC), BCE_PRINTF("%s(%d): RX producer out of range: " "0x%04X > 0x%04X\n", __FILE__, __LINE__, - *chain_prod, (u16) MAX_RX_BD_ALLOC)); + chain_prod, (u16)MAX_RX_BD_ALLOC)); DBPRINT(sc, BCE_EXTREME_RECV, "%s(enter): prod = 0x%04X, " "chain_prod = 0x%04X, prod_bseq = 0x%08X\n", __FUNCTION__, - *prod, *chain_prod, *prod_bseq); + prod, chain_prod, *prod_bseq); /* Update some debug statistic counters */ DBRUNIF((sc->free_rx_bd < sc->rx_low_watermark), @@ -5408,35 +5381,28 @@ bce_get_rx_buf(struct bce_softc *sc, struct mbuf *m, u16 *prod, DBRUNIF((sc->free_rx_bd == sc->max_rx_bd), sc->rx_empty_count++); - /* Check whether this is a new mbuf allocation. */ - if (m == NULL) { - - /* Simulate an mbuf allocation failure. */ - DBRUNIF(DB_RANDOMTRUE(mbuf_alloc_failed_sim_control), - sc->mbuf_alloc_failed_count++; - sc->mbuf_alloc_failed_sim_count++; - rc = ENOBUFS; - goto bce_get_rx_buf_exit); + /* Simulate an mbuf allocation failure. */ + DBRUNIF(DB_RANDOMTRUE(mbuf_alloc_failed_sim_control), + sc->mbuf_alloc_failed_count++; + sc->mbuf_alloc_failed_sim_count++; + rc = ENOBUFS; + goto bce_get_rx_buf_exit); - /* This is a new mbuf allocation. */ - if (bce_hdr_split == TRUE) - MGETHDR(m_new, M_DONTWAIT, MT_DATA); - else - m_new = m_getjcl(M_DONTWAIT, MT_DATA, M_PKTHDR, - sc->rx_bd_mbuf_alloc_size); - - if (m_new == NULL) { - sc->mbuf_alloc_failed_count++; - rc = ENOBUFS; - goto bce_get_rx_buf_exit; - } + /* This is a new mbuf allocation. */ + if (bce_hdr_split == TRUE) + MGETHDR(m_new, M_NOWAIT, MT_DATA); + else + m_new = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, + sc->rx_bd_mbuf_alloc_size); - DBRUN(sc->debug_rx_mbuf_alloc++); - } else { - /* Reuse an existing mbuf. */ - m_new = m; + if (m_new == NULL) { + sc->mbuf_alloc_failed_count++; + rc = ENOBUFS; + goto bce_get_rx_buf_exit; } + DBRUN(sc->debug_rx_mbuf_alloc++); + /* Make sure we have a valid packet header. */ M_ASSERTPKTHDR(m_new); @@ -5447,9 +5413,8 @@ bce_get_rx_buf(struct bce_softc *sc, struct mbuf *m, u16 *prod, /* ToDo: Consider calling m_fragment() to test error handling. */ /* Map the mbuf cluster into device memory. */ - map = sc->rx_mbuf_map[*chain_prod]; - error = bus_dmamap_load_mbuf_sg(sc->rx_mbuf_tag, map, m_new, - segs, &nsegs, BUS_DMA_NOWAIT); + error = bus_dmamap_load_mbuf_sg(sc->rx_mbuf_tag, + sc->rx_mbuf_map[chain_prod], m_new, segs, &nsegs, BUS_DMA_NOWAIT); /* Handle any mapping errors. */ if (error) { @@ -5470,7 +5435,7 @@ bce_get_rx_buf(struct bce_softc *sc, struct mbuf *m, u16 *prod, __FUNCTION__, nsegs)); /* Setup the rx_bd for the segment. */ - rxbd = &sc->rx_bd_chain[RX_PAGE(*chain_prod)][RX_IDX(*chain_prod)]; + rxbd = &sc->rx_bd_chain[RX_PAGE(chain_prod)][RX_IDX(chain_prod)]; rxbd->rx_bd_haddr_lo = htole32(BCE_ADDR_LO(segs[0].ds_addr)); rxbd->rx_bd_haddr_hi = htole32(BCE_ADDR_HI(segs[0].ds_addr)); @@ -5479,15 +5444,15 @@ bce_get_rx_buf(struct bce_softc *sc, struct mbuf *m, u16 *prod, *prod_bseq += segs[0].ds_len; /* Save the mbuf and update our counter. */ - sc->rx_mbuf_ptr[*chain_prod] = m_new; + sc->rx_mbuf_ptr[chain_prod] = m_new; sc->free_rx_bd -= nsegs; DBRUNMSG(BCE_INSANE_RECV, bce_dump_rx_mbuf_chain(sc, debug_chain_prod, nsegs)); DBPRINT(sc, BCE_EXTREME_RECV, "%s(exit): prod = 0x%04X, " - "chain_prod = 0x%04X, prod_bseq = 0x%08X\n", - __FUNCTION__, *prod, *chain_prod, *prod_bseq); + "chain_prod = 0x%04X, prod_bseq = 0x%08X\n", __FUNCTION__, prod, + chain_prod, *prod_bseq); bce_get_rx_buf_exit: DBEXIT(BCE_EXTREME_RESET | BCE_EXTREME_RECV | BCE_EXTREME_LOAD); @@ -5503,68 +5468,56 @@ bce_get_rx_buf_exit: /* 0 for success, positive value for failure. */ /****************************************************************************/ static int -bce_get_pg_buf(struct bce_softc *sc, struct mbuf *m, u16 *prod, - u16 *prod_idx) +bce_get_pg_buf(struct bce_softc *sc, u16 prod, u16 prod_idx) { - bus_dmamap_t map; - bus_addr_t busaddr; + bus_dma_segment_t segs[1]; struct mbuf *m_new = NULL; struct rx_bd *pgbd; - int error, rc = 0; + int error, nsegs, rc = 0; #ifdef BCE_DEBUG - u16 debug_prod_idx = *prod_idx; + u16 debug_prod_idx = prod_idx; #endif DBENTER(BCE_EXTREME_RESET | BCE_EXTREME_RECV | BCE_EXTREME_LOAD); /* Make sure the inputs are valid. */ - DBRUNIF((*prod_idx > MAX_PG_BD_ALLOC), + DBRUNIF((prod_idx > MAX_PG_BD_ALLOC), BCE_PRINTF("%s(%d): page producer out of range: " "0x%04X > 0x%04X\n", __FILE__, __LINE__, - *prod_idx, (u16) MAX_PG_BD_ALLOC)); + prod_idx, (u16)MAX_PG_BD_ALLOC)); DBPRINT(sc, BCE_EXTREME_RECV, "%s(enter): prod = 0x%04X, " - "chain_prod = 0x%04X\n", __FUNCTION__, *prod, *prod_idx); + "chain_prod = 0x%04X\n", __FUNCTION__, prod, prod_idx); /* Update counters if we've hit a new low or run out of pages. */ DBRUNIF((sc->free_pg_bd < sc->pg_low_watermark), sc->pg_low_watermark = sc->free_pg_bd); DBRUNIF((sc->free_pg_bd == sc->max_pg_bd), sc->pg_empty_count++); - /* Check whether this is a new mbuf allocation. */ - if (m == NULL) { - - /* Simulate an mbuf allocation failure. */ - DBRUNIF(DB_RANDOMTRUE(mbuf_alloc_failed_sim_control), - sc->mbuf_alloc_failed_count++; - sc->mbuf_alloc_failed_sim_count++; - rc = ENOBUFS; - goto bce_get_pg_buf_exit); - - /* This is a new mbuf allocation. */ - m_new = m_getcl(M_DONTWAIT, MT_DATA, 0); - if (m_new == NULL) { - sc->mbuf_alloc_failed_count++; - rc = ENOBUFS; - goto bce_get_pg_buf_exit; - } - - DBRUN(sc->debug_pg_mbuf_alloc++); - } else { - /* Reuse an existing mbuf. */ - m_new = m; - m_new->m_data = m_new->m_ext.ext_buf; + /* Simulate an mbuf allocation failure. */ + DBRUNIF(DB_RANDOMTRUE(mbuf_alloc_failed_sim_control), + sc->mbuf_alloc_failed_count++; + sc->mbuf_alloc_failed_sim_count++; + rc = ENOBUFS; + goto bce_get_pg_buf_exit); + + /* This is a new mbuf allocation. */ + m_new = m_getcl(M_NOWAIT, MT_DATA, 0); + if (m_new == NULL) { + sc->mbuf_alloc_failed_count++; + rc = ENOBUFS; + goto bce_get_pg_buf_exit; } - m_new->m_len = sc->pg_bd_mbuf_alloc_size; + DBRUN(sc->debug_pg_mbuf_alloc++); + + m_new->m_len = MCLBYTES; /* ToDo: Consider calling m_fragment() to test error handling. */ /* Map the mbuf cluster into device memory. */ - map = sc->pg_mbuf_map[*prod_idx]; - error = bus_dmamap_load(sc->pg_mbuf_tag, map, mtod(m_new, void *), - sc->pg_bd_mbuf_alloc_size, bce_dma_map_addr, - &busaddr, BUS_DMA_NOWAIT); + error = bus_dmamap_load_mbuf_sg(sc->pg_mbuf_tag, + sc->pg_mbuf_map[prod_idx], m_new, segs, &nsegs, BUS_DMA_NOWAIT); /* Handle any mapping errors. */ if (error) { @@ -5578,28 +5531,32 @@ bce_get_pg_buf(struct bce_softc *sc, struct mbuf *m, u16 *prod, goto bce_get_pg_buf_exit; } + /* All mbufs must map to a single segment. */ + KASSERT(nsegs == 1, ("%s(): Too many segments returned (%d)!", + __FUNCTION__, nsegs)); + /* ToDo: Do we need bus_dmamap_sync(,,BUS_DMASYNC_PREREAD) here? */ /* * The page chain uses the same rx_bd data structure * as the receive chain but doesn't require a byte sequence (bseq). */ - pgbd = &sc->pg_bd_chain[PG_PAGE(*prod_idx)][PG_IDX(*prod_idx)]; + pgbd = &sc->pg_bd_chain[PG_PAGE(prod_idx)][PG_IDX(prod_idx)]; - pgbd->rx_bd_haddr_lo = htole32(BCE_ADDR_LO(busaddr)); - pgbd->rx_bd_haddr_hi = htole32(BCE_ADDR_HI(busaddr)); - pgbd->rx_bd_len = htole32(sc->pg_bd_mbuf_alloc_size); + pgbd->rx_bd_haddr_lo = htole32(BCE_ADDR_LO(segs[0].ds_addr)); + pgbd->rx_bd_haddr_hi = htole32(BCE_ADDR_HI(segs[0].ds_addr)); + pgbd->rx_bd_len = htole32(MCLBYTES); pgbd->rx_bd_flags = htole32(RX_BD_FLAGS_START | RX_BD_FLAGS_END); /* Save the mbuf and update our counter. */ - sc->pg_mbuf_ptr[*prod_idx] = m_new; + sc->pg_mbuf_ptr[prod_idx] = m_new; sc->free_pg_bd--; DBRUNMSG(BCE_INSANE_RECV, bce_dump_pg_mbuf_chain(sc, debug_prod_idx, 1)); DBPRINT(sc, BCE_EXTREME_RECV, "%s(exit): prod = 0x%04X, " - "prod_idx = 0x%04X\n", __FUNCTION__, *prod, *prod_idx); + "prod_idx = 0x%04X\n", __FUNCTION__, prod, prod_idx); bce_get_pg_buf_exit: DBEXIT(BCE_EXTREME_RESET | BCE_EXTREME_RECV | BCE_EXTREME_LOAD); @@ -5921,7 +5878,7 @@ bce_fill_rx_chain(struct bce_softc *sc) /* Keep filling the RX chain until it's full. */ while (sc->free_rx_bd > 0) { prod_idx = RX_CHAIN_IDX(prod); - if (bce_get_rx_buf(sc, NULL, &prod, &prod_idx, &prod_bseq)) { + if (bce_get_rx_buf(sc, prod, prod_idx, &prod_bseq)) { /* Bail out if we can't add an mbuf to the chain. */ break; } @@ -5935,13 +5892,11 @@ bce_fill_rx_chain(struct bce_softc *sc) /* We should never end up pointing to a next page pointer. */ DBRUNIF(((prod & USABLE_RX_BD_PER_PAGE) == USABLE_RX_BD_PER_PAGE), BCE_PRINTF("%s(): Invalid rx_prod value: 0x%04X\n", - __FUNCTION__, sc->rx_prod)); + __FUNCTION__, rx_prod)); /* Write the mailbox and tell the chip about the waiting rx_bd's. */ - REG_WR16(sc, MB_GET_CID_ADDR(RX_CID) + - BCE_L2MQ_RX_HOST_BDIDX, sc->rx_prod); - REG_WR(sc, MB_GET_CID_ADDR(RX_CID) + - BCE_L2MQ_RX_HOST_BSEQ, sc->rx_prod_bseq); + REG_WR16(sc, MB_GET_CID_ADDR(RX_CID) + BCE_L2MQ_RX_HOST_BDIDX, prod); + REG_WR(sc, MB_GET_CID_ADDR(RX_CID) + BCE_L2MQ_RX_HOST_BSEQ, prod_bseq); DBEXIT(BCE_VERBOSE_RESET | BCE_EXTREME_RECV | BCE_VERBOSE_LOAD | BCE_VERBOSE_CTX); @@ -5976,10 +5931,9 @@ bce_free_rx_chain(struct bce_softc *sc) /* Clear each RX chain page. */ for (i = 0; i < sc->rx_pages; i++) - if (sc->rx_bd_chain[i] != NULL) { + if (sc->rx_bd_chain[i] != NULL) bzero((char *)sc->rx_bd_chain[i], BCE_RX_CHAIN_PAGE_SZ); - } sc->free_rx_bd = sc->max_rx_bd; @@ -6043,7 +5997,7 @@ bce_init_pg_chain(struct bce_softc *sc) CTX_WR(sc, GET_CID_ADDR(RX_CID), BCE_L2CTX_RX_PG_BUF_SIZE, 0); /* Configure the rx_bd and page chain mbuf cluster size. */ - val = (sc->rx_bd_mbuf_data_len << 16) | sc->pg_bd_mbuf_alloc_size; + val = (sc->rx_bd_mbuf_data_len << 16) | MCLBYTES; CTX_WR(sc, GET_CID_ADDR(RX_CID), BCE_L2CTX_RX_PG_BUF_SIZE, val); /* Configure the context reserved for jumbo support. */ @@ -6093,7 +6047,7 @@ bce_fill_pg_chain(struct bce_softc *sc) /* Keep filling the page chain until it's full. */ while (sc->free_pg_bd > 0) { prod_idx = PG_CHAIN_IDX(prod); - if (bce_get_pg_buf(sc, NULL, &prod, &prod_idx)) { + if (bce_get_pg_buf(sc, prod, prod_idx)) { /* Bail out if we can't add an mbuf to the chain. */ break; } @@ -6105,14 +6059,14 @@ bce_fill_pg_chain(struct bce_softc *sc) DBRUNIF(((prod & USABLE_RX_BD_PER_PAGE) == USABLE_RX_BD_PER_PAGE), BCE_PRINTF("%s(): Invalid pg_prod value: 0x%04X\n", - __FUNCTION__, sc->pg_prod)); + __FUNCTION__, pg_prod)); /* * Write the mailbox and tell the chip about * the new rx_bd's in the page chain. */ - REG_WR16(sc, MB_GET_CID_ADDR(RX_CID) + - BCE_L2MQ_RX_HOST_PG_BDIDX, sc->pg_prod); + REG_WR16(sc, MB_GET_CID_ADDR(RX_CID) + BCE_L2MQ_RX_HOST_PG_BDIDX, + prod); DBEXIT(BCE_VERBOSE_RESET | BCE_EXTREME_RECV | BCE_VERBOSE_LOAD | BCE_VERBOSE_CTX); @@ -6345,7 +6299,7 @@ bce_ifmedia_upd_locked(struct ifnet *ifp) /* Make sure the MII bus has been enumerated. */ if (mii) { LIST_FOREACH(miisc, &mii->mii_phys, mii_list) - mii_phy_reset(miisc); + PHY_RESET(miisc); error = mii_mediachg(mii); } } @@ -6627,14 +6581,6 @@ bce_rx_intr(struct bce_softc *sc) DBRUN(sc->debug_rx_mbuf_alloc--); sc->free_rx_bd++; - if(m0 == NULL) { - DBPRINT(sc, BCE_EXTREME_RECV, - "%s(): Oops! Empty mbuf pointer " - "found in sc->rx_mbuf_ptr[0x%04X]!\n", - __FUNCTION__, sw_rx_cons_idx); - goto bce_rx_int_next_rx; - } - /* * Frames received on the NetXteme II are prepended * with an l2_fhdr structure which provides status @@ -6793,7 +6739,7 @@ bce_rx_intr(struct bce_softc *sc) m_freem(m0); m0 = NULL; - goto bce_rx_int_next_rx; + goto bce_rx_intr_next_rx; } /* Send the packet to the appropriate interface. */ @@ -6804,7 +6750,6 @@ bce_rx_intr(struct bce_softc *sc) /* Validate the checksum if offload enabled. */ if (ifp->if_capenable & IFCAP_RXCSUM) { - /* Check for an IP datagram. */ if (!(status & L2_FHDR_STATUS_SPLIT) && (status & L2_FHDR_STATUS_IP_DATAGRAM)) { @@ -6834,7 +6779,8 @@ bce_rx_intr(struct bce_softc *sc) } /* Attach the VLAN tag. */ - if (status & L2_FHDR_STATUS_L2_VLAN_TAG) { + if ((status & L2_FHDR_STATUS_L2_VLAN_TAG) && + !(sc->rx_mode & BCE_EMAC_RX_MODE_KEEP_VLAN_TAG)) { DBRUN(sc->vlan_tagged_frames_rcvd++); if (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) { DBRUN(sc->vlan_tagged_frames_stripped++); @@ -6873,7 +6819,7 @@ bce_rx_intr(struct bce_softc *sc) /* Increment received packet statistics. */ ifp->if_ipackets++; -bce_rx_int_next_rx: +bce_rx_intr_next_rx: sw_rx_cons = NEXT_RX_BD(sw_rx_cons); /* If we have a packet, pass it up the stack */ @@ -7165,10 +7111,9 @@ bce_init_locked(struct bce_softc *sc) ether_mtu = ifp->if_mtu; else { if (bce_hdr_split == TRUE) { - if (ifp->if_mtu <= (sc->rx_bd_mbuf_data_len + - sc->pg_bd_mbuf_alloc_size)) - ether_mtu = sc->rx_bd_mbuf_data_len + - sc->pg_bd_mbuf_alloc_size; + if (ifp->if_mtu <= sc->rx_bd_mbuf_data_len + MCLBYTES) + ether_mtu = sc->rx_bd_mbuf_data_len + + MCLBYTES; else ether_mtu = ifp->if_mtu; } else { @@ -7196,9 +7141,6 @@ bce_init_locked(struct bce_softc *sc) bce_set_rx_mode(sc); if (bce_hdr_split == TRUE) { - DBPRINT(sc, BCE_INFO_LOAD, "%s(): pg_bd_mbuf_alloc_size = %d\n", - __FUNCTION__, sc->pg_bd_mbuf_alloc_size); - /* Init page buffer descriptor chain. */ bce_init_pg_chain(sc); } @@ -7303,7 +7245,7 @@ bce_tso_setup(struct bce_softc *sc, struct mbuf **m_head, u16 *flags) /* Controller may modify mbuf chains. */ if (M_WRITABLE(*m_head) == 0) { - m = m_dup(*m_head, M_DONTWAIT); + m = m_dup(*m_head, M_NOWAIT); m_freem(*m_head); if (m == NULL) { sc->mbuf_alloc_failed_count++; @@ -7469,7 +7411,7 @@ bce_tx_encap(struct bce_softc *sc, struct mbuf **m_head) sc->mbuf_frag_count++; /* Try to defrag the mbuf. */ - m0 = m_collapse(*m_head, M_DONTWAIT, BCE_MAX_SEGMENTS); + m0 = m_collapse(*m_head, M_NOWAIT, BCE_MAX_SEGMENTS); if (m0 == NULL) { /* Defrag was unsuccessful */ m_freem(*m_head); @@ -7692,7 +7634,6 @@ bce_start_locked(struct ifnet *ifp) bce_start_locked_exit: DBEXIT(BCE_VERBOSE_SEND | BCE_VERBOSE_CTX); - return; } @@ -7891,18 +7832,42 @@ bce_ioctl(struct ifnet *ifp, u_long command, caddr_t data) static void bce_watchdog(struct bce_softc *sc) { + uint32_t status; + DBENTER(BCE_EXTREME_SEND); BCE_LOCK_ASSERT(sc); + status = 0; /* If the watchdog timer hasn't expired then just exit. */ if (sc->watchdog_timer == 0 || --sc->watchdog_timer) goto bce_watchdog_exit; + status = REG_RD(sc, BCE_EMAC_RX_STATUS); /* If pause frames are active then don't reset the hardware. */ - /* ToDo: Should we reset the timer here? */ - if (REG_RD(sc, BCE_EMAC_TX_STATUS) & BCE_EMAC_TX_STATUS_XOFFED) - goto bce_watchdog_exit; + if ((sc->bce_flags & BCE_USING_RX_FLOW_CONTROL) != 0) { + if ((status & BCE_EMAC_RX_STATUS_FFED) != 0) { + /* + * If link partner has us in XOFF state then wait for + * the condition to clear. + */ + sc->watchdog_timer = BCE_TX_TIMEOUT; + goto bce_watchdog_exit; + } else if ((status & BCE_EMAC_RX_STATUS_FF_RECEIVED) != 0 && + (status & BCE_EMAC_RX_STATUS_N_RECEIVED) != 0) { + /* + * If we're not currently XOFF'ed but have recently + * been XOFF'd/XON'd then assume that's delaying TX + * this time around. + */ + sc->watchdog_timer = BCE_TX_TIMEOUT; + goto bce_watchdog_exit; + } + /* + * Any other condition is unexpected and the controller + * should be reset. + */ + } BCE_PRINTF("%s(%d): Watchdog timeout occurred, resetting!\n", __FILE__, __LINE__); @@ -7926,6 +7891,7 @@ bce_watchdog(struct bce_softc *sc) sc->bce_ifp->if_oerrors++; bce_watchdog_exit: + REG_WR(sc, BCE_EMAC_RX_STATUS, status); DBEXIT(BCE_EXTREME_SEND); } @@ -7939,7 +7905,7 @@ bce_watchdog_exit: /* interrupt causes (PHY, TX, RX). */ /* */ /* Returns: */ -/* 0 for success, positive value for failure. */ +/* Nothing. */ /****************************************************************************/ static void bce_intr(void *xsc) @@ -7961,16 +7927,16 @@ bce_intr(void *xsc) DBRUN(sc->interrupts_generated++); /* Synchnorize before we read from interface's status block */ - bus_dmamap_sync(sc->status_tag, sc->status_map, - BUS_DMASYNC_POSTREAD); + bus_dmamap_sync(sc->status_tag, sc->status_map, BUS_DMASYNC_POSTREAD); /* - * If the hardware status block index - * matches the last value read by the - * driver and we haven't asserted our - * interrupt then there's nothing to do. + * If the hardware status block index matches the last value read + * by the driver and we haven't asserted our interrupt then there's + * nothing to do. This may only happen in case of INTx due to the + * interrupt arriving at the CPU before the status block is updated. */ - if ((sc->status_block->status_idx == sc->last_status_idx) && + if ((sc->bce_flags & (BCE_USING_MSI_FLAG | BCE_USING_MSIX_FLAG)) == 0 && + sc->status_block->status_idx == sc->last_status_idx && (REG_RD(sc, BCE_PCICFG_MISC_STATUS) & BCE_PCICFG_MISC_STATUS_INTA_VALUE)) { DBPRINT(sc, BCE_VERBOSE_INTR, "%s(): Spurious interrupt.\n", @@ -8058,11 +8024,9 @@ bce_intr(void *xsc) if ((hw_rx_cons == sc->hw_rx_cons) && (hw_tx_cons == sc->hw_tx_cons)) break; - } - bus_dmamap_sync(sc->status_tag, sc->status_map, - BUS_DMASYNC_PREREAD); + bus_dmamap_sync(sc->status_tag, sc->status_map, BUS_DMASYNC_PREREAD); /* Re-enable interrupts. */ bce_enable_intr(sc, 0); @@ -8128,8 +8092,9 @@ bce_set_rx_mode(struct bce_softc *sc) /* Enable all multicast addresses. */ for (i = 0; i < NUM_MC_HASH_REGISTERS; i++) { - REG_WR(sc, BCE_EMAC_MULTICAST_HASH0 + (i * 4), 0xffffffff); - } + REG_WR(sc, BCE_EMAC_MULTICAST_HASH0 + (i * 4), + 0xffffffff); + } sort_mode |= BCE_RPM_SORT_USER0_MC_EN; } else { /* Accept one or more multicast(s). */ @@ -8186,6 +8151,8 @@ bce_stats_update(struct bce_softc *sc) ifp = sc->bce_ifp; + bus_dmamap_sync(sc->stats_tag, sc->stats_map, BUS_DMASYNC_POSTREAD); + stats = (struct statistics_block *) sc->stats_block; /* @@ -8493,11 +8460,7 @@ bce_tick(void *xsc) /* Update the statistics from the hardware statistics block. */ bce_stats_update(sc); - /* - * ToDo: This is a safety measure. Need to re-evaluate - * high level processing logic and eliminate this code. - */ - /* Top off the receive and page chains. */ + /* Ensure page and RX chains get refilled in low-memory situations. */ if (bce_hdr_split == TRUE) bce_fill_pg_chain(sc); bce_fill_rx_chain(sc); @@ -8546,7 +8509,6 @@ bce_tick(void *xsc) bce_tick_exit: DBEXIT(BCE_EXTREME_MISC); - return; } static void @@ -8718,6 +8680,8 @@ bce_sysctl_stats_clear(SYSCTL_HANDLER_ARGS) stats = (struct statistics_block *) sc->stats_block; bzero(stats, sizeof(struct statistics_block)); + bus_dmamap_sync(sc->stats_tag, sc->stats_map, + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); /* Clear the internal H/W statistics counters. */ REG_WR(sc, BCE_HC_COMMAND, BCE_HC_COMMAND_CLR_STAT_NOW); @@ -9162,7 +9126,7 @@ bce_add_sysctls(struct bce_softc *sc) 0, "Number of simulated l2_fhdr errors"); #endif - SYSCTL_ADD_INT(ctx, children, OID_AUTO, + SYSCTL_ADD_UINT(ctx, children, OID_AUTO, "l2fhdr_error_count", CTLFLAG_RD, &sc->l2fhdr_error_count, 0, "Number of l2_fhdr errors"); @@ -9173,18 +9137,18 @@ bce_add_sysctls(struct bce_softc *sc) CTLFLAG_RW, &mbuf_alloc_failed_sim_control, 0, "Debug control to force mbuf allocation failures"); - SYSCTL_ADD_INT(ctx, children, OID_AUTO, + SYSCTL_ADD_UINT(ctx, children, OID_AUTO, "mbuf_alloc_failed_sim_count", CTLFLAG_RD, &sc->mbuf_alloc_failed_sim_count, 0, "Number of simulated mbuf cluster allocation failures"); #endif - SYSCTL_ADD_INT(ctx, children, OID_AUTO, + SYSCTL_ADD_UINT(ctx, children, OID_AUTO, "mbuf_alloc_failed_count", CTLFLAG_RD, &sc->mbuf_alloc_failed_count, 0, "Number of mbuf allocation failures"); - SYSCTL_ADD_INT(ctx, children, OID_AUTO, + SYSCTL_ADD_UINT(ctx, children, OID_AUTO, "mbuf_frag_count", CTLFLAG_RD, &sc->mbuf_frag_count, 0, "Number of fragmented mbufs"); @@ -9196,19 +9160,19 @@ bce_add_sysctls(struct bce_softc *sc) 0, "Debug control to force DMA mapping failures"); /* ToDo: Figure out how to update this value in bce_dma_map_addr(). */ - SYSCTL_ADD_INT(ctx, children, OID_AUTO, + SYSCTL_ADD_UINT(ctx, children, OID_AUTO, "dma_map_addr_failed_sim_count", CTLFLAG_RD, &sc->dma_map_addr_failed_sim_count, 0, "Number of simulated DMA mapping failures"); #endif - SYSCTL_ADD_INT(ctx, children, OID_AUTO, + SYSCTL_ADD_UINT(ctx, children, OID_AUTO, "dma_map_addr_rx_failed_count", CTLFLAG_RD, &sc->dma_map_addr_rx_failed_count, 0, "Number of RX DMA mapping failures"); - SYSCTL_ADD_INT(ctx, children, OID_AUTO, + SYSCTL_ADD_UINT(ctx, children, OID_AUTO, "dma_map_addr_tx_failed_count", CTLFLAG_RD, &sc->dma_map_addr_tx_failed_count, 0, "Number of TX DMA mapping failures"); @@ -9219,13 +9183,13 @@ bce_add_sysctls(struct bce_softc *sc) CTLFLAG_RW, &unexpected_attention_sim_control, 0, "Debug control to simulate unexpected attentions"); - SYSCTL_ADD_INT(ctx, children, OID_AUTO, + SYSCTL_ADD_UINT(ctx, children, OID_AUTO, "unexpected_attention_sim_count", CTLFLAG_RW, &sc->unexpected_attention_sim_count, 0, "Number of simulated unexpected attentions"); #endif - SYSCTL_ADD_INT(ctx, children, OID_AUTO, + SYSCTL_ADD_UINT(ctx, children, OID_AUTO, "unexpected_attention_count", CTLFLAG_RW, &sc->unexpected_attention_count, 0, "Number of unexpected attentions"); @@ -9863,7 +9827,7 @@ bce_dump_mbuf(struct bce_softc *sc, struct mbuf *m) "\15M_FIRSTFRAG\16M_LASTFRAG\21M_VLANTAG" "\22M_PROMISC\23M_NOFREE", mp->m_pkthdr.csum_flags, - "\20\1CSUM_IP\2CSUM_TCP\3CSUM_UDP\4CSUM_IP_FRAGS" + "\20\1CSUM_IP\2CSUM_TCP\3CSUM_UDP" "\5CSUM_FRAGMENT\6CSUM_TSO\11CSUM_IP_CHECKED" "\12CSUM_IP_VALID\13CSUM_DATA_VALID" "\14CSUM_PSEUDO_HDR"); @@ -10703,6 +10667,8 @@ bce_dump_status_block(struct bce_softc *sc) { struct status_block *sblk; + bus_dmamap_sync(sc->status_tag, sc->status_map, BUS_DMASYNC_POSTREAD); + sblk = sc->status_block; BCE_PRINTF( @@ -10765,6 +10731,8 @@ bce_dump_stats_block(struct bce_softc *sc) { struct statistics_block *sblk; + bus_dmamap_sync(sc->stats_tag, sc->stats_map, BUS_DMASYNC_POSTREAD); + sblk = sc->stats_block; BCE_PRINTF( @@ -11629,7 +11597,5 @@ bce_breakpoint(struct bce_softc *sc) /* Call the debugger. */ breakpoint(); - - return; } #endif diff --git a/freebsd/sys/dev/bce/if_bcefw.h b/freebsd/sys/dev/bce/if_bcefw.h index 0b30bb83..8d97b31c 100644 --- a/freebsd/sys/dev/bce/if_bcefw.h +++ b/freebsd/sys/dev/bce/if_bcefw.h @@ -57,7 +57,7 @@ u32 bce_COM_b06FwSbssAddr = 0x08004aa0; int bce_COM_b06FwSbssLen = 0x38; u32 bce_COM_b06FwSDataAddr = 0x00000000; int bce_COM_b06FwSDataLen = 0x0; -u32 bce_COM_b06FwText[(0x4a68/4) + 1] = { +const u32 bce_COM_b06FwText[(0x4a68/4) + 1] = { 0xa000046, 0x0, 0x0, 0xd, 0x636f6d36, 0x2e302e31, 0x35000000, 0x6000f02, 0x0, 0x3, 0xc8, @@ -1249,14 +1249,14 @@ u32 bce_COM_b06FwText[(0x4a68/4) + 1] = { 0x440fffe, 0x24020002, 0xaf5101c0, 0xa34201c4, 0x3c021000, 0xaf4201f8, 0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0020, 0x0 }; -u32 bce_COM_b06FwData[(0x0/4) + 1] = { 0x0 }; -u32 bce_COM_b06FwRodata[(0x14/4) + 1] = { +const u32 bce_COM_b06FwData[(0x0/4) + 1] = { 0x0 }; +const u32 bce_COM_b06FwRodata[(0x14/4) + 1] = { 0x8000acc, 0x8000b14, 0x8000b98, 0x8000be4, 0x8000c20, 0x0 }; -u32 bce_COM_b06FwBss[(0xc4/4) + 1] = { 0x0 }; -u32 bce_COM_b06FwSbss[(0x38/4) + 1] = { 0x0 }; -u32 bce_COM_b06FwSdata[(0x0/4) + 1] = { 0x0 }; +const u32 bce_COM_b06FwBss[(0xc4/4) + 1] = { 0x0 }; +const u32 bce_COM_b06FwSbss[(0x38/4) + 1] = { 0x0 }; +const u32 bce_COM_b06FwSdata[(0x0/4) + 1] = { 0x0 }; int bce_RXP_b06FwReleaseMajor = 0x6; @@ -1275,7 +1275,7 @@ u32 bce_RXP_b06FwSbssAddr = 0x08007320; int bce_RXP_b06FwSbssLen = 0x4c; u32 bce_RXP_b06FwSDataAddr = 0x00000000; int bce_RXP_b06FwSDataLen = 0x0; -u32 bce_RXP_b06FwText[(0x72d0/4) + 1] = { +const u32 bce_RXP_b06FwText[(0x72d0/4) + 1] = { 0xa000c84, 0x0, 0x0, 0xd, 0x72787036, 0x2e302e31, 0x35000000, 0x6000f03, 0x0, 0x1, 0x0, @@ -3114,15 +3114,15 @@ u32 bce_RXP_b06FwText[(0x72d0/4) + 1] = { 0x8fbf0020, 0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x3c021000, 0x27bd0028, 0x3e00008, 0xaf4201b8, 0x0 }; -u32 bce_RXP_b06FwData[(0x0/4) + 1] = { 0x0 }; -u32 bce_RXP_b06FwRodata[(0x24/4) + 1] = { +const u32 bce_RXP_b06FwData[(0x0/4) + 1] = { 0x0 }; +const u32 bce_RXP_b06FwRodata[(0x24/4) + 1] = { 0x8003430, 0x8003430, 0x80033a8, 0x80033e0, 0x8003414, 0x8003438, 0x8003438, 0x8003438, 0x8003318, 0x0 }; -u32 bce_RXP_b06FwBss[(0x440/4) + 1] = { 0x0 }; -u32 bce_RXP_b06FwSbss[(0x4c/4) + 1] = { 0x0 }; -u32 bce_RXP_b06FwSdata[(0x0/4) + 1] = { 0x0 }; +const u32 bce_RXP_b06FwBss[(0x440/4) + 1] = { 0x0 }; +const u32 bce_RXP_b06FwSbss[(0x4c/4) + 1] = { 0x0 }; +const u32 bce_RXP_b06FwSdata[(0x0/4) + 1] = { 0x0 }; int bce_TPAT_b06FwReleaseMajor = 0x6; @@ -3141,7 +3141,7 @@ u32 bce_TPAT_b06FwSbssAddr = 0x08001c00; int bce_TPAT_b06FwSbssLen = 0x44; u32 bce_TPAT_b06FwSDataAddr = 0x00000000; int bce_TPAT_b06FwSDataLen = 0x0; -u32 bce_TPAT_b06FwText[(0x17d4/4) + 1] = { +const u32 bce_TPAT_b06FwText[(0x17d4/4) + 1] = { 0xa000124, 0x0, 0x0, 0xd, 0x74706136, 0x2e302e31, 0x35000000, 0x6000f01, 0x0, 0x0, 0x0, @@ -3524,11 +3524,11 @@ u32 bce_TPAT_b06FwText[(0x17d4/4) + 1] = { 0x14a0fffb, 0x42042, 0xc35021, 0x8fbf0010, 0xa4c02, 0x312200ff, 0x27bd0018, 0xaf8a002c, 0x3e00008, 0xaf890030, 0x0 }; -u32 bce_TPAT_b06FwData[(0x0/4) + 1] = { 0x0 }; -u32 bce_TPAT_b06FwRodata[(0x0/4) + 1] = { 0x0 }; -u32 bce_TPAT_b06FwBss[(0x450/4) + 1] = { 0x0 }; -u32 bce_TPAT_b06FwSbss[(0x44/4) + 1] = { 0x0 }; -u32 bce_TPAT_b06FwSdata[(0x0/4) + 1] = { 0x0 }; +const u32 bce_TPAT_b06FwData[(0x0/4) + 1] = { 0x0 }; +const u32 bce_TPAT_b06FwRodata[(0x0/4) + 1] = { 0x0 }; +const u32 bce_TPAT_b06FwBss[(0x450/4) + 1] = { 0x0 }; +const u32 bce_TPAT_b06FwSbss[(0x44/4) + 1] = { 0x0 }; +const u32 bce_TPAT_b06FwSdata[(0x0/4) + 1] = { 0x0 }; int bce_TXP_b06FwReleaseMajor = 0x6; @@ -3547,7 +3547,7 @@ u32 bce_TXP_b06FwSbssAddr = 0x08003c20; int bce_TXP_b06FwSbssLen = 0x68; u32 bce_TXP_b06FwSDataAddr = 0x00000000; int bce_TXP_b06FwSDataLen = 0x0; -u32 bce_TXP_b06FwText[(0x3bfc/4) + 1] = { +const u32 bce_TXP_b06FwText[(0x3bfc/4) + 1] = { 0xa00002a, 0x0, 0x0, 0xd, 0x74787036, 0x2e302e31, 0x35000000, 0x6000f00, 0x0, 0x136, 0xea60, @@ -4509,11 +4509,11 @@ u32 bce_TXP_b06FwText[(0x3bfc/4) + 1] = { 0x3c010800, 0xac243d58, 0x3c010800, 0xac233d68, 0x3c010800, 0xac223d60, 0x3e00008, 0x0, 0x0 }; -u32 bce_TXP_b06FwData[(0x0/4) + 1] = { 0x0 }; -u32 bce_TXP_b06FwRodata[(0x0/4) + 1] = { 0x0 }; -u32 bce_TXP_b06FwBss[(0x14c/4) + 1] = { 0x0 }; -u32 bce_TXP_b06FwSbss[(0x68/4) + 1] = { 0x0 }; -u32 bce_TXP_b06FwSdata[(0x0/4) + 1] = { 0x0 }; +const u32 bce_TXP_b06FwData[(0x0/4) + 1] = { 0x0 }; +const u32 bce_TXP_b06FwRodata[(0x0/4) + 1] = { 0x0 }; +const u32 bce_TXP_b06FwBss[(0x14c/4) + 1] = { 0x0 }; +const u32 bce_TXP_b06FwSbss[(0x68/4) + 1] = { 0x0 }; +const u32 bce_TXP_b06FwSdata[(0x0/4) + 1] = { 0x0 }; int bce_CP_b06FwReleaseMajor = 0x6; @@ -4532,7 +4532,7 @@ u32 bce_CP_b06FwSbssAddr = 0x08005884; int bce_CP_b06FwSbssLen = 0xf1; u32 bce_CP_b06FwSDataAddr = 0x00000000; int bce_CP_b06FwSDataLen = 0x0; -u32 bce_CP_b06FwText[(0x5688/4) + 1] = { +const u32 bce_CP_b06FwText[(0x5688/4) + 1] = { 0xa000028, 0x0, 0x0, 0xd, 0x6370362e, 0x302e3135, 0x0, 0x6000f04, 0x0, 0x0, 0x0, @@ -5918,7 +5918,7 @@ u32 bce_CP_b06FwText[(0x5688/4) + 1] = { 0x27bd0030, 0x8f83001c, 0x8c620004, 0x10400003, 0x0, 0x3e00008, 0x0, 0x8c640010, 0x8c650008, 0xa001527, 0x8c66000c, 0x0 }; -u32 bce_CP_b06FwData[(0x84/4) + 1] = { +const u32 bce_CP_b06FwData[(0x84/4) + 1] = { 0x0, 0x1b, 0xf, 0xa, 0x8, 0x6, 0x5, 0x5, 0x4, 0x4, 0x3, @@ -5928,7 +5928,7 @@ u32 bce_CP_b06FwData[(0x84/4) + 1] = { 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x0 }; -u32 bce_CP_b06FwRodata[(0x158/4) + 1] = { +const u32 bce_CP_b06FwRodata[(0x158/4) + 1] = { 0x8000f24, 0x8000d6c, 0x8000fb8, 0x8001060, 0x8000f4c, 0x8000f8c, 0x8001194, 0x8000d88, 0x80011b8, 0x8000dd8, 0x8001554, @@ -5951,12 +5951,12 @@ u32 bce_CP_b06FwRodata[(0x158/4) + 1] = { 0x8002e1c, 0x8002de4, 0x8002df0, 0x8002dfc, 0x8002e08, 0x80052e8, 0x80052a8, 0x8005274, 0x8005248, 0x8005224, 0x80051e0, 0x0 }; -u32 bce_CP_b06FwBss[(0x5d8/4) + 1] = { 0x0 }; -u32 bce_CP_b06FwSbss[(0xf1/4) + 1] = { 0x0 }; -u32 bce_CP_b06FwSdata[(0x0/4) + 1] = { 0x0 }; +const u32 bce_CP_b06FwBss[(0x5d8/4) + 1] = { 0x0 }; +const u32 bce_CP_b06FwSbss[(0xf1/4) + 1] = { 0x0 }; +const u32 bce_CP_b06FwSdata[(0x0/4) + 1] = { 0x0 }; -u32 bce_rv2p_proc1[] = { +const u32 bce_rv2p_proc1[] = { 0x00000010, 0xb1800006, 0x0000001f, 0x0106000f, 0x00000008, 0x0500ffff, @@ -6681,7 +6681,7 @@ u32 bce_TXP_b09FwSbssAddr = 0x08003d88; int bce_TXP_b09FwSbssLen = 0x64; u32 bce_TXP_b09FwSDataAddr = 0x00000000; int bce_TXP_b09FwSDataLen = 0x0; -u32 bce_TXP_b09FwText[(0x3d28/4) + 1] = { +const u32 bce_TXP_b09FwText[(0x3d28/4) + 1] = { 0xa00002a, 0x0, 0x0, 0xd, 0x74787036, 0x2e302e31, 0x37000000, 0x6001100, 0x0, 0x136, 0xea60, @@ -7661,15 +7661,15 @@ u32 bce_TXP_b09FwText[(0x3d28/4) + 1] = { 0xac263fcc, 0x3c010800, 0xac253fc4, 0x3c010800, 0xac243fc0, 0x3c010800, 0xac233fd0, 0x3c010800, 0xac223fc8, 0x3e00008, 0x0, 0x0 }; -u32 bce_TXP_b09FwData[(0x0/4) + 1] = { 0x0 }; -u32 bce_TXP_b09FwRodata[(0x30/4) + 1] = { +const u32 bce_TXP_b09FwData[(0x0/4) + 1] = { 0x0 }; +const u32 bce_TXP_b09FwRodata[(0x30/4) + 1] = { 0x80000940, 0x80000900, 0x80080100, 0x80080080, 0x80080000, 0x800e0000, 0x80080080, 0x80080000, 0x80000a80, 0x80000a00, 0x80000980, 0x80000900, 0x0 }; -u32 bce_TXP_b09FwBss[(0x24c/4) + 1] = { 0x0 }; -u32 bce_TXP_b09FwSbss[(0x64/4) + 1] = { 0x0 }; -u32 bce_TXP_b09FwSdata[(0x0/4) + 1] = { 0x0 }; +const u32 bce_TXP_b09FwBss[(0x24c/4) + 1] = { 0x0 }; +const u32 bce_TXP_b09FwSbss[(0x64/4) + 1] = { 0x0 }; +const u32 bce_TXP_b09FwSdata[(0x0/4) + 1] = { 0x0 }; int bce_TPAT_b09FwReleaseMajor = 0x6; @@ -7688,7 +7688,7 @@ u32 bce_TPAT_b09FwSbssAddr = 0x08001720; int bce_TPAT_b09FwSbssLen = 0x3c; u32 bce_TPAT_b09FwSDataAddr = 0x00000000; int bce_TPAT_b09FwSDataLen = 0x0; -u32 bce_TPAT_b09FwText[(0x12fc/4) + 1] = { +const u32 bce_TPAT_b09FwText[(0x12fc/4) + 1] = { 0xa000124, 0x0, 0x0, 0xd, 0x74706136, 0x2e302e31, 0x37000000, 0x6001101, 0x0, 0x0, 0x0, @@ -7994,12 +7994,12 @@ u32 bce_TPAT_b09FwText[(0x12fc/4) + 1] = { 0x0, 0x0, 0x2402ffff, 0x2463ffff, 0x1462fffa, 0x24840004, 0x3e00008, 0x0, 0x0 }; -u32 bce_TPAT_b09FwData[(0x0/4) + 1] = { 0x0 }; -u32 bce_TPAT_b09FwRodata[(0x4/4) + 1] = { +const u32 bce_TPAT_b09FwData[(0x0/4) + 1] = { 0x0 }; +const u32 bce_TPAT_b09FwRodata[(0x4/4) + 1] = { 0x1, 0x0 }; -u32 bce_TPAT_b09FwBss[(0x12b4/4) + 1] = { 0x0 }; -u32 bce_TPAT_b09FwSbss[(0x3c/4) + 1] = { 0x0 }; -u32 bce_TPAT_b09FwSdata[(0x0/4) + 1] = { 0x0 }; +const u32 bce_TPAT_b09FwBss[(0x12b4/4) + 1] = { 0x0 }; +const u32 bce_TPAT_b09FwSbss[(0x3c/4) + 1] = { 0x0 }; +const u32 bce_TPAT_b09FwSdata[(0x0/4) + 1] = { 0x0 }; int bce_COM_b09FwReleaseMajor = 0x6; @@ -8018,7 +8018,7 @@ u32 bce_COM_b09FwSbssAddr = 0x08005608; int bce_COM_b09FwSbssLen = 0x30; u32 bce_COM_b09FwSDataAddr = 0x00000000; int bce_COM_b09FwSDataLen = 0x0; -u32 bce_COM_b09FwText[(0x5594/4) + 1] = { +const u32 bce_COM_b09FwText[(0x5594/4) + 1] = { 0xa000046, 0x0, 0x0, 0xd, 0x636f6d36, 0x2e302e31, 0x37000000, 0x6001102, 0x0, 0x3, 0xc8, @@ -9389,15 +9389,15 @@ u32 bce_COM_b09FwText[(0x5594/4) + 1] = { 0x40f809, 0x0, 0xa001560, 0x0, 0xd, 0x3c1c0800, 0x279c5608, 0x8fbf0010, 0x3e00008, 0x27bd0018, 0x0 }; -u32 bce_COM_b09FwData[(0x0/4) + 1] = { 0x0 }; -u32 bce_COM_b09FwRodata[(0x38/4) + 1] = { +const u32 bce_COM_b09FwData[(0x0/4) + 1] = { 0x0 }; +const u32 bce_COM_b09FwRodata[(0x38/4) + 1] = { 0x80080240, 0x80080100, 0x80080080, 0x80080000, 0xc80, 0x3200, 0x8000e98, 0x8000ef4, 0x8000f88, 0x8001028, 0x8001074, 0x80080100, 0x80080080, 0x80080000, 0x0 }; -u32 bce_COM_b09FwBss[(0x11c/4) + 1] = { 0x0 }; -u32 bce_COM_b09FwSbss[(0x30/4) + 1] = { 0x0 }; -u32 bce_COM_b09FwSdata[(0x0/4) + 1] = { 0x0 }; +const u32 bce_COM_b09FwBss[(0x11c/4) + 1] = { 0x0 }; +const u32 bce_COM_b09FwSbss[(0x30/4) + 1] = { 0x0 }; +const u32 bce_COM_b09FwSdata[(0x0/4) + 1] = { 0x0 }; int bce_RXP_b09FwReleaseMajor = 0x6; @@ -9416,7 +9416,7 @@ u32 bce_RXP_b09FwSbssAddr = 0x08009400; int bce_RXP_b09FwSbssLen = 0x78; u32 bce_RXP_b09FwSDataAddr = 0x00000000; int bce_RXP_b09FwSDataLen = 0x0; -u32 bce_RXP_b09FwText[(0x9090/4) + 1] = { +const u32 bce_RXP_b09FwText[(0x9090/4) + 1] = { 0xa000c84, 0x0, 0x0, 0xd, 0x72787036, 0x2e302e31, 0x37000000, 0x6001103, 0x0, 0x1, 0x0, @@ -11786,9 +11786,9 @@ u32 bce_RXP_b09FwRodata[(0x33c/4) + 1] = { 0x8007fc0, 0x8007fc0, 0x8007fc0, 0x8007fc0, 0x8007fe8, 0x8008b6c, 0x8008cc8, 0x8008ca8, 0x8008710, 0x8008b84, 0x0 }; -u32 bce_RXP_b09FwBss[(0x1bc/4) + 1] = { 0x0 }; -u32 bce_RXP_b09FwSbss[(0x78/4) + 1] = { 0x0 }; -u32 bce_RXP_b09FwSdata[(0x0/4) + 1] = { 0x0 }; +const u32 bce_RXP_b09FwBss[(0x1bc/4) + 1] = { 0x0 }; +const u32 bce_RXP_b09FwSbss[(0x78/4) + 1] = { 0x0 }; +const u32 bce_RXP_b09FwSdata[(0x0/4) + 1] = { 0x0 }; int bce_CP_b09FwReleaseMajor = 0x6; @@ -11807,7 +11807,7 @@ u32 bce_CP_b09FwSbssAddr = 0x080059b0; int bce_CP_b09FwSbssLen = 0xa8; u32 bce_CP_b09FwSDataAddr = 0x00000000; int bce_CP_b09FwSDataLen = 0x0; -u32 bce_CP_b09FwText[(0x5744/4) + 1] = { +const u32 bce_CP_b09FwText[(0x5744/4) + 1] = { 0xa000028, 0x0, 0x0, 0xd, 0x6370362e, 0x302e3137, 0x0, 0x6001104, 0x0, 0x0, 0x0, @@ -13205,7 +13205,7 @@ u32 bce_CP_b09FwText[(0x5744/4) + 1] = { 0xa00156a, 0x8fbf001c, 0xe0010d1, 0x0, 0x5040ff9e, 0x8fbf001c, 0x9259007d, 0x3330003f, 0xa0015c6, 0x36020040, 0x0 }; -u32 bce_CP_b09FwData[(0x84/4) + 1] = { +const u32 bce_CP_b09FwData[(0x84/4) + 1] = { 0x0, 0x1b, 0xf, 0xa, 0x8, 0x6, 0x5, 0x5, 0x4, 0x4, 0x3, @@ -13215,7 +13215,7 @@ u32 bce_CP_b09FwData[(0x84/4) + 1] = { 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x0 }; -u32 bce_CP_b09FwRodata[(0x1c0/4) + 1] = { +const u32 bce_CP_b09FwRodata[(0x1c0/4) + 1] = { 0x80080100, 0x80080080, 0x80080000, 0xc00, 0x3080, 0x80011d0, 0x800127c, 0x8001294, 0x80012a8, @@ -13245,12 +13245,12 @@ u32 bce_CP_b09FwRodata[(0x1c0/4) + 1] = { 0x80080080, 0x80080000, 0x80080080, 0x8004c64, 0x8004c9c, 0x8004be4, 0x8004c64, 0x8004c64, 0x80049b8, 0x8004c64, 0x8005050, 0x0 }; -u32 bce_CP_b09FwBss[(0x19c/4) + 1] = { 0x0 }; -u32 bce_CP_b09FwSbss[(0xa8/4) + 1] = { 0x0 }; -u32 bce_CP_b09FwSdata[(0x0/4) + 1] = { 0x0 }; +const u32 bce_CP_b09FwBss[(0x19c/4) + 1] = { 0x0 }; +const u32 bce_CP_b09FwSbss[(0xa8/4) + 1] = { 0x0 }; +const u32 bce_CP_b09FwSdata[(0x0/4) + 1] = { 0x0 }; -u32 bce_xi_rv2p_proc1[] = { +const u32 bce_xi_rv2p_proc1[] = { 0x00000010, 0xb1800006, 0x0000001f, 0x05060011, 0x00000008, 0x0500ffff, @@ -13541,7 +13541,7 @@ u32 bce_xi_rv2p_proc1[] = { }; -u32 bce_xi_rv2p_proc2[] = { +const u32 bce_xi_rv2p_proc2[] = { 0x00000010, 0xb1800004, 0x0000001f, 0x05060011, 0x00000008, 0x050000ff, @@ -14008,9 +14008,9 @@ u32 bce_xi_rv2p_proc2[] = { 0x00000010, 0x001f0000, 0x00000018, 0x8000fe35, }; -
-u32 bce_xi90_rv2p_proc1[] = { + +const u32 bce_xi90_rv2p_proc1[] = { 0x00000010, 0xb1800006, 0x0000001f, 0x03060011, 0x00000008, 0x0500ffff, @@ -14316,7 +14316,7 @@ u32 bce_xi90_rv2p_proc1[] = { }; -u32 bce_xi90_rv2p_proc2[] = { +const u32 bce_xi90_rv2p_proc2[] = { 0x00000010, 0xb1800004, 0x0000001f, 0x03060011, 0x00000008, 0x050000ff, @@ -14849,6 +14849,3 @@ u32 bce_xi90_rv2p_proc2[] = { bce_rv2p_proc2[BCE_RV2P_PROC2_MAX_BD_PAGE_LOC] = \ (bce_rv2p_proc2[BCE_RV2P_PROC2_MAX_BD_PAGE_LOC] & ~0xFFFF) | (value); \ } - - - diff --git a/freebsd/sys/dev/bce/if_bcereg.h b/freebsd/sys/dev/bce/if_bcereg.h index b043df5b..450180bd 100644 --- a/freebsd/sys/dev/bce/if_bcereg.h +++ b/freebsd/sys/dev/bce/if_bcereg.h @@ -32,10 +32,6 @@ #ifndef _BCEREG_H_DEFINED #define _BCEREG_H_DEFINED -#ifdef HAVE_KERNEL_OPTION_HEADERS -#include <rtems/bsd/local/opt_device_polling.h> -#endif - #include <rtems/bsd/sys/param.h> #include <sys/endian.h> #include <sys/systm.h> @@ -6337,13 +6333,13 @@ struct fw_info { u32 bss_addr; u32 bss_len; u32 bss_index; - u32 *bss; + const u32 *bss; /* Read-only section. */ u32 rodata_addr; u32 rodata_len; u32 rodata_index; - u32 *rodata; + const u32 *rodata; }; #define RV2P_PROC1 0 @@ -6422,6 +6418,8 @@ struct fw_info { struct bce_softc { + struct mtx bce_mtx; + /* Interface info */ struct ifnet *bce_ifp; @@ -6449,8 +6447,6 @@ struct bce_softc /* IRQ Resource Handle */ struct resource *bce_res_irq; - struct mtx bce_mtx; - /* Interrupt handler. */ void *bce_intrhand; @@ -6470,6 +6466,7 @@ struct bce_softc #define BCE_USING_MSIX_FLAG 0x00000100 #define BCE_PCIE_FLAG 0x00000200 #define BCE_USING_TX_FLOW_CONTROL 0x00000400 +#define BCE_USING_RX_FLOW_CONTROL 0x00000800 /* Controller capability flags. */ u32 bce_cap_flags; @@ -6564,14 +6561,6 @@ struct bce_softc u16 bce_rx_ticks; u32 bce_stats_ticks; - /* ToDo: Can these be removed? */ - u16 bce_comp_prod_trip_int; - u16 bce_comp_prod_trip; - u16 bce_com_ticks_int; - u16 bce_com_ticks; - u16 bce_cmd_ticks_int; - u16 bce_cmd_ticks; - /* The address of the integrated PHY on the MII bus. */ int bce_phy_addr; @@ -6604,11 +6593,9 @@ struct bce_softc int watchdog_timer; /* Frame size and mbuf allocation size for RX frames. */ - u32 max_frame_size; int rx_bd_mbuf_alloc_size; int rx_bd_mbuf_data_len; int rx_bd_mbuf_align_pad; - int pg_bd_mbuf_alloc_size; /* Receive mode settings (i.e promiscuous, multicast, etc.). */ u32 rx_mode; diff --git a/freebsd/sys/dev/bfe/if_bfe.c b/freebsd/sys/dev/bfe/if_bfe.c index 6d5ce427..e805ad1c 100644 --- a/freebsd/sys/dev/bfe/if_bfe.c +++ b/freebsd/sys/dev/bfe/if_bfe.c @@ -794,7 +794,7 @@ bfe_list_newbuf(struct bfe_softc *sc, int c) u_int32_t ctrl; int nsegs; - m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); + m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); m->m_len = m->m_pkthdr.len = MCLBYTES; if (bus_dmamap_load_mbuf_sg(sc->bfe_rxmbuf_tag, sc->bfe_rx_sparemap, @@ -1522,7 +1522,7 @@ bfe_encap(struct bfe_softc *sc, struct mbuf **m_head) error = bus_dmamap_load_mbuf_sg(sc->bfe_txmbuf_tag, r->bfe_map, *m_head, txsegs, &nsegs, 0); if (error == EFBIG) { - m = m_collapse(*m_head, M_DONTWAIT, BFE_MAXTXSEGS); + m = m_collapse(*m_head, M_NOWAIT, BFE_MAXTXSEGS); if (m == NULL) { m_freem(*m_head); *m_head = NULL; @@ -1742,7 +1742,7 @@ bfe_ifmedia_upd(struct ifnet *ifp) mii = device_get_softc(sc->bfe_miibus); LIST_FOREACH(miisc, &mii->mii_phys, mii_list) - mii_phy_reset(miisc); + PHY_RESET(miisc); error = mii_mediachg(mii); BFE_UNLOCK(sc); diff --git a/freebsd/sys/dev/bge/if_bge.c b/freebsd/sys/dev/bge/if_bge.c index 75912967..f9010aa1 100644 --- a/freebsd/sys/dev/bge/if_bge.c +++ b/freebsd/sys/dev/bge/if_bge.c @@ -37,10 +37,10 @@ __FBSDID("$FreeBSD$"); /* - * Broadcom BCM570x family gigabit ethernet driver for FreeBSD. + * Broadcom BCM57xx(x)/BCM590x NetXtreme and NetLink family Ethernet driver * * The Broadcom BCM5700 is based on technology originally developed by - * Alteon Networks as part of the Tigon I and Tigon II gigabit ethernet + * Alteon Networks as part of the Tigon I and Tigon II Gigabit Ethernet * MAC chips. The BCM5700, sometimes referred to as the Tigon III, has * two on-board MIPS R4000 CPUs and can have as much as 16MB of external * SSRAM. The BCM5700 supports TCP, UDP and IP checksum offload, jumbo @@ -369,8 +369,9 @@ static const struct bge_revision bge_majorrevs[] = { #define BGE_IS_5717_PLUS(sc) ((sc)->bge_flags & BGE_FLAG_5717_PLUS) #define BGE_IS_57765_PLUS(sc) ((sc)->bge_flags & BGE_FLAG_57765_PLUS) -const struct bge_revision * bge_lookup_rev(uint32_t); -const struct bge_vendor * bge_lookup_vendor(uint16_t); +static uint32_t bge_chipid(device_t); +static const struct bge_vendor * bge_lookup_vendor(uint16_t); +static const struct bge_revision * bge_lookup_rev(uint32_t); typedef int (*bge_eaddr_fcn_t)(struct bge_softc *, uint8_t[]); @@ -530,11 +531,11 @@ static devclass_t bge_devclass; DRIVER_MODULE(bge, pci, bge_driver, bge_devclass, 0, 0); DRIVER_MODULE(miibus, bge, miibus_driver, miibus_devclass, 0, 0); -static int bge_allow_asf = 0; +static int bge_allow_asf = 1; TUNABLE_INT("hw.bge.allow_asf", &bge_allow_asf); -SYSCTL_NODE(_hw, OID_AUTO, bge, CTLFLAG_RD, 0, "BGE driver parameters"); +static SYSCTL_NODE(_hw, OID_AUTO, bge, CTLFLAG_RD, 0, "BGE driver parameters"); SYSCTL_INT(_hw_bge, OID_AUTO, allow_asf, CTLFLAG_RD, &bge_allow_asf, 0, "Allow ASF mode if available"); @@ -681,7 +682,7 @@ bge_ape_lock_init(struct bge_softc *sc) bit = BGE_APE_LOCK_GRANT_DRIVER0; break; default: - if (sc->bge_func_addr != 0) + if (sc->bge_func_addr == 0) bit = BGE_APE_LOCK_GRANT_DRIVER0; else bit = (1 << sc->bge_func_addr); @@ -1285,7 +1286,7 @@ bge_miibus_statchg(device_t dev) /* Set MAC flow control behavior to match link flow control settings. */ tx_mode &= ~BGE_TXMODE_FLOWCTL_ENABLE; rx_mode &= ~BGE_RXMODE_FLOWCTL_ENABLE; - if (IFM_OPTIONS(mii->mii_media_active & IFM_FDX) != 0) { + if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0) { if ((IFM_OPTIONS(mii->mii_media_active) & IFM_ETH_TXPAUSE) != 0) tx_mode |= BGE_TXMODE_FLOWCTL_ENABLE; if ((IFM_OPTIONS(mii->mii_media_active) & IFM_ETH_RXPAUSE) != 0) @@ -1314,12 +1315,12 @@ bge_newbuf_std(struct bge_softc *sc, int i) if (sc->bge_flags & BGE_FLAG_JUMBO_STD && (sc->bge_ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN + ETHER_VLAN_ENCAP_LEN > (MCLBYTES - ETHER_ALIGN))) { - m = m_getjcl(M_DONTWAIT, MT_DATA, M_PKTHDR, MJUM9BYTES); + m = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, MJUM9BYTES); if (m == NULL) return (ENOBUFS); m->m_len = m->m_pkthdr.len = MJUM9BYTES; } else { - m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); + m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); if (m == NULL) return (ENOBUFS); m->m_len = m->m_pkthdr.len = MCLBYTES; @@ -1370,11 +1371,11 @@ bge_newbuf_jumbo(struct bge_softc *sc, int i) struct mbuf *m; int error, nsegs; - MGETHDR(m, M_DONTWAIT, MT_DATA); + MGETHDR(m, M_NOWAIT, MT_DATA); if (m == NULL) return (ENOBUFS); - m_cljget(m, M_DONTWAIT, MJUM9BYTES); + m_cljget(m, M_NOWAIT, MJUM9BYTES); if (!(m->m_flags & M_EXT)) { m_freem(m); return (ENOBUFS); @@ -1918,7 +1919,7 @@ bge_chipinit(struct bge_softc *sc) PCI_CLRBIT(sc->bge_dev, BGE_PCI_CMD, PCIM_CMD_INTxDIS | PCIM_CMD_MWIEN, 4); - /* Set the timer prescaler (always 66Mhz) */ + /* Set the timer prescaler (always 66 MHz). */ CSR_WRITE_4(sc, BGE_MISC_CFG, BGE_32BITTIME_66MHZ); /* XXX: The Linux tg3 driver does this at the start of brgphy_reset. */ @@ -2281,9 +2282,9 @@ bge_blockinit(struct bge_softc *sc) /* Set random backoff seed for TX */ CSR_WRITE_4(sc, BGE_TX_RANDOM_BACKOFF, - IF_LLADDR(sc->bge_ifp)[0] + IF_LLADDR(sc->bge_ifp)[1] + + (IF_LLADDR(sc->bge_ifp)[0] + IF_LLADDR(sc->bge_ifp)[1] + IF_LLADDR(sc->bge_ifp)[2] + IF_LLADDR(sc->bge_ifp)[3] + - IF_LLADDR(sc->bge_ifp)[4] + IF_LLADDR(sc->bge_ifp)[5] + + IF_LLADDR(sc->bge_ifp)[4] + IF_LLADDR(sc->bge_ifp)[5]) & BGE_TX_BACKOFF_SEED_MASK); /* Set inter-packet gap */ @@ -2402,7 +2403,7 @@ bge_blockinit(struct bge_softc *sc) DELAY(40); /* Set misc. local control, enable interrupts on attentions */ - CSR_WRITE_4(sc, BGE_MISC_LOCAL_CTL, BGE_MLC_INTR_ONATTN); + BGE_SETBIT(sc, BGE_MISC_LOCAL_CTL, BGE_MLC_INTR_ONATTN); #ifdef notdef /* Assert GPIO pins for PHY reset */ @@ -2588,7 +2589,7 @@ bge_blockinit(struct bge_softc *sc) return (0); } -const struct bge_revision * +static const struct bge_revision * bge_lookup_rev(uint32_t chipid) { const struct bge_revision *br; @@ -2606,7 +2607,7 @@ bge_lookup_rev(uint32_t chipid) return (NULL); } -const struct bge_vendor * +static const struct bge_vendor * bge_lookup_vendor(uint16_t vid) { const struct bge_vendor *v; @@ -2615,10 +2616,47 @@ bge_lookup_vendor(uint16_t vid) if (v->v_id == vid) return (v); - panic("%s: unknown vendor %d", __func__, vid); return (NULL); } +static uint32_t +bge_chipid(device_t dev) +{ + uint32_t id; + + id = pci_read_config(dev, BGE_PCI_MISC_CTL, 4) >> + BGE_PCIMISCCTL_ASICREV_SHIFT; + if (BGE_ASICREV(id) == BGE_ASICREV_USE_PRODID_REG) { + /* + * Find the ASCI revision. Different chips use different + * registers. + */ + switch (pci_get_device(dev)) { + case BCOM_DEVICEID_BCM5717: + case BCOM_DEVICEID_BCM5718: + case BCOM_DEVICEID_BCM5719: + case BCOM_DEVICEID_BCM5720: + id = pci_read_config(dev, + BGE_PCI_GEN2_PRODID_ASICREV, 4); + break; + case BCOM_DEVICEID_BCM57761: + case BCOM_DEVICEID_BCM57762: + case BCOM_DEVICEID_BCM57765: + case BCOM_DEVICEID_BCM57766: + case BCOM_DEVICEID_BCM57781: + case BCOM_DEVICEID_BCM57785: + case BCOM_DEVICEID_BCM57791: + case BCOM_DEVICEID_BCM57795: + id = pci_read_config(dev, + BGE_PCI_GEN15_PRODID_ASICREV, 4); + break; + default: + id = pci_read_config(dev, BGE_PCI_PRODID_ASICREV, 4); + } + } + return (id); +} + /* * Probe for a Broadcom chip. Check the PCI vendor and device IDs * against our list and return its name if we find a match. @@ -2636,61 +2674,34 @@ bge_probe(device_t dev) char model[64]; const struct bge_revision *br; const char *pname; - struct bge_softc *sc = device_get_softc(dev); + struct bge_softc *sc; const struct bge_type *t = bge_devs; const struct bge_vendor *v; uint32_t id; uint16_t did, vid; + sc = device_get_softc(dev); sc->bge_dev = dev; vid = pci_get_vendor(dev); did = pci_get_device(dev); while(t->bge_vid != 0) { if ((vid == t->bge_vid) && (did == t->bge_did)) { - id = pci_read_config(dev, BGE_PCI_MISC_CTL, 4) >> - BGE_PCIMISCCTL_ASICREV_SHIFT; - if (BGE_ASICREV(id) == BGE_ASICREV_USE_PRODID_REG) { - /* - * Find the ASCI revision. Different chips - * use different registers. - */ - switch (pci_get_device(dev)) { - case BCOM_DEVICEID_BCM5717: - case BCOM_DEVICEID_BCM5718: - case BCOM_DEVICEID_BCM5719: - case BCOM_DEVICEID_BCM5720: - id = pci_read_config(dev, - BGE_PCI_GEN2_PRODID_ASICREV, 4); - break; - case BCOM_DEVICEID_BCM57761: - case BCOM_DEVICEID_BCM57762: - case BCOM_DEVICEID_BCM57765: - case BCOM_DEVICEID_BCM57766: - case BCOM_DEVICEID_BCM57781: - case BCOM_DEVICEID_BCM57785: - case BCOM_DEVICEID_BCM57791: - case BCOM_DEVICEID_BCM57795: - id = pci_read_config(dev, - BGE_PCI_GEN15_PRODID_ASICREV, 4); - break; - default: - id = pci_read_config(dev, - BGE_PCI_PRODID_ASICREV, 4); - } - } + id = bge_chipid(dev); br = bge_lookup_rev(id); - v = bge_lookup_vendor(vid); if (bge_has_eaddr(sc) && pci_get_vpd_ident(dev, &pname) == 0) - snprintf(model, 64, "%s", pname); - else - snprintf(model, 64, "%s %s", v->v_name, + snprintf(model, sizeof(model), "%s", pname); + else { + v = bge_lookup_vendor(vid); + snprintf(model, sizeof(model), "%s %s", + v != NULL ? v->v_name : "Unknown", br != NULL ? br->br_name : - "NetXtreme Ethernet Controller"); - snprintf(buf, 96, "%s, %sASIC rev. %#08x", model, - br != NULL ? "" : "unknown ", id); + "NetXtreme/NetLink Ethernet Controller"); + } + snprintf(buf, sizeof(buf), "%s, %sASIC rev. %#08x", + model, br != NULL ? "" : "unknown ", id); device_set_desc_copy(dev, buf); - return (0); + return (BUS_PROBE_DEFAULT); } t++; } @@ -3274,38 +3285,7 @@ bge_attach(device_t dev) /* Save various chip information. */ sc->bge_func_addr = pci_get_function(dev); - sc->bge_chipid = - pci_read_config(dev, BGE_PCI_MISC_CTL, 4) >> - BGE_PCIMISCCTL_ASICREV_SHIFT; - if (BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_USE_PRODID_REG) { - /* - * Find the ASCI revision. Different chips use different - * registers. - */ - switch (pci_get_device(dev)) { - case BCOM_DEVICEID_BCM5717: - case BCOM_DEVICEID_BCM5718: - case BCOM_DEVICEID_BCM5719: - case BCOM_DEVICEID_BCM5720: - sc->bge_chipid = pci_read_config(dev, - BGE_PCI_GEN2_PRODID_ASICREV, 4); - break; - case BCOM_DEVICEID_BCM57761: - case BCOM_DEVICEID_BCM57762: - case BCOM_DEVICEID_BCM57765: - case BCOM_DEVICEID_BCM57766: - case BCOM_DEVICEID_BCM57781: - case BCOM_DEVICEID_BCM57785: - case BCOM_DEVICEID_BCM57791: - case BCOM_DEVICEID_BCM57795: - sc->bge_chipid = pci_read_config(dev, - BGE_PCI_GEN15_PRODID_ASICREV, 4); - break; - default: - sc->bge_chipid = pci_read_config(dev, - BGE_PCI_PRODID_ASICREV, 4); - } - } + sc->bge_chipid = bge_chipid(dev); sc->bge_asicrev = BGE_ASICREV(sc->bge_chipid); sc->bge_chiprev = BGE_CHIPREV(sc->bge_chipid); @@ -3495,6 +3475,8 @@ bge_attach(device_t dev) pci_get_device(dev) == BCOM_DEVICEID_BCM5753F || pci_get_device(dev) == BCOM_DEVICEID_BCM5787F)) || pci_get_device(dev) == BCOM_DEVICEID_BCM57790 || + pci_get_device(dev) == BCOM_DEVICEID_BCM57791 || + pci_get_device(dev) == BCOM_DEVICEID_BCM57795 || sc->bge_asicrev == BGE_ASICREV_BCM5906) { /* These chips are 10/100 only. */ capmask &= ~BMSR_EXTSTAT; @@ -3506,8 +3488,8 @@ bge_attach(device_t dev) * TSO. But the firmware is not available to FreeBSD and Linux * claims that the TSO performed by the firmware is slower than * hardware based TSO. Moreover the firmware based TSO has one - * known bug which can't handle TSO if ethernet header + IP/TCP - * header is greater than 80 bytes. The workaround for the TSO + * known bug which can't handle TSO if Ethernet header + IP/TCP + * header is greater than 80 bytes. A workaround for the TSO * bug exist but it seems it's too expensive than not using * TSO at all. Some hardwares also have the TSO bug so limit * the TSO to the controllers that are not affected TSO issues @@ -3536,7 +3518,7 @@ bge_attach(device_t dev) /* * Check if this is a PCI-X or PCI Express device. */ - if (pci_find_extcap(dev, PCIY_EXPRESS, ®) == 0) { + if (pci_find_cap(dev, PCIY_EXPRESS, ®) == 0) { /* * Found a PCI Express capabilities register, this * must be a PCI Express device. @@ -3558,7 +3540,7 @@ bge_attach(device_t dev) * Check if the device is in PCI-X Mode. * (This bit is not valid on PCI Express controllers.) */ - if (pci_find_extcap(dev, PCIY_PCIX, ®) == 0) + if (pci_find_cap(dev, PCIY_PCIX, ®) == 0) sc->bge_pcixcap = reg; if ((pci_read_config(dev, BGE_PCI_PCISTATE, 4) & BGE_PCISTATE_PCI_BUSMODE) == 0) @@ -3588,7 +3570,7 @@ bge_attach(device_t dev) * normal operation. */ rid = 0; - if (pci_find_extcap(sc->bge_dev, PCIY_MSI, ®) == 0) { + if (pci_find_cap(sc->bge_dev, PCIY_MSI, ®) == 0) { sc->bge_msicap = reg; if (bge_can_use_msi(sc)) { msicount = pci_msi_count(dev); @@ -3826,7 +3808,7 @@ again: error = mii_attach(dev, &sc->bge_miibus, ifp, bge_ifmedia_upd, bge_ifmedia_sts, capmask, sc->bge_phy_addr, MII_OFFSET_ANY, - MIIF_DOPAUSE | MIIF_FORCEPAUSE); + MIIF_DOPAUSE); if (error != 0) { if (trys++ < 4) { device_printf(sc->bge_dev, "Try again\n"); @@ -3880,8 +3862,13 @@ again: error = ENOMEM; goto fail; } - taskqueue_start_threads(&sc->bge_tq, 1, PI_NET, "%s taskq", - device_get_nameunit(sc->bge_dev)); + error = taskqueue_start_threads(&sc->bge_tq, 1, PI_NET, + "%s taskq", device_get_nameunit(sc->bge_dev)); + if (error != 0) { + device_printf(dev, "could not start threads.\n"); + ether_ifdetach(ifp); + goto fail; + } error = bus_setup_intr(dev, sc->bge_irq, INTR_TYPE_NET | INTR_MPSAFE, bge_msi_intr, NULL, sc, &sc->bge_intrhand); @@ -3926,9 +3913,9 @@ bge_detach(device_t dev) if (sc->bge_tq) taskqueue_drain(sc->bge_tq, &sc->bge_intr_task); - if (sc->bge_flags & BGE_FLAG_TBI) { + if (sc->bge_flags & BGE_FLAG_TBI) ifmedia_removeall(&sc->bge_ifmedia); - } else { + else if (sc->bge_miibus != NULL) { bus_generic_detach(dev); device_delete_child(dev, sc->bge_miibus); } @@ -4987,7 +4974,7 @@ bge_cksum_pad(struct mbuf *m) /* Allocate new empty mbuf, pad it. Compact later. */ struct mbuf *n; - MGET(n, M_DONTWAIT, MT_DATA); + MGET(n, M_NOWAIT, MT_DATA); if (n == NULL) return (ENOBUFS); n->m_len = 0; @@ -5029,7 +5016,7 @@ bge_check_short_dma(struct mbuf *m) } if (found > 1) { - n = m_defrag(m, M_DONTWAIT); + n = m_defrag(m, M_NOWAIT); if (n == NULL) m_freem(m); } else @@ -5049,7 +5036,7 @@ bge_setup_tso(struct bge_softc *sc, struct mbuf *m, uint16_t *mss, if (M_WRITABLE(m) == 0) { /* Get a writable copy. */ - n = m_dup(m, M_DONTWAIT); + n = m_dup(m, M_NOWAIT); m_freem(m); if (n == NULL) return (NULL); @@ -5166,9 +5153,9 @@ bge_encap(struct bge_softc *sc, struct mbuf **m_head, uint32_t *txidx) * DMA read operation. */ if (sc->bge_forced_collapse == 1) - m = m_defrag(m, M_DONTWAIT); + m = m_defrag(m, M_NOWAIT); else - m = m_collapse(m, M_DONTWAIT, + m = m_collapse(m, M_NOWAIT, sc->bge_forced_collapse); if (m == NULL) m = *m_head; @@ -5180,7 +5167,7 @@ bge_encap(struct bge_softc *sc, struct mbuf **m_head, uint32_t *txidx) error = bus_dmamap_load_mbuf_sg(sc->bge_cdata.bge_tx_mtag, map, m, segs, &nsegs, BUS_DMA_NOWAIT); if (error == EFBIG) { - m = m_collapse(m, M_DONTWAIT, BGE_NSEG_NEW); + m = m_collapse(m, M_NOWAIT, BGE_NSEG_NEW); if (m == NULL) { m_freem(*m_head); *m_head = NULL; @@ -5311,7 +5298,7 @@ bge_start_locked(struct ifnet *ifp) /* * Set a timeout in case the chip goes out to lunch. */ - sc->bge_timer = 5; + sc->bge_timer = BGE_TX_TIMEOUT; } } @@ -5468,7 +5455,7 @@ bge_init_locked(struct bge_softc *sc) * this number of frames, it will drop subsequent incoming * frames until the MBUF High Watermark is reached. */ - if (sc->bge_asicrev == BGE_ASICREV_BCM57765) + if (BGE_IS_57765_PLUS(sc)) CSR_WRITE_4(sc, BGE_MAX_RX_FRAME_LOWAT, 1); else CSR_WRITE_4(sc, BGE_MAX_RX_FRAME_LOWAT, 2); @@ -5588,7 +5575,7 @@ bge_ifmedia_upd_locked(struct ifnet *ifp) sc->bge_link_evt++; mii = device_get_softc(sc->bge_miibus); LIST_FOREACH(miisc, &mii->mii_phys, mii_list) - mii_phy_reset(miisc); + PHY_RESET(miisc); mii_mediachg(mii); /* @@ -5623,6 +5610,10 @@ bge_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) BGE_LOCK(sc); + if ((ifp->if_flags & IFF_UP) == 0) { + BGE_UNLOCK(sc); + return; + } if (sc->bge_flags & BGE_FLAG_TBI) { ifmr->ifm_status = IFM_AVALID; ifmr->ifm_active = IFM_ETHER; @@ -5812,12 +5803,40 @@ static void bge_watchdog(struct bge_softc *sc) { struct ifnet *ifp; + uint32_t status; BGE_LOCK_ASSERT(sc); if (sc->bge_timer == 0 || --sc->bge_timer) return; + /* If pause frames are active then don't reset the hardware. */ + if ((CSR_READ_4(sc, BGE_RX_MODE) & BGE_RXMODE_FLOWCTL_ENABLE) != 0) { + status = CSR_READ_4(sc, BGE_RX_STS); + if ((status & BGE_RXSTAT_REMOTE_XOFFED) != 0) { + /* + * If link partner has us in XOFF state then wait for + * the condition to clear. + */ + CSR_WRITE_4(sc, BGE_RX_STS, status); + sc->bge_timer = BGE_TX_TIMEOUT; + return; + } else if ((status & BGE_RXSTAT_RCVD_XOFF) != 0 && + (status & BGE_RXSTAT_RCVD_XON) != 0) { + /* + * If link partner has us in XOFF state then wait for + * the condition to clear. + */ + CSR_WRITE_4(sc, BGE_RX_STS, status); + sc->bge_timer = BGE_TX_TIMEOUT; + return; + } + /* + * Any other condition is unexpected and the controller + * should be reset. + */ + } + ifp = sc->bge_ifp; if_printf(ifp, "watchdog timeout -- resetting\n"); @@ -6325,7 +6344,7 @@ bge_add_sysctl_stats(struct bge_softc *sc, struct sysctl_ctx_list *ctx, #undef BGE_SYSCTL_STAT #define BGE_SYSCTL_STAT_ADD64(c, h, n, p, d) \ - SYSCTL_ADD_QUAD(c, h, OID_AUTO, n, CTLFLAG_RD, p, d) + SYSCTL_ADD_UQUAD(c, h, OID_AUTO, n, CTLFLAG_RD, p, d) static void bge_add_sysctl_stats_regs(struct bge_softc *sc, struct sysctl_ctx_list *ctx, diff --git a/freebsd/sys/dev/bge/if_bgereg.h b/freebsd/sys/dev/bge/if_bgereg.h index 93617cd1..09ced543 100644 --- a/freebsd/sys/dev/bge/if_bgereg.h +++ b/freebsd/sys/dev/bge/if_bgereg.h @@ -797,7 +797,7 @@ #define BGE_LEDCTL_BLINKPERIOD_OVERRIDE 0x80000000 /* TX backoff seed register */ -#define BGE_TX_BACKOFF_SEED_MASK 0x3F +#define BGE_TX_BACKOFF_SEED_MASK 0x3FF /* Autopoll status register */ #define BGE_AUTOPOLLSTS_ERROR 0x00000001 @@ -2928,6 +2928,7 @@ struct bge_dmamap_arg { #define BGE_HWREV_TIGON_II 0x02 #define BGE_TIMEOUT 100000 #define BGE_TXCONS_UNSET 0xFFFF /* impossible value */ +#define BGE_TX_TIMEOUT 5 struct bge_bcom_hack { int reg; diff --git a/freebsd/sys/dev/dc/dcphy.c b/freebsd/sys/dev/dc/dcphy.c index 9df39476..32d11c61 100644 --- a/freebsd/sys/dev/dc/dcphy.c +++ b/freebsd/sys/dev/dc/dcphy.c @@ -64,7 +64,6 @@ __FBSDID("$FreeBSD$"); #include <machine/bus.h> #include <machine/resource.h> -#include <sys/bus.h> #include <dev/pci/pcivar.h> @@ -116,6 +115,12 @@ static void dcphy_status(struct mii_softc *); static void dcphy_reset(struct mii_softc *); static int dcphy_auto(struct mii_softc *); +static const struct mii_phy_funcs dcphy_funcs = { + dcphy_service, + dcphy_status, + dcphy_reset +}; + static int dcphy_probe(device_t dev) { @@ -140,30 +145,16 @@ static int dcphy_attach(device_t dev) { struct mii_softc *sc; - struct mii_attach_args *ma; - struct mii_data *mii; struct dc_softc *dc_sc; device_t brdev; sc = device_get_softc(dev); - ma = device_get_ivars(dev); - sc->mii_dev = device_get_parent(dev); - mii = ma->mii_data; - LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list); - sc->mii_flags = miibus_get_flags(dev); - sc->mii_inst = mii->mii_instance++; - sc->mii_phy = ma->mii_phyno; - sc->mii_service = dcphy_service; - sc->mii_pdata = mii; + mii_phy_dev_attach(dev, MIIF_NOISOLATE | MIIF_NOMANPAUSE, + &dcphy_funcs, 0); - /* - * Apparently, we can neither isolate nor do loopback. - */ - sc->mii_flags |= MIIF_NOISOLATE | MIIF_NOLOOP | MIIF_NOMANPAUSE; - - /*dcphy_reset(sc);*/ - dc_sc = mii->mii_ifp->if_softc; + /*PHY_RESET(sc);*/ + dc_sc = sc->mii_pdata->mii_ifp->if_softc; CSR_WRITE_4(dc_sc, DC_10BTSTAT, 0); CSR_WRITE_4(dc_sc, DC_10BTCTRL, 0); @@ -184,7 +175,7 @@ dcphy_attach(device_t dev) break; } - sc->mii_capabilities &= ma->mii_capmask; + sc->mii_capabilities &= sc->mii_capmask; device_printf(dev, " "); mii_phy_add_media(sc); printf("\n"); @@ -221,11 +212,11 @@ dcphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) switch (IFM_SUBTYPE(ife->ifm_media)) { case IFM_AUTO: - /*dcphy_reset(sc);*/ - (void) dcphy_auto(sc); + /*PHY_RESET(sc);*/ + (void)dcphy_auto(sc); break; case IFM_100_TX: - dcphy_reset(sc); + PHY_RESET(sc); DC_CLRBIT(dc_sc, DC_10BTCTRL, DC_TCTL_AUTONEGENBL); mode |= DC_NETCFG_PORTSEL | DC_NETCFG_PCS | DC_NETCFG_SCRAMBLER; @@ -294,7 +285,7 @@ dcphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) } /* Update the media status. */ - dcphy_status(sc); + PHY_STATUS(sc); /* Callback if something changed. */ mii_phy_update(sc, cmd); diff --git a/freebsd/sys/dev/dc/if_dc.c b/freebsd/sys/dev/dc/if_dc.c index 575721c6..0c7a46cb 100644 --- a/freebsd/sys/dev/dc/if_dc.c +++ b/freebsd/sys/dev/dc/if_dc.c @@ -1369,7 +1369,7 @@ dc_netcfg_wait(struct dc_softc *sc) break; DELAY(10); } - if (i == DC_TIMEOUT) { + if (i == DC_TIMEOUT && bus_child_present(sc->dc_dev)) { if (!(isr & DC_ISR_TX_IDLE) && !DC_IS_ASIX(sc)) device_printf(sc->dc_dev, "%s: failed to force tx to idle state\n", __func__); @@ -2652,7 +2652,7 @@ dc_newbuf(struct dc_softc *sc, int i) bus_dma_segment_t segs[1]; int error, nseg; - m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); + m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); if (m == NULL) return (ENOBUFS); m->m_len = m->m_pkthdr.len = MCLBYTES; @@ -3389,7 +3389,7 @@ dc_encap(struct dc_softc *sc, struct mbuf **m_head) defragged = 0; if (sc->dc_flags & DC_TX_COALESCE && ((*m_head)->m_next != NULL || sc->dc_flags & DC_TX_ALIGN)) { - m = m_defrag(*m_head, M_DONTWAIT); + m = m_defrag(*m_head, M_NOWAIT); defragged = 1; } else { /* @@ -3404,7 +3404,7 @@ dc_encap(struct dc_softc *sc, struct mbuf **m_head) if (i > DC_TX_LIST_CNT / 4 || DC_TX_LIST_CNT - i + sc->dc_cdata.dc_tx_cnt <= DC_TX_LIST_RSVD) { - m = m_collapse(*m_head, M_DONTWAIT, DC_MAXFRAGS); + m = m_collapse(*m_head, M_NOWAIT, DC_MAXFRAGS); defragged = 1; } } @@ -3421,7 +3421,7 @@ dc_encap(struct dc_softc *sc, struct mbuf **m_head) error = bus_dmamap_load_mbuf_sg(sc->dc_tx_mtag, sc->dc_cdata.dc_tx_map[idx], *m_head, segs, &nseg, 0); if (error == EFBIG) { - if (defragged != 0 || (m = m_collapse(*m_head, M_DONTWAIT, + if (defragged != 0 || (m = m_collapse(*m_head, M_NOWAIT, DC_MAXFRAGS)) == NULL) { m_freem(*m_head); *m_head = NULL; diff --git a/freebsd/sys/dev/dc/if_dcreg.h b/freebsd/sys/dev/dc/if_dcreg.h index 0a61b7d1..e290881f 100644 --- a/freebsd/sys/dev/dc/if_dcreg.h +++ b/freebsd/sys/dev/dc/if_dcreg.h @@ -1018,7 +1018,7 @@ struct dc_softc { #define DC_VENDORID_MICROSOFT 0x1414 /* - * Supported Microsoft PCI and cardbus NICs. These are really + * Supported Microsoft PCI and CardBus NICs. These are really * ADMtek parts in disguise. */ diff --git a/freebsd/sys/dev/dc/pnphy.c b/freebsd/sys/dev/dc/pnphy.c index c303f9bf..a9a8ec93 100644 --- a/freebsd/sys/dev/dc/pnphy.c +++ b/freebsd/sys/dev/dc/pnphy.c @@ -62,7 +62,6 @@ __FBSDID("$FreeBSD$"); #include <machine/bus.h> #include <machine/resource.h> -#include <sys/bus.h> #include <dev/dc/if_dcreg.h> @@ -92,6 +91,13 @@ DRIVER_MODULE(pnphy, miibus, pnphy_driver, pnphy_devclass, 0, 0); static int pnphy_service(struct mii_softc *, struct mii_data *, int); static void pnphy_status(struct mii_softc *); +static void pnphy_reset(struct mii_softc *); + +static const struct mii_phy_funcs pnphy_funcs = { + pnphy_service, + pnphy_status, + pnphy_reset +}; static int pnphy_probe(device_t dev) @@ -117,29 +123,15 @@ static int pnphy_attach(device_t dev) { struct mii_softc *sc; - struct mii_attach_args *ma; - struct mii_data *mii; sc = device_get_softc(dev); - ma = device_get_ivars(dev); - sc->mii_dev = device_get_parent(dev); - mii = ma->mii_data; - LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list); - sc->mii_flags = miibus_get_flags(dev); - sc->mii_inst = mii->mii_instance++; - sc->mii_phy = ma->mii_phyno; - sc->mii_service = pnphy_service; - sc->mii_pdata = mii; - - /* - * Apparently, we can neither isolate nor do loopback. - */ - sc->mii_flags |= MIIF_NOISOLATE | MIIF_NOLOOP | MIIF_NOMANPAUSE; + mii_phy_dev_attach(dev, MIIF_NOISOLATE | MIIF_NOMANPAUSE, + &pnphy_funcs, 0); sc->mii_capabilities = BMSR_100TXFDX | BMSR_100TXHDX | BMSR_10TFDX | BMSR_10THDX; - sc->mii_capabilities &= ma->mii_capmask; + sc->mii_capabilities &= sc->mii_capmask; device_printf(dev, " "); mii_phy_add_media(sc); printf("\n"); @@ -196,7 +188,7 @@ pnphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) } /* Update the media status. */ - pnphy_status(sc); + PHY_STATUS(sc); /* Callback if something changed. */ mii_phy_update(sc, cmd); @@ -228,3 +220,9 @@ pnphy_status(struct mii_softc *sc) else mii->mii_media_active |= IFM_HDX; } + +static void +pnphy_reset(struct mii_softc *sc __unused) +{ + +} diff --git a/freebsd/sys/dev/e1000/e1000_api.c b/freebsd/sys/dev/e1000/e1000_api.c index 40a1dd3f..3c0eb4f4 100644 --- a/freebsd/sys/dev/e1000/e1000_api.c +++ b/freebsd/sys/dev/e1000/e1000_api.c @@ -331,6 +331,9 @@ s32 e1000_set_mac_type(struct e1000_hw *hw) case E1000_DEV_ID_I350_DA4: mac->type = e1000_i350; break; +#if defined(QV_RELEASE) && defined(SPRINGVILLE_FLASHLESS_HW) + case E1000_DEV_ID_I210_NVMLESS: +#endif /* QV_RELEASE && SPRINGVILLE_FLASHLESS_HW */ case E1000_DEV_ID_I210_COPPER: case E1000_DEV_ID_I210_COPPER_OEM1: case E1000_DEV_ID_I210_COPPER_IT: diff --git a/freebsd/sys/dev/e1000/if_em.c b/freebsd/sys/dev/e1000/if_em.c index 948d5f2b..4c1d3469 100644 --- a/freebsd/sys/dev/e1000/if_em.c +++ b/freebsd/sys/dev/e1000/if_em.c @@ -34,10 +34,11 @@ ******************************************************************************/ /*$FreeBSD$*/ -#ifdef HAVE_KERNEL_OPTION_HEADERS -#include <rtems/bsd/local/opt_device_polling.h> #include <rtems/bsd/local/opt_inet.h> #include <rtems/bsd/local/opt_inet6.h> + +#ifdef HAVE_KERNEL_OPTION_HEADERS +#include <rtems/bsd/local/opt_device_polling.h> #endif #include <rtems/bsd/sys/param.h> @@ -96,7 +97,7 @@ int em_display_debug_stats = 0; /********************************************************************* * Driver version: *********************************************************************/ -char em_driver_version[] = "7.3.7"; +char em_driver_version[] = "7.3.8"; /********************************************************************* * PCI Device ID Table @@ -337,6 +338,9 @@ MODULE_DEPEND(em, ether, 1, 1, 1); #define EM_USECS_TO_TICKS(usecs) ((1000 * (usecs) + 512) / 1024) #define M_TSO_LEN 66 +#define MAX_INTS_PER_SEC 8000 +#define DEFAULT_ITR (1000000000/(MAX_INTS_PER_SEC * 256)) + /* Allow common code without TSO */ #ifndef CSUM_TSO #define CSUM_TSO 0 @@ -572,6 +576,11 @@ em_attach(device_t dev) &adapter->tx_abs_int_delay, E1000_REGISTER(hw, E1000_TADV), em_tx_abs_int_delay_dflt); + em_add_int_delay_sysctl(adapter, "itr", + "interrupt delay limit in usecs/4", + &adapter->tx_itr, + E1000_REGISTER(hw, E1000_ITR), + DEFAULT_ITR); /* Sysctl for limiting the amount of work done in the taskqueue */ em_set_sysctl_value(adapter, "rx_processing_limit", @@ -2135,12 +2144,37 @@ em_set_promisc(struct adapter *adapter) static void em_disable_promisc(struct adapter *adapter) { - u32 reg_rctl; + struct ifnet *ifp = adapter->ifp; + u32 reg_rctl; + int mcnt = 0; reg_rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL); - reg_rctl &= (~E1000_RCTL_UPE); - reg_rctl &= (~E1000_RCTL_MPE); + if (ifp->if_flags & IFF_ALLMULTI) + mcnt = MAX_NUM_MULTICAST_ADDRESSES; + else { + struct ifmultiaddr *ifma; +#if __FreeBSD_version < 800000 + IF_ADDR_LOCK(ifp); +#else + if_maddr_rlock(ifp); +#endif + TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { + if (ifma->ifma_addr->sa_family != AF_LINK) + continue; + if (mcnt == MAX_NUM_MULTICAST_ADDRESSES) + break; + mcnt++; + } +#if __FreeBSD_version < 800000 + IF_ADDR_UNLOCK(ifp); +#else + if_maddr_runlock(ifp); +#endif + } + /* Don't disable if in MAX groups */ + if (mcnt < MAX_NUM_MULTICAST_ADDRESSES) + reg_rctl &= (~E1000_RCTL_MPE); reg_rctl &= (~E1000_RCTL_SBP); E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl); } @@ -2245,7 +2279,7 @@ em_local_timer(void *arg) /* Mask to use in the irq trigger */ if (adapter->msix_mem) - trigger = rxr->ims; /* RX for 82574 */ + trigger = rxr->ims; else trigger = E1000_ICS_RXDMT0; @@ -2410,16 +2444,8 @@ em_identify_hardware(struct adapter *adapter) device_t dev = adapter->dev; /* Make sure our PCI config space has the necessary stuff set */ + pci_enable_busmaster(dev); adapter->hw.bus.pci_cmd_word = pci_read_config(dev, PCIR_COMMAND, 2); - if (!((adapter->hw.bus.pci_cmd_word & PCIM_CMD_BUSMASTEREN) && - (adapter->hw.bus.pci_cmd_word & PCIM_CMD_MEMEN))) { - device_printf(dev, "Memory Access and/or Bus Master bits " - "were not set!\n"); - adapter->hw.bus.pci_cmd_word |= - (PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN); - pci_write_config(dev, PCIR_COMMAND, - adapter->hw.bus.pci_cmd_word, 2); - } /* Save off the information about this board */ adapter->hw.vendor_id = pci_get_vendor(dev); @@ -2718,7 +2744,7 @@ static int em_setup_msix(struct adapter *adapter) { device_t dev = adapter->dev; - int val = 0; + int val; /* ** Setup MSI/X for Hartwell: tests have shown @@ -2732,37 +2758,43 @@ em_setup_msix(struct adapter *adapter) int rid = PCIR_BAR(EM_MSIX_BAR); adapter->msix_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); - if (!adapter->msix_mem) { + if (adapter->msix_mem == NULL) { /* May not be enabled */ device_printf(adapter->dev, "Unable to map MSIX table \n"); goto msi; } val = pci_msix_count(dev); - /* We only need 3 vectors */ - if (val > 3) + /* We only need/want 3 vectors */ + if (val >= 3) val = 3; - if ((val != 3) && (val != 5)) { - bus_release_resource(dev, SYS_RES_MEMORY, - PCIR_BAR(EM_MSIX_BAR), adapter->msix_mem); - adapter->msix_mem = NULL; + else { device_printf(adapter->dev, - "MSIX: incorrect vectors, using MSI\n"); + "MSIX: insufficient vectors, using MSI\n"); goto msi; } - if (pci_alloc_msix(dev, &val) == 0) { + if ((pci_alloc_msix(dev, &val) == 0) && (val == 3)) { device_printf(adapter->dev, "Using MSIX interrupts " "with %d vectors\n", val); + return (val); } - return (val); + /* + ** If MSIX alloc failed or provided us with + ** less than needed, free and fall through to MSI + */ + pci_release_msi(dev); } msi: - val = pci_msi_count(dev); - if (val == 1 && pci_alloc_msi(dev, &val) == 0) { - adapter->msix = 1; + if (adapter->msix_mem != NULL) { + bus_release_resource(dev, SYS_RES_MEMORY, + PCIR_BAR(EM_MSIX_BAR), adapter->msix_mem); + adapter->msix_mem = NULL; + } + val = 1; + if (pci_alloc_msi(dev, &val) == 0) { device_printf(adapter->dev,"Using an MSI interrupt\n"); return (val); } @@ -3805,17 +3837,9 @@ em_txeof(struct tx_ring *txr) EM_TX_LOCK_ASSERT(txr); #ifdef DEV_NETMAP - if (ifp->if_capenable & IFCAP_NETMAP) { - struct netmap_adapter *na = NA(ifp); - - selwakeuppri(&na->tx_rings[txr->me].si, PI_NET); - EM_TX_UNLOCK(txr); - EM_CORE_LOCK(adapter); - selwakeuppri(&na->tx_si, PI_NET); - EM_CORE_UNLOCK(adapter); - EM_TX_LOCK(txr); + if (netmap_tx_irq(ifp, txr->me | + (NETMAP_LOCKED_ENTER | NETMAP_LOCKED_EXIT))) return; - } #endif /* DEV_NETMAP */ /* No work, make sure watchdog is off */ @@ -4256,8 +4280,6 @@ em_free_receive_buffers(struct rx_ring *rxr) * Enable receive unit. * **********************************************************************/ -#define MAX_INTS_PER_SEC 8000 -#define DEFAULT_ITR 1000000000/(MAX_INTS_PER_SEC * 256) static void em_initialize_receive_unit(struct adapter *adapter) @@ -4299,11 +4321,12 @@ em_initialize_receive_unit(struct adapter *adapter) E1000_WRITE_REG(hw, E1000_RFCTL, E1000_RFCTL_ACK_DIS); } - if (ifp->if_capenable & IFCAP_RXCSUM) { - rxcsum = E1000_READ_REG(hw, E1000_RXCSUM); - rxcsum |= (E1000_RXCSUM_IPOFL | E1000_RXCSUM_TUOFL); - E1000_WRITE_REG(hw, E1000_RXCSUM, rxcsum); - } + rxcsum = E1000_READ_REG(hw, E1000_RXCSUM); + if (ifp->if_capenable & IFCAP_RXCSUM) + rxcsum |= E1000_RXCSUM_TUOFL; + else + rxcsum &= ~E1000_RXCSUM_TUOFL; + E1000_WRITE_REG(hw, E1000_RXCSUM, rxcsum); /* ** XXX TEMPORARY WORKAROUND: on some systems with 82573 @@ -4317,6 +4340,8 @@ em_initialize_receive_unit(struct adapter *adapter) for (int i = 0; i < adapter->num_queues; i++, rxr++) { /* Setup the Base and Length of the Rx Descriptor Ring */ + u32 rdt = adapter->num_rx_desc - 1; /* default */ + bus_addr = rxr->rxdma.dma_paddr; E1000_WRITE_REG(hw, E1000_RDLEN(i), adapter->num_rx_desc * sizeof(struct e1000_rx_desc)); @@ -4328,18 +4353,11 @@ em_initialize_receive_unit(struct adapter *adapter) /* * an init() while a netmap client is active must * preserve the rx buffers passed to userspace. - * In this driver it means we adjust RDT to - * something different from na->num_rx_desc - 1. */ - if (ifp->if_capenable & IFCAP_NETMAP) { - struct netmap_adapter *na = NA(adapter->ifp); - struct netmap_kring *kring = &na->rx_rings[i]; - int t = na->num_rx_desc - 1 - kring->nr_hwavail; - - E1000_WRITE_REG(hw, E1000_RDT(i), t); - } else + if (ifp->if_capenable & IFCAP_NETMAP) + rdt -= NA(adapter->ifp)->rx_rings[i].nr_hwavail; #endif /* DEV_NETMAP */ - E1000_WRITE_REG(hw, E1000_RDT(i), adapter->num_rx_desc - 1); + E1000_WRITE_REG(hw, E1000_RDT(i), rdt); } /* Set PTHRESH for improved jumbo performance */ @@ -4416,17 +4434,8 @@ em_rxeof(struct rx_ring *rxr, int count, int *done) EM_RX_LOCK(rxr); #ifdef DEV_NETMAP - if (ifp->if_capenable & IFCAP_NETMAP) { - struct netmap_adapter *na = NA(ifp); - - na->rx_rings[rxr->me].nr_kflags |= NKR_PENDINTR; - selwakeuppri(&na->rx_rings[rxr->me].si, PI_NET); - EM_RX_UNLOCK(rxr); - EM_CORE_LOCK(adapter); - selwakeuppri(&na->rx_si, PI_NET); - EM_CORE_UNLOCK(adapter); - return (0); - } + if (netmap_rx_irq(ifp, rxr->me | NETMAP_LOCKED_ENTER, &processed)) + return (FALSE); #endif /* DEV_NETMAP */ for (i = rxr->next_to_check, processed = 0; count != 0;) { @@ -4621,31 +4630,23 @@ em_fixup_rx(struct rx_ring *rxr) static void em_receive_checksum(struct e1000_rx_desc *rx_desc, struct mbuf *mp) { + mp->m_pkthdr.csum_flags = 0; + /* Ignore Checksum bit is set */ - if (rx_desc->status & E1000_RXD_STAT_IXSM) { - mp->m_pkthdr.csum_flags = 0; + if (rx_desc->status & E1000_RXD_STAT_IXSM) return; - } - if (rx_desc->status & E1000_RXD_STAT_IPCS) { - /* Did it pass? */ - if (!(rx_desc->errors & E1000_RXD_ERR_IPE)) { - /* IP Checksum Good */ - mp->m_pkthdr.csum_flags = CSUM_IP_CHECKED; - mp->m_pkthdr.csum_flags |= CSUM_IP_VALID; + if (rx_desc->errors & (E1000_RXD_ERR_TCPE | E1000_RXD_ERR_IPE)) + return; - } else { - mp->m_pkthdr.csum_flags = 0; - } - } + /* IP Checksum Good? */ + if (rx_desc->status & E1000_RXD_STAT_IPCS) + mp->m_pkthdr.csum_flags = (CSUM_IP_CHECKED | CSUM_IP_VALID); - if (rx_desc->status & E1000_RXD_STAT_TCPCS) { - /* Did it pass? */ - if (!(rx_desc->errors & E1000_RXD_ERR_TCPE)) { - mp->m_pkthdr.csum_flags |= - (CSUM_DATA_VALID | CSUM_PSEUDO_HDR); - mp->m_pkthdr.csum_data = htons(0xffff); - } + /* TCP or UDP checksum */ + if (rx_desc->status & (E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS)) { + mp->m_pkthdr.csum_flags |= (CSUM_DATA_VALID | CSUM_PSEUDO_HDR); + mp->m_pkthdr.csum_data = htons(0xffff); } } @@ -5624,6 +5625,8 @@ em_sysctl_int_delay(SYSCTL_HANDLER_ARGS) return (EINVAL); info->value = usecs; ticks = EM_USECS_TO_TICKS(usecs); + if (info->offset == E1000_ITR) /* units are 256ns here */ + ticks *= 4; adapter = info->adapter; diff --git a/freebsd/sys/dev/e1000/if_em.h b/freebsd/sys/dev/e1000/if_em.h index f1afbadb..09d81d25 100644 --- a/freebsd/sys/dev/e1000/if_em.h +++ b/freebsd/sys/dev/e1000/if_em.h @@ -429,6 +429,7 @@ struct adapter { struct em_int_delay_info tx_abs_int_delay; struct em_int_delay_info rx_int_delay; struct em_int_delay_info rx_abs_int_delay; + struct em_int_delay_info tx_itr; /* Misc stats maintained by the driver */ unsigned long dropped_pkts; diff --git a/freebsd/sys/dev/e1000/if_igb.c b/freebsd/sys/dev/e1000/if_igb.c index a3c7fede..e26a867c 100644 --- a/freebsd/sys/dev/e1000/if_igb.c +++ b/freebsd/sys/dev/e1000/if_igb.c @@ -35,16 +35,17 @@ /*$FreeBSD$*/ -#ifdef HAVE_KERNEL_OPTION_HEADERS -#include <rtems/bsd/local/opt_device_polling.h> #include <rtems/bsd/local/opt_inet.h> #include <rtems/bsd/local/opt_inet6.h> + +#ifdef HAVE_KERNEL_OPTION_HEADERS +#include <rtems/bsd/local/opt_device_polling.h> #include <rtems/bsd/local/opt_altq.h> #endif #include <rtems/bsd/sys/param.h> #include <sys/systm.h> -#if __FreeBSD_version >= 800000 +#ifndef IGB_LEGACY_TX #include <sys/buf_ring.h> #endif #include <sys/bus.h> @@ -102,7 +103,7 @@ int igb_display_debug_stats = 0; /********************************************************************* * Driver version: *********************************************************************/ -char igb_driver_version[] = "version - 2.3.9 - 8"; +char igb_driver_version[] = "version - 2.3.10"; /********************************************************************* @@ -181,7 +182,7 @@ static int igb_detach(device_t); static int igb_shutdown(device_t); static int igb_suspend(device_t); static int igb_resume(device_t); -#if __FreeBSD_version >= 800000 +#ifndef IGB_LEGACY_TX static int igb_mq_start(struct ifnet *, struct mbuf *); static int igb_mq_start_locked(struct ifnet *, struct tx_ring *); static void igb_qflush(struct ifnet *); @@ -376,8 +377,9 @@ SYSCTL_INT(_hw_igb, OID_AUTO, header_split, CTLFLAG_RDTUN, &igb_header_split, 0, "Enable receive mbuf header split"); /* -** This will autoconfigure based on -** the number of CPUs if left at 0. +** This will autoconfigure based on the +** number of CPUs and max supported +** MSIX messages if left at 0. */ static int igb_num_queues = 0; TUNABLE_INT("hw.igb.num_queues", &igb_num_queues); @@ -852,7 +854,7 @@ igb_resume(device_t dev) (ifp->if_drv_flags & IFF_DRV_RUNNING) && adapter->link_active) { for (int i = 0; i < adapter->num_queues; i++, txr++) { IGB_TX_LOCK(txr); -#if __FreeBSD_version >= 800000 +#ifndef IGB_LEGACY_TX /* Process the stack queue only if not depleted */ if (((txr->queue_status & IGB_QUEUE_DEPLETED) == 0) && !drbr_empty(ifp, txr->br)) @@ -870,7 +872,7 @@ igb_resume(device_t dev) } -#if __FreeBSD_version < 800000 +#ifdef IGB_LEGACY_TX /********************************************************************* * Transmit entry point @@ -948,7 +950,7 @@ igb_start(struct ifnet *ifp) return; } -#else /* __FreeBSD_version >= 800000 */ +#else /* ~IGB_LEGACY_TX */ /* ** Multiqueue Transmit Entry: @@ -972,7 +974,13 @@ igb_mq_start(struct ifnet *ifp, struct mbuf *m) que = &adapter->queues[i]; err = drbr_enqueue(ifp, txr->br, m); - taskqueue_enqueue(que->tq, &txr->txq_task); + if (err) + return (err); + if (IGB_TX_TRYLOCK(txr)) { + err = igb_mq_start_locked(ifp, txr); + IGB_TX_UNLOCK(txr); + } else + taskqueue_enqueue(que->tq, &txr->txq_task); return (err); } @@ -981,8 +989,8 @@ static int igb_mq_start_locked(struct ifnet *ifp, struct tx_ring *txr) { struct adapter *adapter = txr->adapter; - struct mbuf *buf; - int err = 0, enq = 0; + struct mbuf *next; + int err = 0, enq; IGB_TX_LOCK_ASSERT(txr); @@ -990,22 +998,32 @@ igb_mq_start_locked(struct ifnet *ifp, struct tx_ring *txr) adapter->link_active == 0) return (ENETDOWN); + enq = 0; + /* Process the queue */ - buf = drbr_dequeue(ifp, txr->br); - while (buf != NULL) { - if ((err = igb_xmit(txr, &buf)) != 0) { - if (buf != NULL) - err = drbr_enqueue(ifp, txr->br, buf); + while ((next = drbr_peek(ifp, txr->br)) != NULL) { + if ((err = igb_xmit(txr, &next)) != 0) { + if (next == NULL) { + /* It was freed, move forward */ + drbr_advance(ifp, txr->br); + } else { + /* + * Still have one left, it may not be + * the same since the transmit function + * may have changed it. + */ + drbr_putback(ifp, txr->br, next); + } break; } + drbr_advance(ifp, txr->br); enq++; - ifp->if_obytes += buf->m_pkthdr.len; - if (buf->m_flags & M_MCAST) + ifp->if_obytes += next->m_pkthdr.len; + if (next->m_flags & M_MCAST) ifp->if_omcasts++; - ETHER_BPF_MTAP(ifp, buf); + ETHER_BPF_MTAP(ifp, next); if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) break; - buf = drbr_dequeue(ifp, txr->br); } if (enq > 0) { /* Set the watchdog */ @@ -1053,7 +1071,7 @@ igb_qflush(struct ifnet *ifp) } if_qflush(ifp); } -#endif /* __FreeBSD_version >= 800000 */ +#endif /* ~IGB_LEGACY_TX */ /********************************************************************* * Ioctl entry point @@ -1379,7 +1397,7 @@ igb_handle_que(void *context, int pending) IGB_TX_LOCK(txr); igb_txeof(txr); -#if __FreeBSD_version >= 800000 +#ifndef IGB_LEGACY_TX /* Process the stack queue only if not depleted */ if (((txr->queue_status & IGB_QUEUE_DEPLETED) == 0) && !drbr_empty(ifp, txr->br)) @@ -1430,7 +1448,7 @@ igb_handle_link_locked(struct adapter *adapter) if ((ifp->if_drv_flags & IFF_DRV_RUNNING) && adapter->link_active) { for (int i = 0; i < adapter->num_queues; i++, txr++) { IGB_TX_LOCK(txr); -#if __FreeBSD_version >= 800000 +#ifndef IGB_LEGACY_TX /* Process the stack queue only if not depleted */ if (((txr->queue_status & IGB_QUEUE_DEPLETED) == 0) && !drbr_empty(ifp, txr->br)) @@ -1532,7 +1550,7 @@ igb_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) do { more = igb_txeof(txr); } while (loop-- && more); -#if __FreeBSD_version >= 800000 +#ifndef IGB_LEGACY_TX if (!drbr_empty(ifp, txr->br)) igb_mq_start_locked(ifp, txr); #else @@ -1562,12 +1580,16 @@ igb_msix_que(void *arg) u32 newitr = 0; bool more_rx; + /* Ignore spurious interrupts */ + if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) + return; + E1000_WRITE_REG(&adapter->hw, E1000_EIMC, que->eims); ++que->irqs; IGB_TX_LOCK(txr); igb_txeof(txr); -#if __FreeBSD_version >= 800000 +#ifndef IGB_LEGACY_TX /* Process the stack queue only if not depleted */ if (((txr->queue_status & IGB_QUEUE_DEPLETED) == 0) && !drbr_empty(ifp, txr->br)) @@ -2087,7 +2109,9 @@ static void igb_disable_promisc(struct adapter *adapter) { struct e1000_hw *hw = &adapter->hw; + struct ifnet *ifp = adapter->ifp; u32 reg; + int mcnt = 0; if (adapter->vf_ifp) { e1000_promisc_set_vf(hw, e1000_promisc_disabled); @@ -2095,7 +2119,31 @@ igb_disable_promisc(struct adapter *adapter) } reg = E1000_READ_REG(hw, E1000_RCTL); reg &= (~E1000_RCTL_UPE); - reg &= (~E1000_RCTL_MPE); + if (ifp->if_flags & IFF_ALLMULTI) + mcnt = MAX_NUM_MULTICAST_ADDRESSES; + else { + struct ifmultiaddr *ifma; +#if __FreeBSD_version < 800000 + IF_ADDR_LOCK(ifp); +#else + if_maddr_rlock(ifp); +#endif + TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { + if (ifma->ifma_addr->sa_family != AF_LINK) + continue; + if (mcnt == MAX_NUM_MULTICAST_ADDRESSES) + break; + mcnt++; + } +#if __FreeBSD_version < 800000 + IF_ADDR_UNLOCK(ifp); +#else + if_maddr_runlock(ifp); +#endif + } + /* Don't disable if in MAX groups */ + if (mcnt < MAX_NUM_MULTICAST_ADDRESSES) + reg &= (~E1000_RCTL_MPE); E1000_WRITE_REG(hw, E1000_RCTL, reg); } @@ -2370,16 +2418,8 @@ igb_identify_hardware(struct adapter *adapter) device_t dev = adapter->dev; /* Make sure our PCI config space has the necessary stuff set */ + pci_enable_busmaster(dev); adapter->hw.bus.pci_cmd_word = pci_read_config(dev, PCIR_COMMAND, 2); - if (!((adapter->hw.bus.pci_cmd_word & PCIM_CMD_BUSMASTEREN) && - (adapter->hw.bus.pci_cmd_word & PCIM_CMD_MEMEN))) { - INIT_DEBUGOUT("Memory Access and/or Bus Master " - "bits were not set!\n"); - adapter->hw.bus.pci_cmd_word |= - (PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN); - pci_write_config(dev, PCIR_COMMAND, - adapter->hw.bus.pci_cmd_word, 2); - } /* Save off the information about this board */ adapter->hw.vendor_id = pci_get_vendor(dev); @@ -2439,7 +2479,6 @@ igb_allocate_legacy(struct adapter *adapter) { device_t dev = adapter->dev; struct igb_queue *que = adapter->queues; - struct tx_ring *txr = adapter->tx_rings; int error, rid = 0; /* Turn off all interrupts */ @@ -2458,8 +2497,8 @@ igb_allocate_legacy(struct adapter *adapter) return (ENXIO); } -#if __FreeBSD_version >= 800000 - TASK_INIT(&txr->txq_task, 0, igb_deferred_mq_start, txr); +#ifndef IGB_LEGACY_TX + TASK_INIT(&que->txr->txq_task, 0, igb_deferred_mq_start, que->txr); #endif /* @@ -2542,7 +2581,7 @@ igb_allocate_msix(struct adapter *adapter) i,igb_last_bind_cpu); igb_last_bind_cpu = CPU_NEXT(igb_last_bind_cpu); } -#if __FreeBSD_version >= 800000 +#ifndef IGB_LEGACY_TX TASK_INIT(&que->txr->txq_task, 0, igb_deferred_mq_start, que->txr); #endif @@ -2768,7 +2807,7 @@ igb_free_pci_resources(struct adapter *adapter) for (int i = 0; i < adapter->num_queues; i++, que++) { if (que->tq != NULL) { -#if __FreeBSD_version >= 800000 +#ifndef IGB_LEGACY_TX taskqueue_drain(que->tq, &que->txr->txq_task); #endif taskqueue_drain(que->tq, &que->que_task); @@ -2803,24 +2842,19 @@ igb_setup_msix(struct adapter *adapter) goto msi; /* First try MSI/X */ + msgs = pci_msix_count(dev); + if (msgs == 0) + goto msi; rid = PCIR_BAR(IGB_MSIX_BAR); adapter->msix_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); - if (!adapter->msix_mem) { + if (adapter->msix_mem == NULL) { /* May not be enabled */ device_printf(adapter->dev, "Unable to map MSIX table \n"); goto msi; } - msgs = pci_msix_count(dev); - if (msgs == 0) { /* system has msix disabled */ - bus_release_resource(dev, SYS_RES_MEMORY, - PCIR_BAR(IGB_MSIX_BAR), adapter->msix_mem); - adapter->msix_mem = NULL; - goto msi; - } - /* Figure out a reasonable auto config value */ queues = (mp_ncpus > (msgs-1)) ? (msgs-1) : mp_ncpus; @@ -2863,20 +2897,32 @@ igb_setup_msix(struct adapter *adapter) "MSIX Configuration Problem, " "%d vectors configured, but %d queues wanted!\n", msgs, want); - return (0); + goto msi; } - if ((msgs) && pci_alloc_msix(dev, &msgs) == 0) { + if ((pci_alloc_msix(dev, &msgs) == 0) && (msgs == want)) { device_printf(adapter->dev, "Using MSIX interrupts with %d vectors\n", msgs); adapter->num_queues = queues; return (msgs); } + /* + ** If MSIX alloc failed or provided us with + ** less than needed, free and fall through to MSI + */ + pci_release_msi(dev); + msi: - msgs = pci_msi_count(dev); - if (msgs == 1 && pci_alloc_msi(dev, &msgs) == 0) { - device_printf(adapter->dev," Using MSI interrupt\n"); + if (adapter->msix_mem != NULL) { + bus_release_resource(dev, SYS_RES_MEMORY, + PCIR_BAR(IGB_MSIX_BAR), adapter->msix_mem); + adapter->msix_mem = NULL; + } + msgs = 1; + if (pci_alloc_msi(dev, &msgs) == 0) { + device_printf(adapter->dev," Using an MSI interrupt\n"); return (msgs); } + device_printf(adapter->dev," Using a Legacy interrupt\n"); return (0); } @@ -3078,7 +3124,7 @@ igb_setup_interface(device_t dev, struct adapter *adapter) ifp->if_softc = adapter; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = igb_ioctl; -#if __FreeBSD_version >= 800000 +#ifndef IGB_LEGACY_TX ifp->if_transmit = igb_mq_start; ifp->if_qflush = igb_qflush; #else @@ -3322,7 +3368,7 @@ igb_allocate_queues(struct adapter *adapter) error = ENOMEM; goto err_tx_desc; } -#if __FreeBSD_version >= 800000 +#ifndef IGB_LEGACY_TX /* Allocate a buf ring */ txr->br = buf_ring_alloc(igb_buf_ring_size, M_DEVBUF, M_WAITOK, &txr->tx_mtx); @@ -3383,7 +3429,7 @@ err_tx_desc: igb_dma_free(adapter, &txr->txdma); free(adapter->rx_rings, M_DEVBUF); rx_fail: -#if __FreeBSD_version >= 800000 +#ifndef IGB_LEGACY_TX buf_ring_free(txr->br, M_DEVBUF); #endif free(adapter->tx_rings, M_DEVBUF); @@ -3641,7 +3687,7 @@ igb_free_transmit_buffers(struct tx_ring *txr) tx_buffer->map = NULL; } } -#if __FreeBSD_version >= 800000 +#ifndef IGB_LEGACY_TX if (txr->br != NULL) buf_ring_free(txr->br, M_DEVBUF); #endif @@ -3863,17 +3909,9 @@ igb_txeof(struct tx_ring *txr) IGB_TX_LOCK_ASSERT(txr); #ifdef DEV_NETMAP - if (ifp->if_capenable & IFCAP_NETMAP) { - struct netmap_adapter *na = NA(ifp); - - selwakeuppri(&na->tx_rings[txr->me].si, PI_NET); - IGB_TX_UNLOCK(txr); - IGB_CORE_LOCK(adapter); - selwakeuppri(&na->tx_si, PI_NET); - IGB_CORE_UNLOCK(adapter); - IGB_TX_LOCK(txr); - return FALSE; - } + if (netmap_tx_irq(ifp, txr->me | + (NETMAP_LOCKED_ENTER|NETMAP_LOCKED_EXIT))) + return (FALSE); #endif /* DEV_NETMAP */ if (txr->tx_avail == adapter->num_tx_desc) { txr->queue_status = IGB_QUEUE_IDLE; @@ -4727,17 +4765,8 @@ igb_rxeof(struct igb_queue *que, int count, int *done) BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); #ifdef DEV_NETMAP - if (ifp->if_capenable & IFCAP_NETMAP) { - struct netmap_adapter *na = NA(ifp); - - na->rx_rings[rxr->me].nr_kflags |= NKR_PENDINTR; - selwakeuppri(&na->rx_rings[rxr->me].si, PI_NET); - IGB_RX_UNLOCK(rxr); - IGB_CORE_LOCK(adapter); - selwakeuppri(&na->rx_si, PI_NET); - IGB_CORE_UNLOCK(adapter); - return (0); - } + if (netmap_rx_irq(ifp, rxr->me | NETMAP_LOCKED_ENTER, &processed)) + return (FALSE); #endif /* DEV_NETMAP */ /* Main clean loop */ @@ -4862,7 +4891,7 @@ igb_rxeof(struct igb_queue *que, int count, int *done) rxr->fmp->m_pkthdr.ether_vtag = vtag; rxr->fmp->m_flags |= M_VLANTAG; } -#if __FreeBSD_version >= 800000 +#ifndef IGB_LEGACY_TX rxr->fmp->m_pkthdr.flowid = que->msix; rxr->fmp->m_flags |= M_FLOWID; #endif diff --git a/freebsd/sys/dev/e1000/if_igb.h b/freebsd/sys/dev/e1000/if_igb.h index f286e67a..6f3a3a54 100644 --- a/freebsd/sys/dev/e1000/if_igb.h +++ b/freebsd/sys/dev/e1000/if_igb.h @@ -297,7 +297,7 @@ struct tx_ring { u32 next_to_clean; volatile u16 tx_avail; struct igb_tx_buffer *tx_buffers; -#if __FreeBSD_version >= 800000 +#ifndef IGB_LEGACY_TX struct buf_ring *br; struct task txq_task; #endif diff --git a/freebsd/sys/dev/e1000/if_lem.c b/freebsd/sys/dev/e1000/if_lem.c index aa64f655..5127445c 100644 --- a/freebsd/sys/dev/e1000/if_lem.c +++ b/freebsd/sys/dev/e1000/if_lem.c @@ -34,10 +34,11 @@ ******************************************************************************/ /*$FreeBSD$*/ -#ifdef HAVE_KERNEL_OPTION_HEADERS -#include <rtems/bsd/local/opt_device_polling.h> #include <rtems/bsd/local/opt_inet.h> #include <rtems/bsd/local/opt_inet6.h> + +#ifdef HAVE_KERNEL_OPTION_HEADERS +#include <rtems/bsd/local/opt_device_polling.h> #endif #include <rtems/bsd/sys/param.h> @@ -87,7 +88,7 @@ /********************************************************************* * Legacy Em Driver version: *********************************************************************/ -char lem_driver_version[] = "1.0.5"; +char lem_driver_version[] = "1.0.6"; /********************************************************************* * PCI Device ID Table @@ -283,6 +284,9 @@ MODULE_DEPEND(lem, ether, 1, 1, 1); #define EM_TICKS_TO_USECS(ticks) ((1024 * (ticks) + 500) / 1000) #define EM_USECS_TO_TICKS(usecs) ((1000 * (usecs) + 512) / 1024) +#define MAX_INTS_PER_SEC 8000 +#define DEFAULT_ITR (1000000000/(MAX_INTS_PER_SEC * 256)) + static int lem_tx_int_delay_dflt = EM_TICKS_TO_USECS(EM_TIDV); static int lem_rx_int_delay_dflt = EM_TICKS_TO_USECS(EM_RDTR); static int lem_tx_abs_int_delay_dflt = EM_TICKS_TO_USECS(EM_TADV); @@ -444,6 +448,11 @@ lem_attach(device_t dev) &adapter->tx_abs_int_delay, E1000_REGISTER(&adapter->hw, E1000_TADV), lem_tx_abs_int_delay_dflt); + lem_add_int_delay_sysctl(adapter, "itr", + "interrupt delay limit in usecs/4", + &adapter->tx_itr, + E1000_REGISTER(&adapter->hw, E1000_ITR), + DEFAULT_ITR); } /* Sysctls for limiting the amount of work done in the taskqueue */ @@ -1339,12 +1348,16 @@ lem_handle_rxtx(void *context, int pending) if (ifp->if_drv_flags & IFF_DRV_RUNNING) { - lem_rxeof(adapter, adapter->rx_process_limit, NULL); + bool more = lem_rxeof(adapter, adapter->rx_process_limit, NULL); EM_TX_LOCK(adapter); lem_txeof(adapter); if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) lem_start_locked(ifp); EM_TX_UNLOCK(adapter); + if (more) { + taskqueue_enqueue(adapter->tq, &adapter->rxtx_task); + return; + } } if (ifp->if_drv_flags & IFF_DRV_RUNNING) @@ -1858,12 +1871,37 @@ lem_set_promisc(struct adapter *adapter) static void lem_disable_promisc(struct adapter *adapter) { - u32 reg_rctl; + struct ifnet *ifp = adapter->ifp; + u32 reg_rctl; + int mcnt = 0; reg_rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL); - reg_rctl &= (~E1000_RCTL_UPE); - reg_rctl &= (~E1000_RCTL_MPE); + if (ifp->if_flags & IFF_ALLMULTI) + mcnt = MAX_NUM_MULTICAST_ADDRESSES; + else { + struct ifmultiaddr *ifma; +#if __FreeBSD_version < 800000 + IF_ADDR_LOCK(ifp); +#else + if_maddr_rlock(ifp); +#endif + TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { + if (ifma->ifma_addr->sa_family != AF_LINK) + continue; + if (mcnt == MAX_NUM_MULTICAST_ADDRESSES) + break; + mcnt++; + } +#if __FreeBSD_version < 800000 + IF_ADDR_UNLOCK(ifp); +#else + if_maddr_runlock(ifp); +#endif + } + /* Don't disable if in MAX groups */ + if (mcnt < MAX_NUM_MULTICAST_ADDRESSES) + reg_rctl &= (~E1000_RCTL_MPE); reg_rctl &= (~E1000_RCTL_SBP); E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl); } @@ -2083,16 +2121,8 @@ lem_identify_hardware(struct adapter *adapter) device_t dev = adapter->dev; /* Make sure our PCI config space has the necessary stuff set */ + pci_enable_busmaster(dev); adapter->hw.bus.pci_cmd_word = pci_read_config(dev, PCIR_COMMAND, 2); - if (!((adapter->hw.bus.pci_cmd_word & PCIM_CMD_BUSMASTEREN) && - (adapter->hw.bus.pci_cmd_word & PCIM_CMD_MEMEN))) { - device_printf(dev, "Memory Access and/or Bus Master bits " - "were not set!\n"); - adapter->hw.bus.pci_cmd_word |= - (PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN); - pci_write_config(dev, PCIR_COMMAND, - adapter->hw.bus.pci_cmd_word, 2); - } /* Save off the information about this board */ adapter->hw.vendor_id = pci_get_vendor(dev); @@ -2957,10 +2987,8 @@ lem_txeof(struct adapter *adapter) EM_TX_LOCK_ASSERT(adapter); #ifdef DEV_NETMAP - if (ifp->if_capenable & IFCAP_NETMAP) { - selwakeuppri(&NA(ifp)->tx_rings[0].si, PI_NET); + if (netmap_tx_irq(ifp, 0 | (NETMAP_LOCKED_ENTER|NETMAP_LOCKED_EXIT))) return; - } #endif /* DEV_NETMAP */ if (adapter->num_tx_desc_avail == adapter->num_tx_desc) return; @@ -3248,8 +3276,6 @@ lem_setup_receive_structures(struct adapter *adapter) * Enable receive unit. * **********************************************************************/ -#define MAX_INTS_PER_SEC 8000 -#define DEFAULT_ITR 1000000000/(MAX_INTS_PER_SEC * 256) static void lem_initialize_receive_unit(struct adapter *adapter) @@ -3340,19 +3366,13 @@ lem_initialize_receive_unit(struct adapter *adapter) * Tail Descriptor Pointers */ E1000_WRITE_REG(&adapter->hw, E1000_RDH(0), 0); + rctl = adapter->num_rx_desc - 1; /* default RDT value */ #ifdef DEV_NETMAP /* preserve buffers already made available to clients */ - if (ifp->if_capenable & IFCAP_NETMAP) { - struct netmap_adapter *na = NA(adapter->ifp); - struct netmap_kring *kring = &na->rx_rings[0]; - int t = na->num_rx_desc - 1 - kring->nr_hwavail; - - if (t >= na->num_rx_desc) - t -= na->num_rx_desc; - E1000_WRITE_REG(&adapter->hw, E1000_RDT(0), t); - } else + if (ifp->if_capenable & IFCAP_NETMAP) + rctl -= NA(adapter->ifp)->rx_rings[0].nr_hwavail; #endif /* DEV_NETMAP */ - E1000_WRITE_REG(&adapter->hw, E1000_RDT(0), adapter->num_rx_desc - 1); + E1000_WRITE_REG(&adapter->hw, E1000_RDT(0), rctl); return; } @@ -3436,13 +3456,8 @@ lem_rxeof(struct adapter *adapter, int count, int *done) BUS_DMASYNC_POSTREAD); #ifdef DEV_NETMAP - if (ifp->if_capenable & IFCAP_NETMAP) { - struct netmap_adapter *na = NA(ifp); - na->rx_rings[0].nr_kflags |= NKR_PENDINTR; - selwakeuppri(&na->rx_rings[0].si, PI_NET); - EM_RX_UNLOCK(adapter); - return (0); - } + if (netmap_rx_irq(ifp, 0 | NETMAP_LOCKED_ENTER, &rx_sent)) + return (FALSE); #endif /* DEV_NETMAP */ if (!((current_desc->status) & E1000_RXD_STAT_DD)) { @@ -4586,6 +4601,8 @@ lem_sysctl_int_delay(SYSCTL_HANDLER_ARGS) return (EINVAL); info->value = usecs; ticks = EM_USECS_TO_TICKS(usecs); + if (info->offset == E1000_ITR) /* units are 256ns here */ + ticks *= 4; adapter = info->adapter; diff --git a/freebsd/sys/dev/e1000/if_lem.h b/freebsd/sys/dev/e1000/if_lem.h index c1973e55..235277d7 100644 --- a/freebsd/sys/dev/e1000/if_lem.h +++ b/freebsd/sys/dev/e1000/if_lem.h @@ -363,6 +363,7 @@ struct adapter { struct em_int_delay_info tx_abs_int_delay; struct em_int_delay_info rx_int_delay; struct em_int_delay_info rx_abs_int_delay; + struct em_int_delay_info tx_itr; /* * Transmit definitions diff --git a/freebsd/sys/dev/fxp/if_fxp.c b/freebsd/sys/dev/fxp/if_fxp.c index c67d4827..806163a2 100644 --- a/freebsd/sys/dev/fxp/if_fxp.c +++ b/freebsd/sys/dev/fxp/if_fxp.c @@ -292,7 +292,7 @@ static device_method_t fxp_methods[] = { DEVMETHOD(miibus_writereg, fxp_miibus_writereg), DEVMETHOD(miibus_statchg, fxp_miibus_statchg), - { 0, 0 } + DEVMETHOD_END }; static driver_t fxp_driver = { @@ -303,8 +303,9 @@ static driver_t fxp_driver = { static devclass_t fxp_devclass; -DRIVER_MODULE(fxp, pci, fxp_driver, fxp_devclass, 0, 0); -DRIVER_MODULE(miibus, fxp, miibus_driver, miibus_devclass, 0, 0); +DRIVER_MODULE_ORDERED(fxp, pci, fxp_driver, fxp_devclass, NULL, NULL, + SI_ORDER_ANY); +DRIVER_MODULE(miibus, fxp, miibus_driver, miibus_devclass, NULL, NULL); static struct resource_spec fxp_res_spec_mem[] = { { SYS_RES_MEMORY, FXP_PCI_MMBA, RF_ACTIVE }, @@ -453,7 +454,6 @@ fxp_attach(device_t dev) * Enable bus mastering. */ pci_enable_busmaster(dev); - val = pci_read_config(dev, PCIR_COMMAND, 2); /* * Figure out which we should try first - memory mapping or i/o mapping? @@ -525,7 +525,7 @@ fxp_attach(device_t dev) sc->revision != FXP_REV_82559S_A) { data = sc->eeprom[FXP_EEPROM_MAP_ID]; if ((data & 0x20) != 0 && - pci_find_extcap(sc->dev, PCIY_PMG, &pmc) == 0) + pci_find_cap(sc->dev, PCIY_PMG, &pmc) == 0) sc->flags |= FXP_FLAG_WOLCAP; } @@ -611,6 +611,7 @@ fxp_attach(device_t dev) * is a valid cacheline size (8 or 16 dwords), then tell * the board to turn on MWI. */ + val = pci_read_config(dev, PCIR_COMMAND, 2); if (val & PCIM_CMD_MWRICEN && pci_read_config(dev, PCIR_CACHELNSZ, 1) != 0) sc->flags |= FXP_FLAG_MWI_ENABLE; @@ -1068,7 +1069,7 @@ fxp_suspend(device_t dev) FXP_LOCK(sc); ifp = sc->ifp; - if (pci_find_extcap(sc->dev, PCIY_PMG, &pmc) == 0) { + if (pci_find_cap(sc->dev, PCIY_PMG, &pmc) == 0) { pmstat = pci_read_config(sc->dev, pmc + PCIR_POWER_STATUS, 2); pmstat &= ~(PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE); if ((ifp->if_capenable & IFCAP_WOL_MAGIC) != 0) { @@ -1103,7 +1104,7 @@ fxp_resume(device_t dev) FXP_LOCK(sc); - if (pci_find_extcap(sc->dev, PCIY_PMG, &pmc) == 0) { + if (pci_find_cap(sc->dev, PCIY_PMG, &pmc) == 0) { sc->flags &= ~FXP_FLAG_WOL; pmstat = pci_read_config(sc->dev, pmc + PCIR_POWER_STATUS, 2); /* Disable PME and clear PME status. */ @@ -1449,7 +1450,7 @@ fxp_encap(struct fxp_softc *sc, struct mbuf **m_head) if (M_WRITABLE(*m_head) == 0) { /* Get a writable copy. */ - m = m_dup(*m_head, M_DONTWAIT); + m = m_dup(*m_head, M_NOWAIT); m_freem(*m_head); if (m == NULL) { *m_head = NULL; @@ -1565,7 +1566,7 @@ fxp_encap(struct fxp_softc *sc, struct mbuf **m_head) error = bus_dmamap_load_mbuf_sg(sc->fxp_txmtag, txp->tx_map, *m_head, segs, &nseg, 0); if (error == EFBIG) { - m = m_collapse(*m_head, M_DONTWAIT, sc->maxtxseg); + m = m_collapse(*m_head, M_NOWAIT, sc->maxtxseg); if (m == NULL) { m_freem(*m_head); *m_head = NULL; @@ -2599,7 +2600,7 @@ fxp_ifmedia_upd(struct ifnet *ifp) mii = device_get_softc(sc->miibus); FXP_LOCK(sc); LIST_FOREACH(miisc, &mii->mii_phys, mii_list) - mii_phy_reset(miisc); + PHY_RESET(miisc); mii_mediachg(mii); FXP_UNLOCK(sc); return (0); @@ -2637,7 +2638,7 @@ fxp_new_rfabuf(struct fxp_softc *sc, struct fxp_rx *rxp) bus_dmamap_t tmp_map; int error; - m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); + m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); if (m == NULL) return (ENOBUFS); diff --git a/freebsd/sys/dev/mii/brgphy.c b/freebsd/sys/dev/mii/brgphy.c index e21e783e..de1249c3 100644 --- a/freebsd/sys/dev/mii/brgphy.c +++ b/freebsd/sys/dev/mii/brgphy.c @@ -70,9 +70,6 @@ static int brgphy_attach(device_t); struct brgphy_softc { struct mii_softc mii_sc; - int mii_oui; - int mii_model; - int mii_rev; int serdes_flags; /* Keeps track of the serdes type used */ #define BRGPHY_5706S 0x0001 #define BRGPHY_5708S 0x0002 @@ -119,39 +116,49 @@ static void brgphy_ethernet_wirespeed(struct mii_softc *); static void brgphy_jumbo_settings(struct mii_softc *, u_long); static const struct mii_phydesc brgphys[] = { - MII_PHY_DESC(xxBROADCOM, BCM5400), - MII_PHY_DESC(xxBROADCOM, BCM5401), - MII_PHY_DESC(xxBROADCOM, BCM5411), - MII_PHY_DESC(xxBROADCOM, BCM54K2), - MII_PHY_DESC(xxBROADCOM, BCM5701), - MII_PHY_DESC(xxBROADCOM, BCM5703), - MII_PHY_DESC(xxBROADCOM, BCM5704), - MII_PHY_DESC(xxBROADCOM, BCM5705), - MII_PHY_DESC(xxBROADCOM, BCM5706), - MII_PHY_DESC(xxBROADCOM, BCM5714), - MII_PHY_DESC(xxBROADCOM, BCM5750), - MII_PHY_DESC(xxBROADCOM, BCM5752), - MII_PHY_DESC(xxBROADCOM, BCM5754), - MII_PHY_DESC(xxBROADCOM, BCM5780), - MII_PHY_DESC(xxBROADCOM, BCM5708C), - MII_PHY_DESC(xxBROADCOM_ALT1, BCM5755), - MII_PHY_DESC(xxBROADCOM_ALT1, BCM5787), - MII_PHY_DESC(xxBROADCOM_ALT1, BCM5708S), - MII_PHY_DESC(xxBROADCOM_ALT1, BCM5709CAX), - MII_PHY_DESC(xxBROADCOM_ALT1, BCM5722), - MII_PHY_DESC(xxBROADCOM_ALT1, BCM5784), - MII_PHY_DESC(xxBROADCOM_ALT1, BCM5709C), - MII_PHY_DESC(xxBROADCOM_ALT1, BCM5761), - MII_PHY_DESC(xxBROADCOM_ALT1, BCM5709S), - MII_PHY_DESC(xxBROADCOM_ALT2, BCM5717C), - MII_PHY_DESC(xxBROADCOM_ALT2, BCM5719C), - MII_PHY_DESC(xxBROADCOM_ALT2, BCM5720C), - MII_PHY_DESC(xxBROADCOM_ALT2, BCM57765), - MII_PHY_DESC(xxBROADCOM_ALT2, BCM57780), - MII_PHY_DESC(BROADCOM2, BCM5906), + MII_PHY_DESC(BROADCOM, BCM5400), + MII_PHY_DESC(BROADCOM, BCM5401), + MII_PHY_DESC(BROADCOM, BCM5411), + MII_PHY_DESC(BROADCOM, BCM54K2), + MII_PHY_DESC(BROADCOM, BCM5701), + MII_PHY_DESC(BROADCOM, BCM5703), + MII_PHY_DESC(BROADCOM, BCM5704), + MII_PHY_DESC(BROADCOM, BCM5705), + MII_PHY_DESC(BROADCOM, BCM5706), + MII_PHY_DESC(BROADCOM, BCM5714), + MII_PHY_DESC(BROADCOM, BCM5421), + MII_PHY_DESC(BROADCOM, BCM5750), + MII_PHY_DESC(BROADCOM, BCM5752), + MII_PHY_DESC(BROADCOM, BCM5780), + MII_PHY_DESC(BROADCOM, BCM5708C), + MII_PHY_DESC(BROADCOM2, BCM5482), + MII_PHY_DESC(BROADCOM2, BCM5708S), + MII_PHY_DESC(BROADCOM2, BCM5709C), + MII_PHY_DESC(BROADCOM2, BCM5709S), + MII_PHY_DESC(BROADCOM2, BCM5709CAX), + MII_PHY_DESC(BROADCOM2, BCM5722), + MII_PHY_DESC(BROADCOM2, BCM5755), + MII_PHY_DESC(BROADCOM2, BCM5754), + MII_PHY_DESC(BROADCOM2, BCM5761), + MII_PHY_DESC(BROADCOM2, BCM5784), +#ifdef notyet /* better handled by ukphy(4) until WARs are implemented */ + MII_PHY_DESC(BROADCOM2, BCM5785), +#endif + MII_PHY_DESC(BROADCOM3, BCM5717C), + MII_PHY_DESC(BROADCOM3, BCM5719C), + MII_PHY_DESC(BROADCOM3, BCM5720C), + MII_PHY_DESC(BROADCOM3, BCM57765), + MII_PHY_DESC(BROADCOM3, BCM57780), + MII_PHY_DESC(xxBROADCOM_ALT1, BCM5906), MII_PHY_END }; +static const struct mii_phy_funcs brgphy_funcs = { + brgphy_service, + brgphy_status, + brgphy_reset +}; + #define HS21_PRODUCT_ID "IBM eServer BladeCenter HS21" #define HS21_BCM_CHIPID 0x57081021 @@ -190,41 +197,17 @@ brgphy_attach(device_t dev) struct bge_softc *bge_sc = NULL; struct bce_softc *bce_sc = NULL; struct mii_softc *sc; - struct mii_attach_args *ma; - struct mii_data *mii; struct ifnet *ifp; bsc = device_get_softc(dev); sc = &bsc->mii_sc; - ma = device_get_ivars(dev); - sc->mii_dev = device_get_parent(dev); - mii = ma->mii_data; - LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list); - - /* Initialize mii_softc structure */ - sc->mii_flags = miibus_get_flags(dev); - sc->mii_inst = mii->mii_instance++; - sc->mii_phy = ma->mii_phyno; - sc->mii_service = brgphy_service; - sc->mii_pdata = mii; - /* - * At least some variants wedge when isolating, at least some also - * don't support loopback. - */ - sc->mii_flags |= MIIF_NOISOLATE | MIIF_NOLOOP | MIIF_NOMANPAUSE; + mii_phy_dev_attach(dev, MIIF_NOISOLATE | MIIF_NOMANPAUSE, + &brgphy_funcs, 0); - /* Initialize brgphy_softc structure */ - bsc->mii_oui = MII_OUI(ma->mii_id1, ma->mii_id2); - bsc->mii_model = MII_MODEL(ma->mii_id2); - bsc->mii_rev = MII_REV(ma->mii_id2); bsc->serdes_flags = 0; ifp = sc->mii_pdata->mii_ifp; - if (bootverbose) - device_printf(dev, "OUI 0x%06x, model 0x%04x, rev. %d\n", - bsc->mii_oui, bsc->mii_model, bsc->mii_rev); - /* Find the MAC driver associated with this PHY. */ if (strcmp(ifp->if_dname, "bge") == 0) bge_sc = ifp->if_softc; @@ -232,11 +215,11 @@ brgphy_attach(device_t dev) bce_sc = ifp->if_softc; /* Handle any special cases based on the PHY ID */ - switch (bsc->mii_oui) { - case MII_OUI_xxBROADCOM: - switch (bsc->mii_model) { - case MII_MODEL_xxBROADCOM_BCM5706: - case MII_MODEL_xxBROADCOM_BCM5714: + switch (sc->mii_mpd_oui) { + case MII_OUI_BROADCOM: + switch (sc->mii_mpd_model) { + case MII_MODEL_BROADCOM_BCM5706: + case MII_MODEL_BROADCOM_BCM5714: /* * The 5464 PHY used in the 5706 supports both copper * and fiber interfaces over GMII. Need to check the @@ -254,13 +237,13 @@ brgphy_attach(device_t dev) break; } break; - case MII_OUI_xxBROADCOM_ALT1: - switch (bsc->mii_model) { - case MII_MODEL_xxBROADCOM_ALT1_BCM5708S: + case MII_OUI_BROADCOM2: + switch (sc->mii_mpd_model) { + case MII_MODEL_BROADCOM2_BCM5708S: bsc->serdes_flags |= BRGPHY_5708S; sc->mii_flags |= MIIF_HAVEFIBER; break; - case MII_MODEL_xxBROADCOM_ALT1_BCM5709S: + case MII_MODEL_BROADCOM2_BCM5709S: /* * XXX * 5720S and 5709S shares the same PHY id. @@ -276,15 +259,15 @@ brgphy_attach(device_t dev) break; } - brgphy_reset(sc); + PHY_RESET(sc); /* Read the PHY's capabilities. */ - sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask; + sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & sc->mii_capmask; if (sc->mii_capabilities & BMSR_EXTSTAT) sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR); device_printf(dev, " "); -#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL) +#define ADD(m, c) ifmedia_add(&sc->mii_pdata->mii_media, (m), (c), NULL) /* Add the supported media types */ if ((sc->mii_flags & MIIF_HAVEFIBER) == 0) { @@ -325,7 +308,6 @@ brgphy_attach(device_t dev) static int brgphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) { - struct brgphy_softc *bsc = (struct brgphy_softc *)sc; struct ifmedia_entry *ife = mii->mii_media.ifm_cur; int val; @@ -338,7 +320,7 @@ brgphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) break; /* Todo: Why is this here? Is it really needed? */ - brgphy_reset(sc); /* XXX hardware bug work-around */ + PHY_RESET(sc); /* XXX hardware bug work-around */ switch (IFM_SUBTYPE(ife->ifm_media)) { case IFM_AUTO: @@ -393,7 +375,7 @@ brgphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) } /* Update the media status. */ - brgphy_status(sc); + PHY_STATUS(sc); /* * Callback if something changed. Note that we need to poke @@ -402,20 +384,20 @@ brgphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) if (sc->mii_media_active != mii->mii_media_active || sc->mii_media_status != mii->mii_media_status || cmd == MII_MEDIACHG) { - switch (bsc->mii_oui) { - case MII_OUI_xxBROADCOM: - switch (bsc->mii_model) { - case MII_MODEL_xxBROADCOM_BCM5400: + switch (sc->mii_mpd_oui) { + case MII_OUI_BROADCOM: + switch (sc->mii_mpd_model) { + case MII_MODEL_BROADCOM_BCM5400: bcm5401_load_dspcode(sc); break; - case MII_MODEL_xxBROADCOM_BCM5401: - if (bsc->mii_rev == 1 || bsc->mii_rev == 3) + case MII_MODEL_BROADCOM_BCM5401: + if (sc->mii_mpd_rev == 1 || sc->mii_mpd_rev == 3) bcm5401_load_dspcode(sc); break; - case MII_MODEL_xxBROADCOM_BCM5411: + case MII_MODEL_BROADCOM_BCM5411: bcm5411_load_dspcode(sc); break; - case MII_MODEL_xxBROADCOM_BCM54K2: + case MII_MODEL_BROADCOM_BCM54K2: bcm54k2_load_dspcode(sc); break; } @@ -474,8 +456,7 @@ brgphy_setmedia(struct mii_softc *sc, int media) if (IFM_SUBTYPE(media) == IFM_1000_T) { gig |= BRGPHY_1000CTL_MSE; - if ((media & IFM_ETH_MASTER) != 0 || - (sc->mii_pdata->mii_ifp->if_flags & IFF_LINK0) != 0) + if ((media & IFM_ETH_MASTER) != 0) gig |= BRGPHY_1000CTL_MSC; } PHY_WRITE(sc, BRGPHY_MII_1000CTL, gig); @@ -625,10 +606,9 @@ brgphy_status(struct mii_softc *sc) static void brgphy_mii_phy_auto(struct mii_softc *sc, int media) { - struct brgphy_softc *bsc = (struct brgphy_softc *)sc; int anar, ktcr = 0; - brgphy_reset(sc); + PHY_RESET(sc); if ((sc->mii_flags & MIIF_HAVEFIBER) == 0) { anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | ANAR_CSMA; @@ -637,7 +617,7 @@ brgphy_mii_phy_auto(struct mii_softc *sc, int media) anar |= BRGPHY_ANAR_PC | BRGPHY_ANAR_ASP; PHY_WRITE(sc, BRGPHY_MII_ANAR, anar); ktcr = BRGPHY_1000CTL_AFD | BRGPHY_1000CTL_AHD; - if (bsc->mii_model == MII_MODEL_xxBROADCOM_BCM5701) + if (sc->mii_mpd_model == MII_MODEL_BROADCOM_BCM5701) ktcr |= BRGPHY_1000CTL_MSE | BRGPHY_1000CTL_MSC; PHY_WRITE(sc, BRGPHY_MII_1000CTL, ktcr); PHY_READ(sc, BRGPHY_MII_1000CTL); @@ -874,12 +854,11 @@ brgphy_ethernet_wirespeed(struct mii_softc *sc) static void brgphy_jumbo_settings(struct mii_softc *sc, u_long mtu) { - struct brgphy_softc *bsc = (struct brgphy_softc *)sc; uint32_t val; /* Set or clear jumbo frame settings in the PHY. */ if (mtu > ETHER_MAX_LEN) { - if (bsc->mii_model == MII_MODEL_xxBROADCOM_BCM5401) { + if (sc->mii_mpd_model == MII_MODEL_BROADCOM_BCM5401) { /* BCM5401 PHY cannot read-modify-write. */ PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x4c20); } else { @@ -907,7 +886,6 @@ brgphy_jumbo_settings(struct mii_softc *sc, u_long mtu) static void brgphy_reset(struct mii_softc *sc) { - struct brgphy_softc *bsc = (struct brgphy_softc *)sc; struct bge_softc *bge_sc = NULL; struct bce_softc *bce_sc = NULL; struct ifnet *ifp; @@ -929,30 +907,30 @@ brgphy_reset(struct mii_softc *sc) } /* Handle any PHY specific procedures following the reset. */ - switch (bsc->mii_oui) { - case MII_OUI_xxBROADCOM: - switch (bsc->mii_model) { - case MII_MODEL_xxBROADCOM_BCM5400: + switch (sc->mii_mpd_oui) { + case MII_OUI_BROADCOM: + switch (sc->mii_mpd_model) { + case MII_MODEL_BROADCOM_BCM5400: bcm5401_load_dspcode(sc); break; - case MII_MODEL_xxBROADCOM_BCM5401: - if (bsc->mii_rev == 1 || bsc->mii_rev == 3) + case MII_MODEL_BROADCOM_BCM5401: + if (sc->mii_mpd_rev == 1 || sc->mii_mpd_rev == 3) bcm5401_load_dspcode(sc); break; - case MII_MODEL_xxBROADCOM_BCM5411: + case MII_MODEL_BROADCOM_BCM5411: bcm5411_load_dspcode(sc); break; - case MII_MODEL_xxBROADCOM_BCM54K2: + case MII_MODEL_BROADCOM_BCM54K2: bcm54k2_load_dspcode(sc); break; } break; - case MII_OUI_xxBROADCOM_ALT2: - switch (bsc->mii_model) { - case MII_MODEL_xxBROADCOM_ALT2_BCM5717C: - case MII_MODEL_xxBROADCOM_ALT2_BCM5719C: - case MII_MODEL_xxBROADCOM_ALT2_BCM5720C: - case MII_MODEL_xxBROADCOM_ALT2_BCM57765: + case MII_OUI_BROADCOM3: + switch (sc->mii_mpd_model) { + case MII_MODEL_BROADCOM3_BCM5717C: + case MII_MODEL_BROADCOM3_BCM5719C: + case MII_MODEL_BROADCOM3_BCM5720C: + case MII_MODEL_BROADCOM3_BCM57765: return; } break; diff --git a/freebsd/sys/dev/mii/icsphy.c b/freebsd/sys/dev/mii/icsphy.c index 47474db7..3d5e6384 100644 --- a/freebsd/sys/dev/mii/icsphy.c +++ b/freebsd/sys/dev/mii/icsphy.c @@ -85,11 +85,6 @@ __FBSDID("$FreeBSD$"); static int icsphy_probe(device_t dev); static int icsphy_attach(device_t dev); -struct icsphy_softc { - struct mii_softc mii_sc; - int mii_model; -}; - static device_method_t icsphy_methods[] = { /* device interface */ DEVMETHOD(device_probe, icsphy_probe), @@ -104,7 +99,7 @@ static devclass_t icsphy_devclass; static driver_t icsphy_driver = { "icsphy", icsphy_methods, - sizeof(struct icsphy_softc) + sizeof(struct mii_softc) }; DRIVER_MODULE(icsphy, miibus, icsphy_driver, icsphy_devclass, 0, 0); @@ -114,13 +109,19 @@ static void icsphy_status(struct mii_softc *); static void icsphy_reset(struct mii_softc *); static const struct mii_phydesc icsphys[] = { - MII_PHY_DESC(xxICS, 1889), - MII_PHY_DESC(xxICS, 1890), - MII_PHY_DESC(xxICS, 1892), - MII_PHY_DESC(xxICS, 1893), + MII_PHY_DESC(ICS, 1889), + MII_PHY_DESC(ICS, 1890), + MII_PHY_DESC(ICS, 1892), + MII_PHY_DESC(ICS, 1893), MII_PHY_END }; +static const struct mii_phy_funcs icsphy_funcs = { + icsphy_service, + icsphy_status, + icsphy_reset +}; + static int icsphy_probe(device_t dev) { @@ -131,40 +132,9 @@ icsphy_probe(device_t dev) static int icsphy_attach(device_t dev) { - struct icsphy_softc *isc; - struct mii_softc *sc; - struct mii_attach_args *ma; - struct mii_data *mii; - - isc = device_get_softc(dev); - sc = &isc->mii_sc; - ma = device_get_ivars(dev); - sc->mii_dev = device_get_parent(dev); - mii = ma->mii_data; - LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list); - - sc->mii_flags = miibus_get_flags(dev); - sc->mii_inst = mii->mii_instance++; - sc->mii_phy = ma->mii_phyno; - sc->mii_service = icsphy_service; - sc->mii_pdata = mii; - - sc->mii_flags |= MIIF_NOISOLATE | MIIF_NOMANPAUSE; - - ifmedia_add(&mii->mii_media, - IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst), - MII_MEDIA_100_TX, NULL); - - isc->mii_model = MII_MODEL(ma->mii_id2); - icsphy_reset(sc); - - sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask; - device_printf(dev, " "); - mii_phy_add_media(sc); - printf("\n"); - - MIIBUS_MEDIAINIT(sc->mii_dev); + mii_phy_dev_attach(dev, MIIF_NOISOLATE | MIIF_NOMANPAUSE, + &icsphy_funcs, 1); return (0); } @@ -193,7 +163,7 @@ icsphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) } /* Update the media status. */ - icsphy_status(sc); + PHY_STATUS(sc); /* Callback if something changed. */ mii_phy_update(sc, cmd); @@ -253,16 +223,15 @@ icsphy_status(struct mii_softc *sc) static void icsphy_reset(struct mii_softc *sc) { - struct icsphy_softc *isc = (struct icsphy_softc *)sc; mii_phy_reset(sc); /* set powerdown feature */ - switch (isc->mii_model) { - case MII_MODEL_xxICS_1890: - case MII_MODEL_xxICS_1893: + switch (sc->mii_mpd_model) { + case MII_MODEL_ICS_1890: + case MII_MODEL_ICS_1893: PHY_WRITE(sc, MII_ICSPHY_ECR2, ECR2_100AUTOPWRDN); break; - case MII_MODEL_xxICS_1892: + case MII_MODEL_ICS_1892: PHY_WRITE(sc, MII_ICSPHY_ECR2, ECR2_10AUTOPWRDN|ECR2_100AUTOPWRDN); break; diff --git a/freebsd/sys/dev/mii/mii.c b/freebsd/sys/dev/mii/mii.c index e3a3ec84..d1f55cb0 100644 --- a/freebsd/sys/dev/mii/mii.c +++ b/freebsd/sys/dev/mii/mii.c @@ -72,6 +72,7 @@ static miibus_writereg_t miibus_writereg; static miibus_linkchg_t miibus_linkchg; static miibus_mediainit_t miibus_mediainit; +static unsigned char mii_bitreverse(unsigned char x); static device_method_t miibus_methods[] = { /* device interface */ @@ -303,19 +304,12 @@ miibus_statchg(device_t dev) { device_t parent; struct mii_data *mii; - struct ifnet *ifp; parent = device_get_parent(dev); MIIBUS_STATCHG(parent); mii = device_get_softc(dev); - - /* - * Note that each NIC's softc must start with an ifnet pointer. - * XXX: EVIL HACK! - */ - ifp = *(struct ifnet **)device_get_softc(parent); - ifp->if_baudrate = ifmedia_baudrate(mii->mii_media_active); + mii->mii_ifp->if_baudrate = ifmedia_baudrate(mii->mii_media_active); } static void @@ -337,11 +331,7 @@ miibus_linkchg(device_t dev) link_state = LINK_STATE_DOWN; } else link_state = LINK_STATE_UNKNOWN; - /* - * Note that each NIC's softc must start with an ifnet pointer. - * XXX: EVIL HACK! - */ - if_link_state_change(*(struct ifnet**)device_get_softc(parent), link_state); + if_link_state_change(mii->mii_ifp, link_state); } static void @@ -493,6 +483,7 @@ mii_attach(device_t dev, device_t *miibus, struct ifnet *ifp, ma.mii_id1 = MIIBUS_READREG(dev, ma.mii_phyno, MII_PHYIDR1); ma.mii_id2 = MIIBUS_READREG(dev, ma.mii_phyno, MII_PHYIDR2); + ma.mii_offset = ivars->mii_offset; args = malloc(sizeof(struct mii_attach_args), M_DEVBUF, M_NOWAIT); if (args == NULL) @@ -544,21 +535,6 @@ mii_attach(device_t dev, device_t *miibus, struct ifnet *ifp, return (rv); } -int -mii_phy_probe(device_t dev, device_t *child, ifm_change_cb_t ifmedia_upd, - ifm_stat_cb_t ifmedia_sts) -{ - struct ifnet *ifp; - - /* - * Note that each NIC's softc must start with an ifnet pointer. - * XXX: EVIL HACK! - */ - ifp = *(struct ifnet **)device_get_softc(dev); - return (mii_attach(dev, child, ifp, ifmedia_upd, ifmedia_sts, - BMSR_DEFCAPMASK, MII_PHY_ANY, MII_OFFSET_ANY, 0)); -} - /* * Media changed; notify all PHYs. */ @@ -588,7 +564,7 @@ mii_mediachg(struct mii_data *mii) BMCR_ISO); continue; } - rv = (*child->mii_service)(child, mii, MII_MEDIACHG); + rv = PHY_SERVICE(child, mii, MII_MEDIACHG); if (rv) return (rv); } @@ -611,7 +587,7 @@ mii_tick(struct mii_data *mii) */ if (IFM_INST(ife->ifm_media) != child->mii_inst) continue; - (void)(*child->mii_service)(child, mii, MII_TICK); + (void)PHY_SERVICE(child, mii, MII_TICK); } } @@ -633,7 +609,7 @@ mii_pollstat(struct mii_data *mii) */ if (IFM_INST(ife->ifm_media) != child->mii_inst) continue; - (void)(*child->mii_service)(child, mii, MII_POLLSTAT); + (void)PHY_SERVICE(child, mii, MII_POLLSTAT); } } @@ -648,3 +624,25 @@ mii_down(struct mii_data *mii) LIST_FOREACH(child, &mii->mii_phys, mii_list) mii_phy_down(child); } + +static unsigned char +mii_bitreverse(unsigned char x) +{ + static unsigned const char nibbletab[16] = { + 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15 + }; + + return ((nibbletab[x & 15] << 4) | nibbletab[x >> 4]); +} + +u_int +mii_oui(u_int id1, u_int id2) +{ + u_int h; + + h = (id1 << 6) | (id2 >> 10); + + return ((mii_bitreverse(h >> 16) << 16) | + (mii_bitreverse((h >> 8) & 0xff) << 8) | + mii_bitreverse(h & 0xff)); +} diff --git a/freebsd/sys/dev/mii/mii.h b/freebsd/sys/dev/mii/mii.h index 5316f1eb..668fb8fb 100644 --- a/freebsd/sys/dev/mii/mii.h +++ b/freebsd/sys/dev/mii/mii.h @@ -106,10 +106,6 @@ #define IDR2_MODEL 0x03f0 /* vendor model */ #define IDR2_REV 0x000f /* vendor revision */ -#define MII_OUI(id1, id2) (((id1) << 6) | ((id2) >> 10)) -#define MII_MODEL(id2) (((id2) & IDR2_MODEL) >> 4) -#define MII_REV(id2) ((id2) & IDR2_REV) - #define MII_ANAR 0x04 /* Autonegotiation advertisement (rw) */ /* section 28.2.4.1 and 37.2.6.1 */ #define ANAR_NP 0x8000 /* Next page (ro) */ diff --git a/freebsd/sys/dev/mii/mii_physubr.c b/freebsd/sys/dev/mii/mii_physubr.c index 7fc4135c..e2725ba6 100644 --- a/freebsd/sys/dev/mii/mii_physubr.c +++ b/freebsd/sys/dev/mii/mii_physubr.c @@ -58,7 +58,7 @@ __FBSDID("$FreeBSD$"); /* * Media to register setting conversion table. Order matters. */ -const struct mii_media mii_media_table[MII_NMEDIA] = { +static const struct mii_media mii_media_table[MII_NMEDIA] = { /* None */ { BMCR_ISO, ANAR_CSMA, 0, }, @@ -152,9 +152,6 @@ mii_phy_setmedia(struct mii_softc *sc) } } - if ((ife->ifm_media & IFM_LOOP) != 0) - bmcr |= BMCR_LOOP; - PHY_WRITE(sc, MII_ANAR, anar); PHY_WRITE(sc, MII_BMCR, bmcr); if ((sc->mii_flags & MIIF_HAVE_GTCR) != 0) @@ -253,7 +250,7 @@ mii_phy_tick(struct mii_softc *sc) return (EJUSTRETURN); sc->mii_ticks = 0; - mii_phy_reset(sc); + PHY_RESET(sc); mii_phy_auto(sc); return (0); } @@ -311,99 +308,6 @@ mii_phy_update(struct mii_softc *sc, int cmd) } /* - * Given an ifmedia word, return the corresponding ANAR value. - */ -int -mii_anar(int media) -{ - int rv; - - switch (media & (IFM_TMASK|IFM_NMASK|IFM_FDX)) { - case IFM_ETHER|IFM_10_T: - rv = ANAR_10|ANAR_CSMA; - break; - case IFM_ETHER|IFM_10_T|IFM_FDX: - rv = ANAR_10_FD|ANAR_CSMA; - break; - case IFM_ETHER|IFM_100_TX: - rv = ANAR_TX|ANAR_CSMA; - break; - case IFM_ETHER|IFM_100_TX|IFM_FDX: - rv = ANAR_TX_FD|ANAR_CSMA; - break; - case IFM_ETHER|IFM_100_T4: - rv = ANAR_T4|ANAR_CSMA; - break; - default: - rv = 0; - break; - } - - return (rv); -} - -/* - * Initialize generic PHY media based on BMSR, called when a PHY is - * attached. We expect to be set up to print a comma-separated list - * of media names. Does not print a newline. - */ -void -mii_add_media(struct mii_softc *sc) -{ - struct mii_data *mii = sc->mii_pdata; - const char *sep = ""; - - if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0) { - printf("no media present"); - return; - } - -#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL) -#define PRINT(s) printf("%s%s", sep, s); sep = ", " - - if (sc->mii_capabilities & BMSR_10THDX) { - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, sc->mii_inst), 0); - PRINT("10baseT"); - } - if (sc->mii_capabilities & BMSR_10TFDX) { - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, IFM_FDX, sc->mii_inst), - BMCR_FDX); - PRINT("10baseT-FDX"); - } - if (sc->mii_capabilities & BMSR_100TXHDX) { - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, 0, sc->mii_inst), - BMCR_S100); - PRINT("100baseTX"); - } - if (sc->mii_capabilities & BMSR_100TXFDX) { - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_FDX, sc->mii_inst), - BMCR_S100|BMCR_FDX); - PRINT("100baseTX-FDX"); - } - if (sc->mii_capabilities & BMSR_100T4) { - /* - * XXX How do you enable 100baseT4? I assume we set - * XXX BMCR_S100 and then assume the PHYs will take - * XXX watever action is necessary to switch themselves - * XXX into T4 mode. - */ - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_T4, 0, sc->mii_inst), - BMCR_S100); - PRINT("100baseT4"); - } - if (sc->mii_capabilities & BMSR_ANEG) { - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst), - BMCR_AUTOEN); - PRINT("auto"); - } - - - -#undef ADD -#undef PRINT -} - -/* * Initialize generic PHY media based on BMSR, called when a PHY is * attached. We expect to be set up to print a comma-separated list * of media names. Does not print a newline. @@ -621,6 +525,50 @@ mii_phy_dev_probe(device_t dev, const struct mii_phydesc *mpd, int mrv) return (ENXIO); } +void +mii_phy_dev_attach(device_t dev, u_int flags, const struct mii_phy_funcs *mpf, + int add_media) +{ + struct mii_softc *sc; + struct mii_attach_args *ma; + struct mii_data *mii; + + sc = device_get_softc(dev); + ma = device_get_ivars(dev); + sc->mii_dev = device_get_parent(dev); + mii = ma->mii_data; + LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list); + + sc->mii_flags = flags | miibus_get_flags(dev); + sc->mii_mpd_oui = MII_OUI(ma->mii_id1, ma->mii_id2); + sc->mii_mpd_model = MII_MODEL(ma->mii_id2); + sc->mii_mpd_rev = MII_REV(ma->mii_id2); + sc->mii_capmask = ma->mii_capmask; + sc->mii_inst = mii->mii_instance++; + sc->mii_phy = ma->mii_phyno; + sc->mii_offset = ma->mii_offset; + sc->mii_funcs = mpf; + sc->mii_pdata = mii; + + if (bootverbose) + device_printf(dev, "OUI 0x%06x, model 0x%04x, rev. %d\n", + sc->mii_mpd_oui, sc->mii_mpd_model, sc->mii_mpd_rev); + + if (add_media == 0) + return; + + PHY_RESET(sc); + + sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & sc->mii_capmask; + if (sc->mii_capabilities & BMSR_EXTSTAT) + sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR); + device_printf(dev, " "); + mii_phy_add_media(sc); + printf("\n"); + + MIIBUS_MEDIAINIT(sc->mii_dev); +} + /* * Return the flow control status flag from MII_ANAR & MII_ANLPAR. */ diff --git a/freebsd/sys/dev/mii/miivar.h b/freebsd/sys/dev/mii/miivar.h index ac58ac20..34b0e9ed 100644 --- a/freebsd/sys/dev/mii/miivar.h +++ b/freebsd/sys/dev/mii/miivar.h @@ -83,10 +83,13 @@ struct mii_data { typedef struct mii_data mii_data_t; /* - * This call is used by the MII layer to call into the PHY driver - * to perform a `service request'. + * Functions provided by the PHY to perform various functions. */ -typedef int (*mii_downcall_t)(struct mii_softc *, struct mii_data *, int); +struct mii_phy_funcs { + int (*pf_service)(struct mii_softc *, struct mii_data *, int); + void (*pf_status)(struct mii_softc *); + void (*pf_reset)(struct mii_softc *); +}; /* * Requests that can be made to the downcall. @@ -105,10 +108,17 @@ struct mii_softc { LIST_ENTRY(mii_softc) mii_list; /* entry on parent's PHY list */ + uint32_t mii_mpd_oui; /* the PHY's OUI (MII_OUI())*/ + uint32_t mii_mpd_model; /* the PHY's model (MII_MODEL())*/ + uint32_t mii_mpd_rev; /* the PHY's revision (MII_REV())*/ + u_int mii_capmask; /* capability mask for BMSR */ u_int mii_phy; /* our MII address */ + u_int mii_offset; /* first PHY, second PHY, etc. */ u_int mii_inst; /* instance for ifmedia */ - mii_downcall_t mii_service; /* our downcall */ + /* Our PHY functions. */ + const struct mii_phy_funcs *mii_funcs; + struct mii_data *mii_pdata; /* pointer to parent's mii_data */ u_int mii_flags; /* misc. flags; see below */ @@ -124,7 +134,9 @@ typedef struct mii_softc mii_softc_t; /* mii_flags */ #define MIIF_INITDONE 0x00000001 /* has been initialized (mii_data) */ #define MIIF_NOISOLATE 0x00000002 /* do not isolate the PHY */ +#if 0 #define MIIF_NOLOOP 0x00000004 /* no loopback capability */ +#endif #define MIIF_DOINGAUTO 0x00000008 /* doing autonegotiation (mii_softc) */ #define MIIF_AUTOTSLEEP 0x00000010 /* use tsleep(), not callout() */ #define MIIF_HAVEFIBER 0x00000020 /* from parent: has fiber interface */ @@ -210,6 +222,15 @@ struct mii_media { #define PHY_WRITE(p, r, v) \ MIIBUS_WRITEREG((p)->mii_dev, (p)->mii_phy, (r), (v)) +#define PHY_SERVICE(p, d, o) \ + (*(p)->mii_funcs->pf_service)((p), (d), (o)) + +#define PHY_STATUS(p) \ + (*(p)->mii_funcs->pf_status)(p) + +#define PHY_RESET(p) \ + (*(p)->mii_funcs->pf_reset)(p) + enum miibus_device_ivars { MIIBUS_IVAR_FLAGS }; @@ -227,13 +248,10 @@ extern driver_t miibus_driver; int mii_attach(device_t, device_t *, struct ifnet *, ifm_change_cb_t, ifm_stat_cb_t, int, int, int, int); -int mii_anar(int); void mii_down(struct mii_data *); int mii_mediachg(struct mii_data *); void mii_tick(struct mii_data *); void mii_pollstat(struct mii_data *); -int mii_phy_probe(device_t, device_t *, ifm_change_cb_t, ifm_stat_cb_t); -void mii_add_media(struct mii_softc *); void mii_phy_add_media(struct mii_softc *); int mii_phy_auto(struct mii_softc *); @@ -250,8 +268,16 @@ const struct mii_phydesc * mii_phy_match(const struct mii_attach_args *ma, const struct mii_phydesc * mii_phy_match_gen(const struct mii_attach_args *ma, const struct mii_phydesc *mpd, size_t endlen); int mii_phy_dev_probe(device_t dev, const struct mii_phydesc *mpd, int mrv); +void mii_phy_dev_attach(device_t dev, u_int flags, + const struct mii_phy_funcs *mpf, int add_media); void ukphy_status(struct mii_softc *); + +u_int mii_oui(u_int, u_int); +#define MII_OUI(id1, id2) mii_oui(id1, id2) +#define MII_MODEL(id2) (((id2) & IDR2_MODEL) >> 4) +#define MII_REV(id2) ((id2) & IDR2_REV) + #endif /* _KERNEL */ #endif /* _DEV_MII_MIIVAR_H_ */ diff --git a/freebsd/sys/dev/pci/pci.c b/freebsd/sys/dev/pci/pci.c index ea1e841e..94eeb844 100644 --- a/freebsd/sys/dev/pci/pci.c +++ b/freebsd/sys/dev/pci/pci.c @@ -64,6 +64,7 @@ __FBSDID("$FreeBSD$"); #include <dev/pci/pcivar.h> #include <dev/pci/pci_private.h> +#include <dev/usb/controller/xhcireg.h> #include <dev/usb/controller/ehcireg.h> #include <dev/usb/controller/ohcireg.h> #include <dev/usb/controller/uhcireg.h> @@ -71,13 +72,6 @@ __FBSDID("$FreeBSD$"); #include <rtems/bsd/local/pcib_if.h> #include <rtems/bsd/local/pci_if.h> -#ifdef __HAVE_ACPI -#include <contrib/dev/acpica/include/acpi.h> -#include <rtems/bsd/local/acpi_if.h> -#else -#define ACPI_PWR_FOR_SLEEP(x, y, z) -#endif - /* * XXX: Due to a limitation of the bus_dma_tag_create() API, we cannot * specify a 4GB boundary on 32-bit targets. Usually this does not @@ -97,6 +91,7 @@ __FBSDID("$FreeBSD$"); (((cfg)->hdrtype == PCIM_HDRTYPE_NORMAL && reg == PCIR_BIOS) || \ ((cfg)->hdrtype == PCIM_HDRTYPE_BRIDGE && reg == PCIR_BIOS_1)) +static int pci_has_quirk(uint32_t devid, int quirk); static pci_addr_t pci_mapbase(uint64_t mapreg); static const char *pci_maptype(uint64_t mapreg); static int pci_mapsize(uint64_t testval); @@ -138,6 +133,7 @@ static void pci_enable_msix(device_t dev, u_int index, static void pci_mask_msix(device_t dev, u_int index); static void pci_unmask_msix(device_t dev, u_int index); static int pci_msi_blacklisted(void); +static int pci_msix_blacklisted(void); static void pci_resume_msi(device_t dev); static void pci_resume_msix(device_t dev); static int pci_remap_intr_method(device_t bus, device_t dev, @@ -201,7 +197,7 @@ static device_method_t pci_methods[] = { DEFINE_CLASS_0(pci, pci_driver, pci_methods, sizeof(struct pci_softc)); static devclass_t pci_devclass; -DRIVER_MODULE(pci, pcib, pci_driver, pci_devclass, pci_modevent, 0); +DRIVER_MODULE(pci, pcib, pci_driver, pci_devclass, pci_modevent, NULL); MODULE_VERSION(pci, 1); static char *pci_vendordata; @@ -211,15 +207,16 @@ struct pci_quirk { uint32_t devid; /* Vendor/device of the card */ int type; #define PCI_QUIRK_MAP_REG 1 /* PCI map register in weird place */ -#define PCI_QUIRK_DISABLE_MSI 2 /* MSI/MSI-X doesn't work */ +#define PCI_QUIRK_DISABLE_MSI 2 /* Neither MSI nor MSI-X work */ #define PCI_QUIRK_ENABLE_MSI_VM 3 /* Older chipset in VM where MSI works */ #define PCI_QUIRK_UNMAP_REG 4 /* Ignore PCI map register */ +#define PCI_QUIRK_DISABLE_MSIX 5 /* MSI-X doesn't work */ int arg1; int arg2; }; static const struct pci_quirk pci_quirks[] = { - /* The Intel 82371AB and 82443MX has a map register at offset 0x90. */ + /* The Intel 82371AB and 82443MX have a map register at offset 0x90. */ { 0x71138086, PCI_QUIRK_MAP_REG, 0x90, 0 }, { 0x719b8086, PCI_QUIRK_MAP_REG, 0x90, 0 }, /* As does the Serverworks OSB4 (the SMBus mapping register) */ @@ -254,8 +251,8 @@ static const struct pci_quirk pci_quirks[] = { * MSI-X allocation doesn't work properly for devices passed through * by VMware up to at least ESXi 5.1. */ - { 0x079015ad, PCI_QUIRK_DISABLE_MSI, 0, 0 }, /* PCI/PCI-X */ - { 0x07a015ad, PCI_QUIRK_DISABLE_MSI, 0, 0 }, /* PCIe */ + { 0x079015ad, PCI_QUIRK_DISABLE_MSIX, 0, 0 }, /* PCI/PCI-X */ + { 0x07a015ad, PCI_QUIRK_DISABLE_MSIX, 0, 0 }, /* PCIe */ /* * Some virtualization environments emulate an older chipset @@ -297,6 +294,12 @@ SYSCTL_INT(_hw_pci, OID_AUTO, enable_io_modes, CTLFLAG_RW, enable these bits correctly. We'd like to do this all the time, but there\n\ are some peripherals that this causes problems with."); +static int pci_do_realloc_bars = 0; +TUNABLE_INT("hw.pci.realloc_bars", &pci_do_realloc_bars); +SYSCTL_INT(_hw_pci, OID_AUTO, realloc_bars, CTLFLAG_RW, + &pci_do_realloc_bars, 0, + "Attempt to allocate a new range for any BARs whose original firmware-assigned ranges fail to allocate during the initial device scan."); + static int pci_do_power_nodriver = 0; TUNABLE_INT("hw.pci.do_power_nodriver", &pci_do_power_nodriver); SYSCTL_INT(_hw_pci, OID_AUTO, do_power_nodriver, CTLFLAG_RW, @@ -306,12 +309,18 @@ disable. 1 means conservatively place devices into D3 state. 2 means\n\ agressively place devices into D3 state. 3 means put absolutely everything\n\ in D3 state."); -static int pci_do_power_resume = 1; +int pci_do_power_resume = 1; TUNABLE_INT("hw.pci.do_power_resume", &pci_do_power_resume); SYSCTL_INT(_hw_pci, OID_AUTO, do_power_resume, CTLFLAG_RW, &pci_do_power_resume, 1, "Transition from D3 -> D0 on resume."); +int pci_do_power_suspend = 1; +TUNABLE_INT("hw.pci.do_power_suspend", &pci_do_power_suspend); +SYSCTL_INT(_hw_pci, OID_AUTO, do_power_suspend, CTLFLAG_RW, + &pci_do_power_suspend, 1, + "Transition from D0 -> D3 on suspend."); + static int pci_do_msi = 1; TUNABLE_INT("hw.pci.enable_msi", &pci_do_msi); SYSCTL_INT(_hw_pci, OID_AUTO, enable_msi, CTLFLAG_RW, &pci_do_msi, 1, @@ -325,7 +334,7 @@ SYSCTL_INT(_hw_pci, OID_AUTO, enable_msix, CTLFLAG_RW, &pci_do_msix, 1, static int pci_honor_msi_blacklist = 1; TUNABLE_INT("hw.pci.honor_msi_blacklist", &pci_honor_msi_blacklist); SYSCTL_INT(_hw_pci, OID_AUTO, honor_msi_blacklist, CTLFLAG_RD, - &pci_honor_msi_blacklist, 1, "Honor chipset blacklist for MSI"); + &pci_honor_msi_blacklist, 1, "Honor chipset blacklist for MSI/MSI-X"); #if defined(__i386__) || defined(__amd64__) static int pci_usb_takeover = 1; @@ -338,6 +347,18 @@ SYSCTL_INT(_hw_pci, OID_AUTO, usb_early_takeover, CTLFLAG_RDTUN, Disable this if you depend on BIOS emulation of USB devices, that is\n\ you use USB devices (like keyboard or mouse) but do not load USB drivers"); +static int +pci_has_quirk(uint32_t devid, int quirk) +{ + const struct pci_quirk *q; + + for (q = &pci_quirks[0]; q->devid; q++) { + if (q->devid == devid && q->type == quirk) + return (1); + } + return (0); +} + /* Find a device_t by bus/slot/function in domain 0 */ device_t @@ -515,12 +536,12 @@ pci_maprange(uint64_t mapreg) static void pci_fixancient(pcicfgregs *cfg) { - if (cfg->hdrtype != 0) + if ((cfg->hdrtype & PCIM_HDRTYPE) != PCIM_HDRTYPE_NORMAL) return; /* PCI to PCI bridges use header type 1 */ if (cfg->baseclass == PCIC_BRIDGE && cfg->subclass == PCIS_BRIDGE_PCI) - cfg->hdrtype = 1; + cfg->hdrtype = PCIM_HDRTYPE_BRIDGE; } /* extract header type specific config data */ @@ -529,16 +550,16 @@ static void pci_hdrtypedata(device_t pcib, int b, int s, int f, pcicfgregs *cfg) { #define REG(n, w) PCIB_READ_CONFIG(pcib, b, s, f, n, w) - switch (cfg->hdrtype) { - case 0: + switch (cfg->hdrtype & PCIM_HDRTYPE) { + case PCIM_HDRTYPE_NORMAL: cfg->subvendor = REG(PCIR_SUBVEND_0, 2); cfg->subdevice = REG(PCIR_SUBDEV_0, 2); cfg->nummaps = PCI_MAXMAPS_0; break; - case 1: + case PCIM_HDRTYPE_BRIDGE: cfg->nummaps = PCI_MAXMAPS_1; break; - case 2: + case PCIM_HDRTYPE_CARDBUS: cfg->subvendor = REG(PCIR_SUBVEND_2, 2); cfg->subdevice = REG(PCIR_SUBDEV_2, 2); cfg->nummaps = PCI_MAXMAPS_2; @@ -635,11 +656,11 @@ pci_read_cap(device_t pcib, pcicfgregs *cfg) int ptr, nextptr, ptrptr; switch (cfg->hdrtype & PCIM_HDRTYPE) { - case 0: - case 1: + case PCIM_HDRTYPE_NORMAL: + case PCIM_HDRTYPE_BRIDGE: ptrptr = PCIR_CAP_PTR; break; - case 2: + case PCIM_HDRTYPE_CARDBUS: ptrptr = PCIR_CAP_PTR_2; /* cardbus capabilities ptr */ break; default: @@ -667,7 +688,7 @@ pci_read_cap(device_t pcib, pcicfgregs *cfg) if (cfg->pp.pp_cap == 0) { cfg->pp.pp_cap = REG(ptr + PCIR_POWER_CAP, 2); cfg->pp.pp_status = ptr + PCIR_POWER_STATUS; - cfg->pp.pp_pmcsr = ptr + PCIR_POWER_PMCSR; + cfg->pp.pp_bse = ptr + PCIR_POWER_BSE; if ((nextptr - ptr) > PCIR_POWER_DATA) cfg->pp.pp_data = ptr + PCIR_POWER_DATA; } @@ -730,7 +751,8 @@ pci_read_cap(device_t pcib, pcicfgregs *cfg) break; case PCIY_SUBVENDOR: /* Should always be true. */ - if ((cfg->hdrtype & PCIM_HDRTYPE) == 1) { + if ((cfg->hdrtype & PCIM_HDRTYPE) == + PCIM_HDRTYPE_BRIDGE) { val = REG(ptr + PCIR_SUBVENDCAP_ID, 4); cfg->subvendor = val & 0xffff; cfg->subdevice = val >> 16; @@ -744,7 +766,8 @@ pci_read_cap(device_t pcib, pcicfgregs *cfg) * PCI-express or HT chipsets might match on * this check as well. */ - if ((cfg->hdrtype & PCIM_HDRTYPE) == 1) + if ((cfg->hdrtype & PCIM_HDRTYPE) == + PCIM_HDRTYPE_BRIDGE) pcix_chipset = 1; break; case PCIY_EXPRESS: /* PCI-express */ @@ -1202,11 +1225,11 @@ pci_find_extcap_method(device_t dev, device_t child, int capability, * Determine the start pointer of the capabilities list. */ switch (cfg->hdrtype & PCIM_HDRTYPE) { - case 0: - case 1: + case PCIM_HDRTYPE_NORMAL: + case PCIM_HDRTYPE_BRIDGE: ptr = PCIR_CAP_PTR; break; - case 2: + case PCIM_HDRTYPE_CARDBUS: ptr = PCIR_CAP_PTR_2; break; default: @@ -1354,8 +1377,8 @@ pci_alloc_msix_method(device_t dev, device_t child, int *count) if (cfg->msi.msi_alloc != 0 || cfg->msix.msix_alloc != 0) return (ENXIO); - /* If MSI is blacklisted for this system, fail. */ - if (pci_msi_blacklisted()) + /* If MSI-X is blacklisted for this system, fail. */ + if (pci_msix_blacklisted()) return (ENXIO); /* MSI-X capability present? */ @@ -1907,38 +1930,15 @@ pci_remap_intr_method(device_t bus, device_t dev, u_int irq) int pci_msi_device_blacklisted(device_t dev) { - const struct pci_quirk *q; if (!pci_honor_msi_blacklist) return (0); - for (q = &pci_quirks[0]; q->devid; q++) { - if (q->devid == pci_get_devid(dev) && - q->type == PCI_QUIRK_DISABLE_MSI) - return (1); - } - return (0); -} - -/* - * Returns true if a specified chipset supports MSI when it is - * emulated hardware in a virtual machine. - */ -static int -pci_msi_vm_chipset(device_t dev) -{ - const struct pci_quirk *q; - - for (q = &pci_quirks[0]; q->devid; q++) { - if (q->devid == pci_get_devid(dev) && - q->type == PCI_QUIRK_ENABLE_MSI_VM) - return (1); - } - return (0); + return (pci_has_quirk(pci_get_devid(dev), PCI_QUIRK_DISABLE_MSI)); } /* - * Determine if MSI is blacklisted globally on this sytem. Currently, + * Determine if MSI is blacklisted globally on this system. Currently, * we just check for blacklisted chipsets as represented by the * host-PCI bridge at device 0:0:0. In the future, it may become * necessary to check other system attributes, such as the kenv values @@ -1955,9 +1955,14 @@ pci_msi_blacklisted(void) /* Blacklist all non-PCI-express and non-PCI-X chipsets. */ if (!(pcie_chipset || pcix_chipset)) { if (vm_guest != VM_GUEST_NO) { + /* + * Whitelist older chipsets in virtual + * machines known to support MSI. + */ dev = pci_find_bsf(0, 0, 0); if (dev != NULL) - return (pci_msi_vm_chipset(dev) == 0); + return (!pci_has_quirk(pci_get_devid(dev), + PCI_QUIRK_ENABLE_MSI_VM)); } return (1); } @@ -1969,6 +1974,45 @@ pci_msi_blacklisted(void) } /* + * Returns true if the specified device is blacklisted because MSI-X + * doesn't work. Note that this assumes that if MSI doesn't work, + * MSI-X doesn't either. + */ +int +pci_msix_device_blacklisted(device_t dev) +{ + + if (!pci_honor_msi_blacklist) + return (0); + + if (pci_has_quirk(pci_get_devid(dev), PCI_QUIRK_DISABLE_MSIX)) + return (1); + + return (pci_msi_device_blacklisted(dev)); +} + +/* + * Determine if MSI-X is blacklisted globally on this system. If MSI + * is blacklisted, assume that MSI-X is as well. Check for additional + * chipsets where MSI works but MSI-X does not. + */ +static int +pci_msix_blacklisted(void) +{ + device_t dev; + + if (!pci_honor_msi_blacklist) + return (0); + + dev = pci_find_bsf(0, 0, 0); + if (dev != NULL && pci_has_quirk(pci_get_devid(dev), + PCI_QUIRK_DISABLE_MSIX)) + return (1); + + return (pci_msi_blacklisted()); +} + +/* * Attempt to allocate *count MSI messages. The actual number allocated is * returned in *count. After this function returns, each message will be * available to the driver as SYS_RES_IRQ resources starting at a rid 1. @@ -2745,22 +2789,40 @@ pci_add_map(device_t bus, device_t dev, int reg, struct resource_list *rl, * driver for this device will later inherit this resource in * pci_alloc_resource(). */ - res = resource_list_alloc(rl, bus, dev, type, ®, start, end, count, + res = resource_list_reserve(rl, bus, dev, type, ®, start, end, count, prefetch ? RF_PREFETCHABLE : 0); + if (pci_do_realloc_bars && res == NULL && (start != 0 || end != ~0ul)) { + /* + * If the allocation fails, try to allocate a resource for + * this BAR using any available range. The firmware felt + * it was important enough to assign a resource, so don't + * disable decoding if we can help it. + */ + resource_list_delete(rl, type, reg); + resource_list_add(rl, type, reg, 0, ~0ul, count); + res = resource_list_reserve(rl, bus, dev, type, ®, 0, ~0ul, + count, prefetch ? RF_PREFETCHABLE : 0); + } if (res == NULL) { /* - * If the allocation fails, clear the BAR and delete - * the resource list entry to force - * pci_alloc_resource() to allocate resources from the - * parent. + * If the allocation fails, delete the resource list entry + * and disable decoding for this device. + * + * If the driver requests this resource in the future, + * pci_reserve_map() will try to allocate a fresh + * resource range. */ resource_list_delete(rl, type, reg); - start = 0; + pci_disable_io(dev, type); + if (bootverbose) + device_printf(bus, + "pci%d:%d:%d:%d bar %#x failed to allocate\n", + pci_get_domain(dev), pci_get_bus(dev), + pci_get_slot(dev), pci_get_function(dev), reg); } else { start = rman_get_start(res); - rman_set_device(res, bus); + pci_write_bar(dev, pm, start); } - pci_write_bar(dev, pm, start); return (barlen); } @@ -2798,14 +2860,12 @@ pci_ata_maps(device_t bus, device_t dev, struct resource_list *rl, int force, } else { rid = PCIR_BAR(0); resource_list_add(rl, type, rid, 0x1f0, 0x1f7, 8); - r = resource_list_alloc(rl, bus, dev, type, &rid, 0x1f0, 0x1f7, - 8, 0); - rman_set_device(r, bus); + r = resource_list_reserve(rl, bus, dev, type, &rid, 0x1f0, + 0x1f7, 8, 0); rid = PCIR_BAR(1); resource_list_add(rl, type, rid, 0x3f6, 0x3f6, 1); - r = resource_list_alloc(rl, bus, dev, type, &rid, 0x3f6, 0x3f6, - 1, 0); - rman_set_device(r, bus); + r = resource_list_reserve(rl, bus, dev, type, &rid, 0x3f6, + 0x3f6, 1, 0); } if (progif & PCIP_STORAGE_IDE_MODESEC) { pci_add_map(bus, dev, PCIR_BAR(2), rl, force, @@ -2815,14 +2875,12 @@ pci_ata_maps(device_t bus, device_t dev, struct resource_list *rl, int force, } else { rid = PCIR_BAR(2); resource_list_add(rl, type, rid, 0x170, 0x177, 8); - r = resource_list_alloc(rl, bus, dev, type, &rid, 0x170, 0x177, - 8, 0); - rman_set_device(r, bus); + r = resource_list_reserve(rl, bus, dev, type, &rid, 0x170, + 0x177, 8, 0); rid = PCIR_BAR(3); resource_list_add(rl, type, rid, 0x376, 0x376, 1); - r = resource_list_alloc(rl, bus, dev, type, &rid, 0x376, 0x376, - 1, 0); - rman_set_device(r, bus); + r = resource_list_reserve(rl, bus, dev, type, &rid, 0x376, + 0x376, 1, 0); } pci_add_map(bus, dev, PCIR_BAR(4), rl, force, prefetchmask & (1 << 4)); @@ -2999,6 +3057,68 @@ ehci_early_takeover(device_t self) bus_release_resource(self, SYS_RES_MEMORY, rid, res); } +/* Perform early XHCI takeover from SMM. */ +static void +xhci_early_takeover(device_t self) +{ + struct resource *res; + uint32_t cparams; + uint32_t eec; + uint8_t eecp; + uint8_t bios_sem; + uint8_t offs; + int rid; + int i; + + rid = PCIR_BAR(0); + res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid, RF_ACTIVE); + if (res == NULL) + return; + + cparams = bus_read_4(res, XHCI_HCSPARAMS0); + + eec = -1; + + /* Synchronise with the BIOS if it owns the controller. */ + for (eecp = XHCI_HCS0_XECP(cparams) << 2; eecp != 0 && XHCI_XECP_NEXT(eec); + eecp += XHCI_XECP_NEXT(eec) << 2) { + eec = bus_read_4(res, eecp); + + if (XHCI_XECP_ID(eec) != XHCI_ID_USB_LEGACY) + continue; + + bios_sem = bus_read_1(res, eecp + XHCI_XECP_BIOS_SEM); + if (bios_sem == 0) + continue; + + if (bootverbose) + printf("xhci early: " + "SMM active, request owner change\n"); + + bus_write_1(res, eecp + XHCI_XECP_OS_SEM, 1); + + /* wait a maximum of 5 second */ + + for (i = 0; (i < 5000) && (bios_sem != 0); i++) { + DELAY(1000); + bios_sem = bus_read_1(res, eecp + + XHCI_XECP_BIOS_SEM); + } + + if (bios_sem != 0) { + if (bootverbose) + printf("xhci early: " + "SMM does not respond\n"); + } + + /* Disable interrupts */ + offs = bus_read_1(res, XHCI_CAPLENGTH); + bus_write_4(res, offs + XHCI_USBCMD, 0); + bus_read_4(res, offs + XHCI_USBSTS); + } + bus_release_resource(self, SYS_RES_MEMORY, rid, res); +} + void pci_add_resources(device_t bus, device_t dev, int force, uint32_t prefetchmask) { @@ -3062,7 +3182,9 @@ pci_add_resources(device_t bus, device_t dev, int force, uint32_t prefetchmask) if (pci_usb_takeover && pci_get_class(dev) == PCIC_SERIALBUS && pci_get_subclass(dev) == PCIS_SERIALBUS_USB) { - if (pci_get_progif(dev) == PCIP_SERIALBUS_USB_EHCI) + if (pci_get_progif(dev) == PCIP_SERIALBUS_USB_XHCI) + xhci_early_takeover(dev); + else if (pci_get_progif(dev) == PCIP_SERIALBUS_USB_EHCI) ehci_early_takeover(dev); else if (pci_get_progif(dev) == PCIP_SERIALBUS_USB_OHCI) ohci_early_takeover(dev); @@ -3184,20 +3306,43 @@ pci_attach(device_t dev) return (bus_generic_attach(dev)); } +static void +pci_set_power_children(device_t dev, device_t *devlist, int numdevs, + int state) +{ + device_t child, pcib; + struct pci_devinfo *dinfo; + int dstate, i; + + /* + * Set the device to the given state. If the firmware suggests + * a different power state, use it instead. If power management + * is not present, the firmware is responsible for managing + * device power. Skip children who aren't attached since they + * are handled separately. + */ + pcib = device_get_parent(dev); + for (i = 0; i < numdevs; i++) { + child = devlist[i]; + dinfo = device_get_ivars(child); + dstate = state; + if (device_is_attached(child) && + PCIB_POWER_FOR_SLEEP(pcib, dev, &dstate) == 0) + pci_set_powerstate(child, dstate); + } +} + int pci_suspend(device_t dev) { - int dstate, error, i, numdevs; - device_t acpi_dev, child, *devlist; + device_t child, *devlist; struct pci_devinfo *dinfo; + int error, i, numdevs; /* * Save the PCI configuration space for each child and set the * device in the appropriate power state for this sleep state. */ - acpi_dev = NULL; - if (pci_do_power_resume) - acpi_dev = devclass_get_device(devclass_find("acpi"), 0); if ((error = device_get_children(dev, &devlist, &numdevs)) != 0) return (error); for (i = 0; i < numdevs; i++) { @@ -3212,23 +3357,9 @@ pci_suspend(device_t dev) free(devlist, M_TEMP); return (error); } - - /* - * Always set the device to D3. If ACPI suggests a different - * power state, use it instead. If ACPI is not present, the - * firmware is responsible for managing device power. Skip - * children who aren't attached since they are powered down - * separately. Only manage type 0 devices for now. - */ - for (i = 0; acpi_dev && i < numdevs; i++) { - child = devlist[i]; - dinfo = (struct pci_devinfo *) device_get_ivars(child); - if (device_is_attached(child) && dinfo->cfg.hdrtype == 0) { - dstate = PCI_POWERSTATE_D3; - ACPI_PWR_FOR_SLEEP(acpi_dev, child, &dstate); - pci_set_powerstate(child, dstate); - } - } + if (pci_do_power_suspend) + pci_set_power_children(dev, devlist, numdevs, + PCI_POWERSTATE_D3); free(devlist, M_TEMP); return (0); } @@ -3236,51 +3367,76 @@ pci_suspend(device_t dev) int pci_resume(device_t dev) { - int i, numdevs, error; - device_t acpi_dev, child, *devlist; + device_t child, *devlist; struct pci_devinfo *dinfo; + int error, i, numdevs; /* * Set each child to D0 and restore its PCI configuration space. */ - acpi_dev = NULL; - if (pci_do_power_resume) - acpi_dev = devclass_get_device(devclass_find("acpi"), 0); if ((error = device_get_children(dev, &devlist, &numdevs)) != 0) return (error); + if (pci_do_power_resume) + pci_set_power_children(dev, devlist, numdevs, + PCI_POWERSTATE_D0); + + /* Now the device is powered up, restore its config space. */ for (i = 0; i < numdevs; i++) { - /* - * Notify ACPI we're going to D0 but ignore the result. If - * ACPI is not present, the firmware is responsible for - * managing device power. Only manage type 0 devices for now. - */ child = devlist[i]; - dinfo = (struct pci_devinfo *) device_get_ivars(child); - if (acpi_dev && device_is_attached(child) && - dinfo->cfg.hdrtype == 0) { - ACPI_PWR_FOR_SLEEP(acpi_dev, child, NULL); - pci_set_powerstate(child, PCI_POWERSTATE_D0); - } + dinfo = device_get_ivars(child); - /* Now the device is powered up, restore its config space. */ pci_cfg_restore(child, dinfo); + if (!device_is_attached(child)) + pci_cfg_save(child, dinfo, 1); + } + + /* + * Resume critical devices first, then everything else later. + */ + for (i = 0; i < numdevs; i++) { + child = devlist[i]; + switch (pci_get_class(child)) { + case PCIC_DISPLAY: + case PCIC_MEMORY: + case PCIC_BRIDGE: + case PCIC_BASEPERIPH: + DEVICE_RESUME(child); + break; + } + } + for (i = 0; i < numdevs; i++) { + child = devlist[i]; + switch (pci_get_class(child)) { + case PCIC_DISPLAY: + case PCIC_MEMORY: + case PCIC_BRIDGE: + case PCIC_BASEPERIPH: + break; + default: + DEVICE_RESUME(child); + } } free(devlist, M_TEMP); - return (bus_generic_resume(dev)); + return (0); } static void pci_load_vendor_data(void) { - caddr_t vendordata, info; - - if ((vendordata = preload_search_by_type("pci_vendor_data")) != NULL) { - info = preload_search_info(vendordata, MODINFO_ADDR); - pci_vendordata = *(char **)info; - info = preload_search_info(vendordata, MODINFO_SIZE); - pci_vendordata_size = *(size_t *)info; - /* terminate the database */ - pci_vendordata[pci_vendordata_size] = '\n'; + caddr_t data; + void *ptr; + size_t sz; + + data = preload_search_by_type("pci_vendor_data"); + if (data != NULL) { + ptr = preload_fetch_addr(data); + sz = preload_fetch_size(data); + if (ptr != NULL && sz != 0) { + pci_vendordata = ptr; + pci_vendordata_size = sz; + /* terminate the database */ + pci_vendordata[pci_vendordata_size] = '\n'; + } } } @@ -3742,7 +3898,7 @@ pci_describe_device(device_t dev) if ((desc = malloc(strlen(vp) + strlen(dp) + 3, M_DEVBUF, M_NOWAIT)) != NULL) sprintf(desc, "%s, %s", vp, dp); - out: +out: if (vp != NULL) free(vp, M_DEVBUF); if (dp != NULL) @@ -3917,7 +4073,7 @@ DB_SHOW_COMMAND(pciregs, db_pci_dump) #endif /* DDB */ static struct resource * -pci_alloc_map(device_t dev, device_t child, int type, int *rid, +pci_reserve_map(device_t dev, device_t child, int type, int *rid, u_long start, u_long end, u_long count, u_int flags) { struct pci_devinfo *dinfo = device_get_ivars(child); @@ -4003,22 +4159,22 @@ pci_alloc_map(device_t dev, device_t child, int type, int *rid, count, *rid, type, start, end); goto out; } - rman_set_device(res, dev); resource_list_add(rl, type, *rid, start, end, count); rle = resource_list_find(rl, type, *rid); if (rle == NULL) - panic("pci_alloc_map: unexpectedly can't find resource."); + panic("pci_reserve_map: unexpectedly can't find resource."); rle->res = res; rle->start = rman_get_start(res); rle->end = rman_get_end(res); rle->count = count; + rle->flags = RLE_RESERVED; if (bootverbose) device_printf(child, "Lazy allocation of %#lx bytes rid %#x type %d at %#lx\n", count, *rid, type, rman_get_start(res)); map = rman_get_start(res); pci_write_bar(child, pm, map); -out:; +out: return (res); } @@ -4080,34 +4236,13 @@ pci_alloc_resource(device_t dev, device_t child, int type, int *rid, } } #endif - /* Allocate resources for this BAR if needed. */ + /* Reserve resources for this BAR if needed. */ rle = resource_list_find(rl, type, *rid); if (rle == NULL) { - res = pci_alloc_map(dev, child, type, rid, start, end, + res = pci_reserve_map(dev, child, type, rid, start, end, count, flags); if (res == NULL) return (NULL); - rle = resource_list_find(rl, type, *rid); - } - - /* - * If the resource belongs to the bus, then give it to - * the child. We need to activate it if requested - * since the bus always allocates inactive resources. - */ - if (rle != NULL && rle->res != NULL && - rman_get_device(rle->res) == dev) { - if (bootverbose) - device_printf(child, - "Reserved %#lx bytes for rid %#x type %d at %#lx\n", - rman_get_size(rle->res), *rid, type, - rman_get_start(rle->res)); - rman_set_device(rle->res, child); - if ((flags & RF_ACTIVE) && - bus_activate_resource(child, type, *rid, - rle->res) != 0) - return (NULL); - return (rle->res); } } return (resource_list_alloc(rl, dev, child, type, rid, @@ -4115,37 +4250,6 @@ pci_alloc_resource(device_t dev, device_t child, int type, int *rid, } int -pci_release_resource(device_t dev, device_t child, int type, int rid, - struct resource *r) -{ - int error; - - if (device_get_parent(child) != dev) - return (BUS_RELEASE_RESOURCE(device_get_parent(dev), child, - type, rid, r)); - - /* - * For BARs we don't actually want to release the resource. - * Instead, we deactivate the resource if needed and then give - * ownership of the BAR back to the bus. - */ - switch (type) { - case SYS_RES_IOPORT: - case SYS_RES_MEMORY: - if (rman_get_device(r) != child) - return (EINVAL); - if (rman_get_flags(r) & RF_ACTIVE) { - error = bus_deactivate_resource(child, type, rid, r); - if (error) - return (error); - } - rman_set_device(r, dev); - return (0); - } - return (bus_generic_rl_release_resource(dev, child, type, rid, r)); -} - -int pci_activate_resource(device_t dev, device_t child, int type, int rid, struct resource *r) { @@ -4195,6 +4299,46 @@ pci_deactivate_resource(device_t dev, device_t child, int type, } void +pci_delete_child(device_t dev, device_t child) +{ + struct resource_list_entry *rle; + struct resource_list *rl; + struct pci_devinfo *dinfo; + + dinfo = device_get_ivars(child); + rl = &dinfo->resources; + + if (device_is_attached(child)) + device_detach(child); + + /* Turn off access to resources we're about to free */ + pci_write_config(child, PCIR_COMMAND, pci_read_config(child, + PCIR_COMMAND, 2) & ~(PCIM_CMD_MEMEN | PCIM_CMD_PORTEN), 2); + + /* Free all allocated resources */ + STAILQ_FOREACH(rle, rl, link) { + if (rle->res) { + if (rman_get_flags(rle->res) & RF_ACTIVE || + resource_list_busy(rl, rle->type, rle->rid)) { + pci_printf(&dinfo->cfg, + "Resource still owned, oops. " + "(type=%d, rid=%d, addr=%lx)\n", + rle->type, rle->rid, + rman_get_start(rle->res)); + bus_release_resource(child, rle->type, rle->rid, + rle->res); + } + resource_list_unreserve(rl, dev, child, rle->type, + rle->rid); + } + } + resource_list_free(rl); + + device_delete_child(dev, child); + pci_freecfg(dinfo); +} + +void pci_delete_resource(device_t dev, device_t child, int type, int rid) { struct pci_devinfo *dinfo; @@ -4211,29 +4355,15 @@ pci_delete_resource(device_t dev, device_t child, int type, int rid) return; if (rle->res) { - if (rman_get_device(rle->res) != dev || - rman_get_flags(rle->res) & RF_ACTIVE) { + if (rman_get_flags(rle->res) & RF_ACTIVE || + resource_list_busy(rl, type, rid)) { device_printf(dev, "delete_resource: " "Resource still owned by child, oops. " "(type=%d, rid=%d, addr=%lx)\n", - rle->type, rle->rid, - rman_get_start(rle->res)); + type, rid, rman_get_start(rle->res)); return; } - -#ifndef __PCI_BAR_ZERO_VALID - /* - * If this is a BAR, clear the BAR so it stops - * decoding before releasing the resource. - */ - switch (type) { - case SYS_RES_IOPORT: - case SYS_RES_MEMORY: - pci_write_bar(child, pci_find_bar(child, rid), 0); - break; - } -#endif - bus_release_resource(dev, type, rid, rle->res); + resource_list_unreserve(rl, dev, child, type, rid); } resource_list_delete(rl, type, rid); } @@ -4344,7 +4474,7 @@ pci_cfg_restore(device_t dev, struct pci_devinfo *dinfo) * Other types are unknown, and we err on the side of safety * by ignoring them. */ - if (dinfo->cfg.hdrtype != 0) + if ((dinfo->cfg.hdrtype & PCIM_HDRTYPE) != PCIM_HDRTYPE_NORMAL) return; /* @@ -4388,7 +4518,7 @@ pci_cfg_save(device_t dev, struct pci_devinfo *dinfo, int setstate) * we err on the side of safety by ignoring them. Powering down * bridges should not be undertaken lightly. */ - if (dinfo->cfg.hdrtype != 0) + if ((dinfo->cfg.hdrtype & PCIM_HDRTYPE) != PCIM_HDRTYPE_NORMAL) return; /* diff --git a/freebsd/sys/dev/pci/pci_pci.c b/freebsd/sys/dev/pci/pci_pci.c index b0951024..bfaabf35 100644 --- a/freebsd/sys/dev/pci/pci_pci.c +++ b/freebsd/sys/dev/pci/pci_pci.c @@ -40,23 +40,24 @@ __FBSDID("$FreeBSD$"); #include <rtems/bsd/sys/param.h> #include <sys/bus.h> #include <sys/kernel.h> -#include <sys/libkern.h> #include <sys/malloc.h> #include <sys/module.h> #include <sys/rman.h> #include <sys/sysctl.h> #include <sys/systm.h> -#include <machine/bus.h> -#include <machine/resource.h> - #include <dev/pci/pcivar.h> #include <dev/pci/pcireg.h> +#include <dev/pci/pci_private.h> #include <dev/pci/pcib_private.h> #include <rtems/bsd/local/pcib_if.h> static int pcib_probe(device_t dev); +static int pcib_suspend(device_t dev); +static int pcib_resume(device_t dev); +static int pcib_power_for_sleep(device_t pcib, device_t dev, + int *pstate); static device_method_t pcib_methods[] = { /* Device interface */ @@ -64,8 +65,8 @@ static device_method_t pcib_methods[] = { DEVMETHOD(device_attach, pcib_attach), DEVMETHOD(device_detach, bus_generic_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), - DEVMETHOD(device_suspend, bus_generic_suspend), - DEVMETHOD(device_resume, bus_generic_resume), + DEVMETHOD(device_suspend, pcib_suspend), + DEVMETHOD(device_resume, pcib_resume), /* Bus interface */ DEVMETHOD(bus_read_ivar, pcib_read_ivar), @@ -93,6 +94,7 @@ static device_method_t pcib_methods[] = { DEVMETHOD(pcib_alloc_msix, pcib_alloc_msix), DEVMETHOD(pcib_release_msix, pcib_release_msix), DEVMETHOD(pcib_map_msi, pcib_map_msi), + DEVMETHOD(pcib_power_for_sleep, pcib_power_for_sleep), DEVMETHOD_END }; @@ -100,7 +102,7 @@ static device_method_t pcib_methods[] = { static devclass_t pcib_devclass; DEFINE_CLASS_0(pcib, pcib_driver, pcib_methods, sizeof(struct pcib_softc)); -DRIVER_MODULE(pcib, pci, pcib_driver, pcib_devclass, 0, 0); +DRIVER_MODULE(pcib, pci, pcib_driver, pcib_devclass, NULL, NULL); #ifdef NEW_PCIB /* @@ -365,7 +367,161 @@ pcib_is_io_open(struct pcib_softc *sc) { return (sc->iobase > 0 && sc->iobase < sc->iolimit); } + +/* + * Get current I/O decode. + */ +static void +pcib_get_io_decode(struct pcib_softc *sc) +{ + device_t dev; + uint32_t iolow; + + dev = sc->dev; + + iolow = pci_read_config(dev, PCIR_IOBASEL_1, 1); + if ((iolow & PCIM_BRIO_MASK) == PCIM_BRIO_32) + sc->iobase = PCI_PPBIOBASE( + pci_read_config(dev, PCIR_IOBASEH_1, 2), iolow); + else + sc->iobase = PCI_PPBIOBASE(0, iolow); + + iolow = pci_read_config(dev, PCIR_IOLIMITL_1, 1); + if ((iolow & PCIM_BRIO_MASK) == PCIM_BRIO_32) + sc->iolimit = PCI_PPBIOLIMIT( + pci_read_config(dev, PCIR_IOLIMITH_1, 2), iolow); + else + sc->iolimit = PCI_PPBIOLIMIT(0, iolow); +} + +/* + * Get current memory decode. + */ +static void +pcib_get_mem_decode(struct pcib_softc *sc) +{ + device_t dev; + pci_addr_t pmemlow; + + dev = sc->dev; + + sc->membase = PCI_PPBMEMBASE(0, + pci_read_config(dev, PCIR_MEMBASE_1, 2)); + sc->memlimit = PCI_PPBMEMLIMIT(0, + pci_read_config(dev, PCIR_MEMLIMIT_1, 2)); + + pmemlow = pci_read_config(dev, PCIR_PMBASEL_1, 2); + if ((pmemlow & PCIM_BRPM_MASK) == PCIM_BRPM_64) + sc->pmembase = PCI_PPBMEMBASE( + pci_read_config(dev, PCIR_PMBASEH_1, 4), pmemlow); + else + sc->pmembase = PCI_PPBMEMBASE(0, pmemlow); + + pmemlow = pci_read_config(dev, PCIR_PMLIMITL_1, 2); + if ((pmemlow & PCIM_BRPM_MASK) == PCIM_BRPM_64) + sc->pmemlimit = PCI_PPBMEMLIMIT( + pci_read_config(dev, PCIR_PMLIMITH_1, 4), pmemlow); + else + sc->pmemlimit = PCI_PPBMEMLIMIT(0, pmemlow); +} + +/* + * Restore previous I/O decode. + */ +static void +pcib_set_io_decode(struct pcib_softc *sc) +{ + device_t dev; + uint32_t iohi; + + dev = sc->dev; + + iohi = sc->iobase >> 16; + if (iohi > 0) + pci_write_config(dev, PCIR_IOBASEH_1, iohi, 2); + pci_write_config(dev, PCIR_IOBASEL_1, sc->iobase >> 8, 1); + + iohi = sc->iolimit >> 16; + if (iohi > 0) + pci_write_config(dev, PCIR_IOLIMITH_1, iohi, 2); + pci_write_config(dev, PCIR_IOLIMITL_1, sc->iolimit >> 8, 1); +} + +/* + * Restore previous memory decode. + */ +static void +pcib_set_mem_decode(struct pcib_softc *sc) +{ + device_t dev; + pci_addr_t pmemhi; + + dev = sc->dev; + + pci_write_config(dev, PCIR_MEMBASE_1, sc->membase >> 16, 2); + pci_write_config(dev, PCIR_MEMLIMIT_1, sc->memlimit >> 16, 2); + + pmemhi = sc->pmembase >> 32; + if (pmemhi > 0) + pci_write_config(dev, PCIR_PMBASEH_1, pmemhi, 4); + pci_write_config(dev, PCIR_PMBASEL_1, sc->pmembase >> 16, 2); + + pmemhi = sc->pmemlimit >> 32; + if (pmemhi > 0) + pci_write_config(dev, PCIR_PMLIMITH_1, pmemhi, 4); + pci_write_config(dev, PCIR_PMLIMITL_1, sc->pmemlimit >> 16, 2); +} +#endif + +/* + * Get current bridge configuration. + */ +static void +pcib_cfg_save(struct pcib_softc *sc) +{ + device_t dev; + + dev = sc->dev; + + sc->command = pci_read_config(dev, PCIR_COMMAND, 2); + sc->pribus = pci_read_config(dev, PCIR_PRIBUS_1, 1); + sc->secbus = pci_read_config(dev, PCIR_SECBUS_1, 1); + sc->subbus = pci_read_config(dev, PCIR_SUBBUS_1, 1); + sc->bridgectl = pci_read_config(dev, PCIR_BRIDGECTL_1, 2); + sc->seclat = pci_read_config(dev, PCIR_SECLAT_1, 1); +#ifndef NEW_PCIB + if (sc->command & PCIM_CMD_PORTEN) + pcib_get_io_decode(sc); + if (sc->command & PCIM_CMD_MEMEN) + pcib_get_mem_decode(sc); +#endif +} + +/* + * Restore previous bridge configuration. + */ +static void +pcib_cfg_restore(struct pcib_softc *sc) +{ + device_t dev; + + dev = sc->dev; + + pci_write_config(dev, PCIR_COMMAND, sc->command, 2); + pci_write_config(dev, PCIR_PRIBUS_1, sc->pribus, 1); + pci_write_config(dev, PCIR_SECBUS_1, sc->secbus, 1); + pci_write_config(dev, PCIR_SUBBUS_1, sc->subbus, 1); + pci_write_config(dev, PCIR_BRIDGECTL_1, sc->bridgectl, 2); + pci_write_config(dev, PCIR_SECLAT_1, sc->seclat, 1); +#ifdef NEW_PCIB + pcib_write_windows(sc, WIN_IO | WIN_MEM | WIN_PMEM); +#else + if (sc->command & PCIM_CMD_PORTEN) + pcib_set_io_decode(sc); + if (sc->command & PCIM_CMD_MEMEN) + pcib_set_mem_decode(sc); #endif +} /* * Generic device interface @@ -385,9 +541,6 @@ void pcib_attach_common(device_t dev) { struct pcib_softc *sc; -#ifndef NEW_PCIB - uint8_t iolow; -#endif struct sysctl_ctx_list *sctx; struct sysctl_oid *soid; @@ -397,14 +550,9 @@ pcib_attach_common(device_t dev) /* * Get current bridge configuration. */ - sc->command = pci_read_config(dev, PCIR_COMMAND, 1); - sc->domain = pci_get_domain(dev); - sc->pribus = pci_read_config(dev, PCIR_PRIBUS_1, 1); - sc->secbus = pci_read_config(dev, PCIR_SECBUS_1, 1); - sc->subbus = pci_read_config(dev, PCIR_SUBBUS_1, 1); - sc->secstat = pci_read_config(dev, PCIR_SECSTAT_1, 2); - sc->bridgectl = pci_read_config(dev, PCIR_BRIDGECTL_1, 2); - sc->seclat = pci_read_config(dev, PCIR_SECLAT_1, 1); + sc->domain = pci_get_domain(dev); + sc->secstat = pci_read_config(dev, PCIR_SECSTAT_1, 2); + pcib_cfg_save(sc); /* * Setup sysctl reporting nodes @@ -420,53 +568,6 @@ pcib_attach_common(device_t dev) SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "subbus", CTLFLAG_RD, &sc->subbus, 0, "Subordinate bus number"); -#ifndef NEW_PCIB - /* - * Determine current I/O decode. - */ - if (sc->command & PCIM_CMD_PORTEN) { - iolow = pci_read_config(dev, PCIR_IOBASEL_1, 1); - if ((iolow & PCIM_BRIO_MASK) == PCIM_BRIO_32) { - sc->iobase = PCI_PPBIOBASE(pci_read_config(dev, PCIR_IOBASEH_1, 2), - pci_read_config(dev, PCIR_IOBASEL_1, 1)); - } else { - sc->iobase = PCI_PPBIOBASE(0, pci_read_config(dev, PCIR_IOBASEL_1, 1)); - } - - iolow = pci_read_config(dev, PCIR_IOLIMITL_1, 1); - if ((iolow & PCIM_BRIO_MASK) == PCIM_BRIO_32) { - sc->iolimit = PCI_PPBIOLIMIT(pci_read_config(dev, PCIR_IOLIMITH_1, 2), - pci_read_config(dev, PCIR_IOLIMITL_1, 1)); - } else { - sc->iolimit = PCI_PPBIOLIMIT(0, pci_read_config(dev, PCIR_IOLIMITL_1, 1)); - } - } - - /* - * Determine current memory decode. - */ - if (sc->command & PCIM_CMD_MEMEN) { - sc->membase = PCI_PPBMEMBASE(0, pci_read_config(dev, PCIR_MEMBASE_1, 2)); - sc->memlimit = PCI_PPBMEMLIMIT(0, pci_read_config(dev, PCIR_MEMLIMIT_1, 2)); - iolow = pci_read_config(dev, PCIR_PMBASEL_1, 1); - if ((iolow & PCIM_BRPM_MASK) == PCIM_BRPM_64) - sc->pmembase = PCI_PPBMEMBASE( - pci_read_config(dev, PCIR_PMBASEH_1, 4), - pci_read_config(dev, PCIR_PMBASEL_1, 2)); - else - sc->pmembase = PCI_PPBMEMBASE(0, - pci_read_config(dev, PCIR_PMBASEL_1, 2)); - iolow = pci_read_config(dev, PCIR_PMLIMITL_1, 1); - if ((iolow & PCIM_BRPM_MASK) == PCIM_BRPM_64) - sc->pmemlimit = PCI_PPBMEMLIMIT( - pci_read_config(dev, PCIR_PMLIMITH_1, 4), - pci_read_config(dev, PCIR_PMLIMITL_1, 2)); - else - sc->pmemlimit = PCI_PPBMEMLIMIT(0, - pci_read_config(dev, PCIR_PMLIMITL_1, 2)); - } -#endif - /* * Quirk handling. */ @@ -527,6 +628,9 @@ pcib_attach_common(device_t dev) if (pci_msi_device_blacklisted(dev)) sc->flags |= PCIB_DISABLE_MSI; + if (pci_msix_device_blacklisted(dev)) + sc->flags |= PCIB_DISABLE_MSIX; + /* * Intel 815, 845 and other chipsets say they are PCI-PCI bridges, * but have a ProgIF of 0x80. The 82801 family (AA, AB, BAM/CAM, @@ -614,6 +718,37 @@ pcib_attach(device_t dev) } int +pcib_suspend(device_t dev) +{ + device_t pcib; + int dstate, error; + + pcib_cfg_save(device_get_softc(dev)); + error = bus_generic_suspend(dev); + if (error == 0 && pci_do_power_suspend) { + dstate = PCI_POWERSTATE_D3; + pcib = device_get_parent(device_get_parent(dev)); + if (PCIB_POWER_FOR_SLEEP(pcib, dev, &dstate) == 0) + pci_set_powerstate(dev, dstate); + } + return (error); +} + +int +pcib_resume(device_t dev) +{ + device_t pcib; + + if (pci_do_power_resume) { + pcib = device_get_parent(device_get_parent(dev)); + if (PCIB_POWER_FOR_SLEEP(pcib, dev, NULL) == 0) + pci_set_powerstate(dev, PCI_POWERSTATE_D0); + } + pcib_cfg_restore(device_get_softc(dev)); + return (bus_generic_resume(dev)); +} + +int pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) { struct pcib_softc *sc = device_get_softc(dev); @@ -645,18 +780,6 @@ pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t value) } #ifdef NEW_PCIB -static const char * -pcib_child_name(device_t child) -{ - static char buf[64]; - - if (device_get_nameunit(child) != NULL) - return (device_get_nameunit(child)); - snprintf(buf, sizeof(buf), "pci%d:%d:%d:%d", pci_get_domain(child), - pci_get_bus(child), pci_get_slot(child), pci_get_function(child)); - return (buf); -} - /* * Attempt to allocate a resource from the existing resources assigned * to a window. @@ -1263,7 +1386,7 @@ pcib_alloc_msix(device_t pcib, device_t dev, int *irq) struct pcib_softc *sc = device_get_softc(pcib); device_t bus; - if (sc->flags & PCIB_DISABLE_MSI) + if (sc->flags & PCIB_DISABLE_MSIX) return (ENXIO); bus = device_get_parent(pcib); return (PCIB_ALLOC_MSIX(device_get_parent(bus), dev, irq)); @@ -1296,90 +1419,12 @@ pcib_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr, return (0); } -/* - * Try to read the bus number of a host-PCI bridge using appropriate config - * registers. - */ +/* Pass request for device power state up to parent bridge. */ int -host_pcib_get_busno(pci_read_config_fn read_config, int bus, int slot, int func, - uint8_t *busnum) +pcib_power_for_sleep(device_t pcib, device_t dev, int *pstate) { - uint32_t id; - - id = read_config(bus, slot, func, PCIR_DEVVENDOR, 4); - if (id == 0xffffffff) - return (0); - - switch (id) { - case 0x12258086: - /* Intel 824?? */ - /* XXX This is a guess */ - /* *busnum = read_config(bus, slot, func, 0x41, 1); */ - *busnum = bus; - break; - case 0x84c48086: - /* Intel 82454KX/GX (Orion) */ - *busnum = read_config(bus, slot, func, 0x4a, 1); - break; - case 0x84ca8086: - /* - * For the 450nx chipset, there is a whole bundle of - * things pretending to be host bridges. The MIOC will - * be seen first and isn't really a pci bridge (the - * actual busses are attached to the PXB's). We need to - * read the registers of the MIOC to figure out the - * bus numbers for the PXB channels. - * - * Since the MIOC doesn't have a pci bus attached, we - * pretend it wasn't there. - */ - return (0); - case 0x84cb8086: - switch (slot) { - case 0x12: - /* Intel 82454NX PXB#0, Bus#A */ - *busnum = read_config(bus, 0x10, func, 0xd0, 1); - break; - case 0x13: - /* Intel 82454NX PXB#0, Bus#B */ - *busnum = read_config(bus, 0x10, func, 0xd1, 1) + 1; - break; - case 0x14: - /* Intel 82454NX PXB#1, Bus#A */ - *busnum = read_config(bus, 0x10, func, 0xd3, 1); - break; - case 0x15: - /* Intel 82454NX PXB#1, Bus#B */ - *busnum = read_config(bus, 0x10, func, 0xd4, 1) + 1; - break; - } - break; - - /* ServerWorks -- vendor 0x1166 */ - case 0x00051166: - case 0x00061166: - case 0x00081166: - case 0x00091166: - case 0x00101166: - case 0x00111166: - case 0x00171166: - case 0x01011166: - case 0x010f1014: - case 0x01101166: - case 0x02011166: - case 0x02251166: - case 0x03021014: - *busnum = read_config(bus, slot, func, 0x44, 1); - break; - - /* Compaq/HP -- vendor 0x0e11 */ - case 0x60100e11: - *busnum = read_config(bus, slot, func, 0xc8, 1); - break; - default: - /* Don't know how to read bus number. */ - return 0; - } + device_t bus; - return 1; + bus = device_get_parent(pcib); + return (PCIB_POWER_FOR_SLEEP(bus, dev, pstate)); } diff --git a/freebsd/sys/dev/pci/pci_private.h b/freebsd/sys/dev/pci/pci_private.h index b3ff50d5..b8e446ea 100644 --- a/freebsd/sys/dev/pci/pci_private.h +++ b/freebsd/sys/dev/pci/pci_private.h @@ -42,12 +42,16 @@ struct pci_softc { bus_dma_tag_t sc_dma_tag; }; +extern int pci_do_power_resume; +extern int pci_do_power_suspend; + void pci_add_children(device_t dev, int domain, int busno, size_t dinfo_size); void pci_add_child(device_t bus, struct pci_devinfo *dinfo); void pci_add_resources(device_t bus, device_t dev, int force, uint32_t prefetchmask); int pci_attach_common(device_t dev); +void pci_delete_child(device_t dev, device_t child); void pci_driver_added(device_t dev, driver_t *driver); int pci_print_child(device_t dev, device_t child); void pci_probe_nomatch(device_t dev, device_t child); @@ -87,8 +91,6 @@ int pci_msix_count_method(device_t dev, device_t child); struct resource *pci_alloc_resource(device_t dev, device_t child, int type, int *rid, u_long start, u_long end, u_long count, u_int flags); -int pci_release_resource(device_t dev, device_t child, int type, - int rid, struct resource *r); int pci_activate_resource(device_t dev, device_t child, int type, int rid, struct resource *r); int pci_deactivate_resource(device_t dev, device_t child, int type, diff --git a/freebsd/sys/dev/pci/pci_user.c b/freebsd/sys/dev/pci/pci_user.c index c2723ad3..63d64c39 100644 --- a/freebsd/sys/dev/pci/pci_user.c +++ b/freebsd/sys/dev/pci/pci_user.c @@ -227,6 +227,51 @@ struct pci_io_old { u_int32_t pi_data; /* data to write or result of read */ }; +#ifdef COMPAT_FREEBSD32 +struct pci_conf_old32 { + struct pcisel_old pc_sel; /* bus+slot+function */ + uint8_t pc_hdr; /* PCI header type */ + uint16_t pc_subvendor; /* card vendor ID */ + uint16_t pc_subdevice; /* card device ID, assigned by + card vendor */ + uint16_t pc_vendor; /* chip vendor ID */ + uint16_t pc_device; /* chip device ID, assigned by + chip vendor */ + uint8_t pc_class; /* chip PCI class */ + uint8_t pc_subclass; /* chip PCI subclass */ + uint8_t pc_progif; /* chip PCI programming interface */ + uint8_t pc_revid; /* chip revision ID */ + char pd_name[PCI_MAXNAMELEN + 1]; /* device name */ + uint32_t pd_unit; /* device unit number (u_long) */ +}; + +struct pci_match_conf_old32 { + struct pcisel_old pc_sel; /* bus+slot+function */ + char pd_name[PCI_MAXNAMELEN + 1]; /* device name */ + uint32_t pd_unit; /* Unit number (u_long) */ + uint16_t pc_vendor; /* PCI Vendor ID */ + uint16_t pc_device; /* PCI Device ID */ + uint8_t pc_class; /* PCI class */ + pci_getconf_flags_old flags; /* Matching expression */ +}; + +struct pci_conf_io32 { + uint32_t pat_buf_len; /* pattern buffer length */ + uint32_t num_patterns; /* number of patterns */ + uint32_t patterns; /* pattern buffer + (struct pci_match_conf_old32 *) */ + uint32_t match_buf_len; /* match buffer length */ + uint32_t num_matches; /* number of matches returned */ + uint32_t matches; /* match buffer + (struct pci_conf_old32 *) */ + uint32_t offset; /* offset into device list */ + uint32_t generation; /* device list generation */ + pci_getconf_status status; /* request status */ +}; + +#define PCIOCGETCONF_OLD32 _IOWR('p', 1, struct pci_conf_io32) +#endif /* COMPAT_FREEBSD32 */ + #define PCIOCGETCONF_OLD _IOWR('p', 1, struct pci_conf_io) #define PCIOCREAD_OLD _IOWR('p', 2, struct pci_io_old) #define PCIOCWRITE_OLD _IOWR('p', 3, struct pci_io_old) @@ -297,7 +342,71 @@ pci_conf_match_old(struct pci_match_conf_old *matches, int num_matches, return(1); } -#endif +#ifdef COMPAT_FREEBSD32 +static int +pci_conf_match_old32(struct pci_match_conf_old32 *matches, int num_matches, + struct pci_conf *match_buf) +{ + int i; + + if ((matches == NULL) || (match_buf == NULL) || (num_matches <= 0)) + return(1); + + for (i = 0; i < num_matches; i++) { + if (match_buf->pc_sel.pc_domain != 0) + continue; + + /* + * I'm not sure why someone would do this...but... + */ + if (matches[i].flags == PCI_GETCONF_NO_MATCH_OLD) + continue; + + /* + * Look at each of the match flags. If it's set, do the + * comparison. If the comparison fails, we don't have a + * match, go on to the next item if there is one. + */ + if (((matches[i].flags & PCI_GETCONF_MATCH_BUS_OLD) != 0) && + (match_buf->pc_sel.pc_bus != matches[i].pc_sel.pc_bus)) + continue; + + if (((matches[i].flags & PCI_GETCONF_MATCH_DEV_OLD) != 0) && + (match_buf->pc_sel.pc_dev != matches[i].pc_sel.pc_dev)) + continue; + + if (((matches[i].flags & PCI_GETCONF_MATCH_FUNC_OLD) != 0) && + (match_buf->pc_sel.pc_func != matches[i].pc_sel.pc_func)) + continue; + + if (((matches[i].flags & PCI_GETCONF_MATCH_VENDOR_OLD) != 0) && + (match_buf->pc_vendor != matches[i].pc_vendor)) + continue; + + if (((matches[i].flags & PCI_GETCONF_MATCH_DEVICE_OLD) != 0) && + (match_buf->pc_device != matches[i].pc_device)) + continue; + + if (((matches[i].flags & PCI_GETCONF_MATCH_CLASS_OLD) != 0) && + (match_buf->pc_class != matches[i].pc_class)) + continue; + + if (((matches[i].flags & PCI_GETCONF_MATCH_UNIT_OLD) != 0) && + ((u_int32_t)match_buf->pd_unit != matches[i].pd_unit)) + continue; + + if (((matches[i].flags & PCI_GETCONF_MATCH_NAME_OLD) != 0) && + (strncmp(matches[i].pd_name, match_buf->pd_name, + sizeof(match_buf->pd_name)) != 0)) + continue; + + return (0); + } + + return (1); +} +#endif /* COMPAT_FREEBSD32 */ +#endif /* PRE7_COMPAT */ static int pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td) @@ -306,7 +415,7 @@ pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t void *confdata; const char *name; struct devlist *devlist_head; - struct pci_conf_io *cio; + struct pci_conf_io *cio = NULL; struct pci_devinfo *dinfo; struct pci_io *io; struct pci_bar_io *bio; @@ -315,13 +424,17 @@ pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t size_t confsz, iolen, pbufsz; int error, ionum, i, num_patterns; #ifdef PRE7_COMPAT +#ifdef COMPAT_FREEBSD32 + struct pci_conf_io32 *cio32 = NULL; + struct pci_conf_old32 conf_old32; + struct pci_match_conf_old32 *pattern_buf_old32 = NULL; +#endif struct pci_conf_old conf_old; struct pci_io iodata; struct pci_io_old *io_old; - struct pci_match_conf_old *pattern_buf_old; + struct pci_match_conf_old *pattern_buf_old = NULL; io_old = NULL; - pattern_buf_old = NULL; if (!(flag & FWRITE) && cmd != PCIOCGETBAR && cmd != PCIOCGETCONF && cmd != PCIOCGETCONF_OLD) @@ -333,11 +446,36 @@ pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t switch(cmd) { #ifdef PRE7_COMPAT +#ifdef COMPAT_FREEBSD32 + case PCIOCGETCONF_OLD32: + cio32 = (struct pci_conf_io32 *)data; + cio = malloc(sizeof(struct pci_conf_io), M_TEMP, M_WAITOK); + cio->pat_buf_len = cio32->pat_buf_len; + cio->num_patterns = cio32->num_patterns; + cio->patterns = (void *)(uintptr_t)cio32->patterns; + cio->match_buf_len = cio32->match_buf_len; + cio->num_matches = cio32->num_matches; + cio->matches = (void *)(uintptr_t)cio32->matches; + cio->offset = cio32->offset; + cio->generation = cio32->generation; + cio->status = cio32->status; + cio32->num_matches = 0; + break; +#endif case PCIOCGETCONF_OLD: - /* FALLTHROUGH */ #endif case PCIOCGETCONF: cio = (struct pci_conf_io *)data; + } + + switch(cmd) { +#ifdef PRE7_COMPAT +#ifdef COMPAT_FREEBSD32 + case PCIOCGETCONF_OLD32: +#endif + case PCIOCGETCONF_OLD: +#endif + case PCIOCGETCONF: pattern_buf = NULL; num_patterns = 0; @@ -355,7 +493,7 @@ pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t && (cio->generation != pci_generation)){ cio->status = PCI_GETCONF_LIST_CHANGED; error = 0; - break; + goto getconfexit; } /* @@ -365,7 +503,7 @@ pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t if (cio->offset >= pci_numdevs) { cio->status = PCI_GETCONF_LAST_DEVICE; error = 0; - break; + goto getconfexit; } /* get the head of the device queue */ @@ -378,6 +516,11 @@ pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t * didn't specify a multiple of that size. */ #ifdef PRE7_COMPAT +#ifdef COMPAT_FREEBSD32 + if (cmd == PCIOCGETCONF_OLD32) + confsz = sizeof(struct pci_conf_old32); + else +#endif if (cmd == PCIOCGETCONF_OLD) confsz = sizeof(struct pci_conf_old); else @@ -412,6 +555,11 @@ pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t * updated their kernel but not their userland. */ #ifdef PRE7_COMPAT +#ifdef COMPAT_FREEBSD32 + if (cmd == PCIOCGETCONF_OLD32) + pbufsz = sizeof(struct pci_match_conf_old32); + else +#endif if (cmd == PCIOCGETCONF_OLD) pbufsz = sizeof(struct pci_match_conf_old); else @@ -421,20 +569,28 @@ pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t /* The user made a mistake, return an error. */ cio->status = PCI_GETCONF_ERROR; error = EINVAL; - break; + goto getconfexit; } /* * Allocate a buffer to hold the patterns. */ #ifdef PRE7_COMPAT +#ifdef COMPAT_FREEBSD32 + if (cmd == PCIOCGETCONF_OLD32) { + pattern_buf_old32 = malloc(cio->pat_buf_len, + M_TEMP, M_WAITOK); + error = copyin(cio->patterns, + pattern_buf_old32, cio->pat_buf_len); + } else +#endif /* COMPAT_FREEBSD32 */ if (cmd == PCIOCGETCONF_OLD) { pattern_buf_old = malloc(cio->pat_buf_len, M_TEMP, M_WAITOK); error = copyin(cio->patterns, pattern_buf_old, cio->pat_buf_len); } else -#endif +#endif /* PRE7_COMPAT */ { pattern_buf = malloc(cio->pat_buf_len, M_TEMP, M_WAITOK); @@ -453,7 +609,7 @@ pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t */ cio->status = PCI_GETCONF_ERROR; error = EINVAL; - break; + goto getconfexit; } /* @@ -485,7 +641,14 @@ pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t } #ifdef PRE7_COMPAT - if ((cmd == PCIOCGETCONF_OLD && + if ( +#ifdef COMPAT_FREEBSD32 + (cmd == PCIOCGETCONF_OLD32 && + (pattern_buf_old32 == NULL || + pci_conf_match_old32(pattern_buf_old32, + num_patterns, &dinfo->conf) == 0)) || +#endif + (cmd == PCIOCGETCONF_OLD && (pattern_buf_old == NULL || pci_conf_match_old(pattern_buf_old, num_patterns, &dinfo->conf) == 0)) || @@ -510,6 +673,40 @@ pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t break; #ifdef PRE7_COMPAT +#ifdef COMPAT_FREEBSD32 + if (cmd == PCIOCGETCONF_OLD32) { + conf_old32.pc_sel.pc_bus = + dinfo->conf.pc_sel.pc_bus; + conf_old32.pc_sel.pc_dev = + dinfo->conf.pc_sel.pc_dev; + conf_old32.pc_sel.pc_func = + dinfo->conf.pc_sel.pc_func; + conf_old32.pc_hdr = dinfo->conf.pc_hdr; + conf_old32.pc_subvendor = + dinfo->conf.pc_subvendor; + conf_old32.pc_subdevice = + dinfo->conf.pc_subdevice; + conf_old32.pc_vendor = + dinfo->conf.pc_vendor; + conf_old32.pc_device = + dinfo->conf.pc_device; + conf_old32.pc_class = + dinfo->conf.pc_class; + conf_old32.pc_subclass = + dinfo->conf.pc_subclass; + conf_old32.pc_progif = + dinfo->conf.pc_progif; + conf_old32.pc_revid = + dinfo->conf.pc_revid; + strncpy(conf_old32.pd_name, + dinfo->conf.pd_name, + sizeof(conf_old32.pd_name)); + conf_old32.pd_name[PCI_MAXNAMELEN] = 0; + conf_old32.pd_unit = + (uint32_t)dinfo->conf.pd_unit; + confdata = &conf_old32; + } else +#endif /* COMPAT_FREEBSD32 */ if (cmd == PCIOCGETCONF_OLD) { conf_old.pc_sel.pc_bus = dinfo->conf.pc_sel.pc_bus; @@ -542,7 +739,7 @@ pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t dinfo->conf.pd_unit; confdata = &conf_old; } else -#endif +#endif /* PRE7_COMPAT */ confdata = &dinfo->conf; /* Only if we can copy it out do we count it. */ if (!(error = copyout(confdata, @@ -576,12 +773,23 @@ pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t cio->status = PCI_GETCONF_MORE_DEVS; getconfexit: - if (pattern_buf != NULL) - free(pattern_buf, M_TEMP); #ifdef PRE7_COMPAT +#ifdef COMPAT_FREEBSD32 + if (cmd == PCIOCGETCONF_OLD32) { + cio32->status = cio->status; + cio32->generation = cio->generation; + cio32->offset = cio->offset; + cio32->num_matches = cio->num_matches; + free(cio, M_TEMP); + } + if (pattern_buf_old32 != NULL) + free(pattern_buf_old32, M_TEMP); +#endif if (pattern_buf_old != NULL) free(pattern_buf_old, M_TEMP); #endif + if (pattern_buf != NULL) + free(pattern_buf, M_TEMP); break; @@ -696,6 +904,16 @@ getconfexit: bio->pbi_enabled = pci_bar_enabled(pcidev, pm); error = 0; break; + case PCIOCATTACHED: + error = 0; + io = (struct pci_io *)data; + pcidev = pci_find_dbsf(io->pi_sel.pc_domain, io->pi_sel.pc_bus, + io->pi_sel.pc_dev, io->pi_sel.pc_func); + if (pcidev != NULL) + io->pi_data = device_is_attached(pcidev); + else + error = ENODEV; + break; default: error = ENOTTY; break; diff --git a/freebsd/sys/dev/pci/pcib_private.h b/freebsd/sys/dev/pci/pcib_private.h index 1574deb7..79135afa 100644 --- a/freebsd/sys/dev/pci/pcib_private.h +++ b/freebsd/sys/dev/pci/pcib_private.h @@ -33,6 +33,31 @@ #ifndef __PCIB_PRIVATE_H__ #define __PCIB_PRIVATE_H__ +#ifdef NEW_PCIB +/* + * Data structure and routines that Host to PCI bridge drivers can use + * to restrict allocations for child devices to ranges decoded by the + * bridge. + */ +struct pcib_host_resources { + device_t hr_pcib; + struct resource_list hr_rl; +}; + +int pcib_host_res_init(device_t pcib, + struct pcib_host_resources *hr); +int pcib_host_res_free(device_t pcib, + struct pcib_host_resources *hr); +int pcib_host_res_decodes(struct pcib_host_resources *hr, int type, + u_long start, u_long end, u_int flags); +struct resource *pcib_host_res_alloc(struct pcib_host_resources *hr, + device_t dev, int type, int *rid, u_long start, u_long end, + u_long count, u_int flags); +int pcib_host_res_adjust(struct pcib_host_resources *hr, + device_t dev, int type, struct resource *r, u_long start, + u_long end); +#endif + /* * Export portions of generic PCI:PCI bridge support so that it can be * used by subclasses. @@ -66,6 +91,7 @@ struct pcib_softc uint32_t flags; /* flags */ #define PCIB_SUBTRACTIVE 0x1 #define PCIB_DISABLE_MSI 0x2 +#define PCIB_DISABLE_MSIX 0x4 uint16_t command; /* command register */ u_int domain; /* domain number */ u_int pribus; /* primary bus number */ @@ -90,6 +116,9 @@ struct pcib_softc typedef uint32_t pci_read_config_fn(int b, int s, int f, int reg, int width); +#ifdef NEW_PCIB +const char *pcib_child_name(device_t child); +#endif int host_pcib_get_busno(pci_read_config_fn read_config, int bus, int slot, int func, uint8_t *busnum); int pcib_attach(device_t dev); diff --git a/freebsd/sys/dev/pci/pcireg.h b/freebsd/sys/dev/pci/pcireg.h index 0127e776..ef351356 100644 --- a/freebsd/sys/dev/pci/pcireg.h +++ b/freebsd/sys/dev/pci/pcireg.h @@ -69,7 +69,6 @@ #define PCIM_STATUS_66CAPABLE 0x0020 #define PCIM_STATUS_BACKTOBACK 0x0080 #define PCIM_STATUS_MDPERR 0x0100 -#define PCIM_STATUS_PERRREPORT PCIM_STATUS_MDPERR #define PCIM_STATUS_SEL_FAST 0x0000 #define PCIM_STATUS_SEL_MEDIMUM 0x0200 #define PCIM_STATUS_SEL_SLOW 0x0400 @@ -445,12 +444,16 @@ #define PCIR_POWER_CAP 0x2 #define PCIM_PCAP_SPEC 0x0007 #define PCIM_PCAP_PMEREQCLK 0x0008 -#define PCIM_PCAP_PMEREQPWR 0x0010 #define PCIM_PCAP_DEVSPECINIT 0x0020 -#define PCIM_PCAP_DYNCLOCK 0x0040 -#define PCIM_PCAP_SECCLOCK 0x00c0 -#define PCIM_PCAP_CLOCKMASK 0x00c0 -#define PCIM_PCAP_REQFULLCLOCK 0x0100 +#define PCIM_PCAP_AUXPWR_0 0x0000 +#define PCIM_PCAP_AUXPWR_55 0x0040 +#define PCIM_PCAP_AUXPWR_100 0x0080 +#define PCIM_PCAP_AUXPWR_160 0x00c0 +#define PCIM_PCAP_AUXPWR_220 0x0100 +#define PCIM_PCAP_AUXPWR_270 0x0140 +#define PCIM_PCAP_AUXPWR_320 0x0180 +#define PCIM_PCAP_AUXPWR_375 0x01c0 +#define PCIM_PCAP_AUXPWRMASK 0x01c0 #define PCIM_PCAP_D1SUPP 0x0200 #define PCIM_PCAP_D2SUPP 0x0400 #define PCIM_PCAP_D0PME 0x0800 @@ -465,16 +468,17 @@ #define PCIM_PSTAT_D2 0x0002 #define PCIM_PSTAT_D3 0x0003 #define PCIM_PSTAT_DMASK 0x0003 -#define PCIM_PSTAT_REPENABLE 0x0010 +#define PCIM_PSTAT_NOSOFTRESET 0x0008 #define PCIM_PSTAT_PMEENABLE 0x0100 #define PCIM_PSTAT_D0POWER 0x0000 #define PCIM_PSTAT_D1POWER 0x0200 #define PCIM_PSTAT_D2POWER 0x0400 #define PCIM_PSTAT_D3POWER 0x0600 #define PCIM_PSTAT_D0HEAT 0x0800 -#define PCIM_PSTAT_D1HEAT 0x1000 -#define PCIM_PSTAT_D2HEAT 0x1200 -#define PCIM_PSTAT_D3HEAT 0x1400 +#define PCIM_PSTAT_D1HEAT 0x0a00 +#define PCIM_PSTAT_D2HEAT 0x0c00 +#define PCIM_PSTAT_D3HEAT 0x0e00 +#define PCIM_PSTAT_DATASELMASK 0x1e00 #define PCIM_PSTAT_DATAUNKN 0x0000 #define PCIM_PSTAT_DATADIV10 0x2000 #define PCIM_PSTAT_DATADIV100 0x4000 @@ -482,11 +486,10 @@ #define PCIM_PSTAT_DATADIVMASK 0x6000 #define PCIM_PSTAT_PME 0x8000 -#define PCIR_POWER_PMCSR 0x6 -#define PCIM_PMCSR_DCLOCK 0x10 -#define PCIM_PMCSR_B2SUPP 0x20 -#define PCIM_BMCSR_B3SUPP 0x40 -#define PCIM_BMCSR_BPCE 0x80 +#define PCIR_POWER_BSE 0x6 +#define PCIM_PMCSR_BSE_D3B3 0x00 +#define PCIM_PMCSR_BSE_D3B2 0x40 +#define PCIM_PMCSR_BSE_BPCCE 0x80 #define PCIR_POWER_DATA 0x7 @@ -609,6 +612,10 @@ #define PCIM_HTCAP_VCSET 0xb800 /* 10111 */ #define PCIM_HTCAP_RETRY_MODE 0xc000 /* 11000 */ #define PCIM_HTCAP_X86_ENCODING 0xc800 /* 11001 */ +#define PCIM_HTCAP_GEN3 0xd000 /* 11010 */ +#define PCIM_HTCAP_FLE 0xd800 /* 11011 */ +#define PCIM_HTCAP_PM 0xe000 /* 11100 */ +#define PCIM_HTCAP_HIGH_NODE_COUNT 0xe800 /* 11101 */ /* HT MSI Mapping Capability definitions. */ #define PCIM_HTCMD_MSI_ENABLE 0x0001 @@ -770,7 +777,7 @@ #define PCIER_SLOT_CAP2 0x34 #define PCIER_SLOT_CTL2 0x38 #define PCIER_SLOT_STA2 0x3a - + /* Old compatibility definitions for PCI Express registers */ #define PCIR_EXPRESS_FLAGS PCIER_FLAGS #define PCIM_EXP_FLAGS_VERSION PCIEM_FLAGS_VERSION diff --git a/freebsd/sys/dev/pci/pcivar.h b/freebsd/sys/dev/pci/pcivar.h index b0359d30..84e7c871 100644 --- a/freebsd/sys/dev/pci/pcivar.h +++ b/freebsd/sys/dev/pci/pcivar.h @@ -42,9 +42,9 @@ typedef uint64_t pci_addr_t; /* Interesting values for PCI power management */ struct pcicfg_pp { uint16_t pp_cap; /* PCI power management capabilities */ - uint8_t pp_status; /* config space address of PCI power status reg */ - uint8_t pp_pmcsr; /* config space address of PMCSR reg */ - uint8_t pp_data; /* config space address of PCI power data reg */ + uint8_t pp_status; /* conf. space addr. of PM control/status reg */ + uint8_t pp_bse; /* conf. space addr. of PM BSE reg */ + uint8_t pp_data; /* conf. space addr. of PM data reg */ }; struct pci_map { @@ -465,6 +465,7 @@ device_t pci_find_class(uint8_t class, uint8_t subclass); int pci_pending_msix(device_t dev, u_int index); int pci_msi_device_blacklisted(device_t dev); +int pci_msix_device_blacklisted(device_t dev); void pci_ht_map_msi(device_t dev, uint64_t addr); diff --git a/freebsd/sys/dev/re/if_re.c b/freebsd/sys/dev/re/if_re.c index fb86f6a8..cde6bcee 100644 --- a/freebsd/sys/dev/re/if_re.c +++ b/freebsd/sys/dev/re/if_re.c @@ -298,6 +298,10 @@ static void re_setwol (struct rl_softc *); static void re_clrwol (struct rl_softc *); static void re_set_linkspeed (struct rl_softc *); +#ifdef DEV_NETMAP /* see ixgbe.c for details */ +#include <dev/netmap/if_re_netmap.h> +#endif /* !DEV_NETMAP */ + #ifdef RE_DIAG static int re_diag (struct rl_softc *); #endif @@ -756,7 +760,7 @@ re_diag(struct rl_softc *sc) u_int8_t src[] = { 0x00, 'w', 'o', 'r', 'l', 'd' }; /* Allocate a single mbuf */ - MGETHDR(m0, M_DONTWAIT, MT_DATA); + MGETHDR(m0, M_NOWAIT, MT_DATA); if (m0 == NULL) return (ENOBUFS); @@ -1243,7 +1247,7 @@ re_attach(device_t dev) msic = pci_msi_count(dev); msixc = pci_msix_count(dev); - if (pci_find_extcap(dev, PCIY_EXPRESS, ®) == 0) { + if (pci_find_cap(dev, PCIY_EXPRESS, ®) == 0) { sc->rl_flags |= RL_FLAG_PCIE; sc->rl_expcap = reg; } @@ -1585,7 +1589,8 @@ re_attach(device_t dev) * packet has IP options so disable TX IP checksum offloading. */ if (sc->rl_hwrev->rl_rev == RL_HWREV_8168C || - sc->rl_hwrev->rl_rev == RL_HWREV_8168C_SPIN2) + sc->rl_hwrev->rl_rev == RL_HWREV_8168C_SPIN2 || + sc->rl_hwrev->rl_rev == RL_HWREV_8168CP) ifp->if_hwassist = CSUM_TCP | CSUM_UDP; else ifp->if_hwassist = CSUM_IP | CSUM_TCP | CSUM_UDP; @@ -1622,7 +1627,7 @@ re_attach(device_t dev) if (ifp->if_capabilities & IFCAP_HWCSUM) ifp->if_capabilities |= IFCAP_VLAN_HWCSUM; /* Enable WOL if PM is supported. */ - if (pci_find_extcap(sc->rl_dev, PCIY_PMG, ®) == 0) + if (pci_find_cap(sc->rl_dev, PCIY_PMG, ®) == 0) ifp->if_capabilities |= IFCAP_WOL; ifp->if_capenable = ifp->if_capabilities; ifp->if_capenable &= ~(IFCAP_WOL_UCAST | IFCAP_WOL_MCAST); @@ -1643,6 +1648,9 @@ re_attach(device_t dev) */ ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header); +#ifdef DEV_NETMAP + re_netmap_attach(sc); +#endif /* DEV_NETMAP */ #ifdef RE_DIAG /* * Perform hardware diagnostic on the original RTL8169. @@ -1748,8 +1756,12 @@ re_detach(device_t dev) bus_teardown_intr(dev, sc->rl_irq[0], sc->rl_intrhand[0]); sc->rl_intrhand[0] = NULL; } - if (ifp != NULL) + if (ifp != NULL) { +#ifdef DEV_NETMAP + netmap_detach(ifp); +#endif /* DEV_NETMAP */ if_free(ifp); + } if ((sc->rl_flags & (RL_FLAG_MSI | RL_FLAG_MSIX)) == 0) rid = 0; else @@ -1877,7 +1889,7 @@ re_newbuf(struct rl_softc *sc, int idx) uint32_t cmdstat; int error, nsegs; - m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); + m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); if (m == NULL) return (ENOBUFS); @@ -1941,7 +1953,7 @@ re_jumbo_newbuf(struct rl_softc *sc, int idx) uint32_t cmdstat; int error, nsegs; - m = m_getjcl(M_DONTWAIT, MT_DATA, M_PKTHDR, MJUM9BYTES); + m = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, MJUM9BYTES); if (m == NULL) return (ENOBUFS); m->m_len = m->m_pkthdr.len = MJUM9BYTES; @@ -2012,6 +2024,9 @@ re_tx_list_init(struct rl_softc *sc) sc->rl_ldata.rl_tx_desc_cnt * sizeof(struct rl_desc)); for (i = 0; i < sc->rl_ldata.rl_tx_desc_cnt; i++) sc->rl_ldata.rl_tx_desc[i].tx_m = NULL; +#ifdef DEV_NETMAP + re_netmap_tx_init(sc); +#endif /* DEV_NETMAP */ /* Set EOR. */ desc = &sc->rl_ldata.rl_tx_list[sc->rl_ldata.rl_tx_desc_cnt - 1]; desc->rl_cmdstat |= htole32(RL_TDESC_CMD_EOR); @@ -2039,6 +2054,9 @@ re_rx_list_init(struct rl_softc *sc) if ((error = re_newbuf(sc, i)) != 0) return (error); } +#ifdef DEV_NETMAP + re_netmap_rx_init(sc); +#endif /* DEV_NETMAP */ /* Flush the RX descriptors */ @@ -2095,6 +2113,11 @@ re_rxeof(struct rl_softc *sc, int *rx_npktsp) RL_LOCK_ASSERT(sc); ifp = sc->rl_ifp; +#ifdef DEV_NETMAP + if (netmap_rx_irq(ifp, 0 | (NETMAP_LOCKED_ENTER|NETMAP_LOCKED_EXIT), + &rx_npkts)) + return 0; +#endif /* DEV_NETMAP */ if (ifp->if_mtu > RL_MTU && (sc->rl_flags & RL_FLAG_JUMBOV2) != 0) jumbo = 1; else @@ -2336,6 +2359,10 @@ re_txeof(struct rl_softc *sc) return; ifp = sc->rl_ifp; +#ifdef DEV_NETMAP + if (netmap_tx_irq(ifp, 0 | (NETMAP_LOCKED_ENTER|NETMAP_LOCKED_EXIT))) + return; +#endif /* DEV_NETMAP */ /* Invalidate the TX descriptor list */ bus_dmamap_sync(sc->rl_ldata.rl_tx_list_tag, sc->rl_ldata.rl_tx_list_map, @@ -2672,7 +2699,7 @@ re_encap(struct rl_softc *sc, struct mbuf **m_head) padlen = RL_MIN_FRAMELEN - (*m_head)->m_pkthdr.len; if (M_WRITABLE(*m_head) == 0) { /* Get a writable copy. */ - m_new = m_dup(*m_head, M_DONTWAIT); + m_new = m_dup(*m_head, M_NOWAIT); m_freem(*m_head); if (m_new == NULL) { *m_head = NULL; @@ -2682,7 +2709,7 @@ re_encap(struct rl_softc *sc, struct mbuf **m_head) } if ((*m_head)->m_next != NULL || M_TRAILINGSPACE(*m_head) < padlen) { - m_new = m_defrag(*m_head, M_DONTWAIT); + m_new = m_defrag(*m_head, M_NOWAIT); if (m_new == NULL) { m_freem(*m_head); *m_head = NULL; @@ -2706,7 +2733,7 @@ re_encap(struct rl_softc *sc, struct mbuf **m_head) error = bus_dmamap_load_mbuf_sg(sc->rl_ldata.rl_tx_mtag, txd->tx_dmamap, *m_head, segs, &nsegs, BUS_DMA_NOWAIT); if (error == EFBIG) { - m_new = m_collapse(*m_head, M_DONTWAIT, RL_NTXSEGS); + m_new = m_collapse(*m_head, M_NOWAIT, RL_NTXSEGS); if (m_new == NULL) { m_freem(*m_head); *m_head = NULL; @@ -2854,6 +2881,21 @@ re_start_locked(struct ifnet *ifp) sc = ifp->if_softc; +#ifdef DEV_NETMAP + /* XXX is this necessary ? */ + if (ifp->if_capenable & IFCAP_NETMAP) { + struct netmap_kring *kring = &NA(ifp)->tx_rings[0]; + if (sc->rl_ldata.rl_tx_prodidx != kring->nr_hwcur) { + /* kick the tx unit */ + CSR_WRITE_1(sc, sc->rl_txstart, RL_TXSTART_START); +#ifdef RE_TX_MODERATION + CSR_WRITE_4(sc, RL_TIMERCNT, 1); +#endif + sc->rl_watchdog_timer = 5; + } + return; + } +#endif /* DEV_NETMAP */ if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != IFF_DRV_RUNNING || (sc->rl_flags & RL_FLAG_LINK) == 0) return; @@ -3376,7 +3418,8 @@ re_ioctl(struct ifnet *ifp, u_long command, caddr_t data) if ((ifp->if_capenable & IFCAP_TXCSUM) != 0) { rev = sc->rl_hwrev->rl_rev; if (rev == RL_HWREV_8168C || - rev == RL_HWREV_8168C_SPIN2) + rev == RL_HWREV_8168C_SPIN2 || + rev == RL_HWREV_8168CP) ifp->if_hwassist |= CSUM_TCP | CSUM_UDP; else ifp->if_hwassist |= RE_CSUM_FEATURES; @@ -3692,7 +3735,7 @@ re_set_linkspeed(struct rl_softc *sc) miisc = LIST_FIRST(&mii->mii_phys); phyno = miisc->mii_phy; LIST_FOREACH(miisc, &mii->mii_phys, mii_list) - mii_phy_reset(miisc); + PHY_RESET(miisc); re_miibus_writereg(sc->rl_dev, phyno, MII_100T2CR, 0); re_miibus_writereg(sc->rl_dev, phyno, MII_ANAR, ANAR_TX_FD | ANAR_TX | ANAR_10_FD | ANAR_10 | ANAR_CSMA); @@ -3742,7 +3785,7 @@ re_setwol(struct rl_softc *sc) RL_LOCK_ASSERT(sc); - if (pci_find_extcap(sc->rl_dev, PCIY_PMG, &pmc) != 0) + if (pci_find_cap(sc->rl_dev, PCIY_PMG, &pmc) != 0) return; ifp = sc->rl_ifp; @@ -3814,7 +3857,7 @@ re_clrwol(struct rl_softc *sc) RL_LOCK_ASSERT(sc); - if (pci_find_extcap(sc->rl_dev, PCIY_PMG, &pmc) != 0) + if (pci_find_cap(sc->rl_dev, PCIY_PMG, &pmc) != 0) return; /* Enable config register write. */ diff --git a/freebsd/sys/dev/smc/if_smc.c b/freebsd/sys/dev/smc/if_smc.c index b6cb58fd..073a35c1 100644 --- a/freebsd/sys/dev/smc/if_smc.c +++ b/freebsd/sys/dev/smc/if_smc.c @@ -690,11 +690,11 @@ smc_task_rx(void *context, int pending) /* * Grab an mbuf and attach a cluster. */ - MGETHDR(m, M_DONTWAIT, MT_DATA); + MGETHDR(m, M_NOWAIT, MT_DATA); if (m == NULL) { break; } - MCLGET(m, M_DONTWAIT); + MCLGET(m, M_NOWAIT); if ((m->m_flags & M_EXT) == 0) { m_freem(m); break; diff --git a/freebsd/sys/dev/usb/controller/ehci.c b/freebsd/sys/dev/usb/controller/ehci.c index 18864431..456aff61 100644 --- a/freebsd/sys/dev/usb/controller/ehci.c +++ b/freebsd/sys/dev/usb/controller/ehci.c @@ -96,7 +96,7 @@ static int ehcinohighspeed = 0; static int ehciiaadbug = 0; static int ehcilostintrbug = 0; -SYSCTL_NODE(_hw_usb, OID_AUTO, ehci, CTLFLAG_RW, 0, "USB ehci"); +static SYSCTL_NODE(_hw_usb, OID_AUTO, ehci, CTLFLAG_RW, 0, "USB ehci"); SYSCTL_INT(_hw_usb_ehci, OID_AUTO, debug, CTLFLAG_RW | CTLFLAG_TUN, &ehcidebug, 0, "Debug level"); TUNABLE_INT("hw.usb.ehci.debug", &ehcidebug); @@ -334,14 +334,18 @@ ehci_init(ehci_softc_t *sc) sc->sc_noport = EHCI_HCS_N_PORTS(sparams); sc->sc_bus.usbrev = USB_REV_2_0; - /* Reset the controller */ - DPRINTF("%s: resetting\n", device_get_nameunit(sc->sc_bus.bdev)); + if (!(sc->sc_flags & EHCI_SCFLG_DONTRESET)) { + /* Reset the controller */ + DPRINTF("%s: resetting\n", + device_get_nameunit(sc->sc_bus.bdev)); - err = ehci_hcreset(sc); - if (err) { - device_printf(sc->sc_bus.bdev, "reset timeout\n"); - return (err); + err = ehci_hcreset(sc); + if (err) { + device_printf(sc->sc_bus.bdev, "reset timeout\n"); + return (err); + } } + /* * use current frame-list-size selection 0: 1024*4 bytes 1: 512*4 * bytes 2: 256*4 bytes 3: unknown diff --git a/freebsd/sys/dev/usb/controller/ehci.h b/freebsd/sys/dev/usb/controller/ehci.h index a64d48a0..f718a8a7 100644 --- a/freebsd/sys/dev/usb/controller/ehci.h +++ b/freebsd/sys/dev/usb/controller/ehci.h @@ -345,6 +345,8 @@ typedef struct ehci_softc { #define EHCI_SCFLG_TT 0x0020 /* transaction translator present */ #define EHCI_SCFLG_LOSTINTRBUG 0x0040 /* workaround for VIA / ATI chipsets */ #define EHCI_SCFLG_IAADBUG 0x0080 /* workaround for nVidia chipsets */ +#define EHCI_SCFLG_DONTRESET 0x0100 /* don't reset ctrl. in ehci_init() */ +#define EHCI_SCFLG_DONEINIT 0x1000 /* ehci_init() has been called. */ uint8_t sc_offs; /* offset to operational registers */ uint8_t sc_doorbell_disable; /* set on doorbell failure */ diff --git a/freebsd/sys/dev/usb/controller/ohci.c b/freebsd/sys/dev/usb/controller/ohci.c index 94e94fd9..42129a8e 100644 --- a/freebsd/sys/dev/usb/controller/ohci.c +++ b/freebsd/sys/dev/usb/controller/ohci.c @@ -82,7 +82,7 @@ __FBSDID("$FreeBSD$"); #ifdef USB_DEBUG static int ohcidebug = 0; -SYSCTL_NODE(_hw_usb, OID_AUTO, ohci, CTLFLAG_RW, 0, "USB ohci"); +static SYSCTL_NODE(_hw_usb, OID_AUTO, ohci, CTLFLAG_RW, 0, "USB ohci"); SYSCTL_INT(_hw_usb_ohci, OID_AUTO, debug, CTLFLAG_RW | CTLFLAG_TUN, &ohcidebug, 0, "ohci debug level"); TUNABLE_INT("hw.usb.ohci.debug", &ohcidebug); diff --git a/freebsd/sys/dev/usb/controller/usb_controller.c b/freebsd/sys/dev/usb/controller/usb_controller.c index 3f9c8742..37f79364 100644 --- a/freebsd/sys/dev/usb/controller/usb_controller.c +++ b/freebsd/sys/dev/usb/controller/usb_controller.c @@ -81,7 +81,7 @@ static void usb_attach_sub(device_t, struct usb_bus *); #ifdef USB_DEBUG static int usb_ctrl_debug = 0; -SYSCTL_NODE(_hw_usb, OID_AUTO, ctrl, CTLFLAG_RW, 0, "USB controller"); +static SYSCTL_NODE(_hw_usb, OID_AUTO, ctrl, CTLFLAG_RW, 0, "USB controller"); SYSCTL_INT(_hw_usb_ctrl, OID_AUTO, debug, CTLFLAG_RW, &usb_ctrl_debug, 0, "Debug level"); #endif @@ -889,3 +889,28 @@ usb_bus_mem_free_all(struct usb_bus *bus, usb_bus_mem_cb_t *cb) mtx_destroy(&bus->bus_mtx); } + +/* convenience wrappers */ +void +usb_proc_explore_mwait(struct usb_device *udev, void *pm1, void *pm2) +{ + usb_proc_mwait(&udev->bus->explore_proc, pm1, pm2); +} + +void * +usb_proc_explore_msignal(struct usb_device *udev, void *pm1, void *pm2) +{ + return (usb_proc_msignal(&udev->bus->explore_proc, pm1, pm2)); +} + +void +usb_proc_explore_lock(struct usb_device *udev) +{ + USB_BUS_LOCK(udev->bus); +} + +void +usb_proc_explore_unlock(struct usb_device *udev) +{ + USB_BUS_UNLOCK(udev->bus); +} diff --git a/freebsd/sys/dev/usb/controller/xhcireg.h b/freebsd/sys/dev/usb/controller/xhcireg.h new file mode 100644 index 00000000..85d989a6 --- /dev/null +++ b/freebsd/sys/dev/usb/controller/xhcireg.h @@ -0,0 +1,221 @@ +/* $FreeBSD$ */ + +/*- + * Copyright (c) 2010 Hans Petter Selasky. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _XHCIREG_H_ +#define _XHCIREG_H_ + +/* XHCI PCI config registers */ +#define PCI_XHCI_CBMEM 0x10 /* configuration base MEM */ +#define PCI_XHCI_USBREV 0x60 /* RO USB protocol revision */ +#define PCI_USB_REV_3_0 0x30 /* USB 3.0 */ +#define PCI_XHCI_FLADJ 0x61 /* RW frame length adjust */ + +#define PCI_XHCI_INTEL_XUSB2PR 0xD0 /* Intel USB2 Port Routing */ +#define PCI_XHCI_INTEL_USB3_PSSEN 0xD8 /* Intel USB3 Port SuperSpeed Enable */ + +/* XHCI capability registers */ +#define XHCI_CAPLENGTH 0x00 /* RO capability */ +#define XHCI_RESERVED 0x01 /* Reserved */ +#define XHCI_HCIVERSION 0x02 /* RO Interface version number */ +#define XHCI_HCIVERSION_0_9 0x0090 /* xHCI version 0.9 */ +#define XHCI_HCIVERSION_1_0 0x0100 /* xHCI version 1.0 */ +#define XHCI_HCSPARAMS1 0x04 /* RO structual parameters 1 */ +#define XHCI_HCS1_DEVSLOT_MAX(x)((x) & 0xFF) +#define XHCI_HCS1_IRQ_MAX(x) (((x) >> 8) & 0x3FF) +#define XHCI_HCS1_N_PORTS(x) (((x) >> 24) & 0xFF) +#define XHCI_HCSPARAMS2 0x08 /* RO structual parameters 2 */ +#define XHCI_HCS2_IST(x) ((x) & 0xF) +#define XHCI_HCS2_ERST_MAX(x) (((x) >> 4) & 0xF) +#define XHCI_HCS2_SPR(x) (((x) >> 24) & 0x1) +#define XHCI_HCS2_SPB_MAX(x) (((x) >> 27) & 0x7F) +#define XHCI_HCSPARAMS3 0x0C /* RO structual parameters 3 */ +#define XHCI_HCS3_U1_DEL(x) ((x) & 0xFF) +#define XHCI_HCS3_U2_DEL(x) (((x) >> 16) & 0xFFFF) +#define XHCI_HCSPARAMS0 0x10 /* RO capability parameters */ +#define XHCI_HCS0_AC64(x) ((x) & 0x1) /* 64-bit capable */ +#define XHCI_HCS0_BNC(x) (((x) >> 1) & 0x1) /* BW negotiation */ +#define XHCI_HCS0_CSZ(x) (((x) >> 2) & 0x1) /* context size */ +#define XHCI_HCS0_PPC(x) (((x) >> 3) & 0x1) /* port power control */ +#define XHCI_HCS0_PIND(x) (((x) >> 4) & 0x1) /* port indicators */ +#define XHCI_HCS0_LHRC(x) (((x) >> 5) & 0x1) /* light HC reset */ +#define XHCI_HCS0_LTC(x) (((x) >> 6) & 0x1) /* latency tolerance msg */ +#define XHCI_HCS0_NSS(x) (((x) >> 7) & 0x1) /* no secondary sid */ +#define XHCI_HCS0_PSA_SZ_MAX(x) (((x) >> 12) & 0xF) /* max pri. stream array size */ +#define XHCI_HCS0_XECP(x) (((x) >> 16) & 0xFFFF) /* extended capabilities pointer */ +#define XHCI_DBOFF 0x14 /* RO doorbell offset */ +#define XHCI_RTSOFF 0x18 /* RO runtime register space offset */ + +/* XHCI operational registers. Offset given by XHCI_CAPLENGTH register */ +#define XHCI_USBCMD 0x00 /* XHCI command */ +#define XHCI_CMD_RS 0x00000001 /* RW Run/Stop */ +#define XHCI_CMD_HCRST 0x00000002 /* RW Host Controller Reset */ +#define XHCI_CMD_INTE 0x00000004 /* RW Interrupter Enable */ +#define XHCI_CMD_HSEE 0x00000008 /* RW Host System Error Enable */ +#define XHCI_CMD_LHCRST 0x00000080 /* RO/RW Light Host Controller Reset */ +#define XHCI_CMD_CSS 0x00000100 /* RW Controller Save State */ +#define XHCI_CMD_CRS 0x00000200 /* RW Controller Restore State */ +#define XHCI_CMD_EWE 0x00000400 /* RW Enable Wrap Event */ +#define XHCI_CMD_EU3S 0x00000800 /* RW Enable U3 MFINDEX Stop */ +#define XHCI_USBSTS 0x04 /* XHCI status */ +#define XHCI_STS_HCH 0x00000001 /* RO - Host Controller Halted */ +#define XHCI_STS_HSE 0x00000004 /* RW - Host System Error */ +#define XHCI_STS_EINT 0x00000008 /* RW - Event Interrupt */ +#define XHCI_STS_PCD 0x00000010 /* RW - Port Change Detect */ +#define XHCI_STS_SSS 0x00000100 /* RO - Save State Status */ +#define XHCI_STS_RSS 0x00000200 /* RO - Restore State Status */ +#define XHCI_STS_SRE 0x00000400 /* RW - Save/Restore Error */ +#define XHCI_STS_CNR 0x00000800 /* RO - Controller Not Ready */ +#define XHCI_STS_HCE 0x00001000 /* RO - Host Controller Error */ +#define XHCI_PAGESIZE 0x08 /* XHCI page size mask */ +#define XHCI_PAGESIZE_4K 0x00000001 /* 4K Page Size */ +#define XHCI_PAGESIZE_8K 0x00000002 /* 8K Page Size */ +#define XHCI_PAGESIZE_16K 0x00000004 /* 16K Page Size */ +#define XHCI_PAGESIZE_32K 0x00000008 /* 32K Page Size */ +#define XHCI_PAGESIZE_64K 0x00000010 /* 64K Page Size */ +#define XHCI_DNCTRL 0x14 /* XHCI device notification control */ +#define XHCI_DNCTRL_MASK(n) (1U << (n)) +#define XHCI_CRCR_LO 0x18 /* XHCI command ring control */ +#define XHCI_CRCR_LO_RCS 0x00000001 /* RW - consumer cycle state */ +#define XHCI_CRCR_LO_CS 0x00000002 /* RW - command stop */ +#define XHCI_CRCR_LO_CA 0x00000004 /* RW - command abort */ +#define XHCI_CRCR_LO_CRR 0x00000008 /* RW - command ring running */ +#define XHCI_CRCR_LO_MASK 0x0000000F +#define XHCI_CRCR_HI 0x1C /* XHCI command ring control */ +#define XHCI_DCBAAP_LO 0x30 /* XHCI dev context BA pointer */ +#define XHCI_DCBAAP_HI 0x34 /* XHCI dev context BA pointer */ +#define XHCI_CONFIG 0x38 +#define XHCI_CONFIG_SLOTS_MASK 0x000000FF /* RW - number of device slots enabled */ + +/* XHCI port status registers */ +#define XHCI_PORTSC(n) (0x3F0 + (0x10 * (n))) /* XHCI port status */ +#define XHCI_PS_CCS 0x00000001 /* RO - current connect status */ +#define XHCI_PS_PED 0x00000002 /* RW - port enabled / disabled */ +#define XHCI_PS_OCA 0x00000008 /* RO - over current active */ +#define XHCI_PS_PR 0x00000010 /* RW - port reset */ +#define XHCI_PS_PLS_GET(x) (((x) >> 5) & 0xF) /* RW - port link state */ +#define XHCI_PS_PLS_SET(x) (((x) & 0xF) << 5) /* RW - port link state */ +#define XHCI_PS_PP 0x00000200 /* RW - port power */ +#define XHCI_PS_SPEED_GET(x) (((x) >> 10) & 0xF) /* RO - port speed */ +#define XHCI_PS_PIC_GET(x) (((x) >> 14) & 0x3) /* RW - port indicator */ +#define XHCI_PS_PIC_SET(x) (((x) & 0x3) << 14) /* RW - port indicator */ +#define XHCI_PS_LWS 0x00010000 /* RW - port link state write strobe */ +#define XHCI_PS_CSC 0x00020000 /* RW - connect status change */ +#define XHCI_PS_PEC 0x00040000 /* RW - port enable/disable change */ +#define XHCI_PS_WRC 0x00080000 /* RW - warm port reset change */ +#define XHCI_PS_OCC 0x00100000 /* RW - over-current change */ +#define XHCI_PS_PRC 0x00200000 /* RW - port reset change */ +#define XHCI_PS_PLC 0x00400000 /* RW - port link state change */ +#define XHCI_PS_CEC 0x00800000 /* RW - config error change */ +#define XHCI_PS_CAS 0x01000000 /* RO - cold attach status */ +#define XHCI_PS_WCE 0x02000000 /* RW - wake on connect enable */ +#define XHCI_PS_WDE 0x04000000 /* RW - wake on disconnect enable */ +#define XHCI_PS_WOE 0x08000000 /* RW - wake on over-current enable */ +#define XHCI_PS_DR 0x40000000 /* RO - device removable */ +#define XHCI_PS_WPR 0x80000000U /* RW - warm port reset */ +#define XHCI_PS_CLEAR 0x80FF01FFU /* command bits */ + +#define XHCI_PORTPMSC(n) (0x3F4 + (0x10 * (n))) /* XHCI status and control */ +#define XHCI_PM3_U1TO_GET(x) (((x) >> 0) & 0xFF) /* RW - U1 timeout */ +#define XHCI_PM3_U1TO_SET(x) (((x) & 0xFF) << 0) /* RW - U1 timeout */ +#define XHCI_PM3_U2TO_GET(x) (((x) >> 8) & 0xFF) /* RW - U2 timeout */ +#define XHCI_PM3_U2TO_SET(x) (((x) & 0xFF) << 8) /* RW - U2 timeout */ +#define XHCI_PM3_FLA 0x00010000 /* RW - Force Link PM Accept */ +#define XHCI_PM2_L1S_GET(x) (((x) >> 0) & 0x7) /* RO - L1 status */ +#define XHCI_PM2_RWE 0x00000008 /* RW - remote wakup enable */ +#define XHCI_PM2_HIRD_GET(x) (((x) >> 4) & 0xF) /* RW - host initiated resume duration */ +#define XHCI_PM2_HIRD_SET(x) (((x) & 0xF) << 4) /* RW - host initiated resume duration */ +#define XHCI_PM2_L1SLOT_GET(x) (((x) >> 8) & 0xFF) /* RW - L1 device slot */ +#define XHCI_PM2_L1SLOT_SET(x) (((x) & 0xFF) << 8) /* RW - L1 device slot */ +#define XHCI_PM2_HLE 0x00010000 /* RW - hardware LPM enable */ +#define XHCI_PORTLI(n) (0x3F8 + (0x10 * (n))) /* XHCI port link info */ +#define XHCI_PLI3_ERR_GET(x) (((x) >> 0) & 0xFFFF) /* RO - port link errors */ +#define XHCI_PORTRSV(n) (0x3FC + (0x10 * (n))) /* XHCI port reserved */ + +/* XHCI runtime registers. Offset given by XHCI_CAPLENGTH + XHCI_RTSOFF registers */ +#define XHCI_MFINDEX 0x0000 /* RO - microframe index */ +#define XHCI_MFINDEX_GET(x) ((x) & 0x3FFF) +#define XHCI_IMAN(n) (0x0020 + (0x20 * (n))) /* XHCI interrupt management */ +#define XHCI_IMAN_INTR_PEND 0x00000001 /* RW - interrupt pending */ +#define XHCI_IMAN_INTR_ENA 0x00000002 /* RW - interrupt enable */ +#define XHCI_IMOD(n) (0x0024 + (0x20 * (n))) /* XHCI interrupt moderation */ +#define XHCI_IMOD_IVAL_GET(x) (((x) >> 0) & 0xFFFF) /* 250ns unit */ +#define XHCI_IMOD_IVAL_SET(x) (((x) & 0xFFFF) << 0) /* 250ns unit */ +#define XHCI_IMOD_ICNT_GET(x) (((x) >> 16) & 0xFFFF) /* 250ns unit */ +#define XHCI_IMOD_ICNT_SET(x) (((x) & 0xFFFF) << 16) /* 250ns unit */ +#define XHCI_IMOD_DEFAULT 0x000003E8U /* 8000 IRQ/second */ +#define XHCI_ERSTSZ(n) (0x0028 + (0x20 * (n))) /* XHCI event ring segment table size */ +#define XHCI_ERSTS_GET(x) ((x) & 0xFFFF) +#define XHCI_ERSTS_SET(x) ((x) & 0xFFFF) +#define XHCI_ERSTBA_LO(n) (0x0030 + (0x20 * (n))) /* XHCI event ring segment table BA */ +#define XHCI_ERSTBA_HI(n) (0x0034 + (0x20 * (n))) /* XHCI event ring segment table BA */ +#define XHCI_ERDP_LO(n) (0x0038 + (0x20 * (n))) /* XHCI event ring dequeue pointer */ +#define XHCI_ERDP_LO_SINDEX(x) ((x) & 0x7) /* RO - dequeue segment index */ +#define XHCI_ERDP_LO_BUSY 0x00000008 /* RW - event handler busy */ +#define XHCI_ERDP_HI(n) (0x003C + (0x20 * (n))) /* XHCI event ring dequeue pointer */ + +/* XHCI doorbell registers. Offset given by XHCI_CAPLENGTH + XHCI_DBOFF registers */ +#define XHCI_DOORBELL(n) (0x0000 + (4 * (n))) +#define XHCI_DB_TARGET_GET(x) ((x) & 0xFF) /* RW - doorbell target */ +#define XHCI_DB_TARGET_SET(x) ((x) & 0xFF) /* RW - doorbell target */ +#define XHCI_DB_SID_GET(x) (((x) >> 16) & 0xFFFF) /* RW - doorbell stream ID */ +#define XHCI_DB_SID_SET(x) (((x) & 0xFFFF) << 16) /* RW - doorbell stream ID */ + +/* XHCI legacy support */ +#define XHCI_XECP_ID(x) ((x) & 0xFF) +#define XHCI_XECP_NEXT(x) (((x) >> 8) & 0xFF) +#define XHCI_XECP_BIOS_SEM 0x0002 +#define XHCI_XECP_OS_SEM 0x0003 + +/* XHCI capability ID's */ +#define XHCI_ID_USB_LEGACY 0x0001 +#define XHCI_ID_PROTOCOLS 0x0002 +#define XHCI_ID_POWER_MGMT 0x0003 +#define XHCI_ID_VIRTUALIZATION 0x0004 +#define XHCI_ID_MSG_IRQ 0x0005 +#define XHCI_ID_USB_LOCAL_MEM 0x0006 + +/* XHCI register R/W wrappers */ +#define XREAD1(sc, what, a) \ + bus_space_read_1((sc)->sc_io_tag, (sc)->sc_io_hdl, \ + (a) + (sc)->sc_##what##_off) +#define XREAD2(sc, what, a) \ + bus_space_read_2((sc)->sc_io_tag, (sc)->sc_io_hdl, \ + (a) + (sc)->sc_##what##_off) +#define XREAD4(sc, what, a) \ + bus_space_read_4((sc)->sc_io_tag, (sc)->sc_io_hdl, \ + (a) + (sc)->sc_##what##_off) +#define XWRITE1(sc, what, a, x) \ + bus_space_write_1((sc)->sc_io_tag, (sc)->sc_io_hdl, \ + (a) + (sc)->sc_##what##_off, (x)) +#define XWRITE2(sc, what, a, x) \ + bus_space_write_2((sc)->sc_io_tag, (sc)->sc_io_hdl, \ + (a) + (sc)->sc_##what##_off, (x)) +#define XWRITE4(sc, what, a, x) \ + bus_space_write_4((sc)->sc_io_tag, (sc)->sc_io_hdl, \ + (a) + (sc)->sc_##what##_off, (x)) + +#endif /* _XHCIREG_H_ */ diff --git a/freebsd/sys/dev/usb/quirk/usb_quirk.c b/freebsd/sys/dev/usb/quirk/usb_quirk.c index 2df2de5e..9042c166 100644 --- a/freebsd/sys/dev/usb/quirk/usb_quirk.c +++ b/freebsd/sys/dev/usb/quirk/usb_quirk.c @@ -96,6 +96,7 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = { USB_QUIRK(SILICONPORTALS, YAPPHONE, 0x100, 0x100, UQ_AU_INP_ASYNC), USB_QUIRK(LOGITECH, UN53B, 0x0000, 0xffff, UQ_NO_STRINGS), USB_QUIRK(ELSA, MODEM1, 0x0000, 0xffff, UQ_CFG_INDEX_1), + USB_QUIRK(PLANEX2, MZKUE150N, 0x0000, 0xffff, UQ_CFG_INDEX_1), /* Quirks for printer devices */ USB_QUIRK(HP, 895C, 0x0000, 0xffff, UQ_BROKEN_BIDIR), USB_QUIRK(HP, 880C, 0x0000, 0xffff, UQ_BROKEN_BIDIR), @@ -127,6 +128,8 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = { /* MS keyboards do weird things */ USB_QUIRK(MICROSOFT, NATURAL4000, 0x0000, 0xFFFF, UQ_KBD_BOOTPROTO), USB_QUIRK(MICROSOFT, WLINTELLIMOUSE, 0x0000, 0xffff, UQ_MS_LEADING_BYTE), + /* Quirk for Corsair Vengeance K60 keyboard */ + USB_QUIRK(CORSAIR, K60, 0x0000, 0xffff, UQ_KBD_BOOTPROTO), /* umodem(4) device quirks */ USB_QUIRK(METRICOM, RICOCHET_GS, 0x100, 0x100, UQ_ASSUME_CM_OVER_DATA), USB_QUIRK(SANYO, SCP4900, 0x000, 0x000, UQ_ASSUME_CM_OVER_DATA), @@ -254,6 +257,7 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = { USB_QUIRK(MICROTECH, DPCM, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_TEST_UNIT_READY, UQ_MSC_NO_START_STOP), + USB_QUIRK(MICRON, REALSSD, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE), USB_QUIRK(MICROTECH, SCSIDB25, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI), USB_QUIRK(MICROTECH, SCSIHD50, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB, @@ -391,6 +395,7 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = { UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_GETMAXLUN), USB_QUIRK(SONY, PORTABLE_HDD_V2, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI), + USB_QUIRK(STMICRO, ST72682, 0x0000, 0xffff, UQ_MSC_NO_PREVENT_ALLOW), USB_QUIRK(SUPERTOP, IDE, 0x0000, 0xffff, UQ_MSC_IGNORE_RESIDUE, UQ_MSC_NO_SYNC_CACHE), USB_QUIRK(TAUGA, CAMERAMATE, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_SCSI), @@ -443,6 +448,9 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = { USB_QUIRK(MEIZU, M6_SL, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY, UQ_MSC_NO_SYNC_CACHE), + USB_QUIRK(TOSHIBA, TRANSMEMORY, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE), + USB_QUIRK(VIALABS, USB30SATABRIDGE, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE), + /* Non-standard USB MIDI devices */ USB_QUIRK(ROLAND, UM1, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS), USB_QUIRK(ROLAND, SC8850, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS), @@ -460,7 +468,13 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = { USB_QUIRK(ROLAND, SD20, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS), USB_QUIRK(ROLAND, SD80, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS), USB_QUIRK(ROLAND, UA700, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS), + USB_QUIRK(EGO, M4U, 0x0000, 0xffff, UQ_SINGLE_CMD_MIDI), + USB_QUIRK(LOGILINK, U2M, 0x0000, 0xffff, UQ_SINGLE_CMD_MIDI), USB_QUIRK(MEDELI, DD305, 0x0000, 0xffff, UQ_SINGLE_CMD_MIDI, UQ_MATCH_VENDOR_ONLY), + USB_QUIRK(REDOCTANE, GHMIDI, 0x0000, 0xffff, UQ_SINGLE_CMD_MIDI), + USB_QUIRK(TEXTECH, U2M_1, 0x0000, 0xffff, UQ_SINGLE_CMD_MIDI), + USB_QUIRK(TEXTECH, U2M_2, 0x0000, 0xffff, UQ_SINGLE_CMD_MIDI), + USB_QUIRK(WCH2, U2M, 0x0000, 0xffff, UQ_SINGLE_CMD_MIDI), /* Non-standard USB AUDIO devices */ USB_QUIRK(MAUDIO, FASTTRACKULTRA, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS), @@ -514,6 +528,7 @@ static const char *usb_quirk_str[USB_QUIRK_MAX] = { [UQ_MSC_NO_GETMAXLUN] = "UQ_MSC_NO_GETMAXLUN", [UQ_MSC_NO_INQUIRY] = "UQ_MSC_NO_INQUIRY", [UQ_MSC_NO_INQUIRY_EVPD] = "UQ_MSC_NO_INQUIRY_EVPD", + [UQ_MSC_NO_PREVENT_ALLOW] = "UQ_MSC_NO_PREVENT_ALLOW", [UQ_MSC_NO_SYNC_CACHE] = "UQ_MSC_NO_SYNC_CACHE", [UQ_MSC_SHUTTLE_INIT] = "UQ_MSC_SHUTTLE_INIT", [UQ_MSC_ALT_IFACE_1] = "UQ_MSC_ALT_IFACE_1", diff --git a/freebsd/sys/dev/usb/quirk/usb_quirk.h b/freebsd/sys/dev/usb/quirk/usb_quirk.h index f2c10dd8..32a60a10 100644 --- a/freebsd/sys/dev/usb/quirk/usb_quirk.h +++ b/freebsd/sys/dev/usb/quirk/usb_quirk.h @@ -75,6 +75,7 @@ enum { UQ_MSC_NO_GETMAXLUN, /* does not support get max LUN */ UQ_MSC_NO_INQUIRY, /* fake generic inq response */ UQ_MSC_NO_INQUIRY_EVPD, /* does not support inq EVPD */ + UQ_MSC_NO_PREVENT_ALLOW, /* does not support medium removal */ UQ_MSC_NO_SYNC_CACHE, /* does not support sync cache */ UQ_MSC_SHUTTLE_INIT, /* requires Shuttle init sequence */ UQ_MSC_ALT_IFACE_1, /* switch to alternate interface 1 */ diff --git a/freebsd/sys/dev/usb/storage/umass.c b/freebsd/sys/dev/usb/storage/umass.c index d3d2040f..76a1fcb6 100644 --- a/freebsd/sys/dev/usb/storage/umass.c +++ b/freebsd/sys/dev/usb/storage/umass.c @@ -139,14 +139,6 @@ __FBSDID("$FreeBSD$"); #include <cam/cam_periph.h> -#define UMASS_EXT_BUFFER -#ifdef UMASS_EXT_BUFFER -/* this enables loading of virtual buffers into DMA */ -#define UMASS_USB_FLAGS .ext_buffer=1, -#else -#define UMASS_USB_FLAGS -#endif - #ifdef USB_DEBUG #define DIF(m, x) \ do { \ @@ -173,19 +165,21 @@ __FBSDID("$FreeBSD$"); #define UDMASS_CBI 0x00400000 /* CBI transfers */ #define UDMASS_WIRE (UDMASS_BBB|UDMASS_CBI) #define UDMASS_ALL 0xffff0000 /* all of the above */ -static int umass_debug = 0; +static int umass_debug; +static int umass_throttle; -SYSCTL_NODE(_hw_usb, OID_AUTO, umass, CTLFLAG_RW, 0, "USB umass"); +static SYSCTL_NODE(_hw_usb, OID_AUTO, umass, CTLFLAG_RW, 0, "USB umass"); SYSCTL_INT(_hw_usb_umass, OID_AUTO, debug, CTLFLAG_RW | CTLFLAG_TUN, &umass_debug, 0, "umass debug level"); TUNABLE_INT("hw.usb.umass.debug", &umass_debug); +SYSCTL_INT(_hw_usb_umass, OID_AUTO, throttle, CTLFLAG_RW | CTLFLAG_TUN, + &umass_throttle, 0, "Forced delay between commands in milliseconds"); +TUNABLE_INT("hw.usb.umass.throttle", &umass_throttle); #else #define DIF(...) do { } while (0) #define DPRINTF(...) do { } while (0) #endif -#define UMASS_GONE ((struct umass_softc *)1) - #define UMASS_BULK_SIZE (1 << 17) #define UMASS_CBI_DIAGNOSTIC_CMDLEN 12 /* bytes */ #define UMASS_MAX_CMDLEN MAX(12, CAM_MAX_CDBLEN) /* bytes */ @@ -373,6 +367,8 @@ typedef uint8_t (umass_transform_t)(struct umass_softc *sc, uint8_t *cmd_ptr, * result. */ #define NO_SYNCHRONIZE_CACHE 0x4000 + /* Device does not support 'PREVENT/ALLOW MEDIUM REMOVAL'. */ +#define NO_PREVENT_ALLOW 0x8000 struct umass_softc { @@ -545,7 +541,7 @@ static struct usb_config umass_bbb_config[UMASS_T_BBB_MAX] = { .endpoint = UE_ADDR_ANY, .direction = UE_DIR_IN, .bufsize = UMASS_BULK_SIZE, - .flags = {.proxy_buffer = 1,.short_xfer_ok = 1, UMASS_USB_FLAGS}, + .flags = {.proxy_buffer = 1,.short_xfer_ok = 1,.ext_buffer=1,}, .callback = &umass_t_bbb_data_read_callback, .timeout = 0, /* overwritten later */ }, @@ -564,7 +560,7 @@ static struct usb_config umass_bbb_config[UMASS_T_BBB_MAX] = { .endpoint = UE_ADDR_ANY, .direction = UE_DIR_OUT, .bufsize = UMASS_BULK_SIZE, - .flags = {.proxy_buffer = 1,.short_xfer_ok = 1, UMASS_USB_FLAGS}, + .flags = {.proxy_buffer = 1,.short_xfer_ok = 1,.ext_buffer=1,}, .callback = &umass_t_bbb_data_write_callback, .timeout = 0, /* overwritten later */ }, @@ -637,7 +633,7 @@ static struct usb_config umass_cbi_config[UMASS_T_CBI_MAX] = { .endpoint = UE_ADDR_ANY, .direction = UE_DIR_IN, .bufsize = UMASS_BULK_SIZE, - .flags = {.proxy_buffer = 1,.short_xfer_ok = 1, UMASS_USB_FLAGS}, + .flags = {.proxy_buffer = 1,.short_xfer_ok = 1,.ext_buffer=1,}, .callback = &umass_t_cbi_data_read_callback, .timeout = 0, /* overwritten later */ }, @@ -656,7 +652,7 @@ static struct usb_config umass_cbi_config[UMASS_T_CBI_MAX] = { .endpoint = UE_ADDR_ANY, .direction = UE_DIR_OUT, .bufsize = UMASS_BULK_SIZE, - .flags = {.proxy_buffer = 1,.short_xfer_ok = 1, UMASS_USB_FLAGS}, + .flags = {.proxy_buffer = 1,.short_xfer_ok = 1,.ext_buffer=1,}, .callback = &umass_t_cbi_data_write_callback, .timeout = 0, /* overwritten later */ }, @@ -845,6 +841,8 @@ umass_probe_proto(device_t dev, struct usb_attach_arg *uaa) quirks |= NO_INQUIRY; if (usb_test_quirk(uaa, UQ_MSC_NO_INQUIRY_EVPD)) quirks |= NO_INQUIRY_EVPD; + if (usb_test_quirk(uaa, UQ_MSC_NO_PREVENT_ALLOW)) + quirks |= NO_PREVENT_ALLOW; if (usb_test_quirk(uaa, UQ_MSC_NO_SYNC_CACHE)) quirks |= NO_SYNCHRONIZE_CACHE; if (usb_test_quirk(uaa, UQ_MSC_SHUTTLE_INIT)) @@ -891,7 +889,7 @@ umass_attach(device_t dev) struct usb_attach_arg *uaa = device_get_ivars(dev); struct umass_probe_proto temp = umass_probe_proto(dev, uaa); struct usb_interface_descriptor *id; - int32_t err; + int err; /* * NOTE: the softc struct is cleared in device_set_driver. @@ -1004,6 +1002,24 @@ umass_attach(device_t dev) "transfers, %s\n", usbd_errstr(err)); goto detach; } +#ifdef USB_DEBUG + if (umass_throttle > 0) { + uint8_t x; + int iv; + + iv = umass_throttle; + + if (iv < 1) + iv = 1; + else if (iv > 8000) + iv = 8000; + + for (x = 0; x != UMASS_T_MAX; x++) { + if (sc->sc_xfer[x] != NULL) + usbd_xfer_set_interval(sc->sc_xfer[x], iv); + } + } +#endif sc->sc_transform = (sc->sc_proto & UMASS_PROTO_SCSI) ? &umass_scsi_transform : (sc->sc_proto & UMASS_PROTO_UFI) ? &umass_ufi_transform : @@ -1058,14 +1074,16 @@ umass_detach(device_t dev) usbd_transfer_unsetup(sc->sc_xfer, UMASS_T_MAX); -#if (__FreeBSD_version >= 700037) mtx_lock(&sc->sc_mtx); -#endif + + /* cancel any leftover CCB's */ + + umass_cancel_ccb(sc); + umass_cam_detach_sim(sc); -#if (__FreeBSD_version >= 700037) mtx_unlock(&sc->sc_mtx); -#endif + mtx_destroy(&sc->sc_mtx); return (0); /* success */ @@ -1206,7 +1224,6 @@ umass_t_bbb_reset1_callback(struct usb_xfer *xfer, usb_error_t error) default: /* Error */ umass_tr_error(xfer, error); return; - } } @@ -1245,7 +1262,6 @@ tr_transferred: default: /* Error */ umass_tr_error(xfer, error); return; - } } @@ -1331,7 +1347,6 @@ umass_t_bbb_command_callback(struct usb_xfer *xfer, usb_error_t error) default: /* Error */ umass_tr_error(xfer, error); return; - } } @@ -1340,19 +1355,12 @@ umass_t_bbb_data_read_callback(struct usb_xfer *xfer, usb_error_t error) { struct umass_softc *sc = usbd_xfer_softc(xfer); uint32_t max_bulk = usbd_xfer_max_len(xfer); -#ifndef UMASS_EXT_BUFFER - struct usb_page_cache *pc; -#endif int actlen, sumlen; usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL); switch (USB_GET_STATE(xfer)) { case USB_ST_TRANSFERRED: -#ifndef UMASS_EXT_BUFFER - pc = usbd_xfer_get_frame(xfer, 0); - usbd_copy_out(pc, 0, sc->sc_transfer.data_ptr, actlen); -#endif sc->sc_transfer.data_rem -= actlen; sc->sc_transfer.data_ptr += actlen; sc->sc_transfer.actlen += actlen; @@ -1374,12 +1382,9 @@ umass_t_bbb_data_read_callback(struct usb_xfer *xfer, usb_error_t error) } usbd_xfer_set_timeout(xfer, sc->sc_transfer.data_timeout); -#ifdef UMASS_EXT_BUFFER usbd_xfer_set_frame_data(xfer, 0, sc->sc_transfer.data_ptr, max_bulk); -#else - usbd_xfer_set_frame_len(xfer, 0, max_bulk); -#endif + usbd_transfer_submit(xfer); return; @@ -1390,7 +1395,6 @@ umass_t_bbb_data_read_callback(struct usb_xfer *xfer, usb_error_t error) umass_transfer_start(sc, UMASS_T_BBB_DATA_RD_CS); } return; - } } @@ -1406,9 +1410,6 @@ umass_t_bbb_data_write_callback(struct usb_xfer *xfer, usb_error_t error) { struct umass_softc *sc = usbd_xfer_softc(xfer); uint32_t max_bulk = usbd_xfer_max_len(xfer); -#ifndef UMASS_EXT_BUFFER - struct usb_page_cache *pc; -#endif int actlen, sumlen; usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL); @@ -1436,14 +1437,8 @@ umass_t_bbb_data_write_callback(struct usb_xfer *xfer, usb_error_t error) } usbd_xfer_set_timeout(xfer, sc->sc_transfer.data_timeout); -#ifdef UMASS_EXT_BUFFER usbd_xfer_set_frame_data(xfer, 0, sc->sc_transfer.data_ptr, max_bulk); -#else - pc = usbd_xfer_get_frame(xfer, 0); - usbd_copy_in(pc, 0, sc->sc_transfer.data_ptr, max_bulk); - usbd_xfer_set_frame_len(xfer, 0, max_bulk); -#endif usbd_transfer_submit(xfer); return; @@ -1455,7 +1450,6 @@ umass_t_bbb_data_write_callback(struct usb_xfer *xfer, usb_error_t error) umass_transfer_start(sc, UMASS_T_BBB_DATA_WR_CS); } return; - } } @@ -1581,7 +1575,6 @@ tr_error: umass_transfer_start(sc, UMASS_T_BBB_DATA_RD_CS); } return; - } } @@ -1612,8 +1605,7 @@ umass_command_start(struct umass_softc *sc, uint8_t dir, if (sc->sc_xfer[sc->sc_last_xfer_index]) { usbd_transfer_start(sc->sc_xfer[sc->sc_last_xfer_index]); } else { - ccb->ccb_h.status = CAM_TID_INVALID; - xpt_done(ccb); + umass_cancel_ccb(sc); } } @@ -1733,7 +1725,6 @@ umass_t_cbi_reset1_callback(struct usb_xfer *xfer, usb_error_t error) else umass_transfer_start(sc, UMASS_T_CBI_RESET2); break; - } } @@ -1788,7 +1779,6 @@ tr_transferred: default: /* Error */ umass_tr_error(xfer, error); break; - } } @@ -1878,19 +1868,12 @@ umass_t_cbi_data_read_callback(struct usb_xfer *xfer, usb_error_t error) { struct umass_softc *sc = usbd_xfer_softc(xfer); uint32_t max_bulk = usbd_xfer_max_len(xfer); -#ifndef UMASS_EXT_BUFFER - struct usb_page_cache *pc; -#endif int actlen, sumlen; usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL); switch (USB_GET_STATE(xfer)) { case USB_ST_TRANSFERRED: -#ifndef UMASS_EXT_BUFFER - pc = usbd_xfer_get_frame(xfer, 0); - usbd_copy_out(pc, 0, sc->sc_transfer.data_ptr, actlen); -#endif sc->sc_transfer.data_rem -= actlen; sc->sc_transfer.data_ptr += actlen; sc->sc_transfer.actlen += actlen; @@ -1912,12 +1895,9 @@ umass_t_cbi_data_read_callback(struct usb_xfer *xfer, usb_error_t error) } usbd_xfer_set_timeout(xfer, sc->sc_transfer.data_timeout); -#ifdef UMASS_EXT_BUFFER usbd_xfer_set_frame_data(xfer, 0, sc->sc_transfer.data_ptr, max_bulk); -#else - usbd_xfer_set_frame_len(xfer, 0, max_bulk); -#endif + usbd_transfer_submit(xfer); break; @@ -1929,7 +1909,6 @@ umass_t_cbi_data_read_callback(struct usb_xfer *xfer, usb_error_t error) umass_transfer_start(sc, UMASS_T_CBI_DATA_RD_CS); } break; - } } @@ -1945,9 +1924,6 @@ umass_t_cbi_data_write_callback(struct usb_xfer *xfer, usb_error_t error) { struct umass_softc *sc = usbd_xfer_softc(xfer); uint32_t max_bulk = usbd_xfer_max_len(xfer); -#ifndef UMASS_EXT_BUFFER - struct usb_page_cache *pc; -#endif int actlen, sumlen; usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL); @@ -1975,14 +1951,8 @@ umass_t_cbi_data_write_callback(struct usb_xfer *xfer, usb_error_t error) } usbd_xfer_set_timeout(xfer, sc->sc_transfer.data_timeout); -#ifdef UMASS_EXT_BUFFER usbd_xfer_set_frame_data(xfer, 0, sc->sc_transfer.data_ptr, max_bulk); -#else - pc = usbd_xfer_get_frame(xfer, 0); - usbd_copy_in(pc, 0, sc->sc_transfer.data_ptr, max_bulk); - usbd_xfer_set_frame_len(xfer, 0, max_bulk); -#endif usbd_transfer_submit(xfer); break; @@ -1995,7 +1965,6 @@ umass_t_cbi_data_write_callback(struct usb_xfer *xfer, usb_error_t error) umass_transfer_start(sc, UMASS_T_CBI_DATA_WR_CS); } break; - } } @@ -2097,7 +2066,6 @@ tr_setup: usbd_errstr(error)); umass_tr_error(xfer, error); break; - } } @@ -2126,9 +2094,7 @@ umass_cam_attach_sim(struct umass_softc *sc) DEVNAME_SIM, sc /* priv */ , sc->sc_unit /* unit number */ , -#if (__FreeBSD_version >= 700037) &sc->sc_mtx /* mutex */ , -#endif 1 /* maximum device openings */ , 0 /* maximum tagged device openings */ , devq); @@ -2138,27 +2104,15 @@ umass_cam_attach_sim(struct umass_softc *sc) return (ENOMEM); } -#if (__FreeBSD_version >= 700037) mtx_lock(&sc->sc_mtx); -#endif -#if (__FreeBSD_version >= 700048) - if (xpt_bus_register(sc->sc_sim, sc->sc_dev, sc->sc_unit) != CAM_SUCCESS) { + if (xpt_bus_register(sc->sc_sim, sc->sc_dev, + sc->sc_unit) != CAM_SUCCESS) { mtx_unlock(&sc->sc_mtx); return (ENOMEM); } -#else - if (xpt_bus_register(sc->sc_sim, sc->sc_unit) != CAM_SUCCESS) { -#if (__FreeBSD_version >= 700037) - mtx_unlock(&sc->sc_mtx); -#endif - return (ENOMEM); - } -#endif - -#if (__FreeBSD_version >= 700037) mtx_unlock(&sc->sc_mtx); -#endif + return (0); } @@ -2186,7 +2140,7 @@ umass_cam_detach_sim(struct umass_softc *sc) if (sc->sc_sim != NULL) { if (xpt_bus_deregister(cam_sim_path(sc->sc_sim))) { /* accessing the softc is not possible after this */ - sc->sc_sim->softc = UMASS_GONE; + sc->sc_sim->softc = NULL; cam_sim_free(sc->sc_sim, /* free_devq */ TRUE); } else { panic("%s: CAM layer is busy\n", @@ -2205,68 +2159,11 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb) { struct umass_softc *sc = (struct umass_softc *)sim->softc; - if (sc == UMASS_GONE || - (sc != NULL && !usbd_device_attached(sc->sc_udev))) { + if (sc == NULL) { ccb->ccb_h.status = CAM_SEL_TIMEOUT; xpt_done(ccb); return; } - if (sc) { -#if (__FreeBSD_version < 700037) - mtx_lock(&sc->sc_mtx); -#endif - } - /* - * Verify, depending on the operation to perform, that we either got - * a valid sc, because an existing target was referenced, or - * otherwise the SIM is addressed. - * - * This avoids bombing out at a printf and does give the CAM layer some - * sensible feedback on errors. - */ - switch (ccb->ccb_h.func_code) { - case XPT_SCSI_IO: - case XPT_RESET_DEV: - case XPT_GET_TRAN_SETTINGS: - case XPT_SET_TRAN_SETTINGS: - case XPT_CALC_GEOMETRY: - /* the opcodes requiring a target. These should never occur. */ - if (sc == NULL) { - DPRINTF(sc, UDMASS_GEN, "%s:%d:%d:%d:func_code 0x%04x: " - "Invalid target (target needed)\n", - DEVNAME_SIM, cam_sim_path(sc->sc_sim), - ccb->ccb_h.target_id, ccb->ccb_h.target_lun, - ccb->ccb_h.func_code); - - ccb->ccb_h.status = CAM_TID_INVALID; - xpt_done(ccb); - goto done; - } - break; - case XPT_PATH_INQ: - case XPT_NOOP: - /* - * The opcodes sometimes aimed at a target (sc is valid), - * sometimes aimed at the SIM (sc is invalid and target is - * CAM_TARGET_WILDCARD) - */ - if ((sc == NULL) && - (ccb->ccb_h.target_id != CAM_TARGET_WILDCARD)) { - DPRINTF(sc, UDMASS_SCSI, "%s:%d:%d:%d:func_code 0x%04x: " - "Invalid target (no wildcard)\n", - DEVNAME_SIM, cam_sim_path(sc->sc_sim), - ccb->ccb_h.target_id, ccb->ccb_h.target_lun, - ccb->ccb_h.func_code); - - ccb->ccb_h.status = CAM_TID_INVALID; - xpt_done(ccb); - goto done; - } - break; - default: - /* XXX Hm, we should check the input parameters */ - break; - } /* Perform the requested action */ switch (ccb->ccb_h.func_code) { @@ -2353,17 +2250,20 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb) */ if ((sc->sc_quirks & (NO_INQUIRY_EVPD | NO_INQUIRY)) && (sc->sc_transfer.cmd_data[1] & SI_EVPD)) { - struct scsi_sense_data *sense; - - sense = &ccb->csio.sense_data; - bzero(sense, sizeof(*sense)); - sense->error_code = SSD_CURRENT_ERROR; - sense->flags = SSD_KEY_ILLEGAL_REQUEST; - sense->add_sense_code = 0x24; - sense->extra_len = 10; + + scsi_set_sense_data(&ccb->csio.sense_data, + /*sense_format*/ SSD_TYPE_NONE, + /*current_error*/ 1, + /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST, + /*asc*/ 0x24, + /*ascq*/ 0x00, + /*extra args*/ SSD_ELEM_NONE); ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; - ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR | - CAM_AUTOSNS_VALID; + ccb->ccb_h.status = + CAM_SCSI_STATUS_ERROR | + CAM_AUTOSNS_VALID | + CAM_DEV_QFRZN; + xpt_freeze_devq(ccb->ccb_h.path, 1); xpt_done(ccb); goto done; } @@ -2382,6 +2282,13 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb) if (sc->sc_quirks & FORCE_SHORT_INQUIRY) { ccb->csio.dxfer_len = SHORT_INQUIRY_LENGTH; } + } else if (sc->sc_transfer.cmd_data[0] == PREVENT_ALLOW) { + if (sc->sc_quirks & NO_PREVENT_ALLOW) { + ccb->csio.scsi_status = SCSI_STATUS_OK; + ccb->ccb_h.status = CAM_REQ_CMP; + xpt_done(ccb); + goto done; + } } else if (sc->sc_transfer.cmd_data[0] == SYNCHRONIZE_CACHE) { if (sc->sc_quirks & NO_SYNCHRONIZE_CACHE) { ccb->csio.scsi_status = SCSI_STATUS_OK; @@ -2418,12 +2325,11 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb) strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); cpi->unit_number = cam_sim_unit(sim); cpi->bus_id = sc->sc_unit; -#if (__FreeBSD_version >= 700025) cpi->protocol = PROTO_SCSI; cpi->protocol_version = SCSI_REV_2; cpi->transport = XPORT_USB; cpi->transport_version = 0; -#endif + if (sc == NULL) { cpi->base_transfer_speed = 0; cpi->max_lun = 0; @@ -2475,16 +2381,12 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb) cam_sim_path(sc->sc_sim), ccb->ccb_h.target_id, ccb->ccb_h.target_lun); -#if (__FreeBSD_version >= 700025) cts->protocol = PROTO_SCSI; cts->protocol_version = SCSI_REV_2; cts->transport = XPORT_USB; cts->transport_version = 0; cts->xport_specific.valid = 0; -#else - cts->valid = 0; - cts->flags = 0; /* no disconnection, tagging */ -#endif + ccb->ccb_h.status = CAM_REQ_CMP; xpt_done(ccb); break; @@ -2529,11 +2431,6 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb) } done: -#if (__FreeBSD_version < 700037) - if (sc) { - mtx_unlock(&sc->sc_mtx); - } -#endif return; } @@ -2542,7 +2439,7 @@ umass_cam_poll(struct cam_sim *sim) { struct umass_softc *sc = (struct umass_softc *)sim->softc; - if (sc == UMASS_GONE) + if (sc == NULL) return; DPRINTF(sc, UDMASS_SCSI, "CAM poll\n"); @@ -2628,7 +2525,8 @@ umass_cam_cb(struct umass_softc *sc, union ccb *ccb, uint32_t residue, * recovered. We return an error to CAM and let CAM * retry the command if necessary. */ - ccb->ccb_h.status = CAM_REQ_CMP_ERR; + xpt_freeze_devq(ccb->ccb_h.path, 1); + ccb->ccb_h.status = CAM_REQ_CMP_ERR | CAM_DEV_QFRZN; xpt_done(ccb); break; } @@ -2642,12 +2540,17 @@ umass_cam_sense_cb(struct umass_softc *sc, union ccb *ccb, uint32_t residue, uint8_t status) { uint8_t *cmd; - uint8_t key; switch (status) { case STATUS_CMD_OK: case STATUS_CMD_UNKNOWN: - case STATUS_CMD_FAILED: + case STATUS_CMD_FAILED: { + int key, sense_len; + + ccb->csio.sense_resid = residue; + sense_len = ccb->csio.sense_len - ccb->csio.sense_resid; + key = scsi_get_sense_key(&ccb->csio.sense_data, sense_len, + /*show_errors*/ 1); if (ccb->csio.ccb_h.flags & CAM_CDB_POINTER) { cmd = (uint8_t *)(ccb->csio.cdb_io.cdb_ptr); @@ -2655,8 +2558,6 @@ umass_cam_sense_cb(struct umass_softc *sc, union ccb *ccb, uint32_t residue, cmd = (uint8_t *)(ccb->csio.cdb_io.cdb_bytes); } - key = (ccb->csio.sense_data.flags & SSD_KEY); - /* * Getting sense data always succeeds (apart from wire * failures): @@ -2688,8 +2589,9 @@ umass_cam_sense_cb(struct umass_softc *sc, union ccb *ccb, uint32_t residue, * usual. */ + xpt_freeze_devq(ccb->ccb_h.path, 1); ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR - | CAM_AUTOSNS_VALID; + | CAM_AUTOSNS_VALID | CAM_DEV_QFRZN; ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; #if 0 @@ -2700,34 +2602,40 @@ umass_cam_sense_cb(struct umass_softc *sc, union ccb *ccb, uint32_t residue, /* the rest of the command was filled in at attach */ - if (umass_std_transform(sc, ccb, + if ((sc->sc_transform)(sc, &sc->cam_scsi_test_unit_ready.opcode, - sizeof(sc->cam_scsi_test_unit_ready))) { + sizeof(sc->cam_scsi_test_unit_ready)) == 1) { umass_command_start(sc, DIR_NONE, NULL, 0, ccb->ccb_h.timeout, &umass_cam_quirk_cb, ccb); + break; } - break; } else { - ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR - | CAM_AUTOSNS_VALID; - ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; + xpt_freeze_devq(ccb->ccb_h.path, 1); + if (key >= 0) { + ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR + | CAM_AUTOSNS_VALID | CAM_DEV_QFRZN; + ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; + } else + ccb->ccb_h.status = CAM_AUTOSENSE_FAIL + | CAM_DEV_QFRZN; } xpt_done(ccb); break; - + } default: DPRINTF(sc, UDMASS_SCSI, "Autosense failed, " "status %d\n", status); - ccb->ccb_h.status = CAM_AUTOSENSE_FAIL; + xpt_freeze_devq(ccb->ccb_h.path, 1); + ccb->ccb_h.status = CAM_AUTOSENSE_FAIL | CAM_DEV_QFRZN; xpt_done(ccb); } } /* * This completion code just handles the fact that we sent a test-unit-ready - * after having previously failed a READ CAPACITY with CHECK_COND. Even - * though this command succeeded, we have to tell CAM to retry. + * after having previously failed a READ CAPACITY with CHECK_COND. The CCB + * status for CAM is already set earlier. */ static void umass_cam_quirk_cb(struct umass_softc *sc, union ccb *ccb, uint32_t residue, @@ -2736,9 +2644,6 @@ umass_cam_quirk_cb(struct umass_softc *sc, union ccb *ccb, uint32_t residue, DPRINTF(sc, UDMASS_SCSI, "Test unit ready " "returned status %d\n", status); - ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR - | CAM_AUTOSNS_VALID; - ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; xpt_done(ccb); } @@ -3027,7 +2932,8 @@ umass_std_transform(struct umass_softc *sc, union ccb *ccb, xpt_done(ccb); return (0); } else if (retval == 0) { - ccb->ccb_h.status = CAM_REQ_INVALID; + xpt_freeze_devq(ccb->ccb_h.path, 1); + ccb->ccb_h.status = CAM_REQ_INVALID | CAM_DEV_QFRZN; xpt_done(ccb); return (0); } diff --git a/freebsd/sys/dev/usb/usb.h b/freebsd/sys/dev/usb/usb.h index 2f216d27..9492d491 100644 --- a/freebsd/sys/dev/usb/usb.h +++ b/freebsd/sys/dev/usb/usb.h @@ -223,7 +223,8 @@ typedef struct usb_device_request usb_device_request_t; #define UR_RESET_TT 0x09 #define UR_GET_TT_STATE 0x0a #define UR_STOP_TT 0x0b -#define UR_SET_HUB_DEPTH 0x0c +#define UR_SET_AND_TEST 0x0c /* USB 2.0 only */ +#define UR_SET_HUB_DEPTH 0x0c /* USB 3.0 only */ #define USB_SS_HUB_DEPTH_MAX 5 #define UR_GET_PORT_ERR_COUNT 0x0d @@ -246,6 +247,7 @@ typedef struct usb_device_request usb_device_request_t; #define UHF_PORT_LINK_STATE 5 #define UHF_PORT_POWER 8 #define UHF_PORT_LOW_SPEED 9 +#define UHF_PORT_L1 10 #define UHF_C_PORT_CONNECTION 16 #define UHF_C_PORT_ENABLE 17 #define UHF_C_PORT_SUSPEND 18 @@ -253,6 +255,7 @@ typedef struct usb_device_request usb_device_request_t; #define UHF_C_PORT_RESET 20 #define UHF_PORT_TEST 21 #define UHF_PORT_INDICATOR 22 +#define UHF_C_PORT_L1 23 /* SuperSpeed HUB specific features */ #define UHF_PORT_U1_TIMEOUT 23 @@ -322,7 +325,12 @@ struct usb_devcap_usb2ext_descriptor { uByte bDescriptorType; uByte bDevCapabilityType; uDWord bmAttributes; -#define USB_V2EXT_LPM 0x02 +#define USB_V2EXT_LPM (1U << 1) +#define USB_V2EXT_BESL_SUPPORTED (1U << 2) +#define USB_V2EXT_BESL_BASELINE_VALID (1U << 3) +#define USB_V2EXT_BESL_DEEP_VALID (1U << 4) +#define USB_V2EXT_BESL_BASELINE_GET(x) (((x) >> 8) & 0xF) +#define USB_V2EXT_BESL_DEEP_GET(x) (((x) >> 12) & 0xF) } __packed; typedef struct usb_devcap_usb2ext_descriptor usb_devcap_usb2ext_descriptor_t; @@ -669,6 +677,7 @@ struct usb_port_status { #define UPS_SUSPEND 0x0004 #define UPS_OVERCURRENT_INDICATOR 0x0008 #define UPS_RESET 0x0010 +#define UPS_PORT_L1 0x0020 /* USB 2.0 only */ /* The link-state bits are valid for Super-Speed USB HUBs */ #define UPS_PORT_LINK_STATE_GET(x) (((x) >> 5) & 0xF) #define UPS_PORT_LINK_STATE_SET(x) (((x) & 0xF) << 5) @@ -699,7 +708,8 @@ struct usb_port_status { #define UPS_C_SUSPEND 0x0004 #define UPS_C_OVERCURRENT_INDICATOR 0x0008 #define UPS_C_PORT_RESET 0x0010 -#define UPS_C_BH_PORT_RESET 0x0020 +#define UPS_C_PORT_L1 0x0020 /* USB 2.0 only */ +#define UPS_C_BH_PORT_RESET 0x0020 /* USB 3.0 only */ #define UPS_C_PORT_LINK_STATE 0x0040 #define UPS_C_PORT_CONFIG_ERROR 0x0080 } __packed; diff --git a/freebsd/sys/dev/usb/usb_dev.c b/freebsd/sys/dev/usb/usb_dev.c index 7ca10d7b..7697b64c 100644 --- a/freebsd/sys/dev/usb/usb_dev.c +++ b/freebsd/sys/dev/usb/usb_dev.c @@ -83,7 +83,7 @@ #ifdef USB_DEBUG static int usb_fifo_debug = 0; -SYSCTL_NODE(_hw_usb, OID_AUTO, dev, CTLFLAG_RW, 0, "USB device"); +static SYSCTL_NODE(_hw_usb, OID_AUTO, dev, CTLFLAG_RW, 0, "USB device"); SYSCTL_INT(_hw_usb_dev, OID_AUTO, debug, CTLFLAG_RW | CTLFLAG_TUN, &usb_fifo_debug, 0, "Debug Level"); TUNABLE_INT("hw.usb.dev.debug", &usb_fifo_debug); @@ -770,7 +770,7 @@ usb_fifo_close(struct usb_fifo *f, int fflags) /* check if a thread wants SIGIO */ if (f->async_p != NULL) { PROC_LOCK(f->async_p); - psignal(f->async_p, SIGIO); + kern_psignal(f->async_p, SIGIO); PROC_UNLOCK(f->async_p); f->async_p = NULL; } @@ -844,7 +844,7 @@ usb_open(struct cdev *dev, int fflags, int devtype, struct thread *td) struct usb_cdev_privdata *cpd; int err, ep; - DPRINTFN(2, "%s fflags=0x%08x\n", dev->si_name, fflags); + DPRINTFN(2, "%s fflags=0x%08x\n", devtoname(dev), fflags); KASSERT(fflags & (FREAD|FWRITE), ("invalid open flags")); if (((fflags & FREAD) && !(pd->mode & FREAD)) || @@ -1584,7 +1584,7 @@ usb_fifo_wakeup(struct usb_fifo *f) } if (f->async_p != NULL) { PROC_LOCK(f->async_p); - psignal(f->async_p, SIGIO); + kern_psignal(f->async_p, SIGIO); PROC_UNLOCK(f->async_p); } } diff --git a/freebsd/sys/dev/usb/usb_device.c b/freebsd/sys/dev/usb/usb_device.c index 3a58158d..78ae3d8c 100644 --- a/freebsd/sys/dev/usb/usb_device.c +++ b/freebsd/sys/dev/usb/usb_device.c @@ -2431,77 +2431,6 @@ usbd_get_device_index(struct usb_device *udev) } #if USB_HAVE_DEVCTL -/*------------------------------------------------------------------------* - * usb_notify_addq - * - * This function will generate events for dev. - *------------------------------------------------------------------------*/ -#ifndef BURN_BRIDGES -static void -usb_notify_addq_compat(const char *type, struct usb_device *udev) -{ - char *data = NULL; - const char *ntype; - struct malloc_type *mt; - const size_t buf_size = 512; - - /* Convert notify type */ - if (strcmp(type, "ATTACH") == 0) - ntype = "+"; - else if (strcmp(type, "DETACH") == 0) - ntype = "-"; - else - return; - - mtx_lock(&malloc_mtx); - mt = malloc_desc2type("bus"); /* XXX M_BUS */ - mtx_unlock(&malloc_mtx); - if (mt == NULL) - return; - - data = malloc(buf_size, mt, M_NOWAIT); - if (data == NULL) - return; - - /* String it all together. */ - snprintf(data, buf_size, - "%s" -#if USB_HAVE_UGEN - "%s " -#endif - "at port=%u " - "vendor=0x%04x " - "product=0x%04x " - "devclass=0x%02x " - "devsubclass=0x%02x " - "sernum=\"%s\" " - "release=0x%04x " -#if USB_HAVE_UGEN - "on %s\n" -#endif - "", - ntype, -#if USB_HAVE_UGEN - udev->ugen_name, -#endif - udev->port_no, - UGETW(udev->ddesc.idVendor), - UGETW(udev->ddesc.idProduct), - udev->ddesc.bDeviceClass, - udev->ddesc.bDeviceSubClass, - usb_get_serial(udev), - UGETW(udev->ddesc.bcdDevice) -#if USB_HAVE_UGEN - , udev->parent_hub != NULL ? - udev->parent_hub->ugen_name : - device_get_nameunit(device_get_parent(udev->bus->bdev)) -#endif - ); - - devctl_queue_data(data); -} -#endif - static void usb_notify_addq(const char *type, struct usb_device *udev) { @@ -2509,10 +2438,6 @@ usb_notify_addq(const char *type, struct usb_device *udev) struct sbuf *sb; int i; -#ifndef BURN_BRIDGES - usb_notify_addq_compat(type, udev); -#endif - /* announce the device */ sb = sbuf_new_auto(); sbuf_printf(sb, diff --git a/freebsd/sys/dev/usb/usb_device.h b/freebsd/sys/dev/usb/usb_device.h index 03ddf1e6..8e13e3de 100644 --- a/freebsd/sys/dev/usb/usb_device.h +++ b/freebsd/sys/dev/usb/usb_device.h @@ -215,6 +215,7 @@ struct usb_device { uint16_t power; /* mA the device uses */ uint16_t langid; /* language for strings */ + uint16_t autoQuirk[USB_MAX_AUTO_QUIRK]; /* dynamic quirks */ uint8_t address; /* device addess */ uint8_t device_index; /* device index in "bus->devices" */ @@ -257,8 +258,6 @@ struct usb_device { uint32_t clear_stall_errors; /* number of clear-stall failures */ - uint16_t autoQuirk[USB_MAX_AUTO_QUIRK]; /* dynamic quirks */ - union usb_device_scratch scratch; }; diff --git a/freebsd/sys/dev/usb/usb_freebsd.h b/freebsd/sys/dev/usb/usb_freebsd.h index 8f9bb4c6..06369a25 100644 --- a/freebsd/sys/dev/usb/usb_freebsd.h +++ b/freebsd/sys/dev/usb/usb_freebsd.h @@ -48,7 +48,15 @@ #define USB_TD_GET_PROC(td) (td)->td_proc #define USB_PROC_GET_GID(td) (td)->p_pgid +#if (!defined(USB_HOST_ALIGN)) || (USB_HOST_ALIGN <= 0) +/* Use default value. */ +#undef USB_HOST_ALIGN #define USB_HOST_ALIGN 8 /* bytes, must be power of two */ +#endif +/* Sanity check for USB_HOST_ALIGN: Verify power of two. */ +#if ((-USB_HOST_ALIGN) & USB_HOST_ALIGN) != USB_HOST_ALIGN +#error "USB_HOST_ALIGN is not power of two." +#endif #define USB_FS_ISOC_UFRAME_MAX 4 /* exclusive unit */ #define USB_BUS_MAX 256 /* units */ #define USB_MAX_DEVICES 128 /* units */ diff --git a/freebsd/sys/dev/usb/usb_generic.c b/freebsd/sys/dev/usb/usb_generic.c index 361ee2ef..a0b7f007 100644 --- a/freebsd/sys/dev/usb/usb_generic.c +++ b/freebsd/sys/dev/usb/usb_generic.c @@ -128,7 +128,7 @@ struct usb_fifo_methods usb_ugen_methods = { #ifdef USB_DEBUG static int ugen_debug = 0; -SYSCTL_NODE(_hw_usb, OID_AUTO, ugen, CTLFLAG_RW, 0, "USB generic"); +static SYSCTL_NODE(_hw_usb, OID_AUTO, ugen, CTLFLAG_RW, 0, "USB generic"); SYSCTL_INT(_hw_usb_ugen, OID_AUTO, debug, CTLFLAG_RW | CTLFLAG_TUN, &ugen_debug, 0, "Debug level"); TUNABLE_INT("hw.usb.ugen.debug", &ugen_debug); @@ -1833,6 +1833,17 @@ ugen_get_power_mode(struct usb_fifo *f) } static int +ugen_get_power_usage(struct usb_fifo *f) +{ + struct usb_device *udev = f->udev; + + if (udev == NULL) + return (0); + + return (udev->power); +} + +static int ugen_do_port_feature(struct usb_fifo *f, uint8_t port_no, uint8_t set, uint16_t feature) { @@ -2194,6 +2205,10 @@ ugen_ioctl_post(struct usb_fifo *f, u_long cmd, void *addr, int fflags) *u.pint = ugen_get_power_mode(f); break; + case USB_GET_POWER_USAGE: + *u.pint = ugen_get_power_usage(f); + break; + case USB_SET_PORT_ENABLE: error = ugen_do_port_feature(f, *u.pint, 1, UHF_PORT_ENABLE); diff --git a/freebsd/sys/dev/usb/usb_hid.c b/freebsd/sys/dev/usb/usb_hid.c index 86fa27b0..737237bd 100644 --- a/freebsd/sys/dev/usb/usb_hid.c +++ b/freebsd/sys/dev/usb/usb_hid.c @@ -847,3 +847,79 @@ usbd_req_get_hid_desc(struct usb_device *udev, struct mtx *mtx, } return (USB_ERR_NORMAL_COMPLETION); } + +/*------------------------------------------------------------------------* + * hid_is_mouse + * + * This function will decide if a USB descriptor belongs to a USB mouse. + * + * Return values: + * Zero: Not a USB mouse. + * Else: Is a USB mouse. + *------------------------------------------------------------------------*/ +int +hid_is_mouse(const void *d_ptr, uint16_t d_len) +{ + struct hid_data *hd; + struct hid_item hi; + int mdepth; + int found; + + hd = hid_start_parse(d_ptr, d_len, 1 << hid_input); + if (hd == NULL) + return (0); + + mdepth = 0; + found = 0; + + while (hid_get_item(hd, &hi)) { + switch (hi.kind) { + case hid_collection: + if (mdepth != 0) + mdepth++; + else if (hi.collection == 1 && + hi.usage == + HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE)) + mdepth++; + break; + case hid_endcollection: + if (mdepth != 0) + mdepth--; + break; + case hid_input: + if (mdepth == 0) + break; + if (hi.usage == + HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X) && + (hi.flags & (HIO_CONST|HIO_RELATIVE)) == HIO_RELATIVE) + found++; + if (hi.usage == + HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y) && + (hi.flags & (HIO_CONST|HIO_RELATIVE)) == HIO_RELATIVE) + found++; + break; + default: + break; + } + } + hid_end_parse(hd); + return (found); +} + +/*------------------------------------------------------------------------* + * hid_is_keyboard + * + * This function will decide if a USB descriptor belongs to a USB keyboard. + * + * Return values: + * Zero: Not a USB keyboard. + * Else: Is a USB keyboard. + *------------------------------------------------------------------------*/ +int +hid_is_keyboard(const void *d_ptr, uint16_t d_len) +{ + if (hid_is_collection(d_ptr, d_len, + HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_KEYBOARD))) + return (1); + return (0); +} diff --git a/freebsd/sys/dev/usb/usb_hub.c b/freebsd/sys/dev/usb/usb_hub.c index 97b3a4dd..2dee6784 100644 --- a/freebsd/sys/dev/usb/usb_hub.c +++ b/freebsd/sys/dev/usb/usb_hub.c @@ -78,7 +78,7 @@ #ifdef USB_DEBUG static int uhub_debug = 0; -SYSCTL_NODE(_hw_usb, OID_AUTO, uhub, CTLFLAG_RW, 0, "USB HUB"); +static SYSCTL_NODE(_hw_usb, OID_AUTO, uhub, CTLFLAG_RW, 0, "USB HUB"); SYSCTL_INT(_hw_usb_uhub, OID_AUTO, debug, CTLFLAG_RW | CTLFLAG_TUN, &uhub_debug, 0, "Debug level"); TUNABLE_INT("hw.usb.uhub.debug", &uhub_debug); diff --git a/freebsd/sys/dev/usb/usb_ioctl.h b/freebsd/sys/dev/usb/usb_ioctl.h index 9af6ee5c..9e66bd5a 100644 --- a/freebsd/sys/dev/usb/usb_ioctl.h +++ b/freebsd/sys/dev/usb/usb_ioctl.h @@ -270,7 +270,8 @@ struct usb_gen_quirk { #define USB_IFACE_DRIVER_DETACH _IOW ('U', 125, int) #define USB_GET_PLUGTIME _IOR ('U', 126, uint32_t) #define USB_READ_DIR _IOW ('U', 127, struct usb_read_dir) -/* 128 - 135 unused */ +/* 128 - 134 unused */ +#define USB_GET_POWER_USAGE _IOR ('U', 135, int) #define USB_SET_TX_FORCE_SHORT _IOW ('U', 136, int) #define USB_SET_TX_TIMEOUT _IOW ('U', 137, int) #define USB_GET_TX_FRAME_SIZE _IOR ('U', 138, int) diff --git a/freebsd/sys/dev/usb/usb_msctest.c b/freebsd/sys/dev/usb/usb_msctest.c index 5e8eebb3..fcb9f026 100644 --- a/freebsd/sys/dev/usb/usb_msctest.c +++ b/freebsd/sys/dev/usb/usb_msctest.c @@ -64,7 +64,6 @@ #include <dev/usb/usb_transfer.h> #include <dev/usb/usb_msctest.h> #include <dev/usb/usb_debug.h> -#include <dev/usb/usb_busdma.h> #include <dev/usb/usb_device.h> #include <dev/usb/usb_request.h> #include <dev/usb/usb_util.h> @@ -106,6 +105,8 @@ static uint8_t scsi_sync_cache[] = { 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static uint8_t scsi_request_sense[] = { 0x03, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +static uint8_t scsi_read_capacity[] = { 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 }; #define BULK_SIZE 64 /* dummy */ #define ERR_CSW_FAILED -1 @@ -481,7 +482,7 @@ bbb_command_start(struct bbb_transfer *sc, uint8_t dir, uint8_t lun, sc->cmd_len = cmd_len; memset(&sc->cbw.CBWCDB, 0, sizeof(sc->cbw.CBWCDB)); memcpy(&sc->cbw.CBWCDB, cmd_ptr, cmd_len); - DPRINTFN(1, "SCSI cmd = %*D\n", (int)cmd_len, &sc->cbw.CBWCDB, ":"); + DPRINTFN(1, "SCSI cmd = %*D\n", (int)cmd_len, (char *)sc->cbw.CBWCDB, ":"); mtx_lock(&sc->mtx); usbd_transfer_start(sc->xfer[sc->state]); @@ -650,7 +651,7 @@ usb_msc_auto_quirk(struct usb_device *udev, uint8_t iface_index) } is_no_direct = 1; - for (timeout = 4; timeout; timeout--) { + for (timeout = 4; timeout != 0; timeout--) { err = bbb_command_start(sc, DIR_IN, 0, sc->buffer, SCSI_INQ_LEN, &scsi_inquiry, sizeof(scsi_inquiry), USB_MS_HZ); @@ -660,8 +661,11 @@ usb_msc_auto_quirk(struct usb_device *udev, uint8_t iface_index) if (sid_type == 0x00) is_no_direct = 0; break; - } else if (err != ERR_CSW_FAILED) - break; /* non retryable error */ + } else if (err != ERR_CSW_FAILED) { + DPRINTF("Device is not responding " + "properly to SCSI INQUIRY command.\n"); + goto error; /* non retryable error */ + } usb_pause_mtx(NULL, hz); } @@ -679,7 +683,9 @@ usb_msc_auto_quirk(struct usb_device *udev, uint8_t iface_index) if (err != ERR_CSW_FAILED) goto error; } + timeout = 1; +retry_sync_cache: err = bbb_command_start(sc, DIR_IN, 0, NULL, 0, &scsi_sync_cache, sizeof(scsi_sync_cache), USB_MS_HZ); @@ -692,6 +698,42 @@ usb_msc_auto_quirk(struct usb_device *udev, uint8_t iface_index) DPRINTF("Device doesn't handle synchronize cache\n"); usbd_add_dynamic_quirk(udev, UQ_MSC_NO_SYNC_CACHE); + + } else { + + /* + * Certain Kingston memory sticks fail the first + * read capacity after a synchronize cache command + * has been issued. Disable the synchronize cache + * command for such devices. + */ + + err = bbb_command_start(sc, DIR_IN, 0, sc->buffer, 8, + &scsi_read_capacity, sizeof(scsi_read_capacity), + USB_MS_HZ); + + if (err != 0) { + if (err != ERR_CSW_FAILED) + goto error; + + err = bbb_command_start(sc, DIR_IN, 0, sc->buffer, 8, + &scsi_read_capacity, sizeof(scsi_read_capacity), + USB_MS_HZ); + + if (err == 0) { + if (timeout--) + goto retry_sync_cache; + + DPRINTF("Device most likely doesn't " + "handle synchronize cache\n"); + + usbd_add_dynamic_quirk(udev, + UQ_MSC_NO_SYNC_CACHE); + } else { + if (err != ERR_CSW_FAILED) + goto error; + } + } } /* clear sense status of any failed commands on the device */ diff --git a/freebsd/sys/dev/usb/usb_process.c b/freebsd/sys/dev/usb/usb_process.c index fb422df4..59b26567 100644 --- a/freebsd/sys/dev/usb/usb_process.c +++ b/freebsd/sys/dev/usb/usb_process.c @@ -69,17 +69,13 @@ static int usb_pcount; #define USB_THREAD_CREATE(f, s, p, ...) \ kproc_kthread_add((f), (s), &usbproc, (p), RFHIGHPID, \ 0, "usb", __VA_ARGS__) -#if (__FreeBSD_version >= 900000) #define USB_THREAD_SUSPEND_CHECK() kthread_suspend_check() -#else -#define USB_THREAD_SUSPEND_CHECK() kthread_suspend_check(curthread) -#endif #define USB_THREAD_SUSPEND(p) kthread_suspend(p,0) #define USB_THREAD_EXIT(err) kthread_exit() #else #define USB_THREAD_CREATE(f, s, p, ...) \ kthread_create((f), (s), (p), RFHIGHPID, 0, __VA_ARGS__) -#define USB_THREAD_SUSPEND_CHECK() kthread_suspend_check(curproc) +#define USB_THREAD_SUSPEND_CHECK() kthread_suspend_check() #define USB_THREAD_SUSPEND(p) kthread_suspend(p,0) #define USB_THREAD_EXIT(err) kthread_exit(err) #endif @@ -87,7 +83,7 @@ static int usb_pcount; #ifdef USB_DEBUG static int usb_proc_debug; -SYSCTL_NODE(_hw_usb, OID_AUTO, proc, CTLFLAG_RW, 0, "USB process"); +static SYSCTL_NODE(_hw_usb, OID_AUTO, proc, CTLFLAG_RW, 0, "USB process"); SYSCTL_INT(_hw_usb_proc, OID_AUTO, debug, CTLFLAG_RW | CTLFLAG_TUN, &usb_proc_debug, 0, "Debug level"); TUNABLE_INT("hw.usb.proc.debug", &usb_proc_debug); diff --git a/freebsd/sys/dev/usb/usb_process.h b/freebsd/sys/dev/usb/usb_process.h index 23cf6607..9b1a8534 100644 --- a/freebsd/sys/dev/usb/usb_process.h +++ b/freebsd/sys/dev/usb/usb_process.h @@ -42,6 +42,7 @@ /* structure prototypes */ struct usb_proc_msg; +struct usb_device; /* * The following structure defines the USB process. @@ -79,4 +80,9 @@ void usb_proc_free(struct usb_process *up); void *usb_proc_msignal(struct usb_process *up, void *pm0, void *pm1); void usb_proc_rewakeup(struct usb_process *up); +void usb_proc_explore_mwait(struct usb_device *, void *, void *); +void *usb_proc_explore_msignal(struct usb_device *, void *, void *); +void usb_proc_explore_lock(struct usb_device *); +void usb_proc_explore_unlock(struct usb_device *); + #endif /* _USB_PROCESS_H_ */ diff --git a/freebsd/sys/dev/usb/usb_request.c b/freebsd/sys/dev/usb/usb_request.c index 2897cadb..167a7228 100644 --- a/freebsd/sys/dev/usb/usb_request.c +++ b/freebsd/sys/dev/usb/usb_request.c @@ -2158,3 +2158,57 @@ usbd_req_set_port_link_state(struct usb_device *udev, struct mtx *mtx, USETW(req.wLength, 0); return (usbd_do_request(udev, mtx, &req, 0)); } + +/*------------------------------------------------------------------------* + * usbd_req_set_lpm_info + * + * USB 2.0 specific request for Link Power Management. + * + * Returns: + * 0: Success + * USB_ERR_PENDING_REQUESTS: NYET + * USB_ERR_TIMEOUT: TIMEOUT + * USB_ERR_STALL: STALL + * Else: Failure + *------------------------------------------------------------------------*/ +usb_error_t +usbd_req_set_lpm_info(struct usb_device *udev, struct mtx *mtx, + uint8_t port, uint8_t besl, uint8_t addr, uint8_t rwe) +{ + struct usb_device_request req; + usb_error_t err; + uint8_t buf[1]; + + req.bmRequestType = UT_WRITE_CLASS_OTHER; + req.bRequest = UR_SET_AND_TEST; + USETW(req.wValue, UHF_PORT_L1); + req.wIndex[0] = (port & 0xF) | ((besl & 0xF) << 4); + req.wIndex[1] = (addr & 0x7F) | (rwe ? 0x80 : 0x00); + USETW(req.wLength, sizeof(buf)); + + /* set default value in case of short transfer */ + buf[0] = 0x00; + + err = usbd_do_request(udev, mtx, &req, buf); + if (err) + return (err); + + switch (buf[0]) { + case 0x00: /* SUCCESS */ + break; + case 0x10: /* NYET */ + err = USB_ERR_PENDING_REQUESTS; + break; + case 0x11: /* TIMEOUT */ + err = USB_ERR_TIMEOUT; + break; + case 0x30: /* STALL */ + err = USB_ERR_STALLED; + break; + default: /* reserved */ + err = USB_ERR_IOERROR; + break; + } + return (err); +} + diff --git a/freebsd/sys/dev/usb/usb_request.h b/freebsd/sys/dev/usb/usb_request.h index 74823af2..5fcedd5e 100644 --- a/freebsd/sys/dev/usb/usb_request.h +++ b/freebsd/sys/dev/usb/usb_request.h @@ -91,5 +91,7 @@ usb_error_t usbd_req_clear_tt_buffer(struct usb_device *udev, struct mtx *mtx, uint8_t port, uint8_t addr, uint8_t type, uint8_t endpoint); usb_error_t usbd_req_set_port_link_state(struct usb_device *udev, struct mtx *mtx, uint8_t port, uint8_t link_state); +usb_error_t usbd_req_set_lpm_info(struct usb_device *udev, struct mtx *mtx, + uint8_t port, uint8_t besl, uint8_t addr, uint8_t rwe); #endif /* _USB_REQUEST_H_ */ diff --git a/freebsd/sys/dev/usb/usb_transfer.c b/freebsd/sys/dev/usb/usb_transfer.c index d3d41709..b2528186 100644 --- a/freebsd/sys/dev/usb/usb_transfer.c +++ b/freebsd/sys/dev/usb/usb_transfer.c @@ -2206,7 +2206,7 @@ usbd_callback_wrapper(struct usb_xfer_queue *pq) struct usb_xfer_root *info = xfer->xroot; USB_BUS_LOCK_ASSERT(info->bus, MA_OWNED); - if (!mtx_owned(info->xfer_mtx)) { + if (!mtx_owned(info->xfer_mtx) && !SCHEDULER_STOPPED()) { /* * Cases that end up here: * @@ -3179,14 +3179,14 @@ usbd_transfer_poll(struct usb_xfer **ppxfer, uint16_t max) /* make sure that the BUS mutex is not locked */ drop_bus = 0; - while (mtx_owned(&xroot->udev->bus->bus_mtx)) { + while (mtx_owned(&xroot->udev->bus->bus_mtx) && !SCHEDULER_STOPPED()) { mtx_unlock(&xroot->udev->bus->bus_mtx); drop_bus++; } /* make sure that the transfer mutex is not locked */ drop_xfer = 0; - while (mtx_owned(xroot->xfer_mtx)) { + while (mtx_owned(xroot->xfer_mtx) && !SCHEDULER_STOPPED()) { mtx_unlock(xroot->xfer_mtx); drop_xfer++; } diff --git a/freebsd/sys/dev/usb/usb_util.c b/freebsd/sys/dev/usb/usb_util.c index 5c56da87..24558b84 100644 --- a/freebsd/sys/dev/usb/usb_util.c +++ b/freebsd/sys/dev/usb/usb_util.c @@ -60,31 +60,6 @@ #include <dev/usb/usb_bus.h> /*------------------------------------------------------------------------* - * device_delete_all_children - delete all children of a device - *------------------------------------------------------------------------*/ -#ifndef device_delete_all_children -int -device_delete_all_children(device_t dev) -{ - device_t *devlist; - int devcount; - int error; - - error = device_get_children(dev, &devlist, &devcount); - if (error == 0) { - while (devcount-- > 0) { - error = device_delete_child(dev, devlist[devcount]); - if (error) { - break; - } - } - free(devlist, M_TEMP); - } - return (error); -} -#endif - -/*------------------------------------------------------------------------* * device_set_usb_desc * * This function can be called at probe or attach to set the USB @@ -150,33 +125,21 @@ device_set_usb_desc(device_t dev) * * This function will delay the code by the passed number of system * ticks. The passed mutex "mtx" will be dropped while waiting, if - * "mtx" is not NULL. + * "mtx" is different from NULL. *------------------------------------------------------------------------*/ void -usb_pause_mtx(struct mtx *mtx, int _ticks) +usb_pause_mtx(struct mtx *mtx, int timo) { if (mtx != NULL) mtx_unlock(mtx); - if (cold) { - /* convert to milliseconds */ - _ticks = (_ticks * 1000) / hz; - /* convert to microseconds, rounded up */ - _ticks = (_ticks + 1) * 1000; - DELAY(_ticks); - - } else { + /* + * Add one tick to the timeout so that we don't return too + * early! Note that pause() will assert that the passed + * timeout is positive and non-zero! + */ + pause("USBWAIT", timo + 1); - /* - * Add one to the number of ticks so that we don't return - * too early! - */ - _ticks++; - - if (pause("USBWAIT", _ticks)) { - /* ignore */ - } - } if (mtx != NULL) mtx_lock(mtx); } diff --git a/freebsd/sys/dev/usb/usb_util.h b/freebsd/sys/dev/usb/usb_util.h index 35abeddd..7e52404f 100644 --- a/freebsd/sys/dev/usb/usb_util.h +++ b/freebsd/sys/dev/usb/usb_util.h @@ -27,7 +27,6 @@ #ifndef _USB_UTIL_H_ #define _USB_UTIL_H_ -int device_delete_all_children(device_t dev); uint8_t usb_make_str_desc(void *ptr, uint16_t max_len, const char *s); void usb_printbcd(char *p, uint16_t p_len, uint16_t bcd); void usb_trim_spaces(char *p); diff --git a/freebsd/sys/dev/usb/usbhid.h b/freebsd/sys/dev/usb/usbhid.h index f40232aa..f6c447ca 100644 --- a/freebsd/sys/dev/usb/usbhid.h +++ b/freebsd/sys/dev/usb/usbhid.h @@ -242,5 +242,7 @@ struct usb_hid_descriptor *hid_get_descriptor_from_usb( usb_error_t usbd_req_get_hid_desc(struct usb_device *udev, struct mtx *mtx, void **descp, uint16_t *sizep, struct malloc_type *mem, uint8_t iface_index); +int hid_is_mouse(const void *d_ptr, uint16_t d_len); +int hid_is_keyboard(const void *d_ptr, uint16_t d_len); #endif /* _KERNEL */ #endif /* _USB_HID_H_ */ |