diff options
author | Mike Belopuhov <mikeb@cvs.openbsd.org> | 2012-10-12 17:41:41 +0000 |
---|---|---|
committer | Mike Belopuhov <mikeb@cvs.openbsd.org> | 2012-10-12 17:41:41 +0000 |
commit | 1d974704b9b6a82fa327aac41fb4bfdb28fc7082 (patch) | |
tree | e3586c656d75db3bc76097bd824822ad5748a082 /sys/dev | |
parent | f902b818adf04bf6c31412950480fcdefa5bb366 (diff) |
major cleanup
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/pci/if_oce.c | 456 | ||||
-rw-r--r-- | sys/dev/pci/oce.c | 562 | ||||
-rw-r--r-- | sys/dev/pci/ocevar.h | 523 |
3 files changed, 683 insertions, 858 deletions
diff --git a/sys/dev/pci/if_oce.c b/sys/dev/pci/if_oce.c index 83a71abb075..f5fe4887579 100644 --- a/sys/dev/pci/if_oce.c +++ b/sys/dev/pci/if_oce.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_oce.c,v 1.17 2012/10/12 15:16:45 mikeb Exp $ */ +/* $OpenBSD: if_oce.c,v 1.18 2012/10/12 17:41:40 mikeb Exp $ */ /* * Copyright (c) 2012 Mike Belopuhov @@ -99,13 +99,17 @@ int oce_probe(struct device *parent, void *match, void *aux); void oce_attach(struct device *parent, struct device *self, void *aux); void oce_attachhook(void *arg); +int oce_attach_ifp(struct oce_softc *sc); int oce_ioctl(struct ifnet *ifp, u_long command, caddr_t data); void oce_init(void *xsc); void oce_stop(struct oce_softc *sc); void oce_iff(struct oce_softc *sc); +int oce_pci_alloc(struct oce_softc *sc); int oce_intr(void *arg); int oce_alloc_intr(struct oce_softc *sc); +void oce_intr_enable(struct oce_softc *sc); +void oce_intr_disable(struct oce_softc *sc); void oce_media_status(struct ifnet *ifp, struct ifmediareq *ifmr); int oce_media_change(struct ifnet *ifp); @@ -130,9 +134,8 @@ int oce_start_rq(struct oce_rq *rq); void oce_stop_rq(struct oce_rq *rq); void oce_free_posted_rxbuf(struct oce_rq *rq); -int oce_attach_ifp(struct oce_softc *sc); int oce_vid_config(struct oce_softc *sc); -void oce_mac_addr_set(struct oce_softc *sc); +void oce_set_macaddr(struct oce_softc *sc); void oce_local_timer(void *arg); #if defined(INET6) || defined(INET) @@ -206,11 +209,8 @@ oce_attach(struct device *parent, struct device *self, void *aux) { struct pci_attach_args *pa = (struct pci_attach_args *)aux; struct oce_softc *sc = (struct oce_softc *)self; - int rc = 0; - uint16_t devid; - devid = PCI_PRODUCT(pa->pa_id); - switch (devid) { + switch (PCI_PRODUCT(pa->pa_id)) { case PCI_PRODUCT_SERVERENGINES_BE2: case PCI_PRODUCT_SERVERENGINES_OCBE2: sc->flags |= OCE_FLAGS_BE2; @@ -225,7 +225,7 @@ oce_attach(struct device *parent, struct device *self, void *aux) } sc->pa = *pa; - if (oce_hw_pci_alloc(sc)) + if (oce_pci_alloc(sc)) return; sc->rss_enable = 0; @@ -234,33 +234,53 @@ oce_attach(struct device *parent, struct device *self, void *aux) sc->rq_frag_size = OCE_RQ_BUF_SIZE; sc->flow_control = OCE_DEFAULT_FLOW_CONTROL; - /* initialise the hardware */ - rc = oce_hw_init(sc); - if (rc) + /* create the bootstrap mailbox */ + if (oce_dma_alloc(sc, sizeof(struct oce_bmbx), &sc->bsmbx)) { + printf(": failed to allocate mailbox memory\n"); return; + } + + if (oce_init_fw(sc)) + goto fail_1; + + if (oce_mbox_init(sc)) { + printf(": failed to initialize mailbox\n"); + goto fail_1; + } + + if (oce_get_fw_version(sc) || oce_get_fw_config(sc)) { + printf(": failed to fetch fw configuration\n"); + goto fail_1; + } + + if (IS_BE(sc) && (sc->flags & OCE_FLAGS_BE3)) { + if (oce_check_native_mode(sc)) + goto fail_1; + } else + sc->be3_native = 0; + + if (oce_read_macaddr(sc, sc->macaddr)) { + printf(": failed to fetch MAC address\n"); + goto fail_1; + } + bcopy(sc->macaddr, sc->arpcom.ac_enaddr, ETH_ADDR_LEN); sc->nrqs = 1; sc->nwqs = 1; sc->intr_count = 1; - rc = oce_alloc_intr(sc); - if (rc) - goto dma_free; - - rc = oce_init_queues(sc); - if (rc) - goto dma_free; + if (oce_alloc_intr(sc)) + goto fail_1; - bcopy(sc->macaddr.mac_addr, sc->arpcom.ac_enaddr, ETH_ADDR_LEN); + if (oce_init_queues(sc)) + goto fail_1; - rc = oce_attach_ifp(sc); - if (rc) - goto queues_free; + if (oce_attach_ifp(sc)) + goto fail_2; #ifdef OCE_LRO - rc = oce_init_lro(sc); - if (rc) - goto ifp_free; + if (oce_init_lro(sc)) + goto fail_3; #endif timeout_set(&sc->timer, oce_local_timer, sc); @@ -268,20 +288,21 @@ oce_attach(struct device *parent, struct device *self, void *aux) mountroothook_establish(oce_attachhook, sc); - printf(", address %s\n", ether_sprintf(sc->macaddr.mac_addr)); + printf(", address %s\n", ether_sprintf(sc->arpcom.ac_enaddr)); + printf("%s: %s ASIC %d\n", sc->dev.dv_xname, sc->fw_version, sc->asic_revision); return; #ifdef OCE_LRO -lro_free: +fail_4: oce_free_lro(sc); -ifp_free: +fail_3: #endif ether_ifdetach(&sc->arpcom.ac_if); if_detach(&sc->arpcom.ac_if); -queues_free: +fail_2: oce_release_queues(sc); -dma_free: +fail_1: oce_dma_free(sc, &sc->bsmbx); } @@ -292,14 +313,14 @@ oce_attachhook(void *arg) oce_get_link_status(sc); - oce_arm_cq(sc->mq->parent, sc->mq->cq->cq_id, 0, TRUE); + oce_arm_cq(sc->mq->sc, sc->mq->cq->id, 0, TRUE); /* * We need to get MCC async events. So enable intrs and arm * first EQ, Other EQs will be armed after interface is UP */ - oce_hw_intr_enable(sc); - oce_arm_eq(sc, sc->eq[0]->eq_id, 0, TRUE, FALSE); + oce_intr_enable(sc); + oce_arm_eq(sc, sc->eq[0]->id, 0, TRUE, FALSE); /* * Send first mcc cmd and after that we get gracious @@ -309,6 +330,50 @@ oce_attachhook(void *arg) } int +oce_attach_ifp(struct oce_softc *sc) +{ + struct ifnet *ifp = &sc->arpcom.ac_if; + + ifmedia_init(&sc->media, IFM_IMASK, oce_media_change, oce_media_status); + ifmedia_add(&sc->media, IFM_ETHER | IFM_AUTO, 0, NULL); + ifmedia_set(&sc->media, IFM_ETHER | IFM_AUTO); + + strlcpy(ifp->if_xname, sc->dev.dv_xname, IFNAMSIZ); + ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; + ifp->if_ioctl = oce_ioctl; + ifp->if_start = oce_start; + ifp->if_watchdog = oce_watchdog; + ifp->if_hardmtu = OCE_MAX_MTU; + ifp->if_softc = sc; + IFQ_SET_MAXLEN(&ifp->if_snd, sc->tx_ring_size - 1); + IFQ_SET_READY(&ifp->if_snd); + + /* oce splits jumbos into 2k chunks... */ + m_clsetwms(ifp, MCLBYTES, 8, sc->rx_ring_size); + + ifp->if_capabilities = IFCAP_VLAN_MTU; + +#if NVLAN > 0 + ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING; +#endif + +#if defined(INET6) || defined(INET) +#ifdef OCE_TSO + ifp->if_capabilities |= IFCAP_TSO; + ifp->if_capabilities |= IFCAP_VLAN_HWTSO; +#endif +#ifdef OCE_LRO + ifp->if_capabilities |= IFCAP_LRO; +#endif +#endif + + if_attach(ifp); + ether_ifattach(ifp); + + return 0; +} + +int oce_ioctl(struct ifnet *ifp, u_long command, caddr_t data) { struct oce_softc *sc = ifp->if_softc; @@ -429,7 +494,7 @@ oce_intr(void *arg) claimed = 1; /* Clear EQ entries, but dont arm */ - oce_arm_eq(sc, eq->eq_id, num_eqes, FALSE, TRUE); + oce_arm_eq(sc, eq->id, num_eqes, FALSE, TRUE); /* Process TX, RX and MCC. But dont arm CQ */ for (i = 0; i < eq->cq_valid; i++) { @@ -440,14 +505,91 @@ oce_intr(void *arg) /* Arm all cqs connected to this EQ */ for (i = 0; i < eq->cq_valid; i++) { cq = eq->cq[i]; - oce_arm_cq(sc, cq->cq_id, 0, TRUE); + oce_arm_cq(sc, cq->id, 0, TRUE); } eq_arm: - oce_arm_eq(sc, eq->eq_id, 0, TRUE, FALSE); + oce_arm_eq(sc, eq->id, 0, TRUE, FALSE); return (claimed); } + +int +oce_pci_alloc(struct oce_softc *sc) +{ + struct pci_attach_args *pa = &sc->pa; + pci_sli_intf_t intf; + pcireg_t memtype, reg; + + /* setup the device config region */ + if (IS_BE(sc) && (sc->flags & OCE_FLAGS_BE2)) + reg = OCE_BAR_CFG_BE2; + else + reg = OCE_BAR_CFG; + + memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, reg); + if (pci_mapreg_map(pa, reg, memtype, 0, &sc->cfg_iot, + &sc->cfg_ioh, NULL, &sc->cfg_size, + IS_BE(sc) ? 0 : 32768)) { + printf(": can't find cfg mem space\n"); + return (ENXIO); + } + + /* Read the SLI_INTF register and determine whether we + * can use this port and its features + */ + intf.dw0 = pci_conf_read(pa->pa_pc, pa->pa_tag, OCE_INTF_REG_OFFSET); + + if (intf.bits.sli_valid != OCE_INTF_VALID_SIG) { + printf(": invalid signature\n"); + goto fail_1; + } + + if (intf.bits.sli_rev != OCE_INTF_SLI_REV4) { + printf(": adapter doesnt support SLI revision %d\n", + intf.bits.sli_rev); + goto fail_1; + } + + if (intf.bits.sli_if_type == OCE_INTF_IF_TYPE_1) + sc->flags |= OCE_FLAGS_MBOX_ENDIAN_RQD; + + if (intf.bits.sli_hint1 == OCE_INTF_FUNC_RESET_REQD) + sc->flags |= OCE_FLAGS_FUNCRESET_RQD; + + if (intf.bits.sli_func_type == OCE_INTF_VIRT_FUNC) + sc->flags |= OCE_FLAGS_VIRTUAL_PORT; + + /* Lancer has one BAR (CFG) but BE3 has three (CFG, CSR, DB) */ + if (IS_BE(sc)) { + /* set up CSR region */ + reg = OCE_BAR_CSR; + memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, reg); + if (pci_mapreg_map(pa, reg, memtype, 0, &sc->csr_iot, + &sc->csr_ioh, NULL, &sc->csr_size, 0)) { + printf(": can't find csr mem space\n"); + goto fail_1; + } + + /* set up DB doorbell region */ + reg = OCE_BAR_DB; + memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, reg); + if (pci_mapreg_map(pa, reg, memtype, 0, &sc->db_iot, + &sc->db_ioh, NULL, &sc->db_size, 0)) { + printf(": can't find csr mem space\n"); + goto fail_2; + } + } + + return (0); + +fail_2: + bus_space_unmap(sc->csr_iot, sc->csr_ioh, sc->csr_size); +fail_1: + bus_space_unmap(sc->cfg_iot, sc->cfg_ioh, sc->cfg_size); + return (ENXIO); +} + int oce_alloc_intr(struct oce_softc *sc) { @@ -477,6 +619,26 @@ oce_alloc_intr(struct oce_softc *sc) } void +oce_intr_enable(struct oce_softc *sc) +{ + uint32_t reg; + + reg = OCE_READ_REG32(sc, cfg, PCICFG_INTR_CTRL); + reg |= HOSTINTR_MASK; + OCE_WRITE_REG32(sc, cfg, PCICFG_INTR_CTRL, reg); +} + +void +oce_intr_disable(struct oce_softc *sc) +{ + uint32_t reg; + + reg = OCE_READ_REG32(sc, cfg, PCICFG_INTR_CTRL); + reg &= ~HOSTINTR_MASK; + OCE_WRITE_REG32(sc, cfg, PCICFG_INTR_CTRL, reg); +} + +void oce_update_link_status(struct oce_softc *sc) { struct ifnet *ifp = &sc->arpcom.ac_if; @@ -712,7 +874,7 @@ retry: oce_dma_sync(&wq->ring->dma, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); - reg_value = (num_wqes << 16) | wq->wq_id; + reg_value = (num_wqes << 16) | wq->id; OCE_WRITE_REG32(sc, db, PD_TXULP_DB, reg_value); return 0; @@ -726,7 +888,7 @@ free_ret: void oce_txeof(struct oce_wq *wq, uint32_t wqe_idx, uint32_t status) { - struct oce_softc *sc = (struct oce_softc *) wq->parent; + struct oce_softc *sc = (struct oce_softc *) wq->sc; struct oce_packet_desc *pd; struct ifnet *ifp = &sc->arpcom.ac_if; struct mbuf *m; @@ -881,7 +1043,7 @@ void oce_wq_handler(void *arg) { struct oce_wq *wq = (struct oce_wq *)arg; - struct oce_softc *sc = wq->parent; + struct oce_softc *sc = wq->sc; struct oce_cq *cq = wq->cq; struct oce_nic_tx_cqe *cqe; int num_cqes = 0; @@ -906,13 +1068,13 @@ oce_wq_handler(void *arg) } if (num_cqes) - oce_arm_cq(sc, cq->cq_id, num_cqes, FALSE); + oce_arm_cq(sc, cq->id, num_cqes, FALSE); } void oce_rxeof(struct oce_rq *rq, struct oce_nic_rx_cqe *cqe) { - struct oce_softc *sc = (struct oce_softc *)rq->parent; + struct oce_softc *sc = (struct oce_softc *)rq->sc; struct oce_packet_desc *pd; struct ifnet *ifp = &sc->arpcom.ac_if; struct mbuf *m = NULL, *tail = NULL; @@ -1047,7 +1209,7 @@ oce_discard_rx_comp(struct oce_rq *rq, struct oce_nic_rx_cqe *cqe) { uint32_t out, i = 0; struct oce_packet_desc *pd; - struct oce_softc *sc = (struct oce_softc *) rq->parent; + struct oce_softc *sc = (struct oce_softc *) rq->sc; int num_frags = cqe->u0.s.num_fragments; if (IS_XE201(sc) && cqe->u0.s.error) { @@ -1115,7 +1277,7 @@ oce_rx_flush_lro(struct oce_rq *rq) { struct lro_ctrl *lro = &rq->lro; struct lro_entry *queued; - struct oce_softc *sc = (struct oce_softc *) rq->parent; + struct oce_softc *sc = (struct oce_softc *) rq->sc; if (!IF_LRO_ENABLED(sc)) return; @@ -1166,7 +1328,7 @@ oce_free_lro(struct oce_softc *sc) int oce_get_buf(struct oce_rq *rq) { - struct oce_softc *sc = (struct oce_softc *)rq->parent; + struct oce_softc *sc = (struct oce_softc *)rq->sc; struct ifnet *ifp = &sc->arpcom.ac_if; struct oce_packet_desc *pd; struct oce_nic_rqe *rqe; @@ -1218,7 +1380,7 @@ oce_get_buf(struct oce_rq *rq) int oce_alloc_rx_bufs(struct oce_rq *rq) { - struct oce_softc *sc = (struct oce_softc *)rq->parent; + struct oce_softc *sc = (struct oce_softc *)rq->sc; pd_rxulp_db_t rxdb_reg; int i, nbufs = 0; @@ -1230,14 +1392,14 @@ oce_alloc_rx_bufs(struct oce_rq *rq) DELAY(1); bzero(&rxdb_reg, sizeof(rxdb_reg)); rxdb_reg.bits.num_posted = OCE_MAX_RQ_POSTS; - rxdb_reg.bits.qid = rq->rq_id; + rxdb_reg.bits.qid = rq->id; OCE_WRITE_REG32(sc, db, PD_RXULP_DB, rxdb_reg.dw0); nbufs -= OCE_MAX_RQ_POSTS; } if (nbufs > 0) { DELAY(1); bzero(&rxdb_reg, sizeof(rxdb_reg)); - rxdb_reg.bits.qid = rq->rq_id; + rxdb_reg.bits.qid = rq->id; rxdb_reg.bits.num_posted = nbufs; OCE_WRITE_REG32(sc, db, PD_RXULP_DB, rxdb_reg.dw0); } @@ -1266,7 +1428,7 @@ oce_rq_handler(void *arg) { struct oce_rq *rq = (struct oce_rq *)arg; struct oce_cq *cq = rq->cq; - struct oce_softc *sc = rq->parent; + struct oce_softc *sc = rq->sc; struct oce_nic_rx_cqe *cqe; struct ifnet *ifp = &sc->arpcom.ac_if; int num_cqes = 0, rq_buffers_used = 0; @@ -1314,74 +1476,28 @@ oce_rq_handler(void *arg) #endif if (num_cqes) { - oce_arm_cq(sc, cq->cq_id, num_cqes, FALSE); + oce_arm_cq(sc, cq->id, num_cqes, FALSE); rq_buffers_used = OCE_RQ_PACKET_ARRAY_SIZE - rq->pending; if (rq_buffers_used > 1 && !oce_alloc_rx_bufs(rq)) timeout_add(&sc->rxrefill, 1); } } -int -oce_attach_ifp(struct oce_softc *sc) -{ - struct ifnet *ifp = &sc->arpcom.ac_if; - - ifmedia_init(&sc->media, IFM_IMASK, oce_media_change, oce_media_status); - ifmedia_add(&sc->media, IFM_ETHER | IFM_AUTO, 0, NULL); - ifmedia_set(&sc->media, IFM_ETHER | IFM_AUTO); - - strlcpy(ifp->if_xname, sc->dev.dv_xname, IFNAMSIZ); - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; - ifp->if_ioctl = oce_ioctl; - ifp->if_start = oce_start; - ifp->if_watchdog = oce_watchdog; - ifp->if_hardmtu = OCE_MAX_MTU; - ifp->if_softc = sc; - IFQ_SET_MAXLEN(&ifp->if_snd, sc->tx_ring_size - 1); - IFQ_SET_READY(&ifp->if_snd); - - /* oce splits jumbos into 2k chunks... */ - m_clsetwms(ifp, MCLBYTES, 8, sc->rx_ring_size); - - ifp->if_capabilities = IFCAP_VLAN_MTU; - -#if NVLAN > 0 - ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING; -#endif - -#if defined(INET6) || defined(INET) -#ifdef OCE_TSO - ifp->if_capabilities |= IFCAP_TSO; - ifp->if_capabilities |= IFCAP_VLAN_HWTSO; -#endif -#ifdef OCE_LRO - ifp->if_capabilities |= IFCAP_LRO; -#endif -#endif - - if_attach(ifp); - ether_ifattach(ifp); - - return 0; -} - void -oce_mac_addr_set(struct oce_softc *sc) +oce_set_macaddr(struct oce_softc *sc) { uint32_t old_pmac_id = sc->pmac_id; int status = 0; - if (!bcmp(sc->arpcom.ac_enaddr, sc->macaddr.mac_addr, ETH_ADDR_LEN)) + if (!bcmp(sc->macaddr, sc->arpcom.ac_enaddr, ETH_ADDR_LEN)) return; - status = oce_mbox_macaddr_add(sc, sc->arpcom.ac_enaddr, sc->if_id, + status = oce_macaddr_add(sc, sc->arpcom.ac_enaddr, sc->if_id, &sc->pmac_id); - if (!status) { - status = oce_mbox_macaddr_del(sc, sc->if_id, old_pmac_id); - bcopy(sc->arpcom.ac_enaddr, sc->macaddr.mac_addr, - sc->macaddr.size_of_struct); - } else - printf("%s: Failed to update MAC address\n", sc->dev.dv_xname); + if (!status) + status = oce_macaddr_del(sc, sc->if_id, old_pmac_id); + else + printf("%s: failed to set MAC address\n", sc->dev.dv_xname); } void @@ -1422,7 +1538,7 @@ oce_stop(struct oce_softc *sc) ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); /* Stop intrs and finish any bottom halves pending */ - oce_hw_intr_disable(sc); + oce_intr_disable(sc); /* Invalidate any pending cq and eq entries */ for_all_eq_queues(sc, eq, i) @@ -1452,7 +1568,7 @@ oce_init(void *arg) DELAY(10); - oce_mac_addr_set(sc); + oce_set_macaddr(sc); oce_iff(sc); @@ -1484,15 +1600,15 @@ oce_init(void *arg) #endif for_all_rq_queues(sc, rq, i) - oce_arm_cq(rq->parent, rq->cq->cq_id, 0, TRUE); + oce_arm_cq(rq->sc, rq->cq->id, 0, TRUE); for_all_wq_queues(sc, wq, i) - oce_arm_cq(wq->parent, wq->cq->cq_id, 0, TRUE); + oce_arm_cq(wq->sc, wq->cq->id, 0, TRUE); - oce_arm_cq(sc->mq->parent, sc->mq->cq->cq_id, 0, TRUE); + oce_arm_cq(sc->mq->sc, sc->mq->cq->id, 0, TRUE); for_all_eq_queues(sc, eq, i) - oce_arm_eq(sc, eq->eq_id, 0, TRUE, FALSE); + oce_arm_eq(sc, eq->id, 0, TRUE, FALSE); if (oce_get_link_status(sc) == 0) oce_update_link_status(sc); @@ -1502,7 +1618,7 @@ oce_init(void *arg) timeout_add_sec(&sc->timer, 1); - oce_hw_intr_enable(sc); + oce_intr_enable(sc); return; error: @@ -1531,7 +1647,7 @@ void oce_mq_handler(void *arg) { struct oce_mq *mq = (struct oce_mq *)arg; - struct oce_softc *sc = mq->parent; + struct oce_softc *sc = mq->sc; struct oce_cq *cq = mq->cq; struct oce_mq_cqe *cqe; struct oce_async_cqe_link_state *acqe; @@ -1568,7 +1684,7 @@ oce_mq_handler(void *arg) } if (num_cqes) - oce_arm_cq(sc, cq->cq_id, num_cqes, FALSE /* TRUE */); + oce_arm_cq(sc, cq->id, num_cqes, FALSE /* TRUE */); } int @@ -1594,7 +1710,7 @@ oce_init_queues(struct oce_softc *sc) } /* Create network interface on card */ - if (oce_create_iface(sc)) + if (oce_create_iface(sc, sc->macaddr)) goto error; /* create all of the event queues */ @@ -1685,9 +1801,8 @@ oce_wq_init(struct oce_softc *sc, uint32_t q_len, uint32_t wq_type) wq->cfg.wq_type = (uint8_t) wq_type; wq->cfg.eqd = OCE_DEFAULT_WQ_EQD; wq->cfg.nbufs = 2 * wq->cfg.q_len; - wq->cfg.nhdl = 2 * wq->cfg.q_len; - wq->parent = sc; + wq->sc = sc; wq->tag = sc->pa.pa_dmat; for (i = 0; i < OCE_WQ_PACKET_ARRAY_SIZE; i++) { @@ -1712,11 +1827,11 @@ free_wq: void oce_wq_destroy(struct oce_wq *wq) { - struct oce_softc *sc = wq->parent; + struct oce_softc *sc = wq->sc; int i; - if (wq->qstate == QCREATED) - oce_mbox_destroy_q(sc, QTYPE_WQ, wq->wq_id); + if (wq->state == QCREATED) + oce_destroy_queue(sc, QTYPE_WQ, wq->id); if (wq->cq != NULL) oce_cq_destroy(wq->cq); @@ -1742,7 +1857,7 @@ oce_wq_destroy(struct oce_wq *wq) int oce_wq_create(struct oce_wq *wq, struct oce_eq *eq) { - struct oce_softc *sc = wq->parent; + struct oce_softc *sc = wq->sc; struct oce_cq *cq; int rc = 0; @@ -1753,12 +1868,11 @@ oce_wq_create(struct oce_wq *wq, struct oce_eq *eq) wq->cq = cq; - rc = oce_mbox_create_wq(wq); + rc = oce_create_wq(sc, wq); if (rc) goto error; - wq->qstate = QCREATED; - wq->wq_free = wq->cfg.q_len; + wq->state = QCREATED; wq->ring->cidx = 0; wq->ring->pidx = 0; @@ -1804,7 +1918,7 @@ oce_rq_init(struct oce_softc *sc, uint32_t q_len, uint32_t frag_size, rq->cfg.frag_size = frag_size; rq->cfg.is_rss_queue = rss; - rq->parent = sc; + rq->sc = sc; rq->tag = sc->pa.pa_dmat; for (i = 0; i < OCE_RQ_PACKET_ARRAY_SIZE; i++) { @@ -1827,11 +1941,11 @@ free_rq: void oce_rq_destroy(struct oce_rq *rq) { - struct oce_softc *sc = rq->parent; + struct oce_softc *sc = rq->sc; int i; - if (rq->qstate == QCREATED) - oce_mbox_destroy_q(sc, QTYPE_RQ, rq->rq_id); + if (rq->state == QCREATED) + oce_destroy_queue(sc, QTYPE_RQ, rq->id); if (rq->cq != NULL) oce_cq_destroy(rq->cq); @@ -1860,7 +1974,7 @@ oce_rq_destroy(struct oce_rq *rq) int oce_rq_create(struct oce_rq *rq, uint32_t if_id, struct oce_eq *eq) { - struct oce_softc *sc = rq->parent; + struct oce_softc *sc = rq->sc; struct oce_cq *cq; cq = oce_cq_create(sc, eq, CQ_LEN_1024, sizeof(struct oce_nic_rx_cqe), @@ -1883,10 +1997,12 @@ oce_rq_create(struct oce_rq *rq, uint32_t if_id, struct oce_eq *eq) int oce_start_rq(struct oce_rq *rq) { - if (rq->qstate != QCREATED) { - if (oce_mbox_create_rq(rq)) + struct oce_softc *sc = rq->sc; + + if (rq->state != QCREATED) { + if (oce_create_rq(sc, rq)) return 1; - rq->qstate = QCREATED; + rq->state = QCREATED; rq->pending = 0; rq->ring->cidx = 0; rq->ring->pidx = 0; @@ -1900,11 +2016,11 @@ oce_start_rq(struct oce_rq *rq) void oce_stop_rq(struct oce_rq *rq) { - struct oce_softc *sc = rq->parent; + struct oce_softc *sc = rq->sc; - if (rq->qstate == QCREATED) { - oce_mbox_destroy_q(sc, QTYPE_RQ, rq->rq_id); - rq->qstate = QDELETED; + if (rq->state == QCREATED) { + oce_destroy_queue(sc, QTYPE_RQ, rq->id); + rq->state = QDELETED; DELAY(10); } } @@ -1936,13 +2052,13 @@ oce_eq_create(struct oce_softc *sc, uint32_t q_len, uint32_t item_size, return NULL; } - eq->parent = sc; - eq->eq_id = 0xffff; - eq->eq_cfg.q_len = q_len; - eq->eq_cfg.item_size = item_size; - eq->eq_cfg.cur_eqd = (uint8_t)eq_delay; + eq->sc = sc; + eq->id = 0xffff; + eq->cfg.q_len = q_len; + eq->cfg.item_size = item_size; + eq->cfg.cur_eqd = (uint8_t)eq_delay; - rc = oce_mbox_create_eq(eq); + rc = oce_create_eq(sc, eq); if (rc) goto free_eq; @@ -1955,10 +2071,10 @@ free_eq: void oce_eq_destroy(struct oce_eq *eq) { - struct oce_softc *sc = eq->parent; + struct oce_softc *sc = eq->sc; - if (eq->eq_id != 0xffff) - oce_mbox_destroy_q(sc, QTYPE_EQ, eq->eq_id); + if (eq->id != 0xffff) + oce_destroy_queue(sc, QTYPE_EQ, eq->id); if (eq->ring != NULL) oce_destroy_ring(sc, eq->ring); @@ -1992,7 +2108,7 @@ oce_mq_create(struct oce_softc *sc, struct oce_eq *eq, uint32_t q_len) return NULL; } - mq->parent = sc; + mq->sc = sc; mq->cq = cq; mq->ring = oce_create_ring(sc, q_len, sizeof(struct oce_mbx), 8); @@ -2001,14 +2117,14 @@ oce_mq_create(struct oce_softc *sc, struct oce_eq *eq, uint32_t q_len) mq->cfg.q_len = (uint8_t)q_len; - rc = oce_mbox_create_mq(mq); + rc = oce_create_mq(sc, mq); if (rc) goto free_mq; eq->cq[eq->cq_valid] = cq; eq->cq_valid++; mq->cq->eq = eq; - mq->qstate = QCREATED; + mq->state = QCREATED; mq->cq->cb_arg = mq; mq->cq->cq_handler = oce_mq_handler; @@ -2021,10 +2137,10 @@ free_mq: void oce_mq_destroy(struct oce_mq *mq) { - struct oce_softc *sc = mq->parent; + struct oce_softc *sc = mq->sc; - if (mq->qstate == QCREATED) - oce_mbox_destroy_q(sc, QTYPE_MQ, mq->mq_id); + if (mq->state == QCREATED) + oce_destroy_queue(sc, QTYPE_MQ, mq->id); if (mq->ring != NULL) oce_destroy_ring(sc, mq->ring); @@ -2048,7 +2164,7 @@ oce_mq_destroy(struct oce_mq *mq) */ struct oce_cq * oce_cq_create(struct oce_softc *sc, struct oce_eq *eq, uint32_t q_len, - uint32_t item_size, uint32_t is_eventable, uint32_t nodelay, + uint32_t item_size, uint32_t eventable, uint32_t nodelay, uint32_t ncoalesce) { struct oce_cq *cq = NULL; @@ -2064,13 +2180,15 @@ oce_cq_create(struct oce_softc *sc, struct oce_eq *eq, uint32_t q_len, return NULL; } - cq->parent = sc; + cq->sc = sc; cq->eq = eq; - cq->cq_cfg.q_len = q_len; - cq->cq_cfg.item_size = item_size; - cq->cq_cfg.nodelay = (uint8_t) nodelay; + cq->cfg.q_len = q_len; + cq->cfg.item_size = item_size; + cq->cfg.nodelay = (uint8_t) nodelay; + cq->cfg.ncoalesce = ncoalesce; + cq->cfg.eventable = eventable; - rc = oce_mbox_create_cq(cq, ncoalesce, is_eventable); + rc = oce_create_cq(sc, cq); if (rc) goto free_cq; @@ -2085,10 +2203,10 @@ free_cq: void oce_cq_destroy(struct oce_cq *cq) { - struct oce_softc *sc = cq->parent; + struct oce_softc *sc = cq->sc; if (cq->ring != NULL) { - oce_mbox_destroy_q(sc, QTYPE_CQ, cq->cq_id); + oce_destroy_queue(sc, QTYPE_CQ, cq->id); oce_destroy_ring(sc, cq->ring); } @@ -2147,7 +2265,7 @@ oce_drain_eq(struct oce_eq *eq) { struct oce_eqe *eqe; uint16_t num_eqe = 0; - struct oce_softc *sc = eq->parent; + struct oce_softc *sc = eq->sc; for (;;) { eqe = RING_GET_CONSUMER_ITEM_VA(eq->ring, struct oce_eqe); @@ -2159,13 +2277,13 @@ oce_drain_eq(struct oce_eq *eq) RING_GET(eq->ring, 1); } - oce_arm_eq(sc, eq->eq_id, num_eqe, FALSE, TRUE); + oce_arm_eq(sc, eq->id, num_eqe, FALSE, TRUE); } void oce_drain_wq(struct oce_wq *wq) { - struct oce_softc *sc = wq->parent; + struct oce_softc *sc = wq->sc; struct oce_cq *cq = wq->cq; struct oce_nic_tx_cqe *cqe; int num_cqes = 0; @@ -2182,7 +2300,7 @@ oce_drain_wq(struct oce_wq *wq) num_cqes++; } - oce_arm_cq(sc, cq->cq_id, num_cqes, FALSE); + oce_arm_cq(sc, cq->id, num_cqes, FALSE); } /* @@ -2210,7 +2328,7 @@ oce_drain_rq(struct oce_rq *rq) struct oce_cq *cq; struct oce_softc *sc; - sc = rq->parent; + sc = rq->sc; cq = rq->cq; cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring, struct oce_nic_rx_cqe); /* dequeue till you reach an invalid cqe */ @@ -2222,7 +2340,7 @@ oce_drain_rq(struct oce_rq *rq) num_cqe++; } - oce_arm_cq(sc, cq->cq_id, num_cqe, FALSE); + oce_arm_cq(sc, cq->id, num_cqe, FALSE); } void @@ -2324,13 +2442,6 @@ oce_dma_free(struct oce_softc *sc, struct oce_dma_mem *dma) } } -void -oce_destroy_ring(struct oce_softc *sc, struct oce_ring *ring) -{ - oce_dma_free(sc, &ring->dma); - free(ring, M_DEVBUF); -} - struct oce_ring * oce_create_ring(struct oce_softc *sc, int q_len, int item_size, int max_segs) @@ -2389,6 +2500,13 @@ fail_0: return NULL; } +void +oce_destroy_ring(struct oce_softc *sc, struct oce_ring *ring) +{ + oce_dma_free(sc, &ring->dma); + free(ring, M_DEVBUF); +} + int oce_load_ring(struct oce_softc *sc, struct oce_ring *ring, struct phys_addr *pa_list, int max_segs) diff --git a/sys/dev/pci/oce.c b/sys/dev/pci/oce.c index 389fa3b8ee0..73e7253757c 100644 --- a/sys/dev/pci/oce.c +++ b/sys/dev/pci/oce.c @@ -1,4 +1,4 @@ -/* $OpenBSD: oce.c,v 1.10 2012/10/12 15:16:45 mikeb Exp $ */ +/* $OpenBSD: oce.c,v 1.11 2012/10/12 17:41:40 mikeb Exp $ */ /* * Copyright (c) 2012 Mike Belopuhov @@ -96,20 +96,12 @@ #include <dev/pci/ocereg.h> #include <dev/pci/ocevar.h> -int oce_reset_fw(struct oce_softc *sc); -int oce_post(struct oce_softc *sc); int oce_mbox_wait(struct oce_softc *sc); int oce_mbox_dispatch(struct oce_softc *sc); -int oce_mbox_init(struct oce_softc *sc); int oce_fw(struct oce_softc *sc, int subsys, int opcode, int version, void *payload, int length); -int oce_get_fw_version(struct oce_softc *sc); -int oce_get_fw_config(struct oce_softc *sc); -int oce_if_create(struct oce_softc *sc, uint32_t cap_flags, uint32_t en_flags, - uint16_t vlan_tag, uint8_t *mac_addr, uint32_t *if_id); -int oce_if_del(struct oce_softc *sc, uint32_t if_id); int oce_config_vlan(struct oce_softc *sc, uint32_t if_id, struct normal_vlan *vtag_arr, uint8_t vtag_cnt, uint32_t untagged, uint32_t enable_promisc); @@ -119,22 +111,22 @@ int oce_rss_itbl_init(struct oce_softc *sc, struct mbx_config_nic_rss *fwcmd); int oce_set_common_iface_rx_filter(struct oce_softc *sc, struct oce_dma_mem *sgl); -int oce_mbox_check_native_mode(struct oce_softc *sc); - int oce_mbox_get_nic_stats_v0(struct oce_softc *sc, void *buf); int oce_mbox_get_nic_stats(struct oce_softc *sc, void *buf); int oce_mbox_get_pport_stats(struct oce_softc *sc, void *buf, uint32_t reset_stats); /** - * @brief Function to post status + * @brief Wait for FW to become ready and reset it * @param sc software handle to the device */ int -oce_post(struct oce_softc *sc) +oce_init_fw(struct oce_softc *sc) { + struct ioctl_common_function_reset fwcmd; mpu_ep_semaphore_t post_status; int tmo = 60000; + int err = 0; /* read semaphore CSR */ post_status.dw0 = OCE_READ_REG32(sc, csr, MPU_EP_SEMAPHORE(sc)); @@ -145,7 +137,7 @@ oce_post(struct oce_softc *sc) OCE_WRITE_REG32(sc, csr, MPU_EP_SEMAPHORE(sc), post_status.dw0); } - /* wait for FW ready */ + /* wait for FW to become ready */ for (;;) { if (--tmo == 0) break; @@ -154,169 +146,42 @@ oce_post(struct oce_softc *sc) post_status.dw0 = OCE_READ_REG32(sc, csr, MPU_EP_SEMAPHORE(sc)); if (post_status.bits.error) { - printf("%s: POST failed: %x\n", sc->dev.dv_xname, - post_status.dw0); + printf(": POST failed: %x\n", post_status.dw0); return ENXIO; } - if (post_status.bits.stage == POST_STAGE_ARMFW_READY) - return 0; + if (post_status.bits.stage == POST_STAGE_ARMFW_READY) { + /* reset FW */ + bzero(&fwcmd, sizeof(fwcmd)); + if (sc->flags & OCE_FLAGS_FUNCRESET_RQD) + err = oce_fw(sc, MBX_SUBSYSTEM_COMMON, + OPCODE_COMMON_FUNCTION_RESET, OCE_MBX_VER_V0, + &fwcmd, sizeof(fwcmd)); + return (err); + } } - printf("%s: POST timed out: %x\n", sc->dev.dv_xname, post_status.dw0); + printf(": POST timed out: %x\n", post_status.dw0); return ENXIO; } /** - * @brief Function for hardware initialization - * @param sc software handle to the device - */ -int -oce_hw_init(struct oce_softc *sc) -{ - int rc = 0; - - rc = oce_post(sc); - if (rc) - return rc; - - /* create the bootstrap mailbox */ - rc = oce_dma_alloc(sc, sizeof(struct oce_bmbx), &sc->bsmbx); - if (rc) { - printf("%s: Mailbox alloc failed\n", sc->dev.dv_xname); - return rc; - } - - rc = oce_reset_fw(sc); - if (rc) - goto error; - - rc = oce_mbox_init(sc); - if (rc) - goto error; - - rc = oce_get_fw_version(sc); - if (rc) - goto error; - - rc = oce_get_fw_config(sc); - if (rc) - goto error; - - sc->macaddr.size_of_struct = 6; - rc = oce_read_mac_addr(sc, 0, 1, MAC_ADDRESS_TYPE_NETWORK, - &sc->macaddr); - if (rc) - goto error; - - if (IS_BE(sc) && (sc->flags & OCE_FLAGS_BE3)) { - rc = oce_mbox_check_native_mode(sc); - if (rc) - goto error; - } else - sc->be3_native = 0; - - return rc; - -error: - oce_dma_free(sc, &sc->bsmbx); - printf("%s: Hardware initialisation failed\n", sc->dev.dv_xname); - return rc; -} - -/** * @brief Allocate PCI resources. * * @param sc software handle to the device * @returns 0 if successful, or error */ -int -oce_hw_pci_alloc(struct oce_softc *sc) -{ - struct pci_attach_args *pa = &sc->pa; - pci_sli_intf_t intf; - pcireg_t memtype, reg; - - /* setup the device config region */ - if (IS_BE(sc) && (sc->flags & OCE_FLAGS_BE2)) - reg = OCE_BAR_CFG_BE2; - else - reg = OCE_BAR_CFG; - - memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, reg); - if (pci_mapreg_map(pa, reg, memtype, 0, &sc->cfg_btag, - &sc->cfg_bhandle, NULL, &sc->cfg_size, - IS_BE(sc) ? 0 : 32768)) { - printf(": can't find cfg mem space\n"); - return ENXIO; - } - - /* Read the SLI_INTF register and determine whether we - * can use this port and its features - */ - intf.dw0 = pci_conf_read(pa->pa_pc, pa->pa_tag, OCE_INTF_REG_OFFSET); - - if (intf.bits.sli_valid != OCE_INTF_VALID_SIG) { - printf(": invalid signature\n"); - goto fail_1; - } - - if (intf.bits.sli_rev != OCE_INTF_SLI_REV4) { - printf(": adapter doesnt support SLI revision %d\n", - intf.bits.sli_rev); - goto fail_1; - } - - if (intf.bits.sli_if_type == OCE_INTF_IF_TYPE_1) - sc->flags |= OCE_FLAGS_MBOX_ENDIAN_RQD; - - if (intf.bits.sli_hint1 == OCE_INTF_FUNC_RESET_REQD) - sc->flags |= OCE_FLAGS_FUNCRESET_RQD; - - if (intf.bits.sli_func_type == OCE_INTF_VIRT_FUNC) - sc->flags |= OCE_FLAGS_VIRTUAL_PORT; - - /* Lancer has one BAR (CFG) but BE3 has three (CFG, CSR, DB) */ - if (IS_BE(sc)) { - /* set up CSR region */ - reg = OCE_BAR_CSR; - memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, reg); - if (pci_mapreg_map(pa, reg, memtype, 0, &sc->csr_btag, - &sc->csr_bhandle, NULL, &sc->csr_size, 0)) { - printf(": can't find csr mem space\n"); - goto fail_1; - } - - /* set up DB doorbell region */ - reg = OCE_BAR_DB; - memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, reg); - if (pci_mapreg_map(pa, reg, memtype, 0, &sc->db_btag, - &sc->db_bhandle, NULL, &sc->db_size, 0)) { - printf(": can't find csr mem space\n"); - goto fail_2; - } - } - - return 0; - -fail_2: - bus_space_unmap(sc->csr_btag, sc->csr_bhandle, sc->csr_size); -fail_1: - bus_space_unmap(sc->cfg_btag, sc->cfg_bhandle, sc->cfg_size); - return ENXIO; -} - /** * @brief Function for creating nw interface. * @param sc software handle to the device * @returns 0 on success, error otherwise */ int -oce_create_iface(struct oce_softc *sc) +oce_create_iface(struct oce_softc *sc, uint8_t *macaddr) { - int rc; - uint32_t capab_flags; - uint32_t capab_en_flags; + struct mbx_create_common_iface fwcmd; + uint32_t capab_flags, capab_en_flags; + int err = 0; /* interface capabilities to give device when creating interface */ capab_flags = OCE_CAPAB_FLAGS; @@ -338,104 +203,42 @@ oce_create_iface(struct oce_softc *sc) capab_flags &= ~MBX_RX_IFACE_FLAGS_RSS; } - rc = oce_if_create(sc, capab_flags, capab_en_flags, 0, - &sc->macaddr.mac_addr[0], &sc->if_id); - if (rc) - return rc; - - sc->nifs++; - - sc->if_cap_flags = capab_en_flags; - - /* Enable VLAN Promisc on HW */ - rc = oce_config_vlan(sc, (uint8_t)sc->if_id, NULL, 0, 1, 1); - if (rc) - goto error; - - /* set default flow control */ - rc = oce_set_flow_control(sc, sc->flow_control); - if (rc) - goto error; - - return rc; - -error: - oce_if_del(sc, sc->if_id); - sc->nifs--; - return rc; -} - -/** - * @brief Function for hardware enable interupts. - * @param sc software handle to the device - */ -void -oce_hw_intr_enable(struct oce_softc *sc) -{ - uint32_t reg; - - reg = OCE_READ_REG32(sc, cfg, PCICFG_INTR_CTRL); - reg |= HOSTINTR_MASK; - OCE_WRITE_REG32(sc, cfg, PCICFG_INTR_CTRL, reg); -} + bzero(&fwcmd, sizeof(fwcmd)); -/** - * @brief Function for hardware disable interupts - * @param sc software handle to the device - */ -void -oce_hw_intr_disable(struct oce_softc *sc) -{ - uint32_t reg; + fwcmd.params.req.version = 0; + fwcmd.params.req.cap_flags = htole32(capab_flags); + fwcmd.params.req.enable_flags = htole32(capab_en_flags); + if (macaddr != NULL) { + bcopy(macaddr, &fwcmd.params.req.mac_addr[0], ETH_ADDR_LEN); + fwcmd.params.req.mac_invalid = 0; + } else + fwcmd.params.req.mac_invalid = 1; - reg = OCE_READ_REG32(sc, cfg, PCICFG_INTR_CTRL); - reg &= ~HOSTINTR_MASK; - OCE_WRITE_REG32(sc, cfg, PCICFG_INTR_CTRL, reg); -} + err = oce_fw(sc, MBX_SUBSYSTEM_COMMON, OPCODE_COMMON_CREATE_IFACE, + OCE_MBX_VER_V0, &fwcmd, sizeof(fwcmd)); + if (err) + return (err); -/** - * @brief Function for hardware update multicast filter - * @param sc software handle to the device - * @param multi table of multicast addresses - * @param naddr number of multicast addresses in the table - */ -int -oce_update_mcast(struct oce_softc *sc, - uint8_t multi[][ETH_ADDR_LEN], int naddr) -{ - struct mbx_set_common_iface_multicast fwcmd; - int err; + sc->if_id = letoh32(fwcmd.params.rsp.if_id); - bzero(&fwcmd, sizeof(fwcmd)); + if (macaddr != NULL) + sc->pmac_id = letoh32(fwcmd.params.rsp.pmac_id); - bcopy(&multi[0], &fwcmd.params.req.mac[0], naddr * ETH_ADDR_LEN); - fwcmd.params.req.num_mac = htole16(naddr); - fwcmd.params.req.if_id = sc->if_id; + sc->nifs++; - err = oce_fw(sc, MBX_SUBSYSTEM_COMMON, - OPCODE_COMMON_SET_IFACE_MULTICAST, OCE_MBX_VER_V0, - &fwcmd, sizeof(fwcmd)); - return (err); -} + sc->if_cap_flags = capab_en_flags; -/** - * @brief Reset (firmware) common function - * @param sc software handle to the device - * @returns 0 on success, ETIMEDOUT on failure - */ -int -oce_reset_fw(struct oce_softc *sc) -{ - struct ioctl_common_function_reset fwcmd; - int err = 0; + /* Enable VLAN Promisc on HW */ + err = oce_config_vlan(sc, (uint8_t)sc->if_id, NULL, 0, 1, 1); + if (err) + return (err); - bzero(&fwcmd, sizeof(fwcmd)); + /* set default flow control */ + err = oce_set_flow_control(sc, sc->flow_control); + if (err) + return (err); - if (sc->flags & OCE_FLAGS_FUNCRESET_RQD) - err = oce_fw(sc, MBX_SUBSYSTEM_COMMON, - OPCODE_COMMON_FUNCTION_RESET, OCE_MBX_VER_V0, - &fwcmd, sizeof(fwcmd)); - return (err); + return 0; } /** @@ -619,80 +422,6 @@ oce_get_fw_version(struct oce_softc *sc) } /** - * @brief Firmware will send gracious notifications during - * attach only after sending first mcc commnad. We - * use MCC queue only for getting async and mailbox - * for sending cmds. So to get gracious notifications - * atleast send one dummy command on mcc. - */ -int -oce_first_mcc_cmd(struct oce_softc *sc) -{ - struct oce_mbx *mbx; - struct oce_mq *mq = sc->mq; - struct mbx_hdr *hdr; - struct mbx_get_common_fw_version *fwcmd; - uint32_t reg_value; - - mbx = RING_GET_PRODUCER_ITEM_VA(mq->ring, struct oce_mbx); - bzero(mbx, sizeof(struct oce_mbx)); - - fwcmd = (struct mbx_get_common_fw_version *)&mbx->payload; - - hdr = &fwcmd->hdr; - hdr->u0.req.subsystem = MBX_SUBSYSTEM_COMMON; - hdr->u0.req.opcode = OPCODE_COMMON_GET_FW_VERSION; - hdr->u0.req.version = OCE_MBX_VER_V0; - hdr->u0.req.timeout = MBX_TIMEOUT_SEC; - hdr->u0.req.request_length = sizeof(*fwcmd) - sizeof(*hdr); - - mbx->u0.s.embedded = 1; - mbx->payload_length = sizeof(*fwcmd); - oce_dma_sync(&mq->ring->dma, BUS_DMASYNC_PREREAD | - BUS_DMASYNC_PREWRITE); - RING_PUT(mq->ring, 1); - reg_value = (1 << 16) | mq->mq_id; - OCE_WRITE_REG32(sc, db, PD_MQ_DB, reg_value); - - return 0; -} - -/** - * @brief Function to read the mac address associated with an interface - * @param sc software handle to the device - * @param if_id interface id to read the address from - * @param perm set to 1 if reading the factory mac address. - * In this case if_id is ignored - * @param type type of the mac address, whether network or storage - * @param[out] mac [OUTPUT] pointer to a buffer containing the - * mac address when the command succeeds. - * @returns 0 on success, EIO on failure - */ -int -oce_read_mac_addr(struct oce_softc *sc, uint32_t if_id, uint8_t perm, - uint8_t type, struct mac_address_format *mac) -{ - struct mbx_query_common_iface_mac fwcmd; - int err; - - bzero(&fwcmd, sizeof(fwcmd)); - - fwcmd.params.req.type = type; - fwcmd.params.req.permanent = perm; - if (!perm) - fwcmd.params.req.if_id = (uint16_t)if_id; - - err = oce_fw(sc, MBX_SUBSYSTEM_COMMON, OPCODE_COMMON_QUERY_IFACE_MAC, - OCE_MBX_VER_V0, &fwcmd, sizeof(fwcmd)); - if (err == 0) { - mac->size_of_struct = fwcmd.params.rsp.mac.size_of_struct; - bcopy(&fwcmd.params.rsp.mac.mac_addr[0], &mac->mac_addr[0], - mac->size_of_struct); - } - return (err); -} - -/** * @brief Function to query the fw attributes from the hw * @param sc software handle to the device * @returns 0 on success, EIO on failure @@ -711,7 +440,6 @@ oce_get_fw_config(struct oce_softc *sc) if (err) return (err); - sc->config_number = fwcmd.params.rsp.config_number; sc->asic_revision = fwcmd.params.rsp.asic_revision; sc->port_id = fwcmd.params.rsp.port_id; sc->function_mode = fwcmd.params.rsp.function_mode; @@ -729,67 +457,59 @@ oce_get_fw_config(struct oce_softc *sc) } /** - * - * @brief function to create a device interface - * @param sc software handle to the device - * @param cap_flags capability flags - * @param en_flags enable capability flags - * @param vlan_tag optional vlan tag to associate with the if - * @param mac_addr pointer to a buffer containing the mac address - * @param[out] if_id [OUTPUT] pointer to an integer to hold the ID of the - interface created - * @returns 0 on success, EIO on failure + * @brief Firmware will send gracious notifications during + * attach only after sending first mcc commnad. We + * use MCC queue only for getting async and mailbox + * for sending cmds. So to get gracious notifications + * atleast send one dummy command on mcc. */ int -oce_if_create(struct oce_softc *sc, uint32_t cap_flags, uint32_t en_flags, - uint16_t vlan_tag, uint8_t *mac_addr, uint32_t *if_id) +oce_first_mcc_cmd(struct oce_softc *sc) { - struct mbx_create_common_iface fwcmd; - int err = 0; - - bzero(&fwcmd, sizeof(fwcmd)); + struct oce_mbx *mbx; + struct oce_mq *mq = sc->mq; + struct mbx_hdr *hdr; + struct mbx_get_common_fw_version *fwcmd; + uint32_t reg_value; - fwcmd.params.req.version = 0; - fwcmd.params.req.cap_flags = htole32(cap_flags); - fwcmd.params.req.enable_flags = htole32(en_flags); - if (mac_addr != NULL) { - bcopy(mac_addr, &fwcmd.params.req.mac_addr[0], 6); - fwcmd.params.req.vlan_tag.u0.normal.vtag = htole16(vlan_tag); - fwcmd.params.req.mac_invalid = 0; - } else - fwcmd.params.req.mac_invalid = 1; + mbx = RING_GET_PRODUCER_ITEM_VA(mq->ring, struct oce_mbx); + bzero(mbx, sizeof(struct oce_mbx)); - err = oce_fw(sc, MBX_SUBSYSTEM_COMMON, OPCODE_COMMON_CREATE_IFACE, - OCE_MBX_VER_V0, &fwcmd, sizeof(fwcmd)); - if (err) - return (err); + fwcmd = (struct mbx_get_common_fw_version *)&mbx->payload; - *if_id = letoh32(fwcmd.params.rsp.if_id); + hdr = &fwcmd->hdr; + hdr->u0.req.subsystem = MBX_SUBSYSTEM_COMMON; + hdr->u0.req.opcode = OPCODE_COMMON_GET_FW_VERSION; + hdr->u0.req.version = OCE_MBX_VER_V0; + hdr->u0.req.timeout = MBX_TIMEOUT_SEC; + hdr->u0.req.request_length = sizeof(*fwcmd) - sizeof(*hdr); - if (mac_addr != NULL) - sc->pmac_id = letoh32(fwcmd.params.rsp.pmac_id); + mbx->u0.s.embedded = 1; + mbx->payload_length = sizeof(*fwcmd); + oce_dma_sync(&mq->ring->dma, BUS_DMASYNC_PREREAD | + BUS_DMASYNC_PREWRITE); + RING_PUT(mq->ring, 1); + reg_value = (1 << 16) | mq->id; + OCE_WRITE_REG32(sc, db, PD_MQ_DB, reg_value); - return (0); + return 0; } -/** - * @brief Function to delete an interface - * @param sc software handle to the device - * @param if_id ID of the interface to delete - * @returns 0 on success, EIO on failure - */ int -oce_if_del(struct oce_softc *sc, uint32_t if_id) +oce_read_macaddr(struct oce_softc *sc, uint8_t *macaddr) { - struct mbx_destroy_common_iface fwcmd; + struct mbx_query_common_iface_mac fwcmd; int err; bzero(&fwcmd, sizeof(fwcmd)); - fwcmd.params.req.if_id = if_id; + fwcmd.params.req.type = MAC_ADDRESS_TYPE_NETWORK; + fwcmd.params.req.permanent = 1; - err = oce_fw(sc, MBX_SUBSYSTEM_COMMON, OPCODE_COMMON_DESTROY_IFACE, + err = oce_fw(sc, MBX_SUBSYSTEM_COMMON, OPCODE_COMMON_QUERY_IFACE_MAC, OCE_MBX_VER_V0, &fwcmd, sizeof(fwcmd)); + if (err == 0) + bcopy(&fwcmd.params.rsp.mac.mac_addr[0], macaddr, ETH_ADDR_LEN); return (err); } @@ -929,6 +649,31 @@ oce_config_nic_rss(struct oce_softc *sc, uint32_t if_id, uint16_t enable_rss) #endif /* OCE_RSS */ /** + * @brief Function for hardware update multicast filter + * @param sc software handle to the device + * @param multi table of multicast addresses + * @param naddr number of multicast addresses in the table + */ +int +oce_update_mcast(struct oce_softc *sc, + uint8_t multi[][ETH_ADDR_LEN], int naddr) +{ + struct mbx_set_common_iface_multicast fwcmd; + int err; + + bzero(&fwcmd, sizeof(fwcmd)); + + bcopy(&multi[0], &fwcmd.params.req.mac[0], naddr * ETH_ADDR_LEN); + fwcmd.params.req.num_mac = htole16(naddr); + fwcmd.params.req.if_id = sc->if_id; + + err = oce_fw(sc, MBX_SUBSYSTEM_COMMON, + OPCODE_COMMON_SET_IFACE_MULTICAST, OCE_MBX_VER_V0, + &fwcmd, sizeof(fwcmd)); + return (err); +} + +/** * @brief RXF function to enable/disable device promiscuous mode * @param sc software handle to the device * @param enable enable/disable flag @@ -999,7 +744,7 @@ oce_get_link_status(struct oce_softc *sc) } int -oce_mbox_macaddr_add(struct oce_softc *sc, uint8_t *mac_addr, uint32_t if_id, +oce_macaddr_add(struct oce_softc *sc, uint8_t *enaddr, uint32_t if_id, uint32_t *pmac_id) { struct mbx_add_common_iface_mac fwcmd; @@ -1008,7 +753,7 @@ oce_mbox_macaddr_add(struct oce_softc *sc, uint8_t *mac_addr, uint32_t if_id, bzero(&fwcmd, sizeof(fwcmd)); fwcmd.params.req.if_id = htole16(if_id); - bcopy(mac_addr, fwcmd.params.req.mac_address, ETH_ADDR_LEN); + bcopy(enaddr, fwcmd.params.req.mac_address, ETH_ADDR_LEN); err = oce_fw(sc, MBX_SUBSYSTEM_COMMON, OPCODE_COMMON_ADD_IFACE_MAC, OCE_MBX_VER_V0, &fwcmd, sizeof(fwcmd)); @@ -1018,7 +763,7 @@ oce_mbox_macaddr_add(struct oce_softc *sc, uint8_t *mac_addr, uint32_t if_id, } int -oce_mbox_macaddr_del(struct oce_softc *sc, uint32_t if_id, uint32_t pmac_id) +oce_macaddr_del(struct oce_softc *sc, uint32_t if_id, uint32_t pmac_id) { struct mbx_del_common_iface_mac fwcmd; int err; @@ -1034,7 +779,7 @@ oce_mbox_macaddr_del(struct oce_softc *sc, uint32_t if_id, uint32_t pmac_id) } int -oce_mbox_check_native_mode(struct oce_softc *sc) +oce_check_native_mode(struct oce_softc *sc) { struct mbx_common_set_function_cap fwcmd; int err; @@ -1058,15 +803,11 @@ oce_mbox_check_native_mode(struct oce_softc *sc) } int -oce_mbox_create_rq(struct oce_rq *rq) +oce_create_rq(struct oce_softc *sc, struct oce_rq *rq) { struct mbx_create_nic_rq fwcmd; - struct oce_softc *sc = rq->parent; int err, npages; - if (rq->qstate == QCREATED) - return 0; - bzero(&fwcmd, sizeof(fwcmd)); npages = oce_load_ring(sc, rq->ring, &fwcmd.params.req.pages[0], @@ -1082,7 +823,7 @@ oce_mbox_create_rq(struct oce_rq *rq) } else fwcmd.params.req.frag_size = ilog2(rq->cfg.frag_size); fwcmd.params.req.num_pages = npages; - fwcmd.params.req.cq_id = rq->cq->cq_id; + fwcmd.params.req.cq_id = rq->cq->id; fwcmd.params.req.if_id = htole32(sc->if_id); fwcmd.params.req.max_frame_size = htole16(rq->cfg.mtu); fwcmd.params.req.is_rss_queue = htole32(rq->cfg.is_rss_queue); @@ -1093,17 +834,16 @@ oce_mbox_create_rq(struct oce_rq *rq) if (err) return (err); - rq->rq_id = letoh16(fwcmd.params.rsp.rq_id); + rq->id = letoh16(fwcmd.params.rsp.rq_id); rq->rss_cpuid = fwcmd.params.rsp.rss_cpuid; return (0); } int -oce_mbox_create_wq(struct oce_wq *wq) +oce_create_wq(struct oce_softc *sc, struct oce_wq *wq) { struct mbx_create_nic_wq fwcmd; - struct oce_softc *sc = wq->parent; int err, npages; bzero(&fwcmd, sizeof(fwcmd)); @@ -1120,7 +860,7 @@ oce_mbox_create_wq(struct oce_wq *wq) fwcmd.params.req.nic_wq_type = wq->cfg.wq_type; fwcmd.params.req.num_pages = npages; fwcmd.params.req.wq_size = ilog2(wq->cfg.q_len) + 1; - fwcmd.params.req.cq_id = htole16(wq->cq->cq_id); + fwcmd.params.req.cq_id = htole16(wq->cq->id); fwcmd.params.req.ulp_num = 1; err = oce_fw(sc, MBX_SUBSYSTEM_NIC, OPCODE_NIC_CREATE_WQ, @@ -1129,16 +869,15 @@ oce_mbox_create_wq(struct oce_wq *wq) if (err) return (err); - wq->wq_id = letoh16(fwcmd.params.rsp.wq_id); + wq->id = letoh16(fwcmd.params.rsp.wq_id); return (0); } int -oce_mbox_create_mq(struct oce_mq *mq) +oce_create_mq(struct oce_softc *sc, struct oce_mq *mq) { struct mbx_create_common_mq_ex fwcmd; - struct oce_softc *sc = mq->parent; union oce_mq_ext_ctx *ctx; int err, npages; @@ -1153,7 +892,7 @@ oce_mbox_create_mq(struct oce_mq *mq) ctx = &fwcmd.params.req.context; ctx->v0.num_pages = npages; - ctx->v0.cq_id = mq->cq->cq_id; + ctx->v0.cq_id = mq->cq->id; ctx->v0.ring_size = ilog2(mq->cfg.q_len) + 1; ctx->v0.valid = 1; /* Subscribe to Link State and Group 5 Events(bits 1 and 5 set) */ @@ -1164,16 +903,15 @@ oce_mbox_create_mq(struct oce_mq *mq) if (err) return (err); - mq->mq_id = letoh16(fwcmd.params.rsp.mq_id); + mq->id = letoh16(fwcmd.params.rsp.mq_id); return (0); } int -oce_mbox_create_eq(struct oce_eq *eq) +oce_create_eq(struct oce_softc *sc, struct oce_eq *eq) { struct mbx_create_common_eq fwcmd; - struct oce_softc *sc = eq->parent; int err, npages; bzero(&fwcmd, sizeof(fwcmd)); @@ -1187,27 +925,25 @@ oce_mbox_create_eq(struct oce_eq *eq) fwcmd.params.req.ctx.num_pages = htole16(npages); fwcmd.params.req.ctx.valid = 1; - fwcmd.params.req.ctx.size = (eq->eq_cfg.item_size == 4) ? 0 : 1; - fwcmd.params.req.ctx.count = ilog2(eq->eq_cfg.q_len / 256); + fwcmd.params.req.ctx.size = (eq->cfg.item_size == 4) ? 0 : 1; + fwcmd.params.req.ctx.count = ilog2(eq->cfg.q_len / 256); fwcmd.params.req.ctx.armed = 0; - fwcmd.params.req.ctx.delay_mult = htole32(eq->eq_cfg.cur_eqd); + fwcmd.params.req.ctx.delay_mult = htole32(eq->cfg.cur_eqd); err = oce_fw(sc, MBX_SUBSYSTEM_COMMON, OPCODE_COMMON_CREATE_EQ, OCE_MBX_VER_V0, &fwcmd, sizeof(fwcmd)); if (err) return (err); - eq->eq_id = letoh16(fwcmd.params.rsp.eq_id); + eq->id = letoh16(fwcmd.params.rsp.eq_id); return (0); } int -oce_mbox_create_cq(struct oce_cq *cq, uint32_t ncoalesce, - uint32_t is_eventable) +oce_create_cq(struct oce_softc *sc, struct oce_cq *cq) { struct mbx_create_common_cq fwcmd; - struct oce_softc *sc = cq->parent; union oce_cq_ctx *ctx; int err, npages; @@ -1225,28 +961,28 @@ oce_mbox_create_cq(struct oce_cq *cq, uint32_t ncoalesce, if (IS_XE201(sc)) { ctx->v2.num_pages = htole16(npages); ctx->v2.page_size = 1; /* for 4K */ - ctx->v2.eventable = is_eventable; + ctx->v2.eventable = cq->cfg.eventable; ctx->v2.valid = 1; - ctx->v2.count = ilog2(cq->cq_cfg.q_len / 256); - ctx->v2.nodelay = cq->cq_cfg.nodelay; - ctx->v2.coalesce_wm = ncoalesce; + ctx->v2.count = ilog2(cq->cfg.q_len / 256); + ctx->v2.nodelay = cq->cfg.nodelay; + ctx->v2.coalesce_wm = cq->cfg.ncoalesce; ctx->v2.armed = 0; - ctx->v2.eq_id = cq->eq->eq_id; + ctx->v2.eq_id = cq->eq->id; if (ctx->v2.count == 3) { - if (cq->cq_cfg.q_len > (4*1024)-1) + if (cq->cfg.q_len > (4*1024)-1) ctx->v2.cqe_count = (4*1024)-1; else - ctx->v2.cqe_count = cq->cq_cfg.q_len; + ctx->v2.cqe_count = cq->cfg.q_len; } } else { ctx->v0.num_pages = htole16(npages); - ctx->v0.eventable = is_eventable; + ctx->v0.eventable = cq->cfg.eventable; ctx->v0.valid = 1; - ctx->v0.count = ilog2(cq->cq_cfg.q_len / 256); - ctx->v0.nodelay = cq->cq_cfg.nodelay; - ctx->v0.coalesce_wm = ncoalesce; + ctx->v0.count = ilog2(cq->cfg.q_len / 256); + ctx->v0.nodelay = cq->cfg.nodelay; + ctx->v0.coalesce_wm = cq->cfg.ncoalesce; ctx->v0.armed = 0; - ctx->v0.eq_id = cq->eq->eq_id; + ctx->v0.eq_id = cq->eq->id; } err = oce_fw(sc, MBX_SUBSYSTEM_COMMON, OPCODE_COMMON_CREATE_CQ, @@ -1255,38 +991,38 @@ oce_mbox_create_cq(struct oce_cq *cq, uint32_t ncoalesce, if (err) return (err); - cq->cq_id = letoh16(fwcmd.params.rsp.cq_id); + cq->id = letoh16(fwcmd.params.rsp.cq_id); return (0); } int -oce_mbox_destroy_q(struct oce_softc *sc, enum qtype qtype, uint32_t qid) +oce_destroy_queue(struct oce_softc *sc, enum qtype qtype, uint32_t qid) { struct mbx_destroy_common_mq fwcmd; int opcode, subsys, err; switch (qtype) { - case QTYPE_EQ: - opcode = OPCODE_COMMON_DESTROY_EQ; - subsys = MBX_SUBSYSTEM_COMMON; - break; case QTYPE_CQ: opcode = OPCODE_COMMON_DESTROY_CQ; subsys = MBX_SUBSYSTEM_COMMON; break; + case QTYPE_EQ: + opcode = OPCODE_COMMON_DESTROY_EQ; + subsys = MBX_SUBSYSTEM_COMMON; + break; case QTYPE_MQ: opcode = OPCODE_COMMON_DESTROY_MQ; subsys = MBX_SUBSYSTEM_COMMON; break; - case QTYPE_WQ: - opcode = OPCODE_NIC_DELETE_WQ; - subsys = MBX_SUBSYSTEM_NIC; - break; case QTYPE_RQ: opcode = OPCODE_NIC_DELETE_RQ; subsys = MBX_SUBSYSTEM_NIC; break; + case QTYPE_WQ: + opcode = OPCODE_NIC_DELETE_WQ; + subsys = MBX_SUBSYSTEM_NIC; + break; default: return (EINVAL); } diff --git a/sys/dev/pci/ocevar.h b/sys/dev/pci/ocevar.h index cd211bcd282..c740d7492e3 100644 --- a/sys/dev/pci/ocevar.h +++ b/sys/dev/pci/ocevar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ocevar.h,v 1.13 2012/10/12 15:16:45 mikeb Exp $ */ +/* $OpenBSD: ocevar.h,v 1.14 2012/10/12 17:41:40 mikeb Exp $ */ /*- * Copyright (C) 2012 Emulex @@ -185,29 +185,29 @@ enum { struct oce_packet_desc { - struct mbuf *mbuf; - bus_dmamap_t map; - int nsegs; - uint32_t wqe_idx; + struct mbuf * mbuf; + bus_dmamap_t map; + int nsegs; + uint32_t wqe_idx; }; struct oce_dma_mem { - bus_dma_tag_t tag; - bus_dmamap_t map; - bus_dma_segment_t segs; - int nsegs; - bus_size_t size; - caddr_t vaddr; - bus_addr_t paddr; + bus_dma_tag_t tag; + bus_dmamap_t map; + bus_dma_segment_t segs; + int nsegs; + bus_size_t size; + caddr_t vaddr; + bus_addr_t paddr; }; struct oce_ring { - uint16_t cidx; /* Get ptr */ - uint16_t pidx; /* Put Ptr */ - size_t item_size; - size_t num_items; - uint32_t num_used; - struct oce_dma_mem dma; + uint16_t cidx; /* Get ptr */ + uint16_t pidx; /* Put Ptr */ + size_t item_size; + size_t num_items; + uint32_t num_used; + struct oce_dma_mem dma; }; /* Stats */ @@ -351,7 +351,6 @@ struct oce_xe_stats { uint64_t rx_pkts_8192_to_9216_bytes; }; -typedef int boolean_t; #define TRUE 1 #define FALSE 0 @@ -367,7 +366,13 @@ typedef int boolean_t; #define OCE_WQ_PACKET_ARRAY_SIZE (OCE_TX_RING_SIZE/2) #define OCE_RQ_PACKET_ARRAY_SIZE (OCE_RX_RING_SIZE) -struct oce_dev; +struct oce_softc; + +enum cq_len { + CQ_LEN_256 = 256, + CQ_LEN_512 = 512, + CQ_LEN_1024 = 1024 +}; enum eq_len { EQ_LEN_256 = 256, @@ -391,180 +396,157 @@ enum qtype { QTYPE_RSS }; -typedef enum qstate_e { +enum qstate { QDELETED = 0x0, QCREATED = 0x1 -} qstate_t; +}; + +struct oce_queue { + struct oce_softc * sc; + struct oce_ring * ring; + uint32_t id; + enum qtype type; + enum qstate state; +}; struct eq_config { - enum eq_len q_len; - enum eqe_size item_size; - uint32_t q_vector_num; - uint8_t min_eqd; - uint8_t max_eqd; - uint8_t cur_eqd; + enum eq_len q_len; + enum eqe_size item_size; + int q_vector_num; + int min_eqd; + int max_eqd; + int cur_eqd; }; struct oce_eq { - uint32_t eq_id; - void *parent; - void *cb_context; - struct oce_ring *ring; - qstate_t qstate; - struct oce_cq *cq[OCE_MAX_CQ_EQ]; - int cq_valid; - struct eq_config eq_cfg; - int vector; -}; + struct oce_softc * sc; + struct oce_ring * ring; + uint32_t id; + enum qtype type; + enum qstate state; -enum cq_len { - CQ_LEN_256 = 256, - CQ_LEN_512 = 512, - CQ_LEN_1024 = 1024 + struct oce_cq * cq[OCE_MAX_CQ_EQ]; + int cq_valid; + + struct eq_config cfg; }; struct cq_config { - enum cq_len q_len; - uint32_t item_size; - boolean_t is_eventable; - boolean_t sol_eventable; - boolean_t nodelay; - uint16_t dma_coalescing; + enum cq_len q_len; + int item_size; + int nodelay; + int dma_coalescing; + int ncoalesce; + int eventable; }; struct oce_cq { - uint32_t cq_id; - void *parent; - struct oce_eq *eq; - void (*cq_handler)(void *); - void *cb_arg; - struct oce_ring *ring; - qstate_t qstate; - struct cq_config cq_cfg; + struct oce_softc * sc; + struct oce_ring * ring; + uint32_t id; + enum qtype type; + enum qstate state; + + struct oce_eq * eq; + + struct cq_config cfg; + + void (*cq_handler)(void *); + void * cb_arg; }; struct mq_config { - uint32_t eqd; - uint8_t q_len; + int eqd; + int q_len; }; struct oce_mq { - void *parent; - struct oce_ring *ring; - uint32_t mq_id; - struct oce_cq *cq; - struct oce_cq *async_cq; - uint32_t mq_free; - qstate_t qstate; - struct mq_config cfg; -}; + struct oce_softc * sc; + struct oce_ring * ring; + uint32_t id; + enum qtype type; + enum qstate state; -struct oce_mbx_ctx { - struct oce_mbx *mbx; - void (*cb) (void *ctx); - void *cb_ctx; -}; + struct oce_cq * cq; -struct wq_config { - uint8_t wq_type; - uint16_t buf_size; - uint32_t q_len; - uint16_t pd_id; - uint16_t pci_fn_num; - uint32_t eqd; /* interrupt delay */ - uint32_t nbufs; - uint32_t nhdl; + struct mq_config cfg; }; -struct oce_tx_queue_stats { - uint64_t tx_pkts; - uint64_t tx_bytes; - uint32_t tx_reqs; - uint32_t tx_stops; /* number of times TX Q was stopped */ - uint32_t tx_wrbs; - uint32_t tx_compl; - uint32_t tx_rate; - uint32_t ipv6_ext_hdr_tx_drop; +struct wq_config { + int wq_type; + int buf_size; + int q_len; + int eqd; /* interrupt delay */ + int nbufs; }; struct oce_wq { - void *parent; - struct oce_ring *ring; - struct oce_cq *cq; - bus_dma_tag_t tag; - struct oce_packet_desc pckts[OCE_WQ_PACKET_ARRAY_SIZE]; - uint32_t packets_in; - uint32_t packets_out; - uint32_t wqm_used; - boolean_t resched; - uint32_t wq_free; - uint32_t tx_deferd; - uint32_t pkt_drops; - qstate_t qstate; - uint16_t wq_id; - struct wq_config cfg; - int queue_index; -}; + struct oce_softc * sc; + struct oce_ring * ring; + uint32_t id; + enum qtype type; + enum qstate state; -struct rq_config { - uint32_t q_len; - uint32_t frag_size; - uint32_t mtu; - uint32_t if_id; - uint32_t is_rss_queue; - uint32_t eqd; - uint32_t nbufs; + bus_dma_tag_t tag; + + struct oce_cq *cq; + struct oce_packet_desc pckts[OCE_WQ_PACKET_ARRAY_SIZE]; + + uint32_t packets_in; + uint32_t packets_out; + + struct wq_config cfg; + + int queue_index; }; -struct oce_rx_queue_stats { - uint32_t rx_post_fail; - uint32_t rx_ucast_pkts; - uint32_t rx_compl; - uint64_t rx_bytes; - uint64_t rx_bytes_prev; - uint64_t rx_pkts; - uint32_t rx_rate; - uint32_t rx_mcast_pkts; - uint32_t rxcp_err; - uint32_t rx_frags; - uint32_t prev_rx_frags; - uint32_t rx_fps; +struct rq_config { + int q_len; + int frag_size; + int mtu; + int if_id; + int is_rss_queue; + int eqd; + int nbufs; }; struct oce_rq { - struct rq_config cfg; - uint32_t rq_id; - int queue_index; - uint32_t rss_cpuid; - void *parent; - struct oce_ring *ring; - struct oce_cq *cq; - bus_dma_tag_t tag; - struct oce_packet_desc pckts[OCE_RQ_PACKET_ARRAY_SIZE]; - uint32_t packets_in; - uint32_t packets_out; - uint32_t pending; -#ifdef notdef - struct mbuf *head; - struct mbuf *tail; - int fragsleft; -#endif - qstate_t qstate; + struct oce_softc * sc; + struct oce_ring * ring; + uint32_t id; + enum qtype type; + enum qstate state; + + bus_dma_tag_t tag; + + struct oce_cq * cq; + struct oce_packet_desc pckts[OCE_RQ_PACKET_ARRAY_SIZE]; + + uint32_t packets_in; + uint32_t packets_out; + uint32_t pending; + + uint32_t rss_cpuid; + #ifdef OCE_LRO - struct lro_ctrl lro; - int lro_pkts_queued; + struct lro_ctrl lro; + int lro_pkts_queued; #endif + + struct rq_config cfg; + + int queue_index; }; struct link_status { - uint8_t physical_port; - uint8_t mac_duplex; - uint8_t mac_speed; - uint8_t mac_fault; - uint8_t mgmt_mac_duplex; - uint8_t mgmt_mac_speed; - uint16_t qos_link_speed; - uint32_t logical_link_status; + uint8_t physical_port; + uint8_t mac_duplex; + uint8_t mac_speed; + uint8_t mac_fault; + uint8_t mgmt_mac_duplex; + uint8_t mgmt_mac_speed; + uint16_t qos_link_speed; + uint32_t logical_link_status; } __packed; #define OCE_FLAGS_PCIX 0x00000001 @@ -581,71 +563,71 @@ struct link_status { #define OCE_FLAGS_BE2 0x00000800 struct oce_softc { - struct device dev; + struct device dev; + + uint32_t flags; - uint32_t flags; + struct pci_attach_args pa; - struct pci_attach_args pa; + bus_space_tag_t cfg_iot; + bus_space_handle_t cfg_ioh; + bus_size_t cfg_size; - bus_space_tag_t cfg_btag; - bus_space_handle_t cfg_bhandle; - bus_size_t cfg_size; + bus_space_tag_t csr_iot; + bus_space_handle_t csr_ioh; + bus_size_t csr_size; - bus_space_tag_t csr_btag; - bus_space_handle_t csr_bhandle; - bus_size_t csr_size; + bus_space_tag_t db_iot; + bus_space_handle_t db_ioh; + bus_size_t db_size; - bus_space_tag_t db_btag; - bus_space_handle_t db_bhandle; - bus_size_t db_size; + struct arpcom arpcom; + struct ifmedia media; + int link_active; + uint8_t link_status; + uint8_t link_speed; + uint8_t duplex; + uint32_t qos_link_speed; - struct arpcom arpcom; - struct ifmedia media; - int link_active; - uint8_t link_status; - uint8_t link_speed; - uint8_t duplex; - uint32_t qos_link_speed; + char fw_version[32]; - char fw_version[32]; - struct mac_address_format macaddr; + struct oce_dma_mem bsmbx; - struct oce_dma_mem bsmbx; + uint32_t asic_revision; + uint32_t port_id; + uint32_t function_mode; + uint32_t function_caps; + uint32_t max_tx_rings; + uint32_t max_rx_rings; - uint32_t config_number; - uint32_t asic_revision; - uint32_t port_id; - uint32_t function_mode; - uint32_t function_caps; - uint32_t max_tx_rings; - uint32_t max_rx_rings; + struct oce_wq *wq[OCE_MAX_WQ]; /* TX work queues */ + struct oce_rq *rq[OCE_MAX_RQ]; /* RX work queues */ + struct oce_cq *cq[OCE_MAX_CQ]; /* Completion queues */ + struct oce_eq *eq[OCE_MAX_EQ]; /* Event queues */ + struct oce_mq *mq; /* Mailbox queue */ - struct oce_wq *wq[OCE_MAX_WQ]; /* TX work queues */ - struct oce_rq *rq[OCE_MAX_RQ]; /* RX work queues */ - struct oce_cq *cq[OCE_MAX_CQ]; /* Completion queues */ - struct oce_eq *eq[OCE_MAX_EQ]; /* Event queues */ - struct oce_mq *mq; /* Mailbox queue */ + ushort neqs; + ushort ncqs; + ushort nrqs; + ushort nwqs; + ushort intr_count; + ushort tx_ring_size; + ushort rx_ring_size; + ushort rq_frag_size; + ushort rss_enable; - ushort neqs; - ushort ncqs; - ushort nrqs; - ushort nwqs; - ushort intr_count; - ushort tx_ring_size; - ushort rx_ring_size; - ushort rq_frag_size; - ushort rss_enable; + uint32_t if_id; /* interface ID */ + uint32_t nifs; /* number of adapter interfaces, 0 or 1 */ + uint32_t pmac_id; /* PMAC id */ - uint32_t if_id; /* interface ID */ - uint32_t nifs; /* number of adapter interfaces, 0 or 1 */ - uint32_t pmac_id; /* PMAC id */ + char macaddr[ETH_ADDR_LEN]; - uint32_t if_cap_flags; + uint32_t if_cap_flags; - uint32_t flow_control; + uint32_t flow_control; - char be3_native; - uint32_t pvid; + int be3_native; + uint32_t pvid; union { struct mbx_get_pport_stats xe; @@ -653,11 +635,11 @@ struct oce_softc { struct mbx_get_nic_stats be3; } stats; - uint64_t rx_errors; - uint64_t tx_errors; + uint64_t rx_errors; + uint64_t tx_errors; - struct timeout timer; - struct timeout rxrefill; + struct timeout timer; + struct timeout rxrefill; }; /************************************************** @@ -667,36 +649,30 @@ struct oce_softc { **************************************************/ #if 1 #define OCE_READ_REG32(sc, space, o) \ - ((IS_BE(sc)) ? (bus_space_read_4((sc)->space##_btag, \ - (sc)->space##_bhandle,o)) \ - : (bus_space_read_4((sc)->cfg_btag, \ - (sc)->cfg_bhandle,o))) + ((IS_BE(sc)) ? (bus_space_read_4((sc)->space##_iot, \ + (sc)->space##_ioh,o)) \ + : (bus_space_read_4((sc)->cfg_iot, (sc)->cfg_ioh,o))) #define OCE_READ_REG16(sc, space, o) \ - ((IS_BE(sc)) ? (bus_space_read_2((sc)->space##_btag, \ - (sc)->space##_bhandle,o)) \ - : (bus_space_read_2((sc)->cfg_btag, \ - (sc)->cfg_bhandle,o))) + ((IS_BE(sc)) ? (bus_space_read_2((sc)->space##_iot, \ + (sc)->space##_ioh,o)) \ + : (bus_space_read_2((sc)->cfg_iot, (sc)->cfg_ioh,o))) #define OCE_READ_REG8(sc, space, o) \ - ((IS_BE(sc)) ? (bus_space_read_1((sc)->space##_btag, \ - (sc)->space##_bhandle,o)) \ - : (bus_space_read_1((sc)->cfg_btag, \ - (sc)->cfg_bhandle,o))) + ((IS_BE(sc)) ? (bus_space_read_1((sc)->space##_iot, \ + (sc)->space##_ioh,o)) \ + : (bus_space_read_1((sc)->cfg_iot, (sc)->cfg_ioh,o))) #define OCE_WRITE_REG32(sc, space, o, v) \ - ((IS_BE(sc)) ? (bus_space_write_4((sc)->space##_btag, \ - (sc)->space##_bhandle,o,v)) \ - : (bus_space_write_4((sc)->cfg_btag, \ - (sc)->cfg_bhandle,o,v))) + ((IS_BE(sc)) ? (bus_space_write_4((sc)->space##_iot, \ + (sc)->space##_ioh,o,v)) \ + : (bus_space_write_4((sc)->cfg_iot, (sc)->cfg_ioh,o,v))) #define OCE_WRITE_REG16(sc, space, o, v) \ - ((IS_BE(sc)) ? (bus_space_write_2((sc)->space##_btag, \ - (sc)->space##_bhandle,o,v)) \ - : (bus_space_write_2((sc)->cfg_btag, \ - (sc)->cfg_bhandle,o,v))) + ((IS_BE(sc)) ? (bus_space_write_2((sc)->space##_iot, \ + (sc)->space##_ioh,o,v)) \ + : (bus_space_write_2((sc)->cfg_iot, (sc)->cfg_ioh,o,v))) #define OCE_WRITE_REG8(sc, space, o, v) \ - ((IS_BE(sc)) ? (bus_space_write_1((sc)->space##_btag, \ - (sc)->space##_bhandle,o,v)) \ - : (bus_space_write_1((sc)->cfg_btag, \ - (sc)->cfg_bhandle,o,v))) + ((IS_BE(sc)) ? (bus_space_write_1((sc)->space##_iot, \ + (sc)->space##_ioh,o,v)) \ + : (bus_space_write_1((sc)->cfg_iot, (sc)->cfg_ioh,o,v))) #else static __inline u_int32_t oce_bus_read_4(bus_space_tag_t tag, bus_space_handle_t handle, bus_size_t reg) @@ -744,36 +720,30 @@ oce_bus_write_1(bus_space_tag_t tag, bus_space_handle_t handle, bus_size_t reg, } #define OCE_READ_REG32(sc, space, o) \ - ((IS_BE(sc)) ? (oce_bus_read_4((sc)->space##_btag, \ - (sc)->space##_bhandle,o)) \ - : (oce_bus_read_4((sc)->cfg_btag, \ - (sc)->cfg_bhandle,o))) + ((IS_BE(sc)) ? (oce_bus_read_4((sc)->space##_iot, \ + (sc)->space##_ioh,o)) \ + : (oce_bus_read_4((sc)->cfg_iot, (sc)->cfg_ioh,o))) #define OCE_READ_REG16(sc, space, o) \ - ((IS_BE(sc)) ? (oce_bus_read_2((sc)->space##_btag, \ - (sc)->space##_bhandle,o)) \ - : (oce_bus_read_2((sc)->cfg_btag, \ - (sc)->cfg_bhandle,o))) + ((IS_BE(sc)) ? (oce_bus_read_2((sc)->space##_iot, \ + (sc)->space##_ioh,o)) \ + : (oce_bus_read_2((sc)->cfg_iot, (sc)->cfg_ioh,o))) #define OCE_READ_REG8(sc, space, o) \ - ((IS_BE(sc)) ? (oce_bus_read_1((sc)->space##_btag, \ - (sc)->space##_bhandle,o)) \ - : (oce_bus_read_1((sc)->cfg_btag, \ - (sc)->cfg_bhandle,o))) + ((IS_BE(sc)) ? (oce_bus_read_1((sc)->space##_iot, \ + (sc)->space##_ioh,o)) \ + : (oce_bus_read_1((sc)->cfg_iot, (sc)->cfg_ioh,o))) #define OCE_WRITE_REG32(sc, space, o, v) \ - ((IS_BE(sc)) ? (oce_bus_write_4((sc)->space##_btag, \ - (sc)->space##_bhandle,o,v)) \ - : (oce_bus_write_4((sc)->cfg_btag, \ - (sc)->cfg_bhandle,o,v))) + ((IS_BE(sc)) ? (oce_bus_write_4((sc)->space##_iot, \ + (sc)->space##_ioh,o,v)) \ + : (oce_bus_write_4((sc)->cfg_iot, (sc)->cfg_ioh,o,v))) #define OCE_WRITE_REG16(sc, space, o, v) \ - ((IS_BE(sc)) ? (oce_bus_write_2((sc)->space##_btag, \ - (sc)->space##_bhandle,o,v)) \ - : (oce_bus_write_2((sc)->cfg_btag, \ - (sc)->cfg_bhandle,o,v))) + ((IS_BE(sc)) ? (oce_bus_write_2((sc)->space##_iot, \ + (sc)->space##_ioh,o,v)) \ + : (oce_bus_write_2((sc)->cfg_iot, (sc)->cfg_ioh,o,v))) #define OCE_WRITE_REG8(sc, space, o, v) \ - ((IS_BE(sc)) ? (oce_bus_write_1((sc)->space##_btag, \ - (sc)->space##_bhandle,o,v)) \ - : (oce_bus_write_1((sc)->cfg_btag, \ - (sc)->cfg_bhandle,o,v))) + ((IS_BE(sc)) ? (oce_bus_write_1((sc)->space##_iot, \ + (sc)->space##_ioh,o,v)) \ + : (oce_bus_write_1((sc)->cfg_iot, (sc)->cfg_ioh,o,v))) #endif /*********************************************************** @@ -793,19 +763,20 @@ int oce_load_ring(struct oce_softc *sc, struct oce_ring *ring, struct phys_addr *pa_list, int max_segs); /************************************************************ - * Some functions + * Firmware functions ************************************************************/ -int oce_hw_pci_alloc(struct oce_softc *sc); -int oce_hw_init(struct oce_softc *sc); -void oce_hw_intr_enable(struct oce_softc *sc); -void oce_hw_intr_disable(struct oce_softc *sc); -int oce_create_iface(struct oce_softc *sc); +int oce_init_fw(struct oce_softc *sc); +int oce_get_fw_version(struct oce_softc *sc); +int oce_get_fw_config(struct oce_softc *sc); +int oce_check_native_mode(struct oce_softc *sc); +int oce_create_iface(struct oce_softc *sc, uint8_t *); int oce_update_mcast(struct oce_softc *sc, uint8_t multi[][ETH_ADDR_LEN], int naddr); /************************************************************ * Mailbox functions ************************************************************/ +int oce_mbox_init(struct oce_softc *sc); int oce_first_mcc_cmd(struct oce_softc *sc); int oce_get_link_status(struct oce_softc *sc); @@ -813,20 +784,20 @@ int oce_set_promisc(struct oce_softc *sc, uint32_t enable); int oce_config_nic_rss(struct oce_softc *sc, uint32_t if_id, uint16_t enable_rss); -int oce_mbox_macaddr_del(struct oce_softc *sc, uint32_t if_id, +int oce_macaddr_del(struct oce_softc *sc, uint32_t if_id, uint32_t pmac_id); -int oce_mbox_macaddr_add(struct oce_softc *sc, uint8_t *mac_addr, +int oce_macaddr_add(struct oce_softc *sc, uint8_t *macaddr, uint32_t if_id, uint32_t *pmac_id); -int oce_read_mac_addr(struct oce_softc *sc, uint32_t if_id, uint8_t perm, - uint8_t type, struct mac_address_format *mac); - -int oce_mbox_create_rq(struct oce_rq *rq); -int oce_mbox_create_wq(struct oce_wq *wq); -int oce_mbox_create_mq(struct oce_mq *mq); -int oce_mbox_create_eq(struct oce_eq *eq); -int oce_mbox_create_cq(struct oce_cq *cq, uint32_t ncoalesce, - uint32_t is_eventable); -int oce_mbox_destroy_q(struct oce_softc *sc, enum qtype qtype, uint32_t qid); +int oce_read_macaddr(struct oce_softc *sc, uint8_t *macaddr); + +int oce_create_qeueu(struct oce_softc *sc, struct oce_queue *q, + enum qtype qtype); +int oce_create_rq(struct oce_softc *sc, struct oce_rq *rq); +int oce_create_wq(struct oce_softc *sc, struct oce_wq *wq); +int oce_create_mq(struct oce_softc *sc, struct oce_mq *mq); +int oce_create_eq(struct oce_softc *sc, struct oce_eq *eq); +int oce_create_cq(struct oce_softc *sc, struct oce_cq *cq); +int oce_destroy_queue(struct oce_softc *sc, enum qtype qtype, uint32_t qid); /************************************************************ * Statistics functions |