Update to FreeBSD stable/12 2019-01-29

Git mirror commit 7005c2e76a6bfb359bf2f1acb8382c0b7a01f4be.
This commit is contained in:
Sebastian Huber 2019-01-29 10:57:36 +01:00
parent 0c9e63d2bd
commit a5b385b26f
34 changed files with 645 additions and 235 deletions

@ -1 +1 @@
Subproject commit 3a48f3689d65c5304cf706bbf2c5576daeb60a96 Subproject commit 7005c2e76a6bfb359bf2f1acb8382c0b7a01f4be

View File

@ -47,19 +47,19 @@ __FBSDID("$FreeBSD$");
#include "un-namespace.h" #include "un-namespace.h"
/* Entries EAI_ADDRFAMILY (1) and EAI_NODATA (7) are obsoleted, but left */ /* Entries EAI_ADDRFAMILY (1) and EAI_NODATA (7) are obsoleted, but left */
/* for backward compatibility with userland code prior to 2553bis-02 */ /* for backwards compatibility with userland code prior to RFC2553bis-02 */
static const char *ai_errlist[] = { static const char *ai_errlist[] = {
"Success", /* 0 */ "Success", /* 0 */
"Address family for hostname not supported", /* 1 */ "Address family for hostname not supported", /* 1: Obsolete */
"Temporary failure in name resolution", /* EAI_AGAIN */ "Name could not be resolved at this time", /* EAI_AGAIN */
"Invalid value for ai_flags", /* EAI_BADFLAGS */ "Flags parameter had an invalid value", /* EAI_BADFLAGS */
"Non-recoverable failure in name resolution", /* EAI_FAIL */ "Non-recoverable failure in name resolution", /* EAI_FAIL */
"ai_family not supported", /* EAI_FAMILY */ "Address family not recognized", /* EAI_FAMILY */
"Memory allocation failure", /* EAI_MEMORY */ "Memory allocation failure", /* EAI_MEMORY */
"No address associated with hostname", /* 7 */ "No address associated with hostname", /* 7: Obsolete*/
"hostname nor servname provided, or not known", /* EAI_NONAME */ "Name does not resolve", /* EAI_NONAME */
"servname not supported for ai_socktype", /* EAI_SERVICE */ "Service was not recognized for socket type", /* EAI_SERVICE */
"ai_socktype not supported", /* EAI_SOCKTYPE */ "Intended socket type was not recognized", /* EAI_SOCKTYPE */
"System error returned in errno", /* EAI_SYSTEM */ "System error returned in errno", /* EAI_SYSTEM */
"Invalid value for hints", /* EAI_BADHINTS */ "Invalid value for hints", /* EAI_BADHINTS */
"Resolved protocol is unknown", /* EAI_PROTOCOL */ "Resolved protocol is unknown", /* EAI_PROTOCOL */

View File

@ -1539,9 +1539,6 @@ getmodeflags(const char *val)
return flags; return flags;
} }
#define IEEE80211_CHAN_HTA (IEEE80211_CHAN_HT|IEEE80211_CHAN_5GHZ)
#define IEEE80211_CHAN_HTG (IEEE80211_CHAN_HT|IEEE80211_CHAN_2GHZ)
#define _APPLY(_flags, _base, _param, _v) do { \ #define _APPLY(_flags, _base, _param, _v) do { \
if (_flags & IEEE80211_CHAN_HT) { \ if (_flags & IEEE80211_CHAN_HT) { \
if ((_flags & (IEEE80211_CHAN_5GHZ|IEEE80211_CHAN_2GHZ)) == 0) {\ if ((_flags & (IEEE80211_CHAN_5GHZ|IEEE80211_CHAN_2GHZ)) == 0) {\
@ -1731,8 +1728,6 @@ DECL_CMD_FUNC(set80211maxretry, val, d)
} }
#undef _APPLY_RATE #undef _APPLY_RATE
#undef _APPLY #undef _APPLY
#undef IEEE80211_CHAN_HTA
#undef IEEE80211_CHAN_HTG
static static
DECL_CMD_FUNC(set80211fragthreshold, val, d) DECL_CMD_FUNC(set80211fragthreshold, val, d)

View File

@ -757,7 +757,7 @@ static driver_t ti_sdhci_driver = {
DRIVER_MODULE(sdhci_ti, simplebus, ti_sdhci_driver, ti_sdhci_devclass, NULL, DRIVER_MODULE(sdhci_ti, simplebus, ti_sdhci_driver, ti_sdhci_devclass, NULL,
NULL); NULL);
MODULE_DEPEND(sdhci_ti, sdhci, 1, 1, 1); SDHCI_DEPEND(sdhci_ti);
#ifndef MMCCAM #ifndef MMCCAM
MMC_DECLARE_BRIDGE(sdhci_ti); MMC_DECLARE_BRIDGE(sdhci_ti);

View File

@ -4467,6 +4467,7 @@ int
pci_suspend_child(device_t dev, device_t child) pci_suspend_child(device_t dev, device_t child)
{ {
struct pci_devinfo *dinfo; struct pci_devinfo *dinfo;
struct resource_list_entry *rle;
int error; int error;
dinfo = device_get_ivars(child); dinfo = device_get_ivars(child);
@ -4483,8 +4484,20 @@ pci_suspend_child(device_t dev, device_t child)
if (error) if (error)
return (error); return (error);
if (pci_do_power_suspend) if (pci_do_power_suspend) {
/*
* Make sure this device's interrupt handler is not invoked
* in the case the device uses a shared interrupt that can
* be raised by some other device.
* This is applicable only to regular (legacy) PCI interrupts
* as MSI/MSI-X interrupts are never shared.
*/
rle = resource_list_find(&dinfo->resources,
SYS_RES_IRQ, 0);
if (rle != NULL && rle->res != NULL)
(void)bus_suspend_intr(child, rle->res);
pci_set_power_child(dev, child, PCI_POWERSTATE_D3); pci_set_power_child(dev, child, PCI_POWERSTATE_D3);
}
return (0); return (0);
} }
@ -4493,6 +4506,7 @@ int
pci_resume_child(device_t dev, device_t child) pci_resume_child(device_t dev, device_t child)
{ {
struct pci_devinfo *dinfo; struct pci_devinfo *dinfo;
struct resource_list_entry *rle;
if (pci_do_power_resume) if (pci_do_power_resume)
pci_set_power_child(dev, child, PCI_POWERSTATE_D0); pci_set_power_child(dev, child, PCI_POWERSTATE_D0);
@ -4504,6 +4518,16 @@ pci_resume_child(device_t dev, device_t child)
bus_generic_resume_child(dev, child); bus_generic_resume_child(dev, child);
/*
* Allow interrupts only after fully resuming the driver and hardware.
*/
if (pci_do_power_suspend) {
/* See pci_suspend_child for details. */
rle = resource_list_find(&dinfo->resources, SYS_RES_IRQ, 0);
if (rle != NULL && rle->res != NULL)
(void)bus_resume_intr(child, rle->res);
}
return (0); return (0);
} }

View File

@ -1016,7 +1016,7 @@ static driver_t fsl_sdhci_driver = {
DRIVER_MODULE(sdhci_fsl, simplebus, fsl_sdhci_driver, fsl_sdhci_devclass, DRIVER_MODULE(sdhci_fsl, simplebus, fsl_sdhci_driver, fsl_sdhci_devclass,
NULL, NULL); NULL, NULL);
MODULE_DEPEND(sdhci_fsl, sdhci, 1, 1, 1); SDHCI_DEPEND(sdhci_fsl);
#ifndef MMCCAM #ifndef MMCCAM
MMC_DECLARE_BRIDGE(sdhci_fsl); MMC_DECLARE_BRIDGE(sdhci_fsl);

View File

@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$");
#include <sys/conf.h> #include <sys/conf.h>
#include <sys/kernel.h> #include <sys/kernel.h>
#include <sys/kobj.h> #include <sys/kobj.h>
#include <sys/libkern.h>
#include <sys/lock.h> #include <sys/lock.h>
#include <sys/malloc.h> #include <sys/malloc.h>
#include <sys/module.h> #include <sys/module.h>
@ -110,19 +111,20 @@ static void sdhci_retune(void *arg);
static void sdhci_set_clock(struct sdhci_slot *slot, uint32_t clock); static void sdhci_set_clock(struct sdhci_slot *slot, uint32_t clock);
static void sdhci_set_power(struct sdhci_slot *slot, u_char power); static void sdhci_set_power(struct sdhci_slot *slot, u_char power);
static void sdhci_set_transfer_mode(struct sdhci_slot *slot, static void sdhci_set_transfer_mode(struct sdhci_slot *slot,
struct mmc_data *data); const struct mmc_data *data);
static void sdhci_start(struct sdhci_slot *slot); static void sdhci_start(struct sdhci_slot *slot);
static void sdhci_timeout(void *arg); static void sdhci_timeout(void *arg);
static void sdhci_start_command(struct sdhci_slot *slot, static void sdhci_start_command(struct sdhci_slot *slot,
struct mmc_command *cmd); struct mmc_command *cmd);
static void sdhci_start_data(struct sdhci_slot *slot, struct mmc_data *data); static void sdhci_start_data(struct sdhci_slot *slot,
const struct mmc_data *data);
static void sdhci_write_block_pio(struct sdhci_slot *slot); static void sdhci_write_block_pio(struct sdhci_slot *slot);
static void sdhci_transfer_pio(struct sdhci_slot *slot); static void sdhci_transfer_pio(struct sdhci_slot *slot);
#ifdef MMCCAM #ifdef MMCCAM
/* CAM-related */ /* CAM-related */
static void sdhci_cam_action(struct cam_sim *sim, union ccb *ccb); static void sdhci_cam_action(struct cam_sim *sim, union ccb *ccb);
static int sdhci_cam_get_possible_host_clock(struct sdhci_slot *slot, static int sdhci_cam_get_possible_host_clock(const struct sdhci_slot *slot,
int proposed_clock); int proposed_clock);
static void sdhci_cam_handle_mmcio(struct cam_sim *sim, union ccb *ccb); static void sdhci_cam_handle_mmcio(struct cam_sim *sim, union ccb *ccb);
static void sdhci_cam_poll(struct cam_sim *sim); static void sdhci_cam_poll(struct cam_sim *sim);
@ -132,12 +134,14 @@ static int sdhci_cam_update_ios(struct sdhci_slot *slot);
#endif #endif
/* helper routines */ /* helper routines */
static int sdhci_dma_alloc(struct sdhci_slot *slot);
static void sdhci_dma_free(struct sdhci_slot *slot);
static void sdhci_dumpregs(struct sdhci_slot *slot); static void sdhci_dumpregs(struct sdhci_slot *slot);
static void sdhci_getaddr(void *arg, bus_dma_segment_t *segs, int nsegs, static void sdhci_getaddr(void *arg, bus_dma_segment_t *segs, int nsegs,
int error); int error);
static int slot_printf(struct sdhci_slot *slot, const char * fmt, ...) static int slot_printf(const struct sdhci_slot *slot, const char * fmt, ...)
__printflike(2, 3); __printflike(2, 3);
static uint32_t sdhci_tuning_intmask(struct sdhci_slot *slot); static uint32_t sdhci_tuning_intmask(const struct sdhci_slot *slot);
#define SDHCI_LOCK(_slot) mtx_lock(&(_slot)->mtx) #define SDHCI_LOCK(_slot) mtx_lock(&(_slot)->mtx)
#define SDHCI_UNLOCK(_slot) mtx_unlock(&(_slot)->mtx) #define SDHCI_UNLOCK(_slot) mtx_unlock(&(_slot)->mtx)
@ -181,7 +185,7 @@ sdhci_getaddr(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
} }
static int static int
slot_printf(struct sdhci_slot *slot, const char * fmt, ...) slot_printf(const struct sdhci_slot *slot, const char * fmt, ...)
{ {
va_list ap; va_list ap;
int retval; int retval;
@ -292,7 +296,7 @@ sdhci_reset(struct sdhci_slot *slot, uint8_t mask)
} }
static uint32_t static uint32_t
sdhci_tuning_intmask(struct sdhci_slot *slot) sdhci_tuning_intmask(const struct sdhci_slot *slot)
{ {
uint32_t intmask; uint32_t intmask;
@ -739,6 +743,81 @@ sdhci_card_poll(void *arg)
sdhci_card_poll, slot); sdhci_card_poll, slot);
} }
static int
sdhci_dma_alloc(struct sdhci_slot *slot)
{
int err;
if (!(slot->quirks & SDHCI_QUIRK_BROKEN_SDMA_BOUNDARY)) {
if (MAXPHYS <= 1024 * 4)
slot->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_4K;
else if (MAXPHYS <= 1024 * 8)
slot->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_8K;
else if (MAXPHYS <= 1024 * 16)
slot->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_16K;
else if (MAXPHYS <= 1024 * 32)
slot->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_32K;
else if (MAXPHYS <= 1024 * 64)
slot->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_64K;
else if (MAXPHYS <= 1024 * 128)
slot->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_128K;
else if (MAXPHYS <= 1024 * 256)
slot->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_256K;
else
slot->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_512K;
}
slot->sdma_bbufsz = SDHCI_SDMA_BNDRY_TO_BBUFSZ(slot->sdma_boundary);
/*
* Allocate the DMA tag for an SDMA bounce buffer.
* Note that the SDHCI specification doesn't state any alignment
* constraint for the SDMA system address. However, controllers
* typically ignore the SDMA boundary bits in SDHCI_DMA_ADDRESS when
* forming the actual address of data, requiring the SDMA buffer to
* be aligned to the SDMA boundary.
*/
err = bus_dma_tag_create(bus_get_dma_tag(slot->bus), slot->sdma_bbufsz,
0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
slot->sdma_bbufsz, 1, slot->sdma_bbufsz, BUS_DMA_ALLOCNOW,
NULL, NULL, &slot->dmatag);
if (err != 0) {
slot_printf(slot, "Can't create DMA tag for SDMA\n");
return (err);
}
/* Allocate DMA memory for the SDMA bounce buffer. */
err = bus_dmamem_alloc(slot->dmatag, (void **)&slot->dmamem,
BUS_DMA_NOWAIT, &slot->dmamap);
if (err != 0) {
slot_printf(slot, "Can't alloc DMA memory for SDMA\n");
bus_dma_tag_destroy(slot->dmatag);
return (err);
}
/* Map the memory of the SDMA bounce buffer. */
err = bus_dmamap_load(slot->dmatag, slot->dmamap,
(void *)slot->dmamem, slot->sdma_bbufsz, sdhci_getaddr,
&slot->paddr, 0);
if (err != 0 || slot->paddr == 0) {
slot_printf(slot, "Can't load DMA memory for SDMA\n");
bus_dmamem_free(slot->dmatag, slot->dmamem, slot->dmamap);
bus_dma_tag_destroy(slot->dmatag);
if (err)
return (err);
else
return (EFAULT);
}
return (0);
}
static void
sdhci_dma_free(struct sdhci_slot *slot)
{
bus_dmamap_unload(slot->dmatag, slot->dmamap);
bus_dmamem_free(slot->dmatag, slot->dmamem, slot->dmamap);
bus_dma_tag_destroy(slot->dmatag);
}
int int
sdhci_init_slot(device_t dev, struct sdhci_slot *slot, int num) sdhci_init_slot(device_t dev, struct sdhci_slot *slot, int num)
{ {
@ -752,42 +831,6 @@ sdhci_init_slot(device_t dev, struct sdhci_slot *slot, int num)
slot->num = num; slot->num = num;
slot->bus = dev; slot->bus = dev;
/* Allocate DMA tag. */
err = bus_dma_tag_create(bus_get_dma_tag(dev),
DMA_BLOCK_SIZE, 0, BUS_SPACE_MAXADDR_32BIT,
BUS_SPACE_MAXADDR, NULL, NULL,
DMA_BLOCK_SIZE, 1, DMA_BLOCK_SIZE,
BUS_DMA_ALLOCNOW, NULL, NULL,
&slot->dmatag);
if (err != 0) {
device_printf(dev, "Can't create DMA tag\n");
SDHCI_LOCK_DESTROY(slot);
return (err);
}
/* Allocate DMA memory. */
err = bus_dmamem_alloc(slot->dmatag, (void **)&slot->dmamem,
BUS_DMA_NOWAIT, &slot->dmamap);
if (err != 0) {
device_printf(dev, "Can't alloc DMA memory\n");
bus_dma_tag_destroy(slot->dmatag);
SDHCI_LOCK_DESTROY(slot);
return (err);
}
/* Map the memory. */
err = bus_dmamap_load(slot->dmatag, slot->dmamap,
(void *)slot->dmamem, DMA_BLOCK_SIZE,
sdhci_getaddr, &slot->paddr, 0);
if (err != 0 || slot->paddr == 0) {
device_printf(dev, "Can't load DMA memory\n");
bus_dmamem_free(slot->dmatag, slot->dmamem, slot->dmamap);
bus_dma_tag_destroy(slot->dmatag);
SDHCI_LOCK_DESTROY(slot);
if (err)
return (err);
else
return (EFAULT);
}
slot->version = (RD2(slot, SDHCI_HOST_VERSION) slot->version = (RD2(slot, SDHCI_HOST_VERSION)
>> SDHCI_SPEC_VER_SHIFT) & SDHCI_SPEC_VER_MASK; >> SDHCI_SPEC_VER_SHIFT) & SDHCI_SPEC_VER_MASK;
if (slot->quirks & SDHCI_QUIRK_MISSING_CAPS) { if (slot->quirks & SDHCI_QUIRK_MISSING_CAPS) {
@ -803,12 +846,8 @@ sdhci_init_slot(device_t dev, struct sdhci_slot *slot, int num)
if (slot->version >= SDHCI_SPEC_300) { if (slot->version >= SDHCI_SPEC_300) {
if ((caps & SDHCI_SLOTTYPE_MASK) != SDHCI_SLOTTYPE_REMOVABLE && if ((caps & SDHCI_SLOTTYPE_MASK) != SDHCI_SLOTTYPE_REMOVABLE &&
(caps & SDHCI_SLOTTYPE_MASK) != SDHCI_SLOTTYPE_EMBEDDED) { (caps & SDHCI_SLOTTYPE_MASK) != SDHCI_SLOTTYPE_EMBEDDED) {
device_printf(dev, slot_printf(slot,
"Driver doesn't support shared bus slots\n"); "Driver doesn't support shared bus slots\n");
bus_dmamap_unload(slot->dmatag, slot->dmamap);
bus_dmamem_free(slot->dmatag, slot->dmamem,
slot->dmamap);
bus_dma_tag_destroy(slot->dmatag);
SDHCI_LOCK_DESTROY(slot); SDHCI_LOCK_DESTROY(slot);
return (ENXIO); return (ENXIO);
} else if ((caps & SDHCI_SLOTTYPE_MASK) == } else if ((caps & SDHCI_SLOTTYPE_MASK) ==
@ -832,7 +871,7 @@ sdhci_init_slot(device_t dev, struct sdhci_slot *slot, int num)
*/ */
if (slot->max_clk == 0) { if (slot->max_clk == 0) {
slot->max_clk = SDHCI_DEFAULT_MAX_FREQ * 1000000; slot->max_clk = SDHCI_DEFAULT_MAX_FREQ * 1000000;
device_printf(dev, "Hardware doesn't specify base clock " slot_printf(slot, "Hardware doesn't specify base clock "
"frequency, using %dMHz as default.\n", "frequency, using %dMHz as default.\n",
SDHCI_DEFAULT_MAX_FREQ); SDHCI_DEFAULT_MAX_FREQ);
} }
@ -853,7 +892,7 @@ sdhci_init_slot(device_t dev, struct sdhci_slot *slot, int num)
* max timeout, but still mention it. * max timeout, but still mention it.
*/ */
if (slot->timeout_clk == 0) { if (slot->timeout_clk == 0) {
device_printf(dev, "Hardware doesn't specify timeout clock " slot_printf(slot, "Hardware doesn't specify timeout clock "
"frequency, setting BROKEN_TIMEOUT quirk.\n"); "frequency, setting BROKEN_TIMEOUT quirk.\n");
slot->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; slot->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
} }
@ -869,7 +908,7 @@ sdhci_init_slot(device_t dev, struct sdhci_slot *slot, int num)
if ((caps & SDHCI_CAN_VDD_180) && (slot->opt & SDHCI_SLOT_EMBEDDED)) if ((caps & SDHCI_CAN_VDD_180) && (slot->opt & SDHCI_SLOT_EMBEDDED))
slot->host.host_ocr |= MMC_OCR_LOW_VOLTAGE; slot->host.host_ocr |= MMC_OCR_LOW_VOLTAGE;
if (slot->host.host_ocr == 0) { if (slot->host.host_ocr == 0) {
device_printf(dev, "Hardware doesn't report any " slot_printf(slot, "Hardware doesn't report any "
"support voltages.\n"); "support voltages.\n");
} }
@ -955,7 +994,7 @@ no_tuning:
slot->retune_count = (caps2 & SDHCI_RETUNE_CNT_MASK) >> slot->retune_count = (caps2 & SDHCI_RETUNE_CNT_MASK) >>
SDHCI_RETUNE_CNT_SHIFT; SDHCI_RETUNE_CNT_SHIFT;
if (slot->retune_count > 0xb) { if (slot->retune_count > 0xb) {
device_printf(dev, "Unknown re-tuning count " slot_printf(slot, "Unknown re-tuning count "
"%x, using 1 sec\n", slot->retune_count); "%x, using 1 sec\n", slot->retune_count);
slot->retune_count = 1; slot->retune_count = 1;
} else if (slot->retune_count != 0) } else if (slot->retune_count != 0)
@ -1014,6 +1053,19 @@ no_tuning:
if (slot->opt & SDHCI_PLATFORM_TRANSFER) if (slot->opt & SDHCI_PLATFORM_TRANSFER)
slot->opt &= ~SDHCI_HAVE_DMA; slot->opt &= ~SDHCI_HAVE_DMA;
if (slot->opt & SDHCI_HAVE_DMA) {
err = sdhci_dma_alloc(slot);
if (err != 0) {
if (slot->opt & SDHCI_TUNING_SUPPORTED) {
free(slot->tune_req, M_DEVBUF);
free(slot->tune_cmd, M_DEVBUF);
free(slot->tune_data, M_DEVBUF);
}
SDHCI_LOCK_DESTROY(slot);
return (err);
}
}
if (bootverbose || sdhci_debug) { if (bootverbose || sdhci_debug) {
slot_printf(slot, slot_printf(slot,
"%uMHz%s %s VDD:%s%s%s VCCQ: 3.3V%s%s DRV: B%s%s%s %s %s\n", "%uMHz%s %s VDD:%s%s%s VCCQ: 3.3V%s%s DRV: B%s%s%s %s %s\n",
@ -1111,9 +1163,8 @@ sdhci_cleanup_slot(struct sdhci_slot *slot)
SDHCI_LOCK(slot); SDHCI_LOCK(slot);
sdhci_reset(slot, SDHCI_RESET_ALL); sdhci_reset(slot, SDHCI_RESET_ALL);
SDHCI_UNLOCK(slot); SDHCI_UNLOCK(slot);
bus_dmamap_unload(slot->dmatag, slot->dmamap); if (slot->opt & SDHCI_HAVE_DMA)
bus_dmamem_free(slot->dmatag, slot->dmamem, slot->dmamap); sdhci_dma_free(slot);
bus_dma_tag_destroy(slot->dmatag);
if (slot->opt & SDHCI_TUNING_SUPPORTED) { if (slot->opt & SDHCI_TUNING_SUPPORTED) {
free(slot->tune_req, M_DEVBUF); free(slot->tune_req, M_DEVBUF);
free(slot->tune_cmd, M_DEVBUF); free(slot->tune_cmd, M_DEVBUF);
@ -1177,7 +1228,7 @@ sdhci_generic_get_card_present(device_t brdev __unused, struct sdhci_slot *slot)
void void
sdhci_generic_set_uhs_timing(device_t brdev __unused, struct sdhci_slot *slot) sdhci_generic_set_uhs_timing(device_t brdev __unused, struct sdhci_slot *slot)
{ {
struct mmc_ios *ios; const struct mmc_ios *ios;
uint16_t hostctrl2; uint16_t hostctrl2;
if (slot->version < SDHCI_SPEC_300) if (slot->version < SDHCI_SPEC_300)
@ -1310,7 +1361,7 @@ int
sdhci_generic_tune(device_t brdev __unused, device_t reqdev, bool hs400) sdhci_generic_tune(device_t brdev __unused, device_t reqdev, bool hs400)
{ {
struct sdhci_slot *slot = device_get_ivars(reqdev); struct sdhci_slot *slot = device_get_ivars(reqdev);
struct mmc_ios *ios = &slot->host.ios; const struct mmc_ios *ios = &slot->host.ios;
struct mmc_command *tune_cmd; struct mmc_command *tune_cmd;
struct mmc_data *tune_data; struct mmc_data *tune_data;
uint32_t opcode; uint32_t opcode;
@ -1579,7 +1630,7 @@ sdhci_timeout(void *arg)
} }
static void static void
sdhci_set_transfer_mode(struct sdhci_slot *slot, struct mmc_data *data) sdhci_set_transfer_mode(struct sdhci_slot *slot, const struct mmc_data *data)
{ {
uint16_t mode; uint16_t mode;
@ -1781,9 +1832,9 @@ sdhci_finish_command(struct sdhci_slot *slot)
} }
static void static void
sdhci_start_data(struct sdhci_slot *slot, struct mmc_data *data) sdhci_start_data(struct sdhci_slot *slot, const struct mmc_data *data)
{ {
uint32_t target_timeout, current_timeout; uint32_t blkcnt, blksz, current_timeout, sdma_bbufsz, target_timeout;
uint8_t div; uint8_t div;
if (data == NULL && (slot->curcmd->flags & MMC_RSP_BUSY) == 0) { if (data == NULL && (slot->curcmd->flags & MMC_RSP_BUSY) == 0) {
@ -1819,7 +1870,7 @@ sdhci_start_data(struct sdhci_slot *slot, struct mmc_data *data)
/* Use DMA if possible. */ /* Use DMA if possible. */
if ((slot->opt & SDHCI_HAVE_DMA)) if ((slot->opt & SDHCI_HAVE_DMA))
slot->flags |= SDHCI_USE_DMA; slot->flags |= SDHCI_USE_DMA;
/* If data is small, broken DMA may return zeroes instead of data, */ /* If data is small, broken DMA may return zeroes instead of data. */
if ((slot->quirks & SDHCI_QUIRK_BROKEN_TIMINGS) && if ((slot->quirks & SDHCI_QUIRK_BROKEN_TIMINGS) &&
(data->len <= 512)) (data->len <= 512))
slot->flags &= ~SDHCI_USE_DMA; slot->flags &= ~SDHCI_USE_DMA;
@ -1829,20 +1880,22 @@ sdhci_start_data(struct sdhci_slot *slot, struct mmc_data *data)
slot->flags &= ~SDHCI_USE_DMA; slot->flags &= ~SDHCI_USE_DMA;
/* Load DMA buffer. */ /* Load DMA buffer. */
if (slot->flags & SDHCI_USE_DMA) { if (slot->flags & SDHCI_USE_DMA) {
sdma_bbufsz = slot->sdma_bbufsz;
if (data->flags & MMC_DATA_READ) if (data->flags & MMC_DATA_READ)
bus_dmamap_sync(slot->dmatag, slot->dmamap, bus_dmamap_sync(slot->dmatag, slot->dmamap,
BUS_DMASYNC_PREREAD); BUS_DMASYNC_PREREAD);
else { else {
memcpy(slot->dmamem, data->data, memcpy(slot->dmamem, data->data, ulmin(data->len,
(data->len < DMA_BLOCK_SIZE) ? sdma_bbufsz));
data->len : DMA_BLOCK_SIZE);
bus_dmamap_sync(slot->dmatag, slot->dmamap, bus_dmamap_sync(slot->dmatag, slot->dmamap,
BUS_DMASYNC_PREWRITE); BUS_DMASYNC_PREWRITE);
} }
WR4(slot, SDHCI_DMA_ADDRESS, slot->paddr); WR4(slot, SDHCI_DMA_ADDRESS, slot->paddr);
/* Interrupt aggregation: Mask border interrupt /*
* for the last page and unmask else. */ * Interrupt aggregation: Mask border interrupt for the last
if (data->len == DMA_BLOCK_SIZE) * bounce buffer and unmask otherwise.
*/
if (data->len == sdma_bbufsz)
slot->intmask &= ~SDHCI_INT_DMA_END; slot->intmask &= ~SDHCI_INT_DMA_END;
else else
slot->intmask |= SDHCI_INT_DMA_END; slot->intmask |= SDHCI_INT_DMA_END;
@ -1850,16 +1903,15 @@ sdhci_start_data(struct sdhci_slot *slot, struct mmc_data *data)
} }
/* Current data offset for both PIO and DMA. */ /* Current data offset for both PIO and DMA. */
slot->offset = 0; slot->offset = 0;
/* Set block size and request IRQ on 4K border. */ /* Set block size and request border interrupts on the SDMA boundary. */
WR2(slot, SDHCI_BLOCK_SIZE, SDHCI_MAKE_BLKSZ(DMA_BOUNDARY, blksz = SDHCI_MAKE_BLKSZ(slot->sdma_boundary, ulmin(data->len, 512));
(data->len < 512) ? data->len : 512)); WR2(slot, SDHCI_BLOCK_SIZE, blksz);
/* Set block count. */ /* Set block count. */
WR2(slot, SDHCI_BLOCK_COUNT, (data->len + 511) / 512); blkcnt = howmany(data->len, 512);
WR2(slot, SDHCI_BLOCK_COUNT, blkcnt);
if (__predict_false(sdhci_debug > 1)) if (__predict_false(sdhci_debug > 1))
slot_printf(slot, "Block size: %02x, count %lu\n", slot_printf(slot, "Blk size: 0x%08x | Blk cnt: 0x%08x\n",
(unsigned int)SDHCI_MAKE_BLKSZ(DMA_BOUNDARY, (data->len < 512) ? data->len : 512), blksz, blkcnt);
(unsigned long)(data->len + 511) / 512);
} }
void void
@ -1883,7 +1935,7 @@ sdhci_finish_data(struct sdhci_slot *slot)
bus_dmamap_sync(slot->dmatag, slot->dmamap, bus_dmamap_sync(slot->dmatag, slot->dmamap,
BUS_DMASYNC_POSTREAD); BUS_DMASYNC_POSTREAD);
memcpy((u_char*)data->data + slot->offset, slot->dmamem, memcpy((u_char*)data->data + slot->offset, slot->dmamem,
(left < DMA_BLOCK_SIZE) ? left : DMA_BLOCK_SIZE); ulmin(left, slot->sdma_bbufsz));
} else } else
bus_dmamap_sync(slot->dmatag, slot->dmamap, bus_dmamap_sync(slot->dmatag, slot->dmamap,
BUS_DMASYNC_POSTWRITE); BUS_DMASYNC_POSTWRITE);
@ -1908,14 +1960,13 @@ static void
sdhci_start(struct sdhci_slot *slot) sdhci_start(struct sdhci_slot *slot)
{ {
union ccb *ccb; union ccb *ccb;
struct ccb_mmcio *mmcio;
ccb = slot->ccb; ccb = slot->ccb;
if (ccb == NULL) if (ccb == NULL)
return; return;
struct ccb_mmcio *mmcio;
mmcio = &ccb->mmcio; mmcio = &ccb->mmcio;
if (!(slot->flags & CMD_STARTED)) { if (!(slot->flags & CMD_STARTED)) {
slot->flags |= CMD_STARTED; slot->flags |= CMD_STARTED;
sdhci_start_command(slot, &mmcio->cmd); sdhci_start_command(slot, &mmcio->cmd);
@ -1947,7 +1998,7 @@ sdhci_start(struct sdhci_slot *slot)
static void static void
sdhci_start(struct sdhci_slot *slot) sdhci_start(struct sdhci_slot *slot)
{ {
struct mmc_request *req; const struct mmc_request *req;
req = slot->req; req = slot->req;
if (req == NULL) if (req == NULL)
@ -2076,6 +2127,7 @@ sdhci_data_irq(struct sdhci_slot *slot, uint32_t intmask)
{ {
struct mmc_data *data; struct mmc_data *data;
size_t left; size_t left;
uint32_t sdma_bbufsz;
if (!slot->curcmd) { if (!slot->curcmd) {
slot_printf(slot, "Got data interrupt 0x%08x, but " slot_printf(slot, "Got data interrupt 0x%08x, but "
@ -2130,6 +2182,7 @@ sdhci_data_irq(struct sdhci_slot *slot, uint32_t intmask)
/* Handle DMA border. */ /* Handle DMA border. */
if (intmask & SDHCI_INT_DMA_END) { if (intmask & SDHCI_INT_DMA_END) {
data = slot->curcmd->data; data = slot->curcmd->data;
sdma_bbufsz = slot->sdma_bbufsz;
/* Unload DMA buffer ... */ /* Unload DMA buffer ... */
left = data->len - slot->offset; left = data->len - slot->offset;
@ -2137,26 +2190,28 @@ sdhci_data_irq(struct sdhci_slot *slot, uint32_t intmask)
bus_dmamap_sync(slot->dmatag, slot->dmamap, bus_dmamap_sync(slot->dmatag, slot->dmamap,
BUS_DMASYNC_POSTREAD); BUS_DMASYNC_POSTREAD);
memcpy((u_char*)data->data + slot->offset, slot->dmamem, memcpy((u_char*)data->data + slot->offset, slot->dmamem,
(left < DMA_BLOCK_SIZE) ? left : DMA_BLOCK_SIZE); ulmin(left, sdma_bbufsz));
} else { } else {
bus_dmamap_sync(slot->dmatag, slot->dmamap, bus_dmamap_sync(slot->dmatag, slot->dmamap,
BUS_DMASYNC_POSTWRITE); BUS_DMASYNC_POSTWRITE);
} }
/* ... and reload it again. */ /* ... and reload it again. */
slot->offset += DMA_BLOCK_SIZE; slot->offset += sdma_bbufsz;
left = data->len - slot->offset; left = data->len - slot->offset;
if (data->flags & MMC_DATA_READ) { if (data->flags & MMC_DATA_READ) {
bus_dmamap_sync(slot->dmatag, slot->dmamap, bus_dmamap_sync(slot->dmatag, slot->dmamap,
BUS_DMASYNC_PREREAD); BUS_DMASYNC_PREREAD);
} else { } else {
memcpy(slot->dmamem, (u_char*)data->data + slot->offset, memcpy(slot->dmamem, (u_char*)data->data + slot->offset,
(left < DMA_BLOCK_SIZE)? left : DMA_BLOCK_SIZE); ulmin(left, sdma_bbufsz));
bus_dmamap_sync(slot->dmatag, slot->dmamap, bus_dmamap_sync(slot->dmatag, slot->dmamap,
BUS_DMASYNC_PREWRITE); BUS_DMASYNC_PREWRITE);
} }
/* Interrupt aggregation: Mask border interrupt /*
* for the last page. */ * Interrupt aggregation: Mask border interrupt for the last
if (left == DMA_BLOCK_SIZE) { * bounce buffer.
*/
if (left == sdma_bbufsz) {
slot->intmask &= ~SDHCI_INT_DMA_END; slot->intmask &= ~SDHCI_INT_DMA_END;
WR4(slot, SDHCI_SIGNAL_ENABLE, slot->intmask); WR4(slot, SDHCI_SIGNAL_ENABLE, slot->intmask);
} }
@ -2279,7 +2334,7 @@ int
sdhci_generic_read_ivar(device_t bus, device_t child, int which, sdhci_generic_read_ivar(device_t bus, device_t child, int which,
uintptr_t *result) uintptr_t *result)
{ {
struct sdhci_slot *slot = device_get_ivars(child); const struct sdhci_slot *slot = device_get_ivars(child);
switch (which) { switch (which) {
default: default:
@ -2442,6 +2497,7 @@ sdhci_generic_write_ivar(device_t bus, device_t child, int which,
void void
sdhci_start_slot(struct sdhci_slot *slot) sdhci_start_slot(struct sdhci_slot *slot)
{ {
if ((slot->devq = cam_simq_alloc(1)) == NULL) { if ((slot->devq = cam_simq_alloc(1)) == NULL) {
goto fail; goto fail;
} }
@ -2601,7 +2657,8 @@ sdhci_cam_poll(struct cam_sim *sim)
} }
static int static int
sdhci_cam_get_possible_host_clock(struct sdhci_slot *slot, int proposed_clock) sdhci_cam_get_possible_host_clock(const struct sdhci_slot *slot,
int proposed_clock)
{ {
int max_clock, clock, i; int max_clock, clock, i;
@ -2628,15 +2685,14 @@ sdhci_cam_get_possible_host_clock(struct sdhci_slot *slot, int proposed_clock)
return clock; return clock;
} }
int static int
sdhci_cam_settran_settings(struct sdhci_slot *slot, union ccb *ccb) sdhci_cam_settran_settings(struct sdhci_slot *slot, union ccb *ccb)
{ {
struct mmc_ios *ios; struct mmc_ios *ios;
struct mmc_ios *new_ios; const struct mmc_ios *new_ios;
struct ccb_trans_settings_mmc *cts; const struct ccb_trans_settings_mmc *cts;
ios = &slot->host.ios; ios = &slot->host.ios;
cts = &ccb->cts.proto_specific.mmc; cts = &ccb->cts.proto_specific.mmc;
new_ios = &cts->ios; new_ios = &cts->ios;
@ -2674,7 +2730,7 @@ sdhci_cam_settran_settings(struct sdhci_slot *slot, union ccb *ccb)
return (sdhci_cam_update_ios(slot)); return (sdhci_cam_update_ios(slot));
} }
int static int
sdhci_cam_update_ios(struct sdhci_slot *slot) sdhci_cam_update_ios(struct sdhci_slot *slot)
{ {
struct mmc_ios *ios = &slot->host.ios; struct mmc_ios *ios = &slot->host.ios;
@ -2716,10 +2772,10 @@ sdhci_cam_update_ios(struct sdhci_slot *slot)
return (0); return (0);
} }
int static int
sdhci_cam_request(struct sdhci_slot *slot, union ccb *ccb) sdhci_cam_request(struct sdhci_slot *slot, union ccb *ccb)
{ {
struct ccb_mmcio *mmcio; const struct ccb_mmcio *mmcio;
mmcio = &ccb->mmcio; mmcio = &ccb->mmcio;
@ -2754,4 +2810,4 @@ sdhci_cam_request(struct sdhci_slot *slot, union ccb *ccb)
} }
#endif /* MMCCAM */ #endif /* MMCCAM */
MODULE_VERSION(sdhci, 1); MODULE_VERSION(sdhci, SDHCI_VERSION);

View File

@ -32,8 +32,8 @@
#include <rtems/bsd/local/opt_mmccam.h> #include <rtems/bsd/local/opt_mmccam.h>
#define DMA_BLOCK_SIZE 4096 /* Macro for sizing the SDMA bounce buffer on the SDMA buffer boundary. */
#define DMA_BOUNDARY 0 /* DMA reload every 4K */ #define SDHCI_SDMA_BNDRY_TO_BBUFSZ(bndry) (4096 * (1 << bndry))
/* Controller doesn't honor resets unless we touch the clock register */ /* Controller doesn't honor resets unless we touch the clock register */
#define SDHCI_QUIRK_CLOCK_BEFORE_RESET (1 << 0) #define SDHCI_QUIRK_CLOCK_BEFORE_RESET (1 << 0)
@ -95,6 +95,8 @@
#define SDHCI_QUIRK_BROKEN_AUTO_STOP (1 << 28) #define SDHCI_QUIRK_BROKEN_AUTO_STOP (1 << 28)
/* Controller supports eMMC HS400 mode if SDHCI_CAN_SDR104 is set. */ /* Controller supports eMMC HS400 mode if SDHCI_CAN_SDR104 is set. */
#define SDHCI_QUIRK_MMC_HS400_IF_CAN_SDR104 (1 << 29) #define SDHCI_QUIRK_MMC_HS400_IF_CAN_SDR104 (1 << 29)
/* SDMA boundary in SDHCI_BLOCK_SIZE broken - use front-end supplied value. */
#define SDHCI_QUIRK_BROKEN_SDMA_BOUNDARY (1 << 30)
/* /*
* Controller registers * Controller registers
@ -102,6 +104,14 @@
#define SDHCI_DMA_ADDRESS 0x00 #define SDHCI_DMA_ADDRESS 0x00
#define SDHCI_BLOCK_SIZE 0x04 #define SDHCI_BLOCK_SIZE 0x04
#define SDHCI_BLKSZ_SDMA_BNDRY_4K 0x00
#define SDHCI_BLKSZ_SDMA_BNDRY_8K 0x01
#define SDHCI_BLKSZ_SDMA_BNDRY_16K 0x02
#define SDHCI_BLKSZ_SDMA_BNDRY_32K 0x03
#define SDHCI_BLKSZ_SDMA_BNDRY_64K 0x04
#define SDHCI_BLKSZ_SDMA_BNDRY_128K 0x05
#define SDHCI_BLKSZ_SDMA_BNDRY_256K 0x06
#define SDHCI_BLKSZ_SDMA_BNDRY_512K 0x07
#define SDHCI_MAKE_BLKSZ(dma, blksz) (((dma & 0x7) << 12) | (blksz & 0xFFF)) #define SDHCI_MAKE_BLKSZ(dma, blksz) (((dma & 0x7) << 12) | (blksz & 0xFFF))
#define SDHCI_BLOCK_COUNT 0x06 #define SDHCI_BLOCK_COUNT 0x06
@ -362,6 +372,8 @@ struct sdhci_slot {
bus_dmamap_t dmamap; bus_dmamap_t dmamap;
u_char *dmamem; u_char *dmamem;
bus_addr_t paddr; /* DMA buffer address */ bus_addr_t paddr; /* DMA buffer address */
uint32_t sdma_bbufsz; /* SDMA bounce buffer size */
uint8_t sdma_boundary; /* SDMA boundary */
struct task card_task; /* Card presence check task */ struct task card_task; /* Card presence check task */
struct timeout_task struct timeout_task
card_delayed_task;/* Card insert delayed task */ card_delayed_task;/* Card insert delayed task */
@ -434,4 +446,9 @@ bool sdhci_generic_get_card_present(device_t brdev, struct sdhci_slot *slot);
void sdhci_generic_set_uhs_timing(device_t brdev, struct sdhci_slot *slot); void sdhci_generic_set_uhs_timing(device_t brdev, struct sdhci_slot *slot);
void sdhci_handle_card_present(struct sdhci_slot *slot, bool is_present); void sdhci_handle_card_present(struct sdhci_slot *slot, bool is_present);
#define SDHCI_VERSION 2
#define SDHCI_DEPEND(name) \
MODULE_DEPEND(name, sdhci, SDHCI_VERSION, SDHCI_VERSION, SDHCI_VERSION);
#endif /* __SDHCI_H__ */ #endif /* __SDHCI_H__ */

View File

@ -2826,69 +2826,80 @@ run_rx_frame(struct run_softc *sc, struct mbuf *m, uint32_t dmalen)
uint8_t ant, rssi; uint8_t ant, rssi;
int8_t nf; int8_t nf;
rxwi = mtod(m, struct rt2860_rxwi *);
len = le16toh(rxwi->len) & 0xfff;
rxwisize = sizeof(struct rt2860_rxwi); rxwisize = sizeof(struct rt2860_rxwi);
if (sc->mac_ver == 0x5592) if (sc->mac_ver == 0x5592)
rxwisize += sizeof(uint64_t); rxwisize += sizeof(uint64_t);
else if (sc->mac_ver == 0x3593) else if (sc->mac_ver == 0x3593)
rxwisize += sizeof(uint32_t); rxwisize += sizeof(uint32_t);
if (__predict_false(len > dmalen)) {
m_freem(m); if (__predict_false(dmalen <
counter_u64_add(ic->ic_ierrors, 1); rxwisize + sizeof(struct ieee80211_frame_ack))) {
RUN_DPRINTF(sc, RUN_DEBUG_RECV,
"payload is too short: dma length %u < %zu\n",
dmalen, rxwisize + sizeof(struct ieee80211_frame_ack));
goto fail;
}
rxwi = mtod(m, struct rt2860_rxwi *);
len = le16toh(rxwi->len) & 0xfff;
if (__predict_false(len > dmalen - rxwisize)) {
RUN_DPRINTF(sc, RUN_DEBUG_RECV, RUN_DPRINTF(sc, RUN_DEBUG_RECV,
"bad RXWI length %u > %u\n", len, dmalen); "bad RXWI length %u > %u\n", len, dmalen);
return; goto fail;
} }
/* Rx descriptor is located at the end */ /* Rx descriptor is located at the end */
rxd = (struct rt2870_rxd *)(mtod(m, caddr_t) + dmalen); rxd = (struct rt2870_rxd *)(mtod(m, caddr_t) + dmalen);
flags = le32toh(rxd->flags); flags = le32toh(rxd->flags);
if (__predict_false(flags & (RT2860_RX_CRCERR | RT2860_RX_ICVERR))) { if (__predict_false(flags & (RT2860_RX_CRCERR | RT2860_RX_ICVERR))) {
m_freem(m);
counter_u64_add(ic->ic_ierrors, 1);
RUN_DPRINTF(sc, RUN_DEBUG_RECV, "%s error.\n", RUN_DPRINTF(sc, RUN_DEBUG_RECV, "%s error.\n",
(flags & RT2860_RX_CRCERR)?"CRC":"ICV"); (flags & RT2860_RX_CRCERR)?"CRC":"ICV");
return; goto fail;
}
m->m_data += rxwisize;
m->m_pkthdr.len = m->m_len -= rxwisize;
wh = mtod(m, struct ieee80211_frame *);
if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
wh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED;
m->m_flags |= M_WEP;
} }
if (flags & RT2860_RX_L2PAD) { if (flags & RT2860_RX_L2PAD) {
/*
* XXX OpenBSD removes padding between header
* and payload here...
*/
RUN_DPRINTF(sc, RUN_DEBUG_RECV, RUN_DPRINTF(sc, RUN_DEBUG_RECV,
"received RT2860_RX_L2PAD frame\n"); "received RT2860_RX_L2PAD frame\n");
len += 2; len += 2;
} }
m->m_data += rxwisize;
m->m_pkthdr.len = m->m_len = len;
wh = mtod(m, struct ieee80211_frame *);
/* XXX wrong for monitor mode */
if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
wh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED;
m->m_flags |= M_WEP;
}
if (len >= sizeof(struct ieee80211_frame_min)) {
ni = ieee80211_find_rxnode(ic, ni = ieee80211_find_rxnode(ic,
mtod(m, struct ieee80211_frame_min *)); mtod(m, struct ieee80211_frame_min *));
} else
ni = NULL;
if (__predict_false(flags & RT2860_RX_MICERR)) { if (__predict_false(flags & RT2860_RX_MICERR)) {
/* report MIC failures to net80211 for TKIP */ /* report MIC failures to net80211 for TKIP */
if (ni != NULL) if (ni != NULL)
ieee80211_notify_michael_failure(ni->ni_vap, wh, ieee80211_notify_michael_failure(ni->ni_vap, wh,
rxwi->keyidx); rxwi->keyidx);
m_freem(m);
counter_u64_add(ic->ic_ierrors, 1);
RUN_DPRINTF(sc, RUN_DEBUG_RECV, RUN_DPRINTF(sc, RUN_DEBUG_RECV,
"MIC error. Someone is lying.\n"); "MIC error. Someone is lying.\n");
return; goto fail;
} }
ant = run_maxrssi_chain(sc, rxwi); ant = run_maxrssi_chain(sc, rxwi);
rssi = rxwi->rssi[ant]; rssi = rxwi->rssi[ant];
nf = run_rssi2dbm(sc, rssi, ant); nf = run_rssi2dbm(sc, rssi, ant);
m->m_pkthdr.len = m->m_len = len;
if (__predict_false(ieee80211_radiotap_active(ic))) { if (__predict_false(ieee80211_radiotap_active(ic))) {
struct run_rx_radiotap_header *tap = &sc->sc_rxtap; struct run_rx_radiotap_header *tap = &sc->sc_rxtap;
uint16_t phy; uint16_t phy;
@ -2936,6 +2947,12 @@ run_rx_frame(struct run_softc *sc, struct mbuf *m, uint32_t dmalen)
} else { } else {
(void)ieee80211_input_all(ic, m, rssi, nf); (void)ieee80211_input_all(ic, m, rssi, nf);
} }
return;
fail:
m_freem(m);
counter_u64_add(ic->ic_ierrors, 1);
} }
static void static void
@ -2945,7 +2962,7 @@ run_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error)
struct ieee80211com *ic = &sc->sc_ic; struct ieee80211com *ic = &sc->sc_ic;
struct mbuf *m = NULL; struct mbuf *m = NULL;
struct mbuf *m0; struct mbuf *m0;
uint32_t dmalen; uint32_t dmalen, mbuf_len;
uint16_t rxwisize; uint16_t rxwisize;
int xferlen; int xferlen;
@ -3051,6 +3068,14 @@ tr_setup:
break; break;
} }
mbuf_len = dmalen + sizeof(struct rt2870_rxd);
if (__predict_false(mbuf_len > MCLBYTES)) {
RUN_DPRINTF(sc, RUN_DEBUG_RECV_DESC | RUN_DEBUG_USB,
"payload is too big: mbuf_len %u\n", mbuf_len);
counter_u64_add(ic->ic_ierrors, 1);
break;
}
/* copy aggregated frames to another mbuf */ /* copy aggregated frames to another mbuf */
m0 = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); m0 = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
if (__predict_false(m0 == NULL)) { if (__predict_false(m0 == NULL)) {
@ -3060,14 +3085,13 @@ tr_setup:
break; break;
} }
m_copydata(m, 4 /* skip 32-bit DMA-len header */, m_copydata(m, 4 /* skip 32-bit DMA-len header */,
dmalen + sizeof(struct rt2870_rxd), mtod(m0, caddr_t)); mbuf_len, mtod(m0, caddr_t));
m0->m_pkthdr.len = m0->m_len = m0->m_pkthdr.len = m0->m_len = mbuf_len;
dmalen + sizeof(struct rt2870_rxd);
run_rx_frame(sc, m0, dmalen); run_rx_frame(sc, m0, dmalen);
/* update data ptr */ /* update data ptr */
m->m_data += dmalen + 8; m->m_data += mbuf_len + 4;
m->m_pkthdr.len = m->m_len -= dmalen + 8; m->m_pkthdr.len = m->m_len -= mbuf_len + 4;
} }
/* make sure we free the source buffer, if any */ /* make sure we free the source buffer, if any */

View File

@ -3935,21 +3935,18 @@ urtw_rxeof(struct usb_xfer *xfer, struct urtw_data *data, int *rssi_p,
usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
if (actlen < (int)URTW_MIN_RXBUFSZ) {
counter_u64_add(ic->ic_ierrors, 1);
return (NULL);
}
if (sc->sc_flags & URTW_RTL8187B) { if (sc->sc_flags & URTW_RTL8187B) {
struct urtw_8187b_rxhdr *rx; struct urtw_8187b_rxhdr *rx;
if (actlen < sizeof(*rx) + IEEE80211_ACK_LEN)
goto fail;
rx = (struct urtw_8187b_rxhdr *)(data->buf + rx = (struct urtw_8187b_rxhdr *)(data->buf +
(actlen - (sizeof(struct urtw_8187b_rxhdr)))); (actlen - (sizeof(struct urtw_8187b_rxhdr))));
flen = le32toh(rx->flag) & 0xfff; flen = le32toh(rx->flag) & 0xfff;
if (flen > actlen) { if (flen > actlen - sizeof(*rx))
counter_u64_add(ic->ic_ierrors, 1); goto fail;
return (NULL);
}
rate = (le32toh(rx->flag) >> URTW_RX_FLAG_RXRATE_SHIFT) & 0xf; rate = (le32toh(rx->flag) >> URTW_RX_FLAG_RXRATE_SHIFT) & 0xf;
/* XXX correct? */ /* XXX correct? */
rssi = rx->rssi & URTW_RX_RSSI_MASK; rssi = rx->rssi & URTW_RX_RSSI_MASK;
@ -3957,13 +3954,14 @@ urtw_rxeof(struct usb_xfer *xfer, struct urtw_data *data, int *rssi_p,
} else { } else {
struct urtw_8187l_rxhdr *rx; struct urtw_8187l_rxhdr *rx;
if (actlen < sizeof(*rx) + IEEE80211_ACK_LEN)
goto fail;
rx = (struct urtw_8187l_rxhdr *)(data->buf + rx = (struct urtw_8187l_rxhdr *)(data->buf +
(actlen - (sizeof(struct urtw_8187l_rxhdr)))); (actlen - (sizeof(struct urtw_8187l_rxhdr))));
flen = le32toh(rx->flag) & 0xfff; flen = le32toh(rx->flag) & 0xfff;
if (flen > actlen) { if (flen > actlen - sizeof(*rx))
counter_u64_add(ic->ic_ierrors, 1); goto fail;
return (NULL);
}
rate = (le32toh(rx->flag) >> URTW_RX_FLAG_RXRATE_SHIFT) & 0xf; rate = (le32toh(rx->flag) >> URTW_RX_FLAG_RXRATE_SHIFT) & 0xf;
/* XXX correct? */ /* XXX correct? */
@ -3971,11 +3969,12 @@ urtw_rxeof(struct usb_xfer *xfer, struct urtw_data *data, int *rssi_p,
noise = rx->noise; noise = rx->noise;
} }
if (flen < IEEE80211_ACK_LEN)
goto fail;
mnew = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); mnew = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
if (mnew == NULL) { if (mnew == NULL)
counter_u64_add(ic->ic_ierrors, 1); goto fail;
return (NULL);
}
m = data->m; m = data->m;
data->m = mnew; data->m = mnew;
@ -3994,13 +3993,17 @@ urtw_rxeof(struct usb_xfer *xfer, struct urtw_data *data, int *rssi_p,
} }
wh = mtod(m, struct ieee80211_frame *); wh = mtod(m, struct ieee80211_frame *);
if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_DATA) if (IEEE80211_IS_DATA(wh))
sc->sc_currate = (rate > 0) ? rate : sc->sc_currate; sc->sc_currate = (rate > 0) ? rate : sc->sc_currate;
*rssi_p = rssi; *rssi_p = rssi;
*nf_p = noise; /* XXX correct? */ *nf_p = noise; /* XXX correct? */
return (m); return (m);
fail:
counter_u64_add(ic->ic_ierrors, 1);
return (NULL);
} }
static void static void
@ -4008,7 +4011,6 @@ urtw_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error)
{ {
struct urtw_softc *sc = usbd_xfer_softc(xfer); struct urtw_softc *sc = usbd_xfer_softc(xfer);
struct ieee80211com *ic = &sc->sc_ic; struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_frame *wh;
struct ieee80211_node *ni; struct ieee80211_node *ni;
struct mbuf *m = NULL; struct mbuf *m = NULL;
struct urtw_data *data; struct urtw_data *data;
@ -4046,9 +4048,13 @@ setup:
*/ */
URTW_UNLOCK(sc); URTW_UNLOCK(sc);
if (m != NULL) { if (m != NULL) {
wh = mtod(m, struct ieee80211_frame *); if (m->m_pkthdr.len >=
sizeof(struct ieee80211_frame_min)) {
ni = ieee80211_find_rxnode(ic, ni = ieee80211_find_rxnode(ic,
(struct ieee80211_frame_min *)wh); mtod(m, struct ieee80211_frame_min *));
} else
ni = NULL;
if (ni != NULL) { if (ni != NULL) {
(void) ieee80211_input(ni, m, rssi, nf); (void) ieee80211_input(ni, m, rssi, nf);
/* node is no longer needed */ /* node is no longer needed */

View File

@ -47,10 +47,6 @@ struct urtw_data {
}; };
typedef STAILQ_HEAD(, urtw_data) urtw_datahead; typedef STAILQ_HEAD(, urtw_data) urtw_datahead;
/* XXX not correct.. */
#define URTW_MIN_RXBUFSZ \
(sizeof(struct ieee80211_frame_min))
#define URTW_RX_DATA_LIST_COUNT 4 #define URTW_RX_DATA_LIST_COUNT 4
#define URTW_TX_DATA_LIST_COUNT 16 #define URTW_TX_DATA_LIST_COUNT 16
#define URTW_RX_MAXSIZE 0x9c4 #define URTW_RX_MAXSIZE 0x9c4

View File

@ -756,6 +756,28 @@ intr_event_barrier(struct intr_event *ie)
atomic_thread_fence_acq(); atomic_thread_fence_acq();
} }
static void
intr_handler_barrier(struct intr_handler *handler)
{
struct intr_event *ie;
ie = handler->ih_event;
mtx_assert(&ie->ie_lock, MA_OWNED);
KASSERT((handler->ih_flags & IH_DEAD) == 0,
("update for a removed handler"));
if (ie->ie_thread == NULL) {
intr_event_barrier(ie);
return;
}
if ((handler->ih_flags & IH_CHANGED) == 0) {
handler->ih_flags |= IH_CHANGED;
intr_event_schedule_thread(ie);
}
while ((handler->ih_flags & IH_CHANGED) != 0)
msleep(handler, &ie->ie_lock, 0, "ih_barr", 0);
}
/* /*
* Sleep until an ithread finishes executing an interrupt handler. * Sleep until an ithread finishes executing an interrupt handler.
* *
@ -880,6 +902,49 @@ intr_event_remove_handler(void *cookie)
} }
#endif /* __rtems__ */ #endif /* __rtems__ */
int
intr_event_suspend_handler(void *cookie)
{
struct intr_handler *handler = (struct intr_handler *)cookie;
struct intr_event *ie;
if (handler == NULL)
return (EINVAL);
ie = handler->ih_event;
KASSERT(ie != NULL,
("interrupt handler \"%s\" has a NULL interrupt event",
handler->ih_name));
mtx_lock(&ie->ie_lock);
handler->ih_flags |= IH_SUSP;
intr_handler_barrier(handler);
mtx_unlock(&ie->ie_lock);
return (0);
}
int
intr_event_resume_handler(void *cookie)
{
struct intr_handler *handler = (struct intr_handler *)cookie;
struct intr_event *ie;
if (handler == NULL)
return (EINVAL);
ie = handler->ih_event;
KASSERT(ie != NULL,
("interrupt handler \"%s\" has a NULL interrupt event",
handler->ih_name));
/*
* intr_handler_barrier() acts not only as a barrier,
* it also allows to check for any pending interrupts.
*/
mtx_lock(&ie->ie_lock);
handler->ih_flags &= ~IH_SUSP;
intr_handler_barrier(handler);
mtx_unlock(&ie->ie_lock);
return (0);
}
static int static int
intr_event_schedule_thread(struct intr_event *ie) intr_event_schedule_thread(struct intr_event *ie)
{ {
@ -1068,10 +1133,21 @@ intr_event_execute_handlers(struct proc *p, struct intr_event *ie)
*/ */
ihp = ih; ihp = ih;
if ((ih->ih_flags & IH_CHANGED) != 0) {
mtx_lock(&ie->ie_lock);
ih->ih_flags &= ~IH_CHANGED;
wakeup(ih);
mtx_unlock(&ie->ie_lock);
}
/* Skip filter only handlers */ /* Skip filter only handlers */
if (ih->ih_handler == NULL) if (ih->ih_handler == NULL)
continue; continue;
/* Skip suspended handlers */
if ((ih->ih_flags & IH_SUSP) != 0)
continue;
/* /*
* For software interrupt threads, we only execute * For software interrupt threads, we only execute
* handlers that have their need flag set. Hardware * handlers that have their need flag set. Hardware
@ -1255,8 +1331,9 @@ intr_event_handle(struct intr_event *ie, struct trapframe *frame)
struct intr_handler *ih; struct intr_handler *ih;
struct trapframe *oldframe; struct trapframe *oldframe;
struct thread *td; struct thread *td;
int ret, thread;
int phase; int phase;
int ret;
bool filter, thread;
td = curthread; td = curthread;
@ -1275,7 +1352,8 @@ intr_event_handle(struct intr_event *ie, struct trapframe *frame)
* a trapframe as its argument. * a trapframe as its argument.
*/ */
td->td_intr_nesting_level++; td->td_intr_nesting_level++;
thread = 0; filter = false;
thread = false;
ret = 0; ret = 0;
critical_enter(); critical_enter();
oldframe = td->td_intr_frame; oldframe = td->td_intr_frame;
@ -1291,8 +1369,10 @@ intr_event_handle(struct intr_event *ie, struct trapframe *frame)
atomic_thread_fence_seq_cst(); atomic_thread_fence_seq_cst();
CK_SLIST_FOREACH(ih, &ie->ie_handlers, ih_next) { CK_SLIST_FOREACH(ih, &ie->ie_handlers, ih_next) {
if ((ih->ih_flags & IH_SUSP) != 0)
continue;
if (ih->ih_filter == NULL) { if (ih->ih_filter == NULL) {
thread = 1; thread = true;
continue; continue;
} }
CTR4(KTR_INTR, "%s: exec %p(%p) for %s", __func__, CTR4(KTR_INTR, "%s: exec %p(%p) for %s", __func__,
@ -1307,6 +1387,7 @@ intr_event_handle(struct intr_event *ie, struct trapframe *frame)
(ret & ~(FILTER_SCHEDULE_THREAD | FILTER_HANDLED)) == 0), (ret & ~(FILTER_SCHEDULE_THREAD | FILTER_HANDLED)) == 0),
("%s: incorrect return value %#x from %s", __func__, ret, ("%s: incorrect return value %#x from %s", __func__, ret,
ih->ih_name)); ih->ih_name));
filter = filter || ret == FILTER_HANDLED;
/* /*
* Wrapper handler special handling: * Wrapper handler special handling:
@ -1320,11 +1401,11 @@ intr_event_handle(struct intr_event *ie, struct trapframe *frame)
* of just an ithread handler. * of just an ithread handler.
* *
* TODO: write a generic wrapper to avoid people rolling * TODO: write a generic wrapper to avoid people rolling
* their own * their own.
*/ */
if (!thread) { if (!thread) {
if (ret == FILTER_SCHEDULE_THREAD) if (ret == FILTER_SCHEDULE_THREAD)
thread = 1; thread = true;
} }
} }
atomic_add_rel_int(&ie->ie_active[phase], -1); atomic_add_rel_int(&ie->ie_active[phase], -1);
@ -1348,6 +1429,11 @@ intr_event_handle(struct intr_event *ie, struct trapframe *frame)
} }
critical_exit(); critical_exit();
td->td_intr_nesting_level--; td->td_intr_nesting_level--;
#ifdef notyet
/* The interrupt is not aknowledged by any filter and has no ithread. */
if (!thread && !filter)
return (EINVAL);
#endif
return (0); return (0);
} }

View File

@ -64,14 +64,14 @@ static MALLOC_DEFINE(M_MTXPOOL, "mtx_pool", "mutex pool");
/* Pool sizes must be a power of two */ /* Pool sizes must be a power of two */
#ifndef MTX_POOL_SLEEP_SIZE #ifndef MTX_POOL_SLEEP_SIZE
#define MTX_POOL_SLEEP_SIZE 128 #define MTX_POOL_SLEEP_SIZE 1024
#endif #endif
struct mtxpool_header { struct mtxpool_header {
int mtxpool_size; int mtxpool_size;
int mtxpool_mask; int mtxpool_mask;
int mtxpool_shift; int mtxpool_shift;
int mtxpool_next; int mtxpool_next __aligned(CACHE_LINE_SIZE);
}; };
struct mtx_pool { struct mtx_pool {

View File

@ -4100,6 +4100,36 @@ bus_generic_teardown_intr(device_t dev, device_t child, struct resource *irq,
return (EINVAL); return (EINVAL);
} }
/**
* @brief Helper function for implementing BUS_SUSPEND_INTR().
*
* This simple implementation of BUS_SUSPEND_INTR() simply calls the
* BUS_SUSPEND_INTR() method of the parent of @p dev.
*/
int
bus_generic_suspend_intr(device_t dev, device_t child, struct resource *irq)
{
/* Propagate up the bus hierarchy until someone handles it. */
if (dev->parent)
return (BUS_SUSPEND_INTR(dev->parent, child, irq));
return (EINVAL);
}
/**
* @brief Helper function for implementing BUS_RESUME_INTR().
*
* This simple implementation of BUS_RESUME_INTR() simply calls the
* BUS_RESUME_INTR() method of the parent of @p dev.
*/
int
bus_generic_resume_intr(device_t dev, device_t child, struct resource *irq)
{
/* Propagate up the bus hierarchy until someone handles it. */
if (dev->parent)
return (BUS_RESUME_INTR(dev->parent, child, irq));
return (EINVAL);
}
/** /**
* @brief Helper function for implementing BUS_ADJUST_RESOURCE(). * @brief Helper function for implementing BUS_ADJUST_RESOURCE().
* *
@ -4667,6 +4697,34 @@ bus_teardown_intr(device_t dev, struct resource *r, void *cookie)
return (BUS_TEARDOWN_INTR(dev->parent, dev, r, cookie)); return (BUS_TEARDOWN_INTR(dev->parent, dev, r, cookie));
} }
/**
* @brief Wrapper function for BUS_SUSPEND_INTR().
*
* This function simply calls the BUS_SUSPEND_INTR() method of the
* parent of @p dev.
*/
int
bus_suspend_intr(device_t dev, struct resource *r)
{
if (dev->parent == NULL)
return (EINVAL);
return (BUS_SUSPEND_INTR(dev->parent, dev, r));
}
/**
* @brief Wrapper function for BUS_RESUME_INTR().
*
* This function simply calls the BUS_RESUME_INTR() method of the
* parent of @p dev.
*/
int
bus_resume_intr(device_t dev, struct resource *r)
{
if (dev->parent == NULL)
return (EINVAL);
return (BUS_RESUME_INTR(dev->parent, dev, r));
}
/** /**
* @brief Wrapper function for BUS_BIND_INTR(). * @brief Wrapper function for BUS_BIND_INTR().
* *

View File

@ -96,6 +96,7 @@ struct resource_i {
rman_res_t r_end; /* index of the last entry (inclusive) */ rman_res_t r_end; /* index of the last entry (inclusive) */
u_int r_flags; u_int r_flags;
void *r_virtual; /* virtual address of this resource */ void *r_virtual; /* virtual address of this resource */
void *r_irq_cookie; /* interrupt cookie for this (interrupt) resource */
device_t r_dev; /* device which has allocated this resource */ device_t r_dev; /* device which has allocated this resource */
struct rman *r_rm; /* resource manager from whence this came */ struct rman *r_rm; /* resource manager from whence this came */
int r_rid; /* optional rid for this resource. */ int r_rid; /* optional rid for this resource. */
@ -870,6 +871,20 @@ rman_get_virtual(struct resource *r)
return (r->__r_i->r_virtual); return (r->__r_i->r_virtual);
} }
void
rman_set_irq_cookie(struct resource *r, void *c)
{
r->__r_i->r_irq_cookie = c;
}
void *
rman_get_irq_cookie(struct resource *r)
{
return (r->__r_i->r_irq_cookie);
}
void void
rman_set_bustag(struct resource *r, bus_space_tag_t t) rman_set_bustag(struct resource *r, bus_space_tag_t t)
{ {

View File

@ -407,8 +407,10 @@ ieee80211_ifdetach(struct ieee80211com *ic)
* The VAP is responsible for setting and clearing * The VAP is responsible for setting and clearing
* the VIMAGE context. * the VIMAGE context.
*/ */
while ((vap = TAILQ_FIRST(&ic->ic_vaps)) != NULL) while ((vap = TAILQ_FIRST(&ic->ic_vaps)) != NULL) {
ieee80211_com_vdetach(vap);
ieee80211_vap_destroy(vap); ieee80211_vap_destroy(vap);
}
ieee80211_waitfor_parent(ic); ieee80211_waitfor_parent(ic);
ieee80211_sysctl_detach(ic); ieee80211_sysctl_detach(ic);

View File

@ -664,14 +664,15 @@ ieee80211_crypto_decap(struct ieee80211_node *ni, struct mbuf *m, int hdrlen,
k = &ni->ni_ucastkey; k = &ni->ni_ucastkey;
/* /*
* Insure crypto header is contiguous for all decap work. * Insure crypto header is contiguous and long enough for all
* decap work.
*/ */
cip = k->wk_cipher; cip = k->wk_cipher;
if (m->m_len < hdrlen + cip->ic_header && if (m->m_len < hdrlen + cip->ic_header) {
(m = m_pullup(m, hdrlen + cip->ic_header)) == NULL) {
IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr2, IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr2,
"unable to pullup %s header", cip->ic_name); "frame is too short (%d < %u) for crypto decap",
vap->iv_stats.is_rx_wepfail++; /* XXX */ cip->ic_name, m->m_len, hdrlen + cip->ic_header);
vap->iv_stats.is_rx_tooshort++;
*key = NULL; *key = NULL;
return (0); return (0);
} }

View File

@ -309,6 +309,55 @@ ieee80211_sysctl_vdetach(struct ieee80211vap *vap)
} }
} }
#define MS(_v, _f) (((_v) & _f##_M) >> _f##_S)
int
ieee80211_com_vincref(struct ieee80211vap *vap)
{
uint32_t ostate;
ostate = atomic_fetchadd_32(&vap->iv_com_state, IEEE80211_COM_REF_ADD);
if (ostate & IEEE80211_COM_DETACHED) {
atomic_subtract_32(&vap->iv_com_state, IEEE80211_COM_REF_ADD);
return (ENETDOWN);
}
if (MS(ostate, IEEE80211_COM_REF) == IEEE80211_COM_REF_MAX) {
atomic_subtract_32(&vap->iv_com_state, IEEE80211_COM_REF_ADD);
return (EOVERFLOW);
}
return (0);
}
void
ieee80211_com_vdecref(struct ieee80211vap *vap)
{
uint32_t ostate;
ostate = atomic_fetchadd_32(&vap->iv_com_state, -IEEE80211_COM_REF_ADD);
KASSERT(MS(ostate, IEEE80211_COM_REF) != 0,
("com reference counter underflow"));
(void) ostate;
}
void
ieee80211_com_vdetach(struct ieee80211vap *vap)
{
int sleep_time;
sleep_time = msecs_to_ticks(250);
if (sleep_time == 0)
sleep_time = 1;
atomic_set_32(&vap->iv_com_state, IEEE80211_COM_DETACHED);
while (MS(atomic_load_32(&vap->iv_com_state), IEEE80211_COM_REF) != 0)
pause("comref", sleep_time);
}
#undef MS
int int
ieee80211_node_dectestref(struct ieee80211_node *ni) ieee80211_node_dectestref(struct ieee80211_node *ni)
{ {

View File

@ -224,6 +224,11 @@ typedef struct mtx ieee80211_rt_lock_t;
*/ */
#include <machine/atomic.h> #include <machine/atomic.h>
struct ieee80211vap;
int ieee80211_com_vincref(struct ieee80211vap *);
void ieee80211_com_vdecref(struct ieee80211vap *);
void ieee80211_com_vdetach(struct ieee80211vap *);
#define ieee80211_node_initref(_ni) \ #define ieee80211_node_initref(_ni) \
do { ((_ni)->ni_refcnt = 1); } while (0) do { ((_ni)->ni_refcnt = 1); } while (0)
#define ieee80211_node_incref(_ni) \ #define ieee80211_node_incref(_ni) \
@ -235,7 +240,6 @@ int ieee80211_node_dectestref(struct ieee80211_node *ni);
#define ieee80211_node_refcnt(_ni) (_ni)->ni_refcnt #define ieee80211_node_refcnt(_ni) (_ni)->ni_refcnt
struct ifqueue; struct ifqueue;
struct ieee80211vap;
void ieee80211_drain_ifq(struct ifqueue *); void ieee80211_drain_ifq(struct ifqueue *);
void ieee80211_flush_ifq(struct ifqueue *, struct ieee80211vap *); void ieee80211_flush_ifq(struct ifqueue *, struct ieee80211vap *);

View File

@ -3482,10 +3482,14 @@ ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{ {
struct ieee80211vap *vap = ifp->if_softc; struct ieee80211vap *vap = ifp->if_softc;
struct ieee80211com *ic = vap->iv_ic; struct ieee80211com *ic = vap->iv_ic;
int error = 0, wait = 0; int error = 0, wait = 0, ic_used;
struct ifreq *ifr; struct ifreq *ifr;
struct ifaddr *ifa; /* XXX */ struct ifaddr *ifa; /* XXX */
ic_used = (cmd != SIOCSIFMTU && cmd != SIOCG80211STATS);
if (ic_used && (error = ieee80211_com_vincref(vap)) != 0)
return (error);
switch (cmd) { switch (cmd) {
case SIOCSIFFLAGS: case SIOCSIFFLAGS:
IEEE80211_LOCK(ic); IEEE80211_LOCK(ic);
@ -3622,5 +3626,9 @@ ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
error = ether_ioctl(ifp, cmd, data); error = ether_ioctl(ifp, cmd, data);
break; break;
} }
if (ic_used)
ieee80211_com_vdecref(vap);
return (error); return (error);
} }

View File

@ -474,6 +474,8 @@ static const u_int chanflags[IEEE80211_MODE_MAX] = {
/* check legacy */ /* check legacy */
[IEEE80211_MODE_11NA] = IEEE80211_CHAN_A, [IEEE80211_MODE_11NA] = IEEE80211_CHAN_A,
[IEEE80211_MODE_11NG] = IEEE80211_CHAN_G, [IEEE80211_MODE_11NG] = IEEE80211_CHAN_G,
[IEEE80211_MODE_VHT_5GHZ] = IEEE80211_CHAN_A,
[IEEE80211_MODE_VHT_2GHZ] = IEEE80211_CHAN_G,
}; };
static void static void
@ -496,12 +498,15 @@ add_channels(struct ieee80211vap *vap,
if (c == NULL || isexcluded(vap, c)) if (c == NULL || isexcluded(vap, c))
continue; continue;
if (mode == IEEE80211_MODE_AUTO) { if (mode == IEEE80211_MODE_AUTO) {
KASSERT(IEEE80211_IS_CHAN_B(c),
("%s: wrong channel for 'auto' mode %u / %u\n",
__func__, c->ic_freq, c->ic_flags));
/* /*
* XXX special-case 11b/g channels so we select * XXX special-case 11b/g channels so we select
* the g channel if both are present. * the g channel if both are present.
*/ */
if (IEEE80211_IS_CHAN_B(c) && if ((cg = find11gchannel(ic, i, c->ic_freq)) != NULL)
(cg = find11gchannel(ic, i, c->ic_freq)) != NULL)
c = cg; c = cg;
} }
ss->ss_chans[ss->ss_last++] = c; ss->ss_chans[ss->ss_last++] = c;
@ -620,32 +625,48 @@ makescanlist(struct ieee80211_scan_state *ss, struct ieee80211vap *vap,
*/ */
for (scan = table; scan->list != NULL; scan++) { for (scan = table; scan->list != NULL; scan++) {
mode = scan->mode; mode = scan->mode;
if (vap->iv_des_mode != IEEE80211_MODE_AUTO) {
switch (mode) {
case IEEE80211_MODE_11B:
if (vap->iv_des_mode == IEEE80211_MODE_11B)
break;
/*
* The scan table marks 2.4Ghz channels as b
* so if the desired mode is 11g / 11ng / 11acg,
* then use the 11b channel list but upgrade the mode.
*
* NB: 11b -> AUTO lets add_channels upgrade an
* 11b channel to 11g if available.
*/
if (vap->iv_des_mode == IEEE80211_MODE_AUTO ||
vap->iv_des_mode == IEEE80211_MODE_11G ||
vap->iv_des_mode == IEEE80211_MODE_11NG ||
vap->iv_des_mode == IEEE80211_MODE_VHT_2GHZ) {
mode = vap->iv_des_mode;
break;
}
continue;
case IEEE80211_MODE_11A:
/* Use 11a channel list for 11na / 11ac modes */
if (vap->iv_des_mode == IEEE80211_MODE_11NA ||
vap->iv_des_mode == IEEE80211_MODE_VHT_5GHZ) {
mode = vap->iv_des_mode;
break;
}
/* FALLTHROUGH */
default:
/* /*
* If a desired mode was specified, scan only * If a desired mode was specified, scan only
* channels that satisfy that constraint. * channels that satisfy that constraint.
*/ */
if (vap->iv_des_mode != mode) { if (vap->iv_des_mode != IEEE80211_MODE_AUTO &&
/* vap->iv_des_mode != mode)
* The scan table marks 2.4Ghz channels as b
* so if the desired mode is 11g, then use
* the 11b channel list but upgrade the mode.
*/
if (vap->iv_des_mode == IEEE80211_MODE_11G) {
if (mode == IEEE80211_MODE_11G) /* Skip the G check */
continue; continue;
else if (mode == IEEE80211_MODE_11B)
mode = IEEE80211_MODE_11G; /* upgrade */
}
}
} else {
/*
* This lets add_channels upgrade an 11b channel
* to 11g if available.
*/
if (mode == IEEE80211_MODE_11B)
mode = IEEE80211_MODE_AUTO;
} }
#ifdef IEEE80211_F_XR #ifdef IEEE80211_F_XR
/* XR does not operate on turbo channels */ /* XR does not operate on turbo channels */
if ((vap->iv_flags & IEEE80211_F_XR) && if ((vap->iv_flags & IEEE80211_F_XR) &&

View File

@ -562,7 +562,9 @@ struct ieee80211vap {
const struct wmeParams *wme_params); const struct wmeParams *wme_params);
struct task iv_wme_task; /* deferred VAP WME update */ struct task iv_wme_task; /* deferred VAP WME update */
uint64_t iv_spare[6]; uint64_t iv_spare[5];
uint32_t iv_com_state; /* com usage / detached flag */
uint32_t iv_spare1;
}; };
MALLOC_DECLARE(M_80211_VAP); MALLOC_DECLARE(M_80211_VAP);
@ -685,6 +687,12 @@ MALLOC_DECLARE(M_80211_VAP);
#define IEEE80211_VFHT_BITS \ #define IEEE80211_VFHT_BITS \
"\20\1VHT\2VHT40\3VHT80\4VHT80P80\5VHT160" "\20\1VHT\2VHT40\3VHT80\4VHT80P80\5VHT160"
#define IEEE80211_COM_DETACHED 0x00000001 /* ieee80211_ifdetach called */
#define IEEE80211_COM_REF_ADD 0x00000002 /* add / remove reference */
#define IEEE80211_COM_REF_M 0xfffffffe /* reference counter bits */
#define IEEE80211_COM_REF_S 1
#define IEEE80211_COM_REF_MAX (IEEE80211_COM_REF_M >> IEEE80211_COM_REF_S)
int ic_printf(struct ieee80211com *, const char *, ...) __printflike(2, 3); int ic_printf(struct ieee80211com *, const char *, ...) __printflike(2, 3);
void ieee80211_ifattach(struct ieee80211com *); void ieee80211_ifattach(struct ieee80211com *);
void ieee80211_ifdetach(struct ieee80211com *); void ieee80211_ifdetach(struct ieee80211com *);

View File

@ -1382,15 +1382,13 @@ in_lltable_lookup(struct lltable *llt, u_int flags, const struct sockaddr *l3add
IF_AFDATA_LOCK_ASSERT(llt->llt_ifp); IF_AFDATA_LOCK_ASSERT(llt->llt_ifp);
KASSERT(l3addr->sa_family == AF_INET, KASSERT(l3addr->sa_family == AF_INET,
("sin_family %d", l3addr->sa_family)); ("sin_family %d", l3addr->sa_family));
lle = in_lltable_find_dst(llt, sin->sin_addr); KASSERT((flags & (LLE_UNLOCKED | LLE_EXCLUSIVE)) !=
(LLE_UNLOCKED | LLE_EXCLUSIVE),
("wrong lle request flags: %#x", flags));
lle = in_lltable_find_dst(llt, sin->sin_addr);
if (lle == NULL) if (lle == NULL)
return (NULL); return (NULL);
KASSERT((flags & (LLE_UNLOCKED|LLE_EXCLUSIVE)) !=
(LLE_UNLOCKED|LLE_EXCLUSIVE),("wrong lle request flags: 0x%X",
flags));
if (flags & LLE_UNLOCKED) if (flags & LLE_UNLOCKED)
return (lle); return (lle);
@ -1399,6 +1397,17 @@ in_lltable_lookup(struct lltable *llt, u_int flags, const struct sockaddr *l3add
else else
LLE_RLOCK(lle); LLE_RLOCK(lle);
/*
* If the afdata lock is not held, the LLE may have been unlinked while
* we were blocked on the LLE lock. Check for this case.
*/
if (__predict_false((lle->la_flags & LLE_LINKED) == 0)) {
if (flags & LLE_EXCLUSIVE)
LLE_WUNLOCK(lle);
else
LLE_RUNLOCK(lle);
return (NULL);
}
return (lle); return (lle);
} }

View File

@ -1264,7 +1264,8 @@ ip_ctloutput(struct socket *so, struct sockopt *sopt)
if (inp->inp_options) { if (inp->inp_options) {
struct mbuf *options; struct mbuf *options;
options = m_dup(inp->inp_options, M_NOWAIT); options = m_copym(inp->inp_options, 0,
M_COPYALL, M_NOWAIT);
INP_RUNLOCK(inp); INP_RUNLOCK(inp);
if (options != NULL) { if (options != NULL) {
error = sooptcopyout(sopt, error = sooptcopyout(sopt,

View File

@ -983,6 +983,9 @@ __FBSDID("$FreeBSD$");
((((uint8_t *)&(a)->s_addr)[0] == 169) && \ ((((uint8_t *)&(a)->s_addr)[0] == 169) && \
(((uint8_t *)&(a)->s_addr)[1] == 254)) (((uint8_t *)&(a)->s_addr)[1] == 254))
/* Maximum size of optval for IPPROTO_SCTP level socket options. */
#define SCTP_SOCKET_OPTION_LIMIT (64 * 1024)
#if defined(_KERNEL) #if defined(_KERNEL)
#define SCTP_GETTIME_TIMEVAL(x) (getmicrouptime(x)) #define SCTP_GETTIME_TIMEVAL(x) (getmicrouptime(x))

View File

@ -6830,6 +6830,10 @@ sctp_ctloutput(struct socket *so, struct sockopt *sopt)
return (error); return (error);
} }
optsize = sopt->sopt_valsize; optsize = sopt->sopt_valsize;
if (optsize > SCTP_SOCKET_OPTION_LIMIT) {
SCTP_LTRACE_ERR_RET(so->so_pcb, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOBUFS);
return (ENOBUFS);
}
if (optsize) { if (optsize) {
SCTP_MALLOC(optval, void *, optsize, SCTP_M_SOCKOPT); SCTP_MALLOC(optval, void *, optsize, SCTP_M_SOCKOPT);
if (optval == NULL) { if (optval == NULL) {

View File

@ -658,7 +658,8 @@ after_sack_rexmit:
if (adv >= (int32_t)(2 * tp->t_maxseg) && if (adv >= (int32_t)(2 * tp->t_maxseg) &&
(adv >= (int32_t)(so->so_rcv.sb_hiwat / 4) || (adv >= (int32_t)(so->so_rcv.sb_hiwat / 4) ||
recwin <= (so->so_rcv.sb_hiwat / 8) || recwin <= (so->so_rcv.sb_hiwat / 8) ||
so->so_rcv.sb_hiwat <= 8 * tp->t_maxseg)) so->so_rcv.sb_hiwat <= 8 * tp->t_maxseg ||
adv >= TCP_MAXWIN << tp->rcv_scale))
goto send; goto send;
if (2 * adv >= (int32_t)so->so_rcv.sb_hiwat) if (2 * adv >= (int32_t)so->so_rcv.sb_hiwat)
goto send; goto send;

View File

@ -2319,16 +2319,13 @@ in6_lltable_lookup(struct lltable *llt, u_int flags,
IF_AFDATA_LOCK_ASSERT(llt->llt_ifp); IF_AFDATA_LOCK_ASSERT(llt->llt_ifp);
KASSERT(l3addr->sa_family == AF_INET6, KASSERT(l3addr->sa_family == AF_INET6,
("sin_family %d", l3addr->sa_family)); ("sin_family %d", l3addr->sa_family));
KASSERT((flags & (LLE_UNLOCKED | LLE_EXCLUSIVE)) !=
(LLE_UNLOCKED | LLE_EXCLUSIVE),
("wrong lle request flags: %#x", flags));
lle = in6_lltable_find_dst(llt, &sin6->sin6_addr); lle = in6_lltable_find_dst(llt, &sin6->sin6_addr);
if (lle == NULL) if (lle == NULL)
return (NULL); return (NULL);
KASSERT((flags & (LLE_UNLOCKED|LLE_EXCLUSIVE)) !=
(LLE_UNLOCKED|LLE_EXCLUSIVE),("wrong lle request flags: 0x%X",
flags));
if (flags & LLE_UNLOCKED) if (flags & LLE_UNLOCKED)
return (lle); return (lle);
@ -2336,6 +2333,18 @@ in6_lltable_lookup(struct lltable *llt, u_int flags,
LLE_WLOCK(lle); LLE_WLOCK(lle);
else else
LLE_RLOCK(lle); LLE_RLOCK(lle);
/*
* If the afdata lock is not held, the LLE may have been unlinked while
* we were blocked on the LLE lock. Check for this case.
*/
if (__predict_false((lle->la_flags & LLE_LINKED) == 0)) {
if (flags & LLE_EXCLUSIVE)
LLE_WUNLOCK(lle);
else
LLE_RUNLOCK(lle);
return (NULL);
}
return (lle); return (lle);
} }

View File

@ -53,6 +53,8 @@ __FBSDID("$FreeBSD$");
#include <net/vnet.h> #include <net/vnet.h>
#include <net/pfvar.h> #include <net/pfvar.h>
#define DPFPRINTF(n, x) if (V_pf_status.debug >= (n)) printf x
#define ACCEPT_FLAGS(flags, oklist) \ #define ACCEPT_FLAGS(flags, oklist) \
do { \ do { \
if ((flags & ~(oklist)) & \ if ((flags & ~(oklist)) & \
@ -1994,7 +1996,8 @@ pfr_update_stats(struct pfr_ktable *kt, struct pf_addr *a, sa_family_t af,
} }
if ((ke == NULL || ke->pfrke_not) != notrule) { if ((ke == NULL || ke->pfrke_not) != notrule) {
if (op_pass != PFR_OP_PASS) if (op_pass != PFR_OP_PASS)
printf("pfr_update_stats: assertion failed.\n"); DPFPRINTF(PF_DEBUG_URGENT,
("pfr_update_stats: assertion failed.\n"));
op_pass = PFR_OP_XPASS; op_pass = PFR_OP_XPASS;
} }
kt->pfrkt_packets[dir_out][op_pass]++; kt->pfrkt_packets[dir_out][op_pass]++;

View File

@ -485,6 +485,10 @@ int bus_generic_suspend(device_t dev);
int bus_generic_suspend_child(device_t dev, device_t child); int bus_generic_suspend_child(device_t dev, device_t child);
int bus_generic_teardown_intr(device_t dev, device_t child, int bus_generic_teardown_intr(device_t dev, device_t child,
struct resource *irq, void *cookie); struct resource *irq, void *cookie);
int bus_generic_suspend_intr(device_t dev, device_t child,
struct resource *irq);
int bus_generic_resume_intr(device_t dev, device_t child,
struct resource *irq);
int bus_generic_unmap_resource(device_t dev, device_t child, int type, int bus_generic_unmap_resource(device_t dev, device_t child, int type,
struct resource *r, struct resource *r,
struct resource_map *map); struct resource_map *map);
@ -535,6 +539,8 @@ int bus_setup_intr(device_t dev, struct resource *r, int flags,
driver_filter_t filter, driver_intr_t handler, driver_filter_t filter, driver_intr_t handler,
void *arg, void **cookiep); void *arg, void **cookiep);
int bus_teardown_intr(device_t dev, struct resource *r, void *cookie); int bus_teardown_intr(device_t dev, struct resource *r, void *cookie);
int bus_suspend_intr(device_t dev, struct resource *r);
int bus_resume_intr(device_t dev, struct resource *r);
int bus_bind_intr(device_t dev, struct resource *r, int cpu); int bus_bind_intr(device_t dev, struct resource *r, int cpu);
int bus_describe_intr(device_t dev, struct resource *irq, void *cookie, int bus_describe_intr(device_t dev, struct resource *irq, void *cookie,
const char *fmt, ...) __printflike(4, 5); const char *fmt, ...) __printflike(4, 5);

View File

@ -62,6 +62,8 @@ struct intr_handler {
#define IH_EXCLUSIVE 0x00000002 /* Exclusive interrupt. */ #define IH_EXCLUSIVE 0x00000002 /* Exclusive interrupt. */
#define IH_ENTROPY 0x00000004 /* Device is a good entropy source. */ #define IH_ENTROPY 0x00000004 /* Device is a good entropy source. */
#define IH_DEAD 0x00000008 /* Handler should be removed. */ #define IH_DEAD 0x00000008 /* Handler should be removed. */
#define IH_SUSP 0x00000010 /* Device is powered down. */
#define IH_CHANGED 0x40000000 /* Handler state is changed. */
#define IH_MPSAFE 0x80000000 /* Handler does not need Giant. */ #define IH_MPSAFE 0x80000000 /* Handler does not need Giant. */
/* /*
@ -184,6 +186,8 @@ int intr_event_describe_handler(struct intr_event *ie, void *cookie,
int intr_event_destroy(struct intr_event *ie); int intr_event_destroy(struct intr_event *ie);
int intr_event_handle(struct intr_event *ie, struct trapframe *frame); int intr_event_handle(struct intr_event *ie, struct trapframe *frame);
int intr_event_remove_handler(void *cookie); int intr_event_remove_handler(void *cookie);
int intr_event_suspend_handler(void *cookie);
int intr_event_resume_handler(void *cookie);
int intr_getaffinity(int irq, int mode, void *mask); int intr_getaffinity(int irq, int mode, void *mask);
void *intr_handler_source(void *cookie); void *intr_handler_source(void *cookie);
int intr_setaffinity(int irq, int mode, void *mask); int intr_setaffinity(int irq, int mode, void *mask);

View File

@ -131,6 +131,7 @@ bus_space_tag_t rman_get_bustag(struct resource *);
rman_res_t rman_get_end(struct resource *); rman_res_t rman_get_end(struct resource *);
device_t rman_get_device(struct resource *); device_t rman_get_device(struct resource *);
u_int rman_get_flags(struct resource *); u_int rman_get_flags(struct resource *);
void *rman_get_irq_cookie(struct resource *);
void rman_get_mapping(struct resource *, struct resource_map *); void rman_get_mapping(struct resource *, struct resource_map *);
int rman_get_rid(struct resource *); int rman_get_rid(struct resource *);
rman_res_t rman_get_size(struct resource *); rman_res_t rman_get_size(struct resource *);
@ -155,6 +156,7 @@ void rman_set_bushandle(struct resource *_r, bus_space_handle_t _h);
void rman_set_bustag(struct resource *_r, bus_space_tag_t _t); void rman_set_bustag(struct resource *_r, bus_space_tag_t _t);
void rman_set_device(struct resource *_r, device_t _dev); void rman_set_device(struct resource *_r, device_t _dev);
void rman_set_end(struct resource *_r, rman_res_t _end); void rman_set_end(struct resource *_r, rman_res_t _end);
void rman_set_irq_cookie(struct resource *_r, void *_c);
void rman_set_mapping(struct resource *, struct resource_map *); void rman_set_mapping(struct resource *, struct resource_map *);
void rman_set_rid(struct resource *_r, int _rid); void rman_set_rid(struct resource *_r, int _rid);
void rman_set_start(struct resource *_r, rman_res_t _start); void rman_set_start(struct resource *_r, rman_res_t _start);

View File

@ -55,7 +55,6 @@ void rm_init_flags(struct rmlock *rm, const char *name, int opts);
void rm_destroy(struct rmlock *rm); void rm_destroy(struct rmlock *rm);
int rm_wowned(const struct rmlock *rm); int rm_wowned(const struct rmlock *rm);
void rm_sysinit(void *arg); void rm_sysinit(void *arg);
void rm_sysinit_flags(void *arg);
void _rm_wlock_debug(struct rmlock *rm, const char *file, int line); void _rm_wlock_debug(struct rmlock *rm, const char *file, int line);
void _rm_wunlock_debug(struct rmlock *rm, const char *file, int line); void _rm_wunlock_debug(struct rmlock *rm, const char *file, int line);

View File

@ -136,7 +136,6 @@
void _rw_init_flags(volatile uintptr_t *c, const char *name, int opts); void _rw_init_flags(volatile uintptr_t *c, const char *name, int opts);
void _rw_destroy(volatile uintptr_t *c); void _rw_destroy(volatile uintptr_t *c);
void rw_sysinit(void *arg); void rw_sysinit(void *arg);
void rw_sysinit_flags(void *arg);
int _rw_wowned(const volatile uintptr_t *c); int _rw_wowned(const volatile uintptr_t *c);
void _rw_wlock_cookie(volatile uintptr_t *c, const char *file, int line); void _rw_wlock_cookie(volatile uintptr_t *c, const char *file, int line);
int __rw_try_wlock_int(struct rwlock *rw LOCK_FILE_LINE_ARG_DEF); int __rw_try_wlock_int(struct rwlock *rw LOCK_FILE_LINE_ARG_DEF);