summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/ahci/ahci.c2
-rw-r--r--sys/dev/cas/if_cas.c39
-rw-r--r--sys/dev/e1000/e1000_api.c2
-rw-r--r--sys/dev/e1000/e1000_hw.h2
-rw-r--r--sys/dev/e1000/if_em.c138
-rw-r--r--sys/dev/e1000/if_igb.c326
-rw-r--r--sys/dev/e1000/if_igb.h17
-rw-r--r--sys/dev/fxp/if_fxp.c36
-rw-r--r--sys/dev/fxp/if_fxpvar.h4
-rw-r--r--sys/dev/gem/if_gem.c16
-rw-r--r--sys/dev/mii/bmtphy.c67
-rw-r--r--sys/dev/mii/gentbi.c2
-rw-r--r--sys/dev/mii/inphy.c5
-rw-r--r--sys/dev/mii/mii.c10
-rw-r--r--sys/dev/mii/miidevs2
-rw-r--r--sys/dev/mii/nsgphy.c2
-rw-r--r--sys/dev/mii/nsphyter.c6
-rw-r--r--sys/dev/mii/ukphy.c2
-rw-r--r--sys/dev/pci/pci.c29
-rw-r--r--sys/dev/pci/pci_pci.c2
-rw-r--r--sys/dev/usb/controller/usb_controller.c8
-rw-r--r--sys/dev/usb/serial/u3g.c2
-rw-r--r--sys/dev/usb/usb_bus.h2
-rw-r--r--sys/dev/usb/usb_pf.c1661
-rw-r--r--sys/dev/usb/usb_pf.h225
-rw-r--r--sys/dev/usb/usbdevs10
26 files changed, 478 insertions, 2139 deletions
diff --git a/sys/dev/ahci/ahci.c b/sys/dev/ahci/ahci.c
index 6794f45..4b93d9b 100644
--- a/sys/dev/ahci/ahci.c
+++ b/sys/dev/ahci/ahci.c
@@ -858,7 +858,7 @@ ahci_ch_attach(device_t dev)
ch->caps = ctlr->caps;
ch->caps2 = ctlr->caps2;
ch->quirks = ctlr->quirks;
- ch->numslots = ((ch->caps & AHCI_CAP_NCS) >> AHCI_CAP_NCS_SHIFT) + 1,
+ ch->numslots = ((ch->caps & AHCI_CAP_NCS) >> AHCI_CAP_NCS_SHIFT) + 1;
mtx_init(&ch->mtx, "AHCI channel lock", NULL, MTX_DEF);
resource_int_value(device_get_name(dev),
device_get_unit(dev), "pm_level", &ch->pm_level);
diff --git a/sys/dev/cas/if_cas.c b/sys/dev/cas/if_cas.c
index e454fa1..0fe4fc5 100644
--- a/sys/dev/cas/if_cas.c
+++ b/sys/dev/cas/if_cas.c
@@ -346,7 +346,7 @@ cas_attach(struct cas_softc *sc)
}
error = mii_attach(sc->sc_dev, &sc->sc_miibus, ifp,
cas_mediachange, cas_mediastatus, BMSR_DEFCAPMASK,
- MII_PHY_ANY, MII_OFFSET_ANY, 0);
+ MII_PHY_ANY, MII_OFFSET_ANY, MIIF_DOPAUSE);
}
/*
* Fall back on an internal PHY if no external PHY was found.
@@ -366,7 +366,7 @@ cas_attach(struct cas_softc *sc)
}
error = mii_attach(sc->sc_dev, &sc->sc_miibus, ifp,
cas_mediachange, cas_mediastatus, BMSR_DEFCAPMASK,
- MII_PHY_ANY, MII_OFFSET_ANY, 0);
+ MII_PHY_ANY, MII_OFFSET_ANY, MIIF_DOPAUSE);
}
} else {
/*
@@ -388,7 +388,7 @@ cas_attach(struct cas_softc *sc)
BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
error = mii_attach(sc->sc_dev, &sc->sc_miibus, ifp,
cas_mediachange, cas_mediastatus, BMSR_DEFCAPMASK,
- CAS_PHYAD_EXTERNAL, MII_OFFSET_ANY, 0);
+ CAS_PHYAD_EXTERNAL, MII_OFFSET_ANY, MIIF_DOPAUSE);
}
if (error != 0) {
device_printf(sc->sc_dev, "attaching PHYs failed\n");
@@ -1093,8 +1093,7 @@ cas_init_locked(struct cas_softc *sc)
/* Set the PAUSE thresholds. We use the maximum OFF threshold. */
CAS_WRITE_4(sc, CAS_RX_PTHRS,
- ((111 * 64) << CAS_RX_PTHRS_XOFF_SHFT) |
- ((15 * 64) << CAS_RX_PTHRS_XON_SHFT));
+ (111 << CAS_RX_PTHRS_XOFF_SHFT) | (15 << CAS_RX_PTHRS_XON_SHFT));
/* RX blanking */
CAS_WRITE_4(sc, CAS_RX_BLANK,
@@ -1339,7 +1338,7 @@ cas_init_regs(struct cas_softc *sc)
CAS_WRITE_4(sc, CAS_MAC_PREAMBLE_LEN, 0x7);
CAS_WRITE_4(sc, CAS_MAC_JAM_SIZE, 0x4);
CAS_WRITE_4(sc, CAS_MAC_ATTEMPT_LIMIT, 0x10);
- CAS_WRITE_4(sc, CAS_MAC_CTRL_TYPE, 0x8088);
+ CAS_WRITE_4(sc, CAS_MAC_CTRL_TYPE, 0x8808);
/* random number seed */
CAS_WRITE_4(sc, CAS_MAC_RANDOM_SEED,
@@ -1572,11 +1571,11 @@ cas_tint(struct cas_softc *sc)
}
#ifdef CAS_DEBUG
- CTR4(KTR_CAS, "%s: CAS_TX_STATE_MACHINE %x CAS_TX_DESC_BASE %llx "
+ CTR5(KTR_CAS, "%s: CAS_TX_SM1 %x CAS_TX_SM2 %x CAS_TX_DESC_BASE %llx "
"CAS_TX_COMP3 %x",
- __func__, CAS_READ_4(sc, CAS_TX_STATE_MACHINE),
- ((long long)CAS_READ_4(sc, CAS_TX_DESC_BASE_HI3) << 32) |
- CAS_READ_4(sc, CAS_TX_DESC_BASE_LO3),
+ __func__, CAS_READ_4(sc, CAS_TX_SM1), CAS_READ_4(sc, CAS_TX_SM2),
+ ((long long)CAS_READ_4(sc, CAS_TX_DESC3_BASE_HI) << 32) |
+ CAS_READ_4(sc, CAS_TX_DESC3_BASE_LO),
CAS_READ_4(sc, CAS_TX_COMP3));
#endif
@@ -1638,7 +1637,7 @@ cas_rint(struct cas_softc *sc)
rxhead = CAS_READ_4(sc, CAS_RX_COMP_HEAD);
#ifdef CAS_DEBUG
CTR4(KTR_CAS, "%s: sc->sc_rxcptr %d, sc->sc_rxdptr %d, head %d",
- __func__, sc->rxcptr, sc->sc_rxdptr, rxhead);
+ __func__, sc->sc_rxcptr, sc->sc_rxdptr, rxhead);
#endif
skip = 0;
CAS_CDSYNC(sc, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
@@ -1865,7 +1864,7 @@ cas_rint(struct cas_softc *sc)
#ifdef CAS_DEBUG
CTR4(KTR_CAS, "%s: done sc->sc_rxcptr %d, sc->sc_rxdptr %d, head %d",
- __func__, sc->rxcptr, sc->sc_rxdptr,
+ __func__, sc->sc_rxcptr, sc->sc_rxdptr,
CAS_READ_4(sc, CAS_RX_COMP_HEAD));
#endif
}
@@ -1988,7 +1987,7 @@ cas_intr_task(void *arg, int pending __unused)
#ifdef CAS_DEBUG
CTR4(KTR_CAS, "%s: %s: cplt %x, status %x",
device_get_name(sc->sc_dev), __func__,
- (status >> CAS_STATUS_TX_COMP3_SHIFT), (u_int)status);
+ (status >> CAS_STATUS_TX_COMP3_SHFT), (u_int)status);
/*
* PCS interrupts must be cleared, otherwise no traffic is passed!
@@ -2100,15 +2099,15 @@ cas_watchdog(struct cas_softc *sc)
#ifdef CAS_DEBUG
CTR4(KTR_CAS,
- "%s: CAS_RX_CONFIG %x CAS_MAC_RX_STATUS %x CAS_MAC_RX_CONFIG %x",
- __func__, CAS_READ_4(sc, CAS_RX_CONFIG),
+ "%s: CAS_RX_CONF %x CAS_MAC_RX_STATUS %x CAS_MAC_RX_CONF %x",
+ __func__, CAS_READ_4(sc, CAS_RX_CONF),
CAS_READ_4(sc, CAS_MAC_RX_STATUS),
- CAS_READ_4(sc, CAS_MAC_RX_CONFIG));
+ CAS_READ_4(sc, CAS_MAC_RX_CONF));
CTR4(KTR_CAS,
- "%s: CAS_TX_CONFIG %x CAS_MAC_TX_STATUS %x CAS_MAC_TX_CONFIG %x",
- __func__, CAS_READ_4(sc, CAS_TX_CONFIG),
+ "%s: CAS_TX_CONF %x CAS_MAC_TX_STATUS %x CAS_MAC_TX_CONF %x",
+ __func__, CAS_READ_4(sc, CAS_TX_CONF),
CAS_READ_4(sc, CAS_MAC_TX_STATUS),
- CAS_READ_4(sc, CAS_MAC_TX_CONFIG));
+ CAS_READ_4(sc, CAS_MAC_TX_CONF));
#endif
if (sc->sc_wdog_timer == 0 || --sc->sc_wdog_timer != 0)
@@ -2356,14 +2355,12 @@ cas_mii_statchg(device_t dev)
v = CAS_READ_4(sc, CAS_MAC_CTRL_CONF) &
~(CAS_MAC_CTRL_CONF_TXP | CAS_MAC_CTRL_CONF_RXP);
-#ifdef notyet
if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) &
IFM_ETH_RXPAUSE) != 0)
v |= CAS_MAC_CTRL_CONF_RXP;
if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) &
IFM_ETH_TXPAUSE) != 0)
v |= CAS_MAC_CTRL_CONF_TXP;
-#endif
CAS_WRITE_4(sc, CAS_MAC_CTRL_CONF, v);
/*
diff --git a/sys/dev/e1000/e1000_api.c b/sys/dev/e1000/e1000_api.c
index 3ae023c..b3a7ef9 100644
--- a/sys/dev/e1000/e1000_api.c
+++ b/sys/dev/e1000/e1000_api.c
@@ -312,6 +312,8 @@ s32 e1000_set_mac_type(struct e1000_hw *hw)
case E1000_DEV_ID_82580_SGMII:
case E1000_DEV_ID_82580_COPPER_DUAL:
case E1000_DEV_ID_82580_QUAD_FIBER:
+ case E1000_DEV_ID_DH89XXCC_SGMII:
+ case E1000_DEV_ID_DH89XXCC_SERDES:
mac->type = e1000_82580;
break;
case E1000_DEV_ID_82576_VF:
diff --git a/sys/dev/e1000/e1000_hw.h b/sys/dev/e1000/e1000_hw.h
index ca9c97d..e80e870 100644
--- a/sys/dev/e1000/e1000_hw.h
+++ b/sys/dev/e1000/e1000_hw.h
@@ -150,6 +150,8 @@ struct e1000_hw;
#define E1000_DEV_ID_82580_SGMII 0x1511
#define E1000_DEV_ID_82580_COPPER_DUAL 0x1516
#define E1000_DEV_ID_82580_QUAD_FIBER 0x1527
+#define E1000_DEV_ID_DH89XXCC_SGMII 0x0436
+#define E1000_DEV_ID_DH89XXCC_SERDES 0x0438
#define E1000_REVISION_0 0
#define E1000_REVISION_1 1
#define E1000_REVISION_2 2
diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c
index c41e144..6728a98 100644
--- a/sys/dev/e1000/if_em.c
+++ b/sys/dev/e1000/if_em.c
@@ -93,7 +93,7 @@ int em_display_debug_stats = 0;
/*********************************************************************
* Driver version:
*********************************************************************/
-char em_driver_version[] = "7.1.7";
+char em_driver_version[] = "7.1.8";
/*********************************************************************
* PCI Device ID Table
@@ -272,6 +272,7 @@ static void em_get_wakeup(device_t);
static void em_enable_wakeup(device_t);
static int em_enable_phy_wakeup(struct adapter *);
static void em_led_func(void *, int);
+static void em_disable_aspm(struct adapter *);
static int em_irq_fast(void *);
@@ -1229,9 +1230,9 @@ em_init_locked(struct adapter *adapter)
break;
case e1000_ich9lan:
case e1000_ich10lan:
- case e1000_pchlan:
pba = E1000_PBA_10K;
break;
+ case e1000_pchlan:
case e1000_pch2lan:
pba = E1000_PBA_26K;
break;
@@ -2762,6 +2763,7 @@ em_reset(struct adapter *adapter)
/* Issue a global reset */
e1000_reset_hw(hw);
E1000_WRITE_REG(hw, E1000_WUC, 0);
+ em_disable_aspm(adapter);
if (e1000_init_hw(hw) < 0) {
device_printf(dev, "Hardware Initialization Failed\n");
@@ -4205,68 +4207,66 @@ em_rxeof(struct rx_ring *rxr, int count, int *done)
len = le16toh(cur->length);
eop = (status & E1000_RXD_STAT_EOP) != 0;
- count--;
- if (((cur->errors & E1000_RXD_ERR_FRAME_ERR_MASK) == 0) &&
- (rxr->discard == FALSE)) {
+ if ((rxr->discard == TRUE) || (cur->errors &
+ E1000_RXD_ERR_FRAME_ERR_MASK)) {
+ ifp->if_ierrors++;
+ ++rxr->rx_discarded;
+ if (!eop) /* Catch subsequent segs */
+ rxr->discard = TRUE;
+ else
+ rxr->discard = FALSE;
+ em_rx_discard(rxr, i);
+ goto next_desc;
+ }
- /* Assign correct length to the current fragment */
- mp = rxr->rx_buffers[i].m_head;
- mp->m_len = len;
+ /* Assign correct length to the current fragment */
+ mp = rxr->rx_buffers[i].m_head;
+ mp->m_len = len;
- /* Trigger for refresh */
- rxr->rx_buffers[i].m_head = NULL;
+ /* Trigger for refresh */
+ rxr->rx_buffers[i].m_head = NULL;
- if (rxr->fmp == NULL) {
- mp->m_pkthdr.len = len;
- rxr->fmp = mp; /* Store the first mbuf */
- rxr->lmp = mp;
- } else {
- /* Chain mbuf's together */
- mp->m_flags &= ~M_PKTHDR;
- rxr->lmp->m_next = mp;
- rxr->lmp = rxr->lmp->m_next;
- rxr->fmp->m_pkthdr.len += len;
- }
+ /* First segment? */
+ if (rxr->fmp == NULL) {
+ mp->m_pkthdr.len = len;
+ rxr->fmp = rxr->lmp = mp;
+ } else {
+ /* Chain mbuf's together */
+ mp->m_flags &= ~M_PKTHDR;
+ rxr->lmp->m_next = mp;
+ rxr->lmp = mp;
+ rxr->fmp->m_pkthdr.len += len;
+ }
- if (eop) {
- rxr->fmp->m_pkthdr.rcvif = ifp;
- ifp->if_ipackets++;
- em_receive_checksum(cur, rxr->fmp);
+ if (eop) {
+ --count;
+ sendmp = rxr->fmp;
+ sendmp->m_pkthdr.rcvif = ifp;
+ ifp->if_ipackets++;
+ em_receive_checksum(cur, sendmp);
#ifndef __NO_STRICT_ALIGNMENT
- if (adapter->max_frame_size >
- (MCLBYTES - ETHER_ALIGN) &&
- em_fixup_rx(rxr) != 0)
- goto skip;
+ if (adapter->max_frame_size >
+ (MCLBYTES - ETHER_ALIGN) &&
+ em_fixup_rx(rxr) != 0)
+ goto skip;
#endif
- if (status & E1000_RXD_STAT_VP) {
- rxr->fmp->m_pkthdr.ether_vtag =
- (le16toh(cur->special) &
- E1000_RXD_SPC_VLAN_MASK);
- rxr->fmp->m_flags |= M_VLANTAG;
- }
+ if (status & E1000_RXD_STAT_VP) {
+ sendmp->m_pkthdr.ether_vtag =
+ (le16toh(cur->special) &
+ E1000_RXD_SPC_VLAN_MASK);
+ sendmp->m_flags |= M_VLANTAG;
+ }
#ifdef EM_MULTIQUEUE
- rxr->fmp->m_pkthdr.flowid = rxr->msix;
- rxr->fmp->m_flags |= M_FLOWID;
+ sendmp->m_pkthdr.flowid = rxr->msix;
+ sendmp->m_flags |= M_FLOWID;
#endif
#ifndef __NO_STRICT_ALIGNMENT
skip:
#endif
- sendmp = rxr->fmp;
- rxr->fmp = NULL;
- rxr->lmp = NULL;
- }
- } else {
- ifp->if_ierrors++;
- ++rxr->rx_discarded;
- if (!eop) /* Catch subsequent segs */
- rxr->discard = TRUE;
- else
- rxr->discard = FALSE;
- em_rx_discard(rxr, i);
- sendmp = NULL;
+ rxr->fmp = rxr->lmp = NULL;
}
-
+next_desc:
/* Zero out the receive descriptors status. */
cur->status = 0;
++rxdone; /* cumulative for POLL */
@@ -4293,10 +4293,7 @@ skip:
}
/* Catch any remaining refresh work */
- if (processed != 0) {
- em_refresh_mbufs(rxr, i);
- processed = 0;
- }
+ em_refresh_mbufs(rxr, i);
rxr->next_to_check = i;
if (done != NULL)
@@ -4878,6 +4875,37 @@ em_led_func(void *arg, int onoff)
EM_CORE_UNLOCK(adapter);
}
+/*
+** Disable the L0S and L1 LINK states
+*/
+static void
+em_disable_aspm(struct adapter *adapter)
+{
+ int base, reg;
+ u16 link_cap,link_ctrl;
+ device_t dev = adapter->dev;
+
+ switch (adapter->hw.mac.type) {
+ case e1000_82573:
+ case e1000_82574:
+ case e1000_82583:
+ break;
+ default:
+ return;
+ }
+ if (pci_find_extcap(dev, PCIY_EXPRESS, &base) != 0)
+ return;
+ reg = base + PCIR_EXPRESS_LINK_CAP;
+ link_cap = pci_read_config(dev, reg, 2);
+ if ((link_cap & PCIM_LINK_CAP_ASPM) == 0)
+ return;
+ reg = base + PCIR_EXPRESS_LINK_CTL;
+ link_ctrl = pci_read_config(dev, reg, 2);
+ link_ctrl &= 0xFFFC; /* turn off bit 1 and 2 */
+ pci_write_config(dev, reg, link_ctrl, 2);
+ return;
+}
+
/**********************************************************************
*
* Update the board statistics counters.
diff --git a/sys/dev/e1000/if_igb.c b/sys/dev/e1000/if_igb.c
index ee7ba71..14ccede 100644
--- a/sys/dev/e1000/if_igb.c
+++ b/sys/dev/e1000/if_igb.c
@@ -99,7 +99,7 @@ int igb_display_debug_stats = 0;
/*********************************************************************
* Driver version:
*********************************************************************/
-char igb_driver_version[] = "version - 2.0.4";
+char igb_driver_version[] = "version - 2.0.7";
/*********************************************************************
@@ -137,6 +137,10 @@ static igb_vendor_info_t igb_vendor_info_array[] =
{ 0x8086, E1000_DEV_ID_82580_SGMII, PCI_ANY_ID, PCI_ANY_ID, 0},
{ 0x8086, E1000_DEV_ID_82580_COPPER_DUAL,
PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_82580_QUAD_FIBER,
+ PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_DH89XXCC_SERDES, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_DH89XXCC_SGMII, PCI_ANY_ID, PCI_ANY_ID, 0},
/* required last entry */
{ 0, 0, 0, 0, 0}
};
@@ -307,11 +311,19 @@ static int igb_enable_msix = 1;
TUNABLE_INT("hw.igb.enable_msix", &igb_enable_msix);
/*
- * Header split has seemed to be beneficial in
- * many circumstances tested, however there have
- * been some stability issues, so the default is
- * off.
- */
+** Tuneable Interrupt rate
+*/
+static int igb_max_interrupt_rate = 8000;
+TUNABLE_INT("hw.igb.max_interrupt_rate", &igb_max_interrupt_rate);
+
+/*
+** Header split causes the packet header to
+** be dma'd to a seperate mbuf from the payload.
+** this can have memory alignment benefits. But
+** another plus is that small packets often fit
+** into the header and thus use no cluster. Its
+** a very workload dependent type feature.
+*/
static bool igb_header_split = FALSE;
TUNABLE_INT("hw.igb.hdr_split", &igb_header_split);
@@ -330,15 +342,6 @@ TUNABLE_INT("hw.igb.rx_process_limit", &igb_rx_process_limit);
static int igb_fc_setting = e1000_fc_full;
TUNABLE_INT("hw.igb.fc_setting", &igb_fc_setting);
-/*
-** Shadow VFTA table, this is needed because
-** the real filter table gets cleared during
-** a soft reset and the driver needs to be able
-** to repopulate it.
-*/
-static u32 igb_shadow_vfta[IGB_VFTA_SIZE];
-
-
/*********************************************************************
* Device identification routine
*
@@ -818,7 +821,7 @@ igb_start_locked(struct tx_ring *txr, struct ifnet *ifp)
/* Set watchdog on */
txr->watchdog_time = ticks;
- txr->watchdog_check = TRUE;
+ txr->queue_status = IGB_QUEUE_WORKING;
}
}
@@ -922,7 +925,7 @@ igb_mq_start_locked(struct ifnet *ifp, struct tx_ring *txr, struct mbuf *m)
}
if (enq > 0) {
/* Set the watchdog */
- txr->watchdog_check = TRUE;
+ txr->queue_status = IGB_QUEUE_WORKING;
txr->watchdog_time = ticks;
}
return (err);
@@ -1049,6 +1052,11 @@ igb_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
}
break;
case SIOCSIFMEDIA:
+ /*
+ ** As the speed/duplex settings are being
+ ** changed, we need toreset the PHY.
+ */
+ adapter->hw.phy.reset_disable = FALSE;
/* Check SOL/IDER usage */
IGB_CORE_LOCK(adapter);
if (e1000_check_reset_block(&adapter->hw)) {
@@ -1161,19 +1169,6 @@ igb_init_locked(struct adapter *adapter)
E1000_WRITE_REG(&adapter->hw, E1000_VET, ETHERTYPE_VLAN);
- /* Use real VLAN Filter support? */
- if (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) {
- if (ifp->if_capenable & IFCAP_VLAN_HWFILTER)
- /* Use real VLAN Filter support */
- igb_setup_vlan_hw_support(adapter);
- else {
- u32 ctrl;
- ctrl = E1000_READ_REG(&adapter->hw, E1000_CTRL);
- ctrl |= E1000_CTRL_VME;
- E1000_WRITE_REG(&adapter->hw, E1000_CTRL, ctrl);
- }
- }
-
/* Set hardware offload abilities */
ifp->if_hwassist = 0;
if (ifp->if_capenable & IFCAP_TXCSUM) {
@@ -1201,10 +1196,12 @@ igb_init_locked(struct adapter *adapter)
** Figure out the desired mbuf pool
** for doing jumbo/packetsplit
*/
- if (ifp->if_mtu > ETHERMTU)
+ if (adapter->max_frame_size <= 2048)
+ adapter->rx_mbuf_sz = MCLBYTES;
+ else if (adapter->max_frame_size <= 4096)
adapter->rx_mbuf_sz = MJUMPAGESIZE;
else
- adapter->rx_mbuf_sz = MCLBYTES;
+ adapter->rx_mbuf_sz = MJUM9BYTES;
/* Prepare receive descriptors and buffers */
if (igb_setup_receive_structures(adapter)) {
@@ -1213,6 +1210,19 @@ igb_init_locked(struct adapter *adapter)
}
igb_initialize_receive_units(adapter);
+ /* Use real VLAN Filter support? */
+ if (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) {
+ if (ifp->if_capenable & IFCAP_VLAN_HWFILTER)
+ /* Use real VLAN Filter support */
+ igb_setup_vlan_hw_support(adapter);
+ else {
+ u32 ctrl;
+ ctrl = E1000_READ_REG(&adapter->hw, E1000_CTRL);
+ ctrl |= E1000_CTRL_VME;
+ E1000_WRITE_REG(&adapter->hw, E1000_CTRL, ctrl);
+ }
+ }
+
/* Don't lose promiscuous settings */
igb_set_promisc(adapter);
@@ -1225,9 +1235,6 @@ igb_init_locked(struct adapter *adapter)
if (adapter->msix > 1) /* Set up queue routing */
igb_configure_queues(adapter);
- /* Set up VLAN tag offload and filter */
- igb_setup_vlan_hw_support(adapter);
-
/* this clears any pending interrupts */
E1000_READ_REG(&adapter->hw, E1000_ICR);
#ifdef DEVICE_POLLING
@@ -1627,11 +1634,6 @@ igb_media_change(struct ifnet *ifp)
device_printf(adapter->dev, "Unsupported media type\n");
}
- /* As the speed/duplex settings my have changed we need to
- * reset the PHY.
- */
- adapter->hw.phy.reset_disable = FALSE;
-
igb_init_locked(adapter);
IGB_CORE_UNLOCK(adapter);
@@ -1947,18 +1949,9 @@ igb_local_timer(void *arg)
/*
** Watchdog: check for time since any descriptor was cleaned
*/
- for (int i = 0; i < adapter->num_queues; i++, txr++) {
- IGB_TX_LOCK(txr);
- if ((txr->watchdog_check == FALSE) ||
- (txr->tx_avail == adapter->num_tx_desc)) {
- IGB_TX_UNLOCK(txr);
- continue;
- }
- if ((ticks - txr->watchdog_time) > IGB_WATCHDOG)
+ for (int i = 0; i < adapter->num_queues; i++, txr++)
+ if (txr->queue_status == IGB_QUEUE_HUNG)
goto timeout;
- IGB_TX_UNLOCK(txr);
- }
-
out:
callout_reset(&adapter->timer, hz, igb_local_timer, adapter);
return;
@@ -1973,7 +1966,6 @@ timeout:
txr->me, txr->tx_avail, txr->next_to_clean);
adapter->ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
adapter->watchdog_events++;
- IGB_TX_UNLOCK(txr);
igb_init_locked(adapter);
}
@@ -2037,7 +2029,7 @@ igb_update_link_status(struct adapter *adapter)
if_link_state_change(ifp, LINK_STATE_DOWN);
/* Turn off watchdogs */
for (int i = 0; i < adapter->num_queues; i++, txr++)
- txr->watchdog_check = FALSE;
+ txr->queue_status = IGB_QUEUE_IDLE;
}
}
@@ -2069,7 +2061,7 @@ igb_stop(void *arg)
/* Unarm watchdog timer. */
for (int i = 0; i < adapter->num_queues; i++, txr++) {
IGB_TX_LOCK(txr);
- txr->watchdog_check = FALSE;
+ txr->queue_status = IGB_QUEUE_IDLE;
IGB_TX_UNLOCK(txr);
}
@@ -2280,8 +2272,7 @@ igb_configure_queues(struct adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
struct igb_queue *que;
- u32 tmp, ivar = 0;
- u32 newitr = IGB_DEFAULT_ITR;
+ u32 tmp, ivar = 0, newitr = 0;
/* First turn on RSS capability */
if (adapter->hw.mac.type > e1000_82575)
@@ -2398,6 +2389,9 @@ igb_configure_queues(struct adapter *adapter)
}
/* Set the starting interrupt rate */
+ if (igb_max_interrupt_rate > 0)
+ newitr = (4000000 / igb_max_interrupt_rate) & 0x7FFC;
+
if (hw->mac.type == e1000_82575)
newitr |= newitr << 16;
else
@@ -2509,6 +2503,8 @@ igb_setup_msix(struct adapter *adapter)
/* Manual override */
if (igb_num_queues != 0)
queues = igb_num_queues;
+ if (queues > 8) /* max queues */
+ queues = 8;
/* Can have max of 4 queues on 82575 */
if ((adapter->hw.mac.type == e1000_82575) && (queues > 4))
@@ -2636,7 +2632,7 @@ igb_reset(struct adapter *adapter)
fc->send_xon = TRUE;
/* Set Flow control, use the tunable location if sane */
- if ((igb_fc_setting >= 0) || (igb_fc_setting < 4))
+ if ((igb_fc_setting >= 0) && (igb_fc_setting < 4))
fc->requested_mode = igb_fc_setting;
else
fc->requested_mode = e1000_fc_none;
@@ -2728,10 +2724,11 @@ igb_setup_interface(device_t dev, struct adapter *adapter)
ifp->if_capabilities = IFCAP_HWCSUM | IFCAP_VLAN_HWCSUM;
ifp->if_capabilities |= IFCAP_TSO4;
ifp->if_capabilities |= IFCAP_JUMBO_MTU;
- if (igb_header_split)
- ifp->if_capabilities |= IFCAP_LRO;
-
ifp->if_capenable = ifp->if_capabilities;
+
+ /* Don't enable LRO by default */
+ ifp->if_capabilities |= IFCAP_LRO;
+
#ifdef DEVICE_POLLING
ifp->if_capabilities |= IFCAP_POLLING;
#endif
@@ -3172,7 +3169,7 @@ igb_initialize_transmit_units(struct adapter *adapter)
E1000_READ_REG(hw, E1000_TDBAL(i)),
E1000_READ_REG(hw, E1000_TDLEN(i)));
- txr->watchdog_check = FALSE;
+ txr->queue_status = IGB_QUEUE_IDLE;
txdctl |= IGB_TX_PTHRESH;
txdctl |= IGB_TX_HTHRESH << 8;
@@ -3184,14 +3181,14 @@ igb_initialize_transmit_units(struct adapter *adapter)
if (adapter->hw.mac.type == e1000_vfadapt)
return;
+ e1000_config_collision_dist(hw);
+
/* Program the Transmit Control Register */
tctl = E1000_READ_REG(hw, E1000_TCTL);
tctl &= ~E1000_TCTL_CT;
tctl |= (E1000_TCTL_PSP | E1000_TCTL_RTLC | E1000_TCTL_EN |
(E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT));
- e1000_config_collision_dist(hw);
-
/* This write will effectively turn on the transmit unit. */
E1000_WRITE_REG(hw, E1000_TCTL, tctl);
}
@@ -3500,16 +3497,19 @@ static bool
igb_txeof(struct tx_ring *txr)
{
struct adapter *adapter = txr->adapter;
- int first, last, done;
+ int first, last, done, processed;
struct igb_tx_buffer *tx_buffer;
struct e1000_tx_desc *tx_desc, *eop_desc;
struct ifnet *ifp = adapter->ifp;
IGB_TX_LOCK_ASSERT(txr);
- if (txr->tx_avail == adapter->num_tx_desc)
+ if (txr->tx_avail == adapter->num_tx_desc) {
+ txr->queue_status = IGB_QUEUE_IDLE;
return FALSE;
+ }
+ processed = 0;
first = txr->next_to_clean;
tx_desc = &txr->tx_base[first];
tx_buffer = &txr->tx_buffers[first];
@@ -3536,6 +3536,7 @@ igb_txeof(struct tx_ring *txr)
tx_desc->lower.data = 0;
tx_desc->buffer_addr = 0;
++txr->tx_avail;
+ ++processed;
if (tx_buffer->m_head) {
txr->bytes +=
@@ -3575,6 +3576,15 @@ igb_txeof(struct tx_ring *txr)
txr->next_to_clean = first;
+ /*
+ ** Watchdog calculation, we know there's
+ ** work outstanding or the first return
+ ** would have been taken, so none processed
+ ** for too long indicates a hang.
+ */
+ if ((!processed) && ((ticks - txr->watchdog_time) > IGB_WATCHDOG))
+ txr->queue_status = IGB_QUEUE_HUNG;
+
/*
* If we have enough room, clear IFF_DRV_OACTIVE
* to tell the stack that it is OK to send packets.
@@ -3583,7 +3593,7 @@ igb_txeof(struct tx_ring *txr)
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
/* All clean, turn off the watchdog */
if (txr->tx_avail == adapter->num_tx_desc) {
- txr->watchdog_check = FALSE;
+ txr->queue_status = IGB_QUEUE_IDLE;
return (FALSE);
}
}
@@ -3615,51 +3625,59 @@ igb_refresh_mbufs(struct rx_ring *rxr, int limit)
cleaned = -1; /* Signify no completions */
while (i != limit) {
rxbuf = &rxr->rx_buffers[i];
- if ((rxbuf->m_head == NULL) && (rxr->hdr_split)) {
+ /* No hdr mbuf used with header split off */
+ if (rxr->hdr_split == FALSE)
+ goto no_split;
+ if (rxbuf->m_head == NULL) {
mh = m_gethdr(M_DONTWAIT, MT_DATA);
if (mh == NULL)
goto update;
- mh->m_pkthdr.len = mh->m_len = MHLEN;
- mh->m_len = MHLEN;
- mh->m_flags |= M_PKTHDR;
- m_adj(mh, ETHER_ALIGN);
- /* Get the memory mapping */
- error = bus_dmamap_load_mbuf_sg(rxr->htag,
- rxbuf->hmap, mh, hseg, &nsegs, BUS_DMA_NOWAIT);
- if (error != 0) {
- printf("GET BUF: dmamap load"
- " failure - %d\n", error);
- m_free(mh);
- goto update;
- }
- rxbuf->m_head = mh;
- bus_dmamap_sync(rxr->htag, rxbuf->hmap,
- BUS_DMASYNC_PREREAD);
- rxr->rx_base[i].read.hdr_addr =
- htole64(hseg[0].ds_addr);
- }
+ } else
+ mh = rxbuf->m_head;
+ mh->m_pkthdr.len = mh->m_len = MHLEN;
+ mh->m_len = MHLEN;
+ mh->m_flags |= M_PKTHDR;
+ /* Get the memory mapping */
+ error = bus_dmamap_load_mbuf_sg(rxr->htag,
+ rxbuf->hmap, mh, hseg, &nsegs, BUS_DMA_NOWAIT);
+ if (error != 0) {
+ printf("Refresh mbufs: hdr dmamap load"
+ " failure - %d\n", error);
+ m_free(mh);
+ rxbuf->m_head = NULL;
+ goto update;
+ }
+ rxbuf->m_head = mh;
+ bus_dmamap_sync(rxr->htag, rxbuf->hmap,
+ BUS_DMASYNC_PREREAD);
+ rxr->rx_base[i].read.hdr_addr =
+ htole64(hseg[0].ds_addr);
+no_split:
if (rxbuf->m_pack == NULL) {
mp = m_getjcl(M_DONTWAIT, MT_DATA,
M_PKTHDR, adapter->rx_mbuf_sz);
if (mp == NULL)
goto update;
- mp->m_pkthdr.len = mp->m_len = adapter->rx_mbuf_sz;
- /* Get the memory mapping */
- error = bus_dmamap_load_mbuf_sg(rxr->ptag,
- rxbuf->pmap, mp, pseg, &nsegs, BUS_DMA_NOWAIT);
- if (error != 0) {
- printf("GET BUF: dmamap load"
- " failure - %d\n", error);
- m_free(mp);
- goto update;
- }
- rxbuf->m_pack = mp;
- bus_dmamap_sync(rxr->ptag, rxbuf->pmap,
- BUS_DMASYNC_PREREAD);
- rxr->rx_base[i].read.pkt_addr =
- htole64(pseg[0].ds_addr);
+ } else
+ mp = rxbuf->m_pack;
+
+ mp->m_pkthdr.len = mp->m_len = adapter->rx_mbuf_sz;
+ /* Get the memory mapping */
+ error = bus_dmamap_load_mbuf_sg(rxr->ptag,
+ rxbuf->pmap, mp, pseg, &nsegs, BUS_DMA_NOWAIT);
+ if (error != 0) {
+ printf("Refresh mbufs: payload dmamap load"
+ " failure - %d\n", error);
+ m_free(mp);
+ rxbuf->m_pack = NULL;
+ goto update;
}
+ rxbuf->m_pack = mp;
+ bus_dmamap_sync(rxr->ptag, rxbuf->pmap,
+ BUS_DMASYNC_PREREAD);
+ rxr->rx_base[i].read.pkt_addr =
+ htole64(pseg[0].ds_addr);
cleaned = i;
/* Calculate next index */
@@ -3722,9 +3740,9 @@ igb_allocate_receive_buffers(struct rx_ring *rxr)
BUS_SPACE_MAXADDR, /* lowaddr */
BUS_SPACE_MAXADDR, /* highaddr */
NULL, NULL, /* filter, filterarg */
- MJUMPAGESIZE, /* maxsize */
+ MJUM9BYTES, /* maxsize */
1, /* nsegments */
- MJUMPAGESIZE, /* maxsegsize */
+ MJUM9BYTES, /* maxsegsize */
0, /* flags */
NULL, /* lockfunc */
NULL, /* lockfuncarg */
@@ -3826,7 +3844,7 @@ igb_setup_receive_ring(struct rx_ring *rxr)
rxr->hdr_split = TRUE;
/* Now replenish the ring mbufs */
- for (int j = 0; j != adapter->num_rx_desc; ++j) {
+ for (int j = 0; j < adapter->num_rx_desc; ++j) {
struct mbuf *mh, *mp;
rxbuf = &rxr->rx_buffers[j];
@@ -3897,8 +3915,8 @@ skip_head:
** are undesireable in similar setups.
*/
if (ifp->if_capenable & IFCAP_LRO) {
- int err = tcp_lro_init(lro);
- if (err) {
+ error = tcp_lro_init(lro);
+ if (error) {
device_printf(dev, "LRO Initialization failed!\n");
goto fail;
}
@@ -3940,7 +3958,9 @@ fail:
*/
for (int j = 0; j > i; ++j) {
rxr = &adapter->rx_rings[i];
+ IGB_RX_LOCK(rxr);
igb_free_receive_ring(rxr);
+ IGB_RX_UNLOCK(rxr);
}
return (ENOBUFS);
@@ -3983,9 +4003,13 @@ igb_initialize_receive_units(struct adapter *adapter)
*/
if (ifp->if_mtu > ETHERMTU) {
rctl |= E1000_RCTL_LPE;
- srrctl |= 4096 >> E1000_SRRCTL_BSIZEPKT_SHIFT;
- rctl |= E1000_RCTL_SZ_4096 | E1000_RCTL_BSEX;
-
+ if (adapter->rx_mbuf_sz == MJUMPAGESIZE) {
+ srrctl |= 4096 >> E1000_SRRCTL_BSIZEPKT_SHIFT;
+ rctl |= E1000_RCTL_SZ_4096 | E1000_RCTL_BSEX;
+ } else if (adapter->rx_mbuf_sz > MJUMPAGESIZE) {
+ srrctl |= 8192 >> E1000_SRRCTL_BSIZEPKT_SHIFT;
+ rctl |= E1000_RCTL_SZ_8192 | E1000_RCTL_BSEX;
+ }
/* Set maximum packet len */
psize = adapter->max_frame_size;
/* are we on a vlan? */
@@ -4194,11 +4218,11 @@ igb_free_receive_buffers(struct rx_ring *rxr)
static __inline void
igb_rx_discard(struct rx_ring *rxr, int i)
{
- struct adapter *adapter = rxr->adapter;
struct igb_rx_buf *rbuf;
- struct mbuf *mh, *mp;
rbuf = &rxr->rx_buffers[i];
+
+ /* Partially received? Free the chain */
if (rxr->fmp != NULL) {
rxr->fmp->m_flags |= M_PKTHDR;
m_freem(rxr->fmp);
@@ -4206,19 +4230,23 @@ igb_rx_discard(struct rx_ring *rxr, int i)
rxr->lmp = NULL;
}
- mh = rbuf->m_head;
- mp = rbuf->m_pack;
+ /*
+ ** With advanced descriptors the writeback
+ ** clobbers the buffer addrs, so its easier
+ ** to just free the existing mbufs and take
+ ** the normal refresh path to get new buffers
+ ** and mapping.
+ */
+ if (rbuf->m_head) {
+ m_free(rbuf->m_head);
+ rbuf->m_head = NULL;
+ }
- /* Reuse loaded DMA map and just update mbuf chain */
- if (mh) { /* with no hdr split would be null */
- mh->m_len = MHLEN;
- mh->m_flags |= M_PKTHDR;
- mh->m_next = NULL;
+ if (rbuf->m_pack) {
+ m_free(rbuf->m_pack);
+ rbuf->m_pack = NULL;
}
- mp->m_len = mp->m_pkthdr.len = adapter->rx_mbuf_sz;
- mp->m_data = mp->m_ext.ext_buf;
- mp->m_next = NULL;
return;
}
@@ -4333,10 +4361,9 @@ igb_rxeof(struct igb_queue *que, int count, int *done)
E1000_RXDADV_HDRBUFLEN_SHIFT;
if (hlen > IGB_HDR_BUF)
hlen = IGB_HDR_BUF;
- /* Handle the header mbuf */
mh = rxr->rx_buffers[i].m_head;
mh->m_len = hlen;
- /* clear buf info for refresh */
+ /* clear buf pointer for refresh */
rxbuf->m_head = NULL;
/*
** Get the payload length, this
@@ -4347,7 +4374,7 @@ igb_rxeof(struct igb_queue *que, int count, int *done)
mp = rxr->rx_buffers[i].m_pack;
mp->m_len = plen;
mh->m_next = mp;
- /* clear buf info for refresh */
+ /* clear buf pointer */
rxbuf->m_pack = NULL;
rxr->rx_split_packets++;
}
@@ -4368,7 +4395,7 @@ igb_rxeof(struct igb_queue *que, int count, int *done)
/* Initial frame - setup */
if (rxr->fmp == NULL) {
mh->m_pkthdr.len = mh->m_len;
- /* Store the first mbuf */
+ /* Save the head of the chain */
rxr->fmp = mh;
rxr->lmp = mh;
if (mp != NULL) {
@@ -4533,12 +4560,15 @@ igb_register_vlan(void *arg, struct ifnet *ifp, u16 vtag)
if ((vtag == 0) || (vtag > 4095)) /* Invalid */
return;
+ IGB_CORE_LOCK(adapter);
index = (vtag >> 5) & 0x7F;
bit = vtag & 0x1F;
- igb_shadow_vfta[index] |= (1 << bit);
+ adapter->shadow_vfta[index] |= (1 << bit);
++adapter->num_vlans;
/* Re-init to load the changes */
- igb_init(adapter);
+ if (ifp->if_capenable & IFCAP_VLAN_HWFILTER)
+ igb_init_locked(adapter);
+ IGB_CORE_UNLOCK(adapter);
}
/*
@@ -4557,12 +4587,15 @@ igb_unregister_vlan(void *arg, struct ifnet *ifp, u16 vtag)
if ((vtag == 0) || (vtag > 4095)) /* Invalid */
return;
+ IGB_CORE_LOCK(adapter);
index = (vtag >> 5) & 0x7F;
bit = vtag & 0x1F;
- igb_shadow_vfta[index] &= ~(1 << bit);
+ adapter->shadow_vfta[index] &= ~(1 << bit);
--adapter->num_vlans;
/* Re-init to load the changes */
- igb_init(adapter);
+ if (ifp->if_capenable & IFCAP_VLAN_HWFILTER)
+ igb_init_locked(adapter);
+ IGB_CORE_UNLOCK(adapter);
}
static void
@@ -4585,12 +4618,13 @@ igb_setup_vlan_hw_support(struct adapter *adapter)
** we need to repopulate it now.
*/
for (int i = 0; i < IGB_VFTA_SIZE; i++)
- if (igb_shadow_vfta[i] != 0) {
+ if (adapter->shadow_vfta[i] != 0) {
if (hw->mac.type == e1000_vfadapt)
- e1000_vfta_set_vf(hw, igb_shadow_vfta[i], TRUE);
+ e1000_vfta_set_vf(hw,
+ adapter->shadow_vfta[i], TRUE);
else
E1000_WRITE_REG_ARRAY(hw, E1000_VFTA,
- i, igb_shadow_vfta[i]);
+ i, adapter->shadow_vfta[i]);
}
if (hw->mac.type == e1000_vfadapt)
@@ -4994,6 +5028,28 @@ igb_sysctl_reg_handler(SYSCTL_HANDLER_ARGS)
}
/*
+** Tuneable interrupt rate handler
+*/
+static int
+igb_sysctl_interrupt_rate_handler(SYSCTL_HANDLER_ARGS)
+{
+ struct igb_queue *que = ((struct igb_queue *)oidp->oid_arg1);
+ int error;
+ u32 reg, usec, rate;
+
+ reg = E1000_READ_REG(&que->adapter->hw, E1000_EITR(que->msix));
+ usec = ((reg & 0x7FFC) >> 2);
+ if (usec > 0)
+ rate = 1000000 / usec;
+ else
+ rate = 0;
+ error = sysctl_handle_int(oidp, &rate, 0, req);
+ if (error || !req->newptr)
+ return error;
+ return 0;
+}
+
+/*
* Add sysctl variables, one per statistic, to the system.
*/
static void
@@ -5065,6 +5121,12 @@ igb_add_hw_stats(struct adapter *adapter)
CTLFLAG_RD, NULL, "Queue Name");
queue_list = SYSCTL_CHILDREN(queue_node);
+ SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "interrupt_rate",
+ CTLFLAG_RD, &adapter->queues[i],
+ sizeof(&adapter->queues[i]),
+ igb_sysctl_interrupt_rate_handler,
+ "IU", "Interrupt Rate");
+
SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "txd_head",
CTLFLAG_RD, adapter, E1000_TDH(txr->me),
igb_sysctl_reg_handler, "IU",
diff --git a/sys/dev/e1000/if_igb.h b/sys/dev/e1000/if_igb.h
index 059a8b9..15fdceb 100644
--- a/sys/dev/e1000/if_igb.h
+++ b/sys/dev/e1000/if_igb.h
@@ -190,6 +190,9 @@
#define IGB_TX_BUFFER_SIZE ((uint32_t) 1514)
#define IGB_FC_PAUSE_TIME 0x0680
#define IGB_EEPROM_APME 0x400;
+#define IGB_QUEUE_IDLE 0
+#define IGB_QUEUE_WORKING 1
+#define IGB_QUEUE_HUNG 2
/*
* TDBA/RDBA should be aligned on 16 byte boundary. But TDLEN/RDLEN should be
@@ -237,7 +240,7 @@
/* Define the starting Interrupt rate per Queue */
#define IGB_INTS_PER_SEC 8000
-#define IGB_DEFAULT_ITR 1000000000/(IGB_INTS_PER_SEC * 256)
+#define IGB_DEFAULT_ITR ((1000000/IGB_INTS_PER_SEC) << 2)
#define IGB_LINK_ITR 2000
@@ -300,7 +303,7 @@ struct tx_ring {
u32 bytes;
u32 packets;
- bool watchdog_check;
+ int queue_status;
int watchdog_time;
int tdt;
int tdh;
@@ -384,7 +387,15 @@ struct adapter {
int wol;
int has_manage;
- /* Info about the board itself */
+ /*
+ ** Shadow VFTA table, this is needed because
+ ** the real vlan filter table gets cleared during
+ ** a soft reset and the driver needs to be able
+ ** to repopulate it.
+ */
+ u32 shadow_vfta[IGB_VFTA_SIZE];
+
+ /* Info about the interface */
u8 link_active;
u16 link_speed;
u16 link_duplex;
diff --git a/sys/dev/fxp/if_fxp.c b/sys/dev/fxp/if_fxp.c
index 5710ca7..2d522c3 100644
--- a/sys/dev/fxp/if_fxp.c
+++ b/sys/dev/fxp/if_fxp.c
@@ -107,11 +107,11 @@ static int tx_threshold = 64;
/*
* The configuration byte map has several undefined fields which
* must be one or must be zero. Set up a template for these bits.
- * The actual configuration is performed in fxp_init.
+ * The actual configuration is performed in fxp_init_body.
*
* See struct fxp_cb_config for the bit definitions.
*/
-static u_char fxp_cb_config_template[] = {
+static const u_char const fxp_cb_config_template[] = {
0x0, 0x0, /* cb_status */
0x0, 0x0, /* cb_command */
0x0, 0x0, 0x0, 0x0, /* link_addr */
@@ -155,7 +155,7 @@ static u_char fxp_cb_config_template[] = {
* particular variants, but we don't currently differentiate between
* them.
*/
-static struct fxp_ident fxp_ident_table[] = {
+static const struct fxp_ident const fxp_ident_table[] = {
{ 0x1029, -1, 0, "Intel 82559 PCI/CardBus Pro/100" },
{ 0x1030, -1, 0, "Intel 82559 Pro/100 Ethernet" },
{ 0x1031, -1, 3, "Intel 82801CAM (ICH3) Pro/100 VE Ethernet" },
@@ -217,7 +217,7 @@ static int fxp_shutdown(device_t dev);
static int fxp_suspend(device_t dev);
static int fxp_resume(device_t dev);
-static struct fxp_ident *fxp_find_ident(device_t dev);
+static const struct fxp_ident *fxp_find_ident(device_t dev);
static void fxp_intr(void *xsc);
static void fxp_rxcsum(struct fxp_softc *sc, struct ifnet *ifp,
struct mbuf *m, uint16_t status, int pos);
@@ -366,12 +366,12 @@ fxp_dma_wait(struct fxp_softc *sc, volatile uint16_t *status,
device_printf(sc->dev, "DMA timeout\n");
}
-static struct fxp_ident *
+static const struct fxp_ident *
fxp_find_ident(device_t dev)
{
uint16_t devid;
uint8_t revid;
- struct fxp_ident *ident;
+ const struct fxp_ident *ident;
if (pci_get_vendor(dev) == FXP_VENDORID_INTEL) {
devid = pci_get_device(dev);
@@ -392,7 +392,7 @@ fxp_find_ident(device_t dev)
static int
fxp_probe(device_t dev)
{
- struct fxp_ident *ident;
+ const struct fxp_ident *ident;
ident = fxp_find_ident(dev);
if (ident != NULL) {
@@ -1614,21 +1614,7 @@ fxp_encap(struct fxp_softc *sc, struct mbuf **m_head)
/*
* Advance the end of list forward.
*/
-
-#ifdef __alpha__
- /*
- * On platforms which can't access memory in 16-bit
- * granularities, we must prevent the card from DMA'ing
- * up the status while we update the command field.
- * This could cause us to overwrite the completion status.
- * XXX This is probably bogus and we're _not_ looking
- * for atomicity here.
- */
- atomic_clear_16(&sc->fxp_desc.tx_last->tx_cb->cb_command,
- htole16(FXP_CB_COMMAND_S));
-#else
sc->fxp_desc.tx_last->tx_cb->cb_command &= htole16(~FXP_CB_COMMAND_S);
-#endif /*__alpha__*/
sc->fxp_desc.tx_last = txp;
/*
@@ -2985,13 +2971,13 @@ static uint32_t fxp_ucode_d102e[] = D102_E_RCVBUNDLE_UCODE;
#define UCODE(x) x, sizeof(x)/sizeof(uint32_t)
-struct ucode {
+static const struct ucode {
uint32_t revision;
uint32_t *ucode;
int length;
u_short int_delay_offset;
u_short bundle_max_offset;
-} ucode_table[] = {
+} const ucode_table[] = {
{ FXP_REV_82558_A4, UCODE(fxp_ucode_d101a), D101_CPUSAVER_DWORD, 0 },
{ FXP_REV_82558_B0, UCODE(fxp_ucode_d101b0), D101_CPUSAVER_DWORD, 0 },
{ FXP_REV_82559_A0, UCODE(fxp_ucode_d101ma),
@@ -3010,7 +2996,7 @@ struct ucode {
static void
fxp_load_ucode(struct fxp_softc *sc)
{
- struct ucode *uc;
+ const struct ucode *uc;
struct fxp_cb_ucode *cbp;
int i;
@@ -3177,11 +3163,13 @@ sysctl_int_range(SYSCTL_HANDLER_ARGS, int low, int high)
static int
sysctl_hw_fxp_int_delay(SYSCTL_HANDLER_ARGS)
{
+
return (sysctl_int_range(oidp, arg1, arg2, req, 300, 3000));
}
static int
sysctl_hw_fxp_bundle_max(SYSCTL_HANDLER_ARGS)
{
+
return (sysctl_int_range(oidp, arg1, arg2, req, 1, 0xffff));
}
diff --git a/sys/dev/fxp/if_fxpvar.h b/sys/dev/fxp/if_fxpvar.h
index de44636..ca7f7f5 100644
--- a/sys/dev/fxp/if_fxpvar.h
+++ b/sys/dev/fxp/if_fxpvar.h
@@ -146,7 +146,7 @@ struct fxp_ident {
uint16_t devid;
int16_t revid; /* -1 matches anything */
uint8_t ich;
- char *name;
+ const char *name;
};
struct fxp_hwstats {
@@ -182,7 +182,7 @@ struct fxp_softc {
struct resource *fxp_res[2]; /* I/O and IRQ resources */
struct resource_spec *fxp_spec; /* the resource spec we used */
void *ih; /* interrupt handler cookie */
- struct fxp_ident *ident;
+ const struct fxp_ident *ident;
struct mtx sc_mtx;
bus_dma_tag_t fxp_txmtag; /* bus DMA tag for Tx mbufs */
bus_dma_tag_t fxp_rxmtag; /* bus DMA tag for Rx mbufs */
diff --git a/sys/dev/gem/if_gem.c b/sys/dev/gem/if_gem.c
index 5c5750e..e8d9400 100644
--- a/sys/dev/gem/if_gem.c
+++ b/sys/dev/gem/if_gem.c
@@ -302,7 +302,7 @@ gem_attach(struct gem_softc *sc)
}
error = mii_attach(sc->sc_dev, &sc->sc_miibus, ifp,
gem_mediachange, gem_mediastatus, BMSR_DEFCAPMASK, phy,
- MII_OFFSET_ANY, 0);
+ MII_OFFSET_ANY, MIIF_DOPAUSE);
}
/*
@@ -330,7 +330,7 @@ gem_attach(struct gem_softc *sc)
}
error = mii_attach(sc->sc_dev, &sc->sc_miibus, ifp,
gem_mediachange, gem_mediastatus, BMSR_DEFCAPMASK, phy,
- MII_OFFSET_ANY, 0);
+ MII_OFFSET_ANY, MIIF_DOPAUSE);
}
/*
@@ -352,7 +352,7 @@ gem_attach(struct gem_softc *sc)
sc->sc_flags |= GEM_SERDES;
error = mii_attach(sc->sc_dev, &sc->sc_miibus, ifp,
gem_mediachange, gem_mediastatus, BMSR_DEFCAPMASK,
- GEM_PHYAD_EXTERNAL, MII_OFFSET_ANY, 0);
+ GEM_PHYAD_EXTERNAL, MII_OFFSET_ANY, MIIF_DOPAUSE);
}
if (error != 0) {
device_printf(sc->sc_dev, "attaching PHYs failed\n");
@@ -712,6 +712,9 @@ gem_reset_rx(struct gem_softc *sc)
if (!GEM_BANK1_BITWAIT(sc, GEM_RX_CONFIG, GEM_RX_CONFIG_RXDMA_EN, 0))
device_printf(sc->sc_dev, "cannot disable RX DMA\n");
+ /* Wait 5ms extra. */
+ DELAY(5000);
+
/* Finally, reset the ERX. */
GEM_BANK2_WRITE_4(sc, GEM_RESET, GEM_RESET_RX);
GEM_BANK2_BARRIER(sc, GEM_RESET, 4,
@@ -784,6 +787,9 @@ gem_reset_tx(struct gem_softc *sc)
if (!GEM_BANK1_BITWAIT(sc, GEM_TX_CONFIG, GEM_TX_CONFIG_TXDMA_EN, 0))
device_printf(sc->sc_dev, "cannot disable TX DMA\n");
+ /* Wait 5ms extra. */
+ DELAY(5000);
+
/* Finally, reset the ETX. */
GEM_BANK2_WRITE_4(sc, GEM_RESET, GEM_RESET_TX);
GEM_BANK2_BARRIER(sc, GEM_RESET, 4,
@@ -1239,7 +1245,7 @@ gem_init_regs(struct gem_softc *sc)
GEM_BANK1_WRITE_4(sc, GEM_MAC_PREAMBLE_LEN, 0x7);
GEM_BANK1_WRITE_4(sc, GEM_MAC_JAM_SIZE, 0x4);
GEM_BANK1_WRITE_4(sc, GEM_MAC_ATTEMPT_LIMIT, 0x10);
- GEM_BANK1_WRITE_4(sc, GEM_MAC_CONTROL_TYPE, 0x8088);
+ GEM_BANK1_WRITE_4(sc, GEM_MAC_CONTROL_TYPE, 0x8808);
/* random number seed */
GEM_BANK1_WRITE_4(sc, GEM_MAC_RANDOM_SEED,
@@ -2039,14 +2045,12 @@ gem_mii_statchg(device_t dev)
v = GEM_BANK1_READ_4(sc, GEM_MAC_CONTROL_CONFIG) &
~(GEM_MAC_CC_RX_PAUSE | GEM_MAC_CC_TX_PAUSE);
-#ifdef notyet
if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) &
IFM_ETH_RXPAUSE) != 0)
v |= GEM_MAC_CC_RX_PAUSE;
if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) &
IFM_ETH_TXPAUSE) != 0)
v |= GEM_MAC_CC_TX_PAUSE;
-#endif
GEM_BANK1_WRITE_4(sc, GEM_MAC_CONTROL_CONFIG, v);
if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & IFM_FDX) == 0 &&
diff --git a/sys/dev/mii/bmtphy.c b/sys/dev/mii/bmtphy.c
index 63d1df1..6f53349 100644
--- a/sys/dev/mii/bmtphy.c
+++ b/sys/dev/mii/bmtphy.c
@@ -85,6 +85,11 @@ __FBSDID("$FreeBSD$");
static int bmtphy_probe(device_t);
static int bmtphy_attach(device_t);
+struct bmtphy_softc {
+ struct mii_softc mii_sc;
+ int mii_model;
+};
+
static device_method_t bmtphy_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, bmtphy_probe),
@@ -100,18 +105,21 @@ static devclass_t bmtphy_devclass;
static driver_t bmtphy_driver = {
"bmtphy",
bmtphy_methods,
- sizeof(struct mii_softc)
+ sizeof(struct bmtphy_softc)
};
DRIVER_MODULE(bmtphy, miibus, bmtphy_driver, bmtphy_devclass, 0, 0);
static int bmtphy_service(struct mii_softc *, struct mii_data *, int);
static void bmtphy_status(struct mii_softc *);
+static void bmtphy_reset(struct mii_softc *);
static const struct mii_phydesc bmtphys_dp[] = {
MII_PHY_DESC(BROADCOM, BCM4401),
MII_PHY_DESC(BROADCOM, BCM5201),
+ MII_PHY_DESC(BROADCOM, BCM5214),
MII_PHY_DESC(BROADCOM, BCM5221),
+ MII_PHY_DESC(BROADCOM, BCM5222),
MII_PHY_END
};
@@ -137,11 +145,13 @@ bmtphy_probe(device_t dev)
static int
bmtphy_attach(device_t dev)
{
- struct mii_softc *sc;
- struct mii_attach_args *ma;
- struct mii_data *mii;
+ struct bmtphy_softc *bsc;
+ struct mii_softc *sc;
+ struct mii_attach_args *ma;
+ struct mii_data *mii;
- sc = device_get_softc(dev);
+ 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;
@@ -153,7 +163,11 @@ bmtphy_attach(device_t dev)
sc->mii_service = bmtphy_service;
sc->mii_pdata = mii;
- mii_phy_reset(sc);
+ sc->mii_flags |= MIIF_NOMANPAUSE;
+
+ bsc->mii_model = MII_MODEL(ma->mii_id2);
+
+ bmtphy_reset(sc);
sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
device_printf(dev, " ");
@@ -194,16 +208,15 @@ bmtphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
/* Callback if something changed. */
mii_phy_update(sc, cmd);
-
return (0);
}
static void
bmtphy_status(struct mii_softc *sc)
{
- struct mii_data *mii;
- struct ifmedia_entry *ife;
- int bmsr, bmcr, aux_csr;
+ struct mii_data *mii;
+ struct ifmedia_entry *ife;
+ int bmsr, bmcr, aux_csr;
mii = sc->mii_pdata;
ife = mii->mii_media.ifm_cur;
@@ -212,7 +225,6 @@ bmtphy_status(struct mii_softc *sc)
mii->mii_media_active = IFM_ETHER;
bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
- aux_csr = PHY_READ(sc, MII_BMTPHY_AUX_CSR);
if (bmsr & BMSR_LINK)
mii->mii_media_status |= IFM_ACTIVE;
@@ -238,14 +250,45 @@ bmtphy_status(struct mii_softc *sc)
return;
}
+ aux_csr = PHY_READ(sc, MII_BMTPHY_AUX_CSR);
if (aux_csr & AUX_CSR_SPEED)
mii->mii_media_active |= IFM_100_TX;
else
mii->mii_media_active |= IFM_10_T;
if (aux_csr & AUX_CSR_FDX)
- mii->mii_media_active |= IFM_FDX;
+ mii->mii_media_active |=
+ IFM_FDX | mii_phy_flowstatus(sc);
else
mii->mii_media_active |= IFM_HDX;
} else
mii->mii_media_active = ife->ifm_media;
}
+
+static void
+bmtphy_reset(struct mii_softc *sc)
+{
+ struct bmtphy_softc *bsc;
+ u_int16_t data;
+
+ bsc = (struct bmtphy_softc *)sc;
+
+ mii_phy_reset(sc);
+
+ if (bsc->mii_model == MII_MODEL_BROADCOM_BCM5221) {
+ /* Enable shadow register mode. */
+ data = PHY_READ(sc, 0x1f);
+ PHY_WRITE(sc, 0x1f, data | 0x0080);
+
+ /* Enable APD (Auto PowerDetect). */
+ data = PHY_READ(sc, MII_BMTPHY_AUX2);
+ PHY_WRITE(sc, MII_BMTPHY_AUX2, data | 0x0020);
+
+ /* Enable clocks across APD for Auto-MDIX functionality. */
+ data = PHY_READ(sc, MII_BMTPHY_INTR);
+ PHY_WRITE(sc, MII_BMTPHY_INTR, data | 0x0004);
+
+ /* Disable shadow register mode. */
+ data = PHY_READ(sc, 0x1f);
+ PHY_WRITE(sc, 0x1f, data & ~0x0080);
+ }
+}
diff --git a/sys/dev/mii/gentbi.c b/sys/dev/mii/gentbi.c
index f5d3a8b..a36f16a 100644
--- a/sys/dev/mii/gentbi.c
+++ b/sys/dev/mii/gentbi.c
@@ -172,6 +172,8 @@ gentbi_attach(device_t dev)
sc->mii_service = gentbi_service;
sc->mii_pdata = mii;
+ sc->mii_flags |= MIIF_NOMANPAUSE;
+
mii_phy_reset(sc);
/*
diff --git a/sys/dev/mii/inphy.c b/sys/dev/mii/inphy.c
index 6830b5a..1293641 100644
--- a/sys/dev/mii/inphy.c
+++ b/sys/dev/mii/inphy.c
@@ -113,6 +113,8 @@ inphy_attach(device_t dev)
sc->mii_service = inphy_service;
sc->mii_pdata = mii;
+ sc->mii_flags |= MIIF_NOMANPAUSE;
+
ifmedia_add(&mii->mii_media,
IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst),
MII_MEDIA_100_TX, NULL);
@@ -197,7 +199,8 @@ inphy_status(struct mii_softc *sc)
else
mii->mii_media_active |= IFM_10_T;
if (scr & SCR_FDX)
- mii->mii_media_active |= IFM_FDX;
+ mii->mii_media_active |=
+ IFM_FDX | mii_phy_flowstatus(sc);
else
mii->mii_media_active |= IFM_HDX;
} else
diff --git a/sys/dev/mii/mii.c b/sys/dev/mii/mii.c
index 3df5dfa..8485691 100644
--- a/sys/dev/mii/mii.c
+++ b/sys/dev/mii/mii.c
@@ -137,7 +137,7 @@ miibus_attach(device_t dev)
free(children, M_TEMP);
}
if (nchildren == 0) {
- device_printf(dev, "cannot get children");
+ device_printf(dev, "cannot get children\n");
return (ENXIO);
}
ivars = device_get_ivars(dev);
@@ -311,12 +311,12 @@ mii_attach(device_t dev, device_t *miibus, struct ifnet *ifp,
int bmsr, first, i, nchildren, offset, phymax, phymin, rv;
if (phyloc != MII_PHY_ANY && offloc != MII_OFFSET_ANY) {
- printf("%s: phyloc and offloc specified", __func__);
+ printf("%s: phyloc and offloc specified\n", __func__);
return (EINVAL);
}
if (offloc != MII_OFFSET_ANY && (offloc < 0 || offloc >= MII_NPHY)) {
- printf("%s: ivalid offloc %d", __func__, offloc);
+ printf("%s: ivalid offloc %d\n", __func__, offloc);
return (EINVAL);
}
@@ -325,7 +325,7 @@ mii_attach(device_t dev, device_t *miibus, struct ifnet *ifp,
phymax = MII_NPHY - 1;
} else {
if (phyloc < 0 || phyloc >= MII_NPHY) {
- printf("%s: ivalid phyloc %d", __func__, phyloc);
+ printf("%s: ivalid phyloc %d\n", __func__, phyloc);
return (EINVAL);
}
phymin = phymax = phyloc;
@@ -352,7 +352,7 @@ mii_attach(device_t dev, device_t *miibus, struct ifnet *ifp,
if (ivars->ifp != ifp || ivars->ifmedia_upd != ifmedia_upd ||
ivars->ifmedia_sts != ifmedia_sts ||
ivars->mii_flags != flags) {
- printf("%s: non-matching invariant", __func__);
+ printf("%s: non-matching invariant\n", __func__);
return (EINVAL);
}
/*
diff --git a/sys/dev/mii/miidevs b/sys/dev/mii/miidevs
index ec0b846..24cd551 100644
--- a/sys/dev/mii/miidevs
+++ b/sys/dev/mii/miidevs
@@ -128,7 +128,9 @@ model ATHEROS F1_7 0x0007 Atheros F1 10/100/1000 PHY
model BROADCOM 3C905B 0x0012 3c905B 10/100 internal PHY
model BROADCOM 3C905C 0x0017 3c905C 10/100 internal PHY
model BROADCOM BCM5201 0x0021 BCM5201 10/100baseTX PHY
+model BROADCOM BCM5214 0x0028 BCM5214 Quad 10/100 PHY
model BROADCOM BCM5221 0x001e BCM5221 10/100baseTX PHY
+model BROADCOM BCM5222 0x0032 BCM5222 Dual 10/100 PHY
model BROADCOM BCM4401 0x0036 BCM4401 10/100baseTX PHY
model xxBROADCOM BCM5400 0x0004 Broadcom 1000baseTX PHY
model xxBROADCOM BCM5401 0x0005 BCM5401 10/100/1000baseTX PHY
diff --git a/sys/dev/mii/nsgphy.c b/sys/dev/mii/nsgphy.c
index 7cdee42..4177912 100644
--- a/sys/dev/mii/nsgphy.c
+++ b/sys/dev/mii/nsgphy.c
@@ -135,6 +135,8 @@ nsgphy_attach(device_t dev)
sc->mii_service = nsgphy_service;
sc->mii_pdata = mii;
+ sc->mii_flags |= MIIF_NOMANPAUSE;
+
mii_phy_reset(sc);
/*
diff --git a/sys/dev/mii/nsphyter.c b/sys/dev/mii/nsphyter.c
index 5489504..c302181 100644
--- a/sys/dev/mii/nsphyter.c
+++ b/sys/dev/mii/nsphyter.c
@@ -143,6 +143,8 @@ nsphyter_attach(device_t dev)
sc->mii_service = nsphyter_service;
sc->mii_pdata = mii;
+ sc->mii_flags |= MIIF_NOMANPAUSE;
+
#if 1
#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL)
@@ -242,12 +244,8 @@ nsphyter_status(struct mii_softc *sc)
else
mii->mii_media_active |= IFM_100_TX;
if ((physts & PHYSTS_DUPLEX) != 0)
-#ifdef notyet
mii->mii_media_active |=
IFM_FDX | mii_phy_flowstatus(sc);
-#else
- mii->mii_media_active |= IFM_FDX;
-#endif
else
mii->mii_media_active |= IFM_HDX;
} else
diff --git a/sys/dev/mii/ukphy.c b/sys/dev/mii/ukphy.c
index 05b1b45..10842b7 100644
--- a/sys/dev/mii/ukphy.c
+++ b/sys/dev/mii/ukphy.c
@@ -136,6 +136,8 @@ ukphy_attach(device_t dev)
sc->mii_service = ukphy_service;
sc->mii_pdata = mii;
+ sc->mii_flags |= MIIF_NOMANPAUSE;
+
mii_phy_reset(sc);
sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c
index 6069b6d..e3b6159 100644
--- a/sys/dev/pci/pci.c
+++ b/sys/dev/pci/pci.c
@@ -3022,8 +3022,35 @@ pci_resume(device_t dev)
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
diff --git a/sys/dev/pci/pci_pci.c b/sys/dev/pci/pci_pci.c
index 7915818..199c132 100644
--- a/sys/dev/pci/pci_pci.c
+++ b/sys/dev/pci/pci_pci.c
@@ -860,7 +860,9 @@ host_pcib_get_busno(pci_read_config_fn read_config, int bus, int slot, int func,
case 0x00171166:
case 0x01011166:
case 0x010f1014:
+ case 0x01101166:
case 0x02011166:
+ case 0x02251166:
case 0x03021014:
*busnum = read_config(bus, slot, func, 0x44, 1);
break;
diff --git a/sys/dev/usb/controller/usb_controller.c b/sys/dev/usb/controller/usb_controller.c
index afc2118..d774d34 100644
--- a/sys/dev/usb/controller/usb_controller.c
+++ b/sys/dev/usb/controller/usb_controller.c
@@ -207,6 +207,8 @@ usb_detach(device_t dev)
usb_proc_free(&bus->control_xfer_proc);
+ usbpf_detach(bus);
+
return (0);
}
@@ -435,6 +437,8 @@ usb_attach_sub(device_t dev, struct usb_bus *bus)
usb_devclass_ptr = devclass_find("usbus");
mtx_unlock(&Giant);
+ usbpf_attach(bus);
+
/* Initialise USB process messages */
bus->explore_msg[0].hdr.pm_callback = &usb_bus_explore;
bus->explore_msg[0].bus = bus;
@@ -548,8 +552,6 @@ usb_bus_mem_alloc_all(struct usb_bus *bus, bus_dma_tag_t dmat,
TAILQ_INIT(&bus->intr_q.head);
- usbpf_attach(bus, &bus->uif);
-
#if USB_HAVE_BUSDMA
usb_dma_tag_setup(bus->dma_parent_tag, bus->dma_tags,
dmat, &bus->bus_mtx, NULL, 32, USB_BUS_DMA_TAG_MAX);
@@ -597,8 +599,6 @@ usb_bus_mem_free_all(struct usb_bus *bus, usb_bus_mem_cb_t *cb)
usb_dma_tag_unsetup(bus->dma_parent_tag);
#endif
- usbpf_detach(bus);
-
mtx_destroy(&bus->bus_mtx);
}
diff --git a/sys/dev/usb/serial/u3g.c b/sys/dev/usb/serial/u3g.c
index 646063a..c19f1fd 100644
--- a/sys/dev/usb/serial/u3g.c
+++ b/sys/dev/usb/serial/u3g.c
@@ -281,12 +281,12 @@ static const struct usb_device_id u3g_devs[] = {
U3G_DEV(HUAWEI, E143D, U3GINIT_HUAWEI),
U3G_DEV(HUAWEI, E143E, U3GINIT_HUAWEI),
U3G_DEV(HUAWEI, E143F, U3GINIT_HUAWEI),
- U3G_DEV(HUAWEI, E14AC, U3GINIT_HUAWEI),
U3G_DEV(HUAWEI, E180V, U3GINIT_HUAWEI),
U3G_DEV(HUAWEI, E220, U3GINIT_HUAWEI),
U3G_DEV(HUAWEI, E220BIS, U3GINIT_HUAWEI),
U3G_DEV(HUAWEI, MOBILE, U3GINIT_HUAWEI),
U3G_DEV(HUAWEI, E1752, U3GINIT_HUAWEISCSI),
+ U3G_DEV(HUAWEI, E1820, U3GINIT_HUAWEISCSI),
U3G_DEV(HUAWEI, K3765, U3GINIT_HUAWEI),
U3G_DEV(HUAWEI, K3765_INIT, U3GINIT_HUAWEISCSI),
U3G_DEV(KYOCERA2, CDMA_MSM_K, 0),
diff --git a/sys/dev/usb/usb_bus.h b/sys/dev/usb/usb_bus.h
index c5dfeff..1dd9d6a 100644
--- a/sys/dev/usb/usb_bus.h
+++ b/sys/dev/usb/usb_bus.h
@@ -86,7 +86,7 @@ struct usb_bus {
struct usb_bus_methods *methods; /* filled by HC driver */
struct usb_device **devices;
- struct usbpf_if *uif; /* USB Packet Filter */
+ struct ifnet *ifp; /* only for USB Packet Filter */
usb_power_mask_t hw_power_state; /* see USB_HW_POWER_XXX */
usb_size_t uframe_usage[USB_HS_MICRO_FRAMES_MAX];
diff --git a/sys/dev/usb/usb_pf.c b/sys/dev/usb/usb_pf.c
index 3f5f204..c2925c2 100644
--- a/sys/dev/usb/usb_pf.c
+++ b/sys/dev/usb/usb_pf.c
@@ -43,6 +43,8 @@ __FBSDID("$FreeBSD$");
#include <sys/socket.h>
#include <sys/sockio.h>
#include <net/if.h>
+#include <net/if_types.h>
+#include <net/bpf.h>
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
@@ -55,1623 +57,39 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb_pf.h>
#include <dev/usb/usb_transfer.h>
-/*
- * All usbpf implementations are extracted from bpf(9) APIs and it's
- * specialized for USB packet filtering between the driver and the host
- * controller.
- */
-
-MALLOC_DEFINE(M_USBPF, "USBPktFilter", "USB Packet Filter");
-
-/*
- * Rotate the packet buffers in descriptor ud. Move the store buffer into the
- * hold slot, and the free buffer ino the store slot. Zero the length of the
- * new store buffer. Descriptor lock should be held.
- */
-#define USBPF_ROTATE_BUFFERS(ud) do { \
- (ud)->ud_hbuf = (ud)->ud_sbuf; \
- (ud)->ud_hlen = (ud)->ud_slen; \
- (ud)->ud_sbuf = (ud)->ud_fbuf; \
- (ud)->ud_slen = 0; \
- (ud)->ud_fbuf = NULL; \
- usbpf_bufheld(ud); \
-} while (0)
-
-#ifndef __i386__
-#define USBPF_ALIGN
-#endif
-
-#ifndef USBPF_ALIGN
-#define USBPF_EXTRACT_SHORT(p) ((u_int16_t)ntohs(*(u_int16_t *)p))
-#define USBPF_EXTRACT_LONG(p) (ntohl(*(u_int32_t *)p))
-#else
-#define USBPF_EXTRACT_SHORT(p) \
- ((u_int16_t) \
- ((u_int16_t)*((u_char *)p+0)<<8| \
- (u_int16_t)*((u_char *)p+1)<<0))
-#define USBPF_EXTRACT_LONG(p) \
- ((u_int32_t)*((u_char *)p+0)<<24| \
- (u_int32_t)*((u_char *)p+1)<<16| \
- (u_int32_t)*((u_char *)p+2)<<8| \
- (u_int32_t)*((u_char *)p+3)<<0)
-#endif
-
-/*
- * Number of scratch memory words (for USBPF_LD|USBPF_MEM and USBPF_ST).
- */
-#define USBPF_MEMWORDS 16
-
-/* Values for ud_state */
-#define USBPF_IDLE 0 /* no select in progress */
-#define USBPF_WAITING 1 /* waiting for read timeout in select */
-#define USBPF_TIMED_OUT 2 /* read timeout has expired in select */
-
-#define PRIUSB 26 /* interruptible */
-
-/* Frame directions */
-enum usbpf_direction {
- USBPF_D_IN, /* See incoming frames */
- USBPF_D_INOUT, /* See incoming and outgoing frames */
- USBPF_D_OUT /* See outgoing frames */
-};
-
-static void usbpf_append_bytes(struct usbpf_d *, caddr_t, u_int, void *,
- u_int);
-static void usbpf_attachd(struct usbpf_d *, struct usbpf_if *);
-static void usbpf_detachd(struct usbpf_d *);
-static int usbpf_canfreebuf(struct usbpf_d *);
-static void usbpf_buf_reclaimed(struct usbpf_d *);
-static int usbpf_canwritebuf(struct usbpf_d *);
-
-static d_open_t usbpf_open;
-static d_read_t usbpf_read;
-static d_write_t usbpf_write;
-static d_ioctl_t usbpf_ioctl;
-static d_poll_t usbpf_poll;
-static d_kqfilter_t usbpf_kqfilter;
-
-static struct cdevsw usbpf_cdevsw = {
- .d_version = D_VERSION,
- .d_open = usbpf_open,
- .d_read = usbpf_read,
- .d_write = usbpf_write,
- .d_ioctl = usbpf_ioctl,
- .d_poll = usbpf_poll,
- .d_name = "usbpf",
- .d_kqfilter = usbpf_kqfilter,
-};
-
-static LIST_HEAD(, usbpf_if) usbpf_iflist;
-static struct mtx usbpf_mtx; /* global lock */
-static int usbpf_uifd_cnt;
-
-static int usbpf_bufsize = 4096;
-#define USBPF_MINBUFSIZE 32
-#define USBPF_MAXBUFSIZE 0x80000
-static int usbpf_maxbufsize = USBPF_MAXBUFSIZE;
-#define USBPF_MAXINSNS 512
-static int usbpf_maxinsns = USBPF_MAXINSNS;
-
-static void
-usbpf_buffer_init(struct usbpf_d *ud)
-{
-
- ud->ud_bufsize = usbpf_bufsize;
-}
-
-/*
- * Free USBPF kernel buffers on device close.
- */
-static void
-usbpf_buffer_free(struct usbpf_d *ud)
-{
-
- if (ud->ud_sbuf != NULL)
- free(ud->ud_sbuf, M_USBPF);
- if (ud->ud_hbuf != NULL)
- free(ud->ud_hbuf, M_USBPF);
- if (ud->ud_fbuf != NULL)
- free(ud->ud_fbuf, M_USBPF);
-
-#ifdef INVARIANTS
- ud->ud_sbuf = ud->ud_hbuf = ud->ud_fbuf = (caddr_t)~0;
-#endif
-}
-
-static void
-usbpf_buffer_alloc(struct usbpf_d *ud)
-{
-
- KASSERT(ud->ud_fbuf == NULL, ("%s: ud_fbuf != NULL", __func__));
- KASSERT(ud->ud_sbuf == NULL, ("%s: ud_sbuf != NULL", __func__));
- KASSERT(ud->ud_hbuf == NULL, ("%s: ud_hbuf != NULL", __func__));
-
- ud->ud_fbuf = (caddr_t)malloc(ud->ud_bufsize, M_USBPF, M_WAITOK);
- ud->ud_sbuf = (caddr_t)malloc(ud->ud_bufsize, M_USBPF, M_WAITOK);
- ud->ud_hbuf = NULL;
- ud->ud_slen = 0;
- ud->ud_hlen = 0;
-}
-
-/*
- * Copy buffer storage to user space in read().
- */
-static int
-usbpf_buffer_uiomove(struct usbpf_d *ud, caddr_t buf, u_int len,
- struct uio *uio)
-{
-
- return (uiomove(buf, len, uio));
-}
-
-/*
- * Simple data copy to the current kernel buffer.
- */
-static void
-usbpf_buffer_append_bytes(struct usbpf_d *ud, caddr_t buf, u_int offset,
- void *src, u_int len)
-{
- u_char *src_bytes;
-
- src_bytes = (u_char *)src;
- bcopy(src_bytes, buf + offset, len);
-}
-
-/*
- * Allocate or resize buffers.
- */
-static int
-usbpf_buffer_ioctl_sblen(struct usbpf_d *ud, u_int *i)
-{
- u_int size;
-
- USBPFD_LOCK(ud);
- if (ud->ud_bif != NULL) {
- USBPFD_UNLOCK(ud);
- return (EINVAL);
- }
- size = *i;
- if (size > usbpf_maxbufsize)
- *i = size = usbpf_maxbufsize;
- else if (size < USBPF_MINBUFSIZE)
- *i = size = USBPF_MINBUFSIZE;
- ud->ud_bufsize = size;
- USBPFD_UNLOCK(ud);
- return (0);
-}
-
-static const u_short usbpf_code_map[] = {
- 0x10ff, /* 0x00-0x0f: 1111111100001000 */
- 0x3070, /* 0x10-0x1f: 0000111000001100 */
- 0x3131, /* 0x20-0x2f: 1000110010001100 */
- 0x3031, /* 0x30-0x3f: 1000110000001100 */
- 0x3131, /* 0x40-0x4f: 1000110010001100 */
- 0x1011, /* 0x50-0x5f: 1000100000001000 */
- 0x1013, /* 0x60-0x6f: 1100100000001000 */
- 0x1010, /* 0x70-0x7f: 0000100000001000 */
- 0x0093, /* 0x80-0x8f: 1100100100000000 */
- 0x0000, /* 0x90-0x9f: 0000000000000000 */
- 0x0000, /* 0xa0-0xaf: 0000000000000000 */
- 0x0002, /* 0xb0-0xbf: 0100000000000000 */
- 0x0000, /* 0xc0-0xcf: 0000000000000000 */
- 0x0000, /* 0xd0-0xdf: 0000000000000000 */
- 0x0000, /* 0xe0-0xef: 0000000000000000 */
- 0x0000 /* 0xf0-0xff: 0000000000000000 */
-};
-
-#define USBPF_VALIDATE_CODE(c) \
- ((c) <= 0xff && (usbpf_code_map[(c) >> 4] & (1 << ((c) & 0xf))) != 0)
-
-/*
- * Return true if the 'fcode' is a valid filter program.
- * The constraints are that each jump be forward and to a valid
- * code. The code must terminate with either an accept or reject.
- *
- * The kernel needs to be able to verify an application's filter code.
- * Otherwise, a bogus program could easily crash the system.
- */
-static int
-usbpf_validate(const struct usbpf_insn *f, int len)
-{
- register int i;
- register const struct usbpf_insn *p;
-
- /* Do not accept negative length filter. */
- if (len < 0)
- return (0);
-
- /* An empty filter means accept all. */
- if (len == 0)
- return (1);
-
- for (i = 0; i < len; ++i) {
- p = &f[i];
- /*
- * Check that the code is valid.
- */
- if (!USBPF_VALIDATE_CODE(p->code))
- return (0);
- /*
- * Check that that jumps are forward, and within
- * the code block.
- */
- if (USBPF_CLASS(p->code) == USBPF_JMP) {
- register u_int offset;
-
- if (p->code == (USBPF_JMP|USBPF_JA))
- offset = p->k;
- else
- offset = p->jt > p->jf ? p->jt : p->jf;
- if (offset >= (u_int)(len - i) - 1)
- return (0);
- continue;
- }
- /*
- * Check that memory operations use valid addresses.
- */
- if (p->code == USBPF_ST || p->code == USBPF_STX ||
- p->code == (USBPF_LD|USBPF_MEM) ||
- p->code == (USBPF_LDX|USBPF_MEM)) {
- if (p->k >= USBPF_MEMWORDS)
- return (0);
- continue;
- }
- /*
- * Check for constant division by 0.
- */
- if (p->code == (USBPF_ALU|USBPF_DIV|USBPF_K) && p->k == 0)
- return (0);
- }
- return (USBPF_CLASS(f[len - 1].code) == USBPF_RET);
-}
-
-#ifdef _KERNEL
-#define MINDEX(m, k) \
-{ \
- register int len = m->m_len; \
- \
- while (k >= len) { \
- k -= len; \
- m = m->m_next; \
- if (m == 0) \
- return (0); \
- len = m->m_len; \
- } \
-}
-
-static u_int16_t m_xhalf(struct mbuf *m, usbpf_u_int32 k, int *err);
-static u_int32_t m_xword(struct mbuf *m, usbpf_u_int32 k, int *err);
-
-static u_int32_t
-m_xword(struct mbuf *m, usbpf_u_int32 k, int *err)
-{
- size_t len;
- u_char *cp, *np;
- struct mbuf *m0;
-
- len = m->m_len;
- while (k >= len) {
- k -= len;
- m = m->m_next;
- if (m == 0)
- goto bad;
- len = m->m_len;
- }
- cp = mtod(m, u_char *) + k;
- if (len - k >= 4) {
- *err = 0;
- return (USBPF_EXTRACT_LONG(cp));
- }
- m0 = m->m_next;
- if (m0 == 0 || m0->m_len + len - k < 4)
- goto bad;
- *err = 0;
- np = mtod(m0, u_char *);
- switch (len - k) {
- case 1:
- return (((u_int32_t)cp[0] << 24) |
- ((u_int32_t)np[0] << 16) |
- ((u_int32_t)np[1] << 8) |
- (u_int32_t)np[2]);
-
- case 2:
- return (((u_int32_t)cp[0] << 24) |
- ((u_int32_t)cp[1] << 16) |
- ((u_int32_t)np[0] << 8) |
- (u_int32_t)np[1]);
-
- default:
- return (((u_int32_t)cp[0] << 24) |
- ((u_int32_t)cp[1] << 16) |
- ((u_int32_t)cp[2] << 8) |
- (u_int32_t)np[0]);
- }
- bad:
- *err = 1;
- return (0);
-}
-
-static u_int16_t
-m_xhalf(struct mbuf *m, usbpf_u_int32 k, int *err)
-{
- size_t len;
- u_char *cp;
- struct mbuf *m0;
-
- len = m->m_len;
- while (k >= len) {
- k -= len;
- m = m->m_next;
- if (m == 0)
- goto bad;
- len = m->m_len;
- }
- cp = mtod(m, u_char *) + k;
- if (len - k >= 2) {
- *err = 0;
- return (USBPF_EXTRACT_SHORT(cp));
- }
- m0 = m->m_next;
- if (m0 == 0)
- goto bad;
- *err = 0;
- return ((cp[0] << 8) | mtod(m0, u_char *)[0]);
- bad:
- *err = 1;
- return (0);
-}
-#endif
-
-/*
- * Execute the filter program starting at pc on the packet p
- * wirelen is the length of the original packet
- * buflen is the amount of data present
- */
-static u_int
-usbpf_filter(const struct usbpf_insn *pc, u_char *p, u_int wirelen,
- u_int buflen)
-{
- u_int32_t A = 0, X = 0;
- usbpf_u_int32 k;
- u_int32_t mem[USBPF_MEMWORDS];
-
- /*
- * XXX temporarily the filter system is disabled because currently it
- * could not handle the some machine code properly that leads to
- * kernel crash by invalid usage.
- */
- return ((u_int)-1);
-
- if (pc == NULL)
- /*
- * No filter means accept all.
- */
- return ((u_int)-1);
-
- --pc;
- while (1) {
- ++pc;
- switch (pc->code) {
- default:
-#ifdef _KERNEL
- return (0);
-#else
- abort();
-#endif
-
- case USBPF_RET|USBPF_K:
- return ((u_int)pc->k);
-
- case USBPF_RET|USBPF_A:
- return ((u_int)A);
-
- case USBPF_LD|USBPF_W|USBPF_ABS:
- k = pc->k;
- if (k > buflen || sizeof(int32_t) > buflen - k) {
-#ifdef _KERNEL
- int merr;
-
- if (buflen != 0)
- return (0);
- A = m_xword((struct mbuf *)p, k, &merr);
- if (merr != 0)
- return (0);
- continue;
-#else
- return (0);
-#endif
- }
-#ifdef USBPF_ALIGN
- if (((intptr_t)(p + k) & 3) != 0)
- A = USBPF_EXTRACT_LONG(&p[k]);
- else
-#endif
- A = ntohl(*(int32_t *)(p + k));
- continue;
-
- case USBPF_LD|USBPF_H|USBPF_ABS:
- k = pc->k;
- if (k > buflen || sizeof(int16_t) > buflen - k) {
-#ifdef _KERNEL
- int merr;
-
- if (buflen != 0)
- return (0);
- A = m_xhalf((struct mbuf *)p, k, &merr);
- continue;
-#else
- return (0);
-#endif
- }
- A = USBPF_EXTRACT_SHORT(&p[k]);
- continue;
-
- case USBPF_LD|USBPF_B|USBPF_ABS:
- k = pc->k;
- if (k >= buflen) {
-#ifdef _KERNEL
- struct mbuf *m;
-
- if (buflen != 0)
- return (0);
- m = (struct mbuf *)p;
- MINDEX(m, k);
- A = mtod(m, u_char *)[k];
- continue;
-#else
- return (0);
-#endif
- }
- A = p[k];
- continue;
-
- case USBPF_LD|USBPF_W|USBPF_LEN:
- A = wirelen;
- continue;
-
- case USBPF_LDX|USBPF_W|USBPF_LEN:
- X = wirelen;
- continue;
-
- case USBPF_LD|USBPF_W|USBPF_IND:
- k = X + pc->k;
- if (pc->k > buflen || X > buflen - pc->k ||
- sizeof(int32_t) > buflen - k) {
-#ifdef _KERNEL
- int merr;
-
- if (buflen != 0)
- return (0);
- A = m_xword((struct mbuf *)p, k, &merr);
- if (merr != 0)
- return (0);
- continue;
-#else
- return (0);
-#endif
- }
-#ifdef USBPF_ALIGN
- if (((intptr_t)(p + k) & 3) != 0)
- A = USBPF_EXTRACT_LONG(&p[k]);
- else
-#endif
- A = ntohl(*(int32_t *)(p + k));
- continue;
-
- case USBPF_LD|USBPF_H|USBPF_IND:
- k = X + pc->k;
- if (X > buflen || pc->k > buflen - X ||
- sizeof(int16_t) > buflen - k) {
-#ifdef _KERNEL
- int merr;
-
- if (buflen != 0)
- return (0);
- A = m_xhalf((struct mbuf *)p, k, &merr);
- if (merr != 0)
- return (0);
- continue;
-#else
- return (0);
-#endif
- }
- A = USBPF_EXTRACT_SHORT(&p[k]);
- continue;
-
- case USBPF_LD|USBPF_B|USBPF_IND:
- k = X + pc->k;
- if (pc->k >= buflen || X >= buflen - pc->k) {
-#ifdef _KERNEL
- struct mbuf *m;
-
- if (buflen != 0)
- return (0);
- m = (struct mbuf *)p;
- MINDEX(m, k);
- A = mtod(m, u_char *)[k];
- continue;
-#else
- return (0);
-#endif
- }
- A = p[k];
- continue;
-
- case USBPF_LDX|USBPF_MSH|USBPF_B:
- k = pc->k;
- if (k >= buflen) {
-#ifdef _KERNEL
- register struct mbuf *m;
-
- if (buflen != 0)
- return (0);
- m = (struct mbuf *)p;
- MINDEX(m, k);
- X = (mtod(m, u_char *)[k] & 0xf) << 2;
- continue;
-#else
- return (0);
-#endif
- }
- X = (p[pc->k] & 0xf) << 2;
- continue;
-
- case USBPF_LD|USBPF_IMM:
- A = pc->k;
- continue;
-
- case USBPF_LDX|USBPF_IMM:
- X = pc->k;
- continue;
-
- case USBPF_LD|USBPF_MEM:
- A = mem[pc->k];
- continue;
-
- case USBPF_LDX|USBPF_MEM:
- X = mem[pc->k];
- continue;
-
- case USBPF_ST:
- mem[pc->k] = A;
- continue;
-
- case USBPF_STX:
- mem[pc->k] = X;
- continue;
-
- case USBPF_JMP|USBPF_JA:
- pc += pc->k;
- continue;
-
- case USBPF_JMP|USBPF_JGT|USBPF_K:
- pc += (A > pc->k) ? pc->jt : pc->jf;
- continue;
-
- case USBPF_JMP|USBPF_JGE|USBPF_K:
- pc += (A >= pc->k) ? pc->jt : pc->jf;
- continue;
-
- case USBPF_JMP|USBPF_JEQ|USBPF_K:
- pc += (A == pc->k) ? pc->jt : pc->jf;
- continue;
-
- case USBPF_JMP|USBPF_JSET|USBPF_K:
- pc += (A & pc->k) ? pc->jt : pc->jf;
- continue;
-
- case USBPF_JMP|USBPF_JGT|USBPF_X:
- pc += (A > X) ? pc->jt : pc->jf;
- continue;
-
- case USBPF_JMP|USBPF_JGE|USBPF_X:
- pc += (A >= X) ? pc->jt : pc->jf;
- continue;
-
- case USBPF_JMP|USBPF_JEQ|USBPF_X:
- pc += (A == X) ? pc->jt : pc->jf;
- continue;
-
- case USBPF_JMP|USBPF_JSET|USBPF_X:
- pc += (A & X) ? pc->jt : pc->jf;
- continue;
-
- case USBPF_ALU|USBPF_ADD|USBPF_X:
- A += X;
- continue;
-
- case USBPF_ALU|USBPF_SUB|USBPF_X:
- A -= X;
- continue;
-
- case USBPF_ALU|USBPF_MUL|USBPF_X:
- A *= X;
- continue;
-
- case USBPF_ALU|USBPF_DIV|USBPF_X:
- if (X == 0)
- return (0);
- A /= X;
- continue;
-
- case USBPF_ALU|USBPF_AND|USBPF_X:
- A &= X;
- continue;
-
- case USBPF_ALU|USBPF_OR|USBPF_X:
- A |= X;
- continue;
-
- case USBPF_ALU|USBPF_LSH|USBPF_X:
- A <<= X;
- continue;
-
- case USBPF_ALU|USBPF_RSH|USBPF_X:
- A >>= X;
- continue;
-
- case USBPF_ALU|USBPF_ADD|USBPF_K:
- A += pc->k;
- continue;
-
- case USBPF_ALU|USBPF_SUB|USBPF_K:
- A -= pc->k;
- continue;
-
- case USBPF_ALU|USBPF_MUL|USBPF_K:
- A *= pc->k;
- continue;
-
- case USBPF_ALU|USBPF_DIV|USBPF_K:
- A /= pc->k;
- continue;
-
- case USBPF_ALU|USBPF_AND|USBPF_K:
- A &= pc->k;
- continue;
-
- case USBPF_ALU|USBPF_OR|USBPF_K:
- A |= pc->k;
- continue;
-
- case USBPF_ALU|USBPF_LSH|USBPF_K:
- A <<= pc->k;
- continue;
-
- case USBPF_ALU|USBPF_RSH|USBPF_K:
- A >>= pc->k;
- continue;
-
- case USBPF_ALU|USBPF_NEG:
- A = -A;
- continue;
-
- case USBPF_MISC|USBPF_TAX:
- X = A;
- continue;
-
- case USBPF_MISC|USBPF_TXA:
- A = X;
- continue;
- }
- }
-}
-
-static void
-usbpf_free(struct usbpf_d *ud)
-{
-
- switch (ud->ud_bufmode) {
- case USBPF_BUFMODE_BUFFER:
- return (usbpf_buffer_free(ud));
- default:
- panic("usbpf_buf_free");
- }
-}
-
-/*
- * Notify the buffer model that a buffer has moved into the hold position.
- */
-static void
-usbpf_bufheld(struct usbpf_d *ud)
-{
-
- USBPFD_LOCK_ASSERT(ud);
-}
-
-/*
- * Free buffers currently in use by a descriptor.
- * Called on close.
- */
-static void
-usbpf_freed(struct usbpf_d *ud)
-{
-
- /*
- * We don't need to lock out interrupts since this descriptor has
- * been detached from its interface and it yet hasn't been marked
- * free.
- */
- usbpf_free(ud);
- if (ud->ud_rfilter != NULL)
- free((caddr_t)ud->ud_rfilter, M_USBPF);
- if (ud->ud_wfilter != NULL)
- free((caddr_t)ud->ud_wfilter, M_USBPF);
- mtx_destroy(&ud->ud_mtx);
-}
-
-/*
- * Close the descriptor by detaching it from its interface,
- * deallocating its buffers, and marking it free.
- */
-static void
-usbpf_dtor(void *data)
-{
- struct usbpf_d *ud = data;
-
- USBPFD_LOCK(ud);
- if (ud->ud_state == USBPF_WAITING)
- callout_stop(&ud->ud_callout);
- ud->ud_state = USBPF_IDLE;
- USBPFD_UNLOCK(ud);
- funsetown(&ud->ud_sigio);
- mtx_lock(&usbpf_mtx);
- if (ud->ud_bif)
- usbpf_detachd(ud);
- mtx_unlock(&usbpf_mtx);
- selwakeuppri(&ud->ud_sel, PRIUSB);
- knlist_destroy(&ud->ud_sel.si_note);
- callout_drain(&ud->ud_callout);
- usbpf_freed(ud);
- free(ud, M_USBPF);
-}
-
-/*
- * Open device. Returns ENXIO for illegal minor device number,
- * EBUSY if file is open by another process.
- */
-/* ARGSUSED */
-static int
-usbpf_open(struct cdev *dev, int flags, int fmt, struct thread *td)
-{
- struct usbpf_d *ud;
- int error;
-
- ud = malloc(sizeof(*ud), M_USBPF, M_WAITOK | M_ZERO);
- error = devfs_set_cdevpriv(ud, usbpf_dtor);
- if (error != 0) {
- free(ud, M_USBPF);
- return (error);
- }
-
- usbpf_buffer_init(ud);
- ud->ud_bufmode = USBPF_BUFMODE_BUFFER;
- ud->ud_sig = SIGIO;
- ud->ud_direction = USBPF_D_INOUT;
- ud->ud_pid = td->td_proc->p_pid;
- mtx_init(&ud->ud_mtx, devtoname(dev), "usbpf cdev lock", MTX_DEF);
- callout_init_mtx(&ud->ud_callout, &ud->ud_mtx, 0);
- knlist_init_mtx(&ud->ud_sel.si_note, &ud->ud_mtx);
-
- return (0);
-}
-
-static int
-usbpf_uiomove(struct usbpf_d *ud, caddr_t buf, u_int len, struct uio *uio)
-{
-
- if (ud->ud_bufmode != USBPF_BUFMODE_BUFFER)
- return (EOPNOTSUPP);
- return (usbpf_buffer_uiomove(ud, buf, len, uio));
-}
-
-/*
- * usbpf_read - read next chunk of packets from buffers
- */
-static int
-usbpf_read(struct cdev *dev, struct uio *uio, int ioflag)
-{
- struct usbpf_d *ud;
- int error;
- int non_block;
- int timed_out;
-
- error = devfs_get_cdevpriv((void **)&ud);
- if (error != 0)
- return (error);
-
- /*
- * Restrict application to use a buffer the same size as
- * as kernel buffers.
- */
- if (uio->uio_resid != ud->ud_bufsize)
- return (EINVAL);
-
- non_block = ((ioflag & O_NONBLOCK) != 0);
-
- USBPFD_LOCK(ud);
- ud->ud_pid = curthread->td_proc->p_pid;
- if (ud->ud_bufmode != USBPF_BUFMODE_BUFFER) {
- USBPFD_UNLOCK(ud);
- return (EOPNOTSUPP);
- }
- if (ud->ud_state == USBPF_WAITING)
- callout_stop(&ud->ud_callout);
- timed_out = (ud->ud_state == USBPF_TIMED_OUT);
- ud->ud_state = USBPF_IDLE;
- /*
- * If the hold buffer is empty, then do a timed sleep, which
- * ends when the timeout expires or when enough packets
- * have arrived to fill the store buffer.
- */
- while (ud->ud_hbuf == NULL) {
- if (ud->ud_slen != 0) {
- /*
- * A packet(s) either arrived since the previous
- * read or arrived while we were asleep.
- */
- if (ud->ud_immediate || non_block || timed_out) {
- /*
- * Rotate the buffers and return what's here
- * if we are in immediate mode, non-blocking
- * flag is set, or this descriptor timed out.
- */
- USBPF_ROTATE_BUFFERS(ud);
- break;
- }
- }
-
- /*
- * No data is available, check to see if the usbpf device
- * is still pointed at a real interface. If not, return
- * ENXIO so that the userland process knows to rebind
- * it before using it again.
- */
- if (ud->ud_bif == NULL) {
- USBPFD_UNLOCK(ud);
- return (ENXIO);
- }
-
- if (non_block) {
- USBPFD_UNLOCK(ud);
- return (EWOULDBLOCK);
- }
- error = msleep(ud, &ud->ud_mtx, PRIUSB|PCATCH,
- "uff", ud->ud_rtout);
- if (error == EINTR || error == ERESTART) {
- USBPFD_UNLOCK(ud);
- return (error);
- }
- if (error == EWOULDBLOCK) {
- /*
- * On a timeout, return what's in the buffer,
- * which may be nothing. If there is something
- * in the store buffer, we can rotate the buffers.
- */
- if (ud->ud_hbuf)
- /*
- * We filled up the buffer in between
- * getting the timeout and arriving
- * here, so we don't need to rotate.
- */
- break;
-
- if (ud->ud_slen == 0) {
- USBPFD_UNLOCK(ud);
- return (0);
- }
- USBPF_ROTATE_BUFFERS(ud);
- break;
- }
- }
- /*
- * At this point, we know we have something in the hold slot.
- */
- USBPFD_UNLOCK(ud);
-
- /*
- * Move data from hold buffer into user space.
- * We know the entire buffer is transferred since
- * we checked above that the read buffer is usbpf_bufsize bytes.
- *
- * XXXRW: More synchronization needed here: what if a second thread
- * issues a read on the same fd at the same time? Don't want this
- * getting invalidated.
- */
- error = usbpf_uiomove(ud, ud->ud_hbuf, ud->ud_hlen, uio);
-
- USBPFD_LOCK(ud);
- ud->ud_fbuf = ud->ud_hbuf;
- ud->ud_hbuf = NULL;
- ud->ud_hlen = 0;
- usbpf_buf_reclaimed(ud);
- USBPFD_UNLOCK(ud);
-
- return (error);
-}
-
-static int
-usbpf_write(struct cdev *dev, struct uio *uio, int ioflag)
-{
-
- /* NOT IMPLEMENTED */
- return (ENOSYS);
-}
-
-static int
-usbpf_ioctl_sblen(struct usbpf_d *ud, u_int *i)
-{
-
- if (ud->ud_bufmode != USBPF_BUFMODE_BUFFER)
- return (EOPNOTSUPP);
- return (usbpf_buffer_ioctl_sblen(ud, i));
-}
-
-/*
- * Reset a descriptor by flushing its packet buffer and clearing the receive
- * and drop counts. This is doable for kernel-only buffers, but with
- * zero-copy buffers, we can't write to (or rotate) buffers that are
- * currently owned by userspace. It would be nice if we could encapsulate
- * this logic in the buffer code rather than here.
- */
-static void
-usbpf_reset_d(struct usbpf_d *ud)
-{
-
- USBPFD_LOCK_ASSERT(ud);
-
- if ((ud->ud_hbuf != NULL) &&
- (ud->ud_bufmode != USBPF_BUFMODE_ZBUF || usbpf_canfreebuf(ud))) {
- /* Free the hold buffer. */
- ud->ud_fbuf = ud->ud_hbuf;
- ud->ud_hbuf = NULL;
- ud->ud_hlen = 0;
- usbpf_buf_reclaimed(ud);
- }
- if (usbpf_canwritebuf(ud))
- ud->ud_slen = 0;
- ud->ud_rcount = 0;
- ud->ud_dcount = 0;
- ud->ud_fcount = 0;
- ud->ud_wcount = 0;
- ud->ud_wfcount = 0;
- ud->ud_wdcount = 0;
- ud->ud_zcopy = 0;
-}
-
-static int
-usbpf_setif(struct usbpf_d *ud, struct usbpf_ifreq *ufr)
-{
- struct usbpf_if *uif;
- struct usb_bus *theywant;
-
- theywant = usb_bus_find(ufr->ufr_name);
- if (theywant == NULL || theywant->uif == NULL)
- return (ENXIO);
-
- uif = theywant->uif;
-
- switch (ud->ud_bufmode) {
- case USBPF_BUFMODE_BUFFER:
- if (ud->ud_sbuf == NULL)
- usbpf_buffer_alloc(ud);
- KASSERT(ud->ud_sbuf != NULL, ("%s: ud_sbuf == NULL", __func__));
- break;
-
- default:
- panic("usbpf_setif: bufmode %d", ud->ud_bufmode);
- }
- if (uif != ud->ud_bif) {
- if (ud->ud_bif)
- /*
- * Detach if attached to something else.
- */
- usbpf_detachd(ud);
-
- usbpf_attachd(ud, uif);
- }
- USBPFD_LOCK(ud);
- usbpf_reset_d(ud);
- USBPFD_UNLOCK(ud);
- return (0);
-}
-
-/*
- * Set d's packet filter program to fp. If this file already has a filter,
- * free it and replace it. Returns EINVAL for bogus requests.
- */
-static int
-usbpf_setf(struct usbpf_d *ud, struct usbpf_program *fp, u_long cmd)
-{
- struct usbpf_insn *fcode, *old;
- u_int wfilter, flen, size;
-
- if (cmd == UIOCSETWF) {
- old = ud->ud_wfilter;
- wfilter = 1;
- } else {
- wfilter = 0;
- old = ud->ud_rfilter;
- }
- if (fp->uf_insns == NULL) {
- if (fp->uf_len != 0)
- return (EINVAL);
- USBPFD_LOCK(ud);
- if (wfilter)
- ud->ud_wfilter = NULL;
- else {
- ud->ud_rfilter = NULL;
- if (cmd == UIOCSETF)
- usbpf_reset_d(ud);
- }
- USBPFD_UNLOCK(ud);
- if (old != NULL)
- free((caddr_t)old, M_USBPF);
- return (0);
- }
- flen = fp->uf_len;
- if (flen > usbpf_maxinsns)
- return (EINVAL);
-
- size = flen * sizeof(*fp->uf_insns);
- fcode = (struct usbpf_insn *)malloc(size, M_USBPF, M_WAITOK);
- if (copyin((caddr_t)fp->uf_insns, (caddr_t)fcode, size) == 0 &&
- usbpf_validate(fcode, (int)flen)) {
- USBPFD_LOCK(ud);
- if (wfilter)
- ud->ud_wfilter = fcode;
- else {
- ud->ud_rfilter = fcode;
- if (cmd == UIOCSETF)
- usbpf_reset_d(ud);
- }
- USBPFD_UNLOCK(ud);
- if (old != NULL)
- free((caddr_t)old, M_USBPF);
-
- return (0);
- }
- free((caddr_t)fcode, M_USBPF);
- return (EINVAL);
-}
-
-static int
-usbpf_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
- struct thread *td)
-{
- struct usbpf_d *ud;
- int error;
-
- error = devfs_get_cdevpriv((void **)&ud);
- if (error != 0)
- return (error);
-
- /*
- * Refresh PID associated with this descriptor.
- */
- USBPFD_LOCK(ud);
- ud->ud_pid = td->td_proc->p_pid;
- if (ud->ud_state == USBPF_WAITING)
- callout_stop(&ud->ud_callout);
- ud->ud_state = USBPF_IDLE;
- USBPFD_UNLOCK(ud);
-
- if (ud->ud_locked == 1) {
- switch (cmd) {
- case UIOCGBLEN:
- case UIOCSBLEN:
- case UIOCVERSION:
- break;
- default:
- return (EPERM);
- }
- }
-
- switch (cmd) {
-
- default:
- error = EINVAL;
- break;
-
- /*
- * Get buffer len [for read()].
- */
- case UIOCGBLEN:
- *(u_int *)addr = ud->ud_bufsize;
- break;
-
- /*
- * Set buffer length.
- */
- case UIOCSBLEN:
- error = usbpf_ioctl_sblen(ud, (u_int *)addr);
- break;
-
- /*
- * Set read filter.
- */
- case UIOCSETF:
- error = usbpf_setf(ud, (struct usbpf_program *)addr, cmd);
- break;
-
- /*
- * Set read timeout.
- */
- case UIOCSRTIMEOUT:
- {
- struct timeval *tv = (struct timeval *)addr;
-
- /*
- * Subtract 1 tick from tvtohz() since this isn't
- * a one-shot timer.
- */
- if ((error = itimerfix(tv)) == 0)
- ud->ud_rtout = tvtohz(tv) - 1;
- break;
- }
-
- /*
- * Get read timeout.
- */
- case UIOCGRTIMEOUT:
- {
- struct timeval *tv = (struct timeval *)addr;
-
- tv->tv_sec = ud->ud_rtout / hz;
- tv->tv_usec = (ud->ud_rtout % hz) * tick;
- break;
- }
-
- /*
- * Get packet stats.
- */
- case UIOCGSTATS:
- {
- struct usbpf_stat *us = (struct usbpf_stat *)addr;
-
- /* XXXCSJP overflow */
- us->us_recv = ud->ud_rcount;
- us->us_drop = ud->ud_dcount;
- break;
- }
-
- case UIOCVERSION:
- {
- struct usbpf_version *uv = (struct usbpf_version *)addr;
-
- uv->uv_major = USBPF_MAJOR_VERSION;
- uv->uv_minor = USBPF_MINOR_VERSION;
- break;
- }
-
- /*
- * Set interface.
- */
- case UIOCSETIF:
- error = usbpf_setif(ud, (struct usbpf_ifreq *)addr);
- break;
-
- }
- return (error);
-}
-
-/*
- * Support for select() and poll() system calls
- *
- * Return true iff the specific operation will not block indefinitely.
- * Otherwise, return false but make a note that a selwakeup() must be done.
- */
-static int
-usbpf_poll(struct cdev *dev, int events, struct thread *td)
-{
-
- /* NOT IMPLEMENTED */
- return (ENOSYS);
-}
-
-/*
- * Support for kevent() system call. Register EVFILT_READ filters and
- * reject all others.
- */
-int
-usbpf_kqfilter(struct cdev *dev, struct knote *kn)
-{
-
- /* NOT IMPLEMENTED */
- return (ENOSYS);
-}
-
-/*
- * Attach file to the usbpf interface, i.e. make d listen on bp.
- */
-static void
-usbpf_attachd(struct usbpf_d *ud, struct usbpf_if *uif)
+void
+usbpf_attach(struct usb_bus *ubus)
{
+ struct ifnet *ifp;
- USBPFIF_LOCK(uif);
- ud->ud_bif = uif;
- LIST_INSERT_HEAD(&uif->uif_dlist, ud, ud_next);
+ ifp = ubus->ifp = if_alloc(IFT_USB);
+ if_initname(ifp, "usbus", device_get_unit(ubus->bdev));
+ if_attach(ifp);
- usbpf_uifd_cnt++;
- USBPFIF_UNLOCK(uif);
-}
-
-/*
- * Detach a file from its interface.
- */
-static void
-usbpf_detachd(struct usbpf_d *ud)
-{
- struct usbpf_if *uif;
- struct usb_bus *ubus;
-
- uif = ud->ud_bif;
- USBPFIF_LOCK(uif);
- USBPFD_LOCK(ud);
- ubus = ud->ud_bif->uif_ubus;
+ KASSERT(sizeof(struct usbpf_pkthdr) == USBPF_HDR_LEN,
+ ("wrong USB pf header length (%zd)", sizeof(struct usbpf_pkthdr)));
/*
- * Remove d from the interface's descriptor list.
+ * XXX According to the specification of DLT_USB, it indicates packets
+ * beginning with USB setup header. But not sure all packets would be.
*/
- LIST_REMOVE(ud, ud_next);
-
- usbpf_uifd_cnt--;
- ud->ud_bif = NULL;
- USBPFD_UNLOCK(ud);
- USBPFIF_UNLOCK(uif);
-}
-
-void
-usbpf_attach(struct usb_bus *ubus, struct usbpf_if **driverp)
-{
- struct usbpf_if *uif;
-
- uif = malloc(sizeof(*uif), M_USBPF, M_WAITOK | M_ZERO);
- LIST_INIT(&uif->uif_dlist);
- uif->uif_ubus = ubus;
- mtx_init(&uif->uif_mtx, "usbpf interface lock", NULL, MTX_DEF);
- KASSERT(*driverp == NULL,
- ("usbpf_attach: driverp already initialized"));
- *driverp = uif;
-
- mtx_lock(&usbpf_mtx);
- LIST_INSERT_HEAD(&usbpf_iflist, uif, uif_next);
- mtx_unlock(&usbpf_mtx);
+ bpfattach(ifp, DLT_USB, USBPF_HDR_LEN);
if (bootverbose)
device_printf(ubus->parent, "usbpf attached\n");
}
-/*
- * If there are processes sleeping on this descriptor, wake them up.
- */
-static __inline void
-usbpf_wakeup(struct usbpf_d *ud)
-{
-
- USBPFD_LOCK_ASSERT(ud);
- if (ud->ud_state == USBPF_WAITING) {
- callout_stop(&ud->ud_callout);
- ud->ud_state = USBPF_IDLE;
- }
- wakeup(ud);
- if (ud->ud_async && ud->ud_sig && ud->ud_sigio)
- pgsigio(&ud->ud_sigio, ud->ud_sig, 0);
-
- selwakeuppri(&ud->ud_sel, PRIUSB);
- KNOTE_LOCKED(&ud->ud_sel.si_note, 0);
-}
-
void
usbpf_detach(struct usb_bus *ubus)
{
- struct usbpf_if *uif;
- struct usbpf_d *ud;
-
- /* Locate USBPF interface information */
- mtx_lock(&usbpf_mtx);
- LIST_FOREACH(uif, &usbpf_iflist, uif_next) {
- if (ubus == uif->uif_ubus)
- break;
- }
-
- /* Interface wasn't attached */
- if ((uif == NULL) || (uif->uif_ubus == NULL)) {
- mtx_unlock(&usbpf_mtx);
- printf("usbpf_detach: not attached\n"); /* XXX */
- return;
- }
-
- LIST_REMOVE(uif, uif_next);
- mtx_unlock(&usbpf_mtx);
-
- while ((ud = LIST_FIRST(&uif->uif_dlist)) != NULL) {
- usbpf_detachd(ud);
- USBPFD_LOCK(ud);
- usbpf_wakeup(ud);
- USBPFD_UNLOCK(ud);
- }
-
- mtx_destroy(&uif->uif_mtx);
- free(uif, M_USBPF);
-}
-
-/* Time stamping functions */
-#define USBPF_T_MICROTIME 0x0000
-#define USBPF_T_NANOTIME 0x0001
-#define USBPF_T_BINTIME 0x0002
-#define USBPF_T_NONE 0x0003
-#define USBPF_T_FORMAT_MASK 0x0003
-#define USBPF_T_NORMAL 0x0000
-#define USBPF_T_FAST 0x0100
-#define USBPF_T_MONOTONIC 0x0200
-#define USBPF_T_FORMAT(t) ((t) & USBPF_T_FORMAT_MASK)
-
-#define USBPF_TSTAMP_NONE 0
-#define USBPF_TSTAMP_FAST 1
-#define USBPF_TSTAMP_NORMAL 2
-
-static int
-usbpf_ts_quality(int tstype)
-{
-
- if (tstype == USBPF_T_NONE)
- return (USBPF_TSTAMP_NONE);
- if ((tstype & USBPF_T_FAST) != 0)
- return (USBPF_TSTAMP_FAST);
-
- return (USBPF_TSTAMP_NORMAL);
-}
-
-static int
-usbpf_gettime(struct bintime *bt, int tstype)
-{
- int quality;
-
- quality = usbpf_ts_quality(tstype);
- if (quality == USBPF_TSTAMP_NONE)
- return (quality);
- if (quality == USBPF_TSTAMP_NORMAL)
- binuptime(bt);
- else
- getbinuptime(bt);
-
- return (quality);
-}
-
-/*
- * If the buffer mechanism has a way to decide that a held buffer can be made
- * free, then it is exposed via the usbpf_canfreebuf() interface. (1) is
- * returned if the buffer can be discarded, (0) is returned if it cannot.
- */
-static int
-usbpf_canfreebuf(struct usbpf_d *ud)
-{
-
- USBPFD_LOCK_ASSERT(ud);
-
- return (0);
-}
-
-/*
- * Allow the buffer model to indicate that the current store buffer is
- * immutable, regardless of the appearance of space. Return (1) if the
- * buffer is writable, and (0) if not.
- */
-static int
-usbpf_canwritebuf(struct usbpf_d *ud)
-{
-
- USBPFD_LOCK_ASSERT(ud);
- return (1);
-}
+ struct ifnet *ifp = ubus->ifp;
-/*
- * Notify buffer model that an attempt to write to the store buffer has
- * resulted in a dropped packet, in which case the buffer may be considered
- * full.
- */
-static void
-usbpf_buffull(struct usbpf_d *ud)
-{
-
- USBPFD_LOCK_ASSERT(ud);
-}
-
-/*
- * This function gets called when the free buffer is re-assigned.
- */
-static void
-usbpf_buf_reclaimed(struct usbpf_d *ud)
-{
-
- USBPFD_LOCK_ASSERT(ud);
-
- switch (ud->ud_bufmode) {
- case USBPF_BUFMODE_BUFFER:
- return;
-
- default:
- panic("usbpf_buf_reclaimed");
+ if (ifp != NULL) {
+ bpfdetach(ifp);
+ if_detach(ifp);
+ if_free(ifp);
}
-}
-
-#define SIZEOF_USBPF_HDR(type) \
- (offsetof(type, uh_hdrlen) + sizeof(((type *)0)->uh_hdrlen))
-
-static int
-usbpf_hdrlen(struct usbpf_d *ud)
-{
- int hdrlen;
-
- hdrlen = ud->ud_bif->uif_hdrlen;
- hdrlen += SIZEOF_USBPF_HDR(struct usbpf_xhdr);
- hdrlen = USBPF_WORDALIGN(hdrlen);
-
- return (hdrlen - ud->ud_bif->uif_hdrlen);
-}
-
-static void
-usbpf_bintime2ts(struct bintime *bt, struct usbpf_ts *ts, int tstype)
-{
- struct bintime bt2;
- struct timeval tsm;
- struct timespec tsn;
-
- if ((tstype & USBPF_T_MONOTONIC) == 0) {
- bt2 = *bt;
- bintime_add(&bt2, &boottimebin);
- bt = &bt2;
- }
- switch (USBPF_T_FORMAT(tstype)) {
- case USBPF_T_MICROTIME:
- bintime2timeval(bt, &tsm);
- ts->ut_sec = tsm.tv_sec;
- ts->ut_frac = tsm.tv_usec;
- break;
- case USBPF_T_NANOTIME:
- bintime2timespec(bt, &tsn);
- ts->ut_sec = tsn.tv_sec;
- ts->ut_frac = tsn.tv_nsec;
- break;
- case USBPF_T_BINTIME:
- ts->ut_sec = bt->sec;
- ts->ut_frac = bt->frac;
- break;
- }
-}
-
-/*
- * Move the packet data from interface memory (pkt) into the
- * store buffer. "cpfn" is the routine called to do the actual data
- * transfer. bcopy is passed in to copy contiguous chunks, while
- * usbpf_append_mbuf is passed in to copy mbuf chains. In the latter case,
- * pkt is really an mbuf.
- */
-static void
-catchpacket(struct usbpf_d *ud, u_char *pkt, u_int pktlen, u_int snaplen,
- void (*cpfn)(struct usbpf_d *, caddr_t, u_int, void *, u_int),
- struct bintime *bt)
-{
- struct usbpf_xhdr hdr;
- int caplen, curlen, hdrlen, totlen;
- int do_wakeup = 0;
- int do_timestamp;
- int tstype;
-
- USBPFD_LOCK_ASSERT(ud);
-
- /*
- * Detect whether user space has released a buffer back to us, and if
- * so, move it from being a hold buffer to a free buffer. This may
- * not be the best place to do it (for example, we might only want to
- * run this check if we need the space), but for now it's a reliable
- * spot to do it.
- */
- if (ud->ud_fbuf == NULL && usbpf_canfreebuf(ud)) {
- ud->ud_fbuf = ud->ud_hbuf;
- ud->ud_hbuf = NULL;
- ud->ud_hlen = 0;
- usbpf_buf_reclaimed(ud);
- }
-
- /*
- * Figure out how many bytes to move. If the packet is
- * greater or equal to the snapshot length, transfer that
- * much. Otherwise, transfer the whole packet (unless
- * we hit the buffer size limit).
- */
- hdrlen = usbpf_hdrlen(ud);
- totlen = hdrlen + min(snaplen, pktlen);
- if (totlen > ud->ud_bufsize)
- totlen = ud->ud_bufsize;
-
- /*
- * Round up the end of the previous packet to the next longword.
- *
- * Drop the packet if there's no room and no hope of room
- * If the packet would overflow the storage buffer or the storage
- * buffer is considered immutable by the buffer model, try to rotate
- * the buffer and wakeup pending processes.
- */
- curlen = USBPF_WORDALIGN(ud->ud_slen);
- if (curlen + totlen > ud->ud_bufsize || !usbpf_canwritebuf(ud)) {
- if (ud->ud_fbuf == NULL) {
- /*
- * There's no room in the store buffer, and no
- * prospect of room, so drop the packet. Notify the
- * buffer model.
- */
- usbpf_buffull(ud);
- ++ud->ud_dcount;
- return;
- }
- USBPF_ROTATE_BUFFERS(ud);
- do_wakeup = 1;
- curlen = 0;
- } else if (ud->ud_immediate || ud->ud_state == USBPF_TIMED_OUT)
- /*
- * Immediate mode is set, or the read timeout has already
- * expired during a select call. A packet arrived, so the
- * reader should be woken up.
- */
- do_wakeup = 1;
- caplen = totlen - hdrlen;
- tstype = ud->ud_tstamp;
- do_timestamp = tstype != USBPF_T_NONE;
-
- /*
- * Append the usbpf header. Note we append the actual header size, but
- * move forward the length of the header plus padding.
- */
- bzero(&hdr, sizeof(hdr));
- if (do_timestamp)
- usbpf_bintime2ts(bt, &hdr.uh_tstamp, tstype);
- hdr.uh_datalen = pktlen;
- hdr.uh_hdrlen = hdrlen;
- hdr.uh_caplen = caplen;
- usbpf_append_bytes(ud, ud->ud_sbuf, curlen, &hdr, sizeof(hdr));
-
- /*
- * Copy the packet data into the store buffer and update its length.
- */
- (*cpfn)(ud, ud->ud_sbuf, curlen + hdrlen, pkt, caplen);
- ud->ud_slen = curlen + totlen;
-
- if (do_wakeup)
- usbpf_wakeup(ud);
-}
-
-/*
- * Incoming linkage from device drivers. Process the packet pkt, of length
- * pktlen, which is stored in a contiguous buffer. The packet is parsed
- * by each process' filter, and if accepted, stashed into the corresponding
- * buffer.
- */
-static void
-usbpf_tap(struct usbpf_if *uif, u_char *pkt, u_int pktlen)
-{
- struct bintime bt;
- struct usbpf_d *ud;
- u_int slen;
- int gottime;
-
- gottime = USBPF_TSTAMP_NONE;
- USBPFIF_LOCK(uif);
- LIST_FOREACH(ud, &uif->uif_dlist, ud_next) {
- USBPFD_LOCK(ud);
- ++ud->ud_rcount;
- slen = usbpf_filter(ud->ud_rfilter, pkt, pktlen, pktlen);
- if (slen != 0) {
- ud->ud_fcount++;
- if (gottime < usbpf_ts_quality(ud->ud_tstamp))
- gottime = usbpf_gettime(&bt, ud->ud_tstamp);
- catchpacket(ud, pkt, pktlen, slen,
- usbpf_append_bytes, &bt);
- }
- USBPFD_UNLOCK(ud);
- }
- USBPFIF_UNLOCK(uif);
+ ubus->ifp = NULL;
}
static uint32_t
@@ -1763,11 +181,7 @@ usbpf_xfertap(struct usb_xfer *xfer, int type)
int i;
char *buf, *ptr, *end;
- /*
- * NB: usbpf_uifd_cnt isn't protected by USBPFIF_LOCK() because it's
- * not harmful.
- */
- if (usbpf_uifd_cnt == 0)
+ if (!bpf_peers_present(bus->ifp->if_bpf))
return;
/*
@@ -1777,7 +191,7 @@ usbpf_xfertap(struct usb_xfer *xfer, int type)
* read filter to pass a virtually linear buffer.
*/
buf = ptr = malloc(sizeof(struct usbpf_pkthdr) + (USB_PAGE_SIZE * 5),
- M_USBPF, M_NOWAIT);
+ M_TEMP, M_NOWAIT);
if (buf == NULL) {
printf("usbpf_xfertap: out of memory\n"); /* XXX */
return;
@@ -1827,36 +241,7 @@ usbpf_xfertap(struct usb_xfer *xfer, int type)
ptr += xfer->frlengths[i];
}
- usbpf_tap(bus->uif, buf, ptr - buf);
+ bpf_tap(bus->ifp->if_bpf, buf, ptr - buf);
done:
- free(buf, M_USBPF);
+ free(buf, M_TEMP);
}
-
-static void
-usbpf_append_bytes(struct usbpf_d *ud, caddr_t buf, u_int offset, void *src,
- u_int len)
-{
-
- USBPFD_LOCK_ASSERT(ud);
-
- switch (ud->ud_bufmode) {
- case USBPF_BUFMODE_BUFFER:
- return (usbpf_buffer_append_bytes(ud, buf, offset, src, len));
- default:
- panic("usbpf_buf_append_bytes");
- }
-}
-
-static void
-usbpf_drvinit(void *unused)
-{
- struct cdev *dev;
-
- mtx_init(&usbpf_mtx, "USB packet filter global lock", NULL,
- MTX_DEF);
- LIST_INIT(&usbpf_iflist);
-
- dev = make_dev(&usbpf_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, "usbpf");
-}
-
-SYSINIT(usbpf_dev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, usbpf_drvinit, NULL);
diff --git a/sys/dev/usb/usb_pf.h b/sys/dev/usb/usb_pf.h
index f5ed9a0..58b9ce9 100644
--- a/sys/dev/usb/usb_pf.h
+++ b/sys/dev/usb/usb_pf.h
@@ -37,190 +37,6 @@
#ifndef _DEV_USB_PF_H
#define _DEV_USB_PF_H
-#ifdef _KERNEL
-#include <sys/callout.h>
-#include <sys/selinfo.h>
-#include <sys/queue.h>
-#include <sys/conf.h>
-#endif
-
-typedef int32_t usbpf_int32;
-typedef u_int32_t usbpf_u_int32;
-typedef int64_t usbpf_int64;
-typedef u_int64_t usbpf_u_int64;
-
-struct usbpf_if;
-
-/*
- * Alignment macros. USBPF_WORDALIGN rounds up to the next
- * even multiple of USBPF_ALIGNMENT.
- */
-#define USBPF_ALIGNMENT sizeof(long)
-#define USBPF_WORDALIGN(x) (((x)+(USBPF_ALIGNMENT-1))&~(USBPF_ALIGNMENT-1))
-
-/*
- * The instruction encodings.
- */
-
-/* instruction classes */
-#define USBPF_CLASS(code) ((code) & 0x07)
-#define USBPF_LD 0x00
-#define USBPF_LDX 0x01
-#define USBPF_ST 0x02
-#define USBPF_STX 0x03
-#define USBPF_ALU 0x04
-#define USBPF_JMP 0x05
-#define USBPF_RET 0x06
-#define USBPF_MISC 0x07
-
-/* ld/ldx fields */
-#define USBPF_SIZE(code) ((code) & 0x18)
-#define USBPF_W 0x00
-#define USBPF_H 0x08
-#define USBPF_B 0x10
-#define USBPF_MODE(code) ((code) & 0xe0)
-#define USBPF_IMM 0x00
-#define USBPF_ABS 0x20
-#define USBPF_IND 0x40
-#define USBPF_MEM 0x60
-#define USBPF_LEN 0x80
-#define USBPF_MSH 0xa0
-
-/* alu/jmp fields */
-#define USBPF_OP(code) ((code) & 0xf0)
-#define USBPF_ADD 0x00
-#define USBPF_SUB 0x10
-#define USBPF_MUL 0x20
-#define USBPF_DIV 0x30
-#define USBPF_OR 0x40
-#define USBPF_AND 0x50
-#define USBPF_LSH 0x60
-#define USBPF_RSH 0x70
-#define USBPF_NEG 0x80
-#define USBPF_JA 0x00
-#define USBPF_JEQ 0x10
-#define USBPF_JGT 0x20
-#define USBPF_JGE 0x30
-#define USBPF_JSET 0x40
-#define USBPF_SRC(code) ((code) & 0x08)
-#define USBPF_K 0x00
-#define USBPF_X 0x08
-
-/* ret - USBPF_K and USBPF_X also apply */
-#define USBPF_RVAL(code) ((code) & 0x18)
-#define USBPF_A 0x10
-
-/* misc */
-#define USBPF_MISCOP(code) ((code) & 0xf8)
-#define USBPF_TAX 0x00
-#define USBPF_TXA 0x80
-
-/*
- * The instruction data structure.
- */
-struct usbpf_insn {
- u_short code;
- u_char jt;
- u_char jf;
- usbpf_u_int32 k;
-};
-
-#ifdef _KERNEL
-
-/*
- * Descriptor associated with each open uff file.
- */
-
-struct usbpf_d {
- LIST_ENTRY(usbpf_d) ud_next; /* Linked list of descriptors */
- /*
- * Buffer slots: two memory buffers store the incoming packets.
- * The model has three slots. Sbuf is always occupied.
- * sbuf (store) - Receive interrupt puts packets here.
- * hbuf (hold) - When sbuf is full, put buffer here and
- * wakeup read (replace sbuf with fbuf).
- * fbuf (free) - When read is done, put buffer here.
- * On receiving, if sbuf is full and fbuf is 0, packet is dropped.
- */
- caddr_t ud_sbuf; /* store slot */
- caddr_t ud_hbuf; /* hold slot */
- caddr_t ud_fbuf; /* free slot */
- int ud_slen; /* current length of store buffer */
- int ud_hlen; /* current length of hold buffer */
-
- int ud_bufsize; /* absolute length of buffers */
-
- struct usbpf_if *ud_bif; /* interface descriptor */
- u_long ud_rtout; /* Read timeout in 'ticks' */
- struct usbpf_insn *ud_rfilter; /* read filter code */
- struct usbpf_insn *ud_wfilter; /* write filter code */
- void *ud_bfilter; /* binary filter code */
- u_int64_t ud_rcount; /* number of packets received */
- u_int64_t ud_dcount; /* number of packets dropped */
-
- u_char ud_promisc; /* true if listening promiscuously */
- u_char ud_state; /* idle, waiting, or timed out */
- u_char ud_immediate; /* true to return on packet arrival */
- int ud_hdrcmplt; /* false to fill in src lladdr automatically */
- int ud_direction; /* select packet direction */
- int ud_tstamp; /* select time stamping function */
- int ud_feedback; /* true to feed back sent packets */
- int ud_async; /* non-zero if packet reception should generate signal */
- int ud_sig; /* signal to send upon packet reception */
- struct sigio * ud_sigio; /* information for async I/O */
- struct selinfo ud_sel; /* bsd select info */
- struct mtx ud_mtx; /* mutex for this descriptor */
- struct callout ud_callout; /* for USBPF timeouts with select */
- struct label *ud_label; /* MAC label for descriptor */
- u_int64_t ud_fcount; /* number of packets which matched filter */
- pid_t ud_pid; /* PID which created descriptor */
- int ud_locked; /* true if descriptor is locked */
- u_int ud_bufmode; /* Current buffer mode. */
- u_int64_t ud_wcount; /* number of packets written */
- u_int64_t ud_wfcount; /* number of packets that matched write filter */
- u_int64_t ud_wdcount; /* number of packets dropped during a write */
- u_int64_t ud_zcopy; /* number of zero copy operations */
- u_char ud_compat32; /* 32-bit stream on LP64 system */
-};
-
-#define USBPFD_LOCK(ud) mtx_lock(&(ud)->ud_mtx)
-#define USBPFD_UNLOCK(ud) mtx_unlock(&(ud)->ud_mtx)
-#define USBPFD_LOCK_ASSERT(ud) mtx_assert(&(ud)->ud_mtx, MA_OWNED)
-
-/*
- * Descriptor associated with each attached hardware interface.
- */
-struct usbpf_if {
- LIST_ENTRY(usbpf_if) uif_next; /* list of all interfaces */
- LIST_HEAD(, usbpf_d) uif_dlist; /* descriptor list */
- u_int uif_hdrlen; /* length of link header */
- struct usb_bus *uif_ubus; /* corresponding interface */
- struct mtx uif_mtx; /* mutex for interface */
-};
-
-#define USBPFIF_LOCK(uif) mtx_lock(&(uif)->uif_mtx)
-#define USBPFIF_UNLOCK(uif) mtx_unlock(&(uif)->uif_mtx)
-
-#endif
-
-/*
- * Structure prepended to each packet.
- */
-struct usbpf_ts {
- usbpf_int64 ut_sec; /* seconds */
- usbpf_u_int64 ut_frac; /* fraction */
-};
-struct usbpf_xhdr {
- struct usbpf_ts uh_tstamp; /* time stamp */
- usbpf_u_int32 uh_caplen; /* length of captured portion */
- usbpf_u_int32 uh_datalen; /* original length of packet */
- u_short uh_hdrlen; /* length of uff header (this struct
- plus alignment padding) */
-};
-
-#define USBPF_BUFMODE_BUFFER 1 /* Kernel buffers with read(). */
-#define USBPF_BUFMODE_ZBUF 2 /* Zero-copy buffers. */
-
struct usbpf_pkthdr {
int up_busunit; /* Host controller unit number */
u_char up_address; /* USB device address */
@@ -268,50 +84,13 @@ struct usbpf_pkthdr {
u_char up_reserved[96];
};
-struct usbpf_version {
- u_short uv_major;
- u_short uv_minor;
-};
-#define USBPF_MAJOR_VERSION 1
-#define USBPF_MINOR_VERSION 1
-
-#define USBPF_IFNAMSIZ 32
-struct usbpf_ifreq {
- /* bus name, e.g. "usbus0" */
- char ufr_name[USBPF_IFNAMSIZ];
-};
-
-/*
- * Structure for UIOCSETF.
- */
-struct usbpf_program {
- u_int uf_len;
- struct usbpf_insn *uf_insns;
-};
-
-/*
- * Struct returned by UIOCGSTATS.
- */
-struct usbpf_stat {
- u_int us_recv; /* number of packets received */
- u_int us_drop; /* number of packets dropped */
-};
-
-#define UIOCGBLEN _IOR('U', 102, u_int)
-#define UIOCSBLEN _IOWR('U', 102, u_int)
-#define UIOCSETF _IOW('U', 103, struct usbpf_program)
-#define UIOCSETIF _IOW('U', 108, struct usbpf_ifreq)
-#define UIOCSRTIMEOUT _IOW('U', 109, struct timeval)
-#define UIOCGRTIMEOUT _IOR('U', 110, struct timeval)
-#define UIOCGSTATS _IOR('U', 111, struct usbpf_stat)
-#define UIOCVERSION _IOR('U', 113, struct usbpf_version)
-#define UIOCSETWF _IOW('U', 123, struct usbpf_program)
+#define USBPF_HDR_LEN 128
#define USBPF_XFERTAP_SUBMIT 0
#define USBPF_XFERTAP_DONE 1
#ifdef _KERNEL
-void usbpf_attach(struct usb_bus *, struct usbpf_if **);
+void usbpf_attach(struct usb_bus *);
void usbpf_detach(struct usb_bus *);
void usbpf_xfertap(struct usb_xfer *, int);
#endif
diff --git a/sys/dev/usb/usbdevs b/sys/dev/usb/usbdevs
index 91fe9f4..a34ec3c 100644
--- a/sys/dev/usb/usbdevs
+++ b/sys/dev/usb/usbdevs
@@ -1789,8 +1789,8 @@ product HTC LEGENDINTERNET 0x0ffe HTC Legend Internet Sharing
/* HUAWEI products */
product HUAWEI MOBILE 0x1001 Huawei Mobile
-product HUAWEI E220 0x1003 Huawei HSDPA modem
-product HUAWEI E220BIS 0x1004 Huawei HSDPA modem
+product HUAWEI E220 0x1003 HSDPA modem
+product HUAWEI E220BIS 0x1004 HSDPA modem
product HUAWEI E1401 0x1401 3G modem
product HUAWEI E1402 0x1402 3G modem
product HUAWEI E1403 0x1403 3G modem
@@ -1802,7 +1802,7 @@ product HUAWEI E1408 0x1408 3G modem
product HUAWEI E1409 0x1409 3G modem
product HUAWEI E140A 0x140a 3G modem
product HUAWEI E140B 0x140b 3G modem
-product HUAWEI E180V 0x140c Huawei Mobile E180V
+product HUAWEI E180V 0x140c E180V
product HUAWEI E140D 0x140d 3G modem
product HUAWEI E140E 0x140e 3G modem
product HUAWEI E140F 0x140f 3G modem
@@ -1856,8 +1856,8 @@ product HUAWEI E143E 0x143e 3G modem
product HUAWEI E143F 0x143f 3G modem
product HUAWEI E1752 0x1446 3G modem
product HUAWEI K3765 0x1465 3G modem
-product HUAWEI E14AC 0x14ac 3G modem
-product HUAWEI K3765_INIT 0x1520 HUAWEI Mobile K3765 Initial
+product HUAWEI E1820 0x14ac E1820 HSPA+ USB Slider
+product HUAWEI K3765_INIT 0x1520 K3765 Initial
/* HUAWEI 3com products */
product HUAWEI3COM WUB320G 0x0009 Aolynk WUB320g
OpenPOWER on IntegriCloud