diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2019-09-24 11:05:03 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2019-11-13 10:47:04 +0100 |
commit | a5ddb0ea69f21c16b7697a935d7a0c16bb3cffcf (patch) | |
tree | db091fb0f7d091804482156c9f3f55879ac93d5b /freebsd/sys/dev | |
parent | test/syscalls01: Fix sporadic test failures (diff) | |
download | rtems-libbsd-a5ddb0ea69f21c16b7697a935d7a0c16bb3cffcf.tar.bz2 |
Update to FreeBSD head 2019-09-24
Git mirror commit 6b0307a0a5184339393f555d5d424190d8a8277a.
Diffstat (limited to 'freebsd/sys/dev')
125 files changed, 3415 insertions, 1210 deletions
diff --git a/freebsd/sys/dev/bge/if_bge.c b/freebsd/sys/dev/bge/if_bge.c index a4a937b2..79e930ca 100644 --- a/freebsd/sys/dev/bge/if_bge.c +++ b/freebsd/sys/dev/bge/if_bge.c @@ -2929,10 +2929,14 @@ bge_dma_ring_alloc(struct bge_softc *sc, bus_size_t alignment, bus_addr_t *paddr, const char *msg) { struct bge_dmamap_arg ctx; + bus_addr_t lowaddr; + bus_size_t ring_end; int error; + lowaddr = BUS_SPACE_MAXADDR; +again: error = bus_dma_tag_create(sc->bge_cdata.bge_parent_tag, - alignment, 0, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, + alignment, 0, lowaddr, BUS_SPACE_MAXADDR, NULL, NULL, maxsize, 1, maxsize, 0, NULL, NULL, tag); if (error != 0) { device_printf(sc->bge_dev, @@ -2957,6 +2961,25 @@ bge_dma_ring_alloc(struct bge_softc *sc, bus_size_t alignment, return (ENOMEM); } *paddr = ctx.bge_busaddr; + ring_end = *paddr + maxsize; + if ((sc->bge_flags & BGE_FLAG_4G_BNDRY_BUG) != 0 && + BGE_ADDR_HI(*paddr) != BGE_ADDR_HI(ring_end)) { + /* + * 4GB boundary crossed. Limit maximum allowable DMA + * address space to 32bit and try again. + */ + bus_dmamap_unload(*tag, *map); + bus_dmamem_free(*tag, *ring, *map); + bus_dma_tag_destroy(*tag); + if (bootverbose) + device_printf(sc->bge_dev, "4GB boundary crossed, " + "limit DMA address space to 32bit for %s\n", msg); + *ring = NULL; + *tag = NULL; + *map = NULL; + lowaddr = BUS_SPACE_MAXADDR_32BIT; + goto again; + } return (0); } @@ -2964,7 +2987,7 @@ static int bge_dma_alloc(struct bge_softc *sc) { bus_addr_t lowaddr; - bus_size_t rxmaxsegsz, sbsz, txsegsz, txmaxsegsz; + bus_size_t boundary, sbsz, rxmaxsegsz, txsegsz, txmaxsegsz; int i, error; lowaddr = BUS_SPACE_MAXADDR; @@ -3051,7 +3074,9 @@ bge_dma_alloc(struct bge_softc *sc) } /* Create parent tag for buffers. */ + boundary = 0; if ((sc->bge_flags & BGE_FLAG_4G_BNDRY_BUG) != 0) { + boundary = BGE_DMA_BNDRY; /* * XXX * watchdog timeout issue was observed on BCM5704 which @@ -3062,10 +3087,10 @@ bge_dma_alloc(struct bge_softc *sc) if (sc->bge_pcixcap != 0) lowaddr = BUS_SPACE_MAXADDR_32BIT; } - error = bus_dma_tag_create(bus_get_dma_tag(sc->bge_dev), 1, 0, lowaddr, - BUS_SPACE_MAXADDR, NULL, NULL, BUS_SPACE_MAXSIZE_32BIT, 0, - BUS_SPACE_MAXSIZE_32BIT, 0, NULL, NULL, - &sc->bge_cdata.bge_buffer_tag); + error = bus_dma_tag_create(bus_get_dma_tag(sc->bge_dev), + 1, boundary, lowaddr, BUS_SPACE_MAXADDR, NULL, + NULL, BUS_SPACE_MAXSIZE_32BIT, 0, BUS_SPACE_MAXSIZE_32BIT, + 0, NULL, NULL, &sc->bge_cdata.bge_buffer_tag); if (error != 0) { device_printf(sc->bge_dev, "could not allocate buffer dma tag\n"); @@ -3253,6 +3278,8 @@ bge_mbox_reorder(struct bge_softc *sc) bus = device_get_parent(dev); if (device_get_devclass(dev) != pcib) break; + if (device_get_devclass(bus) != pci) + break; for (i = 0; i < nitems(mbox_reorder_lists); i++) { if (pci_get_vendor(dev) == mbox_reorder_lists[i].vendor && @@ -3264,8 +3291,6 @@ bge_mbox_reorder(struct bge_softc *sc) return (1); } } - if (device_get_devclass(bus) != pci) - break; } return (0); } diff --git a/freebsd/sys/dev/bge/if_bgereg.h b/freebsd/sys/dev/bge/if_bgereg.h index eb7686e7..58fe8040 100644 --- a/freebsd/sys/dev/bge/if_bgereg.h +++ b/freebsd/sys/dev/bge/if_bgereg.h @@ -2866,6 +2866,12 @@ struct bge_gib { #define BGE_DMA_MAXADDR 0xFFFFFFFFFF #endif +#if (BUS_SPACE_MAXSIZE > 0xFFFFFFFF) +#define BGE_DMA_BNDRY 0x100000000 +#else +#define BGE_DMA_BNDRY 0 +#endif + /* * Ring structures. Most of these reside in host memory and we tell * the NIC where they are via the ring control blocks. The exceptions diff --git a/freebsd/sys/dev/cadence/if_cgem.c b/freebsd/sys/dev/cadence/if_cgem.c index 191362c4..34340f22 100644 --- a/freebsd/sys/dev/cadence/if_cgem.c +++ b/freebsd/sys/dev/cadence/if_cgem.c @@ -107,6 +107,14 @@ __FBSDID("$FreeBSD$"); #define CGEM_CKSUM_ASSIST (CSUM_IP | CSUM_TCP | CSUM_UDP | \ CSUM_TCP_IPV6 | CSUM_UDP_IPV6) +#ifndef __rtems__ +static struct ofw_compat_data compat_data[] = { + { "cadence,gem", 1 }, + { "cdns,macb", 1 }, + { NULL, 0 }, +}; +#endif /* __rtems__ */ + struct cgem_softc { if_t ifp; struct mtx sc_mtx; @@ -1724,7 +1732,7 @@ cgem_probe(device_t dev) if (!ofw_bus_status_okay(dev)) return (ENXIO); - if (!ofw_bus_is_compatible(dev, "cadence,gem")) + if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) return (ENXIO); #endif /* __rtems__ */ diff --git a/freebsd/sys/dev/e1000/em_txrx.c b/freebsd/sys/dev/e1000/em_txrx.c index c2b60743..4faf806e 100644 --- a/freebsd/sys/dev/e1000/em_txrx.c +++ b/freebsd/sys/dev/e1000/em_txrx.c @@ -459,16 +459,11 @@ em_isc_txd_credits_update(void *arg, uint16_t txqid, bool clear) prev = txr->tx_cidx_processed; ntxd = scctx->isc_ntxd[0]; do { + MPASS(prev != cur); delta = (int32_t)cur - (int32_t)prev; - /* - * XXX This appears to be a hack for first-packet. - * A correct fix would prevent prev == cur in the first place. - */ - MPASS(prev == 0 || delta != 0); - if (prev == 0 && cur == 0) - delta += 1; if (delta < 0) delta += ntxd; + MPASS(delta > 0); DPRINTF(iflib_get_dev(adapter->ctx), "%s: cidx_processed=%u cur=%u clear=%d delta=%d\n", __FUNCTION__, prev, cur, clear, delta); diff --git a/freebsd/sys/dev/e1000/if_em.c b/freebsd/sys/dev/e1000/if_em.c index 803b68ec..32eb4afe 100644 --- a/freebsd/sys/dev/e1000/if_em.c +++ b/freebsd/sys/dev/e1000/if_em.c @@ -251,6 +251,7 @@ static int em_if_mtu_set(if_ctx_t ctx, uint32_t mtu); static void em_if_timer(if_ctx_t ctx, uint16_t qid); static void em_if_vlan_register(if_ctx_t ctx, u16 vtag); static void em_if_vlan_unregister(if_ctx_t ctx, u16 vtag); +static void em_if_watchdog_reset(if_ctx_t ctx); static void em_identify_hardware(if_ctx_t ctx); static int em_allocate_pci_resources(if_ctx_t ctx); @@ -262,10 +263,14 @@ static int em_setup_msix(if_ctx_t ctx); static void em_initialize_transmit_unit(if_ctx_t ctx); static void em_initialize_receive_unit(if_ctx_t ctx); -static void em_if_enable_intr(if_ctx_t ctx); -static void em_if_disable_intr(if_ctx_t ctx); +static void em_if_intr_enable(if_ctx_t ctx); +static void em_if_intr_disable(if_ctx_t ctx); +static void igb_if_intr_enable(if_ctx_t ctx); +static void igb_if_intr_disable(if_ctx_t ctx); static int em_if_rx_queue_intr_enable(if_ctx_t ctx, uint16_t rxqid); static int em_if_tx_queue_intr_enable(if_ctx_t ctx, uint16_t txqid); +static int igb_if_rx_queue_intr_enable(if_ctx_t ctx, uint16_t rxqid); +static int igb_if_tx_queue_intr_enable(if_ctx_t ctx, uint16_t txqid); static void em_if_multi_set(if_ctx_t ctx); static void em_if_update_admin_status(if_ctx_t ctx); static void em_if_debug(if_ctx_t ctx); @@ -295,7 +300,7 @@ static void em_disable_aspm(struct adapter *); int em_intr(void *arg); static void em_disable_promisc(if_ctx_t ctx); -/* MSIX handlers */ +/* MSI-X handlers */ static int em_if_msix_intr_assign(if_ctx_t, int); static int em_msix_link(void *); static void em_handle_link(void *context); @@ -376,8 +381,8 @@ static device_method_t em_if_methods[] = { DEVMETHOD(ifdi_init, em_if_init), DEVMETHOD(ifdi_stop, em_if_stop), DEVMETHOD(ifdi_msix_intr_assign, em_if_msix_intr_assign), - DEVMETHOD(ifdi_intr_enable, em_if_enable_intr), - DEVMETHOD(ifdi_intr_disable, em_if_disable_intr), + DEVMETHOD(ifdi_intr_enable, em_if_intr_enable), + DEVMETHOD(ifdi_intr_disable, em_if_intr_disable), DEVMETHOD(ifdi_tx_queues_alloc, em_if_tx_queues_alloc), DEVMETHOD(ifdi_rx_queues_alloc, em_if_rx_queues_alloc), DEVMETHOD(ifdi_queues_free, em_if_queues_free), @@ -388,6 +393,7 @@ static device_method_t em_if_methods[] = { DEVMETHOD(ifdi_mtu_set, em_if_mtu_set), DEVMETHOD(ifdi_promisc_set, em_if_set_promisc), DEVMETHOD(ifdi_timer, em_if_timer), + DEVMETHOD(ifdi_watchdog_reset, em_if_watchdog_reset), DEVMETHOD(ifdi_vlan_register, em_if_vlan_register), DEVMETHOD(ifdi_vlan_unregister, em_if_vlan_unregister), DEVMETHOD(ifdi_get_counter, em_if_get_counter), @@ -398,14 +404,47 @@ static device_method_t em_if_methods[] = { DEVMETHOD_END }; -/* - * note that if (adapter->msix_mem) is replaced by: - * if (adapter->intr_type == IFLIB_INTR_MSIX) - */ static driver_t em_if_driver = { "em_if", em_if_methods, sizeof(struct adapter) }; +static device_method_t igb_if_methods[] = { + DEVMETHOD(ifdi_attach_pre, em_if_attach_pre), + DEVMETHOD(ifdi_attach_post, em_if_attach_post), + DEVMETHOD(ifdi_detach, em_if_detach), + DEVMETHOD(ifdi_shutdown, em_if_shutdown), + DEVMETHOD(ifdi_suspend, em_if_suspend), + DEVMETHOD(ifdi_resume, em_if_resume), + DEVMETHOD(ifdi_init, em_if_init), + DEVMETHOD(ifdi_stop, em_if_stop), + DEVMETHOD(ifdi_msix_intr_assign, em_if_msix_intr_assign), + DEVMETHOD(ifdi_intr_enable, igb_if_intr_enable), + DEVMETHOD(ifdi_intr_disable, igb_if_intr_disable), + DEVMETHOD(ifdi_tx_queues_alloc, em_if_tx_queues_alloc), + DEVMETHOD(ifdi_rx_queues_alloc, em_if_rx_queues_alloc), + DEVMETHOD(ifdi_queues_free, em_if_queues_free), + DEVMETHOD(ifdi_update_admin_status, em_if_update_admin_status), + DEVMETHOD(ifdi_multi_set, em_if_multi_set), + DEVMETHOD(ifdi_media_status, em_if_media_status), + DEVMETHOD(ifdi_media_change, em_if_media_change), + DEVMETHOD(ifdi_mtu_set, em_if_mtu_set), + DEVMETHOD(ifdi_promisc_set, em_if_set_promisc), + DEVMETHOD(ifdi_timer, em_if_timer), + DEVMETHOD(ifdi_watchdog_reset, em_if_watchdog_reset), + DEVMETHOD(ifdi_vlan_register, em_if_vlan_register), + DEVMETHOD(ifdi_vlan_unregister, em_if_vlan_unregister), + DEVMETHOD(ifdi_get_counter, em_if_get_counter), + DEVMETHOD(ifdi_led_func, em_if_led_func), + DEVMETHOD(ifdi_rx_queue_intr_enable, igb_if_rx_queue_intr_enable), + DEVMETHOD(ifdi_tx_queue_intr_enable, igb_if_tx_queue_intr_enable), + DEVMETHOD(ifdi_debug, em_if_debug), + DEVMETHOD_END +}; + +static driver_t igb_if_driver = { + "igb_if", igb_if_methods, sizeof(struct adapter) +}; + /********************************************************************* * Tunable default values. *********************************************************************/ @@ -525,7 +564,7 @@ static struct if_shared_ctx igb_sctx_init = { .isc_admin_intrcnt = 1, .isc_vendor_info = igb_vendor_info_array, .isc_driver_version = em_driver_version, - .isc_driver = &em_if_driver, + .isc_driver = &igb_if_driver, .isc_flags = IFLIB_NEED_SCRATCH | IFLIB_TSO_INIT_IP | IFLIB_NEED_ZERO_CSUM, .isc_nrxd_min = {EM_MIN_RXD}, @@ -723,7 +762,6 @@ em_set_num_queues(if_ctx_t ctx) * * return 0 on success, positive on failure *********************************************************************/ - static int em_if_attach_pre(if_ctx_t ctx) { @@ -733,15 +771,10 @@ em_if_attach_pre(if_ctx_t ctx) struct e1000_hw *hw; int error = 0; - INIT_DEBUGOUT("em_if_attach_pre begin"); + INIT_DEBUGOUT("em_if_attach_pre: begin"); dev = iflib_get_dev(ctx); adapter = iflib_get_softc(ctx); - if (resource_disabled("em", device_get_unit(dev))) { - device_printf(dev, "Disabled by device hint\n"); - return (ENXIO); - } - adapter->ctx = adapter->osdep.ctx = ctx; adapter->dev = adapter->osdep.dev = dev; scctx = adapter->shared = iflib_get_softc_ctx(ctx); @@ -779,14 +812,13 @@ em_if_attach_pre(if_ctx_t ctx) /* Determine hardware and mac info */ em_identify_hardware(ctx); - scctx->isc_msix_bar = PCIR_BAR(EM_MSIX_BAR); scctx->isc_tx_nsegments = EM_MAX_SCATTER; scctx->isc_nrxqsets_max = scctx->isc_ntxqsets_max = em_set_num_queues(ctx); - device_printf(dev, "attach_pre capping queues at %d\n", scctx->isc_ntxqsets_max); + if (bootverbose) + device_printf(dev, "attach_pre capping queues at %d\n", + scctx->isc_ntxqsets_max); if (adapter->hw.mac.type >= igb_mac_min) { - int try_second_bar; - scctx->isc_txqsizes[0] = roundup2(scctx->isc_ntxd[0] * sizeof(union e1000_adv_tx_desc), EM_DBA_ALIGN); scctx->isc_rxqsizes[0] = roundup2(scctx->isc_nrxd[0] * sizeof(union e1000_adv_rx_desc), EM_DBA_ALIGN); scctx->isc_txd_size[0] = sizeof(union e1000_adv_tx_desc); @@ -800,14 +832,13 @@ em_if_attach_pre(if_ctx_t ctx) CSUM_IP6_TCP | CSUM_IP6_UDP; if (adapter->hw.mac.type != e1000_82575) scctx->isc_tx_csum_flags |= CSUM_SCTP | CSUM_IP6_SCTP; - /* ** Some new devices, as with ixgbe, now may ** use a different BAR, so we need to keep ** track of which is used. */ - try_second_bar = pci_read_config(dev, scctx->isc_msix_bar, 4); - if (try_second_bar == 0) + scctx->isc_msix_bar = PCIR_BAR(EM_MSIX_BAR); + if (pci_read_config(dev, scctx->isc_msix_bar, 4) == 0) scctx->isc_msix_bar += 4; } else if (adapter->hw.mac.type >= em_mac_min) { scctx->isc_txqsizes[0] = roundup2(scctx->isc_ntxd[0]* sizeof(struct e1000_tx_desc), EM_DBA_ALIGN); @@ -837,6 +868,16 @@ em_if_attach_pre(if_ctx_t ctx) */ scctx->isc_capenable &= ~(IFCAP_TSO4 | IFCAP_VLAN_HWTSO); scctx->isc_tx_csum_flags = CSUM_TCP | CSUM_UDP | CSUM_IP_TSO; + /* + * We support MSI-X with 82574 only, but indicate to iflib(4) + * that it shall give MSI at least a try with other devices. + */ + if (adapter->hw.mac.type == e1000_82574) { + scctx->isc_msix_bar = PCIR_BAR(EM_MSIX_BAR); + } else { + scctx->isc_msix_bar = -1; + scctx->isc_disable_msix = 1; + } } else { scctx->isc_txqsizes[0] = roundup2((scctx->isc_ntxd[0] + 1) * sizeof(struct e1000_tx_desc), EM_DBA_ALIGN); scctx->isc_rxqsizes[0] = roundup2((scctx->isc_nrxd[0] + 1) * sizeof(struct e1000_rx_desc), EM_DBA_ALIGN); @@ -847,6 +888,7 @@ em_if_attach_pre(if_ctx_t ctx) scctx->isc_capabilities = scctx->isc_capenable = LEM_CAPS; if (adapter->hw.mac.type < e1000_82543) scctx->isc_capenable &= ~(IFCAP_HWCSUM|IFCAP_VLAN_HWCSUM); + /* INTx only */ scctx->isc_msix_bar = 0; } @@ -1092,13 +1134,12 @@ err_late: * * return 0 on success, positive on failure *********************************************************************/ - static int em_if_detach(if_ctx_t ctx) { struct adapter *adapter = iflib_get_softc(ctx); - INIT_DEBUGOUT("em_detach: begin"); + INIT_DEBUGOUT("em_if_detach: begin"); e1000_phy_hw_reset(&adapter->hw); @@ -1203,16 +1244,16 @@ em_if_mtu_set(if_ctx_t ctx, uint32_t mtu) * by the driver as a hw/sw initialization routine to get to a * consistent state. * - * return 0 on success, positive on failure **********************************************************************/ - static void em_if_init(if_ctx_t ctx) { struct adapter *adapter = iflib_get_softc(ctx); + if_softc_ctx_t scctx = adapter->shared; struct ifnet *ifp = iflib_get_ifp(ctx); struct em_tx_queue *tx_que; int i; + INIT_DEBUGOUT("em_if_init: begin"); /* Get the latest mac address, User can use a LAA */ @@ -1242,7 +1283,14 @@ em_if_init(if_ctx_t ctx) for (i = 0, tx_que = adapter->tx_queues; i < adapter->tx_num_queues; i++, tx_que++) { struct tx_ring *txr = &tx_que->txr; - txr->tx_rs_cidx = txr->tx_rs_pidx = txr->tx_cidx_processed = 0; + txr->tx_rs_cidx = txr->tx_rs_pidx; + + /* Initialize the last processed descriptor to be the end of + * the ring, rather than the start, so that we avoid an + * off-by-one error when calculating how many descriptors are + * done in the credits_update function. + */ + txr->tx_cidx_processed = scctx->isc_ntxd[0] - 1; } /* Setup VLAN support, basic and offload if available */ @@ -1261,21 +1309,7 @@ em_if_init(if_ctx_t ctx) /* Setup Multicast table */ em_if_multi_set(ctx); - /* - * Figure out the desired mbuf - * pool for doing jumbos - */ - if (adapter->hw.mac.max_frame_size <= 2048) - adapter->rx_mbuf_sz = MCLBYTES; -#ifndef CONTIGMALLOC_WORKS - else - adapter->rx_mbuf_sz = MJUMPAGESIZE; -#else - else if (adapter->hw.mac.max_frame_size <= 4096) - adapter->rx_mbuf_sz = MJUMPAGESIZE; - else - adapter->rx_mbuf_sz = MJUM9BYTES; -#endif + adapter->rx_mbuf_sz = iflib_get_rx_mbuf_sz(ctx); em_initialize_receive_unit(ctx); /* Use real VLAN Filter support? */ @@ -1295,7 +1329,7 @@ em_if_init(if_ctx_t ctx) em_if_set_promisc(ctx, IFF_PROMISC); e1000_clear_hw_cntrs_base_generic(&adapter->hw); - /* MSI/X configuration for 82574 */ + /* MSI-X configuration for 82574 */ if (adapter->hw.mac.type == e1000_82574) { int tmp = E1000_READ_REG(&adapter->hw, E1000_CTRL_EXT); @@ -1338,8 +1372,6 @@ em_intr(void *arg) reg_icr = E1000_READ_REG(&adapter->hw, E1000_ICR); - if (adapter->intr_type != IFLIB_INTR_LEGACY) - goto skip_stray; /* Hot eject? */ if (reg_icr == 0xffffffff) return FILTER_STRAY; @@ -1356,7 +1388,14 @@ em_intr(void *arg) (reg_icr & E1000_ICR_INT_ASSERTED) == 0) return FILTER_STRAY; -skip_stray: + /* + * Only MSI-X interrupts have one-shot behavior by taking advantage + * of the EIAC register. Thus, explicitly disable interrupts. This + * also works around the MSI message reordering errata on certain + * systems. + */ + IFDI_INTR_DISABLE(ctx); + /* Link status change */ if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { adapter->hw.mac.get_link_status = 1; @@ -1369,59 +1408,49 @@ skip_stray: return (FILTER_SCHEDULE_THREAD); } -static void -igb_rx_enable_queue(struct adapter *adapter, struct em_rx_queue *rxq) +static int +em_if_rx_queue_intr_enable(if_ctx_t ctx, uint16_t rxqid) { - E1000_WRITE_REG(&adapter->hw, E1000_EIMS, rxq->eims); -} + struct adapter *adapter = iflib_get_softc(ctx); + struct em_rx_queue *rxq = &adapter->rx_queues[rxqid]; -static void -em_rx_enable_queue(struct adapter *adapter, struct em_rx_queue *rxq) -{ E1000_WRITE_REG(&adapter->hw, E1000_IMS, rxq->eims); + return (0); } -static void -igb_tx_enable_queue(struct adapter *adapter, struct em_tx_queue *txq) +static int +em_if_tx_queue_intr_enable(if_ctx_t ctx, uint16_t txqid) { - E1000_WRITE_REG(&adapter->hw, E1000_EIMS, txq->eims); -} + struct adapter *adapter = iflib_get_softc(ctx); + struct em_tx_queue *txq = &adapter->tx_queues[txqid]; -static void -em_tx_enable_queue(struct adapter *adapter, struct em_tx_queue *txq) -{ E1000_WRITE_REG(&adapter->hw, E1000_IMS, txq->eims); + return (0); } static int -em_if_rx_queue_intr_enable(if_ctx_t ctx, uint16_t rxqid) +igb_if_rx_queue_intr_enable(if_ctx_t ctx, uint16_t rxqid) { struct adapter *adapter = iflib_get_softc(ctx); struct em_rx_queue *rxq = &adapter->rx_queues[rxqid]; - if (adapter->hw.mac.type >= igb_mac_min) - igb_rx_enable_queue(adapter, rxq); - else - em_rx_enable_queue(adapter, rxq); + E1000_WRITE_REG(&adapter->hw, E1000_EIMS, rxq->eims); return (0); } static int -em_if_tx_queue_intr_enable(if_ctx_t ctx, uint16_t txqid) +igb_if_tx_queue_intr_enable(if_ctx_t ctx, uint16_t txqid) { struct adapter *adapter = iflib_get_softc(ctx); struct em_tx_queue *txq = &adapter->tx_queues[txqid]; - if (adapter->hw.mac.type >= igb_mac_min) - igb_tx_enable_queue(adapter, txq); - else - em_tx_enable_queue(adapter, txq); + E1000_WRITE_REG(&adapter->hw, E1000_EIMS, txq->eims); return (0); } /********************************************************************* * - * MSIX RX Interrupt Service routine + * MSI-X RX Interrupt Service routine * **********************************************************************/ static int @@ -1436,7 +1465,7 @@ em_msix_que(void *arg) /********************************************************************* * - * MSIX Link Fast Interrupt Service routine + * MSI-X Link Fast Interrupt Service routine * **********************************************************************/ static int @@ -1689,37 +1718,24 @@ em_if_multi_set(if_ctx_t ctx) } } - /********************************************************************* * Timer routine * - * This routine checks for link status and updates statistics. + * This routine schedules em_if_update_admin_status() to check for + * link status and to gather statistics as well as to perform some + * controller-specific hardware patting. * **********************************************************************/ - static void em_if_timer(if_ctx_t ctx, uint16_t qid) { - struct adapter *adapter = iflib_get_softc(ctx); - struct em_rx_queue *que; - int i; - int trigger = 0; if (qid != 0) return; iflib_admin_intr_deferred(ctx); - - /* Mask to use in the irq trigger */ - if (adapter->intr_type == IFLIB_INTR_MSIX) { - for (i = 0, que = adapter->rx_queues; i < adapter->rx_num_queues; i++, que++) - trigger |= que->eims; - } else { - trigger = E1000_ICS_RXDMT0; - } } - static void em_if_update_admin_status(if_ctx_t ctx) { @@ -1825,21 +1841,30 @@ em_if_update_admin_status(if_ctx_t ctx) E1000_WRITE_REG(&adapter->hw, E1000_IMS, EM_MSIX_LINK | E1000_IMS_LSC); } +static void +em_if_watchdog_reset(if_ctx_t ctx) +{ + struct adapter *adapter = iflib_get_softc(ctx); + + /* + * Just count the event; iflib(4) will already trigger a + * sufficient reset of the controller. + */ + adapter->watchdog_events++; +} + /********************************************************************* * * This routine disables all traffic on the adapter by issuing a - * global reset on the MAC and deallocates TX/RX buffers. + * global reset on the MAC. * - * This routine should always be called with BOTH the CORE - * and TX locks. **********************************************************************/ - static void em_if_stop(if_ctx_t ctx) { struct adapter *adapter = iflib_get_softc(ctx); - INIT_DEBUGOUT("em_stop: begin"); + INIT_DEBUGOUT("em_if_stop: begin"); e1000_reset_hw(&adapter->hw); if (adapter->hw.mac.type >= e1000_82544) @@ -1849,7 +1874,6 @@ em_if_stop(if_ctx_t ctx) e1000_cleanup_led(&adapter->hw); } - /********************************************************************* * * Determine hardware revision. @@ -1906,7 +1930,6 @@ em_allocate_pci_resources(if_ctx_t ctx) for (rid = PCIR_BAR(0); rid < PCIR_CIS;) { val = pci_read_config(dev, rid, 4); if (EM_BAR_TYPE(val) == EM_BAR_TYPE_IO) { - adapter->io_rid = rid; break; } rid += 4; @@ -1918,8 +1941,8 @@ em_allocate_pci_resources(if_ctx_t ctx) device_printf(dev, "Unable to locate IO BAR\n"); return (ENXIO); } - adapter->ioport = bus_alloc_resource_any(dev, - SYS_RES_IOPORT, &adapter->io_rid, RF_ACTIVE); + adapter->ioport = bus_alloc_resource_any(dev, SYS_RES_IOPORT, + &rid, RF_ACTIVE); if (adapter->ioport == NULL) { device_printf(dev, "Unable to allocate bus resource: " "ioport\n"); @@ -1939,7 +1962,7 @@ em_allocate_pci_resources(if_ctx_t ctx) /********************************************************************* * - * Setup the MSIX Interrupt handlers + * Set up the MSI-X Interrupt handlers * **********************************************************************/ static int @@ -1968,7 +1991,7 @@ em_if_msix_intr_assign(if_ctx_t ctx, int msix) * Set the bit to enable interrupt * in E1000_IMS -- bits 20 and 21 * are for RX0 and RX1, note this has - * NOTHING to do with the MSIX vector + * NOTHING to do with the MSI-X vector */ if (adapter->hw.mac.type == e1000_82574) { rx_que->eims = 1 << (20 + i); @@ -1989,22 +2012,22 @@ em_if_msix_intr_assign(if_ctx_t ctx, int msix) &adapter->rx_queues[i % adapter->rx_num_queues].que_irq, IFLIB_INTR_TX, tx_que, tx_que->me, buf); - tx_que->msix = (vector % adapter->tx_num_queues); + tx_que->msix = (vector % adapter->rx_num_queues); /* * Set the bit to enable interrupt * in E1000_IMS -- bits 22 and 23 * are for TX0 and TX1, note this has - * NOTHING to do with the MSIX vector + * NOTHING to do with the MSI-X vector */ if (adapter->hw.mac.type == e1000_82574) { tx_que->eims = 1 << (22 + i); adapter->ims |= tx_que->eims; adapter->ivars |= (8 | tx_que->msix) << (8 + (i * 4)); } else if (adapter->hw.mac.type == e1000_82575) { - tx_que->eims = E1000_EICR_TX_QUEUE0 << (i % adapter->tx_num_queues); + tx_que->eims = E1000_EICR_TX_QUEUE0 << i; } else { - tx_que->eims = 1 << (i % adapter->tx_num_queues); + tx_que->eims = 1 << i; } } @@ -2044,7 +2067,7 @@ igb_configure_queues(struct adapter *adapter) E1000_GPIE_MSIX_MODE | E1000_GPIE_EIAME | E1000_GPIE_PBA | E1000_GPIE_NSICR); - /* Turn on MSIX */ + /* Turn on MSI-X */ switch (adapter->hw.mac.type) { case e1000_82580: case e1000_i350: @@ -2178,7 +2201,7 @@ em_free_pci_resources(if_ctx_t ctx) struct em_rx_queue *que = adapter->rx_queues; device_t dev = iflib_get_dev(ctx); - /* Release all msix queue resources */ + /* Release all MSI-X queue resources */ if (adapter->intr_type == IFLIB_INTR_MSIX) iflib_irq_free(ctx, &adapter->irq); @@ -2186,24 +2209,26 @@ em_free_pci_resources(if_ctx_t ctx) iflib_irq_free(ctx, &que->que_irq); } - /* First release all the interrupt resources */ if (adapter->memory != NULL) { bus_release_resource(dev, SYS_RES_MEMORY, - PCIR_BAR(0), adapter->memory); + rman_get_rid(adapter->memory), adapter->memory); adapter->memory = NULL; } if (adapter->flash != NULL) { bus_release_resource(dev, SYS_RES_MEMORY, - EM_FLASH, adapter->flash); + rman_get_rid(adapter->flash), adapter->flash); adapter->flash = NULL; } - if (adapter->ioport != NULL) + + if (adapter->ioport != NULL) { bus_release_resource(dev, SYS_RES_IOPORT, - adapter->io_rid, adapter->ioport); + rman_get_rid(adapter->ioport), adapter->ioport); + adapter->ioport = NULL; + } } -/* Setup MSI or MSI/X */ +/* Set up MSI or MSI-X */ static int em_setup_msix(if_ctx_t ctx) { @@ -2217,11 +2242,9 @@ em_setup_msix(if_ctx_t ctx) /********************************************************************* * - * Initialize the hardware to a configuration - * as specified by the adapter structure. + * Workaround for SmartSpeed on 82541 and 82547 controllers * **********************************************************************/ - static void lem_smartspeed(struct adapter *adapter) { @@ -2386,6 +2409,12 @@ igb_init_dmac(struct adapter *adapter, u32 pba) } } +/********************************************************************* + * + * Initialize the hardware to a configuration as specified by the + * adapter structure. + * + **********************************************************************/ static void em_reset(if_ctx_t ctx) { @@ -2620,6 +2649,11 @@ em_reset(if_ctx_t ctx) e1000_check_for_link(hw); } +/* + * Initialise the RSS mapping for NICs that support multiple transmit/ + * receive rings. + */ + #define RSSKEYLEN 10 static void em_initialize_rss_mapping(struct adapter *adapter) @@ -2660,7 +2694,6 @@ em_initialize_rss_mapping(struct adapter *adapter) E1000_MRQC_RSS_FIELD_IPV6_TCP_EX | E1000_MRQC_RSS_FIELD_IPV6_EX | E1000_MRQC_RSS_FIELD_IPV6); - } static void @@ -2760,7 +2793,7 @@ igb_initialize_rss_mapping(struct adapter *adapter) /********************************************************************* * - * Setup networking device structure and register an interface. + * Setup networking device structure and register interface media. * **********************************************************************/ static int @@ -2845,7 +2878,9 @@ em_if_tx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs, int ntxqs txr->tx_paddr = paddrs[i*ntxqs]; } - device_printf(iflib_get_dev(ctx), "allocated for %d tx_queues\n", adapter->tx_num_queues); + if (bootverbose) + device_printf(iflib_get_dev(ctx), + "allocated for %d tx_queues\n", adapter->tx_num_queues); return (0); fail: em_if_queues_free(ctx); @@ -2883,8 +2918,10 @@ em_if_rx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs, int nrxqs rxr->rx_base = (union e1000_rx_desc_extended *)vaddrs[i*nrxqs]; rxr->rx_paddr = paddrs[i*nrxqs]; } - - device_printf(iflib_get_dev(ctx), "allocated for %d rx_queues\n", adapter->rx_num_queues); + + if (bootverbose) + device_printf(iflib_get_dev(ctx), + "allocated for %d rx_queues\n", adapter->rx_num_queues); return (0); fail: @@ -3127,7 +3164,7 @@ em_initialize_receive_unit(if_ctx_t ctx) rfctl = E1000_READ_REG(hw, E1000_RFCTL); rfctl |= E1000_RFCTL_EXTEN; /* - * When using MSIX interrupts we need to throttle + * When using MSI-X interrupts we need to throttle * using the EITR register (82574 only) */ if (hw->mac.type == e1000_82574) { @@ -3371,7 +3408,7 @@ em_setup_vlan_hw_support(struct adapter *adapter) } static void -em_if_enable_intr(if_ctx_t ctx) +em_if_intr_enable(if_ctx_t ctx) { struct adapter *adapter = iflib_get_softc(ctx); struct e1000_hw *hw = &adapter->hw; @@ -3380,30 +3417,51 @@ em_if_enable_intr(if_ctx_t ctx) if (hw->mac.type == e1000_82574) { E1000_WRITE_REG(hw, EM_EIAC, EM_MSIX_MASK); ims_mask |= adapter->ims; - } else if (adapter->intr_type == IFLIB_INTR_MSIX && hw->mac.type >= igb_mac_min) { - u32 mask = (adapter->que_mask | adapter->link_mask); - - E1000_WRITE_REG(&adapter->hw, E1000_EIAC, mask); - E1000_WRITE_REG(&adapter->hw, E1000_EIAM, mask); - E1000_WRITE_REG(&adapter->hw, E1000_EIMS, mask); - ims_mask = E1000_IMS_LSC; } - E1000_WRITE_REG(hw, E1000_IMS, ims_mask); } static void -em_if_disable_intr(if_ctx_t ctx) +em_if_intr_disable(if_ctx_t ctx) +{ + struct adapter *adapter = iflib_get_softc(ctx); + struct e1000_hw *hw = &adapter->hw; + + if (hw->mac.type == e1000_82574) + E1000_WRITE_REG(hw, EM_EIAC, 0); + E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); +} + +static void +igb_if_intr_enable(if_ctx_t ctx) +{ + struct adapter *adapter = iflib_get_softc(ctx); + struct e1000_hw *hw = &adapter->hw; + u32 mask; + + if (__predict_true(adapter->intr_type == IFLIB_INTR_MSIX)) { + mask = (adapter->que_mask | adapter->link_mask); + E1000_WRITE_REG(hw, E1000_EIAC, mask); + E1000_WRITE_REG(hw, E1000_EIAM, mask); + E1000_WRITE_REG(hw, E1000_EIMS, mask); + E1000_WRITE_REG(hw, E1000_IMS, E1000_IMS_LSC); + } else + E1000_WRITE_REG(hw, E1000_IMS, IMS_ENABLE_MASK); + E1000_WRITE_FLUSH(hw); +} + +static void +igb_if_intr_disable(if_ctx_t ctx) { struct adapter *adapter = iflib_get_softc(ctx); struct e1000_hw *hw = &adapter->hw; - if (adapter->intr_type == IFLIB_INTR_MSIX) { - if (hw->mac.type >= igb_mac_min) - E1000_WRITE_REG(&adapter->hw, E1000_EIMC, ~0); - E1000_WRITE_REG(&adapter->hw, E1000_EIAC, 0); + if (__predict_true(adapter->intr_type == IFLIB_INTR_MSIX)) { + E1000_WRITE_REG(hw, E1000_EIMC, 0xffffffff); + E1000_WRITE_REG(hw, E1000_EIAC, 0); } - E1000_WRITE_REG(&adapter->hw, E1000_IMC, 0xffffffff); + E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); + E1000_WRITE_FLUSH(hw); } /* @@ -4001,13 +4059,7 @@ em_add_hw_stats(struct adapter *adapter) "Driver dropped packets"); SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "link_irq", CTLFLAG_RD, &adapter->link_irq, - "Link MSIX IRQ Handled"); - SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "mbuf_defrag_fail", - CTLFLAG_RD, &adapter->mbuf_defrag_failed, - "Defragmenting mbuf chain failed"); - SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "tx_dma_fail", - CTLFLAG_RD, &adapter->no_tx_dma_setup, - "Driver tx dma failure in xmit"); + "Link MSI-X IRQ Handled"); SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "rx_overruns", CTLFLAG_RD, &adapter->rx_overruns, "RX overruns"); @@ -4518,7 +4570,7 @@ em_print_debug_info(struct adapter *adapter) /* * 82574 only: - * Write a new value to the EEPROM increasing the number of MSIX + * Write a new value to the EEPROM increasing the number of MSI-X * vectors from 3 to 5, for proper multiqueue support. */ static void @@ -4530,10 +4582,11 @@ em_enable_vectors_82574(if_ctx_t ctx) u16 edata; e1000_read_nvm(hw, EM_NVM_PCIE_CTRL, 1, &edata); - printf("Current cap: %#06x\n", edata); + if (bootverbose) + device_printf(dev, "EM_NVM_PCIE_CTRL = %#06x\n", edata); if (((edata & EM_NVM_MSIX_N_MASK) >> EM_NVM_MSIX_N_SHIFT) != 4) { device_printf(dev, "Writing to eeprom: increasing " - "reported MSIX vectors from 3 to 5...\n"); + "reported MSI-X vectors from 3 to 5...\n"); edata &= ~(EM_NVM_MSIX_N_MASK); edata |= 4 << EM_NVM_MSIX_N_SHIFT; e1000_write_nvm(hw, EM_NVM_PCIE_CTRL, 1, &edata); diff --git a/freebsd/sys/dev/e1000/if_em.h b/freebsd/sys/dev/e1000/if_em.h index d573107b..392f6b3a 100644 --- a/freebsd/sys/dev/e1000/if_em.h +++ b/freebsd/sys/dev/e1000/if_em.h @@ -352,8 +352,8 @@ /* * 82574 has a nonstandard address for EIAC - * and since its only used in MSIX, and in - * the em driver only 82574 uses MSIX we can + * and since its only used in MSI-X, and in + * the em driver only 82574 uses MSI-X we can * solve it just using this define. */ #define EM_EIAC 0x000DC @@ -468,7 +468,6 @@ struct adapter { struct resource *memory; struct resource *flash; struct resource *ioport; - int io_rid; struct resource *res; void *tag; @@ -520,7 +519,6 @@ struct adapter { u64 que_mask; - struct em_int_delay_info tx_int_delay; struct em_int_delay_info tx_abs_int_delay; struct em_int_delay_info rx_int_delay; @@ -530,9 +528,6 @@ struct adapter { /* Misc stats maintained by the driver */ unsigned long dropped_pkts; unsigned long link_irq; - unsigned long mbuf_defrag_failed; - unsigned long no_tx_dma_setup; - unsigned long no_tx_map_avail; unsigned long rx_overruns; unsigned long watchdog_events; diff --git a/freebsd/sys/dev/e1000/igb_txrx.c b/freebsd/sys/dev/e1000/igb_txrx.c index c54315f0..6da52b7e 100644 --- a/freebsd/sys/dev/e1000/igb_txrx.c +++ b/freebsd/sys/dev/e1000/igb_txrx.c @@ -334,16 +334,11 @@ igb_isc_txd_credits_update(void *arg, uint16_t txqid, bool clear) prev = txr->tx_cidx_processed; ntxd = scctx->isc_ntxd[0]; do { + MPASS(prev != cur); delta = (int32_t)cur - (int32_t)prev; - /* - * XXX This appears to be a hack for first-packet. - * A correct fix would prevent prev == cur in the first place. - */ - MPASS(prev == 0 || delta != 0); - if (prev == 0 && cur == 0) - delta += 1; if (delta < 0) delta += ntxd; + MPASS(delta > 0); processed += delta; prev = cur; diff --git a/freebsd/sys/dev/evdev/evdev.c b/freebsd/sys/dev/evdev/evdev.c index 63e651a2..90d6423d 100644 --- a/freebsd/sys/dev/evdev/evdev.c +++ b/freebsd/sys/dev/evdev/evdev.c @@ -75,14 +75,16 @@ int evdev_rcpt_mask = EVDEV_RCPT_HW_MOUSE | EVDEV_RCPT_HW_KBD; #endif /* __rtems__ */ int evdev_sysmouse_t_axis = 0; -#ifdef EVDEV_SUPPORT SYSCTL_NODE(_kern, OID_AUTO, evdev, CTLFLAG_RW, 0, "Evdev args"); +#ifdef EVDEV_SUPPORT SYSCTL_INT(_kern_evdev, OID_AUTO, rcpt_mask, CTLFLAG_RW, &evdev_rcpt_mask, 0, "Who is receiving events: bit0 - sysmouse, bit1 - kbdmux, " "bit2 - mouse hardware, bit3 - keyboard hardware"); SYSCTL_INT(_kern_evdev, OID_AUTO, sysmouse_t_axis, CTLFLAG_RW, &evdev_sysmouse_t_axis, 0, "Extract T-axis from 0-none, 1-ums, 2-psm"); #endif +SYSCTL_NODE(_kern_evdev, OID_AUTO, input, CTLFLAG_RD, 0, + "Evdev input devices"); static void evdev_start_repeat(struct evdev_dev *, uint16_t); static void evdev_stop_repeat(struct evdev_dev *); @@ -202,6 +204,87 @@ evdev_estimate_report_size(struct evdev_dev *evdev) return (size); } +static void +evdev_sysctl_create(struct evdev_dev *evdev) +{ + struct sysctl_oid *ev_sysctl_tree; + char ev_unit_str[8]; + + snprintf(ev_unit_str, sizeof(ev_unit_str), "%d", evdev->ev_unit); + sysctl_ctx_init(&evdev->ev_sysctl_ctx); + + ev_sysctl_tree = SYSCTL_ADD_NODE_WITH_LABEL(&evdev->ev_sysctl_ctx, + SYSCTL_STATIC_CHILDREN(_kern_evdev_input), OID_AUTO, + ev_unit_str, CTLFLAG_RD, NULL, "", "device index"); + + SYSCTL_ADD_STRING(&evdev->ev_sysctl_ctx, + SYSCTL_CHILDREN(ev_sysctl_tree), OID_AUTO, "name", CTLFLAG_RD, + evdev->ev_name, 0, + "Input device name"); + + SYSCTL_ADD_STRUCT(&evdev->ev_sysctl_ctx, + SYSCTL_CHILDREN(ev_sysctl_tree), OID_AUTO, "id", CTLFLAG_RD, + &evdev->ev_id, input_id, + "Input device identification"); + + /* ioctl returns ENOENT if phys is not set. sysctl returns "" here */ + SYSCTL_ADD_STRING(&evdev->ev_sysctl_ctx, + SYSCTL_CHILDREN(ev_sysctl_tree), OID_AUTO, "phys", CTLFLAG_RD, + evdev->ev_shortname, 0, + "Input device short name"); + + /* ioctl returns ENOENT if uniq is not set. sysctl returns "" here */ + SYSCTL_ADD_STRING(&evdev->ev_sysctl_ctx, + SYSCTL_CHILDREN(ev_sysctl_tree), OID_AUTO, "uniq", CTLFLAG_RD, + evdev->ev_serial, 0, + "Input device unique number"); + + SYSCTL_ADD_OPAQUE(&evdev->ev_sysctl_ctx, + SYSCTL_CHILDREN(ev_sysctl_tree), OID_AUTO, "props", CTLFLAG_RD, + evdev->ev_prop_flags, sizeof(evdev->ev_prop_flags), "", + "Input device properties"); + + SYSCTL_ADD_OPAQUE(&evdev->ev_sysctl_ctx, + SYSCTL_CHILDREN(ev_sysctl_tree), OID_AUTO, "type_bits", CTLFLAG_RD, + evdev->ev_type_flags, sizeof(evdev->ev_type_flags), "", + "Input device supported events types"); + + SYSCTL_ADD_OPAQUE(&evdev->ev_sysctl_ctx, + SYSCTL_CHILDREN(ev_sysctl_tree), OID_AUTO, "key_bits", CTLFLAG_RD, + evdev->ev_key_flags, sizeof(evdev->ev_key_flags), + "", "Input device supported keys"); + + SYSCTL_ADD_OPAQUE(&evdev->ev_sysctl_ctx, + SYSCTL_CHILDREN(ev_sysctl_tree), OID_AUTO, "rel_bits", CTLFLAG_RD, + evdev->ev_rel_flags, sizeof(evdev->ev_rel_flags), "", + "Input device supported relative events"); + + SYSCTL_ADD_OPAQUE(&evdev->ev_sysctl_ctx, + SYSCTL_CHILDREN(ev_sysctl_tree), OID_AUTO, "abs_bits", CTLFLAG_RD, + evdev->ev_abs_flags, sizeof(evdev->ev_abs_flags), "", + "Input device supported absolute events"); + + SYSCTL_ADD_OPAQUE(&evdev->ev_sysctl_ctx, + SYSCTL_CHILDREN(ev_sysctl_tree), OID_AUTO, "msc_bits", CTLFLAG_RD, + evdev->ev_msc_flags, sizeof(evdev->ev_msc_flags), "", + "Input device supported miscellaneous events"); + + SYSCTL_ADD_OPAQUE(&evdev->ev_sysctl_ctx, + SYSCTL_CHILDREN(ev_sysctl_tree), OID_AUTO, "led_bits", CTLFLAG_RD, + evdev->ev_led_flags, sizeof(evdev->ev_led_flags), "", + "Input device supported LED events"); + + SYSCTL_ADD_OPAQUE(&evdev->ev_sysctl_ctx, + SYSCTL_CHILDREN(ev_sysctl_tree), OID_AUTO, "snd_bits", CTLFLAG_RD, + evdev->ev_snd_flags, sizeof(evdev->ev_snd_flags), "", + "Input device supported sound events"); + + SYSCTL_ADD_OPAQUE(&evdev->ev_sysctl_ctx, + SYSCTL_CHILDREN(ev_sysctl_tree), OID_AUTO, "sw_bits", CTLFLAG_RD, + evdev->ev_sw_flags, sizeof(evdev->ev_sw_flags), "", + "Input device supported switch events"); +} + static int evdev_register_common(struct evdev_dev *evdev) { @@ -241,6 +324,12 @@ evdev_register_common(struct evdev_dev *evdev) /* Create char device node */ ret = evdev_cdev_create(evdev); + if (ret != 0) + goto bail_out; + + /* Create sysctls (for device enumeration without /dev/input access rights) */ + evdev_sysctl_create(evdev); + bail_out: return (ret); } @@ -278,6 +367,8 @@ evdev_unregister(struct evdev_dev *evdev) debugf(evdev, "%s: unregistered evdev provider: %s\n", evdev->ev_shortname, evdev->ev_name); + sysctl_ctx_free(&evdev->ev_sysctl_ctx); + EVDEV_LOCK(evdev); evdev->ev_cdev->si_drv1 = NULL; /* Wake up sleepers */ diff --git a/freebsd/sys/dev/evdev/evdev_private.h b/freebsd/sys/dev/evdev/evdev_private.h index 71bdecaa..d7f0b4ea 100644 --- a/freebsd/sys/dev/evdev/evdev_private.h +++ b/freebsd/sys/dev/evdev/evdev_private.h @@ -32,9 +32,12 @@ #include <sys/bitstring.h> #include <sys/kbio.h> +#include <sys/lock.h> #include <sys/malloc.h> +#include <sys/mutex.h> #include <sys/queue.h> #include <sys/selinfo.h> +#include <sys/sysctl.h> #include <dev/evdev/evdev.h> #include <dev/evdev/input.h> @@ -132,6 +135,9 @@ struct evdev_dev const struct evdev_methods * ev_methods; void * ev_softc; + /* Sysctl: */ + struct sysctl_ctx_list ev_sysctl_ctx; + LIST_ENTRY(evdev_dev) ev_link; LIST_HEAD(, evdev_client) ev_clients; }; diff --git a/freebsd/sys/dev/extres/clk/clk.h b/freebsd/sys/dev/extres/clk/clk.h index 617cd5e7..7e9fe4eb 100644 --- a/freebsd/sys/dev/extres/clk/clk.h +++ b/freebsd/sys/dev/extres/clk/clk.h @@ -48,6 +48,7 @@ #define CLK_SET_ROUND_EXACT 0 #define CLK_SET_ROUND_UP 0x00000001 #define CLK_SET_ROUND_DOWN 0x00000002 +#define CLK_SET_ROUND_MULTIPLE 0x00000004 #define CLK_SET_ROUND_ANY (CLK_SET_ROUND_UP | CLK_SET_ROUND_DOWN) #define CLK_SET_USER_MASK 0x0000FFFF diff --git a/freebsd/sys/dev/fb/fbd.c b/freebsd/sys/dev/fb/fbd.c index 871e193c..56f3605d 100644 --- a/freebsd/sys/dev/fb/fbd.c +++ b/freebsd/sys/dev/fb/fbd.c @@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$"); #include <sys/systm.h> #include <sys/bus.h> #include <sys/conf.h> +#include <sys/eventhandler.h> #include <sys/kernel.h> #include <sys/malloc.h> #include <sys/module.h> diff --git a/freebsd/sys/dev/fdt/fdt_common.c b/freebsd/sys/dev/fdt/fdt_common.c index ff32dc0a..12979fda 100644 --- a/freebsd/sys/dev/fdt/fdt_common.c +++ b/freebsd/sys/dev/fdt/fdt_common.c @@ -401,6 +401,9 @@ fdt_get_phyaddr(phandle_t node, device_t dev, int *phy_addr, void **phy_sc) *phy_addr = phy_reg; + if (phy_sc == NULL) + return (0); + /* * Search for softc used to communicate with phy. */ diff --git a/freebsd/sys/dev/gpio/gpiobus.c b/freebsd/sys/dev/gpio/gpiobus.c index 2b1899e6..d256ee4a 100644 --- a/freebsd/sys/dev/gpio/gpiobus.c +++ b/freebsd/sys/dev/gpio/gpiobus.c @@ -257,13 +257,6 @@ gpiobus_alloc_ivars(struct gpiobus_ivar *devi) M_NOWAIT | M_ZERO); if (devi->pins == NULL) return (ENOMEM); - devi->flags = malloc(sizeof(uint32_t) * devi->npins, M_DEVBUF, - M_NOWAIT | M_ZERO); - if (devi->flags == NULL) { - free(devi->pins, M_DEVBUF); - return (ENOMEM); - } - return (0); } @@ -271,14 +264,11 @@ void gpiobus_free_ivars(struct gpiobus_ivar *devi) { - if (devi->flags) { - free(devi->flags, M_DEVBUF); - devi->flags = NULL; - } if (devi->pins) { free(devi->pins, M_DEVBUF); devi->pins = NULL; } + devi->npins = 0; } int @@ -328,6 +318,34 @@ gpiobus_release_pin(device_t bus, uint32_t pin) } static int +gpiobus_acquire_child_pins(device_t dev, device_t child) +{ + struct gpiobus_ivar *devi = GPIOBUS_IVAR(child); + int i; + + for (i = 0; i < devi->npins; i++) { + /* Reserve the GPIO pin. */ + if (gpiobus_acquire_pin(dev, devi->pins[i]) != 0) { + device_printf(child, "cannot acquire pin %d\n", + devi->pins[i]); + while (--i >= 0) { + (void)gpiobus_release_pin(dev, + devi->pins[i]); + } + gpiobus_free_ivars(devi); + return (EBUSY); + } + } + for (i = 0; i < devi->npins; i++) { + /* Use the child name as pin name. */ + GPIOBUS_PIN_SETNAME(dev, devi->pins[i], + device_get_nameunit(child)); + + } + return (0); +} + +static int gpiobus_parse_pins(struct gpiobus_softc *sc, device_t child, int mask) { struct gpiobus_ivar *devi = GPIOBUS_IVAR(child); @@ -351,17 +369,66 @@ gpiobus_parse_pins(struct gpiobus_softc *sc, device_t child, int mask) for (i = 0; i < 32; i++) { if ((mask & (1 << i)) == 0) continue; - /* Reserve the GPIO pin. */ - if (gpiobus_acquire_pin(sc->sc_busdev, i) != 0) { - gpiobus_free_ivars(devi); - return (EINVAL); - } devi->pins[npins++] = i; - /* Use the child name as pin name. */ - GPIOBUS_PIN_SETNAME(sc->sc_busdev, i, - device_get_nameunit(child)); } + if (gpiobus_acquire_child_pins(sc->sc_busdev, child) != 0) + return (EINVAL); + return (0); +} + +static int +gpiobus_parse_pin_list(struct gpiobus_softc *sc, device_t child, + const char *pins) +{ + struct gpiobus_ivar *devi = GPIOBUS_IVAR(child); + const char *p; + char *endp; + unsigned long pin; + int i, npins; + + npins = 0; + p = pins; + for (;;) { + pin = strtoul(p, &endp, 0); + if (endp == p) + break; + npins++; + if (*endp == '\0') + break; + p = endp + 1; + } + + if (*endp != '\0') { + device_printf(child, "garbage in the pin list: %s\n", endp); + return (EINVAL); + } + if (npins == 0) { + device_printf(child, "empty pin list\n"); + return (EINVAL); + } + + devi->npins = npins; + if (gpiobus_alloc_ivars(devi) != 0) { + device_printf(child, "cannot allocate device ivars\n"); + return (EINVAL); + } + + i = 0; + p = pins; + for (;;) { + pin = strtoul(p, &endp, 0); + + devi->pins[i] = pin; + + if (*endp == '\0') + break; + i++; + p = endp + 1; + } + + if (gpiobus_acquire_child_pins(sc->sc_busdev, child) != 0) + return (EINVAL); return (0); } @@ -541,15 +608,26 @@ gpiobus_hinted_child(device_t bus, const char *dname, int dunit) struct gpiobus_softc *sc = GPIOBUS_SOFTC(bus); struct gpiobus_ivar *devi; device_t child; - int irq, pins; + const char *pins; + int irq, pinmask; 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)) { - resource_list_free(&devi->rl); - free(devi, M_DEVBUF); - device_delete_child(bus, child); + if (resource_int_value(dname, dunit, "pins", &pinmask) == 0) { + if (gpiobus_parse_pins(sc, child, pinmask)) { + resource_list_free(&devi->rl); + free(devi, M_DEVBUF); + device_delete_child(bus, child); + return; + } + } + else if (resource_string_value(dname, dunit, "pin_list", &pins) == 0) { + if (gpiobus_parse_pin_list(sc, child, pins)) { + resource_list_free(&devi->rl); + free(devi, M_DEVBUF); + device_delete_child(bus, child); + return; + } } if (resource_int_value(dname, dunit, "irq", &irq) == 0) { if (bus_set_resource(child, SYS_RES_IRQ, 0, irq, 1) != 0) @@ -576,6 +654,61 @@ gpiobus_set_resource(device_t dev, device_t child, int type, int rid, return (0); } +static int +gpiobus_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) +{ + struct gpiobus_ivar *devi; + + devi = GPIOBUS_IVAR(child); + switch (which) { + case GPIOBUS_IVAR_NPINS: + *result = devi->npins; + break; + case GPIOBUS_IVAR_PINS: + /* Children do not ever need to directly examine this. */ + return (ENOTSUP); + default: + return (ENOENT); + } + + return (0); +} + +static int +gpiobus_write_ivar(device_t dev, device_t child, int which, uintptr_t value) +{ + struct gpiobus_ivar *devi; + const uint32_t *ptr; + int i; + + devi = GPIOBUS_IVAR(child); + switch (which) { + case GPIOBUS_IVAR_NPINS: + /* GPIO ivars are set once. */ + if (devi->npins != 0) { + return (EBUSY); + } + devi->npins = value; + if (gpiobus_alloc_ivars(devi) != 0) { + device_printf(child, "cannot allocate device ivars\n"); + devi->npins = 0; + return (ENOMEM); + } + break; + case GPIOBUS_IVAR_PINS: + ptr = (const uint32_t *)value; + for (i = 0; i < devi->npins; i++) + devi->pins[i] = ptr[i]; + if (gpiobus_acquire_child_pins(dev, child) != 0) + return (EBUSY); + break; + default: + return (ENOENT); + } + + return (0); +} + static struct resource * gpiobus_alloc_resource(device_t bus, device_t child, int type, int *rid, rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) @@ -835,6 +968,8 @@ static device_method_t gpiobus_methods[] = { DEVMETHOD(bus_child_pnpinfo_str, gpiobus_child_pnpinfo_str), DEVMETHOD(bus_child_location_str, gpiobus_child_location_str), DEVMETHOD(bus_hinted_child, gpiobus_hinted_child), + DEVMETHOD(bus_read_ivar, gpiobus_read_ivar), + DEVMETHOD(bus_write_ivar, gpiobus_write_ivar), /* GPIO protocol */ DEVMETHOD(gpiobus_acquire_bus, gpiobus_acquire_bus), diff --git a/freebsd/sys/dev/gpio/gpiobusvar.h b/freebsd/sys/dev/gpio/gpiobusvar.h index 29677298..3ba8993e 100644 --- a/freebsd/sys/dev/gpio/gpiobusvar.h +++ b/freebsd/sys/dev/gpio/gpiobusvar.h @@ -107,10 +107,22 @@ struct gpiobus_ivar { struct resource_list rl; /* isr resource list */ uint32_t npins; /* pins total */ - uint32_t *flags; /* pins flags */ uint32_t *pins; /* pins map */ }; +enum gpiobus_ivars { + GPIOBUS_IVAR_NPINS = 10500, + GPIOBUS_IVAR_PINS, +}; + +#define GPIOBUS_ACCESSOR(var, ivar, type) \ + __BUS_ACCESSOR(gpiobus, var, GPIOBUS, ivar, type) + +GPIOBUS_ACCESSOR(npins, NPINS, uint32_t) +GPIOBUS_ACCESSOR(pins, PINS, const uint32_t *) + +#undef GPIOBUS_ACCESSOR + #ifdef FDT struct ofw_gpiobus_devinfo { struct gpiobus_ivar opd_dinfo; diff --git a/freebsd/sys/dev/gpio/ofw_gpiobus.c b/freebsd/sys/dev/gpio/ofw_gpiobus.c index ac0ea9bf..1cf3aa82 100644 --- a/freebsd/sys/dev/gpio/ofw_gpiobus.c +++ b/freebsd/sys/dev/gpio/ofw_gpiobus.c @@ -327,10 +327,8 @@ ofw_gpiobus_setup_devinfo(device_t bus, device_t child, phandle_t node) ofw_gpiobus_destroy_devinfo(bus, dinfo); return (NULL); } - for (i = 0; i < devi->npins; i++) { - devi->flags[i] = pins[i].flags; + for (i = 0; i < devi->npins; i++) devi->pins[i] = pins[i].pin; - } free(pins, M_DEVBUF); /* Parse the interrupt resources. */ if (ofw_bus_intr_to_rl(bus, node, &dinfo->opd_dinfo.rl, NULL) != 0) { diff --git a/freebsd/sys/dev/iicbus/iicbus.c b/freebsd/sys/dev/iicbus/iicbus.c index d1e55483..db8c8d92 100644 --- a/freebsd/sys/dev/iicbus/iicbus.c +++ b/freebsd/sys/dev/iicbus/iicbus.c @@ -196,9 +196,6 @@ iicbus_read_ivar(device_t bus, device_t child, int which, uintptr_t *result) case IICBUS_IVAR_ADDR: *result = devi->addr; break; - case IICBUS_IVAR_NOSTOP: - *result = devi->nostop; - break; } return (0); } @@ -215,9 +212,6 @@ iicbus_write_ivar(device_t bus, device_t child, int which, uintptr_t value) if (devi->addr != 0) return (EINVAL); devi->addr = value; - case IICBUS_IVAR_NOSTOP: - devi->nostop = value; - break; } return (0); } diff --git a/freebsd/sys/dev/iicbus/iicbus.h b/freebsd/sys/dev/iicbus/iicbus.h index 503305c7..c6382b63 100644 --- a/freebsd/sys/dev/iicbus/iicbus.h +++ b/freebsd/sys/dev/iicbus/iicbus.h @@ -41,6 +41,7 @@ struct iicbus_softc { device_t dev; /* Myself */ device_t owner; /* iicbus owner device structure */ + device_t busydev; /* iicbus_release_bus calls unbusy on this */ u_int owncount; /* iicbus ownership nesting count */ u_char started; /* address of the 'started' slave * 0 if no start condition succeeded */ @@ -54,24 +55,27 @@ struct iicbus_ivar { uint32_t addr; struct resource_list rl; - bool nostop; }; enum { - IICBUS_IVAR_ADDR, /* Address or base address */ - IICBUS_IVAR_NOSTOP, /* nostop defaults */ + IICBUS_IVAR_ADDR /* Address or base address */ }; #define IICBUS_ACCESSOR(A, B, T) \ __BUS_ACCESSOR(iicbus, A, IICBUS, B, T) IICBUS_ACCESSOR(addr, ADDR, uint32_t) -IICBUS_ACCESSOR(nostop, NOSTOP, bool) #define IICBUS_LOCK(sc) mtx_lock(&(sc)->lock) #define IICBUS_UNLOCK(sc) mtx_unlock(&(sc)->lock) #define IICBUS_ASSERT_LOCKED(sc) mtx_assert(&(sc)->lock, MA_OWNED) +#ifdef FDT +#define IICBUS_FDT_PNP_INFO(t) FDTCOMPAT_PNP_INFO(t, iicbus) +#else +#define IICBUS_FDT_PNP_INFO(t) +#endif + int iicbus_generic_intr(device_t dev, int event, char *buf); void iicbus_init_frequency(device_t dev, u_int bus_freq); diff --git a/freebsd/sys/dev/iicbus/iiconf.c b/freebsd/sys/dev/iicbus/iiconf.c index afdce118..c4926852 100644 --- a/freebsd/sys/dev/iicbus/iiconf.c +++ b/freebsd/sys/dev/iicbus/iiconf.c @@ -44,6 +44,18 @@ __FBSDID("$FreeBSD$"); #include <rtems/bsd/local/iicbus_if.h> /* + * Encode a system errno value into the IIC_Exxxxx space by setting the + * IIC_ERRNO marker bit, so that iic2errno() can turn it back into a plain + * system errno value later. This lets controller- and bus-layer code get + * important system errno values (such as EINTR/ERESTART) back to the caller. + */ +int +errno2iic(int error) +{ + return ((error == 0) ? 0 : error | IIC_ERRNO); +} + +/* * Translate IIC_Exxxxx status values to vaguely-equivelent errno values. */ int @@ -61,7 +73,22 @@ iic2errno(int iic_status) case IIC_ENOTSUPP: return (EOPNOTSUPP); case IIC_ENOADDR: return (EADDRNOTAVAIL); case IIC_ERESOURCE: return (ENOMEM); - default: return (EIO); + default: + /* + * If the high bit is set, that means it's a system errno value + * that was encoded into the IIC_Exxxxxx space by setting the + * IIC_ERRNO marker bit. If lots of high-order bits are set, + * then it's one of the negative pseudo-errors such as ERESTART + * and we return it as-is. Otherwise it's a plain "small + * positive integer" errno, so just remove the IIC_ERRNO marker + * bit. If it's some unknown number without the high bit set, + * there isn't much we can do except call it an I/O error. + */ + if ((iic_status & IIC_ERRNO) == 0) + return (EIO); + if ((iic_status & 0xFFFF0000) != 0) + return (iic_status); + return (iic_status & ~IIC_ERRNO); } } @@ -99,7 +126,7 @@ iicbus_poll(struct iicbus_softc *sc, int how) return (IIC_EBUSBSY); } - return (error); + return (errno2iic(error)); } /* @@ -130,6 +157,18 @@ iicbus_request_bus(device_t bus, device_t dev, int how) ++sc->owncount; if (sc->owner == NULL) { sc->owner = dev; + /* + * Mark the device busy while it owns the bus, to + * prevent detaching the device, bus, or hardware + * controller, until ownership is relinquished. If the + * device is doing IO from its probe method before + * attaching, it cannot be busied; mark the bus busy. + */ + if (device_get_state(dev) < DS_ATTACHING) + sc->busydev = bus; + else + sc->busydev = dev; + device_busy(sc->busydev); /* * Drop the lock around the call to the bus driver, it * should be allowed to sleep in the IIC_WAIT case. @@ -146,6 +185,7 @@ iicbus_request_bus(device_t bus, device_t dev, int how) sc->owner = NULL; sc->owncount = 0; wakeup_one(sc); + device_unbusy(sc->busydev); } } } @@ -179,6 +219,7 @@ iicbus_release_bus(device_t bus, device_t dev) IICBUS_LOCK(sc); sc->owner = NULL; wakeup_one(sc); + device_unbusy(sc->busydev); } IICBUS_UNLOCK(sc); return (0); @@ -422,7 +463,7 @@ iicbus_transfer_gen(device_t dev, struct iic_msg *msgs, uint32_t nmsgs) { int i, error, lenread, lenwrote, nkid, rpstart, addr; device_t *children, bus; - bool nostop, started; + bool started; if ((error = device_get_children(dev, &children, &nkid)) != 0) return (IIC_ERESOURCE); @@ -433,7 +474,6 @@ iicbus_transfer_gen(device_t dev, struct iic_msg *msgs, uint32_t nmsgs) bus = children[0]; rpstart = 0; free(children, M_TEMP); - nostop = iicbus_get_nostop(dev); started = false; for (i = 0, error = 0; i < nmsgs && error == 0; i++) { addr = msgs[i].slave; @@ -461,12 +501,11 @@ iicbus_transfer_gen(device_t dev, struct iic_msg *msgs, uint32_t nmsgs) if (error != 0) break; - if ((msgs[i].flags & IIC_M_NOSTOP) != 0 || - (nostop && i + 1 < nmsgs)) { - rpstart = 1; /* Next message gets repeated start */ - } else { + if (!(msgs[i].flags & IIC_M_NOSTOP)) { rpstart = 0; iicbus_stop(bus); + } else { + rpstart = 1; /* Next message gets repeated start */ } } if (error != 0 && started) diff --git a/freebsd/sys/dev/iicbus/iiconf.h b/freebsd/sys/dev/iicbus/iiconf.h index c264183e..5fbfcea5 100644 --- a/freebsd/sys/dev/iicbus/iiconf.h +++ b/freebsd/sys/dev/iicbus/iiconf.h @@ -96,12 +96,14 @@ #define IIC_ENOTSUPP 0x8 /* request not supported */ #define IIC_ENOADDR 0x9 /* no address assigned to the interface */ #define IIC_ERESOURCE 0xa /* resources (memory, whatever) unavailable */ +#define IIC_ERRNO INT_MIN /* marker bit: errno is in low-order bits */ /* * Note that all iicbus functions return IIC_Exxxxx status values, * except iic2errno() (obviously) and iicbus_started() (returns bool). */ extern int iic2errno(int); +extern int errno2iic(int); extern int iicbus_request_bus(device_t, device_t, int); extern int iicbus_release_bus(device_t, device_t); extern device_t iicbus_alloc_bus(device_t); diff --git a/freebsd/sys/dev/led/led.c b/freebsd/sys/dev/led/led.c index 70de95bb..43ae2f66 100644 --- a/freebsd/sys/dev/led/led.c +++ b/freebsd/sys/dev/led/led.c @@ -17,16 +17,19 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/conf.h> +#include <sys/ctype.h> #include <sys/kernel.h> -#include <sys/systm.h> #include <sys/limits.h> +#include <sys/lock.h> #include <sys/malloc.h> -#include <sys/ctype.h> -#include <sys/sbuf.h> +#include <sys/mutex.h> #include <sys/queue.h> -#include <dev/led/led.h> -#include <sys/uio.h> +#include <sys/sbuf.h> #include <sys/sx.h> +#include <sys/systm.h> +#include <sys/uio.h> + +#include <dev/led/led.h> struct ledsc { LIST_ENTRY(ledsc) list; @@ -263,7 +266,7 @@ led_set(char const *name, char const *cmd) mtx_unlock(&led_mtx); if (sb != NULL) sbuf_delete(sb); - return (0); + return (error); } static struct cdevsw led_cdevsw = { diff --git a/freebsd/sys/dev/mii/micphy.c b/freebsd/sys/dev/mii/micphy.c index 01e75357..f9493332 100644 --- a/freebsd/sys/dev/mii/micphy.c +++ b/freebsd/sys/dev/mii/micphy.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-kernel-space.h> /*- - * Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com> + * Copyright (c) 2014,2019 Ruslan Bukin <br@bsdpad.com> * All rights reserved. * * This software was developed by SRI International and the University of @@ -34,7 +34,7 @@ __FBSDID("$FreeBSD$"); /* - * Micrel KSZ9021 Gigabit Ethernet Transceiver + * Micrel KSZ8081/KSZ9021/KSZ9031 Gigabit Ethernet Transceiver */ #include <sys/param.h> @@ -61,6 +61,7 @@ __FBSDID("$FreeBSD$"); #include <dev/ofw/openfirm.h> #include <dev/ofw/ofw_bus.h> #include <dev/ofw/ofw_bus_subr.h> +#include <dev/mii/mii_fdt.h> #define MII_KSZPHY_EXTREG 0x0b #define KSZPHY_EXTREG_WRITE (1 << 15) @@ -253,6 +254,7 @@ micphy_probe(device_t dev) static int micphy_attach(device_t dev) { + mii_fdt_phy_config_t *cfg; struct mii_softc *sc; phandle_t node; device_t miibus; @@ -273,10 +275,12 @@ micphy_attach(device_t dev) if ((node = ofw_bus_get_node(parent)) == -1) return (ENXIO); + cfg = mii_fdt_get_config(dev); + if (sc->mii_mpd_model == MII_MODEL_MICREL_KSZ9031) - ksz9031_load_values(sc, node); + ksz9031_load_values(sc, cfg->phynode); else - ksz9021_load_values(sc, node); + ksz9021_load_values(sc, cfg->phynode); return (0); } diff --git a/freebsd/sys/dev/mmc/bridge.h b/freebsd/sys/dev/mmc/bridge.h index 7af811f1..d32abbac 100644 --- a/freebsd/sys/dev/mmc/bridge.h +++ b/freebsd/sys/dev/mmc/bridge.h @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * - * Copyright (c) 2006 M. Warner Losh. All rights reserved. + * Copyright (c) 2006 M. Warner Losh. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/freebsd/sys/dev/mmc/mmc.c b/freebsd/sys/dev/mmc/mmc.c index 4c8aefcf..5bc3bbf7 100644 --- a/freebsd/sys/dev/mmc/mmc.c +++ b/freebsd/sys/dev/mmc/mmc.c @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2006 Bernd Walter. All rights reserved. - * Copyright (c) 2006 M. Warner Losh. All rights reserved. + * Copyright (c) 2006 M. Warner Losh. * Copyright (c) 2017 Marius Strobl <marius@FreeBSD.org> * * Redistribution and use in source and binary forms, with or without diff --git a/freebsd/sys/dev/mmc/mmc_private.h b/freebsd/sys/dev/mmc/mmc_private.h index 633d0784..a633d235 100644 --- a/freebsd/sys/dev/mmc/mmc_private.h +++ b/freebsd/sys/dev/mmc/mmc_private.h @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Bernd Walter. All rights reserved. - * Copyright (c) 2006 M. Warner Losh. All rights reserved. + * Copyright (c) 2006 M. Warner Losh. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/freebsd/sys/dev/mmc/mmc_subr.c b/freebsd/sys/dev/mmc/mmc_subr.c index 76a14028..1e3bef16 100644 --- a/freebsd/sys/dev/mmc/mmc_subr.c +++ b/freebsd/sys/dev/mmc/mmc_subr.c @@ -2,7 +2,7 @@ /*- * Copyright (c) 2006 Bernd Walter. All rights reserved. - * Copyright (c) 2006 M. Warner Losh. All rights reserved. + * Copyright (c) 2006 M. Warner Losh. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/freebsd/sys/dev/mmc/mmc_subr.h b/freebsd/sys/dev/mmc/mmc_subr.h index 33ea6760..80c1ce2f 100644 --- a/freebsd/sys/dev/mmc/mmc_subr.h +++ b/freebsd/sys/dev/mmc/mmc_subr.h @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Bernd Walter. All rights reserved. - * Copyright (c) 2006 M. Warner Losh. All rights reserved. + * Copyright (c) 2006 M. Warner Losh. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/freebsd/sys/dev/mmc/mmcbrvar.h b/freebsd/sys/dev/mmc/mmcbrvar.h index acddd3a3..f2f107c7 100644 --- a/freebsd/sys/dev/mmc/mmcbrvar.h +++ b/freebsd/sys/dev/mmc/mmcbrvar.h @@ -2,7 +2,7 @@ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2006 Bernd Walter. All rights reserved. - * Copyright (c) 2006 M. Warner Losh. All rights reserved. + * Copyright (c) 2006 M. Warner Losh. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/freebsd/sys/dev/mmc/mmcreg.h b/freebsd/sys/dev/mmc/mmcreg.h index 4b1f8a0e..f6031410 100644 --- a/freebsd/sys/dev/mmc/mmcreg.h +++ b/freebsd/sys/dev/mmc/mmcreg.h @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * - * Copyright (c) 2006 M. Warner Losh. All rights reserved. + * Copyright (c) 2006 M. Warner Losh. * Copyright (c) 2017 Marius Strobl <marius@FreeBSD.org> * Copyright (c) 2015-2016 Ilya Bakulin <kibab@FreeBSD.org> * @@ -200,7 +200,10 @@ struct mmc_data { #define MMC_DATA_READ (1UL << 1) #define MMC_DATA_STREAM (1UL << 2) #define MMC_DATA_MULTI (1UL << 3) +#define MMC_DATA_BLOCK_SIZE (1UL << 4) struct mmc_request *mrq; + size_t block_size; /* block size for CMD53 */ + size_t block_count; /* block count for CMD53 */ }; struct mmc_request { @@ -554,30 +557,39 @@ struct mmc_request { #define SD_IO_RW_LEN(x) (((x) & 0xFF) << 0) #define SD_IOE_RW_LEN(x) (((x) & 0x1FF) << 0) +#define SD_IOE_RW_ADR(x) (((x) & 0x1FFFF) << 9) +#define SD_IOE_RW_INCR (1u << 26) #define SD_IOE_RW_BLK (1u << 27) +#define SD_IOE_RW_FUNC(x) (((x) & 0x7) << 28) +#define SD_IOE_RW_WR (1u << 31) /* Card Common Control Registers (CCCR) */ -#define SD_IO_CCCR_START 0x00000 -#define SD_IO_CCCR_SIZE 0x100 -#define SD_IO_CCCR_FN_ENABLE 0x02 -#define SD_IO_CCCR_FN_READY 0x03 -#define SD_IO_CCCR_INT_ENABLE 0x04 -#define SD_IO_CCCR_INT_PENDING 0x05 -#define SD_IO_CCCR_CTL 0x06 -#define CCCR_CTL_RES (1 << 3) -#define SD_IO_CCCR_BUS_WIDTH 0x07 +#define SD_IO_CCCR_START 0x00000 /* Offset in F0 address space */ +#define SD_IO_CCCR_SIZE 0x100 /* Total size of CCCR */ +#define SD_IO_CCCR_FN_ENABLE 0x02 /* Enabled functions */ +#define SD_IO_CCCR_FN_READY 0x03 /* Function ready status */ +#define SD_IO_CCCR_INT_ENABLE 0x04 /* Per-function interrupt enable */ +#define SD_IO_CCCR_INT_PENDING 0x05 /* Per-function interrupt pending */ +#define SD_IO_CCCR_CTL 0x06 /* I/O Abort register */ +#define CCCR_CTL_RES (1 << 3) /* Perform SDIO reset */ +#define SD_IO_CCCR_BUS_WIDTH 0x07 /* Bus Width register */ #define CCCR_BUS_WIDTH_4 (1 << 1) #define CCCR_BUS_WIDTH_1 (1 << 0) -#define SD_IO_CCCR_CARDCAP 0x08 -#define SD_IO_CCCR_CISPTR 0x09 /* XXX 9-10, 10-11, or 9-12 */ - +#define SD_IO_CCCR_CARDCAP 0x08 /* SDIO card capabilities */ +#define CCCR_CC_SMB (1 << 1) /* CMD53 block mode support */ +#define SD_IO_CCCR_CISPTR 0x09 /* 0x09 - 0x0B */ +#define SD_IO_CCCR_FN0_BLKSZ 0x10 /* 0x10 - 0x11 */ /* Function Basic Registers (FBR) */ -#define SD_IO_FBR_START 0x00100 -#define SD_IO_FBR_SIZE 0x00700 +#define SD_IO_FBR_START 0x00100 /* Offset in F0 address space */ +#define SD_IO_FBR_SIZE 0x00700 /* Total size of FBR */ +#define SD_IO_FBR_F_SIZE 0x00100 /* Size of each function */ +#define SD_IO_FBR_START_F(n) (SD_IO_FBR_START + (n-1) * SD_IO_FBR_F_SIZE) +#define SD_IO_FBR_CIS_OFFSET 0x9 /* Offset of this function's info block within CIS area */ +#define SD_IO_FBR_IOBLKSZ 0x10 /* Block size for CMD53 block mode operations */ /* Card Information Structure (CIS) */ -#define SD_IO_CIS_START 0x01000 -#define SD_IO_CIS_SIZE 0x17000 +#define SD_IO_CIS_START 0x01000 /* Offset in F0 address space */ +#define SD_IO_CIS_SIZE 0x17000 /* Total size of CIS */ /* CIS tuple codes (based on PC Card 16) */ #define SD_IO_CISTPL_VERS_1 0x15 diff --git a/freebsd/sys/dev/mmc/mmcsd.c b/freebsd/sys/dev/mmc/mmcsd.c index e469c1d5..8fc06eb2 100644 --- a/freebsd/sys/dev/mmc/mmcsd.c +++ b/freebsd/sys/dev/mmc/mmcsd.c @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2006 Bernd Walter. All rights reserved. - * Copyright (c) 2006 M. Warner Losh. All rights reserved. + * Copyright (c) 2006 M. Warner Losh. * Copyright (c) 2017 Marius Strobl <marius@FreeBSD.org> * * Redistribution and use in source and binary forms, with or without @@ -813,7 +813,7 @@ mmcsd_add_part(struct mmcsd_softc *sc, u_int type, const char *name, u_int cnt, speed / 1000000, (speed / 100000) % 10, mmcsd_bus_bit_width(dev), sc->max_data); } else if (type == EXT_CSD_PART_CONFIG_ACC_RPMB) { - printf("%s: %ju%sB partion %d%s at %s\n", part->name, bytes, + printf("%s: %ju%sB partition %d%s at %s\n", part->name, bytes, unit, type, ro ? " (read-only)" : "", device_get_nameunit(dev)); } else { @@ -849,12 +849,12 @@ mmcsd_add_part(struct mmcsd_softc *sc, u_int type, const char *name, u_int cnt, } } if (ext == NULL) - printf("%s%d: %ju%sB partion %d%s%s at %s\n", + printf("%s%d: %ju%sB partition %d%s%s at %s\n", part->name, cnt, bytes, unit, type, enh ? " enhanced" : "", ro ? " (read-only)" : "", device_get_nameunit(dev)); else - printf("%s%d: %ju%sB partion %d extended 0x%x " + printf("%s%d: %ju%sB partition %d extended 0x%x " "(%s)%s at %s\n", part->name, cnt, bytes, unit, type, extattr, ext, ro ? " (read-only)" : "", device_get_nameunit(dev)); diff --git a/freebsd/sys/dev/mmc/mmcvar.h b/freebsd/sys/dev/mmc/mmcvar.h index 1604c306..8d8c5547 100644 --- a/freebsd/sys/dev/mmc/mmcvar.h +++ b/freebsd/sys/dev/mmc/mmcvar.h @@ -2,7 +2,7 @@ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2006 Bernd Walter. All rights reserved. - * Copyright (c) 2006 M. Warner Losh. All rights reserved. + * Copyright (c) 2006 M. Warner Losh. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/freebsd/sys/dev/nvme/nvme.h b/freebsd/sys/dev/nvme/nvme.h index 845ba75b..0d4a18b7 100644 --- a/freebsd/sys/dev/nvme/nvme.h +++ b/freebsd/sys/dev/nvme/nvme.h @@ -40,6 +40,7 @@ #define NVME_PASSTHROUGH_CMD _IOWR('n', 0, struct nvme_pt_command) #define NVME_RESET_CONTROLLER _IO('n', 1) +#define NVME_GET_NSID _IOR('n', 2, struct nvme_get_nsid) #define NVME_IO_TEST _IOWR('n', 100, struct nvme_io_test) #define NVME_BIO_TEST _IOWR('n', 101, struct nvme_io_test) @@ -69,15 +70,39 @@ #define NVME_CAP_LO_REG_AMS_MASK (0x3) #define NVME_CAP_LO_REG_TO_SHIFT (24) #define NVME_CAP_LO_REG_TO_MASK (0xFF) +#define NVME_CAP_LO_MQES(x) \ + (((x) >> NVME_CAP_LO_REG_MQES_SHIFT) & NVME_CAP_LO_REG_MQES_MASK) +#define NVME_CAP_LO_CQR(x) \ + (((x) >> NVME_CAP_LO_REG_CQR_SHIFT) & NVME_CAP_LO_REG_CQR_MASK) +#define NVME_CAP_LO_AMS(x) \ + (((x) >> NVME_CAP_LO_REG_AMS_SHIFT) & NVME_CAP_LO_REG_AMS_MASK) +#define NVME_CAP_LO_TO(x) \ + (((x) >> NVME_CAP_LO_REG_TO_SHIFT) & NVME_CAP_LO_REG_TO_MASK) #define NVME_CAP_HI_REG_DSTRD_SHIFT (0) #define NVME_CAP_HI_REG_DSTRD_MASK (0xF) +#define NVME_CAP_HI_REG_NSSRS_SHIFT (4) +#define NVME_CAP_HI_REG_NSSRS_MASK (0x1) #define NVME_CAP_HI_REG_CSS_NVM_SHIFT (5) #define NVME_CAP_HI_REG_CSS_NVM_MASK (0x1) +#define NVME_CAP_HI_REG_BPS_SHIFT (13) +#define NVME_CAP_HI_REG_BPS_MASK (0x1) #define NVME_CAP_HI_REG_MPSMIN_SHIFT (16) #define NVME_CAP_HI_REG_MPSMIN_MASK (0xF) #define NVME_CAP_HI_REG_MPSMAX_SHIFT (20) #define NVME_CAP_HI_REG_MPSMAX_MASK (0xF) +#define NVME_CAP_HI_REG_PMRS_SHIFT (24) +#define NVME_CAP_HI_REG_PMRS_MASK (0x1) +#define NVME_CAP_HI_REG_CMBS_SHIFT (25) +#define NVME_CAP_HI_REG_CMBS_MASK (0x1) +#define NVME_CAP_HI_DSTRD(x) \ + (((x) >> NVME_CAP_HI_REG_DSTRD_SHIFT) & NVME_CAP_HI_REG_DSTRD_MASK) +#define NVME_CAP_HI_CSS_NVM(x) \ + (((x) >> NVME_CAP_HI_REG_CSS_NVM_SHIFT) & NVME_CAP_HI_REG_CSS_NVM_MASK) +#define NVME_CAP_HI_MPSMIN(x) \ + (((x) >> NVME_CAP_HI_REG_MPSMIN_SHIFT) & NVME_CAP_HI_REG_MPSMIN_MASK) +#define NVME_CAP_HI_MPSMAX(x) \ + (((x) >> NVME_CAP_HI_REG_MPSMAX_SHIFT) & NVME_CAP_HI_REG_MPSMAX_MASK) #define NVME_CC_REG_EN_SHIFT (0) #define NVME_CC_REG_EN_MASK (0x1) @@ -100,6 +125,10 @@ #define NVME_CSTS_REG_CFS_MASK (0x1) #define NVME_CSTS_REG_SHST_SHIFT (2) #define NVME_CSTS_REG_SHST_MASK (0x3) +#define NVME_CSTS_REG_NVSRO_SHIFT (4) +#define NVME_CSTS_REG_NVSRO_MASK (0x1) +#define NVME_CSTS_REG_PP_SHIFT (5) +#define NVME_CSTS_REG_PP_MASK (0x1) #define NVME_CSTS_GET_SHST(csts) (((csts) >> NVME_CSTS_REG_SHST_SHIFT) & NVME_CSTS_REG_SHST_MASK) @@ -119,6 +148,8 @@ #define NVME_STATUS_SC_MASK (0xFF) #define NVME_STATUS_SCT_SHIFT (9) #define NVME_STATUS_SCT_MASK (0x7) +#define NVME_STATUS_CRD_SHIFT (12) +#define NVME_STATUS_CRD_MASK (0x3) #define NVME_STATUS_M_SHIFT (14) #define NVME_STATUS_M_MASK (0x1) #define NVME_STATUS_DNR_SHIFT (15) @@ -159,6 +190,9 @@ /* SR-IOV Virtual Function */ #define NVME_CTRLR_DATA_MIC_SRIOVVF_SHIFT (2) #define NVME_CTRLR_DATA_MIC_SRIOVVF_MASK (0x1) +/* Asymmetric Namespace Access Reporting */ +#define NVME_CTRLR_DATA_MIC_ANAR_SHIFT (3) +#define NVME_CTRLR_DATA_MIC_ANAR_MASK (0x1) /** OACS - optional admin command support */ /* supports security send/receive commands */ @@ -188,6 +222,9 @@ /* supports Doorbell Buffer Config */ #define NVME_CTRLR_DATA_OACS_DBBUFFER_SHIFT (8) #define NVME_CTRLR_DATA_OACS_DBBUFFER_MASK (0x1) +/* supports Get LBA Status */ +#define NVME_CTRLR_DATA_OACS_GETLBA_SHIFT (9) +#define NVME_CTRLR_DATA_OACS_GETLBA_MASK (0x1) /** firmware updates */ /* first slot is read-only */ @@ -196,6 +233,9 @@ /* number of firmware slots */ #define NVME_CTRLR_DATA_FRMW_NUM_SLOTS_SHIFT (1) #define NVME_CTRLR_DATA_FRMW_NUM_SLOTS_MASK (0x7) +/* firmware activation without reset */ +#define NVME_CTRLR_DATA_FRMW_ACT_WO_RESET_SHIFT (4) +#define NVME_CTRLR_DATA_FRMW_ACT_WO_RESET_MASK (0x1) /** log page attributes */ /* per namespace smart/health log page */ @@ -212,6 +252,26 @@ #define NVME_CTRLR_DATA_APSTA_APST_SUPP_SHIFT (0) #define NVME_CTRLR_DATA_APSTA_APST_SUPP_MASK (0x1) +/** Sanitize Capabilities */ +/* Crypto Erase Support */ +#define NVME_CTRLR_DATA_SANICAP_CES_SHIFT (0) +#define NVME_CTRLR_DATA_SANICAP_CES_MASK (0x1) +/* Block Erase Support */ +#define NVME_CTRLR_DATA_SANICAP_BES_SHIFT (1) +#define NVME_CTRLR_DATA_SANICAP_BES_MASK (0x1) +/* Overwrite Support */ +#define NVME_CTRLR_DATA_SANICAP_OWS_SHIFT (2) +#define NVME_CTRLR_DATA_SANICAP_OWS_MASK (0x1) +/* No-Deallocate Inhibited */ +#define NVME_CTRLR_DATA_SANICAP_NDI_SHIFT (29) +#define NVME_CTRLR_DATA_SANICAP_NDI_MASK (0x1) +/* No-Deallocate Modifies Media After Sanitize */ +#define NVME_CTRLR_DATA_SANICAP_NODMMAS_SHIFT (30) +#define NVME_CTRLR_DATA_SANICAP_NODMMAS_MASK (0x3) +#define NVME_CTRLR_DATA_SANICAP_NODMMAS_UNDEF (0) +#define NVME_CTRLR_DATA_SANICAP_NODMMAS_NO (1) +#define NVME_CTRLR_DATA_SANICAP_NODMMAS_YES (2) + /** submission queue entry size */ #define NVME_CTRLR_DATA_SQES_MIN_SHIFT (0) #define NVME_CTRLR_DATA_SQES_MIN_MASK (0xF) @@ -239,6 +299,8 @@ #define NVME_CTRLR_DATA_ONCS_RESERV_MASK (0x1) #define NVME_CTRLR_DATA_ONCS_TIMESTAMP_SHIFT (6) #define NVME_CTRLR_DATA_ONCS_TIMESTAMP_MASK (0x1) +#define NVME_CTRLR_DATA_ONCS_VERIFY_SHIFT (7) +#define NVME_CTRLR_DATA_ONCS_VERIFY_MASK (0x1) /** Fused Operation Support */ #define NVME_CTRLR_DATA_FUSES_CNW_SHIFT (0) @@ -253,8 +315,15 @@ #define NVME_CTRLR_DATA_FNA_CRYPTO_ERASE_MASK (0x1) /** volatile write cache */ +/* volatile write cache present */ #define NVME_CTRLR_DATA_VWC_PRESENT_SHIFT (0) #define NVME_CTRLR_DATA_VWC_PRESENT_MASK (0x1) +/* flush all namespaces supported */ +#define NVME_CTRLR_DATA_VWC_ALL_SHIFT (1) +#define NVME_CTRLR_DATA_VWC_ALL_MASK (0x3) +#define NVME_CTRLR_DATA_VWC_ALL_UNKNOWN (0) +#define NVME_CTRLR_DATA_VWC_ALL_NO (2) +#define NVME_CTRLR_DATA_VWC_ALL_YES (3) /** namespace features */ /* thin provisioning */ @@ -269,6 +338,9 @@ /* NGUID and EUI64 fields are not reusable */ #define NVME_NS_DATA_NSFEAT_NO_ID_REUSE_SHIFT (3) #define NVME_NS_DATA_NSFEAT_NO_ID_REUSE_MASK (0x1) +/* NPWG, NPWA, NPDG, NPDA, and NOWS are valid */ +#define NVME_NS_DATA_NSFEAT_NPVALID_SHIFT (4) +#define NVME_NS_DATA_NSFEAT_NPVALID_MASK (0x1) /** formatted lba size */ #define NVME_NS_DATA_FLBAS_FORMAT_SHIFT (0) @@ -349,6 +421,20 @@ #define NVME_NS_DATA_FPI_SUPP_SHIFT (7) #define NVME_NS_DATA_FPI_SUPP_MASK (0x1) +/** Deallocate Logical Block Features */ +/* deallocated logical block read behavior */ +#define NVME_NS_DATA_DLFEAT_READ_SHIFT (0) +#define NVME_NS_DATA_DLFEAT_READ_MASK (0x07) +#define NVME_NS_DATA_DLFEAT_READ_NR (0x00) +#define NVME_NS_DATA_DLFEAT_READ_00 (0x01) +#define NVME_NS_DATA_DLFEAT_READ_FF (0x02) +/* supports the Deallocate bit in the Write Zeroes */ +#define NVME_NS_DATA_DLFEAT_DWZ_SHIFT (3) +#define NVME_NS_DATA_DLFEAT_DWZ_MASK (0x01) +/* Guard field for deallocated logical blocks is set to the CRC */ +#define NVME_NS_DATA_DLFEAT_GCRC_SHIFT (4) +#define NVME_NS_DATA_DLFEAT_GCRC_MASK (0x01) + /** lba format support */ /* metadata size */ #define NVME_NS_DATA_LBAF_MS_SHIFT (0) @@ -373,6 +459,35 @@ enum nvme_critical_warning_state { #define NVME_FIRMWARE_PAGE_AFI_SLOT_SHIFT (0) #define NVME_FIRMWARE_PAGE_AFI_SLOT_MASK (0x7) +/* Commands Supported and Effects */ +#define NVME_CE_PAGE_CSUP_SHIFT (0) +#define NVME_CE_PAGE_CSUP_MASK (0x1) +#define NVME_CE_PAGE_LBCC_SHIFT (1) +#define NVME_CE_PAGE_LBCC_MASK (0x1) +#define NVME_CE_PAGE_NCC_SHIFT (2) +#define NVME_CE_PAGE_NCC_MASK (0x1) +#define NVME_CE_PAGE_NIC_SHIFT (3) +#define NVME_CE_PAGE_NIC_MASK (0x1) +#define NVME_CE_PAGE_CCC_SHIFT (4) +#define NVME_CE_PAGE_CCC_MASK (0x1) +#define NVME_CE_PAGE_CSE_SHIFT (16) +#define NVME_CE_PAGE_CSE_MASK (0x7) +#define NVME_CE_PAGE_UUID_SHIFT (19) +#define NVME_CE_PAGE_UUID_MASK (0x1) + +/* Sanitize Status */ +#define NVME_SS_PAGE_SSTAT_STATUS_SHIFT (0) +#define NVME_SS_PAGE_SSTAT_STATUS_MASK (0x7) +#define NVME_SS_PAGE_SSTAT_STATUS_NEVER (0) +#define NVME_SS_PAGE_SSTAT_STATUS_COMPLETED (1) +#define NVME_SS_PAGE_SSTAT_STATUS_INPROG (2) +#define NVME_SS_PAGE_SSTAT_STATUS_FAILED (3) +#define NVME_SS_PAGE_SSTAT_STATUS_COMPLETEDWD (4) +#define NVME_SS_PAGE_SSTAT_PASSES_SHIFT (3) +#define NVME_SS_PAGE_SSTAT_PASSES_MASK (0x1f) +#define NVME_SS_PAGE_SSTAT_GDE_SHIFT (8) +#define NVME_SS_PAGE_SSTAT_GDE_MASK (0x1) + /* CC register SHN field values */ enum shn_value { NVME_SHN_NORMAL = 0x1, @@ -388,34 +503,37 @@ enum shst_value { struct nvme_registers { - /** controller capabilities */ - uint32_t cap_lo; - uint32_t cap_hi; - - uint32_t vs; /* version */ - uint32_t intms; /* interrupt mask set */ - uint32_t intmc; /* interrupt mask clear */ - - /** controller configuration */ - uint32_t cc; - - uint32_t reserved1; - - /** controller status */ - uint32_t csts; - - uint32_t reserved2; - - /** admin queue attributes */ - uint32_t aqa; - - uint64_t asq; /* admin submission queue base addr */ - uint64_t acq; /* admin completion queue base addr */ - uint32_t reserved3[0x3f2]; - + uint32_t cap_lo; /* controller capabilities */ + uint32_t cap_hi; + uint32_t vs; /* version */ + uint32_t intms; /* interrupt mask set */ + uint32_t intmc; /* interrupt mask clear */ + uint32_t cc; /* controller configuration */ + uint32_t reserved1; + uint32_t csts; /* controller status */ + uint32_t nssr; /* NVM Subsystem Reset */ + uint32_t aqa; /* admin queue attributes */ + uint64_t asq; /* admin submission queue base addr */ + uint64_t acq; /* admin completion queue base addr */ + uint32_t cmbloc; /* Controller Memory Buffer Location */ + uint32_t cmbsz; /* Controller Memory Buffer Size */ + uint32_t bpinfo; /* Boot Partition Information */ + uint32_t bprsel; /* Boot Partition Read Select */ + uint64_t bpmbl; /* Boot Partition Memory Buffer Location */ + uint64_t cmbmsc; /* Controller Memory Buffer Memory Space Control */ + uint32_t cmbsts; /* Controller Memory Buffer Status */ + uint8_t reserved3[3492]; /* 5Ch - DFFh */ + uint32_t pmrcap; /* Persistent Memory Capabilities */ + uint32_t pmrctl; /* Persistent Memory Region Control */ + uint32_t pmrsts; /* Persistent Memory Region Status */ + uint32_t pmrebs; /* Persistent Memory Region Elasticity Buffer Size */ + uint32_t pmrswtp; /* Persistent Memory Region Sustained Write Throughput */ + uint32_t pmrmsc_lo; /* Persistent Memory Region Controller Memory Space Control */ + uint32_t pmrmsc_hi; + uint8_t reserved4[484]; /* E1Ch - FFFh */ struct { - uint32_t sq_tdbl; /* submission queue tail doorbell */ - uint32_t cq_hdbl; /* completion queue head doorbell */ + uint32_t sq_tdbl; /* submission queue tail doorbell */ + uint32_t cq_hdbl; /* completion queue head doorbell */ } doorbell[1] __packed; } __packed; @@ -490,6 +608,7 @@ enum nvme_status_code_type { NVME_SCT_GENERIC = 0x0, NVME_SCT_COMMAND_SPECIFIC = 0x1, NVME_SCT_MEDIA_ERROR = 0x2, + NVME_SCT_PATH_RELATED = 0x3, /* 0x3-0x6 - reserved */ NVME_SCT_VENDOR_SPECIFIC = 0x7, }; @@ -528,6 +647,9 @@ enum nvme_generic_command_status_code { NVME_SC_SANITIZE_IN_PROGRESS = 0x1d, NVME_SC_SGL_DATA_BLOCK_GRAN_INVALID = 0x1e, NVME_SC_NOT_SUPPORTED_IN_CMB = 0x1f, + NVME_SC_NAMESPACE_IS_WRITE_PROTECTED = 0x20, + NVME_SC_COMMAND_INTERRUPTED = 0x21, + NVME_SC_TRANSIENT_TRANSPORT_ERROR = 0x22, NVME_SC_LBA_OUT_OF_RANGE = 0x80, NVME_SC_CAPACITY_EXCEEDED = 0x81, @@ -573,6 +695,9 @@ enum nvme_command_specific_status_code { NVME_SC_INVALID_SEC_CTRLR_STATE = 0x20, NVME_SC_INVALID_NUM_OF_CTRLR_RESRC = 0x21, NVME_SC_INVALID_RESOURCE_ID = 0x22, + NVME_SC_SANITIZE_PROHIBITED_WPMRE = 0x23, + NVME_SC_ANA_GROUP_ID_INVALID = 0x24, + NVME_SC_ANA_ATTACH_FAILED = 0x25, NVME_SC_CONFLICTING_ATTRIBUTES = 0x80, NVME_SC_INVALID_PROTECTION_INFO = 0x81, @@ -591,6 +716,17 @@ enum nvme_media_error_status_code { NVME_SC_DEALLOCATED_OR_UNWRITTEN = 0x87, }; +/* path related status codes */ +enum nvme_path_related_status_code { + NVME_SC_INTERNAL_PATH_ERROR = 0x00, + NVME_SC_ASYMMETRIC_ACCESS_PERSISTENT_LOSS = 0x01, + NVME_SC_ASYMMETRIC_ACCESS_INACCESSIBLE = 0x02, + NVME_SC_ASYMMETRIC_ACCESS_TRANSITION = 0x03, + NVME_SC_CONTROLLER_PATHING_ERROR = 0x60, + NVME_SC_HOST_PATHING_ERROR = 0x70, + NVME_SC_COMMAND_ABOTHED_BY_HOST = 0x71, +}; + /* admin opcodes */ enum nvme_admin_opcode { NVME_OPC_DELETE_IO_SQ = 0x00, @@ -610,20 +746,27 @@ enum nvme_admin_opcode { /* 0x0e-0x0f - reserved */ NVME_OPC_FIRMWARE_ACTIVATE = 0x10, NVME_OPC_FIRMWARE_IMAGE_DOWNLOAD = 0x11, + /* 0x12-0x13 - reserved */ NVME_OPC_DEVICE_SELF_TEST = 0x14, NVME_OPC_NAMESPACE_ATTACHMENT = 0x15, + /* 0x16-0x17 - reserved */ NVME_OPC_KEEP_ALIVE = 0x18, NVME_OPC_DIRECTIVE_SEND = 0x19, NVME_OPC_DIRECTIVE_RECEIVE = 0x1a, + /* 0x1b - reserved */ NVME_OPC_VIRTUALIZATION_MANAGEMENT = 0x1c, NVME_OPC_NVME_MI_SEND = 0x1d, NVME_OPC_NVME_MI_RECEIVE = 0x1e, + /* 0x1f-0x7b - reserved */ NVME_OPC_DOORBELL_BUFFER_CONFIG = 0x7c, NVME_OPC_FORMAT_NVM = 0x80, NVME_OPC_SECURITY_SEND = 0x81, NVME_OPC_SECURITY_RECEIVE = 0x82, + /* 0x83 - reserved */ NVME_OPC_SANITIZE = 0x84, + /* 0x85 - reserved */ + NVME_OPC_GET_LBA_STATUS = 0x86, }; /* nvme nvm opcodes */ @@ -634,11 +777,11 @@ enum nvme_nvm_opcode { /* 0x03 - reserved */ NVME_OPC_WRITE_UNCORRECTABLE = 0x04, NVME_OPC_COMPARE = 0x05, - /* 0x06 - reserved */ + /* 0x06-0x07 - reserved */ NVME_OPC_WRITE_ZEROES = 0x08, - /* 0x07 - reserved */ NVME_OPC_DATASET_MANAGEMENT = 0x09, - /* 0x0a-0x0c - reserved */ + /* 0x0a-0x0b - reserved */ + NVME_OPC_VERIFY = 0x0c, NVME_OPC_RESERVATION_REGISTER = 0x0d, NVME_OPC_RESERVATION_REPORT = 0x0e, /* 0x0f-0x10 - reserved */ @@ -666,10 +809,21 @@ enum nvme_feature { NVME_FEAT_KEEP_ALIVE_TIMER = 0x0F, NVME_FEAT_HOST_CONTROLLED_THERMAL_MGMT = 0x10, NVME_FEAT_NON_OP_POWER_STATE_CONFIG = 0x11, - /* 0x12-0x77 - reserved */ + NVME_FEAT_READ_RECOVERY_LEVEL_CONFIG = 0x12, + NVME_FEAT_PREDICTABLE_LATENCY_MODE_CONFIG = 0x13, + NVME_FEAT_PREDICTABLE_LATENCY_MODE_WINDOW = 0x14, + NVME_FEAT_LBA_STATUS_INFORMATION_ATTRIBUTES = 0x15, + NVME_FEAT_HOST_BEHAVIOR_SUPPORT = 0x16, + NVME_FEAT_SANITIZE_CONFIG = 0x17, + NVME_FEAT_ENDURANCE_GROUP_EVENT_CONFIGURATION = 0x18, + /* 0x19-0x77 - reserved */ /* 0x78-0x7f - NVMe Management Interface */ NVME_FEAT_SOFTWARE_PROGRESS_MARKER = 0x80, - /* 0x81-0xBF - command set specific (reserved) */ + NVME_FEAT_HOST_IDENTIFIER = 0x81, + NVME_FEAT_RESERVATION_NOTIFICATION_MASK = 0x82, + NVME_FEAT_RESERVATION_PERSISTENCE = 0x83, + NVME_FEAT_NAMESPACE_WRITE_PROTECTION_CONFIG = 0x84, + /* 0x85-0xBF - command set specific (reserved) */ /* 0xC0-0xFF - vendor specific */ }; @@ -763,12 +917,27 @@ struct nvme_controller_data { /** Controller Attributes */ uint32_t ctratt; /* bitfield really */ - uint8_t reserved1[12]; + /** Read Recovery Levels Supported */ + uint16_t rrls; + + uint8_t reserved1[9]; + + /** Controller Type */ + uint8_t cntrltype; /** FRU Globally Unique Identifier */ uint8_t fguid[16]; - uint8_t reserved2[128]; + /** Command Retry Delay Time 1 */ + uint16_t crdt1; + + /** Command Retry Delay Time 2 */ + uint16_t crdt2; + + /** Command Retry Delay Time 3 */ + uint16_t crdt3; + + uint8_t reserved2[122]; /* bytes 256-511: admin command set attributes */ @@ -848,7 +1017,34 @@ struct nvme_controller_data { /** Sanitize Capabilities */ uint32_t sanicap; /* Really a bitfield */ - uint8_t reserved3[180]; + /** Host Memory Buffer Minimum Descriptor Entry Size */ + uint32_t hmminds; + + /** Host Memory Maximum Descriptors Entries */ + uint16_t hmmaxd; + + /** NVM Set Identifier Maximum */ + uint16_t nsetidmax; + + /** Endurance Group Identifier Maximum */ + uint16_t endgidmax; + + /** ANA Transition Time */ + uint8_t anatt; + + /** Asymmetric Namespace Access Capabilities */ + uint8_t anacap; + + /** ANA Group Identifier Maximum */ + uint32_t anagrpmax; + + /** Number of ANA Group Identifiers */ + uint32_t nanagrpid; + + /** Persistent Event Log Size */ + uint32_t pels; + + uint8_t reserved3[156]; /* bytes 512-703: nvm command set attributes */ /** submission queue entry size */ @@ -883,7 +1079,9 @@ struct nvme_controller_data { /** NVM Vendor Specific Command Configuration */ uint8_t nvscc; - uint8_t reserved5; + + /** Namespace Write Protection Capabilities */ + uint8_t nwpc; /** Atomic Compare & Write Unit */ uint16_t acwu; @@ -892,8 +1090,11 @@ struct nvme_controller_data { /** SGL Support */ uint32_t sgls; + /** Maximum Number of Allowed Namespaces */ + uint32_t mnan; + /* bytes 540-767: Reserved */ - uint8_t reserved7[228]; + uint8_t reserved7[224]; /** NVM Subsystem NVMe Qualified Name */ uint8_t subnqn[256]; @@ -978,8 +1179,38 @@ struct nvme_namespace_data { /** NVM Capacity */ uint8_t nvmcap[16]; - /* bytes 64-103: Reserved */ - uint8_t reserved5[40]; + /** Namespace Preferred Write Granularity */ + uint16_t npwg; + + /** Namespace Preferred Write Alignment */ + uint16_t npwa; + + /** Namespace Preferred Deallocate Granularity */ + uint16_t npdg; + + /** Namespace Preferred Deallocate Alignment */ + uint16_t npda; + + /** Namespace Optimal Write Size */ + uint16_t nows; + + /* bytes 74-91: Reserved */ + uint8_t reserved5[18]; + + /** ANA Group Identifier */ + uint32_t anagrpid; + + /* bytes 96-98: Reserved */ + uint8_t reserved6[3]; + + /** Namespace Attributes */ + uint8_t nsattr; + + /** NVM Set Identifier */ + uint16_t nvmsetid; + + /** Endurance Group Identifier */ + uint16_t endgid; /** Namespace Globally Unique Identifier */ uint8_t nguid[16]; @@ -990,7 +1221,7 @@ struct nvme_namespace_data { /** lba format support */ uint32_t lbaf[16]; - uint8_t reserved6[192]; + uint8_t reserved7[192]; uint8_t vendor_specific[3712]; } __packed __aligned(4); @@ -1005,9 +1236,21 @@ enum nvme_log_page { NVME_LOG_FIRMWARE_SLOT = 0x03, NVME_LOG_CHANGED_NAMESPACE = 0x04, NVME_LOG_COMMAND_EFFECT = 0x05, + NVME_LOG_DEVICE_SELF_TEST = 0x06, + NVME_LOG_TELEMETRY_HOST_INITIATED = 0x07, + NVME_LOG_TELEMETRY_CONTROLLER_INITIATED = 0x08, + NVME_LOG_ENDURANCE_GROUP_INFORMATION = 0x09, + NVME_LOG_PREDICTABLE_LATENCY_PER_NVM_SET = 0x0a, + NVME_LOG_PREDICTABLE_LATENCY_EVENT_AGGREGATE = 0x0b, + NVME_LOG_ASYMMETRIC_NAMESPAVE_ACCESS = 0x0c, + NVME_LOG_PERSISTENT_EVENT_LOG = 0x0d, + NVME_LOG_LBA_STATUS_INFORMATION = 0x0e, + NVME_LOG_ENDURANCE_GROUP_EVENT_AGGREGATE = 0x0f, /* 0x06-0x7F - reserved */ /* 0x80-0xBF - I/O command set specific */ NVME_LOG_RES_NOTIFICATION = 0x80, + NVME_LOG_SANITIZE_STATUS = 0x81, + /* 0x82-0xBF - reserved */ /* 0xC0-0xFF - vendor specific */ /* @@ -1036,7 +1279,11 @@ struct nvme_error_information_entry { uint64_t lba; uint32_t nsid; uint8_t vendor_specific; - uint8_t reserved[35]; + uint8_t trtype; + uint16_t reserved30; + uint64_t csi; + uint16_t ttsi; + uint8_t reserved[22]; } __packed __aligned(4); _Static_assert(sizeof(struct nvme_error_information_entry) == 64, "bad size for nvme_error_information_entry"); @@ -1072,8 +1319,16 @@ struct nvme_health_information_page { uint32_t warning_temp_time; uint32_t error_temp_time; uint16_t temp_sensor[8]; - - uint8_t reserved2[296]; + /* Thermal Management Temperature 1 Transition Count */ + uint32_t tmt1tc; + /* Thermal Management Temperature 2 Transition Count */ + uint32_t tmt2tc; + /* Total Time For Thermal Management Temperature 1 */ + uint32_t ttftmt1; + /* Total Time For Thermal Management Temperature 2 */ + uint32_t ttftmt2; + + uint8_t reserved2[280]; } __packed __aligned(4); _Static_assert(sizeof(struct nvme_health_information_page) == 512, "bad size for nvme_health_information_page"); @@ -1094,6 +1349,43 @@ struct nvme_ns_list { _Static_assert(sizeof(struct nvme_ns_list) == 4096, "bad size for nvme_ns_list"); +struct nvme_command_effects_page { + uint32_t acs[256]; + uint32_t iocs[256]; + uint8_t reserved[2048]; +} __packed __aligned(4); + +_Static_assert(sizeof(struct nvme_command_effects_page) == 4096, + "bad size for nvme_command_effects_page"); + +struct nvme_res_notification_page { + uint64_t log_page_count; + uint8_t log_page_type; + uint8_t available_log_pages; + uint8_t reserved2; + uint32_t nsid; + uint8_t reserved[48]; +} __packed __aligned(4); + +_Static_assert(sizeof(struct nvme_res_notification_page) == 64, + "bad size for nvme_res_notification_page"); + +struct nvme_sanitize_status_page { + uint16_t sprog; + uint16_t sstat; + uint32_t scdw10; + uint32_t etfo; + uint32_t etfbe; + uint32_t etfce; + uint32_t etfownd; + uint32_t etfbewnd; + uint32_t etfcewnd; + uint8_t reserved[480]; +} __packed __aligned(4); + +_Static_assert(sizeof(struct nvme_sanitize_status_page) == 512, + "bad size for nvme_sanitize_status_page"); + struct intel_log_temp_stats { uint64_t current; @@ -1109,6 +1401,56 @@ struct intel_log_temp_stats _Static_assert(sizeof(struct intel_log_temp_stats) == 13 * 8, "bad size for intel_log_temp_stats"); +struct nvme_resv_reg_ctrlr +{ + uint16_t ctrlr_id; /* Controller ID */ + uint8_t rcsts; /* Reservation Status */ + uint8_t reserved3[5]; + uint64_t hostid; /* Host Identifier */ + uint64_t rkey; /* Reservation Key */ +} __packed __aligned(4); + +_Static_assert(sizeof(struct nvme_resv_reg_ctrlr) == 24, "bad size for nvme_resv_reg_ctrlr"); + +struct nvme_resv_reg_ctrlr_ext +{ + uint16_t ctrlr_id; /* Controller ID */ + uint8_t rcsts; /* Reservation Status */ + uint8_t reserved3[5]; + uint64_t rkey; /* Reservation Key */ + uint64_t hostid[2]; /* Host Identifier */ + uint8_t reserved32[32]; +} __packed __aligned(4); + +_Static_assert(sizeof(struct nvme_resv_reg_ctrlr_ext) == 64, "bad size for nvme_resv_reg_ctrlr_ext"); + +struct nvme_resv_status +{ + uint32_t gen; /* Generation */ + uint8_t rtype; /* Reservation Type */ + uint8_t regctl[2]; /* Number of Registered Controllers */ + uint8_t reserved7[2]; + uint8_t ptpls; /* Persist Through Power Loss State */ + uint8_t reserved10[14]; + struct nvme_resv_reg_ctrlr ctrlr[0]; +} __packed __aligned(4); + +_Static_assert(sizeof(struct nvme_resv_status) == 24, "bad size for nvme_resv_status"); + +struct nvme_resv_status_ext +{ + uint32_t gen; /* Generation */ + uint8_t rtype; /* Reservation Type */ + uint8_t regctl[2]; /* Number of Registered Controllers */ + uint8_t reserved7[2]; + uint8_t ptpls; /* Persist Through Power Loss State */ + uint8_t reserved10[14]; + uint8_t reserved24[40]; + struct nvme_resv_reg_ctrlr_ext ctrlr[0]; +} __packed __aligned(4); + +_Static_assert(sizeof(struct nvme_resv_status_ext) == 64, "bad size for nvme_resv_status_ext"); + #define NVME_TEST_MAX_THREADS 128 struct nvme_io_test { @@ -1184,6 +1526,11 @@ struct nvme_pt_command { struct mtx * driver_lock; }; +struct nvme_get_nsid { + char cdev[SPECNAMELEN + 1]; + uint32_t nsid; +}; + #define nvme_completion_is_error(cpl) \ (NVME_STATUS_GET_SC((cpl)->status) != 0 || NVME_STATUS_GET_SCT((cpl)->status) != 0) @@ -1192,6 +1539,7 @@ void nvme_strvis(uint8_t *dst, const uint8_t *src, int dstlen, int srclen); #ifdef _KERNEL struct bio; +struct thread; struct nvme_namespace; struct nvme_controller; @@ -1281,6 +1629,8 @@ uint32_t nvme_ns_get_stripesize(struct nvme_namespace *ns); int nvme_ns_bio_process(struct nvme_namespace *ns, struct bio *bp, nvme_cb_fn_t cb_fn); +int nvme_ns_ioctl_process(struct nvme_namespace *ns, u_long cmd, + caddr_t arg, int flag, struct thread *td); /* * Command building helper functions -- shared with CAM @@ -1372,6 +1722,10 @@ void nvme_controller_data_swapbytes(struct nvme_controller_data *s) s->rtd3e = le32toh(s->rtd3e); s->oaes = le32toh(s->oaes); s->ctratt = le32toh(s->ctratt); + s->rrls = le16toh(s->rrls); + s->crdt1 = le16toh(s->crdt1); + s->crdt2 = le16toh(s->crdt2); + s->crdt3 = le16toh(s->crdt3); s->oacs = le16toh(s->oacs); s->wctemp = le16toh(s->wctemp); s->cctemp = le16toh(s->cctemp); @@ -1385,6 +1739,13 @@ void nvme_controller_data_swapbytes(struct nvme_controller_data *s) s->mntmt = le16toh(s->mntmt); s->mxtmt = le16toh(s->mxtmt); s->sanicap = le32toh(s->sanicap); + s->hmminds = le32toh(s->hmminds); + s->hmmaxd = le16toh(s->hmmaxd); + s->nsetidmax = le16toh(s->nsetidmax); + s->endgidmax = le16toh(s->endgidmax); + s->anagrpmax = le32toh(s->anagrpmax); + s->nanagrpid = le32toh(s->nanagrpid); + s->pels = le32toh(s->pels); s->maxcmd = le16toh(s->maxcmd); s->nn = le32toh(s->nn); s->oncs = le16toh(s->oncs); @@ -1393,6 +1754,7 @@ void nvme_controller_data_swapbytes(struct nvme_controller_data *s) s->awupf = le16toh(s->awupf); s->acwu = le16toh(s->acwu); s->sgls = le32toh(s->sgls); + s->mnan = le32toh(s->mnan); for (i = 0; i < 32; i++) nvme_power_state_swapbytes(&s->power_state[i]); } @@ -1412,6 +1774,14 @@ void nvme_namespace_data_swapbytes(struct nvme_namespace_data *s) s->nabo = le16toh(s->nabo); s->nabspf = le16toh(s->nabspf); s->noiob = le16toh(s->noiob); + s->npwg = le16toh(s->npwg); + s->npwa = le16toh(s->npwa); + s->npdg = le16toh(s->npdg); + s->npda = le16toh(s->npda); + s->nows = le16toh(s->nows); + s->anagrpid = le32toh(s->anagrpid); + s->nvmsetid = le16toh(s->nvmsetid); + s->endgid = le16toh(s->endgid); for (i = 0; i < 16; i++) s->lbaf[i] = le32toh(s->lbaf[i]); } @@ -1427,6 +1797,8 @@ void nvme_error_information_entry_swapbytes(struct nvme_error_information_entry s->error_location = le16toh(s->error_location); s->lba = le64toh(s->lba); s->nsid = le32toh(s->nsid); + s->csi = le64toh(s->csi); + s->ttsi = le16toh(s->ttsi); } static inline @@ -1467,6 +1839,10 @@ void nvme_health_information_page_swapbytes(struct nvme_health_information_page s->error_temp_time = le32toh(s->error_temp_time); for (i = 0; i < 8; i++) s->temp_sensor[i] = le16toh(s->temp_sensor[i]); + s->tmt1tc = le32toh(s->tmt1tc); + s->tmt2tc = le32toh(s->tmt2tc); + s->ttftmt1 = le32toh(s->ttftmt1); + s->ttftmt2 = le32toh(s->ttftmt2); } @@ -1489,6 +1865,38 @@ void nvme_ns_list_swapbytes(struct nvme_ns_list *s) } static inline +void nvme_command_effects_page_swapbytes(struct nvme_command_effects_page *s) +{ + int i; + + for (i = 0; i < 256; i++) + s->acs[i] = le32toh(s->acs[i]); + for (i = 0; i < 256; i++) + s->iocs[i] = le32toh(s->iocs[i]); +} + +static inline +void nvme_res_notification_page_swapbytes(struct nvme_res_notification_page *s) +{ + s->log_page_count = le64toh(s->log_page_count); + s->nsid = le32toh(s->nsid); +} + +static inline +void nvme_sanitize_status_page_swapbytes(struct nvme_sanitize_status_page *s) +{ + s->sprog = le16toh(s->sprog); + s->sstat = le16toh(s->sstat); + s->scdw10 = le32toh(s->scdw10); + s->etfo = le32toh(s->etfo); + s->etfbe = le32toh(s->etfbe); + s->etfce = le32toh(s->etfce); + s->etfownd = le32toh(s->etfownd); + s->etfbewnd = le32toh(s->etfbewnd); + s->etfcewnd = le32toh(s->etfcewnd); +} + +static inline void intel_log_temp_stats_swapbytes(struct intel_log_temp_stats *s) { @@ -1503,4 +1911,34 @@ void intel_log_temp_stats_swapbytes(struct intel_log_temp_stats *s) s->est_offset = le64toh(s->est_offset); } +static inline +void nvme_resv_status_swapbytes(struct nvme_resv_status *s, size_t size) +{ + u_int i, n; + + s->gen = le32toh(s->gen); + n = (s->regctl[1] << 8) | s->regctl[0]; + n = MIN(n, (size - sizeof(s)) / sizeof(s->ctrlr[0])); + for (i = 0; i < n; i++) { + s->ctrlr[i].ctrlr_id = le16toh(s->ctrlr[i].ctrlr_id); + s->ctrlr[i].hostid = le64toh(s->ctrlr[i].hostid); + s->ctrlr[i].rkey = le64toh(s->ctrlr[i].rkey); + } +} + +static inline +void nvme_resv_status_ext_swapbytes(struct nvme_resv_status_ext *s, size_t size) +{ + u_int i, n; + + s->gen = le32toh(s->gen); + n = (s->regctl[1] << 8) | s->regctl[0]; + n = MIN(n, (size - sizeof(s)) / sizeof(s->ctrlr[0])); + for (i = 0; i < n; i++) { + s->ctrlr[i].ctrlr_id = le16toh(s->ctrlr[i].ctrlr_id); + s->ctrlr[i].rkey = le64toh(s->ctrlr[i].rkey); + nvme_le128toh((void *)s->ctrlr[i].hostid); + } +} + #endif /* __NVME_H__ */ diff --git a/freebsd/sys/dev/ofw/ofw_bus_subr.h b/freebsd/sys/dev/ofw/ofw_bus_subr.h index 468fdc39..218ba710 100644 --- a/freebsd/sys/dev/ofw/ofw_bus_subr.h +++ b/freebsd/sys/dev/ofw/ofw_bus_subr.h @@ -65,9 +65,11 @@ struct intr_map_data_fdt { }; #endif -#define SIMPLEBUS_PNP_DESCR "Z:compat;P:#;" -#define SIMPLEBUS_PNP_INFO(t) \ - MODULE_PNP_INFO(SIMPLEBUS_PNP_DESCR, simplebus, t, t, sizeof(t) / sizeof(t[0])); +#define FDTCOMPAT_PNP_DESCR "Z:compat;P:#;" +#define FDTCOMPAT_PNP_INFO(t, busname) \ + MODULE_PNP_INFO(FDTCOMPAT_PNP_DESCR, busname, t, t, sizeof(t) / sizeof(t[0])); + +#define SIMPLEBUS_PNP_INFO(t) FDTCOMPAT_PNP_INFO(t, simplebus) /* Generic implementation of ofw_bus_if.m methods and helper routines */ int ofw_bus_gen_setup_devinfo(struct ofw_bus_devinfo *, phandle_t); diff --git a/freebsd/sys/dev/ofw/ofw_subr.c b/freebsd/sys/dev/ofw/ofw_subr.c index 4a20727c..7483a2d2 100644 --- a/freebsd/sys/dev/ofw/ofw_subr.c +++ b/freebsd/sys/dev/ofw/ofw_subr.c @@ -81,7 +81,8 @@ int ofw_reg_to_paddr(phandle_t dev, int regno, bus_addr_t *paddr, bus_size_t *psize, pcell_t *ppci_hi) { - pcell_t cell[32], pci_hi; + static pcell_t cell[256]; + pcell_t pci_hi; uint64_t addr, raddr, baddr; uint64_t size, rsize; uint32_t c, nbridge, naddr, nsize; diff --git a/freebsd/sys/dev/pci/pci.c b/freebsd/sys/dev/pci/pci.c index f2a46d03..5402cb66 100644 --- a/freebsd/sys/dev/pci/pci.c +++ b/freebsd/sys/dev/pci/pci.c @@ -33,20 +33,22 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); +#include <rtems/bsd/local/opt_acpi.h> #include <rtems/bsd/local/opt_bus.h> #include <sys/param.h> -#include <sys/systm.h> -#include <sys/malloc.h> -#include <sys/module.h> -#include <sys/limits.h> -#include <sys/linker.h> -#include <sys/fcntl.h> #include <sys/conf.h> +#include <sys/endian.h> +#include <sys/eventhandler.h> +#include <sys/fcntl.h> #include <sys/kernel.h> +#include <sys/limits.h> +#include <sys/linker.h> +#include <sys/malloc.h> +#include <sys/module.h> #include <sys/queue.h> #include <sys/sysctl.h> -#include <sys/endian.h> +#include <sys/systm.h> #include <vm/vm.h> #include <vm/pmap.h> @@ -137,6 +139,10 @@ static int pci_remap_intr_method(device_t bus, device_t dev, static void pci_hint_device_unit(device_t acdev, device_t child, const char *name, int *unitp); #endif /* __rtems__ */ +static int pci_reset_post(device_t dev, device_t child); +static int pci_reset_prepare(device_t dev, device_t child); +static int pci_reset_child(device_t dev, device_t child, + int flags); static int pci_get_id_method(device_t dev, device_t child, enum pci_id_type type, uintptr_t *rid); @@ -161,6 +167,9 @@ static device_method_t pci_methods[] = { DEVMETHOD(bus_driver_added, pci_driver_added), DEVMETHOD(bus_setup_intr, pci_setup_intr), DEVMETHOD(bus_teardown_intr, pci_teardown_intr), + DEVMETHOD(bus_reset_prepare, pci_reset_prepare), + DEVMETHOD(bus_reset_post, pci_reset_post), + DEVMETHOD(bus_reset_child, pci_reset_child), DEVMETHOD(bus_get_dma_tag, pci_get_dma_tag), DEVMETHOD(bus_get_resource_list,pci_get_resource_list), @@ -355,7 +364,7 @@ SYSCTL_INT(_hw_pci, OID_AUTO, enable_io_modes, CTLFLAG_RWTUN, " enable these bits correctly. We'd like to do this all the time, but" " there are some peripherals that this causes problems with."); -static int pci_do_realloc_bars = 0; +static int pci_do_realloc_bars = 1; SYSCTL_INT(_hw_pci, OID_AUTO, realloc_bars, CTLFLAG_RWTUN, &pci_do_realloc_bars, 0, "Attempt to allocate a new range for any BARs whose original " @@ -1678,10 +1687,13 @@ pci_mask_msix(device_t dev, u_int index) KASSERT(msix->msix_msgnum > index, ("bogus index")); offset = msix->msix_table_offset + index * 16 + 12; val = bus_read_4(msix->msix_table_res, offset); - if (!(val & PCIM_MSIX_VCTRL_MASK)) { - val |= PCIM_MSIX_VCTRL_MASK; - bus_write_4(msix->msix_table_res, offset, val); - } + val |= PCIM_MSIX_VCTRL_MASK; + + /* + * Some devices (e.g. Samsung PM961) do not support reads of this + * register, so always write the new value. + */ + bus_write_4(msix->msix_table_res, offset, val); } void @@ -1694,10 +1706,13 @@ pci_unmask_msix(device_t dev, u_int index) KASSERT(msix->msix_table_len > index, ("bogus index")); offset = msix->msix_table_offset + index * 16 + 12; val = bus_read_4(msix->msix_table_res, offset); - if (val & PCIM_MSIX_VCTRL_MASK) { - val &= ~PCIM_MSIX_VCTRL_MASK; - bus_write_4(msix->msix_table_res, offset, val); - } + val &= ~PCIM_MSIX_VCTRL_MASK; + + /* + * Some devices (e.g. Samsung PM961) do not support reads of this + * register, so always write the new value. + */ + bus_write_4(msix->msix_table_res, offset, val); } int @@ -4359,9 +4374,6 @@ pci_attach_common(device_t dev) { struct pci_softc *sc; int busno, domain; -#ifdef PCI_DMA_BOUNDARY - int error, tag_valid; -#endif #ifdef PCI_RES_BUS int rid; #endif @@ -4381,23 +4393,7 @@ pci_attach_common(device_t dev) if (bootverbose) device_printf(dev, "domain=%d, physical bus=%d\n", domain, busno); -#ifdef PCI_DMA_BOUNDARY - tag_valid = 0; - if (device_get_devclass(device_get_parent(device_get_parent(dev))) != - devclass_find("pci")) { - error = bus_dma_tag_create(bus_get_dma_tag(dev), 1, - PCI_DMA_BOUNDARY, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, - NULL, NULL, BUS_SPACE_MAXSIZE, BUS_SPACE_UNRESTRICTED, - BUS_SPACE_MAXSIZE, 0, NULL, NULL, &sc->sc_dma_tag); - if (error) - device_printf(dev, "Failed to create DMA tag: %d\n", - error); - else - tag_valid = 1; - } - if (!tag_valid) -#endif - sc->sc_dma_tag = bus_get_dma_tag(dev); + sc->sc_dma_tag = bus_get_dma_tag(dev); return (0); } @@ -5730,6 +5726,26 @@ pci_get_resource_list (device_t dev, device_t child) return (&dinfo->resources); } +#ifdef ACPI_DMAR +bus_dma_tag_t dmar_get_dma_tag(device_t dev, device_t child); +bus_dma_tag_t +pci_get_dma_tag(device_t bus, device_t dev) +{ + bus_dma_tag_t tag; + struct pci_softc *sc; + + if (device_get_parent(dev) == bus) { + /* try dmar and return if it works */ + tag = dmar_get_dma_tag(bus, dev); + } else + tag = NULL; + if (tag == NULL) { + sc = device_get_softc(bus); + tag = sc->sc_dma_tag; + } + return (tag); +} +#else bus_dma_tag_t pci_get_dma_tag(device_t bus, device_t dev) { @@ -5737,6 +5753,7 @@ pci_get_dma_tag(device_t bus, device_t dev) return (sc->sc_dma_tag); } +#endif uint32_t pci_read_config_method(device_t dev, device_t child, int reg, int width) @@ -6402,6 +6419,94 @@ pcie_flr(device_t dev, u_int max_delay, bool force) return (true); } +/* + * Attempt a power-management reset by cycling the device in/out of D3 + * state. PCI spec says we can only go into D3 state from D0 state. + * Transition from D[12] into D0 before going to D3 state. + */ +int +pci_power_reset(device_t dev) +{ + int ps; + + ps = pci_get_powerstate(dev); + if (ps != PCI_POWERSTATE_D0 && ps != PCI_POWERSTATE_D3) + pci_set_powerstate(dev, PCI_POWERSTATE_D0); + pci_set_powerstate(dev, PCI_POWERSTATE_D3); + pci_set_powerstate(dev, ps); + return (0); +} + +/* + * Try link drop and retrain of the downstream port of upstream + * switch, for PCIe. According to the PCIe 3.0 spec 6.6.1, this must + * cause Conventional Hot reset of the device in the slot. + * Alternative, for PCIe, could be the secondary bus reset initiatied + * on the upstream switch PCIR_BRIDGECTL_1, bit 6. + */ +int +pcie_link_reset(device_t port, int pcie_location) +{ + uint16_t v; + + v = pci_read_config(port, pcie_location + PCIER_LINK_CTL, 2); + v |= PCIEM_LINK_CTL_LINK_DIS; + pci_write_config(port, pcie_location + PCIER_LINK_CTL, v, 2); + pause_sbt("pcier1", mstosbt(20), 0, 0); + v &= ~PCIEM_LINK_CTL_LINK_DIS; + v |= PCIEM_LINK_CTL_RETRAIN_LINK; + pci_write_config(port, pcie_location + PCIER_LINK_CTL, v, 2); + pause_sbt("pcier2", mstosbt(100), 0, 0); /* 100 ms */ + v = pci_read_config(port, pcie_location + PCIER_LINK_STA, 2); + return ((v & PCIEM_LINK_STA_TRAINING) != 0 ? ETIMEDOUT : 0); +} + +static int +pci_reset_post(device_t dev, device_t child) +{ + + if (dev == device_get_parent(child)) + pci_restore_state(child); + return (0); +} + +static int +pci_reset_prepare(device_t dev, device_t child) +{ + + if (dev == device_get_parent(child)) + pci_save_state(child); + return (0); +} + +static int +pci_reset_child(device_t dev, device_t child, int flags) +{ + int error; + + if (dev == NULL || device_get_parent(child) != dev) + return (0); + if ((flags & DEVF_RESET_DETACH) != 0) { + error = device_get_state(child) == DS_ATTACHED ? + device_detach(child) : 0; + } else { + error = BUS_SUSPEND_CHILD(dev, child); + } + if (error == 0) { + if (!pcie_flr(child, 1000, false)) { + error = BUS_RESET_PREPARE(dev, child); + if (error == 0) + pci_power_reset(child); + BUS_RESET_POST(dev, child); + } + if ((flags & DEVF_RESET_DETACH) != 0) + device_probe_and_attach(child); + else + BUS_RESUME_CHILD(dev, child); + } + return (error); +} + const struct pci_device_table * pci_match_device(device_t child, const struct pci_device_table *id, size_t nelt) { diff --git a/freebsd/sys/dev/pci/pci_pci.c b/freebsd/sys/dev/pci/pci_pci.c index 607a0614..cdcba150 100644 --- a/freebsd/sys/dev/pci/pci_pci.c +++ b/freebsd/sys/dev/pci/pci_pci.c @@ -44,8 +44,11 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/bus.h> #include <sys/kernel.h> +#include <sys/lock.h> #include <sys/malloc.h> #include <sys/module.h> +#include <sys/mutex.h> +#include <sys/pciio.h> #include <sys/rman.h> #include <sys/sysctl.h> #include <sys/systm.h> @@ -82,6 +85,7 @@ static void pcib_pcie_dll_timeout(void *arg); #endif static int pcib_request_feature_default(device_t pcib, device_t dev, enum pci_feature feature); +static int pcib_reset_child(device_t dev, device_t child, int flags); static device_method_t pcib_methods[] = { /* Device interface */ @@ -108,6 +112,7 @@ static device_method_t pcib_methods[] = { DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + DEVMETHOD(bus_reset_child, pcib_reset_child), /* pcib interface */ DEVMETHOD(pcib_maxslots, pcib_ari_maxslots), @@ -1167,9 +1172,11 @@ pcib_pcie_intr_hotplug(void *arg) { struct pcib_softc *sc; device_t dev; + uint16_t old_slot_sta; sc = arg; dev = sc->dev; + old_slot_sta = sc->pcie_slot_sta; sc->pcie_slot_sta = pcie_read_config(dev, PCIER_SLOT_STA, 2); /* Clear the events just reported. */ @@ -1185,7 +1192,8 @@ pcib_pcie_intr_hotplug(void *arg) "Attention Button Pressed: Detach Cancelled\n"); sc->flags &= ~PCIB_DETACH_PENDING; callout_stop(&sc->pcie_ab_timer); - } else { + } else if (old_slot_sta & PCIEM_SLOT_STA_PDS) { + /* Only initiate detach sequence if device present. */ device_printf(dev, "Attention Button Pressed: Detaching in 5 seconds\n"); sc->flags |= PCIB_DETACH_PENDING; @@ -1266,11 +1274,8 @@ pcib_pcie_cc_timeout(void *arg) mtx_assert(&Giant, MA_OWNED); sta = pcie_read_config(dev, PCIER_SLOT_STA, 2); if (!(sta & PCIEM_SLOT_STA_CC)) { - device_printf(dev, - "HotPlug Command Timed Out - forcing detach\n"); - sc->flags &= ~(PCIB_HOTPLUG_CMD_PENDING | PCIB_DETACH_PENDING); - sc->flags |= PCIB_DETACHING; - pcib_pcie_hotplug_update(sc, 0, 0, true); + device_printf(dev, "HotPlug Command Timed Out\n"); + sc->flags &= ~PCIB_HOTPLUG_CMD_PENDING; } else { device_printf(dev, "Missed HotPlug interrupt waiting for Command Completion\n"); @@ -2911,3 +2916,31 @@ pcib_request_feature_default(device_t pcib, device_t dev, bus = device_get_parent(pcib); return (PCIB_REQUEST_FEATURE(device_get_parent(bus), dev, feature)); } + +static int +pcib_reset_child(device_t dev, device_t child, int flags) +{ + struct pci_devinfo *pdinfo; + int error; + + error = 0; + if (dev == NULL || device_get_parent(child) != dev) + goto out; + error = ENXIO; + if (device_get_devclass(child) != devclass_find("pci")) + goto out; + pdinfo = device_get_ivars(dev); + if (pdinfo->cfg.pcie.pcie_location != 0 && + (pdinfo->cfg.pcie.pcie_type == PCIEM_TYPE_DOWNSTREAM_PORT || + pdinfo->cfg.pcie.pcie_type == PCIEM_TYPE_ROOT_PORT)) { + error = bus_helper_reset_prepare(child, flags); + if (error == 0) { + error = pcie_link_reset(dev, + pdinfo->cfg.pcie.pcie_location); + /* XXXKIB call _post even if error != 0 ? */ + bus_helper_reset_post(child, flags); + } + } +out: + return (error); +} diff --git a/freebsd/sys/dev/pci/pci_user.c b/freebsd/sys/dev/pci/pci_user.c index 3e2c3c7e..bdf8a935 100644 --- a/freebsd/sys/dev/pci/pci_user.c +++ b/freebsd/sys/dev/pci/pci_user.c @@ -858,6 +858,7 @@ pci_bar_mmap(device_t pcidev, struct pci_bar_mmap *pbm) struct thread *td; struct sglist *sg; struct pci_map *pm; + vm_paddr_t membase; vm_paddr_t pbase; vm_size_t plen; vm_offset_t addr; @@ -880,8 +881,9 @@ pci_bar_mmap(device_t pcidev, struct pci_bar_mmap *pbm) return (EBUSY); /* XXXKIB enable if _ACTIVATE */ if (!PCI_BAR_MEM(pm->pm_value)) return (EIO); - pbase = trunc_page(pm->pm_value); - plen = round_page(pm->pm_value + ((pci_addr_t)1 << pm->pm_size)) - + membase = pm->pm_value & PCIM_BAR_MEM_BASE; + pbase = trunc_page(membase); + plen = round_page(membase + ((pci_addr_t)1 << pm->pm_size)) - pbase; prot = VM_PROT_READ | (((pbm->pbm_flags & PCIIO_BAR_MMAP_RW) != 0) ? VM_PROT_WRITE : 0); @@ -913,7 +915,7 @@ pci_bar_mmap(device_t pcidev, struct pci_bar_mmap *pbm) } pbm->pbm_map_base = (void *)addr; pbm->pbm_map_length = plen; - pbm->pbm_bar_off = pm->pm_value - pbase; + pbm->pbm_bar_off = membase - pbase; pbm->pbm_bar_length = (pci_addr_t)1 << pm->pm_size; out: diff --git a/freebsd/sys/dev/pci/pcivar.h b/freebsd/sys/dev/pci/pcivar.h index 2ea7b877..d27cd1d2 100644 --- a/freebsd/sys/dev/pci/pcivar.h +++ b/freebsd/sys/dev/pci/pcivar.h @@ -33,7 +33,7 @@ #define _PCIVAR_H_ #include <sys/queue.h> -#include <sys/eventhandler.h> +#include <sys/_eventhandler.h> /* some PCI bus constants */ #define PCI_MAXMAPS_0 6 /* max. no. of memory/port maps */ @@ -259,6 +259,13 @@ typedef struct { extern uint32_t pci_numdevs; +/* + * The bitfield has to be stable and match the fields below (so that + * match_flag_vendor must be bit 0) so we have to do the endian dance. We can't + * use enums or #define constants because then the macros for subsetting matches + * wouldn't work. These tables are parsed by devmatch and others to connect + * modules with devices on the PCI bus. + */ struct pci_device_table { #if BYTE_ORDER == LITTLE_ENDIAN uint16_t @@ -674,6 +681,7 @@ int pci_get_max_read_req(device_t dev); void pci_restore_state(device_t dev); void pci_save_state(device_t dev); int pci_set_max_read_req(device_t dev, int size); +int pci_power_reset(device_t dev); uint32_t pcie_read_config(device_t dev, int reg, int width); void pcie_write_config(device_t dev, int reg, uint32_t value, int width); uint32_t pcie_adjust_config(device_t dev, int reg, uint32_t mask, @@ -681,17 +689,10 @@ uint32_t pcie_adjust_config(device_t dev, int reg, uint32_t mask, bool pcie_flr(device_t dev, u_int max_delay, bool force); int pcie_get_max_completion_timeout(device_t dev); bool pcie_wait_for_pending_transactions(device_t dev, u_int max_delay); +int pcie_link_reset(device_t port, int pcie_location); void pci_print_faulted_dev(void); -#ifdef BUS_SPACE_MAXADDR -#if (BUS_SPACE_MAXADDR > 0xFFFFFFFF) -#define PCI_DMA_BOUNDARY 0x100000000 -#else -#define PCI_DMA_BOUNDARY 0 -#endif -#endif - #endif /* _SYS_BUS_H_ */ /* diff --git a/freebsd/sys/dev/rtwn/if_rtwn.c b/freebsd/sys/dev/rtwn/if_rtwn.c index 79868dc0..0ca83e8a 100644 --- a/freebsd/sys/dev/rtwn/if_rtwn.c +++ b/freebsd/sys/dev/rtwn/if_rtwn.c @@ -155,9 +155,6 @@ static void rtwn_stop(struct rtwn_softc *); MALLOC_DEFINE(M_RTWN_PRIV, "rtwn_priv", "rtwn driver private state"); -static const uint8_t rtwn_chan_2ghz[] = - { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 }; - static const uint16_t wme2reg[] = { R92C_EDCA_BE_PARAM, R92C_EDCA_BK_PARAM, R92C_EDCA_VI_PARAM, R92C_EDCA_VO_PARAM }; @@ -1536,9 +1533,8 @@ rtwn_getradiocaps(struct ieee80211com *ic, setbit(bands, IEEE80211_MODE_11B); setbit(bands, IEEE80211_MODE_11G); setbit(bands, IEEE80211_MODE_11NG); - ieee80211_add_channel_list_2ghz(chans, maxchans, nchans, - rtwn_chan_2ghz, nitems(rtwn_chan_2ghz), bands, - !!(ic->ic_htcaps & IEEE80211_HTCAP_CHWIDTH40)); + ieee80211_add_channels_default_2ghz(chans, maxchans, nchans, + bands, !!(ic->ic_htcaps & IEEE80211_HTCAP_CHWIDTH40)); /* XXX workaround add_channel_list() limitations */ setbit(bands, IEEE80211_MODE_11A); @@ -1566,10 +1562,6 @@ rtwn_set_channel(struct ieee80211com *ic) RTWN_LOCK(sc); rtwn_set_chan(sc, c); - sc->sc_rxtap.wr_chan_freq = htole16(c->ic_freq); - sc->sc_rxtap.wr_chan_flags = htole16(c->ic_flags); - sc->sc_txtap.wt_chan_freq = htole16(c->ic_freq); - sc->sc_txtap.wt_chan_flags = htole16(c->ic_flags); RTWN_UNLOCK(sc); } diff --git a/freebsd/sys/dev/rtwn/if_rtwnvar.h b/freebsd/sys/dev/rtwn/if_rtwnvar.h index 3ebcba52..a6e7ea9f 100644 --- a/freebsd/sys/dev/rtwn/if_rtwnvar.h +++ b/freebsd/sys/dev/rtwn/if_rtwnvar.h @@ -62,9 +62,10 @@ struct rtwn_rx_radiotap_header { struct rtwn_tx_radiotap_header { struct ieee80211_radiotap_header wt_ihdr; uint8_t wt_flags; + uint8_t wt_pad; uint16_t wt_chan_freq; uint16_t wt_chan_flags; -} __packed __aligned(8); +} __packed; #define RTWN_TX_RADIOTAP_PRESENT \ (1 << IEEE80211_RADIOTAP_FLAGS | \ diff --git a/freebsd/sys/dev/rtwn/pci/rtwn_pci_attach.h b/freebsd/sys/dev/rtwn/pci/rtwn_pci_attach.h index 6df5812e..796d8c4d 100644 --- a/freebsd/sys/dev/rtwn/pci/rtwn_pci_attach.h +++ b/freebsd/sys/dev/rtwn/pci/rtwn_pci_attach.h @@ -17,9 +17,11 @@ */ void r92ce_attach(struct rtwn_pci_softc *); +void r88ee_attach(struct rtwn_pci_softc *); enum { RTWN_CHIP_RTL8192CE, + RTWN_CHIP_RTL8188EE, RTWN_CHIP_MAX_PCI }; @@ -32,13 +34,16 @@ struct rtwn_pci_ident { static const struct rtwn_pci_ident rtwn_pci_ident_table[] = { { 0x10ec, 0x8176, "Realtek RTL8188CE", RTWN_CHIP_RTL8192CE }, + { 0x10ec, 0x8179, "Realtek RTL8188EE", RTWN_CHIP_RTL8188EE }, + { 0x10ec, 0x8178, "Realtek RTL8192CE", RTWN_CHIP_RTL8192CE }, { 0, 0, NULL, RTWN_CHIP_MAX_PCI } }; typedef void (*chip_pci_attach)(struct rtwn_pci_softc *); static const chip_pci_attach rtwn_chip_pci_attach[RTWN_CHIP_MAX_PCI] = { - [RTWN_CHIP_RTL8192CE] = r92ce_attach + [RTWN_CHIP_RTL8192CE] = r92ce_attach, + [RTWN_CHIP_RTL8188EE] = r88ee_attach }; static __inline void diff --git a/freebsd/sys/dev/rtwn/pci/rtwn_pci_reg.c b/freebsd/sys/dev/rtwn/pci/rtwn_pci_reg.c index 8ce54f0d..5b998b5a 100644 --- a/freebsd/sys/dev/rtwn/pci/rtwn_pci_reg.c +++ b/freebsd/sys/dev/rtwn/pci/rtwn_pci_reg.c @@ -120,6 +120,6 @@ rtwn_pci_delay(struct rtwn_softc *sc, int usec) DELAY(usec); else { (void) mtx_sleep(sc, &sc->sc_mtx, 0, "rtwn_pci", - MAX(msecs_to_ticks(usec / 1000), 1)); + msecs_to_ticks(usec / 1000)); } } diff --git a/freebsd/sys/dev/rtwn/pci/rtwn_pci_rx.c b/freebsd/sys/dev/rtwn/pci/rtwn_pci_rx.c index 1934b741..f97fea44 100644 --- a/freebsd/sys/dev/rtwn/pci/rtwn_pci_rx.c +++ b/freebsd/sys/dev/rtwn/pci/rtwn_pci_rx.c @@ -85,12 +85,12 @@ rtwn_pci_setup_rx_desc(struct rtwn_pci_softc *pc, } static void -rtwn_pci_rx_frame(struct rtwn_softc *sc, struct rtwn_rx_stat_pci *rx_desc, - int desc_idx) +rtwn_pci_rx_frame(struct rtwn_pci_softc *pc) { - struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc); + struct rtwn_softc *sc = &pc->pc_sc; struct rtwn_rx_ring *ring = &pc->rx_ring; - struct rtwn_rx_data *rx_data = &ring->rx_data[desc_idx]; + struct rtwn_rx_stat_pci *rx_desc = &ring->desc[ring->cur]; + struct rtwn_rx_data *rx_data = &ring->rx_data[ring->cur]; struct ieee80211com *ic = &sc->sc_ic; struct ieee80211_node *ni; uint32_t rxdw0; @@ -150,9 +150,6 @@ rtwn_pci_rx_frame(struct rtwn_softc *sc, struct rtwn_rx_stat_pci *rx_desc, panic("%s: could not load old RX mbuf", device_get_name(sc->sc_dev)); - /* Physical address may have changed. */ - rtwn_pci_setup_rx_desc(pc, rx_desc, rx_data->paddr, - MJUMPAGESIZE, desc_idx); goto fail; } @@ -167,10 +164,6 @@ rtwn_pci_rx_frame(struct rtwn_softc *sc, struct rtwn_rx_stat_pci *rx_desc, "%s: Rx frame len %d, infosz %d, shift %d\n", __func__, pktlen, infosz, shift); - /* Update RX descriptor. */ - rtwn_pci_setup_rx_desc(pc, rx_desc, rx_data->paddr, MJUMPAGESIZE, - desc_idx); - /* Send the frame to the 802.11 layer. */ RTWN_UNLOCK(sc); if (ni != NULL) { @@ -188,6 +181,72 @@ fail: counter_u64_add(ic->ic_ierrors, 1); } +static int +rtwn_pci_rx_buf_copy(struct rtwn_pci_softc *pc) +{ + struct rtwn_rx_ring *ring = &pc->rx_ring; + struct rtwn_rx_stat_pci *rx_desc = &ring->desc[ring->cur]; + struct rtwn_rx_data *rx_data = &ring->rx_data[ring->cur]; + uint32_t rxdw0; + int desc_size, pktlen; + + /* + * NB: tx_report() / c2h_report() expects to see USB Rx + * descriptor - same as for PCIe, but without rxbufaddr* fields. + */ + desc_size = sizeof(struct rtwn_rx_stat_common); + KASSERT(sizeof(pc->pc_rx_buf) >= desc_size, + ("adjust size for PCIe Rx buffer!")); + + memcpy(pc->pc_rx_buf, rx_desc, desc_size); + + rxdw0 = le32toh(rx_desc->rxdw0); + pktlen = MS(rxdw0, RTWN_RXDW0_PKTLEN); + + if (pktlen > sizeof(pc->pc_rx_buf) - desc_size) + { + /* Looks like an ordinary Rx frame. */ + return (desc_size); + } + + bus_dmamap_sync(ring->data_dmat, rx_data->map, BUS_DMASYNC_POSTREAD); + memcpy(pc->pc_rx_buf + desc_size, mtod(rx_data->m, void *), pktlen); + + return (desc_size + pktlen); +} + +static void +rtwn_pci_tx_report(struct rtwn_pci_softc *pc, int len) +{ + struct rtwn_softc *sc = &pc->pc_sc; + + if (sc->sc_ratectl != RTWN_RATECTL_NET80211) { + /* shouldn't happen */ + device_printf(sc->sc_dev, + "%s called while ratectl = %d!\n", + __func__, sc->sc_ratectl); + return; + } + + RTWN_NT_LOCK(sc); + rtwn_handle_tx_report(sc, pc->pc_rx_buf, len); + RTWN_NT_UNLOCK(sc); + +#ifdef IEEE80211_SUPPORT_SUPERG + /* + * NB: this will executed only when 'report' bit is set. + */ + if (sc->sc_tx_n_active > 0 && --sc->sc_tx_n_active <= 1) + rtwn_cmd_sleepable(sc, NULL, 0, rtwn_ff_flush_all); +#endif +} + +static void +rtwn_pci_c2h_report(struct rtwn_pci_softc *pc, int len) +{ + rtwn_handle_c2h_report(&pc->pc_sc, pc->pc_rx_buf, len); +} + static void rtwn_pci_tx_done(struct rtwn_softc *sc, int qid) { @@ -199,7 +258,8 @@ rtwn_pci_tx_done(struct rtwn_softc *sc, int qid) RTWN_DPRINTF(sc, RTWN_DEBUG_INTR, "%s: qid %d, last %d, cur %d\n", __func__, qid, ring->last, ring->cur); - bus_dmamap_sync(ring->desc_dmat, ring->desc_map, BUS_DMASYNC_POSTREAD); + bus_dmamap_sync(ring->desc_dmat, ring->desc_map, + BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); while(ring->last != ring->cur) { data = &ring->tx_data[ring->last]; @@ -264,21 +324,50 @@ rtwn_pci_rx_done(struct rtwn_softc *sc) { struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc); struct rtwn_rx_ring *ring = &pc->rx_ring; + struct rtwn_rx_stat_pci *rx_desc; + struct rtwn_rx_data *rx_data; + int len; bus_dmamap_sync(ring->desc_dmat, ring->desc_map, BUS_DMASYNC_POSTREAD); for (;;) { - struct rtwn_rx_stat_pci *rx_desc = &ring->desc[ring->cur]; + rx_desc = &ring->desc[ring->cur]; + rx_data = &ring->rx_data[ring->cur]; if (le32toh(rx_desc->rxdw0) & RTWN_RXDW0_OWN) break; - rtwn_pci_rx_frame(sc, rx_desc, ring->cur); + len = rtwn_pci_rx_buf_copy(pc); + + switch (rtwn_classify_intr(sc, pc->pc_rx_buf, len)) { + case RTWN_RX_DATA: + rtwn_pci_rx_frame(pc); + break; + case RTWN_RX_TX_REPORT: + rtwn_pci_tx_report(pc, len); + break; + case RTWN_RX_OTHER: + rtwn_pci_c2h_report(pc, len); + break; + default: + /* NOTREACHED */ + KASSERT(0, ("unknown Rx classification code")); + break; + } + + /* Update / reset RX descriptor (and set OWN bit). */ + rtwn_pci_setup_rx_desc(pc, rx_desc, rx_data->paddr, + MJUMPAGESIZE, ring->cur); if (!(sc->sc_flags & RTWN_RUNNING)) return; - ring->cur = (ring->cur + 1) % RTWN_PCI_RX_LIST_COUNT; + /* NB: device can reuse current descriptor. */ + bus_dmamap_sync(ring->desc_dmat, ring->desc_map, + BUS_DMASYNC_POSTREAD); + + if (le32toh(rx_desc->rxdw0) & RTWN_RXDW0_OWN) + ring->cur = (ring->cur + 1) % RTWN_PCI_RX_LIST_COUNT; } } @@ -290,13 +379,13 @@ rtwn_pci_intr(void *arg) int i, status, tx_rings; RTWN_LOCK(sc); - status = rtwn_classify_intr(sc, &tx_rings, 0); + status = rtwn_pci_get_intr_status(pc, &tx_rings); RTWN_DPRINTF(sc, RTWN_DEBUG_INTR, "%s: status %08X, tx_rings %08X\n", __func__, status, tx_rings); if (status == 0 && tx_rings == 0) goto unlock; - if (status & RTWN_PCI_INTR_RX) { + if (status & (RTWN_PCI_INTR_RX | RTWN_PCI_INTR_TX_REPORT)) { rtwn_pci_rx_done(sc); if (!(sc->sc_flags & RTWN_RUNNING)) goto unlock; diff --git a/freebsd/sys/dev/rtwn/pci/rtwn_pci_tx.c b/freebsd/sys/dev/rtwn/pci/rtwn_pci_tx.c index 50e915ee..1d3852ca 100644 --- a/freebsd/sys/dev/rtwn/pci/rtwn_pci_tx.c +++ b/freebsd/sys/dev/rtwn/pci/rtwn_pci_tx.c @@ -176,8 +176,8 @@ rtwn_pci_tx_start_frame(struct rtwn_softc *sc, struct ieee80211_node *ni, rtwn_dump_tx_desc(sc, txd); bus_dmamap_sync(ring->desc_dmat, ring->desc_map, - BUS_DMASYNC_POSTWRITE); - bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_POSTWRITE); + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); + bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_PREWRITE); data->m = m; data->ni = ni; diff --git a/freebsd/sys/dev/rtwn/pci/rtwn_pci_var.h b/freebsd/sys/dev/rtwn/pci/rtwn_pci_var.h index 194fab4a..95b2effe 100644 --- a/freebsd/sys/dev/rtwn/pci/rtwn_pci_var.h +++ b/freebsd/sys/dev/rtwn/pci/rtwn_pci_var.h @@ -26,6 +26,9 @@ #define RTWN_PCI_RX_LIST_COUNT 256 #define RTWN_PCI_TX_LIST_COUNT 256 +/* sizeof(struct rtwn_rx_stat_common) + R88E_INTR_MSG_LEN */ +#define RTWN_PCI_RX_TMP_BUF_SIZE 84 + struct rtwn_rx_data { bus_dmamap_t map; struct mbuf *m; @@ -95,8 +98,8 @@ enum { /* Shortcuts */ /* Vendor driver treats RX errors like ROK... */ #define RTWN_PCI_INTR_RX \ - (RTWN_PCI_INTR_RX_OVERFLOW | RTWN_PCI_INTR_RX_DESC_UNAVAIL | \ - RTWN_PCI_INTR_RX_DONE) + (RTWN_PCI_INTR_RX_ERROR | RTWN_PCI_INTR_RX_OVERFLOW | \ + RTWN_PCI_INTR_RX_DESC_UNAVAIL | RTWN_PCI_INTR_RX_DONE) struct rtwn_pci_softc { @@ -109,6 +112,7 @@ struct rtwn_pci_softc { void *pc_ih; bus_size_t pc_mapsize; + uint8_t pc_rx_buf[RTWN_PCI_RX_TMP_BUF_SIZE]; struct rtwn_rx_ring rx_ring; struct rtwn_tx_ring tx_ring[RTWN_PCI_NTXQUEUES]; @@ -122,6 +126,8 @@ struct rtwn_pci_softc { void *, bus_dma_segment_t *); void (*pc_copy_tx_desc)(void *, const void *); void (*pc_enable_intr)(struct rtwn_pci_softc *); + int (*pc_get_intr_status)(struct rtwn_pci_softc *, + int *); }; #define RTWN_PCI_SOFTC(sc) ((struct rtwn_pci_softc *)(sc)) @@ -133,5 +139,7 @@ struct rtwn_pci_softc { (((_pc)->pc_copy_tx_desc)((_dest), (_src))) #define rtwn_pci_enable_intr(_pc) \ (((_pc)->pc_enable_intr)((_pc))) +#define rtwn_pci_get_intr_status(_pc, _tx_rings) \ + (((_pc)->pc_get_intr_status)((_pc), (_tx_rings))) #endif /* RTWN_PCI_VAR_H */ diff --git a/freebsd/sys/dev/rtwn/rtl8188e/r88e.h b/freebsd/sys/dev/rtwn/rtl8188e/r88e.h index 3a3c0865..ce9fa19a 100644 --- a/freebsd/sys/dev/rtwn/rtl8188e/r88e.h +++ b/freebsd/sys/dev/rtwn/rtl8188e/r88e.h @@ -24,9 +24,7 @@ /* * Global definitions. */ -#define R88E_PUBQ_NPAGES 142 #define R88E_TXPKTBUF_COUNT 177 -#define R88E_TX_PAGE_COUNT 169 #define R88E_MACID_MAX 63 #define R88E_RX_DMA_BUFFER_SIZE 0x2400 @@ -67,9 +65,8 @@ int r88e_set_pwrmode(struct rtwn_softc *, struct ieee80211vap *, int); #endif /* r88e_init.c */ -void r88e_init_bb(struct rtwn_softc *); +void r88e_init_bb_common(struct rtwn_softc *); void r88e_init_rf(struct rtwn_softc *); -int r88e_power_on(struct rtwn_softc *); /* r88e_led.c */ void r88e_set_led(struct rtwn_softc *, int, int); @@ -81,6 +78,7 @@ void r88e_rf_write(struct rtwn_softc *, int, uint8_t, uint32_t); void r88e_parse_rom(struct rtwn_softc *, uint8_t *); /* r88e_rx.c */ +int r88e_classify_intr(struct rtwn_softc *, void *, int); void r88e_ratectl_tx_complete(struct rtwn_softc *, uint8_t *, int); void r88e_handle_c2h_report(struct rtwn_softc *, uint8_t *, int); int8_t r88e_get_rssi_cck(struct rtwn_softc *, void *); diff --git a/freebsd/sys/dev/rtwn/rtl8188e/r88e_calib.c b/freebsd/sys/dev/rtwn/rtl8188e/r88e_calib.c index 592f391a..94974983 100644 --- a/freebsd/sys/dev/rtwn/rtl8188e/r88e_calib.c +++ b/freebsd/sys/dev/rtwn/rtl8188e/r88e_calib.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-kernel-space.h> /*- - * Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org> + * Copyright (c) 2016-2019 Andriy Voskoboinyk <avos@FreeBSD.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -44,16 +44,343 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/if_rtwnreg.h> #include <dev/rtwn/if_rtwnvar.h> +#include <dev/rtwn/if_rtwn_debug.h> #include <dev/rtwn/rtl8188e/r88e.h> #include <dev/rtwn/rtl8188e/r88e_reg.h> +/* Registers to save and restore during IQ calibration. */ +struct r88e_iq_cal_reg_vals { + uint32_t adda[16]; + uint8_t txpause; + uint8_t bcn_ctrl[2]; + uint32_t gpio_muxcfg; + uint32_t cck0_afesetting; + uint32_t ofdm0_trxpathena; + uint32_t ofdm0_trmuxpar; + uint32_t fpga0_rfifacesw0; + uint32_t fpga0_rfifacesw1; + uint32_t fpga0_rfifaceoe0; + uint32_t fpga0_rfifaceoe1; + uint32_t config_ant0; + uint32_t config_ant1; +}; + +static int +r88e_iq_calib_chain(struct rtwn_softc *sc, uint16_t tx[2], uint16_t rx[2]) +{ + uint32_t status; + + /* Set Rx IQ calibration mode table. */ + rtwn_bb_write(sc, R92C_FPGA0_IQK, 0); + rtwn_rf_write(sc, 0, R88E_RF_WE_LUT, 0x800a0); + rtwn_rf_write(sc, 0, R92C_RF_RCK_OS, 0x30000); + rtwn_rf_write(sc, 0, R92C_RF_TXPA_G(0), 0xf); + rtwn_rf_write(sc, 0, R92C_RF_TXPA_G(1), 0xf117b); + rtwn_bb_write(sc, R92C_FPGA0_IQK, 0x80800000); + + /* IQ calibration settings. */ + rtwn_bb_write(sc, R92C_TX_IQK, 0x01007c00); + rtwn_bb_write(sc, R92C_RX_IQK, 0x81004800); + + /* IQ calibration settings for chain 0. */ + rtwn_bb_write(sc, R92C_TX_IQK_TONE(0), 0x10008c1c); + rtwn_bb_write(sc, R92C_RX_IQK_TONE(0), 0x30008c1c); + rtwn_bb_write(sc, R92C_TX_IQK_PI(0), 0x82160804); + rtwn_bb_write(sc, R92C_RX_IQK_PI(0), 0x28160000); + + /* LO calibration settings. */ + rtwn_bb_write(sc, R92C_IQK_AGC_RSP, 0x0046a911); + + /* We're doing LO and IQ calibration in one shot. */ + rtwn_bb_write(sc, R92C_IQK_AGC_PTS, 0xf9000000); + rtwn_bb_write(sc, R92C_IQK_AGC_PTS, 0xf8000000); + + /* Give LO and IQ calibrations the time to complete. */ + rtwn_delay(sc, 10000); + + /* Read IQ calibration status. */ + status = rtwn_bb_read(sc, R92C_RX_POWER_IQK_AFTER(0)); + if (status & (1 << 28)) + return (0); /* Tx failed. */ + + /* Read Tx IQ calibration results. */ + tx[0] = MS(rtwn_bb_read(sc, R92C_TX_POWER_IQK_BEFORE(0)), + R92C_POWER_IQK_RESULT); + tx[1] = MS(rtwn_bb_read(sc, R92C_TX_POWER_IQK_AFTER(0)), + R92C_POWER_IQK_RESULT); + if (tx[0] == 0x142 || tx[1] == 0x042) + return (0); /* Tx failed. */ + + rtwn_bb_write(sc, R92C_TX_IQK, 0x80007c00 | (tx[0] << 16) | tx[1]); + + /* Set Rx IQ calibration mode table. */ + rtwn_bb_write(sc, R92C_FPGA0_IQK, 0); + rtwn_rf_write(sc, 0, R88E_RF_WE_LUT, 0x800a0); + rtwn_rf_write(sc, 0, R92C_RF_RCK_OS, 0x30000); + rtwn_rf_write(sc, 0, R92C_RF_TXPA_G(0), 0xf); + rtwn_rf_write(sc, 0, R92C_RF_TXPA_G(1), 0xf7ffa); + rtwn_bb_write(sc, R92C_FPGA0_IQK, 0x80800000); + + /* IQ calibration settings. */ + rtwn_bb_write(sc, R92C_RX_IQK, 0x01004800); + + /* IQ calibration settings for chain 0. */ + rtwn_bb_write(sc, R92C_TX_IQK_TONE(0), 0x30008c1c); + rtwn_bb_write(sc, R92C_RX_IQK_TONE(0), 0x10008c1c); + rtwn_bb_write(sc, R92C_TX_IQK_PI(0), 0x82160c05); + rtwn_bb_write(sc, R92C_RX_IQK_PI(0), 0x28160c05); + + /* LO calibration settings. */ + rtwn_bb_write(sc, R92C_IQK_AGC_RSP, 0x0046a911); + + /* We're doing LO and IQ calibration in one shot. */ + rtwn_bb_write(sc, R92C_IQK_AGC_PTS, 0xf9000000); + rtwn_bb_write(sc, R92C_IQK_AGC_PTS, 0xf8000000); + + /* Give LO and IQ calibrations the time to complete. */ + rtwn_delay(sc, 10000); + + /* Read IQ calibration status. */ + status = rtwn_bb_read(sc, R92C_RX_POWER_IQK_AFTER(0)); + if (status & (1 << 27)) + return (1); /* Rx failed. */ + + /* Read Rx IQ calibration results. */ + rx[0] = MS(rtwn_bb_read(sc, R92C_RX_POWER_IQK_BEFORE(0)), + R92C_POWER_IQK_RESULT); + rx[1] = MS(status, R92C_POWER_IQK_RESULT); + if (rx[0] == 0x132 || rx[1] == 0x036) + return (1); /* Rx failed. */ + + return (3); /* Both Tx and Rx succeeded. */ +} + +static void +r88e_iq_calib_run(struct rtwn_softc *sc, int n, uint16_t tx[2], + uint16_t rx[2], struct r88e_iq_cal_reg_vals *vals) +{ + /* Registers to save and restore during IQ calibration. */ + static const uint16_t reg_adda[16] = { + 0x85c, 0xe6c, 0xe70, 0xe74, + 0xe78, 0xe7c, 0xe80, 0xe84, + 0xe88, 0xe8c, 0xed0, 0xed4, + 0xed8, 0xedc, 0xee0, 0xeec + }; + int i; + uint32_t hssi_param1; + + if (n == 0) { + for (i = 0; i < nitems(reg_adda); i++) + vals->adda[i] = rtwn_bb_read(sc, reg_adda[i]); + + vals->txpause = rtwn_read_1(sc, R92C_TXPAUSE); + vals->bcn_ctrl[0] = rtwn_read_1(sc, R92C_BCN_CTRL(0)); + vals->bcn_ctrl[1] = rtwn_read_1(sc, R92C_BCN_CTRL(1)); + vals->gpio_muxcfg = rtwn_read_4(sc, R92C_GPIO_MUXCFG); + } + + rtwn_bb_write(sc, reg_adda[0], 0x0b1b25a0); + for (i = 1; i < nitems(reg_adda); i++) + rtwn_bb_write(sc, reg_adda[i], 0x0bdb25a0); + + hssi_param1 = rtwn_bb_read(sc, R92C_HSSI_PARAM1(0)); + if (!(hssi_param1 & R92C_HSSI_PARAM1_PI)) { + rtwn_bb_write(sc, R92C_HSSI_PARAM1(0), + hssi_param1 | R92C_HSSI_PARAM1_PI); + rtwn_bb_write(sc, R92C_HSSI_PARAM1(1), + hssi_param1 | R92C_HSSI_PARAM1_PI); + } + + if (n == 0) { + vals->cck0_afesetting = rtwn_bb_read(sc, R92C_CCK0_AFESETTING); + vals->ofdm0_trxpathena = + rtwn_bb_read(sc, R92C_OFDM0_TRXPATHENA); + vals->ofdm0_trmuxpar = rtwn_bb_read(sc, R92C_OFDM0_TRMUXPAR); + vals->fpga0_rfifacesw0 = + rtwn_bb_read(sc, R92C_FPGA0_RFIFACESW(0)); + vals->fpga0_rfifacesw1 = + rtwn_bb_read(sc, R92C_FPGA0_RFIFACESW(1)); + vals->fpga0_rfifaceoe0 = + rtwn_bb_read(sc, R92C_FPGA0_RFIFACEOE(0)); + vals->fpga0_rfifaceoe1 = + rtwn_bb_read(sc, R92C_FPGA0_RFIFACEOE(1)); + vals->config_ant0 = rtwn_bb_read(sc, R92C_CONFIG_ANT(0)); + vals->config_ant1 = rtwn_bb_read(sc, R92C_CONFIG_ANT(1)); + } + + rtwn_bb_setbits(sc, R92C_CCK0_AFESETTING, 0, 0x0f000000); + rtwn_bb_write(sc, R92C_OFDM0_TRXPATHENA, 0x03a05600); + rtwn_bb_write(sc, R92C_OFDM0_TRMUXPAR, 0x000800e4); + rtwn_bb_write(sc, R92C_FPGA0_RFIFACESW(1), 0x22204000); + rtwn_bb_setbits(sc, R92C_FPGA0_RFIFACESW(0), 0, 0x04000400); + rtwn_bb_setbits(sc, R92C_FPGA0_RFIFACEOE(0), 0x400, 0); + rtwn_bb_setbits(sc, R92C_FPGA0_RFIFACEOE(1), 0x400, 0); + + rtwn_write_1(sc, R92C_TXPAUSE, + R92C_TX_QUEUE_AC | R92C_TX_QUEUE_MGT | R92C_TX_QUEUE_HIGH); + rtwn_write_1(sc, R92C_BCN_CTRL(0), + vals->bcn_ctrl[0] & ~R92C_BCN_CTRL_EN_BCN); + rtwn_write_1(sc, R92C_BCN_CTRL(1), + vals->bcn_ctrl[1] & ~R92C_BCN_CTRL_EN_BCN); + rtwn_write_1(sc, R92C_GPIO_MUXCFG, + vals->gpio_muxcfg & ~R92C_GPIO_MUXCFG_ENBT); + + rtwn_bb_write(sc, R92C_CONFIG_ANT(0), 0x0f600000); + + rtwn_bb_write(sc, R92C_FPGA0_IQK, 0x80800000); + rtwn_bb_write(sc, R92C_TX_IQK, 0x01007c00); + rtwn_bb_write(sc, R92C_RX_IQK, 0x01004800); + + /* Run IQ calibration twice. */ + for (i = 0; i < 2; i++) { + int ret; + + ret = r88e_iq_calib_chain(sc, tx, rx); + if (ret == 0) { + RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB, "%s: Tx failed.\n", + __func__); + tx[0] = 0xff; + tx[1] = 0xff; + rx[0] = 0xff; + rx[1] = 0xff; + } else if (ret == 1) { + RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB, "%s: Rx failed.\n", + __func__); + rx[0] = 0xff; + rx[1] = 0xff; + } else if (ret == 3) { + RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB, "%s: Both Tx and Rx" + " succeeded.\n", __func__); + } + } + + RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB, + "%s: results for run %d: tx[0] 0x%x, tx[1] 0x%x, rx[0] 0x%x, " + "rx[1] 0x%x\n", __func__, n, tx[0], tx[1], rx[0], rx[1]); + + rtwn_bb_write(sc, R92C_CCK0_AFESETTING, vals->cck0_afesetting); + rtwn_bb_write(sc, R92C_OFDM0_TRXPATHENA, vals->ofdm0_trxpathena); + rtwn_bb_write(sc, R92C_FPGA0_RFIFACESW(0), vals->fpga0_rfifacesw0); + rtwn_bb_write(sc, R92C_FPGA0_RFIFACESW(1), vals->fpga0_rfifacesw1); + rtwn_bb_write(sc, R92C_OFDM0_TRMUXPAR, vals->ofdm0_trmuxpar); + rtwn_bb_write(sc, R92C_FPGA0_RFIFACEOE(0), vals->fpga0_rfifaceoe0); + rtwn_bb_write(sc, R92C_FPGA0_RFIFACEOE(1), vals->fpga0_rfifaceoe1); + rtwn_bb_write(sc, R92C_CONFIG_ANT(0), vals->config_ant0); + rtwn_bb_write(sc, R92C_CONFIG_ANT(1), vals->config_ant1); + + rtwn_bb_write(sc, R92C_FPGA0_IQK, 0); + rtwn_bb_write(sc, R92C_LSSI_PARAM(0), 0x00032ed3); + + if (n != 0) { + if (!(hssi_param1 & R92C_HSSI_PARAM1_PI)) { + rtwn_bb_write(sc, R92C_HSSI_PARAM1(0), hssi_param1); + rtwn_bb_write(sc, R92C_HSSI_PARAM1(1), hssi_param1); + } + + for (i = 0; i < nitems(reg_adda); i++) + rtwn_bb_write(sc, reg_adda[i], vals->adda[i]); + + rtwn_write_1(sc, R92C_TXPAUSE, vals->txpause); + rtwn_write_1(sc, R92C_BCN_CTRL(0), vals->bcn_ctrl[0]); + rtwn_write_1(sc, R92C_BCN_CTRL(1), vals->bcn_ctrl[1]); + rtwn_write_4(sc, R92C_GPIO_MUXCFG, vals->gpio_muxcfg); + } +} + +#define RTWN_IQ_CAL_MAX_TOLERANCE 5 +static int +r88e_iq_calib_compare_results(struct rtwn_softc *sc, uint16_t tx1[2], + uint16_t rx1[2], uint16_t tx2[2], uint16_t rx2[2]) +{ + int i, tx_ok, rx_ok; + + tx_ok = rx_ok = 0; + for (i = 0; i < 2; i++) { + if (tx1[i] == 0xff || tx2[i] == 0xff || + rx1[i] == 0xff || rx2[i] == 0xff) + continue; + + tx_ok = (abs(tx1[i] - tx2[i]) <= RTWN_IQ_CAL_MAX_TOLERANCE); + rx_ok = (abs(rx1[i] - rx2[i]) <= RTWN_IQ_CAL_MAX_TOLERANCE); + } + + return (tx_ok && rx_ok); +} +#undef RTWN_IQ_CAL_MAX_TOLERANCE + +static void +r88e_iq_calib_write_results(struct rtwn_softc *sc, uint16_t tx[2], + uint16_t rx[2]) +{ + uint32_t reg, val, x; + long y, tx_c; + + if (tx[0] == 0xff || tx[1] == 0xff) + return; + + reg = rtwn_bb_read(sc, R92C_OFDM0_TXIQIMBALANCE(0)); + val = ((reg >> 22) & 0x3ff); + x = tx[0]; + if (x & 0x00000200) + x |= 0xfffffc00; + reg = (((x * val) >> 8) & 0x3ff); + rtwn_bb_setbits(sc, R92C_OFDM0_TXIQIMBALANCE(0), 0x3ff, reg); + rtwn_bb_setbits(sc, R92C_OFDM0_ECCATHRESHOLD, 0x80000000, + ((x * val) & 0x80) << 24); + + y = tx[1]; + if (y & 0x00000200) + y |= 0xfffffc00; + tx_c = (y * val) >> 8; + rtwn_bb_setbits(sc, R92C_OFDM0_TXAFE(0), 0xf0000000, + (tx_c & 0x3c0) << 22); + rtwn_bb_setbits(sc, R92C_OFDM0_TXIQIMBALANCE(0), 0x003f0000, + (tx_c & 0x3f) << 16); + rtwn_bb_setbits(sc, R92C_OFDM0_ECCATHRESHOLD, 0x20000000, + ((y * val) & 0x80) << 22); + + if (rx[0] == 0xff || rx[1] == 0xff) + return; + + rtwn_bb_setbits(sc, R92C_OFDM0_RXIQIMBALANCE(0), 0x3ff, + rx[0] & 0x3ff); + rtwn_bb_setbits(sc, R92C_OFDM0_RXIQIMBALANCE(0), 0xfc00, + (rx[1] & 0x3f) << 10); + rtwn_bb_setbits(sc, R92C_OFDM0_RXIQEXTANTA, 0xf0000000, + (rx[1] & 0x3c0) << 22); +} + +#define RTWN_IQ_CAL_NRUN 3 void r88e_iq_calib(struct rtwn_softc *sc) { - /* XXX TODO */ + struct r88e_iq_cal_reg_vals vals; + uint16_t tx[RTWN_IQ_CAL_NRUN][2], rx[RTWN_IQ_CAL_NRUN][2]; + int n, valid; + + KASSERT(sc->ntxchains == 1, + ("%s: only 1T1R configuration is supported!\n", __func__)); + + valid = 0; + for (n = 0; n < RTWN_IQ_CAL_NRUN; n++) { + r88e_iq_calib_run(sc, n, tx[n], rx[n], &vals); + + if (n == 0) + continue; + + /* Valid results remain stable after consecutive runs. */ + valid = r88e_iq_calib_compare_results(sc, tx[n - 1], + rx[n - 1], tx[n], rx[n]); + if (valid) + break; + } + + if (valid) + r88e_iq_calib_write_results(sc, tx[n], rx[n]); } +#undef RTWN_IQ_CAL_NRUN void r88e_temp_measure(struct rtwn_softc *sc) diff --git a/freebsd/sys/dev/rtwn/rtl8188e/r88e_fw.c b/freebsd/sys/dev/rtwn/rtl8188e/r88e_fw.c index ddc9d0a4..ff48d244 100644 --- a/freebsd/sys/dev/rtwn/rtl8188e/r88e_fw.c +++ b/freebsd/sys/dev/rtwn/rtl8188e/r88e_fw.c @@ -111,7 +111,11 @@ r88e_fw_reset(struct rtwn_softc *sc, int reason) reg = rtwn_read_2(sc, R92C_SYS_FUNC_EN); rtwn_write_2(sc, R92C_SYS_FUNC_EN, reg & ~R92C_SYS_FUNC_EN_CPUEN); - rtwn_write_2(sc, R92C_SYS_FUNC_EN, reg | R92C_SYS_FUNC_EN_CPUEN); + + if (reason != RTWN_FW_RESET_SHUTDOWN) { + rtwn_write_2(sc, R92C_SYS_FUNC_EN, + reg | R92C_SYS_FUNC_EN_CPUEN); + } } void diff --git a/freebsd/sys/dev/rtwn/rtl8188e/r88e_init.c b/freebsd/sys/dev/rtwn/rtl8188e/r88e_init.c index 5225c43f..8c5bbac2 100644 --- a/freebsd/sys/dev/rtwn/rtl8188e/r88e_init.c +++ b/freebsd/sys/dev/rtwn/rtl8188e/r88e_init.c @@ -72,20 +72,8 @@ r88e_crystalcap_write(struct rtwn_softc *sc) } void -r88e_init_bb(struct rtwn_softc *sc) +r88e_init_bb_common(struct rtwn_softc *sc) { - - /* Enable BB and RF. */ - rtwn_setbits_2(sc, R92C_SYS_FUNC_EN, 0, - R92C_SYS_FUNC_EN_BBRSTB | R92C_SYS_FUNC_EN_BB_GLB_RST | - R92C_SYS_FUNC_EN_DIO_RF); - - rtwn_write_1(sc, R92C_RF_CTRL, - R92C_RF_CTRL_EN | R92C_RF_CTRL_RSTB | R92C_RF_CTRL_SDMRSTB); - rtwn_write_1(sc, R92C_SYS_FUNC_EN, - R92C_SYS_FUNC_EN_USBA | R92C_SYS_FUNC_EN_USBD | - R92C_SYS_FUNC_EN_BB_GLB_RST | R92C_SYS_FUNC_EN_BBRSTB); - r92c_init_bb_common(sc); rtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), 0x69553422); @@ -95,66 +83,3 @@ r88e_init_bb(struct rtwn_softc *sc) r88e_crystalcap_write(sc); } - -int -r88e_power_on(struct rtwn_softc *sc) -{ -#define RTWN_CHK(res) do { \ - if (res != 0) \ - return (EIO); \ -} while(0) - int ntries; - - /* Wait for power ready bit. */ - for (ntries = 0; ntries < 5000; ntries++) { - if (rtwn_read_4(sc, R92C_APS_FSMCO) & R92C_APS_FSMCO_SUS_HOST) - break; - rtwn_delay(sc, 10); - } - if (ntries == 5000) { - device_printf(sc->sc_dev, - "timeout waiting for chip power up\n"); - return (ETIMEDOUT); - } - - /* Reset BB. */ - RTWN_CHK(rtwn_setbits_1(sc, R92C_SYS_FUNC_EN, - R92C_SYS_FUNC_EN_BBRSTB | R92C_SYS_FUNC_EN_BB_GLB_RST, 0)); - - RTWN_CHK(rtwn_setbits_1(sc, R92C_AFE_XTAL_CTRL + 2, 0, 0x80)); - - /* Disable HWPDN. */ - RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, - R92C_APS_FSMCO_APDM_HPDN, 0, 1)); - - /* Disable WL suspend. */ - RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, - R92C_APS_FSMCO_AFSM_HSUS | R92C_APS_FSMCO_AFSM_PCIE, 0, 1)); - - RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, - 0, R92C_APS_FSMCO_APFM_ONMAC, 1)); - for (ntries = 0; ntries < 5000; ntries++) { - if (!(rtwn_read_2(sc, R92C_APS_FSMCO) & - R92C_APS_FSMCO_APFM_ONMAC)) - break; - rtwn_delay(sc, 10); - } - if (ntries == 5000) - return (ETIMEDOUT); - - /* Enable LDO normal mode. */ - RTWN_CHK(rtwn_setbits_1(sc, R92C_LPLDO_CTRL, - R92C_LPLDO_CTRL_SLEEP, 0)); - - /* Enable MAC DMA/WMAC/SCHEDULE/SEC blocks. */ - RTWN_CHK(rtwn_write_2(sc, R92C_CR, 0)); - RTWN_CHK(rtwn_setbits_2(sc, R92C_CR, 0, - R92C_CR_HCI_TXDMA_EN | R92C_CR_TXDMA_EN | - R92C_CR_HCI_RXDMA_EN | R92C_CR_RXDMA_EN | - R92C_CR_PROTOCOL_EN | R92C_CR_SCHEDULE_EN | - ((sc->sc_hwcrypto != RTWN_CRYPTO_SW) ? R92C_CR_ENSEC : 0) | - R92C_CR_CALTMR_EN)); - - return (0); -#undef RTWN_CHK -} diff --git a/freebsd/sys/dev/rtwn/rtl8188e/r88e_priv.h b/freebsd/sys/dev/rtwn/rtl8188e/r88e_priv.h index 28f4b1fb..8ec5502d 100644 --- a/freebsd/sys/dev/rtwn/rtl8188e/r88e_priv.h +++ b/freebsd/sys/dev/rtwn/rtl8188e/r88e_priv.h @@ -37,7 +37,7 @@ struct rtwn_r88e_txpwr { /* * MAC initialization values. */ -static const struct rtwn_mac_prog rtl8188eu_mac[] = { +static const struct rtwn_mac_prog rtl8188e_mac[] = { { 0x026, 0x41 }, { 0x027, 0x35 }, { 0x040, 0x00 }, { 0x428, 0x0a }, { 0x429, 0x10 }, { 0x430, 0x00 }, { 0x431, 0x01 }, { 0x432, 0x02 }, { 0x433, 0x04 }, { 0x434, 0x05 }, { 0x435, 0x06 }, { 0x436, 0x07 }, @@ -66,7 +66,7 @@ static const struct rtwn_mac_prog rtl8188eu_mac[] = { /* * Baseband initialization values. */ -static const uint16_t rtl8188eu_bb_regs[] = { +static const uint16_t rtl8188e_bb_regs[] = { 0x800, 0x804, 0x808, 0x80c, 0x810, 0x814, 0x818, 0x81c, 0x820, 0x824, 0x828, 0x82c, 0x830, 0x834, 0x838, 0x83c, 0x840, 0x844, 0x848, 0x84c, 0x850, 0x854, 0x858, 0x85c, @@ -93,7 +93,7 @@ static const uint16_t rtl8188eu_bb_regs[] = { 0xed8, 0xedc, 0xee0, 0xee8, 0xeec, 0xf14, 0xf4c, 0xf00 }; -static const uint32_t rtl8188eu_bb_vals[] = { +static const uint32_t rtl8188e_bb_vals[] = { 0x80040000, 0x00000003, 0x0000fc00, 0x0000000a, 0x10001331, 0x020c3d10, 0x02200385, 0x00000000, 0x01000100, 0x00390204, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, @@ -135,17 +135,17 @@ static const uint32_t rtl8188eu_bb_vals[] = { 0x00000000, 0x00000300 }; -static const struct rtwn_bb_prog rtl8188eu_bb[] = { +static const struct rtwn_bb_prog rtl8188e_bb[] = { { - nitems(rtl8188eu_bb_regs), - rtl8188eu_bb_regs, - rtl8188eu_bb_vals, + nitems(rtl8188e_bb_regs), + rtl8188e_bb_regs, + rtl8188e_bb_vals, { 0 }, NULL } }; -static const uint32_t rtl8188eu_agc_vals[] = { +static const uint32_t rtl8188e_agc_vals[] = { 0xfb000001, 0xfb010001, 0xfb020001, 0xfb030001, 0xfb040001, 0xfb050001, 0xfa060001, 0xf9070001, 0xf8080001, 0xf7090001, 0xf60a0001, 0xf50b0001, 0xf40c0001, 0xf30d0001, 0xf20e0001, @@ -174,10 +174,10 @@ static const uint32_t rtl8188eu_agc_vals[] = { 0x407d0001, 0x407e0001, 0x407f0001 }; -static const struct rtwn_agc_prog rtl8188eu_agc[] = { +static const struct rtwn_agc_prog rtl8188e_agc[] = { { - nitems(rtl8188eu_agc_vals), - rtl8188eu_agc_vals, + nitems(rtl8188e_agc_vals), + rtl8188e_agc_vals, { 0 }, NULL } @@ -186,7 +186,7 @@ static const struct rtwn_agc_prog rtl8188eu_agc[] = { /* * RF initialization values. */ -static const uint8_t rtl8188eu_rf_regs[] = { +static const uint8_t rtl8188e_rf_regs[] = { 0x00, 0x08, 0x18, 0x19, 0x1e, 0x1f, 0x2f, 0x3f, 0x42, 0x57, 0x58, 0x67, 0x83, 0xb0, 0xb1, 0xb2, 0xb4, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbf, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, @@ -199,7 +199,7 @@ static const uint8_t rtl8188eu_rf_regs[] = { 0x1f, 0xfe, 0xfe, 0x1e, 0x1f, 0x00 }; -static const uint32_t rtl8188eu_rf_vals[] = { +static const uint32_t rtl8188e_rf_vals[] = { 0x30000, 0x84000, 0x00407, 0x00012, 0x80009, 0x00880, 0x1a060, 0x00000, 0x060c0, 0xd0000, 0xbe180, 0x01552, 0x00000, 0xff8fc, 0x54400, 0xccc19, 0x43003, 0x4953e, 0x1c718, 0x060ff, 0x80001, @@ -216,11 +216,11 @@ static const uint32_t rtl8188eu_rf_vals[] = { 0x0c350, 0x0c350, 0x00001, 0x80000, 0x33e60 }; -static const struct rtwn_rf_prog rtl8188eu_rf[] = { +static const struct rtwn_rf_prog rtl8188e_rf[] = { { - nitems(rtl8188eu_rf_regs), - rtl8188eu_rf_regs, - rtl8188eu_rf_vals, + nitems(rtl8188e_rf_regs), + rtl8188e_rf_regs, + rtl8188e_rf_vals, { 0 }, NULL }, diff --git a/freebsd/sys/dev/rtwn/rtl8188e/r88e_reg.h b/freebsd/sys/dev/rtwn/rtl8188e/r88e_reg.h index f6f26fa4..94b9a660 100644 --- a/freebsd/sys/dev/rtwn/rtl8188e/r88e_reg.h +++ b/freebsd/sys/dev/rtwn/rtl8188e/r88e_reg.h @@ -32,6 +32,7 @@ #define R88E_HISR 0x0b4 #define R88E_HIMRE 0x0b8 #define R88E_HISRE 0x0bc +#define R88E_XCK_OUT_CTRL 0x07c /* MAC General Configuration. */ #define R88E_32K_CTRL 0x194 #define R88E_HMEBOX_EXT(idx) (0x1f0 + (idx) * 4) @@ -45,16 +46,49 @@ /* Bits for R88E_HIMR. */ -#define R88E_HIMR_CPWM 0x00000100 -#define R88E_HIMR_CPWM2 0x00000200 -#define R88E_HIMR_TBDER 0x04000000 -#define R88E_HIMR_PSTIMEOUT 0x20000000 +#define R88E_HIMR_ROK 0x00000001 /* receive DMA OK */ +#define R88E_HIMR_RDU 0x00000002 /* Rx descriptor unavailable */ +#define R88E_HIMR_VODOK 0x00000004 /* AC_VO DMA OK */ +#define R88E_HIMR_VIDOK 0x00000008 /* AC_VI DMA OK */ +#define R88E_HIMR_BEDOK 0x00000010 /* AC_BE DMA OK */ +#define R88E_HIMR_BKDOK 0x00000020 /* AC_BK DMA OK */ +#define R88E_HIMR_MGNTDOK 0x00000040 /* management queue DMA OK */ +#define R88E_HIMR_HIGHDOK 0x00000080 /* high queue DMA OK */ +#define R88E_HIMR_CPWM 0x00000100 /* CPU power mode intr 1 */ +#define R88E_HIMR_CPWM2 0x00000200 /* CPU power mode intr 2 */ +#define R88E_HIMR_C2HCMD 0x00000400 /* C2H command interrupt */ +#define R88E_HIMR_HISR 0x00000800 /* (HISR & HIMR) != 0 */ +#define R88E_HIMR_ATIMEND 0x00001000 /* ATIM window end interrupt */ +#define R88E_HIMR_HSISR 0x00008000 /* (HSIMR & HSISR) != 0 */ +#define R88E_HIMR_BCNDERR 0x00010000 /* beacon queue DMA error */ +#define R88E_HIMR_BCNINT 0x00100000 /* beacon DMA interrupt 0 */ +#define R88E_HIMR_TSF32 0x01000000 /* TSF 32 bit interrupt */ +#define R88E_HIMR_TBDOK 0x02000000 /* beacon transmit OK */ +#define R88E_HIMR_TBDER 0x04000000 /* beacon transmit error */ +#define R88E_HIMR_GTIMER3 0x08000000 /* GTIMER3 interrupt */ +#define R88E_HIMR_GTIMER4 0x10000000 /* GTIMER4 interrupt */ +#define R88E_HIMR_PSTIMEOUT 0x20000000 /* powersave timeout */ +#define R88E_HIMR_TXRPT 0x40000000 /* Tx report interrupt */ /* Bits for R88E_HIMRE.*/ -#define R88E_HIMRE_RXFOVW 0x00000100 -#define R88E_HIMRE_TXFOVW 0x00000200 -#define R88E_HIMRE_RXERR 0x00000400 -#define R88E_HIMRE_TXERR 0x00000800 +#define R88E_HIMRE_RXFOVW 0x00000100 /* receive FIFO overflow */ +#define R88E_HIMRE_TXFOVW 0x00000200 /* transmit FIFO overflow */ +#define R88E_HIMRE_RXERR 0x00000400 /* receive error */ +#define R88E_HIMRE_TXERR 0x00000800 /* transmit error */ +#define R88E_HIMRE_BCNDOK1 0x00004000 /* beacon queue DMA OK (1) */ +#define R88E_HIMRE_BCNDOK2 0x00008000 /* beacon queue DMA OK (2) */ +#define R88E_HIMRE_BCNDOK3 0x00010000 /* beacon queue DMA OK (3) */ +#define R88E_HIMRE_BCNDOK4 0x00020000 /* beacon queue DMA OK (4) */ +#define R88E_HIMRE_BCNDOK5 0x00040000 /* beacon queue DMA OK (5) */ +#define R88E_HIMRE_BCNDOK6 0x00080000 /* beacon queue DMA OK (6) */ +#define R88E_HIMRE_BCNDOK7 0x00100000 /* beacon queue DMA OK (7) */ +#define R88E_HIMRE_BCNDMAINT1 0x00200000 /* beacon DMA interrupt 1 */ +#define R88E_HIMRE_BCNDMAINT2 0x00400000 /* beacon DMA interrupt 2 */ +#define R88E_HIMRE_BCNDMAINT3 0x00800000 /* beacon DMA interrupt 3 */ +#define R88E_HIMRE_BCNDMAINT4 0x01000000 /* beacon DMA interrupt 4 */ +#define R88E_HIMRE_BCNDMAINT5 0x02000000 /* beacon DMA interrupt 5 */ +#define R88E_HIMRE_BCNDMAINT6 0x04000000 /* beacon DMA interrupt 6 */ +#define R88E_HIMRE_BCNDMAINT7 0x08000000 /* beacon DMA interrupt 7 */ /* Bits for R88E_TX_RPT_CTRL. */ #define R88E_TX_RPT1_ENA 0x01 @@ -79,6 +113,7 @@ * RF (6052) registers. */ #define R88E_RF_T_METER 0x42 +#define R88E_RF_WE_LUT 0xef /* Bits for R92C_RF_CHNLBW. */ #define R88E_RF_CHNLBW_BW20 0x00c00 @@ -88,4 +123,7 @@ #define R88E_RF_T_METER_VAL_S 10 #define R88E_RF_T_METER_START 0x30000 +/* Bits for R88E_XCK_OUT_CTRL. */ +#define R88E_XCK_OUT_CTRL_EN 1 + #endif /* R88E_REG_H */ diff --git a/freebsd/sys/dev/rtwn/rtl8188e/r88e_rom.c b/freebsd/sys/dev/rtwn/rtl8188e/r88e_rom.c index e1337dba..3afa2910 100644 --- a/freebsd/sys/dev/rtwn/rtl8188e/r88e_rom.c +++ b/freebsd/sys/dev/rtwn/rtl8188e/r88e_rom.c @@ -83,5 +83,6 @@ r88e_parse_rom(struct rtwn_softc *sc, uint8_t *buf) __func__,rs->regulatory); sc->thermal_meter = rom->thermal_meter; - IEEE80211_ADDR_COPY(sc->sc_ic.ic_macaddr, rom->macaddr); + + rtwn_r92c_set_rom_opts(sc, buf); } diff --git a/freebsd/sys/dev/rtwn/rtl8188e/r88e_rom_image.h b/freebsd/sys/dev/rtwn/rtl8188e/r88e_rom_image.h index c80028e0..d5d97ffb 100644 --- a/freebsd/sys/dev/rtwn/rtl8188e/r88e_rom_image.h +++ b/freebsd/sys/dev/rtwn/rtl8188e/r88e_rom_image.h @@ -44,11 +44,24 @@ struct r88e_rom { uint8_t reserved4[3]; uint8_t rf_ant_opt; uint8_t reserved5[6]; - uint16_t vid; - uint16_t pid; - uint8_t usb_opt; - uint8_t reserved6[2]; - uint8_t macaddr[IEEE80211_ADDR_LEN]; + + union { + struct { + uint16_t vid; + uint16_t pid; + uint8_t usb_opt; + uint8_t reserved6[2]; + uint8_t macaddr[IEEE80211_ADDR_LEN]; + } __packed usb; + + struct { + uint8_t macaddr[IEEE80211_ADDR_LEN]; + uint16_t vid; + uint16_t pid; + uint8_t reserved6[3]; + } __packed pci; + } __packed diff_d0; + uint8_t reserved7[2]; uint8_t string[33]; /* "realtek 802.11n NIC" */ uint8_t reserved8[256]; diff --git a/freebsd/sys/dev/rtwn/rtl8188e/r88e_rx.c b/freebsd/sys/dev/rtwn/rtl8188e/r88e_rx.c index 53cc722f..eee2f63f 100644 --- a/freebsd/sys/dev/rtwn/rtl8188e/r88e_rx.c +++ b/freebsd/sys/dev/rtwn/rtl8188e/r88e_rx.c @@ -58,6 +58,25 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8188e/r88e_rx_desc.h> +int +r88e_classify_intr(struct rtwn_softc *sc, void *buf, int len) +{ + struct r92c_rx_stat *stat = buf; + int report_sel = MS(le32toh(stat->rxdw3), R88E_RXDW3_RPT); + + switch (report_sel) { + case R88E_RXDW3_RPT_RX: + return (RTWN_RX_DATA); + case R88E_RXDW3_RPT_TX1: /* per-packet Tx report */ + case R88E_RXDW3_RPT_TX2: /* periodical Tx report */ + return (RTWN_RX_TX_REPORT); + case R88E_RXDW3_RPT_HIS: + return (RTWN_RX_OTHER); + default: /* shut up the compiler */ + return (RTWN_RX_DATA); + } +} + void r88e_ratectl_tx_complete(struct rtwn_softc *sc, uint8_t *buf, int len) { diff --git a/freebsd/sys/dev/rtwn/rtl8188e/usb/r88eu.h b/freebsd/sys/dev/rtwn/rtl8188e/usb/r88eu.h index 85b637cb..e79b1387 100644 --- a/freebsd/sys/dev/rtwn/rtl8188e/usb/r88eu.h +++ b/freebsd/sys/dev/rtwn/rtl8188e/usb/r88eu.h @@ -25,15 +25,21 @@ /* + * Global definitions. + */ +#define R88EU_PUBQ_NPAGES 142 +#define R88EU_TX_PAGE_COUNT 169 + + +/* * Function declarations. */ /* r88eu_init.c */ +void r88eu_init_bb(struct rtwn_softc *); +int r88eu_power_on(struct rtwn_softc *); void r88eu_power_off(struct rtwn_softc *); void r88eu_init_intr(struct rtwn_softc *); void r88eu_init_rx_agg(struct rtwn_softc *); void r88eu_post_init(struct rtwn_softc *); -/* r88eu_rx.c */ -int r88eu_classify_intr(struct rtwn_softc *, void *, int); - #endif /* RTL8188EU_H */ diff --git a/freebsd/sys/dev/rtwn/rtl8188e/usb/r88eu_attach.c b/freebsd/sys/dev/rtwn/rtl8188e/usb/r88eu_attach.c index 73cc7856..6b153bcd 100644 --- a/freebsd/sys/dev/rtwn/rtl8188e/usb/r88eu_attach.c +++ b/freebsd/sys/dev/rtwn/rtl8188e/usb/r88eu_attach.c @@ -59,6 +59,7 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8192c/usb/r92cu_tx_desc.h> #include <dev/rtwn/rtl8188e/r88e_priv.h> +#include <dev/rtwn/rtl8188e/r88e_rom_image.h> /* for 'macaddr' field */ #include <dev/rtwn/rtl8188e/usb/r88eu.h> @@ -68,6 +69,14 @@ static struct rtwn_r88e_txpwr r88e_txpwr; void r88eu_attach(struct rtwn_usb_softc *); static void +r88eu_set_macaddr(struct rtwn_softc *sc, uint8_t *buf) +{ + struct r88e_rom *rom = (struct r88e_rom *)buf; + + IEEE80211_ADDR_COPY(sc->sc_ic.ic_macaddr, rom->diff_d0.usb.macaddr); +} + +static void r88e_postattach(struct rtwn_softc *sc) { struct r92c_softc *rs = sc->sc_priv; @@ -95,7 +104,7 @@ r88eu_attach_private(struct rtwn_softc *sc) rs->rs_tx_enable_ampdu = r88e_tx_enable_ampdu; rs->rs_tx_setup_hwseq = r88e_tx_setup_hwseq; rs->rs_tx_setup_macid = r88e_tx_setup_macid; - rs->rs_set_name = rtwn_nop_softc; /* not used */ + rs->rs_set_rom_opts = r88eu_set_macaddr; rs->rf_read_delay[0] = 10; rs->rf_read_delay[1] = 100; @@ -132,7 +141,7 @@ r88eu_attach(struct rtwn_usb_softc *uc) sc->sc_get_rx_stats = r88e_get_rx_stats; sc->sc_get_rssi_cck = r88e_get_rssi_cck; sc->sc_get_rssi_ofdm = r88e_get_rssi_ofdm; - sc->sc_classify_intr = r88eu_classify_intr; + sc->sc_classify_intr = r88e_classify_intr; sc->sc_handle_tx_report = r88e_ratectl_tx_complete; sc->sc_handle_c2h_report = r88e_handle_c2h_report; sc->sc_check_frame = rtwn_nop_int_softc_mbuf; @@ -142,7 +151,7 @@ r88eu_attach(struct rtwn_usb_softc *uc) sc->sc_efuse_postread = rtwn_nop_softc; sc->sc_parse_rom = r88e_parse_rom; sc->sc_set_led = r88e_set_led; - sc->sc_power_on = r88e_power_on; + sc->sc_power_on = r88eu_power_on; sc->sc_power_off = r88eu_power_off; #ifndef RTWN_WITHOUT_UCODE sc->sc_fw_reset = r88e_fw_reset; @@ -151,7 +160,7 @@ r88eu_attach(struct rtwn_usb_softc *uc) sc->sc_llt_init = r92c_llt_init; sc->sc_set_page_size = r92c_set_page_size; sc->sc_lc_calib = r92c_lc_calib; - sc->sc_iq_calib = r88e_iq_calib; /* XXX TODO */ + sc->sc_iq_calib = r88e_iq_calib; sc->sc_read_chipid_vendor = rtwn_nop_softc_uint32; sc->sc_adj_devcaps = r88eu_adj_devcaps; sc->sc_vap_preattach = rtwn_nop_softc_vap; @@ -174,29 +183,29 @@ r88eu_attach(struct rtwn_usb_softc *uc) sc->sc_init_ampdu = rtwn_nop_softc; sc->sc_init_intr = r88eu_init_intr; sc->sc_init_edca = r92c_init_edca; - sc->sc_init_bb = r88e_init_bb; + sc->sc_init_bb = r88eu_init_bb; sc->sc_init_rf = r92c_init_rf; sc->sc_init_antsel = rtwn_nop_softc; sc->sc_post_init = r88eu_post_init; sc->sc_init_bcnq1_boundary = rtwn_nop_int_softc; - sc->mac_prog = &rtl8188eu_mac[0]; - sc->mac_size = nitems(rtl8188eu_mac); - sc->bb_prog = &rtl8188eu_bb[0]; - sc->bb_size = nitems(rtl8188eu_bb); - sc->agc_prog = &rtl8188eu_agc[0]; - sc->agc_size = nitems(rtl8188eu_agc); - sc->rf_prog = &rtl8188eu_rf[0]; + sc->mac_prog = &rtl8188e_mac[0]; + sc->mac_size = nitems(rtl8188e_mac); + sc->bb_prog = &rtl8188e_bb[0]; + sc->bb_size = nitems(rtl8188e_bb); + sc->agc_prog = &rtl8188e_agc[0]; + sc->agc_size = nitems(rtl8188e_agc); + sc->rf_prog = &rtl8188e_rf[0]; sc->name = "RTL8188EU"; sc->fwname = "rtwn-rtl8188eufw"; sc->fwsig = 0x88e; - sc->page_count = R88E_TX_PAGE_COUNT; + sc->page_count = R88EU_TX_PAGE_COUNT; sc->pktbuf_count = R88E_TXPKTBUF_COUNT; sc->ackto = 0x40; - sc->npubqpages = R88E_PUBQ_NPAGES; + sc->npubqpages = R88EU_PUBQ_NPAGES; sc->page_size = R92C_TX_PAGE_SIZE; sc->txdesc_len = sizeof(struct r92cu_tx_desc); diff --git a/freebsd/sys/dev/rtwn/rtl8188e/usb/r88eu_init.c b/freebsd/sys/dev/rtwn/rtl8188e/usb/r88eu_init.c index 2c776671..bfe3681e 100644 --- a/freebsd/sys/dev/rtwn/rtl8188e/usb/r88eu_init.c +++ b/freebsd/sys/dev/rtwn/rtl8188e/usb/r88eu_init.c @@ -57,6 +57,87 @@ __FBSDID("$FreeBSD$"); void +r88eu_init_bb(struct rtwn_softc *sc) +{ + + /* Enable BB and RF. */ + rtwn_setbits_2(sc, R92C_SYS_FUNC_EN, 0, + R92C_SYS_FUNC_EN_BBRSTB | R92C_SYS_FUNC_EN_BB_GLB_RST | + R92C_SYS_FUNC_EN_DIO_RF); + + rtwn_write_1(sc, R92C_RF_CTRL, + R92C_RF_CTRL_EN | R92C_RF_CTRL_RSTB | R92C_RF_CTRL_SDMRSTB); + rtwn_write_1(sc, R92C_SYS_FUNC_EN, + R92C_SYS_FUNC_EN_USBA | R92C_SYS_FUNC_EN_USBD | + R92C_SYS_FUNC_EN_BB_GLB_RST | R92C_SYS_FUNC_EN_BBRSTB); + + r88e_init_bb_common(sc); +} + +int +r88eu_power_on(struct rtwn_softc *sc) +{ +#define RTWN_CHK(res) do { \ + if (res != 0) \ + return (EIO); \ +} while(0) + int ntries; + + /* Wait for power ready bit. */ + for (ntries = 0; ntries < 5000; ntries++) { + if (rtwn_read_4(sc, R92C_APS_FSMCO) & R92C_APS_FSMCO_SUS_HOST) + break; + rtwn_delay(sc, 10); + } + if (ntries == 5000) { + device_printf(sc->sc_dev, + "timeout waiting for chip power up\n"); + return (ETIMEDOUT); + } + + /* Reset BB. */ + RTWN_CHK(rtwn_setbits_1(sc, R92C_SYS_FUNC_EN, + R92C_SYS_FUNC_EN_BBRSTB | R92C_SYS_FUNC_EN_BB_GLB_RST, 0)); + + RTWN_CHK(rtwn_setbits_1(sc, R92C_AFE_XTAL_CTRL + 2, 0, 0x80)); + + /* Disable HWPDN. */ + RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, + R92C_APS_FSMCO_APDM_HPDN, 0, 1)); + + /* Disable WL suspend. */ + RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, + R92C_APS_FSMCO_AFSM_HSUS | R92C_APS_FSMCO_AFSM_PCIE, 0, 1)); + + RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, + 0, R92C_APS_FSMCO_APFM_ONMAC, 1)); + for (ntries = 0; ntries < 5000; ntries++) { + if (!(rtwn_read_2(sc, R92C_APS_FSMCO) & + R92C_APS_FSMCO_APFM_ONMAC)) + break; + rtwn_delay(sc, 10); + } + if (ntries == 5000) + return (ETIMEDOUT); + + /* Enable LDO normal mode. */ + RTWN_CHK(rtwn_setbits_1(sc, R92C_LPLDO_CTRL, + R92C_LPLDO_CTRL_SLEEP, 0)); + + /* Enable MAC DMA/WMAC/SCHEDULE/SEC blocks. */ + RTWN_CHK(rtwn_write_2(sc, R92C_CR, 0)); + RTWN_CHK(rtwn_setbits_2(sc, R92C_CR, 0, + R92C_CR_HCI_TXDMA_EN | R92C_CR_TXDMA_EN | + R92C_CR_HCI_RXDMA_EN | R92C_CR_RXDMA_EN | + R92C_CR_PROTOCOL_EN | R92C_CR_SCHEDULE_EN | + ((sc->sc_hwcrypto != RTWN_CRYPTO_SW) ? R92C_CR_ENSEC : 0) | + R92C_CR_CALTMR_EN)); + + return (0); +#undef RTWN_CHK +} + +void r88eu_power_off(struct rtwn_softc *sc) { uint8_t reg; diff --git a/freebsd/sys/dev/rtwn/rtl8192c/pci/r92ce.h b/freebsd/sys/dev/rtwn/rtl8192c/pci/r92ce.h index 93379f8b..5d13f160 100644 --- a/freebsd/sys/dev/rtwn/rtl8192c/pci/r92ce.h +++ b/freebsd/sys/dev/rtwn/rtl8192c/pci/r92ce.h @@ -60,7 +60,7 @@ void r92ce_post_init(struct rtwn_softc *); void r92ce_set_led(struct rtwn_softc *, int, int); /* r92ce_rx.c */ -int r92ce_classify_intr(struct rtwn_softc *, void *, int); +int r92ce_get_intr_status(struct rtwn_pci_softc *, int *); void r92ce_enable_intr(struct rtwn_pci_softc *); void r92ce_start_xfers(struct rtwn_softc *); diff --git a/freebsd/sys/dev/rtwn/rtl8192c/pci/r92ce_attach.c b/freebsd/sys/dev/rtwn/rtl8192c/pci/r92ce_attach.c index e43d3ac0..61791c41 100644 --- a/freebsd/sys/dev/rtwn/rtl8192c/pci/r92ce_attach.c +++ b/freebsd/sys/dev/rtwn/rtl8192c/pci/r92ce_attach.c @@ -94,7 +94,7 @@ r92ce_postattach(struct rtwn_softc *sc) } static void -r92ce_set_name(struct rtwn_softc *sc) +r92ce_set_name(struct rtwn_softc *sc, uint8_t *buf) { struct r92c_softc *rs = sc->sc_priv; @@ -119,7 +119,7 @@ r92ce_attach_private(struct rtwn_softc *sc) rs->rs_tx_enable_ampdu = r92c_tx_enable_ampdu; rs->rs_tx_setup_hwseq = r92c_tx_setup_hwseq; rs->rs_tx_setup_macid = r92c_tx_setup_macid; - rs->rs_set_name = r92ce_set_name; + rs->rs_set_rom_opts = r92ce_set_name; /* XXX TODO: test with net80211 ratectl! */ #ifndef RTWN_WITHOUT_UCODE @@ -157,6 +157,7 @@ r92ce_attach(struct rtwn_pci_softc *pc) pc->pc_tx_postsetup = r92ce_tx_postsetup; pc->pc_copy_tx_desc = r92ce_copy_tx_desc; pc->pc_enable_intr = r92ce_enable_intr; + pc->pc_get_intr_status = r92ce_get_intr_status; pc->pc_qmap = 0xf771; pc->tcr = @@ -177,7 +178,7 @@ r92ce_attach(struct rtwn_pci_softc *pc) sc->sc_get_rx_stats = r92c_get_rx_stats; sc->sc_get_rssi_cck = r92c_get_rssi_cck; sc->sc_get_rssi_ofdm = r92c_get_rssi_ofdm; - sc->sc_classify_intr = r92ce_classify_intr; + sc->sc_classify_intr = r92c_classify_intr; sc->sc_handle_tx_report = rtwn_nop_softc_uint8_int; sc->sc_handle_c2h_report = rtwn_nop_softc_uint8_int; sc->sc_check_frame = rtwn_nop_int_softc_mbuf; diff --git a/freebsd/sys/dev/rtwn/rtl8192c/pci/r92ce_calib.c b/freebsd/sys/dev/rtwn/rtl8192c/pci/r92ce_calib.c index 070f6e1d..f1cd42e8 100644 --- a/freebsd/sys/dev/rtwn/rtl8192c/pci/r92ce_calib.c +++ b/freebsd/sys/dev/rtwn/rtl8192c/pci/r92ce_calib.c @@ -77,55 +77,58 @@ r92ce_iq_calib_chain(struct rtwn_softc *sc, int chain, uint16_t tx[2], uint16_t rx[2]) { uint32_t status; - int offset = chain * 0x20; if (chain == 0) { /* IQ calibration for chain 0. */ /* IQ calibration settings for chain 0. */ - rtwn_bb_write(sc, 0xe30, 0x10008c1f); - rtwn_bb_write(sc, 0xe34, 0x10008c1f); - rtwn_bb_write(sc, 0xe38, 0x82140102); + rtwn_bb_write(sc, R92C_TX_IQK_TONE(0), 0x10008c1f); + rtwn_bb_write(sc, R92C_RX_IQK_TONE(0), 0x10008c1f); + rtwn_bb_write(sc, R92C_TX_IQK_PI(0), 0x82140102); if (sc->ntxchains > 1) { - rtwn_bb_write(sc, 0xe3c, 0x28160202); /* 2T */ + rtwn_bb_write(sc, R92C_RX_IQK_PI(0), 0x28160202); /* IQ calibration settings for chain 1. */ - rtwn_bb_write(sc, 0xe50, 0x10008c22); - rtwn_bb_write(sc, 0xe54, 0x10008c22); - rtwn_bb_write(sc, 0xe58, 0x82140102); - rtwn_bb_write(sc, 0xe5c, 0x28160202); + rtwn_bb_write(sc, R92C_TX_IQK_TONE(1), 0x10008c22); + rtwn_bb_write(sc, R92C_RX_IQK_TONE(1), 0x10008c22); + rtwn_bb_write(sc, R92C_TX_IQK_PI(1), 0x82140102); + rtwn_bb_write(sc, R92C_RX_IQK_PI(1), 0x28160202); } else - rtwn_bb_write(sc, 0xe3c, 0x28160502); /* 1T */ + rtwn_bb_write(sc, R92C_RX_IQK_PI(0), 0x28160502); /* LO calibration settings. */ - rtwn_bb_write(sc, 0xe4c, 0x001028d1); + rtwn_bb_write(sc, R92C_IQK_AGC_RSP, 0x001028d1); /* We're doing LO and IQ calibration in one shot. */ - rtwn_bb_write(sc, 0xe48, 0xf9000000); - rtwn_bb_write(sc, 0xe48, 0xf8000000); + rtwn_bb_write(sc, R92C_IQK_AGC_PTS, 0xf9000000); + rtwn_bb_write(sc, R92C_IQK_AGC_PTS, 0xf8000000); } else { /* IQ calibration for chain 1. */ /* We're doing LO and IQ calibration in one shot. */ - rtwn_bb_write(sc, 0xe60, 0x00000002); - rtwn_bb_write(sc, 0xe60, 0x00000000); + rtwn_bb_write(sc, R92C_IQK_AGC_CONT, 2); + rtwn_bb_write(sc, R92C_IQK_AGC_CONT, 0); } /* Give LO and IQ calibrations the time to complete. */ rtwn_delay(sc, 1000); /* Read IQ calibration status. */ - status = rtwn_bb_read(sc, 0xeac); + status = rtwn_bb_read(sc, R92C_RX_POWER_IQK_AFTER(0)); if (status & (1 << (28 + chain * 3))) return (0); /* Tx failed. */ /* Read Tx IQ calibration results. */ - tx[0] = (rtwn_bb_read(sc, 0xe94 + offset) >> 16) & 0x3ff; - tx[1] = (rtwn_bb_read(sc, 0xe9c + offset) >> 16) & 0x3ff; + tx[0] = MS(rtwn_bb_read(sc, R92C_TX_POWER_IQK_BEFORE(chain)), + R92C_POWER_IQK_RESULT); + tx[1] = MS(rtwn_bb_read(sc, R92C_TX_POWER_IQK_AFTER(chain)), + R92C_POWER_IQK_RESULT); if (tx[0] == 0x142 || tx[1] == 0x042) return (0); /* Tx failed. */ if (status & (1 << (27 + chain * 3))) return (1); /* Rx failed. */ /* Read Rx IQ calibration results. */ - rx[0] = (rtwn_bb_read(sc, 0xea4 + offset) >> 16) & 0x3ff; - rx[1] = (rtwn_bb_read(sc, 0xeac + offset) >> 16) & 0x3ff; + rx[0] = MS(rtwn_bb_read(sc, R92C_RX_POWER_IQK_BEFORE(chain)), + R92C_POWER_IQK_RESULT); + rx[1] = MS(rtwn_bb_read(sc, R92C_RX_POWER_IQK_AFTER(chain)), + R92C_POWER_IQK_RESULT); if (rx[0] == 0x132 || rx[1] == 0x036) return (1); /* Rx failed. */ @@ -202,18 +205,18 @@ r92ce_iq_calib_run(struct rtwn_softc *sc, int n, uint16_t tx[2][2], if (sc->ntxchains > 1) rtwn_bb_write(sc, 0x0b6c, 0x00080000); - rtwn_bb_write(sc, 0x0e28, 0x80800000); - rtwn_bb_write(sc, 0x0e40, 0x01007c00); - rtwn_bb_write(sc, 0x0e44, 0x01004800); + rtwn_bb_write(sc, R92C_FPGA0_IQK, 0x80800000); + rtwn_bb_write(sc, R92C_TX_IQK, 0x01007c00); + rtwn_bb_write(sc, R92C_RX_IQK, 0x01004800); rtwn_bb_write(sc, 0x0b68, 0x00080000); for (chain = 0; chain < sc->ntxchains; chain++) { if (chain > 0) { /* Put chain 0 on standby. */ - rtwn_bb_write(sc, 0x0e28, 0x00); + rtwn_bb_write(sc, R92C_FPGA0_IQK, 0); rtwn_bb_write(sc, R92C_LSSI_PARAM(0), 0x00010000); - rtwn_bb_write(sc, 0x0e28, 0x80800000); + rtwn_bb_write(sc, R92C_FPGA0_IQK, 0x80800000); /* Enable chain 1. */ for (i = 0; i < nitems(reg_adda); i++) @@ -259,7 +262,7 @@ r92ce_iq_calib_run(struct rtwn_softc *sc, int n, uint16_t tx[2][2], vals->fpga0_rfifacesw1); rtwn_bb_write(sc, R92C_OFDM0_TRMUXPAR, vals->ofdm0_trmuxpar); - rtwn_bb_write(sc, 0x0e28, 0x00); + rtwn_bb_write(sc, R92C_FPGA0_IQK, 0); rtwn_bb_write(sc, R92C_LSSI_PARAM(0), 0x00032ed3); if (sc->ntxchains > 1) rtwn_bb_write(sc, R92C_LSSI_PARAM(1), 0x00032ed3); diff --git a/freebsd/sys/dev/rtwn/rtl8192c/pci/r92ce_rx.c b/freebsd/sys/dev/rtwn/rtl8192c/pci/r92ce_rx.c index 203b0bf8..0f65d1bf 100644 --- a/freebsd/sys/dev/rtwn/rtl8192c/pci/r92ce_rx.c +++ b/freebsd/sys/dev/rtwn/rtl8192c/pci/r92ce_rx.c @@ -60,10 +60,10 @@ __FBSDID("$FreeBSD$"); int -r92ce_classify_intr(struct rtwn_softc *sc, void *arg, int len __unused) +r92ce_get_intr_status(struct rtwn_pci_softc *pc, int *rings) { + struct rtwn_softc *sc = &pc->pc_sc; uint32_t status; - int *rings = arg; int ret; *rings = 0; diff --git a/freebsd/sys/dev/rtwn/rtl8192c/r92c.h b/freebsd/sys/dev/rtwn/rtl8192c/r92c.h index d8f7afc8..f215e34f 100644 --- a/freebsd/sys/dev/rtwn/rtl8192c/r92c.h +++ b/freebsd/sys/dev/rtwn/rtl8192c/r92c.h @@ -102,6 +102,7 @@ void r92c_efuse_postread(struct rtwn_softc *); void r92c_parse_rom(struct rtwn_softc *, uint8_t *); /* r92c_rx.c */ +int r92c_classify_intr(struct rtwn_softc *, void *, int); int8_t r92c_get_rssi_cck(struct rtwn_softc *, void *); int8_t r92c_get_rssi_ofdm(struct rtwn_softc *, void *); uint8_t r92c_rx_radiotap_flags(const void *); diff --git a/freebsd/sys/dev/rtwn/rtl8192c/r92c_calib.c b/freebsd/sys/dev/rtwn/rtl8192c/r92c_calib.c index 6c18a606..ebb4f5cf 100644 --- a/freebsd/sys/dev/rtwn/rtl8192c/r92c_calib.c +++ b/freebsd/sys/dev/rtwn/rtl8192c/r92c_calib.c @@ -48,16 +48,366 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/if_rtwnreg.h> #include <dev/rtwn/if_rtwnvar.h> +#include <dev/rtwn/if_rtwn_debug.h> #include <dev/rtwn/rtl8192c/r92c.h> #include <dev/rtwn/rtl8192c/r92c_reg.h> +/* Registers to save and restore during IQ calibration. */ +struct r92c_iq_cal_reg_vals { + uint32_t adda[16]; + uint8_t txpause; + uint8_t bcn_ctrl[2]; + uint32_t gpio_muxcfg; + uint32_t cck0_afesetting; + uint32_t ofdm0_trxpathena; + uint32_t ofdm0_trmuxpar; + uint32_t fpga0_rfifacesw0; + uint32_t fpga0_rfifacesw1; + uint32_t fpga0_rfifaceoe0; + uint32_t fpga0_rfifaceoe1; + uint32_t config_ant0; + uint32_t config_ant1; +}; + +/* XXX TODO: merge */ +static int +r92c_iq_calib_chain(struct rtwn_softc *sc, int chain, uint16_t tx[2], + uint16_t rx[2]) +{ + uint32_t status; + + if (chain == 0) { /* IQ calibration for chain 0. */ + /* IQ calibration settings for chain 0. */ + rtwn_bb_write(sc, R92C_TX_IQK_TONE(0), 0x10008c1f); + rtwn_bb_write(sc, R92C_RX_IQK_TONE(0), 0x10008c1f); + rtwn_bb_write(sc, R92C_TX_IQK_PI(0), 0x82140102); + + if (sc->ntxchains > 1) { + rtwn_bb_write(sc, R92C_RX_IQK_PI(0), 0x28160202); + /* IQ calibration settings for chain 1. */ + rtwn_bb_write(sc, R92C_TX_IQK_TONE(1), 0x10008c22); + rtwn_bb_write(sc, R92C_RX_IQK_TONE(1), 0x10008c22); + rtwn_bb_write(sc, R92C_TX_IQK_PI(1), 0x82140102); + rtwn_bb_write(sc, R92C_RX_IQK_PI(1), 0x28160202); + } else + rtwn_bb_write(sc, R92C_RX_IQK_PI(0), 0x28160502); + + /* LO calibration settings. */ + rtwn_bb_write(sc, R92C_IQK_AGC_RSP, 0x001028d1); + /* We're doing LO and IQ calibration in one shot. */ + rtwn_bb_write(sc, R92C_IQK_AGC_PTS, 0xf9000000); + rtwn_bb_write(sc, R92C_IQK_AGC_PTS, 0xf8000000); + + } else { /* IQ calibration for chain 1. */ + /* We're doing LO and IQ calibration in one shot. */ + rtwn_bb_write(sc, R92C_IQK_AGC_CONT, 2); + rtwn_bb_write(sc, R92C_IQK_AGC_CONT, 0); + } + + /* Give LO and IQ calibrations the time to complete. */ + rtwn_delay(sc, 10000); + + /* Read IQ calibration status. */ + status = rtwn_bb_read(sc, R92C_RX_POWER_IQK_AFTER(0)); + + if (status & (1 << (28 + chain * 3))) + return (0); /* Tx failed. */ + /* Read Tx IQ calibration results. */ + tx[0] = MS(rtwn_bb_read(sc, R92C_TX_POWER_IQK_BEFORE(chain)), + R92C_POWER_IQK_RESULT); + tx[1] = MS(rtwn_bb_read(sc, R92C_TX_POWER_IQK_AFTER(chain)), + R92C_POWER_IQK_RESULT); + if (tx[0] == 0x142 || tx[1] == 0x042) + return (0); /* Tx failed. */ + + if (status & (1 << (27 + chain * 3))) + return (1); /* Rx failed. */ + /* Read Rx IQ calibration results. */ + rx[0] = MS(rtwn_bb_read(sc, R92C_RX_POWER_IQK_BEFORE(chain)), + R92C_POWER_IQK_RESULT); + rx[1] = MS(rtwn_bb_read(sc, R92C_RX_POWER_IQK_AFTER(chain)), + R92C_POWER_IQK_RESULT); + if (rx[0] == 0x132 || rx[1] == 0x036) + return (1); /* Rx failed. */ + + return (3); /* Both Tx and Rx succeeded. */ +} + +static void +r92c_iq_calib_run(struct rtwn_softc *sc, int n, uint16_t tx[2][2], + uint16_t rx[2][2], struct r92c_iq_cal_reg_vals *vals) +{ + /* Registers to save and restore during IQ calibration. */ + static const uint16_t reg_adda[16] = { + 0x85c, 0xe6c, 0xe70, 0xe74, + 0xe78, 0xe7c, 0xe80, 0xe84, + 0xe88, 0xe8c, 0xed0, 0xed4, + 0xed8, 0xedc, 0xee0, 0xeec + }; + int i, chain; + uint32_t hssi_param1; + + if (n == 0) { + for (i = 0; i < nitems(reg_adda); i++) + vals->adda[i] = rtwn_bb_read(sc, reg_adda[i]); + + vals->txpause = rtwn_read_1(sc, R92C_TXPAUSE); + vals->bcn_ctrl[0] = rtwn_read_1(sc, R92C_BCN_CTRL(0)); + vals->bcn_ctrl[1] = rtwn_read_1(sc, R92C_BCN_CTRL(1)); + vals->gpio_muxcfg = rtwn_read_4(sc, R92C_GPIO_MUXCFG); + } + + if (sc->ntxchains == 1) { + rtwn_bb_write(sc, reg_adda[0], 0x0b1b25a0); + for (i = 1; i < nitems(reg_adda); i++) + rtwn_bb_write(sc, reg_adda[i], 0x0bdb25a0); + } else { + for (i = 0; i < nitems(reg_adda); i++) + rtwn_bb_write(sc, reg_adda[i], 0x04db25a4); + } + + hssi_param1 = rtwn_bb_read(sc, R92C_HSSI_PARAM1(0)); + if (!(hssi_param1 & R92C_HSSI_PARAM1_PI)) { + rtwn_bb_write(sc, R92C_HSSI_PARAM1(0), + hssi_param1 | R92C_HSSI_PARAM1_PI); + rtwn_bb_write(sc, R92C_HSSI_PARAM1(1), + hssi_param1 | R92C_HSSI_PARAM1_PI); + } + + if (n == 0) { + vals->cck0_afesetting = rtwn_bb_read(sc, R92C_CCK0_AFESETTING); + vals->ofdm0_trxpathena = + rtwn_bb_read(sc, R92C_OFDM0_TRXPATHENA); + vals->ofdm0_trmuxpar = rtwn_bb_read(sc, R92C_OFDM0_TRMUXPAR); + vals->fpga0_rfifacesw0 = + rtwn_bb_read(sc, R92C_FPGA0_RFIFACESW(0)); + vals->fpga0_rfifacesw1 = + rtwn_bb_read(sc, R92C_FPGA0_RFIFACESW(1)); + vals->fpga0_rfifaceoe0 = + rtwn_bb_read(sc, R92C_FPGA0_RFIFACEOE(0)); + vals->fpga0_rfifaceoe1 = + rtwn_bb_read(sc, R92C_FPGA0_RFIFACEOE(1)); + vals->config_ant0 = rtwn_bb_read(sc, R92C_CONFIG_ANT(0)); + vals->config_ant1 = rtwn_bb_read(sc, R92C_CONFIG_ANT(1)); + } + + rtwn_bb_setbits(sc, R92C_CCK0_AFESETTING, 0, 0x0f000000); + rtwn_bb_write(sc, R92C_OFDM0_TRXPATHENA, 0x03a05600); + rtwn_bb_write(sc, R92C_OFDM0_TRMUXPAR, 0x000800e4); + rtwn_bb_write(sc, R92C_FPGA0_RFIFACESW(1), 0x22204000); + rtwn_bb_setbits(sc, R92C_FPGA0_RFIFACESW(0), 0, 0x04000400); + rtwn_bb_setbits(sc, R92C_FPGA0_RFIFACEOE(0), 0x400, 0); + rtwn_bb_setbits(sc, R92C_FPGA0_RFIFACEOE(1), 0x400, 0); + + if (sc->ntxchains > 1) { + rtwn_bb_write(sc, R92C_LSSI_PARAM(0), 0x00010000); + rtwn_bb_write(sc, R92C_LSSI_PARAM(1), 0x00010000); + } + + rtwn_write_1(sc, R92C_TXPAUSE, + R92C_TX_QUEUE_AC | R92C_TX_QUEUE_MGT | R92C_TX_QUEUE_HIGH); + rtwn_write_1(sc, R92C_BCN_CTRL(0), + vals->bcn_ctrl[0] & ~R92C_BCN_CTRL_EN_BCN); + rtwn_write_1(sc, R92C_BCN_CTRL(1), + vals->bcn_ctrl[1] & ~R92C_BCN_CTRL_EN_BCN); + rtwn_write_1(sc, R92C_GPIO_MUXCFG, + vals->gpio_muxcfg & ~R92C_GPIO_MUXCFG_ENBT); + + rtwn_bb_write(sc, R92C_CONFIG_ANT(0), 0x00080000); + if (sc->ntxchains > 1) + rtwn_bb_write(sc, R92C_CONFIG_ANT(1), 0x00080000); + + rtwn_bb_write(sc, R92C_FPGA0_IQK, 0x80800000); + rtwn_bb_write(sc, R92C_TX_IQK, 0x01007c00); + rtwn_bb_write(sc, R92C_RX_IQK, 0x01004800); + + for (chain = 0; chain < sc->ntxchains; chain++) { + if (chain > 0) { + /* Put chain 0 on standby. */ + rtwn_bb_write(sc, R92C_FPGA0_IQK, 0); + rtwn_bb_write(sc, R92C_LSSI_PARAM(0), 0x00010000); + rtwn_bb_write(sc, R92C_FPGA0_IQK, 0x80800000); + + /* Enable chain 1. */ + for (i = 0; i < nitems(reg_adda); i++) + rtwn_bb_write(sc, reg_adda[i], 0x0b1b25a4); + } + + /* Run IQ calibration twice. */ + for (i = 0; i < 2; i++) { + int ret; + + ret = r92c_iq_calib_chain(sc, chain, + tx[chain], rx[chain]); + if (ret == 0) { + RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB, + "%s: chain %d: Tx failed.\n", + __func__, chain); + tx[chain][0] = 0xff; + tx[chain][1] = 0xff; + rx[chain][0] = 0xff; + rx[chain][1] = 0xff; + } else if (ret == 1) { + RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB, + "%s: chain %d: Rx failed.\n", + __func__, chain); + rx[chain][0] = 0xff; + rx[chain][1] = 0xff; + } else if (ret == 3) { + RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB, + "%s: chain %d: Both Tx and Rx " + "succeeded.\n", __func__, chain); + } + } + + RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB, + "%s: results for run %d chain %d: tx[0] 0x%x, " + "tx[1] 0x%x, rx[0] 0x%x, rx[1] 0x%x\n", __func__, n, chain, + tx[chain][0], tx[chain][1], rx[chain][0], rx[chain][1]); + } + + rtwn_bb_write(sc, R92C_CCK0_AFESETTING, vals->cck0_afesetting); + rtwn_bb_write(sc, R92C_OFDM0_TRXPATHENA, vals->ofdm0_trxpathena); + rtwn_bb_write(sc, R92C_FPGA0_RFIFACESW(0), vals->fpga0_rfifacesw0); + rtwn_bb_write(sc, R92C_FPGA0_RFIFACESW(1), vals->fpga0_rfifacesw1); + rtwn_bb_write(sc, R92C_OFDM0_TRMUXPAR, vals->ofdm0_trmuxpar); + rtwn_bb_write(sc, R92C_FPGA0_RFIFACEOE(0), vals->fpga0_rfifaceoe0); + rtwn_bb_write(sc, R92C_FPGA0_RFIFACEOE(1), vals->fpga0_rfifaceoe1); + rtwn_bb_write(sc, R92C_CONFIG_ANT(0), vals->config_ant0); + rtwn_bb_write(sc, R92C_CONFIG_ANT(1), vals->config_ant1); + + rtwn_bb_write(sc, R92C_FPGA0_IQK, 0); + rtwn_bb_write(sc, R92C_LSSI_PARAM(0), 0x00032ed3); + if (sc->ntxchains > 1) + rtwn_bb_write(sc, R92C_LSSI_PARAM(1), 0x00032ed3); + + if (n != 0) { + if (!(hssi_param1 & R92C_HSSI_PARAM1_PI)) { + rtwn_bb_write(sc, R92C_HSSI_PARAM1(0), hssi_param1); + rtwn_bb_write(sc, R92C_HSSI_PARAM1(1), hssi_param1); + } + + for (i = 0; i < nitems(reg_adda); i++) + rtwn_bb_write(sc, reg_adda[i], vals->adda[i]); + + rtwn_write_1(sc, R92C_TXPAUSE, vals->txpause); + rtwn_write_1(sc, R92C_BCN_CTRL(0), vals->bcn_ctrl[0]); + rtwn_write_1(sc, R92C_BCN_CTRL(1), vals->bcn_ctrl[1]); + rtwn_write_4(sc, R92C_GPIO_MUXCFG, vals->gpio_muxcfg); + + rtwn_bb_write(sc, R92C_TX_IQK_TONE(0), 0x01008c00); + rtwn_bb_write(sc, R92C_RX_IQK_TONE(0), 0x01008c00); + } +} + +#define RTWN_IQ_CAL_MAX_TOLERANCE 5 +static int +r92c_iq_calib_compare_results(struct rtwn_softc *sc, uint16_t tx1[2][2], + uint16_t rx1[2][2], uint16_t tx2[2][2], uint16_t rx2[2][2]) +{ + int chain, i, tx_ok[2], rx_ok[2]; + + tx_ok[0] = tx_ok[1] = rx_ok[0] = rx_ok[1] = 0; + for (chain = 0; chain < sc->ntxchains; chain++) { + for (i = 0; i < 2; i++) { + if (tx1[chain][i] == 0xff || tx2[chain][i] == 0xff || + rx1[chain][i] == 0xff || rx2[chain][i] == 0xff) + continue; + + tx_ok[chain] = (abs(tx1[chain][i] - tx2[chain][i]) <= + RTWN_IQ_CAL_MAX_TOLERANCE); + + rx_ok[chain] = (abs(rx1[chain][i] - rx2[chain][i]) <= + RTWN_IQ_CAL_MAX_TOLERANCE); + } + } + + if (sc->ntxchains > 1) + return (tx_ok[0] && tx_ok[1] && rx_ok[0] && rx_ok[1]); + else + return (tx_ok[0] && rx_ok[0]); +} +#undef RTWN_IQ_CAL_MAX_TOLERANCE + +static void +r92c_iq_calib_write_results(struct rtwn_softc *sc, uint16_t tx[2], + uint16_t rx[2], int chain) +{ + uint32_t reg, val, x; + long y, tx_c; + + if (tx[0] == 0xff || tx[1] == 0xff) + return; + + reg = rtwn_bb_read(sc, R92C_OFDM0_TXIQIMBALANCE(chain)); + val = ((reg >> 22) & 0x3ff); + x = tx[0]; + if (x & 0x00000200) + x |= 0xfffffc00; + reg = (((x * val) >> 8) & 0x3ff); + rtwn_bb_setbits(sc, R92C_OFDM0_TXIQIMBALANCE(chain), 0x3ff, reg); + rtwn_bb_setbits(sc, R92C_OFDM0_ECCATHRESHOLD, 0x80000000, + ((x * val) & 0x80) << 24); + + y = tx[1]; + if (y & 0x00000200) + y |= 0xfffffc00; + tx_c = (y * val) >> 8; + rtwn_bb_setbits(sc, R92C_OFDM0_TXAFE(chain), 0xf0000000, + (tx_c & 0x3c0) << 22); + rtwn_bb_setbits(sc, R92C_OFDM0_TXIQIMBALANCE(chain), 0x003f0000, + (tx_c & 0x3f) << 16); + rtwn_bb_setbits(sc, R92C_OFDM0_ECCATHRESHOLD, 0x20000000, + ((y * val) & 0x80) << 22); + + if (rx[0] == 0xff || rx[1] == 0xff) + return; + + rtwn_bb_setbits(sc, R92C_OFDM0_RXIQIMBALANCE(chain), 0x3ff, + rx[0] & 0x3ff); + rtwn_bb_setbits(sc, R92C_OFDM0_RXIQIMBALANCE(chain), 0xfc00, + (rx[1] & 0x3f) << 10); + + if (chain == 0) { + rtwn_bb_setbits(sc, R92C_OFDM0_RXIQEXTANTA, 0xf0000000, + (rx[1] & 0x3c0) << 22); + } else { + rtwn_bb_setbits(sc, R92C_OFDM0_AGCRSSITABLE, 0xf000, + (rx[1] & 0x3c0) << 6); + } +} + +#define RTWN_IQ_CAL_NRUN 3 void r92c_iq_calib(struct rtwn_softc *sc) { - /* XXX TODO */ + struct r92c_iq_cal_reg_vals vals; + uint16_t tx[RTWN_IQ_CAL_NRUN][2][2], rx[RTWN_IQ_CAL_NRUN][2][2]; + int n, valid; + + valid = 0; + for (n = 0; n < RTWN_IQ_CAL_NRUN; n++) { + r92c_iq_calib_run(sc, n, tx[n], rx[n], &vals); + + if (n == 0) + continue; + + /* Valid results remain stable after consecutive runs. */ + valid = r92c_iq_calib_compare_results(sc, tx[n - 1], + rx[n - 1], tx[n], rx[n]); + if (valid) + break; + } + + if (valid) { + r92c_iq_calib_write_results(sc, tx[n][0], rx[n][0], 0); + if (sc->ntxchains > 1) + r92c_iq_calib_write_results(sc, tx[n][1], rx[n][1], 1); + } } +#undef RTWN_IQ_CAL_NRUN void r92c_lc_calib(struct rtwn_softc *sc) diff --git a/freebsd/sys/dev/rtwn/rtl8192c/r92c_init.c b/freebsd/sys/dev/rtwn/rtl8192c/r92c_init.c index 199a419f..8cd55fbf 100644 --- a/freebsd/sys/dev/rtwn/rtl8192c/r92c_init.c +++ b/freebsd/sys/dev/rtwn/rtl8192c/r92c_init.c @@ -324,6 +324,7 @@ r92c_init_antsel(struct rtwn_softc *sc) rtwn_bb_setbits(sc, R92C_FPGA0_RFPARAM(0), 0, 0x2000); reg = rtwn_bb_read(sc, R92C_FPGA0_RFIFACEOE(0)); sc->sc_ant = MS(reg, R92C_FPGA0_RFIFACEOE0_ANT); /* XXX */ + rtwn_setbits_1(sc, R92C_LEDCFG2, 0x80, 0); } void diff --git a/freebsd/sys/dev/rtwn/rtl8192c/r92c_reg.h b/freebsd/sys/dev/rtwn/rtl8192c/r92c_reg.h index 34a4b80c..c3def33e 100644 --- a/freebsd/sys/dev/rtwn/rtl8192c/r92c_reg.h +++ b/freebsd/sys/dev/rtwn/rtl8192c/r92c_reg.h @@ -66,6 +66,7 @@ #define R92C_HSIMR 0x058 #define R92C_HSISR 0x05c #define R92C_MULTI_FUNC_CTRL 0x068 +#define R92C_AFE_XTAL_CTRL_EXT 0x078 #define R92C_LDO_SWR_CTRL 0x07c #define R92C_MCUFWDL 0x080 #define R92C_HMEBOX_EXT(idx) (0x088 + (idx) * 2) @@ -147,6 +148,7 @@ #define R92C_RD_RESP_PKT_TH 0x463 #define R92C_INIRTS_RATE_SEL 0x480 #define R92C_INIDATA_RATE_SEL(macid) (0x484 + (macid)) +#define R92C_POWER_STATUS 0x4a4 #define R92C_QUEUE_CTRL 0x4c6 #define R92C_MAX_AGGR_NUM 0x4ca #define R92C_BAR_MODE_CTRL 0x4cc @@ -347,6 +349,7 @@ /* Bits for R92C_GPIO_MUXCFG. */ #define R92C_GPIO_MUXCFG_ENBT 0x0020 +#define R92C_GPIO_MUXCFG_ENSIC 0x1000 /* Bits for R92C_LEDCFG0. */ #define R92C_LEDCFG0_DIS 0x08 @@ -691,6 +694,7 @@ #define R92C_FPGA1_TXINFO 0x90c #define R92C_CCK0_SYSTEM 0xa00 #define R92C_CCK0_AFESETTING 0xa04 +#define R92C_CONFIG_ANT(chain) (0xb68 + (chain) * 4) #define R92C_OFDM0_TRXPATHENA 0xc04 #define R92C_OFDM0_TRMUXPAR 0xc08 #define R92C_OFDM0_RXIQIMBALANCE(chain) (0xc14 + (chain) * 8) @@ -703,6 +707,20 @@ #define R92C_OFDM0_RXIQEXTANTA 0xca0 #define R92C_OFDM0_TXPSEUDONOISEWGT 0xce4 #define R92C_OFDM1_LSTF 0xd00 +#define R92C_FPGA0_IQK 0xe28 +#define R92C_TX_IQK_TONE(chain) (0xe30 + (chain) * 32) +#define R92C_RX_IQK_TONE(chain) (0xe34 + (chain) * 32) +#define R92C_TX_IQK_PI(chain) (0xe38 + (chain) * 32) +#define R92C_RX_IQK_PI(chain) (0xe3c + (chain) * 32) +#define R92C_TX_IQK 0xe40 +#define R92C_RX_IQK 0xe44 +#define R92C_IQK_AGC_PTS 0xe48 +#define R92C_IQK_AGC_RSP 0xe4c +#define R92C_IQK_AGC_CONT 0xe60 +#define R92C_TX_POWER_IQK_BEFORE(chain) (0xe94 + (chain) * 32) +#define R92C_TX_POWER_IQK_AFTER(chain) (0xe9c + (chain) * 32) +#define R92C_RX_POWER_IQK_BEFORE(chain) (0xea4 + (chain) * 32) +#define R92C_RX_POWER_IQK_AFTER(chain) (0xeac + (chain) * 32) /* Bits for R92C_FPGA[01]_RFMOD. */ #define R92C_RFMOD_40MHZ 0x00000001 @@ -828,6 +846,10 @@ #define R92C_OFDM0_AGCCORE1_GAIN_M 0x0000007f #define R92C_OFDM0_AGCCORE1_GAIN_S 0 +/* Bits for R92C_[RT]X_POWER_IQK*. */ +#define R92C_POWER_IQK_RESULT_S 16 +#define R92C_POWER_IQK_RESULT_M 0x03ff0000 + /* * RF (6052) registers. diff --git a/freebsd/sys/dev/rtwn/rtl8192c/r92c_rom.c b/freebsd/sys/dev/rtwn/rtl8192c/r92c_rom.c index 1eb5ca12..bc355e30 100644 --- a/freebsd/sys/dev/rtwn/rtl8192c/r92c_rom.c +++ b/freebsd/sys/dev/rtwn/rtl8192c/r92c_rom.c @@ -98,7 +98,7 @@ r92c_parse_rom(struct rtwn_softc *sc, uint8_t *buf) __func__, rs->regulatory); /* Need to be set before postinit() (but after preinit()). */ - rtwn_r92c_set_name(sc); + rtwn_r92c_set_rom_opts(sc, buf); r92c_set_chains(sc); for (j = 0; j < R92C_GROUP_2G; j++) { diff --git a/freebsd/sys/dev/rtwn/rtl8192c/r92c_rx.c b/freebsd/sys/dev/rtwn/rtl8192c/r92c_rx.c index c98a0203..cbc8eb56 100644 --- a/freebsd/sys/dev/rtwn/rtl8192c/r92c_rx.c +++ b/freebsd/sys/dev/rtwn/rtl8192c/r92c_rx.c @@ -54,6 +54,13 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8192c/r92c_rx_desc.h> +int +r92c_classify_intr(struct rtwn_softc *sc, void *buf, int len) +{ + /* NB: reports are fetched from C2H_MSG register. */ + return (RTWN_RX_DATA); +} + int8_t r92c_get_rssi_cck(struct rtwn_softc *sc, void *physt) { diff --git a/freebsd/sys/dev/rtwn/rtl8192c/r92c_tx.c b/freebsd/sys/dev/rtwn/rtl8192c/r92c_tx.c index 5c80af90..36450e80 100644 --- a/freebsd/sys/dev/rtwn/rtl8192c/r92c_tx.c +++ b/freebsd/sys/dev/rtwn/rtl8192c/r92c_tx.c @@ -105,7 +105,7 @@ r92c_tx_protection(struct rtwn_softc *sc, struct r92c_tx_desc *txd, rate = rtwn_ctl_mcsrate(ic->ic_rt, ridx); else rate = ieee80211_ctl_rate(ic->ic_rt, ridx2rate[ridx]); - ridx = rate2ridx(rate); + ridx = rate2ridx(IEEE80211_RV(rate)); txd->txdw4 |= htole32(SM(R92C_TXDW4_RTSRATE, ridx)); /* RTS rate fallback limit (max). */ @@ -213,6 +213,12 @@ r92c_tx_setup_macid(void *buf, int id) struct r92c_tx_desc *txd = (struct r92c_tx_desc *)buf; txd->txdw1 |= htole32(SM(R92C_TXDW1_MACID, id)); + + /* XXX does not belong here */ + /* XXX temporary (I hope) */ + /* Force CCK1 for RTS / CTS frames (driver bug) */ + txd->txdw4 &= ~htole32(SM(R92C_TXDW4_RTSRATE, R92C_TXDW4_RTSRATE_M)); + txd->txdw4 &= ~htole32(R92C_TXDW4_RTS_SHORT); } void diff --git a/freebsd/sys/dev/rtwn/rtl8192c/r92c_var.h b/freebsd/sys/dev/rtwn/rtl8192c/r92c_var.h index 79592449..2b35ccea 100644 --- a/freebsd/sys/dev/rtwn/rtl8192c/r92c_var.h +++ b/freebsd/sys/dev/rtwn/rtl8192c/r92c_var.h @@ -58,7 +58,7 @@ struct r92c_softc { void (*rs_tx_enable_ampdu)(void *, int); void (*rs_tx_setup_hwseq)(void *); void (*rs_tx_setup_macid)(void *, int); - void (*rs_set_name)(struct rtwn_softc *); + void (*rs_set_rom_opts)(struct rtwn_softc *, uint8_t *); int rf_read_delay[3]; uint32_t rf_chnlbw[R92C_MAX_CHAINS]; @@ -77,7 +77,7 @@ struct r92c_softc { ((R92C_SOFTC(_sc)->rs_tx_setup_hwseq)((_buf))) #define rtwn_r92c_tx_setup_macid(_sc, _buf, _id) \ ((R92C_SOFTC(_sc)->rs_tx_setup_macid)((_buf), (_id))) -#define rtwn_r92c_set_name(_sc) \ - ((R92C_SOFTC(_sc)->rs_set_name)((_sc))) +#define rtwn_r92c_set_rom_opts(_sc, _buf) \ + ((R92C_SOFTC(_sc)->rs_set_rom_opts)((_sc), (_buf))) #endif /* R92C_VAR_H */ diff --git a/freebsd/sys/dev/rtwn/rtl8192c/usb/r92cu.h b/freebsd/sys/dev/rtwn/rtl8192c/usb/r92cu.h index 2486d7fa..4cc01049 100644 --- a/freebsd/sys/dev/rtwn/rtl8192c/usb/r92cu.h +++ b/freebsd/sys/dev/rtwn/rtl8192c/usb/r92cu.h @@ -47,7 +47,6 @@ void r92cu_post_init(struct rtwn_softc *); void r92cu_set_led(struct rtwn_softc *, int, int); /* r92cu_rx.c */ -int r92cu_classify_intr(struct rtwn_softc *, void *, int); int r92cu_align_rx(int, int); /* r92cu_tx.c */ diff --git a/freebsd/sys/dev/rtwn/rtl8192c/usb/r92cu_attach.c b/freebsd/sys/dev/rtwn/rtl8192c/usb/r92cu_attach.c index 4696e8c4..c8270184 100644 --- a/freebsd/sys/dev/rtwn/rtl8192c/usb/r92cu_attach.c +++ b/freebsd/sys/dev/rtwn/rtl8192c/usb/r92cu_attach.c @@ -96,7 +96,7 @@ r92cu_postattach(struct rtwn_softc *sc) } static void -r92cu_set_name(struct rtwn_softc *sc) +r92cu_set_name(struct rtwn_softc *sc, uint8_t *buf) { struct r92c_softc *rs = sc->sc_priv; @@ -126,7 +126,7 @@ r92cu_attach_private(struct rtwn_softc *sc) rs->rs_tx_enable_ampdu = r92c_tx_enable_ampdu; rs->rs_tx_setup_hwseq = r92c_tx_setup_hwseq; rs->rs_tx_setup_macid = r92c_tx_setup_macid; - rs->rs_set_name = r92cu_set_name; + rs->rs_set_rom_opts = r92cu_set_name; #ifndef RTWN_WITHOUT_UCODE rs->rs_c2h_timeout = hz; @@ -170,7 +170,7 @@ r92cu_attach(struct rtwn_usb_softc *uc) sc->sc_get_rx_stats = r92c_get_rx_stats; sc->sc_get_rssi_cck = r92c_get_rssi_cck; sc->sc_get_rssi_ofdm = r92c_get_rssi_ofdm; - sc->sc_classify_intr = r92cu_classify_intr; + sc->sc_classify_intr = r92c_classify_intr; sc->sc_handle_tx_report = rtwn_nop_softc_uint8_int; sc->sc_handle_c2h_report = rtwn_nop_softc_uint8_int; sc->sc_check_frame = rtwn_nop_int_softc_mbuf; @@ -189,7 +189,7 @@ r92cu_attach(struct rtwn_usb_softc *uc) sc->sc_llt_init = r92c_llt_init; sc->sc_set_page_size = r92c_set_page_size; sc->sc_lc_calib = r92c_lc_calib; - sc->sc_iq_calib = r92c_iq_calib; /* XXX TODO */ + sc->sc_iq_calib = r92c_iq_calib; sc->sc_read_chipid_vendor = r92c_read_chipid_vendor; sc->sc_adj_devcaps = r92cu_adj_devcaps; sc->sc_vap_preattach = rtwn_nop_softc_vap; diff --git a/freebsd/sys/dev/rtwn/rtl8192c/usb/r92cu_init.c b/freebsd/sys/dev/rtwn/rtl8192c/usb/r92cu_init.c index 61dd1aa0..08259875 100644 --- a/freebsd/sys/dev/rtwn/rtl8192c/usb/r92cu_init.c +++ b/freebsd/sys/dev/rtwn/rtl8192c/usb/r92cu_init.c @@ -359,6 +359,8 @@ void r92cu_post_init(struct rtwn_softc *sc) { + rtwn_write_4(sc, R92C_POWER_STATUS, 0x5); + /* Perform LO and IQ calibrations. */ r92c_iq_calib(sc); /* Perform LC calibration. */ diff --git a/freebsd/sys/dev/rtwn/rtl8192c/usb/r92cu_rx.c b/freebsd/sys/dev/rtwn/rtl8192c/usb/r92cu_rx.c index 4d040a4e..8d8489c2 100644 --- a/freebsd/sys/dev/rtwn/rtl8192c/usb/r92cu_rx.c +++ b/freebsd/sys/dev/rtwn/rtl8192c/usb/r92cu_rx.c @@ -52,13 +52,6 @@ __FBSDID("$FreeBSD$"); int -r92cu_classify_intr(struct rtwn_softc *sc, void *buf, int len) -{ - /* NB: reports are fetched from C2H_MSG register. */ - return (RTWN_RX_DATA); -} - -int r92cu_align_rx(int totlen, int len) { return (roundup2(totlen, 128)); diff --git a/freebsd/sys/dev/rtwn/rtl8192e/usb/r92eu_attach.c b/freebsd/sys/dev/rtwn/rtl8192e/usb/r92eu_attach.c index ce1e49f4..f906d9fa 100644 --- a/freebsd/sys/dev/rtwn/rtl8192e/usb/r92eu_attach.c +++ b/freebsd/sys/dev/rtwn/rtl8192e/usb/r92eu_attach.c @@ -137,7 +137,7 @@ r92eu_attach(struct rtwn_usb_softc *uc) sc->sc_llt_init = r92e_llt_init; sc->sc_set_page_size = rtwn_nop_int_softc; sc->sc_lc_calib = r92c_lc_calib; - sc->sc_iq_calib = r88e_iq_calib; /* XXX TODO */ + sc->sc_iq_calib = rtwn_nop_softc; /* XXX TODO */ sc->sc_read_chipid_vendor = rtwn_nop_softc_uint32; sc->sc_adj_devcaps = r92eu_adj_devcaps; sc->sc_vap_preattach = rtwn_nop_softc_vap; diff --git a/freebsd/sys/dev/rtwn/rtl8812a/r12a_tx.c b/freebsd/sys/dev/rtwn/rtl8812a/r12a_tx.c index 77e9e423..910a06eb 100644 --- a/freebsd/sys/dev/rtwn/rtl8812a/r12a_tx.c +++ b/freebsd/sys/dev/rtwn/rtl8812a/r12a_tx.c @@ -113,7 +113,7 @@ r12a_tx_protection(struct rtwn_softc *sc, struct r12a_tx_desc *txd, rate = rtwn_ctl_mcsrate(ic->ic_rt, ridx); else rate = ieee80211_ctl_rate(ic->ic_rt, ridx2rate[ridx]); - ridx = rate2ridx(rate); + ridx = rate2ridx(IEEE80211_RV(rate)); txd->txdw4 |= htole32(SM(R12A_TXDW4_RTSRATE, ridx)); /* RTS rate fallback limit (max). */ diff --git a/freebsd/sys/dev/rtwn/usb/rtwn_usb_attach.h b/freebsd/sys/dev/rtwn/usb/rtwn_usb_attach.h index 432d7e97..c757cb79 100644 --- a/freebsd/sys/dev/rtwn/usb/rtwn_usb_attach.h +++ b/freebsd/sys/dev/rtwn/usb/rtwn_usb_attach.h @@ -107,6 +107,7 @@ static const STRUCT_USB_HOST_ID rtwn_devs[] = { { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, RTWN_CHIP_RTL8192EU) } RTWN_RTL8192EU_DEV(DLINK, DWA131E1), RTWN_RTL8192EU_DEV(REALTEK, RTL8192EU), + RTWN_RTL8192EU_DEV(TPLINK, WN821NV5), RTWN_RTL8192EU_DEV(TPLINK, WN822NV4), RTWN_RTL8192EU_DEV(TPLINK, WN823NV2), #undef RTWN_RTL8192EU_DEV @@ -155,7 +156,10 @@ static const STRUCT_USB_HOST_ID rtwn_devs[] = { RTWN_RTL8821AU_DEV(EDIMAX, EW7811UTC_2), RTWN_RTL8821AU_DEV(HAWKING, HD65U), RTWN_RTL8821AU_DEV(MELCO, WIU2433DM), - RTWN_RTL8821AU_DEV(NETGEAR, A6100) + RTWN_RTL8821AU_DEV(NETGEAR, A6100), + RTWN_RTL8821AU_DEV(REALTEK, RTL8821AU_1), + RTWN_RTL8821AU_DEV(REALTEK, RTL8821AU_2), + RTWN_RTL8821AU_DEV(TPLINK, T2UNANO) #undef RTWN_RTL8821AU_DEV }; diff --git a/freebsd/sys/dev/rtwn/usb/rtwn_usb_reg.c b/freebsd/sys/dev/rtwn/usb/rtwn_usb_reg.c index 8225282e..c7cb255e 100644 --- a/freebsd/sys/dev/rtwn/usb/rtwn_usb_reg.c +++ b/freebsd/sys/dev/rtwn/usb/rtwn_usb_reg.c @@ -174,8 +174,6 @@ rtwn_usb_delay(struct rtwn_softc *sc, int usec) /* 1ms delay as default is too big. */ if (usec < 1000) DELAY(usec); - else { - usb_pause_mtx(&sc->sc_mtx, - MAX(msecs_to_ticks(usec / 1000), 1)); - } + else + usb_pause_mtx(&sc->sc_mtx, msecs_to_ticks(usec / 1000)); } diff --git a/freebsd/sys/dev/sdhci/fsl_sdhci.c b/freebsd/sys/dev/sdhci/fsl_sdhci.c index 84665b41..be3d1de3 100644 --- a/freebsd/sys/dev/sdhci/fsl_sdhci.c +++ b/freebsd/sys/dev/sdhci/fsl_sdhci.c @@ -1016,7 +1016,7 @@ static driver_t fsl_sdhci_driver = { DRIVER_MODULE(sdhci_fsl, simplebus, fsl_sdhci_driver, fsl_sdhci_devclass, NULL, NULL); -MODULE_DEPEND(sdhci_fsl, sdhci, 1, 1, 1); +SDHCI_DEPEND(sdhci_fsl); #ifndef MMCCAM MMC_DECLARE_BRIDGE(sdhci_fsl); diff --git a/freebsd/sys/dev/sdhci/sdhci.c b/freebsd/sys/dev/sdhci/sdhci.c index 0bb9edc7..cf853360 100644 --- a/freebsd/sys/dev/sdhci/sdhci.c +++ b/freebsd/sys/dev/sdhci/sdhci.c @@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$"); #include <sys/conf.h> #include <sys/kernel.h> #include <sys/kobj.h> +#include <sys/libkern.h> #include <sys/lock.h> #include <sys/malloc.h> #include <sys/module.h> @@ -110,19 +111,20 @@ static void sdhci_retune(void *arg); static void sdhci_set_clock(struct sdhci_slot *slot, uint32_t clock); static void sdhci_set_power(struct sdhci_slot *slot, u_char power); static void sdhci_set_transfer_mode(struct sdhci_slot *slot, - struct mmc_data *data); + const struct mmc_data *data); static void sdhci_start(struct sdhci_slot *slot); static void sdhci_timeout(void *arg); static void sdhci_start_command(struct sdhci_slot *slot, struct mmc_command *cmd); -static void sdhci_start_data(struct sdhci_slot *slot, struct mmc_data *data); +static void sdhci_start_data(struct sdhci_slot *slot, + const struct mmc_data *data); static void sdhci_write_block_pio(struct sdhci_slot *slot); static void sdhci_transfer_pio(struct sdhci_slot *slot); #ifdef MMCCAM /* CAM-related */ static void sdhci_cam_action(struct cam_sim *sim, union ccb *ccb); -static int sdhci_cam_get_possible_host_clock(struct sdhci_slot *slot, +static int sdhci_cam_get_possible_host_clock(const struct sdhci_slot *slot, int proposed_clock); static void sdhci_cam_handle_mmcio(struct cam_sim *sim, union ccb *ccb); static void sdhci_cam_poll(struct cam_sim *sim); @@ -132,12 +134,14 @@ static int sdhci_cam_update_ios(struct sdhci_slot *slot); #endif /* helper routines */ +static int sdhci_dma_alloc(struct sdhci_slot *slot); +static void sdhci_dma_free(struct sdhci_slot *slot); static void sdhci_dumpregs(struct sdhci_slot *slot); static void sdhci_getaddr(void *arg, bus_dma_segment_t *segs, int nsegs, int error); -static int slot_printf(struct sdhci_slot *slot, const char * fmt, ...) +static int slot_printf(const struct sdhci_slot *slot, const char * fmt, ...) __printflike(2, 3); -static uint32_t sdhci_tuning_intmask(struct sdhci_slot *slot); +static uint32_t sdhci_tuning_intmask(const struct sdhci_slot *slot); #define SDHCI_LOCK(_slot) mtx_lock(&(_slot)->mtx) #define SDHCI_UNLOCK(_slot) mtx_unlock(&(_slot)->mtx) @@ -181,17 +185,22 @@ sdhci_getaddr(void *arg, bus_dma_segment_t *segs, int nsegs, int error) } static int -slot_printf(struct sdhci_slot *slot, const char * fmt, ...) +slot_printf(const struct sdhci_slot *slot, const char * fmt, ...) { + char buf[128]; va_list ap; int retval; - retval = printf("%s-slot%d: ", - device_get_nameunit(slot->bus), slot->num); - + /* + * Make sure we print a single line all together rather than in two + * halves to avoid console gibberish bingo. + */ va_start(ap, fmt); - retval += vprintf(fmt, ap); + retval = vsnprintf(buf, sizeof(buf), fmt, ap); va_end(ap); + + retval += printf("%s-slot%d: %s", + device_get_nameunit(slot->bus), slot->num, buf); return (retval); } @@ -292,7 +301,7 @@ sdhci_reset(struct sdhci_slot *slot, uint8_t mask) } static uint32_t -sdhci_tuning_intmask(struct sdhci_slot *slot) +sdhci_tuning_intmask(const struct sdhci_slot *slot) { uint32_t intmask; @@ -474,7 +483,7 @@ sdhci_set_power(struct sdhci_slot *slot, u_char power) DELAY(100); } if (!(RD1(slot, SDHCI_POWER_CONTROL) & SDHCI_POWER_ON)) - slot_printf(slot, "Bus power failed to enable"); + slot_printf(slot, "Bus power failed to enable\n"); if (slot->quirks & SDHCI_QUIRK_INTEL_POWER_UP_RESET) { WR1(slot, SDHCI_POWER_CONTROL, pwr | 0x10); @@ -494,7 +503,13 @@ sdhci_read_block_pio(struct sdhci_slot *slot) buffer = slot->curcmd->data->data; buffer += slot->offset; /* Transfer one block at a time. */ - left = min(512, slot->curcmd->data->len - slot->offset); +#ifdef MMCCAM + if (slot->curcmd->data->flags & MMC_DATA_BLOCK_SIZE) + left = min(slot->curcmd->data->block_size, + slot->curcmd->data->len - slot->offset); + else +#endif + left = min(512, slot->curcmd->data->len - slot->offset); slot->offset += left; /* If we are too fast, broken controllers return zeroes. */ @@ -537,7 +552,13 @@ sdhci_write_block_pio(struct sdhci_slot *slot) buffer = slot->curcmd->data->data; buffer += slot->offset; /* Transfer one block at a time. */ - left = min(512, slot->curcmd->data->len - slot->offset); +#ifdef MMCCAM + if (slot->curcmd->data->flags & MMC_DATA_BLOCK_SIZE) { + left = min(slot->curcmd->data->block_size, + slot->curcmd->data->len - slot->offset); + } else +#endif + left = min(512, slot->curcmd->data->len - slot->offset); slot->offset += left; /* Handle unaligned and aligned buffer cases. */ @@ -739,55 +760,94 @@ sdhci_card_poll(void *arg) sdhci_card_poll, slot); } -int -sdhci_init_slot(device_t dev, struct sdhci_slot *slot, int num) +static int +sdhci_dma_alloc(struct sdhci_slot *slot) { - kobjop_desc_t kobj_desc; - kobj_method_t *kobj_method; - uint32_t caps, caps2, freq, host_caps; int err; - SDHCI_LOCK_INIT(slot); - - slot->num = num; - slot->bus = dev; + if (!(slot->quirks & SDHCI_QUIRK_BROKEN_SDMA_BOUNDARY)) { + if (MAXPHYS <= 1024 * 4) + slot->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_4K; + else if (MAXPHYS <= 1024 * 8) + slot->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_8K; + else if (MAXPHYS <= 1024 * 16) + slot->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_16K; + else if (MAXPHYS <= 1024 * 32) + slot->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_32K; + else if (MAXPHYS <= 1024 * 64) + slot->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_64K; + else if (MAXPHYS <= 1024 * 128) + slot->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_128K; + else if (MAXPHYS <= 1024 * 256) + slot->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_256K; + else + slot->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_512K; + } + slot->sdma_bbufsz = SDHCI_SDMA_BNDRY_TO_BBUFSZ(slot->sdma_boundary); - /* Allocate DMA tag. */ - err = bus_dma_tag_create(bus_get_dma_tag(dev), - DMA_BLOCK_SIZE, 0, BUS_SPACE_MAXADDR_32BIT, - BUS_SPACE_MAXADDR, NULL, NULL, - DMA_BLOCK_SIZE, 1, DMA_BLOCK_SIZE, - BUS_DMA_ALLOCNOW, NULL, NULL, - &slot->dmatag); + /* + * Allocate the DMA tag for an SDMA bounce buffer. + * Note that the SDHCI specification doesn't state any alignment + * constraint for the SDMA system address. However, controllers + * typically ignore the SDMA boundary bits in SDHCI_DMA_ADDRESS when + * forming the actual address of data, requiring the SDMA buffer to + * be aligned to the SDMA boundary. + */ + err = bus_dma_tag_create(bus_get_dma_tag(slot->bus), slot->sdma_bbufsz, + 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, + slot->sdma_bbufsz, 1, slot->sdma_bbufsz, BUS_DMA_ALLOCNOW, + NULL, NULL, &slot->dmatag); if (err != 0) { - device_printf(dev, "Can't create DMA tag\n"); - SDHCI_LOCK_DESTROY(slot); + slot_printf(slot, "Can't create DMA tag for SDMA\n"); return (err); } - /* Allocate DMA memory. */ + /* Allocate DMA memory for the SDMA bounce buffer. */ err = bus_dmamem_alloc(slot->dmatag, (void **)&slot->dmamem, BUS_DMA_NOWAIT, &slot->dmamap); if (err != 0) { - device_printf(dev, "Can't alloc DMA memory\n"); + slot_printf(slot, "Can't alloc DMA memory for SDMA\n"); bus_dma_tag_destroy(slot->dmatag); - SDHCI_LOCK_DESTROY(slot); return (err); } - /* Map the memory. */ + /* Map the memory of the SDMA bounce buffer. */ err = bus_dmamap_load(slot->dmatag, slot->dmamap, - (void *)slot->dmamem, DMA_BLOCK_SIZE, - sdhci_getaddr, &slot->paddr, 0); + (void *)slot->dmamem, slot->sdma_bbufsz, sdhci_getaddr, + &slot->paddr, 0); if (err != 0 || slot->paddr == 0) { - device_printf(dev, "Can't load DMA memory\n"); + slot_printf(slot, "Can't load DMA memory for SDMA\n"); bus_dmamem_free(slot->dmatag, slot->dmamem, slot->dmamap); bus_dma_tag_destroy(slot->dmatag); - SDHCI_LOCK_DESTROY(slot); if (err) return (err); else return (EFAULT); } + return (0); +} + +static void +sdhci_dma_free(struct sdhci_slot *slot) +{ + + bus_dmamap_unload(slot->dmatag, slot->dmamap); + bus_dmamem_free(slot->dmatag, slot->dmamem, slot->dmamap); + bus_dma_tag_destroy(slot->dmatag); +} + +int +sdhci_init_slot(device_t dev, struct sdhci_slot *slot, int num) +{ + kobjop_desc_t kobj_desc; + kobj_method_t *kobj_method; + uint32_t caps, caps2, freq, host_caps; + int err; + + SDHCI_LOCK_INIT(slot); + + slot->num = num; + slot->bus = dev; + slot->version = (RD2(slot, SDHCI_HOST_VERSION) >> SDHCI_SPEC_VER_SHIFT) & SDHCI_SPEC_VER_MASK; if (slot->quirks & SDHCI_QUIRK_MISSING_CAPS) { @@ -803,12 +863,8 @@ sdhci_init_slot(device_t dev, struct sdhci_slot *slot, int num) if (slot->version >= SDHCI_SPEC_300) { if ((caps & SDHCI_SLOTTYPE_MASK) != SDHCI_SLOTTYPE_REMOVABLE && (caps & SDHCI_SLOTTYPE_MASK) != SDHCI_SLOTTYPE_EMBEDDED) { - device_printf(dev, + slot_printf(slot, "Driver doesn't support shared bus slots\n"); - bus_dmamap_unload(slot->dmatag, slot->dmamap); - bus_dmamem_free(slot->dmatag, slot->dmamem, - slot->dmamap); - bus_dma_tag_destroy(slot->dmatag); SDHCI_LOCK_DESTROY(slot); return (ENXIO); } else if ((caps & SDHCI_SLOTTYPE_MASK) == @@ -832,7 +888,7 @@ sdhci_init_slot(device_t dev, struct sdhci_slot *slot, int num) */ if (slot->max_clk == 0) { slot->max_clk = SDHCI_DEFAULT_MAX_FREQ * 1000000; - device_printf(dev, "Hardware doesn't specify base clock " + slot_printf(slot, "Hardware doesn't specify base clock " "frequency, using %dMHz as default.\n", SDHCI_DEFAULT_MAX_FREQ); } @@ -853,7 +909,7 @@ sdhci_init_slot(device_t dev, struct sdhci_slot *slot, int num) * max timeout, but still mention it. */ if (slot->timeout_clk == 0) { - device_printf(dev, "Hardware doesn't specify timeout clock " + slot_printf(slot, "Hardware doesn't specify timeout clock " "frequency, setting BROKEN_TIMEOUT quirk.\n"); slot->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; } @@ -869,7 +925,7 @@ sdhci_init_slot(device_t dev, struct sdhci_slot *slot, int num) if ((caps & SDHCI_CAN_VDD_180) && (slot->opt & SDHCI_SLOT_EMBEDDED)) slot->host.host_ocr |= MMC_OCR_LOW_VOLTAGE; if (slot->host.host_ocr == 0) { - device_printf(dev, "Hardware doesn't report any " + slot_printf(slot, "Hardware doesn't report any " "support voltages.\n"); } @@ -955,7 +1011,7 @@ no_tuning: slot->retune_count = (caps2 & SDHCI_RETUNE_CNT_MASK) >> SDHCI_RETUNE_CNT_SHIFT; if (slot->retune_count > 0xb) { - device_printf(dev, "Unknown re-tuning count " + slot_printf(slot, "Unknown re-tuning count " "%x, using 1 sec\n", slot->retune_count); slot->retune_count = 1; } else if (slot->retune_count != 0) @@ -1014,6 +1070,19 @@ no_tuning: if (slot->opt & SDHCI_PLATFORM_TRANSFER) slot->opt &= ~SDHCI_HAVE_DMA; + if (slot->opt & SDHCI_HAVE_DMA) { + err = sdhci_dma_alloc(slot); + if (err != 0) { + if (slot->opt & SDHCI_TUNING_SUPPORTED) { + free(slot->tune_req, M_DEVBUF); + free(slot->tune_cmd, M_DEVBUF); + free(slot->tune_data, M_DEVBUF); + } + SDHCI_LOCK_DESTROY(slot); + return (err); + } + } + if (bootverbose || sdhci_debug) { slot_printf(slot, "%uMHz%s %s VDD:%s%s%s VCCQ: 3.3V%s%s DRV: B%s%s%s %s %s\n", @@ -1061,7 +1130,7 @@ no_tuning: slot->timeout = 10; SYSCTL_ADD_INT(device_get_sysctl_ctx(slot->bus), SYSCTL_CHILDREN(device_get_sysctl_tree(slot->bus)), OID_AUTO, - "timeout", CTLFLAG_RW, &slot->timeout, 0, + "timeout", CTLFLAG_RWTUN, &slot->timeout, 0, "Maximum timeout for SDHCI transfers (in secs)"); TASK_INIT(&slot->card_task, 0, sdhci_card_task, slot); TIMEOUT_TASK_INIT(taskqueue_swi_giant, &slot->card_delayed_task, 0, @@ -1111,9 +1180,8 @@ sdhci_cleanup_slot(struct sdhci_slot *slot) SDHCI_LOCK(slot); sdhci_reset(slot, SDHCI_RESET_ALL); SDHCI_UNLOCK(slot); - bus_dmamap_unload(slot->dmatag, slot->dmamap); - bus_dmamem_free(slot->dmatag, slot->dmamem, slot->dmamap); - bus_dma_tag_destroy(slot->dmatag); + if (slot->opt & SDHCI_HAVE_DMA) + sdhci_dma_free(slot); if (slot->opt & SDHCI_TUNING_SUPPORTED) { free(slot->tune_req, M_DEVBUF); free(slot->tune_cmd, M_DEVBUF); @@ -1177,7 +1245,7 @@ sdhci_generic_get_card_present(device_t brdev __unused, struct sdhci_slot *slot) void sdhci_generic_set_uhs_timing(device_t brdev __unused, struct sdhci_slot *slot) { - struct mmc_ios *ios; + const struct mmc_ios *ios; uint16_t hostctrl2; if (slot->version < SDHCI_SPEC_300) @@ -1310,7 +1378,7 @@ int sdhci_generic_tune(device_t brdev __unused, device_t reqdev, bool hs400) { struct sdhci_slot *slot = device_get_ivars(reqdev); - struct mmc_ios *ios = &slot->host.ios; + const struct mmc_ios *ios = &slot->host.ios; struct mmc_command *tune_cmd; struct mmc_data *tune_data; uint32_t opcode; @@ -1513,23 +1581,23 @@ sdhci_retune(void *arg) static void sdhci_req_done(struct sdhci_slot *slot) { - union ccb *ccb; + union ccb *ccb; if (__predict_false(sdhci_debug > 1)) slot_printf(slot, "%s\n", __func__); if (slot->ccb != NULL && slot->curcmd != NULL) { callout_stop(&slot->timeout_callout); - ccb = slot->ccb; - slot->ccb = NULL; + ccb = slot->ccb; + slot->ccb = NULL; slot->curcmd = NULL; - /* Tell CAM the request is finished */ - struct ccb_mmcio *mmcio; - mmcio = &ccb->mmcio; + /* Tell CAM the request is finished */ + struct ccb_mmcio *mmcio; + mmcio = &ccb->mmcio; - ccb->ccb_h.status = - (mmcio->cmd.error == 0 ? CAM_REQ_CMP : CAM_REQ_CMP_ERR); - xpt_done(ccb); + ccb->ccb_h.status = + (mmcio->cmd.error == 0 ? CAM_REQ_CMP : CAM_REQ_CMP_ERR); + xpt_done(ccb); } } #else @@ -1579,7 +1647,7 @@ sdhci_timeout(void *arg) } static void -sdhci_set_transfer_mode(struct sdhci_slot *slot, struct mmc_data *data) +sdhci_set_transfer_mode(struct sdhci_slot *slot, const struct mmc_data *data) { uint16_t mode; @@ -1587,9 +1655,9 @@ sdhci_set_transfer_mode(struct sdhci_slot *slot, struct mmc_data *data) return; mode = SDHCI_TRNS_BLK_CNT_EN; - if (data->len > 512) { + if (data->len > 512 || data->block_count > 1) { mode |= SDHCI_TRNS_MULTI; - if (__predict_true( + if (data->block_count == 0 && __predict_true( #ifdef MMCCAM slot->ccb->mmcio.stop.opcode == MMC_STOP_TRANSMISSION && #else @@ -1714,7 +1782,9 @@ sdhci_start_command(struct sdhci_slot *slot, struct mmc_command *cmd) /* Set data transfer mode. */ sdhci_set_transfer_mode(slot, cmd->data); if (__predict_false(sdhci_debug > 1)) - slot_printf(slot, "Starting command!\n"); + slot_printf(slot, "Starting command opcode %#04x flags %#04x\n", + cmd->opcode, flags); + /* Start command. */ WR2(slot, SDHCI_COMMAND_FLAGS, (cmd->opcode << 8) | (flags & 0xff)); /* Start timeout callout. */ @@ -1730,7 +1800,7 @@ sdhci_finish_command(struct sdhci_slot *slot) uint8_t extra; if (__predict_false(sdhci_debug > 1)) - slot_printf(slot, "%s: called, err %d flags %d\n", + slot_printf(slot, "%s: called, err %d flags %#04x\n", __func__, slot->curcmd->error, slot->curcmd->flags); slot->cmd_done = 1; /* @@ -1771,7 +1841,7 @@ sdhci_finish_command(struct sdhci_slot *slot) slot->curcmd->resp[0] = RD4(slot, SDHCI_RESPONSE); } if (__predict_false(sdhci_debug > 1)) - printf("Resp: %02x %02x %02x %02x\n", + slot_printf(slot, "Resp: %#04x %#04x %#04x %#04x\n", slot->curcmd->resp[0], slot->curcmd->resp[1], slot->curcmd->resp[2], slot->curcmd->resp[3]); @@ -1781,9 +1851,9 @@ sdhci_finish_command(struct sdhci_slot *slot) } static void -sdhci_start_data(struct sdhci_slot *slot, struct mmc_data *data) +sdhci_start_data(struct sdhci_slot *slot, const struct mmc_data *data) { - uint32_t target_timeout, current_timeout; + uint32_t blkcnt, blksz, current_timeout, sdma_bbufsz, target_timeout; uint8_t div; if (data == NULL && (slot->curcmd->flags & MMC_RSP_BUSY) == 0) { @@ -1819,7 +1889,7 @@ sdhci_start_data(struct sdhci_slot *slot, struct mmc_data *data) /* Use DMA if possible. */ if ((slot->opt & SDHCI_HAVE_DMA)) slot->flags |= SDHCI_USE_DMA; - /* If data is small, broken DMA may return zeroes instead of data, */ + /* If data is small, broken DMA may return zeroes instead of data. */ if ((slot->quirks & SDHCI_QUIRK_BROKEN_TIMINGS) && (data->len <= 512)) slot->flags &= ~SDHCI_USE_DMA; @@ -1829,20 +1899,22 @@ sdhci_start_data(struct sdhci_slot *slot, struct mmc_data *data) slot->flags &= ~SDHCI_USE_DMA; /* Load DMA buffer. */ if (slot->flags & SDHCI_USE_DMA) { + sdma_bbufsz = slot->sdma_bbufsz; if (data->flags & MMC_DATA_READ) bus_dmamap_sync(slot->dmatag, slot->dmamap, BUS_DMASYNC_PREREAD); else { - memcpy(slot->dmamem, data->data, - (data->len < DMA_BLOCK_SIZE) ? - data->len : DMA_BLOCK_SIZE); + memcpy(slot->dmamem, data->data, ulmin(data->len, + sdma_bbufsz)); bus_dmamap_sync(slot->dmatag, slot->dmamap, BUS_DMASYNC_PREWRITE); } WR4(slot, SDHCI_DMA_ADDRESS, slot->paddr); - /* Interrupt aggregation: Mask border interrupt - * for the last page and unmask else. */ - if (data->len == DMA_BLOCK_SIZE) + /* + * Interrupt aggregation: Mask border interrupt for the last + * bounce buffer and unmask otherwise. + */ + if (data->len == sdma_bbufsz) slot->intmask &= ~SDHCI_INT_DMA_END; else slot->intmask |= SDHCI_INT_DMA_END; @@ -1850,16 +1922,27 @@ sdhci_start_data(struct sdhci_slot *slot, struct mmc_data *data) } /* Current data offset for both PIO and DMA. */ slot->offset = 0; - /* Set block size and request IRQ on 4K border. */ - WR2(slot, SDHCI_BLOCK_SIZE, SDHCI_MAKE_BLKSZ(DMA_BOUNDARY, - (data->len < 512) ? data->len : 512)); - /* Set block count. */ - WR2(slot, SDHCI_BLOCK_COUNT, (data->len + 511) / 512); +#ifdef MMCCAM + if (data->flags & MMC_DATA_BLOCK_SIZE) { + /* Set block size and request border interrupts on the SDMA boundary. */ + blksz = SDHCI_MAKE_BLKSZ(slot->sdma_boundary, data->block_size); + blkcnt = data->block_count; + if (__predict_false(sdhci_debug > 0)) + slot_printf(slot, "SDIO Custom block params: blksz: " + "%#10x, blk cnt: %#10x\n", blksz, blkcnt); + } else +#endif + { + /* Set block size and request border interrupts on the SDMA boundary. */ + blksz = SDHCI_MAKE_BLKSZ(slot->sdma_boundary, ulmin(data->len, 512)); + blkcnt = howmany(data->len, 512); + } + WR2(slot, SDHCI_BLOCK_SIZE, blksz); + WR2(slot, SDHCI_BLOCK_COUNT, blkcnt); if (__predict_false(sdhci_debug > 1)) - slot_printf(slot, "Block size: %02x, count %lu\n", - (unsigned int)SDHCI_MAKE_BLKSZ(DMA_BOUNDARY, (data->len < 512) ? data->len : 512), - (unsigned long)(data->len + 511) / 512); + slot_printf(slot, "Blk size: 0x%08x | Blk cnt: 0x%08x\n", + blksz, blkcnt); } void @@ -1883,7 +1966,7 @@ sdhci_finish_data(struct sdhci_slot *slot) bus_dmamap_sync(slot->dmatag, slot->dmamap, BUS_DMASYNC_POSTREAD); memcpy((u_char*)data->data + slot->offset, slot->dmamem, - (left < DMA_BLOCK_SIZE) ? left : DMA_BLOCK_SIZE); + ulmin(left, slot->sdma_bbufsz)); } else bus_dmamap_sync(slot->dmatag, slot->dmamap, BUS_DMASYNC_POSTWRITE); @@ -1907,15 +1990,14 @@ sdhci_finish_data(struct sdhci_slot *slot) static void sdhci_start(struct sdhci_slot *slot) { - union ccb *ccb; + union ccb *ccb; + struct ccb_mmcio *mmcio; ccb = slot->ccb; if (ccb == NULL) return; - struct ccb_mmcio *mmcio; mmcio = &ccb->mmcio; - if (!(slot->flags & CMD_STARTED)) { slot->flags |= CMD_STARTED; sdhci_start_command(slot, &mmcio->cmd); @@ -1947,7 +2029,7 @@ sdhci_start(struct sdhci_slot *slot) static void sdhci_start(struct sdhci_slot *slot) { - struct mmc_request *req; + const struct mmc_request *req; req = slot->req; if (req == NULL) @@ -2076,6 +2158,7 @@ sdhci_data_irq(struct sdhci_slot *slot, uint32_t intmask) { struct mmc_data *data; size_t left; + uint32_t sdma_bbufsz; if (!slot->curcmd) { slot_printf(slot, "Got data interrupt 0x%08x, but " @@ -2130,6 +2213,7 @@ sdhci_data_irq(struct sdhci_slot *slot, uint32_t intmask) /* Handle DMA border. */ if (intmask & SDHCI_INT_DMA_END) { data = slot->curcmd->data; + sdma_bbufsz = slot->sdma_bbufsz; /* Unload DMA buffer ... */ left = data->len - slot->offset; @@ -2137,26 +2221,28 @@ sdhci_data_irq(struct sdhci_slot *slot, uint32_t intmask) bus_dmamap_sync(slot->dmatag, slot->dmamap, BUS_DMASYNC_POSTREAD); memcpy((u_char*)data->data + slot->offset, slot->dmamem, - (left < DMA_BLOCK_SIZE) ? left : DMA_BLOCK_SIZE); + ulmin(left, sdma_bbufsz)); } else { bus_dmamap_sync(slot->dmatag, slot->dmamap, BUS_DMASYNC_POSTWRITE); } /* ... and reload it again. */ - slot->offset += DMA_BLOCK_SIZE; + slot->offset += sdma_bbufsz; left = data->len - slot->offset; if (data->flags & MMC_DATA_READ) { bus_dmamap_sync(slot->dmatag, slot->dmamap, BUS_DMASYNC_PREREAD); } else { memcpy(slot->dmamem, (u_char*)data->data + slot->offset, - (left < DMA_BLOCK_SIZE)? left : DMA_BLOCK_SIZE); + ulmin(left, sdma_bbufsz)); bus_dmamap_sync(slot->dmatag, slot->dmamap, BUS_DMASYNC_PREWRITE); } - /* Interrupt aggregation: Mask border interrupt - * for the last page. */ - if (left == DMA_BLOCK_SIZE) { + /* + * Interrupt aggregation: Mask border interrupt for the last + * bounce buffer. + */ + if (left == sdma_bbufsz) { slot->intmask &= ~SDHCI_INT_DMA_END; WR4(slot, SDHCI_SIGNAL_ENABLE, slot->intmask); } @@ -2279,7 +2365,7 @@ int sdhci_generic_read_ivar(device_t bus, device_t child, int which, uintptr_t *result) { - struct sdhci_slot *slot = device_get_ivars(child); + const struct sdhci_slot *slot = device_get_ivars(child); switch (which) { default: @@ -2442,47 +2528,46 @@ sdhci_generic_write_ivar(device_t bus, device_t child, int which, void sdhci_start_slot(struct sdhci_slot *slot) { - if ((slot->devq = cam_simq_alloc(1)) == NULL) { - goto fail; - } - - mtx_init(&slot->sim_mtx, "sdhcisim", NULL, MTX_DEF); - slot->sim = cam_sim_alloc(sdhci_cam_action, sdhci_cam_poll, - "sdhci_slot", slot, device_get_unit(slot->bus), - &slot->sim_mtx, 1, 1, slot->devq); - - if (slot->sim == NULL) { - cam_simq_free(slot->devq); - slot_printf(slot, "cannot allocate CAM SIM\n"); - goto fail; - } - - mtx_lock(&slot->sim_mtx); - if (xpt_bus_register(slot->sim, slot->bus, 0) != 0) { - slot_printf(slot, - "cannot register SCSI pass-through bus\n"); - cam_sim_free(slot->sim, FALSE); - cam_simq_free(slot->devq); - mtx_unlock(&slot->sim_mtx); - goto fail; - } - - mtx_unlock(&slot->sim_mtx); - /* End CAM-specific init */ + + if ((slot->devq = cam_simq_alloc(1)) == NULL) + goto fail; + + mtx_init(&slot->sim_mtx, "sdhcisim", NULL, MTX_DEF); + slot->sim = cam_sim_alloc_dev(sdhci_cam_action, sdhci_cam_poll, + "sdhci_slot", slot, slot->bus, + &slot->sim_mtx, 1, 1, slot->devq); + + if (slot->sim == NULL) { + cam_simq_free(slot->devq); + slot_printf(slot, "cannot allocate CAM SIM\n"); + goto fail; + } + + mtx_lock(&slot->sim_mtx); + if (xpt_bus_register(slot->sim, slot->bus, 0) != 0) { + slot_printf(slot, "cannot register SCSI pass-through bus\n"); + cam_sim_free(slot->sim, FALSE); + cam_simq_free(slot->devq); + mtx_unlock(&slot->sim_mtx); + goto fail; + } + mtx_unlock(&slot->sim_mtx); + + /* End CAM-specific init */ slot->card_present = 0; sdhci_card_task(slot, 0); - return; + return; fail: - if (slot->sim != NULL) { - mtx_lock(&slot->sim_mtx); - xpt_bus_deregister(cam_sim_path(slot->sim)); - cam_sim_free(slot->sim, FALSE); - mtx_unlock(&slot->sim_mtx); - } - - if (slot->devq != NULL) - cam_simq_free(slot->devq); + if (slot->sim != NULL) { + mtx_lock(&slot->sim_mtx); + xpt_bus_deregister(cam_sim_path(slot->sim)); + cam_sim_free(slot->sim, FALSE); + mtx_unlock(&slot->sim_mtx); + } + + if (slot->devq != NULL) + cam_simq_free(slot->devq); } static void @@ -2541,6 +2626,7 @@ sdhci_cam_action(struct cam_sim *sim, union ccb *ccb) case XPT_GET_TRAN_SETTINGS: { struct ccb_trans_settings *cts = &ccb->cts; + uint32_t max_data; if (sdhci_debug > 1) slot_printf(slot, "Got XPT_GET_TRAN_SETTINGS\n"); @@ -2554,6 +2640,19 @@ sdhci_cam_action(struct cam_sim *sim, union ccb *ccb) cts->proto_specific.mmc.host_f_min = slot->host.f_min; cts->proto_specific.mmc.host_f_max = slot->host.f_max; cts->proto_specific.mmc.host_caps = slot->host.caps; + /* + * Re-tuning modes 1 and 2 restrict the maximum data length + * per read/write command to 4 MiB. + */ + if (slot->opt & SDHCI_TUNING_ENABLED && + (slot->retune_mode == SDHCI_RETUNE_MODE_1 || + slot->retune_mode == SDHCI_RETUNE_MODE_2)) { + max_data = 4 * 1024 * 1024 / MMC_SECTOR_SIZE; + } else { + max_data = 65535; + } + cts->proto_specific.mmc.host_max_data = max_data; + memcpy(&cts->proto_specific.mmc.ios, &slot->host.ios, sizeof(struct mmc_ios)); ccb->ccb_h.status = CAM_REQ_CMP; break; @@ -2601,7 +2700,8 @@ sdhci_cam_poll(struct cam_sim *sim) } static int -sdhci_cam_get_possible_host_clock(struct sdhci_slot *slot, int proposed_clock) +sdhci_cam_get_possible_host_clock(const struct sdhci_slot *slot, + int proposed_clock) { int max_clock, clock, i; @@ -2611,15 +2711,13 @@ sdhci_cam_get_possible_host_clock(struct sdhci_slot *slot, int proposed_clock) clock = max_clock; if (slot->version < SDHCI_SPEC_300) { - for (i = 0; i < SDHCI_200_MAX_DIVIDER; - i <<= 1) { + for (i = 0; i < SDHCI_200_MAX_DIVIDER; i <<= 1) { if (clock <= proposed_clock) break; clock >>= 1; } } else { - for (i = 0; i < SDHCI_300_MAX_DIVIDER; - i += 2) { + for (i = 0; i < SDHCI_300_MAX_DIVIDER; i += 2) { if (clock <= proposed_clock) break; clock = max_clock / (i + 2); @@ -2628,15 +2726,14 @@ sdhci_cam_get_possible_host_clock(struct sdhci_slot *slot, int proposed_clock) return clock; } -int +static int sdhci_cam_settran_settings(struct sdhci_slot *slot, union ccb *ccb) { struct mmc_ios *ios; - struct mmc_ios *new_ios; - struct ccb_trans_settings_mmc *cts; + const struct mmc_ios *new_ios; + const struct ccb_trans_settings_mmc *cts; ios = &slot->host.ios; - cts = &ccb->cts.proto_specific.mmc; new_ios = &cts->ios; @@ -2670,11 +2767,11 @@ sdhci_cam_settran_settings(struct sdhci_slot *slot, union ccb *ccb) slot_printf(slot, "Bus mode => %d\n", ios->bus_mode); } - /* XXX Provide a way to call a chip-specific IOS update, required for TI */ + /* XXX Provide a way to call a chip-specific IOS update, required for TI */ return (sdhci_cam_update_ios(slot)); } -int +static int sdhci_cam_update_ios(struct sdhci_slot *slot) { struct mmc_ios *ios = &slot->host.ios; @@ -2716,10 +2813,10 @@ sdhci_cam_update_ios(struct sdhci_slot *slot) return (0); } -int +static int sdhci_cam_request(struct sdhci_slot *slot, union ccb *ccb) { - struct ccb_mmcio *mmcio; + const struct ccb_mmcio *mmcio; mmcio = &ccb->mmcio; @@ -2730,15 +2827,18 @@ sdhci_cam_request(struct sdhci_slot *slot, union ccb *ccb) } */ if (__predict_false(sdhci_debug > 1)) { - slot_printf(slot, "CMD%u arg %#x flags %#x dlen %u dflags %#x\n", - mmcio->cmd.opcode, mmcio->cmd.arg, mmcio->cmd.flags, - mmcio->cmd.data != NULL ? (unsigned int) mmcio->cmd.data->len : 0, - mmcio->cmd.data != NULL ? mmcio->cmd.data->flags: 0); + slot_printf(slot, "CMD%u arg %#x flags %#x dlen %u dflags %#x " + "blksz=%zu blkcnt=%zu\n", + mmcio->cmd.opcode, mmcio->cmd.arg, mmcio->cmd.flags, + mmcio->cmd.data != NULL ? (unsigned int) mmcio->cmd.data->len : 0, + mmcio->cmd.data != NULL ? mmcio->cmd.data->flags : 0, + mmcio->cmd.data != NULL ? mmcio->cmd.data->block_size : 0, + mmcio->cmd.data != NULL ? mmcio->cmd.data->block_count : 0); } if (mmcio->cmd.data != NULL) { if (mmcio->cmd.data->len == 0 || mmcio->cmd.data->flags == 0) panic("data->len = %d, data->flags = %d -- something is b0rked", - (int)mmcio->cmd.data->len, mmcio->cmd.data->flags); + (int)mmcio->cmd.data->len, mmcio->cmd.data->flags); } slot->ccb = ccb; slot->flags = 0; @@ -2754,4 +2854,4 @@ sdhci_cam_request(struct sdhci_slot *slot, union ccb *ccb) } #endif /* MMCCAM */ -MODULE_VERSION(sdhci, 1); +MODULE_VERSION(sdhci, SDHCI_VERSION); diff --git a/freebsd/sys/dev/sdhci/sdhci.h b/freebsd/sys/dev/sdhci/sdhci.h index a22e0235..38c5e1b9 100644 --- a/freebsd/sys/dev/sdhci/sdhci.h +++ b/freebsd/sys/dev/sdhci/sdhci.h @@ -32,8 +32,8 @@ #include <rtems/bsd/local/opt_mmccam.h> -#define DMA_BLOCK_SIZE 4096 -#define DMA_BOUNDARY 0 /* DMA reload every 4K */ +/* Macro for sizing the SDMA bounce buffer on the SDMA buffer boundary. */ +#define SDHCI_SDMA_BNDRY_TO_BBUFSZ(bndry) (4096 * (1 << bndry)) /* Controller doesn't honor resets unless we touch the clock register */ #define SDHCI_QUIRK_CLOCK_BEFORE_RESET (1 << 0) @@ -95,6 +95,8 @@ #define SDHCI_QUIRK_BROKEN_AUTO_STOP (1 << 28) /* Controller supports eMMC HS400 mode if SDHCI_CAN_SDR104 is set. */ #define SDHCI_QUIRK_MMC_HS400_IF_CAN_SDR104 (1 << 29) +/* SDMA boundary in SDHCI_BLOCK_SIZE broken - use front-end supplied value. */ +#define SDHCI_QUIRK_BROKEN_SDMA_BOUNDARY (1 << 30) /* * Controller registers @@ -102,6 +104,14 @@ #define SDHCI_DMA_ADDRESS 0x00 #define SDHCI_BLOCK_SIZE 0x04 +#define SDHCI_BLKSZ_SDMA_BNDRY_4K 0x00 +#define SDHCI_BLKSZ_SDMA_BNDRY_8K 0x01 +#define SDHCI_BLKSZ_SDMA_BNDRY_16K 0x02 +#define SDHCI_BLKSZ_SDMA_BNDRY_32K 0x03 +#define SDHCI_BLKSZ_SDMA_BNDRY_64K 0x04 +#define SDHCI_BLKSZ_SDMA_BNDRY_128K 0x05 +#define SDHCI_BLKSZ_SDMA_BNDRY_256K 0x06 +#define SDHCI_BLKSZ_SDMA_BNDRY_512K 0x07 #define SDHCI_MAKE_BLKSZ(dma, blksz) (((dma & 0x7) << 12) | (blksz & 0xFFF)) #define SDHCI_BLOCK_COUNT 0x06 @@ -362,6 +372,8 @@ struct sdhci_slot { bus_dmamap_t dmamap; u_char *dmamem; bus_addr_t paddr; /* DMA buffer address */ + uint32_t sdma_bbufsz; /* SDMA bounce buffer size */ + uint8_t sdma_boundary; /* SDMA boundary */ struct task card_task; /* Card presence check task */ struct timeout_task card_delayed_task;/* Card insert delayed task */ @@ -401,10 +413,10 @@ struct sdhci_slot { #ifdef MMCCAM /* CAM stuff */ union ccb *ccb; - struct cam_devq *devq; - struct cam_sim *sim; - struct mtx sim_mtx; - u_char card_present; /* XXX Maybe derive this from elsewhere? */ + struct cam_devq *devq; + struct cam_sim *sim; + struct mtx sim_mtx; + u_char card_present; /* XXX Maybe derive this from elsewhere? */ #endif }; @@ -434,4 +446,9 @@ bool sdhci_generic_get_card_present(device_t brdev, struct sdhci_slot *slot); void sdhci_generic_set_uhs_timing(device_t brdev, struct sdhci_slot *slot); void sdhci_handle_card_present(struct sdhci_slot *slot, bool is_present); +#define SDHCI_VERSION 2 + +#define SDHCI_DEPEND(name) \ + MODULE_DEPEND(name, sdhci, SDHCI_VERSION, SDHCI_VERSION, SDHCI_VERSION); + #endif /* __SDHCI_H__ */ diff --git a/freebsd/sys/dev/usb/net/if_aue.c b/freebsd/sys/dev/usb/net/if_aue.c index 5454e2aa..d33176d9 100644 --- a/freebsd/sys/dev/usb/net/if_aue.c +++ b/freebsd/sys/dev/usb/net/if_aue.c @@ -94,6 +94,10 @@ __FBSDID("$FreeBSD$"); #include <net/if.h> #include <net/if_var.h> +#include <net/if_media.h> + +#include <dev/mii/mii.h> +#include <dev/mii/miivar.h> #include <dev/usb/usb.h> #include <dev/usb/usbdi.h> @@ -107,6 +111,8 @@ __FBSDID("$FreeBSD$"); #include <dev/usb/net/usb_ethernet.h> #include <dev/usb/net/if_auereg.h> +#include <rtems/bsd/local/miibus_if.h> + #ifdef USB_DEBUG static int aue_debug = 0; diff --git a/freebsd/sys/dev/usb/net/if_axe.c b/freebsd/sys/dev/usb/net/if_axe.c index cf54e96e..643b46ce 100644 --- a/freebsd/sys/dev/usb/net/if_axe.c +++ b/freebsd/sys/dev/usb/net/if_axe.c @@ -118,6 +118,8 @@ __FBSDID("$FreeBSD$"); #include <dev/usb/net/usb_ethernet.h> #include <dev/usb/net/if_axereg.h> +#include <rtems/bsd/local/miibus_if.h> + /* * AXE_178_MAX_FRAME_BURST * max frame burst size for Ax88178 and Ax88772 @@ -1149,7 +1151,7 @@ axe_rxeof(struct usb_ether *ue, struct usb_page_cache *pc, unsigned int offset, } } - _IF_ENQUEUE(&ue->ue_rxq, m); + (void)mbufq_enqueue(&ue->ue_rxq, m); return (0); } diff --git a/freebsd/sys/dev/usb/net/if_axge.c b/freebsd/sys/dev/usb/net/if_axge.c index f8ed34ae..564d5221 100644 --- a/freebsd/sys/dev/usb/net/if_axge.c +++ b/freebsd/sys/dev/usb/net/if_axge.c @@ -50,6 +50,10 @@ __FBSDID("$FreeBSD$"); #include <net/if.h> #include <net/if_var.h> +#include <net/if_media.h> + +#include <dev/mii/mii.h> +#include <dev/mii/miivar.h> #include <dev/usb/usb.h> #include <dev/usb/usbdi.h> @@ -63,6 +67,8 @@ __FBSDID("$FreeBSD$"); #include <dev/usb/net/usb_ethernet.h> #include <dev/usb/net/if_axgereg.h> +#include <rtems/bsd/local/miibus_if.h> + /* * Various supported device vendors/products. */ @@ -1037,7 +1043,7 @@ axge_rxeof(struct usb_ether *ue, struct usb_page_cache *pc, unsigned int offset, } if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1); - _IF_ENQUEUE(&ue->ue_rxq, m); + (void)mbufq_enqueue(&ue->ue_rxq, m); } static void diff --git a/freebsd/sys/dev/usb/net/if_cdce.c b/freebsd/sys/dev/usb/net/if_cdce.c index 9a15da69..6abe6653 100644 --- a/freebsd/sys/dev/usb/net/if_cdce.c +++ b/freebsd/sys/dev/usb/net/if_cdce.c @@ -52,11 +52,11 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); +#include <sys/gsb_crc32.h> +#include <sys/eventhandler.h> #include <sys/stdint.h> #include <sys/stddef.h> -#include <sys/param.h> #include <sys/queue.h> -#include <sys/types.h> #include <sys/systm.h> #include <sys/socket.h> #include <sys/kernel.h> @@ -278,6 +278,7 @@ static const STRUCT_USB_HOST_ID cdce_host_devs[] = { {USB_VPI(USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SLA300, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)}, {USB_VPI(USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SLC700, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)}, {USB_VPI(USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SLC750, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)}, + {USB_VPI(USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8156, 0)}, {USB_VENDOR(USB_VENDOR_HUAWEI), USB_IFACE_CLASS(UICLASS_VENDOR), USB_IFACE_SUBCLASS(0x02), USB_IFACE_PROTOCOL(0x16), diff --git a/freebsd/sys/dev/usb/net/if_mos.c b/freebsd/sys/dev/usb/net/if_mos.c index 3dd0e5ef..3ab0e62e 100644 --- a/freebsd/sys/dev/usb/net/if_mos.c +++ b/freebsd/sys/dev/usb/net/if_mos.c @@ -122,6 +122,10 @@ __FBSDID("$FreeBSD$"); #include <net/if.h> #include <net/if_var.h> +#include <net/if_media.h> + +#include <dev/mii/mii.h> +#include <dev/mii/miivar.h> #include <dev/usb/usb.h> #include <dev/usb/usbdi.h> @@ -134,6 +138,8 @@ __FBSDID("$FreeBSD$"); #include <dev/usb/net/usb_ethernet.h> +#include <rtems/bsd/local/miibus_if.h> + //#include <dev/usb/net/if_mosreg.h> #include "if_mosreg.h" diff --git a/freebsd/sys/dev/usb/net/if_rue.c b/freebsd/sys/dev/usb/net/if_rue.c index 810a98c8..8d095c86 100644 --- a/freebsd/sys/dev/usb/net/if_rue.c +++ b/freebsd/sys/dev/usb/net/if_rue.c @@ -91,6 +91,10 @@ __FBSDID("$FreeBSD$"); #include <net/if.h> #include <net/if_var.h> +#include <net/if_media.h> + +#include <dev/mii/mii.h> +#include <dev/mii/miivar.h> #include <dev/usb/usb.h> #include <dev/usb/usbdi.h> @@ -104,6 +108,8 @@ __FBSDID("$FreeBSD$"); #include <dev/usb/net/usb_ethernet.h> #include <dev/usb/net/if_ruereg.h> +#include <rtems/bsd/local/miibus_if.h> + #ifdef USB_DEBUG static int rue_debug = 0; diff --git a/freebsd/sys/dev/usb/net/if_smsc.c b/freebsd/sys/dev/usb/net/if_smsc.c index 87e181d8..bbf28ad8 100644 --- a/freebsd/sys/dev/usb/net/if_smsc.c +++ b/freebsd/sys/dev/usb/net/if_smsc.c @@ -89,6 +89,10 @@ __FBSDID("$FreeBSD$"); #include <net/if.h> #include <net/if_var.h> +#include <net/if_media.h> + +#include <dev/mii/mii.h> +#include <dev/mii/miivar.h> #include <netinet/in.h> #include <netinet/ip.h> @@ -99,6 +103,7 @@ __FBSDID("$FreeBSD$"); #include <dev/fdt/fdt_common.h> #include <dev/ofw/ofw_bus.h> #include <dev/ofw/ofw_bus_subr.h> +#include <dev/usb/usb_fdt_support.h> #endif #include <dev/usb/usb.h> @@ -114,6 +119,8 @@ __FBSDID("$FreeBSD$"); #include <dev/usb/net/if_smscreg.h> +#include <rtems/bsd/local/miibus_if.h> + #ifdef USB_DEBUG static int smsc_debug = 0; @@ -1561,147 +1568,6 @@ smsc_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) return (rc); } -#ifdef FDT -/* - * This is FreeBSD-specific compatibility strings for RPi/RPi2 - */ -static phandle_t -smsc_fdt_find_eth_node(phandle_t start) -{ - phandle_t child, node; - - /* Traverse through entire tree to find usb ethernet nodes. */ - for (node = OF_child(start); node != 0; node = OF_peer(node)) { - if ((ofw_bus_node_is_compatible(node, "net,ethernet") && - ofw_bus_node_is_compatible(node, "usb,device")) || - ofw_bus_node_is_compatible(node, "usb424,ec00")) - return (node); - child = smsc_fdt_find_eth_node(node); - if (child != -1) - return (child); - } - - return (-1); -} - -/* - * Check if node's path is <*>/usb/hub/ethernet - */ -static int -smsc_fdt_is_usb_eth(phandle_t node) -{ - char name[16]; - int len; - - memset(name, 0, sizeof(name)); - len = OF_getprop(node, "name", name, sizeof(name)); - if (len <= 0) - return (0); - - if (strcmp(name, "ethernet")) - return (0); - - node = OF_parent(node); - if (node == -1) - return (0); - len = OF_getprop(node, "name", name, sizeof(name)); - if (len <= 0) - return (0); - - if (strcmp(name, "hub")) - return (0); - - node = OF_parent(node); - if (node == -1) - return (0); - len = OF_getprop(node, "name", name, sizeof(name)); - if (len <= 0) - return (0); - - if (strcmp(name, "usb")) - return (0); - - return (1); -} - -static phandle_t -smsc_fdt_find_eth_node_by_path(phandle_t start) -{ - phandle_t child, node; - - /* Traverse through entire tree to find usb ethernet nodes. */ - for (node = OF_child(start); node != 0; node = OF_peer(node)) { - if (smsc_fdt_is_usb_eth(node)) - return (node); - child = smsc_fdt_find_eth_node_by_path(node); - if (child != -1) - return (child); - } - - return (-1); -} - -/* - * Look through known names that can contain mac address - * return 0 if valid MAC address has been found - */ -static int -smsc_fdt_read_mac_property(phandle_t node, unsigned char *mac) -{ - int len; - - /* Check if there is property */ - if ((len = OF_getproplen(node, "local-mac-address")) > 0) { - if (len != ETHER_ADDR_LEN) - return (EINVAL); - - OF_getprop(node, "local-mac-address", mac, - ETHER_ADDR_LEN); - return (0); - } - - if ((len = OF_getproplen(node, "mac-address")) > 0) { - if (len != ETHER_ADDR_LEN) - return (EINVAL); - - OF_getprop(node, "mac-address", mac, - ETHER_ADDR_LEN); - return (0); - } - - return (ENXIO); -} - -/** - * Get MAC address from FDT blob. Firmware or loader should fill - * mac-address or local-mac-address property. Returns 0 if MAC address - * obtained, error code otherwise. - */ -static int -smsc_fdt_find_mac(unsigned char *mac) -{ - phandle_t node, root; - - root = OF_finddevice("/"); - node = smsc_fdt_find_eth_node(root); - if (node != -1) { - if (smsc_fdt_read_mac_property(node, mac) == 0) - return (0); - } - - /* - * If it's not FreeBSD FDT blob for RPi, try more - * generic .../usb/hub/ethernet - */ - node = smsc_fdt_find_eth_node_by_path(root); - - if (node != -1) - return smsc_fdt_read_mac_property(node, mac); - - return (ENXIO); -} -#endif - /** * smsc_attach_post - Called after the driver attached to the USB interface * @ue: the USB ethernet device @@ -1750,7 +1616,7 @@ smsc_attach_post(struct usb_ether *ue) err = smsc_eeprom_read(sc, 0x01, sc->sc_ue.ue_eaddr, ETHER_ADDR_LEN); #ifdef FDT if ((err != 0) || (!ETHER_IS_VALID(sc->sc_ue.ue_eaddr))) - err = smsc_fdt_find_mac(sc->sc_ue.ue_eaddr); + err = usb_fdt_get_mac_addr(sc->sc_ue.ue_dev, &sc->sc_ue); #endif if ((err != 0) || (!ETHER_IS_VALID(sc->sc_ue.ue_eaddr))) { read_random(sc->sc_ue.ue_eaddr, ETHER_ADDR_LEN); diff --git a/freebsd/sys/dev/usb/net/if_udav.c b/freebsd/sys/dev/usb/net/if_udav.c index a4e683ac..8a2ad81f 100644 --- a/freebsd/sys/dev/usb/net/if_udav.c +++ b/freebsd/sys/dev/usb/net/if_udav.c @@ -72,12 +72,18 @@ __FBSDID("$FreeBSD$"); #include <net/if.h> #include <net/if_var.h> +#include <net/if_media.h> + +#include <dev/mii/mii.h> +#include <dev/mii/miivar.h> #include <dev/usb/usb.h> #include <dev/usb/usbdi.h> #include <dev/usb/usbdi_util.h> #include <rtems/bsd/local/usbdevs.h> +#include <rtems/bsd/local/miibus_if.h> + #define USB_DEBUG_VAR udav_debug #include <dev/usb/usb_debug.h> #include <dev/usb/usb_process.h> diff --git a/freebsd/sys/dev/usb/net/if_ure.c b/freebsd/sys/dev/usb/net/if_ure.c index 136b61f9..0130a7bb 100644 --- a/freebsd/sys/dev/usb/net/if_ure.c +++ b/freebsd/sys/dev/usb/net/if_ure.c @@ -43,6 +43,10 @@ __FBSDID("$FreeBSD$"); #include <net/if.h> #include <net/if_var.h> +#include <net/if_media.h> + +#include <dev/mii/mii.h> +#include <dev/mii/miivar.h> #include <dev/usb/usb.h> #include <dev/usb/usbdi.h> @@ -56,6 +60,8 @@ __FBSDID("$FreeBSD$"); #include <dev/usb/net/usb_ethernet.h> #include <dev/usb/net/if_urereg.h> +#include <rtems/bsd/local/miibus_if.h> + #ifdef USB_DEBUG static int ure_debug = 0; @@ -64,6 +70,9 @@ SYSCTL_INT(_hw_usb_ure, OID_AUTO, debug, CTLFLAG_RWTUN, &ure_debug, 0, "Debug level"); #endif +#define ETHER_IS_ZERO(addr) \ + (!(addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5])) + /* * Various supported device vendors/products. */ @@ -71,6 +80,7 @@ static const STRUCT_USB_HOST_ID ure_devs[] = { #define URE_DEV(v,p,i) { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, i) } URE_DEV(LENOVO, RTL8153, 0), URE_DEV(LENOVO, TBT3LAN, 0), + URE_DEV(LENOVO, ONELINK, 0), URE_DEV(LENOVO, USBCLAN, 0), URE_DEV(NVIDIA, RTL8153, 0), URE_DEV(REALTEK, RTL8152, URE_FLAG_8152), @@ -674,12 +684,20 @@ ure_attach_post(struct usb_ether *ue) else ure_rtl8153_init(sc); - if (sc->sc_chip & URE_CHIP_VER_4C00) + if ((sc->sc_chip & URE_CHIP_VER_4C00) || + (sc->sc_chip & URE_CHIP_VER_4C10)) ure_read_mem(sc, URE_PLA_IDR, URE_MCU_TYPE_PLA, ue->ue_eaddr, 8); else ure_read_mem(sc, URE_PLA_BACKUP, URE_MCU_TYPE_PLA, ue->ue_eaddr, 8); + + if (ETHER_IS_ZERO(sc->sc_ue.ue_eaddr)) { + device_printf(sc->sc_ue.ue_dev, "MAC assigned randomly\n"); + arc4rand(sc->sc_ue.ue_eaddr, ETHER_ADDR_LEN, 0); + sc->sc_ue.ue_eaddr[0] &= ~0x01; /* unicast */ + sc->sc_ue.ue_eaddr[0] |= 0x02; /* locally administered */ + } } static int @@ -725,8 +743,10 @@ ure_init(struct usb_ether *ue) ure_reset(sc); /* Set MAC address. */ + ure_write_1(sc, URE_PLA_CRWECR, URE_MCU_TYPE_PLA, URE_CRWECR_CONFIG); ure_write_mem(sc, URE_PLA_IDR, URE_MCU_TYPE_PLA | URE_BYTE_EN_SIX_BYTES, IF_LLADDR(ifp), 8); + ure_write_1(sc, URE_PLA_CRWECR, URE_MCU_TYPE_PLA, URE_CRWECR_NORAML); /* Reset the packet filter. */ ure_write_2(sc, URE_PLA_FMC, URE_MCU_TYPE_PLA, diff --git a/freebsd/sys/dev/usb/net/if_urereg.h b/freebsd/sys/dev/usb/net/if_urereg.h index 8eff1c25..cc70093f 100644 --- a/freebsd/sys/dev/usb/net/if_urereg.h +++ b/freebsd/sys/dev/usb/net/if_urereg.h @@ -176,7 +176,7 @@ #define URE_EEEP_CR_EEEP_TX 0x0002 /* PLA_WDT6_CTRL */ -#define URE_WDT6_SET_MODE 0x001 +#define URE_WDT6_SET_MODE 0x0010 /* PLA_TCR0 */ #define URE_TCR0_TX_EMPTY 0x0800 diff --git a/freebsd/sys/dev/usb/net/usb_ethernet.c b/freebsd/sys/dev/usb/net/usb_ethernet.c index 9ce60eff..2bbcdedc 100644 --- a/freebsd/sys/dev/usb/net/usb_ethernet.c +++ b/freebsd/sys/dev/usb/net/usb_ethernet.c @@ -221,6 +221,7 @@ ue_attach_post_task(struct usb_proc_msg *_task) ue->ue_unit = alloc_unr(ueunit); usb_callout_init_mtx(&ue->ue_watchdog, ue->ue_mtx, 0); sysctl_ctx_init(&ue->ue_sysctl_ctx); + mbufq_init(&ue->ue_rxq, 0 /* unlimited length */); error = 0; CURVNET_SET_QUIET(vnet0); @@ -286,6 +287,11 @@ ue_attach_post_task(struct usb_proc_msg *_task) fail: CURVNET_RESTORE(); + + /* drain mbuf queue */ + mbufq_drain(&ue->ue_rxq); + + /* free unit */ free_unr(ueunit, ue->ue_unit); if (ue->ue_ifp != NULL) { if_free(ue->ue_ifp); @@ -332,6 +338,9 @@ uether_ifdetach(struct usb_ether *ue) /* free sysctl */ sysctl_ctx_free(&ue->ue_sysctl_ctx); + /* drain mbuf queue */ + mbufq_drain(&ue->ue_rxq); + /* free unit */ free_unr(ueunit, ue->ue_unit); } @@ -600,7 +609,7 @@ uether_rxmbuf(struct usb_ether *ue, struct mbuf *m, m->m_pkthdr.len = m->m_len = len; /* enqueue for later when the lock can be released */ - _IF_ENQUEUE(&ue->ue_rxq, m); + (void)mbufq_enqueue(&ue->ue_rxq, m); return (0); } @@ -630,7 +639,7 @@ uether_rxbuf(struct usb_ether *ue, struct usb_page_cache *pc, m->m_pkthdr.len = m->m_len = len; /* enqueue for later when the lock can be released */ - _IF_ENQUEUE(&ue->ue_rxq, m); + (void)mbufq_enqueue(&ue->ue_rxq, m); return (0); } @@ -643,7 +652,7 @@ uether_rxflush(struct usb_ether *ue) UE_LOCK_ASSERT(ue, MA_OWNED); for (;;) { - _IF_DEQUEUE(&ue->ue_rxq, m); + m = mbufq_dequeue(&ue->ue_rxq); if (m == NULL) break; diff --git a/freebsd/sys/dev/usb/net/usb_ethernet.h b/freebsd/sys/dev/usb/net/usb_ethernet.h index 9839db16..87886559 100644 --- a/freebsd/sys/dev/usb/net/usb_ethernet.h +++ b/freebsd/sys/dev/usb/net/usb_ethernet.h @@ -48,11 +48,7 @@ #include <net/bpf.h> #include <net/ethernet.h> -#include <rtems/bsd/local/miibus_if.h> - -#include <dev/mii/mii.h> -#include <dev/mii/miivar.h> - +struct mii_data; struct usb_ether; struct usb_device_request; @@ -91,7 +87,7 @@ struct usb_ether { struct usb_process ue_tq; struct sysctl_ctx_list ue_sysctl_ctx; - struct ifqueue ue_rxq; + struct mbufq ue_rxq; struct usb_callout ue_watchdog; struct usb_ether_cfg_task ue_sync_task[2]; struct usb_ether_cfg_task ue_media_task[2]; diff --git a/freebsd/sys/dev/usb/quirk/usb_quirk.c b/freebsd/sys/dev/usb/quirk/usb_quirk.c index 2aea57c8..6c1589e9 100644 --- a/freebsd/sys/dev/usb/quirk/usb_quirk.c +++ b/freebsd/sys/dev/usb/quirk/usb_quirk.c @@ -98,10 +98,12 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = { USB_QUIRK(TELEX, MIC1, 0x009, 0x009, UQ_AU_NO_FRAC), USB_QUIRK(SILICONPORTALS, YAPPHONE, 0x100, 0x100, UQ_AU_INP_ASYNC), USB_QUIRK(LOGITECH, UN53B, 0x0000, 0xffff, UQ_NO_STRINGS), + USB_QUIRK(LOGITECH, G510S, 0x0000, 0xFFFF, UQ_KBD_BOOTPROTO), USB_QUIRK(REALTEK, RTL8196EU, 0x0000, 0xffff, UQ_CFG_INDEX_1), USB_QUIRK(ELSA, MODEM1, 0x0000, 0xffff, UQ_CFG_INDEX_1), USB_QUIRK(PLANEX2, MZKUE150N, 0x0000, 0xffff, UQ_CFG_INDEX_1), USB_QUIRK(CISCOLINKSYS, USB3GIGV1, 0x0000, 0xffff, UQ_CFG_INDEX_1), + USB_QUIRK(REALTEK, RTL8156, 0x0000, 0xffff, UQ_CFG_INDEX_2), /* Quirks for printer devices */ USB_QUIRK(HP, 895C, 0x0000, 0xffff, UQ_BROKEN_BIDIR), USB_QUIRK(HP, 880C, 0x0000, 0xffff, UQ_BROKEN_BIDIR), @@ -112,8 +114,19 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = { USB_QUIRK(XEROX, WCM15, 0x0000, 0xffff, UQ_BROKEN_BIDIR), /* Devices which should be ignored by uhid */ USB_QUIRK(APC, UPS, 0x0000, 0xffff, UQ_HID_IGNORE), + USB_QUIRK(BELKIN, F6H375USB, 0x0000, 0xffff, UQ_HID_IGNORE), USB_QUIRK(BELKIN, F6C550AVR, 0x0000, 0xffff, UQ_HID_IGNORE), + USB_QUIRK(BELKIN, F6C1250TWRK, 0x0000, 0xffff, UQ_HID_IGNORE), + USB_QUIRK(BELKIN, F6C1500TWRK, 0x0000, 0xffff, UQ_HID_IGNORE), + USB_QUIRK(BELKIN, F6C900UNV, 0x0000, 0xffff, UQ_HID_IGNORE), + USB_QUIRK(BELKIN, F6C100UNV, 0x0000, 0xffff, UQ_HID_IGNORE), + USB_QUIRK(BELKIN, F6C120UNV, 0x0000, 0xffff, UQ_HID_IGNORE), + USB_QUIRK(BELKIN, F6C800UNV, 0x0000, 0xffff, UQ_HID_IGNORE), + USB_QUIRK(BELKIN, F6C1100UNV, 0x0000, 0xffff, UQ_HID_IGNORE), + USB_QUIRK(CYBERPOWER, BC900D, 0x0000, 0xffff, UQ_HID_IGNORE), USB_QUIRK(CYBERPOWER, 1500CAVRLCD, 0x0000, 0xffff, UQ_HID_IGNORE), + USB_QUIRK(CYBERPOWER, OR2200LCDRM2U, 0x0000, 0xffff, UQ_HID_IGNORE), + USB_QUIRK(DELL2, VARIOUS_UPS, 0x0000, 0xffff, UQ_HID_IGNORE), USB_QUIRK(CYPRESS, SILVERSHIELD, 0x0000, 0xffff, UQ_HID_IGNORE), USB_QUIRK(DELORME, EARTHMATE, 0x0000, 0xffff, UQ_HID_IGNORE), USB_QUIRK(DREAMLINK, DL100B, 0x0000, 0xffff, UQ_HID_IGNORE), @@ -121,8 +134,26 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = { USB_QUIRK(ITUNERNET, USBLCD4X20, 0x0000, 0xffff, UQ_HID_IGNORE), USB_QUIRK(LIEBERT, POWERSURE_PXT, 0x0000, 0xffff, UQ_HID_IGNORE), USB_QUIRK(LIEBERT2, PSI1000, 0x0000, 0xffff, UQ_HID_IGNORE), + USB_QUIRK(LIEBERT2, POWERSURE_PSA, 0x0000, 0xffff, UQ_HID_IGNORE), USB_QUIRK(MGE, UPS1, 0x0000, 0xffff, UQ_HID_IGNORE), USB_QUIRK(MGE, UPS2, 0x0000, 0xffff, UQ_HID_IGNORE), + USB_QUIRK(POWERCOM, IMPERIAL_SERIES, 0x0000, 0xffff, UQ_HID_IGNORE), + USB_QUIRK(POWERCOM, SMART_KING_PRO, 0x0000, 0xffff, UQ_HID_IGNORE), + USB_QUIRK(POWERCOM, WOW, 0x0000, 0xffff, UQ_HID_IGNORE), + USB_QUIRK(POWERCOM, VANGUARD, 0x0000, 0xffff, UQ_HID_IGNORE), + USB_QUIRK(POWERCOM, BLACK_KNIGHT_PRO, 0x0000, 0xffff, UQ_HID_IGNORE), + USB_QUIRK(TRIPPLITE2, AVR550U, 0x0000, 0xffff, UQ_HID_IGNORE), + USB_QUIRK(TRIPPLITE2, AVR750U, 0x0000, 0xffff, UQ_HID_IGNORE), + USB_QUIRK(TRIPPLITE2, ECO550UPS, 0x0000, 0xffff, UQ_HID_IGNORE), + USB_QUIRK(TRIPPLITE2, T750_INTL, 0x0000, 0xffff, UQ_HID_IGNORE), + USB_QUIRK(TRIPPLITE2, RT_2200_INTL, 0x0000, 0xffff, UQ_HID_IGNORE), + USB_QUIRK(TRIPPLITE2, OMNI1000LCD, 0x0000, 0xffff, UQ_HID_IGNORE), + USB_QUIRK(TRIPPLITE2, OMNI900LCD, 0x0000, 0xffff, UQ_HID_IGNORE), + USB_QUIRK(TRIPPLITE2, SMART_2200RMXL2U, 0x0000, 0xffff, UQ_HID_IGNORE), + USB_QUIRK(TRIPPLITE2, UPS_3014, 0x0000, 0xffff, UQ_HID_IGNORE), + USB_QUIRK(TRIPPLITE2, SU1500RTXL2UA, 0x0000, 0xffff, UQ_HID_IGNORE), + USB_QUIRK(TRIPPLITE2, SU6000RT4U, 0x0000, 0xffff, UQ_HID_IGNORE), + USB_QUIRK(TRIPPLITE2, SU1500RTXL2UA_2, 0x0000, 0xffff, UQ_HID_IGNORE), USB_QUIRK(APPLE, IPHONE, 0x0000, 0xffff, UQ_HID_IGNORE), USB_QUIRK(APPLE, IPHONE_3G, 0x0000, 0xffff, UQ_HID_IGNORE), USB_QUIRK(MEGATEC, UPS, 0x0000, 0xffff, UQ_HID_IGNORE), @@ -137,12 +168,15 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = { USB_QUIRK(MICROSOFT, WLINTELLIMOUSE, 0x0000, 0xffff, UQ_MS_LEADING_BYTE), /* Quirk for Corsair Vengeance K60 keyboard */ USB_QUIRK(CORSAIR, K60, 0x0000, 0xffff, UQ_KBD_BOOTPROTO), + /* Quirk for Corsair Gaming K68 keyboard */ + USB_QUIRK(CORSAIR, K68, 0x0000, 0xffff, UQ_KBD_BOOTPROTO), /* Quirk for Corsair Vengeance K70 keyboard */ USB_QUIRK(CORSAIR, K70, 0x0000, 0xffff, UQ_KBD_BOOTPROTO), /* Quirk for Corsair K70 RGB keyboard */ USB_QUIRK(CORSAIR, K70_RGB, 0x0000, 0xffff, UQ_KBD_BOOTPROTO), /* Quirk for Corsair STRAFE Gaming keyboard */ USB_QUIRK(CORSAIR, STRAFE, 0x0000, 0xffff, UQ_KBD_BOOTPROTO), + USB_QUIRK(CORSAIR, STRAFE2, 0x0000, 0xffff, UQ_KBD_BOOTPROTO), /* umodem(4) device quirks */ USB_QUIRK(METRICOM, RICOCHET_GS, 0x100, 0x100, UQ_ASSUME_CM_OVER_DATA), USB_QUIRK(SANYO, SCP4900, 0x000, 0x000, UQ_ASSUME_CM_OVER_DATA), @@ -188,6 +222,8 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = { USB_QUIRK(CENTURY, EX35QUAT, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_FORCE_SHORT_INQ, UQ_MSC_NO_START_STOP, UQ_MSC_IGNORE_RESIDUE), + USB_QUIRK(CREATIVE, NOMAD, 0x0001, 0xffff, UQ_MSC_FORCE_WIRE_BBB, + UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_READ_CAP_OFFBY1), USB_QUIRK(CYPRESS, XX6830XX, 0x0000, 0xffff, UQ_MSC_NO_GETMAXLUN, UQ_MSC_NO_SYNC_CACHE), USB_QUIRK(DESKNOTE, UCR_61S2B, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB, @@ -240,7 +276,7 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = { UQ_MSC_FORCE_PROTO_RBC), USB_QUIRK(INSYSTEM, STORAGE_V2, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_RBC), - USB_QUIRK(INTENSO, MEMORY_BOX, 0x0000, 0xffff, UQ_MSC_NO_INQUIRY), + USB_QUIRK(VIALABS, VL701, 0x0000, 0xffff, UQ_MSC_NO_INQUIRY), USB_QUIRK(IODATA, IU_CD2, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI), USB_QUIRK(IODATA, DVR_UEH8, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB, @@ -248,6 +284,7 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = { USB_QUIRK(IOMEGA, ZIP100, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_TEST_UNIT_READY), /* XXX ZIP drives can also use ATAPI */ + USB_QUIRK(JMICRON, JMS566, 0x0000, 0xffff, UQ_MSC_NO_GETMAXLUN), USB_QUIRK(JMICRON, JMS567, 0x0000, 0xffff, UQ_MSC_NO_GETMAXLUN), USB_QUIRK(JMICRON, JM20337, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI, @@ -362,6 +399,8 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = { UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_IGNORE_RESIDUE), USB_QUIRK(SANDISK, SDCZ4_256, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_IGNORE_RESIDUE), + USB_QUIRK(SANDISK, SDCZ48_32, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE, + UQ_MSC_NO_TEST_UNIT_READY), USB_QUIRK(SANDISK, SDDR31, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_READ_CAP_OFFBY1), USB_QUIRK(SANDISK, IMAGEMATE_SDDR289, 0x0000, 0xffff, @@ -498,6 +537,7 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = { USB_QUIRK(VIALABS, USB30SATABRIDGE, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE), USB_QUIRK(QUALCOMMINC, ZTE_MF730M, 0x0000, 0xffff, UQ_MSC_NO_GETMAXLUN, UQ_MSC_NO_INQUIRY, UQ_CFG_INDEX_0), + USB_QUIRK(SMART2, G2MEMKEY, 0x0000, 0xffff, UQ_MSC_NO_INQUIRY), /* Non-standard USB MIDI devices */ USB_QUIRK(ROLAND, UM1, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS), USB_QUIRK(ROLAND, SC8850, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS), @@ -528,6 +568,8 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = { USB_QUIRK(MAUDIO, FASTTRACKULTRA, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS), USB_QUIRK(MAUDIO, FASTTRACKULTRA8R, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS), USB_QUIRK(CMEDIA, CM6206, 0x0000, 0xffff, UQ_AU_SET_SPDIF_CM6206), + USB_QUIRK(PLOYTEC, SPL_CRIMSON_1, 0x0000, 0xffff, UQ_CFG_INDEX_1), + USB_QUIRK(ROLAND, UA25EX_AD, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS), /* * Quirks for manufacturers which USB devices does not respond diff --git a/freebsd/sys/dev/usb/serial/u3g.c b/freebsd/sys/dev/usb/serial/u3g.c index 8d72ef49..dd82a2b2 100644 --- a/freebsd/sys/dev/usb/serial/u3g.c +++ b/freebsd/sys/dev/usb/serial/u3g.c @@ -33,11 +33,11 @@ */ +#include <sys/param.h> +#include <sys/eventhandler.h> #include <sys/stdint.h> #include <sys/stddef.h> -#include <sys/param.h> #include <sys/queue.h> -#include <sys/types.h> #include <sys/systm.h> #include <sys/kernel.h> #include <sys/bus.h> diff --git a/freebsd/sys/dev/usb/serial/ugensa.c b/freebsd/sys/dev/usb/serial/ugensa.c index 2737227c..10a3ea33 100644 --- a/freebsd/sys/dev/usb/serial/ugensa.c +++ b/freebsd/sys/dev/usb/serial/ugensa.c @@ -72,6 +72,7 @@ #define UGENSA_CONFIG_INDEX 0 #define UGENSA_IFACE_INDEX 0 #define UGENSA_IFACE_MAX 8 /* exclusivly */ +#define UGENSA_PORT_MAX 8 /* exclusivly */ enum { UGENSA_BULK_DT_WR, @@ -86,11 +87,11 @@ struct ugensa_sub_softc { struct ugensa_softc { struct ucom_super_softc sc_super_ucom; - struct ucom_softc sc_ucom[UGENSA_IFACE_MAX]; - struct ugensa_sub_softc sc_sub[UGENSA_IFACE_MAX]; + struct ucom_softc sc_ucom[UGENSA_PORT_MAX]; + struct ugensa_sub_softc sc_sub[UGENSA_PORT_MAX]; struct mtx sc_mtx; - uint8_t sc_niface; + uint8_t sc_nports; }; /* prototypes */ @@ -156,12 +157,13 @@ static driver_t ugensa_driver = { .size = sizeof(struct ugensa_softc), }; +/* Driver-info is max number of serial ports per interface */ static const STRUCT_USB_HOST_ID ugensa_devs[] = { - {USB_VPI(USB_VENDOR_AIRPRIME, USB_PRODUCT_AIRPRIME_PC5220, 0)}, - {USB_VPI(USB_VENDOR_CMOTECH, USB_PRODUCT_CMOTECH_CDMA_MODEM1, 0)}, - {USB_VPI(USB_VENDOR_KYOCERA2, USB_PRODUCT_KYOCERA2_CDMA_MSM_K, 0)}, - {USB_VPI(USB_VENDOR_HP, USB_PRODUCT_HP_49GPLUS, 0)}, - {USB_VPI(USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_FLEXPACKGPS, 0)}, + {USB_VPI(USB_VENDOR_AIRPRIME, USB_PRODUCT_AIRPRIME_PC5220, 1)}, + {USB_VPI(USB_VENDOR_CMOTECH, USB_PRODUCT_CMOTECH_CDMA_MODEM1, 1)}, + {USB_VPI(USB_VENDOR_KYOCERA2, USB_PRODUCT_KYOCERA2_CDMA_MSM_K, 1)}, + {USB_VPI(USB_VENDOR_HP, USB_PRODUCT_HP_49GPLUS, 1)}, + {USB_VPI(USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_FLEXPACKGPS, 3)}, }; DRIVER_MODULE(ugensa, uhub, ugensa_driver, ugensa_devclass, NULL, 0); @@ -194,65 +196,68 @@ ugensa_attach(device_t dev) struct ugensa_softc *sc = device_get_softc(dev); struct ugensa_sub_softc *ssc; struct usb_interface *iface; + struct usb_config xfer_config[UGENSA_N_TRANSFER]; int32_t error; uint8_t iface_index; - int x, cnt; + int x, maxports; + maxports = USB_GET_DRIVER_INFO(uaa); device_set_usb_desc(dev); mtx_init(&sc->sc_mtx, "ugensa", NULL, MTX_DEF); ucom_ref(&sc->sc_super_ucom); - /* Figure out how many interfaces this device has got */ - for (cnt = 0; cnt < UGENSA_IFACE_MAX; cnt++) { - if ((usbd_get_endpoint(uaa->device, cnt, ugensa_xfer_config + 0) == NULL) || - (usbd_get_endpoint(uaa->device, cnt, ugensa_xfer_config + 1) == NULL)) { - /* we have reached the end */ - break; - } - } + for (iface_index = UGENSA_IFACE_INDEX; iface_index < UGENSA_IFACE_MAX; iface_index++) { - if (cnt == 0) { - device_printf(dev, "No interfaces\n"); - goto detach; - } - for (x = 0; x < cnt; x++) { - iface = usbd_get_iface(uaa->device, x); - if (iface->idesc->bInterfaceClass != UICLASS_VENDOR) + iface = usbd_get_iface(uaa->device, iface_index); + if (iface == NULL || iface->idesc->bInterfaceClass != UICLASS_VENDOR) /* Not a serial port, most likely a SD reader */ continue; - ssc = sc->sc_sub + sc->sc_niface; - ssc->sc_ucom_ptr = sc->sc_ucom + sc->sc_niface; - - iface_index = (UGENSA_IFACE_INDEX + x); - error = usbd_transfer_setup(uaa->device, - &iface_index, ssc->sc_xfer, ugensa_xfer_config, - UGENSA_N_TRANSFER, ssc, &sc->sc_mtx); - - if (error) { - device_printf(dev, "allocating USB " - "transfers failed\n"); - goto detach; + /* Loop over all endpoints pairwise */ + for (x = 0; x < maxports && sc->sc_nports < UGENSA_PORT_MAX; x++) { + + ssc = sc->sc_sub + sc->sc_nports; + ssc->sc_ucom_ptr = sc->sc_ucom + sc->sc_nports; + + memcpy(xfer_config, ugensa_xfer_config, sizeof ugensa_xfer_config); + xfer_config[UGENSA_BULK_DT_RD].ep_index = x; + xfer_config[UGENSA_BULK_DT_WR].ep_index = x; + + error = usbd_transfer_setup(uaa->device, + &iface_index, ssc->sc_xfer, xfer_config, + UGENSA_N_TRANSFER, ssc, &sc->sc_mtx); + + if (error) { + if (x == 0) { + device_printf(dev, "allocating USB " + "transfers failed (%d)\n", error); + goto detach; + } + break; + } + + /* clear stall at first run */ + mtx_lock(&sc->sc_mtx); + usbd_xfer_set_stall(ssc->sc_xfer[UGENSA_BULK_DT_WR]); + usbd_xfer_set_stall(ssc->sc_xfer[UGENSA_BULK_DT_RD]); + mtx_unlock(&sc->sc_mtx); + + /* initialize port number */ + ssc->sc_ucom_ptr->sc_portno = sc->sc_nports; + if (iface_index != uaa->info.bIfaceIndex) { + usbd_set_parent_iface(uaa->device, iface_index, + uaa->info.bIfaceIndex); + } + sc->sc_nports++; } - /* clear stall at first run */ - mtx_lock(&sc->sc_mtx); - usbd_xfer_set_stall(ssc->sc_xfer[UGENSA_BULK_DT_WR]); - usbd_xfer_set_stall(ssc->sc_xfer[UGENSA_BULK_DT_RD]); - mtx_unlock(&sc->sc_mtx); - - /* initialize port number */ - ssc->sc_ucom_ptr->sc_portno = sc->sc_niface; - sc->sc_niface++; - if (x != uaa->info.bIfaceIndex) - usbd_set_parent_iface(uaa->device, x, - uaa->info.bIfaceIndex); } - device_printf(dev, "Found %d interfaces.\n", sc->sc_niface); + device_printf(dev, "Found %d serial ports.\n", sc->sc_nports); - error = ucom_attach(&sc->sc_super_ucom, sc->sc_ucom, sc->sc_niface, sc, + error = ucom_attach(&sc->sc_super_ucom, sc->sc_ucom, sc->sc_nports, sc, &ugensa_callback, &sc->sc_mtx); + if (error) { - DPRINTF("attach failed\n"); + DPRINTF("ucom attach failed\n"); goto detach; } ucom_set_pnpinfo_usb(&sc->sc_super_ucom, dev); @@ -272,7 +277,7 @@ ugensa_detach(device_t dev) ucom_detach(&sc->sc_super_ucom, sc->sc_ucom); - for (x = 0; x < sc->sc_niface; x++) { + for (x = 0; x < sc->sc_nports; x++) { usbd_transfer_unsetup(sc->sc_sub[x].sc_xfer, UGENSA_N_TRANSFER); } diff --git a/freebsd/sys/dev/usb/serial/umcs.c b/freebsd/sys/dev/usb/serial/umcs.c index 8f083ce3..3a5fc70f 100644 --- a/freebsd/sys/dev/usb/serial/umcs.c +++ b/freebsd/sys/dev/usb/serial/umcs.c @@ -501,7 +501,9 @@ umcs7840_cfg_open(struct ucom_softc *ucom) * Enable DTR/RTS on modem control, enable modem interrupts -- * documented */ - sc->sc_ports[pn].sc_mcr = MCS7840_UART_MCR_DTR | MCS7840_UART_MCR_RTS | MCS7840_UART_MCR_IE; + sc->sc_ports[pn].sc_mcr = MCS7840_UART_MCR_IE; + if (ucom->sc_tty == NULL || (ucom->sc_tty->t_termios.c_cflag & CNO_RTSDTR) == 0) + sc->sc_ports[pn].sc_mcr |= MCS7840_UART_MCR_DTR | MCS7840_UART_MCR_RTS; if (umcs7840_set_UART_reg_sync(sc, pn, MCS7840_UART_REG_MCR, sc->sc_ports[pn].sc_mcr)) return; diff --git a/freebsd/sys/dev/usb/serial/usb_serial.c b/freebsd/sys/dev/usb/serial/usb_serial.c index a3f9b5de..c649056a 100644 --- a/freebsd/sys/dev/usb/serial/usb_serial.c +++ b/freebsd/sys/dev/usb/serial/usb_serial.c @@ -810,7 +810,8 @@ ucom_open(struct tty *tp) &sc->sc_start_task[0].hdr, &sc->sc_start_task[1].hdr); - ucom_modem(tp, SER_DTR | SER_RTS, 0); + if (sc->sc_tty == NULL || (sc->sc_tty->t_termios.c_cflag & CNO_RTSDTR) == 0) + ucom_modem(tp, SER_DTR | SER_RTS, 0); ucom_ring(sc, 0); diff --git a/freebsd/sys/dev/usb/usb.h b/freebsd/sys/dev/usb/usb.h index ff33cf00..0075d429 100644 --- a/freebsd/sys/dev/usb/usb.h +++ b/freebsd/sys/dev/usb/usb.h @@ -444,6 +444,7 @@ typedef struct usb_interface_assoc_descriptor usb_interface_assoc_descriptor_t; #define UIPROTO_CDC_NONE 0 #define UIPROTO_CDC_AT 1 +#define UIPROTO_CDC_EEM 7 #define UICLASS_HID 0x03 #define UISUBCLASS_BOOT 1 diff --git a/freebsd/sys/dev/usb/usb_bus.h b/freebsd/sys/dev/usb/usb_bus.h index 710436c1..9f8586e6 100644 --- a/freebsd/sys/dev/usb/usb_bus.h +++ b/freebsd/sys/dev/usb/usb_bus.h @@ -131,6 +131,7 @@ struct usb_bus { uint8_t do_probe; /* set if USB should be re-probed */ uint8_t no_explore; /* don't explore USB ports */ uint8_t dma_bits; /* number of DMA address lines */ + uint8_t control_ep_quirk; /* need 64kByte buffer for data stage */ }; #endif /* _USB_BUS_H_ */ diff --git a/freebsd/sys/dev/usb/usb_device.c b/freebsd/sys/dev/usb/usb_device.c index 5d6b9d0f..ee240949 100644 --- a/freebsd/sys/dev/usb/usb_device.c +++ b/freebsd/sys/dev/usb/usb_device.c @@ -34,8 +34,8 @@ #include <sys/stdint.h> #include <sys/stddef.h> #include <sys/param.h> +#include <sys/eventhandler.h> #include <sys/queue.h> -#include <sys/types.h> #include <sys/systm.h> #include <sys/kernel.h> #include <sys/bus.h> diff --git a/freebsd/sys/dev/usb/usb_fdt_support.h b/freebsd/sys/dev/usb/usb_fdt_support.h new file mode 100644 index 00000000..e4249e85 --- /dev/null +++ b/freebsd/sys/dev/usb/usb_fdt_support.h @@ -0,0 +1,48 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Ian Lepore <ian@FreeBSD.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _USB_FDT_SUPPORT_H_ +#define _USB_FDT_SUPPORT_H_ + +struct usb_device; +struct usb_ether; + +/* + * Get the device's MAC address from the FDT data. Fills in ue->ue_eaddr and + * returns 0 on success, otherwise leaves ue_eaddr untouched and returns + * non-zero. This first attempts to get the address from the "mac-address" + * property, and if that's not valid it tries the "local-mac-address" property; + * this matches the linux interpretation of the precedence of those properties. + */ +int usb_fdt_get_mac_addr(device_t dev, struct usb_ether* ue); + +/* Get the FDT node for dev. Returns -1 if dev is not in the FDT data. */ +phandle_t usb_fdt_get_node(device_t dev, struct usb_device* udev); + +#endif diff --git a/freebsd/sys/dev/usb/usb_generic.c b/freebsd/sys/dev/usb/usb_generic.c index 29a27d53..6d359226 100644 --- a/freebsd/sys/dev/usb/usb_generic.c +++ b/freebsd/sys/dev/usb/usb_generic.c @@ -185,7 +185,8 @@ ugen_open(struct usb_fifo *f, int fflags) struct usb_endpoint_descriptor *ed = ep->edesc; uint8_t type; - DPRINTFN(6, "flag=0x%x\n", fflags); + DPRINTFN(1, "flag=0x%x pid=%d name=%s\n", fflags, + curthread->td_proc->p_pid, curthread->td_proc->p_comm); mtx_lock(f->priv_mtx); switch (usbd_get_speed(f->udev)) { @@ -215,7 +216,9 @@ ugen_open(struct usb_fifo *f, int fflags) static void ugen_close(struct usb_fifo *f, int fflags) { - DPRINTFN(6, "flag=0x%x\n", fflags); + + DPRINTFN(1, "flag=0x%x pid=%d name=%s\n", fflags, + curthread->td_proc->p_pid, curthread->td_proc->p_comm); /* cleanup */ @@ -1218,6 +1221,40 @@ complete: } static int +ugen_fs_copy_out_cancelled(struct usb_fs_endpoint *fs_ep_uptr) +{ + struct usb_fs_endpoint fs_ep; + int error; + + error = copyin(fs_ep_uptr, &fs_ep, sizeof(fs_ep)); + if (error) + return (error); + + fs_ep.status = USB_ERR_CANCELLED; + fs_ep.aFrames = 0; + fs_ep.isoc_time_complete = 0; + + /* update "aFrames" */ + error = copyout(&fs_ep.aFrames, &fs_ep_uptr->aFrames, + sizeof(fs_ep.aFrames)); + if (error) + goto done; + + /* update "isoc_time_complete" */ + error = copyout(&fs_ep.isoc_time_complete, + &fs_ep_uptr->isoc_time_complete, + sizeof(fs_ep.isoc_time_complete)); + if (error) + goto done; + + /* update "status" */ + error = copyout(&fs_ep.status, &fs_ep_uptr->status, + sizeof(fs_ep.status)); +done: + return (error); +} + +static int ugen_fs_copy_out(struct usb_fifo *f, uint8_t ep_index) { struct usb_device_request *req; @@ -1242,7 +1279,12 @@ ugen_fs_copy_out(struct usb_fifo *f, uint8_t ep_index) return (EINVAL); mtx_lock(f->priv_mtx); - if (usbd_transfer_pending(xfer)) { + if (!xfer->flags_int.transferring && + !xfer->flags_int.started) { + mtx_unlock(f->priv_mtx); + DPRINTF("Returning fake cancel event\n"); + return (ugen_fs_copy_out_cancelled(f->fs_ep_ptr + ep_index)); + } else if (usbd_transfer_pending(xfer)) { mtx_unlock(f->priv_mtx); return (EBUSY); /* should not happen */ } @@ -1363,6 +1405,7 @@ complete: sizeof(fs_ep.isoc_time_complete)); if (error) goto done; + /* update "status" */ error = copyout(&fs_ep.status, &fs_ep_uptr->status, sizeof(fs_ep.status)); @@ -1451,12 +1494,15 @@ ugen_ioctl(struct usb_fifo *f, u_long cmd, void *addr, int fflags) xfer = f->fs_xfer[u.pstart->ep_index]; if (usbd_transfer_pending(xfer)) { usbd_transfer_stop(xfer); + /* * Check if the USB transfer was stopped - * before it was even started. Else a cancel - * callback will be pending. + * before it was even started and fake a + * cancel event. */ - if (!xfer->flags_int.transferring) { + if (!xfer->flags_int.transferring && + !xfer->flags_int.started) { + DPRINTF("Issuing fake completion event\n"); ugen_fs_set_complete(xfer->priv_sc, USB_P2U(xfer->priv_fifo)); } diff --git a/freebsd/sys/dev/usb/usb_hid.c b/freebsd/sys/dev/usb/usb_hid.c index 7ae052b7..21289f0d 100644 --- a/freebsd/sys/dev/usb/usb_hid.c +++ b/freebsd/sys/dev/usb/usb_hid.c @@ -76,7 +76,7 @@ static uint8_t hid_get_byte(struct hid_data *s, const uint16_t wSize); #define MAXUSAGE 64 #define MAXPUSH 4 #define MAXID 16 -#define MAXLOCCNT 1024 +#define MAXLOCCNT 2048 struct hid_pos_data { int32_t rid; diff --git a/freebsd/sys/dev/usb/usb_hub.c b/freebsd/sys/dev/usb/usb_hub.c index a0ad462f..b3543a8f 100644 --- a/freebsd/sys/dev/usb/usb_hub.c +++ b/freebsd/sys/dev/usb/usb_hub.c @@ -77,14 +77,9 @@ #include <dev/usb/usb_bus.h> #endif /* USB_GLOBAL_INCLUDE_FILE */ -#define UHUB_INTR_INTERVAL 250 /* ms */ -enum { - UHUB_INTR_TRANSFER, -#if USB_HAVE_TT_SUPPORT - UHUB_RESET_TT_TRANSFER, -#endif - UHUB_N_TRANSFER, -}; + +#include <dev/usb/usb_hub_private.h> + #ifdef USB_DEBUG static int uhub_debug = 0; @@ -113,27 +108,6 @@ SYSCTL_INT(_hw_usb, OID_AUTO, disable_port_power, CTLFLAG_RWTUN, &usb_disable_port_power, 0, "Set to disable all USB port power."); #endif -struct uhub_current_state { - uint16_t port_change; - uint16_t port_status; -}; - -struct uhub_softc { - struct uhub_current_state sc_st;/* current state */ -#if (USB_HAVE_FIXED_PORT != 0) - struct usb_hub sc_hub; -#endif - device_t sc_dev; /* base device */ - struct mtx sc_mtx; /* our mutex */ - struct usb_device *sc_udev; /* USB device */ - struct usb_xfer *sc_xfer[UHUB_N_TRANSFER]; /* interrupt xfer */ -#if USB_HAVE_DISABLE_ENUM - int sc_disable_enumeration; - int sc_disable_port_power; -#endif - uint8_t sc_flags; -#define UHUB_FLAG_DID_EXPLORE 0x01 -}; #define UHUB_PROTO(sc) ((sc)->sc_udev->ddesc.bDeviceProtocol) #define UHUB_IS_HIGH_SPEED(sc) (UHUB_PROTO(sc) != UDPROTO_FSHUB) @@ -143,14 +117,10 @@ struct uhub_softc { /* prototypes for type checking: */ -static device_probe_t uhub_probe; -static device_attach_t uhub_attach; -static device_detach_t uhub_detach; static device_suspend_t uhub_suspend; static device_resume_t uhub_resume; static bus_driver_added_t uhub_driver_added; -static bus_child_location_str_t uhub_child_location_string; static bus_child_pnpinfo_str_t uhub_child_pnpinfo_string; static usb_callback_t uhub_intr_callback; @@ -207,7 +177,7 @@ static device_method_t uhub_methods[] = { DEVMETHOD_END }; -static driver_t uhub_driver = { +driver_t uhub_driver = { .name = "uhub", .methods = uhub_methods, .size = sizeof(struct uhub_softc) @@ -589,13 +559,25 @@ uhub_read_port_status(struct uhub_softc *sc, uint8_t portno) struct usb_port_status ps; usb_error_t err; + if (sc->sc_usb_port_errors >= UHUB_USB_PORT_ERRORS_MAX) { + DPRINTFN(4, "port %d, HUB looks dead, too many errors\n", portno); + sc->sc_st.port_status = 0; + sc->sc_st.port_change = 0; + return (USB_ERR_TIMEOUT); + } + err = usbd_req_get_port_status( sc->sc_udev, NULL, &ps, portno); - /* update status regardless of error */ - - sc->sc_st.port_status = UGETW(ps.wPortStatus); - sc->sc_st.port_change = UGETW(ps.wPortChange); + if (err == 0) { + sc->sc_st.port_status = UGETW(ps.wPortStatus); + sc->sc_st.port_change = UGETW(ps.wPortChange); + sc->sc_usb_port_errors = 0; + } else { + sc->sc_st.port_status = 0; + sc->sc_st.port_change = 0; + sc->sc_usb_port_errors++; + } /* debugging print */ @@ -1126,7 +1108,7 @@ uhub_explore(struct usb_device *udev) return (USB_ERR_NORMAL_COMPLETION); } -static int +int uhub_probe(device_t dev) { struct usb_attach_arg *uaa = device_get_ivars(dev); @@ -1140,7 +1122,7 @@ uhub_probe(device_t dev) */ if (uaa->info.bConfigIndex == 0 && uaa->info.bDeviceClass == UDCLASS_HUB) - return (0); + return (BUS_PROBE_DEFAULT); return (ENXIO); } @@ -1206,7 +1188,7 @@ uhub_query_info(struct usb_device *udev, uint8_t *pnports, uint8_t *ptt) return (err); } -static int +int uhub_attach(device_t dev) { struct uhub_softc *sc = device_get_softc(dev); @@ -1552,7 +1534,7 @@ error: * Called from process context when the hub is gone. * Detach all devices on active ports. */ -static int +int uhub_detach(device_t dev) { struct uhub_softc *sc = device_get_softc(dev); @@ -1622,13 +1604,7 @@ uhub_driver_added(device_t dev, driver_t *driver) usb_needs_explore_all(); } -struct hub_result { - struct usb_device *udev; - uint8_t portno; - uint8_t iface_index; -}; - -static void +void uhub_find_iface_index(struct usb_hub *hub, device_t child, struct hub_result *res) { @@ -1661,7 +1637,7 @@ uhub_find_iface_index(struct usb_hub *hub, device_t child, res->portno = 0; } -static int +int uhub_child_location_string(device_t parent, device_t child, char *buf, size_t buflen) { diff --git a/freebsd/sys/dev/usb/usb_hub_private.h b/freebsd/sys/dev/usb/usb_hub_private.h new file mode 100644 index 00000000..1151ed7d --- /dev/null +++ b/freebsd/sys/dev/usb/usb_hub_private.h @@ -0,0 +1,86 @@ +/* $FreeBSD$ */ +/*- + * SPDX-License-Identifier: BSD-2-Clause-NetBSD + * + * Copyright (c) 1998 The NetBSD Foundation, Inc. All rights reserved. + * Copyright (c) 1998 Lennart Augustsson. All rights reserved. + * Copyright (c) 2008-2010 Hans Petter Selasky. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * USB spec: http://www.usb.org/developers/docs/usbspec.zip + */ + +#ifndef USB_HUB_PRIVATE_H_ +#define USB_HUB_PRIVATE_H_ +#define UHUB_INTR_INTERVAL 250 /* ms */ + +enum { + UHUB_INTR_TRANSFER, +#if USB_HAVE_TT_SUPPORT + UHUB_RESET_TT_TRANSFER, +#endif + UHUB_N_TRANSFER, +}; + + +struct uhub_current_state { + uint16_t port_change; + uint16_t port_status; +}; + +struct uhub_softc { + struct uhub_current_state sc_st; /* current state */ +#if (USB_HAVE_FIXED_PORT != 0) + struct usb_hub sc_hub; +#endif + device_t sc_dev; /* base device */ + struct mtx sc_mtx; /* our mutex */ + struct usb_device *sc_udev; /* USB device */ + struct usb_xfer *sc_xfer[UHUB_N_TRANSFER]; /* interrupt xfer */ +#if USB_HAVE_DISABLE_ENUM + int sc_disable_enumeration; + int sc_disable_port_power; +#endif + uint8_t sc_usb_port_errors; /* error counter */ +#define UHUB_USB_PORT_ERRORS_MAX 4 + uint8_t sc_flags; +#define UHUB_FLAG_DID_EXPLORE 0x01 +}; +struct hub_result { + struct usb_device *udev; + uint8_t portno; + uint8_t iface_index; +}; + +void +uhub_find_iface_index(struct usb_hub *hub, device_t child, + struct hub_result *res); + +device_probe_t uhub_probe; +device_attach_t uhub_attach; +device_detach_t uhub_detach; +bus_child_location_str_t uhub_child_location_string; + +#endif diff --git a/freebsd/sys/dev/usb/usb_ioctl.h b/freebsd/sys/dev/usb/usb_ioctl.h index fcd31e31..c4023cab 100644 --- a/freebsd/sys/dev/usb/usb_ioctl.h +++ b/freebsd/sys/dev/usb/usb_ioctl.h @@ -70,6 +70,7 @@ enum { USB_TEMP_SERIALNET, /* USB CDC Ethernet and Modem */ USB_TEMP_MIDI, /* USB MIDI */ USB_TEMP_MULTI, /* USB Ethernet, serial, and storage */ + USB_TEMP_CDCEEM, /* USB Ethernet Emulation Model */ USB_TEMP_MAX, }; @@ -223,7 +224,7 @@ struct usb_fs_uninit { } USB_IOCTL_STRUCT_ALIGN(1); struct usb_fs_open { -#define USB_FS_MAX_BUFSIZE (1 << 18) +#define USB_FS_MAX_BUFSIZE (1 << 25) /* 32 MBytes */ uint32_t max_bufsize; #define USB_FS_MAX_FRAMES (1U << 12) #define USB_FS_MAX_FRAMES_PRE_SCALE (1U << 31) /* for ISOCHRONOUS transfers */ diff --git a/freebsd/sys/dev/usb/usb_request.c b/freebsd/sys/dev/usb/usb_request.c index d2a15f3c..f288378e 100644 --- a/freebsd/sys/dev/usb/usb_request.c +++ b/freebsd/sys/dev/usb/usb_request.c @@ -1603,8 +1603,9 @@ usbd_req_get_port_status(struct usb_device *udev, struct mtx *mtx, USETW(req.wValue, 0); req.wIndex[0] = port; req.wIndex[1] = 0; - USETW(req.wLength, sizeof *ps); - return (usbd_do_request(udev, mtx, &req, ps)); + USETW(req.wLength, sizeof(*ps)); + + return (usbd_do_request_flags(udev, mtx, &req, ps, 0, NULL, 1000)); } /*------------------------------------------------------------------------* diff --git a/freebsd/sys/dev/usb/usb_transfer.c b/freebsd/sys/dev/usb/usb_transfer.c index 7ea25337..3b67c20c 100644 --- a/freebsd/sys/dev/usb/usb_transfer.c +++ b/freebsd/sys/dev/usb/usb_transfer.c @@ -111,6 +111,33 @@ static const struct usb_config usb_control_ep_cfg[USB_CTRL_XFER_MAX] = { }, }; +static const struct usb_config usb_control_ep_quirk_cfg[USB_CTRL_XFER_MAX] = { + + /* This transfer is used for generic control endpoint transfers */ + + [0] = { + .type = UE_CONTROL, + .endpoint = 0x00, /* Control endpoint */ + .direction = UE_DIR_ANY, + .bufsize = 65535, /* bytes */ + .callback = &usb_request_callback, + .usb_mode = USB_MODE_DUAL, /* both modes */ + }, + + /* This transfer is used for generic clear stall only */ + + [1] = { + .type = UE_CONTROL, + .endpoint = 0x00, /* Control pipe */ + .direction = UE_DIR_ANY, + .bufsize = sizeof(struct usb_device_request), + .callback = &usb_do_clear_stall_callback, + .timeout = 1000, /* 1 second */ + .interval = 50, /* 50ms */ + .usb_mode = USB_MODE_HOST, + }, +}; + /* function prototypes */ static void usbd_update_max_frame_size(struct usb_xfer *); @@ -1051,7 +1078,8 @@ usbd_transfer_setup(struct usb_device *udev, * context, else there is a chance of * deadlock! */ - if (setup_start == usb_control_ep_cfg) + if (setup_start == usb_control_ep_cfg || + setup_start == usb_control_ep_quirk_cfg) info->done_p = USB_BUS_CONTROL_XFER_PROC(udev->bus); else if (xfer_mtx == &Giant) @@ -3179,7 +3207,8 @@ repeat: */ iface_index = 0; if (usbd_transfer_setup(udev, &iface_index, - udev->ctrl_xfer, usb_control_ep_cfg, USB_CTRL_XFER_MAX, NULL, + udev->ctrl_xfer, udev->bus->control_ep_quirk ? + usb_control_ep_quirk_cfg : usb_control_ep_cfg, USB_CTRL_XFER_MAX, NULL, &udev->device_mtx)) { DPRINTFN(0, "could not setup default " "USB transfer\n"); diff --git a/freebsd/sys/dev/usb/usbdi.h b/freebsd/sys/dev/usb/usbdi.h index d5648c03..0a393844 100644 --- a/freebsd/sys/dev/usb/usbdi.h +++ b/freebsd/sys/dev/usb/usbdi.h @@ -105,7 +105,7 @@ typedef void (usb_fifo_filter_t)(struct usb_fifo *fifo, struct usb_mbuf *m); /* USB events */ #ifndef USB_GLOBAL_INCLUDE_FILE -#include <sys/eventhandler.h> +#include <sys/_eventhandler.h> #endif typedef void (*usb_dev_configured_t)(void *, struct usb_device *, struct usb_attach_arg *); diff --git a/freebsd/sys/dev/usb/wlan/if_rsu.c b/freebsd/sys/dev/usb/wlan/if_rsu.c index b730ce59..112b8675 100644 --- a/freebsd/sys/dev/usb/wlan/if_rsu.c +++ b/freebsd/sys/dev/usb/wlan/if_rsu.c @@ -44,13 +44,9 @@ __FBSDID("$FreeBSD$"); #include <sys/systm.h> #include <sys/conf.h> #include <sys/bus.h> -#include <sys/rman.h> #include <sys/firmware.h> #include <sys/module.h> -#include <machine/bus.h> -#include <machine/resource.h> - #include <net/bpf.h> #include <net/if.h> #include <net/if_var.h> @@ -291,9 +287,6 @@ MODULE_DEPEND(rsu, firmware, 1, 1, 1); MODULE_VERSION(rsu, 1); USB_PNP_HOST_INFO(rsu_devs); -static const uint8_t rsu_chan_2ghz[] = - { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 }; - static uint8_t rsu_wme_ac_xfer_map[4] = { [WME_AC_BE] = RSU_BULK_TX_BE_BK, [WME_AC_BK] = RSU_BULK_TX_BE_BK, @@ -789,9 +782,8 @@ rsu_getradiocaps(struct ieee80211com *ic, setbit(bands, IEEE80211_MODE_11G); if (sc->sc_ht) setbit(bands, IEEE80211_MODE_11NG); - ieee80211_add_channel_list_2ghz(chans, maxchans, nchans, - rsu_chan_2ghz, nitems(rsu_chan_2ghz), bands, - (ic->ic_htcaps & IEEE80211_HTCAP_CHWIDTH40) != 0); + ieee80211_add_channels_default_2ghz(chans, maxchans, nchans, + bands, (ic->ic_htcaps & IEEE80211_HTCAP_CHWIDTH40) != 0); } static void @@ -2460,8 +2452,6 @@ rsu_rx_frame(struct rsu_softc *sc, struct mbuf *m) tap->wr_rate = rxs.c_rate; tap->wr_dbm_antsignal = rssi; - tap->wr_chan_freq = htole16(ic->ic_curchan->ic_freq); - tap->wr_chan_flags = htole16(ic->ic_curchan->ic_flags); }; (void) ieee80211_add_rx_params(m, &rxs); @@ -2762,15 +2752,16 @@ static int rsu_tx_start(struct rsu_softc *sc, struct ieee80211_node *ni, struct mbuf *m0, struct rsu_data *data) { - struct ieee80211com *ic = &sc->sc_ic; + const struct ieee80211_txparam *tp = ni->ni_txparms; struct ieee80211vap *vap = ni->ni_vap; struct ieee80211_frame *wh; struct ieee80211_key *k = NULL; struct r92s_tx_desc *txd; - uint8_t type, cipher; + uint8_t rate, ridx, type, cipher, qos; int prio = 0; uint8_t which; int hasqos; + int ismcast; int xferlen; int qid; @@ -2778,10 +2769,26 @@ rsu_tx_start(struct rsu_softc *sc, struct ieee80211_node *ni, wh = mtod(m0, struct ieee80211_frame *); type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; + ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1); RSU_DPRINTF(sc, RSU_DEBUG_TX, "%s: data=%p, m=%p\n", __func__, data, m0); + /* Choose a TX rate index. */ + if (type == IEEE80211_FC0_TYPE_MGT || + type == IEEE80211_FC0_TYPE_CTL || + (m0->m_flags & M_EAPOL) != 0) + rate = tp->mgmtrate; + else if (ismcast) + rate = tp->mcastrate; + else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) + rate = tp->ucastrate; + else + rate = 0; + + if (rate != 0) + ridx = rate2ridx(rate); + if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { k = ieee80211_crypto_encap(ni, m0); if (k == NULL) { @@ -2799,12 +2806,14 @@ rsu_tx_start(struct rsu_softc *sc, struct ieee80211_node *ni, prio = M_WME_GETAC(m0); which = rsu_wme_ac_xfer_map[prio]; hasqos = 1; + qos = ((const struct ieee80211_qosframe *)wh)->i_qos[0]; } else { /* Non-QoS TID */ /* XXX TODO: tid=0 for non-qos TID? */ which = rsu_wme_ac_xfer_map[WME_AC_BE]; hasqos = 0; prio = 0; + qos = 0; } qid = rsu_ac2qid[prio]; @@ -2860,8 +2869,23 @@ rsu_tx_start(struct rsu_softc *sc, struct ieee80211_node *ni, } /* XXX todo: set AGGEN bit if appropriate? */ txd->txdw2 |= htole32(R92S_TXDW2_BK); - if (IEEE80211_IS_MULTICAST(wh->i_addr1)) + if (ismcast) txd->txdw2 |= htole32(R92S_TXDW2_BMCAST); + + if (!ismcast && (!qos || (qos & IEEE80211_QOS_ACKPOLICY) != + IEEE80211_QOS_ACKPOLICY_NOACK)) { + txd->txdw2 |= htole32(R92S_TXDW2_RTY_LMT_ENA); + txd->txdw2 |= htole32(SM(R92S_TXDW2_RTY_LMT, tp->maxretry)); + } + + /* Force mgmt / mcast / ucast rate if needed. */ + if (rate != 0) { + /* Data rate fallback limit (max). */ + txd->txdw5 |= htole32(SM(R92S_TXDW5_DATARATE_FB_LMT, 0x1f)); + txd->txdw5 |= htole32(SM(R92S_TXDW5_DATARATE, ridx)); + txd->txdw4 |= htole32(R92S_TXDW4_DRVRATE); + } + /* * Firmware will use and increment the sequence number for the * specified priority. @@ -2872,8 +2896,6 @@ rsu_tx_start(struct rsu_softc *sc, struct ieee80211_node *ni, struct rsu_tx_radiotap_header *tap = &sc->sc_txtap; tap->wt_flags = 0; - tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq); - tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags); ieee80211_radiotap_tx(vap, m0); } diff --git a/freebsd/sys/dev/usb/wlan/if_rsureg.h b/freebsd/sys/dev/usb/wlan/if_rsureg.h index 973280cf..246b06b7 100644 --- a/freebsd/sys/dev/usb/wlan/if_rsureg.h +++ b/freebsd/sys/dev/usb/wlan/if_rsureg.h @@ -688,6 +688,9 @@ struct r92s_tx_desc { #define R92S_TXDW1_HWPC 0x80000000 uint32_t txdw2; +#define R92S_TXDW2_RTY_LMT_M 0x0000003f +#define R92S_TXDW2_RTY_LMT_S 0 +#define R92S_TXDW2_RTY_LMT_ENA 0x00000040 #define R92S_TXDW2_BMCAST 0x00000080 #define R92S_TXDW2_AGGEN 0x20000000 #define R92S_TXDW2_BK 0x40000000 @@ -700,9 +703,14 @@ struct r92s_tx_desc { uint32_t txdw4; #define R92S_TXDW4_TXBW 0x00040000 +#define R92S_TXDW4_DRVRATE 0x80000000 uint32_t txdw5; -#define R92S_TXDW5_DISFB 0x00008000 +#define R92S_TXDW5_DATARATE_M 0x00007e00 +#define R92S_TXDW5_DATARATE_S 9 +#define R92S_TXDW5_DISFB 0x00008000 +#define R92S_TXDW5_DATARATE_FB_LMT_M 0x001f0000 +#define R92S_TXDW5_DATARATE_FB_LMT_S 16 uint16_t ipchksum; uint16_t tcpchksum; @@ -792,9 +800,10 @@ struct rsu_rx_radiotap_header { struct rsu_tx_radiotap_header { struct ieee80211_radiotap_header wt_ihdr; uint8_t wt_flags; + uint8_t wt_pad; uint16_t wt_chan_freq; uint16_t wt_chan_flags; -} __packed __aligned(8); +} __packed; #define RSU_TX_RADIOTAP_PRESENT \ (1 << IEEE80211_RADIOTAP_FLAGS | \ diff --git a/freebsd/sys/dev/usb/wlan/if_rum.c b/freebsd/sys/dev/usb/wlan/if_rum.c index 5c826cac..c2f68406 100644 --- a/freebsd/sys/dev/usb/wlan/if_rum.c +++ b/freebsd/sys/dev/usb/wlan/if_rum.c @@ -46,10 +46,6 @@ __FBSDID("$FreeBSD$"); #include <sys/endian.h> #include <sys/kdb.h> -#include <machine/bus.h> -#include <machine/resource.h> -#include <sys/rman.h> - #include <net/bpf.h> #include <net/if.h> #include <net/if_var.h> @@ -344,9 +340,6 @@ static const struct { { 107, 0x04 } }; -static const uint8_t rum_chan_2ghz[] = - { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 }; - static const uint8_t rum_chan_5ghz[] = { 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, @@ -3222,8 +3215,7 @@ rum_getradiocaps(struct ieee80211com *ic, memset(bands, 0, sizeof(bands)); setbit(bands, IEEE80211_MODE_11B); setbit(bands, IEEE80211_MODE_11G); - ieee80211_add_channel_list_2ghz(chans, maxchans, nchans, - rum_chan_2ghz, nitems(rum_chan_2ghz), bands, 0); + ieee80211_add_channels_default_2ghz(chans, maxchans, nchans, bands, 0); if (sc->rf_rev == RT2573_RF_5225 || sc->rf_rev == RT2573_RF_5226) { setbit(bands, IEEE80211_MODE_11A); diff --git a/freebsd/sys/dev/usb/wlan/if_rumvar.h b/freebsd/sys/dev/usb/wlan/if_rumvar.h index 4ff831f4..e19a7088 100644 --- a/freebsd/sys/dev/usb/wlan/if_rumvar.h +++ b/freebsd/sys/dev/usb/wlan/if_rumvar.h @@ -49,7 +49,7 @@ struct rum_tx_radiotap_header { uint16_t wt_chan_freq; uint16_t wt_chan_flags; uint8_t wt_antenna; -} __packed __aligned(8); +} __packed; #define RT2573_TX_RADIOTAP_PRESENT \ ((1 << IEEE80211_RADIOTAP_FLAGS) | \ diff --git a/freebsd/sys/dev/usb/wlan/if_run.c b/freebsd/sys/dev/usb/wlan/if_run.c index 3bd247e3..9f11a3a3 100644 --- a/freebsd/sys/dev/usb/wlan/if_run.c +++ b/freebsd/sys/dev/usb/wlan/if_run.c @@ -30,6 +30,7 @@ __FBSDID("$FreeBSD$"); #include <rtems/bsd/local/opt_wlan.h> #include <sys/param.h> +#include <sys/eventhandler.h> #include <sys/sockio.h> #include <sys/sysctl.h> #include <sys/lock.h> @@ -46,10 +47,6 @@ __FBSDID("$FreeBSD$"); #include <sys/firmware.h> #include <sys/kdb.h> -#include <machine/bus.h> -#include <machine/resource.h> -#include <sys/rman.h> - #include <net/bpf.h> #include <net/if.h> #include <net/if_var.h> @@ -470,6 +467,7 @@ static void run_usb_timeout_cb(void *); static void run_reset_livelock(struct run_softc *); static void run_enable_tsf_sync(struct run_softc *); static void run_enable_tsf(struct run_softc *); +static void run_disable_tsf(struct run_softc *); static void run_get_tsf(struct run_softc *, uint64_t *); static void run_enable_mrr(struct run_softc *); static void run_set_txpreamble(struct run_softc *); @@ -2035,7 +2033,8 @@ run_read_eeprom(struct run_softc *sc) static struct ieee80211_node * run_node_alloc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN]) { - return malloc(sizeof (struct run_node), M_DEVBUF, M_NOWAIT | M_ZERO); + return malloc(sizeof (struct run_node), M_80211_NODE, + M_NOWAIT | M_ZERO); } static int @@ -2095,7 +2094,6 @@ run_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) struct run_vap *rvp = RUN_VAP(vap); enum ieee80211_state ostate; uint32_t sta[3]; - uint32_t tmp; uint8_t ratectl; uint8_t restart_ratectl = 0; uint8_t bid = 1 << rvp->rvp_id; @@ -2128,12 +2126,8 @@ run_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) sc->runbmap &= ~bid; /* abort TSF synchronization if there is no vap running */ - if (--sc->running == 0) { - run_read(sc, RT2860_BCN_TIME_CFG, &tmp); - run_write(sc, RT2860_BCN_TIME_CFG, - tmp & ~(RT2860_BCN_TX_EN | RT2860_TSF_TIMER_EN | - RT2860_TBTT_TIMER_EN)); - } + if (--sc->running == 0) + run_disable_tsf(sc); break; case IEEE80211_S_RUN: @@ -2826,76 +2820,83 @@ run_rx_frame(struct run_softc *sc, struct mbuf *m, uint32_t dmalen) uint8_t ant, rssi; int8_t nf; - rxwi = mtod(m, struct rt2860_rxwi *); - len = le16toh(rxwi->len) & 0xfff; rxwisize = sizeof(struct rt2860_rxwi); if (sc->mac_ver == 0x5592) rxwisize += sizeof(uint64_t); else if (sc->mac_ver == 0x3593) rxwisize += sizeof(uint32_t); - if (__predict_false(len > dmalen)) { - m_freem(m); - counter_u64_add(ic->ic_ierrors, 1); + + if (__predict_false(dmalen < + rxwisize + sizeof(struct ieee80211_frame_ack))) { + RUN_DPRINTF(sc, RUN_DEBUG_RECV, + "payload is too short: dma length %u < %zu\n", + dmalen, rxwisize + sizeof(struct ieee80211_frame_ack)); + goto fail; + } + + rxwi = mtod(m, struct rt2860_rxwi *); + len = le16toh(rxwi->len) & 0xfff; + + if (__predict_false(len > dmalen - rxwisize)) { RUN_DPRINTF(sc, RUN_DEBUG_RECV, "bad RXWI length %u > %u\n", len, dmalen); - return; + goto fail; } + /* Rx descriptor is located at the end */ rxd = (struct rt2870_rxd *)(mtod(m, caddr_t) + dmalen); flags = le32toh(rxd->flags); if (__predict_false(flags & (RT2860_RX_CRCERR | RT2860_RX_ICVERR))) { - m_freem(m); - counter_u64_add(ic->ic_ierrors, 1); RUN_DPRINTF(sc, RUN_DEBUG_RECV, "%s error.\n", (flags & RT2860_RX_CRCERR)?"CRC":"ICV"); - return; + goto fail; + } + + if (flags & RT2860_RX_L2PAD) { + RUN_DPRINTF(sc, RUN_DEBUG_RECV, + "received RT2860_RX_L2PAD frame\n"); + len += 2; } m->m_data += rxwisize; - m->m_pkthdr.len = m->m_len -= rxwisize; + m->m_pkthdr.len = m->m_len = len; wh = mtod(m, struct ieee80211_frame *); - if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { + if ((wh->i_fc[1] & IEEE80211_FC1_PROTECTED) != 0 && + (flags & RT2860_RX_DEC) != 0) { wh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED; m->m_flags |= M_WEP; } - if (flags & RT2860_RX_L2PAD) { - RUN_DPRINTF(sc, RUN_DEBUG_RECV, - "received RT2860_RX_L2PAD frame\n"); - len += 2; - } - - ni = ieee80211_find_rxnode(ic, - mtod(m, struct ieee80211_frame_min *)); + if (len >= sizeof(struct ieee80211_frame_min)) { + ni = ieee80211_find_rxnode(ic, + mtod(m, struct ieee80211_frame_min *)); + } else + ni = NULL; if (__predict_false(flags & RT2860_RX_MICERR)) { /* report MIC failures to net80211 for TKIP */ if (ni != NULL) ieee80211_notify_michael_failure(ni->ni_vap, wh, rxwi->keyidx); - m_freem(m); - counter_u64_add(ic->ic_ierrors, 1); RUN_DPRINTF(sc, RUN_DEBUG_RECV, "MIC error. Someone is lying.\n"); - return; + goto fail; } ant = run_maxrssi_chain(sc, rxwi); rssi = rxwi->rssi[ant]; nf = run_rssi2dbm(sc, rssi, ant); - m->m_pkthdr.len = m->m_len = len; - if (__predict_false(ieee80211_radiotap_active(ic))) { struct run_rx_radiotap_header *tap = &sc->sc_rxtap; uint16_t phy; tap->wr_flags = 0; - tap->wr_chan_freq = htole16(ic->ic_curchan->ic_freq); - tap->wr_chan_flags = htole16(ic->ic_curchan->ic_flags); + if (flags & RT2860_RX_L2PAD) + tap->wr_flags |= IEEE80211_RADIOTAP_F_DATAPAD; tap->wr_antsignal = rssi; tap->wr_antenna = ant; tap->wr_dbm_antsignal = run_rssi2dbm(sc, rssi, ant); @@ -2936,6 +2937,12 @@ run_rx_frame(struct run_softc *sc, struct mbuf *m, uint32_t dmalen) } else { (void)ieee80211_input_all(ic, m, rssi, nf); } + + return; + +fail: + m_freem(m); + counter_u64_add(ic->ic_ierrors, 1); } static void @@ -2945,7 +2952,7 @@ run_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error) struct ieee80211com *ic = &sc->sc_ic; struct mbuf *m = NULL; struct mbuf *m0; - uint32_t dmalen; + uint32_t dmalen, mbuf_len; uint16_t rxwisize; int xferlen; @@ -3051,6 +3058,14 @@ tr_setup: break; } + mbuf_len = dmalen + sizeof(struct rt2870_rxd); + if (__predict_false(mbuf_len > MCLBYTES)) { + RUN_DPRINTF(sc, RUN_DEBUG_RECV_DESC | RUN_DEBUG_USB, + "payload is too big: mbuf_len %u\n", mbuf_len); + counter_u64_add(ic->ic_ierrors, 1); + break; + } + /* copy aggregated frames to another mbuf */ m0 = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); if (__predict_false(m0 == NULL)) { @@ -3060,14 +3075,13 @@ tr_setup: break; } m_copydata(m, 4 /* skip 32-bit DMA-len header */, - dmalen + sizeof(struct rt2870_rxd), mtod(m0, caddr_t)); - m0->m_pkthdr.len = m0->m_len = - dmalen + sizeof(struct rt2870_rxd); + mbuf_len, mtod(m0, caddr_t)); + m0->m_pkthdr.len = m0->m_len = mbuf_len; run_rx_frame(sc, m0, dmalen); /* update data ptr */ - m->m_data += dmalen + 8; - m->m_pkthdr.len = m->m_len -= dmalen + 8; + m->m_data += mbuf_len + 4; + m->m_pkthdr.len = m->m_len -= mbuf_len + 4; } /* make sure we free the source buffer, if any */ @@ -3149,16 +3163,23 @@ tr_setup: vap = data->ni->ni_vap; if (ieee80211_radiotap_active_vap(vap)) { + const struct ieee80211_frame *wh; struct run_tx_radiotap_header *tap = &sc->sc_txtap; struct rt2860_txwi *txwi = (struct rt2860_txwi *)(&data->desc + sizeof(struct rt2870_txd)); + int has_l2pad; + + wh = mtod(m, struct ieee80211_frame *); + has_l2pad = IEEE80211_HAS_ADDR4(wh) != + IEEE80211_QOS_HAS_SEQ(wh); + tap->wt_flags = 0; tap->wt_rate = rt2860_rates[data->ridx].rate; - tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq); - tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags); tap->wt_hwqueue = index; if (le16toh(txwi->phy) & RT2860_PHY_SHPRE) tap->wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE; + if (has_l2pad) + tap->wt_flags |= IEEE80211_RADIOTAP_F_DATAPAD; ieee80211_radiotap_tx(vap, m); } @@ -3350,11 +3371,7 @@ run_tx(struct run_softc *sc, struct mbuf *m, struct ieee80211_node *ni) if ((hasqos = IEEE80211_QOS_HAS_SEQ(wh))) { uint8_t *frm; - if(IEEE80211_HAS_ADDR4(wh)) - frm = ((struct ieee80211_qosframe_addr4 *)wh)->i_qos; - else - frm =((struct ieee80211_qosframe *)wh)->i_qos; - + frm = ieee80211_getqos(wh); qos = le16toh(*(const uint16_t *)frm); tid = qos & IEEE80211_QOS_TID; qid = TID_TO_WME_AC(tid); @@ -4837,8 +4854,7 @@ run_getradiocaps(struct ieee80211com *ic, memset(bands, 0, sizeof(bands)); setbit(bands, IEEE80211_MODE_11B); setbit(bands, IEEE80211_MODE_11G); - ieee80211_add_channel_list_2ghz(chans, maxchans, nchans, - run_chan_2ghz, nitems(run_chan_2ghz), bands, 0); + ieee80211_add_channels_default_2ghz(chans, maxchans, nchans, bands, 0); if (sc->rf_rev == RT2860_RF_2750 || sc->rf_rev == RT2860_RF_2850 || sc->rf_rev == RT3070_RF_3052 || sc->rf_rev == RT3593_RF_3053 || @@ -4853,15 +4869,11 @@ static void run_scan_start(struct ieee80211com *ic) { struct run_softc *sc = ic->ic_softc; - uint32_t tmp; RUN_LOCK(sc); /* abort TSF synchronization */ - run_read(sc, RT2860_BCN_TIME_CFG, &tmp); - run_write(sc, RT2860_BCN_TIME_CFG, - tmp & ~(RT2860_BCN_TX_EN | RT2860_TSF_TIMER_EN | - RT2860_TBTT_TIMER_EN)); + run_disable_tsf(sc); run_set_bssid(sc, ieee80211broadcastaddr); RUN_UNLOCK(sc); @@ -5148,6 +5160,18 @@ run_enable_tsf(struct run_softc *sc) } static void +run_disable_tsf(struct run_softc *sc) +{ + uint32_t tmp; + + if (run_read(sc, RT2860_BCN_TIME_CFG, &tmp) == 0) { + tmp &= ~(RT2860_BCN_TX_EN | RT2860_TSF_TIMER_EN | + RT2860_TBTT_TIMER_EN); + run_write(sc, RT2860_BCN_TIME_CFG, tmp); + } +} + +static void run_get_tsf(struct run_softc *sc, uint64_t *buf) { run_read_region_1(sc, RT2860_TSF_TIMER_DW0, (uint8_t *)buf, @@ -6098,10 +6122,7 @@ run_init_locked(struct run_softc *sc) } /* abort TSF synchronization */ - run_read(sc, RT2860_BCN_TIME_CFG, &tmp); - tmp &= ~(RT2860_BCN_TX_EN | RT2860_TSF_TIMER_EN | - RT2860_TBTT_TIMER_EN); - run_write(sc, RT2860_BCN_TIME_CFG, tmp); + run_disable_tsf(sc); /* clear RX WCID search table */ run_set_region_4(sc, RT2860_WCID_ENTRY(0), 0, 512); diff --git a/freebsd/sys/dev/usb/wlan/if_runreg.h b/freebsd/sys/dev/usb/wlan/if_runreg.h index c09aac8f..8561d2c1 100644 --- a/freebsd/sys/dev/usb/wlan/if_runreg.h +++ b/freebsd/sys/dev/usb/wlan/if_runreg.h @@ -1086,9 +1086,6 @@ struct rt2860_rxwi { /* * Channel map for run(4) driver; taken from the table below. */ -static const uint8_t run_chan_2ghz[] = - { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 }; - static const uint8_t run_chan_5ghz[] = { 36, 38, 40, 44, 46, 48, 52, 54, 56, 60, 62, 64, 100, 102, 104, 108, 110, 112, 116, 118, 120, 124, 126, 128, 132, 134, 136, 140, diff --git a/freebsd/sys/dev/usb/wlan/if_runvar.h b/freebsd/sys/dev/usb/wlan/if_runvar.h index 7209bfc7..a17d5b46 100644 --- a/freebsd/sys/dev/usb/wlan/if_runvar.h +++ b/freebsd/sys/dev/usb/wlan/if_runvar.h @@ -71,7 +71,7 @@ struct run_tx_radiotap_header { uint16_t wt_chan_freq; uint16_t wt_chan_flags; uint8_t wt_hwqueue; -} __packed __aligned(8); +} __packed; #define IEEE80211_RADIOTAP_HWQUEUE 15 diff --git a/freebsd/sys/dev/usb/wlan/if_uath.c b/freebsd/sys/dev/usb/wlan/if_uath.c index 2b97060e..9f0c9d5d 100644 --- a/freebsd/sys/dev/usb/wlan/if_uath.c +++ b/freebsd/sys/dev/usb/wlan/if_uath.c @@ -87,10 +87,6 @@ __FBSDID("$FreeBSD$"); #include <sys/endian.h> #include <sys/kdb.h> -#include <machine/bus.h> -#include <machine/resource.h> -#include <sys/rman.h> - #include <net/bpf.h> #include <net/if.h> #include <net/if_var.h> @@ -1282,8 +1278,8 @@ uath_watchdog(void *arg) if (sc->sc_tx_timer > 0) { if (--sc->sc_tx_timer == 0) { device_printf(sc->sc_dev, "device timeout\n"); - /*uath_init(sc); XXX needs a process context! */ counter_u64_add(ic->ic_oerrors, 1); + ieee80211_restart_all(ic); return; } callout_reset(&sc->watchdog_ch, hz, uath_watchdog, sc); diff --git a/freebsd/sys/dev/usb/wlan/if_uathvar.h b/freebsd/sys/dev/usb/wlan/if_uathvar.h index a38f54fc..a0ef4eab 100644 --- a/freebsd/sys/dev/usb/wlan/if_uathvar.h +++ b/freebsd/sys/dev/usb/wlan/if_uathvar.h @@ -67,9 +67,10 @@ struct uath_rx_radiotap_header { struct uath_tx_radiotap_header { struct ieee80211_radiotap_header wt_ihdr; uint8_t wt_flags; + uint8_t wt_pad; uint16_t wt_chan_freq; uint16_t wt_chan_flags; -} __packed __aligned(8); +} __packed; #define UATH_TX_RADIOTAP_PRESENT \ ((1 << IEEE80211_RADIOTAP_FLAGS) | \ diff --git a/freebsd/sys/dev/usb/wlan/if_upgt.c b/freebsd/sys/dev/usb/wlan/if_upgt.c index e1923bab..c556d108 100644 --- a/freebsd/sys/dev/usb/wlan/if_upgt.c +++ b/freebsd/sys/dev/usb/wlan/if_upgt.c @@ -43,7 +43,6 @@ #include <net/if_types.h> #include <sys/bus.h> -#include <machine/bus.h> #include <net80211/ieee80211_var.h> #include <net80211/ieee80211_phy.h> @@ -1618,7 +1617,7 @@ upgt_fw_load(struct upgt_softc *sc) data_cmd->buflen = bsize; upgt_bulk_tx(sc, data_cmd); - DPRINTF(sc, UPGT_DEBUG_FW, "FW offset=%d, read=%d, sent=%d\n", + DPRINTF(sc, UPGT_DEBUG_FW, "FW offset=%zu, read=%d, sent=%d\n", offset, n, bsize); bsize = n; } @@ -1775,7 +1774,7 @@ upgt_fw_verify(struct upgt_softc *sc) } DPRINTF(sc, UPGT_DEBUG_FW, - "firmware Boot Record Area found at offset %d\n", offset); + "firmware Boot Record Area found at offset %zu\n", offset); /* * Parse Boot Record Area (BRA) options. diff --git a/freebsd/sys/dev/usb/wlan/if_upgtvar.h b/freebsd/sys/dev/usb/wlan/if_upgtvar.h index ce996f6a..9d4c85e6 100644 --- a/freebsd/sys/dev/usb/wlan/if_upgtvar.h +++ b/freebsd/sys/dev/usb/wlan/if_upgtvar.h @@ -394,7 +394,7 @@ struct upgt_tx_radiotap_header { uint8_t wt_rate; uint16_t wt_chan_freq; uint16_t wt_chan_flags; -} __packed __aligned(8); +} __packed; #define UPGT_TX_RADIOTAP_PRESENT \ ((1 << IEEE80211_RADIOTAP_FLAGS) | \ diff --git a/freebsd/sys/dev/usb/wlan/if_ural.c b/freebsd/sys/dev/usb/wlan/if_ural.c index 4de0a9c5..8897f148 100644 --- a/freebsd/sys/dev/usb/wlan/if_ural.c +++ b/freebsd/sys/dev/usb/wlan/if_ural.c @@ -47,10 +47,6 @@ __FBSDID("$FreeBSD$"); #include <sys/endian.h> #include <sys/kdb.h> -#include <machine/bus.h> -#include <machine/resource.h> -#include <sys/rman.h> - #include <net/bpf.h> #include <net/if.h> #include <net/if_var.h> @@ -363,9 +359,6 @@ static const struct { { 161, 0x08808, 0x0242f, 0x00281 } }; -static const uint8_t ural_chan_2ghz[] = - { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 }; - static const uint8_t ural_chan_5ghz[] = { 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, @@ -1593,8 +1586,7 @@ ural_getradiocaps(struct ieee80211com *ic, memset(bands, 0, sizeof(bands)); setbit(bands, IEEE80211_MODE_11B); setbit(bands, IEEE80211_MODE_11G); - ieee80211_add_channel_list_2ghz(chans, maxchans, nchans, - ural_chan_2ghz, nitems(ural_chan_2ghz), bands, 0); + ieee80211_add_channels_default_2ghz(chans, maxchans, nchans, bands, 0); if (sc->rf_rev == RAL_RF_5222) { setbit(bands, IEEE80211_MODE_11A); diff --git a/freebsd/sys/dev/usb/wlan/if_uralvar.h b/freebsd/sys/dev/usb/wlan/if_uralvar.h index dd863fe0..b59b7911 100644 --- a/freebsd/sys/dev/usb/wlan/if_uralvar.h +++ b/freebsd/sys/dev/usb/wlan/if_uralvar.h @@ -51,7 +51,7 @@ struct ural_tx_radiotap_header { uint16_t wt_chan_freq; uint16_t wt_chan_flags; uint8_t wt_antenna; -} __packed __aligned(8); +} __packed; #define RAL_TX_RADIOTAP_PRESENT \ ((1 << IEEE80211_RADIOTAP_FLAGS) | \ diff --git a/freebsd/sys/dev/usb/wlan/if_urtw.c b/freebsd/sys/dev/usb/wlan/if_urtw.c index 309375f0..aba334af 100644 --- a/freebsd/sys/dev/usb/wlan/if_urtw.c +++ b/freebsd/sys/dev/usb/wlan/if_urtw.c @@ -36,10 +36,6 @@ __FBSDID("$FreeBSD$"); #include <sys/endian.h> #include <sys/kdb.h> -#include <machine/bus.h> -#include <machine/resource.h> -#include <sys/rman.h> - #include <net/if.h> #include <net/if_var.h> #include <net/if_arp.h> @@ -217,9 +213,6 @@ static uint8_t urtw_8225z2_agc[] = { 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31 }; -static const uint8_t urtw_chan_2ghz[] = - { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 }; - static uint32_t urtw_8225_channel[] = { 0x0000, /* dummy channel 0 */ 0x085c, /* 1 */ @@ -679,6 +672,7 @@ static void urtw_scan_end(struct ieee80211com *); static void urtw_getradiocaps(struct ieee80211com *, int, int *, struct ieee80211_channel[]); static void urtw_set_channel(struct ieee80211com *); +static void urtw_update_promisc(struct ieee80211com *); static void urtw_update_mcast(struct ieee80211com *); static int urtw_tx_start(struct urtw_softc *, struct ieee80211_node *, struct mbuf *, @@ -760,6 +754,7 @@ static void urtw_free_tx_data_list(struct urtw_softc *); static void urtw_free_rx_data_list(struct urtw_softc *); static void urtw_free_data_list(struct urtw_softc *, struct urtw_data data[], int, int); +static usb_error_t urtw_set_macaddr(struct urtw_softc *, const uint8_t *); static usb_error_t urtw_adapter_start(struct urtw_softc *); static usb_error_t urtw_adapter_start_b(struct urtw_softc *); static usb_error_t urtw_set_mode(struct urtw_softc *, uint32_t); @@ -905,6 +900,7 @@ urtw_attach(device_t dev) ic->ic_updateslot = urtw_updateslot; ic->ic_vap_create = urtw_vap_create; ic->ic_vap_delete = urtw_vap_delete; + ic->ic_update_promisc = urtw_update_promisc; ic->ic_update_mcast = urtw_update_mcast; ic->ic_parent = urtw_parent; ic->ic_transmit = urtw_transmit; @@ -1194,9 +1190,23 @@ fail: } static usb_error_t +urtw_set_macaddr(struct urtw_softc *sc, const uint8_t *macaddr) +{ + usb_error_t error; + + urtw_write32_m(sc, URTW_MAC0, ((const uint32_t *)macaddr)[0]); + urtw_write16_m(sc, URTW_MAC4, ((const uint32_t *)macaddr)[1] & 0xffff); + +fail: + return (error); +} + +static usb_error_t urtw_adapter_start(struct urtw_softc *sc) { struct ieee80211com *ic = &sc->sc_ic; + struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); + const uint8_t *macaddr; usb_error_t error; error = urtw_reset(sc); @@ -1216,8 +1226,11 @@ urtw_adapter_start(struct urtw_softc *sc) if (error) goto fail; /* applying MAC address again. */ - urtw_write32_m(sc, URTW_MAC0, ((uint32_t *)ic->ic_macaddr)[0]); - urtw_write16_m(sc, URTW_MAC4, ((uint32_t *)ic->ic_macaddr)[1] & 0xffff); + macaddr = vap ? vap->iv_myaddr : ic->ic_macaddr; + urtw_set_macaddr(sc, macaddr); + if (error) + goto fail; + error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL); if (error) goto fail; @@ -1587,8 +1600,7 @@ urtw_getradiocaps(struct ieee80211com *ic, memset(bands, 0, sizeof(bands)); setbit(bands, IEEE80211_MODE_11B); setbit(bands, IEEE80211_MODE_11G); - ieee80211_add_channel_list_2ghz(chans, maxchans, nchans, - urtw_chan_2ghz, nitems(urtw_chan_2ghz), bands, 0); + ieee80211_add_channels_default_2ghz(chans, maxchans, nchans, bands, 0); } static void @@ -1641,6 +1653,17 @@ fail: } static void +urtw_update_promisc(struct ieee80211com *ic) +{ + struct urtw_softc *sc = ic->ic_softc; + + URTW_LOCK(sc); + if (sc->sc_flags & URTW_RUNNING) + urtw_rx_setconf(sc); + URTW_UNLOCK(sc); +} + +static void urtw_update_mcast(struct ieee80211com *ic) { @@ -1694,11 +1717,7 @@ urtw_tx_start(struct urtw_softc *sc, struct ieee80211_node *ni, struct mbuf *m0, if (ieee80211_radiotap_active_vap(vap)) { struct urtw_tx_radiotap_header *tap = &sc->sc_txtap; - /* XXX Are variables correct? */ tap->wt_flags = 0; - tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq); - tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags); - ieee80211_radiotap_tx(vap, m0); } @@ -1892,11 +1911,13 @@ static void urtw_watchdog(void *arg) { struct urtw_softc *sc = arg; + struct ieee80211com *ic = &sc->sc_ic; if (sc->sc_txtimer > 0) { if (--sc->sc_txtimer == 0) { device_printf(sc->sc_dev, "device timeout\n"); - counter_u64_add(sc->sc_ic.ic_oerrors, 1); + counter_u64_add(ic->ic_oerrors, 1); + ieee80211_restart_all(ic); return; } callout_reset(&sc->sc_watchdog_ch, hz, urtw_watchdog, sc); @@ -3179,6 +3200,8 @@ static usb_error_t urtw_8225v2b_rf_init(struct urtw_softc *sc) { struct ieee80211com *ic = &sc->sc_ic; + struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); + const uint8_t *macaddr; unsigned int i; uint8_t data8; usb_error_t error; @@ -3226,8 +3249,10 @@ urtw_8225v2b_rf_init(struct urtw_softc *sc) urtw_write8_m(sc, URTW_CONFIG1, data8); /* applying MAC address again. */ - urtw_write32_m(sc, URTW_MAC0, ((uint32_t *)ic->ic_macaddr)[0]); - urtw_write16_m(sc, URTW_MAC4, ((uint32_t *)ic->ic_macaddr)[1] & 0xffff); + macaddr = vap ? vap->iv_myaddr : ic->ic_macaddr; + error = urtw_set_macaddr(sc, macaddr); + if (error) + goto fail; error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL); if (error) @@ -3887,7 +3912,6 @@ urtw_rx_setconf(struct urtw_softc *sc) if (sc->sc_flags & URTW_RTL8187B) { data = data | URTW_RX_FILTER_MNG | URTW_RX_FILTER_DATA | URTW_RX_FILTER_MCAST | URTW_RX_FILTER_BCAST | - URTW_RX_FILTER_NICMAC | URTW_RX_CHECK_BSSID | URTW_RX_FIFO_THRESHOLD_NONE | URTW_MAX_RX_DMA_2048 | URTW_RX_AUTORESETPHY | URTW_RCR_ONLYERLPKT; @@ -3902,14 +3926,6 @@ urtw_rx_setconf(struct urtw_softc *sc) if (sc->sc_crcmon == 1 && ic->ic_opmode == IEEE80211_M_MONITOR) data = data | URTW_RX_FILTER_CRCERR; - if (ic->ic_opmode == IEEE80211_M_MONITOR || - ic->ic_promisc > 0 || ic->ic_allmulti > 0) { - data = data | URTW_RX_FILTER_ALLMAC; - } else { - data = data | URTW_RX_FILTER_NICMAC; - data = data | URTW_RX_CHECK_BSSID; - } - data = data &~ URTW_RX_FIFO_THRESHOLD_MASK; data = data | URTW_RX_FIFO_THRESHOLD_NONE | URTW_RX_AUTORESETPHY; @@ -3917,6 +3933,16 @@ urtw_rx_setconf(struct urtw_softc *sc) data = data | URTW_MAX_RX_DMA_2048 | URTW_RCR_ONLYERLPKT; } + /* XXX allmulti should not be checked here... */ + if (ic->ic_opmode == IEEE80211_M_MONITOR || + ic->ic_promisc > 0 || ic->ic_allmulti > 0) { + data = data | URTW_RX_FILTER_CTL; + data = data | URTW_RX_FILTER_ALLMAC; + } else { + data = data | URTW_RX_FILTER_NICMAC; + data = data | URTW_RX_CHECK_BSSID; + } + urtw_write32_m(sc, URTW_RX, data); fail: return (error); @@ -3932,50 +3958,56 @@ urtw_rxeof(struct usb_xfer *xfer, struct urtw_data *data, int *rssi_p, struct urtw_softc *sc = data->sc; struct ieee80211com *ic = &sc->sc_ic; uint8_t noise = 0, rate; + uint64_t mactime; usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); - if (actlen < (int)URTW_MIN_RXBUFSZ) { - counter_u64_add(ic->ic_ierrors, 1); - return (NULL); - } - if (sc->sc_flags & URTW_RTL8187B) { struct urtw_8187b_rxhdr *rx; + if (actlen < sizeof(*rx) + IEEE80211_ACK_LEN) + goto fail; + rx = (struct urtw_8187b_rxhdr *)(data->buf + (actlen - (sizeof(struct urtw_8187b_rxhdr)))); flen = le32toh(rx->flag) & 0xfff; - if (flen > actlen) { - counter_u64_add(ic->ic_ierrors, 1); - return (NULL); - } + if (flen > actlen - sizeof(*rx)) + goto fail; + rate = (le32toh(rx->flag) >> URTW_RX_FLAG_RXRATE_SHIFT) & 0xf; /* XXX correct? */ rssi = rx->rssi & URTW_RX_RSSI_MASK; noise = rx->noise; + + if (ieee80211_radiotap_active(ic)) + mactime = rx->mactime; } else { struct urtw_8187l_rxhdr *rx; + if (actlen < sizeof(*rx) + IEEE80211_ACK_LEN) + goto fail; + rx = (struct urtw_8187l_rxhdr *)(data->buf + (actlen - (sizeof(struct urtw_8187l_rxhdr)))); flen = le32toh(rx->flag) & 0xfff; - if (flen > actlen) { - counter_u64_add(ic->ic_ierrors, 1); - return (NULL); - } + if (flen > actlen - sizeof(*rx)) + goto fail; rate = (le32toh(rx->flag) >> URTW_RX_FLAG_RXRATE_SHIFT) & 0xf; /* XXX correct? */ rssi = rx->rssi & URTW_RX_8187L_RSSI_MASK; noise = rx->noise; + + if (ieee80211_radiotap_active(ic)) + mactime = rx->mactime; } + if (flen < IEEE80211_ACK_LEN) + goto fail; + mnew = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); - if (mnew == NULL) { - counter_u64_add(ic->ic_ierrors, 1); - return (NULL); - } + if (mnew == NULL) + goto fail; m = data->m; data->m = mnew; @@ -3987,20 +4019,23 @@ urtw_rxeof(struct usb_xfer *xfer, struct urtw_data *data, int *rssi_p, if (ieee80211_radiotap_active(ic)) { struct urtw_rx_radiotap_header *tap = &sc->sc_rxtap; - /* XXX Are variables correct? */ - tap->wr_chan_freq = htole16(ic->ic_curchan->ic_freq); - tap->wr_chan_flags = htole16(ic->ic_curchan->ic_flags); + tap->wr_tsf = mactime; + tap->wr_flags = 0; tap->wr_dbm_antsignal = (int8_t)rssi; } wh = mtod(m, struct ieee80211_frame *); - if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_DATA) + if (IEEE80211_IS_DATA(wh)) sc->sc_currate = (rate > 0) ? rate : sc->sc_currate; *rssi_p = rssi; *nf_p = noise; /* XXX correct? */ return (m); + +fail: + counter_u64_add(ic->ic_ierrors, 1); + return (NULL); } static void @@ -4008,7 +4043,6 @@ urtw_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error) { struct urtw_softc *sc = usbd_xfer_softc(xfer); struct ieee80211com *ic = &sc->sc_ic; - struct ieee80211_frame *wh; struct ieee80211_node *ni; struct mbuf *m = NULL; struct urtw_data *data; @@ -4046,9 +4080,13 @@ setup: */ URTW_UNLOCK(sc); if (m != NULL) { - wh = mtod(m, struct ieee80211_frame *); - ni = ieee80211_find_rxnode(ic, - (struct ieee80211_frame_min *)wh); + if (m->m_pkthdr.len >= + sizeof(struct ieee80211_frame_min)) { + ni = ieee80211_find_rxnode(ic, + mtod(m, struct ieee80211_frame_min *)); + } else + ni = NULL; + if (ni != NULL) { (void) ieee80211_input(ni, m, rssi, nf); /* node is no longer needed */ diff --git a/freebsd/sys/dev/usb/wlan/if_urtwvar.h b/freebsd/sys/dev/usb/wlan/if_urtwvar.h index 08ffc8f3..87c24d64 100644 --- a/freebsd/sys/dev/usb/wlan/if_urtwvar.h +++ b/freebsd/sys/dev/usb/wlan/if_urtwvar.h @@ -47,10 +47,6 @@ struct urtw_data { }; typedef STAILQ_HEAD(, urtw_data) urtw_datahead; -/* XXX not correct.. */ -#define URTW_MIN_RXBUFSZ \ - (sizeof(struct ieee80211_frame_min)) - #define URTW_RX_DATA_LIST_COUNT 4 #define URTW_TX_DATA_LIST_COUNT 16 #define URTW_RX_MAXSIZE 0x9c4 @@ -59,23 +55,27 @@ typedef STAILQ_HEAD(, urtw_data) urtw_datahead; struct urtw_rx_radiotap_header { struct ieee80211_radiotap_header wr_ihdr; + uint64_t wr_tsf; uint8_t wr_flags; + uint8_t wr_pad; uint16_t wr_chan_freq; uint16_t wr_chan_flags; int8_t wr_dbm_antsignal; } __packed __aligned(8); #define URTW_RX_RADIOTAP_PRESENT \ - ((1 << IEEE80211_RADIOTAP_FLAGS) | \ + ((1 << IEEE80211_RADIOTAP_TSFT) | \ + (1 << IEEE80211_RADIOTAP_FLAGS) | \ (1 << IEEE80211_RADIOTAP_CHANNEL) | \ (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL)) struct urtw_tx_radiotap_header { struct ieee80211_radiotap_header wt_ihdr; uint8_t wt_flags; + uint8_t wt_pad; uint16_t wt_chan_freq; uint16_t wt_chan_flags; -} __packed __aligned(8); +} __packed; #define URTW_TX_RADIOTAP_PRESENT \ ((1 << IEEE80211_RADIOTAP_FLAGS) | \ diff --git a/freebsd/sys/dev/usb/wlan/if_zyd.c b/freebsd/sys/dev/usb/wlan/if_zyd.c index 1835b58b..bb4a9e40 100644 --- a/freebsd/sys/dev/usb/wlan/if_zyd.c +++ b/freebsd/sys/dev/usb/wlan/if_zyd.c @@ -46,10 +46,6 @@ __FBSDID("$FreeBSD$"); #include <sys/endian.h> #include <sys/kdb.h> -#include <machine/bus.h> -#include <machine/resource.h> -#include <sys/rman.h> - #include <net/bpf.h> #include <net/if.h> #include <net/if_var.h> @@ -2891,8 +2887,7 @@ zyd_getradiocaps(struct ieee80211com *ic, memset(bands, 0, sizeof(bands)); setbit(bands, IEEE80211_MODE_11B); setbit(bands, IEEE80211_MODE_11G); - ieee80211_add_channel_list_2ghz(chans, maxchans, nchans, - zyd_chan_2ghz, nitems(zyd_chan_2ghz), bands, 0); + ieee80211_add_channels_default_2ghz(chans, maxchans, nchans, bands, 0); } static void diff --git a/freebsd/sys/dev/usb/wlan/if_zydreg.h b/freebsd/sys/dev/usb/wlan/if_zydreg.h index 724b8c57..a4523199 100644 --- a/freebsd/sys/dev/usb/wlan/if_zydreg.h +++ b/freebsd/sys/dev/usb/wlan/if_zydreg.h @@ -421,10 +421,6 @@ #define ZYD_CR254 0x93f8 #define ZYD_CR255 0x93fc -/* nitems(ZYD_*_CHANTABLE) */ -static const uint8_t zyd_chan_2ghz[] = - { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 }; - /* copied nearly verbatim from the Linux driver rewrite */ #define ZYD_DEF_PHY \ { \ @@ -1204,7 +1200,7 @@ struct zyd_tx_radiotap_header { uint8_t wt_rate; uint16_t wt_chan_freq; uint16_t wt_chan_flags; -} __packed __aligned(8); +} __packed; #define ZYD_TX_RADIOTAP_PRESENT \ ((1 << IEEE80211_RADIOTAP_FLAGS) | \ |