--- if_myri10ge.c.pre-review-changes Thu Feb 9 10:59:26 2006 +++ if_myri10ge.c Wed Feb 15 12:07:16 2006 @@ -75,6 +75,9 @@ #include #include +#include /* for pmap_mapdev() */ +#include + #include #include #include @@ -165,13 +168,14 @@ } static int -myri10ge_dma_alloc(device_t dev, myri10ge_dma_t *dma, size_t bytes, +myri10ge_dma_alloc(myri10ge_softc_t *sc, myri10ge_dma_t *dma, size_t bytes, bus_size_t alignment) { int err; + device_t dev = sc->dev; /* allocate DMAable memory tags */ - err = bus_dma_tag_create(NULL, /* parent */ + err = bus_dma_tag_create(sc->parent_dmat, /* parent */ alignment, /* alignment */ 4096, /* boundary */ BUS_SPACE_MAXADDR, /* low */ @@ -180,7 +184,7 @@ bytes, /* maxsize */ 1, /* num segs */ 4096, /* maxsegsize */ - BUS_DMA_ALLOCNOW, /* flags */ + BUS_DMA_COHERENT, /* flags */ NULL, NULL, /* lock */ &dma->dmat); /* tag */ if (err != 0) { @@ -268,9 +272,6 @@ } #if #cpu(i386) || defined __i386 || defined i386 || defined __i386__ || #cpu(x86_64) || defined __x86_64__ -void *pmap_mapdev(vm_paddr_t, vm_size_t); -void pmap_unmapdev(vm_offset_t, vm_size_t); - static int myri10ge_enable_nvidia_ecrc(myri10ge_softc_t *sc, device_t pdev) { @@ -280,7 +281,15 @@ uint16_t vendor_id, device_id; uintptr_t bus, slot, func, ivend, idev; uint32_t *ptr32; - + + /* XXXX + Test below is commented because it is believed that doing + config read/write beyond 0xff will access the config space + for the next larger function. Uncomment this and remove + the hacky pmap_mapdev() way of accessing config space when + FreeBSD grows support for extended pcie config space access + */ +#if 0 /* See if we can, by some miracle, access the extended config space */ val = pci_read_config(pdev, 0x178, 4); @@ -289,6 +298,7 @@ pci_write_config(pdev, 0x178, val, 4); return 0; } +#endif /* Rather than using normal pci config space writes, we must * map the Nvidia config space ourselves. This is because on * opteron/nvidia class machine the 0xe000000 mapping is @@ -1045,8 +1055,7 @@ static void myri10ge_encap(myri10ge_softc_t *sc, struct mbuf *m) { - mcp_kreq_ether_send_t *req, *req_list; - char req_bytes[8 + sizeof (*req_list) * (MYRI10GE_MCP_ETHER_MAX_SEND_DESC + 4)]; + mcp_kreq_ether_send_t *req; bus_dma_segment_t seg_list[MYRI10GE_MCP_ETHER_MAX_SEND_DESC]; bus_dma_segment_t *seg; struct mbuf *m_tmp; @@ -1089,9 +1098,7 @@ bus_dmamap_sync(tx->dmat, tx->info[idx].map, BUS_DMASYNC_PREWRITE); - /* ensure req_list entries are aligned to 8 bytes */ - req = req_list = (mcp_kreq_ether_send_t *) - ((unsigned long)(req_bytes + 7) & ~7UL); + req = tx->req_list; cksum_offset = 0; flags = htobe16(MYRI10GE_MCP_ETHER_FLAGS_VALID | MYRI10GE_MCP_ETHER_FLAGS_NOT_LAST); @@ -1150,9 +1157,9 @@ req->flags &= ~(htobe16(MYRI10GE_MCP_ETHER_FLAGS_NOT_LAST)); tx->info[idx].m = m; if (tx->wc_fifo == NULL) - myri10ge_submit_req(tx, req_list, cnt); + myri10ge_submit_req(tx, tx->req_list, cnt); else - myri10ge_submit_req_wc(tx, req_list, cnt); + myri10ge_submit_req_wc(tx, tx->req_list, cnt); return; drop: @@ -1604,9 +1611,13 @@ if (sc->link_state != sc->fw_stats->link_up) { sc->link_state = sc->fw_stats->link_up; if (sc->link_state) { + if_link_state_change(sc->ifp, + LINK_STATE_UP); device_printf(sc->dev, "link up\n"); } else { + if_link_state_change(sc->ifp, + LINK_STATE_DOWN); device_printf(sc->dev, "link down\n"); } @@ -1718,7 +1729,9 @@ { int i; - + if (sc->tx.req_bytes != NULL) { + free(sc->tx.req_bytes, M_DEVBUF); + } if (sc->rx_small.shadow != NULL) free(sc->rx_small.shadow, M_DEVBUF); if (sc->rx_big.shadow != NULL) @@ -1794,11 +1807,22 @@ sc->rx_small.mask = sc->rx_big.mask = rx_ring_entries - 1; err = ENOMEM; + + /* allocate the tx request copy block */ + bytes = 8 + + sizeof (*sc->tx.req_list) * (MYRI10GE_MCP_ETHER_MAX_SEND_DESC + 4); + sc->tx.req_bytes = malloc(bytes, M_DEVBUF, M_WAITOK); + if (sc->tx.req_bytes == NULL) + goto abort_with_nothing; + /* ensure req_list entries are aligned to 8 bytes */ + sc->tx.req_list = (mcp_kreq_ether_send_t *) + ((unsigned long)(sc->tx.req_bytes + 7) & ~7UL); + /* allocate the rx shadow rings */ bytes = rx_ring_entries * sizeof (*sc->rx_small.shadow); sc->rx_small.shadow = malloc(bytes, M_DEVBUF, M_ZERO|M_WAITOK); if (sc->rx_small.shadow == NULL) - goto abort_with_nothing; + goto abort_with_alloc; bytes = rx_ring_entries * sizeof (*sc->rx_big.shadow); sc->rx_big.shadow = malloc(bytes, M_DEVBUF, M_ZERO|M_WAITOK); @@ -1822,7 +1846,7 @@ goto abort_with_alloc; /* allocate the busdma resources */ - err = bus_dma_tag_create(NULL, /* parent */ + err = bus_dma_tag_create(sc->parent_dmat, /* parent */ 1, /* alignment */ sc->tx.boundary, /* boundary */ BUS_SPACE_MAXADDR, /* low */ @@ -1841,7 +1865,7 @@ goto abort_with_alloc; } - err = bus_dma_tag_create(NULL, /* parent */ + err = bus_dma_tag_create(sc->parent_dmat, /* parent */ 1, /* alignment */ 4096, /* boundary */ BUS_SPACE_MAXADDR, /* low */ @@ -1859,7 +1883,7 @@ goto abort_with_alloc; } - err = bus_dma_tag_create(NULL, /* parent */ + err = bus_dma_tag_create(sc->parent_dmat, /* parent */ 1, /* alignment */ 4096, /* boundary */ BUS_SPACE_MAXADDR, /* low */ @@ -1953,7 +1977,14 @@ err = myri10ge_alloc_rings(sc); if (err != 0) { device_printf(sc->dev, "failed to allocate rings\n"); - return err;; + return err; + } + + err = bus_setup_intr(sc->dev, sc->irq_res, + INTR_TYPE_NET | INTR_MPSAFE, + myri10ge_intr, sc, &sc->ih); + if (err != 0) { + goto abort_with_rings; } /* get the lanai pointers to the send and receive rings */ @@ -1972,7 +2003,8 @@ if (err != 0) { device_printf(sc->dev, "failed to get ring sizes or locations\n"); - return EIO; + err = EIO; + goto abort_with_irq; } if (sc->wc) { @@ -2043,6 +2075,9 @@ abort: myri10ge_free_mbufs(sc); +abort_with_irq: + bus_teardown_intr(sc->dev, sc->irq_res, sc->ih); +abort_with_rings: myri10ge_free_rings(sc); return err; } @@ -2067,6 +2102,8 @@ if (old_down_cnt == sc->down_cnt) { device_printf(sc->dev, "never got down irq\n"); } + if (sc->ih != NULL) + bus_teardown_intr(sc->dev, sc->irq_res, sc->ih); myri10ge_free_mbufs(sc); myri10ge_free_rings(sc); return 0; @@ -2220,11 +2257,31 @@ sc->dev = dev; myri10ge_fetch_tunables(sc); + + err = bus_dma_tag_create(NULL, /* parent */ + 1, /* alignment */ + 4096, /* boundary */ + BUS_SPACE_MAXADDR, /* low */ + BUS_SPACE_MAXADDR, /* high */ + NULL, NULL, /* filter */ + MYRI10GE_MAX_ETHER_MTU,/* maxsize */ + MYRI10GE_MCP_ETHER_MAX_SEND_DESC, /* num segs */ + 4096, /* maxsegsize */ + 0, /* flags */ + NULL, NULL, /* lock */ + &sc->parent_dmat); /* tag */ + + if (err != 0) { + device_printf(sc->dev, "Err %d allocating parent dmat\n", + err); + goto abort_with_nothing; + } + ifp = sc->ifp = if_alloc(IFT_ETHER); if (ifp == NULL) { device_printf(dev, "can not if_alloc()\n"); err = ENOSPC; - goto abort_with_nothing; + goto abort_with_parent_dmat; } mtx_init(&sc->cmd_lock, NULL, MTX_NETWORK_LOCK, MTX_DEF); @@ -2272,16 +2329,16 @@ myri10ge_enable_wc(sc); /* Allocate the out of band dma memory */ - err = myri10ge_dma_alloc(dev, &sc->cmd_dma, + err = myri10ge_dma_alloc(sc, &sc->cmd_dma, sizeof (myri10ge_cmd_t), 64); if (err != 0) goto abort_with_mem_res; sc->cmd = (mcp_cmd_response_t *) sc->cmd_dma.addr; - err = myri10ge_dma_alloc(dev, &sc->zeropad_dma, 64, 64); + err = myri10ge_dma_alloc(sc, &sc->zeropad_dma, 64, 64); if (err != 0) goto abort_with_cmd_dma; - err = myri10ge_dma_alloc(dev, &sc->fw_stats_dma, + err = myri10ge_dma_alloc(sc, &sc->fw_stats_dma, sizeof (*sc->fw_stats), 64); if (err != 0) goto abort_with_zeropad_dma; @@ -2291,7 +2348,7 @@ /* allocate interrupt queues */ bytes = myri10ge_max_intr_slots * sizeof (*sc->intr.q[0]); for (i = 0; i < MYRI10GE_NUM_INTRQS; i++) { - err = myri10ge_dma_alloc(dev, &sc->intr.dma[i], + err = myri10ge_dma_alloc(sc, &sc->intr.dma[i], bytes, 4096); if (err != 0) goto abort_with_intrq; @@ -2307,22 +2364,15 @@ goto abort_with_intrq; } - err = bus_setup_intr(dev, sc->irq_res, - INTR_TYPE_NET | INTR_MPSAFE, - myri10ge_intr, sc, &sc->ih); - if (err != 0) { - goto abort_with_irq_res; - } - /* load the firmware */ myri10ge_select_firmware(sc); err = myri10ge_load_firmware(sc); if (err != 0) - goto abort_with_ithread; + goto abort_with_irq_res; err = myri10ge_reset(sc); if (err != 0) - goto abort_with_ithread; + goto abort_with_irq_res; /* hook into the network stack */ if_initname(ifp, device_get_name(dev), device_get_unit(dev)); @@ -2348,8 +2398,6 @@ myri10ge_add_sysctls(sc); return 0; -abort_with_ithread: - bus_teardown_intr(dev, sc->irq_res, sc->ih); abort_with_irq_res: bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res); abort_with_intrq: @@ -2372,6 +2420,9 @@ mtx_destroy(&sc->tx_lock); sx_destroy(&sc->driver_lock); if_free(ifp); +abort_with_parent_dmat: + bus_dma_tag_destroy(sc->parent_dmat); + abort_with_nothing: return err; } @@ -2386,8 +2437,6 @@ if (sc->ifp->if_drv_flags & IFF_DRV_RUNNING) myri10ge_close(sc); sx_xunlock(&sc->driver_lock); - if (sc->ih != NULL) - bus_teardown_intr(dev, sc->irq_res, sc->ih); ether_ifdetach(sc->ifp); bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res); for (i = 0; i < MYRI10GE_NUM_INTRQS; i++) { @@ -2405,6 +2454,7 @@ mtx_destroy(&sc->tx_lock); sx_destroy(&sc->driver_lock); if_free(sc->ifp); + bus_dma_tag_destroy(sc->parent_dmat); return 0; }