diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-08-09 13:04:41 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-09-21 10:29:37 +0200 |
commit | e4a8065910cd6b2e7e0448cc6431ca2906322389 (patch) | |
tree | 73492991cfa40f994c20d761d476e6bc16304536 /freebsd/sys/dev | |
parent | Update to FreeBSD head 2017-08-01 (diff) | |
download | rtems-libbsd-e4a8065910cd6b2e7e0448cc6431ca2906322389.tar.bz2 |
Update to FreeBSD head 2017-10-01
Git mirror commit b2f0376b45428f13151d229c5ae9d4d8f74acbd1.
Update #3472.
Diffstat (limited to 'freebsd/sys/dev')
39 files changed, 760 insertions, 383 deletions
diff --git a/freebsd/sys/dev/e1000/if_em.c b/freebsd/sys/dev/e1000/if_em.c index f5a0b94e..dba6ef0a 100644 --- a/freebsd/sys/dev/e1000/if_em.c +++ b/freebsd/sys/dev/e1000/if_em.c @@ -341,6 +341,8 @@ MODULE_DEPEND(em, pci, 1, 1, 1); MODULE_DEPEND(em, ether, 1, 1, 1); MODULE_DEPEND(em, iflib, 1, 1, 1); +IFLIB_PNP_INFO(pci, em, em_vendor_info_array); + static driver_t igb_driver = { "igb", igb_methods, sizeof(struct adapter), }; @@ -352,6 +354,7 @@ MODULE_DEPEND(igb, pci, 1, 1, 1); MODULE_DEPEND(igb, ether, 1, 1, 1); MODULE_DEPEND(igb, iflib, 1, 1, 1); +IFLIB_PNP_INFO(pci, igb, igb_vendor_info_array); static device_method_t em_if_methods[] = { DEVMETHOD(ifdi_attach_pre, em_if_attach_pre), @@ -485,7 +488,7 @@ static struct if_shared_ctx em_sctx_init = { .isc_vendor_info = em_vendor_info_array, .isc_driver_version = em_driver_version, .isc_driver = &em_if_driver, - .isc_flags = IFLIB_NEED_SCRATCH | IFLIB_TSO_INIT_IP, + .isc_flags = IFLIB_NEED_SCRATCH | IFLIB_TSO_INIT_IP | IFLIB_NEED_ZERO_CSUM, .isc_nrxd_min = {EM_MIN_RXD}, .isc_ntxd_min = {EM_MIN_TXD}, @@ -513,12 +516,12 @@ static struct if_shared_ctx igb_sctx_init = { .isc_vendor_info = igb_vendor_info_array, .isc_driver_version = em_driver_version, .isc_driver = &em_if_driver, - .isc_flags = IFLIB_NEED_SCRATCH | IFLIB_TSO_INIT_IP, + .isc_flags = IFLIB_NEED_SCRATCH | IFLIB_TSO_INIT_IP | IFLIB_NEED_ZERO_CSUM, .isc_nrxd_min = {EM_MIN_RXD}, .isc_ntxd_min = {EM_MIN_TXD}, - .isc_nrxd_max = {EM_MAX_RXD}, - .isc_ntxd_max = {EM_MAX_TXD}, + .isc_nrxd_max = {IGB_MAX_RXD}, + .isc_ntxd_max = {IGB_MAX_TXD}, .isc_nrxd_default = {EM_DEFAULT_RXD}, .isc_ntxd_default = {EM_DEFAULT_TXD}, }; @@ -536,22 +539,26 @@ static int em_get_regs(SYSCTL_HANDLER_ARGS) { struct adapter *adapter = (struct adapter *)arg1; struct e1000_hw *hw = &adapter->hw; - struct sbuf *sb; - u32 *regs_buff = (u32 *)malloc(sizeof(u32) * IGB_REGS_LEN, M_DEVBUF, M_NOWAIT); + u32 *regs_buff; int rc; + regs_buff = malloc(sizeof(u32) * IGB_REGS_LEN, M_DEVBUF, M_WAITOK); memset(regs_buff, 0, IGB_REGS_LEN * sizeof(u32)); rc = sysctl_wire_old_buffer(req, 0); MPASS(rc == 0); - if (rc != 0) + if (rc != 0) { + free(regs_buff, M_DEVBUF); return (rc); + } sb = sbuf_new_for_sysctl(NULL, NULL, 32*400, req); MPASS(sb != NULL); - if (sb == NULL) + if (sb == NULL) { + free(regs_buff, M_DEVBUF); return (ENOMEM); + } /* General Registers */ regs_buff[0] = E1000_READ_REG(hw, E1000_CTRL); @@ -607,6 +614,8 @@ static int em_get_regs(SYSCTL_HANDLER_ARGS) sbuf_printf(sb, "\tTDFHS\t %08x\n", regs_buff[20]); sbuf_printf(sb, "\tTDFPC\t %08x\n\n", regs_buff[21]); + free(regs_buff, M_DEVBUF); + #ifdef DUMP_DESCS { if_softc_ctx_t scctx = adapter->shared; @@ -3641,34 +3650,13 @@ em_enable_wakeup(if_ctx_t ctx) struct adapter *adapter = iflib_get_softc(ctx); device_t dev = iflib_get_dev(ctx); if_t ifp = iflib_get_ifp(ctx); - u32 pmc, ctrl, ctrl_ext, rctl, wuc; + int error = 0; + u32 pmc, ctrl, ctrl_ext, rctl; u16 status; - if ((pci_find_cap(dev, PCIY_PMG, &pmc) != 0)) + if (pci_find_cap(dev, PCIY_PMG, &pmc) != 0) return; - /* Advertise the wakeup capability */ - ctrl = E1000_READ_REG(&adapter->hw, E1000_CTRL); - ctrl |= (E1000_CTRL_SWDPIN2 | E1000_CTRL_SWDPIN3); - E1000_WRITE_REG(&adapter->hw, E1000_CTRL, ctrl); - wuc = E1000_READ_REG(&adapter->hw, E1000_WUC); - wuc |= (E1000_WUC_PME_EN | E1000_WUC_APME); - E1000_WRITE_REG(&adapter->hw, E1000_WUC, wuc); - - if ((adapter->hw.mac.type == e1000_ich8lan) || - (adapter->hw.mac.type == e1000_pchlan) || - (adapter->hw.mac.type == e1000_ich9lan) || - (adapter->hw.mac.type == e1000_ich10lan)) - e1000_suspend_workarounds_ich8lan(&adapter->hw); - - /* Keep the laser running on Fiber adapters */ - if (adapter->hw.phy.media_type == e1000_media_type_fiber || - adapter->hw.phy.media_type == e1000_media_type_internal_serdes) { - ctrl_ext = E1000_READ_REG(&adapter->hw, E1000_CTRL_EXT); - ctrl_ext |= E1000_CTRL_EXT_SDP3_DATA; - E1000_WRITE_REG(&adapter->hw, E1000_CTRL_EXT, ctrl_ext); - } - /* * Determine type of Wakeup: note that wol * is set with all bits on by default. @@ -3687,10 +3675,34 @@ em_enable_wakeup(if_ctx_t ctx) E1000_WRITE_REG(&adapter->hw, E1000_RCTL, rctl); } + if (!(adapter->wol & (E1000_WUFC_EX | E1000_WUFC_MAG | E1000_WUFC_MC))) + goto pme; + + /* Advertise the wakeup capability */ + ctrl = E1000_READ_REG(&adapter->hw, E1000_CTRL); + ctrl |= (E1000_CTRL_SWDPIN2 | E1000_CTRL_SWDPIN3); + E1000_WRITE_REG(&adapter->hw, E1000_CTRL, ctrl); + + /* Keep the laser running on Fiber adapters */ + if (adapter->hw.phy.media_type == e1000_media_type_fiber || + adapter->hw.phy.media_type == e1000_media_type_internal_serdes) { + ctrl_ext = E1000_READ_REG(&adapter->hw, E1000_CTRL_EXT); + ctrl_ext |= E1000_CTRL_EXT_SDP3_DATA; + E1000_WRITE_REG(&adapter->hw, E1000_CTRL_EXT, ctrl_ext); + } + + if ((adapter->hw.mac.type == e1000_ich8lan) || + (adapter->hw.mac.type == e1000_pchlan) || + (adapter->hw.mac.type == e1000_ich9lan) || + (adapter->hw.mac.type == e1000_ich10lan)) + e1000_suspend_workarounds_ich8lan(&adapter->hw); + if ( adapter->hw.mac.type >= e1000_pchlan) { - if (em_enable_phy_wakeup(adapter)) - return; + error = em_enable_phy_wakeup(adapter); + if (error) + goto pme; } else { + /* Enable wakeup by the MAC */ E1000_WRITE_REG(&adapter->hw, E1000_WUC, E1000_WUC_PME_EN); E1000_WRITE_REG(&adapter->hw, E1000_WUFC, adapter->wol); } @@ -3698,10 +3710,10 @@ em_enable_wakeup(if_ctx_t ctx) if (adapter->hw.phy.type == e1000_phy_igp_3) e1000_igp3_phy_powerdown_workaround_ich8lan(&adapter->hw); - /* Request PME */ +pme: status = pci_read_config(dev, pmc + PCIR_POWER_STATUS, 2); status &= ~(PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE); - if (if_getcapenable(ifp) & IFCAP_WOL) + if (!error && (if_getcapenable(ifp) & IFCAP_WOL)) status |= PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE; pci_write_config(dev, pmc + PCIR_POWER_STATUS, status, 2); diff --git a/freebsd/sys/dev/e1000/if_em.h b/freebsd/sys/dev/e1000/if_em.h index 67d97e17..b7599291 100644 --- a/freebsd/sys/dev/e1000/if_em.h +++ b/freebsd/sys/dev/e1000/if_em.h @@ -96,10 +96,10 @@ /* Tunables */ /* - * EM_TXD: Maximum number of Transmit Descriptors + * EM_MAX_TXD: Maximum number of Transmit Descriptors * Valid Range: 80-256 for 82542 and 82543-based adapters * 80-4096 for others - * Default Value: 256 + * Default Value: 1024 * This value is the number of transmit descriptors allocated by the driver. * Increasing this value allows the driver to queue more transmits. Each * descriptor is 16 bytes. @@ -111,12 +111,13 @@ #define EM_MAX_TXD 4096 #define EM_DEFAULT_TXD 1024 #define EM_DEFAULT_MULTI_TXD 4096 +#define IGB_MAX_TXD 4096 /* - * EM_RXD - Maximum number of receive Descriptors + * EM_MAX_RXD - Maximum number of receive Descriptors * Valid Range: 80-256 for 82542 and 82543-based adapters * 80-4096 for others - * Default Value: 256 + * Default Value: 1024 * This value is the number of receive descriptors allocated by the driver. * Increasing this value allows the driver to buffer more incoming packets. * Each descriptor is 16 bytes. A receive buffer is also allocated for each @@ -129,6 +130,7 @@ #define EM_MAX_RXD 4096 #define EM_DEFAULT_RXD 1024 #define EM_DEFAULT_MULTI_RXD 4096 +#define IGB_MAX_RXD 4096 /* * EM_TIDV - Transmit Interrupt Delay Value @@ -555,26 +557,6 @@ typedef struct _em_vendor_info_t { void em_dump_rs(struct adapter *); -#define EM_CORE_LOCK_INIT(_sc, _name) \ - mtx_init(&(_sc)->core_mtx, _name, "EM Core Lock", MTX_DEF) -#define EM_TX_LOCK_INIT(_sc, _name) \ - mtx_init(&(_sc)->tx_mtx, _name, "EM TX Lock", MTX_DEF) -#define EM_RX_LOCK_INIT(_sc, _name) \ - mtx_init(&(_sc)->rx_mtx, _name, "EM RX Lock", MTX_DEF) -#define EM_CORE_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->core_mtx) -#define EM_TX_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->tx_mtx) -#define EM_RX_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->rx_mtx) -#define EM_CORE_LOCK(_sc) mtx_lock(&(_sc)->core_mtx) -#define EM_TX_LOCK(_sc) mtx_lock(&(_sc)->tx_mtx) -#define EM_TX_TRYLOCK(_sc) mtx_trylock(&(_sc)->tx_mtx) -#define EM_RX_LOCK(_sc) mtx_lock(&(_sc)->rx_mtx) -#define EM_CORE_UNLOCK(_sc) mtx_unlock(&(_sc)->core_mtx) -#define EM_TX_UNLOCK(_sc) mtx_unlock(&(_sc)->tx_mtx) -#define EM_RX_UNLOCK(_sc) mtx_unlock(&(_sc)->rx_mtx) -#define EM_CORE_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->core_mtx, MA_OWNED) -#define EM_TX_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->tx_mtx, MA_OWNED) -#define EM_RX_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->rx_mtx, MA_OWNED) - #define EM_RSSRK_SIZE 4 #define EM_RSSRK_VAL(key, i) (key[(i) * EM_RSSRK_SIZE] | \ key[(i) * EM_RSSRK_SIZE + 1] << 8 | \ diff --git a/freebsd/sys/dev/fdt/fdt_common.c b/freebsd/sys/dev/fdt/fdt_common.c index b149695c..c8c777f1 100644 --- a/freebsd/sys/dev/fdt/fdt_common.c +++ b/freebsd/sys/dev/fdt/fdt_common.c @@ -62,6 +62,7 @@ __FBSDID("$FreeBSD$"); #define FDT_TYPE_LEN 64 #define FDT_REG_CELLS 4 +#define FDT_RANGES_SIZE 48 SYSCTL_NODE(_hw, OID_AUTO, fdt, CTLFLAG_RD, 0, "Flattened Device Tree"); @@ -151,7 +152,7 @@ fdt_get_range_by_busaddr(phandle_t node, u_long addr, u_long *base, int fdt_get_range(phandle_t node, int range_id, u_long *base, u_long *size) { - pcell_t ranges[6], *rangesptr; + pcell_t ranges[FDT_RANGES_SIZE], *rangesptr; pcell_t addr_cells, size_cells, par_addr_cells; u_long par_bus_addr, pbase, psize; int err, len, tuple_size, tuples; diff --git a/freebsd/sys/dev/mmc/bridge.h b/freebsd/sys/dev/mmc/bridge.h index 53e61b48..b7d95ffc 100644 --- a/freebsd/sys/dev/mmc/bridge.h +++ b/freebsd/sys/dev/mmc/bridge.h @@ -65,12 +65,10 @@ * linux/mmc/host.h file. * * A mmc bridge is a chipset that can have one or more mmc and/or sd - * cards attached to it. mmc cards are attached on a bus topology, - * while sd and sdio cards are attached using a star topology (meaning - * in practice each sd card has its own, independent slot). Each - * mmcbr is assumed to be derived from the mmcbr. This is done to - * allow for easier addition of bridges (as each bridge does not need - * to be added to the mmcbus file). + * cards attached to it. mmc devices are attached on a bus topology, + * while sd and sdio cards usually are attached using a star topology + * (meaning in practice each sd card has its own, independent slot). + * Since SDHCI v3.00, buses for esd and esdio are possible, though. * * Attached to the mmc bridge is an mmcbus. The mmcbus is described * in dev/mmc/mmcbus_if.m. @@ -182,7 +180,7 @@ struct mmc_host { extern driver_t mmc_driver; extern devclass_t mmc_devclass; -#define MMC_VERSION 4 +#define MMC_VERSION 5 #define MMC_DECLARE_BRIDGE(name) \ DRIVER_MODULE(mmc, name, mmc_driver, mmc_devclass, NULL, NULL); \ diff --git a/freebsd/sys/dev/mmc/mmc.c b/freebsd/sys/dev/mmc/mmc.c index 74e26332..77934e86 100644 --- a/freebsd/sys/dev/mmc/mmc.c +++ b/freebsd/sys/dev/mmc/mmc.c @@ -106,12 +106,34 @@ struct mmc_ivars { uint32_t hs_tran_speed; /* Max speed in high speed mode */ uint32_t erase_sector; /* Card native erase sector size */ uint32_t cmd6_time; /* Generic switch timeout [us] */ + uint32_t quirks; /* Quirks as per mmc_quirk->quirks */ char card_id_string[64];/* Formatted CID info (serial, MFG, etc) */ char card_sn_string[16];/* Formatted serial # for disk->d_ident */ }; #define CMD_RETRIES 3 +static const struct mmc_quirk mmc_quirks[] = { + /* + * For some SanDisk iNAND devices, the CMD38 argument needs to be + * provided in EXT_CSD[113]. + */ + { 0x2, 0x100, "SEM02G", MMC_QUIRK_INAND_CMD38 }, + { 0x2, 0x100, "SEM04G", MMC_QUIRK_INAND_CMD38 }, + { 0x2, 0x100, "SEM08G", MMC_QUIRK_INAND_CMD38 }, + { 0x2, 0x100, "SEM16G", MMC_QUIRK_INAND_CMD38 }, + { 0x2, 0x100, "SEM32G", MMC_QUIRK_INAND_CMD38 }, + + /* + * Disable TRIM for Kingston eMMCs where a firmware bug can lead to + * unrecoverable data corruption. + */ + { 0x70, MMC_QUIRK_OID_ANY, "V10008", MMC_QUIRK_BROKEN_TRIM }, + { 0x70, MMC_QUIRK_OID_ANY, "V10016", MMC_QUIRK_BROKEN_TRIM }, + + { 0x0, 0x0, NULL, 0x0 } +}; + static SYSCTL_NODE(_hw, OID_AUTO, mmc, CTLFLAG_RD, NULL, "mmc driver"); static int mmc_debug; @@ -1123,7 +1145,7 @@ mmc_format_card_id_string(struct mmc_ivars *ivar) /* * Format a card ID string for use by the mmcsd driver, it's what * appears between the <> in the following: - * mmcsd0: 968MB <SD SD01G 8.0 SN 2686905 Mfg 08/2008 by 3 TN> at mmc0 + * mmcsd0: 968MB <SD SD01G 8.0 SN 2686905 MFG 08/2008 by 3 TN> at mmc0 * 22.5MHz/4bit/128-block * * Also format just the card serial number, which the mmcsd driver will @@ -1561,6 +1583,7 @@ mmc_log_card(device_t dev, struct mmc_ivars *ivar, int newcard) break; } } + device_printf(dev, " quirks: %b\n", ivar->quirks, MMC_QUIRKS_FMT); device_printf(dev, " bus: %ubit, %uMHz (%s timing)\n", (ivar->bus_width == bus_width_1 ? 1 : (ivar->bus_width == bus_width_4 ? 4 : 8)), @@ -1577,6 +1600,7 @@ mmc_discover_cards(struct mmc_softc *sc) u_char switch_res[64]; uint32_t raw_cid[4]; struct mmc_ivars *ivar = NULL; + const struct mmc_quirk *quirk; device_t child; int err, host_caps, i, newcard; uint32_t resp, sec_count, status; @@ -1884,6 +1908,18 @@ mmc_discover_cards(struct mmc_softc *sc) ivar->raw_ext_csd[EXT_CSD_REV] >= 5); child_common: + for (quirk = &mmc_quirks[0]; quirk->mid != 0x0; quirk++) { + if ((quirk->mid == MMC_QUIRK_MID_ANY || + quirk->mid == ivar->cid.mid) && + (quirk->oid == MMC_QUIRK_OID_ANY || + quirk->oid == ivar->cid.oid) && + strncmp(quirk->pnm, ivar->cid.pnm, + sizeof(ivar->cid.pnm)) == 0) { + ivar->quirks = quirk->quirks; + break; + } + } + /* * Some cards that report maximum I/O block sizes greater * than 512 require the block length to be set to 512, even @@ -2485,6 +2521,12 @@ mmc_read_ivar(device_t bus, device_t child, int which, uintptr_t *result) case MMC_IVAR_MAX_DATA: *result = mmcbr_get_max_data(bus); break; + case MMC_IVAR_CMD6_TIMEOUT: + *result = ivar->cmd6_time; + break; + case MMC_IVAR_QUIRKS: + *result = ivar->quirks; + break; case MMC_IVAR_CARD_ID_STRING: *(char **)result = ivar->card_id_string; break; diff --git a/freebsd/sys/dev/mmc/mmc_subr.c b/freebsd/sys/dev/mmc/mmc_subr.c index 006354ba..76a14028 100644 --- a/freebsd/sys/dev/mmc/mmc_subr.c +++ b/freebsd/sys/dev/mmc/mmc_subr.c @@ -74,7 +74,7 @@ __FBSDID("$FreeBSD$"); #define LOG_PPS 5 /* Log no more than 5 errors per second. */ int -mmc_wait_for_cmd(device_t brdev, device_t reqdev, struct mmc_command *cmd, +mmc_wait_for_cmd(device_t busdev, device_t dev, struct mmc_command *cmd, int retries) { struct mmc_request mreq; @@ -89,14 +89,14 @@ mmc_wait_for_cmd(device_t brdev, device_t reqdev, struct mmc_command *cmd, if (cmd->data != NULL) cmd->data->mrq = &mreq; mreq.cmd = cmd; - if (MMCBUS_WAIT_FOR_REQUEST(brdev, reqdev, &mreq) != 0) + if (MMCBUS_WAIT_FOR_REQUEST(busdev, dev, &mreq) != 0) err = MMC_ERR_FAILED; else err = cmd->error; } while (err != MMC_ERR_NONE && retries-- > 0); - if (err != MMC_ERR_NONE && brdev == reqdev) { - sc = device_get_softc(brdev); + if (err != MMC_ERR_NONE && busdev == dev) { + sc = device_get_softc(busdev); if (sc->squelched == 0 && ppsratecheck(&sc->log_time, &sc->log_count, LOG_PPS)) { device_printf(sc->dev, "CMD%d failed, RESULT: %d\n", @@ -108,14 +108,14 @@ mmc_wait_for_cmd(device_t brdev, device_t reqdev, struct mmc_command *cmd, } int -mmc_wait_for_app_cmd(device_t brdev, device_t reqdev, uint16_t rca, +mmc_wait_for_app_cmd(device_t busdev, device_t dev, uint16_t rca, struct mmc_command *cmd, int retries) { struct mmc_command appcmd; struct mmc_softc *sc; int err; - sc = device_get_softc(brdev); + sc = device_get_softc(busdev); /* Squelch error reporting at lower levels, we report below. */ sc->squelched++; @@ -124,14 +124,14 @@ mmc_wait_for_app_cmd(device_t brdev, device_t reqdev, uint16_t rca, appcmd.opcode = MMC_APP_CMD; appcmd.arg = (uint32_t)rca << 16; appcmd.flags = MMC_RSP_R1 | MMC_CMD_AC; - if (mmc_wait_for_cmd(brdev, reqdev, &appcmd, 0) != 0) + if (mmc_wait_for_cmd(busdev, dev, &appcmd, 0) != 0) err = MMC_ERR_FAILED; else err = appcmd.error; if (err == MMC_ERR_NONE) { if (!(appcmd.resp[0] & R1_APP_CMD)) err = MMC_ERR_FAILED; - else if (mmc_wait_for_cmd(brdev, reqdev, cmd, 0) != 0) + else if (mmc_wait_for_cmd(busdev, dev, cmd, 0) != 0) err = MMC_ERR_FAILED; else err = cmd->error; @@ -139,7 +139,7 @@ mmc_wait_for_app_cmd(device_t brdev, device_t reqdev, uint16_t rca, } while (err != MMC_ERR_NONE && retries-- > 0); sc->squelched--; - if (err != MMC_ERR_NONE && brdev == reqdev) { + if (err != MMC_ERR_NONE && busdev == dev) { if (sc->squelched == 0 && ppsratecheck(&sc->log_time, &sc->log_count, LOG_PPS)) { device_printf(sc->dev, "ACMD%d failed, RESULT: %d\n", @@ -151,7 +151,7 @@ mmc_wait_for_app_cmd(device_t brdev, device_t reqdev, uint16_t rca, } int -mmc_switch(device_t brdev, device_t reqdev, uint16_t rca, uint8_t set, +mmc_switch(device_t busdev, device_t dev, uint16_t rca, uint8_t set, uint8_t index, uint8_t value, u_int timeout, bool status) { struct mmc_command cmd; @@ -160,7 +160,7 @@ mmc_switch(device_t brdev, device_t reqdev, uint16_t rca, uint8_t set, KASSERT(timeout != 0, ("%s: no timeout", __func__)); - sc = device_get_softc(brdev); + sc = device_get_softc(busdev); memset(&cmd, 0, sizeof(cmd)); cmd.opcode = MMC_SWITCH_FUNC; @@ -171,8 +171,8 @@ mmc_switch(device_t brdev, device_t reqdev, uint16_t rca, uint8_t set, * exceeds the maximum host timeout, use a R1 instead of a R1B * response in order to keep the hardware from timing out. */ - if (mmcbr_get_caps(brdev) & MMC_CAP_WAIT_WHILE_BUSY && - timeout > mmcbr_get_max_busy_timeout(brdev)) + if (mmcbr_get_caps(busdev) & MMC_CAP_WAIT_WHILE_BUSY && + timeout > mmcbr_get_max_busy_timeout(busdev)) cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; else cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; @@ -182,17 +182,17 @@ mmc_switch(device_t brdev, device_t reqdev, uint16_t rca, uint8_t set, * than to a tuning command that may have snuck in between. */ sc->retune_paused++; - err = mmc_wait_for_cmd(brdev, reqdev, &cmd, CMD_RETRIES); + err = mmc_wait_for_cmd(busdev, dev, &cmd, CMD_RETRIES); if (err != MMC_ERR_NONE || status == false) goto out; - err = mmc_switch_status(brdev, reqdev, rca, timeout); + err = mmc_switch_status(busdev, dev, rca, timeout); out: sc->retune_paused--; return (err); } int -mmc_switch_status(device_t brdev, device_t reqdev, uint16_t rca, u_int timeout) +mmc_switch_status(device_t busdev, device_t dev, uint16_t rca, u_int timeout) { struct timeval cur, end; int err; @@ -207,7 +207,7 @@ mmc_switch_status(device_t brdev, device_t reqdev, uint16_t rca, u_int timeout) */ end.tv_sec = end.tv_usec = 0; for (;;) { - err = mmc_send_status(brdev, reqdev, rca, &status); + err = mmc_send_status(busdev, dev, rca, &status); if (err != MMC_ERR_NONE) break; if (R1_CURRENT_STATE(status) == R1_STATE_TRAN) @@ -228,7 +228,7 @@ mmc_switch_status(device_t brdev, device_t reqdev, uint16_t rca, u_int timeout) } int -mmc_send_ext_csd(device_t brdev, device_t reqdev, uint8_t *rawextcsd) +mmc_send_ext_csd(device_t busdev, device_t dev, uint8_t *rawextcsd) { struct mmc_command cmd; struct mmc_data data; @@ -246,12 +246,12 @@ mmc_send_ext_csd(device_t brdev, device_t reqdev, uint8_t *rawextcsd) data.len = MMC_EXTCSD_SIZE; data.flags = MMC_DATA_READ; - err = mmc_wait_for_cmd(brdev, reqdev, &cmd, CMD_RETRIES); + err = mmc_wait_for_cmd(busdev, dev, &cmd, CMD_RETRIES); return (err); } int -mmc_send_status(device_t brdev, device_t reqdev, uint16_t rca, uint32_t *status) +mmc_send_status(device_t busdev, device_t dev, uint16_t rca, uint32_t *status) { struct mmc_command cmd; int err; @@ -260,7 +260,7 @@ mmc_send_status(device_t brdev, device_t reqdev, uint16_t rca, uint32_t *status) cmd.opcode = MMC_SEND_STATUS; cmd.arg = (uint32_t)rca << 16; cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; - err = mmc_wait_for_cmd(brdev, reqdev, &cmd, CMD_RETRIES); + err = mmc_wait_for_cmd(busdev, dev, &cmd, CMD_RETRIES); *status = cmd.resp[0]; return (err); } diff --git a/freebsd/sys/dev/mmc/mmc_subr.h b/freebsd/sys/dev/mmc/mmc_subr.h index 6e300d2f..33ea6760 100644 --- a/freebsd/sys/dev/mmc/mmc_subr.h +++ b/freebsd/sys/dev/mmc/mmc_subr.h @@ -57,16 +57,16 @@ struct mmc_command; -int mmc_send_ext_csd(device_t brdev, device_t reqdev, uint8_t *rawextcsd); -int mmc_send_status(device_t brdev, device_t reqdev, uint16_t rca, +int mmc_send_ext_csd(device_t busdev, device_t dev, uint8_t *rawextcsd); +int mmc_send_status(device_t busdev, device_t dev, uint16_t rca, uint32_t *status); -int mmc_switch(device_t brdev, device_t reqdev, uint16_t rca, uint8_t set, +int mmc_switch(device_t busdev, device_t dev, uint16_t rca, uint8_t set, uint8_t index, uint8_t value, u_int timeout, bool send_status); -int mmc_switch_status(device_t brdev, device_t reqdev, uint16_t rca, +int mmc_switch_status(device_t busdev, device_t dev, uint16_t rca, u_int timeout); -int mmc_wait_for_app_cmd(device_t brdev, device_t reqdev, uint16_t rca, +int mmc_wait_for_app_cmd(device_t busdev, device_t dev, uint16_t rca, struct mmc_command *cmd, int retries); -int mmc_wait_for_cmd(device_t brdev, device_t reqdev, struct mmc_command *cmd, +int mmc_wait_for_cmd(device_t busdev, device_t dev, struct mmc_command *cmd, int retries); #endif /* DEV_MMC_SUBR_H */ diff --git a/freebsd/sys/dev/mmc/mmcreg.h b/freebsd/sys/dev/mmc/mmcreg.h index 80f433c1..8120b69f 100644 --- a/freebsd/sys/dev/mmc/mmcreg.h +++ b/freebsd/sys/dev/mmc/mmcreg.h @@ -276,6 +276,13 @@ struct mmc_request { #define MMC_ERASE_GROUP_END 36 /* 37 -- reserved old command */ #define MMC_ERASE 38 +#define MMC_ERASE_ERASE 0x00000000 +#define MMC_ERASE_TRIM 0x00000001 +#define MMC_ERASE_FULE 0x00000002 +#define MMC_ERASE_DISCARD 0x00000003 +#define MMC_ERASE_SECURE_ERASE 0x80000000 +#define MMC_ERASE_SECURE_TRIM1 0x80000001 +#define MMC_ERASE_SECURE_TRIM2 0x80008000 /* Class 9: I/O mode commands */ #define MMC_FAST_IO 39 @@ -383,6 +390,7 @@ struct mmc_request { #define EXT_CSD_ERASE_TO_MULT 223 /* RO */ #define EXT_CSD_ERASE_GRP_SIZE 224 /* RO */ #define EXT_CSD_BOOT_SIZE_MULT 226 /* RO */ +#define EXT_CSD_SEC_FEATURE_SUPPORT 231 /* RO */ #define EXT_CSD_PWR_CL_200_195 236 /* RO */ #define EXT_CSD_PWR_CL_200_360 237 /* RO */ #define EXT_CSD_PWR_CL_52_195_DDR 238 /* RO */ @@ -467,6 +475,22 @@ struct mmc_request { #define EXT_CSD_STROBE_SUPPORT_EN 0x01 +#define EXT_CSD_SEC_FEATURE_SUPPORT_ER_EN 0x01 +#define EXT_CSD_SEC_FEATURE_SUPPORT_BD_BLK_EN 0x04 +#define EXT_CSD_SEC_FEATURE_SUPPORT_GB_CL_EN 0x10 +#define EXT_CSD_SEC_FEATURE_SUPPORT_SANITIZE 0x40 + +/* + * Vendor specific EXT_CSD fields + */ +/* SanDisk iNAND */ +#define EXT_CSD_INAND_CMD38 113 +#define EXT_CSD_INAND_CMD38_ERASE 0x00 +#define EXT_CSD_INAND_CMD38_TRIM 0x01 +#define EXT_CSD_INAND_CMD38_SECURE_ERASE 0x80 +#define EXT_CSD_INAND_CMD38_SECURE_TRIM1 0x81 +#define EXT_CSD_INAND_CMD38_SECURE_TRIM2 0x82 + #define MMC_TYPE_HS_26_MAX 26000000 #define MMC_TYPE_HS_52_MAX 52000000 #define MMC_TYPE_DDR52_MAX 52000000 @@ -608,8 +632,7 @@ struct mmc_cid { uint8_t fwrev; }; -struct mmc_csd -{ +struct mmc_csd { uint8_t csd_structure; uint8_t spec_vers; uint16_t ccc; @@ -635,16 +658,14 @@ struct mmc_csd wp_grp_enable:1; }; -struct mmc_scr -{ +struct mmc_scr { unsigned char sda_vsn; unsigned char bus_widths; #define SD_SCR_BUS_WIDTH_1 (1 << 0) #define SD_SCR_BUS_WIDTH_4 (1 << 2) }; -struct mmc_sd_status -{ +struct mmc_sd_status { uint8_t bus_width; uint8_t secured_mode; uint16_t card_type; @@ -657,6 +678,19 @@ struct mmc_sd_status uint8_t erase_offset; }; +struct mmc_quirk { + uint32_t mid; +#define MMC_QUIRK_MID_ANY ((uint32_t)-1) + uint16_t oid; +#define MMC_QUIRK_OID_ANY ((uint16_t)-1) + const char *pnm; + uint32_t quirks; +#define MMC_QUIRK_INAND_CMD38 0x0001 +#define MMC_QUIRK_BROKEN_TRIM 0x0002 +}; + +#define MMC_QUIRKS_FMT "\020" "\001INAND_CMD38" "\002BROKEN_TRIM" + /* * Various MMC/SD constants */ diff --git a/freebsd/sys/dev/mmc/mmcsd.c b/freebsd/sys/dev/mmc/mmcsd.c index 195feae2..45bd9c50 100644 --- a/freebsd/sys/dev/mmc/mmcsd.c +++ b/freebsd/sys/dev/mmc/mmcsd.c @@ -128,7 +128,7 @@ struct mmcsd_part { struct mmcsd_softc { device_t dev; - device_t mmcbr; + device_t mmcbus; struct mmcsd_part *part[MMC_PART_MAX]; enum mmc_card_mode mode; u_int max_data; /* Maximum data size [blocks] */ @@ -137,6 +137,10 @@ struct mmcsd_softc { uint8_t part_curr; /* Partition currently switched to */ uint8_t ext_csd[MMC_EXTCSD_SIZE]; uint16_t rca; + uint32_t flags; +#define MMCSD_INAND_CMD38 0x0001 +#define MMCSD_USE_TRIM 0x0002 + uint32_t cmd6_time; /* Generic switch timeout [us] */ uint32_t part_time; /* Partition switch timeout [us] */ off_t enh_base; /* Enhanced user data area slice base ... */ off_t enh_size; /* ... and size [bytes] */ @@ -147,6 +151,9 @@ struct mmcsd_softc { #ifndef __rtems__ static const char *errmsg[] = +#else /* __rtems__ */ +static const char * const errmsg[] = +#endif /* __rtems__ */ { "None", "Timeout", @@ -156,7 +163,6 @@ static const char *errmsg[] = "Invalid", "NO MEMORY" }; -#endif /* __rtems__ */ #define LOG_PPS 5 /* Log no more than 5 errors per second. */ @@ -183,11 +189,12 @@ static int mmcsd_ioctl_rpmb(struct cdev *dev, u_long cmd, caddr_t data, int fflag, struct thread *td); static void mmcsd_add_part(struct mmcsd_softc *sc, u_int type, - const char *name, u_int cnt, off_t media_size, off_t erase_size, bool ro); + const char *name, u_int cnt, off_t media_size, bool ro); static int mmcsd_bus_bit_width(device_t dev); #ifndef __rtems__ static daddr_t mmcsd_delete(struct mmcsd_part *part, struct bio *bp); #endif /* __rtems__ */ +static const char *mmcsd_errmsg(int e); static int mmcsd_ioctl(struct mmcsd_part *part, u_long cmd, void *data, int fflag); static int mmcsd_ioctl_cmd(struct mmcsd_part *part, struct mmc_ioc_cmd *mic, @@ -440,20 +447,21 @@ error: static int mmcsd_attach(device_t dev) { - device_t mmcbr; + device_t mmcbus; struct mmcsd_softc *sc; const uint8_t *ext_csd; off_t erase_size, sector_size, size, wp_size; uintmax_t bytes; int err, i; + uint32_t quirks; uint8_t rev; bool comp, ro; char unit[2]; sc = device_get_softc(dev); sc->dev = dev; - sc->mmcbr = mmcbr = device_get_parent(dev); - sc->mode = mmcbr_get_mode(mmcbr); + sc->mmcbus = mmcbus = device_get_parent(dev); + sc->mode = mmcbr_get_mode(mmcbus); /* * Note that in principle with an SDHCI-like re-tuning implementation, * the maximum data size can change at runtime due to a device removal/ @@ -464,20 +472,47 @@ mmcsd_attach(device_t dev) * place either. */ sc->max_data = mmc_get_max_data(dev); - sc->erase_sector = mmc_get_erase_sector(dev); sc->high_cap = mmc_get_high_cap(dev); sc->rca = mmc_get_rca(dev); + sc->cmd6_time = mmc_get_cmd6_timeout(dev); + quirks = mmc_get_quirks(dev); /* Only MMC >= 4.x devices support EXT_CSD. */ if (mmc_get_spec_vers(dev) >= 4) { - MMCBUS_ACQUIRE_BUS(mmcbr, dev); - err = mmc_send_ext_csd(mmcbr, dev, sc->ext_csd); - MMCBUS_RELEASE_BUS(mmcbr, dev); - if (err != MMC_ERR_NONE) - bzero(sc->ext_csd, sizeof(sc->ext_csd)); + MMCBUS_ACQUIRE_BUS(mmcbus, dev); + err = mmc_send_ext_csd(mmcbus, dev, sc->ext_csd); + MMCBUS_RELEASE_BUS(mmcbus, dev); + if (err != MMC_ERR_NONE) { + device_printf(dev, "Error reading EXT_CSD %s\n", + mmcsd_errmsg(err)); + return (ENXIO); + } } ext_csd = sc->ext_csd; + if ((quirks & MMC_QUIRK_INAND_CMD38) != 0) { + if (mmc_get_spec_vers(dev) < 4) { + device_printf(dev, + "MMC_QUIRK_INAND_CMD38 set but no EXT_CSD\n"); + return (EINVAL); + } + sc->flags |= MMCSD_INAND_CMD38; + } + + /* + * EXT_CSD_SEC_FEATURE_SUPPORT_GB_CL_EN denotes support for both + * insecure and secure TRIM. + */ + if ((ext_csd[EXT_CSD_SEC_FEATURE_SUPPORT] & + EXT_CSD_SEC_FEATURE_SUPPORT_GB_CL_EN) != 0 && + (quirks & MMC_QUIRK_BROKEN_TRIM) == 0) { + if (bootverbose) + device_printf(dev, "taking advantage of TRIM\n"); + sc->flags |= MMCSD_USE_TRIM; + sc->erase_sector = 1; + } else + sc->erase_sector = mmc_get_erase_sector(dev); + /* * Enhanced user data area and general purpose partitions are only * supported in revision 1.4 (EXT_CSD_REV == 4) and later, the RPMB @@ -531,8 +566,7 @@ mmcsd_attach(device_t dev) */ ro = mmc_get_read_only(dev); mmcsd_add_part(sc, EXT_CSD_PART_CONFIG_ACC_DEFAULT, "mmcsd", - device_get_unit(dev), mmc_get_media_size(dev) * sector_size, - sc->erase_sector * sector_size, ro); + device_get_unit(dev), mmc_get_media_size(dev) * sector_size, ro); if (mmc_get_spec_vers(dev) < 3) return (0); @@ -555,13 +589,13 @@ mmcsd_attach(device_t dev) /* Add boot partitions, which are of a fixed multiple of 128 KB. */ size = ext_csd[EXT_CSD_BOOT_SIZE_MULT] * MMC_BOOT_RPMB_BLOCK_SIZE; - if (size > 0 && (mmcbr_get_caps(mmcbr) & MMC_CAP_BOOT_NOACC) == 0) { + if (size > 0 && (mmcbr_get_caps(mmcbus) & MMC_CAP_BOOT_NOACC) == 0) { mmcsd_add_part(sc, EXT_CSD_PART_CONFIG_ACC_BOOT0, - MMCSD_FMT_BOOT, 0, size, MMC_BOOT_RPMB_BLOCK_SIZE, + MMCSD_FMT_BOOT, 0, size, ro | ((ext_csd[EXT_CSD_BOOT_WP_STATUS] & EXT_CSD_BOOT_WP_STATUS_BOOT0_MASK) != 0)); mmcsd_add_part(sc, EXT_CSD_PART_CONFIG_ACC_BOOT1, - MMCSD_FMT_BOOT, 1, size, MMC_BOOT_RPMB_BLOCK_SIZE, + MMCSD_FMT_BOOT, 1, size, ro | ((ext_csd[EXT_CSD_BOOT_WP_STATUS] & EXT_CSD_BOOT_WP_STATUS_BOOT1_MASK) != 0)); } @@ -570,7 +604,7 @@ mmcsd_attach(device_t dev) size = ext_csd[EXT_CSD_RPMB_MULT] * MMC_BOOT_RPMB_BLOCK_SIZE; if (rev >= 5 && size > 0) mmcsd_add_part(sc, EXT_CSD_PART_CONFIG_ACC_RPMB, - MMCSD_FMT_RPMB, 0, size, MMC_BOOT_RPMB_BLOCK_SIZE, ro); + MMCSD_FMT_RPMB, 0, size, ro); if (rev <= 3 || comp == FALSE) return (0); @@ -590,8 +624,7 @@ mmcsd_attach(device_t dev) if (size == 0) continue; mmcsd_add_part(sc, EXT_CSD_PART_CONFIG_ACC_GP0 + i, - MMCSD_FMT_GP, i, size * erase_size * wp_size, - erase_size, ro); + MMCSD_FMT_GP, i, size * erase_size * wp_size, ro); } } return (0); @@ -644,10 +677,10 @@ static struct cdevsw mmcsd_rpmb_cdevsw = { static void mmcsd_add_part(struct mmcsd_softc *sc, u_int type, const char *name, u_int cnt, - off_t media_size, off_t erase_size, bool ro) + off_t media_size, bool ro) { struct make_dev_args args; - device_t dev, mmcbr; + device_t dev, mmcbus; const char *ext; const uint8_t *ext_csd; struct mmcsd_part *part; @@ -662,7 +695,7 @@ mmcsd_add_part(struct mmcsd_softc *sc, u_int type, const char *name, u_int cnt, char unit[2]; dev = sc->dev; - mmcbr = sc->mmcbr; + mmcbus = sc->mmcbus; part = sc->part[type] = malloc(sizeof(*part), M_DEVBUF, M_WAITOK | M_ZERO); part->sc = sc; @@ -710,10 +743,10 @@ mmcsd_add_part(struct mmcsd_softc *sc, u_int type, const char *name, u_int cnt, d->d_sectorsize = mmc_get_sector_size(dev); d->d_maxsize = sc->max_data * d->d_sectorsize; d->d_mediasize = media_size; - d->d_stripesize = erase_size; + d->d_stripesize = sc->erase_sector * d->d_sectorsize; d->d_unit = cnt; d->d_flags = DISKFLAG_CANDELETE; - d->d_delmaxsize = erase_size; + d->d_delmaxsize = mmc_get_erase_sector(dev) * d->d_sectorsize; strlcpy(d->d_ident, mmc_get_card_sn_string(dev), sizeof(d->d_ident)); strlcpy(d->d_descr, mmc_get_card_id_string(dev), @@ -735,10 +768,10 @@ mmcsd_add_part(struct mmcsd_softc *sc, u_int type, const char *name, u_int cnt, bytes = mmcsd_pretty_size(media_size, unit); if (type == EXT_CSD_PART_CONFIG_ACC_DEFAULT) { - speed = mmcbr_get_clock(mmcbr); + speed = mmcbr_get_clock(mmcbus); printf("%s%d: %ju%sB <%s>%s at %s %d.%01dMHz/%dbit/%d-block\n", part->name, cnt, bytes, unit, mmc_get_card_id_string(dev), - ro ? " (read-only)" : "", device_get_nameunit(mmcbr), + ro ? " (read-only)" : "", device_get_nameunit(mmcbus), speed / 1000000, (speed / 100000) % 10, mmcsd_bus_bit_width(dev), sc->max_data); } else if (type == EXT_CSD_PART_CONFIG_ACC_RPMB) { @@ -1053,7 +1086,7 @@ mmcsd_ioctl_cmd(struct mmcsd_part *part, struct mmc_ioc_cmd *mic, int fflag) struct mmc_command cmd; struct mmc_data data; struct mmcsd_softc *sc; - device_t dev, mmcbr; + device_t dev, mmcbus; void *dp; u_long len; int err, retries; @@ -1136,9 +1169,9 @@ mmcsd_ioctl_cmd(struct mmcsd_part *part, struct mmc_ioc_cmd *mic, int fflag) } } dev = sc->dev; - mmcbr = sc->mmcbr; - MMCBUS_ACQUIRE_BUS(mmcbr, dev); - err = mmcsd_switch_part(mmcbr, dev, rca, part->type); + mmcbus = sc->mmcbus; + MMCBUS_ACQUIRE_BUS(mmcbus, dev); + err = mmcsd_switch_part(mmcbus, dev, rca, part->type); if (err != MMC_ERR_NONE) goto release; if (part->type == EXT_CSD_PART_CONFIG_ACC_RPMB) { @@ -1148,9 +1181,9 @@ mmcsd_ioctl_cmd(struct mmcsd_part *part, struct mmc_ioc_cmd *mic, int fflag) goto switch_back; } if (mic->is_acmd != 0) - (void)mmc_wait_for_app_cmd(mmcbr, dev, rca, &cmd, 0); + (void)mmc_wait_for_app_cmd(mmcbus, dev, rca, &cmd, 0); else - (void)mmc_wait_for_cmd(mmcbr, dev, &cmd, 0); + (void)mmc_wait_for_cmd(mmcbus, dev, &cmd, 0); if (part->type == EXT_CSD_PART_CONFIG_ACC_RPMB) { /* * If the request went to the RPMB partition, try to ensure @@ -1158,7 +1191,7 @@ mmcsd_ioctl_cmd(struct mmcsd_part *part, struct mmc_ioc_cmd *mic, int fflag) */ retries = MMCSD_CMD_RETRIES; do { - err = mmc_send_status(mmcbr, dev, rca, &status); + err = mmc_send_status(mmcbus, dev, rca, &status); if (err != MMC_ERR_NONE) break; if (R1_STATUS(status) == 0 && @@ -1169,7 +1202,7 @@ mmcsd_ioctl_cmd(struct mmcsd_part *part, struct mmc_ioc_cmd *mic, int fflag) switch_back: /* ... and always switch back to the default partition. */ - err = mmcsd_switch_part(mmcbr, dev, rca, + err = mmcsd_switch_part(mmcbus, dev, rca, EXT_CSD_PART_CONFIG_ACC_DEFAULT); if (err != MMC_ERR_NONE) goto release; @@ -1180,11 +1213,11 @@ switch_back: * so retrieve EXT_CSD again. */ if (cmd.opcode == MMC_SWITCH_FUNC) { - err = mmc_send_ext_csd(mmcbr, dev, sc->ext_csd); + err = mmc_send_ext_csd(mmcbus, dev, sc->ext_csd); if (err != MMC_ERR_NONE) goto release; } - MMCBUS_RELEASE_BUS(mmcbr, dev); + MMCBUS_RELEASE_BUS(mmcbus, dev); if (cmd.error != MMC_ERR_NONE) { switch (cmd.error) { case MMC_ERR_TIMEOUT: @@ -1214,7 +1247,7 @@ switch_back: goto out; release: - MMCBUS_RELEASE_BUS(mmcbr, dev); + MMCBUS_RELEASE_BUS(mmcbus, dev); err = EIO; out: @@ -1262,7 +1295,7 @@ mmcsd_set_blockcount(struct mmcsd_softc *sc, u_int count, bool reliable) if (reliable) cmd.arg |= 1 << 31; cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; - MMCBUS_WAIT_FOR_REQUEST(sc->mmcbr, sc->dev, &req); + MMCBUS_WAIT_FOR_REQUEST(sc->mmcbus, sc->dev, &req); return (cmd.error); } @@ -1289,7 +1322,7 @@ mmcsd_switch_part(device_t bus, device_t dev, uint16_t rca, u_int part) * anew. */ if (part == EXT_CSD_PART_CONFIG_ACC_RPMB) - MMCBUS_RETUNE_PAUSE(sc->mmcbr, sc->dev, true); + MMCBUS_RETUNE_PAUSE(sc->mmcbus, sc->dev, true); if (sc->part_curr == part) return (MMC_ERR_NONE); @@ -1301,18 +1334,17 @@ mmcsd_switch_part(device_t bus, device_t dev, uint16_t rca, u_int part) EXT_CSD_PART_CONFIG, value, sc->part_time, true); if (err != MMC_ERR_NONE) { if (part == EXT_CSD_PART_CONFIG_ACC_RPMB) - MMCBUS_RETUNE_UNPAUSE(sc->mmcbr, sc->dev); + MMCBUS_RETUNE_UNPAUSE(sc->mmcbus, sc->dev); return (err); } sc->ext_csd[EXT_CSD_PART_CONFIG] = value; if (sc->part_curr == EXT_CSD_PART_CONFIG_ACC_RPMB) - MMCBUS_RETUNE_UNPAUSE(sc->mmcbr, sc->dev); + MMCBUS_RETUNE_UNPAUSE(sc->mmcbus, sc->dev); sc->part_curr = part; return (MMC_ERR_NONE); } -#ifndef __rtems__ static const char * mmcsd_errmsg(int e) { @@ -1322,6 +1354,7 @@ mmcsd_errmsg(int e) return (errmsg[e]); } +#ifndef __rtems__ static daddr_t mmcsd_rw(struct mmcsd_part *part, struct bio *bp) { @@ -1331,13 +1364,13 @@ mmcsd_rw(struct mmcsd_part *part, struct bio *bp) struct mmc_request req; struct mmc_data data; struct mmcsd_softc *sc; - device_t dev, mmcbr; + device_t dev, mmcbus; u_int numblocks, sz; char *vaddr; sc = part->sc; dev = sc->dev; - mmcbr = sc->mmcbr; + mmcbus = sc->mmcbus; block = bp->bio_pblkno; sz = part->disk->d_sectorsize; @@ -1382,7 +1415,7 @@ mmcsd_rw(struct mmcsd_part *part, struct bio *bp) stop.mrq = &req; req.stop = &stop; } - MMCBUS_WAIT_FOR_REQUEST(mmcbr, dev, &req); + MMCBUS_WAIT_FOR_REQUEST(mmcbus, dev, &req); if (req.cmd->error != MMC_ERR_NONE) { if (ppsratecheck(&sc->log_time, &sc->log_count, LOG_PPS)) @@ -1403,32 +1436,56 @@ mmcsd_delete(struct mmcsd_part *part, struct bio *bp) struct mmc_command cmd; struct mmc_request req; struct mmcsd_softc *sc; - device_t dev, mmcbr; + device_t dev, mmcbus; u_int erase_sector, sz; + int err; + bool use_trim; sc = part->sc; dev = sc->dev; - mmcbr = sc->mmcbr; + mmcbus = sc->mmcbus; block = bp->bio_pblkno; sz = part->disk->d_sectorsize; end = bp->bio_pblkno + (bp->bio_bcount / sz); - /* Coalesce with part remaining from previous request. */ - if (block > part->eblock && block <= part->eend) - block = part->eblock; - if (end >= part->eblock && end < part->eend) - end = part->eend; - /* Safe round to the erase sector boundaries. */ - erase_sector = sc->erase_sector; - start = block + erase_sector - 1; /* Round up. */ - start -= start % erase_sector; - stop = end; /* Round down. */ - stop -= end % erase_sector; - /* We can't erase an area smaller than a sector, store it for later. */ - if (start >= stop) { - part->eblock = block; - part->eend = end; - return (end); + use_trim = sc->flags & MMCSD_USE_TRIM; + if (use_trim == true) { + start = block; + stop = end; + } else { + /* Coalesce with the remainder of the previous request. */ + if (block > part->eblock && block <= part->eend) + block = part->eblock; + if (end >= part->eblock && end < part->eend) + end = part->eend; + /* Safely round to the erase sector boundaries. */ + erase_sector = sc->erase_sector; + start = block + erase_sector - 1; /* Round up. */ + start -= start % erase_sector; + stop = end; /* Round down. */ + stop -= end % erase_sector; + /* + * We can't erase an area smaller than an erase sector, so + * store it for later. + */ + if (start >= stop) { + part->eblock = block; + part->eend = end; + return (end); + } + } + + if ((sc->flags & MMCSD_INAND_CMD38) != 0) { + err = mmc_switch(mmcbus, dev, sc->rca, EXT_CSD_CMD_SET_NORMAL, + EXT_CSD_INAND_CMD38, use_trim == true ? + EXT_CSD_INAND_CMD38_TRIM : EXT_CSD_INAND_CMD38_ERASE, + sc->cmd6_time, true); + if (err != MMC_ERR_NONE) { + device_printf(dev, + "Setting iNAND erase command failed %s\n", + mmcsd_errmsg(err)); + return (block); + } } /* @@ -1436,7 +1493,7 @@ mmcsd_delete(struct mmcsd_part *part, struct bio *bp) * commands. Note that these latter don't use the data lines, so * re-tuning shouldn't actually become necessary during erase. */ - MMCBUS_RETUNE_PAUSE(mmcbr, dev, false); + MMCBUS_RETUNE_PAUSE(mmcbus, dev, false); /* Set erase start position. */ memset(&req, 0, sizeof(req)); memset(&cmd, 0, sizeof(cmd)); @@ -1450,10 +1507,10 @@ mmcsd_delete(struct mmcsd_part *part, struct bio *bp) if (sc->high_cap == 0) cmd.arg <<= 9; cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; - MMCBUS_WAIT_FOR_REQUEST(mmcbr, dev, &req); + MMCBUS_WAIT_FOR_REQUEST(mmcbus, dev, &req); if (req.cmd->error != MMC_ERR_NONE) { - device_printf(dev, "Setting erase start position failed %d\n", - req.cmd->error); + device_printf(dev, "Setting erase start position failed %s\n", + mmcsd_errmsg(req.cmd->error)); block = bp->bio_pblkno; goto unpause; } @@ -1470,10 +1527,10 @@ mmcsd_delete(struct mmcsd_part *part, struct bio *bp) cmd.arg <<= 9; cmd.arg--; cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; - MMCBUS_WAIT_FOR_REQUEST(mmcbr, dev, &req); + MMCBUS_WAIT_FOR_REQUEST(mmcbus, dev, &req); if (req.cmd->error != MMC_ERR_NONE) { - device_printf(dev, "Setting erase stop position failed %d\n", - req.cmd->error); + device_printf(dev, "Setting erase stop position failed %s\n", + mmcsd_errmsg(req.cmd->error)); block = bp->bio_pblkno; goto unpause; } @@ -1482,27 +1539,28 @@ mmcsd_delete(struct mmcsd_part *part, struct bio *bp) memset(&cmd, 0, sizeof(cmd)); req.cmd = &cmd; cmd.opcode = MMC_ERASE; - cmd.arg = 0; + cmd.arg = use_trim == true ? MMC_ERASE_TRIM : MMC_ERASE_ERASE; cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; - MMCBUS_WAIT_FOR_REQUEST(mmcbr, dev, &req); + MMCBUS_WAIT_FOR_REQUEST(mmcbus, dev, &req); if (req.cmd->error != MMC_ERR_NONE) { - device_printf(dev, "erase err3: %d\n", req.cmd->error); - device_printf(dev, "Issuing erase command failed %d\n", - req.cmd->error); + device_printf(dev, "Issuing erase command failed %s\n", + mmcsd_errmsg(req.cmd->error)); block = bp->bio_pblkno; goto unpause; } - /* Store one of remaining parts for the next call. */ - if (bp->bio_pblkno >= part->eblock || block == start) { - part->eblock = stop; /* Predict next forward. */ - part->eend = end; - } else { - part->eblock = block; /* Predict next backward. */ - part->eend = start; + if (use_trim == false) { + /* Store one of the remaining parts for the next call. */ + if (bp->bio_pblkno >= part->eblock || block == start) { + part->eblock = stop; /* Predict next forward. */ + part->eend = end; + } else { + part->eblock = block; /* Predict next backward. */ + part->eend = start; + } } block = end; unpause: - MMCBUS_RETUNE_UNPAUSE(mmcbr, dev); + MMCBUS_RETUNE_UNPAUSE(mmcbus, dev); return (block); } @@ -1515,7 +1573,7 @@ mmcsd_dump(void *arg, void *virtual, vm_offset_t physical, off_t offset, struct disk *disk; struct mmcsd_softc *sc; struct mmcsd_part *part; - device_t dev, mmcbr; + device_t dev, mmcbus; int err; /* length zero is special and really means flush buffers to media */ @@ -1526,7 +1584,7 @@ mmcsd_dump(void *arg, void *virtual, vm_offset_t physical, off_t offset, part = disk->d_drv1; sc = part->sc; dev = sc->dev; - mmcbr = sc->mmcbr; + mmcbus = sc->mmcbus; g_reset_bio(&bp); bp.bio_disk = disk; @@ -1535,16 +1593,16 @@ mmcsd_dump(void *arg, void *virtual, vm_offset_t physical, off_t offset, bp.bio_data = virtual; bp.bio_cmd = BIO_WRITE; end = bp.bio_pblkno + bp.bio_bcount / disk->d_sectorsize; - MMCBUS_ACQUIRE_BUS(mmcbr, dev); - err = mmcsd_switch_part(mmcbr, dev, sc->rca, part->type); + MMCBUS_ACQUIRE_BUS(mmcbus, dev); + err = mmcsd_switch_part(mmcbus, dev, sc->rca, part->type); if (err != MMC_ERR_NONE) { if (ppsratecheck(&sc->log_time, &sc->log_count, LOG_PPS)) device_printf(dev, "Partition switch error\n"); - MMCBUS_RELEASE_BUS(mmcbr, dev); + MMCBUS_RELEASE_BUS(mmcbus, dev); return (EIO); } block = mmcsd_rw(part, &bp); - MMCBUS_RELEASE_BUS(mmcbr, dev); + MMCBUS_RELEASE_BUS(mmcbus, dev); return ((end < block) ? EIO : 0); } @@ -1555,13 +1613,13 @@ mmcsd_task(void *arg) struct mmcsd_part *part; struct mmcsd_softc *sc; struct bio *bp; - device_t dev, mmcbr; + device_t dev, mmcbus; int err, sz; part = arg; sc = part->sc; dev = sc->dev; - mmcbr = sc->mmcbr; + mmcbus = sc->mmcbus; while (1) { MMCSD_DISK_LOCK(part); @@ -1581,11 +1639,11 @@ mmcsd_task(void *arg) biodone(bp); continue; } - MMCBUS_ACQUIRE_BUS(mmcbr, dev); + MMCBUS_ACQUIRE_BUS(mmcbus, dev); sz = part->disk->d_sectorsize; block = bp->bio_pblkno; end = bp->bio_pblkno + (bp->bio_bcount / sz); - err = mmcsd_switch_part(mmcbr, dev, sc->rca, part->type); + err = mmcsd_switch_part(mmcbus, dev, sc->rca, part->type); if (err != MMC_ERR_NONE) { if (ppsratecheck(&sc->log_time, &sc->log_count, LOG_PPS)) @@ -1601,7 +1659,7 @@ mmcsd_task(void *arg) block = mmcsd_delete(part, bp); } release: - MMCBUS_RELEASE_BUS(mmcbr, dev); + MMCBUS_RELEASE_BUS(mmcbus, dev); if (block < end) { bp->bio_error = EIO; bp->bio_resid = (end - block) * sz; diff --git a/freebsd/sys/dev/mmc/mmcvar.h b/freebsd/sys/dev/mmc/mmcvar.h index 9f62b112..d0f4e330 100644 --- a/freebsd/sys/dev/mmc/mmcvar.h +++ b/freebsd/sys/dev/mmc/mmcvar.h @@ -68,6 +68,8 @@ enum mmc_device_ivars { MMC_IVAR_BUS_WIDTH, MMC_IVAR_ERASE_SECTOR, MMC_IVAR_MAX_DATA, + MMC_IVAR_CMD6_TIMEOUT, + MMC_IVAR_QUIRKS, MMC_IVAR_CARD_ID_STRING, MMC_IVAR_CARD_SN_STRING, }; @@ -90,6 +92,8 @@ MMC_ACCESSOR(card_type, CARD_TYPE, int) MMC_ACCESSOR(bus_width, BUS_WIDTH, int) MMC_ACCESSOR(erase_sector, ERASE_SECTOR, int) MMC_ACCESSOR(max_data, MAX_DATA, int) +MMC_ACCESSOR(cmd6_timeout, CMD6_TIMEOUT, u_int) +MMC_ACCESSOR(quirks, QUIRKS, u_int) MMC_ACCESSOR(card_id_string, CARD_ID_STRING, const char *) MMC_ACCESSOR(card_sn_string, CARD_SN_STRING, const char *) diff --git a/freebsd/sys/dev/nvme/nvme.h b/freebsd/sys/dev/nvme/nvme.h index aa640b37..d4fc131e 100644 --- a/freebsd/sys/dev/nvme/nvme.h +++ b/freebsd/sys/dev/nvme/nvme.h @@ -69,6 +69,8 @@ union cap_lo_register { } bits __packed; } __packed; +_Static_assert(sizeof(union cap_lo_register) == 4, "bad size for cap_lo_register"); + union cap_hi_register { uint32_t raw; struct { @@ -93,6 +95,8 @@ union cap_hi_register { } bits __packed; } __packed; +_Static_assert(sizeof(union cap_hi_register) == 4, "bad size of cap_hi_register"); + union cc_register { uint32_t raw; struct { @@ -123,6 +127,8 @@ union cc_register { } bits __packed; } __packed; +_Static_assert(sizeof(union cc_register) == 4, "bad size for cc_register"); + enum shn_value { NVME_SHN_NORMAL = 0x1, NVME_SHN_ABRUPT = 0x2, @@ -144,6 +150,8 @@ union csts_register { } bits __packed; } __packed; +_Static_assert(sizeof(union csts_register) == 4, "bad size for csts_register"); + enum shst_value { NVME_SHST_NORMAL = 0x0, NVME_SHST_OCCURRING = 0x1, @@ -165,6 +173,8 @@ union aqa_register { } bits __packed; } __packed; +_Static_assert(sizeof(union aqa_register) == 4, "bad size for aqa_resgister"); + struct nvme_registers { /** controller capabilities */ @@ -198,6 +208,8 @@ struct nvme_registers } doorbell[1] __packed; } __packed; +_Static_assert(sizeof(struct nvme_registers) == 0x1008, "bad size for nvme_registers"); + struct nvme_command { /* dword 0 */ @@ -231,6 +243,8 @@ struct nvme_command uint32_t cdw15; /* command-specific */ } __packed; +_Static_assert(sizeof(struct nvme_command) == 16 * 4, "bad size for nvme_command"); + struct nvme_status { uint16_t p : 1; /* phase tag */ @@ -241,6 +255,8 @@ struct nvme_status { uint16_t dnr : 1; /* do not retry */ } __packed; +_Static_assert(sizeof(struct nvme_status) == 2, "bad size for nvme_status"); + struct nvme_completion { /* dword 0 */ @@ -258,6 +274,8 @@ struct nvme_completion { struct nvme_status status; } __packed; +_Static_assert(sizeof(struct nvme_completion) == 4 * 4, "bad size for nvme_completion"); + struct nvme_dsm_range { uint32_t attributes; @@ -265,6 +283,8 @@ struct nvme_dsm_range { uint64_t starting_lba; } __packed; +_Static_assert(sizeof(struct nvme_dsm_range) == 16, "bad size for nvme_dsm_ranage"); + /* status code types */ enum nvme_status_code_type { NVME_SCT_GENERIC = 0x0, @@ -377,7 +397,14 @@ enum nvme_feature { NVME_FEAT_INTERRUPT_VECTOR_CONFIGURATION = 0x09, NVME_FEAT_WRITE_ATOMICITY = 0x0A, NVME_FEAT_ASYNC_EVENT_CONFIGURATION = 0x0B, - /* 0x0C-0x7F - reserved */ + NVME_FEAT_AUTONOMOUS_POWER_STATE_TRANSITION = 0x0C, + NVME_FEAT_HOST_MEMORY_BUFFER = 0x0D, + NVME_FEAT_TIMESTAMP = 0x0E, + NVME_FEAT_KEEP_ALIVE_TIMER = 0x0F, + NVME_FEAT_HOST_CONTROLLED_THERMAL_MGMT = 0x10, + NVME_FEAT_NON_OP_POWER_STATE_CONFIG = 0x11, + /* 0x12-0x77 - reserved */ + /* 0x78-0x7f - NVMe Management Interface */ NVME_FEAT_SOFTWARE_PROGRESS_MARKER = 0x80, /* 0x81-0xBF - command set specific (reserved) */ /* 0xC0-0xFF - vendor specific */ @@ -423,6 +450,8 @@ struct nvme_power_state { uint8_t ps_rsvd10[9]; } __packed; +_Static_assert(sizeof(struct nvme_power_state) == 32, "bad size for nvme_power_state"); + #define NVME_SERIAL_NUMBER_LENGTH 20 #define NVME_MODEL_NUMBER_LENGTH 40 #define NVME_FIRMWARE_REVISION_LENGTH 8 @@ -461,7 +490,27 @@ struct nvme_controller_data { /** Controller ID */ uint16_t ctrlr_id; - uint8_t reserved1[176]; + /** Version */ + uint32_t ver; + + /** RTD3 Resume Latency */ + uint32_t rtd3r; + + /** RTD3 Enter Latency */ + uint32_t rtd3e; + + /** Optional Asynchronous Events Supported */ + uint32_t oaes; /* bitfield really */ + + /** Controller Attributes */ + uint32_t ctratt; /* bitfield really */ + + uint8_t reserved1[12]; + + /** FRU Globally Unique Identifier */ + uint8_t fguid[16]; + + uint8_t reserved2[128]; /* bytes 256-511: admin command set attributes */ @@ -521,7 +570,28 @@ struct nvme_controller_data { uint8_t avscc_rsvd : 7; } __packed avscc; - uint8_t reserved2[15]; + /** Autonomous Power State Transition Attributes */ + struct { + /* Autonmous Power State Transitions supported */ + uint8_t apst_supp : 1; + + uint8_t apsta_rsvd : 7; + } __packed apsta; + + /** Warning Composite Temperature Threshold */ + uint16_t wctemp; + + /** Critical Composite Temperature Threshold */ + uint16_t cctemp; + + /** Maximum Time for Firmware Activation */ + uint16_t mtfa; + + /** Host Memory Buffer Preferred Size */ + uint32_t hmpre; + + /** Host Memory Buffer Minimum Size */ + uint32_t hmmin; /** Name space capabilities */ struct { @@ -530,7 +600,34 @@ struct nvme_controller_data { uint8_t unvmcap[16]; } __packed untncap; - uint8_t reserved3[200]; + /** Replay Protected Memory Block Support */ + uint32_t rpmbs; /* Really a bitfield */ + + /** Extended Device Self-test Time */ + uint16_t edstt; + + /** Device Self-test Options */ + uint8_t dsto; /* Really a bitfield */ + + /** Firmware Update Granularity */ + uint8_t fwug; + + /** Keep Alive Support */ + uint16_t kas; + + /** Host Controlled Thermal Management Attributes */ + uint16_t hctma; /* Really a bitfield */ + + /** Minimum Thermal Management Temperature */ + uint16_t mntmt; + + /** Maximum Thermal Management Temperature */ + uint16_t mxtmt; + + /** Sanitize Capabilities */ + uint32_t sanicap; /* Really a bitfield */ + + uint8_t reserved3[180]; /* bytes 512-703: nvm command set attributes */ /** submission queue entry size */ @@ -545,7 +642,8 @@ struct nvme_controller_data { uint8_t max : 4; } __packed cqes; - uint8_t reserved4[2]; + /** Maximum Outstanding Commands */ + uint16_t maxcmd; /** number of namespaces */ uint32_t nn; @@ -583,6 +681,8 @@ struct nvme_controller_data { uint8_t vs[1024]; } __packed __aligned(4); +_Static_assert(sizeof(struct nvme_controller_data) == 4096, "bad size for nvme_controller_data"); + struct nvme_namespace_data { /** namespace size */ @@ -673,6 +773,8 @@ struct nvme_namespace_data { uint8_t vendor_specific[3712]; } __packed __aligned(4); +_Static_assert(sizeof(struct nvme_namespace_data) == 4096, "bad size for nvme_namepsace_data"); + enum nvme_log_page { /* 0x00 - reserved */ @@ -715,6 +817,8 @@ struct nvme_error_information_entry { uint8_t reserved[35]; } __packed __aligned(4); +_Static_assert(sizeof(struct nvme_error_information_entry) == 64, "bad size for nvme_error_information_entry"); + union nvme_critical_warning_state { uint8_t raw; @@ -729,6 +833,8 @@ union nvme_critical_warning_state { } __packed bits; } __packed; +_Static_assert(sizeof(union nvme_critical_warning_state) == 1, "bad size for nvme_critical_warning_state"); + struct nvme_health_information_page { union nvme_critical_warning_state critical_warning; @@ -765,6 +871,8 @@ struct nvme_health_information_page { uint8_t reserved2[296]; } __packed __aligned(4); +_Static_assert(sizeof(struct nvme_health_information_page) == 512, "bad size for nvme_health_information_page"); + struct nvme_firmware_page { struct { @@ -777,6 +885,8 @@ struct nvme_firmware_page { uint8_t reserved2[448]; } __packed __aligned(4); +_Static_assert(sizeof(struct nvme_firmware_page) == 512, "bad size for nvme_firmware_page"); + struct intel_log_temp_stats { uint64_t current; @@ -790,6 +900,8 @@ struct intel_log_temp_stats uint64_t est_offset; } __packed __aligned(4); +_Static_assert(sizeof(struct intel_log_temp_stats) == 13 * 8, "bad size for intel_log_temp_stats"); + #define NVME_TEST_MAX_THREADS 128 struct nvme_io_test { @@ -958,7 +1070,7 @@ int nvme_ns_bio_process(struct nvme_namespace *ns, struct bio *bp, /* Command building helper functions -- shared with CAM */ static inline -void nvme_ns_flush_cmd(struct nvme_command *cmd, uint16_t nsid) +void nvme_ns_flush_cmd(struct nvme_command *cmd, uint32_t nsid) { cmd->opc = NVME_OPC_FLUSH; @@ -966,7 +1078,7 @@ void nvme_ns_flush_cmd(struct nvme_command *cmd, uint16_t nsid) } static inline -void nvme_ns_rw_cmd(struct nvme_command *cmd, uint32_t rwcmd, uint16_t nsid, +void nvme_ns_rw_cmd(struct nvme_command *cmd, uint32_t rwcmd, uint32_t nsid, uint64_t lba, uint32_t count) { cmd->opc = rwcmd; @@ -980,21 +1092,21 @@ void nvme_ns_rw_cmd(struct nvme_command *cmd, uint32_t rwcmd, uint16_t nsid, } static inline -void nvme_ns_write_cmd(struct nvme_command *cmd, uint16_t nsid, +void nvme_ns_write_cmd(struct nvme_command *cmd, uint32_t nsid, uint64_t lba, uint32_t count) { nvme_ns_rw_cmd(cmd, NVME_OPC_WRITE, nsid, lba, count); } static inline -void nvme_ns_read_cmd(struct nvme_command *cmd, uint16_t nsid, +void nvme_ns_read_cmd(struct nvme_command *cmd, uint32_t nsid, uint64_t lba, uint32_t count) { nvme_ns_rw_cmd(cmd, NVME_OPC_READ, nsid, lba, count); } static inline -void nvme_ns_trim_cmd(struct nvme_command *cmd, uint16_t nsid, +void nvme_ns_trim_cmd(struct nvme_command *cmd, uint32_t nsid, uint32_t num_ranges) { cmd->opc = NVME_OPC_DATASET_MANAGEMENT; @@ -1003,6 +1115,8 @@ void nvme_ns_trim_cmd(struct nvme_command *cmd, uint16_t nsid, cmd->cdw11 = NVME_DSM_ATTR_DEALLOCATE; } +extern int nvme_use_nvd; + #endif /* _KERNEL */ #endif /* __NVME_H__ */ diff --git a/freebsd/sys/dev/ofw/ofw_bus_subr.c b/freebsd/sys/dev/ofw/ofw_bus_subr.c index cc30578d..418304a0 100644 --- a/freebsd/sys/dev/ofw/ofw_bus_subr.c +++ b/freebsd/sys/dev/ofw/ofw_bus_subr.c @@ -722,22 +722,14 @@ phandle_t ofw_bus_find_compatible(phandle_t node, const char *onecompat) { phandle_t child, ret; - void *compat; - int len; /* * Traverse all children of 'start' node, and find first with * matching 'compatible' property. */ for (child = OF_child(node); child != 0; child = OF_peer(child)) { - len = OF_getprop_alloc(child, "compatible", 1, &compat); - if (len >= 0) { - ret = ofw_bus_node_is_compatible_int(compat, len, - onecompat); - free(compat, M_OFWPROP); - if (ret != 0) - return (child); - } + if (ofw_bus_node_is_compatible(child, onecompat) != 0) + return (child); ret = ofw_bus_find_compatible(child, onecompat); if (ret != 0) diff --git a/freebsd/sys/dev/ofw/ofw_fdt.c b/freebsd/sys/dev/ofw/ofw_fdt.c index 766be90f..282c3667 100644 --- a/freebsd/sys/dev/ofw/ofw_fdt.c +++ b/freebsd/sys/dev/ofw/ofw_fdt.c @@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$"); #include <dev/fdt/fdt_common.h> #include <dev/ofw/ofwvar.h> #include <dev/ofw/openfirm.h> +#include <dev/ofw/ofw_bus_subr.h> #include <rtems/bsd/local/ofw_if.h> @@ -388,7 +389,11 @@ ofw_fdt_setprop(ofw_t ofw, phandle_t package, const char *propname, if (offset < 0) return (-1); - return (fdt_setprop_inplace(fdtp, offset, propname, buf, len)); + if (fdt_setprop_inplace(fdtp, offset, propname, buf, len) != 0) + /* Try to add property, when setting value inplace failed */ + return (fdt_setprop(fdtp, offset, propname, buf, len)); + + return (0); } /* Convert a device specifier to a fully qualified pathname. */ @@ -459,7 +464,15 @@ ofw_fdt_fixup(ofw_t ofw) for (i = 0; fdt_fixup_table[i].model != NULL; i++) { if (strncmp(model, fdt_fixup_table[i].model, FDT_MODEL_LEN) != 0) - continue; + /* + * Sometimes it's convenient to provide one + * fixup entry that refers to many boards. + * To handle this case, simply check if model + * is compatible parameter + */ + if(!ofw_bus_node_is_compatible(root, + fdt_fixup_table[i].model)) + continue; if (fdt_fixup_table[i].handler != NULL) (*fdt_fixup_table[i].handler)(root); diff --git a/freebsd/sys/dev/pci/pci.c b/freebsd/sys/dev/pci/pci.c index be4c626f..69497d2c 100644 --- a/freebsd/sys/dev/pci/pci.c +++ b/freebsd/sys/dev/pci/pci.c @@ -2906,13 +2906,21 @@ pci_read_bar(device_t dev, int reg, pci_addr_t *mapp, pci_addr_t *testvalp, * Determine the BAR's length by writing all 1's. The bottom * log_2(size) bits of the BAR will stick as 0 when we read * the value back. + * + * NB: according to the PCI Local Bus Specification, rev. 3.0: + * "Software writes 0FFFFFFFFh to both registers, reads them back, + * and combines the result into a 64-bit value." (section 6.2.5.1) + * + * Writes to both registers must be performed before attempting to + * read back the size value. */ + testval = 0; pci_write_config(dev, reg, 0xffffffff, 4); - testval = pci_read_config(dev, reg, 4); if (ln2range == 64) { pci_write_config(dev, reg + 4, 0xffffffff, 4); testval |= (pci_addr_t)pci_read_config(dev, reg + 4, 4) << 32; } + testval |= pci_read_config(dev, reg, 4); /* * Restore the original value of the BAR. We may have reprogrammed diff --git a/freebsd/sys/dev/rtwn/if_rtwn_ridx.h b/freebsd/sys/dev/rtwn/if_rtwn_ridx.h index eef43898..76f87aab 100644 --- a/freebsd/sys/dev/rtwn/if_rtwn_ridx.h +++ b/freebsd/sys/dev/rtwn/if_rtwn_ridx.h @@ -36,7 +36,7 @@ #define RTWN_RIDX_OFDM36 9 #define RTWN_RIDX_OFDM48 10 #define RTWN_RIDX_OFDM54 11 -#define RTWN_RIDX_MCS(i) (12 + (i)) +#define RTWN_RIDX_HT_MCS(i) (12 + (i)) #define RTWN_RIDX_COUNT 28 #define RTWN_RIDX_UNKNOWN (uint8_t)-1 @@ -82,10 +82,10 @@ rtwn_ctl_mcsrate(const struct ieee80211_rate_table *rt, uint8_t ridx) uint8_t cix, rate; /* Check if we are using MCS rate. */ - KASSERT(ridx >= RTWN_RIDX_MCS(0) && ridx != RTWN_RIDX_UNKNOWN, + KASSERT(ridx >= RTWN_RIDX_HT_MCS(0) && ridx != RTWN_RIDX_UNKNOWN, ("bad mcs rate index %d", ridx)); - rate = (ridx - RTWN_RIDX_MCS(0)) | IEEE80211_RATE_MCS; + rate = (ridx - RTWN_RIDX_HT_MCS(0)) | IEEE80211_RATE_MCS; cix = rt->info[rt->rateCodeToIndex[rate]].ctlRateIndex; KASSERT(cix != (uint8_t)-1, ("rate %d (%d) has no info", rate, ridx)); return rt->info[cix].dot11Rate; diff --git a/freebsd/sys/dev/rtwn/if_rtwn_rx.c b/freebsd/sys/dev/rtwn/if_rtwn_rx.c index 7b3f1c2e..fb260596 100644 --- a/freebsd/sys/dev/rtwn/if_rtwn_rx.c +++ b/freebsd/sys/dev/rtwn/if_rtwn_rx.c @@ -90,7 +90,7 @@ rtwn_get_rates(struct rtwn_softc *sc, const struct ieee80211_rateset *rs, if ((rs_ht->rs_rates[i] & 0x7f) > 0xf) continue; /* 11n rates start at index 12 */ - ridx = RTWN_RIDX_MCS((rs_ht->rs_rates[i]) & 0xf); + ridx = RTWN_RIDX_HT_MCS((rs_ht->rs_rates[i]) & 0xf); rates |= (1 << ridx); /* Guard against the rate table being oddly ordered */ diff --git a/freebsd/sys/dev/rtwn/rtl8188e/r88e.h b/freebsd/sys/dev/rtwn/rtl8188e/r88e.h index 1c03ddd3..3a3c0865 100644 --- a/freebsd/sys/dev/rtwn/rtl8188e/r88e.h +++ b/freebsd/sys/dev/rtwn/rtl8188e/r88e.h @@ -49,7 +49,7 @@ uint8_t r88e_temp_read(struct rtwn_softc *); /* r88e_chan.c */ void r88e_get_txpower(struct rtwn_softc *, int, - struct ieee80211_channel *, uint16_t[]); + struct ieee80211_channel *, uint8_t[]); void r88e_set_bw20(struct rtwn_softc *, uint8_t); void r88e_set_gain(struct rtwn_softc *, uint8_t); diff --git a/freebsd/sys/dev/rtwn/rtl8188e/r88e_chan.c b/freebsd/sys/dev/rtwn/rtl8188e/r88e_chan.c index 903398a4..530df320 100644 --- a/freebsd/sys/dev/rtwn/rtl8188e/r88e_chan.c +++ b/freebsd/sys/dev/rtwn/rtl8188e/r88e_chan.c @@ -87,7 +87,7 @@ r88e_get_power_group(struct rtwn_softc *sc, struct ieee80211_channel *c) void r88e_get_txpower(struct rtwn_softc *sc, int chain, - struct ieee80211_channel *c, uint16_t power[RTWN_RIDX_COUNT]) + struct ieee80211_channel *c, uint8_t power[RTWN_RIDX_COUNT]) { struct r92c_softc *rs = sc->sc_priv; const struct rtwn_r88e_txpwr *rt = rs->rs_txpwr; @@ -103,7 +103,7 @@ r88e_get_txpower(struct rtwn_softc *sc, int chain, /* XXX net80211 regulatory */ - max_mcs = RTWN_RIDX_MCS(sc->ntxchains * 8 - 1); + max_mcs = RTWN_RIDX_HT_MCS(sc->ntxchains * 8 - 1); KASSERT(max_mcs <= RTWN_RIDX_COUNT, ("increase ridx limit\n")); memset(power, 0, max_mcs * sizeof(power[0])); @@ -123,7 +123,7 @@ r88e_get_txpower(struct rtwn_softc *sc, int chain, power[ridx] = ofdmpow; bw20pow = htpow + rt->bw20_tx_pwr_diff; - for (ridx = RTWN_RIDX_MCS(0); ridx <= max_mcs; ridx++) + for (ridx = RTWN_RIDX_HT_MCS(0); ridx <= max_mcs; ridx++) power[ridx] = bw20pow; /* Apply max limit. */ diff --git a/freebsd/sys/dev/rtwn/rtl8192c/r92c.h b/freebsd/sys/dev/rtwn/rtl8192c/r92c.h index 5ac666d0..d8f7afc8 100644 --- a/freebsd/sys/dev/rtwn/rtl8192c/r92c.h +++ b/freebsd/sys/dev/rtwn/rtl8192c/r92c.h @@ -55,7 +55,9 @@ uint8_t r92c_temp_read(struct rtwn_softc *); /* r92c_chan.c */ void r92c_get_txpower(struct rtwn_softc *, int, - struct ieee80211_channel *, uint16_t[]); + struct ieee80211_channel *, uint8_t[]); +void r92c_write_txpower(struct rtwn_softc *, int, + uint8_t power[]); void r92c_set_bw20(struct rtwn_softc *, uint8_t); void r92c_set_chan(struct rtwn_softc *, struct ieee80211_channel *); void r92c_set_gain(struct rtwn_softc *, uint8_t); diff --git a/freebsd/sys/dev/rtwn/rtl8192c/r92c_chan.c b/freebsd/sys/dev/rtwn/rtl8192c/r92c_chan.c index c5d72f87..2e50daf1 100644 --- a/freebsd/sys/dev/rtwn/rtl8192c/r92c_chan.c +++ b/freebsd/sys/dev/rtwn/rtl8192c/r92c_chan.c @@ -84,7 +84,7 @@ r92c_get_power_group(struct rtwn_softc *sc, struct ieee80211_channel *c) /* XXX recheck */ void r92c_get_txpower(struct rtwn_softc *sc, int chain, - struct ieee80211_channel *c, uint16_t power[RTWN_RIDX_COUNT]) + struct ieee80211_channel *c, uint8_t power[RTWN_RIDX_COUNT]) { struct r92c_softc *rs = sc->sc_priv; struct rtwn_r92c_txpwr *rt = rs->rs_txpwr; @@ -101,7 +101,7 @@ r92c_get_txpower(struct rtwn_softc *sc, int chain, /* XXX net80211 regulatory */ - max_mcs = RTWN_RIDX_MCS(sc->ntxchains * 8 - 1); + max_mcs = RTWN_RIDX_HT_MCS(sc->ntxchains * 8 - 1); KASSERT(max_mcs <= RTWN_RIDX_COUNT, ("increase ridx limit\n")); memset(power, 0, max_mcs * sizeof(power[0])); @@ -148,7 +148,7 @@ r92c_get_txpower(struct rtwn_softc *sc, int chain, diff = rt->ht20_tx_pwr_diff[chain][group]; htpow += diff; /* HT40->HT20 correction. */ } - for (ridx = RTWN_RIDX_MCS(0); ridx <= max_mcs; ridx++) + for (ridx = RTWN_RIDX_HT_MCS(0); ridx <= max_mcs; ridx++) power[ridx] += htpow; /* Apply max limit. */ @@ -158,9 +158,9 @@ r92c_get_txpower(struct rtwn_softc *sc, int chain, } } -static void +void r92c_write_txpower(struct rtwn_softc *sc, int chain, - uint16_t power[RTWN_RIDX_COUNT]) + uint8_t power[RTWN_RIDX_COUNT]) { uint32_t reg; @@ -197,33 +197,33 @@ r92c_write_txpower(struct rtwn_softc *sc, int chain, SM(R92C_TXAGC_RATE54, power[RTWN_RIDX_OFDM54])); /* Write per-MCS Tx power. */ rtwn_bb_write(sc, R92C_TXAGC_MCS03_MCS00(chain), - SM(R92C_TXAGC_MCS00, power[RTWN_RIDX_MCS(0)]) | - SM(R92C_TXAGC_MCS01, power[RTWN_RIDX_MCS(1)]) | - SM(R92C_TXAGC_MCS02, power[RTWN_RIDX_MCS(2)]) | - SM(R92C_TXAGC_MCS03, power[RTWN_RIDX_MCS(3)])); + SM(R92C_TXAGC_MCS00, power[RTWN_RIDX_HT_MCS(0)]) | + SM(R92C_TXAGC_MCS01, power[RTWN_RIDX_HT_MCS(1)]) | + SM(R92C_TXAGC_MCS02, power[RTWN_RIDX_HT_MCS(2)]) | + SM(R92C_TXAGC_MCS03, power[RTWN_RIDX_HT_MCS(3)])); rtwn_bb_write(sc, R92C_TXAGC_MCS07_MCS04(chain), - SM(R92C_TXAGC_MCS04, power[RTWN_RIDX_MCS(4)]) | - SM(R92C_TXAGC_MCS05, power[RTWN_RIDX_MCS(5)]) | - SM(R92C_TXAGC_MCS06, power[RTWN_RIDX_MCS(6)]) | - SM(R92C_TXAGC_MCS07, power[RTWN_RIDX_MCS(7)])); + SM(R92C_TXAGC_MCS04, power[RTWN_RIDX_HT_MCS(4)]) | + SM(R92C_TXAGC_MCS05, power[RTWN_RIDX_HT_MCS(5)]) | + SM(R92C_TXAGC_MCS06, power[RTWN_RIDX_HT_MCS(6)]) | + SM(R92C_TXAGC_MCS07, power[RTWN_RIDX_HT_MCS(7)])); if (sc->ntxchains >= 2) { rtwn_bb_write(sc, R92C_TXAGC_MCS11_MCS08(chain), - SM(R92C_TXAGC_MCS08, power[RTWN_RIDX_MCS(8)]) | - SM(R92C_TXAGC_MCS09, power[RTWN_RIDX_MCS(9)]) | - SM(R92C_TXAGC_MCS10, power[RTWN_RIDX_MCS(10)]) | - SM(R92C_TXAGC_MCS11, power[RTWN_RIDX_MCS(11)])); + SM(R92C_TXAGC_MCS08, power[RTWN_RIDX_HT_MCS(8)]) | + SM(R92C_TXAGC_MCS09, power[RTWN_RIDX_HT_MCS(9)]) | + SM(R92C_TXAGC_MCS10, power[RTWN_RIDX_HT_MCS(10)]) | + SM(R92C_TXAGC_MCS11, power[RTWN_RIDX_HT_MCS(11)])); rtwn_bb_write(sc, R92C_TXAGC_MCS15_MCS12(chain), - SM(R92C_TXAGC_MCS12, power[RTWN_RIDX_MCS(12)]) | - SM(R92C_TXAGC_MCS13, power[RTWN_RIDX_MCS(13)]) | - SM(R92C_TXAGC_MCS14, power[RTWN_RIDX_MCS(14)]) | - SM(R92C_TXAGC_MCS15, power[RTWN_RIDX_MCS(15)])); + SM(R92C_TXAGC_MCS12, power[RTWN_RIDX_HT_MCS(12)]) | + SM(R92C_TXAGC_MCS13, power[RTWN_RIDX_HT_MCS(13)]) | + SM(R92C_TXAGC_MCS14, power[RTWN_RIDX_HT_MCS(14)]) | + SM(R92C_TXAGC_MCS15, power[RTWN_RIDX_HT_MCS(15)])); } } static void r92c_set_txpower(struct rtwn_softc *sc, struct ieee80211_channel *c) { - uint16_t power[RTWN_RIDX_COUNT]; + uint8_t power[RTWN_RIDX_COUNT]; int i; for (i = 0; i < sc->ntxchains; i++) { @@ -233,7 +233,7 @@ r92c_set_txpower(struct rtwn_softc *sc, struct ieee80211_channel *c) if (sc->sc_debug & RTWN_DEBUG_TXPWR) { int max_mcs, ridx; - max_mcs = RTWN_RIDX_MCS(sc->ntxchains * 8 - 1); + max_mcs = RTWN_RIDX_HT_MCS(sc->ntxchains * 8 - 1); /* Dump per-rate Tx power values. */ printf("Tx power for chain %d:\n", i); diff --git a/freebsd/sys/dev/rtwn/rtl8192c/r92c_fw.c b/freebsd/sys/dev/rtwn/rtl8192c/r92c_fw.c index ab8b4989..e6c09eb2 100644 --- a/freebsd/sys/dev/rtwn/rtl8192c/r92c_fw.c +++ b/freebsd/sys/dev/rtwn/rtl8192c/r92c_fw.c @@ -200,7 +200,7 @@ r92c_send_ra_cmd(struct rtwn_softc *sc, int macid, uint32_t rates, #endif /* Set rates mask for unicast frames. */ - if (maxrate >= RTWN_RIDX_MCS(0)) + if (maxrate >= RTWN_RIDX_HT_MCS(0)) mode = R92C_RAID_11GN; else if (maxrate >= RTWN_RIDX_OFDM6) mode = R92C_RAID_11BG; diff --git a/freebsd/sys/dev/rtwn/rtl8192c/r92c_priv.h b/freebsd/sys/dev/rtwn/rtl8192c/r92c_priv.h index 13c38fb2..80f05828 100644 --- a/freebsd/sys/dev/rtwn/rtl8192c/r92c_priv.h +++ b/freebsd/sys/dev/rtwn/rtl8192c/r92c_priv.h @@ -333,7 +333,7 @@ static const struct rtwn_rf_prog rtl8192c_rf[] = { struct rtwn_r92c_txagc { - uint8_t pwr[R92C_GROUP_2G][28]; /* RTWN_RIDX_MCS(15) + 1 */ + uint8_t pwr[R92C_GROUP_2G][28]; /* RTWN_RIDX_HT_MCS(15) + 1 */ }; /* diff --git a/freebsd/sys/dev/rtwn/rtl8192c/r92c_rx.c b/freebsd/sys/dev/rtwn/rtl8192c/r92c_rx.c index b877fb88..80d2859c 100644 --- a/freebsd/sys/dev/rtwn/rtl8192c/r92c_rx.c +++ b/freebsd/sys/dev/rtwn/rtl8192c/r92c_rx.c @@ -119,7 +119,7 @@ r92c_get_rx_stats(struct rtwn_softc *sc, struct ieee80211_rx_stats *rxs, rxs->c_pktflags |= IEEE80211_RX_F_AMPDU; else if (rxdw1 & R92C_RXDW1_AMPDU_MORE) rxs->c_pktflags |= IEEE80211_RX_F_AMPDU_MORE; - if ((rxdw3 & R92C_RXDW3_SPLCP) && rate >= RTWN_RIDX_MCS(0)) + if ((rxdw3 & R92C_RXDW3_SPLCP) && rate >= RTWN_RIDX_HT_MCS(0)) rxs->c_pktflags |= IEEE80211_RX_F_SHORTGI; if (rxdw3 & R92C_RXDW3_HT40) @@ -129,13 +129,13 @@ r92c_get_rx_stats(struct rtwn_softc *sc, struct ieee80211_rx_stats *rxs, if (RTWN_RATE_IS_CCK(rate)) rxs->c_phytype = IEEE80211_RX_FP_11B; - else if (rate < RTWN_RIDX_MCS(0)) + else if (rate < RTWN_RIDX_HT_MCS(0)) rxs->c_phytype = IEEE80211_RX_FP_11G; else rxs->c_phytype = IEEE80211_RX_FP_11NG; /* Map HW rate index to 802.11 rate. */ - if (rate < RTWN_RIDX_MCS(0)) { + if (rate < RTWN_RIDX_HT_MCS(0)) { rxs->c_rate = ridx2rate[rate]; if (RTWN_RATE_IS_CCK(rate)) rxs->c_pktflags |= IEEE80211_RX_F_CCK; diff --git a/freebsd/sys/dev/rtwn/rtl8192c/r92c_tx.c b/freebsd/sys/dev/rtwn/rtl8192c/r92c_tx.c index c2a6eab0..5c80af90 100644 --- a/freebsd/sys/dev/rtwn/rtl8192c/r92c_tx.c +++ b/freebsd/sys/dev/rtwn/rtl8192c/r92c_tx.c @@ -101,7 +101,7 @@ r92c_tx_protection(struct rtwn_softc *sc, struct r92c_tx_desc *txd, if (mode == IEEE80211_PROT_CTSONLY || mode == IEEE80211_PROT_RTSCTS) { - if (ridx >= RTWN_RIDX_MCS(0)) + if (ridx >= RTWN_RIDX_HT_MCS(0)) rate = rtwn_ctl_mcsrate(ic->ic_rt, ridx); else rate = ieee80211_ctl_rate(ic->ic_rt, ridx2rate[ridx]); @@ -287,7 +287,7 @@ r92c_fill_tx_desc(struct rtwn_softc *sc, struct ieee80211_node *ni, txd->txdw4 |= htole32(R92C_TXDW4_DATA_SHPRE); prot = IEEE80211_PROT_NONE; - if (ridx >= RTWN_RIDX_MCS(0)) { + if (ridx >= RTWN_RIDX_HT_MCS(0)) { r92c_tx_set_ht40(sc, txd, ni); r92c_tx_set_sgi(sc, txd, ni); prot = ic->ic_htprotmode; diff --git a/freebsd/sys/dev/rtwn/rtl8192c/r92c_var.h b/freebsd/sys/dev/rtwn/rtl8192c/r92c_var.h index c48318d9..79592449 100644 --- a/freebsd/sys/dev/rtwn/rtl8192c/r92c_var.h +++ b/freebsd/sys/dev/rtwn/rtl8192c/r92c_var.h @@ -53,7 +53,7 @@ struct r92c_softc { void (*rs_set_bw20)(struct rtwn_softc *, uint8_t); void (*rs_get_txpower)(struct rtwn_softc *, int, - struct ieee80211_channel *, uint16_t[]); + struct ieee80211_channel *, uint8_t[]); void (*rs_set_gain)(struct rtwn_softc *, uint8_t); void (*rs_tx_enable_ampdu)(void *, int); void (*rs_tx_setup_hwseq)(void *); diff --git a/freebsd/sys/dev/rtwn/rtl8192e/r92e_chan.c b/freebsd/sys/dev/rtwn/rtl8192e/r92e_chan.c index 130ac5ca..0046b9f0 100644 --- a/freebsd/sys/dev/rtwn/rtl8192e/r92e_chan.c +++ b/freebsd/sys/dev/rtwn/rtl8192e/r92e_chan.c @@ -59,6 +59,8 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/if_rtwn_ridx.h> #include <dev/rtwn/if_rtwn_rx.h> +#include <dev/rtwn/rtl8192c/r92c.h> + #include <dev/rtwn/rtl8192e/r92e.h> #include <dev/rtwn/rtl8192e/r92e_reg.h> #include <dev/rtwn/rtl8192e/r92e_var.h> @@ -102,7 +104,7 @@ r92e_get_txpower(struct rtwn_softc *sc, int chain, struct ieee80211_channel *c, return; } - max_mcs = RTWN_RIDX_MCS(sc->ntxchains * 8 - 1); + max_mcs = RTWN_RIDX_HT_MCS(sc->ntxchains * 8 - 1); /* XXX regulatory */ /* XXX net80211 regulatory */ @@ -124,7 +126,7 @@ r92e_get_txpower(struct rtwn_softc *sc, int chain, struct ieee80211_channel *c, else pwr_diff = rs->bw20_tx_pwr_diff_2g[chain][i]; - min_mcs = RTWN_RIDX_MCS(i * 8); + min_mcs = RTWN_RIDX_HT_MCS(i * 8); for (ridx = min_mcs; ridx <= max_mcs; ridx++) power[ridx] += pwr_diff; @@ -146,69 +148,6 @@ r92e_get_txpower(struct rtwn_softc *sc, int chain, struct ieee80211_channel *c, #endif } - -static void -r92e_write_txpower(struct rtwn_softc *sc, int chain, - uint8_t power[RTWN_RIDX_COUNT]) -{ - uint32_t reg; - - /* Write per-CCK rate Tx power. */ - if (chain == 0) { - reg = rtwn_bb_read(sc, R92C_TXAGC_A_CCK1_MCS32); - reg = RW(reg, R92C_TXAGC_A_CCK1, power[RTWN_RIDX_CCK1]); - rtwn_bb_write(sc, R92C_TXAGC_A_CCK1_MCS32, reg); - reg = rtwn_bb_read(sc, R92C_TXAGC_B_CCK11_A_CCK2_11); - reg = RW(reg, R92C_TXAGC_A_CCK2, power[RTWN_RIDX_CCK2]); - reg = RW(reg, R92C_TXAGC_A_CCK55, power[RTWN_RIDX_CCK55]); - reg = RW(reg, R92C_TXAGC_A_CCK11, power[RTWN_RIDX_CCK11]); - rtwn_bb_write(sc, R92C_TXAGC_B_CCK11_A_CCK2_11, reg); - } else { - reg = rtwn_bb_read(sc, R92C_TXAGC_B_CCK1_55_MCS32); - reg = RW(reg, R92C_TXAGC_B_CCK1, power[RTWN_RIDX_CCK1]); - reg = RW(reg, R92C_TXAGC_B_CCK2, power[RTWN_RIDX_CCK2]); - reg = RW(reg, R92C_TXAGC_B_CCK55, power[RTWN_RIDX_CCK55]); - rtwn_bb_write(sc, R92C_TXAGC_B_CCK1_55_MCS32, reg); - reg = rtwn_bb_read(sc, R92C_TXAGC_B_CCK11_A_CCK2_11); - reg = RW(reg, R92C_TXAGC_B_CCK11, power[RTWN_RIDX_CCK11]); - rtwn_bb_write(sc, R92C_TXAGC_B_CCK11_A_CCK2_11, reg); - } - /* Write per-OFDM rate Tx power. */ - rtwn_bb_write(sc, R92C_TXAGC_RATE18_06(chain), - SM(R92C_TXAGC_RATE06, power[RTWN_RIDX_OFDM6]) | - SM(R92C_TXAGC_RATE09, power[RTWN_RIDX_OFDM9]) | - SM(R92C_TXAGC_RATE12, power[RTWN_RIDX_OFDM12]) | - SM(R92C_TXAGC_RATE18, power[RTWN_RIDX_OFDM18])); - rtwn_bb_write(sc, R92C_TXAGC_RATE54_24(chain), - SM(R92C_TXAGC_RATE24, power[RTWN_RIDX_OFDM24]) | - SM(R92C_TXAGC_RATE36, power[RTWN_RIDX_OFDM36]) | - SM(R92C_TXAGC_RATE48, power[RTWN_RIDX_OFDM48]) | - SM(R92C_TXAGC_RATE54, power[RTWN_RIDX_OFDM54])); - /* Write per-MCS Tx power. */ - rtwn_bb_write(sc, R92C_TXAGC_MCS03_MCS00(chain), - SM(R92C_TXAGC_MCS00, power[RTWN_RIDX_MCS(0)]) | - SM(R92C_TXAGC_MCS01, power[RTWN_RIDX_MCS(1)]) | - SM(R92C_TXAGC_MCS02, power[RTWN_RIDX_MCS(2)]) | - SM(R92C_TXAGC_MCS03, power[RTWN_RIDX_MCS(3)])); - rtwn_bb_write(sc, R92C_TXAGC_MCS07_MCS04(chain), - SM(R92C_TXAGC_MCS04, power[RTWN_RIDX_MCS(4)]) | - SM(R92C_TXAGC_MCS05, power[RTWN_RIDX_MCS(5)]) | - SM(R92C_TXAGC_MCS06, power[RTWN_RIDX_MCS(6)]) | - SM(R92C_TXAGC_MCS07, power[RTWN_RIDX_MCS(7)])); - if (sc->ntxchains >= 2) { - rtwn_bb_write(sc, R92C_TXAGC_MCS11_MCS08(chain), - SM(R92C_TXAGC_MCS08, power[RTWN_RIDX_MCS(8)]) | - SM(R92C_TXAGC_MCS09, power[RTWN_RIDX_MCS(9)]) | - SM(R92C_TXAGC_MCS10, power[RTWN_RIDX_MCS(10)]) | - SM(R92C_TXAGC_MCS11, power[RTWN_RIDX_MCS(11)])); - rtwn_bb_write(sc, R92C_TXAGC_MCS15_MCS12(chain), - SM(R92C_TXAGC_MCS12, power[RTWN_RIDX_MCS(12)]) | - SM(R92C_TXAGC_MCS13, power[RTWN_RIDX_MCS(13)]) | - SM(R92C_TXAGC_MCS14, power[RTWN_RIDX_MCS(14)]) | - SM(R92C_TXAGC_MCS15, power[RTWN_RIDX_MCS(15)])); - } -} - static void r92e_set_txpower(struct rtwn_softc *sc, struct ieee80211_channel *c) { @@ -220,7 +159,7 @@ r92e_set_txpower(struct rtwn_softc *sc, struct ieee80211_channel *c) /* Compute per-rate Tx power values. */ r92e_get_txpower(sc, i, c, power); /* Write per-rate Tx power values to hardware. */ - r92e_write_txpower(sc, i, power); + r92c_write_txpower(sc, i, power); } } diff --git a/freebsd/sys/dev/rtwn/rtl8812a/r12a_chan.c b/freebsd/sys/dev/rtwn/rtl8812a/r12a_chan.c index 27a71bd9..1f18bf56 100644 --- a/freebsd/sys/dev/rtwn/rtl8812a/r12a_chan.c +++ b/freebsd/sys/dev/rtwn/rtl8812a/r12a_chan.c @@ -91,26 +91,26 @@ r12a_write_txpower(struct rtwn_softc *sc, int chain, SM(R12A_TXAGC_OFDM54, power[RTWN_RIDX_OFDM54])); /* Write per-MCS Tx power. */ rtwn_bb_write(sc, R12A_TXAGC_MCS3_0(chain), - SM(R12A_TXAGC_MCS0, power[RTWN_RIDX_MCS(0)]) | - SM(R12A_TXAGC_MCS1, power[RTWN_RIDX_MCS(1)]) | - SM(R12A_TXAGC_MCS2, power[RTWN_RIDX_MCS(2)]) | - SM(R12A_TXAGC_MCS3, power[RTWN_RIDX_MCS(3)])); + SM(R12A_TXAGC_MCS0, power[RTWN_RIDX_HT_MCS(0)]) | + SM(R12A_TXAGC_MCS1, power[RTWN_RIDX_HT_MCS(1)]) | + SM(R12A_TXAGC_MCS2, power[RTWN_RIDX_HT_MCS(2)]) | + SM(R12A_TXAGC_MCS3, power[RTWN_RIDX_HT_MCS(3)])); rtwn_bb_write(sc, R12A_TXAGC_MCS7_4(chain), - SM(R12A_TXAGC_MCS4, power[RTWN_RIDX_MCS(4)]) | - SM(R12A_TXAGC_MCS5, power[RTWN_RIDX_MCS(5)]) | - SM(R12A_TXAGC_MCS6, power[RTWN_RIDX_MCS(6)]) | - SM(R12A_TXAGC_MCS7, power[RTWN_RIDX_MCS(7)])); + SM(R12A_TXAGC_MCS4, power[RTWN_RIDX_HT_MCS(4)]) | + SM(R12A_TXAGC_MCS5, power[RTWN_RIDX_HT_MCS(5)]) | + SM(R12A_TXAGC_MCS6, power[RTWN_RIDX_HT_MCS(6)]) | + SM(R12A_TXAGC_MCS7, power[RTWN_RIDX_HT_MCS(7)])); if (sc->ntxchains >= 2) { rtwn_bb_write(sc, R12A_TXAGC_MCS11_8(chain), - SM(R12A_TXAGC_MCS8, power[RTWN_RIDX_MCS(8)]) | - SM(R12A_TXAGC_MCS9, power[RTWN_RIDX_MCS(9)]) | - SM(R12A_TXAGC_MCS10, power[RTWN_RIDX_MCS(10)]) | - SM(R12A_TXAGC_MCS11, power[RTWN_RIDX_MCS(11)])); + SM(R12A_TXAGC_MCS8, power[RTWN_RIDX_HT_MCS(8)]) | + SM(R12A_TXAGC_MCS9, power[RTWN_RIDX_HT_MCS(9)]) | + SM(R12A_TXAGC_MCS10, power[RTWN_RIDX_HT_MCS(10)]) | + SM(R12A_TXAGC_MCS11, power[RTWN_RIDX_HT_MCS(11)])); rtwn_bb_write(sc, R12A_TXAGC_MCS15_12(chain), - SM(R12A_TXAGC_MCS12, power[RTWN_RIDX_MCS(12)]) | - SM(R12A_TXAGC_MCS13, power[RTWN_RIDX_MCS(13)]) | - SM(R12A_TXAGC_MCS14, power[RTWN_RIDX_MCS(14)]) | - SM(R12A_TXAGC_MCS15, power[RTWN_RIDX_MCS(15)])); + SM(R12A_TXAGC_MCS12, power[RTWN_RIDX_HT_MCS(12)]) | + SM(R12A_TXAGC_MCS13, power[RTWN_RIDX_HT_MCS(13)]) | + SM(R12A_TXAGC_MCS14, power[RTWN_RIDX_HT_MCS(14)]) | + SM(R12A_TXAGC_MCS15, power[RTWN_RIDX_HT_MCS(15)])); } /* TODO: VHT rates */ @@ -178,7 +178,7 @@ r12a_get_txpower(struct rtwn_softc *sc, int chain, } /* TODO: VHT rates. */ - max_mcs = RTWN_RIDX_MCS(sc->ntxchains * 8 - 1); + max_mcs = RTWN_RIDX_HT_MCS(sc->ntxchains * 8 - 1); /* XXX regulatory */ /* XXX net80211 regulatory */ @@ -207,7 +207,7 @@ r12a_get_txpower(struct rtwn_softc *sc, int chain, else pwr_diff = rs->bw20_tx_pwr_diff_2g[chain][i]; - min_mcs = RTWN_RIDX_MCS(i * 8); + min_mcs = RTWN_RIDX_HT_MCS(i * 8); for (ridx = min_mcs; ridx <= max_mcs; ridx++) power[ridx] += pwr_diff; } @@ -233,7 +233,7 @@ r12a_get_txpower(struct rtwn_softc *sc, int chain, else pwr_diff = rs->bw20_tx_pwr_diff_5g[chain][i]; - min_mcs = RTWN_RIDX_MCS(i * 8); + min_mcs = RTWN_RIDX_HT_MCS(i * 8); for (ridx = min_mcs; ridx <= max_mcs; ridx++) power[ridx] += pwr_diff; } diff --git a/freebsd/sys/dev/rtwn/rtl8812a/r12a_rx.c b/freebsd/sys/dev/rtwn/rtl8812a/r12a_rx.c index dd90d7e9..c2dc4c3a 100644 --- a/freebsd/sys/dev/rtwn/rtl8812a/r12a_rx.c +++ b/freebsd/sys/dev/rtwn/rtl8812a/r12a_rx.c @@ -264,7 +264,7 @@ r12a_get_rx_stats(struct rtwn_softc *sc, struct ieee80211_rx_stats *rxs, rxs->c_pktflags |= IEEE80211_RX_F_AMPDU_MORE; } - if ((rxdw4 & R12A_RXDW4_SPLCP) && rate >= RTWN_RIDX_MCS(0)) + if ((rxdw4 & R12A_RXDW4_SPLCP) && rate >= RTWN_RIDX_HT_MCS(0)) rxs->c_pktflags |= IEEE80211_RX_F_SHORTGI; switch (MS(rxdw4, R12A_RXDW4_BW)) { @@ -290,7 +290,7 @@ r12a_get_rx_stats(struct rtwn_softc *sc, struct ieee80211_rx_stats *rxs, /* XXX check with RTL8812AU */ is5ghz = (physt->cfosho[2] != 0x01); - if (rate < RTWN_RIDX_MCS(0)) { + if (rate < RTWN_RIDX_HT_MCS(0)) { if (is5ghz) rxs->c_phytype = IEEE80211_RX_FP_11A; else @@ -304,7 +304,7 @@ r12a_get_rx_stats(struct rtwn_softc *sc, struct ieee80211_rx_stats *rxs, } /* Map HW rate index to 802.11 rate. */ - if (rate < RTWN_RIDX_MCS(0)) { + if (rate < RTWN_RIDX_HT_MCS(0)) { rxs->c_rate = ridx2rate[rate]; if (RTWN_RATE_IS_CCK(rate)) rxs->c_pktflags |= IEEE80211_RX_F_CCK; diff --git a/freebsd/sys/dev/rtwn/rtl8812a/r12a_tx.c b/freebsd/sys/dev/rtwn/rtl8812a/r12a_tx.c index 895f71e4..77e9e423 100644 --- a/freebsd/sys/dev/rtwn/rtl8812a/r12a_tx.c +++ b/freebsd/sys/dev/rtwn/rtl8812a/r12a_tx.c @@ -109,7 +109,7 @@ r12a_tx_protection(struct rtwn_softc *sc, struct r12a_tx_desc *txd, if (mode == IEEE80211_PROT_CTSONLY || mode == IEEE80211_PROT_RTSCTS) { - if (ridx >= RTWN_RIDX_MCS(0)) + if (ridx >= RTWN_RIDX_HT_MCS(0)) rate = rtwn_ctl_mcsrate(ic->ic_rt, ridx); else rate = ieee80211_ctl_rate(ic->ic_rt, ridx2rate[ridx]); @@ -294,7 +294,7 @@ r12a_fill_tx_desc(struct rtwn_softc *sc, struct ieee80211_node *ni, txd->txdw5 |= htole32(R12A_TXDW5_DATA_SHORT); prot = IEEE80211_PROT_NONE; - if (ridx >= RTWN_RIDX_MCS(0)) { + if (ridx >= RTWN_RIDX_HT_MCS(0)) { r12a_tx_set_ht40(sc, txd, ni); r12a_tx_set_sgi(sc, txd, ni); r12a_tx_set_ldpc(sc, txd, ni); diff --git a/freebsd/sys/dev/sdhci/sdhci.c b/freebsd/sys/dev/sdhci/sdhci.c index f1616a6e..8d1fed8f 100644 --- a/freebsd/sys/dev/sdhci/sdhci.c +++ b/freebsd/sys/dev/sdhci/sdhci.c @@ -1053,12 +1053,14 @@ no_tuning: return (0); } +#ifndef MMCCAM void sdhci_start_slot(struct sdhci_slot *slot) { sdhci_card_task(slot, 0); } +#endif int sdhci_cleanup_slot(struct sdhci_slot *slot) @@ -2398,7 +2400,7 @@ sdhci_generic_write_ivar(device_t bus, device_t child, int which, #ifdef MMCCAM void -sdhci_cam_start_slot(struct sdhci_slot *slot) +sdhci_start_slot(struct sdhci_slot *slot) { if ((slot->devq = cam_simq_alloc(1)) == NULL) { goto fail; diff --git a/freebsd/sys/dev/sdhci/sdhci.h b/freebsd/sys/dev/sdhci/sdhci.h index 73aa84b6..ba66415f 100644 --- a/freebsd/sys/dev/sdhci/sdhci.h +++ b/freebsd/sys/dev/sdhci/sdhci.h @@ -430,9 +430,4 @@ 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); -#ifdef MMCCAM -/* CAM-related */ -void sdhci_cam_start_slot(struct sdhci_slot *slot); -#endif - #endif /* __SDHCI_H__ */ diff --git a/freebsd/sys/dev/smc/if_smc.c b/freebsd/sys/dev/smc/if_smc.c index a018e09e..fd1a0960 100644 --- a/freebsd/sys/dev/smc/if_smc.c +++ b/freebsd/sys/dev/smc/if_smc.c @@ -784,7 +784,7 @@ smc_task_rx(void *context, int pending) } #ifdef DEVICE_POLLING -static void +static int smc_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) { struct smc_softc *sc; @@ -794,12 +794,13 @@ smc_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) SMC_LOCK(sc); if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { SMC_UNLOCK(sc); - return; + return (0); } SMC_UNLOCK(sc); if (cmd == POLL_AND_CHECK_STATUS) taskqueue_enqueue(sc->smc_tq, &sc->smc_intr); + return (0); } #endif diff --git a/freebsd/sys/dev/usb/net/if_ure.c b/freebsd/sys/dev/usb/net/if_ure.c index 27e3ecca..89ce723b 100644 --- a/freebsd/sys/dev/usb/net/if_ure.c +++ b/freebsd/sys/dev/usb/net/if_ure.c @@ -69,6 +69,7 @@ SYSCTL_INT(_hw_usb_ure, OID_AUTO, debug, CTLFLAG_RWTUN, &ure_debug, 0, */ 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(REALTEK, RTL8152, URE_FLAG_8152), URE_DEV(REALTEK, RTL8153, 0), #undef URE_DEV diff --git a/freebsd/sys/dev/usb/quirk/usb_quirk.c b/freebsd/sys/dev/usb/quirk/usb_quirk.c index a5fac1b3..3ea3f3c6 100644 --- a/freebsd/sys/dev/usb/quirk/usb_quirk.c +++ b/freebsd/sys/dev/usb/quirk/usb_quirk.c @@ -236,6 +236,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(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, @@ -335,7 +336,7 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = { UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_IGNORE_RESIDUE, UQ_MSC_NO_START_STOP), USB_QUIRK(PROLIFIC, PL2506, 0x0000, 0xffff, - UQ_MSC_NO_SYNC_CACHE), + UQ_MSC_NO_SYNC_CACHE, UQ_MSC_NO_PREVENT_ALLOW), USB_QUIRK_VP(USB_VENDOR_SAMSUNG_TECHWIN, USB_PRODUCT_SAMSUNG_TECHWIN_DIGIMAX_410, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY), @@ -509,6 +510,7 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = { USB_QUIRK(ROLAND, SD20, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS), USB_QUIRK(ROLAND, SD80, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS), USB_QUIRK(ROLAND, UA700, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS), + USB_QUIRK(ROLAND, PCR300, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS), USB_QUIRK(EGO, M4U, 0x0000, 0xffff, UQ_SINGLE_CMD_MIDI), USB_QUIRK(LOGILINK, U2M, 0x0000, 0xffff, UQ_SINGLE_CMD_MIDI), USB_QUIRK(MEDELI, DD305, 0x0000, 0xffff, UQ_SINGLE_CMD_MIDI, UQ_MATCH_VENDOR_ONLY), @@ -608,6 +610,7 @@ static const char *usb_quirk_str[USB_QUIRK_MAX] = { [UQ_SINGLE_CMD_MIDI] = "UQ_SINGLE_CMD_MIDI", [UQ_MSC_DYMO_EJECT] = "UQ_MSC_DYMO_EJECT", [UQ_AU_SET_SPDIF_CM6206] = "UQ_AU_SET_SPDIF_CM6206", + [UQ_WMT_IGNORE] = "UQ_WMT_IGNORE", }; /*------------------------------------------------------------------------* diff --git a/freebsd/sys/dev/usb/quirk/usb_quirk.h b/freebsd/sys/dev/usb/quirk/usb_quirk.h index f7e490ce..bb9fe190 100644 --- a/freebsd/sys/dev/usb/quirk/usb_quirk.h +++ b/freebsd/sys/dev/usb/quirk/usb_quirk.h @@ -110,6 +110,7 @@ enum { UQ_SINGLE_CMD_MIDI, /* at most one command per USB packet */ UQ_MSC_DYMO_EJECT, /* ejects Dymo MSC device */ UQ_AU_SET_SPDIF_CM6206, /* enable S/PDIF audio output */ + UQ_WMT_IGNORE, /* device should be ignored by wmt driver */ USB_QUIRK_MAX }; diff --git a/freebsd/sys/dev/usb/usb_hid.c b/freebsd/sys/dev/usb/usb_hid.c index 56e31a6e..5019aa1a 100644 --- a/freebsd/sys/dev/usb/usb_hid.c +++ b/freebsd/sys/dev/usb/usb_hid.c @@ -851,6 +851,80 @@ usbd_req_get_hid_desc(struct usb_device *udev, struct mtx *mtx, } /*------------------------------------------------------------------------* + * calculate HID item resolution. unit/mm for distances, unit/rad for angles + *------------------------------------------------------------------------*/ +int32_t +hid_item_resolution(struct hid_item *hi) +{ + /* + * hid unit scaling table according to HID Usage Table Review + * Request 39 Tbl 17 http://www.usb.org/developers/hidpage/HUTRR39b.pdf + */ + static const int64_t scale[0x10][2] = { + [0x00] = { 1, 1 }, + [0x01] = { 1, 10 }, + [0x02] = { 1, 100 }, + [0x03] = { 1, 1000 }, + [0x04] = { 1, 10000 }, + [0x05] = { 1, 100000 }, + [0x06] = { 1, 1000000 }, + [0x07] = { 1, 10000000 }, + [0x08] = { 100000000, 1 }, + [0x09] = { 10000000, 1 }, + [0x0A] = { 1000000, 1 }, + [0x0B] = { 100000, 1 }, + [0x0C] = { 10000, 1 }, + [0x0D] = { 1000, 1 }, + [0x0E] = { 100, 1 }, + [0x0F] = { 10, 1 }, + }; + int64_t logical_size; + int64_t physical_size; + int64_t multiplier; + int64_t divisor; + int64_t resolution; + + switch (hi->unit) { + case HUM_CENTIMETER: + multiplier = 1; + divisor = 10; + break; + case HUM_INCH: + multiplier = 10; + divisor = 254; + break; + case HUM_RADIAN: + multiplier = 1; + divisor = 1; + break; + case HUM_DEGREE: + multiplier = 573; + divisor = 10; + break; + default: + return (0); + } + + if ((hi->logical_maximum <= hi->logical_minimum) || + (hi->physical_maximum <= hi->physical_minimum) || + (hi->unit_exponent < 0) || (hi->unit_exponent >= nitems(scale))) + return (0); + + logical_size = (int64_t)hi->logical_maximum - + (int64_t)hi->logical_minimum; + physical_size = (int64_t)hi->physical_maximum - + (int64_t)hi->physical_minimum; + /* Round to ceiling */ + resolution = logical_size * multiplier * scale[hi->unit_exponent][0] / + (physical_size * divisor * scale[hi->unit_exponent][1]); + + if (resolution > INT32_MAX) + return (0); + + return (resolution); +} + +/*------------------------------------------------------------------------* * hid_is_mouse * * This function will decide if a USB descriptor belongs to a USB mouse. diff --git a/freebsd/sys/dev/usb/usb_hub.c b/freebsd/sys/dev/usb/usb_hub.c index e70be43b..0eaeeb60 100644 --- a/freebsd/sys/dev/usb/usb_hub.c +++ b/freebsd/sys/dev/usb/usb_hub.c @@ -102,7 +102,9 @@ SYSCTL_INT(_hw_usb, OID_AUTO, power_timeout, CTLFLAG_RWTUN, #if USB_HAVE_DISABLE_ENUM static int usb_disable_enumeration = 0; SYSCTL_INT(_hw_usb, OID_AUTO, disable_enumeration, CTLFLAG_RWTUN, - &usb_disable_enumeration, 0, "Set to disable all USB device enumeration."); + &usb_disable_enumeration, 0, "Set to disable all USB device enumeration. " + "This can secure against USB devices turning evil, " + "for example a USB memory stick becoming a USB keyboard."); static int usb_disable_port_power = 0; SYSCTL_INT(_hw_usb, OID_AUTO, disable_port_power, CTLFLAG_RWTUN, diff --git a/freebsd/sys/dev/usb/usbhid.h b/freebsd/sys/dev/usb/usbhid.h index 28dfede2..31aa7ea4 100644 --- a/freebsd/sys/dev/usb/usbhid.h +++ b/freebsd/sys/dev/usb/usbhid.h @@ -134,6 +134,12 @@ struct usb_hid_descriptor { /* Usages Digitizers */ #define HUD_UNDEFINED 0x0000 +#define HUD_DIGITIZER 0x0001 +#define HUD_PEN 0x0002 +#define HUD_TOUCHSCREEN 0x0004 +#define HUD_TOUCHPAD 0x0005 +#define HUD_CONFIG 0x000e +#define HUD_FINGER 0x0022 #define HUD_TIP_PRESSURE 0x0030 #define HUD_BARREL_PRESSURE 0x0031 #define HUD_IN_RANGE 0x0032 @@ -157,6 +163,16 @@ struct usb_hid_descriptor { #define HUD_BARREL_SWITCH 0x0044 #define HUD_ERASER 0x0045 #define HUD_TABLET_PICK 0x0046 +#define HUD_CONFIDENCE 0x0047 +#define HUD_WIDTH 0x0048 +#define HUD_HEIGHT 0x0049 +#define HUD_CONTACTID 0x0051 +#define HUD_INPUT_MODE 0x0052 +#define HUD_DEVICE_INDEX 0x0053 +#define HUD_CONTACTCOUNT 0x0054 +#define HUD_CONTACT_MAX 0x0055 +#define HUD_SCAN_TIME 0x0056 +#define HUD_BUTTON_TYPE 0x0059 /* Usages, Consumer */ #define HUC_AC_PAN 0x0238 @@ -178,6 +194,12 @@ struct usb_hid_descriptor { #define HIO_VOLATILE 0x080 #define HIO_BUFBYTES 0x100 +/* Units of Measure */ +#define HUM_CENTIMETER 0x11 +#define HUM_RADIAN 0x12 +#define HUM_INCH 0x13 +#define HUM_DEGREE 0x14 + #ifdef _KERNEL struct usb_config_descriptor; @@ -244,6 +266,7 @@ struct usb_hid_descriptor *hid_get_descriptor_from_usb( usb_error_t usbd_req_get_hid_desc(struct usb_device *udev, struct mtx *mtx, void **descp, uint16_t *sizep, struct malloc_type *mem, uint8_t iface_index); +int32_t hid_item_resolution(struct hid_item *hi); int hid_is_mouse(const void *d_ptr, uint16_t d_len); int hid_is_keyboard(const void *d_ptr, uint16_t d_len); #endif /* _KERNEL */ diff --git a/freebsd/sys/dev/usb/wlan/if_uath.c b/freebsd/sys/dev/usb/wlan/if_uath.c index c3435d57..c4ebe5ed 100644 --- a/freebsd/sys/dev/usb/wlan/if_uath.c +++ b/freebsd/sys/dev/usb/wlan/if_uath.c @@ -2203,17 +2203,19 @@ uath_sysctl_node(struct uath_softc *sc) #undef UATH_SYSCTL_STAT_ADD32 +CTASSERT(sizeof(u_int) >= sizeof(uint32_t)); + static void uath_cmdeof(struct uath_softc *sc, struct uath_cmd *cmd) { struct uath_cmd_hdr *hdr; - int dlen; + uint32_t dlen; hdr = (struct uath_cmd_hdr *)cmd->buf; /* NB: msgid is passed thru w/o byte swapping */ #ifdef UATH_DEBUG if (sc->sc_debug & UATH_DEBUG_CMDS) { - int len = be32toh(hdr->len); + uint32_t len = be32toh(hdr->len); printf("%s: %s [ix %u] len %u status %u\n", __func__, uath_codename(be32toh(hdr->code)), hdr->msgid, len, be32toh(hdr->magic)); @@ -2229,15 +2231,9 @@ uath_cmdeof(struct uath_softc *sc, struct uath_cmd *cmd) switch (hdr->code & 0xff) { /* reply to a read command */ default: - dlen = hdr->len - sizeof(*hdr); - if (dlen < 0) { - device_printf(sc->sc_dev, - "Invalid header length %d\n", dlen); - return; - } DPRINTF(sc, UATH_DEBUG_RX_PROC | UATH_DEBUG_RECV_ALL, - "%s: code %d data len %u\n", - __func__, hdr->code & 0xff, dlen); + "%s: code %d hdr len %u\n", + __func__, hdr->code & 0xff, hdr->len); /* * The first response from the target after the * HOST_AVAILABLE has an invalid msgid so we must @@ -2247,8 +2243,8 @@ uath_cmdeof(struct uath_softc *sc, struct uath_cmd *cmd) uint32_t *rp = (uint32_t *)(hdr+1); u_int olen; - if (!(sizeof(*hdr) <= hdr->len && - hdr->len < UATH_MAX_CMDSZ)) { + if (sizeof(*hdr) > hdr->len || + hdr->len >= UATH_MAX_CMDSZ) { device_printf(sc->sc_dev, "%s: invalid WDC msg length %u; " "msg ignored\n", __func__, hdr->len); @@ -2260,7 +2256,8 @@ uath_cmdeof(struct uath_softc *sc, struct uath_cmd *cmd) * number of bytes--unless it's 0 in which * case a single 32-bit word should be present. */ - if (dlen >= (int)sizeof(uint32_t)) { + dlen = hdr->len - sizeof(*hdr); + if (dlen >= sizeof(uint32_t)) { olen = be32toh(rp[0]); dlen -= sizeof(uint32_t); if (olen == 0) { @@ -2280,7 +2277,7 @@ uath_cmdeof(struct uath_softc *sc, struct uath_cmd *cmd) cmd->olen); olen = cmd->olen; } - if (olen > (u_int)dlen) { + if (olen > dlen) { /* XXX complain, shouldn't happen */ device_printf(sc->sc_dev, "%s: cmd 0x%x olen %u dlen %u\n", @@ -2302,8 +2299,10 @@ uath_cmdeof(struct uath_softc *sc, struct uath_cmd *cmd) return; } dlen = hdr->len - sizeof(*hdr); - if (dlen != (int)sizeof(uint32_t)) { - /* XXX something wrong */ + if (dlen != sizeof(uint32_t)) { + device_printf(sc->sc_dev, + "%s: dlen (%u) != %zu!\n", + __func__, dlen, sizeof(uint32_t)); return; } /* XXX have submitter do this */ @@ -2332,6 +2331,7 @@ uath_intr_rx_callback(struct usb_xfer *xfer, usb_error_t error) { struct uath_softc *sc = usbd_xfer_softc(xfer); struct uath_cmd *cmd; + struct uath_cmd_hdr *hdr; struct usb_page_cache *pc; int actlen; @@ -2349,10 +2349,25 @@ uath_intr_rx_callback(struct usb_xfer *xfer, usb_error_t error) STAILQ_INSERT_TAIL(&sc->sc_cmd_inactive, cmd, next); UATH_STAT_INC(sc, st_cmd_inactive); - KASSERT(actlen >= (int)sizeof(struct uath_cmd_hdr), - ("short xfer error")); + if (actlen < sizeof(struct uath_cmd_hdr)) { + device_printf(sc->sc_dev, + "%s: short xfer error (actlen %d)\n", + __func__, actlen); + goto setup; + } + pc = usbd_xfer_get_frame(xfer, 0); usbd_copy_out(pc, 0, cmd->buf, actlen); + + hdr = (struct uath_cmd_hdr *)cmd->buf; + hdr->len = be32toh(hdr->len); + if (hdr->len > (uint32_t)actlen) { + device_printf(sc->sc_dev, + "%s: truncated xfer (len %u, actlen %d)\n", + __func__, hdr->len, actlen); + goto setup; + } + uath_cmdeof(sc, cmd); case USB_ST_SETUP: setup: @@ -2453,6 +2468,8 @@ uath_update_rxstat(struct uath_softc *sc, uint32_t status) } } +CTASSERT(UATH_MIN_RXBUFSZ >= sizeof(struct uath_chunk)); + static struct mbuf * uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data, struct uath_rx_desc **pdesc) @@ -2475,13 +2492,24 @@ uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data, } chunk = (struct uath_chunk *)data->buf; - if (chunk->seqnum == 0 && chunk->flags == 0 && chunk->length == 0) { + chunklen = be16toh(chunk->length); + if (chunk->seqnum == 0 && chunk->flags == 0 && chunklen == 0) { device_printf(sc->sc_dev, "%s: strange response\n", __func__); counter_u64_add(ic->ic_ierrors, 1); UATH_RESET_INTRX(sc); return (NULL); } + if (chunklen > actlen) { + device_printf(sc->sc_dev, + "%s: invalid chunk length (len %u > actlen %d)\n", + __func__, chunklen, actlen); + counter_u64_add(ic->ic_ierrors, 1); + /* XXX cleanup? */ + UATH_RESET_INTRX(sc); + return (NULL); + } + if (chunk->seqnum != sc->sc_intrx_nextnum) { DPRINTF(sc, UATH_DEBUG_XMIT, "invalid seqnum %d, expected %d\n", chunk->seqnum, sc->sc_intrx_nextnum); @@ -2498,9 +2526,19 @@ uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data, chunk->flags & UATH_CFLAGS_RXMSG) UATH_STAT_INC(sc, st_multichunk); - chunklen = be16toh(chunk->length); - if (chunk->flags & UATH_CFLAGS_FINAL) + if (chunk->flags & UATH_CFLAGS_FINAL) { + if (chunklen < sizeof(struct uath_rx_desc)) { + device_printf(sc->sc_dev, + "%s: invalid chunk length %d\n", + __func__, chunklen); + counter_u64_add(ic->ic_ierrors, 1); + if (sc->sc_intrx_head != NULL) + m_freem(sc->sc_intrx_head); + UATH_RESET_INTRX(sc); + return (NULL); + } chunklen -= sizeof(struct uath_rx_desc); + } if (chunklen > 0 && (!(chunk->flags & UATH_CFLAGS_FINAL) || !(chunk->seqnum == 0))) { @@ -2561,6 +2599,19 @@ uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data, (struct uath_rx_desc *)(((uint8_t *)chunk) + sizeof(struct uath_chunk) + be16toh(chunk->length) - sizeof(struct uath_rx_desc)); + if ((uint8_t *)chunk + actlen - sizeof(struct uath_rx_desc) < + (uint8_t *)desc) { + device_printf(sc->sc_dev, + "%s: wrong Rx descriptor pointer " + "(desc %p chunk %p actlen %d)\n", + __func__, desc, chunk, actlen); + counter_u64_add(ic->ic_ierrors, 1); + if (sc->sc_intrx_head != NULL) + m_freem(sc->sc_intrx_head); + UATH_RESET_INTRX(sc); + return (NULL); + } + *pdesc = desc; DPRINTF(sc, UATH_DEBUG_RECV | UATH_DEBUG_RECV_ALL, @@ -2588,8 +2639,33 @@ uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data, /* finalize mbuf */ if (sc->sc_intrx_head == NULL) { - m->m_pkthdr.len = m->m_len = - be32toh(desc->framelen) - UATH_RX_DUMMYSIZE; + uint32_t framelen; + + if (be32toh(desc->framelen) < UATH_RX_DUMMYSIZE) { + device_printf(sc->sc_dev, + "%s: framelen too small (%u)\n", + __func__, be32toh(desc->framelen)); + counter_u64_add(ic->ic_ierrors, 1); + if (sc->sc_intrx_head != NULL) + m_freem(sc->sc_intrx_head); + UATH_RESET_INTRX(sc); + return (NULL); + } + + framelen = be32toh(desc->framelen) - UATH_RX_DUMMYSIZE; + if (framelen > actlen - sizeof(struct uath_chunk) || + framelen < sizeof(struct ieee80211_frame_ack)) { + device_printf(sc->sc_dev, + "%s: wrong frame length (%u, actlen %d)!\n", + __func__, framelen, actlen); + counter_u64_add(ic->ic_ierrors, 1); + if (sc->sc_intrx_head != NULL) + m_freem(sc->sc_intrx_head); + UATH_RESET_INTRX(sc); + return (NULL); + } + + m->m_pkthdr.len = m->m_len = framelen; m->m_data += sizeof(struct uath_chunk); } else { mp = sc->sc_intrx_head; |