diff options
Diffstat (limited to 'sys/dev')
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, ×tamp, sizeof(timestamp)); - randomdev_hash_iterate(&hash, buf, count); - timestamp = (uint32_t)get_cyclecount(); - randomdev_hash_iterate(&hash, ×tamp, 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, ×tamp, sizeof(timestamp)); + randomdev_hash_iterate(&hash, buf, count); + timestamp = (uint32_t)get_cyclecount(); + randomdev_hash_iterate(&hash, ×tamp, 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, ×tamp, sizeof(timestamp)); - randomdev_hash_iterate(&hash, buf, count); - timestamp = (uint32_t)get_cyclecount(); - randomdev_hash_iterate(&hash, ×tamp, 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); |