if_bwfm_pci.c revision 1.72
1/* $OpenBSD: if_bwfm_pci.c,v 1.72 2022/10/23 13:45:32 kettenis Exp $ */ 2/* 3 * Copyright (c) 2010-2016 Broadcom Corporation 4 * Copyright (c) 2017 Patrick Wildt <patrick@blueri.se> 5 * 6 * Permission to use, copy, modify, and/or distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19#include "bpfilter.h" 20 21#include <sys/param.h> 22#include <sys/systm.h> 23#include <sys/buf.h> 24#include <sys/kernel.h> 25#include <sys/malloc.h> 26#include <sys/device.h> 27#include <sys/queue.h> 28#include <sys/socket.h> 29 30#if defined(__HAVE_FDT) 31#include <machine/fdt.h> 32#include <dev/ofw/openfirm.h> 33#endif 34 35#if NBPFILTER > 0 36#include <net/bpf.h> 37#endif 38#include <net/if.h> 39#include <net/if_dl.h> 40#include <net/if_media.h> 41 42#include <netinet/in.h> 43#include <netinet/if_ether.h> 44 45#include <net80211/ieee80211_var.h> 46 47#include <machine/bus.h> 48 49#include <dev/pci/pcireg.h> 50#include <dev/pci/pcivar.h> 51#include <dev/pci/pcidevs.h> 52 53#include <dev/ic/bwfmvar.h> 54#include <dev/ic/bwfmreg.h> 55#include <dev/pci/if_bwfm_pci.h> 56 57#define BWFM_DMA_D2H_SCRATCH_BUF_LEN 8 58#define BWFM_DMA_D2H_RINGUPD_BUF_LEN 1024 59#define BWFM_DMA_H2D_IOCTL_BUF_LEN ETHER_MAX_LEN 60 61#define BWFM_NUM_TX_MSGRINGS 2 62#define BWFM_NUM_RX_MSGRINGS 3 63 64#define BWFM_NUM_IOCTL_PKTIDS 8 65#define BWFM_NUM_TX_PKTIDS 2048 66#define BWFM_NUM_RX_PKTIDS 1024 67 68#define BWFM_NUM_IOCTL_DESCS 1 69#define BWFM_NUM_TX_DESCS 1 70#define BWFM_NUM_RX_DESCS 1 71 72#ifdef BWFM_DEBUG 73#define DPRINTF(x) do { if (bwfm_debug > 0) printf x; } while (0) 74#define DPRINTFN(n, x) do { if (bwfm_debug >= (n)) printf x; } while (0) 75static int bwfm_debug = 2; 76#else 77#define DPRINTF(x) do { ; } while (0) 78#define DPRINTFN(n, x) do { ; } while (0) 79#endif 80 81#define DEVNAME(sc) ((sc)->sc_sc.sc_dev.dv_xname) 82 83enum ring_status { 84 RING_CLOSED, 85 RING_CLOSING, 86 RING_OPEN, 87 RING_OPENING, 88}; 89 90struct bwfm_pci_msgring { 91 uint32_t w_idx_addr; 92 uint32_t r_idx_addr; 93 uint32_t w_ptr; 94 uint32_t r_ptr; 95 int nitem; 96 int itemsz; 97 enum ring_status status; 98 struct bwfm_pci_dmamem *ring; 99 struct mbuf *m; 100 101 int fifo; 102 uint8_t mac[ETHER_ADDR_LEN]; 103}; 104 105struct bwfm_pci_ioctl { 106 uint16_t transid; 107 uint16_t retlen; 108 int16_t status; 109 struct mbuf *m; 110 TAILQ_ENTRY(bwfm_pci_ioctl) next; 111}; 112 113struct bwfm_pci_buf { 114 bus_dmamap_t bb_map; 115 struct mbuf *bb_m; 116}; 117 118struct bwfm_pci_pkts { 119 struct bwfm_pci_buf *pkts; 120 uint32_t npkt; 121 int last; 122}; 123 124struct bwfm_pci_softc { 125 struct bwfm_softc sc_sc; 126 pci_chipset_tag_t sc_pc; 127 pcitag_t sc_tag; 128 pcireg_t sc_id; 129 void *sc_ih; 130 131 int sc_initialized; 132 133 bus_space_tag_t sc_reg_iot; 134 bus_space_handle_t sc_reg_ioh; 135 bus_size_t sc_reg_ios; 136 137 bus_space_tag_t sc_tcm_iot; 138 bus_space_handle_t sc_tcm_ioh; 139 bus_size_t sc_tcm_ios; 140 141 bus_dma_tag_t sc_dmat; 142 143 uint32_t sc_shared_address; 144 uint32_t sc_shared_flags; 145 uint8_t sc_shared_version; 146 147 uint8_t sc_dma_idx_sz; 148 struct bwfm_pci_dmamem *sc_dma_idx_buf; 149 size_t sc_dma_idx_bufsz; 150 151 uint16_t sc_max_rxbufpost; 152 uint32_t sc_rx_dataoffset; 153 uint32_t sc_htod_mb_data_addr; 154 uint32_t sc_dtoh_mb_data_addr; 155 uint32_t sc_ring_info_addr; 156 157 uint32_t sc_console_base_addr; 158 uint32_t sc_console_buf_addr; 159 uint32_t sc_console_buf_size; 160 uint32_t sc_console_readidx; 161 162 uint16_t sc_max_flowrings; 163 uint16_t sc_max_submissionrings; 164 uint16_t sc_max_completionrings; 165 166 struct bwfm_pci_msgring sc_ctrl_submit; 167 struct bwfm_pci_msgring sc_rxpost_submit; 168 struct bwfm_pci_msgring sc_ctrl_complete; 169 struct bwfm_pci_msgring sc_tx_complete; 170 struct bwfm_pci_msgring sc_rx_complete; 171 struct bwfm_pci_msgring *sc_flowrings; 172 173 struct bwfm_pci_dmamem *sc_scratch_buf; 174 struct bwfm_pci_dmamem *sc_ringupd_buf; 175 176 TAILQ_HEAD(, bwfm_pci_ioctl) sc_ioctlq; 177 uint16_t sc_ioctl_transid; 178 179 struct if_rxring sc_ioctl_ring; 180 struct if_rxring sc_event_ring; 181 struct if_rxring sc_rxbuf_ring; 182 183 struct bwfm_pci_pkts sc_ioctl_pkts; 184 struct bwfm_pci_pkts sc_rx_pkts; 185 struct bwfm_pci_pkts sc_tx_pkts; 186 int sc_tx_pkts_full; 187 188 uint8_t sc_mbdata_done; 189 uint8_t sc_pcireg64; 190}; 191 192struct bwfm_pci_dmamem { 193 bus_dmamap_t bdm_map; 194 bus_dma_segment_t bdm_seg; 195 size_t bdm_size; 196 caddr_t bdm_kva; 197}; 198 199#define BWFM_PCI_DMA_MAP(_bdm) ((_bdm)->bdm_map) 200#define BWFM_PCI_DMA_LEN(_bdm) ((_bdm)->bdm_size) 201#define BWFM_PCI_DMA_DVA(_bdm) ((uint64_t)(_bdm)->bdm_map->dm_segs[0].ds_addr) 202#define BWFM_PCI_DMA_KVA(_bdm) ((void *)(_bdm)->bdm_kva) 203 204int bwfm_pci_match(struct device *, void *, void *); 205void bwfm_pci_attach(struct device *, struct device *, void *); 206int bwfm_pci_detach(struct device *, int); 207int bwfm_pci_activate(struct device *, int); 208void bwfm_pci_cleanup(struct bwfm_pci_softc *); 209 210#if defined(__HAVE_FDT) 211int bwfm_pci_read_otp(struct bwfm_pci_softc *); 212void bwfm_pci_process_otp_tuple(struct bwfm_pci_softc *, uint8_t, 213 uint8_t, uint8_t *); 214#endif 215 216int bwfm_pci_intr(void *); 217void bwfm_pci_intr_enable(struct bwfm_pci_softc *); 218void bwfm_pci_intr_disable(struct bwfm_pci_softc *); 219uint32_t bwfm_pci_intr_status(struct bwfm_pci_softc *); 220void bwfm_pci_intr_ack(struct bwfm_pci_softc *, uint32_t); 221uint32_t bwfm_pci_intmask(struct bwfm_pci_softc *); 222void bwfm_pci_hostready(struct bwfm_pci_softc *); 223int bwfm_pci_load_microcode(struct bwfm_pci_softc *, const u_char *, 224 size_t, const u_char *, size_t); 225void bwfm_pci_select_core(struct bwfm_pci_softc *, int ); 226 227struct bwfm_pci_dmamem * 228 bwfm_pci_dmamem_alloc(struct bwfm_pci_softc *, bus_size_t, 229 bus_size_t); 230void bwfm_pci_dmamem_free(struct bwfm_pci_softc *, struct bwfm_pci_dmamem *); 231int bwfm_pci_pktid_avail(struct bwfm_pci_softc *, 232 struct bwfm_pci_pkts *); 233int bwfm_pci_pktid_new(struct bwfm_pci_softc *, 234 struct bwfm_pci_pkts *, struct mbuf *, 235 uint32_t *, paddr_t *); 236struct mbuf * bwfm_pci_pktid_free(struct bwfm_pci_softc *, 237 struct bwfm_pci_pkts *, uint32_t); 238void bwfm_pci_fill_rx_ioctl_ring(struct bwfm_pci_softc *, 239 struct if_rxring *, uint32_t); 240void bwfm_pci_fill_rx_buf_ring(struct bwfm_pci_softc *); 241void bwfm_pci_fill_rx_rings(struct bwfm_pci_softc *); 242int bwfm_pci_setup_ring(struct bwfm_pci_softc *, struct bwfm_pci_msgring *, 243 int, size_t, uint32_t, uint32_t, int, uint32_t, uint32_t *); 244int bwfm_pci_setup_flowring(struct bwfm_pci_softc *, struct bwfm_pci_msgring *, 245 int, size_t); 246 247void bwfm_pci_ring_bell(struct bwfm_pci_softc *, 248 struct bwfm_pci_msgring *); 249void bwfm_pci_ring_update_rptr(struct bwfm_pci_softc *, 250 struct bwfm_pci_msgring *); 251void bwfm_pci_ring_update_wptr(struct bwfm_pci_softc *, 252 struct bwfm_pci_msgring *); 253void bwfm_pci_ring_write_rptr(struct bwfm_pci_softc *, 254 struct bwfm_pci_msgring *); 255void bwfm_pci_ring_write_wptr(struct bwfm_pci_softc *, 256 struct bwfm_pci_msgring *); 257void * bwfm_pci_ring_write_reserve(struct bwfm_pci_softc *, 258 struct bwfm_pci_msgring *); 259void * bwfm_pci_ring_write_reserve_multi(struct bwfm_pci_softc *, 260 struct bwfm_pci_msgring *, int, int *); 261void * bwfm_pci_ring_read_avail(struct bwfm_pci_softc *, 262 struct bwfm_pci_msgring *, int *); 263void bwfm_pci_ring_read_commit(struct bwfm_pci_softc *, 264 struct bwfm_pci_msgring *, int); 265void bwfm_pci_ring_write_commit(struct bwfm_pci_softc *, 266 struct bwfm_pci_msgring *); 267void bwfm_pci_ring_write_cancel(struct bwfm_pci_softc *, 268 struct bwfm_pci_msgring *, int); 269 270void bwfm_pci_ring_rx(struct bwfm_pci_softc *, 271 struct bwfm_pci_msgring *, struct mbuf_list *); 272void bwfm_pci_msg_rx(struct bwfm_pci_softc *, void *, 273 struct mbuf_list *); 274 275uint32_t bwfm_pci_buscore_read(struct bwfm_softc *, uint32_t); 276void bwfm_pci_buscore_write(struct bwfm_softc *, uint32_t, 277 uint32_t); 278int bwfm_pci_buscore_prepare(struct bwfm_softc *); 279int bwfm_pci_buscore_reset(struct bwfm_softc *); 280void bwfm_pci_buscore_activate(struct bwfm_softc *, uint32_t); 281 282int bwfm_pci_flowring_lookup(struct bwfm_pci_softc *, 283 struct mbuf *); 284void bwfm_pci_flowring_create(struct bwfm_pci_softc *, 285 struct mbuf *); 286void bwfm_pci_flowring_create_cb(struct bwfm_softc *, void *); 287void bwfm_pci_flowring_delete(struct bwfm_pci_softc *, int); 288void bwfm_pci_flowring_delete_cb(struct bwfm_softc *, void *); 289 290int bwfm_pci_preinit(struct bwfm_softc *); 291void bwfm_pci_stop(struct bwfm_softc *); 292int bwfm_pci_txcheck(struct bwfm_softc *); 293int bwfm_pci_txdata(struct bwfm_softc *, struct mbuf *); 294 295int bwfm_pci_send_mb_data(struct bwfm_pci_softc *, uint32_t); 296void bwfm_pci_handle_mb_data(struct bwfm_pci_softc *); 297 298#ifdef BWFM_DEBUG 299void bwfm_pci_debug_console(struct bwfm_pci_softc *); 300#endif 301 302int bwfm_pci_msgbuf_query_dcmd(struct bwfm_softc *, int, 303 int, char *, size_t *); 304int bwfm_pci_msgbuf_set_dcmd(struct bwfm_softc *, int, 305 int, char *, size_t); 306void bwfm_pci_msgbuf_rxioctl(struct bwfm_pci_softc *, 307 struct msgbuf_ioctl_resp_hdr *); 308 309struct bwfm_buscore_ops bwfm_pci_buscore_ops = { 310 .bc_read = bwfm_pci_buscore_read, 311 .bc_write = bwfm_pci_buscore_write, 312 .bc_prepare = bwfm_pci_buscore_prepare, 313 .bc_reset = bwfm_pci_buscore_reset, 314 .bc_setup = NULL, 315 .bc_activate = bwfm_pci_buscore_activate, 316}; 317 318struct bwfm_bus_ops bwfm_pci_bus_ops = { 319 .bs_preinit = bwfm_pci_preinit, 320 .bs_stop = bwfm_pci_stop, 321 .bs_txcheck = bwfm_pci_txcheck, 322 .bs_txdata = bwfm_pci_txdata, 323 .bs_txctl = NULL, 324}; 325 326struct bwfm_proto_ops bwfm_pci_msgbuf_ops = { 327 .proto_query_dcmd = bwfm_pci_msgbuf_query_dcmd, 328 .proto_set_dcmd = bwfm_pci_msgbuf_set_dcmd, 329 .proto_rx = NULL, 330 .proto_rxctl = NULL, 331}; 332 333const struct cfattach bwfm_pci_ca = { 334 sizeof(struct bwfm_pci_softc), 335 bwfm_pci_match, 336 bwfm_pci_attach, 337 bwfm_pci_detach, 338 bwfm_pci_activate, 339}; 340 341static const struct pci_matchid bwfm_pci_devices[] = { 342 { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM4350 }, 343 { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM4356 }, 344 { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM43602 }, 345 { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM4371 }, 346 { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM4378 }, 347 { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM4387 }, 348}; 349 350int 351bwfm_pci_match(struct device *parent, void *match, void *aux) 352{ 353 return (pci_matchbyid(aux, bwfm_pci_devices, 354 nitems(bwfm_pci_devices))); 355} 356 357void 358bwfm_pci_attach(struct device *parent, struct device *self, void *aux) 359{ 360 struct bwfm_pci_softc *sc = (struct bwfm_pci_softc *)self; 361 struct pci_attach_args *pa = (struct pci_attach_args *)aux; 362 const char *intrstr; 363 pci_intr_handle_t ih; 364 365 if (pci_mapreg_map(pa, PCI_MAPREG_START + 0x08, 366 PCI_MAPREG_MEM_TYPE_64BIT, 0, &sc->sc_tcm_iot, &sc->sc_tcm_ioh, 367 NULL, &sc->sc_tcm_ios, 0)) { 368 printf(": can't map bar1\n"); 369 return; 370 } 371 372 if (pci_mapreg_map(pa, PCI_MAPREG_START + 0x00, 373 PCI_MAPREG_MEM_TYPE_64BIT, 0, &sc->sc_reg_iot, &sc->sc_reg_ioh, 374 NULL, &sc->sc_reg_ios, 0)) { 375 printf(": can't map bar0\n"); 376 goto bar1; 377 } 378 379 sc->sc_pc = pa->pa_pc; 380 sc->sc_tag = pa->pa_tag; 381 sc->sc_id = pa->pa_id; 382 sc->sc_dmat = pa->pa_dmat; 383 384 /* Map and establish the interrupt. */ 385 if (pci_intr_map_msi(pa, &ih) != 0 && pci_intr_map(pa, &ih) != 0) { 386 printf(": couldn't map interrupt\n"); 387 goto bar0; 388 } 389 intrstr = pci_intr_string(pa->pa_pc, ih); 390 391 sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_NET, 392 bwfm_pci_intr, sc, DEVNAME(sc)); 393 if (sc->sc_ih == NULL) { 394 printf(": couldn't establish interrupt"); 395 if (intrstr != NULL) 396 printf(" at %s", intrstr); 397 printf("\n"); 398 goto bar1; 399 } 400 printf(": %s\n", intrstr); 401 402#if defined(__HAVE_FDT) 403 sc->sc_sc.sc_node = PCITAG_NODE(pa->pa_tag); 404 if (sc->sc_sc.sc_node) { 405 if (OF_getproplen(sc->sc_sc.sc_node, "brcm,cal-blob") > 0) { 406 sc->sc_sc.sc_calsize = OF_getproplen(sc->sc_sc.sc_node, 407 "brcm,cal-blob"); 408 sc->sc_sc.sc_cal = malloc(sc->sc_sc.sc_calsize, 409 M_DEVBUF, M_WAITOK); 410 OF_getprop(sc->sc_sc.sc_node, "brcm,cal-blob", 411 sc->sc_sc.sc_cal, sc->sc_sc.sc_calsize); 412 } 413 } 414#endif 415 416 sc->sc_sc.sc_bus_ops = &bwfm_pci_bus_ops; 417 sc->sc_sc.sc_proto_ops = &bwfm_pci_msgbuf_ops; 418 bwfm_attach(&sc->sc_sc); 419 config_mountroot(self, bwfm_attachhook); 420 return; 421 422bar0: 423 bus_space_unmap(sc->sc_reg_iot, sc->sc_reg_ioh, sc->sc_reg_ios); 424bar1: 425 bus_space_unmap(sc->sc_tcm_iot, sc->sc_tcm_ioh, sc->sc_tcm_ios); 426} 427 428int 429bwfm_pci_preinit(struct bwfm_softc *bwfm) 430{ 431 struct bwfm_pci_softc *sc = (void *)bwfm; 432 struct bwfm_pci_ringinfo ringinfo; 433 const char *chip = NULL; 434 u_char *ucode, *nvram; 435 size_t size, nvsize, nvlen; 436 uint32_t d2h_w_idx_ptr, d2h_r_idx_ptr; 437 uint32_t h2d_w_idx_ptr, h2d_r_idx_ptr; 438 uint32_t idx_offset, reg; 439 int i; 440 441 if (sc->sc_initialized) 442 return 0; 443 444 sc->sc_sc.sc_buscore_ops = &bwfm_pci_buscore_ops; 445 if (bwfm_chip_attach(&sc->sc_sc) != 0) { 446 printf("%s: cannot attach chip\n", DEVNAME(sc)); 447 return 1; 448 } 449 450#if defined(__HAVE_FDT) 451 if (bwfm_pci_read_otp(sc)) { 452 printf("%s: cannot read OTP\n", DEVNAME(sc)); 453 return 1; 454 } 455#endif 456 457 bwfm_pci_select_core(sc, BWFM_AGENT_CORE_PCIE2); 458 bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh, 459 BWFM_PCI_PCIE2REG_CONFIGADDR, 0x4e0); 460 reg = bus_space_read_4(sc->sc_reg_iot, sc->sc_reg_ioh, 461 BWFM_PCI_PCIE2REG_CONFIGDATA); 462 bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh, 463 BWFM_PCI_PCIE2REG_CONFIGDATA, reg); 464 465 switch (bwfm->sc_chip.ch_chip) { 466 case BRCM_CC_4350_CHIP_ID: 467 if (bwfm->sc_chip.ch_chiprev <= 7) 468 chip = "4350c2"; 469 else 470 chip = "4350"; 471 break; 472 case BRCM_CC_4355_CHIP_ID: 473 chip = "4355c1"; 474 break; 475 case BRCM_CC_4356_CHIP_ID: 476 chip = "4356"; 477 break; 478 case BRCM_CC_4364_CHIP_ID: 479 if (bwfm->sc_chip.ch_chiprev <= 3) 480 chip = "4364b2"; 481 else 482 chip = "4364b3"; 483 break; 484 case BRCM_CC_43602_CHIP_ID: 485 chip = "43602"; 486 break; 487 case BRCM_CC_4371_CHIP_ID: 488 chip = "4371"; 489 break; 490 case BRCM_CC_4377_CHIP_ID: 491 chip = "4377b3"; 492 break; 493 case BRCM_CC_4378_CHIP_ID: 494 chip = "4378b1"; 495 break; 496 case BRCM_CC_4387_CHIP_ID: 497 chip = "4387c2"; 498 break; 499 default: 500 printf("%s: unknown firmware for chip %s\n", 501 DEVNAME(sc), bwfm->sc_chip.ch_name); 502 return 1; 503 } 504 505 if (bwfm_loadfirmware(bwfm, chip, "-pcie", &ucode, &size, 506 &nvram, &nvsize, &nvlen) != 0) 507 return 1; 508 509 /* Retrieve RAM size from firmware. */ 510 if (size >= BWFM_RAMSIZE + 8) { 511 uint32_t *ramsize = (uint32_t *)&ucode[BWFM_RAMSIZE]; 512 if (letoh32(ramsize[0]) == BWFM_RAMSIZE_MAGIC) 513 bwfm->sc_chip.ch_ramsize = letoh32(ramsize[1]); 514 } 515 516 if (bwfm_pci_load_microcode(sc, ucode, size, nvram, nvlen) != 0) { 517 printf("%s: could not load microcode\n", 518 DEVNAME(sc)); 519 free(ucode, M_DEVBUF, size); 520 free(nvram, M_DEVBUF, nvsize); 521 return 1; 522 } 523 free(ucode, M_DEVBUF, size); 524 free(nvram, M_DEVBUF, nvsize); 525 526 sc->sc_shared_flags = bus_space_read_4(sc->sc_tcm_iot, sc->sc_tcm_ioh, 527 sc->sc_shared_address + BWFM_SHARED_INFO); 528 sc->sc_shared_version = sc->sc_shared_flags; 529 if (sc->sc_shared_version > BWFM_SHARED_INFO_MAX_VERSION || 530 sc->sc_shared_version < BWFM_SHARED_INFO_MIN_VERSION) { 531 printf("%s: PCIe version %d unsupported\n", 532 DEVNAME(sc), sc->sc_shared_version); 533 return 1; 534 } 535 536 sc->sc_dma_idx_sz = 0; 537 if (sc->sc_shared_flags & BWFM_SHARED_INFO_DMA_INDEX) { 538 if (sc->sc_shared_flags & BWFM_SHARED_INFO_DMA_2B_IDX) 539 sc->sc_dma_idx_sz = sizeof(uint16_t); 540 else 541 sc->sc_dma_idx_sz = sizeof(uint32_t); 542 } 543 544 /* Maximum RX data buffers in the ring. */ 545 sc->sc_max_rxbufpost = bus_space_read_2(sc->sc_tcm_iot, sc->sc_tcm_ioh, 546 sc->sc_shared_address + BWFM_SHARED_MAX_RXBUFPOST); 547 if (sc->sc_max_rxbufpost == 0) 548 sc->sc_max_rxbufpost = BWFM_SHARED_MAX_RXBUFPOST_DEFAULT; 549 550 /* Alternative offset of data in a packet */ 551 sc->sc_rx_dataoffset = bus_space_read_4(sc->sc_tcm_iot, sc->sc_tcm_ioh, 552 sc->sc_shared_address + BWFM_SHARED_RX_DATAOFFSET); 553 554 /* For Power Management */ 555 sc->sc_htod_mb_data_addr = bus_space_read_4(sc->sc_tcm_iot, sc->sc_tcm_ioh, 556 sc->sc_shared_address + BWFM_SHARED_HTOD_MB_DATA_ADDR); 557 sc->sc_dtoh_mb_data_addr = bus_space_read_4(sc->sc_tcm_iot, sc->sc_tcm_ioh, 558 sc->sc_shared_address + BWFM_SHARED_DTOH_MB_DATA_ADDR); 559 560 /* Ring information */ 561 sc->sc_ring_info_addr = bus_space_read_4(sc->sc_tcm_iot, sc->sc_tcm_ioh, 562 sc->sc_shared_address + BWFM_SHARED_RING_INFO_ADDR); 563 564 /* Firmware's "dmesg" */ 565 sc->sc_console_base_addr = bus_space_read_4(sc->sc_tcm_iot, sc->sc_tcm_ioh, 566 sc->sc_shared_address + BWFM_SHARED_CONSOLE_ADDR); 567 sc->sc_console_buf_addr = bus_space_read_4(sc->sc_tcm_iot, sc->sc_tcm_ioh, 568 sc->sc_console_base_addr + BWFM_CONSOLE_BUFADDR); 569 sc->sc_console_buf_size = bus_space_read_4(sc->sc_tcm_iot, sc->sc_tcm_ioh, 570 sc->sc_console_base_addr + BWFM_CONSOLE_BUFSIZE); 571 572 /* Read ring information. */ 573 bus_space_read_region_1(sc->sc_tcm_iot, sc->sc_tcm_ioh, 574 sc->sc_ring_info_addr, (void *)&ringinfo, sizeof(ringinfo)); 575 576 if (sc->sc_shared_version >= 6) { 577 sc->sc_max_submissionrings = le16toh(ringinfo.max_submissionrings); 578 sc->sc_max_flowrings = le16toh(ringinfo.max_flowrings); 579 sc->sc_max_completionrings = le16toh(ringinfo.max_completionrings); 580 } else { 581 sc->sc_max_submissionrings = le16toh(ringinfo.max_flowrings); 582 sc->sc_max_flowrings = sc->sc_max_submissionrings - 583 BWFM_NUM_TX_MSGRINGS; 584 sc->sc_max_completionrings = BWFM_NUM_RX_MSGRINGS; 585 } 586 587 if (sc->sc_dma_idx_sz == 0) { 588 d2h_w_idx_ptr = letoh32(ringinfo.d2h_w_idx_ptr); 589 d2h_r_idx_ptr = letoh32(ringinfo.d2h_r_idx_ptr); 590 h2d_w_idx_ptr = letoh32(ringinfo.h2d_w_idx_ptr); 591 h2d_r_idx_ptr = letoh32(ringinfo.h2d_r_idx_ptr); 592 idx_offset = sizeof(uint32_t); 593 } else { 594 uint64_t address; 595 596 /* Each TX/RX Ring has a Read and Write Ptr */ 597 sc->sc_dma_idx_bufsz = (sc->sc_max_submissionrings + 598 sc->sc_max_completionrings) * sc->sc_dma_idx_sz * 2; 599 sc->sc_dma_idx_buf = bwfm_pci_dmamem_alloc(sc, 600 sc->sc_dma_idx_bufsz, 8); 601 if (sc->sc_dma_idx_buf == NULL) { 602 /* XXX: Fallback to TCM? */ 603 printf("%s: cannot allocate idx buf\n", 604 DEVNAME(sc)); 605 return 1; 606 } 607 608 idx_offset = sc->sc_dma_idx_sz; 609 h2d_w_idx_ptr = 0; 610 address = BWFM_PCI_DMA_DVA(sc->sc_dma_idx_buf); 611 ringinfo.h2d_w_idx_hostaddr_low = 612 htole32(address & 0xffffffff); 613 ringinfo.h2d_w_idx_hostaddr_high = 614 htole32(address >> 32); 615 616 h2d_r_idx_ptr = h2d_w_idx_ptr + 617 sc->sc_max_submissionrings * idx_offset; 618 address += sc->sc_max_submissionrings * idx_offset; 619 ringinfo.h2d_r_idx_hostaddr_low = 620 htole32(address & 0xffffffff); 621 ringinfo.h2d_r_idx_hostaddr_high = 622 htole32(address >> 32); 623 624 d2h_w_idx_ptr = h2d_r_idx_ptr + 625 sc->sc_max_submissionrings * idx_offset; 626 address += sc->sc_max_submissionrings * idx_offset; 627 ringinfo.d2h_w_idx_hostaddr_low = 628 htole32(address & 0xffffffff); 629 ringinfo.d2h_w_idx_hostaddr_high = 630 htole32(address >> 32); 631 632 d2h_r_idx_ptr = d2h_w_idx_ptr + 633 sc->sc_max_completionrings * idx_offset; 634 address += sc->sc_max_completionrings * idx_offset; 635 ringinfo.d2h_r_idx_hostaddr_low = 636 htole32(address & 0xffffffff); 637 ringinfo.d2h_r_idx_hostaddr_high = 638 htole32(address >> 32); 639 640 bus_space_write_region_1(sc->sc_tcm_iot, sc->sc_tcm_ioh, 641 sc->sc_ring_info_addr, (void *)&ringinfo, sizeof(ringinfo)); 642 } 643 644 uint32_t ring_mem_ptr = letoh32(ringinfo.ringmem); 645 /* TX ctrl ring: Send ctrl buffers, send IOCTLs */ 646 if (bwfm_pci_setup_ring(sc, &sc->sc_ctrl_submit, 64, 40, 647 h2d_w_idx_ptr, h2d_r_idx_ptr, 0, idx_offset, 648 &ring_mem_ptr)) 649 goto cleanup; 650 /* TX rxpost ring: Send clean data mbufs for RX */ 651 if (bwfm_pci_setup_ring(sc, &sc->sc_rxpost_submit, 1024, 32, 652 h2d_w_idx_ptr, h2d_r_idx_ptr, 1, idx_offset, 653 &ring_mem_ptr)) 654 goto cleanup; 655 /* RX completion rings: recv our filled buffers back */ 656 if (bwfm_pci_setup_ring(sc, &sc->sc_ctrl_complete, 64, 24, 657 d2h_w_idx_ptr, d2h_r_idx_ptr, 0, idx_offset, 658 &ring_mem_ptr)) 659 goto cleanup; 660 if (bwfm_pci_setup_ring(sc, &sc->sc_tx_complete, 1024, 661 sc->sc_shared_version >= 7 ? 24 : 16, 662 d2h_w_idx_ptr, d2h_r_idx_ptr, 1, idx_offset, 663 &ring_mem_ptr)) 664 goto cleanup; 665 if (bwfm_pci_setup_ring(sc, &sc->sc_rx_complete, 1024, 666 sc->sc_shared_version >= 7 ? 40 : 32, 667 d2h_w_idx_ptr, d2h_r_idx_ptr, 2, idx_offset, 668 &ring_mem_ptr)) 669 goto cleanup; 670 671 /* Dynamic TX rings for actual data */ 672 sc->sc_flowrings = malloc(sc->sc_max_flowrings * 673 sizeof(struct bwfm_pci_msgring), M_DEVBUF, M_WAITOK | M_ZERO); 674 for (i = 0; i < sc->sc_max_flowrings; i++) { 675 struct bwfm_pci_msgring *ring = &sc->sc_flowrings[i]; 676 ring->w_idx_addr = h2d_w_idx_ptr + (i + 2) * idx_offset; 677 ring->r_idx_addr = h2d_r_idx_ptr + (i + 2) * idx_offset; 678 } 679 680 /* Scratch and ring update buffers for firmware */ 681 if ((sc->sc_scratch_buf = bwfm_pci_dmamem_alloc(sc, 682 BWFM_DMA_D2H_SCRATCH_BUF_LEN, 8)) == NULL) 683 goto cleanup; 684 bus_space_write_4(sc->sc_tcm_iot, sc->sc_tcm_ioh, 685 sc->sc_shared_address + BWFM_SHARED_DMA_SCRATCH_ADDR_LOW, 686 BWFM_PCI_DMA_DVA(sc->sc_scratch_buf) & 0xffffffff); 687 bus_space_write_4(sc->sc_tcm_iot, sc->sc_tcm_ioh, 688 sc->sc_shared_address + BWFM_SHARED_DMA_SCRATCH_ADDR_HIGH, 689 BWFM_PCI_DMA_DVA(sc->sc_scratch_buf) >> 32); 690 bus_space_write_4(sc->sc_tcm_iot, sc->sc_tcm_ioh, 691 sc->sc_shared_address + BWFM_SHARED_DMA_SCRATCH_LEN, 692 BWFM_DMA_D2H_SCRATCH_BUF_LEN); 693 694 if ((sc->sc_ringupd_buf = bwfm_pci_dmamem_alloc(sc, 695 BWFM_DMA_D2H_RINGUPD_BUF_LEN, 8)) == NULL) 696 goto cleanup; 697 bus_space_write_4(sc->sc_tcm_iot, sc->sc_tcm_ioh, 698 sc->sc_shared_address + BWFM_SHARED_DMA_RINGUPD_ADDR_LOW, 699 BWFM_PCI_DMA_DVA(sc->sc_ringupd_buf) & 0xffffffff); 700 bus_space_write_4(sc->sc_tcm_iot, sc->sc_tcm_ioh, 701 sc->sc_shared_address + BWFM_SHARED_DMA_RINGUPD_ADDR_HIGH, 702 BWFM_PCI_DMA_DVA(sc->sc_ringupd_buf) >> 32); 703 bus_space_write_4(sc->sc_tcm_iot, sc->sc_tcm_ioh, 704 sc->sc_shared_address + BWFM_SHARED_DMA_RINGUPD_LEN, 705 BWFM_DMA_D2H_RINGUPD_BUF_LEN); 706 707 bwfm_pci_select_core(sc, BWFM_AGENT_CORE_PCIE2); 708 bwfm_pci_intr_enable(sc); 709 bwfm_pci_hostready(sc); 710 711 /* Maps RX mbufs to a packet id and back. */ 712 sc->sc_rx_pkts.npkt = BWFM_NUM_RX_PKTIDS; 713 sc->sc_rx_pkts.pkts = malloc(BWFM_NUM_RX_PKTIDS * 714 sizeof(struct bwfm_pci_buf), M_DEVBUF, M_WAITOK | M_ZERO); 715 for (i = 0; i < BWFM_NUM_RX_PKTIDS; i++) 716 bus_dmamap_create(sc->sc_dmat, MSGBUF_MAX_CTL_PKT_SIZE, 717 BWFM_NUM_RX_DESCS, MSGBUF_MAX_CTL_PKT_SIZE, 0, BUS_DMA_WAITOK, 718 &sc->sc_rx_pkts.pkts[i].bb_map); 719 720 /* Maps TX mbufs to a packet id and back. */ 721 sc->sc_tx_pkts.npkt = BWFM_NUM_TX_PKTIDS; 722 sc->sc_tx_pkts.pkts = malloc(BWFM_NUM_TX_PKTIDS 723 * sizeof(struct bwfm_pci_buf), M_DEVBUF, M_WAITOK | M_ZERO); 724 for (i = 0; i < BWFM_NUM_TX_PKTIDS; i++) 725 bus_dmamap_create(sc->sc_dmat, MSGBUF_MAX_PKT_SIZE, 726 BWFM_NUM_TX_DESCS, MSGBUF_MAX_PKT_SIZE, 0, BUS_DMA_WAITOK, 727 &sc->sc_tx_pkts.pkts[i].bb_map); 728 sc->sc_tx_pkts_full = 0; 729 730 /* Maps IOCTL mbufs to a packet id and back. */ 731 sc->sc_ioctl_pkts.npkt = BWFM_NUM_IOCTL_PKTIDS; 732 sc->sc_ioctl_pkts.pkts = malloc(BWFM_NUM_IOCTL_PKTIDS 733 * sizeof(struct bwfm_pci_buf), M_DEVBUF, M_WAITOK | M_ZERO); 734 for (i = 0; i < BWFM_NUM_IOCTL_PKTIDS; i++) 735 bus_dmamap_create(sc->sc_dmat, MSGBUF_MAX_PKT_SIZE, 736 BWFM_NUM_IOCTL_DESCS, MSGBUF_MAX_PKT_SIZE, 0, BUS_DMA_WAITOK, 737 &sc->sc_ioctl_pkts.pkts[i].bb_map); 738 739 /* 740 * For whatever reason, could also be a bug somewhere in this 741 * driver, the firmware needs a bunch of RX buffers otherwise 742 * it won't send any RX complete messages. 743 */ 744 if_rxr_init(&sc->sc_rxbuf_ring, min(256, sc->sc_max_rxbufpost), 745 sc->sc_max_rxbufpost); 746 if_rxr_init(&sc->sc_ioctl_ring, 8, 8); 747 if_rxr_init(&sc->sc_event_ring, 8, 8); 748 bwfm_pci_fill_rx_rings(sc); 749 750 TAILQ_INIT(&sc->sc_ioctlq); 751 752#ifdef BWFM_DEBUG 753 sc->sc_console_readidx = 0; 754 bwfm_pci_debug_console(sc); 755#endif 756 757 sc->sc_initialized = 1; 758 return 0; 759 760cleanup: 761 if (sc->sc_ringupd_buf) 762 bwfm_pci_dmamem_free(sc, sc->sc_ringupd_buf); 763 if (sc->sc_scratch_buf) 764 bwfm_pci_dmamem_free(sc, sc->sc_scratch_buf); 765 if (sc->sc_rx_complete.ring) 766 bwfm_pci_dmamem_free(sc, sc->sc_rx_complete.ring); 767 if (sc->sc_tx_complete.ring) 768 bwfm_pci_dmamem_free(sc, sc->sc_tx_complete.ring); 769 if (sc->sc_ctrl_complete.ring) 770 bwfm_pci_dmamem_free(sc, sc->sc_ctrl_complete.ring); 771 if (sc->sc_rxpost_submit.ring) 772 bwfm_pci_dmamem_free(sc, sc->sc_rxpost_submit.ring); 773 if (sc->sc_ctrl_submit.ring) 774 bwfm_pci_dmamem_free(sc, sc->sc_ctrl_submit.ring); 775 if (sc->sc_dma_idx_buf) 776 bwfm_pci_dmamem_free(sc, sc->sc_dma_idx_buf); 777 return 1; 778} 779 780int 781bwfm_pci_load_microcode(struct bwfm_pci_softc *sc, const u_char *ucode, size_t size, 782 const u_char *nvram, size_t nvlen) 783{ 784 struct bwfm_softc *bwfm = (void *)sc; 785 struct bwfm_core *core; 786 struct bwfm_pci_random_seed_footer footer; 787 uint32_t addr, shared, written; 788 uint8_t *rndbuf; 789 int i; 790 791 if (bwfm->sc_chip.ch_chip == BRCM_CC_43602_CHIP_ID) { 792 bwfm_pci_select_core(sc, BWFM_AGENT_CORE_ARM_CR4); 793 bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh, 794 BWFM_PCI_ARMCR4REG_BANKIDX, 5); 795 bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh, 796 BWFM_PCI_ARMCR4REG_BANKPDA, 0); 797 bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh, 798 BWFM_PCI_ARMCR4REG_BANKIDX, 7); 799 bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh, 800 BWFM_PCI_ARMCR4REG_BANKPDA, 0); 801 } 802 803 for (i = 0; i < size; i++) 804 bus_space_write_1(sc->sc_tcm_iot, sc->sc_tcm_ioh, 805 bwfm->sc_chip.ch_rambase + i, ucode[i]); 806 807 /* Firmware replaces this with a pointer once up. */ 808 bus_space_write_4(sc->sc_tcm_iot, sc->sc_tcm_ioh, 809 bwfm->sc_chip.ch_rambase + bwfm->sc_chip.ch_ramsize - 4, 0); 810 811 if (nvram) { 812 addr = bwfm->sc_chip.ch_rambase + bwfm->sc_chip.ch_ramsize - 813 nvlen; 814 for (i = 0; i < nvlen; i++) 815 bus_space_write_1(sc->sc_tcm_iot, sc->sc_tcm_ioh, 816 addr + i, nvram[i]); 817 818 footer.length = htole32(BWFM_RANDOM_SEED_LENGTH); 819 footer.magic = htole32(BWFM_RANDOM_SEED_MAGIC); 820 addr -= sizeof(footer); 821 for (i = 0; i < sizeof(footer); i++) 822 bus_space_write_1(sc->sc_tcm_iot, sc->sc_tcm_ioh, 823 addr + i, ((uint8_t *)&footer)[i]); 824 825 rndbuf = malloc(BWFM_RANDOM_SEED_LENGTH, M_TEMP, M_WAITOK); 826 arc4random_buf(rndbuf, BWFM_RANDOM_SEED_LENGTH); 827 addr -= BWFM_RANDOM_SEED_LENGTH; 828 for (i = 0; i < BWFM_RANDOM_SEED_LENGTH; i++) 829 bus_space_write_1(sc->sc_tcm_iot, sc->sc_tcm_ioh, 830 addr + i, rndbuf[i]); 831 free(rndbuf, M_TEMP, BWFM_RANDOM_SEED_LENGTH); 832 } 833 834 written = bus_space_read_4(sc->sc_tcm_iot, sc->sc_tcm_ioh, 835 bwfm->sc_chip.ch_rambase + bwfm->sc_chip.ch_ramsize - 4); 836 837 /* Load reset vector from firmware and kickstart core. */ 838 if (bwfm->sc_chip.ch_chip == BRCM_CC_43602_CHIP_ID) { 839 core = bwfm_chip_get_core(bwfm, BWFM_AGENT_INTERNAL_MEM); 840 bwfm->sc_chip.ch_core_reset(bwfm, core, 0, 0, 0); 841 } 842 bwfm_chip_set_active(bwfm, *(uint32_t *)ucode); 843 844 for (i = 0; i < 100; i++) { 845 delay(50 * 1000); 846 shared = bus_space_read_4(sc->sc_tcm_iot, sc->sc_tcm_ioh, 847 bwfm->sc_chip.ch_rambase + bwfm->sc_chip.ch_ramsize - 4); 848 if (shared != written) 849 break; 850 } 851 if (shared == written) { 852 printf("%s: firmware did not come up\n", DEVNAME(sc)); 853 return 1; 854 } 855 if (shared < bwfm->sc_chip.ch_rambase || 856 shared >= bwfm->sc_chip.ch_rambase + bwfm->sc_chip.ch_ramsize) { 857 printf("%s: invalid shared RAM address 0x%08x\n", DEVNAME(sc), 858 shared); 859 return 1; 860 } 861 862 sc->sc_shared_address = shared; 863 return 0; 864} 865 866int 867bwfm_pci_detach(struct device *self, int flags) 868{ 869 struct bwfm_pci_softc *sc = (struct bwfm_pci_softc *)self; 870 871 bwfm_detach(&sc->sc_sc, flags); 872 bwfm_pci_cleanup(sc); 873 874 return 0; 875} 876 877void 878bwfm_pci_cleanup(struct bwfm_pci_softc *sc) 879{ 880 int i; 881 882 for (i = 0; i < BWFM_NUM_RX_PKTIDS; i++) { 883 bus_dmamap_destroy(sc->sc_dmat, sc->sc_rx_pkts.pkts[i].bb_map); 884 if (sc->sc_rx_pkts.pkts[i].bb_m) 885 m_freem(sc->sc_rx_pkts.pkts[i].bb_m); 886 } 887 free(sc->sc_rx_pkts.pkts, M_DEVBUF, BWFM_NUM_RX_PKTIDS * 888 sizeof(struct bwfm_pci_buf)); 889 890 for (i = 0; i < BWFM_NUM_TX_PKTIDS; i++) { 891 bus_dmamap_destroy(sc->sc_dmat, sc->sc_tx_pkts.pkts[i].bb_map); 892 if (sc->sc_tx_pkts.pkts[i].bb_m) 893 m_freem(sc->sc_tx_pkts.pkts[i].bb_m); 894 } 895 free(sc->sc_tx_pkts.pkts, M_DEVBUF, BWFM_NUM_TX_PKTIDS * 896 sizeof(struct bwfm_pci_buf)); 897 898 for (i = 0; i < BWFM_NUM_IOCTL_PKTIDS; i++) { 899 bus_dmamap_destroy(sc->sc_dmat, sc->sc_ioctl_pkts.pkts[i].bb_map); 900 if (sc->sc_ioctl_pkts.pkts[i].bb_m) 901 m_freem(sc->sc_ioctl_pkts.pkts[i].bb_m); 902 } 903 free(sc->sc_ioctl_pkts.pkts, M_DEVBUF, BWFM_NUM_IOCTL_PKTIDS * 904 sizeof(struct bwfm_pci_buf)); 905 906 for (i = 0; i < sc->sc_max_flowrings; i++) { 907 if (sc->sc_flowrings[i].status >= RING_OPEN) 908 bwfm_pci_dmamem_free(sc, sc->sc_flowrings[i].ring); 909 } 910 free(sc->sc_flowrings, M_DEVBUF, sc->sc_max_flowrings * 911 sizeof(struct bwfm_pci_msgring)); 912 913 bwfm_pci_dmamem_free(sc, sc->sc_ringupd_buf); 914 bwfm_pci_dmamem_free(sc, sc->sc_scratch_buf); 915 bwfm_pci_dmamem_free(sc, sc->sc_rx_complete.ring); 916 bwfm_pci_dmamem_free(sc, sc->sc_tx_complete.ring); 917 bwfm_pci_dmamem_free(sc, sc->sc_ctrl_complete.ring); 918 bwfm_pci_dmamem_free(sc, sc->sc_rxpost_submit.ring); 919 bwfm_pci_dmamem_free(sc, sc->sc_ctrl_submit.ring); 920 if (sc->sc_dma_idx_buf) { 921 bwfm_pci_dmamem_free(sc, sc->sc_dma_idx_buf); 922 sc->sc_dma_idx_buf = NULL; 923 } 924 925 sc->sc_initialized = 0; 926} 927 928int 929bwfm_pci_activate(struct device *self, int act) 930{ 931 struct bwfm_pci_softc *sc = (struct bwfm_pci_softc *)self; 932 struct bwfm_softc *bwfm = (void *)sc; 933 int error = 0; 934 935 switch (act) { 936 case DVACT_QUIESCE: 937 error = bwfm_activate(bwfm, act); 938 if (error) 939 return error; 940 if (sc->sc_initialized) { 941 sc->sc_mbdata_done = 0; 942 error = bwfm_pci_send_mb_data(sc, 943 BWFM_PCI_H2D_HOST_D3_INFORM); 944 if (error) 945 return error; 946 tsleep_nsec(&sc->sc_mbdata_done, PCATCH, 947 DEVNAME(sc), SEC_TO_NSEC(2)); 948 if (!sc->sc_mbdata_done) 949 return ETIMEDOUT; 950 } 951 break; 952 case DVACT_WAKEUP: 953 if (sc->sc_initialized) { 954 /* If device can't be resumed, re-init. */ 955 if (bwfm_pci_intmask(sc) == 0 || 956 bwfm_pci_send_mb_data(sc, 957 BWFM_PCI_H2D_HOST_D0_INFORM) != 0) { 958 bwfm_cleanup(bwfm); 959 bwfm_pci_cleanup(sc); 960 } 961 } 962 error = bwfm_activate(bwfm, act); 963 if (error) 964 return error; 965 break; 966 default: 967 break; 968 } 969 970 return 0; 971} 972 973#if defined(__HAVE_FDT) 974int 975bwfm_pci_read_otp(struct bwfm_pci_softc *sc) 976{ 977 struct bwfm_softc *bwfm = (void *)sc; 978 struct bwfm_core *core; 979 uint32_t coreid, base, words; 980 uint32_t page, offset, sromctl; 981 uint8_t *otp; 982 int i; 983 984 switch (bwfm->sc_chip.ch_chip) { 985 case BRCM_CC_4355_CHIP_ID: 986 coreid = BWFM_AGENT_CORE_CHIPCOMMON; 987 base = 0x8c0; 988 words = 0xb2; 989 break; 990 case BRCM_CC_4364_CHIP_ID: 991 coreid = BWFM_AGENT_CORE_CHIPCOMMON; 992 base = 0x8c0; 993 words = 0x1a0; 994 break; 995 case BRCM_CC_4377_CHIP_ID: 996 case BRCM_CC_4378_CHIP_ID: 997 coreid = BWFM_AGENT_CORE_GCI; 998 base = 0x1120; 999 words = 0x170; 1000 break; 1001 case BRCM_CC_4387_CHIP_ID: 1002 coreid = BWFM_AGENT_CORE_GCI; 1003 base = 0x113c; 1004 words = 0x170; 1005 break; 1006 default: 1007 return 0; 1008 } 1009 1010 core = bwfm_chip_get_core(bwfm, coreid); 1011 if (core == NULL) 1012 return 1; 1013 1014 /* Map OTP to shadow area */ 1015 if (coreid == BWFM_AGENT_CORE_CHIPCOMMON) { 1016 bwfm_pci_select_core(sc, coreid); 1017 sromctl = bus_space_read_4(sc->sc_reg_iot, sc->sc_reg_ioh, 1018 BWFM_CHIP_REG_SROMCONTROL); 1019 1020 if (!(sromctl & BWFM_CHIP_REG_SROMCONTROL_OTP_PRESENT)) 1021 return 0; 1022 1023 bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh, 1024 BWFM_CHIP_REG_SROMCONTROL, sromctl | 1025 BWFM_CHIP_REG_SROMCONTROL_OTPSEL); 1026 } 1027 1028 /* Map bus window to SROM/OTP shadow area */ 1029 page = (core->co_base + base) & ~(BWFM_PCI_BAR0_REG_SIZE - 1); 1030 offset = (core->co_base + base) & (BWFM_PCI_BAR0_REG_SIZE - 1); 1031 pci_conf_write(sc->sc_pc, sc->sc_tag, BWFM_PCI_BAR0_WINDOW, page); 1032 1033 otp = mallocarray(words, sizeof(uint16_t), M_TEMP, M_WAITOK); 1034 for (i = 0; i < words; i++) 1035 ((uint16_t *)otp)[i] = bus_space_read_2(sc->sc_reg_iot, 1036 sc->sc_reg_ioh, offset + i * sizeof(uint16_t)); 1037 1038 /* Unmap OTP */ 1039 if (coreid == BWFM_AGENT_CORE_CHIPCOMMON) { 1040 bwfm_pci_select_core(sc, coreid); 1041 bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh, 1042 BWFM_CHIP_REG_SROMCONTROL, sromctl); 1043 } 1044 1045 for (i = 0; i < (words * sizeof(uint16_t)) - 1; i += otp[i + 1]) { 1046 if (otp[i + 0] == 0) 1047 break; 1048 if (i + otp[i + 1] > words * sizeof(uint16_t)) 1049 break; 1050 bwfm_pci_process_otp_tuple(sc, otp[i + 0], otp[i + 1], 1051 &otp[i + 2]); 1052 } 1053 1054 free(otp, M_TEMP, words * sizeof(uint16_t)); 1055 return 0; 1056} 1057 1058void 1059bwfm_pci_process_otp_tuple(struct bwfm_pci_softc *sc, uint8_t type, uint8_t size, 1060 uint8_t *data) 1061{ 1062 struct bwfm_softc *bwfm = (void *)sc; 1063 char chiprev[8] = "", module[8] = "", modrev[8] = "", vendor[8] = "", chip[8] = ""; 1064 char board_type[128] = ""; 1065 int len; 1066 1067 switch (type) { 1068 case 0x15: /* system vendor OTP */ 1069 DPRINTF(("%s: system vendor OTP\n", DEVNAME(sc))); 1070 if (size < sizeof(uint32_t)) 1071 return; 1072 if (data[0] != 0x08 || data[1] != 0x00 || 1073 data[2] != 0x00 || data[3] != 0x00) 1074 return; 1075 size -= sizeof(uint32_t); 1076 data += sizeof(uint32_t); 1077 while (size) { 1078 /* reached end */ 1079 if (data[0] == 0xff) 1080 break; 1081 for (len = 0; len < size; len++) 1082 if (data[len] == 0x00 || data[len] == ' ' || 1083 data[len] == 0xff) 1084 break; 1085 if (len < 3 || len > 9) /* X=abcdef */ 1086 goto next; 1087 if (data[1] != '=') 1088 goto next; 1089 /* NULL-terminate string */ 1090 if (data[len] == ' ') 1091 data[len] = '\0'; 1092 switch (data[0]) { 1093 case 's': 1094 strlcpy(chiprev, &data[2], sizeof(chiprev)); 1095 break; 1096 case 'M': 1097 strlcpy(module, &data[2], sizeof(module)); 1098 break; 1099 case 'm': 1100 strlcpy(modrev, &data[2], sizeof(modrev)); 1101 break; 1102 case 'V': 1103 strlcpy(vendor, &data[2], sizeof(vendor)); 1104 break; 1105 } 1106next: 1107 /* skip content */ 1108 data += len; 1109 size -= len; 1110 /* skip spacer tag */ 1111 if (size) { 1112 data++; 1113 size--; 1114 } 1115 } 1116 snprintf(chip, sizeof(chip), 1117 bwfm->sc_chip.ch_chip > 40000 ? "%05d" : "%04x", 1118 bwfm->sc_chip.ch_chip); 1119 if (sc->sc_sc.sc_node) { 1120 OF_getprop(sc->sc_sc.sc_node, "brcm,board-type", 1121 board_type, sizeof(board_type)); 1122 if (strncmp(board_type, "apple,", 6) == 0) { 1123 strlcpy(sc->sc_sc.sc_fwdir, "apple-bwfm/", 1124 sizeof(sc->sc_sc.sc_fwdir)); 1125 } 1126 } 1127 strlcpy(sc->sc_sc.sc_board_type, board_type, 1128 sizeof(sc->sc_sc.sc_board_type)); 1129 strlcpy(sc->sc_sc.sc_module, module, 1130 sizeof(sc->sc_sc.sc_module)); 1131 strlcpy(sc->sc_sc.sc_vendor, vendor, 1132 sizeof(sc->sc_sc.sc_vendor)); 1133 strlcpy(sc->sc_sc.sc_modrev, modrev, 1134 sizeof(sc->sc_sc.sc_modrev)); 1135 break; 1136 case 0x80: /* Broadcom CIS */ 1137 DPRINTF(("%s: Broadcom CIS\n", DEVNAME(sc))); 1138 break; 1139 default: 1140 DPRINTF(("%s: unknown OTP tuple\n", DEVNAME(sc))); 1141 break; 1142 } 1143} 1144#endif 1145 1146/* DMA code */ 1147struct bwfm_pci_dmamem * 1148bwfm_pci_dmamem_alloc(struct bwfm_pci_softc *sc, bus_size_t size, bus_size_t align) 1149{ 1150 struct bwfm_pci_dmamem *bdm; 1151 int nsegs; 1152 1153 bdm = malloc(sizeof(*bdm), M_DEVBUF, M_WAITOK | M_ZERO); 1154 bdm->bdm_size = size; 1155 1156 if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0, 1157 BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW, &bdm->bdm_map) != 0) 1158 goto bdmfree; 1159 1160 if (bus_dmamem_alloc(sc->sc_dmat, size, align, 0, &bdm->bdm_seg, 1, 1161 &nsegs, BUS_DMA_WAITOK) != 0) 1162 goto destroy; 1163 1164 if (bus_dmamem_map(sc->sc_dmat, &bdm->bdm_seg, nsegs, size, 1165 &bdm->bdm_kva, BUS_DMA_WAITOK | BUS_DMA_COHERENT) != 0) 1166 goto free; 1167 1168 if (bus_dmamap_load(sc->sc_dmat, bdm->bdm_map, bdm->bdm_kva, size, 1169 NULL, BUS_DMA_WAITOK) != 0) 1170 goto unmap; 1171 1172 bzero(bdm->bdm_kva, size); 1173 1174 return (bdm); 1175 1176unmap: 1177 bus_dmamem_unmap(sc->sc_dmat, bdm->bdm_kva, size); 1178free: 1179 bus_dmamem_free(sc->sc_dmat, &bdm->bdm_seg, 1); 1180destroy: 1181 bus_dmamap_destroy(sc->sc_dmat, bdm->bdm_map); 1182bdmfree: 1183 free(bdm, M_DEVBUF, sizeof(*bdm)); 1184 1185 return (NULL); 1186} 1187 1188void 1189bwfm_pci_dmamem_free(struct bwfm_pci_softc *sc, struct bwfm_pci_dmamem *bdm) 1190{ 1191 bus_dmamem_unmap(sc->sc_dmat, bdm->bdm_kva, bdm->bdm_size); 1192 bus_dmamem_free(sc->sc_dmat, &bdm->bdm_seg, 1); 1193 bus_dmamap_destroy(sc->sc_dmat, bdm->bdm_map); 1194 free(bdm, M_DEVBUF, sizeof(*bdm)); 1195} 1196 1197/* 1198 * We need a simple mapping from a packet ID to mbufs, because when 1199 * a transfer completed, we only know the ID so we have to look up 1200 * the memory for the ID. This simply looks for an empty slot. 1201 */ 1202int 1203bwfm_pci_pktid_avail(struct bwfm_pci_softc *sc, struct bwfm_pci_pkts *pkts) 1204{ 1205 int i, idx; 1206 1207 idx = pkts->last + 1; 1208 for (i = 0; i < pkts->npkt; i++) { 1209 if (idx == pkts->npkt) 1210 idx = 0; 1211 if (pkts->pkts[idx].bb_m == NULL) 1212 return 0; 1213 idx++; 1214 } 1215 return ENOBUFS; 1216} 1217 1218int 1219bwfm_pci_pktid_new(struct bwfm_pci_softc *sc, struct bwfm_pci_pkts *pkts, 1220 struct mbuf *m, uint32_t *pktid, paddr_t *paddr) 1221{ 1222 int i, idx; 1223 1224 idx = pkts->last + 1; 1225 for (i = 0; i < pkts->npkt; i++) { 1226 if (idx == pkts->npkt) 1227 idx = 0; 1228 if (pkts->pkts[idx].bb_m == NULL) { 1229 if (bus_dmamap_load_mbuf(sc->sc_dmat, 1230 pkts->pkts[idx].bb_map, m, BUS_DMA_NOWAIT) != 0) { 1231 if (m_defrag(m, M_DONTWAIT)) 1232 return EFBIG; 1233 if (bus_dmamap_load_mbuf(sc->sc_dmat, 1234 pkts->pkts[idx].bb_map, m, BUS_DMA_NOWAIT) != 0) 1235 return EFBIG; 1236 } 1237 bus_dmamap_sync(sc->sc_dmat, pkts->pkts[idx].bb_map, 1238 0, pkts->pkts[idx].bb_map->dm_mapsize, 1239 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1240 pkts->last = idx; 1241 pkts->pkts[idx].bb_m = m; 1242 *pktid = idx; 1243 *paddr = pkts->pkts[idx].bb_map->dm_segs[0].ds_addr; 1244 return 0; 1245 } 1246 idx++; 1247 } 1248 return ENOBUFS; 1249} 1250 1251struct mbuf * 1252bwfm_pci_pktid_free(struct bwfm_pci_softc *sc, struct bwfm_pci_pkts *pkts, 1253 uint32_t pktid) 1254{ 1255 struct mbuf *m; 1256 1257 if (pktid >= pkts->npkt || pkts->pkts[pktid].bb_m == NULL) 1258 return NULL; 1259 bus_dmamap_sync(sc->sc_dmat, pkts->pkts[pktid].bb_map, 0, 1260 pkts->pkts[pktid].bb_map->dm_mapsize, 1261 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 1262 bus_dmamap_unload(sc->sc_dmat, pkts->pkts[pktid].bb_map); 1263 m = pkts->pkts[pktid].bb_m; 1264 pkts->pkts[pktid].bb_m = NULL; 1265 return m; 1266} 1267 1268void 1269bwfm_pci_fill_rx_rings(struct bwfm_pci_softc *sc) 1270{ 1271 bwfm_pci_fill_rx_buf_ring(sc); 1272 bwfm_pci_fill_rx_ioctl_ring(sc, &sc->sc_ioctl_ring, 1273 MSGBUF_TYPE_IOCTLRESP_BUF_POST); 1274 bwfm_pci_fill_rx_ioctl_ring(sc, &sc->sc_event_ring, 1275 MSGBUF_TYPE_EVENT_BUF_POST); 1276} 1277 1278void 1279bwfm_pci_fill_rx_ioctl_ring(struct bwfm_pci_softc *sc, struct if_rxring *rxring, 1280 uint32_t msgtype) 1281{ 1282 struct msgbuf_rx_ioctl_resp_or_event *req; 1283 struct mbuf *m; 1284 uint32_t pktid; 1285 paddr_t paddr; 1286 int s, slots; 1287 1288 s = splnet(); 1289 for (slots = if_rxr_get(rxring, 8); slots > 0; slots--) { 1290 if (bwfm_pci_pktid_avail(sc, &sc->sc_rx_pkts)) 1291 break; 1292 req = bwfm_pci_ring_write_reserve(sc, &sc->sc_ctrl_submit); 1293 if (req == NULL) 1294 break; 1295 m = MCLGETL(NULL, M_DONTWAIT, MSGBUF_MAX_CTL_PKT_SIZE); 1296 if (m == NULL) { 1297 bwfm_pci_ring_write_cancel(sc, &sc->sc_ctrl_submit, 1); 1298 break; 1299 } 1300 m->m_len = m->m_pkthdr.len = MSGBUF_MAX_CTL_PKT_SIZE; 1301 if (bwfm_pci_pktid_new(sc, &sc->sc_rx_pkts, m, &pktid, &paddr)) { 1302 bwfm_pci_ring_write_cancel(sc, &sc->sc_ctrl_submit, 1); 1303 m_freem(m); 1304 break; 1305 } 1306 memset(req, 0, sizeof(*req)); 1307 req->msg.msgtype = msgtype; 1308 req->msg.request_id = htole32(pktid); 1309 req->host_buf_len = htole16(MSGBUF_MAX_CTL_PKT_SIZE); 1310 req->host_buf_addr.high_addr = htole32((uint64_t)paddr >> 32); 1311 req->host_buf_addr.low_addr = htole32(paddr & 0xffffffff); 1312 bwfm_pci_ring_write_commit(sc, &sc->sc_ctrl_submit); 1313 } 1314 if_rxr_put(rxring, slots); 1315 splx(s); 1316} 1317 1318void 1319bwfm_pci_fill_rx_buf_ring(struct bwfm_pci_softc *sc) 1320{ 1321 struct msgbuf_rx_bufpost *req; 1322 struct mbuf *m; 1323 uint32_t pktid; 1324 paddr_t paddr; 1325 int s, slots; 1326 1327 s = splnet(); 1328 for (slots = if_rxr_get(&sc->sc_rxbuf_ring, sc->sc_max_rxbufpost); 1329 slots > 0; slots--) { 1330 if (bwfm_pci_pktid_avail(sc, &sc->sc_rx_pkts)) 1331 break; 1332 req = bwfm_pci_ring_write_reserve(sc, &sc->sc_rxpost_submit); 1333 if (req == NULL) 1334 break; 1335 m = MCLGETL(NULL, M_DONTWAIT, MSGBUF_MAX_PKT_SIZE); 1336 if (m == NULL) { 1337 bwfm_pci_ring_write_cancel(sc, &sc->sc_rxpost_submit, 1); 1338 break; 1339 } 1340 m->m_len = m->m_pkthdr.len = MSGBUF_MAX_PKT_SIZE; 1341 if (bwfm_pci_pktid_new(sc, &sc->sc_rx_pkts, m, &pktid, &paddr)) { 1342 bwfm_pci_ring_write_cancel(sc, &sc->sc_rxpost_submit, 1); 1343 m_freem(m); 1344 break; 1345 } 1346 memset(req, 0, sizeof(*req)); 1347 req->msg.msgtype = MSGBUF_TYPE_RXBUF_POST; 1348 req->msg.request_id = htole32(pktid); 1349 req->data_buf_len = htole16(MSGBUF_MAX_PKT_SIZE); 1350 req->data_buf_addr.high_addr = htole32((uint64_t)paddr >> 32); 1351 req->data_buf_addr.low_addr = htole32(paddr & 0xffffffff); 1352 bwfm_pci_ring_write_commit(sc, &sc->sc_rxpost_submit); 1353 } 1354 if_rxr_put(&sc->sc_rxbuf_ring, slots); 1355 splx(s); 1356} 1357 1358int 1359bwfm_pci_setup_ring(struct bwfm_pci_softc *sc, struct bwfm_pci_msgring *ring, 1360 int nitem, size_t itemsz, uint32_t w_idx, uint32_t r_idx, 1361 int idx, uint32_t idx_off, uint32_t *ring_mem) 1362{ 1363 ring->w_idx_addr = w_idx + idx * idx_off; 1364 ring->r_idx_addr = r_idx + idx * idx_off; 1365 ring->w_ptr = 0; 1366 ring->r_ptr = 0; 1367 ring->nitem = nitem; 1368 ring->itemsz = itemsz; 1369 bwfm_pci_ring_write_rptr(sc, ring); 1370 bwfm_pci_ring_write_wptr(sc, ring); 1371 1372 ring->ring = bwfm_pci_dmamem_alloc(sc, nitem * itemsz, 8); 1373 if (ring->ring == NULL) 1374 return ENOMEM; 1375 bus_space_write_4(sc->sc_tcm_iot, sc->sc_tcm_ioh, 1376 *ring_mem + BWFM_RING_MEM_BASE_ADDR_LOW, 1377 BWFM_PCI_DMA_DVA(ring->ring) & 0xffffffff); 1378 bus_space_write_4(sc->sc_tcm_iot, sc->sc_tcm_ioh, 1379 *ring_mem + BWFM_RING_MEM_BASE_ADDR_HIGH, 1380 BWFM_PCI_DMA_DVA(ring->ring) >> 32); 1381 bus_space_write_2(sc->sc_tcm_iot, sc->sc_tcm_ioh, 1382 *ring_mem + BWFM_RING_MAX_ITEM, nitem); 1383 bus_space_write_2(sc->sc_tcm_iot, sc->sc_tcm_ioh, 1384 *ring_mem + BWFM_RING_LEN_ITEMS, itemsz); 1385 *ring_mem = *ring_mem + BWFM_RING_MEM_SZ; 1386 return 0; 1387} 1388 1389int 1390bwfm_pci_setup_flowring(struct bwfm_pci_softc *sc, struct bwfm_pci_msgring *ring, 1391 int nitem, size_t itemsz) 1392{ 1393 ring->w_ptr = 0; 1394 ring->r_ptr = 0; 1395 ring->nitem = nitem; 1396 ring->itemsz = itemsz; 1397 bwfm_pci_ring_write_rptr(sc, ring); 1398 bwfm_pci_ring_write_wptr(sc, ring); 1399 1400 ring->ring = bwfm_pci_dmamem_alloc(sc, nitem * itemsz, 8); 1401 if (ring->ring == NULL) 1402 return ENOMEM; 1403 return 0; 1404} 1405 1406/* Ring helpers */ 1407void 1408bwfm_pci_ring_bell(struct bwfm_pci_softc *sc, 1409 struct bwfm_pci_msgring *ring) 1410{ 1411 if (sc->sc_pcireg64) 1412 bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh, 1413 BWFM_PCI_64_PCIE2REG_H2D_MAILBOX_0, 1); 1414 else 1415 bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh, 1416 BWFM_PCI_PCIE2REG_H2D_MAILBOX_0, 1); 1417} 1418 1419void 1420bwfm_pci_ring_update_rptr(struct bwfm_pci_softc *sc, 1421 struct bwfm_pci_msgring *ring) 1422{ 1423 if (sc->sc_dma_idx_sz == 0) { 1424 ring->r_ptr = bus_space_read_2(sc->sc_tcm_iot, 1425 sc->sc_tcm_ioh, ring->r_idx_addr); 1426 } else { 1427 bus_dmamap_sync(sc->sc_dmat, 1428 BWFM_PCI_DMA_MAP(sc->sc_dma_idx_buf), ring->r_idx_addr, 1429 sizeof(uint16_t), BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 1430 ring->r_ptr = *(uint16_t *)(BWFM_PCI_DMA_KVA(sc->sc_dma_idx_buf) 1431 + ring->r_idx_addr); 1432 } 1433} 1434 1435void 1436bwfm_pci_ring_update_wptr(struct bwfm_pci_softc *sc, 1437 struct bwfm_pci_msgring *ring) 1438{ 1439 if (sc->sc_dma_idx_sz == 0) { 1440 ring->w_ptr = bus_space_read_2(sc->sc_tcm_iot, 1441 sc->sc_tcm_ioh, ring->w_idx_addr); 1442 } else { 1443 bus_dmamap_sync(sc->sc_dmat, 1444 BWFM_PCI_DMA_MAP(sc->sc_dma_idx_buf), ring->w_idx_addr, 1445 sizeof(uint16_t), BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 1446 ring->w_ptr = *(uint16_t *)(BWFM_PCI_DMA_KVA(sc->sc_dma_idx_buf) 1447 + ring->w_idx_addr); 1448 } 1449} 1450 1451void 1452bwfm_pci_ring_write_rptr(struct bwfm_pci_softc *sc, 1453 struct bwfm_pci_msgring *ring) 1454{ 1455 if (sc->sc_dma_idx_sz == 0) { 1456 bus_space_write_2(sc->sc_tcm_iot, sc->sc_tcm_ioh, 1457 ring->r_idx_addr, ring->r_ptr); 1458 } else { 1459 *(uint16_t *)(BWFM_PCI_DMA_KVA(sc->sc_dma_idx_buf) 1460 + ring->r_idx_addr) = ring->r_ptr; 1461 bus_dmamap_sync(sc->sc_dmat, 1462 BWFM_PCI_DMA_MAP(sc->sc_dma_idx_buf), ring->r_idx_addr, 1463 sizeof(uint16_t), BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1464 } 1465} 1466 1467void 1468bwfm_pci_ring_write_wptr(struct bwfm_pci_softc *sc, 1469 struct bwfm_pci_msgring *ring) 1470{ 1471 if (sc->sc_dma_idx_sz == 0) { 1472 bus_space_write_2(sc->sc_tcm_iot, sc->sc_tcm_ioh, 1473 ring->w_idx_addr, ring->w_ptr); 1474 } else { 1475 *(uint16_t *)(BWFM_PCI_DMA_KVA(sc->sc_dma_idx_buf) 1476 + ring->w_idx_addr) = ring->w_ptr; 1477 bus_dmamap_sync(sc->sc_dmat, 1478 BWFM_PCI_DMA_MAP(sc->sc_dma_idx_buf), ring->w_idx_addr, 1479 sizeof(uint16_t), BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1480 } 1481} 1482 1483/* 1484 * Retrieve a free descriptor to put new stuff in, but don't commit 1485 * to it yet so we can rollback later if any error occurs. 1486 */ 1487void * 1488bwfm_pci_ring_write_reserve(struct bwfm_pci_softc *sc, 1489 struct bwfm_pci_msgring *ring) 1490{ 1491 int available; 1492 char *ret; 1493 1494 bwfm_pci_ring_update_rptr(sc, ring); 1495 1496 if (ring->r_ptr > ring->w_ptr) 1497 available = ring->r_ptr - ring->w_ptr; 1498 else 1499 available = ring->r_ptr + (ring->nitem - ring->w_ptr); 1500 1501 if (available <= 1) 1502 return NULL; 1503 1504 ret = BWFM_PCI_DMA_KVA(ring->ring) + (ring->w_ptr * ring->itemsz); 1505 ring->w_ptr += 1; 1506 if (ring->w_ptr == ring->nitem) 1507 ring->w_ptr = 0; 1508 return ret; 1509} 1510 1511void * 1512bwfm_pci_ring_write_reserve_multi(struct bwfm_pci_softc *sc, 1513 struct bwfm_pci_msgring *ring, int count, int *avail) 1514{ 1515 int available; 1516 char *ret; 1517 1518 bwfm_pci_ring_update_rptr(sc, ring); 1519 1520 if (ring->r_ptr > ring->w_ptr) 1521 available = ring->r_ptr - ring->w_ptr; 1522 else 1523 available = ring->r_ptr + (ring->nitem - ring->w_ptr); 1524 1525 if (available <= 1) 1526 return NULL; 1527 1528 ret = BWFM_PCI_DMA_KVA(ring->ring) + (ring->w_ptr * ring->itemsz); 1529 *avail = min(count, available - 1); 1530 if (*avail + ring->w_ptr > ring->nitem) 1531 *avail = ring->nitem - ring->w_ptr; 1532 ring->w_ptr += *avail; 1533 if (ring->w_ptr == ring->nitem) 1534 ring->w_ptr = 0; 1535 return ret; 1536} 1537 1538/* 1539 * Read number of descriptors available (submitted by the firmware) 1540 * and retrieve pointer to first descriptor. 1541 */ 1542void * 1543bwfm_pci_ring_read_avail(struct bwfm_pci_softc *sc, 1544 struct bwfm_pci_msgring *ring, int *avail) 1545{ 1546 bwfm_pci_ring_update_wptr(sc, ring); 1547 1548 if (ring->w_ptr >= ring->r_ptr) 1549 *avail = ring->w_ptr - ring->r_ptr; 1550 else 1551 *avail = ring->nitem - ring->r_ptr; 1552 1553 if (*avail == 0) 1554 return NULL; 1555 1556 bus_dmamap_sync(sc->sc_dmat, BWFM_PCI_DMA_MAP(ring->ring), 1557 ring->r_ptr * ring->itemsz, *avail * ring->itemsz, 1558 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 1559 return BWFM_PCI_DMA_KVA(ring->ring) + (ring->r_ptr * ring->itemsz); 1560} 1561 1562/* 1563 * Let firmware know we read N descriptors. 1564 */ 1565void 1566bwfm_pci_ring_read_commit(struct bwfm_pci_softc *sc, 1567 struct bwfm_pci_msgring *ring, int nitem) 1568{ 1569 ring->r_ptr += nitem; 1570 if (ring->r_ptr == ring->nitem) 1571 ring->r_ptr = 0; 1572 bwfm_pci_ring_write_rptr(sc, ring); 1573} 1574 1575/* 1576 * Let firmware know that we submitted some descriptors. 1577 */ 1578void 1579bwfm_pci_ring_write_commit(struct bwfm_pci_softc *sc, 1580 struct bwfm_pci_msgring *ring) 1581{ 1582 bus_dmamap_sync(sc->sc_dmat, BWFM_PCI_DMA_MAP(ring->ring), 1583 0, BWFM_PCI_DMA_LEN(ring->ring), BUS_DMASYNC_PREREAD | 1584 BUS_DMASYNC_PREWRITE); 1585 bwfm_pci_ring_write_wptr(sc, ring); 1586 bwfm_pci_ring_bell(sc, ring); 1587} 1588 1589/* 1590 * Rollback N descriptors in case we don't actually want 1591 * to commit to it. 1592 */ 1593void 1594bwfm_pci_ring_write_cancel(struct bwfm_pci_softc *sc, 1595 struct bwfm_pci_msgring *ring, int nitem) 1596{ 1597 if (ring->w_ptr == 0) 1598 ring->w_ptr = ring->nitem - nitem; 1599 else 1600 ring->w_ptr -= nitem; 1601} 1602 1603/* 1604 * Foreach written descriptor on the ring, pass the descriptor to 1605 * a message handler and let the firmware know we handled it. 1606 */ 1607void 1608bwfm_pci_ring_rx(struct bwfm_pci_softc *sc, struct bwfm_pci_msgring *ring, 1609 struct mbuf_list *ml) 1610{ 1611 void *buf; 1612 int avail, processed; 1613 1614again: 1615 buf = bwfm_pci_ring_read_avail(sc, ring, &avail); 1616 if (buf == NULL) 1617 return; 1618 1619 processed = 0; 1620 while (avail) { 1621 bwfm_pci_msg_rx(sc, buf + sc->sc_rx_dataoffset, ml); 1622 buf += ring->itemsz; 1623 processed++; 1624 if (processed == 48) { 1625 bwfm_pci_ring_read_commit(sc, ring, processed); 1626 processed = 0; 1627 } 1628 avail--; 1629 } 1630 if (processed) 1631 bwfm_pci_ring_read_commit(sc, ring, processed); 1632 if (ring->r_ptr == 0) 1633 goto again; 1634} 1635 1636void 1637bwfm_pci_msg_rx(struct bwfm_pci_softc *sc, void *buf, struct mbuf_list *ml) 1638{ 1639 struct ifnet *ifp = &sc->sc_sc.sc_ic.ic_if; 1640 struct msgbuf_ioctl_resp_hdr *resp; 1641 struct msgbuf_tx_status *tx; 1642 struct msgbuf_rx_complete *rx; 1643 struct msgbuf_rx_event *event; 1644 struct msgbuf_common_hdr *msg; 1645 struct msgbuf_flowring_create_resp *fcr; 1646 struct msgbuf_flowring_delete_resp *fdr; 1647 struct bwfm_cmd_flowring_create fdcmd; 1648 struct bwfm_pci_msgring *ring; 1649 struct mbuf *m; 1650 int flowid; 1651 1652 msg = (struct msgbuf_common_hdr *)buf; 1653 switch (msg->msgtype) 1654 { 1655 case MSGBUF_TYPE_FLOW_RING_CREATE_CMPLT: 1656 fcr = (struct msgbuf_flowring_create_resp *)buf; 1657 flowid = letoh16(fcr->compl_hdr.flow_ring_id); 1658 if (flowid < 2) 1659 break; 1660 flowid -= 2; 1661 if (flowid >= sc->sc_max_flowrings) 1662 break; 1663 ring = &sc->sc_flowrings[flowid]; 1664 if (ring->status != RING_OPENING) 1665 break; 1666 if (fcr->compl_hdr.status) { 1667 printf("%s: failed to open flowring %d\n", 1668 DEVNAME(sc), flowid); 1669 ring->status = RING_CLOSED; 1670 if (ring->m) { 1671 m_freem(ring->m); 1672 ring->m = NULL; 1673 } 1674 ifq_restart(&ifp->if_snd); 1675 break; 1676 } 1677 ring->status = RING_OPEN; 1678 if (ring->m != NULL) { 1679 m = ring->m; 1680 ring->m = NULL; 1681 if (bwfm_pci_txdata(&sc->sc_sc, m)) 1682 m_freem(ring->m); 1683 } 1684 ifq_restart(&ifp->if_snd); 1685 break; 1686 case MSGBUF_TYPE_FLOW_RING_DELETE_CMPLT: 1687 fdr = (struct msgbuf_flowring_delete_resp *)buf; 1688 flowid = letoh16(fdr->compl_hdr.flow_ring_id); 1689 if (flowid < 2) 1690 break; 1691 flowid -= 2; 1692 if (flowid >= sc->sc_max_flowrings) 1693 break; 1694 ring = &sc->sc_flowrings[flowid]; 1695 if (ring->status != RING_CLOSING) 1696 break; 1697 if (fdr->compl_hdr.status) { 1698 printf("%s: failed to delete flowring %d\n", 1699 DEVNAME(sc), flowid); 1700 break; 1701 } 1702 fdcmd.flowid = flowid; 1703 bwfm_do_async(&sc->sc_sc, bwfm_pci_flowring_delete_cb, 1704 &fdcmd, sizeof(fdcmd)); 1705 break; 1706 case MSGBUF_TYPE_IOCTLPTR_REQ_ACK: 1707 m = bwfm_pci_pktid_free(sc, &sc->sc_ioctl_pkts, 1708 letoh32(msg->request_id)); 1709 if (m == NULL) 1710 break; 1711 m_freem(m); 1712 break; 1713 case MSGBUF_TYPE_IOCTL_CMPLT: 1714 resp = (struct msgbuf_ioctl_resp_hdr *)buf; 1715 bwfm_pci_msgbuf_rxioctl(sc, resp); 1716 if_rxr_put(&sc->sc_ioctl_ring, 1); 1717 bwfm_pci_fill_rx_rings(sc); 1718 break; 1719 case MSGBUF_TYPE_WL_EVENT: 1720 event = (struct msgbuf_rx_event *)buf; 1721 m = bwfm_pci_pktid_free(sc, &sc->sc_rx_pkts, 1722 letoh32(event->msg.request_id)); 1723 if (m == NULL) 1724 break; 1725 m_adj(m, sc->sc_rx_dataoffset); 1726 m->m_len = m->m_pkthdr.len = letoh16(event->event_data_len); 1727 bwfm_rx(&sc->sc_sc, m, ml); 1728 if_rxr_put(&sc->sc_event_ring, 1); 1729 bwfm_pci_fill_rx_rings(sc); 1730 break; 1731 case MSGBUF_TYPE_TX_STATUS: 1732 tx = (struct msgbuf_tx_status *)buf; 1733 m = bwfm_pci_pktid_free(sc, &sc->sc_tx_pkts, 1734 letoh32(tx->msg.request_id) - 1); 1735 if (m == NULL) 1736 break; 1737 m_freem(m); 1738 if (sc->sc_tx_pkts_full) { 1739 sc->sc_tx_pkts_full = 0; 1740 ifq_restart(&ifp->if_snd); 1741 } 1742 break; 1743 case MSGBUF_TYPE_RX_CMPLT: 1744 rx = (struct msgbuf_rx_complete *)buf; 1745 m = bwfm_pci_pktid_free(sc, &sc->sc_rx_pkts, 1746 letoh32(rx->msg.request_id)); 1747 if (m == NULL) 1748 break; 1749 if (letoh16(rx->data_offset)) 1750 m_adj(m, letoh16(rx->data_offset)); 1751 else if (sc->sc_rx_dataoffset) 1752 m_adj(m, sc->sc_rx_dataoffset); 1753 m->m_len = m->m_pkthdr.len = letoh16(rx->data_len); 1754 bwfm_rx(&sc->sc_sc, m, ml); 1755 if_rxr_put(&sc->sc_rxbuf_ring, 1); 1756 bwfm_pci_fill_rx_rings(sc); 1757 break; 1758 default: 1759 printf("%s: msgtype 0x%08x\n", __func__, msg->msgtype); 1760 break; 1761 } 1762} 1763 1764/* Bus core helpers */ 1765void 1766bwfm_pci_select_core(struct bwfm_pci_softc *sc, int id) 1767{ 1768 struct bwfm_softc *bwfm = (void *)sc; 1769 struct bwfm_core *core; 1770 1771 core = bwfm_chip_get_core(bwfm, id); 1772 if (core == NULL) { 1773 printf("%s: could not find core to select", DEVNAME(sc)); 1774 return; 1775 } 1776 1777 pci_conf_write(sc->sc_pc, sc->sc_tag, 1778 BWFM_PCI_BAR0_WINDOW, core->co_base); 1779 if (pci_conf_read(sc->sc_pc, sc->sc_tag, 1780 BWFM_PCI_BAR0_WINDOW) != core->co_base) 1781 pci_conf_write(sc->sc_pc, sc->sc_tag, 1782 BWFM_PCI_BAR0_WINDOW, core->co_base); 1783} 1784 1785uint32_t 1786bwfm_pci_buscore_read(struct bwfm_softc *bwfm, uint32_t reg) 1787{ 1788 struct bwfm_pci_softc *sc = (void *)bwfm; 1789 uint32_t page, offset; 1790 1791 page = reg & ~(BWFM_PCI_BAR0_REG_SIZE - 1); 1792 offset = reg & (BWFM_PCI_BAR0_REG_SIZE - 1); 1793 pci_conf_write(sc->sc_pc, sc->sc_tag, BWFM_PCI_BAR0_WINDOW, page); 1794 return bus_space_read_4(sc->sc_reg_iot, sc->sc_reg_ioh, offset); 1795} 1796 1797void 1798bwfm_pci_buscore_write(struct bwfm_softc *bwfm, uint32_t reg, uint32_t val) 1799{ 1800 struct bwfm_pci_softc *sc = (void *)bwfm; 1801 uint32_t page, offset; 1802 1803 page = reg & ~(BWFM_PCI_BAR0_REG_SIZE - 1); 1804 offset = reg & (BWFM_PCI_BAR0_REG_SIZE - 1); 1805 pci_conf_write(sc->sc_pc, sc->sc_tag, BWFM_PCI_BAR0_WINDOW, page); 1806 bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh, offset, val); 1807} 1808 1809int 1810bwfm_pci_buscore_prepare(struct bwfm_softc *bwfm) 1811{ 1812 return 0; 1813} 1814 1815int 1816bwfm_pci_buscore_reset(struct bwfm_softc *bwfm) 1817{ 1818 struct bwfm_pci_softc *sc = (void *)bwfm; 1819 struct bwfm_core *core; 1820 uint32_t reg; 1821 int i; 1822 1823 bwfm_pci_select_core(sc, BWFM_AGENT_CORE_PCIE2); 1824 reg = pci_conf_read(sc->sc_pc, sc->sc_tag, 1825 BWFM_PCI_CFGREG_LINK_STATUS_CTRL); 1826 pci_conf_write(sc->sc_pc, sc->sc_tag, BWFM_PCI_CFGREG_LINK_STATUS_CTRL, 1827 reg & ~BWFM_PCI_CFGREG_LINK_STATUS_CTRL_ASPM_ENAB); 1828 1829 bwfm_pci_select_core(sc, BWFM_AGENT_CORE_CHIPCOMMON); 1830 bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh, 1831 BWFM_CHIP_REG_WATCHDOG, 4); 1832 delay(100 * 1000); 1833 1834 bwfm_pci_select_core(sc, BWFM_AGENT_CORE_PCIE2); 1835 pci_conf_write(sc->sc_pc, sc->sc_tag, 1836 BWFM_PCI_CFGREG_LINK_STATUS_CTRL, reg); 1837 1838 core = bwfm_chip_get_core(bwfm, BWFM_AGENT_CORE_PCIE2); 1839 if (core->co_rev <= 13) { 1840 uint16_t cfg_offset[] = { 1841 BWFM_PCI_CFGREG_STATUS_CMD, 1842 BWFM_PCI_CFGREG_PM_CSR, 1843 BWFM_PCI_CFGREG_MSI_CAP, 1844 BWFM_PCI_CFGREG_MSI_ADDR_L, 1845 BWFM_PCI_CFGREG_MSI_ADDR_H, 1846 BWFM_PCI_CFGREG_MSI_DATA, 1847 BWFM_PCI_CFGREG_LINK_STATUS_CTRL2, 1848 BWFM_PCI_CFGREG_RBAR_CTRL, 1849 BWFM_PCI_CFGREG_PML1_SUB_CTRL1, 1850 BWFM_PCI_CFGREG_REG_BAR2_CONFIG, 1851 BWFM_PCI_CFGREG_REG_BAR3_CONFIG, 1852 }; 1853 1854 for (i = 0; i < nitems(cfg_offset); i++) { 1855 bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh, 1856 BWFM_PCI_PCIE2REG_CONFIGADDR, cfg_offset[i]); 1857 reg = bus_space_read_4(sc->sc_reg_iot, sc->sc_reg_ioh, 1858 BWFM_PCI_PCIE2REG_CONFIGDATA); 1859 DPRINTFN(3, ("%s: config offset 0x%04x, value 0x%04x\n", 1860 DEVNAME(sc), cfg_offset[i], reg)); 1861 bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh, 1862 BWFM_PCI_PCIE2REG_CONFIGDATA, reg); 1863 } 1864 } 1865 if (core->co_rev >= 64) 1866 sc->sc_pcireg64 = 1; 1867 1868 reg = bwfm_pci_intr_status(sc); 1869 if (reg != 0xffffffff) 1870 bwfm_pci_intr_ack(sc, reg); 1871 1872 return 0; 1873} 1874 1875void 1876bwfm_pci_buscore_activate(struct bwfm_softc *bwfm, uint32_t rstvec) 1877{ 1878 struct bwfm_pci_softc *sc = (void *)bwfm; 1879 bus_space_write_4(sc->sc_tcm_iot, sc->sc_tcm_ioh, 0, rstvec); 1880} 1881 1882static int bwfm_pci_prio2fifo[8] = { 1883 0, /* best effort */ 1884 1, /* IPTOS_PREC_IMMEDIATE */ 1885 1, /* IPTOS_PREC_PRIORITY */ 1886 0, /* IPTOS_PREC_FLASH */ 1887 2, /* IPTOS_PREC_FLASHOVERRIDE */ 1888 2, /* IPTOS_PREC_CRITIC_ECP */ 1889 3, /* IPTOS_PREC_INTERNETCONTROL */ 1890 3, /* IPTOS_PREC_NETCONTROL */ 1891}; 1892 1893int 1894bwfm_pci_flowring_lookup(struct bwfm_pci_softc *sc, struct mbuf *m) 1895{ 1896 struct ieee80211com *ic = &sc->sc_sc.sc_ic; 1897#ifndef IEEE80211_STA_ONLY 1898 uint8_t *da = mtod(m, uint8_t *); 1899#endif 1900 int flowid, prio, fifo; 1901 int i, found; 1902 1903 prio = ieee80211_classify(ic, m); 1904 fifo = bwfm_pci_prio2fifo[prio]; 1905 1906 switch (ic->ic_opmode) 1907 { 1908 case IEEE80211_M_STA: 1909 flowid = fifo; 1910 break; 1911#ifndef IEEE80211_STA_ONLY 1912 case IEEE80211_M_HOSTAP: 1913 if (ETHER_IS_MULTICAST(da)) 1914 da = etherbroadcastaddr; 1915 flowid = da[5] * 2 + fifo; 1916 break; 1917#endif 1918 default: 1919 printf("%s: state not supported\n", DEVNAME(sc)); 1920 return ENOBUFS; 1921 } 1922 1923 found = 0; 1924 flowid = flowid % sc->sc_max_flowrings; 1925 for (i = 0; i < sc->sc_max_flowrings; i++) { 1926 if (ic->ic_opmode == IEEE80211_M_STA && 1927 sc->sc_flowrings[flowid].status >= RING_OPEN && 1928 sc->sc_flowrings[flowid].fifo == fifo) { 1929 found = 1; 1930 break; 1931 } 1932#ifndef IEEE80211_STA_ONLY 1933 if (ic->ic_opmode == IEEE80211_M_HOSTAP && 1934 sc->sc_flowrings[flowid].status >= RING_OPEN && 1935 sc->sc_flowrings[flowid].fifo == fifo && 1936 !memcmp(sc->sc_flowrings[flowid].mac, da, ETHER_ADDR_LEN)) { 1937 found = 1; 1938 break; 1939 } 1940#endif 1941 flowid = (flowid + 1) % sc->sc_max_flowrings; 1942 } 1943 1944 if (found) 1945 return flowid; 1946 1947 return -1; 1948} 1949 1950void 1951bwfm_pci_flowring_create(struct bwfm_pci_softc *sc, struct mbuf *m) 1952{ 1953 struct ieee80211com *ic = &sc->sc_sc.sc_ic; 1954 struct bwfm_cmd_flowring_create cmd; 1955#ifndef IEEE80211_STA_ONLY 1956 uint8_t *da = mtod(m, uint8_t *); 1957#endif 1958 struct bwfm_pci_msgring *ring; 1959 int flowid, prio, fifo; 1960 int i, found; 1961 1962 prio = ieee80211_classify(ic, m); 1963 fifo = bwfm_pci_prio2fifo[prio]; 1964 1965 switch (ic->ic_opmode) 1966 { 1967 case IEEE80211_M_STA: 1968 flowid = fifo; 1969 break; 1970#ifndef IEEE80211_STA_ONLY 1971 case IEEE80211_M_HOSTAP: 1972 if (ETHER_IS_MULTICAST(da)) 1973 da = etherbroadcastaddr; 1974 flowid = da[5] * 2 + fifo; 1975 break; 1976#endif 1977 default: 1978 printf("%s: state not supported\n", DEVNAME(sc)); 1979 return; 1980 } 1981 1982 found = 0; 1983 flowid = flowid % sc->sc_max_flowrings; 1984 for (i = 0; i < sc->sc_max_flowrings; i++) { 1985 ring = &sc->sc_flowrings[flowid]; 1986 if (ring->status == RING_CLOSED) { 1987 ring->status = RING_OPENING; 1988 found = 1; 1989 break; 1990 } 1991 flowid = (flowid + 1) % sc->sc_max_flowrings; 1992 } 1993 1994 /* 1995 * We cannot recover from that so far. Only a stop/init 1996 * cycle can revive this if it ever happens at all. 1997 */ 1998 if (!found) { 1999 printf("%s: no flowring available\n", DEVNAME(sc)); 2000 return; 2001 } 2002 2003 cmd.m = m; 2004 cmd.prio = prio; 2005 cmd.flowid = flowid; 2006 bwfm_do_async(&sc->sc_sc, bwfm_pci_flowring_create_cb, &cmd, sizeof(cmd)); 2007} 2008 2009void 2010bwfm_pci_flowring_create_cb(struct bwfm_softc *bwfm, void *arg) 2011{ 2012 struct bwfm_pci_softc *sc = (void *)bwfm; 2013#ifndef IEEE80211_STA_ONLY 2014 struct ieee80211com *ic = &sc->sc_sc.sc_ic; 2015#endif 2016 struct bwfm_cmd_flowring_create *cmd = arg; 2017 struct msgbuf_tx_flowring_create_req *req; 2018 struct bwfm_pci_msgring *ring; 2019 uint8_t *da, *sa; 2020 int s; 2021 2022 da = mtod(cmd->m, char *) + 0 * ETHER_ADDR_LEN; 2023 sa = mtod(cmd->m, char *) + 1 * ETHER_ADDR_LEN; 2024 2025 ring = &sc->sc_flowrings[cmd->flowid]; 2026 if (ring->status != RING_OPENING) { 2027 printf("%s: flowring not opening\n", DEVNAME(sc)); 2028 return; 2029 } 2030 2031 if (bwfm_pci_setup_flowring(sc, ring, 512, 48)) { 2032 printf("%s: cannot setup flowring\n", DEVNAME(sc)); 2033 return; 2034 } 2035 2036 s = splnet(); 2037 req = bwfm_pci_ring_write_reserve(sc, &sc->sc_ctrl_submit); 2038 if (req == NULL) { 2039 printf("%s: cannot reserve for flowring\n", DEVNAME(sc)); 2040 splx(s); 2041 return; 2042 } 2043 2044 ring->status = RING_OPENING; 2045 ring->fifo = bwfm_pci_prio2fifo[cmd->prio]; 2046 ring->m = cmd->m; 2047 memcpy(ring->mac, da, ETHER_ADDR_LEN); 2048#ifndef IEEE80211_STA_ONLY 2049 if (ic->ic_opmode == IEEE80211_M_HOSTAP && ETHER_IS_MULTICAST(da)) 2050 memcpy(ring->mac, etherbroadcastaddr, ETHER_ADDR_LEN); 2051#endif 2052 2053 req->msg.msgtype = MSGBUF_TYPE_FLOW_RING_CREATE; 2054 req->msg.ifidx = 0; 2055 req->msg.request_id = 0; 2056 req->tid = bwfm_pci_prio2fifo[cmd->prio]; 2057 req->flow_ring_id = letoh16(cmd->flowid + 2); 2058 memcpy(req->da, da, ETHER_ADDR_LEN); 2059 memcpy(req->sa, sa, ETHER_ADDR_LEN); 2060 req->flow_ring_addr.high_addr = 2061 letoh32(BWFM_PCI_DMA_DVA(ring->ring) >> 32); 2062 req->flow_ring_addr.low_addr = 2063 letoh32(BWFM_PCI_DMA_DVA(ring->ring) & 0xffffffff); 2064 req->max_items = letoh16(512); 2065 req->len_item = letoh16(48); 2066 2067 bwfm_pci_ring_write_commit(sc, &sc->sc_ctrl_submit); 2068 splx(s); 2069} 2070 2071void 2072bwfm_pci_flowring_delete(struct bwfm_pci_softc *sc, int flowid) 2073{ 2074 struct msgbuf_tx_flowring_delete_req *req; 2075 struct bwfm_pci_msgring *ring; 2076 int s; 2077 2078 ring = &sc->sc_flowrings[flowid]; 2079 if (ring->status != RING_OPEN) { 2080 printf("%s: flowring not open\n", DEVNAME(sc)); 2081 return; 2082 } 2083 2084 s = splnet(); 2085 req = bwfm_pci_ring_write_reserve(sc, &sc->sc_ctrl_submit); 2086 if (req == NULL) { 2087 printf("%s: cannot reserve for flowring\n", DEVNAME(sc)); 2088 splx(s); 2089 return; 2090 } 2091 2092 ring->status = RING_CLOSING; 2093 2094 req->msg.msgtype = MSGBUF_TYPE_FLOW_RING_DELETE; 2095 req->msg.ifidx = 0; 2096 req->msg.request_id = 0; 2097 req->flow_ring_id = letoh16(flowid + 2); 2098 req->reason = 0; 2099 2100 bwfm_pci_ring_write_commit(sc, &sc->sc_ctrl_submit); 2101 splx(s); 2102} 2103 2104void 2105bwfm_pci_flowring_delete_cb(struct bwfm_softc *bwfm, void *arg) 2106{ 2107 struct bwfm_pci_softc *sc = (void *)bwfm; 2108 struct bwfm_cmd_flowring_create *cmd = arg; 2109 struct bwfm_pci_msgring *ring; 2110 2111 ring = &sc->sc_flowrings[cmd->flowid]; 2112 bwfm_pci_dmamem_free(sc, ring->ring); 2113 ring->status = RING_CLOSED; 2114} 2115 2116void 2117bwfm_pci_stop(struct bwfm_softc *bwfm) 2118{ 2119 struct bwfm_pci_softc *sc = (void *)bwfm; 2120 struct bwfm_pci_msgring *ring; 2121 int i; 2122 2123 for (i = 0; i < sc->sc_max_flowrings; i++) { 2124 ring = &sc->sc_flowrings[i]; 2125 if (ring->status == RING_OPEN) 2126 bwfm_pci_flowring_delete(sc, i); 2127 } 2128} 2129 2130int 2131bwfm_pci_txcheck(struct bwfm_softc *bwfm) 2132{ 2133 struct bwfm_pci_softc *sc = (void *)bwfm; 2134 struct bwfm_pci_msgring *ring; 2135 int i; 2136 2137 /* If we are transitioning, we cannot send. */ 2138 for (i = 0; i < sc->sc_max_flowrings; i++) { 2139 ring = &sc->sc_flowrings[i]; 2140 if (ring->status == RING_OPENING) 2141 return ENOBUFS; 2142 } 2143 2144 if (bwfm_pci_pktid_avail(sc, &sc->sc_tx_pkts)) { 2145 sc->sc_tx_pkts_full = 1; 2146 return ENOBUFS; 2147 } 2148 2149 return 0; 2150} 2151 2152int 2153bwfm_pci_txdata(struct bwfm_softc *bwfm, struct mbuf *m) 2154{ 2155 struct bwfm_pci_softc *sc = (void *)bwfm; 2156 struct bwfm_pci_msgring *ring; 2157 struct msgbuf_tx_msghdr *tx; 2158 uint32_t pktid; 2159 paddr_t paddr; 2160 int flowid, ret; 2161 2162 flowid = bwfm_pci_flowring_lookup(sc, m); 2163 if (flowid < 0) { 2164 /* 2165 * We cannot send the packet right now as there is 2166 * no flowring yet. The flowring will be created 2167 * asynchronously. While the ring is transitioning 2168 * the TX check will tell the upper layers that we 2169 * cannot send packets right now. When the flowring 2170 * is created the queue will be restarted and this 2171 * mbuf will be transmitted. 2172 */ 2173 bwfm_pci_flowring_create(sc, m); 2174 return 0; 2175 } 2176 2177 ring = &sc->sc_flowrings[flowid]; 2178 if (ring->status == RING_OPENING || 2179 ring->status == RING_CLOSING) { 2180 printf("%s: tried to use a flow that was " 2181 "transitioning in status %d\n", 2182 DEVNAME(sc), ring->status); 2183 return ENOBUFS; 2184 } 2185 2186 tx = bwfm_pci_ring_write_reserve(sc, ring); 2187 if (tx == NULL) 2188 return ENOBUFS; 2189 2190 memset(tx, 0, sizeof(*tx)); 2191 tx->msg.msgtype = MSGBUF_TYPE_TX_POST; 2192 tx->msg.ifidx = 0; 2193 tx->flags = BWFM_MSGBUF_PKT_FLAGS_FRAME_802_3; 2194 tx->flags |= ieee80211_classify(&sc->sc_sc.sc_ic, m) << 2195 BWFM_MSGBUF_PKT_FLAGS_PRIO_SHIFT; 2196 tx->seg_cnt = 1; 2197 memcpy(tx->txhdr, mtod(m, char *), ETHER_HDR_LEN); 2198 2199 ret = bwfm_pci_pktid_new(sc, &sc->sc_tx_pkts, m, &pktid, &paddr); 2200 if (ret) { 2201 if (ret == ENOBUFS) { 2202 printf("%s: no pktid available for TX\n", 2203 DEVNAME(sc)); 2204 sc->sc_tx_pkts_full = 1; 2205 } 2206 bwfm_pci_ring_write_cancel(sc, ring, 1); 2207 return ret; 2208 } 2209 paddr += ETHER_HDR_LEN; 2210 2211 tx->msg.request_id = htole32(pktid + 1); 2212 tx->data_len = htole16(m->m_len - ETHER_HDR_LEN); 2213 tx->data_buf_addr.high_addr = htole32((uint64_t)paddr >> 32); 2214 tx->data_buf_addr.low_addr = htole32(paddr & 0xffffffff); 2215 2216 bwfm_pci_ring_write_commit(sc, ring); 2217 return 0; 2218} 2219 2220int 2221bwfm_pci_send_mb_data(struct bwfm_pci_softc *sc, uint32_t htod_mb_data) 2222{ 2223 struct bwfm_softc *bwfm = (void *)sc; 2224 struct bwfm_core *core; 2225 uint32_t reg; 2226 int i; 2227 2228 for (i = 0; i < 100; i++) { 2229 reg = bus_space_read_4(sc->sc_tcm_iot, sc->sc_tcm_ioh, 2230 sc->sc_htod_mb_data_addr); 2231 if (reg == 0) 2232 break; 2233 delay(10 * 1000); 2234 } 2235 if (i == 100) { 2236 DPRINTF(("%s: MB transaction already pending\n", DEVNAME(sc))); 2237 return EIO; 2238 } 2239 2240 bus_space_write_4(sc->sc_tcm_iot, sc->sc_tcm_ioh, 2241 sc->sc_htod_mb_data_addr, htod_mb_data); 2242 pci_conf_write(sc->sc_pc, sc->sc_tag, BWFM_PCI_REG_SBMBX, 1); 2243 2244 core = bwfm_chip_get_core(bwfm, BWFM_AGENT_CORE_PCIE2); 2245 if (core->co_rev <= 13) 2246 pci_conf_write(sc->sc_pc, sc->sc_tag, BWFM_PCI_REG_SBMBX, 1); 2247 2248 return 0; 2249} 2250 2251void 2252bwfm_pci_handle_mb_data(struct bwfm_pci_softc *sc) 2253{ 2254 uint32_t reg; 2255 2256 reg = bus_space_read_4(sc->sc_tcm_iot, sc->sc_tcm_ioh, 2257 sc->sc_dtoh_mb_data_addr); 2258 if (reg == 0) 2259 return; 2260 2261 bus_space_write_4(sc->sc_tcm_iot, sc->sc_tcm_ioh, 2262 sc->sc_dtoh_mb_data_addr, 0); 2263 2264 if (reg & BWFM_PCI_D2H_DEV_D3_ACK) { 2265 sc->sc_mbdata_done = 1; 2266 wakeup(&sc->sc_mbdata_done); 2267 } 2268 2269 /* TODO: support more events */ 2270 if (reg & ~BWFM_PCI_D2H_DEV_D3_ACK) 2271 printf("%s: handle MB data 0x%08x\n", DEVNAME(sc), reg); 2272} 2273 2274#ifdef BWFM_DEBUG 2275void 2276bwfm_pci_debug_console(struct bwfm_pci_softc *sc) 2277{ 2278 uint32_t newidx = bus_space_read_4(sc->sc_tcm_iot, sc->sc_tcm_ioh, 2279 sc->sc_console_base_addr + BWFM_CONSOLE_WRITEIDX); 2280 2281 if (newidx != sc->sc_console_readidx) 2282 DPRINTFN(3, ("BWFM CONSOLE: ")); 2283 while (newidx != sc->sc_console_readidx) { 2284 uint8_t ch = bus_space_read_1(sc->sc_tcm_iot, sc->sc_tcm_ioh, 2285 sc->sc_console_buf_addr + sc->sc_console_readidx); 2286 sc->sc_console_readidx++; 2287 if (sc->sc_console_readidx == sc->sc_console_buf_size) 2288 sc->sc_console_readidx = 0; 2289 if (ch == '\r') 2290 continue; 2291 DPRINTFN(3, ("%c", ch)); 2292 } 2293} 2294#endif 2295 2296int 2297bwfm_pci_intr(void *v) 2298{ 2299 struct bwfm_pci_softc *sc = (void *)v; 2300 struct ifnet *ifp = &sc->sc_sc.sc_ic.ic_if; 2301 struct mbuf_list ml = MBUF_LIST_INITIALIZER(); 2302 uint32_t status, mask; 2303 2304 if (!sc->sc_initialized) 2305 return 0; 2306 2307 status = bwfm_pci_intr_status(sc); 2308 /* FIXME: interrupt status seems to be zero? */ 2309 if (status == 0 && sc->sc_pcireg64) 2310 status |= BWFM_PCI_64_PCIE2REG_MAILBOXMASK_INT_D2H_DB; 2311 if (status == 0) 2312 return 0; 2313 2314 bwfm_pci_intr_disable(sc); 2315 bwfm_pci_intr_ack(sc, status); 2316 2317 if (!sc->sc_pcireg64 && 2318 (status & (BWFM_PCI_PCIE2REG_MAILBOXMASK_INT_FN0_0 | 2319 BWFM_PCI_PCIE2REG_MAILBOXMASK_INT_FN0_1))) 2320 bwfm_pci_handle_mb_data(sc); 2321 2322 mask = BWFM_PCI_PCIE2REG_MAILBOXMASK_INT_D2H_DB; 2323 if (sc->sc_pcireg64) 2324 mask = BWFM_PCI_64_PCIE2REG_MAILBOXMASK_INT_D2H_DB; 2325 2326 if (status & mask) { 2327 bwfm_pci_ring_rx(sc, &sc->sc_rx_complete, &ml); 2328 bwfm_pci_ring_rx(sc, &sc->sc_tx_complete, &ml); 2329 bwfm_pci_ring_rx(sc, &sc->sc_ctrl_complete, &ml); 2330 2331 if (ifiq_input(&ifp->if_rcv, &ml)) 2332 if_rxr_livelocked(&sc->sc_rxbuf_ring); 2333 } 2334 2335#ifdef BWFM_DEBUG 2336 bwfm_pci_debug_console(sc); 2337#endif 2338 2339 bwfm_pci_intr_enable(sc); 2340 return 1; 2341} 2342 2343void 2344bwfm_pci_intr_enable(struct bwfm_pci_softc *sc) 2345{ 2346 if (sc->sc_pcireg64) 2347 bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh, 2348 BWFM_PCI_64_PCIE2REG_MAILBOXMASK, 2349 BWFM_PCI_64_PCIE2REG_MAILBOXMASK_INT_D2H_DB); 2350 else 2351 bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh, 2352 BWFM_PCI_PCIE2REG_MAILBOXMASK, 2353 BWFM_PCI_PCIE2REG_MAILBOXMASK_INT_FN0_0 | 2354 BWFM_PCI_PCIE2REG_MAILBOXMASK_INT_FN0_1 | 2355 BWFM_PCI_PCIE2REG_MAILBOXMASK_INT_D2H_DB); 2356} 2357 2358void 2359bwfm_pci_intr_disable(struct bwfm_pci_softc *sc) 2360{ 2361 if (sc->sc_pcireg64) 2362 bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh, 2363 BWFM_PCI_64_PCIE2REG_MAILBOXMASK, 0); 2364 else 2365 bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh, 2366 BWFM_PCI_PCIE2REG_MAILBOXMASK, 0); 2367} 2368 2369uint32_t 2370bwfm_pci_intr_status(struct bwfm_pci_softc *sc) 2371{ 2372 if (sc->sc_pcireg64) 2373 return bus_space_read_4(sc->sc_reg_iot, sc->sc_reg_ioh, 2374 BWFM_PCI_64_PCIE2REG_MAILBOXINT); 2375 else 2376 return bus_space_read_4(sc->sc_reg_iot, sc->sc_reg_ioh, 2377 BWFM_PCI_PCIE2REG_MAILBOXINT); 2378} 2379 2380void 2381bwfm_pci_intr_ack(struct bwfm_pci_softc *sc, uint32_t status) 2382{ 2383 if (sc->sc_pcireg64) 2384 bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh, 2385 BWFM_PCI_64_PCIE2REG_MAILBOXINT, status); 2386 else 2387 bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh, 2388 BWFM_PCI_PCIE2REG_MAILBOXINT, status); 2389} 2390 2391uint32_t 2392bwfm_pci_intmask(struct bwfm_pci_softc *sc) 2393{ 2394 if (sc->sc_pcireg64) 2395 return bus_space_read_4(sc->sc_reg_iot, sc->sc_reg_ioh, 2396 BWFM_PCI_64_PCIE2REG_INTMASK); 2397 else 2398 return bus_space_read_4(sc->sc_reg_iot, sc->sc_reg_ioh, 2399 BWFM_PCI_PCIE2REG_INTMASK); 2400} 2401 2402void 2403bwfm_pci_hostready(struct bwfm_pci_softc *sc) 2404{ 2405 if ((sc->sc_shared_flags & BWFM_SHARED_INFO_HOSTRDY_DB1) == 0) 2406 return; 2407 2408 if (sc->sc_pcireg64) 2409 bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh, 2410 BWFM_PCI_64_PCIE2REG_H2D_MAILBOX_1, 1); 2411 else 2412 bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh, 2413 BWFM_PCI_PCIE2REG_H2D_MAILBOX_1, 1); 2414} 2415 2416/* Msgbuf protocol implementation */ 2417int 2418bwfm_pci_msgbuf_query_dcmd(struct bwfm_softc *bwfm, int ifidx, 2419 int cmd, char *buf, size_t *len) 2420{ 2421 struct bwfm_pci_softc *sc = (void *)bwfm; 2422 struct msgbuf_ioctl_req_hdr *req; 2423 struct bwfm_pci_ioctl *ctl; 2424 struct mbuf *m; 2425 uint32_t pktid; 2426 paddr_t paddr; 2427 size_t buflen; 2428 int s; 2429 2430 buflen = min(*len, BWFM_DMA_H2D_IOCTL_BUF_LEN); 2431 m = MCLGETL(NULL, M_DONTWAIT, buflen); 2432 if (m == NULL) 2433 return 1; 2434 m->m_len = m->m_pkthdr.len = buflen; 2435 2436 if (buf) 2437 memcpy(mtod(m, char *), buf, buflen); 2438 else 2439 memset(mtod(m, char *), 0, buflen); 2440 2441 s = splnet(); 2442 req = bwfm_pci_ring_write_reserve(sc, &sc->sc_ctrl_submit); 2443 if (req == NULL) { 2444 splx(s); 2445 m_freem(m); 2446 return 1; 2447 } 2448 2449 if (bwfm_pci_pktid_new(sc, &sc->sc_ioctl_pkts, m, &pktid, &paddr)) { 2450 bwfm_pci_ring_write_cancel(sc, &sc->sc_ctrl_submit, 1); 2451 splx(s); 2452 m_freem(m); 2453 return 1; 2454 } 2455 2456 ctl = malloc(sizeof(*ctl), M_TEMP, M_WAITOK|M_ZERO); 2457 ctl->transid = sc->sc_ioctl_transid++; 2458 TAILQ_INSERT_TAIL(&sc->sc_ioctlq, ctl, next); 2459 2460 req->msg.msgtype = MSGBUF_TYPE_IOCTLPTR_REQ; 2461 req->msg.ifidx = 0; 2462 req->msg.flags = 0; 2463 req->msg.request_id = htole32(pktid); 2464 req->cmd = htole32(cmd); 2465 req->output_buf_len = htole16(*len); 2466 req->trans_id = htole16(ctl->transid); 2467 2468 req->input_buf_len = htole16(m->m_len); 2469 req->req_buf_addr.high_addr = htole32((uint64_t)paddr >> 32); 2470 req->req_buf_addr.low_addr = htole32(paddr & 0xffffffff); 2471 2472 bwfm_pci_ring_write_commit(sc, &sc->sc_ctrl_submit); 2473 splx(s); 2474 2475 tsleep_nsec(ctl, PWAIT, "bwfm", SEC_TO_NSEC(5)); 2476 TAILQ_REMOVE(&sc->sc_ioctlq, ctl, next); 2477 2478 if (ctl->m == NULL) { 2479 free(ctl, M_TEMP, sizeof(*ctl)); 2480 return 1; 2481 } 2482 2483 *len = min(ctl->retlen, m->m_len); 2484 *len = min(*len, buflen); 2485 if (buf) 2486 m_copydata(ctl->m, 0, *len, buf); 2487 m_freem(ctl->m); 2488 2489 if (ctl->status < 0) { 2490 free(ctl, M_TEMP, sizeof(*ctl)); 2491 return 1; 2492 } 2493 2494 free(ctl, M_TEMP, sizeof(*ctl)); 2495 return 0; 2496} 2497 2498int 2499bwfm_pci_msgbuf_set_dcmd(struct bwfm_softc *bwfm, int ifidx, 2500 int cmd, char *buf, size_t len) 2501{ 2502 return bwfm_pci_msgbuf_query_dcmd(bwfm, ifidx, cmd, buf, &len); 2503} 2504 2505void 2506bwfm_pci_msgbuf_rxioctl(struct bwfm_pci_softc *sc, 2507 struct msgbuf_ioctl_resp_hdr *resp) 2508{ 2509 struct bwfm_pci_ioctl *ctl, *tmp; 2510 struct mbuf *m; 2511 2512 m = bwfm_pci_pktid_free(sc, &sc->sc_rx_pkts, 2513 letoh32(resp->msg.request_id)); 2514 2515 TAILQ_FOREACH_SAFE(ctl, &sc->sc_ioctlq, next, tmp) { 2516 if (ctl->transid != letoh16(resp->trans_id)) 2517 continue; 2518 ctl->m = m; 2519 ctl->retlen = letoh16(resp->resp_len); 2520 ctl->status = letoh16(resp->compl_hdr.status); 2521 wakeup(ctl); 2522 return; 2523 } 2524 2525 m_freem(m); 2526} 2527