1 /* $OpenBSD: if_myx.c,v 1.113 2020/12/12 11:48:53 jan Exp $ */ 2 3 /* 4 * Copyright (c) 2007 Reyk Floeter <reyk@openbsd.org> 5 * 6 * Permission to use, copy, modify, and 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 /* 20 * Driver for the Myricom Myri-10G Lanai-Z8E Ethernet chipsets. 21 */ 22 23 #include "bpfilter.h" 24 #include "kstat.h" 25 26 #include <sys/param.h> 27 #include <sys/systm.h> 28 #include <sys/sockio.h> 29 #include <sys/mbuf.h> 30 #include <sys/kernel.h> 31 #include <sys/socket.h> 32 #include <sys/malloc.h> 33 #include <sys/pool.h> 34 #include <sys/timeout.h> 35 #include <sys/device.h> 36 #include <sys/proc.h> 37 #include <sys/queue.h> 38 #include <sys/rwlock.h> 39 #include <sys/kstat.h> 40 41 #include <machine/bus.h> 42 #include <machine/intr.h> 43 44 #include <net/if.h> 45 #include <net/if_dl.h> 46 #include <net/if_media.h> 47 48 #if NBPFILTER > 0 49 #include <net/bpf.h> 50 #endif 51 52 #include <netinet/in.h> 53 #include <netinet/if_ether.h> 54 55 #include <dev/pci/pcireg.h> 56 #include <dev/pci/pcivar.h> 57 #include <dev/pci/pcidevs.h> 58 59 #include <dev/pci/if_myxreg.h> 60 61 #ifdef MYX_DEBUG 62 #define MYXDBG_INIT (1<<0) /* chipset initialization */ 63 #define MYXDBG_CMD (2<<0) /* commands */ 64 #define MYXDBG_INTR (3<<0) /* interrupts */ 65 #define MYXDBG_ALL 0xffff /* enable all debugging messages */ 66 int myx_debug = MYXDBG_ALL; 67 #define DPRINTF(_lvl, _arg...) do { \ 68 if (myx_debug & (_lvl)) \ 69 printf(_arg); \ 70 } while (0) 71 #else 72 #define DPRINTF(_lvl, arg...) 73 #endif 74 75 #define DEVNAME(_s) ((_s)->sc_dev.dv_xname) 76 77 struct myx_dmamem { 78 bus_dmamap_t mxm_map; 79 bus_dma_segment_t mxm_seg; 80 int mxm_nsegs; 81 size_t mxm_size; 82 caddr_t mxm_kva; 83 }; 84 85 struct pool *myx_mcl_pool; 86 87 struct myx_slot { 88 bus_dmamap_t ms_map; 89 struct mbuf *ms_m; 90 }; 91 92 struct myx_rx_ring { 93 struct myx_softc *mrr_softc; 94 struct timeout mrr_refill; 95 struct if_rxring mrr_rxr; 96 struct myx_slot *mrr_slots; 97 u_int32_t mrr_offset; 98 u_int mrr_running; 99 u_int mrr_prod; 100 u_int mrr_cons; 101 struct mbuf *(*mrr_mclget)(void); 102 }; 103 104 enum myx_state { 105 MYX_S_OFF = 0, 106 MYX_S_RUNNING, 107 MYX_S_DOWN 108 }; 109 110 struct myx_softc { 111 struct device sc_dev; 112 struct arpcom sc_ac; 113 114 pci_chipset_tag_t sc_pc; 115 pci_intr_handle_t sc_ih; 116 pcitag_t sc_tag; 117 118 bus_dma_tag_t sc_dmat; 119 bus_space_tag_t sc_memt; 120 bus_space_handle_t sc_memh; 121 bus_size_t sc_mems; 122 123 struct myx_dmamem sc_zerodma; 124 struct myx_dmamem sc_cmddma; 125 struct myx_dmamem sc_paddma; 126 127 struct myx_dmamem sc_sts_dma; 128 volatile struct myx_status *sc_sts; 129 130 int sc_intx; 131 void *sc_irqh; 132 u_int32_t sc_irqcoaloff; 133 u_int32_t sc_irqclaimoff; 134 u_int32_t sc_irqdeassertoff; 135 136 struct myx_dmamem sc_intrq_dma; 137 struct myx_intrq_desc *sc_intrq; 138 u_int sc_intrq_count; 139 u_int sc_intrq_idx; 140 141 u_int sc_rx_ring_count; 142 #define MYX_RXSMALL 0 143 #define MYX_RXBIG 1 144 struct myx_rx_ring sc_rx_ring[2]; 145 146 bus_size_t sc_tx_boundary; 147 u_int sc_tx_ring_count; 148 u_int32_t sc_tx_ring_offset; 149 u_int sc_tx_nsegs; 150 u_int32_t sc_tx_count; /* shadows ms_txdonecnt */ 151 u_int sc_tx_ring_prod; 152 u_int sc_tx_ring_cons; 153 154 u_int sc_tx_prod; 155 u_int sc_tx_cons; 156 struct myx_slot *sc_tx_slots; 157 158 struct ifmedia sc_media; 159 160 volatile enum myx_state sc_state; 161 volatile u_int8_t sc_linkdown; 162 163 struct rwlock sc_sff_lock; 164 165 #if NKSTAT > 0 166 struct mutex sc_kstat_mtx; 167 struct timeout sc_kstat_tmo; 168 struct kstat *sc_kstat; 169 #endif 170 }; 171 172 #define MYX_RXSMALL_SIZE MCLBYTES 173 #define MYX_RXBIG_SIZE (MYX_MTU - \ 174 (ETHER_ALIGN + ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN)) 175 176 int myx_match(struct device *, void *, void *); 177 void myx_attach(struct device *, struct device *, void *); 178 int myx_pcie_dc(struct myx_softc *, struct pci_attach_args *); 179 int myx_query(struct myx_softc *sc, char *, size_t); 180 u_int myx_ether_aton(char *, u_int8_t *, u_int); 181 void myx_attachhook(struct device *); 182 int myx_loadfirmware(struct myx_softc *, const char *); 183 int myx_probe_firmware(struct myx_softc *); 184 185 void myx_read(struct myx_softc *, bus_size_t, void *, bus_size_t); 186 void myx_write(struct myx_softc *, bus_size_t, void *, bus_size_t); 187 188 #if defined(__LP64__) 189 #define _myx_bus_space_write bus_space_write_raw_region_8 190 typedef u_int64_t myx_bus_t; 191 #else 192 #define _myx_bus_space_write bus_space_write_raw_region_4 193 typedef u_int32_t myx_bus_t; 194 #endif 195 #define myx_bus_space_write(_sc, _o, _a, _l) \ 196 _myx_bus_space_write((_sc)->sc_memt, (_sc)->sc_memh, (_o), (_a), (_l)) 197 198 int myx_cmd(struct myx_softc *, u_int32_t, struct myx_cmd *, u_int32_t *); 199 int myx_boot(struct myx_softc *, u_int32_t); 200 201 int myx_rdma(struct myx_softc *, u_int); 202 int myx_dmamem_alloc(struct myx_softc *, struct myx_dmamem *, 203 bus_size_t, u_int align); 204 void myx_dmamem_free(struct myx_softc *, struct myx_dmamem *); 205 int myx_media_change(struct ifnet *); 206 void myx_media_status(struct ifnet *, struct ifmediareq *); 207 void myx_link_state(struct myx_softc *, u_int32_t); 208 void myx_watchdog(struct ifnet *); 209 int myx_ioctl(struct ifnet *, u_long, caddr_t); 210 int myx_rxrinfo(struct myx_softc *, struct if_rxrinfo *); 211 void myx_up(struct myx_softc *); 212 void myx_iff(struct myx_softc *); 213 void myx_down(struct myx_softc *); 214 int myx_get_sffpage(struct myx_softc *, struct if_sffpage *); 215 216 void myx_start(struct ifqueue *); 217 void myx_write_txd_tail(struct myx_softc *, struct myx_slot *, u_int8_t, 218 u_int32_t, u_int); 219 int myx_load_mbuf(struct myx_softc *, struct myx_slot *, struct mbuf *); 220 int myx_setlladdr(struct myx_softc *, u_int32_t, u_int8_t *); 221 int myx_intr(void *); 222 void myx_rxeof(struct myx_softc *); 223 void myx_txeof(struct myx_softc *, u_int32_t); 224 225 int myx_buf_fill(struct myx_softc *, struct myx_slot *, 226 struct mbuf *(*)(void)); 227 struct mbuf * myx_mcl_small(void); 228 struct mbuf * myx_mcl_big(void); 229 230 int myx_rx_init(struct myx_softc *, int, bus_size_t); 231 int myx_rx_fill(struct myx_softc *, struct myx_rx_ring *); 232 void myx_rx_empty(struct myx_softc *, struct myx_rx_ring *); 233 void myx_rx_free(struct myx_softc *, struct myx_rx_ring *); 234 235 int myx_tx_init(struct myx_softc *, bus_size_t); 236 void myx_tx_empty(struct myx_softc *); 237 void myx_tx_free(struct myx_softc *); 238 239 void myx_refill(void *); 240 241 #if NKSTAT > 0 242 void myx_kstat_attach(struct myx_softc *); 243 void myx_kstat_start(struct myx_softc *); 244 void myx_kstat_stop(struct myx_softc *); 245 #endif 246 247 struct cfdriver myx_cd = { 248 NULL, "myx", DV_IFNET 249 }; 250 struct cfattach myx_ca = { 251 sizeof(struct myx_softc), myx_match, myx_attach 252 }; 253 254 const struct pci_matchid myx_devices[] = { 255 { PCI_VENDOR_MYRICOM, PCI_PRODUCT_MYRICOM_Z8E }, 256 { PCI_VENDOR_MYRICOM, PCI_PRODUCT_MYRICOM_Z8E_9 } 257 }; 258 259 int 260 myx_match(struct device *parent, void *match, void *aux) 261 { 262 return (pci_matchbyid(aux, myx_devices, nitems(myx_devices))); 263 } 264 265 void 266 myx_attach(struct device *parent, struct device *self, void *aux) 267 { 268 struct myx_softc *sc = (struct myx_softc *)self; 269 struct pci_attach_args *pa = aux; 270 char part[32]; 271 pcireg_t memtype; 272 273 rw_init(&sc->sc_sff_lock, "myxsff"); 274 275 sc->sc_pc = pa->pa_pc; 276 sc->sc_tag = pa->pa_tag; 277 sc->sc_dmat = pa->pa_dmat; 278 279 sc->sc_rx_ring[MYX_RXSMALL].mrr_softc = sc; 280 sc->sc_rx_ring[MYX_RXSMALL].mrr_mclget = myx_mcl_small; 281 timeout_set(&sc->sc_rx_ring[MYX_RXSMALL].mrr_refill, myx_refill, 282 &sc->sc_rx_ring[MYX_RXSMALL]); 283 sc->sc_rx_ring[MYX_RXBIG].mrr_softc = sc; 284 sc->sc_rx_ring[MYX_RXBIG].mrr_mclget = myx_mcl_big; 285 timeout_set(&sc->sc_rx_ring[MYX_RXBIG].mrr_refill, myx_refill, 286 &sc->sc_rx_ring[MYX_RXBIG]); 287 288 /* Map the PCI memory space */ 289 memtype = pci_mapreg_type(sc->sc_pc, sc->sc_tag, MYXBAR0); 290 if (pci_mapreg_map(pa, MYXBAR0, memtype, BUS_SPACE_MAP_PREFETCHABLE, 291 &sc->sc_memt, &sc->sc_memh, NULL, &sc->sc_mems, 0)) { 292 printf(": unable to map register memory\n"); 293 return; 294 } 295 296 /* Get board details (mac/part) */ 297 memset(part, 0, sizeof(part)); 298 if (myx_query(sc, part, sizeof(part)) != 0) 299 goto unmap; 300 301 /* Map the interrupt */ 302 if (pci_intr_map_msi(pa, &sc->sc_ih) != 0) { 303 if (pci_intr_map(pa, &sc->sc_ih) != 0) { 304 printf(": unable to map interrupt\n"); 305 goto unmap; 306 } 307 sc->sc_intx = 1; 308 } 309 310 printf(": %s, model %s, address %s\n", 311 pci_intr_string(pa->pa_pc, sc->sc_ih), 312 part[0] == '\0' ? "(unknown)" : part, 313 ether_sprintf(sc->sc_ac.ac_enaddr)); 314 315 if (myx_pcie_dc(sc, pa) != 0) 316 printf("%s: unable to configure PCI Express\n", DEVNAME(sc)); 317 318 config_mountroot(self, myx_attachhook); 319 320 return; 321 322 unmap: 323 bus_space_unmap(sc->sc_memt, sc->sc_memh, sc->sc_mems); 324 sc->sc_mems = 0; 325 } 326 327 int 328 myx_pcie_dc(struct myx_softc *sc, struct pci_attach_args *pa) 329 { 330 pcireg_t dcsr; 331 pcireg_t mask = PCI_PCIE_DCSR_MPS | PCI_PCIE_DCSR_ERO; 332 pcireg_t dc = ((fls(4096) - 8) << 12) | PCI_PCIE_DCSR_ERO; 333 int reg; 334 335 if (pci_get_capability(sc->sc_pc, pa->pa_tag, PCI_CAP_PCIEXPRESS, 336 ®, NULL) == 0) 337 return (-1); 338 339 reg += PCI_PCIE_DCSR; 340 dcsr = pci_conf_read(sc->sc_pc, pa->pa_tag, reg); 341 if ((dcsr & mask) != dc) { 342 CLR(dcsr, mask); 343 SET(dcsr, dc); 344 pci_conf_write(sc->sc_pc, pa->pa_tag, reg, dcsr); 345 } 346 347 return (0); 348 } 349 350 u_int 351 myx_ether_aton(char *mac, u_int8_t *lladdr, u_int maxlen) 352 { 353 u_int i, j; 354 u_int8_t digit; 355 356 memset(lladdr, 0, ETHER_ADDR_LEN); 357 for (i = j = 0; mac[i] != '\0' && i < maxlen; i++) { 358 if (mac[i] >= '0' && mac[i] <= '9') 359 digit = mac[i] - '0'; 360 else if (mac[i] >= 'A' && mac[i] <= 'F') 361 digit = mac[i] - 'A' + 10; 362 else if (mac[i] >= 'a' && mac[i] <= 'f') 363 digit = mac[i] - 'a' + 10; 364 else 365 continue; 366 if ((j & 1) == 0) 367 digit <<= 4; 368 lladdr[j++/2] |= digit; 369 } 370 371 return (i); 372 } 373 374 int 375 myx_query(struct myx_softc *sc, char *part, size_t partlen) 376 { 377 struct myx_gen_hdr hdr; 378 u_int32_t offset; 379 u_int8_t strings[MYX_STRING_SPECS_SIZE]; 380 u_int i, len, maxlen; 381 382 myx_read(sc, MYX_HEADER_POS, &offset, sizeof(offset)); 383 offset = betoh32(offset); 384 if (offset + sizeof(hdr) > sc->sc_mems) { 385 printf(": header is outside register window\n"); 386 return (1); 387 } 388 389 myx_read(sc, offset, &hdr, sizeof(hdr)); 390 offset = betoh32(hdr.fw_specs); 391 len = min(betoh32(hdr.fw_specs_len), sizeof(strings)); 392 393 bus_space_read_region_1(sc->sc_memt, sc->sc_memh, offset, strings, len); 394 395 for (i = 0; i < len; i++) { 396 maxlen = len - i; 397 if (strings[i] == '\0') 398 break; 399 if (maxlen > 4 && memcmp("MAC=", &strings[i], 4) == 0) { 400 i += 4; 401 i += myx_ether_aton(&strings[i], 402 sc->sc_ac.ac_enaddr, maxlen); 403 } else if (maxlen > 3 && memcmp("PC=", &strings[i], 3) == 0) { 404 i += 3; 405 i += strlcpy(part, &strings[i], min(maxlen, partlen)); 406 } 407 for (; i < len; i++) { 408 if (strings[i] == '\0') 409 break; 410 } 411 } 412 413 return (0); 414 } 415 416 int 417 myx_loadfirmware(struct myx_softc *sc, const char *filename) 418 { 419 struct myx_gen_hdr hdr; 420 u_int8_t *fw; 421 size_t fwlen; 422 u_int32_t offset; 423 u_int i, ret = 1; 424 425 if (loadfirmware(filename, &fw, &fwlen) != 0) { 426 printf("%s: could not load firmware %s\n", DEVNAME(sc), 427 filename); 428 return (1); 429 } 430 if (fwlen > MYX_SRAM_SIZE || fwlen < MYXFW_MIN_LEN) { 431 printf("%s: invalid firmware %s size\n", DEVNAME(sc), filename); 432 goto err; 433 } 434 435 memcpy(&offset, fw + MYX_HEADER_POS, sizeof(offset)); 436 offset = betoh32(offset); 437 if ((offset + sizeof(hdr)) > fwlen) { 438 printf("%s: invalid firmware %s\n", DEVNAME(sc), filename); 439 goto err; 440 } 441 442 memcpy(&hdr, fw + offset, sizeof(hdr)); 443 DPRINTF(MYXDBG_INIT, "%s: " 444 "fw hdr off %u, length %u, type 0x%x, version %s\n", 445 DEVNAME(sc), offset, betoh32(hdr.fw_hdrlength), 446 betoh32(hdr.fw_type), hdr.fw_version); 447 448 if (betoh32(hdr.fw_type) != MYXFW_TYPE_ETH || 449 memcmp(MYXFW_VER, hdr.fw_version, strlen(MYXFW_VER)) != 0) { 450 printf("%s: invalid firmware type 0x%x version %s\n", 451 DEVNAME(sc), betoh32(hdr.fw_type), hdr.fw_version); 452 goto err; 453 } 454 455 /* Write the firmware to the card's SRAM */ 456 for (i = 0; i < fwlen; i += 256) 457 myx_write(sc, i + MYX_FW, fw + i, min(256, fwlen - i)); 458 459 if (myx_boot(sc, fwlen) != 0) { 460 printf("%s: failed to boot %s\n", DEVNAME(sc), filename); 461 goto err; 462 } 463 464 ret = 0; 465 466 err: 467 free(fw, M_DEVBUF, fwlen); 468 return (ret); 469 } 470 471 void 472 myx_attachhook(struct device *self) 473 { 474 struct myx_softc *sc = (struct myx_softc *)self; 475 struct ifnet *ifp = &sc->sc_ac.ac_if; 476 struct myx_cmd mc; 477 478 /* this is sort of racy */ 479 if (myx_mcl_pool == NULL) { 480 myx_mcl_pool = malloc(sizeof(*myx_mcl_pool), M_DEVBUF, 481 M_WAITOK); 482 483 m_pool_init(myx_mcl_pool, MYX_RXBIG_SIZE, MYX_BOUNDARY, 484 "myxmcl"); 485 pool_cache_init(myx_mcl_pool); 486 } 487 488 /* Allocate command DMA memory */ 489 if (myx_dmamem_alloc(sc, &sc->sc_cmddma, MYXALIGN_CMD, 490 MYXALIGN_CMD) != 0) { 491 printf("%s: failed to allocate command DMA memory\n", 492 DEVNAME(sc)); 493 return; 494 } 495 496 /* Try the firmware stored on disk */ 497 if (myx_loadfirmware(sc, MYXFW_ALIGNED) != 0) { 498 /* error printed by myx_loadfirmware */ 499 goto freecmd; 500 } 501 502 memset(&mc, 0, sizeof(mc)); 503 504 if (myx_cmd(sc, MYXCMD_RESET, &mc, NULL) != 0) { 505 printf("%s: failed to reset the device\n", DEVNAME(sc)); 506 goto freecmd; 507 } 508 509 sc->sc_tx_boundary = 4096; 510 511 if (myx_probe_firmware(sc) != 0) { 512 printf("%s: error while selecting firmware\n", DEVNAME(sc)); 513 goto freecmd; 514 } 515 516 sc->sc_irqh = pci_intr_establish(sc->sc_pc, sc->sc_ih, 517 IPL_NET | IPL_MPSAFE, myx_intr, sc, DEVNAME(sc)); 518 if (sc->sc_irqh == NULL) { 519 printf("%s: unable to establish interrupt\n", DEVNAME(sc)); 520 goto freecmd; 521 } 522 523 #if NKSTAT > 0 524 myx_kstat_attach(sc); 525 #endif 526 527 ifp->if_softc = sc; 528 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 529 ifp->if_xflags = IFXF_MPSAFE; 530 ifp->if_ioctl = myx_ioctl; 531 ifp->if_qstart = myx_start; 532 ifp->if_watchdog = myx_watchdog; 533 ifp->if_hardmtu = MYX_RXBIG_SIZE; 534 strlcpy(ifp->if_xname, DEVNAME(sc), IFNAMSIZ); 535 ifq_set_maxlen(&ifp->if_snd, 1); 536 537 ifp->if_capabilities = IFCAP_VLAN_MTU; 538 #if 0 539 ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING; 540 ifp->if_capabilities |= IFCAP_CSUM_IPv4 | IFCAP_CSUM_TCPv4 | 541 IFCAP_CSUM_UDPv4; 542 #endif 543 544 ifmedia_init(&sc->sc_media, 0, myx_media_change, myx_media_status); 545 ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_AUTO, 0, NULL); 546 ifmedia_set(&sc->sc_media, IFM_ETHER | IFM_AUTO); 547 548 if_attach(ifp); 549 ether_ifattach(ifp); 550 551 return; 552 553 freecmd: 554 myx_dmamem_free(sc, &sc->sc_cmddma); 555 } 556 557 int 558 myx_probe_firmware(struct myx_softc *sc) 559 { 560 struct myx_dmamem test; 561 bus_dmamap_t map; 562 struct myx_cmd mc; 563 pcireg_t csr; 564 int offset; 565 int width = 0; 566 567 if (pci_get_capability(sc->sc_pc, sc->sc_tag, PCI_CAP_PCIEXPRESS, 568 &offset, NULL)) { 569 csr = pci_conf_read(sc->sc_pc, sc->sc_tag, 570 offset + PCI_PCIE_LCSR); 571 width = (csr >> 20) & 0x3f; 572 573 if (width <= 4) { 574 /* 575 * if the link width is 4 or less we can use the 576 * aligned firmware. 577 */ 578 return (0); 579 } 580 } 581 582 if (myx_dmamem_alloc(sc, &test, 4096, 4096) != 0) 583 return (1); 584 map = test.mxm_map; 585 586 bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize, 587 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 588 589 memset(&mc, 0, sizeof(mc)); 590 mc.mc_data0 = htobe32(MYX_ADDRLOW(map->dm_segs[0].ds_addr)); 591 mc.mc_data1 = htobe32(MYX_ADDRHIGH(map->dm_segs[0].ds_addr)); 592 mc.mc_data2 = htobe32(4096 * 0x10000); 593 if (myx_cmd(sc, MYXCMD_UNALIGNED_DMA_TEST, &mc, NULL) != 0) { 594 printf("%s: DMA read test failed\n", DEVNAME(sc)); 595 goto fail; 596 } 597 598 memset(&mc, 0, sizeof(mc)); 599 mc.mc_data0 = htobe32(MYX_ADDRLOW(map->dm_segs[0].ds_addr)); 600 mc.mc_data1 = htobe32(MYX_ADDRHIGH(map->dm_segs[0].ds_addr)); 601 mc.mc_data2 = htobe32(4096 * 0x1); 602 if (myx_cmd(sc, MYXCMD_UNALIGNED_DMA_TEST, &mc, NULL) != 0) { 603 printf("%s: DMA write test failed\n", DEVNAME(sc)); 604 goto fail; 605 } 606 607 memset(&mc, 0, sizeof(mc)); 608 mc.mc_data0 = htobe32(MYX_ADDRLOW(map->dm_segs[0].ds_addr)); 609 mc.mc_data1 = htobe32(MYX_ADDRHIGH(map->dm_segs[0].ds_addr)); 610 mc.mc_data2 = htobe32(4096 * 0x10001); 611 if (myx_cmd(sc, MYXCMD_UNALIGNED_DMA_TEST, &mc, NULL) != 0) { 612 printf("%s: DMA read/write test failed\n", DEVNAME(sc)); 613 goto fail; 614 } 615 616 bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize, 617 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 618 myx_dmamem_free(sc, &test); 619 return (0); 620 621 fail: 622 bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize, 623 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 624 myx_dmamem_free(sc, &test); 625 626 if (myx_loadfirmware(sc, MYXFW_UNALIGNED) != 0) { 627 printf("%s: unable to load %s\n", DEVNAME(sc), 628 MYXFW_UNALIGNED); 629 return (1); 630 } 631 632 sc->sc_tx_boundary = 2048; 633 634 printf("%s: using unaligned firmware\n", DEVNAME(sc)); 635 return (0); 636 } 637 638 void 639 myx_read(struct myx_softc *sc, bus_size_t off, void *ptr, bus_size_t len) 640 { 641 bus_space_barrier(sc->sc_memt, sc->sc_memh, off, len, 642 BUS_SPACE_BARRIER_READ); 643 bus_space_read_raw_region_4(sc->sc_memt, sc->sc_memh, off, ptr, len); 644 } 645 646 void 647 myx_write(struct myx_softc *sc, bus_size_t off, void *ptr, bus_size_t len) 648 { 649 bus_space_write_raw_region_4(sc->sc_memt, sc->sc_memh, off, ptr, len); 650 bus_space_barrier(sc->sc_memt, sc->sc_memh, off, len, 651 BUS_SPACE_BARRIER_WRITE); 652 } 653 654 int 655 myx_dmamem_alloc(struct myx_softc *sc, struct myx_dmamem *mxm, 656 bus_size_t size, u_int align) 657 { 658 mxm->mxm_size = size; 659 660 if (bus_dmamap_create(sc->sc_dmat, mxm->mxm_size, 1, 661 mxm->mxm_size, 0, BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW, 662 &mxm->mxm_map) != 0) 663 return (1); 664 if (bus_dmamem_alloc(sc->sc_dmat, mxm->mxm_size, 665 align, 0, &mxm->mxm_seg, 1, &mxm->mxm_nsegs, 666 BUS_DMA_WAITOK | BUS_DMA_ZERO) != 0) 667 goto destroy; 668 if (bus_dmamem_map(sc->sc_dmat, &mxm->mxm_seg, mxm->mxm_nsegs, 669 mxm->mxm_size, &mxm->mxm_kva, BUS_DMA_WAITOK) != 0) 670 goto free; 671 if (bus_dmamap_load(sc->sc_dmat, mxm->mxm_map, mxm->mxm_kva, 672 mxm->mxm_size, NULL, BUS_DMA_WAITOK) != 0) 673 goto unmap; 674 675 return (0); 676 unmap: 677 bus_dmamem_unmap(sc->sc_dmat, mxm->mxm_kva, mxm->mxm_size); 678 free: 679 bus_dmamem_free(sc->sc_dmat, &mxm->mxm_seg, 1); 680 destroy: 681 bus_dmamap_destroy(sc->sc_dmat, mxm->mxm_map); 682 return (1); 683 } 684 685 void 686 myx_dmamem_free(struct myx_softc *sc, struct myx_dmamem *mxm) 687 { 688 bus_dmamap_unload(sc->sc_dmat, mxm->mxm_map); 689 bus_dmamem_unmap(sc->sc_dmat, mxm->mxm_kva, mxm->mxm_size); 690 bus_dmamem_free(sc->sc_dmat, &mxm->mxm_seg, 1); 691 bus_dmamap_destroy(sc->sc_dmat, mxm->mxm_map); 692 } 693 694 int 695 myx_cmd(struct myx_softc *sc, u_int32_t cmd, struct myx_cmd *mc, u_int32_t *r) 696 { 697 bus_dmamap_t map = sc->sc_cmddma.mxm_map; 698 struct myx_response *mr; 699 u_int i; 700 u_int32_t result, data; 701 702 mc->mc_cmd = htobe32(cmd); 703 mc->mc_addr_high = htobe32(MYX_ADDRHIGH(map->dm_segs[0].ds_addr)); 704 mc->mc_addr_low = htobe32(MYX_ADDRLOW(map->dm_segs[0].ds_addr)); 705 706 mr = (struct myx_response *)sc->sc_cmddma.mxm_kva; 707 mr->mr_result = 0xffffffff; 708 709 /* Send command */ 710 myx_write(sc, MYX_CMD, (u_int8_t *)mc, sizeof(struct myx_cmd)); 711 bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize, 712 BUS_DMASYNC_PREREAD); 713 714 for (i = 0; i < 20; i++) { 715 bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize, 716 BUS_DMASYNC_POSTREAD); 717 result = betoh32(mr->mr_result); 718 data = betoh32(mr->mr_data); 719 720 if (result != 0xffffffff) 721 break; 722 723 bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize, 724 BUS_DMASYNC_PREREAD); 725 delay(1000); 726 } 727 728 DPRINTF(MYXDBG_CMD, "%s(%s): cmd %u completed, i %d, " 729 "result 0x%x, data 0x%x (%u)\n", DEVNAME(sc), __func__, 730 cmd, i, result, data, data); 731 732 if (result == MYXCMD_OK) { 733 if (r != NULL) 734 *r = data; 735 } 736 737 return (result); 738 } 739 740 int 741 myx_boot(struct myx_softc *sc, u_int32_t length) 742 { 743 struct myx_bootcmd bc; 744 bus_dmamap_t map = sc->sc_cmddma.mxm_map; 745 u_int32_t *status; 746 u_int i, ret = 1; 747 748 memset(&bc, 0, sizeof(bc)); 749 bc.bc_addr_high = htobe32(MYX_ADDRHIGH(map->dm_segs[0].ds_addr)); 750 bc.bc_addr_low = htobe32(MYX_ADDRLOW(map->dm_segs[0].ds_addr)); 751 bc.bc_result = 0xffffffff; 752 bc.bc_offset = htobe32(MYX_FW_BOOT); 753 bc.bc_length = htobe32(length - 8); 754 bc.bc_copyto = htobe32(8); 755 bc.bc_jumpto = htobe32(0); 756 757 status = (u_int32_t *)sc->sc_cmddma.mxm_kva; 758 *status = 0; 759 760 /* Send command */ 761 myx_write(sc, MYX_BOOT, &bc, sizeof(bc)); 762 bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize, 763 BUS_DMASYNC_PREREAD); 764 765 for (i = 0; i < 200; i++) { 766 bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize, 767 BUS_DMASYNC_POSTREAD); 768 if (*status == 0xffffffff) { 769 ret = 0; 770 break; 771 } 772 773 bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize, 774 BUS_DMASYNC_PREREAD); 775 delay(1000); 776 } 777 778 DPRINTF(MYXDBG_CMD, "%s: boot completed, i %d, result %d\n", 779 DEVNAME(sc), i, ret); 780 781 return (ret); 782 } 783 784 int 785 myx_rdma(struct myx_softc *sc, u_int do_enable) 786 { 787 struct myx_rdmacmd rc; 788 bus_dmamap_t map = sc->sc_cmddma.mxm_map; 789 bus_dmamap_t pad = sc->sc_paddma.mxm_map; 790 u_int32_t *status; 791 int ret = 1; 792 u_int i; 793 794 /* 795 * It is required to setup a _dummy_ RDMA address. It also makes 796 * some PCI-E chipsets resend dropped messages. 797 */ 798 rc.rc_addr_high = htobe32(MYX_ADDRHIGH(map->dm_segs[0].ds_addr)); 799 rc.rc_addr_low = htobe32(MYX_ADDRLOW(map->dm_segs[0].ds_addr)); 800 rc.rc_result = 0xffffffff; 801 rc.rc_rdma_high = htobe32(MYX_ADDRHIGH(pad->dm_segs[0].ds_addr)); 802 rc.rc_rdma_low = htobe32(MYX_ADDRLOW(pad->dm_segs[0].ds_addr)); 803 rc.rc_enable = htobe32(do_enable); 804 805 status = (u_int32_t *)sc->sc_cmddma.mxm_kva; 806 *status = 0; 807 808 bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize, 809 BUS_DMASYNC_PREREAD); 810 811 /* Send command */ 812 myx_write(sc, MYX_RDMA, &rc, sizeof(rc)); 813 814 for (i = 0; i < 20; i++) { 815 bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize, 816 BUS_DMASYNC_POSTREAD); 817 818 if (*status == 0xffffffff) { 819 ret = 0; 820 break; 821 } 822 823 bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize, 824 BUS_DMASYNC_PREREAD); 825 delay(1000); 826 } 827 828 DPRINTF(MYXDBG_CMD, "%s(%s): dummy RDMA %s, i %d, result 0x%x\n", 829 DEVNAME(sc), __func__, 830 do_enable ? "enabled" : "disabled", i, betoh32(*status)); 831 832 return (ret); 833 } 834 835 int 836 myx_media_change(struct ifnet *ifp) 837 { 838 /* ignore */ 839 return (0); 840 } 841 842 void 843 myx_media_status(struct ifnet *ifp, struct ifmediareq *imr) 844 { 845 struct myx_softc *sc = (struct myx_softc *)ifp->if_softc; 846 bus_dmamap_t map = sc->sc_sts_dma.mxm_map; 847 u_int32_t sts; 848 849 imr->ifm_active = IFM_ETHER | IFM_AUTO; 850 if (!ISSET(ifp->if_flags, IFF_RUNNING)) { 851 imr->ifm_status = 0; 852 return; 853 } 854 855 bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize, 856 BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 857 sts = sc->sc_sts->ms_linkstate; 858 bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize, 859 BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 860 861 myx_link_state(sc, sts); 862 863 imr->ifm_status = IFM_AVALID; 864 if (!LINK_STATE_IS_UP(ifp->if_link_state)) 865 return; 866 867 imr->ifm_active |= IFM_FDX | IFM_FLOW | 868 IFM_ETH_RXPAUSE | IFM_ETH_TXPAUSE; 869 imr->ifm_status |= IFM_ACTIVE; 870 } 871 872 void 873 myx_link_state(struct myx_softc *sc, u_int32_t sts) 874 { 875 struct ifnet *ifp = &sc->sc_ac.ac_if; 876 int link_state = LINK_STATE_DOWN; 877 878 if (betoh32(sts) == MYXSTS_LINKUP) 879 link_state = LINK_STATE_FULL_DUPLEX; 880 if (ifp->if_link_state != link_state) { 881 ifp->if_link_state = link_state; 882 if_link_state_change(ifp); 883 ifp->if_baudrate = LINK_STATE_IS_UP(ifp->if_link_state) ? 884 IF_Gbps(10) : 0; 885 } 886 } 887 888 void 889 myx_watchdog(struct ifnet *ifp) 890 { 891 return; 892 } 893 894 int 895 myx_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 896 { 897 struct myx_softc *sc = (struct myx_softc *)ifp->if_softc; 898 struct ifreq *ifr = (struct ifreq *)data; 899 int s, error = 0; 900 901 s = splnet(); 902 903 switch (cmd) { 904 case SIOCSIFADDR: 905 ifp->if_flags |= IFF_UP; 906 /* FALLTHROUGH */ 907 908 case SIOCSIFFLAGS: 909 if (ISSET(ifp->if_flags, IFF_UP)) { 910 if (ISSET(ifp->if_flags, IFF_RUNNING)) 911 error = ENETRESET; 912 else 913 myx_up(sc); 914 } else { 915 if (ISSET(ifp->if_flags, IFF_RUNNING)) 916 myx_down(sc); 917 } 918 break; 919 920 case SIOCGIFMEDIA: 921 case SIOCSIFMEDIA: 922 error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd); 923 break; 924 925 case SIOCGIFRXR: 926 error = myx_rxrinfo(sc, (struct if_rxrinfo *)ifr->ifr_data); 927 break; 928 929 case SIOCGIFSFFPAGE: 930 error = rw_enter(&sc->sc_sff_lock, RW_WRITE|RW_INTR); 931 if (error != 0) 932 break; 933 934 error = myx_get_sffpage(sc, (struct if_sffpage *)data); 935 rw_exit(&sc->sc_sff_lock); 936 break; 937 938 default: 939 error = ether_ioctl(ifp, &sc->sc_ac, cmd, data); 940 } 941 942 if (error == ENETRESET) { 943 if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == 944 (IFF_UP | IFF_RUNNING)) 945 myx_iff(sc); 946 error = 0; 947 } 948 949 splx(s); 950 return (error); 951 } 952 953 int 954 myx_rxrinfo(struct myx_softc *sc, struct if_rxrinfo *ifri) 955 { 956 struct if_rxring_info ifr[2]; 957 958 memset(ifr, 0, sizeof(ifr)); 959 960 ifr[0].ifr_size = MYX_RXSMALL_SIZE; 961 ifr[0].ifr_info = sc->sc_rx_ring[0].mrr_rxr; 962 strlcpy(ifr[0].ifr_name, "small", sizeof(ifr[0].ifr_name)); 963 964 ifr[1].ifr_size = MYX_RXBIG_SIZE; 965 ifr[1].ifr_info = sc->sc_rx_ring[1].mrr_rxr; 966 strlcpy(ifr[1].ifr_name, "large", sizeof(ifr[1].ifr_name)); 967 968 return (if_rxr_info_ioctl(ifri, nitems(ifr), ifr)); 969 } 970 971 static int 972 myx_i2c_byte(struct myx_softc *sc, uint8_t addr, uint8_t off, uint8_t *byte) 973 { 974 struct myx_cmd mc; 975 int result; 976 uint32_t r; 977 unsigned int ms; 978 979 memset(&mc, 0, sizeof(mc)); 980 mc.mc_data0 = htobe32(0); /* get 1 byte */ 981 mc.mc_data1 = htobe32((addr << 8) | off); 982 result = myx_cmd(sc, MYXCMD_I2C_READ, &mc, NULL); 983 if (result != 0) 984 return (EIO); 985 986 for (ms = 0; ms < 50; ms++) { 987 memset(&mc, 0, sizeof(mc)); 988 mc.mc_data0 = htobe32(off); 989 result = myx_cmd(sc, MYXCMD_I2C_BYTE, &mc, &r); 990 switch (result) { 991 case MYXCMD_OK: 992 *byte = r; 993 return (0); 994 case MYXCMD_ERR_BUSY: 995 break; 996 default: 997 return (EIO); 998 } 999 1000 delay(1000); 1001 } 1002 1003 return (EBUSY); 1004 } 1005 1006 int 1007 myx_get_sffpage(struct myx_softc *sc, struct if_sffpage *sff) 1008 { 1009 unsigned int i; 1010 int result; 1011 1012 if (sff->sff_addr == IFSFF_ADDR_EEPROM) { 1013 uint8_t page; 1014 1015 result = myx_i2c_byte(sc, IFSFF_ADDR_EEPROM, 127, &page); 1016 if (result != 0) 1017 return (result); 1018 1019 if (page != sff->sff_page) 1020 return (ENXIO); 1021 } 1022 1023 for (i = 0; i < sizeof(sff->sff_data); i++) { 1024 result = myx_i2c_byte(sc, sff->sff_addr, 1025 i, &sff->sff_data[i]); 1026 if (result != 0) 1027 return (result); 1028 } 1029 1030 return (0); 1031 } 1032 1033 void 1034 myx_up(struct myx_softc *sc) 1035 { 1036 struct ifnet *ifp = &sc->sc_ac.ac_if; 1037 struct myx_cmd mc; 1038 bus_dmamap_t map; 1039 size_t size; 1040 u_int maxpkt; 1041 u_int32_t r; 1042 1043 memset(&mc, 0, sizeof(mc)); 1044 if (myx_cmd(sc, MYXCMD_RESET, &mc, NULL) != 0) { 1045 printf("%s: failed to reset the device\n", DEVNAME(sc)); 1046 return; 1047 } 1048 1049 if (myx_dmamem_alloc(sc, &sc->sc_zerodma, 1050 64, MYXALIGN_CMD) != 0) { 1051 printf("%s: failed to allocate zero pad memory\n", 1052 DEVNAME(sc)); 1053 return; 1054 } 1055 memset(sc->sc_zerodma.mxm_kva, 0, 64); 1056 bus_dmamap_sync(sc->sc_dmat, sc->sc_zerodma.mxm_map, 0, 1057 sc->sc_zerodma.mxm_map->dm_mapsize, BUS_DMASYNC_PREREAD); 1058 1059 if (myx_dmamem_alloc(sc, &sc->sc_paddma, 1060 MYXALIGN_CMD, MYXALIGN_CMD) != 0) { 1061 printf("%s: failed to allocate pad DMA memory\n", 1062 DEVNAME(sc)); 1063 goto free_zero; 1064 } 1065 bus_dmamap_sync(sc->sc_dmat, sc->sc_paddma.mxm_map, 0, 1066 sc->sc_paddma.mxm_map->dm_mapsize, 1067 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1068 1069 if (myx_rdma(sc, MYXRDMA_ON) != 0) { 1070 printf("%s: failed to enable dummy RDMA\n", DEVNAME(sc)); 1071 goto free_pad; 1072 } 1073 1074 if (myx_cmd(sc, MYXCMD_GET_RXRINGSZ, &mc, &r) != 0) { 1075 printf("%s: unable to get rx ring size\n", DEVNAME(sc)); 1076 goto free_pad; 1077 } 1078 sc->sc_rx_ring_count = r / sizeof(struct myx_rx_desc); 1079 1080 memset(&mc, 0, sizeof(mc)); 1081 if (myx_cmd(sc, MYXCMD_GET_TXRINGSZ, &mc, &r) != 0) { 1082 printf("%s: unable to get tx ring size\n", DEVNAME(sc)); 1083 goto free_pad; 1084 } 1085 sc->sc_tx_ring_prod = 0; 1086 sc->sc_tx_ring_cons = 0; 1087 sc->sc_tx_ring_count = r / sizeof(struct myx_tx_desc); 1088 sc->sc_tx_nsegs = min(16, sc->sc_tx_ring_count / 4); /* magic */ 1089 sc->sc_tx_count = 0; 1090 ifq_set_maxlen(&ifp->if_snd, sc->sc_tx_ring_count - 1); 1091 1092 /* Allocate Interrupt Queue */ 1093 1094 sc->sc_intrq_count = sc->sc_rx_ring_count * 2; 1095 sc->sc_intrq_idx = 0; 1096 1097 size = sc->sc_intrq_count * sizeof(struct myx_intrq_desc); 1098 if (myx_dmamem_alloc(sc, &sc->sc_intrq_dma, 1099 size, MYXALIGN_DATA) != 0) { 1100 goto free_pad; 1101 } 1102 sc->sc_intrq = (struct myx_intrq_desc *)sc->sc_intrq_dma.mxm_kva; 1103 map = sc->sc_intrq_dma.mxm_map; 1104 memset(sc->sc_intrq, 0, size); 1105 bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize, 1106 BUS_DMASYNC_PREREAD); 1107 1108 memset(&mc, 0, sizeof(mc)); 1109 mc.mc_data0 = htobe32(size); 1110 if (myx_cmd(sc, MYXCMD_SET_INTRQSZ, &mc, NULL) != 0) { 1111 printf("%s: failed to set intrq size\n", DEVNAME(sc)); 1112 goto free_intrq; 1113 } 1114 1115 memset(&mc, 0, sizeof(mc)); 1116 mc.mc_data0 = htobe32(MYX_ADDRLOW(map->dm_segs[0].ds_addr)); 1117 mc.mc_data1 = htobe32(MYX_ADDRHIGH(map->dm_segs[0].ds_addr)); 1118 if (myx_cmd(sc, MYXCMD_SET_INTRQDMA, &mc, NULL) != 0) { 1119 printf("%s: failed to set intrq address\n", DEVNAME(sc)); 1120 goto free_intrq; 1121 } 1122 1123 /* 1124 * get interrupt offsets 1125 */ 1126 1127 memset(&mc, 0, sizeof(mc)); 1128 if (myx_cmd(sc, MYXCMD_GET_INTRACKOFF, &mc, 1129 &sc->sc_irqclaimoff) != 0) { 1130 printf("%s: failed to get IRQ ack offset\n", DEVNAME(sc)); 1131 goto free_intrq; 1132 } 1133 1134 memset(&mc, 0, sizeof(mc)); 1135 if (myx_cmd(sc, MYXCMD_GET_INTRDEASSERTOFF, &mc, 1136 &sc->sc_irqdeassertoff) != 0) { 1137 printf("%s: failed to get IRQ deassert offset\n", DEVNAME(sc)); 1138 goto free_intrq; 1139 } 1140 1141 memset(&mc, 0, sizeof(mc)); 1142 if (myx_cmd(sc, MYXCMD_GET_INTRCOALDELAYOFF, &mc, 1143 &sc->sc_irqcoaloff) != 0) { 1144 printf("%s: failed to get IRQ coal offset\n", DEVNAME(sc)); 1145 goto free_intrq; 1146 } 1147 1148 /* Set an appropriate interrupt coalescing period */ 1149 r = htobe32(MYX_IRQCOALDELAY); 1150 myx_write(sc, sc->sc_irqcoaloff, &r, sizeof(r)); 1151 1152 if (myx_setlladdr(sc, MYXCMD_SET_LLADDR, LLADDR(ifp->if_sadl)) != 0) { 1153 printf("%s: failed to configure lladdr\n", DEVNAME(sc)); 1154 goto free_intrq; 1155 } 1156 1157 memset(&mc, 0, sizeof(mc)); 1158 if (myx_cmd(sc, MYXCMD_UNSET_PROMISC, &mc, NULL) != 0) { 1159 printf("%s: failed to disable promisc mode\n", DEVNAME(sc)); 1160 goto free_intrq; 1161 } 1162 1163 memset(&mc, 0, sizeof(mc)); 1164 if (myx_cmd(sc, MYXCMD_FC_DEFAULT, &mc, NULL) != 0) { 1165 printf("%s: failed to configure flow control\n", DEVNAME(sc)); 1166 goto free_intrq; 1167 } 1168 1169 memset(&mc, 0, sizeof(mc)); 1170 if (myx_cmd(sc, MYXCMD_GET_TXRINGOFF, &mc, 1171 &sc->sc_tx_ring_offset) != 0) { 1172 printf("%s: unable to get tx ring offset\n", DEVNAME(sc)); 1173 goto free_intrq; 1174 } 1175 1176 memset(&mc, 0, sizeof(mc)); 1177 if (myx_cmd(sc, MYXCMD_GET_RXSMALLRINGOFF, &mc, 1178 &sc->sc_rx_ring[MYX_RXSMALL].mrr_offset) != 0) { 1179 printf("%s: unable to get small rx ring offset\n", DEVNAME(sc)); 1180 goto free_intrq; 1181 } 1182 1183 memset(&mc, 0, sizeof(mc)); 1184 if (myx_cmd(sc, MYXCMD_GET_RXBIGRINGOFF, &mc, 1185 &sc->sc_rx_ring[MYX_RXBIG].mrr_offset) != 0) { 1186 printf("%s: unable to get big rx ring offset\n", DEVNAME(sc)); 1187 goto free_intrq; 1188 } 1189 1190 /* Allocate Interrupt Data */ 1191 if (myx_dmamem_alloc(sc, &sc->sc_sts_dma, 1192 sizeof(struct myx_status), MYXALIGN_DATA) != 0) { 1193 printf("%s: failed to allocate status DMA memory\n", 1194 DEVNAME(sc)); 1195 goto free_intrq; 1196 } 1197 sc->sc_sts = (struct myx_status *)sc->sc_sts_dma.mxm_kva; 1198 map = sc->sc_sts_dma.mxm_map; 1199 bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize, 1200 BUS_DMASYNC_PREREAD); 1201 1202 memset(&mc, 0, sizeof(mc)); 1203 mc.mc_data0 = htobe32(MYX_ADDRLOW(map->dm_segs[0].ds_addr)); 1204 mc.mc_data1 = htobe32(MYX_ADDRHIGH(map->dm_segs[0].ds_addr)); 1205 mc.mc_data2 = htobe32(sizeof(struct myx_status)); 1206 if (myx_cmd(sc, MYXCMD_SET_STATSDMA, &mc, NULL) != 0) { 1207 printf("%s: failed to set status DMA offset\n", DEVNAME(sc)); 1208 goto free_sts; 1209 } 1210 1211 maxpkt = ifp->if_hardmtu + ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN; 1212 1213 memset(&mc, 0, sizeof(mc)); 1214 mc.mc_data0 = htobe32(maxpkt); 1215 if (myx_cmd(sc, MYXCMD_SET_MTU, &mc, NULL) != 0) { 1216 printf("%s: failed to set MTU size %d\n", DEVNAME(sc), maxpkt); 1217 goto free_sts; 1218 } 1219 1220 if (myx_tx_init(sc, maxpkt) != 0) 1221 goto free_sts; 1222 1223 if (myx_rx_init(sc, MYX_RXSMALL, MCLBYTES) != 0) 1224 goto free_tx_ring; 1225 1226 if (myx_rx_fill(sc, &sc->sc_rx_ring[MYX_RXSMALL]) != 0) 1227 goto free_rx_ring_small; 1228 1229 if (myx_rx_init(sc, MYX_RXBIG, MYX_RXBIG_SIZE) != 0) 1230 goto empty_rx_ring_small; 1231 1232 if (myx_rx_fill(sc, &sc->sc_rx_ring[MYX_RXBIG]) != 0) 1233 goto free_rx_ring_big; 1234 1235 memset(&mc, 0, sizeof(mc)); 1236 mc.mc_data0 = htobe32(MYX_RXSMALL_SIZE - ETHER_ALIGN); 1237 if (myx_cmd(sc, MYXCMD_SET_SMALLBUFSZ, &mc, NULL) != 0) { 1238 printf("%s: failed to set small buf size\n", DEVNAME(sc)); 1239 goto empty_rx_ring_big; 1240 } 1241 1242 memset(&mc, 0, sizeof(mc)); 1243 mc.mc_data0 = htobe32(16384); 1244 if (myx_cmd(sc, MYXCMD_SET_BIGBUFSZ, &mc, NULL) != 0) { 1245 printf("%s: failed to set big buf size\n", DEVNAME(sc)); 1246 goto empty_rx_ring_big; 1247 } 1248 1249 sc->sc_state = MYX_S_RUNNING; 1250 1251 if (myx_cmd(sc, MYXCMD_SET_IFUP, &mc, NULL) != 0) { 1252 printf("%s: failed to start the device\n", DEVNAME(sc)); 1253 goto empty_rx_ring_big; 1254 } 1255 1256 myx_iff(sc); 1257 SET(ifp->if_flags, IFF_RUNNING); 1258 ifq_restart(&ifp->if_snd); 1259 1260 #if NKSTAT > 0 1261 timeout_add_sec(&sc->sc_kstat_tmo, 1); 1262 #endif 1263 1264 return; 1265 1266 empty_rx_ring_big: 1267 myx_rx_empty(sc, &sc->sc_rx_ring[MYX_RXBIG]); 1268 free_rx_ring_big: 1269 myx_rx_free(sc, &sc->sc_rx_ring[MYX_RXBIG]); 1270 empty_rx_ring_small: 1271 myx_rx_empty(sc, &sc->sc_rx_ring[MYX_RXSMALL]); 1272 free_rx_ring_small: 1273 myx_rx_free(sc, &sc->sc_rx_ring[MYX_RXSMALL]); 1274 free_tx_ring: 1275 myx_tx_free(sc); 1276 free_sts: 1277 bus_dmamap_sync(sc->sc_dmat, sc->sc_sts_dma.mxm_map, 0, 1278 sc->sc_sts_dma.mxm_map->dm_mapsize, BUS_DMASYNC_POSTREAD); 1279 myx_dmamem_free(sc, &sc->sc_sts_dma); 1280 free_intrq: 1281 bus_dmamap_sync(sc->sc_dmat, sc->sc_intrq_dma.mxm_map, 0, 1282 sc->sc_intrq_dma.mxm_map->dm_mapsize, BUS_DMASYNC_POSTREAD); 1283 myx_dmamem_free(sc, &sc->sc_intrq_dma); 1284 free_pad: 1285 bus_dmamap_sync(sc->sc_dmat, sc->sc_paddma.mxm_map, 0, 1286 sc->sc_paddma.mxm_map->dm_mapsize, 1287 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 1288 myx_dmamem_free(sc, &sc->sc_paddma); 1289 1290 memset(&mc, 0, sizeof(mc)); 1291 if (myx_cmd(sc, MYXCMD_RESET, &mc, NULL) != 0) { 1292 printf("%s: failed to reset the device\n", DEVNAME(sc)); 1293 } 1294 free_zero: 1295 bus_dmamap_sync(sc->sc_dmat, sc->sc_zerodma.mxm_map, 0, 1296 sc->sc_zerodma.mxm_map->dm_mapsize, BUS_DMASYNC_POSTREAD); 1297 myx_dmamem_free(sc, &sc->sc_zerodma); 1298 } 1299 1300 int 1301 myx_setlladdr(struct myx_softc *sc, u_int32_t cmd, u_int8_t *addr) 1302 { 1303 struct myx_cmd mc; 1304 1305 memset(&mc, 0, sizeof(mc)); 1306 mc.mc_data0 = htobe32(addr[0] << 24 | addr[1] << 16 | 1307 addr[2] << 8 | addr[3]); 1308 mc.mc_data1 = htobe32(addr[4] << 8 | addr[5]); 1309 1310 if (myx_cmd(sc, cmd, &mc, NULL) != 0) { 1311 printf("%s: failed to set the lladdr\n", DEVNAME(sc)); 1312 return (-1); 1313 } 1314 return (0); 1315 } 1316 1317 void 1318 myx_iff(struct myx_softc *sc) 1319 { 1320 struct myx_cmd mc; 1321 struct ifnet *ifp = &sc->sc_ac.ac_if; 1322 struct ether_multi *enm; 1323 struct ether_multistep step; 1324 u_int8_t *addr; 1325 1326 CLR(ifp->if_flags, IFF_ALLMULTI); 1327 1328 if (myx_cmd(sc, ISSET(ifp->if_flags, IFF_PROMISC) ? 1329 MYXCMD_SET_PROMISC : MYXCMD_UNSET_PROMISC, &mc, NULL) != 0) { 1330 printf("%s: failed to configure promisc mode\n", DEVNAME(sc)); 1331 return; 1332 } 1333 1334 if (myx_cmd(sc, MYXCMD_SET_ALLMULTI, &mc, NULL) != 0) { 1335 printf("%s: failed to enable ALLMULTI\n", DEVNAME(sc)); 1336 return; 1337 } 1338 1339 if (myx_cmd(sc, MYXCMD_UNSET_MCAST, &mc, NULL) != 0) { 1340 printf("%s: failed to leave all mcast groups \n", DEVNAME(sc)); 1341 return; 1342 } 1343 1344 if (ISSET(ifp->if_flags, IFF_PROMISC) || 1345 sc->sc_ac.ac_multirangecnt > 0) { 1346 SET(ifp->if_flags, IFF_ALLMULTI); 1347 return; 1348 } 1349 1350 ETHER_FIRST_MULTI(step, &sc->sc_ac, enm); 1351 while (enm != NULL) { 1352 addr = enm->enm_addrlo; 1353 1354 memset(&mc, 0, sizeof(mc)); 1355 mc.mc_data0 = htobe32(addr[0] << 24 | addr[1] << 16 | 1356 addr[2] << 8 | addr[3]); 1357 mc.mc_data1 = htobe32(addr[4] << 24 | addr[5] << 16); 1358 if (myx_cmd(sc, MYXCMD_SET_MCASTGROUP, &mc, NULL) != 0) { 1359 printf("%s: failed to join mcast group\n", DEVNAME(sc)); 1360 return; 1361 } 1362 1363 ETHER_NEXT_MULTI(step, enm); 1364 } 1365 1366 memset(&mc, 0, sizeof(mc)); 1367 if (myx_cmd(sc, MYXCMD_UNSET_ALLMULTI, &mc, NULL) != 0) { 1368 printf("%s: failed to disable ALLMULTI\n", DEVNAME(sc)); 1369 return; 1370 } 1371 } 1372 1373 void 1374 myx_down(struct myx_softc *sc) 1375 { 1376 struct ifnet *ifp = &sc->sc_ac.ac_if; 1377 volatile struct myx_status *sts = sc->sc_sts; 1378 bus_dmamap_t map = sc->sc_sts_dma.mxm_map; 1379 struct sleep_state sls; 1380 struct myx_cmd mc; 1381 int s; 1382 int ring; 1383 1384 CLR(ifp->if_flags, IFF_RUNNING); 1385 1386 bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize, 1387 BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 1388 sc->sc_linkdown = sts->ms_linkdown; 1389 bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize, 1390 BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 1391 1392 sc->sc_state = MYX_S_DOWN; 1393 membar_producer(); 1394 1395 memset(&mc, 0, sizeof(mc)); 1396 (void)myx_cmd(sc, MYXCMD_SET_IFDOWN, &mc, NULL); 1397 1398 while (sc->sc_state != MYX_S_OFF) { 1399 sleep_setup(&sls, sts, PWAIT, "myxdown"); 1400 membar_consumer(); 1401 sleep_finish(&sls, sc->sc_state != MYX_S_OFF); 1402 } 1403 1404 s = splnet(); 1405 if (ifp->if_link_state != LINK_STATE_UNKNOWN) { 1406 ifp->if_link_state = LINK_STATE_UNKNOWN; 1407 ifp->if_baudrate = 0; 1408 if_link_state_change(ifp); 1409 } 1410 splx(s); 1411 1412 memset(&mc, 0, sizeof(mc)); 1413 if (myx_cmd(sc, MYXCMD_RESET, &mc, NULL) != 0) { 1414 printf("%s: failed to reset the device\n", DEVNAME(sc)); 1415 } 1416 1417 ifq_clr_oactive(&ifp->if_snd); 1418 ifq_barrier(&ifp->if_snd); 1419 1420 for (ring = 0; ring < 2; ring++) { 1421 struct myx_rx_ring *mrr = &sc->sc_rx_ring[ring]; 1422 1423 timeout_del(&mrr->mrr_refill); 1424 myx_rx_empty(sc, mrr); 1425 myx_rx_free(sc, mrr); 1426 } 1427 1428 myx_tx_empty(sc); 1429 myx_tx_free(sc); 1430 1431 #if NKSTAT > 0 1432 myx_kstat_stop(sc); 1433 sc->sc_sts = NULL; 1434 #endif 1435 1436 /* the sleep shizz above already synced this dmamem */ 1437 myx_dmamem_free(sc, &sc->sc_sts_dma); 1438 1439 bus_dmamap_sync(sc->sc_dmat, sc->sc_intrq_dma.mxm_map, 0, 1440 sc->sc_intrq_dma.mxm_map->dm_mapsize, BUS_DMASYNC_POSTREAD); 1441 myx_dmamem_free(sc, &sc->sc_intrq_dma); 1442 1443 bus_dmamap_sync(sc->sc_dmat, sc->sc_paddma.mxm_map, 0, 1444 sc->sc_paddma.mxm_map->dm_mapsize, BUS_DMASYNC_POSTREAD); 1445 myx_dmamem_free(sc, &sc->sc_paddma); 1446 1447 bus_dmamap_sync(sc->sc_dmat, sc->sc_zerodma.mxm_map, 0, 1448 sc->sc_zerodma.mxm_map->dm_mapsize, BUS_DMASYNC_POSTREAD); 1449 myx_dmamem_free(sc, &sc->sc_zerodma); 1450 } 1451 1452 void 1453 myx_write_txd_tail(struct myx_softc *sc, struct myx_slot *ms, u_int8_t flags, 1454 u_int32_t offset, u_int idx) 1455 { 1456 struct myx_tx_desc txd; 1457 bus_dmamap_t zmap = sc->sc_zerodma.mxm_map; 1458 bus_dmamap_t map = ms->ms_map; 1459 int i; 1460 1461 for (i = 1; i < map->dm_nsegs; i++) { 1462 memset(&txd, 0, sizeof(txd)); 1463 txd.tx_addr = htobe64(map->dm_segs[i].ds_addr); 1464 txd.tx_length = htobe16(map->dm_segs[i].ds_len); 1465 txd.tx_flags = flags; 1466 1467 myx_bus_space_write(sc, 1468 offset + sizeof(txd) * ((idx + i) % sc->sc_tx_ring_count), 1469 &txd, sizeof(txd)); 1470 } 1471 1472 /* pad runt frames */ 1473 if (map->dm_mapsize < 60) { 1474 memset(&txd, 0, sizeof(txd)); 1475 txd.tx_addr = htobe64(zmap->dm_segs[0].ds_addr); 1476 txd.tx_length = htobe16(60 - map->dm_mapsize); 1477 txd.tx_flags = flags; 1478 1479 myx_bus_space_write(sc, 1480 offset + sizeof(txd) * ((idx + i) % sc->sc_tx_ring_count), 1481 &txd, sizeof(txd)); 1482 } 1483 } 1484 1485 void 1486 myx_start(struct ifqueue *ifq) 1487 { 1488 struct ifnet *ifp = ifq->ifq_if; 1489 struct myx_tx_desc txd; 1490 struct myx_softc *sc = ifp->if_softc; 1491 struct myx_slot *ms; 1492 bus_dmamap_t map; 1493 struct mbuf *m; 1494 u_int32_t offset = sc->sc_tx_ring_offset; 1495 u_int idx, cons, prod; 1496 u_int free, used; 1497 u_int8_t flags; 1498 1499 idx = sc->sc_tx_ring_prod; 1500 1501 /* figure out space */ 1502 free = sc->sc_tx_ring_cons; 1503 if (free <= idx) 1504 free += sc->sc_tx_ring_count; 1505 free -= idx; 1506 1507 cons = prod = sc->sc_tx_prod; 1508 1509 used = 0; 1510 1511 for (;;) { 1512 if (used + sc->sc_tx_nsegs + 1 > free) { 1513 ifq_set_oactive(ifq); 1514 break; 1515 } 1516 1517 m = ifq_dequeue(ifq); 1518 if (m == NULL) 1519 break; 1520 1521 ms = &sc->sc_tx_slots[prod]; 1522 1523 if (myx_load_mbuf(sc, ms, m) != 0) { 1524 m_freem(m); 1525 ifp->if_oerrors++; 1526 continue; 1527 } 1528 1529 #if NBPFILTER > 0 1530 if (ifp->if_bpf) 1531 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT); 1532 #endif 1533 1534 map = ms->ms_map; 1535 bus_dmamap_sync(sc->sc_dmat, map, 0, 1536 map->dm_mapsize, BUS_DMASYNC_PREWRITE); 1537 1538 used += map->dm_nsegs + (map->dm_mapsize < 60 ? 1 : 0); 1539 1540 if (++prod >= sc->sc_tx_ring_count) 1541 prod = 0; 1542 } 1543 1544 if (cons == prod) 1545 return; 1546 1547 ms = &sc->sc_tx_slots[cons]; 1548 1549 for (;;) { 1550 idx += ms->ms_map->dm_nsegs + 1551 (ms->ms_map->dm_mapsize < 60 ? 1 : 0); 1552 if (idx >= sc->sc_tx_ring_count) 1553 idx -= sc->sc_tx_ring_count; 1554 1555 if (++cons >= sc->sc_tx_ring_count) 1556 cons = 0; 1557 1558 if (cons == prod) 1559 break; 1560 1561 ms = &sc->sc_tx_slots[cons]; 1562 map = ms->ms_map; 1563 1564 flags = MYXTXD_FLAGS_NO_TSO; 1565 if (map->dm_mapsize < 1520) 1566 flags |= MYXTXD_FLAGS_SMALL; 1567 1568 memset(&txd, 0, sizeof(txd)); 1569 txd.tx_addr = htobe64(map->dm_segs[0].ds_addr); 1570 txd.tx_length = htobe16(map->dm_segs[0].ds_len); 1571 txd.tx_nsegs = map->dm_nsegs + (map->dm_mapsize < 60 ? 1 : 0); 1572 txd.tx_flags = flags | MYXTXD_FLAGS_FIRST; 1573 myx_bus_space_write(sc, 1574 offset + sizeof(txd) * idx, &txd, sizeof(txd)); 1575 1576 myx_write_txd_tail(sc, ms, flags, offset, idx); 1577 } 1578 1579 /* go back and post first packet */ 1580 ms = &sc->sc_tx_slots[sc->sc_tx_prod]; 1581 map = ms->ms_map; 1582 1583 flags = MYXTXD_FLAGS_NO_TSO; 1584 if (map->dm_mapsize < 1520) 1585 flags |= MYXTXD_FLAGS_SMALL; 1586 1587 memset(&txd, 0, sizeof(txd)); 1588 txd.tx_addr = htobe64(map->dm_segs[0].ds_addr); 1589 txd.tx_length = htobe16(map->dm_segs[0].ds_len); 1590 txd.tx_nsegs = map->dm_nsegs + (map->dm_mapsize < 60 ? 1 : 0); 1591 txd.tx_flags = flags | MYXTXD_FLAGS_FIRST; 1592 1593 /* make sure the first descriptor is seen after the others */ 1594 myx_write_txd_tail(sc, ms, flags, offset, sc->sc_tx_ring_prod); 1595 1596 myx_bus_space_write(sc, 1597 offset + sizeof(txd) * sc->sc_tx_ring_prod, &txd, 1598 sizeof(txd) - sizeof(myx_bus_t)); 1599 1600 bus_space_barrier(sc->sc_memt, sc->sc_memh, offset, 1601 sizeof(txd) * sc->sc_tx_ring_count, BUS_SPACE_BARRIER_WRITE); 1602 1603 myx_bus_space_write(sc, 1604 offset + sizeof(txd) * (sc->sc_tx_ring_prod + 1) - 1605 sizeof(myx_bus_t), 1606 (u_int8_t *)&txd + sizeof(txd) - sizeof(myx_bus_t), 1607 sizeof(myx_bus_t)); 1608 1609 bus_space_barrier(sc->sc_memt, sc->sc_memh, 1610 offset + sizeof(txd) * sc->sc_tx_ring_prod, sizeof(txd), 1611 BUS_SPACE_BARRIER_WRITE); 1612 1613 /* commit */ 1614 sc->sc_tx_ring_prod = idx; 1615 sc->sc_tx_prod = prod; 1616 } 1617 1618 int 1619 myx_load_mbuf(struct myx_softc *sc, struct myx_slot *ms, struct mbuf *m) 1620 { 1621 bus_dma_tag_t dmat = sc->sc_dmat; 1622 bus_dmamap_t dmap = ms->ms_map; 1623 1624 switch (bus_dmamap_load_mbuf(dmat, dmap, m, 1625 BUS_DMA_STREAMING | BUS_DMA_NOWAIT)) { 1626 case 0: 1627 break; 1628 1629 case EFBIG: /* mbuf chain is too fragmented */ 1630 if (m_defrag(m, M_DONTWAIT) == 0 && 1631 bus_dmamap_load_mbuf(dmat, dmap, m, 1632 BUS_DMA_STREAMING | BUS_DMA_NOWAIT) == 0) 1633 break; 1634 default: 1635 return (1); 1636 } 1637 1638 ms->ms_m = m; 1639 return (0); 1640 } 1641 1642 int 1643 myx_intr(void *arg) 1644 { 1645 struct myx_softc *sc = (struct myx_softc *)arg; 1646 volatile struct myx_status *sts = sc->sc_sts; 1647 enum myx_state state; 1648 bus_dmamap_t map = sc->sc_sts_dma.mxm_map; 1649 u_int32_t data; 1650 u_int8_t valid = 0; 1651 1652 state = sc->sc_state; 1653 if (state == MYX_S_OFF) 1654 return (0); 1655 1656 bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize, 1657 BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 1658 1659 valid = sts->ms_isvalid; 1660 if (valid == 0x0) { 1661 bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize, 1662 BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 1663 return (0); 1664 } 1665 1666 if (sc->sc_intx) { 1667 data = htobe32(0); 1668 bus_space_write_raw_region_4(sc->sc_memt, sc->sc_memh, 1669 sc->sc_irqdeassertoff, &data, sizeof(data)); 1670 } 1671 sts->ms_isvalid = 0; 1672 1673 do { 1674 data = sts->ms_txdonecnt; 1675 1676 bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize, 1677 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE | 1678 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 1679 } while (sts->ms_isvalid); 1680 1681 data = betoh32(data); 1682 if (data != sc->sc_tx_count) 1683 myx_txeof(sc, data); 1684 1685 data = htobe32(3); 1686 if (valid & 0x1) { 1687 myx_rxeof(sc); 1688 1689 bus_space_write_raw_region_4(sc->sc_memt, sc->sc_memh, 1690 sc->sc_irqclaimoff, &data, sizeof(data)); 1691 } 1692 bus_space_write_raw_region_4(sc->sc_memt, sc->sc_memh, 1693 sc->sc_irqclaimoff + sizeof(data), &data, sizeof(data)); 1694 1695 if (sts->ms_statusupdated) { 1696 if (state == MYX_S_DOWN && 1697 sc->sc_linkdown != sts->ms_linkdown) { 1698 sc->sc_state = MYX_S_OFF; 1699 membar_producer(); 1700 wakeup(sts); 1701 } else { 1702 data = sts->ms_linkstate; 1703 if (data != 0xffffffff) { 1704 KERNEL_LOCK(); 1705 myx_link_state(sc, data); 1706 KERNEL_UNLOCK(); 1707 } 1708 } 1709 } 1710 1711 bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize, 1712 BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 1713 1714 return (1); 1715 } 1716 1717 void 1718 myx_refill(void *xmrr) 1719 { 1720 struct myx_rx_ring *mrr = xmrr; 1721 struct myx_softc *sc = mrr->mrr_softc; 1722 1723 myx_rx_fill(sc, mrr); 1724 1725 if (mrr->mrr_prod == mrr->mrr_cons) 1726 timeout_add(&mrr->mrr_refill, 1); 1727 } 1728 1729 void 1730 myx_txeof(struct myx_softc *sc, u_int32_t done_count) 1731 { 1732 struct ifnet *ifp = &sc->sc_ac.ac_if; 1733 struct myx_slot *ms; 1734 bus_dmamap_t map; 1735 u_int idx, cons; 1736 1737 idx = sc->sc_tx_ring_cons; 1738 cons = sc->sc_tx_cons; 1739 1740 do { 1741 ms = &sc->sc_tx_slots[cons]; 1742 map = ms->ms_map; 1743 1744 idx += map->dm_nsegs + (map->dm_mapsize < 60 ? 1 : 0); 1745 1746 bus_dmamap_sync(sc->sc_dmat, map, 0, 1747 map->dm_mapsize, BUS_DMASYNC_POSTWRITE); 1748 bus_dmamap_unload(sc->sc_dmat, map); 1749 m_freem(ms->ms_m); 1750 1751 if (++cons >= sc->sc_tx_ring_count) 1752 cons = 0; 1753 } while (++sc->sc_tx_count != done_count); 1754 1755 if (idx >= sc->sc_tx_ring_count) 1756 idx -= sc->sc_tx_ring_count; 1757 1758 sc->sc_tx_ring_cons = idx; 1759 sc->sc_tx_cons = cons; 1760 1761 if (ifq_is_oactive(&ifp->if_snd)) 1762 ifq_restart(&ifp->if_snd); 1763 } 1764 1765 void 1766 myx_rxeof(struct myx_softc *sc) 1767 { 1768 static const struct myx_intrq_desc zerodesc = { 0, 0 }; 1769 struct ifnet *ifp = &sc->sc_ac.ac_if; 1770 struct mbuf_list ml = MBUF_LIST_INITIALIZER(); 1771 struct myx_rx_ring *mrr; 1772 struct myx_slot *ms; 1773 struct mbuf *m; 1774 int ring; 1775 u_int rxfree[2] = { 0 , 0 }; 1776 u_int len; 1777 int livelocked; 1778 1779 bus_dmamap_sync(sc->sc_dmat, sc->sc_intrq_dma.mxm_map, 0, 1780 sc->sc_intrq_dma.mxm_map->dm_mapsize, BUS_DMASYNC_POSTREAD); 1781 1782 while ((len = betoh16(sc->sc_intrq[sc->sc_intrq_idx].iq_length)) != 0) { 1783 sc->sc_intrq[sc->sc_intrq_idx] = zerodesc; 1784 1785 if (++sc->sc_intrq_idx >= sc->sc_intrq_count) 1786 sc->sc_intrq_idx = 0; 1787 1788 ring = (len <= (MYX_RXSMALL_SIZE - ETHER_ALIGN)) ? 1789 MYX_RXSMALL : MYX_RXBIG; 1790 1791 mrr = &sc->sc_rx_ring[ring]; 1792 ms = &mrr->mrr_slots[mrr->mrr_cons]; 1793 1794 if (++mrr->mrr_cons >= sc->sc_rx_ring_count) 1795 mrr->mrr_cons = 0; 1796 1797 bus_dmamap_sync(sc->sc_dmat, ms->ms_map, 0, 1798 ms->ms_map->dm_mapsize, BUS_DMASYNC_POSTREAD); 1799 bus_dmamap_unload(sc->sc_dmat, ms->ms_map); 1800 1801 m = ms->ms_m; 1802 m->m_data += ETHER_ALIGN; 1803 m->m_pkthdr.len = m->m_len = len; 1804 1805 ml_enqueue(&ml, m); 1806 1807 rxfree[ring]++; 1808 } 1809 1810 bus_dmamap_sync(sc->sc_dmat, sc->sc_intrq_dma.mxm_map, 0, 1811 sc->sc_intrq_dma.mxm_map->dm_mapsize, BUS_DMASYNC_PREREAD); 1812 1813 livelocked = ifiq_input(&ifp->if_rcv, &ml); 1814 for (ring = MYX_RXSMALL; ring <= MYX_RXBIG; ring++) { 1815 if (rxfree[ring] == 0) 1816 continue; 1817 1818 mrr = &sc->sc_rx_ring[ring]; 1819 1820 if (livelocked) 1821 if_rxr_livelocked(&mrr->mrr_rxr); 1822 1823 if_rxr_put(&mrr->mrr_rxr, rxfree[ring]); 1824 myx_rx_fill(sc, mrr); 1825 if (mrr->mrr_prod == mrr->mrr_cons) 1826 timeout_add(&mrr->mrr_refill, 0); 1827 } 1828 } 1829 1830 static int 1831 myx_rx_fill_slots(struct myx_softc *sc, struct myx_rx_ring *mrr, u_int slots) 1832 { 1833 struct myx_rx_desc rxd; 1834 struct myx_slot *ms; 1835 u_int32_t offset = mrr->mrr_offset; 1836 u_int p, first, fills; 1837 1838 first = p = mrr->mrr_prod; 1839 if (myx_buf_fill(sc, &mrr->mrr_slots[first], mrr->mrr_mclget) != 0) 1840 return (slots); 1841 1842 if (++p >= sc->sc_rx_ring_count) 1843 p = 0; 1844 1845 for (fills = 1; fills < slots; fills++) { 1846 ms = &mrr->mrr_slots[p]; 1847 1848 if (myx_buf_fill(sc, ms, mrr->mrr_mclget) != 0) 1849 break; 1850 1851 rxd.rx_addr = htobe64(ms->ms_map->dm_segs[0].ds_addr); 1852 myx_bus_space_write(sc, offset + p * sizeof(rxd), 1853 &rxd, sizeof(rxd)); 1854 1855 if (++p >= sc->sc_rx_ring_count) 1856 p = 0; 1857 } 1858 1859 mrr->mrr_prod = p; 1860 1861 /* make sure the first descriptor is seen after the others */ 1862 if (fills > 1) { 1863 bus_space_barrier(sc->sc_memt, sc->sc_memh, 1864 offset, sizeof(rxd) * sc->sc_rx_ring_count, 1865 BUS_SPACE_BARRIER_WRITE); 1866 } 1867 1868 ms = &mrr->mrr_slots[first]; 1869 rxd.rx_addr = htobe64(ms->ms_map->dm_segs[0].ds_addr); 1870 myx_bus_space_write(sc, offset + first * sizeof(rxd), 1871 &rxd, sizeof(rxd)); 1872 1873 return (slots - fills); 1874 } 1875 1876 int 1877 myx_rx_init(struct myx_softc *sc, int ring, bus_size_t size) 1878 { 1879 struct myx_rx_desc rxd; 1880 struct myx_rx_ring *mrr = &sc->sc_rx_ring[ring]; 1881 struct myx_slot *ms; 1882 u_int32_t offset = mrr->mrr_offset; 1883 int rv; 1884 int i; 1885 1886 mrr->mrr_slots = mallocarray(sizeof(*ms), sc->sc_rx_ring_count, 1887 M_DEVBUF, M_WAITOK); 1888 if (mrr->mrr_slots == NULL) 1889 return (ENOMEM); 1890 1891 memset(&rxd, 0xff, sizeof(rxd)); 1892 for (i = 0; i < sc->sc_rx_ring_count; i++) { 1893 ms = &mrr->mrr_slots[i]; 1894 rv = bus_dmamap_create(sc->sc_dmat, size, 1, size, 0, 1895 BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW, &ms->ms_map); 1896 if (rv != 0) 1897 goto destroy; 1898 1899 myx_bus_space_write(sc, offset + i * sizeof(rxd), 1900 &rxd, sizeof(rxd)); 1901 } 1902 1903 if_rxr_init(&mrr->mrr_rxr, 2, sc->sc_rx_ring_count - 2); 1904 mrr->mrr_prod = mrr->mrr_cons = 0; 1905 1906 return (0); 1907 1908 destroy: 1909 while (i-- > 0) { 1910 ms = &mrr->mrr_slots[i]; 1911 bus_dmamap_destroy(sc->sc_dmat, ms->ms_map); 1912 } 1913 free(mrr->mrr_slots, M_DEVBUF, sizeof(*ms) * sc->sc_rx_ring_count); 1914 return (rv); 1915 } 1916 1917 int 1918 myx_rx_fill(struct myx_softc *sc, struct myx_rx_ring *mrr) 1919 { 1920 u_int slots; 1921 1922 slots = if_rxr_get(&mrr->mrr_rxr, sc->sc_rx_ring_count); 1923 if (slots == 0) 1924 return (1); 1925 1926 slots = myx_rx_fill_slots(sc, mrr, slots); 1927 if (slots > 0) 1928 if_rxr_put(&mrr->mrr_rxr, slots); 1929 1930 return (0); 1931 } 1932 1933 void 1934 myx_rx_empty(struct myx_softc *sc, struct myx_rx_ring *mrr) 1935 { 1936 struct myx_slot *ms; 1937 1938 while (mrr->mrr_cons != mrr->mrr_prod) { 1939 ms = &mrr->mrr_slots[mrr->mrr_cons]; 1940 1941 if (++mrr->mrr_cons >= sc->sc_rx_ring_count) 1942 mrr->mrr_cons = 0; 1943 1944 bus_dmamap_sync(sc->sc_dmat, ms->ms_map, 0, 1945 ms->ms_map->dm_mapsize, BUS_DMASYNC_POSTREAD); 1946 bus_dmamap_unload(sc->sc_dmat, ms->ms_map); 1947 m_freem(ms->ms_m); 1948 } 1949 1950 if_rxr_init(&mrr->mrr_rxr, 2, sc->sc_rx_ring_count - 2); 1951 } 1952 1953 void 1954 myx_rx_free(struct myx_softc *sc, struct myx_rx_ring *mrr) 1955 { 1956 struct myx_slot *ms; 1957 int i; 1958 1959 for (i = 0; i < sc->sc_rx_ring_count; i++) { 1960 ms = &mrr->mrr_slots[i]; 1961 bus_dmamap_destroy(sc->sc_dmat, ms->ms_map); 1962 } 1963 1964 free(mrr->mrr_slots, M_DEVBUF, sizeof(*ms) * sc->sc_rx_ring_count); 1965 } 1966 1967 struct mbuf * 1968 myx_mcl_small(void) 1969 { 1970 struct mbuf *m; 1971 1972 m = MCLGETL(NULL, M_DONTWAIT, MYX_RXSMALL_SIZE); 1973 if (m == NULL) 1974 return (NULL); 1975 1976 m->m_len = m->m_pkthdr.len = MYX_RXSMALL_SIZE; 1977 1978 return (m); 1979 } 1980 1981 struct mbuf * 1982 myx_mcl_big(void) 1983 { 1984 struct mbuf *m; 1985 void *mcl; 1986 1987 MGETHDR(m, M_DONTWAIT, MT_DATA); 1988 if (m == NULL) 1989 return (NULL); 1990 1991 mcl = pool_get(myx_mcl_pool, PR_NOWAIT); 1992 if (mcl == NULL) { 1993 m_free(m); 1994 return (NULL); 1995 } 1996 1997 MEXTADD(m, mcl, MYX_RXBIG_SIZE, M_EXTWR, MEXTFREE_POOL, myx_mcl_pool); 1998 m->m_len = m->m_pkthdr.len = MYX_RXBIG_SIZE; 1999 2000 return (m); 2001 } 2002 2003 int 2004 myx_buf_fill(struct myx_softc *sc, struct myx_slot *ms, 2005 struct mbuf *(*mclget)(void)) 2006 { 2007 struct mbuf *m; 2008 int rv; 2009 2010 m = (*mclget)(); 2011 if (m == NULL) 2012 return (ENOMEM); 2013 2014 rv = bus_dmamap_load_mbuf(sc->sc_dmat, ms->ms_map, m, BUS_DMA_NOWAIT); 2015 if (rv != 0) { 2016 m_freem(m); 2017 return (rv); 2018 } 2019 2020 bus_dmamap_sync(sc->sc_dmat, ms->ms_map, 0, 2021 ms->ms_map->dm_mapsize, BUS_DMASYNC_PREREAD); 2022 2023 ms->ms_m = m; 2024 2025 return (0); 2026 } 2027 2028 int 2029 myx_tx_init(struct myx_softc *sc, bus_size_t size) 2030 { 2031 struct myx_slot *ms; 2032 int rv; 2033 int i; 2034 2035 sc->sc_tx_slots = mallocarray(sizeof(*ms), sc->sc_tx_ring_count, 2036 M_DEVBUF, M_WAITOK); 2037 if (sc->sc_tx_slots == NULL) 2038 return (ENOMEM); 2039 2040 for (i = 0; i < sc->sc_tx_ring_count; i++) { 2041 ms = &sc->sc_tx_slots[i]; 2042 rv = bus_dmamap_create(sc->sc_dmat, size, sc->sc_tx_nsegs, 2043 sc->sc_tx_boundary, sc->sc_tx_boundary, 2044 BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW, &ms->ms_map); 2045 if (rv != 0) 2046 goto destroy; 2047 } 2048 2049 sc->sc_tx_prod = sc->sc_tx_cons = 0; 2050 2051 return (0); 2052 2053 destroy: 2054 while (i-- > 0) { 2055 ms = &sc->sc_tx_slots[i]; 2056 bus_dmamap_destroy(sc->sc_dmat, ms->ms_map); 2057 } 2058 free(sc->sc_tx_slots, M_DEVBUF, sizeof(*ms) * sc->sc_tx_ring_count); 2059 return (rv); 2060 } 2061 2062 void 2063 myx_tx_empty(struct myx_softc *sc) 2064 { 2065 struct myx_slot *ms; 2066 u_int cons = sc->sc_tx_cons; 2067 u_int prod = sc->sc_tx_prod; 2068 2069 while (cons != prod) { 2070 ms = &sc->sc_tx_slots[cons]; 2071 2072 bus_dmamap_sync(sc->sc_dmat, ms->ms_map, 0, 2073 ms->ms_map->dm_mapsize, BUS_DMASYNC_POSTWRITE); 2074 bus_dmamap_unload(sc->sc_dmat, ms->ms_map); 2075 m_freem(ms->ms_m); 2076 2077 if (++cons >= sc->sc_tx_ring_count) 2078 cons = 0; 2079 } 2080 2081 sc->sc_tx_cons = cons; 2082 } 2083 2084 void 2085 myx_tx_free(struct myx_softc *sc) 2086 { 2087 struct myx_slot *ms; 2088 int i; 2089 2090 for (i = 0; i < sc->sc_tx_ring_count; i++) { 2091 ms = &sc->sc_tx_slots[i]; 2092 bus_dmamap_destroy(sc->sc_dmat, ms->ms_map); 2093 } 2094 2095 free(sc->sc_tx_slots, M_DEVBUF, sizeof(*ms) * sc->sc_tx_ring_count); 2096 } 2097 2098 #if NKSTAT > 0 2099 enum myx_counters { 2100 myx_stat_dropped_pause, 2101 myx_stat_dropped_ucast_filtered, 2102 myx_stat_dropped_bad_crc32, 2103 myx_stat_dropped_bad_phy, 2104 myx_stat_dropped_mcast_filtered, 2105 myx_stat_send_done, 2106 myx_stat_dropped_link_overflow, 2107 myx_stat_dropped_link, 2108 myx_stat_dropped_runt, 2109 myx_stat_dropped_overrun, 2110 myx_stat_dropped_no_small_bufs, 2111 myx_stat_dropped_no_large_bufs, 2112 2113 myx_ncounters, 2114 }; 2115 2116 struct myx_counter { 2117 const char *mc_name; 2118 unsigned int mc_offset; 2119 }; 2120 2121 #define MYX_C_OFF(_f) offsetof(struct myx_status, _f) 2122 2123 static const struct myx_counter myx_counters[myx_ncounters] = { 2124 { "pause drops", MYX_C_OFF(ms_dropped_pause), }, 2125 { "ucast filtered", MYX_C_OFF(ms_dropped_unicast), }, 2126 { "bad crc32", MYX_C_OFF(ms_dropped_pause), }, 2127 { "bad phy", MYX_C_OFF(ms_dropped_phyerr), }, 2128 { "mcast filtered", MYX_C_OFF(ms_dropped_mcast), }, 2129 { "tx done", MYX_C_OFF(ms_txdonecnt), }, 2130 { "rx discards", MYX_C_OFF(ms_dropped_linkoverflow), }, 2131 { "rx errors", MYX_C_OFF(ms_dropped_linkerror), }, 2132 { "rx undersize", MYX_C_OFF(ms_dropped_runt), }, 2133 { "rx oversize", MYX_C_OFF(ms_dropped_overrun), }, 2134 { "small discards", MYX_C_OFF(ms_dropped_smallbufunderrun), }, 2135 { "large discards", MYX_C_OFF(ms_dropped_bigbufunderrun), }, 2136 }; 2137 2138 struct myx_kstats { 2139 struct kstat_kv mk_counters[myx_ncounters]; 2140 struct kstat_kv mk_rdma_tags_available; 2141 }; 2142 2143 struct myx_kstat_cache { 2144 uint32_t mkc_counters[myx_ncounters]; 2145 }; 2146 2147 struct myx_kstat_state { 2148 struct myx_kstat_cache mks_caches[2]; 2149 unsigned int mks_gen; 2150 }; 2151 2152 int 2153 myx_kstat_read(struct kstat *ks) 2154 { 2155 struct myx_softc *sc = ks->ks_softc; 2156 struct myx_kstats *mk = ks->ks_data; 2157 struct myx_kstat_state *mks = ks->ks_ptr; 2158 unsigned int gen = (mks->mks_gen++ & 1); 2159 struct myx_kstat_cache *omkc = &mks->mks_caches[gen]; 2160 struct myx_kstat_cache *nmkc = &mks->mks_caches[!gen]; 2161 unsigned int i = 0; 2162 2163 volatile struct myx_status *sts = sc->sc_sts; 2164 bus_dmamap_t map = sc->sc_sts_dma.mxm_map; 2165 2166 if (sc->sc_sts == NULL) 2167 return (0); /* counters are valid, just not updated */ 2168 2169 getnanouptime(&ks->ks_updated); 2170 2171 bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize, 2172 BUS_DMASYNC_POSTREAD); 2173 for (i = 0; i < myx_ncounters; i++) { 2174 const struct myx_counter *mc = &myx_counters[i]; 2175 nmkc->mkc_counters[i] = 2176 bemtoh32((uint32_t *)((uint8_t *)sts + mc->mc_offset)); 2177 } 2178 2179 kstat_kv_u32(&mk->mk_rdma_tags_available) = 2180 bemtoh32(&sts->ms_rdmatags_available); 2181 bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize, 2182 BUS_DMASYNC_PREREAD); 2183 2184 for (i = 0; i < myx_ncounters; i++) { 2185 kstat_kv_u64(&mk->mk_counters[i]) += 2186 nmkc->mkc_counters[i] - omkc->mkc_counters[i]; 2187 } 2188 2189 return (0); 2190 } 2191 2192 void 2193 myx_kstat_tick(void *arg) 2194 { 2195 struct myx_softc *sc = arg; 2196 2197 if (!ISSET(sc->sc_ac.ac_if.if_flags, IFF_RUNNING)) 2198 return; 2199 2200 timeout_add_sec(&sc->sc_kstat_tmo, 4); 2201 2202 if (!mtx_enter_try(&sc->sc_kstat_mtx)) 2203 return; 2204 2205 myx_kstat_read(sc->sc_kstat); 2206 2207 mtx_leave(&sc->sc_kstat_mtx); 2208 } 2209 2210 void 2211 myx_kstat_start(struct myx_softc *sc) 2212 { 2213 if (sc->sc_kstat == NULL) 2214 return; 2215 2216 myx_kstat_tick(sc); 2217 } 2218 2219 void 2220 myx_kstat_stop(struct myx_softc *sc) 2221 { 2222 struct myx_kstat_state *mks; 2223 2224 if (sc->sc_kstat == NULL) 2225 return; 2226 2227 timeout_del_barrier(&sc->sc_kstat_tmo); 2228 2229 mks = sc->sc_kstat->ks_ptr; 2230 2231 mtx_enter(&sc->sc_kstat_mtx); 2232 memset(mks, 0, sizeof(*mks)); 2233 mtx_leave(&sc->sc_kstat_mtx); 2234 } 2235 2236 void 2237 myx_kstat_attach(struct myx_softc *sc) 2238 { 2239 struct kstat *ks; 2240 struct myx_kstats *mk; 2241 struct myx_kstat_state *mks; 2242 unsigned int i; 2243 2244 mtx_init(&sc->sc_kstat_mtx, IPL_SOFTCLOCK); 2245 timeout_set(&sc->sc_kstat_tmo, myx_kstat_tick, sc); 2246 2247 ks = kstat_create(DEVNAME(sc), 0, "myx-stats", 0, KSTAT_T_KV, 0); 2248 if (ks == NULL) 2249 return; 2250 2251 mk = malloc(sizeof(*mk), M_DEVBUF, M_WAITOK|M_ZERO); 2252 for (i = 0; i < myx_ncounters; i++) { 2253 const struct myx_counter *mc = &myx_counters[i]; 2254 2255 kstat_kv_unit_init(&mk->mk_counters[i], mc->mc_name, 2256 KSTAT_KV_T_COUNTER64, KSTAT_KV_U_PACKETS); 2257 } 2258 kstat_kv_init(&mk->mk_rdma_tags_available, "rdma tags free", 2259 KSTAT_KV_T_UINT32); 2260 2261 mks = malloc(sizeof(*mks), M_DEVBUF, M_WAITOK|M_ZERO); 2262 /* these start at 0 */ 2263 2264 kstat_set_mutex(ks, &sc->sc_kstat_mtx); 2265 ks->ks_data = mk; 2266 ks->ks_datalen = sizeof(*mk); 2267 ks->ks_read = myx_kstat_read; 2268 ks->ks_ptr = mks; 2269 2270 ks->ks_softc = sc; 2271 sc->sc_kstat = ks; 2272 kstat_install(ks); 2273 } 2274 #endif /* NKSTAT > 0 */ 2275