if_ath_btcoex.c revision 251606
1/*- 2 * Copyright (c) 2013 Adrian Chadd <adrian@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer, 10 * without modification. 11 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 13 * redistribution must be conditioned upon including a substantially 14 * similar Disclaimer requirement for further binary redistribution. 15 * 16 * NO WARRANTY 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 20 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 22 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27 * THE POSSIBILITY OF SUCH DAMAGES. 28 * 29 * $FreeBSD: head/sys/dev/ath/if_ath_btcoex.c 251606 2013-06-10 20:10:34Z adrian $ 30 */ 31#include <sys/cdefs.h> 32__FBSDID("$FreeBSD: head/sys/dev/ath/if_ath_btcoex.c 251606 2013-06-10 20:10:34Z adrian $"); 33 34/* 35 * This implements some very basic bluetooth coexistence methods for 36 * the ath(4) hardware. 37 */ 38#include "opt_ath.h" 39#include "opt_inet.h" 40#include "opt_wlan.h" 41 42#include <sys/param.h> 43#include <sys/systm.h> 44#include <sys/sysctl.h> 45#include <sys/kernel.h> 46#include <sys/lock.h> 47#include <sys/mutex.h> 48#include <sys/errno.h> 49 50#include <machine/bus.h> 51#include <machine/resource.h> 52#include <sys/bus.h> 53 54#include <sys/socket.h> 55 56#include <net/if.h> 57#include <net/if_media.h> 58#include <net/if_arp.h> 59#include <net/ethernet.h> /* XXX for ether_sprintf */ 60 61#include <net80211/ieee80211_var.h> 62 63#include <net/bpf.h> 64 65#ifdef INET 66#include <netinet/in.h> 67#include <netinet/if_ether.h> 68#endif 69 70#include <dev/ath/if_athvar.h> 71#include <dev/ath/if_ath_btcoex.h> 72 73/* 74 * Initial AR9285 / (WB195) bluetooth coexistence settings, 75 * just for experimentation. 76 * 77 * Return 0 for OK; errno for error. 78 * 79 * XXX TODO: There needs to be a PCIe workaround to disable ASPM if 80 * bluetooth coexistence is enabled. 81 */ 82static int 83ath_btcoex_cfg_wb195(struct ath_softc *sc) 84{ 85 HAL_BT_COEX_INFO btinfo; 86 HAL_BT_COEX_CONFIG btconfig; 87 struct ath_hal *ah = sc->sc_ah; 88 89 if (! ath_hal_btcoex_supported(ah)) 90 return (EINVAL); 91 92 bzero(&btinfo, sizeof(btinfo)); 93 bzero(&btconfig, sizeof(btconfig)); 94 95 device_printf(sc->sc_dev, "Enabling WB195 BTCOEX\n"); 96 97 btinfo.bt_module = HAL_BT_MODULE_JANUS; 98 btinfo.bt_coex_config = HAL_BT_COEX_CFG_3WIRE; 99 /* 100 * These are the three GPIO pins hooked up between the AR9285 and 101 * the AR3011. 102 */ 103 btinfo.bt_gpio_bt_active = 6; 104 btinfo.bt_gpio_bt_priority = 7; 105 btinfo.bt_gpio_wlan_active = 5; 106 btinfo.bt_active_polarity = 1; /* XXX not used */ 107 btinfo.bt_single_ant = 1; /* 1 antenna on ar9285 ? */ 108 btinfo.bt_isolation = 0; /* in dB, not used */ 109 110 ath_hal_btcoex_set_info(ah, &btinfo); 111 112 btconfig.bt_time_extend = 0; 113 btconfig.bt_txstate_extend = 1; /* true */ 114 btconfig.bt_txframe_extend = 1; /* true */ 115 btconfig.bt_mode = HAL_BT_COEX_MODE_SLOTTED; 116 btconfig.bt_quiet_collision = 1; /* true */ 117 btconfig.bt_rxclear_polarity = 1; /* true */ 118 btconfig.bt_priority_time = 2; 119 btconfig.bt_first_slot_time = 5; 120 btconfig.bt_hold_rxclear = 1; /* true */ 121 122 ath_hal_btcoex_set_config(ah, &btconfig); 123 124 /* 125 * Enable antenna diversity. 126 */ 127 ath_hal_btcoex_set_parameter(ah, HAL_BT_COEX_ANTENNA_DIVERSITY, 1); 128 129 return (0); 130} 131 132#if 0 133/* 134 * When using bluetooth coexistence, ASPM needs to be disabled 135 * otherwise the sleeping interferes with the bluetooth (USB) 136 * operation and the MAC sleep/wakeup hardware. 137 * 138 * The PCIe powersave routine also needs to not be called 139 * by the driver during suspend/resume, else things will get 140 * a little odd. Check Linux ath9k for more details. 141 */ 142static int 143ath_btcoex_aspm_wb195(struct ath_softc *sc) 144{ 145 146 /* XXX TODO: clear device ASPM L0S and L1 */ 147 /* XXX TODO: clear _parent_ ASPM L0S and L1 */ 148} 149#endif 150 151/* 152 * Methods which are required 153 */ 154 155/* 156 * Attach btcoex to the given interface 157 */ 158int 159ath_btcoex_attach(struct ath_softc *sc) 160{ 161 int ret; 162 struct ath_hal *ah = sc->sc_ah; 163 const char *profname; 164 165 /* 166 * No chipset bluetooth coexistence? Then do nothing. 167 */ 168 if (! ath_hal_btcoex_supported(ah)) 169 return (0); 170 171 /* 172 * Look at the hints to determine which bluetooth 173 * profile to configure. 174 */ 175 ret = resource_string_value(device_get_name(sc->sc_dev), 176 device_get_unit(sc->sc_dev), 177 "btcoex_profile", 178 &profname); 179 if (ret != 0) { 180 /* nothing to do */ 181 return (0); 182 } 183 184 if (strncmp(profname, "wb195", 5) == 0) { 185 ret = ath_btcoex_cfg_wb195(sc); 186 } else { 187 return (0); 188 } 189 190 /* 191 * Propagate up failure from the actual attach phase. 192 */ 193 if (ret != 0) 194 return (ret); 195 196 return (0); 197} 198 199/* 200 * Detach btcoex from the given interface 201 */ 202int 203ath_btcoex_detach(struct ath_softc *sc) 204{ 205 206 return (0); 207} 208 209/* 210 * Configure or disable bluetooth coexistence on the given channel. 211 * 212 * For AR9285/AR9287/AR9485, we'll never see a 5GHz channel, so we just 213 * assume bluetooth coexistence is always on. 214 * 215 * For AR9462, we may see a 5GHz channel; bluetooth coexistence should 216 * not be enabled on those channels. 217 */ 218int 219ath_btcoex_enable(struct ath_softc *sc, const struct ieee80211_channel *chan) 220{ 221 222 return (0); 223} 224 225/* 226 * Handle ioctl requests from the diagnostic interface. 227 * 228 * The initial part of this code resembles ath_ioctl_diag(); 229 * it's likely a good idea to reduce duplication between 230 * these two routines. 231 */ 232int 233ath_btcoex_ioctl(struct ath_softc *sc, struct ath_diag *ad) 234{ 235 unsigned int id = ad->ad_id & ATH_DIAG_ID; 236 void *indata = NULL; 237 void *outdata = NULL; 238 u_int32_t insize = ad->ad_in_size; 239 u_int32_t outsize = ad->ad_out_size; 240 int error = 0; 241// int val; 242 243 if (ad->ad_id & ATH_DIAG_IN) { 244 /* 245 * Copy in data. 246 */ 247 indata = malloc(insize, M_TEMP, M_NOWAIT); 248 if (indata == NULL) { 249 error = ENOMEM; 250 goto bad; 251 } 252 error = copyin(ad->ad_in_data, indata, insize); 253 if (error) 254 goto bad; 255 } 256 if (ad->ad_id & ATH_DIAG_DYN) { 257 /* 258 * Allocate a buffer for the results (otherwise the HAL 259 * returns a pointer to a buffer where we can read the 260 * results). Note that we depend on the HAL leaving this 261 * pointer for us to use below in reclaiming the buffer; 262 * may want to be more defensive. 263 */ 264 outdata = malloc(outsize, M_TEMP, M_NOWAIT); 265 if (outdata == NULL) { 266 error = ENOMEM; 267 goto bad; 268 } 269 } 270 switch (id) { 271 default: 272 error = EINVAL; 273 } 274 if (outsize < ad->ad_out_size) 275 ad->ad_out_size = outsize; 276 if (outdata && copyout(outdata, ad->ad_out_data, ad->ad_out_size)) 277 error = EFAULT; 278bad: 279 if ((ad->ad_id & ATH_DIAG_IN) && indata != NULL) 280 free(indata, M_TEMP); 281 if ((ad->ad_id & ATH_DIAG_DYN) && outdata != NULL) 282 free(outdata, M_TEMP); 283 return (error); 284} 285 286