summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/ata/ata-all.c30
-rw-r--r--sys/dev/ata/ata-all.h9
-rw-r--r--sys/dev/ath/if_ath.c59
-rw-r--r--sys/dev/ath/if_ath_keycache.c6
-rw-r--r--sys/dev/ath/if_ath_rx.c2
-rw-r--r--sys/dev/ath/if_ath_tdma.c2
-rw-r--r--sys/dev/ath/if_ath_tx.c12
-rw-r--r--sys/dev/bxe/ecore_hsi.h6
-rw-r--r--sys/dev/e1000/e1000_80003es2lan.c2
-rw-r--r--sys/dev/e1000/e1000_80003es2lan.h2
-rw-r--r--sys/dev/e1000/e1000_82540.c2
-rw-r--r--sys/dev/e1000/e1000_82541.c2
-rw-r--r--sys/dev/e1000/e1000_82541.h2
-rw-r--r--sys/dev/e1000/e1000_82542.c2
-rw-r--r--sys/dev/e1000/e1000_82543.c2
-rw-r--r--sys/dev/e1000/e1000_82543.h2
-rw-r--r--sys/dev/e1000/e1000_82571.c2
-rw-r--r--sys/dev/e1000/e1000_82571.h2
-rw-r--r--sys/dev/e1000/e1000_82575.c2
-rw-r--r--sys/dev/e1000/e1000_82575.h2
-rw-r--r--sys/dev/e1000/e1000_api.c2
-rw-r--r--sys/dev/e1000/e1000_api.h2
-rw-r--r--sys/dev/e1000/e1000_defines.h2
-rw-r--r--sys/dev/e1000/e1000_hw.h2
-rw-r--r--sys/dev/e1000/e1000_i210.c2
-rw-r--r--sys/dev/e1000/e1000_i210.h2
-rw-r--r--sys/dev/e1000/e1000_ich8lan.c2
-rw-r--r--sys/dev/e1000/e1000_ich8lan.h2
-rw-r--r--sys/dev/e1000/e1000_mac.c2
-rw-r--r--sys/dev/e1000/e1000_mac.h2
-rw-r--r--sys/dev/e1000/e1000_manage.c2
-rw-r--r--sys/dev/e1000/e1000_manage.h2
-rw-r--r--sys/dev/e1000/e1000_mbx.c2
-rw-r--r--sys/dev/e1000/e1000_mbx.h2
-rw-r--r--sys/dev/e1000/e1000_nvm.c2
-rw-r--r--sys/dev/e1000/e1000_nvm.h2
-rw-r--r--sys/dev/e1000/e1000_osdep.c2
-rw-r--r--sys/dev/e1000/e1000_osdep.h2
-rw-r--r--sys/dev/e1000/e1000_phy.c2
-rw-r--r--sys/dev/e1000/e1000_phy.h2
-rw-r--r--sys/dev/e1000/e1000_regs.h2
-rw-r--r--sys/dev/e1000/e1000_vf.c2
-rw-r--r--sys/dev/e1000/e1000_vf.h2
-rw-r--r--sys/dev/e1000/if_em.c151
-rw-r--r--sys/dev/e1000/if_em.h2
-rw-r--r--sys/dev/e1000/if_igb.c2
-rw-r--r--sys/dev/e1000/if_igb.h2
-rw-r--r--sys/dev/e1000/if_lem.c8
-rw-r--r--sys/dev/e1000/if_lem.h5
-rw-r--r--sys/dev/gpio/gpiobus.c18
-rw-r--r--sys/dev/gpio/gpioled.c1
-rw-r--r--sys/dev/md/md.c36
-rw-r--r--sys/dev/random/fortuna.c45
-rw-r--r--sys/dev/random/other_algorithm.c209
-rw-r--r--sys/dev/random/other_algorithm.h62
-rw-r--r--sys/dev/random/random_harvestq.c73
-rw-r--r--sys/dev/random/random_harvestq.h2
-rw-r--r--sys/dev/random/random_infra.c128
-rw-r--r--sys/dev/random/randomdev.c181
-rw-r--r--sys/dev/random/randomdev.h38
-rw-r--r--sys/dev/random/randomdev_none.c72
-rw-r--r--sys/dev/random/unit_test.c32
-rw-r--r--sys/dev/random/yarrow.c63
-rw-r--r--sys/dev/usb/controller/dwc_otg.c492
-rw-r--r--sys/dev/usb/controller/dwc_otg.h5
-rw-r--r--sys/dev/usb/controller/usb_controller.c14
-rw-r--r--sys/dev/usb/usb_bus.h19
-rw-r--r--sys/dev/usb/usb_device.c2
-rw-r--r--sys/dev/usb/usb_hub.c4
-rw-r--r--sys/dev/usb/usb_pf.c6
-rw-r--r--sys/dev/usb/usb_process.h1
-rw-r--r--sys/dev/usb/usb_transfer.c63
-rw-r--r--sys/dev/usb/usbdi.h2
-rw-r--r--sys/dev/vt/hw/efifb/efifb.c26
-rw-r--r--sys/dev/vt/hw/vga/vt_vga.c10
-rw-r--r--sys/dev/vt/hw/vga/vt_vga_reg.h2
-rw-r--r--sys/dev/vt/vt_core.c5
-rw-r--r--sys/dev/xen/netfront/netfront.c60
78 files changed, 1141 insertions, 896 deletions
diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c
index 52db44d..118e38e 100644
--- a/sys/dev/ata/ata-all.c
+++ b/sys/dev/ata/ata-all.c
@@ -64,18 +64,15 @@ static void ata_cam_end_transaction(device_t dev, struct ata_request *request);
static void ata_cam_request_sense(device_t dev, struct ata_request *request);
static int ata_check_ids(device_t dev, union ccb *ccb);
static void ata_conn_event(void *context, int dummy);
-static void ata_init(void);
static void ata_interrupt_locked(void *data);
static int ata_module_event_handler(module_t mod, int what, void *arg);
static void ata_periodic_poll(void *data);
static int ata_str2mode(const char *str);
-static void ata_uninit(void);
/* global vars */
MALLOC_DEFINE(M_ATA, "ata_generic", "ATA driver generic layer");
int (*ata_raid_ioctl_func)(u_long cmd, caddr_t data) = NULL;
devclass_t ata_devclass;
-uma_zone_t ata_request_zone;
int ata_dma_check_80pin = 1;
/* sysctl vars */
@@ -650,12 +647,7 @@ ata_cam_begin_transaction(device_t dev, union ccb *ccb)
struct ata_channel *ch = device_get_softc(dev);
struct ata_request *request;
- if (!(request = ata_alloc_request())) {
- device_printf(dev, "FAILURE - out of memory in start\n");
- ccb->ccb_h.status = CAM_REQ_INVALID;
- xpt_done(ccb);
- return;
- }
+ request = &ch->request;
bzero(request, sizeof(*request));
/* setup request */
@@ -794,7 +786,6 @@ ata_cam_process_sense(device_t dev, struct ata_request *request)
ccb->ccb_h.status |= CAM_AUTOSENSE_FAIL;
}
- ata_free_request(request);
xpt_done(ccb);
/* Do error recovery if needed. */
if (fatalerr)
@@ -865,10 +856,8 @@ ata_cam_end_transaction(device_t dev, struct ata_request *request)
if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR &&
(ccb->ccb_h.flags & CAM_DIS_AUTOSENSE) == 0)
ata_cam_request_sense(dev, request);
- else {
- ata_free_request(request);
+ else
xpt_done(ccb);
- }
/* Do error recovery if needed. */
if (fatalerr)
ata_reinit(dev);
@@ -1148,18 +1137,3 @@ static moduledata_t ata_moduledata = { "ata", ata_module_event_handler, NULL };
DECLARE_MODULE(ata, ata_moduledata, SI_SUB_CONFIGURE, SI_ORDER_SECOND);
MODULE_VERSION(ata, 1);
MODULE_DEPEND(ata, cam, 1, 1, 1);
-
-static void
-ata_init(void)
-{
- ata_request_zone = uma_zcreate("ata_request", sizeof(struct ata_request),
- NULL, NULL, NULL, NULL, 0, 0);
-}
-SYSINIT(ata_register, SI_SUB_DRIVERS, SI_ORDER_SECOND, ata_init, NULL);
-
-static void
-ata_uninit(void)
-{
- uma_zdestroy(ata_request_zone);
-}
-SYSUNINIT(ata_unregister, SI_SUB_DRIVERS, SI_ORDER_SECOND, ata_uninit, NULL);
diff --git a/sys/dev/ata/ata-all.h b/sys/dev/ata/ata-all.h
index 19cb7ef..cf8ed78 100644
--- a/sys/dev/ata/ata-all.h
+++ b/sys/dev/ata/ata-all.h
@@ -450,6 +450,7 @@ struct ata_channel {
struct ata_cam_device curr[16]; /* Current settings */
int requestsense; /* CCB waiting for SENSE. */
struct callout poll_callout; /* Periodic status poll. */
+ struct ata_request request;
};
/* disk bay/enclosure related */
@@ -507,14 +508,6 @@ int ata_sata_getrev(device_t dev, int target);
int ata_request2fis_h2d(struct ata_request *request, u_int8_t *fis);
void ata_pm_identify(device_t dev);
-/* macros for alloc/free of struct ata_request */
-extern uma_zone_t ata_request_zone;
-#define ata_alloc_request() uma_zalloc(ata_request_zone, M_NOWAIT | M_ZERO)
-#define ata_free_request(request) { \
- if (!(request->flags & ATA_R_DANGER2)) \
- uma_zfree(ata_request_zone, request); \
- }
-
MALLOC_DECLARE(M_ATA);
/* misc newbus defines */
diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c
index 2c935a2b..26bf591 100644
--- a/sys/dev/ath/if_ath.c
+++ b/sys/dev/ath/if_ath.c
@@ -1473,7 +1473,7 @@ ath_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
const uint8_t bssid[IEEE80211_ADDR_LEN],
const uint8_t mac0[IEEE80211_ADDR_LEN])
{
- struct ath_softc *sc = ic->ic_ifp->if_softc;
+ struct ath_softc *sc = ic->ic_softc;
struct ath_vap *avp;
struct ieee80211vap *vap;
uint8_t mac[IEEE80211_ADDR_LEN];
@@ -1732,7 +1732,7 @@ ath_vap_delete(struct ieee80211vap *vap)
{
struct ieee80211com *ic = vap->iv_ic;
struct ifnet *ifp = ic->ic_ifp;
- struct ath_softc *sc = ifp->if_softc;
+ struct ath_softc *sc = ic->ic_softc;
struct ath_hal *ah = sc->sc_ah;
struct ath_vap *avp = ATH_VAP(vap);
@@ -2340,7 +2340,7 @@ ath_fatal_proc(void *arg, int pending)
static void
ath_bmiss_vap(struct ieee80211vap *vap)
{
- struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc;
+ struct ath_softc *sc = vap->iv_ic->ic_softc;
/*
* Workaround phantom bmiss interrupts by sanity-checking
@@ -2361,8 +2361,6 @@ ath_bmiss_vap(struct ieee80211vap *vap)
ATH_UNLOCK(sc);
if ((vap->iv_flags_ext & IEEE80211_FEXT_SWBMISS) == 0) {
- struct ifnet *ifp = vap->iv_ic->ic_ifp;
- struct ath_softc *sc = ifp->if_softc;
u_int64_t lastrx = sc->sc_lastrx;
u_int64_t tsf = ath_hal_gettsf64(sc->sc_ah);
/* XXX should take a locked ref to iv_bss */
@@ -2851,8 +2849,8 @@ ath_stop(struct ifnet *ifp)
int
ath_reset(struct ifnet *ifp, ATH_RESET_TYPE reset_type)
{
- struct ath_softc *sc = ifp->if_softc;
struct ieee80211com *ic = ifp->if_l2com;
+ struct ath_softc *sc = ic->ic_softc;
struct ath_hal *ah = sc->sc_ah;
HAL_STATUS status;
int i;
@@ -3045,7 +3043,7 @@ ath_reset_vap(struct ieee80211vap *vap, u_long cmd)
{
struct ieee80211com *ic = vap->iv_ic;
struct ifnet *ifp = ic->ic_ifp;
- struct ath_softc *sc = ifp->if_softc;
+ struct ath_softc *sc = ic->ic_softc;
struct ath_hal *ah = sc->sc_ah;
switch (cmd) {
@@ -3248,7 +3246,7 @@ static int
ath_transmit(struct ifnet *ifp, struct mbuf *m)
{
struct ieee80211com *ic = ifp->if_l2com;
- struct ath_softc *sc = ic->ic_ifp->if_softc;
+ struct ath_softc *sc = ic->ic_softc;
struct ieee80211_node *ni;
struct mbuf *next;
struct ath_buf *bf;
@@ -3538,8 +3536,7 @@ ath_media_change(struct ifnet *ifp)
static void
ath_key_update_begin(struct ieee80211vap *vap)
{
- struct ifnet *ifp = vap->iv_ic->ic_ifp;
- struct ath_softc *sc = ifp->if_softc;
+ struct ath_softc *sc = vap->iv_ic->ic_softc;
DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s:\n", __func__);
taskqueue_block(sc->sc_tq);
@@ -3548,8 +3545,7 @@ ath_key_update_begin(struct ieee80211vap *vap)
static void
ath_key_update_end(struct ieee80211vap *vap)
{
- struct ifnet *ifp = vap->iv_ic->ic_ifp;
- struct ath_softc *sc = ifp->if_softc;
+ struct ath_softc *sc = vap->iv_ic->ic_softc;
DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s:\n", __func__);
taskqueue_unblock(sc->sc_tq);
@@ -4156,7 +4152,7 @@ static struct ieee80211_node *
ath_node_alloc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN])
{
struct ieee80211com *ic = vap->iv_ic;
- struct ath_softc *sc = ic->ic_ifp->if_softc;
+ struct ath_softc *sc = ic->ic_softc;
const size_t space = sizeof(struct ath_node) + sc->sc_rc->arc_space;
struct ath_node *an;
@@ -4183,7 +4179,7 @@ static void
ath_node_cleanup(struct ieee80211_node *ni)
{
struct ieee80211com *ic = ni->ni_ic;
- struct ath_softc *sc = ic->ic_ifp->if_softc;
+ struct ath_softc *sc = ic->ic_softc;
DPRINTF(sc, ATH_DEBUG_NODE, "%s: %6D: an %p\n", __func__,
ni->ni_macaddr, ":", ATH_NODE(ni));
@@ -4198,7 +4194,7 @@ static void
ath_node_free(struct ieee80211_node *ni)
{
struct ieee80211com *ic = ni->ni_ic;
- struct ath_softc *sc = ic->ic_ifp->if_softc;
+ struct ath_softc *sc = ic->ic_softc;
DPRINTF(sc, ATH_DEBUG_NODE, "%s: %6D: an %p\n", __func__,
ni->ni_macaddr, ":", ATH_NODE(ni));
@@ -4210,7 +4206,7 @@ static void
ath_node_getsignal(const struct ieee80211_node *ni, int8_t *rssi, int8_t *noise)
{
struct ieee80211com *ic = ni->ni_ic;
- struct ath_softc *sc = ic->ic_ifp->if_softc;
+ struct ath_softc *sc = ic->ic_softc;
struct ath_hal *ah = sc->sc_ah;
*rssi = ic->ic_node_getrssi(ni);
@@ -4422,7 +4418,7 @@ ath_txq_update(struct ath_softc *sc, int ac)
int
ath_wme_update(struct ieee80211com *ic)
{
- struct ath_softc *sc = ic->ic_ifp->if_softc;
+ struct ath_softc *sc = ic->ic_softc;
return !ath_txq_update(sc, WME_AC_BE) ||
!ath_txq_update(sc, WME_AC_BK) ||
@@ -5797,7 +5793,7 @@ static void
ath_scan_start(struct ieee80211com *ic)
{
struct ifnet *ifp = ic->ic_ifp;
- struct ath_softc *sc = ifp->if_softc;
+ struct ath_softc *sc = ic->ic_softc;
struct ath_hal *ah = sc->sc_ah;
u_int32_t rfilt;
@@ -5821,8 +5817,7 @@ ath_scan_start(struct ieee80211com *ic)
static void
ath_scan_end(struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
- struct ath_softc *sc = ifp->if_softc;
+ struct ath_softc *sc = ic->ic_softc;
struct ath_hal *ah = sc->sc_ah;
u_int32_t rfilt;
@@ -5862,8 +5857,7 @@ ath_scan_end(struct ieee80211com *ic)
static void
ath_update_chw(struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
- struct ath_softc *sc = ifp->if_softc;
+ struct ath_softc *sc = ic->ic_softc;
DPRINTF(sc, ATH_DEBUG_STATE, "%s: called\n", __func__);
ath_set_channel(ic);
@@ -5873,8 +5867,7 @@ ath_update_chw(struct ieee80211com *ic)
static void
ath_set_channel(struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
- struct ath_softc *sc = ifp->if_softc;
+ struct ath_softc *sc = ic->ic_softc;
ATH_LOCK(sc);
ath_power_set_power_state(sc, HAL_PM_AWAKE);
@@ -5916,7 +5909,7 @@ static int
ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
struct ieee80211com *ic = vap->iv_ic;
- struct ath_softc *sc = ic->ic_ifp->if_softc;
+ struct ath_softc *sc = ic->ic_softc;
struct ath_vap *avp = ATH_VAP(vap);
struct ath_hal *ah = sc->sc_ah;
struct ieee80211_node *ni = NULL;
@@ -6252,7 +6245,7 @@ static void
ath_setup_stationkey(struct ieee80211_node *ni)
{
struct ieee80211vap *vap = ni->ni_vap;
- struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc;
+ struct ath_softc *sc = vap->iv_ic->ic_softc;
ieee80211_keyix keyix, rxkeyix;
/* XXX should take a locked ref to vap->iv_bss */
@@ -6285,7 +6278,7 @@ ath_newassoc(struct ieee80211_node *ni, int isnew)
{
struct ath_node *an = ATH_NODE(ni);
struct ieee80211vap *vap = ni->ni_vap;
- struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc;
+ struct ath_softc *sc = vap->iv_ic->ic_softc;
const struct ieee80211_txparam *tp = ni->ni_txparms;
an->an_mcastrix = ath_tx_findrix(sc, tp->mcastrate);
@@ -6337,7 +6330,7 @@ static int
ath_setregdomain(struct ieee80211com *ic, struct ieee80211_regdomain *reg,
int nchans, struct ieee80211_channel chans[])
{
- struct ath_softc *sc = ic->ic_ifp->if_softc;
+ struct ath_softc *sc = ic->ic_softc;
struct ath_hal *ah = sc->sc_ah;
HAL_STATUS status;
@@ -6361,7 +6354,7 @@ static void
ath_getradiocaps(struct ieee80211com *ic,
int maxchans, int *nchans, struct ieee80211_channel chans[])
{
- struct ath_softc *sc = ic->ic_ifp->if_softc;
+ struct ath_softc *sc = ic->ic_softc;
struct ath_hal *ah = sc->sc_ah;
DPRINTF(sc, ATH_DEBUG_REGDOMAIN, "%s: use rd %u cc %d\n",
@@ -6693,8 +6686,8 @@ ath_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
#define IS_RUNNING(ifp) \
((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING))
- struct ath_softc *sc = ifp->if_softc;
struct ieee80211com *ic = ifp->if_l2com;
+ struct ath_softc *sc = ic->ic_softc;
struct ifreq *ifr = (struct ifreq *)data;
const HAL_RATE_TABLE *rt;
int error = 0;
@@ -6864,7 +6857,7 @@ ath_node_powersave(struct ieee80211_node *ni, int enable)
#ifdef ATH_SW_PSQ
struct ath_node *an = ATH_NODE(ni);
struct ieee80211com *ic = ni->ni_ic;
- struct ath_softc *sc = ic->ic_ifp->if_softc;
+ struct ath_softc *sc = ic->ic_softc;
struct ath_vap *avp = ATH_VAP(ni->ni_vap);
/* XXX and no TXQ locks should be held here */
@@ -6931,7 +6924,7 @@ ath_node_set_tim(struct ieee80211_node *ni, int enable)
{
#ifdef ATH_SW_PSQ
struct ieee80211com *ic = ni->ni_ic;
- struct ath_softc *sc = ic->ic_ifp->if_softc;
+ struct ath_softc *sc = ic->ic_softc;
struct ath_node *an = ATH_NODE(ni);
struct ath_vap *avp = ATH_VAP(ni->ni_vap);
int changed = 0;
@@ -7136,7 +7129,7 @@ ath_node_recv_pspoll(struct ieee80211_node *ni, struct mbuf *m)
struct ath_node *an;
struct ath_vap *avp;
struct ieee80211com *ic = ni->ni_ic;
- struct ath_softc *sc = ic->ic_ifp->if_softc;
+ struct ath_softc *sc = ic->ic_softc;
int tid;
/* Just paranoia */
diff --git a/sys/dev/ath/if_ath_keycache.c b/sys/dev/ath/if_ath_keycache.c
index fe99f10..b8a77e8 100644
--- a/sys/dev/ath/if_ath_keycache.c
+++ b/sys/dev/ath/if_ath_keycache.c
@@ -425,7 +425,7 @@ int
ath_key_alloc(struct ieee80211vap *vap, struct ieee80211_key *k,
ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix)
{
- struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc;
+ struct ath_softc *sc = vap->iv_ic->ic_softc;
/*
* Group key allocation must be handled specially for
@@ -493,7 +493,7 @@ ath_key_alloc(struct ieee80211vap *vap, struct ieee80211_key *k,
int
ath_key_delete(struct ieee80211vap *vap, const struct ieee80211_key *k)
{
- struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc;
+ struct ath_softc *sc = vap->iv_ic->ic_softc;
struct ath_hal *ah = sc->sc_ah;
const struct ieee80211_cipher *cip = k->wk_cipher;
u_int keyix = k->wk_keyix;
@@ -538,7 +538,7 @@ int
ath_key_set(struct ieee80211vap *vap, const struct ieee80211_key *k,
const u_int8_t mac[IEEE80211_ADDR_LEN])
{
- struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc;
+ struct ath_softc *sc = vap->iv_ic->ic_softc;
return ath_keyset(sc, vap, k, vap->iv_bss);
}
diff --git a/sys/dev/ath/if_ath_rx.c b/sys/dev/ath/if_ath_rx.c
index 2779b7a..e391dd7 100644
--- a/sys/dev/ath/if_ath_rx.c
+++ b/sys/dev/ath/if_ath_rx.c
@@ -330,7 +330,7 @@ ath_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m,
int subtype, const struct ieee80211_rx_stats *rxs, int rssi, int nf)
{
struct ieee80211vap *vap = ni->ni_vap;
- struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc;
+ struct ath_softc *sc = vap->iv_ic->ic_softc;
uint64_t tsf_beacon_old, tsf_beacon;
uint64_t nexttbtt;
int64_t tsf_delta;
diff --git a/sys/dev/ath/if_ath_tdma.c b/sys/dev/ath/if_ath_tdma.c
index fd23db1..d4c9ccd 100644
--- a/sys/dev/ath/if_ath_tdma.c
+++ b/sys/dev/ath/if_ath_tdma.c
@@ -359,7 +359,7 @@ ath_tdma_update(struct ieee80211_node *ni,
#define TU_TO_TSF(_tu) (((u_int64_t)(_tu)) << 10)
struct ieee80211vap *vap = ni->ni_vap;
struct ieee80211com *ic = ni->ni_ic;
- struct ath_softc *sc = ic->ic_ifp->if_softc;
+ struct ath_softc *sc = ic->ic_softc;
struct ath_hal *ah = sc->sc_ah;
const HAL_RATE_TABLE *rt = sc->sc_currates;
u_int64_t tsf, rstamp, nextslot, nexttbtt, nexttbtt_full;
diff --git a/sys/dev/ath/if_ath_tx.c b/sys/dev/ath/if_ath_tx.c
index c15b158..916d4cb 100644
--- a/sys/dev/ath/if_ath_tx.c
+++ b/sys/dev/ath/if_ath_tx.c
@@ -2341,7 +2341,7 @@ ath_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
{
struct ieee80211com *ic = ni->ni_ic;
struct ifnet *ifp = ic->ic_ifp;
- struct ath_softc *sc = ifp->if_softc;
+ struct ath_softc *sc = ic->ic_softc;
struct ath_buf *bf;
struct ieee80211_frame *wh = mtod(m, struct ieee80211_frame *);
int error = 0;
@@ -5731,7 +5731,7 @@ int
ath_addba_request(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap,
int dialogtoken, int baparamset, int batimeout)
{
- struct ath_softc *sc = ni->ni_ic->ic_ifp->if_softc;
+ struct ath_softc *sc = ni->ni_ic->ic_softc;
int tid = tap->txa_tid;
struct ath_node *an = ATH_NODE(ni);
struct ath_tid *atid = &an->an_tid[tid];
@@ -5809,7 +5809,7 @@ int
ath_addba_response(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap,
int status, int code, int batimeout)
{
- struct ath_softc *sc = ni->ni_ic->ic_ifp->if_softc;
+ struct ath_softc *sc = ni->ni_ic->ic_softc;
int tid = tap->txa_tid;
struct ath_node *an = ATH_NODE(ni);
struct ath_tid *atid = &an->an_tid[tid];
@@ -5856,7 +5856,7 @@ ath_addba_response(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap,
void
ath_addba_stop(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap)
{
- struct ath_softc *sc = ni->ni_ic->ic_ifp->if_softc;
+ struct ath_softc *sc = ni->ni_ic->ic_softc;
int tid = tap->txa_tid;
struct ath_node *an = ATH_NODE(ni);
struct ath_tid *atid = &an->an_tid[tid];
@@ -5991,7 +5991,7 @@ void
ath_bar_response(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap,
int status)
{
- struct ath_softc *sc = ni->ni_ic->ic_ifp->if_softc;
+ struct ath_softc *sc = ni->ni_ic->ic_softc;
int tid = tap->txa_tid;
struct ath_node *an = ATH_NODE(ni);
struct ath_tid *atid = &an->an_tid[tid];
@@ -6064,7 +6064,7 @@ void
ath_addba_response_timeout(struct ieee80211_node *ni,
struct ieee80211_tx_ampdu *tap)
{
- struct ath_softc *sc = ni->ni_ic->ic_ifp->if_softc;
+ struct ath_softc *sc = ni->ni_ic->ic_softc;
int tid = tap->txa_tid;
struct ath_node *an = ATH_NODE(ni);
struct ath_tid *atid = &an->an_tid[tid];
diff --git a/sys/dev/bxe/ecore_hsi.h b/sys/dev/bxe/ecore_hsi.h
index 005bb2e..f78f4ea 100644
--- a/sys/dev/bxe/ecore_hsi.h
+++ b/sys/dev/bxe/ecore_hsi.h
@@ -2536,9 +2536,9 @@ struct shmem2_region {
#define SHMEM_EEE_SUPPORTED_MASK 0x000f0000
#define SHMEM_EEE_SUPPORTED_SHIFT 16
#define SHMEM_EEE_ADV_STATUS_MASK 0x00f00000
- #define SHMEM_EEE_100M_ADV (1<<0)
- #define SHMEM_EEE_1G_ADV (1<<1)
- #define SHMEM_EEE_10G_ADV (1<<2)
+ #define SHMEM_EEE_100M_ADV (1U<<0)
+ #define SHMEM_EEE_1G_ADV (1U<<1)
+ #define SHMEM_EEE_10G_ADV (1U<<2)
#define SHMEM_EEE_ADV_STATUS_SHIFT 20
#define SHMEM_EEE_LP_ADV_STATUS_MASK 0x0f000000
#define SHMEM_EEE_LP_ADV_STATUS_SHIFT 24
diff --git a/sys/dev/e1000/e1000_80003es2lan.c b/sys/dev/e1000/e1000_80003es2lan.c
index 076e02b..b948bb4 100644
--- a/sys/dev/e1000/e1000_80003es2lan.c
+++ b/sys/dev/e1000/e1000_80003es2lan.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2013, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/sys/dev/e1000/e1000_80003es2lan.h b/sys/dev/e1000/e1000_80003es2lan.h
index 3807e46..89b1551 100644
--- a/sys/dev/e1000/e1000_80003es2lan.h
+++ b/sys/dev/e1000/e1000_80003es2lan.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2013, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/sys/dev/e1000/e1000_82540.c b/sys/dev/e1000/e1000_82540.c
index 141b92e..68f92c6 100644
--- a/sys/dev/e1000/e1000_82540.c
+++ b/sys/dev/e1000/e1000_82540.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2011, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/sys/dev/e1000/e1000_82541.c b/sys/dev/e1000/e1000_82541.c
index 781aa93..69fcee4 100644
--- a/sys/dev/e1000/e1000_82541.c
+++ b/sys/dev/e1000/e1000_82541.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2011, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/sys/dev/e1000/e1000_82541.h b/sys/dev/e1000/e1000_82541.h
index 3b6b961..1eebfad 100644
--- a/sys/dev/e1000/e1000_82541.h
+++ b/sys/dev/e1000/e1000_82541.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2008, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/sys/dev/e1000/e1000_82542.c b/sys/dev/e1000/e1000_82542.c
index 19d5402..a6b3616 100644
--- a/sys/dev/e1000/e1000_82542.c
+++ b/sys/dev/e1000/e1000_82542.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2014, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/sys/dev/e1000/e1000_82543.c b/sys/dev/e1000/e1000_82543.c
index 1c01658..3350f17 100644
--- a/sys/dev/e1000/e1000_82543.c
+++ b/sys/dev/e1000/e1000_82543.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2011, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/sys/dev/e1000/e1000_82543.h b/sys/dev/e1000/e1000_82543.h
index 60e5c15..0fa813b 100644
--- a/sys/dev/e1000/e1000_82543.h
+++ b/sys/dev/e1000/e1000_82543.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2008, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/sys/dev/e1000/e1000_82571.c b/sys/dev/e1000/e1000_82571.c
index e209d43..a64ef56 100644
--- a/sys/dev/e1000/e1000_82571.c
+++ b/sys/dev/e1000/e1000_82571.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2014, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/sys/dev/e1000/e1000_82571.h b/sys/dev/e1000/e1000_82571.h
index c76f16f..cda87a2 100644
--- a/sys/dev/e1000/e1000_82571.h
+++ b/sys/dev/e1000/e1000_82571.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2010, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/sys/dev/e1000/e1000_82575.c b/sys/dev/e1000/e1000_82575.c
index d79db67..8981ae3 100644
--- a/sys/dev/e1000/e1000_82575.c
+++ b/sys/dev/e1000/e1000_82575.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2014, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/sys/dev/e1000/e1000_82575.h b/sys/dev/e1000/e1000_82575.h
index 6569b98..503fdce 100644
--- a/sys/dev/e1000/e1000_82575.h
+++ b/sys/dev/e1000/e1000_82575.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2014, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/sys/dev/e1000/e1000_api.c b/sys/dev/e1000/e1000_api.c
index 374ffa6..5db22db 100644
--- a/sys/dev/e1000/e1000_api.c
+++ b/sys/dev/e1000/e1000_api.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2014, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/sys/dev/e1000/e1000_api.h b/sys/dev/e1000/e1000_api.h
index a2ffa16..e87acc8 100644
--- a/sys/dev/e1000/e1000_api.h
+++ b/sys/dev/e1000/e1000_api.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2014, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/sys/dev/e1000/e1000_defines.h b/sys/dev/e1000/e1000_defines.h
index 5deada2..9472ca4 100644
--- a/sys/dev/e1000/e1000_defines.h
+++ b/sys/dev/e1000/e1000_defines.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2014, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/sys/dev/e1000/e1000_hw.h b/sys/dev/e1000/e1000_hw.h
index faf64a3..3ec921e 100644
--- a/sys/dev/e1000/e1000_hw.h
+++ b/sys/dev/e1000/e1000_hw.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2014, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/sys/dev/e1000/e1000_i210.c b/sys/dev/e1000/e1000_i210.c
index f12c13f..563f11a 100644
--- a/sys/dev/e1000/e1000_i210.c
+++ b/sys/dev/e1000/e1000_i210.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2014, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/sys/dev/e1000/e1000_i210.h b/sys/dev/e1000/e1000_i210.h
index 2a20ca1..f940915 100644
--- a/sys/dev/e1000/e1000_i210.h
+++ b/sys/dev/e1000/e1000_i210.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2014, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/sys/dev/e1000/e1000_ich8lan.c b/sys/dev/e1000/e1000_ich8lan.c
index 204c39c..23e7b95 100644
--- a/sys/dev/e1000/e1000_ich8lan.c
+++ b/sys/dev/e1000/e1000_ich8lan.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2014, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/sys/dev/e1000/e1000_ich8lan.h b/sys/dev/e1000/e1000_ich8lan.h
index f045ebd..9cb79c0 100644
--- a/sys/dev/e1000/e1000_ich8lan.h
+++ b/sys/dev/e1000/e1000_ich8lan.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2014, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/sys/dev/e1000/e1000_mac.c b/sys/dev/e1000/e1000_mac.c
index b888b34..1c86307 100644
--- a/sys/dev/e1000/e1000_mac.c
+++ b/sys/dev/e1000/e1000_mac.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2014, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/sys/dev/e1000/e1000_mac.h b/sys/dev/e1000/e1000_mac.h
index 2c1bfe3..1daed9b 100644
--- a/sys/dev/e1000/e1000_mac.h
+++ b/sys/dev/e1000/e1000_mac.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2014, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/sys/dev/e1000/e1000_manage.c b/sys/dev/e1000/e1000_manage.c
index 8087e65..f319c8b 100644
--- a/sys/dev/e1000/e1000_manage.c
+++ b/sys/dev/e1000/e1000_manage.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2014, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/sys/dev/e1000/e1000_manage.h b/sys/dev/e1000/e1000_manage.h
index 51f17671..303e99e 100644
--- a/sys/dev/e1000/e1000_manage.h
+++ b/sys/dev/e1000/e1000_manage.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2012, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/sys/dev/e1000/e1000_mbx.c b/sys/dev/e1000/e1000_mbx.c
index 55477b2..d9fb9ac 100644
--- a/sys/dev/e1000/e1000_mbx.c
+++ b/sys/dev/e1000/e1000_mbx.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2014, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/sys/dev/e1000/e1000_mbx.h b/sys/dev/e1000/e1000_mbx.h
index d2aea5c4..fadd849 100644
--- a/sys/dev/e1000/e1000_mbx.h
+++ b/sys/dev/e1000/e1000_mbx.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2014, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/sys/dev/e1000/e1000_nvm.c b/sys/dev/e1000/e1000_nvm.c
index f702f71..0a1a18d 100644
--- a/sys/dev/e1000/e1000_nvm.c
+++ b/sys/dev/e1000/e1000_nvm.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2014, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/sys/dev/e1000/e1000_nvm.h b/sys/dev/e1000/e1000_nvm.h
index 34077b2..31f2180 100644
--- a/sys/dev/e1000/e1000_nvm.h
+++ b/sys/dev/e1000/e1000_nvm.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2013, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/sys/dev/e1000/e1000_osdep.c b/sys/dev/e1000/e1000_osdep.c
index 75a7b79..2987cda 100644
--- a/sys/dev/e1000/e1000_osdep.c
+++ b/sys/dev/e1000/e1000_osdep.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2010, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/sys/dev/e1000/e1000_osdep.h b/sys/dev/e1000/e1000_osdep.h
index 1324110..fc46f48 100644
--- a/sys/dev/e1000/e1000_osdep.h
+++ b/sys/dev/e1000/e1000_osdep.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2014, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/sys/dev/e1000/e1000_phy.c b/sys/dev/e1000/e1000_phy.c
index f27889c..adb6732 100644
--- a/sys/dev/e1000/e1000_phy.c
+++ b/sys/dev/e1000/e1000_phy.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2014, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/sys/dev/e1000/e1000_phy.h b/sys/dev/e1000/e1000_phy.h
index 0e5b2e6..d3d563f 100644
--- a/sys/dev/e1000/e1000_phy.h
+++ b/sys/dev/e1000/e1000_phy.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2014, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/sys/dev/e1000/e1000_regs.h b/sys/dev/e1000/e1000_regs.h
index 952a7dc..da93d75 100644
--- a/sys/dev/e1000/e1000_regs.h
+++ b/sys/dev/e1000/e1000_regs.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2014, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/sys/dev/e1000/e1000_vf.c b/sys/dev/e1000/e1000_vf.c
index 2cabac9..4af985b 100644
--- a/sys/dev/e1000/e1000_vf.c
+++ b/sys/dev/e1000/e1000_vf.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2014, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/sys/dev/e1000/e1000_vf.h b/sys/dev/e1000/e1000_vf.h
index 2a780741..e6f834e 100644
--- a/sys/dev/e1000/e1000_vf.h
+++ b/sys/dev/e1000/e1000_vf.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2014, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c
index 830325b..e36a3d8 100644
--- a/sys/dev/e1000/if_em.c
+++ b/sys/dev/e1000/if_em.c
@@ -364,8 +364,14 @@ MODULE_DEPEND(em, netmap, 1, 1, 1);
#define CSUM_TSO 0
#endif
+#define TSO_WORKAROUND 4
+
static SYSCTL_NODE(_hw, OID_AUTO, em, CTLFLAG_RD, 0, "EM driver parameters");
+static int em_disable_crc_stripping = 0;
+SYSCTL_INT(_hw_em, OID_AUTO, disable_crc_stripping, CTLFLAG_RDTUN,
+ &em_disable_crc_stripping, 0, "Disable CRC Stripping");
+
static int em_tx_int_delay_dflt = EM_TICKS_TO_USECS(EM_TIDV);
static int em_rx_int_delay_dflt = EM_TICKS_TO_USECS(EM_RDTR);
SYSCTL_INT(_hw_em, OID_AUTO, tx_int_delay, CTLFLAG_RDTUN, &em_tx_int_delay_dflt,
@@ -1872,13 +1878,15 @@ em_xmit(struct tx_ring *txr, struct mbuf **m_headp)
struct ether_header *eh;
struct ip *ip = NULL;
struct tcphdr *tp = NULL;
- u32 txd_upper = 0, txd_lower = 0, txd_used = 0;
+ u32 txd_upper = 0, txd_lower = 0;
int ip_off, poff;
int nsegs, i, j, first, last = 0;
- int error, do_tso, tso_desc = 0, remap = 1;
+ int error;
+ bool do_tso, tso_desc, remap = TRUE;
m_head = *m_headp;
- do_tso = ((m_head->m_pkthdr.csum_flags & CSUM_TSO) != 0);
+ do_tso = (m_head->m_pkthdr.csum_flags & CSUM_TSO);
+ tso_desc = FALSE;
ip_off = poff = 0;
/*
@@ -1914,74 +1922,82 @@ em_xmit(struct tx_ring *txr, struct mbuf **m_headp)
* for IPv6 yet.
*/
ip_off = sizeof(struct ether_header);
- m_head = m_pullup(m_head, ip_off);
- if (m_head == NULL) {
- *m_headp = NULL;
- return (ENOBUFS);
+ if (m_head->m_len < ip_off) {
+ m_head = m_pullup(m_head, ip_off);
+ if (m_head == NULL) {
+ *m_headp = NULL;
+ return (ENOBUFS);
+ }
}
eh = mtod(m_head, struct ether_header *);
if (eh->ether_type == htons(ETHERTYPE_VLAN)) {
ip_off = sizeof(struct ether_vlan_header);
- m_head = m_pullup(m_head, ip_off);
+ if (m_head->m_len < ip_off) {
+ m_head = m_pullup(m_head, ip_off);
+ if (m_head == NULL) {
+ *m_headp = NULL;
+ return (ENOBUFS);
+ }
+ }
+ }
+ if (m_head->m_len < ip_off + sizeof(struct ip)) {
+ m_head = m_pullup(m_head, ip_off + sizeof(struct ip));
if (m_head == NULL) {
*m_headp = NULL;
return (ENOBUFS);
}
}
- m_head = m_pullup(m_head, ip_off + sizeof(struct ip));
- if (m_head == NULL) {
- *m_headp = NULL;
- return (ENOBUFS);
- }
ip = (struct ip *)(mtod(m_head, char *) + ip_off);
poff = ip_off + (ip->ip_hl << 2);
- if (do_tso) {
- m_head = m_pullup(m_head, poff + sizeof(struct tcphdr));
- if (m_head == NULL) {
- *m_headp = NULL;
- return (ENOBUFS);
+
+ if (do_tso || (m_head->m_pkthdr.csum_flags & CSUM_TCP)) {
+ if (m_head->m_len < poff + sizeof(struct tcphdr)) {
+ m_head = m_pullup(m_head, poff +
+ sizeof(struct tcphdr));
+ if (m_head == NULL) {
+ *m_headp = NULL;
+ return (ENOBUFS);
+ }
}
tp = (struct tcphdr *)(mtod(m_head, char *) + poff);
/*
* TSO workaround:
* pull 4 more bytes of data into it.
*/
- m_head = m_pullup(m_head, poff + (tp->th_off << 2) + 4);
- if (m_head == NULL) {
- *m_headp = NULL;
- return (ENOBUFS);
+ if (m_head->m_len < poff + (tp->th_off << 2)) {
+ m_head = m_pullup(m_head, poff +
+ (tp->th_off << 2) +
+ TSO_WORKAROUND);
+ if (m_head == NULL) {
+ *m_headp = NULL;
+ return (ENOBUFS);
+ }
}
ip = (struct ip *)(mtod(m_head, char *) + ip_off);
- ip->ip_len = 0;
- ip->ip_sum = 0;
- /*
- * The pseudo TCP checksum does not include TCP payload
- * length so driver should recompute the checksum here
- * what hardware expect to see. This is adherence of
- * Microsoft's Large Send specification.
- */
tp = (struct tcphdr *)(mtod(m_head, char *) + poff);
- tp->th_sum = in_pseudo(ip->ip_src.s_addr,
- ip->ip_dst.s_addr, htons(IPPROTO_TCP));
- } else if (m_head->m_pkthdr.csum_flags & CSUM_TCP) {
- m_head = m_pullup(m_head, poff + sizeof(struct tcphdr));
- if (m_head == NULL) {
- *m_headp = NULL;
- return (ENOBUFS);
+ if (do_tso) {
+ ip->ip_len = htons(m_head->m_pkthdr.tso_segsz +
+ (ip->ip_hl << 2) +
+ (tp->th_off << 2));
+ ip->ip_sum = 0;
+ /*
+ * The pseudo TCP checksum does not include TCP
+ * payload length so driver should recompute
+ * the checksum here what hardware expect to
+ * see. This is adherence of Microsoft's Large
+ * Send specification.
+ */
+ tp->th_sum = in_pseudo(ip->ip_src.s_addr,
+ ip->ip_dst.s_addr, htons(IPPROTO_TCP));
}
- tp = (struct tcphdr *)(mtod(m_head, char *) + poff);
- m_head = m_pullup(m_head, poff + (tp->th_off << 2));
- if (m_head == NULL) {
- *m_headp = NULL;
- return (ENOBUFS);
- }
- ip = (struct ip *)(mtod(m_head, char *) + ip_off);
- tp = (struct tcphdr *)(mtod(m_head, char *) + poff);
} else if (m_head->m_pkthdr.csum_flags & CSUM_UDP) {
- m_head = m_pullup(m_head, poff + sizeof(struct udphdr));
- if (m_head == NULL) {
- *m_headp = NULL;
- return (ENOBUFS);
+ if (m_head->m_len < poff + sizeof(struct udphdr)) {
+ m_head = m_pullup(m_head, poff +
+ sizeof(struct udphdr));
+ if (m_head == NULL) {
+ *m_headp = NULL;
+ return (ENOBUFS);
+ }
}
ip = (struct ip *)(mtod(m_head, char *) + ip_off);
}
@@ -2027,7 +2043,7 @@ retry:
*m_headp = m;
/* Try it again, but only once */
- remap = 0;
+ remap = FALSE;
goto retry;
} else if (error != 0) {
adapter->no_tx_dma_setup++;
@@ -2042,13 +2058,13 @@ retry:
* it follows a TSO burst, then we need to add a
* sentinel descriptor to prevent premature writeback.
*/
- if ((do_tso == 0) && (txr->tx_tso == TRUE)) {
+ if ((!do_tso) && (txr->tx_tso == TRUE)) {
if (nsegs == 1)
tso_desc = TRUE;
txr->tx_tso = FALSE;
}
- if (nsegs > (txr->tx_avail - 2)) {
+ if (nsegs > (txr->tx_avail - EM_MAX_SCATTER)) {
txr->no_desc_avail++;
bus_dmamap_unload(txr->txtag, map);
return (ENOBUFS);
@@ -2088,23 +2104,23 @@ retry:
** If this is the last descriptor, we want to
** split it so we have a small final sentinel
*/
- if (tso_desc && (j == (nsegs -1)) && (seg_len > 8)) {
- seg_len -= 4;
+ if (tso_desc && (j == (nsegs - 1)) && (seg_len > 8)) {
+ seg_len -= TSO_WORKAROUND;
ctxd->buffer_addr = htole64(seg_addr);
ctxd->lower.data = htole32(
- adapter->txd_cmd | txd_lower | seg_len);
- ctxd->upper.data =
- htole32(txd_upper);
+ adapter->txd_cmd | txd_lower | seg_len);
+ ctxd->upper.data = htole32(txd_upper);
if (++i == adapter->num_tx_desc)
i = 0;
+
/* Now make the sentinel */
- ++txd_used; /* using an extra txd */
+ txr->tx_avail--;
ctxd = &txr->tx_base[i];
tx_buffer = &txr->tx_buffers[i];
ctxd->buffer_addr =
htole64(seg_addr + seg_len);
ctxd->lower.data = htole32(
- adapter->txd_cmd | txd_lower | 4);
+ adapter->txd_cmd | txd_lower | TSO_WORKAROUND);
ctxd->upper.data =
htole32(txd_upper);
last = i;
@@ -2114,8 +2130,7 @@ retry:
ctxd->buffer_addr = htole64(seg_addr);
ctxd->lower.data = htole32(
adapter->txd_cmd | txd_lower | seg_len);
- ctxd->upper.data =
- htole32(txd_upper);
+ ctxd->upper.data = htole32(txd_upper);
last = i;
if (++i == adapter->num_tx_desc)
i = 0;
@@ -2126,8 +2141,6 @@ retry:
txr->next_avail_desc = i;
txr->tx_avail -= nsegs;
- if (tso_desc) /* TSO used an extra for sentinel */
- txr->tx_avail -= txd_used;
tx_buffer->m_head = m_head;
/*
@@ -3030,6 +3043,11 @@ em_setup_interface(device_t dev, struct adapter *adapter)
if_setflags(ifp, IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST);
if_setioctlfn(ifp, em_ioctl);
if_setgetcounterfn(ifp, em_get_counter);
+ /* TSO parameters */
+ ifp->if_hw_tsomax = EM_TSO_SIZE;
+ ifp->if_hw_tsomaxsegcount = EM_MAX_SCATTER;
+ ifp->if_hw_tsomaxsegsize = EM_TSO_SEG_SIZE;
+
#ifdef EM_MULTIQUEUE
/* Multiqueue stack interface */
if_settransmitfn(ifp, em_mq_start);
@@ -4514,7 +4532,8 @@ em_initialize_receive_unit(struct adapter *adapter)
(hw->mac.mc_filter_type << E1000_RCTL_MO_SHIFT);
/* Strip the CRC */
- rctl |= E1000_RCTL_SECRC;
+ if (!em_disable_crc_stripping)
+ rctl |= E1000_RCTL_SECRC;
/* Make sure VLAN Filters are off */
rctl &= ~E1000_RCTL_VFE;
@@ -4888,8 +4907,8 @@ em_enable_intr(struct adapter *adapter)
u32 ims_mask = IMS_ENABLE_MASK;
if (hw->mac.type == e1000_82574) {
- E1000_WRITE_REG(hw, EM_EIAC, EM_MSIX_MASK);
- ims_mask |= EM_MSIX_MASK;
+ E1000_WRITE_REG(hw, EM_EIAC, adapter->ims);
+ ims_mask |= adapter->ims;
}
E1000_WRITE_REG(hw, E1000_IMS, ims_mask);
}
diff --git a/sys/dev/e1000/if_em.h b/sys/dev/e1000/if_em.h
index be18a6c..8725de3 100644
--- a/sys/dev/e1000/if_em.h
+++ b/sys/dev/e1000/if_em.h
@@ -266,7 +266,7 @@
#define HW_DEBUGOUT1(S, A) if (DEBUG_HW) printf(S "\n", A)
#define HW_DEBUGOUT2(S, A, B) if (DEBUG_HW) printf(S "\n", A, B)
-#define EM_MAX_SCATTER 32
+#define EM_MAX_SCATTER 64
#define EM_VFTA_SIZE 128
#define EM_TSO_SIZE (65535 + sizeof(struct ether_vlan_header))
#define EM_TSO_SEG_SIZE 4096 /* Max dma segment size */
diff --git a/sys/dev/e1000/if_igb.c b/sys/dev/e1000/if_igb.c
index 9eacc78..a3ea8d0 100644
--- a/sys/dev/e1000/if_igb.c
+++ b/sys/dev/e1000/if_igb.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2013, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/sys/dev/e1000/if_igb.h b/sys/dev/e1000/if_igb.h
index f2d0926..a4222e3 100644
--- a/sys/dev/e1000/if_igb.h
+++ b/sys/dev/e1000/if_igb.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2013, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/sys/dev/e1000/if_lem.c b/sys/dev/e1000/if_lem.c
index f34010e..7476be5 100644
--- a/sys/dev/e1000/if_lem.c
+++ b/sys/dev/e1000/if_lem.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2012, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -97,7 +97,7 @@
/*********************************************************************
* Legacy Em Driver version:
*********************************************************************/
-char lem_driver_version[] = "1.0.6";
+char lem_driver_version[] = "1.1.0";
/*********************************************************************
* PCI Device ID Table
@@ -2913,10 +2913,6 @@ lem_free_transmit_structures(struct adapter *adapter)
bus_dma_tag_destroy(adapter->txtag);
adapter->txtag = NULL;
}
-#if __FreeBSD_version >= 800000
- if (adapter->br != NULL)
- buf_ring_free(adapter->br, M_DEVBUF);
-#endif
}
/*********************************************************************
diff --git a/sys/dev/e1000/if_lem.h b/sys/dev/e1000/if_lem.h
index 41447d1..4c43bdd 100644
--- a/sys/dev/e1000/if_lem.h
+++ b/sys/dev/e1000/if_lem.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2011, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -296,9 +296,6 @@ struct em_int_delay_info {
/* Our adapter structure */
struct adapter {
if_t ifp;
-#if __FreeBSD_version >= 800000
- struct buf_ring *br;
-#endif
struct e1000_hw hw;
/* FreeBSD operating-system-specific structures. */
diff --git a/sys/dev/gpio/gpiobus.c b/sys/dev/gpio/gpiobus.c
index e741d28..6cafdaf 100644
--- a/sys/dev/gpio/gpiobus.c
+++ b/sys/dev/gpio/gpiobus.c
@@ -155,12 +155,16 @@ gpiobus_attach_bus(device_t dev)
int
gpiobus_detach_bus(device_t dev)
{
+ int err;
#ifdef FDT
ofw_gpiobus_unregister_provider(dev);
#endif
+ err = bus_generic_detach(dev);
+ if (err != 0)
+ return (err);
- return (bus_generic_detach(dev));
+ return (device_delete_children(dev));
}
int
@@ -338,11 +342,14 @@ gpiobus_detach(device_t dev)
if ((err = device_get_children(dev, &devlist, &ndevs)) != 0)
return (err);
for (i = 0; i < ndevs; i++) {
- device_delete_child(dev, devlist[i]);
devi = GPIOBUS_IVAR(devlist[i]);
gpiobus_free_ivars(devi);
+ resource_list_free(&devi->rl);
+ free(devi, M_DEVBUF);
+ device_delete_child(dev, devlist[i]);
}
free(devlist, M_TEMP);
+ rman_fini(&sc->sc_intr_rman);
if (sc->sc_pins) {
for (i = 0; i < sc->sc_npins; i++) {
if (sc->sc_pins[i].name != NULL)
@@ -442,7 +449,7 @@ gpiobus_add_child(device_t dev, u_int order, const char *name, int unit)
devi = malloc(sizeof(struct gpiobus_ivar), M_DEVBUF, M_NOWAIT | M_ZERO);
if (devi == NULL) {
device_delete_child(dev, child);
- return (0);
+ return (NULL);
}
resource_list_init(&devi->rl);
device_set_ivars(child, devi);
@@ -461,8 +468,11 @@ gpiobus_hinted_child(device_t bus, const char *dname, int dunit)
child = BUS_ADD_CHILD(bus, 0, dname, dunit);
devi = GPIOBUS_IVAR(child);
resource_int_value(dname, dunit, "pins", &pins);
- if (gpiobus_parse_pins(sc, child, pins))
+ if (gpiobus_parse_pins(sc, child, pins)) {
+ resource_list_free(&devi->rl);
+ free(devi, M_DEVBUF);
device_delete_child(bus, child);
+ }
if (resource_int_value(dname, dunit, "irq", &irq) == 0) {
if (bus_set_resource(child, SYS_RES_IRQ, 0, irq, 1) != 0)
device_printf(bus,
diff --git a/sys/dev/gpio/gpioled.c b/sys/dev/gpio/gpioled.c
index 01710c2..e699128 100644
--- a/sys/dev/gpio/gpioled.c
+++ b/sys/dev/gpio/gpioled.c
@@ -255,3 +255,4 @@ static driver_t gpioled_driver = {
};
DRIVER_MODULE(gpioled, gpiobus, gpioled_driver, gpioled_devclass, 0, 0);
+MODULE_DEPEND(gpioled, gpiobus, 1, 1, 1);
diff --git a/sys/dev/md/md.c b/sys/dev/md/md.c
index a82d81d..c19f7fe 100644
--- a/sys/dev/md/md.c
+++ b/sys/dev/md/md.c
@@ -89,6 +89,7 @@
#include <sys/vnode.h>
#include <geom/geom.h>
+#include <geom/geom_int.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
@@ -121,9 +122,12 @@ SYSCTL_INT(_vm, OID_AUTO, md_malloc_wait, CTLFLAG_RW, &md_malloc_wait, 0,
#define MD_ROOT_FSTYPE "ufs"
#endif
-#if defined(MD_ROOT) && defined(MD_ROOT_SIZE)
+#if defined(MD_ROOT)
/*
* Preloaded image gets put here.
+ */
+#if defined(MD_ROOT_SIZE)
+/*
* Applications that patch the object with the image can determine
* the size looking at the start and end markers (strings),
* so we want them contiguous.
@@ -135,6 +139,14 @@ static struct {
.start = "MFS Filesystem goes here",
.end = "MFS Filesystem had better STOP here",
};
+const int mfs_root_size = sizeof(mfs_root.start);
+#else
+extern volatile u_char __weak_symbol mfs_root;
+extern volatile u_char __weak_symbol mfs_root_end;
+__GLOBL(mfs_root);
+__GLOBL(mfs_root_end);
+#define mfs_root_size ((uintptr_t)(&mfs_root_end - &mfs_root))
+#endif
#endif
static g_init_t g_md_init;
@@ -1552,6 +1564,9 @@ md_preloaded(u_char *image, size_t length, const char *name)
if (name != NULL) {
printf("%s%d: Preloaded image <%s> %zd bytes at %p\n",
MD_NAME, sc->unit, name, length, image);
+ } else {
+ printf("%s%d: Embedded image %zd bytes at %p\n",
+ MD_NAME, sc->unit, length, image);
}
}
@@ -1571,10 +1586,13 @@ g_md_init(struct g_class *mp __unused)
sx_init(&md_sx, "MD config lock");
g_topology_unlock();
md_uh = new_unrhdr(0, INT_MAX, NULL);
-#ifdef MD_ROOT_SIZE
- sx_xlock(&md_sx);
- md_preloaded(mfs_root.start, sizeof(mfs_root.start), NULL);
- sx_xunlock(&md_sx);
+#ifdef MD_ROOT
+ if (mfs_root_size != 0) {
+ sx_xlock(&md_sx);
+ md_preloaded(__DEVOLATILE(u_char *, &mfs_root), mfs_root_size,
+ NULL);
+ sx_xunlock(&md_sx);
+ }
#endif
/* XXX: are preload_* static or do they need Giant ? */
while ((mod = preload_search_next_name(mod)) != NULL) {
@@ -1660,9 +1678,11 @@ g_md_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp,
"read-only");
sbuf_printf(sb, "%s<type>%s</type>\n", indent,
type);
- if (mp->type == MD_VNODE && mp->vnode != NULL)
- sbuf_printf(sb, "%s<file>%s</file>\n",
- indent, mp->file);
+ if (mp->type == MD_VNODE && mp->vnode != NULL) {
+ sbuf_printf(sb, "%s<file>", indent);
+ g_conf_printf_escaped(sb, "%s", mp->file);
+ sbuf_printf(sb, "</file>\n");
+ }
}
}
}
diff --git a/sys/dev/random/fortuna.c b/sys/dev/random/fortuna.c
index 2aafba4..0b03931 100644
--- a/sys/dev/random/fortuna.c
+++ b/sys/dev/random/fortuna.c
@@ -58,6 +58,7 @@ __FBSDID("$FreeBSD$");
#include <dev/random/fortuna.h>
#else /* !_KERNEL */
#include <inttypes.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -124,9 +125,7 @@ static uint8_t zero_region[RANDOM_ZERO_BLOCKSIZE];
static void random_fortuna_pre_read(void);
static void random_fortuna_read(uint8_t *, u_int);
-static void random_fortuna_write(uint8_t *, u_int);
-static void random_fortuna_reseed(void);
-static int random_fortuna_seeded(void);
+static bool random_fortuna_seeded(void);
static void random_fortuna_process_event(struct harvest_event *);
static void random_fortuna_init_alg(void *);
static void random_fortuna_deinit_alg(void *);
@@ -139,8 +138,6 @@ struct random_algorithm random_alg_context = {
.ra_deinit_alg = random_fortuna_deinit_alg,
.ra_pre_read = random_fortuna_pre_read,
.ra_read = random_fortuna_read,
- .ra_write = random_fortuna_write,
- .ra_reseed = random_fortuna_reseed,
.ra_seeded = random_fortuna_seeded,
.ra_event_processor = random_fortuna_process_event,
.ra_poolcount = RANDOM_FORTUNA_NPOOLS,
@@ -420,43 +417,7 @@ random_fortuna_read(uint8_t *buf, u_int bytecount)
RANDOM_RESEED_UNLOCK();
}
-/* Internal function to hand external entropy to the PRNG. */
-void
-random_fortuna_write(uint8_t *buf, u_int count)
-{
- static u_int destination = 0;
- struct harvest_event event;
- struct randomdev_hash hash;
- uint32_t entropy_data[RANDOM_KEYSIZE_WORDS], timestamp;
- int i;
-
- /* Extra timing here is helpful to scrape scheduler timing entropy */
- randomdev_hash_init(&hash);
- timestamp = (uint32_t)get_cyclecount();
- randomdev_hash_iterate(&hash, &timestamp, sizeof(timestamp));
- randomdev_hash_iterate(&hash, buf, count);
- timestamp = (uint32_t)get_cyclecount();
- randomdev_hash_iterate(&hash, &timestamp, sizeof(timestamp));
- randomdev_hash_finish(&hash, entropy_data);
- explicit_bzero(&hash, sizeof(hash));
- for (i = 0; i < RANDOM_KEYSIZE_WORDS; i += sizeof(event.he_entropy)/sizeof(event.he_entropy[0])) {
- event.he_somecounter = (uint32_t)get_cyclecount();
- event.he_size = sizeof(event.he_entropy);
- event.he_bits = event.he_size/8;
- event.he_source = RANDOM_CACHED;
- event.he_destination = destination++; /* Harmless cheating */
- memcpy(event.he_entropy, entropy_data + i, sizeof(event.he_entropy));
- random_fortuna_process_event(&event);
- }
- explicit_bzero(entropy_data, sizeof(entropy_data));
-}
-
-void
-random_fortuna_reseed(void)
-{
-}
-
-int
+bool
random_fortuna_seeded(void)
{
diff --git a/sys/dev/random/other_algorithm.c b/sys/dev/random/other_algorithm.c
new file mode 100644
index 0000000..740e879
--- /dev/null
+++ b/sys/dev/random/other_algorithm.c
@@ -0,0 +1,209 @@
+/*-
+ * Copyright (c) 2015 Mark R V Murray
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*-
+ * This is a skeleton for folks who wish to build a loadable module
+ * containing an alternative entropy-processing algorithm for random(4).
+ *
+ * The functions below should be completed with the appropriate code,
+ * and the nearby yarrow.c and fortuna.c may be consulted for examples
+ * of working code.
+ *
+ * The author is willing to provide reasonable help to those wishing to
+ * write such a module for themselves. Please use the markm@ FreeBSD
+ * email address, and ensure that you are developing this on a suitably
+ * supported branch (This is currently 11-CURRENT, and will be no
+ * older than 11-STABLE in the future).
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/random.h>
+#include <sys/sysctl.h>
+#include <sys/systm.h>
+
+#include <machine/cpu.h>
+
+#include <crypto/rijndael/rijndael-api-fst.h>
+#include <crypto/sha2/sha2.h>
+
+#include <dev/random/hash.h>
+#include <dev/random/randomdev.h>
+#include <dev/random/random_harvestq.h>
+#include <dev/random/uint128.h>
+#include <dev/random/other_algorithm.h>
+
+static void random_other_pre_read(void);
+static void random_other_read(uint8_t *, u_int);
+static bool random_other_seeded(void);
+static void random_other_process_event(struct harvest_event *);
+static void random_other_init_alg(void *);
+static void random_other_deinit_alg(void *);
+
+/*
+ * RANDOM_OTHER_NPOOLS is used when reading hardware random
+ * number sources to ensure that each pool gets one read sample
+ * per loop iteration. Yarrow has 2 such pools (FAST and SLOW),
+ * and fortuna has 32 (0-31). The RNG used prior to Yarrow and
+ * ported from Linux had just 1 pool.
+ */
+#define RANDOM_OTHER_NPOOLS 1
+
+struct random_algorithm random_alg_context = {
+ .ra_ident = "other",
+ .ra_init_alg = random_other_init_alg,
+ .ra_deinit_alg = random_other_deinit_alg,
+ .ra_pre_read = random_other_pre_read,
+ .ra_read = random_other_read,
+ .ra_seeded = random_other_seeded,
+ .ra_event_processor = random_other_process_event,
+ .ra_poolcount = RANDOM_OTHER_NPOOLS,
+};
+
+/* Use a mutex to protect your reseed variables? */
+static mtx_t other_mtx;
+
+/*
+ * void random_other_init_alg(void *unused __unused)
+ *
+ * Do algorithm-specific initialisation here.
+ */
+void
+random_other_init_alg(void *unused __unused)
+{
+
+ RANDOM_RESEED_INIT_LOCK();
+ /*
+ * Do set-up work here!
+ */
+}
+
+/*
+ * void random_other_deinit_alg(void *unused __unused)
+ *
+ * Do algorithm-specific deinitialisation here.
+ */
+static void
+random_other_deinit_alg(void *unused __unused)
+{
+
+ /*
+ * Do tear-down work here!
+ */
+ RANDOM_RESEED_DEINIT_LOCK();
+}
+
+/*
+ * void random_other_pre_read(void)
+ *
+ * Do any pre-read preparation you need to. This will be called
+ * before >=1 calls to random_other_read() corresponding to one
+ * read(2).
+ *
+ * This routine will be called periodically while the generator is
+ * still blocked and a read is being attempted, giving you an
+ * opportunity to unblock.
+ */
+static void
+random_other_pre_read(void)
+{
+
+ RANDOM_RESEED_LOCK();
+ /*
+ * Do pre-read housekeeping work here!
+ * You may use this as a chance to unblock the generator.
+ */
+ RANDOM_RESEED_UNLOCK();
+}
+
+/*
+ * void random_other_read(uint8_t *buf, u_int count)
+ *
+ * Generate <count> bytes of output into <*buf>.
+ * You may use the fact that <count> will be a multiple of
+ * RANDOM_BLOCKSIZE for optimization purposes.
+ *
+ * This function will always be called with your generator
+ * unblocked and ready. If you are not ready to generate
+ * output here, then feel free to KASSERT() or panic().
+ */
+static void
+random_other_read(uint8_t *buf, u_int count)
+{
+
+ RANDOM_RESEED_LOCK();
+ /*
+ * Do random-number generation work here!
+ */
+ RANDOM_RESEED_UNLOCK();
+}
+
+/*
+ * bool random_other_seeded(void)
+ *
+ * Return true if your generator is ready to generate
+ * output, and false otherwise.
+ */
+static bool
+random_other_seeded(void)
+{
+ bool seeded = false;
+
+ /*
+ * Find out if your generator is seeded here!
+ */
+ return (seeded);
+}
+
+/*
+ * void random_other_process_event(struct harvest_event *event)
+ *
+ * Process one stochastic event <*event> into your entropy
+ * processor.
+ *
+ * The structure of the event may change, so it is easier to
+ * just grab the whole thing into your accumulation system.
+ * You may pick-and-choose bits, but please don't complain
+ * when/if these change.
+ */
+static void
+random_other_process_event(struct harvest_event *event)
+{
+
+ RANDOM_RESEED_LOCK();
+ /*
+ * Do entropy accumulation work here!
+ * You may use this as a chance to unblock the generator.
+ */
+ RANDOM_RESEED_UNLOCK();
+}
diff --git a/sys/dev/random/other_algorithm.h b/sys/dev/random/other_algorithm.h
new file mode 100644
index 0000000..8ca2bb8
--- /dev/null
+++ b/sys/dev/random/other_algorithm.h
@@ -0,0 +1,62 @@
+/*-
+ * Copyright (c) 2015 Mark R V Murray
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*-
+ * This is a skeleton for folks who wish to build a loadable module
+ * containing an alternative entropy-processing algorithm for random(4).
+ *
+ * The functions below should be completed with the appropriate code,
+ * and the nearby yarrow.c and fortuna.c may be consulted for examples
+ * of working code.
+ *
+ * The author is willing to provide reasonable help to those wishing to
+ * write such a module for themselves. Please use the markm@ FreeBSD
+ * email address, and ensure that you are developing this on a suitably
+ * supported branch (This is currently 11-CURRENT, and will be no
+ * older than 11-STABLE in the future).
+ */
+
+#ifndef SYS_DEV_RANDOM_OTHER_H_INCLUDED
+#define SYS_DEV_RANDOM_OTHER_H_INCLUDED
+
+#ifdef _KERNEL
+typedef struct mtx mtx_t;
+#define RANDOM_RESEED_INIT_LOCK(x) mtx_init(&other_mtx, "reseed mutex", NULL, MTX_DEF)
+#define RANDOM_RESEED_DEINIT_LOCK(x) mtx_destroy(&other_mtx)
+#define RANDOM_RESEED_LOCK(x) mtx_lock(&other_mtx)
+#define RANDOM_RESEED_UNLOCK(x) mtx_unlock(&other_mtx)
+#define RANDOM_RESEED_ASSERT_LOCK_OWNED(x) mtx_assert(&other_mtx, MA_OWNED)
+#else
+#define RANDOM_RESEED_INIT_LOCK(x) mtx_init(&other_mtx, mtx_plain)
+#define RANDOM_RESEED_DEINIT_LOCK(x) mtx_destroy(&other_mtx)
+#define RANDOM_RESEED_LOCK(x) mtx_lock(&other_mtx)
+#define RANDOM_RESEED_UNLOCK(x) mtx_unlock(&other_mtx)
+#define RANDOM_RESEED_ASSERT_LOCK_OWNED(x)
+#endif
+
+#endif /* SYS_DEV_RANDOM_OTHER_H_INCLUDED */
diff --git a/sys/dev/random/random_harvestq.c b/sys/dev/random/random_harvestq.c
index 34a809b..255136c 100644
--- a/sys/dev/random/random_harvestq.c
+++ b/sys/dev/random/random_harvestq.c
@@ -47,12 +47,21 @@ __FBSDID("$FreeBSD$");
#include <sys/sysctl.h>
#include <sys/unistd.h>
+#if defined(RANDOM_LOADABLE)
+#include <sys/lock.h>
+#include <sys/sx.h>
+#endif
+
+#include <machine/atomic.h>
#include <machine/cpu.h>
#include <dev/random/randomdev.h>
#include <dev/random/random_harvestq.h>
static void random_kthread(void);
+static void random_sources_feed(void);
+
+static u_int read_rate;
/* List for the dynamic sysctls */
static struct sysctl_ctx_list random_clist;
@@ -66,7 +75,7 @@ static struct sysctl_ctx_list random_clist;
#define RANDOM_RING_MAX 1024
#define RANDOM_ACCUM_MAX 8
-/* 1 to let the kernel thread run, 0 to terminate */
+/* 1 to let the kernel thread run, 0 to terminate, -1 to mark completion */
volatile int random_kthread_control;
/*
@@ -123,13 +132,18 @@ static struct kproc_desc random_proc_kp = {
&harvest_context.hc_kthread_proc,
};
-
/* Pass the given event straight through to Fortuna/Yarrow/Whatever. */
static __inline void
random_harvestq_fast_process_event(struct harvest_event *event)
{
- if (random_alg_context.ra_event_processor)
- random_alg_context.ra_event_processor(event);
+#if defined(RANDOM_LOADABLE)
+ RANDOM_CONFIG_S_LOCK();
+ if (p_random_alg_context)
+#endif
+ p_random_alg_context->ra_event_processor(event);
+#if defined(RANDOM_LOADABLE)
+ RANDOM_CONFIG_S_UNLOCK();
+#endif
}
static void
@@ -163,12 +177,58 @@ random_kthread(void)
/* XXX: FIX!! This is a *great* place to pass hardware/live entropy to random(9) */
tsleep_sbt(&harvest_context.hc_kthread_proc, 0, "-", SBT_1S/10, 0, C_PREL(1));
}
+ random_kthread_control = -1;
wakeup(&harvest_context.hc_kthread_proc);
kproc_exit(0);
/* NOTREACHED */
}
+/* This happens well after SI_SUB_RANDOM */
SYSINIT(random_device_h_proc, SI_SUB_CREATE_INIT, SI_ORDER_ANY, kproc_start, &random_proc_kp);
+/*
+ * Run through all fast sources reading entropy for the given
+ * number of rounds, which should be a multiple of the number
+ * of entropy accumulation pools in use; 2 for Yarrow and 32
+ * for Fortuna.
+ */
+static void
+random_sources_feed(void)
+{
+ uint32_t entropy[HARVESTSIZE];
+ struct random_sources *rrs;
+ u_int i, n, local_read_rate;
+
+ /*
+ * Step over all of live entropy sources, and feed their output
+ * to the system-wide RNG.
+ */
+#if defined(RANDOM_LOADABLE)
+ RANDOM_CONFIG_S_LOCK();
+ if (p_random_alg_context) {
+ /* It's an indenting error. Yeah, Yeah. */
+#endif
+ local_read_rate = atomic_readandclear_32(&read_rate);
+ LIST_FOREACH(rrs, &source_list, rrs_entries) {
+ for (i = 0; i < p_random_alg_context->ra_poolcount*(local_read_rate + 1); i++) {
+ n = rrs->rrs_source->rs_read(entropy, sizeof(entropy));
+ KASSERT((n > 0 && n <= sizeof(entropy)), ("very bad return from rs_read (= %d) in %s", n, __func__));
+ random_harvest_direct(entropy, n, (n*8)/2, rrs->rrs_source->rs_source);
+ }
+ }
+ explicit_bzero(entropy, sizeof(entropy));
+#if defined(RANDOM_LOADABLE)
+ }
+ RANDOM_CONFIG_S_UNLOCK();
+#endif
+}
+
+void
+read_rate_increment(u_int chunk)
+{
+
+ atomic_add_32(&read_rate, chunk);
+}
+
/* ARGSUSED */
RANDOM_CHECK_UINT(harvestmask, 0, RANDOM_HARVEST_EVERYTHING_MASK);
@@ -317,7 +377,8 @@ random_harvestq_deinit(void *unused __unused)
/* Command the hash/reseed thread to end and wait for it to finish */
random_kthread_control = 0;
- tsleep(&harvest_context.hc_kthread_proc, 0, "harvqterm", 0);
+ while (random_kthread_control >= 0)
+ tsleep(&harvest_context.hc_kthread_proc, 0, "harvqterm", hz/5);
sysctl_ctx_free(&random_clist);
}
SYSUNINIT(random_device_h_init, SI_SUB_RANDOM, SI_ORDER_SECOND, random_harvestq_deinit, NULL);
@@ -412,3 +473,5 @@ random_harvest_direct(const void *entropy, u_int size, u_int bits, enum random_e
random_harvestq_fast_process_event(&event);
explicit_bzero(&event, sizeof(event));
}
+
+MODULE_VERSION(random_harvestq, 1);
diff --git a/sys/dev/random/random_harvestq.h b/sys/dev/random/random_harvestq.h
index f1de86f..421b592 100644
--- a/sys/dev/random/random_harvestq.h
+++ b/sys/dev/random/random_harvestq.h
@@ -43,6 +43,8 @@ struct harvest_event {
uint8_t he_source; /* origin of the entropy */
} __packed;
+void read_rate_increment(u_int);
+
#define RANDOM_HARVESTQ_BOOT_ENTROPY_FILE "/boot/entropy"
#define RANDOM_HARVEST_INIT_LOCK(x) mtx_init(&harvest_context.hc_mtx, "entropy harvest mutex", NULL, MTX_SPIN)
diff --git a/sys/dev/random/random_infra.c b/sys/dev/random/random_infra.c
new file mode 100644
index 0000000..d31b84b
--- /dev/null
+++ b/sys/dev/random/random_infra.c
@@ -0,0 +1,128 @@
+/*-
+ * Copyright (c) 2015 Mark R V Murray
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/random.h>
+#include <sys/sysctl.h>
+
+#if defined(RANDOM_LOADABLE)
+#include <sys/lock.h>
+#include <sys/sx.h>
+#endif
+
+#include <dev/random/randomdev.h>
+
+/* Set up the sysctl root node for the entropy device */
+SYSCTL_NODE(_kern, OID_AUTO, random, CTLFLAG_RW, 0, "Cryptographically Secure Random Number Generator");
+
+MALLOC_DEFINE(M_ENTROPY, "entropy", "Entropy harvesting buffers and data structures");
+
+struct sources_head source_list = LIST_HEAD_INITIALIZER(source_list);
+
+#if defined(RANDOM_LOADABLE)
+struct random_algorithm *p_random_alg_context = NULL;
+#else /* !defined(RANDOM_LOADABLE) */
+struct random_algorithm *p_random_alg_context = &random_alg_context;
+#endif /* defined(RANDOM_LOADABLE) */
+
+#if defined(RANDOM_LOADABLE)
+
+struct random_readers {
+ int (*read_random_uio)(struct uio *, bool);
+ u_int (*read_random)(void *, u_int);
+} random_reader_context = {
+ (int (*)(struct uio *, bool))nullop,
+ (u_int (*)(void *, u_int))nullop,
+};
+
+struct sx randomdev_config_lock;
+
+static void
+random_infra_sysinit(void *dummy __unused)
+{
+
+ RANDOM_CONFIG_INIT_LOCK();
+}
+SYSINIT(random_device_h_init, SI_SUB_RANDOM, SI_ORDER_FIRST, random_infra_sysinit, NULL);
+
+void
+random_infra_init(int (*p_random_read_uio)(struct uio *, bool), u_int (*p_random_read)(void *, u_int))
+{
+
+ RANDOM_CONFIG_X_LOCK();
+ random_reader_context.read_random_uio = p_random_read_uio;
+ random_reader_context.read_random = p_random_read;
+ RANDOM_CONFIG_X_UNLOCK();
+}
+
+void
+random_infra_uninit(void)
+{
+
+ RANDOM_CONFIG_X_LOCK();
+ random_reader_context.read_random_uio = (int (*)(struct uio *, bool))nullop;
+ random_reader_context.read_random = (u_int (*)(void *, u_int))nullop;
+ RANDOM_CONFIG_X_UNLOCK();
+}
+
+static void
+random_infra_sysuninit(void *dummy __unused)
+{
+
+ RANDOM_CONFIG_DEINIT_LOCK();
+}
+SYSUNINIT(random_device_h_init, SI_SUB_RANDOM, SI_ORDER_FIRST, random_infra_sysuninit, NULL);
+
+int
+read_random_uio(struct uio *uio, bool nonblock)
+{
+ int retval;
+
+ RANDOM_CONFIG_S_LOCK();
+ retval = random_reader_context.read_random_uio(uio, nonblock);
+ RANDOM_CONFIG_S_UNLOCK();
+ return (retval);
+}
+
+u_int
+read_random(void *buf, u_int len)
+{
+ u_int retval;
+
+ RANDOM_CONFIG_S_LOCK();
+ retval = random_reader_context.read_random(buf, len);
+ RANDOM_CONFIG_S_UNLOCK();
+ return (retval);
+}
+
+#endif /* defined(RANDOM_LOADABLE) */
diff --git a/sys/dev/random/randomdev.c b/sys/dev/random/randomdev.c
index 5c20c5d..f20a462 100644
--- a/sys/dev/random/randomdev.c
+++ b/sys/dev/random/randomdev.c
@@ -56,14 +56,18 @@ __FBSDID("$FreeBSD$");
#include <dev/random/randomdev.h>
#include <dev/random/random_harvestq.h>
-#include "opt_random.h"
+#define RANDOM_UNIT 0
-#if defined(RANDOM_DUMMY) && defined(RANDOM_YARROW)
-#error "Cannot define both RANDOM_DUMMY and RANDOM_YARROW"
+#if defined(RANDOM_LOADABLE)
+#define READ_RANDOM_UIO _read_random_uio
+#define READ_RANDOM _read_random
+static int READ_RANDOM_UIO(struct uio *, bool);
+static u_int READ_RANDOM(void *, u_int);
+#else
+#define READ_RANDOM_UIO read_random_uio
+#define READ_RANDOM read_random
#endif
-#define RANDOM_UNIT 0
-
/* Return the largest number >= x that is a multiple of m */
#define CEIL_TO_MULTIPLE(x, m) ((((x) + (m) - 1)/(m))*(m))
@@ -84,68 +88,31 @@ static struct cdevsw random_cdevsw = {
/* For use with make_dev(9)/destroy_dev(9). */
static struct cdev *random_dev;
-/* Set up the sysctl root node for the entropy device */
-SYSCTL_NODE(_kern, OID_AUTO, random, CTLFLAG_RW, 0, "Cryptographically Secure Random Number Generator");
-
-MALLOC_DEFINE(M_ENTROPY, "entropy", "Entropy harvesting buffers and data structures");
-
-#if defined(RANDOM_DUMMY)
-
-/*-
- * Dummy "always block" pseudo algorithm, used when there is no real
- * random(4) driver to provide a CSPRNG.
- */
-
-static u_int
-dummy_random_zero(void)
-{
-
- return (0);
-}
-
-static void
-dummy_random(void)
-{
-}
-
-struct random_algorithm random_alg_context = {
- .ra_ident = "Dummy",
- .ra_init_alg = NULL,
- .ra_deinit_alg = NULL,
- .ra_pre_read = dummy_random,
- .ra_read = (random_alg_read_t *)dummy_random_zero,
- .ra_write = (random_alg_write_t *)dummy_random_zero,
- .ra_reseed = dummy_random,
- .ra_seeded = (random_alg_seeded_t *)dummy_random_zero,
- .ra_event_processor = NULL,
- .ra_poolcount = 0,
-};
-
-#else /* !defined(RANDOM_DUMMY) */
-
-LIST_HEAD(sources_head, random_sources);
-static struct sources_head source_list = LIST_HEAD_INITIALIZER(source_list);
-static u_int read_rate;
-
static void
random_alg_context_ra_init_alg(void *data)
{
- random_alg_context.ra_init_alg(data);
+ p_random_alg_context = &random_alg_context;
+ p_random_alg_context->ra_init_alg(data);
+#if defined(RANDOM_LOADABLE)
+ random_infra_init(READ_RANDOM_UIO, READ_RANDOM);
+#endif
}
static void
random_alg_context_ra_deinit_alg(void *data)
{
- random_alg_context.ra_deinit_alg(data);
+#if defined(RANDOM_LOADABLE)
+ random_infra_uninit();
+#endif
+ p_random_alg_context->ra_deinit_alg(data);
+ p_random_alg_context = NULL;
}
SYSINIT(random_device, SI_SUB_RANDOM, SI_ORDER_THIRD, random_alg_context_ra_init_alg, NULL);
SYSUNINIT(random_device, SI_SUB_RANDOM, SI_ORDER_THIRD, random_alg_context_ra_deinit_alg, NULL);
-#endif /* defined(RANDOM_DUMMY) */
-
static struct selinfo rsel;
/*
@@ -156,28 +123,28 @@ static int
randomdev_read(struct cdev *dev __unused, struct uio *uio, int flags)
{
- return (read_random_uio(uio, (flags & O_NONBLOCK) != 0));
+ return (READ_RANDOM_UIO(uio, (flags & O_NONBLOCK) != 0));
}
int
-read_random_uio(struct uio *uio, bool nonblock)
+READ_RANDOM_UIO(struct uio *uio, bool nonblock)
{
uint8_t *random_buf;
int error, spamcount;
ssize_t read_len, total_read, c;
random_buf = malloc(PAGE_SIZE, M_ENTROPY, M_WAITOK);
- random_alg_context.ra_pre_read();
+ p_random_alg_context->ra_pre_read();
error = 0;
spamcount = 0;
/* (Un)Blocking logic */
- while (!random_alg_context.ra_seeded()) {
+ while (!p_random_alg_context->ra_seeded()) {
if (nonblock) {
error = EWOULDBLOCK;
break;
}
/* keep tapping away at the pre-read until we seed/unblock. */
- random_alg_context.ra_pre_read();
+ p_random_alg_context->ra_pre_read();
/* Only bother the console every 10 seconds or so */
if (spamcount == 0)
printf("random: %s unblock wait\n", __func__);
@@ -187,10 +154,7 @@ read_random_uio(struct uio *uio, bool nonblock)
break;
}
if (error == 0) {
-#if !defined(RANDOM_DUMMY)
- /* XXX: FIX!! Next line as an atomic operation? */
- read_rate += (uio->uio_resid + sizeof(uint32_t))/sizeof(uint32_t);
-#endif
+ read_rate_increment((uio->uio_resid + sizeof(uint32_t))/sizeof(uint32_t));
total_read = 0;
while (uio->uio_resid && !error) {
read_len = uio->uio_resid;
@@ -203,7 +167,7 @@ read_random_uio(struct uio *uio, bool nonblock)
read_len = CEIL_TO_MULTIPLE(read_len, RANDOM_BLOCKSIZE);
/* Work in chunks page-sized or less */
read_len = MIN(read_len, PAGE_SIZE);
- random_alg_context.ra_read(random_buf, read_len);
+ p_random_alg_context->ra_read(random_buf, read_len);
c = MIN(uio->uio_resid, read_len);
error = uiomove(random_buf, c, uio);
total_read += c;
@@ -224,19 +188,16 @@ read_random_uio(struct uio *uio, bool nonblock)
* RANDOM_BLOCKSIZE bytes.
*/
u_int
-read_random(void *random_buf, u_int len)
+READ_RANDOM(void *random_buf, u_int len)
{
u_int read_len;
uint8_t local_buf[len + RANDOM_BLOCKSIZE];
KASSERT(random_buf != NULL, ("No suitable random buffer in %s", __func__));
- random_alg_context.ra_pre_read();
+ p_random_alg_context->ra_pre_read();
/* (Un)Blocking logic; if not seeded, return nothing. */
- if (random_alg_context.ra_seeded()) {
-#if !defined(RANDOM_DUMMY)
- /* XXX: FIX!! Next line as an atomic operation? */
- read_rate += (len + sizeof(uint32_t))/sizeof(uint32_t);
-#endif
+ if (p_random_alg_context->ra_seeded()) {
+ read_rate_increment((len + sizeof(uint32_t))/sizeof(uint32_t));
if (len > 0) {
/*
* Belt-and-braces.
@@ -244,7 +205,7 @@ read_random(void *random_buf, u_int len)
* which is what the underlying generator is expecting.
*/
read_len = CEIL_TO_MULTIPLE(len, RANDOM_BLOCKSIZE);
- random_alg_context.ra_read(local_buf, read_len);
+ p_random_alg_context->ra_read(local_buf, read_len);
memcpy(random_buf, local_buf, len);
}
} else
@@ -252,6 +213,37 @@ read_random(void *random_buf, u_int len)
return (len);
}
+static __inline void
+randomdev_accumulate(uint8_t *buf, u_int count)
+{
+ static u_int destination = 0;
+ static struct harvest_event event;
+ static struct randomdev_hash hash;
+ static uint32_t entropy_data[RANDOM_KEYSIZE_WORDS];
+ uint32_t timestamp;
+ int i;
+
+ /* Extra timing here is helpful to scrape scheduler jitter entropy */
+ randomdev_hash_init(&hash);
+ timestamp = (uint32_t)get_cyclecount();
+ randomdev_hash_iterate(&hash, &timestamp, sizeof(timestamp));
+ randomdev_hash_iterate(&hash, buf, count);
+ timestamp = (uint32_t)get_cyclecount();
+ randomdev_hash_iterate(&hash, &timestamp, sizeof(timestamp));
+ randomdev_hash_finish(&hash, entropy_data);
+ explicit_bzero(&hash, sizeof(hash));
+ for (i = 0; i < RANDOM_KEYSIZE_WORDS; i += sizeof(event.he_entropy)/sizeof(event.he_entropy[0])) {
+ event.he_somecounter = (uint32_t)get_cyclecount();
+ event.he_size = sizeof(event.he_entropy);
+ event.he_bits = event.he_size/8;
+ event.he_source = RANDOM_CACHED;
+ event.he_destination = destination++; /* Harmless cheating */
+ memcpy(event.he_entropy, entropy_data + i, sizeof(event.he_entropy));
+ p_random_alg_context->ra_event_processor(&event);
+ }
+ explicit_bzero(entropy_data, sizeof(entropy_data));
+}
+
/* ARGSUSED */
static int
randomdev_write(struct cdev *dev __unused, struct uio *uio, int flags __unused)
@@ -267,7 +259,7 @@ randomdev_write(struct cdev *dev __unused, struct uio *uio, int flags __unused)
error = uiomove(random_buf, c, uio);
if (error)
break;
- random_alg_context.ra_write(random_buf, c);
+ randomdev_accumulate(random_buf, c);
tsleep(&random_alg_context, 0, "randwr", hz/10);
}
if (nbytes != uio->uio_resid && (error == ERESTART || error == EINTR))
@@ -283,7 +275,7 @@ randomdev_poll(struct cdev *dev __unused, int events, struct thread *td __unused
{
if (events & (POLLIN | POLLRDNORM)) {
- if (random_alg_context.ra_seeded())
+ if (p_random_alg_context->ra_seeded())
events &= (POLLIN | POLLRDNORM);
else
selrecord(td, &rsel);
@@ -325,9 +317,6 @@ randomdev_ioctl(struct cdev *dev __unused, u_long cmd, caddr_t addr __unused,
void
random_source_register(struct random_source *rsource)
{
-#if defined(RANDOM_DUMMY)
- (void)rsource;
-#else /* !defined(RANDOM_DUMMY) */
struct random_sources *rrs;
KASSERT(rsource != NULL, ("invalid input to %s", __func__));
@@ -337,15 +326,11 @@ random_source_register(struct random_source *rsource)
printf("random: registering fast source %s\n", rsource->rs_ident);
LIST_INSERT_HEAD(&source_list, rrs, rrs_entries);
-#endif /* defined(RANDOM_DUMMY) */
}
void
random_source_deregister(struct random_source *rsource)
{
-#if defined(RANDOM_DUMMY)
- (void)rsource;
-#else /* !defined(RANDOM_DUMMY) */
struct random_sources *rrs = NULL;
KASSERT(rsource != NULL, ("invalid input to %s", __func__));
@@ -356,41 +341,6 @@ random_source_deregister(struct random_source *rsource)
}
if (rrs != NULL)
free(rrs, M_ENTROPY);
-#endif /* defined(RANDOM_DUMMY) */
-}
-
-#if !defined(RANDOM_DUMMY)
-/*
- * Run through all fast sources reading entropy for the given
- * number of rounds, which should be a multiple of the number
- * of entropy accumulation pools in use; 2 for Yarrow and 32
- * for Fortuna.
- *
- * BEWARE!!!
- * This function runs inside the RNG thread! Don't do anything silly!
- */
-void
-random_sources_feed(void)
-{
- uint32_t entropy[HARVESTSIZE];
- struct random_sources *rrs;
- u_int i, n, local_read_rate;
-
- /*
- * Step over all of live entropy sources, and feed their output
- * to the system-wide RNG.
- */
- /* XXX: FIX!! Next lines as an atomic operation? */
- local_read_rate = read_rate;
- read_rate = RANDOM_ALG_READ_RATE_MINIMUM;
- LIST_FOREACH(rrs, &source_list, rrs_entries) {
- for (i = 0; i < random_alg_context.ra_poolcount*local_read_rate; i++) {
- n = rrs->rrs_source->rs_read(entropy, sizeof(entropy));
- KASSERT((n > 0 && n <= sizeof(entropy)), ("very bad return from rs_read (= %d) in %s", n, __func__));
- random_harvest_direct(entropy, n, (n*8)/2, rrs->rrs_source->rs_source);
- }
- }
- explicit_bzero(entropy, sizeof(entropy));
}
static int
@@ -414,7 +364,6 @@ random_source_handler(SYSCTL_HANDLER_ARGS)
SYSCTL_PROC(_kern_random, OID_AUTO, random_sources, CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
NULL, 0, random_source_handler, "A",
"List of active fast entropy sources.");
-#endif /* !defined(RANDOM_DUMMY) */
/* ARGSUSED */
static int
@@ -449,3 +398,5 @@ static moduledata_t randomdev_mod = {
DECLARE_MODULE(random_device, randomdev_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST);
MODULE_VERSION(random_device, 1);
+MODULE_DEPEND(random_device, crypto, 1, 1, 1);
+MODULE_DEPEND(random_device, random_harvestq, 1, 1, 1);
diff --git a/sys/dev/random/randomdev.h b/sys/dev/random/randomdev.h
index 799efb1..0f3b359 100644
--- a/sys/dev/random/randomdev.h
+++ b/sys/dev/random/randomdev.h
@@ -55,16 +55,15 @@ random_check_uint_##name(SYSCTL_HANDLER_ARGS) \
MALLOC_DECLARE(M_ENTROPY);
-#define RANDOM_ALG_READ_RATE_MINIMUM 32
-
#endif /* _KERNEL */
struct harvest_event;
+typedef void random_alg_init_t(void *);
+typedef void random_alg_deinit_t(void *);
typedef void random_alg_pre_read_t(void);
typedef void random_alg_read_t(uint8_t *, u_int);
-typedef void random_alg_write_t(uint8_t *, u_int);
-typedef int random_alg_seeded_t(void);
+typedef bool random_alg_seeded_t(void);
typedef void random_alg_reseed_t(void);
typedef void random_alg_eventprocessor_t(struct harvest_event *);
@@ -81,13 +80,11 @@ struct random_algorithm {
void (*ra_deinit_alg)(void *);
random_alg_pre_read_t *ra_pre_read;
random_alg_read_t *ra_read;
- random_alg_write_t *ra_write;
- random_alg_reseed_t *ra_reseed;
random_alg_seeded_t *ra_seeded;
random_alg_eventprocessor_t *ra_event_processor;
};
-extern struct random_algorithm random_alg_context;
+extern struct random_algorithm random_alg_context, *p_random_alg_context;
#ifdef _KERNEL
@@ -97,22 +94,33 @@ extern struct random_algorithm random_alg_context;
* upon request.
*/
struct random_source {
- const char *rs_ident;
- enum random_entropy_source rs_source;
- random_source_read_t *rs_read;
+ const char *rs_ident;
+ enum random_entropy_source rs_source;
+ random_source_read_t *rs_read;
};
-#if !defined(RANDOM_DUMMY)
struct random_sources {
- LIST_ENTRY(random_sources) rrs_entries;
- struct random_source *rrs_source;
+ LIST_ENTRY(random_sources) rrs_entries;
+ struct random_source *rrs_source;
};
-#endif /* !defined(RANDOM_DUMMY) */
+
+LIST_HEAD(sources_head, random_sources);
+extern struct sources_head source_list;
void random_source_register(struct random_source *);
void random_source_deregister(struct random_source *);
-void random_sources_feed(void);
+#if defined(RANDOM_LOADABLE)
+extern struct sx randomdev_config_lock;
+#define RANDOM_CONFIG_INIT_LOCK(x) sx_init(&randomdev_config_lock, "configuration change lock")
+#define RANDOM_CONFIG_X_LOCK(x) sx_xlock(&randomdev_config_lock)
+#define RANDOM_CONFIG_X_UNLOCK(x) sx_xunlock(&randomdev_config_lock)
+#define RANDOM_CONFIG_S_LOCK(x) sx_slock(&randomdev_config_lock)
+#define RANDOM_CONFIG_S_UNLOCK(x) sx_sunlock(&randomdev_config_lock)
+#define RANDOM_CONFIG_DEINIT_LOCK(x) sx_destroy(&randomdev_config_lock)
+void random_infra_init(int (*)(struct uio *, bool), u_int (*)(void *, u_int));
+void random_infra_uninit(void);
+#endif
#endif /* _KERNEL */
diff --git a/sys/dev/random/randomdev_none.c b/sys/dev/random/randomdev_none.c
deleted file mode 100644
index ee5cbf2..0000000
--- a/sys/dev/random/randomdev_none.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/*-
- * Copyright (c) 2015 Mark R V Murray
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer
- * in this position and unchanged.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/malloc.h>
-#include <sys/random.h>
-#include <sys/systm.h>
-
-#include <dev/random/randomdev.h>
-
-#include "opt_random.h"
-
-#if defined(RANDOM_DUMMY) || defined(RANDOM_YARROW)
-#error "Cannot define any of RANDOM_DUMMY and RANDOM_YARROW without 'device random'"
-#endif
-
-/*-
- * Dummy "not even here" device. Stub out all routines that the kernel would need.
- */
-
-/* ARGSUSED */
-u_int
-read_random(void *random_buf __unused, u_int len __unused)
-{
-
- return (0);
-}
-
-/* ARGSUSED */
-void
-random_harvest_direct(const void *entropy __unused, u_int count __unused, u_int bits __unused, enum random_entropy_source origin __unused)
-{
-}
-
-/* ARGSUSED */
-void
-random_harvest_queue(const void *entropy __unused, u_int count __unused, u_int bits __unused, enum random_entropy_source origin __unused)
-{
-}
-
-/* ARGSUSED */
-void
-random_harvest_fast(const void *entropy __unused, u_int count __unused, u_int bits __unused, enum random_entropy_source origin __unused)
-{
-}
diff --git a/sys/dev/random/unit_test.c b/sys/dev/random/unit_test.c
index 7ae5716..fac4c8d 100644
--- a/sys/dev/random/unit_test.c
+++ b/sys/dev/random/unit_test.c
@@ -46,6 +46,7 @@ Where <alg> is YARROW or FORTUNA.
#include <sys/types.h>
#include <inttypes.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <threads.h>
@@ -172,35 +173,6 @@ RunHarvester(void *arg __unused)
}
static int
-WriteCSPRNG(void *threadid)
-{
- uint8_t *buf;
- int i;
-
- printf("Thread #1 starts\n");
-
- for (i = 0; ; i++) {
- if (stopseeding)
- break;
- buf = malloc(4096);
- if (i % 1000 == 0)
- printf("Thread write 1 - %d\n", i);
- if (buf != NULL) {
- printf("Thread 1 writing.\n");
- random_alg_context.ra_write(buf, i);
- free(buf);
- }
- usleep(1000000);
- }
-
- printf("Thread #1 ends\n");
-
- thrd_exit(0);
-
- return (0);
-}
-
-static int
ReadCSPRNG(void *threadid)
{
size_t tid, zsize;
@@ -271,7 +243,7 @@ main(int argc, char *argv[])
for (t = 0; t < NUM_THREADS; t++) {
printf("In main: creating thread %ld\n", t);
- rc = thrd_create(&threads[t], (t == 0 ? RunHarvester : (t == 1 ? WriteCSPRNG : ReadCSPRNG)), NULL);
+ rc = thrd_create(&threads[t], (t == 0 ? RunHarvester : ReadCSPRNG), NULL);
if (rc != thrd_success) {
printf("ERROR; return code from thrd_create() is %d\n", rc);
exit(-1);
diff --git a/sys/dev/random/yarrow.c b/sys/dev/random/yarrow.c
index d6ebd46..2ef15a4 100644
--- a/sys/dev/random/yarrow.c
+++ b/sys/dev/random/yarrow.c
@@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$");
#include <dev/random/yarrow.h>
#else /* !_KERNEL */
#include <inttypes.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
@@ -92,7 +93,7 @@ static struct yarrow_state {
u_int ysp_thresh; /* pool reseed threshhold */
struct randomdev_hash ysp_hash; /* accumulated entropy */
} ys_pool[RANDOM_YARROW_NPOOLS];/* pool[0] is fast, pool[1] is slow */
- int ys_seeded;
+ bool ys_seeded;
/* Reseed lock */
mtx_t ys_mtx;
} yarrow_state;
@@ -108,9 +109,7 @@ RANDOM_CHECK_UINT(slowoverthresh, 1, 5);
static void random_yarrow_pre_read(void);
static void random_yarrow_read(uint8_t *, u_int);
-static void random_yarrow_write(uint8_t *, u_int);
-static void random_yarrow_reseed(void);
-static int random_yarrow_seeded(void);
+static bool random_yarrow_seeded(void);
static void random_yarrow_process_event(struct harvest_event *);
static void random_yarrow_init_alg(void *);
static void random_yarrow_deinit_alg(void *);
@@ -123,8 +122,6 @@ struct random_algorithm random_alg_context = {
.ra_deinit_alg = random_yarrow_deinit_alg,
.ra_pre_read = random_yarrow_pre_read,
.ra_read = random_yarrow_read,
- .ra_write = random_yarrow_write,
- .ra_reseed = random_yarrow_reseed,
.ra_seeded = random_yarrow_seeded,
.ra_event_processor = random_yarrow_process_event,
.ra_poolcount = RANDOM_YARROW_NPOOLS,
@@ -141,7 +138,7 @@ random_yarrow_init_alg(void *unused __unused)
RANDOM_RESEED_INIT_LOCK();
/* Start unseeded, therefore blocked. */
- yarrow_state.ys_seeded = 0;
+ yarrow_state.ys_seeded = false;
#ifdef _KERNEL
/*
* Yarrow parameters. Do not adjust these unless you have
@@ -266,12 +263,14 @@ random_yarrow_reseed_internal(u_int fastslow)
RANDOM_RESEED_ASSERT_LOCK_OWNED();
#ifdef RANDOM_DEBUG
/* WARNING! This is dangerously tedious to do with mutexes held! */
- printf("random: %s %s seeded = %d\n", __func__, (fastslow == RANDOM_YARROW_FAST ? "RANDOM_YARROW_FAST" : "RANDOM_YARROW_SLOW"), yarrow_state.ys_seeded);
- printf("random: %s - fast - thresh %d,1 - ", __func__, yarrow_state.ys_pool[RANDOM_YARROW_FAST].ysp_thresh);
+ printf("random: %s ", __func__);
+ printf("type/pool = %s ", fastslow == RANDOM_YARROW_FAST ? "RANDOM_YARROW_FAST" : "RANDOM_YARROW_SLOW");
+ printf("seeded = %s\n", yarrow_state.ys_seeded ? "true" : "false");
+ printf("random: fast - thresh %d,1 - ", yarrow_state.ys_pool[RANDOM_YARROW_FAST].ysp_thresh);
for (i = RANDOM_START; i < ENTROPYSOURCE; i++)
printf(" %d", yarrow_state.ys_pool[RANDOM_YARROW_FAST].ysp_source_bits[i]);
printf("\n");
- printf("random: %s - slow - thresh %d,%d - ", __func__, yarrow_state.ys_pool[RANDOM_YARROW_SLOW].ysp_thresh, yarrow_state.ys_slowoverthresh);
+ printf("random: slow - thresh %d,%d - ", yarrow_state.ys_pool[RANDOM_YARROW_SLOW].ysp_thresh, yarrow_state.ys_slowoverthresh);
for (i = RANDOM_START; i < ENTROPYSOURCE; i++)
printf(" %d", yarrow_state.ys_pool[RANDOM_YARROW_SLOW].ysp_source_bits[i]);
printf("\n");
@@ -338,7 +337,7 @@ random_yarrow_reseed_internal(u_int fastslow)
#endif
/* Unblock the device if it was blocked due to being unseeded */
if (!yarrow_state.ys_seeded) {
- yarrow_state.ys_seeded = 1;
+ yarrow_state.ys_seeded = true;
randomdev_unblock();
}
}
@@ -395,47 +394,7 @@ random_yarrow_read(uint8_t *buf, u_int bytecount)
RANDOM_RESEED_UNLOCK();
}
-/* Internal function to hand external entropy to the PRNG. */
-void
-random_yarrow_write(uint8_t *buf, u_int count)
-{
- static u_int destination = 0;
- static struct harvest_event event;
- struct randomdev_hash hash;
- uint32_t entropy_data[RANDOM_KEYSIZE_WORDS], timestamp;
- int i;
-
- /* Extra timing here is helpful to scrape scheduler timing entropy */
- randomdev_hash_init(&hash);
- timestamp = (uint32_t)get_cyclecount();
- randomdev_hash_iterate(&hash, &timestamp, sizeof(timestamp));
- randomdev_hash_iterate(&hash, buf, count);
- timestamp = (uint32_t)get_cyclecount();
- randomdev_hash_iterate(&hash, &timestamp, sizeof(timestamp));
- randomdev_hash_finish(&hash, entropy_data);
- explicit_bzero(&hash, sizeof(hash));
- for (i = 0; i < RANDOM_KEYSIZE_WORDS; i += sizeof(event.he_entropy)/sizeof(event.he_entropy[0])) {
- event.he_somecounter = (uint32_t)get_cyclecount();
- event.he_size = sizeof(event.he_entropy);
- event.he_bits = event.he_size/8;
- event.he_source = RANDOM_CACHED;
- event.he_destination = destination++; /* Harmless cheating */
- memcpy(event.he_entropy, entropy_data + i, sizeof(event.he_entropy));
- random_yarrow_process_event(&event);
- }
- explicit_bzero(entropy_data, sizeof(entropy_data));
-}
-
-void
-random_yarrow_reseed(void)
-{
-
- RANDOM_RESEED_LOCK();
- random_yarrow_reseed_internal(RANDOM_YARROW_SLOW);
- RANDOM_RESEED_UNLOCK();
-}
-
-int
+bool
random_yarrow_seeded(void)
{
diff --git a/sys/dev/usb/controller/dwc_otg.c b/sys/dev/usb/controller/dwc_otg.c
index bd3e51b..e018ab5 100644
--- a/sys/dev/usb/controller/dwc_otg.c
+++ b/sys/dev/usb/controller/dwc_otg.c
@@ -1,7 +1,7 @@
/* $FreeBSD$ */
/*-
* Copyright (c) 2015 Daisuke Aoyama. All rights reserved.
- * Copyright (c) 2012 Hans Petter Selasky. All rights reserved.
+ * Copyright (c) 2012-2015 Hans Petter Selasky. All rights reserved.
* Copyright (c) 2010-2011 Aleksandr Rybalko. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -597,14 +597,18 @@ dwc_otg_clear_hcint(struct dwc_otg_softc *sc, uint8_t x)
}
static uint8_t
-dwc_otg_host_check_fifo_empty(struct dwc_otg_softc *sc, struct dwc_otg_td *td)
+dwc_otg_host_check_tx_fifo_empty(struct dwc_otg_softc *sc, struct dwc_otg_td *td)
{
uint32_t temp;
temp = DWC_OTG_READ_4(sc, DOTG_GINTSTS);
- if (td->ep_type == UE_INTERRUPT ||
- td->ep_type == UE_ISOCHRONOUS) {
+ if (td->ep_type == UE_ISOCHRONOUS) {
+ /*
+ * NOTE: USB INTERRUPT transactions are executed like
+ * USB CONTROL transactions! See the setup standard
+ * chain function for more information.
+ */
if (!(temp & GINTSTS_PTXFEMP)) {
DPRINTF("Periodic TX FIFO is not empty\n");
if (!(sc->sc_irq_mask & GINTMSK_PTXFEMPMSK)) {
@@ -631,8 +635,10 @@ dwc_otg_host_channel_alloc(struct dwc_otg_softc *sc,
struct dwc_otg_td *td, uint8_t is_out)
{
uint8_t x;
+ uint8_t y;
+ uint8_t z;
- if (td->channel < DWC_OTG_MAX_CHANNELS)
+ if (td->channel[0] < DWC_OTG_MAX_CHANNELS)
return (0); /* already allocated */
/* check if device is suspended */
@@ -641,20 +647,42 @@ dwc_otg_host_channel_alloc(struct dwc_otg_softc *sc,
/* compute needed TX FIFO size */
if (is_out != 0) {
- if (dwc_otg_host_check_fifo_empty(sc, td) != 0)
+ if (dwc_otg_host_check_tx_fifo_empty(sc, td) != 0)
return (1); /* busy - cannot transfer data */
}
-
- for (x = 0; x != sc->sc_host_ch_max; x++) {
+ z = td->max_packet_count;
+ for (x = y = 0; x != sc->sc_host_ch_max; x++) {
/* check if channel is allocated */
if (sc->sc_chan_state[x].allocated != 0)
continue;
/* check if channel is still enabled */
if (sc->sc_chan_state[x].wait_halted != 0)
continue;
+ /* store channel number */
+ td->channel[y++] = x;
+ /* check if we got all channels */
+ if (y == z)
+ break;
+ }
+ if (y != z) {
+ /* reset channel variable */
+ td->channel[0] = DWC_OTG_MAX_CHANNELS;
+ td->channel[1] = DWC_OTG_MAX_CHANNELS;
+ td->channel[2] = DWC_OTG_MAX_CHANNELS;
+ /* wait a bit */
+ dwc_otg_enable_sof_irq(sc);
+ return (1); /* busy - not enough channels */
+ }
+
+ for (y = 0; y != z; y++) {
+ x = td->channel[y];
+ /* set allocated */
sc->sc_chan_state[x].allocated = 1;
+ /* set wait halted */
+ sc->sc_chan_state[x].wait_halted = 1;
+
/* clear interrupts */
dwc_otg_clear_hcint(sc, x);
@@ -663,29 +691,22 @@ dwc_otg_host_channel_alloc(struct dwc_otg_softc *sc,
/* set active channel */
sc->sc_active_rx_ep |= (1 << x);
-
- /* set channel */
- td->channel = x;
-
- return (0); /* allocated */
}
- /* wait a bit */
- dwc_otg_enable_sof_irq(sc);
- return (1); /* busy */
+ return (0); /* allocated */
}
static void
-dwc_otg_host_channel_free(struct dwc_otg_softc *sc, struct dwc_otg_td *td)
+dwc_otg_host_channel_free_sub(struct dwc_otg_softc *sc, struct dwc_otg_td *td, uint8_t index)
{
uint32_t hcchar;
uint8_t x;
- if (td->channel >= DWC_OTG_MAX_CHANNELS)
+ if (td->channel[index] >= DWC_OTG_MAX_CHANNELS)
return; /* already freed */
/* free channel */
- x = td->channel;
- td->channel = DWC_OTG_MAX_CHANNELS;
+ x = td->channel[index];
+ td->channel[index] = DWC_OTG_MAX_CHANNELS;
DPRINTF("CH=%d\n", x);
@@ -704,26 +725,42 @@ dwc_otg_host_channel_free(struct dwc_otg_softc *sc, struct dwc_otg_td *td)
/* clear active channel */
sc->sc_active_rx_ep &= ~(1 << x);
+ /* check if already halted */
+ if (sc->sc_chan_state[x].wait_halted == 0)
+ return;
+
/* disable host channel */
hcchar = DWC_OTG_READ_4(sc, DOTG_HCCHAR(x));
if (hcchar & HCCHAR_CHENA) {
DPRINTF("Halting channel %d\n", x);
DWC_OTG_WRITE_4(sc, DOTG_HCCHAR(x),
hcchar | HCCHAR_CHDIS);
- sc->sc_chan_state[x].wait_halted = 1;
/* don't write HCCHAR until the channel is halted */
+ } else {
+ sc->sc_chan_state[x].wait_halted = 0;
}
}
static void
+dwc_otg_host_channel_free(struct dwc_otg_softc *sc, struct dwc_otg_td *td)
+{
+ uint8_t x;
+ for (x = 0; x != td->max_packet_count; x++)
+ dwc_otg_host_channel_free_sub(sc, td, x);
+}
+
+static void
dwc_otg_host_dump_rx(struct dwc_otg_softc *sc, struct dwc_otg_td *td)
{
+ uint8_t x;
/* dump any pending messages */
- if (sc->sc_last_rx_status != 0) {
- if (td->channel < DWC_OTG_MAX_CHANNELS &&
- td->channel == GRXSTSRD_CHNUM_GET(sc->sc_last_rx_status)) {
- dwc_otg_common_rx_ack(sc);
- }
+ if (sc->sc_last_rx_status == 0)
+ return;
+ for (x = 0; x != td->max_packet_count; x++) {
+ if (td->channel[x] >= DWC_OTG_MAX_CHANNELS ||
+ td->channel[x] != GRXSTSRD_CHNUM_GET(sc->sc_last_rx_status))
+ continue;
+ dwc_otg_common_rx_ack(sc);
}
}
@@ -737,13 +774,13 @@ dwc_otg_host_setup_tx(struct dwc_otg_softc *sc, struct dwc_otg_td *td)
dwc_otg_host_dump_rx(sc, td);
- if (td->channel < DWC_OTG_MAX_CHANNELS) {
- hcint = sc->sc_chan_state[td->channel].hcint;
+ if (td->channel[0] < DWC_OTG_MAX_CHANNELS) {
+ hcint = sc->sc_chan_state[td->channel[0]].hcint;
DPRINTF("CH=%d ST=%d HCINT=0x%08x HCCHAR=0x%08x HCTSIZ=0x%08x\n",
- td->channel, td->state, hcint,
- DWC_OTG_READ_4(sc, DOTG_HCCHAR(td->channel)),
- DWC_OTG_READ_4(sc, DOTG_HCTSIZ(td->channel)));
+ td->channel[0], td->state, hcint,
+ DWC_OTG_READ_4(sc, DOTG_HCCHAR(td->channel[0])),
+ DWC_OTG_READ_4(sc, DOTG_HCTSIZ(td->channel[0])));
} else {
hcint = 0;
goto check_state;
@@ -753,12 +790,12 @@ dwc_otg_host_setup_tx(struct dwc_otg_softc *sc, struct dwc_otg_td *td)
HCINT_ACK | HCINT_NYET)) {
/* give success bits priority over failure bits */
} else if (hcint & HCINT_STALL) {
- DPRINTF("CH=%d STALL\n", td->channel);
+ DPRINTF("CH=%d STALL\n", td->channel[0]);
td->error_stall = 1;
td->error_any = 1;
goto complete;
} else if (hcint & HCINT_ERRORS) {
- DPRINTF("CH=%d ERROR\n", td->channel);
+ DPRINTF("CH=%d ERROR\n", td->channel[0]);
td->errcnt++;
if (td->hcsplt != 0 || td->errcnt >= 3) {
td->error_any = 1;
@@ -863,23 +900,23 @@ send_pkt:
usbd_copy_out(td->pc, 0, &req, sizeof(req));
- DWC_OTG_WRITE_4(sc, DOTG_HCTSIZ(td->channel),
+ DWC_OTG_WRITE_4(sc, DOTG_HCTSIZ(td->channel[0]),
(sizeof(req) << HCTSIZ_XFERSIZE_SHIFT) |
(1 << HCTSIZ_PKTCNT_SHIFT) |
(HCTSIZ_PID_SETUP << HCTSIZ_PID_SHIFT));
- DWC_OTG_WRITE_4(sc, DOTG_HCSPLT(td->channel), td->hcsplt);
+ DWC_OTG_WRITE_4(sc, DOTG_HCSPLT(td->channel[0]), td->hcsplt);
hcchar = td->hcchar;
hcchar &= ~(HCCHAR_EPDIR_IN | HCCHAR_EPTYPE_MASK);
hcchar |= UE_CONTROL << HCCHAR_EPTYPE_SHIFT;
/* must enable channel before writing data to FIFO */
- DWC_OTG_WRITE_4(sc, DOTG_HCCHAR(td->channel), hcchar);
+ DWC_OTG_WRITE_4(sc, DOTG_HCCHAR(td->channel[0]), hcchar);
/* transfer data into FIFO */
bus_space_write_region_4(sc->sc_io_tag, sc->sc_io_hdl,
- DOTG_DFIFO(td->channel), (uint32_t *)&req, sizeof(req) / 4);
+ DOTG_DFIFO(td->channel[0]), (uint32_t *)&req, sizeof(req) / 4);
/* wait until next slot before trying complete split */
td->tt_complete_slot = sc->sc_last_frame_num + 1;
@@ -916,17 +953,17 @@ send_cpkt:
td->hcsplt |= HCSPLT_COMPSPLT;
td->state = DWC_CHAN_ST_WAIT_C_ANE;
- DWC_OTG_WRITE_4(sc, DOTG_HCTSIZ(td->channel),
+ DWC_OTG_WRITE_4(sc, DOTG_HCTSIZ(td->channel[0]),
(HCTSIZ_PID_SETUP << HCTSIZ_PID_SHIFT));
- DWC_OTG_WRITE_4(sc, DOTG_HCSPLT(td->channel), td->hcsplt);
+ DWC_OTG_WRITE_4(sc, DOTG_HCSPLT(td->channel[0]), td->hcsplt);
hcchar = td->hcchar;
hcchar &= ~(HCCHAR_EPDIR_IN | HCCHAR_EPTYPE_MASK);
hcchar |= UE_CONTROL << HCCHAR_EPTYPE_SHIFT;
/* must enable channel before writing data to FIFO */
- DWC_OTG_WRITE_4(sc, DOTG_HCCHAR(td->channel), hcchar);
+ DWC_OTG_WRITE_4(sc, DOTG_HCCHAR(td->channel[0]), hcchar);
busy:
return (1); /* busy */
@@ -1060,50 +1097,51 @@ dwc_otg_host_rate_check_interrupt(struct dwc_otg_softc *sc, struct dwc_otg_td *t
static uint8_t
dwc_otg_host_rate_check(struct dwc_otg_softc *sc, struct dwc_otg_td *td)
{
+ uint8_t frame_num = (uint8_t)sc->sc_last_frame_num;
+
if (td->ep_type == UE_ISOCHRONOUS) {
/* non TT isochronous traffic */
- if ((td->tmr_val != 0) ||
- (sc->sc_last_frame_num & (td->tmr_res - 1))) {
+ if (frame_num & (td->tmr_res - 1))
goto busy;
- }
- td->tmr_val = 1; /* executed */
+ if ((frame_num ^ td->tmr_val) & td->tmr_res)
+ goto busy;
+ td->tmr_val = td->tmr_res + sc->sc_last_frame_num;
td->toggle = 0;
-
+ return (0);
} else if (td->ep_type == UE_INTERRUPT) {
if (!td->tt_scheduled)
goto busy;
td->tt_scheduled = 0;
+ return (0);
} else if (td->did_nak != 0) {
- uint8_t frame_num = (uint8_t)sc->sc_last_frame_num;
/* check if we should pause sending queries for 125us */
if (td->tmr_res == frame_num) {
/* wait a bit */
dwc_otg_enable_sof_irq(sc);
goto busy;
}
- /* query for data one more time */
- td->tmr_res = frame_num;
- td->did_nak = 0;
} else if (td->set_toggle) {
td->set_toggle = 0;
td->toggle = 1;
}
+ /* query for data one more time */
+ td->tmr_res = frame_num;
+ td->did_nak = 0;
return (0);
busy:
return (1);
}
static uint8_t
-dwc_otg_host_data_rx_sub(struct dwc_otg_softc *sc, struct dwc_otg_td *td)
+dwc_otg_host_data_rx_sub(struct dwc_otg_softc *sc, struct dwc_otg_td *td,
+ uint8_t channel)
{
uint32_t count;
- uint8_t channel;
/* check endpoint status */
if (sc->sc_last_rx_status == 0)
goto busy;
- channel = td->channel;
if (channel >= DWC_OTG_MAX_CHANNELS)
goto busy;
@@ -1128,21 +1166,22 @@ dwc_otg_host_data_rx_sub(struct dwc_otg_softc *sc, struct dwc_otg_td *td)
/* get the packet byte count */
count = GRXSTSRD_BCNT_GET(sc->sc_last_rx_status);
- /* check for isochronous transfer or high-speed bandwidth endpoint */
- if (td->ep_type == UE_ISOCHRONOUS || td->max_packet_count > 1) {
- if ((sc->sc_last_rx_status & GRXSTSRD_DPID_MASK) != GRXSTSRD_DPID_DATA0) {
+ /* check for ISOCHRONOUS endpoint */
+ if (td->ep_type == UE_ISOCHRONOUS) {
+ if ((sc->sc_last_rx_status & GRXSTSRD_DPID_MASK) !=
+ GRXSTSRD_DPID_DATA0) {
+ /* more data to be received */
td->tt_xactpos = HCSPLT_XACTPOS_MIDDLE;
} else {
+ /* all data received */
td->tt_xactpos = HCSPLT_XACTPOS_BEGIN;
-
/* verify the packet byte count */
- if (count < td->max_packet_size) {
+ if (count != td->remainder) {
/* we have a short packet */
td->short_pkt = 1;
td->got_short = 1;
}
}
- td->toggle = 0;
} else {
/* verify the packet byte count */
if (count != td->max_packet_size) {
@@ -1194,15 +1233,17 @@ complete:
static uint8_t
dwc_otg_host_data_rx(struct dwc_otg_softc *sc, struct dwc_otg_td *td)
{
- uint32_t hcint;
+ uint32_t hcint = 0;
uint32_t hcchar;
uint8_t delta;
uint8_t channel;
+ uint8_t x;
- channel = td->channel;
-
- if (channel < DWC_OTG_MAX_CHANNELS) {
- hcint = sc->sc_chan_state[channel].hcint;
+ for (x = 0; x != td->max_packet_count; x++) {
+ channel = td->channel[x];
+ if (channel >= DWC_OTG_MAX_CHANNELS)
+ continue;
+ hcint |= sc->sc_chan_state[channel].hcint;
DPRINTF("CH=%d ST=%d HCINT=0x%08x HCCHAR=0x%08x HCTSIZ=0x%08x\n",
channel, td->state, hcint,
@@ -1230,19 +1271,17 @@ dwc_otg_host_data_rx(struct dwc_otg_softc *sc, struct dwc_otg_td *td)
}
/* check channels for data, if any */
- if (dwc_otg_host_data_rx_sub(sc, td))
+ if (dwc_otg_host_data_rx_sub(sc, td, channel))
goto complete;
/* refresh interrupt status */
- hcint = sc->sc_chan_state[channel].hcint;
+ hcint |= sc->sc_chan_state[channel].hcint;
if (hcint & (HCINT_ERRORS | HCINT_RETRY |
HCINT_ACK | HCINT_NYET)) {
if (!(hcint & HCINT_ERRORS))
td->errcnt = 0;
}
- } else {
- hcint = 0;
}
switch (td->state) {
@@ -1269,6 +1308,8 @@ dwc_otg_host_data_rx(struct dwc_otg_softc *sc, struct dwc_otg_td *td)
td->toggle ^= 1;
goto receive_pkt;
}
+ } else if (td->ep_type == UE_ISOCHRONOUS) {
+ goto complete;
}
td->did_nak = 1;
td->tt_scheduled = 0;
@@ -1292,12 +1333,12 @@ dwc_otg_host_data_rx(struct dwc_otg_softc *sc, struct dwc_otg_td *td)
if (td->ep_type == UE_ISOCHRONOUS) {
/* check if we are complete */
- if ((td->remainder == 0) ||
- (td->tt_xactpos == HCSPLT_XACTPOS_BEGIN)) {
+ if (td->tt_xactpos == HCSPLT_XACTPOS_BEGIN) {
goto complete;
+ } else {
+ /* get more packets */
+ goto busy;
}
- /* get another packet */
- goto receive_pkt;
} else {
/* check if we are complete */
if ((td->remainder == 0) || (td->got_short != 0)) {
@@ -1365,8 +1406,7 @@ receive_pkt:
}
/* complete split */
td->hcsplt |= HCSPLT_COMPSPLT;
- } else if (td->tt_xactpos == HCSPLT_XACTPOS_BEGIN &&
- dwc_otg_host_rate_check(sc, td)) {
+ } else if (dwc_otg_host_rate_check(sc, td)) {
td->state = DWC_CHAN_ST_WAIT_C_PKT;
goto busy;
}
@@ -1377,8 +1417,6 @@ receive_pkt:
goto busy;
}
- channel = td->channel;
-
/* set toggle, if any */
if (td->set_toggle) {
td->set_toggle = 0;
@@ -1387,28 +1425,31 @@ receive_pkt:
td->state = DWC_CHAN_ST_WAIT_ANE;
- /* receive one packet */
- DWC_OTG_WRITE_4(sc, DOTG_HCTSIZ(channel),
- (td->max_packet_size << HCTSIZ_XFERSIZE_SHIFT) |
- (1 << HCTSIZ_PKTCNT_SHIFT) |
- (td->toggle ? (HCTSIZ_PID_DATA1 << HCTSIZ_PID_SHIFT) :
- (HCTSIZ_PID_DATA0 << HCTSIZ_PID_SHIFT)));
+ for (x = 0; x != td->max_packet_count; x++) {
+ channel = td->channel[x];
- DWC_OTG_WRITE_4(sc, DOTG_HCSPLT(channel), td->hcsplt);
+ /* receive one packet */
+ DWC_OTG_WRITE_4(sc, DOTG_HCTSIZ(channel),
+ (td->max_packet_size << HCTSIZ_XFERSIZE_SHIFT) |
+ (1 << HCTSIZ_PKTCNT_SHIFT) |
+ (td->toggle ? (HCTSIZ_PID_DATA1 << HCTSIZ_PID_SHIFT) :
+ (HCTSIZ_PID_DATA0 << HCTSIZ_PID_SHIFT)));
- hcchar = td->hcchar;
- hcchar |= HCCHAR_EPDIR_IN;
+ DWC_OTG_WRITE_4(sc, DOTG_HCSPLT(channel), td->hcsplt);
- /* receive complete split ASAP */
- if ((sc->sc_last_frame_num & 1) != 0 &&
- (td->ep_type == UE_INTERRUPT || td->ep_type == UE_ISOCHRONOUS))
- hcchar |= HCCHAR_ODDFRM;
- else
- hcchar &= ~HCCHAR_ODDFRM;
+ hcchar = td->hcchar;
+ hcchar |= HCCHAR_EPDIR_IN;
- /* must enable channel before data can be received */
- DWC_OTG_WRITE_4(sc, DOTG_HCCHAR(channel), hcchar);
+ /* receive complete split ASAP */
+ if ((sc->sc_last_frame_num & 1) != 0 &&
+ td->ep_type == UE_ISOCHRONOUS)
+ hcchar |= HCCHAR_ODDFRM;
+ else
+ hcchar &= ~HCCHAR_ODDFRM;
+ /* must enable channel before data can be received */
+ DWC_OTG_WRITE_4(sc, DOTG_HCCHAR(channel), hcchar);
+ }
/* wait until next slot before trying complete split */
td->tt_complete_slot = sc->sc_last_frame_num + 1;
@@ -1437,7 +1478,7 @@ receive_spkt:
goto busy;
}
- channel = td->channel;
+ channel = td->channel[0];
td->hcsplt &= ~HCSPLT_COMPSPLT;
td->state = DWC_CHAN_ST_WAIT_S_ANE;
@@ -1450,7 +1491,7 @@ receive_spkt:
/* send after next SOF event */
if ((sc->sc_last_frame_num & 1) == 0 &&
- (td->ep_type == UE_INTERRUPT || td->ep_type == UE_ISOCHRONOUS))
+ td->ep_type == UE_ISOCHRONOUS)
td->hcchar |= HCCHAR_ODDFRM;
else
td->hcchar &= ~HCCHAR_ODDFRM;
@@ -1605,10 +1646,12 @@ dwc_otg_host_data_tx(struct dwc_otg_softc *sc, struct dwc_otg_td *td)
uint32_t hcchar;
uint8_t delta;
uint8_t channel;
+ uint8_t x;
dwc_otg_host_dump_rx(sc, td);
- channel = td->channel;
+ /* check that last channel is complete */
+ channel = td->channel[td->npkt];
if (channel < DWC_OTG_MAX_CHANNELS) {
hcint = sc->sc_chan_state[channel].hcint;
@@ -1658,7 +1701,11 @@ dwc_otg_host_data_tx(struct dwc_otg_softc *sc, struct dwc_otg_td *td)
td->offset += td->tx_bytes;
td->remainder -= td->tx_bytes;
td->toggle ^= 1;
- td->did_nak = 0;
+ /* check if next response will be a NAK */
+ if (hcint & HCINT_NYET)
+ td->did_nak = 1;
+ else
+ td->did_nak = 0;
td->tt_scheduled = 0;
/* check remainder */
@@ -1715,33 +1762,13 @@ dwc_otg_host_data_tx(struct dwc_otg_softc *sc, struct dwc_otg_td *td)
goto send_cpkt;
case DWC_CHAN_ST_TX_WAIT_ISOC:
-
- /* Check if isochronous OUT traffic is complete */
+ /* Check if ISOCHRONOUS OUT traffic is complete */
if ((hcint & HCINT_HCH_DONE_MASK) == 0)
break;
td->offset += td->tx_bytes;
td->remainder -= td->tx_bytes;
-
- if (td->hcsplt != 0 || td->remainder == 0)
- goto complete;
-
- /* check for next packet */
- if (td->max_packet_count > 1)
- td->tt_xactpos++;
-
- /* free existing channel, if any */
- dwc_otg_host_channel_free(sc, td);
-
- td->state = DWC_CHAN_ST_TX_PKT_ISOC;
-
- /* FALLTHROUGH */
-
- case DWC_CHAN_ST_TX_PKT_ISOC:
- if (dwc_otg_host_channel_alloc(sc, td, 1))
- break;
- channel = td->channel;
- goto send_isoc_pkt;
+ goto complete;
default:
break;
}
@@ -1775,8 +1802,6 @@ send_pkt:
goto busy;
}
- channel = td->channel;
-
/* set toggle, if any */
if (td->set_toggle) {
td->set_toggle = 0;
@@ -1784,8 +1809,7 @@ send_pkt:
}
if (td->ep_type == UE_ISOCHRONOUS) {
-send_isoc_pkt:
- /* Isochronous OUT transfers don't have any ACKs */
+ /* ISOCHRONOUS OUT transfers don't have any ACKs */
td->state = DWC_CHAN_ST_TX_WAIT_ISOC;
td->hcsplt &= ~HCSPLT_COMPSPLT;
if (td->hcsplt != 0) {
@@ -1799,123 +1823,110 @@ send_isoc_pkt:
/* Update transaction position */
td->hcsplt &= ~HCSPLT_XACTPOS_MASK;
td->hcsplt |= (HCSPLT_XACTPOS_ALL << HCSPLT_XACTPOS_SHIFT);
- } else {
- /* send one packet at a time */
- count = td->max_packet_size;
- if (td->remainder < count) {
- /* we have a short packet */
- td->short_pkt = 1;
- count = td->remainder;
- }
}
} else if (td->hcsplt != 0) {
-
td->hcsplt &= ~HCSPLT_COMPSPLT;
-
/* Wait for ACK/NAK/ERR from TT */
td->state = DWC_CHAN_ST_WAIT_S_ANE;
-
- /* send one packet at a time */
- count = td->max_packet_size;
- if (td->remainder < count) {
- /* we have a short packet */
- td->short_pkt = 1;
- count = td->remainder;
- }
} else {
/* Wait for ACK/NAK/STALL from device */
td->state = DWC_CHAN_ST_WAIT_ANE;
+ }
+
+ td->tx_bytes = 0;
+
+ for (x = 0; x != td->max_packet_count; x++) {
+ uint32_t rem_bytes;
+
+ channel = td->channel[x];
/* send one packet at a time */
count = td->max_packet_size;
- if (td->remainder < count) {
+ rem_bytes = td->remainder - td->tx_bytes;
+ if (rem_bytes < count) {
/* we have a short packet */
td->short_pkt = 1;
- count = td->remainder;
- }
- }
-
- /* check for High-Speed multi-packets */
- if ((td->hcsplt == 0) && (td->max_packet_count > 1)) {
- if (td->npkt == 0) {
- if (td->remainder >= (3 * td->max_packet_size))
- td->npkt = 3;
- else if (td->remainder >= (2 * td->max_packet_size))
- td->npkt = 2;
- else
- td->npkt = 1;
-
- if (td->npkt > td->max_packet_count)
- td->npkt = td->max_packet_count;
-
- td->tt_xactpos = 1; /* overload */
+ count = rem_bytes;
}
- if (td->tt_xactpos == td->npkt) {
- if (td->npkt == 1) {
+ if (count == rem_bytes) {
+ /* last packet */
+ switch (x) {
+ case 0:
DWC_OTG_WRITE_4(sc, DOTG_HCTSIZ(channel),
(count << HCTSIZ_XFERSIZE_SHIFT) |
(1 << HCTSIZ_PKTCNT_SHIFT) |
- (HCTSIZ_PID_DATA0 << HCTSIZ_PID_SHIFT));
- } else if (td->npkt == 2) {
+ (td->toggle ? (HCTSIZ_PID_DATA1 << HCTSIZ_PID_SHIFT) :
+ (HCTSIZ_PID_DATA0 << HCTSIZ_PID_SHIFT)));
+ break;
+ case 1:
DWC_OTG_WRITE_4(sc, DOTG_HCTSIZ(channel),
(count << HCTSIZ_XFERSIZE_SHIFT) |
(1 << HCTSIZ_PKTCNT_SHIFT) |
(HCTSIZ_PID_DATA1 << HCTSIZ_PID_SHIFT));
- } else {
+ break;
+ default:
DWC_OTG_WRITE_4(sc, DOTG_HCTSIZ(channel),
(count << HCTSIZ_XFERSIZE_SHIFT) |
(1 << HCTSIZ_PKTCNT_SHIFT) |
(HCTSIZ_PID_DATA2 << HCTSIZ_PID_SHIFT));
+ break;
}
- td->npkt = 0;
- } else {
+ } else if (td->ep_type == UE_ISOCHRONOUS &&
+ td->max_packet_count > 1) {
+ /* ISOCHRONOUS multi packet */
DWC_OTG_WRITE_4(sc, DOTG_HCTSIZ(channel),
(count << HCTSIZ_XFERSIZE_SHIFT) |
(1 << HCTSIZ_PKTCNT_SHIFT) |
(HCTSIZ_PID_MDATA << HCTSIZ_PID_SHIFT));
+ } else {
+ /* TODO: HCTSIZ_DOPNG */
+ /* standard BULK/INTERRUPT/CONTROL packet */
+ DWC_OTG_WRITE_4(sc, DOTG_HCTSIZ(channel),
+ (count << HCTSIZ_XFERSIZE_SHIFT) |
+ (1 << HCTSIZ_PKTCNT_SHIFT) |
+ (td->toggle ? (HCTSIZ_PID_DATA1 << HCTSIZ_PID_SHIFT) :
+ (HCTSIZ_PID_DATA0 << HCTSIZ_PID_SHIFT)));
}
- } else {
- /* TODO: HCTSIZ_DOPNG */
- DWC_OTG_WRITE_4(sc, DOTG_HCTSIZ(channel),
- (count << HCTSIZ_XFERSIZE_SHIFT) |
- (1 << HCTSIZ_PKTCNT_SHIFT) |
- (td->toggle ? (HCTSIZ_PID_DATA1 << HCTSIZ_PID_SHIFT) :
- (HCTSIZ_PID_DATA0 << HCTSIZ_PID_SHIFT)));
- }
+ DWC_OTG_WRITE_4(sc, DOTG_HCSPLT(channel), td->hcsplt);
- DWC_OTG_WRITE_4(sc, DOTG_HCSPLT(channel), td->hcsplt);
+ hcchar = td->hcchar;
+ hcchar &= ~HCCHAR_EPDIR_IN;
- hcchar = td->hcchar;
- hcchar &= ~HCCHAR_EPDIR_IN;
+ /* send after next SOF event */
+ if ((sc->sc_last_frame_num & 1) == 0 &&
+ td->ep_type == UE_ISOCHRONOUS)
+ hcchar |= HCCHAR_ODDFRM;
+ else
+ hcchar &= ~HCCHAR_ODDFRM;
- /* send after next SOF event */
- if ((sc->sc_last_frame_num & 1) == 0 &&
- (td->ep_type == UE_INTERRUPT || td->ep_type == UE_ISOCHRONOUS))
- hcchar |= HCCHAR_ODDFRM;
- else
- hcchar &= ~HCCHAR_ODDFRM;
+ /* must enable before writing data to FIFO */
+ DWC_OTG_WRITE_4(sc, DOTG_HCCHAR(channel), hcchar);
- /* must enable before writing data to FIFO */
- DWC_OTG_WRITE_4(sc, DOTG_HCCHAR(channel), hcchar);
+ if (count != 0) {
+ /* clear topmost word before copy */
+ sc->sc_tx_bounce_buffer[(count - 1) / 4] = 0;
- if (count != 0) {
+ /* copy out data */
+ usbd_copy_out(td->pc, td->offset + td->tx_bytes,
+ sc->sc_tx_bounce_buffer, count);
- /* clear topmost word before copy */
- sc->sc_tx_bounce_buffer[(count - 1) / 4] = 0;
+ /* transfer data into FIFO */
+ bus_space_write_region_4(sc->sc_io_tag, sc->sc_io_hdl,
+ DOTG_DFIFO(channel),
+ sc->sc_tx_bounce_buffer, (count + 3) / 4);
+ }
- /* copy out data */
- usbd_copy_out(td->pc, td->offset,
- sc->sc_tx_bounce_buffer, count);
+ /* store number of bytes transmitted */
+ td->tx_bytes += count;
- /* transfer data into FIFO */
- bus_space_write_region_4(sc->sc_io_tag, sc->sc_io_hdl,
- DOTG_DFIFO(channel),
- sc->sc_tx_bounce_buffer, (count + 3) / 4);
+ /* store last packet index */
+ td->npkt = x;
+
+ /* check for last packet */
+ if (count == rem_bytes)
+ break;
}
-
- /* store number of bytes transmitted */
- td->tx_bytes = count;
goto busy;
send_cpkt:
@@ -1941,7 +1952,7 @@ send_cpkt:
goto busy;
}
- channel = td->channel;
+ channel = td->channel[0];
td->hcsplt |= HCSPLT_COMPSPLT;
td->state = DWC_CHAN_ST_WAIT_C_ANE;
@@ -1956,7 +1967,7 @@ send_cpkt:
/* receive complete split ASAP */
if ((sc->sc_last_frame_num & 1) != 0 &&
- (td->ep_type == UE_INTERRUPT || td->ep_type == UE_ISOCHRONOUS))
+ td->ep_type == UE_ISOCHRONOUS)
hcchar |= HCCHAR_ODDFRM;
else
hcchar &= ~HCCHAR_ODDFRM;
@@ -2383,9 +2394,6 @@ dwc_otg_update_host_transfer_schedule_locked(struct dwc_otg_softc *sc)
if ((td->hcchar & HCCHAR_EPDIR_IN) != 0)
continue;
- /* execute more frames */
- td->tmr_val = 0;
-
sc->sc_needsof = 1;
if (td->hcsplt == 0 || td->tt_scheduled != 0)
@@ -2417,9 +2425,6 @@ dwc_otg_update_host_transfer_schedule_locked(struct dwc_otg_softc *sc)
if ((td->hcchar & HCCHAR_EPDIR_IN) == 0)
continue;
- /* execute more frames */
- td->tmr_val = 0;
-
sc->sc_needsof = 1;
if (td->hcsplt == 0 || td->tt_scheduled != 0)
@@ -2513,10 +2518,10 @@ dwc_otg_update_host_transfer_schedule_locked(struct dwc_otg_softc *sc)
TAILQ_CONCAT(&head, &sc->sc_bus.intr_q.head, wait_entry);
TAILQ_CONCAT(&sc->sc_bus.intr_q.head, &head, wait_entry);
- /* put non-TT BULK transfers last */
+ /* put non-TT non-ISOCHRONOUS transfers last */
TAILQ_FOREACH_SAFE(xfer, &sc->sc_bus.intr_q.head, wait_entry, xfer_next) {
td = xfer->td_transfer_cache;
- if (td == NULL || td->hcsplt != 0 || td->ep_type != UE_BULK)
+ if (td == NULL || td->hcsplt != 0 || td->ep_type == UE_ISOCHRONOUS)
continue;
TAILQ_REMOVE(&sc->sc_bus.intr_q.head, xfer, wait_entry);
TAILQ_INSERT_TAIL(&head, xfer, wait_entry);
@@ -2551,11 +2556,19 @@ static void
dwc_otg_interrupt_poll_locked(struct dwc_otg_softc *sc)
{
struct usb_xfer *xfer;
- uint32_t count = 0;
+ uint32_t count;
uint32_t temp;
uint8_t got_rx_status;
uint8_t x;
+ if (sc->sc_flags.status_device_mode == 0) {
+ /*
+ * Update host transfer schedule, so that new
+ * transfers can be issued:
+ */
+ dwc_otg_update_host_transfer_schedule_locked(sc);
+ }
+ count = 0;
repeat:
if (++count == 16) {
/* give other interrupts a chance */
@@ -2659,12 +2672,6 @@ repeat:
sc->sc_irq_mask &= ~GINTMSK_RXFLVLMSK;
DWC_OTG_WRITE_4(sc, DOTG_GINTMSK, sc->sc_irq_mask);
}
-
- if (sc->sc_flags.status_device_mode == 0 && sc->sc_xfer_complete == 0) {
- /* update host transfer schedule, so that new transfers can be issued */
- if (dwc_otg_update_host_transfer_schedule_locked(sc))
- goto repeat;
- }
}
static void
@@ -2944,12 +2951,6 @@ dwc_otg_interrupt(void *arg)
/* complete FIFOs, if any */
dwc_otg_interrupt_complete_locked(sc);
-
- if (sc->sc_flags.status_device_mode == 0) {
- /* update host transfer schedule, so that new transfers can be issued */
- if (dwc_otg_update_host_transfer_schedule_locked(sc))
- dwc_otg_interrupt_poll_locked(sc);
- }
}
USB_BUS_SPIN_UNLOCK(&sc->sc_bus);
USB_BUS_UNLOCK(&sc->sc_bus);
@@ -2982,7 +2983,9 @@ dwc_otg_setup_standard_chain_sub(struct dwc_otg_std_temp *temp)
td->set_toggle = 0;
td->got_short = 0;
td->did_nak = 0;
- td->channel = DWC_OTG_MAX_CHANNELS;
+ td->channel[0] = DWC_OTG_MAX_CHANNELS;
+ td->channel[1] = DWC_OTG_MAX_CHANNELS;
+ td->channel[2] = DWC_OTG_MAX_CHANNELS;
td->state = 0;
td->errcnt = 0;
td->tt_scheduled = 0;
@@ -3247,8 +3250,10 @@ dwc_otg_setup_standard_chain(struct usb_xfer *xfer)
td->tmr_val = sc->sc_tmr_val + ival;
td->tmr_res = ival;
} else if (td->ep_type == UE_ISOCHRONOUS) {
- td->tmr_val = 0;
td->tmr_res = 1;
+ td->tmr_val = sc->sc_last_frame_num;
+ if (td->hcchar & HCCHAR_EPDIR_IN)
+ td->tmr_val++;
} else {
td->tmr_val = 0;
td->tmr_res = (uint8_t)sc->sc_last_frame_num;
@@ -3258,10 +3263,8 @@ dwc_otg_setup_standard_chain(struct usb_xfer *xfer)
hcsplt = 0;
if (td->ep_type == UE_INTERRUPT) {
uint32_t ival;
-#if 0
hcchar |= ((xfer->max_packet_count & 3)
<< HCCHAR_MC_SHIFT);
-#endif
ival = xfer->interval / DWC_OTG_HOST_TIMER_RATE;
if (ival == 0)
ival = 1;
@@ -3272,8 +3275,11 @@ dwc_otg_setup_standard_chain(struct usb_xfer *xfer)
} else if (td->ep_type == UE_ISOCHRONOUS) {
hcchar |= ((xfer->max_packet_count & 3)
<< HCCHAR_MC_SHIFT);
- td->tmr_val = 0;
td->tmr_res = 1 << usbd_xfer_get_fps_shift(xfer);
+ td->tmr_val = sc->sc_last_frame_num;
+ if (td->hcchar & HCCHAR_EPDIR_IN)
+ td->tmr_val += td->tmr_res;
+
} else {
td->tmr_val = 0;
td->tmr_res = (uint8_t)sc->sc_last_frame_num;
@@ -3330,6 +3336,19 @@ dwc_otg_start_standard_chain(struct usb_xfer *xfer)
dwc_otg_xfer_do_fifo(sc, xfer);
if (dwc_otg_xfer_do_complete_locked(sc, xfer))
goto done;
+ } else {
+ struct dwc_otg_td *td = xfer->td_transfer_cache;
+ if (td->ep_type == UE_ISOCHRONOUS &&
+ (td->hcchar & HCCHAR_EPDIR_IN) == 0) {
+ /*
+ * Need to start ISOCHRONOUS OUT transfer ASAP
+ * because execution is delayed by one 125us
+ * microframe:
+ */
+ dwc_otg_xfer_do_fifo(sc, xfer);
+ if (dwc_otg_xfer_do_complete_locked(sc, xfer))
+ goto done;
+ }
}
/* put transfer on interrupt queue */
@@ -3950,11 +3969,6 @@ dwc_otg_do_poll(struct usb_bus *bus)
USB_BUS_SPIN_LOCK(&sc->sc_bus);
dwc_otg_interrupt_poll_locked(sc);
dwc_otg_interrupt_complete_locked(sc);
- if (sc->sc_flags.status_device_mode == 0) {
- /* update host transfer schedule, so that new transfers can be issued */
- if (dwc_otg_update_host_transfer_schedule_locked(sc))
- dwc_otg_interrupt_poll_locked(sc);
- }
USB_BUS_SPIN_UNLOCK(&sc->sc_bus);
USB_BUS_UNLOCK(&sc->sc_bus);
}
@@ -4728,6 +4742,9 @@ dwc_otg_xfer_setup(struct usb_setup_params *parm)
/* init TD */
td->max_packet_size = xfer->max_packet_size;
td->max_packet_count = xfer->max_packet_count;
+ /* range check */
+ if (td->max_packet_count == 0 || td->max_packet_count > 3)
+ td->max_packet_count = 1;
td->ep_no = ep_no;
td->ep_type = ep_type;
td->obj_next = last_obj;
@@ -4766,12 +4783,13 @@ dwc_otg_ep_init(struct usb_device *udev, struct usb_endpoint_descriptor *edesc,
return;
}
} else {
- if (udev->speed == USB_SPEED_HIGH) {
- if ((UGETW(edesc->wMaxPacketSize) >> 11) & 3) {
- /* high bandwidth endpoint - not tested */
- DPRINTF("High Bandwidth Endpoint - not tested\n");
- return;
- }
+ if (udev->speed == USB_SPEED_HIGH &&
+ (edesc->wMaxPacketSize[1] & 0x18) != 0 &&
+ (edesc->bmAttributes & UE_XFERTYPE) != UE_ISOCHRONOUS) {
+ /* not supported */
+ DPRINTFN(-1, "Non-isochronous high bandwidth "
+ "endpoint not supported\n");
+ return;
}
}
if ((edesc->bmAttributes & UE_XFERTYPE) == UE_ISOCHRONOUS)
diff --git a/sys/dev/usb/controller/dwc_otg.h b/sys/dev/usb/controller/dwc_otg.h
index 39c9529..f5e9887 100644
--- a/sys/dev/usb/controller/dwc_otg.h
+++ b/sys/dev/usb/controller/dwc_otg.h
@@ -69,7 +69,7 @@ struct dwc_otg_td {
uint8_t tmr_val;
uint8_t ep_no;
uint8_t ep_type;
- uint8_t channel;
+ uint8_t channel[3];
uint8_t tt_index; /* TT data */
uint8_t tt_start_slot; /* TT data */
uint8_t tt_complete_slot; /* TT data */
@@ -80,8 +80,7 @@ struct dwc_otg_td {
#define DWC_CHAN_ST_WAIT_S_ANE 2
#define DWC_CHAN_ST_WAIT_C_ANE 3
#define DWC_CHAN_ST_WAIT_C_PKT 4
-#define DWC_CHAN_ST_TX_PKT_ISOC 5
-#define DWC_CHAN_ST_TX_WAIT_ISOC 6
+#define DWC_CHAN_ST_TX_WAIT_ISOC 5
uint8_t error_any:1;
uint8_t error_stall:1;
uint8_t alt_next:1;
diff --git a/sys/dev/usb/controller/usb_controller.c b/sys/dev/usb/controller/usb_controller.c
index 92ea6c5..9f7ce24 100644
--- a/sys/dev/usb/controller/usb_controller.c
+++ b/sys/dev/usb/controller/usb_controller.c
@@ -231,7 +231,8 @@ usb_detach(device_t dev)
/* Get rid of USB callback processes */
usb_proc_free(USB_BUS_GIANT_PROC(bus));
- usb_proc_free(USB_BUS_NON_GIANT_PROC(bus));
+ usb_proc_free(USB_BUS_NON_GIANT_ISOC_PROC(bus));
+ usb_proc_free(USB_BUS_NON_GIANT_BULK_PROC(bus));
/* Get rid of USB explore process */
@@ -395,7 +396,8 @@ usb_bus_explore(struct usb_proc_msg *pm)
*/
usb_proc_rewakeup(USB_BUS_CONTROL_XFER_PROC(bus));
usb_proc_rewakeup(USB_BUS_GIANT_PROC(bus));
- usb_proc_rewakeup(USB_BUS_NON_GIANT_PROC(bus));
+ usb_proc_rewakeup(USB_BUS_NON_GIANT_ISOC_PROC(bus));
+ usb_proc_rewakeup(USB_BUS_NON_GIANT_BULK_PROC(bus));
#endif
USB_BUS_UNLOCK(bus);
@@ -860,9 +862,13 @@ usb_attach_sub(device_t dev, struct usb_bus *bus)
&bus->bus_mtx, device_get_nameunit(dev), USB_PRI_MED)) {
device_printf(dev, "WARNING: Creation of USB Giant "
"callback process failed.\n");
- } else if (usb_proc_create(USB_BUS_NON_GIANT_PROC(bus),
+ } else if (usb_proc_create(USB_BUS_NON_GIANT_ISOC_PROC(bus),
+ &bus->bus_mtx, device_get_nameunit(dev), USB_PRI_HIGHEST)) {
+ device_printf(dev, "WARNING: Creation of USB non-Giant ISOC "
+ "callback process failed.\n");
+ } else if (usb_proc_create(USB_BUS_NON_GIANT_BULK_PROC(bus),
&bus->bus_mtx, device_get_nameunit(dev), USB_PRI_HIGH)) {
- device_printf(dev, "WARNING: Creation of USB non-Giant "
+ device_printf(dev, "WARNING: Creation of USB non-Giant BULK "
"callback process failed.\n");
} else if (usb_proc_create(USB_BUS_EXPLORE_PROC(bus),
&bus->bus_mtx, device_get_nameunit(dev), USB_PRI_MED)) {
diff --git a/sys/dev/usb/usb_bus.h b/sys/dev/usb/usb_bus.h
index bdd1681..3ceeb1e 100644
--- a/sys/dev/usb/usb_bus.h
+++ b/sys/dev/usb/usb_bus.h
@@ -57,19 +57,26 @@ struct usb_bus {
struct root_hold_token *bus_roothold;
#endif
+/* convenience macros */
+#define USB_BUS_TT_PROC(bus) USB_BUS_NON_GIANT_ISOC_PROC(bus)
+#define USB_BUS_CS_PROC(bus) USB_BUS_NON_GIANT_ISOC_PROC(bus)
+
#if USB_HAVE_PER_BUS_PROCESS
#define USB_BUS_GIANT_PROC(bus) (&(bus)->giant_callback_proc)
-#define USB_BUS_NON_GIANT_PROC(bus) (&(bus)->non_giant_callback_proc)
+#define USB_BUS_NON_GIANT_ISOC_PROC(bus) (&(bus)->non_giant_isoc_callback_proc)
+#define USB_BUS_NON_GIANT_BULK_PROC(bus) (&(bus)->non_giant_bulk_callback_proc)
#define USB_BUS_EXPLORE_PROC(bus) (&(bus)->explore_proc)
#define USB_BUS_CONTROL_XFER_PROC(bus) (&(bus)->control_xfer_proc)
-
/*
- * There are two callback processes. One for Giant locked
- * callbacks. One for non-Giant locked callbacks. This should
- * avoid congestion and reduce response time in most cases.
+ * There are three callback processes. One for Giant locked
+ * callbacks. One for non-Giant locked non-periodic callbacks
+ * and one for non-Giant locked periodic callbacks. This
+ * should avoid congestion and reduce response time in most
+ * cases.
*/
struct usb_process giant_callback_proc;
- struct usb_process non_giant_callback_proc;
+ struct usb_process non_giant_isoc_callback_proc;
+ struct usb_process non_giant_bulk_callback_proc;
/* Explore process */
struct usb_process explore_proc;
diff --git a/sys/dev/usb/usb_device.c b/sys/dev/usb/usb_device.c
index 5ffc07f..13e2c14 100644
--- a/sys/dev/usb/usb_device.c
+++ b/sys/dev/usb/usb_device.c
@@ -2181,7 +2181,7 @@ usb_free_device(struct usb_device *udev, uint8_t flag)
* anywhere:
*/
USB_BUS_LOCK(udev->bus);
- usb_proc_mwait(USB_BUS_NON_GIANT_PROC(udev->bus),
+ usb_proc_mwait(USB_BUS_CS_PROC(udev->bus),
&udev->cs_msg[0], &udev->cs_msg[1]);
USB_BUS_UNLOCK(udev->bus);
diff --git a/sys/dev/usb/usb_hub.c b/sys/dev/usb/usb_hub.c
index 2f1459c..a54fa2e 100644
--- a/sys/dev/usb/usb_hub.c
+++ b/sys/dev/usb/usb_hub.c
@@ -346,7 +346,7 @@ uhub_tt_buffer_reset_async_locked(struct usb_device *child, struct usb_endpoint
}
up->req_reset_tt = req;
/* get reset transfer started */
- usb_proc_msignal(USB_BUS_NON_GIANT_PROC(udev->bus),
+ usb_proc_msignal(USB_BUS_TT_PROC(udev->bus),
&hub->tt_msg[0], &hub->tt_msg[1]);
}
#endif
@@ -1579,7 +1579,7 @@ uhub_detach(device_t dev)
#if USB_HAVE_TT_SUPPORT
/* Make sure our TT messages are not queued anywhere */
USB_BUS_LOCK(bus);
- usb_proc_mwait(USB_BUS_NON_GIANT_PROC(bus),
+ usb_proc_mwait(USB_BUS_TT_PROC(bus),
&hub->tt_msg[0], &hub->tt_msg[1]);
USB_BUS_UNLOCK(bus);
#endif
diff --git a/sys/dev/usb/usb_pf.c b/sys/dev/usb/usb_pf.c
index 468eafb..82ad8e4 100644
--- a/sys/dev/usb/usb_pf.c
+++ b/sys/dev/usb/usb_pf.c
@@ -221,7 +221,13 @@ usbpf_clone_destroy(struct if_clone *ifc, struct ifnet *ifp)
ubus = ifp->if_softc;
unit = ifp->if_dunit;
+ /*
+ * Lock USB before clearing the "ifp" pointer, to avoid
+ * clearing the pointer in the middle of a TAP operation:
+ */
+ USB_BUS_LOCK(ubus);
ubus->ifp = NULL;
+ USB_BUS_UNLOCK(ubus);
bpfdetach(ifp);
if_detach(ifp);
if_free(ifp);
diff --git a/sys/dev/usb/usb_process.h b/sys/dev/usb/usb_process.h
index c12cdc4..dd20afd 100644
--- a/sys/dev/usb/usb_process.h
+++ b/sys/dev/usb/usb_process.h
@@ -34,6 +34,7 @@
#endif
/* defines */
+#define USB_PRI_HIGHEST PI_SWI(SWI_TTY)
#define USB_PRI_HIGH PI_SWI(SWI_NET)
#define USB_PRI_MED PI_SWI(SWI_CAMBIO)
diff --git a/sys/dev/usb/usb_transfer.c b/sys/dev/usb/usb_transfer.c
index 5650790..783a96c 100644
--- a/sys/dev/usb/usb_transfer.c
+++ b/sys/dev/usb/usb_transfer.c
@@ -872,6 +872,19 @@ done:
}
}
+static uint8_t
+usbd_transfer_setup_has_bulk(const struct usb_config *setup_start,
+ uint16_t n_setup)
+{
+ while (n_setup--) {
+ uint8_t type = setup_start[n_setup].type;
+ if (type == UE_BULK || type == UE_BULK_INTR ||
+ type == UE_TYPE_ANY)
+ return (1);
+ }
+ return (0);
+}
+
/*------------------------------------------------------------------------*
* usbd_transfer_setup - setup an array of USB transfers
*
@@ -1013,9 +1026,12 @@ usbd_transfer_setup(struct usb_device *udev,
else if (xfer_mtx == &Giant)
info->done_p =
USB_BUS_GIANT_PROC(udev->bus);
+ else if (usbd_transfer_setup_has_bulk(setup_start, n_setup))
+ info->done_p =
+ USB_BUS_NON_GIANT_BULK_PROC(udev->bus);
else
info->done_p =
- USB_BUS_NON_GIANT_PROC(udev->bus);
+ USB_BUS_NON_GIANT_ISOC_PROC(udev->bus);
}
/* reset sizes */
@@ -2280,10 +2296,8 @@ usbd_callback_ss_done_defer(struct usb_xfer *xfer)
* will have a Lock Order Reversal, LOR, if we try to
* proceed !
*/
- if (usb_proc_msignal(info->done_p,
- &info->done_m[0], &info->done_m[1])) {
- /* ignore */
- }
+ (void) usb_proc_msignal(info->done_p,
+ &info->done_m[0], &info->done_m[1]);
} else {
/* clear second recurse flag */
pq->recurse_2 = 0;
@@ -2307,23 +2321,26 @@ usbd_callback_wrapper(struct usb_xfer_queue *pq)
struct usb_xfer_root *info = xfer->xroot;
USB_BUS_LOCK_ASSERT(info->bus, MA_OWNED);
- if (!mtx_owned(info->xfer_mtx) && !SCHEDULER_STOPPED()) {
+ if ((pq->recurse_3 != 0 || mtx_owned(info->xfer_mtx) == 0) &&
+ SCHEDULER_STOPPED() == 0) {
/*
* Cases that end up here:
*
* 5) HW interrupt done callback or other source.
+ * 6) HW completed transfer during callback
*/
- DPRINTFN(3, "case 5\n");
+ DPRINTFN(3, "case 5 and 6\n");
/*
* We have to postpone the callback due to the fact we
* will have a Lock Order Reversal, LOR, if we try to
- * proceed !
+ * proceed!
+ *
+ * Postponing the callback also ensures that other USB
+ * transfer queues get a chance.
*/
- if (usb_proc_msignal(info->done_p,
- &info->done_m[0], &info->done_m[1])) {
- /* ignore */
- }
+ (void) usb_proc_msignal(info->done_p,
+ &info->done_m[0], &info->done_m[1]);
return;
}
/*
@@ -2381,8 +2398,11 @@ usbd_callback_wrapper(struct usb_xfer_queue *pq)
}
#if USB_HAVE_PF
- if (xfer->usb_state != USB_ST_SETUP)
+ if (xfer->usb_state != USB_ST_SETUP) {
+ USB_BUS_LOCK(info->bus);
usbpf_xfertap(xfer, USBPF_XFERTAP_DONE);
+ USB_BUS_UNLOCK(info->bus);
+ }
#endif
/* call processing routine */
(xfer->callback) (xfer, xfer->error);
@@ -2694,7 +2714,7 @@ usbd_pipe_start(struct usb_xfer_queue *pq)
} else if (udev->ctrl_xfer[1]) {
info = udev->ctrl_xfer[1]->xroot;
usb_proc_msignal(
- USB_BUS_NON_GIANT_PROC(info->bus),
+ USB_BUS_CS_PROC(info->bus),
&udev->cs_msg[0], &udev->cs_msg[1]);
} else {
/* should not happen */
@@ -3019,9 +3039,11 @@ usb_command_wrapper(struct usb_xfer_queue *pq, struct usb_xfer *xfer)
if (!pq->recurse_1) {
- do {
+ /* clear third recurse flag */
+ pq->recurse_3 = 0;
- /* set both recurse flags */
+ do {
+ /* set two first recurse flags */
pq->recurse_1 = 1;
pq->recurse_2 = 1;
@@ -3040,6 +3062,12 @@ usb_command_wrapper(struct usb_xfer_queue *pq, struct usb_xfer *xfer)
(pq->command) (pq);
DPRINTFN(6, "cb %p (leave)\n", pq->curr);
+ /*
+ * Set third recurse flag to indicate
+ * recursion happened:
+ */
+ pq->recurse_3 = 1;
+
} while (!pq->recurse_2);
/* clear first recurse flag */
@@ -3315,7 +3343,8 @@ usbd_transfer_poll(struct usb_xfer **ppxfer, uint16_t max)
USB_BUS_CONTROL_XFER_PROC(udev->bus)->up_msleep = 0;
USB_BUS_EXPLORE_PROC(udev->bus)->up_msleep = 0;
USB_BUS_GIANT_PROC(udev->bus)->up_msleep = 0;
- USB_BUS_NON_GIANT_PROC(udev->bus)->up_msleep = 0;
+ USB_BUS_NON_GIANT_ISOC_PROC(udev->bus)->up_msleep = 0;
+ USB_BUS_NON_GIANT_BULK_PROC(udev->bus)->up_msleep = 0;
/* poll USB hardware */
(udev->bus->methods->xfer_poll) (udev->bus);
diff --git a/sys/dev/usb/usbdi.h b/sys/dev/usb/usbdi.h
index 09b0ca7..ecd5a81 100644
--- a/sys/dev/usb/usbdi.h
+++ b/sys/dev/usb/usbdi.h
@@ -128,6 +128,8 @@ struct usb_xfer_queue {
void (*command) (struct usb_xfer_queue *pq);
uint8_t recurse_1:1;
uint8_t recurse_2:1;
+ uint8_t recurse_3:1;
+ uint8_t reserved:5;
};
/*
diff --git a/sys/dev/vt/hw/efifb/efifb.c b/sys/dev/vt/hw/efifb/efifb.c
index ec029c8..4184f77 100644
--- a/sys/dev/vt/hw/efifb/efifb.c
+++ b/sys/dev/vt/hw/efifb/efifb.c
@@ -96,7 +96,6 @@ vt_efifb_probe(struct vt_device *vd)
static int
vt_efifb_init(struct vt_device *vd)
{
- int depth, d;
struct fb_info *info;
struct efi_fb *efifb;
caddr_t kmdp;
@@ -116,16 +115,13 @@ vt_efifb_init(struct vt_device *vd)
info->fb_height = efifb->fb_height;
info->fb_width = efifb->fb_width;
- depth = fls(efifb->fb_mask_red);
- d = fls(efifb->fb_mask_green);
- depth = d > depth ? d : depth;
- d = fls(efifb->fb_mask_blue);
- depth = d > depth ? d : depth;
- d = fls(efifb->fb_mask_reserved);
- depth = d > depth ? d : depth;
- info->fb_depth = depth;
+ info->fb_depth = fls(efifb->fb_mask_red | efifb->fb_mask_green |
+ efifb->fb_mask_blue | efifb->fb_mask_reserved);
+ /* Round to a multiple of the bits in a byte. */
+ info->fb_bpp = (info->fb_depth + NBBY - 1) & ~(NBBY - 1);
- info->fb_stride = efifb->fb_stride * (depth / 8);
+ /* Stride in bytes, not pixels */
+ info->fb_stride = efifb->fb_stride * (info->fb_bpp / NBBY);
vt_generate_cons_palette(info->fb_cmap, COLOR_FORMAT_RGB,
efifb->fb_mask_red, ffs(efifb->fb_mask_red) - 1,
@@ -137,16 +133,6 @@ vt_efifb_init(struct vt_device *vd)
info->fb_vbase = (intptr_t)pmap_mapdev_attr(info->fb_pbase,
info->fb_size, VM_MEMATTR_WRITE_COMBINING);
- /* Get pixel storage size. */
- info->fb_bpp = info->fb_stride / info->fb_width * 8;
-
- /*
- * Early FB driver work with static window buffer, so reduce to minimal
- * size, buffer or screen.
- */
- info->fb_width = MIN(info->fb_width, VT_FB_DEFAULT_WIDTH);
- info->fb_height = MIN(info->fb_height, VT_FB_DEFAULT_HEIGHT);
-
vt_fb_init(vd);
return (CN_INTERNAL);
diff --git a/sys/dev/vt/hw/vga/vt_vga.c b/sys/dev/vt/hw/vga/vt_vga.c
index 0b7ebe4..4661f35 100644
--- a/sys/dev/vt/hw/vga/vt_vga.c
+++ b/sys/dev/vt/hw/vga/vt_vga.c
@@ -883,9 +883,9 @@ vga_bitblt_text_txtmode(struct vt_device *vd, const struct vt_window *vw,
/* Convert colors to VGA attributes. */
attr = bg << 4 | fg;
- MEM_WRITE1(sc, 0x18000 + (row * 80 + col) * 2 + 0,
+ MEM_WRITE1(sc, (row * 80 + col) * 2 + 0,
ch);
- MEM_WRITE1(sc, 0x18000 + (row * 80 + col) * 2 + 1,
+ MEM_WRITE1(sc, (row * 80 + col) * 2 + 1,
attr);
}
}
@@ -1226,8 +1226,6 @@ vga_init(struct vt_device *vd)
# error "Architecture not yet supported!"
#endif
- bus_space_map(sc->vga_fb_tag, VGA_MEM_BASE, VGA_MEM_SIZE, 0,
- &sc->vga_fb_handle);
bus_space_map(sc->vga_reg_tag, VGA_REG_BASE, VGA_REG_SIZE, 0,
&sc->vga_reg_handle);
@@ -1236,9 +1234,13 @@ vga_init(struct vt_device *vd)
vd->vd_flags |= VDF_TEXTMODE;
vd->vd_width = 80;
vd->vd_height = 25;
+ bus_space_map(sc->vga_fb_tag, VGA_TXT_BASE, VGA_TXT_SIZE, 0,
+ &sc->vga_fb_handle);
} else {
vd->vd_width = VT_VGA_WIDTH;
vd->vd_height = VT_VGA_HEIGHT;
+ bus_space_map(sc->vga_fb_tag, VGA_MEM_BASE, VGA_MEM_SIZE, 0,
+ &sc->vga_fb_handle);
}
if (vga_initialize(vd, textmode) != 0)
return (CN_DEAD);
diff --git a/sys/dev/vt/hw/vga/vt_vga_reg.h b/sys/dev/vt/hw/vga/vt_vga_reg.h
index 5bfb8ce..cf33a37 100644
--- a/sys/dev/vt/hw/vga/vt_vga_reg.h
+++ b/sys/dev/vt/hw/vga/vt_vga_reg.h
@@ -49,6 +49,8 @@
#define VGA_MEM_BASE 0xA0000
#define VGA_MEM_SIZE 0x10000
+#define VGA_TXT_BASE 0xB8000
+#define VGA_TXT_SIZE 0x08000
#define VGA_REG_BASE 0x3c0
#define VGA_REG_SIZE 0x10+0x0c
diff --git a/sys/dev/vt/vt_core.c b/sys/dev/vt/vt_core.c
index 99da892..702df42 100644
--- a/sys/dev/vt/vt_core.c
+++ b/sys/dev/vt/vt_core.c
@@ -264,8 +264,9 @@ vt_update_static(void *dummy)
if (!vty_enabled(VTY_VT))
return;
if (main_vd->vd_driver != NULL)
- printf("VT: running with driver \"%s\".\n",
- main_vd->vd_driver->vd_name);
+ printf("VT(%s): %s %ux%u\n", main_vd->vd_driver->vd_name,
+ (main_vd->vd_flags & VDF_TEXTMODE) ? "text" : "resolution",
+ main_vd->vd_width, main_vd->vd_height);
else
printf("VT: init without driver.\n");
diff --git a/sys/dev/xen/netfront/netfront.c b/sys/dev/xen/netfront/netfront.c
index 2f972b8..302c017 100644
--- a/sys/dev/xen/netfront/netfront.c
+++ b/sys/dev/xen/netfront/netfront.c
@@ -280,8 +280,6 @@ struct netfront_info {
struct callout xn_stat_ch;
u_long rx_pfn_array[NET_RX_RING_SIZE];
- multicall_entry_t rx_mcl[NET_RX_RING_SIZE+1];
- mmu_update_t rx_mmu[NET_RX_RING_SIZE];
struct ifmedia sc_media;
bool xn_resume;
@@ -882,13 +880,6 @@ refill:
gnttab_grant_foreign_transfer_ref(ref,
otherend_id, pfn);
sc->rx_pfn_array[nr_flips] = pfn;
- if (!xen_feature(XENFEAT_auto_translated_physmap)) {
- /* Remove this page before passing
- * back to Xen.
- */
- MULTI_update_va_mapping(&sc->rx_mcl[i],
- vaddr, 0, 0);
- }
nr_flips++;
} else {
gnttab_grant_foreign_access_ref(ref,
@@ -918,25 +909,6 @@ refill:
reservation.extent_order = 0;
reservation.address_bits = 0;
reservation.domid = DOMID_SELF;
-
- if (!xen_feature(XENFEAT_auto_translated_physmap)) {
- /* After all PTEs have been zapped, flush the TLB. */
- sc->rx_mcl[i-1].args[MULTI_UVMFLAGS_INDEX] =
- UVMF_TLB_FLUSH|UVMF_ALL;
-
- /* Give away a batch of pages. */
- sc->rx_mcl[i].op = __HYPERVISOR_memory_op;
- sc->rx_mcl[i].args[0] = XENMEM_decrease_reservation;
- sc->rx_mcl[i].args[1] = (u_long)&reservation;
- /* Zap PTEs and give away pages in one big multicall. */
- (void)HYPERVISOR_multicall(sc->rx_mcl, i+1);
-
- if (__predict_false(sc->rx_mcl[i].result != i ||
- HYPERVISOR_memory_op(XENMEM_decrease_reservation,
- &reservation) != i))
- panic("%s: unable to reduce memory "
- "reservation\n", __func__);
- }
} else {
wmb();
}
@@ -961,7 +933,6 @@ xn_rxeof(struct netfront_info *np)
struct netif_rx_response *rx = &rinfo.rx;
struct netif_extra_info *extras = rinfo.extras;
RING_IDX i, rp;
- multicall_entry_t *mcl;
struct mbuf *m;
struct mbufq rxq, errq;
int err, pages_flipped = 0, work_to_do;
@@ -1022,19 +993,6 @@ xn_rxeof(struct netfront_info *np)
#ifdef notyet
balloon_update_driver_allowance(-pages_flipped);
#endif
- /* Do all the remapping work, and M->P updates, in one big
- * hypercall.
- */
- if (!!xen_feature(XENFEAT_auto_translated_physmap)) {
- mcl = np->rx_mcl + pages_flipped;
- mcl->op = __HYPERVISOR_mmu_update;
- mcl->args[0] = (u_long)np->rx_mmu;
- mcl->args[1] = pages_flipped;
- mcl->args[2] = 0;
- mcl->args[3] = DOMID_SELF;
- (void)HYPERVISOR_multicall(np->rx_mcl,
- pages_flipped + 1);
- }
}
mbufq_drain(&errq);
@@ -1273,8 +1231,6 @@ xennet_get_responses(struct netfront_info *np,
int *pages_flipped_p)
{
int pages_flipped = *pages_flipped_p;
- struct mmu_update *mmu;
- struct multicall_entry *mcl;
struct netif_rx_response *rx = &rinfo->rx;
struct netif_extra_info *extras = rinfo->extras;
struct mbuf *m, *m0, *m_prev;
@@ -1346,22 +1302,6 @@ xennet_get_responses(struct netfront_info *np,
goto next;
}
- if (!xen_feature( XENFEAT_auto_translated_physmap)) {
- /* Remap the page. */
- void *vaddr = mtod(m, void *);
- uint32_t pfn;
-
- mcl = np->rx_mcl + pages_flipped;
- mmu = np->rx_mmu + pages_flipped;
-
- MULTI_update_va_mapping(mcl, (u_long)vaddr,
- (((vm_paddr_t)mfn) << PAGE_SHIFT) | PG_RW |
- PG_V | PG_M | PG_A, 0);
- pfn = (uintptr_t)m->m_ext.ext_arg1;
- mmu->ptr = ((vm_paddr_t)mfn << PAGE_SHIFT) |
- MMU_MACHPHYS_UPDATE;
- mmu->val = pfn;
- }
pages_flipped++;
} else {
ret = gnttab_end_foreign_access_ref(ref);
OpenPOWER on IntegriCloud