1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2013 Adrian Chadd <adrian@FreeBSD.org> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer, 12 * without modification. 13 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 14 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 15 * redistribution must be conditioned upon including a substantially 16 * similar Disclaimer requirement for further binary redistribution. 17 * 18 * NO WARRANTY 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 22 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 23 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 24 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 27 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 29 * THE POSSIBILITY OF SUCH DAMAGES. 30 */ 31 #include <sys/cdefs.h> 32 /* 33 * This implements some very basic bluetooth coexistence methods for 34 * the ath(4) hardware. 35 */ 36 #include "opt_ath.h" 37 #include "opt_inet.h" 38 #include "opt_wlan.h" 39 40 #include <sys/param.h> 41 #include <sys/systm.h> 42 #include <sys/sysctl.h> 43 #include <sys/kernel.h> 44 #include <sys/lock.h> 45 #include <sys/malloc.h> 46 #include <sys/mutex.h> 47 #include <sys/errno.h> 48 #include <machine/bus.h> 49 #include <machine/resource.h> 50 51 #include <sys/bus.h> 52 53 #include <sys/socket.h> 54 55 #include <net/if.h> 56 #include <net/if_var.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 #include <dev/ath/if_ath_btcoex_mci.h> 73 74 MALLOC_DECLARE(M_ATHDEV); 75 76 /* 77 * Initial AR9285 / (WB195) bluetooth coexistence settings, 78 * just for experimentation. 79 * 80 * Return 0 for OK; errno for error. 81 * 82 * XXX TODO: There needs to be a PCIe workaround to disable ASPM if 83 * bluetooth coexistence is enabled. 84 */ 85 static int 86 ath_btcoex_cfg_wb195(struct ath_softc *sc) 87 { 88 HAL_BT_COEX_INFO btinfo; 89 HAL_BT_COEX_CONFIG btconfig; 90 struct ath_hal *ah = sc->sc_ah; 91 92 if (! ath_hal_btcoex_supported(ah)) 93 return (EINVAL); 94 95 bzero(&btinfo, sizeof(btinfo)); 96 bzero(&btconfig, sizeof(btconfig)); 97 98 device_printf(sc->sc_dev, "Enabling WB195 BTCOEX\n"); 99 100 btinfo.bt_module = HAL_BT_MODULE_JANUS; 101 btinfo.bt_coex_config = HAL_BT_COEX_CFG_3WIRE; 102 /* 103 * These are the three GPIO pins hooked up between the AR9285 and 104 * the AR3011. 105 */ 106 btinfo.bt_gpio_bt_active = 6; 107 btinfo.bt_gpio_bt_priority = 7; 108 btinfo.bt_gpio_wlan_active = 5; 109 btinfo.bt_active_polarity = 1; /* XXX not used */ 110 btinfo.bt_single_ant = 1; /* 1 antenna on ar9285 ? */ 111 btinfo.bt_isolation = 0; /* in dB, not used */ 112 113 ath_hal_btcoex_set_info(ah, &btinfo); 114 115 btconfig.bt_time_extend = 0; 116 btconfig.bt_txstate_extend = 1; /* true */ 117 btconfig.bt_txframe_extend = 1; /* true */ 118 btconfig.bt_mode = HAL_BT_COEX_MODE_SLOTTED; 119 btconfig.bt_quiet_collision = 1; /* true */ 120 btconfig.bt_rxclear_polarity = 1; /* true */ 121 btconfig.bt_priority_time = 2; 122 btconfig.bt_first_slot_time = 5; 123 btconfig.bt_hold_rxclear = 1; /* true */ 124 125 ath_hal_btcoex_set_config(ah, &btconfig); 126 127 /* 128 * Enable antenna diversity. 129 */ 130 ath_hal_btcoex_set_parameter(ah, HAL_BT_COEX_ANTENNA_DIVERSITY, 1); 131 132 return (0); 133 } 134 135 /* 136 * Initial AR9485 / (WB225) bluetooth coexistence settings, 137 * just for experimentation. 138 * 139 * Return 0 for OK; errno for error. 140 */ 141 static int 142 ath_btcoex_cfg_wb225(struct ath_softc *sc) 143 { 144 HAL_BT_COEX_INFO btinfo; 145 HAL_BT_COEX_CONFIG btconfig; 146 struct ath_hal *ah = sc->sc_ah; 147 148 if (! ath_hal_btcoex_supported(ah)) 149 return (EINVAL); 150 151 bzero(&btinfo, sizeof(btinfo)); 152 bzero(&btconfig, sizeof(btconfig)); 153 154 device_printf(sc->sc_dev, "Enabling WB225 BTCOEX\n"); 155 156 btinfo.bt_module = HAL_BT_MODULE_JANUS; /* XXX not used? */ 157 btinfo.bt_coex_config = HAL_BT_COEX_CFG_3WIRE; 158 /* 159 * These are the three GPIO pins hooked up between the AR9485 and 160 * the bluetooth module. 161 */ 162 btinfo.bt_gpio_bt_active = 4; 163 btinfo.bt_gpio_bt_priority = 8; 164 btinfo.bt_gpio_wlan_active = 5; 165 166 btinfo.bt_active_polarity = 1; /* XXX not used */ 167 btinfo.bt_single_ant = 1; /* 1 antenna on ar9285 ? */ 168 btinfo.bt_isolation = 0; /* in dB, not used */ 169 170 ath_hal_btcoex_set_info(ah, &btinfo); 171 172 btconfig.bt_time_extend = 0; 173 btconfig.bt_txstate_extend = 1; /* true */ 174 btconfig.bt_txframe_extend = 1; /* true */ 175 btconfig.bt_mode = HAL_BT_COEX_MODE_SLOTTED; 176 btconfig.bt_quiet_collision = 1; /* true */ 177 btconfig.bt_rxclear_polarity = 1; /* true */ 178 btconfig.bt_priority_time = 2; 179 btconfig.bt_first_slot_time = 5; 180 btconfig.bt_hold_rxclear = 1; /* true */ 181 182 ath_hal_btcoex_set_config(ah, &btconfig); 183 184 /* 185 * Enable antenna diversity. 186 */ 187 ath_hal_btcoex_set_parameter(ah, HAL_BT_COEX_ANTENNA_DIVERSITY, 1); 188 189 return (0); 190 } 191 192 static int 193 ath_btcoex_cfg_mci(struct ath_softc *sc, uint32_t mci_cfg, int do_btdiv) 194 { 195 HAL_BT_COEX_INFO btinfo; 196 HAL_BT_COEX_CONFIG btconfig; 197 struct ath_hal *ah = sc->sc_ah; 198 199 if (! ath_hal_btcoex_supported(ah)) 200 return (EINVAL); 201 202 bzero(&btinfo, sizeof(btinfo)); 203 bzero(&btconfig, sizeof(btconfig)); 204 205 sc->sc_ah->ah_config.ath_hal_mci_config = mci_cfg; 206 207 if (ath_btcoex_mci_attach(sc) != 0) { 208 device_printf(sc->sc_dev, "Failed to setup btcoex\n"); 209 return (EINVAL); 210 } 211 212 btinfo.bt_module = HAL_BT_MODULE_JANUS; /* XXX not used? */ 213 btinfo.bt_coex_config = HAL_BT_COEX_CFG_MCI; 214 215 /* 216 * MCI uses a completely different interface to speak 217 * to the bluetooth module - it's a command based 218 * thing over a serial line, rather than 219 * state pins to/from the bluetooth module. 220 * 221 * So, the GPIO configuration, polarity, etc 222 * doesn't matter on MCI devices; it's just 223 * completely ignored by the HAL. 224 */ 225 btinfo.bt_gpio_bt_active = 4; 226 btinfo.bt_gpio_bt_priority = 8; 227 btinfo.bt_gpio_wlan_active = 5; 228 229 btinfo.bt_active_polarity = 1; /* XXX not used */ 230 btinfo.bt_single_ant = 0; /* 2 antenna on WB335 */ 231 btinfo.bt_isolation = 0; /* in dB, not used */ 232 233 ath_hal_btcoex_set_info(ah, &btinfo); 234 235 btconfig.bt_time_extend = 0; 236 btconfig.bt_txstate_extend = 1; /* true */ 237 btconfig.bt_txframe_extend = 1; /* true */ 238 btconfig.bt_mode = HAL_BT_COEX_MODE_SLOTTED; 239 btconfig.bt_quiet_collision = 1; /* true */ 240 btconfig.bt_rxclear_polarity = 1; /* true */ 241 btconfig.bt_priority_time = 2; 242 btconfig.bt_first_slot_time = 5; 243 btconfig.bt_hold_rxclear = 1; /* true */ 244 245 ath_hal_btcoex_set_config(ah, &btconfig); 246 247 /* Enable */ 248 ath_hal_btcoex_enable(sc->sc_ah); 249 250 /* Stomp */ 251 ath_hal_btcoex_set_weights(ah, HAL_BT_COEX_STOMP_NONE); 252 253 /* 254 * Enable antenna diversity. 255 */ 256 ath_hal_btcoex_set_parameter(ah, HAL_BT_COEX_ANTENNA_DIVERSITY, 257 do_btdiv); 258 259 return (0); 260 } 261 262 /* 263 * Initial AR9462 / (WB222) bluetooth coexistence settings. 264 * 265 * Return 0 for OK; errno for error. 266 */ 267 static int 268 ath_btcoex_cfg_wb222(struct ath_softc *sc) 269 { 270 271 device_printf(sc->sc_dev, "Enabling WB222 BTCOEX\n"); 272 /* XXX from ath9k */ 273 return (ath_btcoex_cfg_mci(sc, 0x2201, 1)); 274 } 275 276 /* 277 * Initial QCA9565 / (WB335B) bluetooth coexistence settings. 278 * 279 * Return 0 for OK; errno for error. 280 */ 281 static int 282 ath_btcoex_cfg_wb335b(struct ath_softc *sc) 283 { 284 uint32_t flags; 285 int do_btdiv = 0; 286 287 /* ath9k default */ 288 flags = 0xa4c1; 289 290 /* 1-ant and 2-ant AR9565 */ 291 /* 292 * XXX TODO: ensure these actually make it down to the 293 * HAL correctly! 294 */ 295 if (sc->sc_pci_devinfo & ATH_PCI_AR9565_1ANT) { 296 flags &= ~ATH_MCI_CONFIG_ANT_ARCH; 297 flags |= ATH_MCI_ANT_ARCH_1_ANT_PA_LNA_SHARED << 298 ATH_MCI_CONFIG_ANT_ARCH_S; 299 } else if (sc->sc_pci_devinfo & ATH_PCI_AR9565_2ANT) { 300 flags &= ~ATH_MCI_CONFIG_ANT_ARCH; 301 flags |= ATH_MCI_ANT_ARCH_2_ANT_PA_LNA_NON_SHARED << 302 ATH_MCI_CONFIG_ANT_ARCH_S; 303 } 304 305 if (sc->sc_pci_devinfo & ATH_PCI_BT_ANT_DIV) { 306 do_btdiv = 1; 307 } 308 309 device_printf(sc->sc_dev, "Enabling WB335 BTCOEX\n"); 310 /* XXX from ath9k */ 311 return (ath_btcoex_cfg_mci(sc, flags, do_btdiv)); 312 } 313 314 #if 0 315 /* 316 * When using bluetooth coexistence, ASPM needs to be disabled 317 * otherwise the sleeping interferes with the bluetooth (USB) 318 * operation and the MAC sleep/wakeup hardware. 319 * 320 * The PCIe powersave routine also needs to not be called 321 * by the driver during suspend/resume, else things will get 322 * a little odd. Check Linux ath9k for more details. 323 */ 324 static int 325 ath_btcoex_aspm_wb195(struct ath_softc *sc) 326 { 327 328 /* XXX TODO: clear device ASPM L0S and L1 */ 329 /* XXX TODO: clear _parent_ ASPM L0S and L1 */ 330 } 331 #endif 332 333 /* 334 * Methods which are required 335 */ 336 337 /* 338 * Attach btcoex to the given interface 339 */ 340 int 341 ath_btcoex_attach(struct ath_softc *sc) 342 { 343 int ret; 344 struct ath_hal *ah = sc->sc_ah; 345 const char *profname; 346 347 /* 348 * No chipset bluetooth coexistence? Then do nothing. 349 */ 350 if (! ath_hal_btcoex_supported(ah)) 351 return (0); 352 353 /* 354 * Look at the hints to determine which bluetooth 355 * profile to configure. 356 */ 357 ret = resource_string_value(device_get_name(sc->sc_dev), 358 device_get_unit(sc->sc_dev), 359 "btcoex_profile", 360 &profname); 361 if (ret != 0) { 362 /* nothing to do */ 363 return (0); 364 } 365 366 if (strncmp(profname, "wb195", 5) == 0) { 367 ret = ath_btcoex_cfg_wb195(sc); 368 } else if (strncmp(profname, "wb222", 5) == 0) { 369 ret = ath_btcoex_cfg_wb222(sc); 370 } else if (strncmp(profname, "wb225", 5) == 0) { 371 ret = ath_btcoex_cfg_wb225(sc); 372 } else if (strncmp(profname, "wb335", 5) == 0) { 373 ret = ath_btcoex_cfg_wb335b(sc); 374 } else { 375 return (0); 376 } 377 378 /* 379 * Propagate up failure from the actual attach phase. 380 */ 381 if (ret != 0) 382 return (ret); 383 384 return (0); 385 } 386 387 /* 388 * Detach btcoex from the given interface 389 */ 390 int 391 ath_btcoex_detach(struct ath_softc *sc) 392 { 393 if (sc->sc_btcoex_mci) { 394 ath_btcoex_mci_detach(sc); 395 } 396 397 return (0); 398 } 399 400 /* 401 * Configure or disable bluetooth coexistence on the given channel. 402 * 403 * For AR9285/AR9287/AR9485, we'll never see a 5GHz channel, so we just 404 * assume bluetooth coexistence is always on. 405 * 406 * For AR9462, we may see a 5GHz channel; bluetooth coexistence should 407 * not be enabled on those channels. 408 */ 409 int 410 ath_btcoex_enable(struct ath_softc *sc, const struct ieee80211_channel *chan) 411 { 412 if (sc->sc_btcoex_mci) { 413 ath_btcoex_mci_enable(sc, chan); 414 } 415 416 return (0); 417 } 418 419 /* 420 * Handle ioctl requests from the diagnostic interface. 421 * 422 * The initial part of this code resembles ath_ioctl_diag(); 423 * it's likely a good idea to reduce duplication between 424 * these two routines. 425 */ 426 int 427 ath_btcoex_ioctl(struct ath_softc *sc, struct ath_diag *ad) 428 { 429 unsigned int id = ad->ad_id & ATH_DIAG_ID; 430 void *indata = NULL; 431 void *outdata = NULL; 432 u_int32_t insize = ad->ad_in_size; 433 u_int32_t outsize = ad->ad_out_size; 434 int error = 0; 435 // int val; 436 437 if (ad->ad_id & ATH_DIAG_IN) { 438 /* 439 * Copy in data. 440 */ 441 indata = malloc(insize, M_TEMP, M_NOWAIT); 442 if (indata == NULL) { 443 error = ENOMEM; 444 goto bad; 445 } 446 error = copyin(ad->ad_in_data, indata, insize); 447 if (error) 448 goto bad; 449 } 450 if (ad->ad_id & ATH_DIAG_DYN) { 451 /* 452 * Allocate a buffer for the results (otherwise the HAL 453 * returns a pointer to a buffer where we can read the 454 * results). Note that we depend on the HAL leaving this 455 * pointer for us to use below in reclaiming the buffer; 456 * may want to be more defensive. 457 */ 458 outdata = malloc(outsize, M_TEMP, M_NOWAIT | M_ZERO); 459 if (outdata == NULL) { 460 error = ENOMEM; 461 goto bad; 462 } 463 } 464 switch (id) { 465 default: 466 error = EINVAL; 467 goto bad; 468 } 469 if (outsize < ad->ad_out_size) 470 ad->ad_out_size = outsize; 471 if (outdata && copyout(outdata, ad->ad_out_data, ad->ad_out_size)) 472 error = EFAULT; 473 bad: 474 if ((ad->ad_id & ATH_DIAG_IN) && indata != NULL) 475 free(indata, M_TEMP); 476 if ((ad->ad_id & ATH_DIAG_DYN) && outdata != NULL) 477 free(outdata, M_TEMP); 478 return (error); 479 } 480