diff options
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/ath/if_ath.c | 31 | ||||
-rw-r--r-- | sys/dev/ath/if_ath_btcoex.c | 281 | ||||
-rw-r--r-- | sys/dev/ath/if_ath_btcoex.h | 40 |
3 files changed, 352 insertions, 0 deletions
diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c index 757ee6f..91c5bf6 100644 --- a/sys/dev/ath/if_ath.c +++ b/sys/dev/ath/if_ath.c @@ -111,6 +111,7 @@ __FBSDID("$FreeBSD$"); #include <dev/ath/if_ath_rx_edma.h> #include <dev/ath/if_ath_tx_edma.h> #include <dev/ath/if_ath_beacon.h> +#include <dev/ath/if_ath_btcoex.h> #include <dev/ath/if_ath_spectral.h> #include <dev/ath/if_athdfs.h> @@ -521,6 +522,14 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) goto bad2; } + /* Attach bluetooth coexistence module */ + if (ath_btcoex_attach(sc) < 0) { + device_printf(sc->sc_dev, + "%s: unable to attach bluetooth coexistence\n", __func__); + error = EIO; + goto bad2; + } + /* Start DFS processing tasklet */ TASK_INIT(&sc->sc_dfstask, 0, ath_dfs_tasklet, sc); @@ -1029,6 +1038,7 @@ ath_detach(struct ath_softc *sc) #ifdef ATH_DEBUG_ALQ if_ath_alq_tidyup(&sc->sc_alq); #endif + ath_btcoex_detach(sc); ath_spectral_detach(sc); ath_dfs_detach(sc); ath_desc_free(sc); @@ -1589,6 +1599,11 @@ ath_resume(struct ath_softc *sc) ath_spectral_enable(sc, ic->ic_curchan); /* + * Let bluetooth coexistence at in case it's needed for this channel + */ + ath_btcoex_enable(sc, ic->ic_curchan); + + /* * If we're doing TDMA, enforce the TXOP limitation for chips that * support it. */ @@ -2045,6 +2060,11 @@ ath_init(void *arg) ath_spectral_enable(sc, ic->ic_curchan); /* + * Let bluetooth coexistence at in case it's needed for this channel + */ + ath_btcoex_enable(sc, ic->ic_curchan); + + /* * If we're doing TDMA, enforce the TXOP limitation for chips that * support it. */ @@ -2384,6 +2404,11 @@ ath_reset(struct ifnet *ifp, ATH_RESET_TYPE reset_type) ath_spectral_enable(sc, ic->ic_curchan); /* + * Let bluetooth coexistence at in case it's needed for this channel + */ + ath_btcoex_enable(sc, ic->ic_curchan); + + /* * If we're doing TDMA, enforce the TXOP limitation for chips that * support it. */ @@ -4946,6 +4971,12 @@ ath_chan_set(struct ath_softc *sc, struct ieee80211_channel *chan) ath_spectral_enable(sc, chan); /* + * Let bluetooth coexistence at in case it's needed for this + * channel + */ + ath_btcoex_enable(sc, ic->ic_curchan); + + /* * If we're doing TDMA, enforce the TXOP limitation for chips * that support it. */ diff --git a/sys/dev/ath/if_ath_btcoex.c b/sys/dev/ath/if_ath_btcoex.c new file mode 100644 index 0000000..ef9073d --- /dev/null +++ b/sys/dev/ath/if_ath_btcoex.c @@ -0,0 +1,281 @@ +/*- + * Copyright (c) 2013 Adrian Chadd <adrian@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + * + * $FreeBSD$ + */ +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +/* + * This implements some very basic bluetooth coexistence methods for + * the ath(4) hardware. + */ +#include "opt_ath.h" +#include "opt_inet.h" +#include "opt_wlan.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/sysctl.h> +#include <sys/kernel.h> +#include <sys/lock.h> +#include <sys/mutex.h> +#include <sys/errno.h> + +#include <machine/bus.h> +#include <machine/resource.h> +#include <sys/bus.h> + +#include <sys/socket.h> + +#include <net/if.h> +#include <net/if_media.h> +#include <net/if_arp.h> +#include <net/ethernet.h> /* XXX for ether_sprintf */ + +#include <net80211/ieee80211_var.h> + +#include <net/bpf.h> + +#ifdef INET +#include <netinet/in.h> +#include <netinet/if_ether.h> +#endif + +#include <dev/ath/if_athvar.h> +#include <dev/ath/if_ath_btcoex.h> + +/* + * Initial AR9285 / (WB195) bluetooth coexistence settings, + * just for experimentation. + * + * Return 0 for OK; errno for error. + * + * XXX TODO: There needs to be a PCIe workaround to disable ASPM if + * bluetooth coexistence is enabled. + */ +static int +ath_btcoex_cfg_wb195(struct ath_softc *sc) +{ + HAL_BT_COEX_INFO btinfo; + HAL_BT_COEX_CONFIG btconfig; + struct ath_hal *ah = sc->sc_ah; + + if (! ath_hal_btcoex_supported(ah)) + return (EINVAL); + + bzero(&btinfo, sizeof(btinfo)); + bzero(&btconfig, sizeof(btconfig)); + + device_printf(sc->sc_dev, "Enabling WB195 BTCOEX\n"); + + btinfo.bt_module = HAL_BT_MODULE_JANUS; + btinfo.bt_coex_config = HAL_BT_COEX_CFG_3WIRE; + /* + * These are the three GPIO pins hooked up between the AR9285 and + * the AR3011. + */ + btinfo.bt_gpio_bt_active = 6; + btinfo.bt_gpio_bt_priority = 7; + btinfo.bt_gpio_wlan_active = 5; + btinfo.bt_active_polarity = 1; /* XXX not used */ + btinfo.bt_single_ant = 1; /* 1 antenna on ar9285 ? */ + btinfo.bt_isolation = 0; /* in dB, not used */ + + ath_hal_btcoex_set_info(ah, &btinfo); + + btconfig.bt_time_extend = 0; + btconfig.bt_txstate_extend = 1; /* true */ + btconfig.bt_txframe_extend = 1; /* true */ + btconfig.bt_mode = HAL_BT_COEX_MODE_SLOTTED; + btconfig.bt_quiet_collision = 1; /* true */ + btconfig.bt_rxclear_polarity = 1; /* true */ + btconfig.bt_priority_time = 2; + btconfig.bt_first_slot_time = 5; + btconfig.bt_hold_rxclear = 1; /* true */ + + ath_hal_btcoex_set_config(ah, &btconfig); + + /* + * Enable antenna diversity. + */ + ath_hal_btcoex_set_parameter(ah, HAL_BT_COEX_ANTENNA_DIVERSITY, 1); + + return (0); +} + +#if 0 +/* + * When using bluetooth coexistence, ASPM needs to be disabled + * otherwise the sleeping interferes with the bluetooth (USB) + * operation and the MAC sleep/wakeup hardware. + */ +static int +ath_btcoex_aspm_wb195(struct ath_softc *sc) +{ + + /* XXX TODO: clear device ASPM L0S and L1 */ + /* XXX TODO: clear _parent_ ASPM L0S and L1 */ +} +#endif + +/* + * Methods which are required + */ + +/* + * Attach btcoex to the given interface + */ +int +ath_btcoex_attach(struct ath_softc *sc) +{ + int ret; + struct ath_hal *ah = sc->sc_ah; + const char *profname; + + /* + * No chipset bluetooth coexistence? Then do nothing. + */ + if (! ath_hal_btcoex_supported(ah)) + return (0); + + /* + * Look at the hints to determine which bluetooth + * profile to configure. + */ + ret = resource_string_value(device_get_name(sc->sc_dev), + device_get_unit(sc->sc_dev), + "btcoex_profile", + &profname); + if (ret != 0) { + /* nothing to do */ + return (0); + } + + if (strncmp(profname, "wb195", 5) == 0) { + ret = ath_btcoex_cfg_wb195(sc); + } else { + return (0); + } + + /* + * Propagate up failure from the actual attach phase. + */ + if (ret != 0) + return (ret); + + return (0); +} + +/* + * Detach btcoex from the given interface + */ +int +ath_btcoex_detach(struct ath_softc *sc) +{ + + return (0); +} + +/* + * Configure or disable bluetooth coexistence on the given channel. + * + * For AR9285/AR9287/AR9485, we'll never see a 5GHz channel, so we just + * assume bluetooth coexistence is always on. + * + * For AR9462, we may see a 5GHz channel; bluetooth coexistence should + * not be enabled on those channels. + */ +int +ath_btcoex_enable(struct ath_softc *sc, const struct ieee80211_channel *chan) +{ + + return (0); +} + +/* + * Handle ioctl requests from the diagnostic interface. + * + * The initial part of this code resembles ath_ioctl_diag(); + * it's likely a good idea to reduce duplication between + * these two routines. + */ +int +ath_btcoex_ioctl(struct ath_softc *sc, struct ath_diag *ad) +{ + unsigned int id = ad->ad_id & ATH_DIAG_ID; + void *indata = NULL; + void *outdata = NULL; + u_int32_t insize = ad->ad_in_size; + u_int32_t outsize = ad->ad_out_size; + int error = 0; +// int val; + + if (ad->ad_id & ATH_DIAG_IN) { + /* + * Copy in data. + */ + indata = malloc(insize, M_TEMP, M_NOWAIT); + if (indata == NULL) { + error = ENOMEM; + goto bad; + } + error = copyin(ad->ad_in_data, indata, insize); + if (error) + goto bad; + } + if (ad->ad_id & ATH_DIAG_DYN) { + /* + * Allocate a buffer for the results (otherwise the HAL + * returns a pointer to a buffer where we can read the + * results). Note that we depend on the HAL leaving this + * pointer for us to use below in reclaiming the buffer; + * may want to be more defensive. + */ + outdata = malloc(outsize, M_TEMP, M_NOWAIT); + if (outdata == NULL) { + error = ENOMEM; + goto bad; + } + } + switch (id) { + default: + error = EINVAL; + } + if (outsize < ad->ad_out_size) + ad->ad_out_size = outsize; + if (outdata && copyout(outdata, ad->ad_out_data, ad->ad_out_size)) + error = EFAULT; +bad: + if ((ad->ad_id & ATH_DIAG_IN) && indata != NULL) + free(indata, M_TEMP); + if ((ad->ad_id & ATH_DIAG_DYN) && outdata != NULL) + free(outdata, M_TEMP); + return (error); +} + diff --git a/sys/dev/ath/if_ath_btcoex.h b/sys/dev/ath/if_ath_btcoex.h new file mode 100644 index 0000000..8b175d2 --- /dev/null +++ b/sys/dev/ath/if_ath_btcoex.h @@ -0,0 +1,40 @@ +/*- + * Copyright (c) 2013 Adrian Chadd <adrian@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + * + * $FreeBSD$ + */ +#ifndef __IF_ATH_BTCOEX_H__ +#define __IF_ATH_BTCOEX_H__ + +extern int ath_btcoex_attach(struct ath_softc *sc); +extern int ath_btcoex_detach(struct ath_softc *sc); +extern int ath_btcoex_ioctl(struct ath_softc *sc, struct ath_diag *ad); +extern int ath_btcoex_enable(struct ath_softc *sc, + const struct ieee80211_channel *ch); + +#endif /* __IF_ATH_BTCOEX_H__ */ |