summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/dev
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2013-11-06 16:20:21 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2013-11-11 10:08:08 +0100
commit66659ff1ad6831b0ea7425fa6ecd8a8687523658 (patch)
tree48e22b475fa8854128e0861a33fed6f78c8094b5 /freebsd/sys/dev
parentDefine __GLOBL1() and __GLOBL() (diff)
downloadrtems-libbsd-66659ff1ad6831b0ea7425fa6ecd8a8687523658.tar.bz2
Update to FreeBSD 9.2
Diffstat (limited to 'freebsd/sys/dev')
-rw-r--r--freebsd/sys/dev/bce/if_bce.c406
-rw-r--r--freebsd/sys/dev/bce/if_bcefw.h131
-rw-r--r--freebsd/sys/dev/bce/if_bcereg.h23
-rw-r--r--freebsd/sys/dev/bfe/if_bfe.c6
-rw-r--r--freebsd/sys/dev/bge/if_bge.c241
-rw-r--r--freebsd/sys/dev/bge/if_bgereg.h3
-rw-r--r--freebsd/sys/dev/dc/dcphy.c39
-rw-r--r--freebsd/sys/dev/dc/if_dc.c10
-rw-r--r--freebsd/sys/dev/dc/if_dcreg.h2
-rw-r--r--freebsd/sys/dev/dc/pnphy.c36
-rw-r--r--freebsd/sys/dev/e1000/e1000_api.c3
-rw-r--r--freebsd/sys/dev/e1000/if_em.c179
-rw-r--r--freebsd/sys/dev/e1000/if_em.h1
-rw-r--r--freebsd/sys/dev/e1000/if_igb.c195
-rw-r--r--freebsd/sys/dev/e1000/if_igb.h2
-rw-r--r--freebsd/sys/dev/e1000/if_lem.c93
-rw-r--r--freebsd/sys/dev/e1000/if_lem.h1
-rw-r--r--freebsd/sys/dev/fxp/if_fxp.c23
-rw-r--r--freebsd/sys/dev/mii/brgphy.c186
-rw-r--r--freebsd/sys/dev/mii/icsphy.c67
-rw-r--r--freebsd/sys/dev/mii/mii.c60
-rw-r--r--freebsd/sys/dev/mii/mii.h4
-rw-r--r--freebsd/sys/dev/mii/mii_physubr.c144
-rw-r--r--freebsd/sys/dev/mii/miivar.h40
-rw-r--r--freebsd/sys/dev/pci/pci.c542
-rw-r--r--freebsd/sys/dev/pci/pci_pci.c367
-rw-r--r--freebsd/sys/dev/pci/pci_private.h6
-rw-r--r--freebsd/sys/dev/pci/pci_user.c246
-rw-r--r--freebsd/sys/dev/pci/pcib_private.h29
-rw-r--r--freebsd/sys/dev/pci/pcireg.h39
-rw-r--r--freebsd/sys/dev/pci/pcivar.h7
-rw-r--r--freebsd/sys/dev/re/if_re.c71
-rw-r--r--freebsd/sys/dev/smc/if_smc.c4
-rw-r--r--freebsd/sys/dev/usb/controller/ehci.c18
-rw-r--r--freebsd/sys/dev/usb/controller/ehci.h2
-rw-r--r--freebsd/sys/dev/usb/controller/ohci.c2
-rw-r--r--freebsd/sys/dev/usb/controller/usb_controller.c27
-rw-r--r--freebsd/sys/dev/usb/controller/xhcireg.h221
-rw-r--r--freebsd/sys/dev/usb/quirk/usb_quirk.c15
-rw-r--r--freebsd/sys/dev/usb/quirk/usb_quirk.h1
-rw-r--r--freebsd/sys/dev/usb/storage/umass.c292
-rw-r--r--freebsd/sys/dev/usb/usb.h16
-rw-r--r--freebsd/sys/dev/usb/usb_dev.c8
-rw-r--r--freebsd/sys/dev/usb/usb_device.c75
-rw-r--r--freebsd/sys/dev/usb/usb_device.h3
-rw-r--r--freebsd/sys/dev/usb/usb_freebsd.h8
-rw-r--r--freebsd/sys/dev/usb/usb_generic.c17
-rw-r--r--freebsd/sys/dev/usb/usb_hid.c76
-rw-r--r--freebsd/sys/dev/usb/usb_hub.c2
-rw-r--r--freebsd/sys/dev/usb/usb_ioctl.h3
-rw-r--r--freebsd/sys/dev/usb/usb_msctest.c52
-rw-r--r--freebsd/sys/dev/usb/usb_process.c8
-rw-r--r--freebsd/sys/dev/usb/usb_process.h6
-rw-r--r--freebsd/sys/dev/usb/usb_request.c54
-rw-r--r--freebsd/sys/dev/usb/usb_request.h2
-rw-r--r--freebsd/sys/dev/usb/usb_transfer.c6
-rw-r--r--freebsd/sys/dev/usb/usb_util.c53
-rw-r--r--freebsd/sys/dev/usb/usb_util.h1
-rw-r--r--freebsd/sys/dev/usb/usbhid.h2
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, &reg) == 0) {
+ if (pci_find_cap(dev, PCIY_PCIX, &reg) == 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, &reg) == 0) {
+ if (pci_find_cap(dev, PCIY_EXPRESS, &reg) == 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, &reg) == 0) {
+ if (pci_find_cap(dev, PCIY_MSI, &reg) == 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, &reg) == 0) {
+ if (pci_find_cap(dev, PCIY_MSIX, &reg) == 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, &reg) == 0) {
+ if (pci_find_cap(dev, PCIY_EXPRESS, &reg) == 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, &reg) == 0)
+ if (pci_find_cap(dev, PCIY_PCIX, &reg) == 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, &reg) == 0) {
+ if (pci_find_cap(sc->bge_dev, PCIY_MSI, &reg) == 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, &reg, start, end, count,
+ res = resource_list_reserve(rl, bus, dev, type, &reg, 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, &reg, 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, &reg) == 0) {
+ if (pci_find_cap(dev, PCIY_EXPRESS, &reg) == 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, &reg) == 0)
+ if (pci_find_cap(sc->rl_dev, PCIY_PMG, &reg) == 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_ */