diff options
-rw-r--r-- | sys/dev/oce/oce_hw.c | 8 | ||||
-rw-r--r-- | sys/dev/oce/oce_hw.h | 152 | ||||
-rw-r--r-- | sys/dev/oce/oce_if.c | 240 | ||||
-rw-r--r-- | sys/dev/oce/oce_if.h | 47 | ||||
-rw-r--r-- | sys/dev/oce/oce_mbox.c | 429 | ||||
-rw-r--r-- | sys/dev/oce/oce_queue.c | 61 | ||||
-rw-r--r-- | sys/dev/oce/oce_sysctl.c | 52 | ||||
-rw-r--r-- | sys/dev/oce/oce_util.c | 5 |
8 files changed, 810 insertions, 184 deletions
diff --git a/sys/dev/oce/oce_hw.c b/sys/dev/oce/oce_hw.c index e68ba7a..274c4d1 100644 --- a/sys/dev/oce/oce_hw.c +++ b/sys/dev/oce/oce_hw.c @@ -405,11 +405,6 @@ oce_create_nw_interface(POCE_SOFTC sc) 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) @@ -477,12 +472,9 @@ oce_hw_start(POCE_SOFTC sc) return 1; if (link.logical_link_status == NTWK_LOGICAL_LINK_UP) { - sc->ifp->if_drv_flags |= IFF_DRV_RUNNING; sc->link_status = NTWK_LOGICAL_LINK_UP; if_link_state_change(sc->ifp, LINK_STATE_UP); } else { - sc->ifp->if_drv_flags &= - ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); sc->link_status = NTWK_LOGICAL_LINK_DOWN; if_link_state_change(sc->ifp, LINK_STATE_DOWN); } diff --git a/sys/dev/oce/oce_hw.h b/sys/dev/oce/oce_hw.h index 0e79218..aac0a8a 100644 --- a/sys/dev/oce/oce_hw.h +++ b/sys/dev/oce/oce_hw.h @@ -38,6 +38,8 @@ /* $FreeBSD$ */ +/* $FreeBSD$ */ + #include <sys/types.h> #undef _BIG_ENDIAN /* TODO */ @@ -155,7 +157,10 @@ #define ASYNC_EVENT_LINK_UP 0x1 #define ASYNC_EVENT_LINK_DOWN 0x0 #define ASYNC_EVENT_GRP5 0x5 +#define ASYNC_EVENT_CODE_DEBUG 0x6 #define ASYNC_EVENT_PVID_STATE 0x3 +#define ASYNC_EVENT_DEBUG_QNQ 0x1 +#define ASYNC_EVENT_CODE_SLIPORT 0x11 #define VLAN_VID_MASK 0x0FFF /* port link_status */ @@ -707,6 +712,17 @@ struct oce_async_event_grp5_pvid_state { uint32_t code; }; +/* async event indicating outer VLAN tag in QnQ */ +struct oce_async_event_qnq { + uint8_t valid; /* Indicates if outer VLAN is valid */ + uint8_t rsvd0; + uint16_t vlan_tag; + uint32_t event_tag; + uint8_t rsvd1[4]; + uint32_t code; +} ; + + typedef union oce_mq_ext_ctx_u { uint32_t dw[6]; struct { @@ -750,6 +766,44 @@ typedef union oce_mq_ext_ctx_u { /* dw5 */ uint32_t dw8rsvd1; } v0; + struct { + #ifdef _BIG_ENDIAN + /* dw0 */ + uint32_t cq_id:16; + uint32_t num_pages:16; + /* dw1 */ + uint32_t async_evt_bitmap; + /* dw2 */ + uint32_t dw5rsvd2:12; + uint32_t ring_size:4; + uint32_t async_cq_id:16; + /* dw3 */ + uint32_t valid:1; + uint32_t dw6rsvd1:31; + /* dw4 */ + uint32_t dw7rsvd1:31; + uint32_t async_cq_valid:1; + #else + /* dw0 */ + uint32_t num_pages:16; + uint32_t cq_id:16; + /* dw1 */ + uint32_t async_evt_bitmap; + /* dw2 */ + uint32_t async_cq_id:16; + uint32_t ring_size:4; + uint32_t dw5rsvd2:12; + /* dw3 */ + uint32_t dw6rsvd1:31; + uint32_t valid:1; + /* dw4 */ + uint32_t async_cq_valid:1; + uint32_t dw7rsvd1:31; + #endif + /* dw5 */ + uint32_t dw8rsvd1; + } v1; + } oce_mq_ext_ctx_t; @@ -826,6 +880,7 @@ enum COMMON_SUBSYSTEM_OPCODES { OPCODE_COMMON_SET_BEACON_CONFIG = 69, OPCODE_COMMON_GET_BEACON_CONFIG = 70, OPCODE_COMMON_GET_PHYSICAL_LINK_CONFIG = 71, + OPCODE_COMMON_READ_TRANSRECEIVER_DATA = 73, OPCODE_COMMON_GET_OEM_ATTRIBUTES = 76, OPCODE_COMMON_GET_PORT_NAME = 77, OPCODE_COMMON_GET_CONFIG_SIGNATURE = 78, @@ -1724,6 +1779,12 @@ struct mbx_set_common_iface_rx_filter { } params; }; +struct be_set_eqd { + uint32_t eq_id; + uint32_t phase; + uint32_t dm; +}; + /* [41] OPCODE_COMMON_MODIFY_EQ_DELAY */ struct mbx_modify_common_eq_delay { struct mbx_hdr hdr; @@ -1743,6 +1804,76 @@ struct mbx_modify_common_eq_delay { } params; }; +/* [32] OPCODE_COMMON_GET_CNTL_ATTRIBUTES */ + +struct mgmt_hba_attr { + int8_t flashrom_ver_str[32]; + int8_t manufac_name[32]; + uint32_t supp_modes; + int8_t seeprom_ver_lo; + int8_t seeprom_ver_hi; + int8_t rsvd0[2]; + uint32_t ioctl_data_struct_ver; + uint32_t ep_fw_data_struct_ver; + uint8_t ncsi_ver_str[12]; + uint32_t def_ext_to; + int8_t cntl_mod_num[32]; + int8_t cntl_desc[64]; + int8_t cntl_ser_num[32]; + int8_t ip_ver_str[32]; + int8_t fw_ver_str[32]; + int8_t bios_ver_str[32]; + int8_t redboot_ver_str[32]; + int8_t drv_ver_str[32]; + int8_t fw_on_flash_ver_str[32]; + uint32_t funcs_supp; + uint16_t max_cdblen; + uint8_t asic_rev; + uint8_t gen_guid[16]; + uint8_t hba_port_count; + uint16_t default_link_down_timeout; + uint8_t iscsi_ver_min_max; + uint8_t multifunc_dev; + uint8_t cache_valid; + uint8_t hba_status; + uint8_t max_domains_supp; + uint8_t phy_port; + uint32_t fw_post_status; + uint32_t hba_mtu[8]; + uint8_t iSCSI_feat; + uint8_t asic_gen; + uint8_t future_u8[2]; + uint32_t future_u32[3]; +}; + +struct mgmt_cntl_attr { + struct mgmt_hba_attr hba_attr; + uint16_t pci_vendor_id; + uint16_t pci_device_id; + uint16_t pci_sub_vendor_id; + uint16_t pci_sub_system_id; + uint8_t pci_bus_num; + uint8_t pci_dev_num; + uint8_t pci_func_num; + uint8_t interface_type; + uint64_t unique_id; + uint8_t netfilters; + uint8_t rsvd0[3]; + uint32_t future_u32[4]; +}; + +struct mbx_common_get_cntl_attr { + struct mbx_hdr hdr; + union { + struct { + uint32_t rsvd0; + } req; + struct { + struct mgmt_cntl_attr cntl_attr_info; + } rsp; + } params; +}; + /* [59] OPCODE_ADD_COMMON_IFACE_MAC */ struct mbx_add_common_iface_mac { struct mbx_hdr hdr; @@ -1785,6 +1916,23 @@ struct ioctl_common_function_reset { struct mbx_hdr hdr; }; +/* [73] OPCODE_COMMON_READ_TRANSRECEIVER_DATA */ +struct mbx_read_common_transrecv_data { + struct mbx_hdr hdr; + union { + struct { + uint32_t page_num; + uint32_t port; + } req; + struct { + uint32_t page_num; + uint32_t port; + uint32_t page_data[32]; + } rsp; + } params; + +}; + /* [80] OPCODE_COMMON_FUNCTION_LINK_CONFIG */ struct mbx_common_func_link_cfg { struct mbx_hdr hdr; @@ -2110,7 +2258,9 @@ enum RSS_ENABLE_FLAGS { RSS_ENABLE_IPV4 = 0x1, /* (IPV4 HASH enabled ) */ RSS_ENABLE_TCP_IPV4 = 0x2, /* (TCP IPV4 Hash enabled) */ RSS_ENABLE_IPV6 = 0x4, /* (IPV6 HASH enabled) */ - RSS_ENABLE_TCP_IPV6 = 0x8 /* (TCP IPV6 HASH */ + RSS_ENABLE_TCP_IPV6 = 0x8, /* (TCP IPV6 HASH */ + RSS_ENABLE_UDP_IPV4 = 0x10, /* UDP IPV4 HASH */ + RSS_ENABLE_UDP_IPV6 = 0x20 /* UDP IPV6 HASH */ }; #define RSS_ENABLE (RSS_ENABLE_IPV4 | RSS_ENABLE_TCP_IPV4) #define RSS_DISABLE RSS_ENABLE_NONE diff --git a/sys/dev/oce/oce_if.c b/sys/dev/oce/oce_if.c index 426acd9..48cdb16 100644 --- a/sys/dev/oce/oce_if.c +++ b/sys/dev/oce/oce_if.c @@ -36,6 +36,7 @@ * Costa Mesa, CA 92626 */ + /* $FreeBSD$ */ #include "opt_inet6.h" @@ -94,7 +95,8 @@ static void setup_max_queues_want(POCE_SOFTC sc); static void update_queues_got(POCE_SOFTC sc); static void process_link_state(POCE_SOFTC sc, struct oce_async_cqe_link_state *acqe); - +static int oce_tx_asic_stall_verify(POCE_SOFTC sc, struct mbuf *m); +static struct mbuf *oce_insert_vlan_tag(POCE_SOFTC sc, struct mbuf *m, boolean_t *complete); /* IP specific */ #if defined(INET6) || defined(INET) @@ -266,8 +268,6 @@ oce_attach(device_t dev) rc = callout_reset(&sc->timer, 2 * hz, oce_local_timer, sc); if (rc) goto stats_free; -#ifdef DEV_NETMAP -#endif /* DEV_NETMAP */ return 0; @@ -485,7 +485,7 @@ oce_multiq_start(struct ifnet *ifp, struct mbuf *m) struct oce_wq *wq = NULL; int queue_index = 0; int status = 0; - + if ((m->m_flags & M_FLOWID) != 0) queue_index = m->m_pkthdr.flowid % sc->nwqs; @@ -568,6 +568,7 @@ oce_intr(void *arg, int pending) eq_arm: oce_arm_eq(sc, eq->eq_id, 0, TRUE, FALSE); + return; } @@ -633,6 +634,8 @@ oce_fast_isr(void *arg) taskqueue_enqueue_fast(ii->tq, &ii->task); + ii->eq->intr++; + return FILTER_HANDLED; } @@ -780,6 +783,7 @@ oce_tx(POCE_SOFTC sc, struct mbuf **mpp, int wq_index) struct oce_nic_frag_wqe *nicfrag; int num_wqes; uint32_t reg_value; + boolean_t complete = TRUE; m = *mpp; if (!m) @@ -790,6 +794,15 @@ oce_tx(POCE_SOFTC sc, struct mbuf **mpp, int wq_index) goto free_ret; } + if(oce_tx_asic_stall_verify(sc, m)) { + m = oce_insert_vlan_tag(sc, m, &complete); + if(!m) { + device_printf(sc->dev, "Insertion unsuccessful\n"); + return 0; + } + + } + if (m->m_pkthdr.csum_flags & CSUM_TSO) { /* consolidate packet buffers for TSO/LSO segment offload */ #if defined(INET6) || defined(INET) @@ -837,15 +850,15 @@ retry: nichdr->u0.dw[2] = 0; nichdr->u0.dw[3] = 0; - nichdr->u0.s.complete = 1; + nichdr->u0.s.complete = complete; nichdr->u0.s.event = 1; nichdr->u0.s.crc = 1; nichdr->u0.s.forward = 0; nichdr->u0.s.ipcs = (m->m_pkthdr.csum_flags & CSUM_IP) ? 1 : 0; nichdr->u0.s.udpcs = - (m->m_pkthdr.csum_flags & CSUM_UDP) ? 1 : 0; + (m->m_pkthdr.csum_flags & CSUM_UDP) ? 1 : 0; nichdr->u0.s.tcpcs = - (m->m_pkthdr.csum_flags & CSUM_TCP) ? 1 : 0; + (m->m_pkthdr.csum_flags & CSUM_TCP) ? 1 : 0; nichdr->u0.s.num_wqe = num_wqes; nichdr->u0.s.total_length = m->m_pkthdr.len; if (m->m_flags & M_VLANTAG) { @@ -895,7 +908,7 @@ retry: wq->tx_stats.tx_wrbs += num_wqes; wq->tx_stats.tx_bytes += m->m_pkthdr.len; wq->tx_stats.tx_pkts++; - + bus_dmamap_sync(wq->ring->dma.tag, wq->ring->dma.map, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); reg_value = (num_wqes << 16) | wq->wq_id; @@ -1081,6 +1094,9 @@ oce_start(struct ifnet *ifp) if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != IFF_DRV_RUNNING) return; + + if (!sc->link_status) + return; do { IF_DEQUEUE(&sc->ifp->if_snd, m); @@ -1303,7 +1319,6 @@ oce_rx(struct oce_rq *rq, uint32_t rqe_idx, struct oce_nic_rx_cqe *cqe) #if defined(INET6) || defined(INET) /* Try to queue to LRO */ if (IF_LRO_ENABLED(sc) && - !(m->m_flags & M_VLANTAG) && (cqe->u0.s.ip_cksum_pass) && (cqe->u0.s.l4_cksum_pass) && (!cqe->u0.s.ip_ver) && @@ -1343,13 +1358,6 @@ oce_discard_rx_comp(struct oce_rq *rq, struct oce_nic_rx_cqe *cqe) POCE_SOFTC sc = (POCE_SOFTC) rq->parent; int num_frags = cqe->u0.s.num_fragments; - if (IS_XE201(sc) && cqe->u0.s.error) { - /* Lancer A0 workaround - * num_frags will be 1 more than actual in case of error - */ - if (num_frags) - num_frags -= 1; - } for (i = 0; i < num_frags; i++) { if (rq->packets_out == rq->packets_in) { device_printf(sc->dev, @@ -1458,7 +1466,7 @@ oce_free_lro(POCE_SOFTC sc) tcp_lro_free(lro); } } -#endif /* INET6 || INET */ +#endif int oce_alloc_rx_bufs(struct oce_rq *rq, int count) @@ -1471,7 +1479,7 @@ oce_alloc_rx_bufs(struct oce_rq *rq, int count) struct oce_nic_rqe *rqe; pd_rxulp_db_t rxdb_reg; - + bzero(&rxdb_reg, sizeof(pd_rxulp_db_t)); for (i = 0; i < count; i++) { in = rq->packets_in + 1; if (in == OCE_RQ_PACKET_ARRAY_SIZE) @@ -1512,14 +1520,12 @@ oce_alloc_rx_bufs(struct oce_rq *rq, int count) } if (added != 0) { for (i = added / OCE_MAX_RQ_POSTS; i > 0; i--) { - DELAY(1); rxdb_reg.bits.num_posted = OCE_MAX_RQ_POSTS; rxdb_reg.bits.qid = rq->rq_id; OCE_WRITE_REG32(sc, db, PD_RXULP_DB, rxdb_reg.dw0); added -= OCE_MAX_RQ_POSTS; } if (added > 0) { - DELAY(1); rxdb_reg.bits.qid = rq->rq_id; rxdb_reg.bits.num_posted = added; OCE_WRITE_REG32(sc, db, PD_RXULP_DB, rxdb_reg.dw0); @@ -1554,13 +1560,8 @@ oce_rq_handler(void *arg) } else { rq->rx_stats.rxcp_err++; sc->ifp->if_ierrors++; - if (IS_XE201(sc)) - /* Lancer A0 no buffer workaround */ - oce_discard_rx_comp(rq, cqe); - else - /* Post L3/L4 errors to stack.*/ - oce_rx(rq, cqe->u0.s.frag_index, cqe); - + /* Post L3/L4 errors to stack.*/ + oce_rx(rq, cqe->u0.s.frag_index, cqe); } rq->rx_stats.rx_compl++; cqe->u0.dw[2] = 0; @@ -1757,18 +1758,18 @@ oce_handle_passthrough(struct ifnet *ifp, caddr_t data) uint32_t req_size; struct mbx_hdr req; OCE_DMA_MEM dma_mem; - + struct mbx_common_get_cntl_attr *fw_cmd; if (copyin(priv_data, cookie, strlen(IOCTL_COOKIE))) return EFAULT; - + if (memcmp(cookie, IOCTL_COOKIE, strlen(IOCTL_COOKIE))) return EINVAL; - + ioctl_ptr = (char *)priv_data + strlen(IOCTL_COOKIE); if (copyin(ioctl_ptr, &req, sizeof(struct mbx_hdr))) return EFAULT; - + req_size = le32toh(req.u0.req.request_length); if (req_size > 65536) return EINVAL; @@ -1792,12 +1793,86 @@ oce_handle_passthrough(struct ifnet *ifp, caddr_t data) if (copyout(OCE_DMAPTR(&dma_mem,char), ioctl_ptr, req_size)) rc = EFAULT; + /* + firmware is filling all the attributes for this ioctl except + the driver version..so fill it + */ + if(req.u0.rsp.opcode == OPCODE_COMMON_GET_CNTL_ATTRIBUTES) { + fw_cmd = (struct mbx_common_get_cntl_attr *) ioctl_ptr; + strncpy(fw_cmd->params.rsp.cntl_attr_info.hba_attr.drv_ver_str, + COMPONENT_REVISION, strlen(COMPONENT_REVISION)); + } + dma_free: oce_dma_free(sc, &dma_mem); return rc; } +static void +oce_eqd_set_periodic(POCE_SOFTC sc) +{ + struct oce_set_eqd set_eqd[OCE_MAX_EQ]; + struct oce_aic_obj *aic; + struct oce_eq *eqo; + uint64_t now = 0, delta; + int eqd, i, num = 0; + uint32_t ips = 0; + int tps; + + for (i = 0 ; i < sc->neqs; i++) { + eqo = sc->eq[i]; + aic = &sc->aic_obj[i]; + /* When setting the static eq delay from the user space */ + if (!aic->enable) { + eqd = aic->et_eqd; + goto modify_eqd; + } + + now = ticks; + + /* Over flow check */ + if ((now < aic->ticks) || (eqo->intr < aic->intr_prev)) + goto done; + + delta = now - aic->ticks; + tps = delta/hz; + + /* Interrupt rate based on elapsed ticks */ + if(tps) + ips = (uint32_t)(eqo->intr - aic->intr_prev) / tps; + + if (ips > INTR_RATE_HWM) + eqd = aic->cur_eqd + 20; + else if (ips < INTR_RATE_LWM) + eqd = aic->cur_eqd / 2; + else + goto done; + + if (eqd < 10) + eqd = 0; + + /* Make sure that the eq delay is in the known range */ + eqd = min(eqd, aic->max_eqd); + eqd = max(eqd, aic->min_eqd); + +modify_eqd: + if (eqd != aic->cur_eqd) { + set_eqd[num].delay_multiplier = (eqd * 65)/100; + set_eqd[num].eq_id = eqo->eq_id; + aic->cur_eqd = eqd; + num++; + } +done: + aic->intr_prev = eqo->intr; + aic->ticks = now; + } + + /* Is there atleast one eq that needs to be modified? */ + if(num) + oce_mbox_eqd_modify_periodic(sc, set_eqd, num); + +} static void oce_local_timer(void *arg) @@ -1813,6 +1888,10 @@ oce_local_timer(void *arg) for (i = 0; i < sc->nwqs; i++) oce_tx_restart(sc, sc->wq[i]); + /* calculate and set the eq delay for optimal interrupt rate */ + if (IS_BE(sc)) + oce_eqd_set_periodic(sc); + callout_reset(&sc->timer, hz, oce_local_timer, sc); } @@ -1849,17 +1928,17 @@ oce_if_deactivate(POCE_SOFTC sc) /* Stop intrs and finish any bottom halves pending */ oce_hw_intr_disable(sc); - /* Since taskqueue_drain takes a Giant Lock, We should not acquire - any other lock. So unlock device lock and require after - completing taskqueue_drain. - */ - UNLOCK(&sc->dev_lock); + /* Since taskqueue_drain takes a Gaint Lock, We should not acquire + any other lock. So unlock device lock and require after + completing taskqueue_drain. + */ + UNLOCK(&sc->dev_lock); for (i = 0; i < sc->intr_count; i++) { if (sc->intrs[i].tq != NULL) { taskqueue_drain(sc->intrs[i].tq, &sc->intrs[i].task); } } - LOCK(&sc->dev_lock); + LOCK(&sc->dev_lock); /* Delete RX queue in card with flush param */ oce_stop_rx(sc); @@ -1874,7 +1953,7 @@ oce_if_deactivate(POCE_SOFTC sc) /* But still we need to get MCC aync events. So enable intrs and also arm first EQ - */ + */ oce_hw_intr_enable(sc); oce_arm_eq(sc, sc->eq[0]->eq_id, 0, TRUE, FALSE); @@ -1947,6 +2026,7 @@ oce_mq_handler(void *arg) struct oce_mq_cqe *cqe; struct oce_async_cqe_link_state *acqe; struct oce_async_event_grp5_pvid_state *gcqe; + struct oce_async_event_qnq *dbgcqe; bus_dmamap_sync(cq->ring->dma.tag, @@ -1973,6 +2053,14 @@ oce_mq_handler(void *arg) sc->pvid = 0; } + else if(evt_type == ASYNC_EVENT_CODE_DEBUG && + optype == ASYNC_EVENT_DEBUG_QNQ) { + dbgcqe = + (struct oce_async_event_qnq *)cqe; + if(dbgcqe->valid) + sc->qnqid = dbgcqe->vlan_tag; + sc->qnq_debug_event = TRUE; + } } cqe->u0.dw[3] = 0; RING_GET(cq->ring, 1); @@ -2032,3 +2120,79 @@ update_queues_got(POCE_SOFTC sc) } } +static int +oce_check_ipv6_ext_hdr(struct mbuf *m) +{ + struct ether_header *eh = mtod(m, struct ether_header *); + caddr_t m_datatemp = m->m_data; + + if (eh->ether_type == htons(ETHERTYPE_IPV6)) { + m->m_data += sizeof(struct ether_header); + struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); + + if((ip6->ip6_nxt != IPPROTO_TCP) && \ + (ip6->ip6_nxt != IPPROTO_UDP)){ + struct ip6_ext *ip6e = NULL; + m->m_data += sizeof(struct ip6_hdr); + + ip6e = (struct ip6_ext *) mtod(m, struct ip6_ext *); + if(ip6e->ip6e_len == 0xff) { + m->m_data = m_datatemp; + return TRUE; + } + } + m->m_data = m_datatemp; + } + return FALSE; +} + +static int +is_be3_a1(POCE_SOFTC sc) +{ + if((sc->flags & OCE_FLAGS_BE3) && ((sc->asic_revision & 0xFF) < 2)) { + return TRUE; + } + return FALSE; +} + +static struct mbuf * +oce_insert_vlan_tag(POCE_SOFTC sc, struct mbuf *m, boolean_t *complete) +{ + uint16_t vlan_tag = 0; + + if(!M_WRITABLE(m)) + return NULL; + + /* Embed vlan tag in the packet if it is not part of it */ + if(m->m_flags & M_VLANTAG) { + vlan_tag = EVL_VLANOFTAG(m->m_pkthdr.ether_vtag); + m->m_flags &= ~M_VLANTAG; + } + + /* if UMC, ignore vlan tag insertion and instead insert pvid */ + if(sc->pvid) { + if(!vlan_tag) + vlan_tag = sc->pvid; + *complete = FALSE; + } + + if(vlan_tag) { + m = ether_vlanencap(m, vlan_tag); + } + + if(sc->qnqid) { + m = ether_vlanencap(m, sc->qnqid); + *complete = FALSE; + } + return m; +} + +static int +oce_tx_asic_stall_verify(POCE_SOFTC sc, struct mbuf *m) +{ + if(is_be3_a1(sc) && IS_QNQ_OR_UMC(sc) && \ + oce_check_ipv6_ext_hdr(m)) { + return TRUE; + } + return FALSE; +} diff --git a/sys/dev/oce/oce_if.h b/sys/dev/oce/oce_if.h index 6428f88..ee684bd 100644 --- a/sys/dev/oce/oce_if.h +++ b/sys/dev/oce/oce_if.h @@ -36,6 +36,7 @@ * Costa Mesa, CA 92626 */ + /* $FreeBSD$ */ #include <sys/param.h> @@ -87,9 +88,7 @@ #include "oce_hw.h" -/* OCE device driver module component revision informaiton */ -#define COMPONENT_REVISION "4.2.127.0" - +#define COMPONENT_REVISION "4.6.95.0" /* OCE devices supported by this driver */ #define PCI_VENDOR_EMULEX 0x10df /* Emulex */ @@ -132,7 +131,7 @@ extern int mp_ncpus; /* system's total active cpu cores */ #define OCE_RQ_BUF_SIZE 2048 #define OCE_LSO_MAX_SIZE (64 * 1024) #define LONG_TIMEOUT 30 -#define OCE_MAX_JUMBO_FRAME_SIZE 16360 +#define OCE_MAX_JUMBO_FRAME_SIZE 9018 #define OCE_MAX_MTU (OCE_MAX_JUMBO_FRAME_SIZE - \ ETHER_VLAN_ENCAP_LEN - \ ETHER_HDR_LEN) @@ -481,7 +480,27 @@ struct oce_drv_stats { } u0; }; +#define INTR_RATE_HWM 15000 +#define INTR_RATE_LWM 10000 + +#define OCE_MAX_EQD 128u +#define OCE_MIN_EQD 50u + +struct oce_set_eqd { + uint32_t eq_id; + uint32_t phase; + uint32_t delay_multiplier; +}; +struct oce_aic_obj { /* Adaptive interrupt coalescing (AIC) info */ + boolean_t enable; + uint32_t min_eqd; /* in usecs */ + uint32_t max_eqd; /* in usecs */ + uint32_t cur_eqd; /* in usecs */ + uint32_t et_eqd; /* configured value when aic is off */ + uint64_t ticks; + uint64_t intr_prev; +}; #define MAX_LOCK_DESC_LEN 32 struct oce_lock { @@ -565,6 +584,7 @@ struct oce_eq { int cq_valid; struct eq_config eq_cfg; int vector; + uint64_t intr; }; enum cq_len { @@ -827,6 +847,9 @@ typedef struct oce_softc { uint32_t flow_control; uint32_t promisc; + + struct oce_aic_obj aic_obj[OCE_MAX_EQ]; + /*Vlan Filtering related */ eventhandler_tag vlan_attach; eventhandler_tag vlan_detach; @@ -837,7 +860,9 @@ typedef struct oce_softc { struct oce_drv_stats oce_stats_info; struct callout timer; int8_t be3_native; - uint32_t pvid; + uint16_t qnq_debug_event; + uint16_t qnqid; + uint16_t pvid; } OCE_SOFTC, *POCE_SOFTC; @@ -996,6 +1021,9 @@ int oce_mbox_create_wq(struct oce_wq *wq); int oce_mbox_create_eq(struct oce_eq *eq); int oce_mbox_cq_create(struct oce_cq *cq, uint32_t ncoalesce, uint32_t is_eventable); +int oce_mbox_read_transrecv_data(POCE_SOFTC sc, uint32_t page_num); +void oce_mbox_eqd_modify_periodic(POCE_SOFTC sc, struct oce_set_eqd *set_eqd, + int num); void mbx_common_req_hdr_init(struct mbx_hdr *hdr, uint8_t dom, uint8_t port, @@ -1076,3 +1104,12 @@ static inline uint32_t oce_highbit(uint32_t x) return 0; } +#define TRANSCEIVER_DATA_NUM_ELE 64 +#define TRANSCEIVER_DATA_SIZE 256 +#define TRANSCEIVER_A0_SIZE 128 +#define TRANSCEIVER_A2_SIZE 128 +#define PAGE_NUM_A0 0xa0 +#define PAGE_NUM_A2 0xa2 +#define IS_QNQ_OR_UMC(sc) ((sc->pvid && (sc->function_mode & FNM_UMC_MODE ))\ + || (sc->qnqid && (sc->function_mode & FNM_FLEX10_MODE))) + diff --git a/sys/dev/oce/oce_mbox.c b/sys/dev/oce/oce_mbox.c index 07107a2..2db5934 100644 --- a/sys/dev/oce/oce_mbox.c +++ b/sys/dev/oce/oce_mbox.c @@ -37,10 +37,12 @@ */ + /* $FreeBSD$ */ -#include "oce_if.h" +#include "oce_if.h" +extern uint32_t sfp_vpd_dump_buffer[TRANSCEIVER_DATA_NUM_ELE]; /** * @brief Reset (firmware) common function @@ -276,12 +278,17 @@ oce_get_fw_version(POCE_SOFTC sc) DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); ret = oce_mbox_post(sc, &mbx, NULL); - if (ret) - return ret; + if (!ret) + ret = fwcmd->hdr.u0.rsp.status; + if (ret) { + device_printf(sc->dev,"%s failed - cmd status: %d\n", + __FUNCTION__, ret); + goto error; + } bcopy(fwcmd->params.rsp.fw_ver_str, sc->fw_version, 32); - - return 0; +error: + return ret; } @@ -428,15 +435,20 @@ oce_read_mac_addr(POCE_SOFTC sc, uint32_t if_id, DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); ret = oce_mbox_post(sc, &mbx, NULL); - if (ret) - return ret; + if (!ret) + ret = fwcmd->hdr.u0.rsp.status; + if (ret) { + device_printf(sc->dev,"%s failed - cmd status: %d\n", + __FUNCTION__, ret); + goto error; + } /* copy the mac addres in the output parameter */ 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 0; +error: + return ret; } /** @@ -466,8 +478,13 @@ oce_get_fw_config(POCE_SOFTC sc) DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); ret = oce_mbox_post(sc, &mbx, NULL); - if (ret) - return ret; + if (!ret) + ret = fwcmd->hdr.u0.rsp.status; + if (ret) { + device_printf(sc->dev,"%s failed - cmd status: %d\n", + __FUNCTION__, ret); + goto error; + } DW_SWAP(u32ptr(fwcmd), sizeof(struct mbx_common_query_fw_config)); @@ -485,7 +502,8 @@ oce_get_fw_config(POCE_SOFTC sc) sc->max_rx_rings = fwcmd->params.rsp.ulp[1].lro_rqid_tot; } - return 0; +error: + return ret; } @@ -540,15 +558,20 @@ oce_if_create(POCE_SOFTC sc, DW_SWAP(u32ptr(&mbx), OCE_BMBX_RHDR_SZ); rc = oce_mbox_post(sc, &mbx, NULL); - if (rc) - return rc; + if (!rc) + rc = fwcmd->hdr.u0.rsp.status; + if (rc) { + device_printf(sc->dev,"%s failed - cmd status: %d\n", + __FUNCTION__, rc); + goto error; + } *if_id = LE_32(fwcmd->params.rsp.if_id); if (mac_addr != NULL) sc->pmac_id = LE_32(fwcmd->params.rsp.pmac_id); - - return 0; +error: + return rc; } /** @@ -581,6 +604,11 @@ oce_if_del(POCE_SOFTC sc, uint32_t if_id) DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); rc = oce_mbox_post(sc, &mbx, NULL); + if (!rc) + rc = fwcmd->hdr.u0.rsp.status; + if (rc) + device_printf(sc->dev,"%s failed - cmd status: %d\n", + __FUNCTION__, rc); return rc; } @@ -628,8 +656,12 @@ oce_config_vlan(POCE_SOFTC sc, DW_SWAP(u32ptr(&mbx), (OCE_BMBX_RHDR_SZ + mbx.payload_length)); rc = oce_mbox_post(sc, &mbx, NULL); - - return rc; + if (!rc) + rc = fwcmd->hdr.u0.rsp.status; + if (rc) + device_printf(sc->dev,"%s failed - cmd status: %d\n", + __FUNCTION__, rc); + return 0; } @@ -667,7 +699,11 @@ oce_set_flow_control(POCE_SOFTC sc, uint32_t flow_control) DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); rc = oce_mbox_post(sc, &mbx, NULL); - + if (!rc) + rc = fwcmd->hdr.u0.rsp.status; + if (rc) + device_printf(sc->dev,"%s failed - cmd status: %d\n", + __FUNCTION__, rc); return rc; } @@ -726,20 +762,28 @@ oce_config_nic_rss(POCE_SOFTC sc, uint32_t if_id, uint16_t enable_rss) struct oce_mbx mbx; struct mbx_config_nic_rss *fwcmd = (struct mbx_config_nic_rss *)&mbx.payload; + int version; bzero(&mbx, sizeof(struct oce_mbx)); + if (IS_XE201(sc)) { + version = OCE_MBX_VER_V1; + fwcmd->params.req.enable_rss = RSS_ENABLE_UDP_IPV4 | + RSS_ENABLE_UDP_IPV6; + } else + version = OCE_MBX_VER_V0; + mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, MBX_SUBSYSTEM_NIC, NIC_CONFIG_RSS, MBX_TIMEOUT_SEC, sizeof(struct mbx_config_nic_rss), - OCE_MBX_VER_V0); + version); if (enable_rss) - fwcmd->params.req.enable_rss = (RSS_ENABLE_IPV4 | - RSS_ENABLE_TCP_IPV4 | - RSS_ENABLE_IPV6 | - RSS_ENABLE_TCP_IPV6); + fwcmd->params.req.enable_rss |= (RSS_ENABLE_IPV4 | + RSS_ENABLE_TCP_IPV4 | + RSS_ENABLE_IPV6 | + RSS_ENABLE_TCP_IPV6); fwcmd->params.req.flush = OCE_FLUSH; fwcmd->params.req.if_id = LE_32(if_id); @@ -753,9 +797,12 @@ oce_config_nic_rss(POCE_SOFTC sc, uint32_t if_id, uint16_t enable_rss) DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); rc = oce_mbox_post(sc, &mbx, NULL); - + if (!rc) + rc = fwcmd->hdr.u0.rsp.status; + if (rc) + device_printf(sc->dev,"%s failed - cmd status: %d\n", + __FUNCTION__, rc); } - return rc; } @@ -834,7 +881,12 @@ oce_set_common_iface_rx_filter(POCE_SOFTC sc, POCE_DMA_MEM sgl) DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); rc = oce_mbox_post(sc, &mbx, NULL); - return rc; + if (!rc) + rc = fwcmd->hdr.u0.rsp.status; + if (rc) + device_printf(sc->dev,"%s failed - cmd status: %d\n", + __FUNCTION__, rc); + return 0; } /** @@ -848,17 +900,19 @@ oce_get_link_status(POCE_SOFTC sc, struct link_status *link) { struct oce_mbx mbx; struct mbx_query_common_link_config *fwcmd; - int rc = 0; + int rc = 0, version; bzero(&mbx, sizeof(struct oce_mbx)); + IS_XE201(sc) ? (version = OCE_MBX_VER_V1) : (version = OCE_MBX_VER_V0); + fwcmd = (struct mbx_query_common_link_config *)&mbx.payload; mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, MBX_SUBSYSTEM_COMMON, OPCODE_COMMON_QUERY_LINK_CONFIG, MBX_TIMEOUT_SEC, sizeof(struct mbx_query_common_link_config), - OCE_MBX_VER_V0); + version); mbx.u0.s.embedded = 1; mbx.payload_length = sizeof(struct mbx_query_common_link_config); @@ -866,15 +920,18 @@ oce_get_link_status(POCE_SOFTC sc, struct link_status *link) rc = oce_mbox_post(sc, &mbx, NULL); + if (!rc) + rc = fwcmd->hdr.u0.rsp.status; if (rc) { - device_printf(sc->dev, "Could not get link speed: %d\n", rc); - } else { - /* interpret response */ - bcopy(&fwcmd->params.rsp, link, sizeof(struct link_status)); - link->logical_link_status = LE_32(link->logical_link_status); - link->qos_link_speed = LE_16(link->qos_link_speed); + device_printf(sc->dev,"%s failed - cmd status: %d\n", + __FUNCTION__, rc); + goto error; } - + /* interpret response */ + bcopy(&fwcmd->params.rsp, link, sizeof(struct link_status)); + link->logical_link_status = LE_32(link->logical_link_status); + link->qos_link_speed = LE_16(link->qos_link_speed); +error: return rc; } @@ -916,11 +973,11 @@ oce_mbox_get_nic_stats_v0(POCE_SOFTC sc, POCE_DMA_MEM pstats_dma_mem) oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_POSTWRITE); - if (rc) { - device_printf(sc->dev, - "Could not get nic statistics: %d\n", rc); - } - + if (!rc) + rc = fwcmd->hdr.u0.rsp.status; + if (rc) + device_printf(sc->dev,"%s failed - cmd status: %d\n", + __FUNCTION__, rc); return rc; } @@ -966,10 +1023,11 @@ oce_mbox_get_nic_stats(POCE_SOFTC sc, POCE_DMA_MEM pstats_dma_mem) rc = oce_mbox_post(sc, &mbx, NULL); oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_POSTWRITE); - if (rc) { - device_printf(sc->dev, - "Could not get nic statistics: %d\n", rc); - } + if (!rc) + rc = fwcmd->hdr.u0.rsp.status; + if (rc) + device_printf(sc->dev,"%s failed - cmd status: %d\n", + __FUNCTION__, rc); return rc; } @@ -1001,7 +1059,7 @@ oce_mbox_get_pport_stats(POCE_SOFTC sc, POCE_DMA_MEM pstats_dma_mem, OCE_MBX_VER_V0); fwcmd->params.req.reset_stats = reset_stats; - fwcmd->params.req.port_number = sc->if_id; + fwcmd->params.req.port_number = sc->port_id; mbx.u0.s.embedded = 0; /* stats too large for embedded mbx rsp */ mbx.u0.s.sge_count = 1; /* using scatter gather instead */ @@ -1017,11 +1075,11 @@ oce_mbox_get_pport_stats(POCE_SOFTC sc, POCE_DMA_MEM pstats_dma_mem, rc = oce_mbox_post(sc, &mbx, NULL); oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_POSTWRITE); - if (rc != 0) { - device_printf(sc->dev, - "Could not get physical port statistics: %d\n", rc); - } - + if (!rc) + rc = fwcmd->hdr.u0.rsp.status; + if (rc) + device_printf(sc->dev,"%s failed - cmd status: %d\n", + __FUNCTION__, rc); return rc; } @@ -1070,11 +1128,11 @@ oce_mbox_get_vport_stats(POCE_SOFTC sc, POCE_DMA_MEM pstats_dma_mem, rc = oce_mbox_post(sc, &mbx, NULL); oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_POSTWRITE); - if (rc != 0) { - device_printf(sc->dev, - "Could not get physical port statistics: %d\n", rc); - } - + if (!rc) + rc = fwcmd->hdr.u0.rsp.status; + if (rc) + device_printf(sc->dev,"%s failed - cmd status: %d\n", + __FUNCTION__, rc); return rc; } @@ -1115,7 +1173,11 @@ oce_update_multicast(POCE_SOFTC sc, POCE_DMA_MEM pdma_mem) DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); rc = oce_mbox_post(sc, &mbx, NULL); - + if (!rc) + rc = req->hdr.u0.rsp.status; + if (rc) + device_printf(sc->dev,"%s failed - cmd status: %d\n", + __FUNCTION__, rc); return rc; } @@ -1176,11 +1238,15 @@ oce_mbox_macaddr_add(POCE_SOFTC sc, uint8_t *mac_addr, mbx.payload_length = sizeof(struct mbx_add_common_iface_mac); DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); rc = oce_mbox_post(sc, &mbx, NULL); - if (rc) - return rc; - + if (!rc) + rc = fwcmd->hdr.u0.rsp.status; + if (rc) { + device_printf(sc->dev,"%s failed - cmd status: %d\n", + __FUNCTION__, rc); + goto error; + } *pmac_id = fwcmd->params.rsp.pmac_id; - +error: return rc; } @@ -1210,6 +1276,11 @@ oce_mbox_macaddr_del(POCE_SOFTC sc, uint32_t if_id, uint32_t pmac_id) DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); rc = oce_mbox_post(sc, &mbx, NULL); + if (!rc) + rc = fwcmd->hdr.u0.rsp.status; + if (rc) + device_printf(sc->dev,"%s failed - cmd status: %d\n", + __FUNCTION__, rc); return rc; } @@ -1242,12 +1313,17 @@ oce_mbox_check_native_mode(POCE_SOFTC sc) DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); rc = oce_mbox_post(sc, &mbx, NULL); - //if (rc != 0) This can fail in legacy mode. So skip - // FN_LEAVE(rc); - + if (!rc) + rc = fwcmd->hdr.u0.rsp.status; + if (rc) { + device_printf(sc->dev,"%s failed - cmd status: %d\n", + __FUNCTION__, rc); + goto error; + } sc->be3_native = fwcmd->params.rsp.capability_flags & CAP_BE3_NATIVE_ERX_API; +error: return 0; } @@ -1282,6 +1358,11 @@ oce_mbox_cmd_set_loopback(POCE_SOFTC sc, uint8_t port_num, DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); rc = oce_mbox_post(sc, &mbx, NULL); + if (!rc) + rc = fwcmd->hdr.u0.rsp.status; + if (rc) + device_printf(sc->dev,"%s failed - cmd status: %d\n", + __FUNCTION__, rc); return rc; @@ -1320,10 +1401,13 @@ oce_mbox_cmd_test_loopback(POCE_SOFTC sc, uint32_t port_num, DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); rc = oce_mbox_post(sc, &mbx, NULL); + if (!rc) + rc = fwcmd->hdr.u0.rsp.status; if (rc) - return rc; + device_printf(sc->dev,"%s failed - cmd status: %d\n", + __FUNCTION__, rc); - return(fwcmd->params.rsp.status); + return rc; } int @@ -1362,11 +1446,11 @@ oce_mbox_write_flashrom(POCE_SOFTC sc, uint32_t optype,uint32_t opcode, /* post the command */ rc = oce_mbox_post(sc, &mbx, NULL); - if (rc) { - device_printf(sc->dev, "Write FlashROM mbox post failed\n"); - } else { - rc = fwcmd->hdr.u0.rsp.status; - } + if (!rc) + rc = fwcmd->hdr.u0.rsp.status; + if (rc) + device_printf(sc->dev,"%s failed - cmd status: %d\n", + __FUNCTION__, rc); return rc; @@ -1408,12 +1492,15 @@ oce_mbox_get_flashrom_crc(POCE_SOFTC sc, uint8_t *flash_crc, /* post the command */ rc = oce_mbox_post(sc, &mbx, NULL); + if (!rc) + rc = fwcmd->hdr.u0.rsp.status; if (rc) { - device_printf(sc->dev, "Read FlashROM CRC mbox post failed\n"); - } else { - bcopy(fwcmd->data_buffer, flash_crc, 4); - rc = fwcmd->hdr.u0.rsp.status; + device_printf(sc->dev,"%s failed - cmd status: %d\n", + __FUNCTION__, rc); + goto error; } + bcopy(fwcmd->data_buffer, flash_crc, 4); +error: return rc; } @@ -1440,20 +1527,22 @@ oce_mbox_get_phy_info(POCE_SOFTC sc, struct oce_phy_info *phy_info) /* now post the command */ rc = oce_mbox_post(sc, &mbx, NULL); + if (!rc) + rc = fwcmd->hdr.u0.rsp.status; if (rc) { - device_printf(sc->dev, "Read PHY info mbox post failed\n"); - } else { - rc = fwcmd->hdr.u0.rsp.status; - phy_info->phy_type = fwcmd->params.rsp.phy_info.phy_type; - phy_info->interface_type = - fwcmd->params.rsp.phy_info.interface_type; - phy_info->auto_speeds_supported = - fwcmd->params.rsp.phy_info.auto_speeds_supported; - phy_info->fixed_speeds_supported = - fwcmd->params.rsp.phy_info.fixed_speeds_supported; - phy_info->misc_params =fwcmd->params.rsp.phy_info.misc_params; - + device_printf(sc->dev,"%s failed - cmd status: %d\n", + __FUNCTION__, rc); + goto error; } + phy_info->phy_type = fwcmd->params.rsp.phy_info.phy_type; + phy_info->interface_type = + fwcmd->params.rsp.phy_info.interface_type; + phy_info->auto_speeds_supported = + fwcmd->params.rsp.phy_info.auto_speeds_supported; + phy_info->fixed_speeds_supported = + fwcmd->params.rsp.phy_info.fixed_speeds_supported; + phy_info->misc_params =fwcmd->params.rsp.phy_info.misc_params; +error: return rc; } @@ -1499,14 +1588,16 @@ oce_mbox_lancer_write_flashrom(POCE_SOFTC sc, uint32_t data_size, /* post the command */ rc = oce_mbox_post(sc, &mbx, NULL); + if (!rc) + rc = fwcmd->params.rsp.status; if (rc) { - device_printf(sc->dev, - "Write Lancer FlashROM mbox post failed\n"); - } else { - *written_data = fwcmd->params.rsp.actual_write_length; - *additional_status = fwcmd->params.rsp.additional_status; - rc = fwcmd->params.rsp.status; + device_printf(sc->dev,"%s failed - cmd status: %d\n", + __FUNCTION__, rc); + goto error; } + *written_data = fwcmd->params.rsp.actual_write_length; + *additional_status = fwcmd->params.rsp.additional_status; +error: return rc; } @@ -1553,15 +1644,16 @@ oce_mbox_create_rq(struct oce_rq *rq) mbx.payload_length = sizeof(struct mbx_create_nic_rq); rc = oce_mbox_post(sc, &mbx, NULL); - if (rc) + if (!rc) + rc = fwcmd->hdr.u0.rsp.status; + if (rc) { + device_printf(sc->dev,"%s failed - cmd status: %d\n", + __FUNCTION__, rc); goto error; - + } rq->rq_id = fwcmd->params.rsp.rq_id; rq->rss_cpuid = fwcmd->params.rsp.rss_cpuid; - - return 0; error: - device_printf(sc->dev, "Mbox Create RQ failed\n"); return rc; } @@ -1603,14 +1695,15 @@ oce_mbox_create_wq(struct oce_wq *wq) mbx.payload_length = sizeof(struct mbx_create_nic_wq); rc = oce_mbox_post(sc, &mbx, NULL); - if (rc) + if (!rc) + rc = fwcmd->hdr.u0.rsp.status; + if (rc) { + device_printf(sc->dev,"%s failed - cmd status: %d\n", + __FUNCTION__, rc); goto error; - + } wq->wq_id = LE_16(fwcmd->params.rsp.wq_id); - - return 0; error: - device_printf(sc->dev, "Mbox Create WQ failed\n"); return rc; } @@ -1649,14 +1742,15 @@ oce_mbox_create_eq(struct oce_eq *eq) mbx.payload_length = sizeof(struct mbx_create_common_eq); rc = oce_mbox_post(sc, &mbx, NULL); - if (rc) + if (!rc) + rc = fwcmd->hdr.u0.rsp.status; + if (rc) { + device_printf(sc->dev,"%s failed - cmd status: %d\n", + __FUNCTION__, rc); goto error; - + } eq->eq_id = LE_16(fwcmd->params.rsp.eq_id); - - return 0; error: - device_printf(sc->dev, "Mbox Create EQ failed\n"); return rc; } @@ -1726,14 +1820,125 @@ oce_mbox_cq_create(struct oce_cq *cq, uint32_t ncoalesce, uint32_t is_eventable) mbx.payload_length = sizeof(struct mbx_create_common_cq); rc = oce_mbox_post(sc, &mbx, NULL); - if (rc) + if (!rc) + rc = fwcmd->hdr.u0.rsp.status; + if (rc) { + device_printf(sc->dev,"%s failed - cmd status: %d\n", + __FUNCTION__, rc); goto error; - + } cq->cq_id = LE_16(fwcmd->params.rsp.cq_id); +error: + return rc; - return 0; +} + +int +oce_mbox_read_transrecv_data(POCE_SOFTC sc, uint32_t page_num) +{ + int rc = 0; + struct oce_mbx mbx; + struct mbx_read_common_transrecv_data *fwcmd; + struct oce_mq_sge *sgl; + OCE_DMA_MEM dma; + + /* Allocate DMA mem*/ + if (oce_dma_alloc(sc, sizeof(struct mbx_read_common_transrecv_data), + &dma, 0)) + return ENOMEM; + + fwcmd = OCE_DMAPTR(&dma, struct mbx_read_common_transrecv_data); + bzero(fwcmd, sizeof(struct mbx_read_common_transrecv_data)); + + bzero(&mbx, sizeof(struct oce_mbx)); + mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, + MBX_SUBSYSTEM_COMMON, + OPCODE_COMMON_READ_TRANSRECEIVER_DATA, + MBX_TIMEOUT_SEC, + sizeof(struct mbx_read_common_transrecv_data), + OCE_MBX_VER_V0); + + /* fill rest of mbx */ + mbx.u0.s.embedded = 0; + mbx.payload_length = sizeof(struct mbx_read_common_transrecv_data); + mbx.u0.s.sge_count = 1; + sgl = &mbx.payload.u0.u1.sgl[0]; + sgl->pa_hi = htole32(upper_32_bits(dma.paddr)); + sgl->pa_lo = htole32((dma.paddr) & 0xFFFFFFFF); + sgl->length = htole32(mbx.payload_length); + DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); + + fwcmd->params.req.port = LE_32(sc->port_id); + fwcmd->params.req.page_num = LE_32(page_num); + + /* command post */ + rc = oce_mbox_post(sc, &mbx, NULL); + if (!rc) + rc = fwcmd->hdr.u0.rsp.status; + if (rc) { + device_printf(sc->dev,"%s failed - cmd status: %d\n", + __FUNCTION__, rc); + goto error; + } + if(fwcmd->params.rsp.page_num == PAGE_NUM_A0) + { + bcopy((char *)fwcmd->params.rsp.page_data, + (char *)&sfp_vpd_dump_buffer[0], + TRANSCEIVER_A0_SIZE); + } + + if(fwcmd->params.rsp.page_num == PAGE_NUM_A2) + { + bcopy((char *)fwcmd->params.rsp.page_data, + (char *)&sfp_vpd_dump_buffer[32], + TRANSCEIVER_A2_SIZE); + } error: - device_printf(sc->dev, "Mbox Create CQ failed\n"); return rc; +} +void +oce_mbox_eqd_modify_periodic(POCE_SOFTC sc, struct oce_set_eqd *set_eqd, + int num) +{ + struct oce_mbx mbx; + struct mbx_modify_common_eq_delay *fwcmd; + int rc = 0; + int i = 0; + + bzero(&mbx, sizeof(struct oce_mbx)); + + /* Initialize MODIFY_EQ_DELAY ioctl header */ + fwcmd = (struct mbx_modify_common_eq_delay *)&mbx.payload; + mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, + MBX_SUBSYSTEM_COMMON, + OPCODE_COMMON_MODIFY_EQ_DELAY, + MBX_TIMEOUT_SEC, + sizeof(struct mbx_modify_common_eq_delay), + OCE_MBX_VER_V0); + /* fill rest of mbx */ + mbx.u0.s.embedded = 1; + mbx.payload_length = sizeof(struct mbx_modify_common_eq_delay); + DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); + + fwcmd->params.req.num_eq = num; + for (i = 0; i < num; i++) { + fwcmd->params.req.delay[i].eq_id = + htole32(set_eqd[i].eq_id); + fwcmd->params.req.delay[i].phase = 0; + fwcmd->params.req.delay[i].dm = + htole32(set_eqd[i].delay_multiplier); + } + + + /* command post */ + rc = oce_mbox_post(sc, &mbx, NULL); + + if (!rc) + rc = fwcmd->hdr.u0.rsp.status; + if (rc) + device_printf(sc->dev,"%s failed - cmd status: %d\n", + __FUNCTION__, rc); } + + diff --git a/sys/dev/oce/oce_queue.c b/sys/dev/oce/oce_queue.c index 580853e..82972ee 100644 --- a/sys/dev/oce/oce_queue.c +++ b/sys/dev/oce/oce_queue.c @@ -36,8 +36,11 @@ * Costa Mesa, CA 92626 */ + + /* $FreeBSD$ */ + #include "oce_if.h" /***************************************************** @@ -89,6 +92,7 @@ oce_queue_init_all(POCE_SOFTC sc) int rc = 0, i, vector; struct oce_wq *wq; struct oce_rq *rq; + struct oce_aic_obj *aic; /* alloc TX/RX queues */ for_all_wq_queues(sc, wq, i) { @@ -113,6 +117,13 @@ oce_queue_init_all(POCE_SOFTC sc) /* create all of the event queues */ for (vector = 0; vector < sc->intr_count; vector++) { + /* setup aic defaults for each event queue */ + aic = &sc->aic_obj[vector]; + aic->max_eqd = OCE_MAX_EQD; + aic->min_eqd = OCE_MIN_EQD; + aic->et_eqd = OCE_MIN_EQD; + aic->enable = TRUE; + sc->eq[vector] = oce_eq_create(sc, EQ_LEN_1024, EQE_SIZE_4, 0, vector); if (!sc->eq[vector]) @@ -657,8 +668,7 @@ oce_mq_create(POCE_SOFTC sc, struct oce_eq *eq, uint32_t q_len) oce_mq_ext_ctx_t *ctx; uint32_t num_pages; uint32_t page_size; - uint32_t version; - + int version; cq = oce_cq_create(sc, eq, CQ_LEN_256, sizeof(struct oce_mq_cqe), 1, 1, 0, 0); @@ -680,8 +690,8 @@ oce_mq_create(POCE_SOFTC sc, struct oce_eq *eq, uint32_t q_len) bzero(&mbx, sizeof(struct oce_mbx)); + IS_XE201(sc) ? (version = OCE_MBX_VER_V1) : (version = OCE_MBX_VER_V0); fwcmd = (struct mbx_create_common_mq_ex *)&mbx.payload; - version = OCE_MBX_VER_V0; mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, MBX_SUBSYSTEM_COMMON, OPCODE_COMMON_CREATE_MQ_EXT, @@ -693,21 +703,41 @@ oce_mq_create(POCE_SOFTC sc, struct oce_eq *eq, uint32_t q_len) page_size = mq->ring->num_items * mq->ring->item_size; ctx = &fwcmd->params.req.context; - ctx->v0.num_pages = num_pages; - ctx->v0.cq_id = cq->cq_id; - ctx->v0.ring_size = OCE_LOG2(q_len) + 1; - ctx->v0.valid = 1; - /* Subscribe to Link State and Group 5 Events(bits 1 and 5 set) */ - ctx->v0.async_evt_bitmap = 0xffffffff; + + if (IS_XE201(sc)) { + ctx->v1.num_pages = num_pages; + ctx->v1.ring_size = OCE_LOG2(q_len) + 1; + ctx->v1.cq_id = cq->cq_id; + ctx->v1.valid = 1; + ctx->v1.async_cq_id = cq->cq_id; + ctx->v1.async_cq_valid = 1; + /* Subscribe to Link State and Group 5 Events(bits 1 & 5 set) */ + ctx->v1.async_evt_bitmap |= LE_32(0x00000022); + ctx->v1.async_evt_bitmap |= LE_32(1 << ASYNC_EVENT_CODE_DEBUG); + ctx->v1.async_evt_bitmap |= + LE_32(1 << ASYNC_EVENT_CODE_SLIPORT); + } + else { + ctx->v0.num_pages = num_pages; + ctx->v0.cq_id = cq->cq_id; + ctx->v0.ring_size = OCE_LOG2(q_len) + 1; + ctx->v0.valid = 1; + /* Subscribe to Link State and Group5 Events(bits 1 & 5 set) */ + ctx->v0.async_evt_bitmap = 0xffffffff; + } mbx.u0.s.embedded = 1; mbx.payload_length = sizeof(struct mbx_create_common_mq_ex); DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); rc = oce_mbox_post(sc, &mbx, NULL); - if (rc) + if (!rc) + rc = fwcmd->hdr.u0.rsp.status; + if (rc) { + device_printf(sc->dev,"%s failed - cmd status: %d\n", + __FUNCTION__, rc); goto error; - + } mq->mq_id = LE_16(fwcmd->params.rsp.mq_id); mq->cq = cq; eq->cq[eq->cq_valid] = cq; @@ -824,10 +854,11 @@ oce_destroy_q(POCE_SOFTC sc, struct oce_mbx *mbx, size_t req_size, DW_SWAP(u32ptr(mbx), mbx->payload_length + OCE_BMBX_RHDR_SZ); rc = oce_mbox_post(sc, mbx, NULL); - - if (rc != 0) - device_printf(sc->dev, "Failed to del q\n"); - + if (!rc) + rc = hdr->u0.rsp.status; + if (rc) + device_printf(sc->dev,"%s failed - cmd status: %d\n", + __FUNCTION__, rc); return rc; } diff --git a/sys/dev/oce/oce_sysctl.c b/sys/dev/oce/oce_sysctl.c index 93117f6..d8a88de 100644 --- a/sys/dev/oce/oce_sysctl.c +++ b/sys/dev/oce/oce_sysctl.c @@ -38,6 +38,9 @@ /* $FreeBSD$ */ +/* $FreeBSD$ */ + + #include "oce_if.h" static void copy_stats_to_sc_xe201(POCE_SOFTC sc); @@ -49,6 +52,7 @@ static int oce_sys_fwupgrade(SYSCTL_HANDLER_ARGS); static int oce_be3_flashdata(POCE_SOFTC sc, const struct firmware *fw, int num_imgs); static int oce_lancer_fwupgrade(POCE_SOFTC sc, const struct firmware *fw); +static int oce_sysctl_sfp_vpd_dump(SYSCTL_HANDLER_ARGS); static boolean_t oce_phy_flashing_required(POCE_SOFTC sc); static boolean_t oce_img_flashing_required(POCE_SOFTC sc, const char *p, int img_optype, uint32_t img_offset, @@ -61,7 +65,7 @@ static void oce_add_stats_sysctls_xe201(POCE_SOFTC sc, struct sysctl_oid *stats_node); extern char component_revision[32]; - +uint32_t sfp_vpd_dump_buffer[TRANSCEIVER_DATA_NUM_ELE]; void oce_add_sysctls(POCE_SOFTC sc) @@ -93,7 +97,8 @@ oce_add_sysctls(POCE_SOFTC sc) sizeof(oce_max_rsp_handled), "Maximum receive frames handled per interupt"); - if (sc->function_mode & FNM_FLEX10_MODE) + if ((sc->function_mode & FNM_FLEX10_MODE) || + (sc->function_mode & FNM_UMC_MODE)) SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "speed", CTLFLAG_RD, @@ -121,6 +126,19 @@ oce_add_sysctls(POCE_SOFTC sc) CTLTYPE_STRING | CTLFLAG_RW, (void *)sc, 0, oce_sys_fwupgrade, "A", "Firmware ufi file"); + /* + * Dumps Transceiver data + * "sysctl dev.oce.0.sfp_vpd_dump=0" + * "sysctl -x dev.oce.0.sfp_vpd_dump_buffer" for hex dump + * "sysctl -b dev.oce.0.sfp_vpd_dump_buffer > sfp.bin" for binary dump + */ + SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "sfp_vpd_dump", + CTLTYPE_INT | CTLFLAG_RW, (void *)sc, 0, oce_sysctl_sfp_vpd_dump, + "I", "Initiate a sfp_vpd_dump operation"); + SYSCTL_ADD_OPAQUE(ctx, child, OID_AUTO, "sfp_vpd_dump_buffer", + CTLFLAG_RD, sfp_vpd_dump_buffer, + TRANSCEIVER_DATA_SIZE, "IU", "Access sfp_vpd_dump buffer"); + stats_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "stats", CTLFLAG_RD, NULL, "Ethernet Statistics"); @@ -133,7 +151,6 @@ oce_add_sysctls(POCE_SOFTC sc) } - static uint32_t oce_loopback_test(struct oce_softc *sc, uint8_t loopback_type) { @@ -147,7 +164,6 @@ oce_loopback_test(struct oce_softc *sc, uint8_t loopback_type) return status; } - static int oce_sysctl_loopback(SYSCTL_HANDLER_ARGS) { @@ -1303,3 +1319,31 @@ oce_refresh_nic_stats(POCE_SOFTC sc) return rc; } + +static int +oce_sysctl_sfp_vpd_dump(SYSCTL_HANDLER_ARGS) +{ + int result = 0, error; + int rc = 0; + POCE_SOFTC sc = (POCE_SOFTC) arg1; + + /* sysctl default handler */ + error = sysctl_handle_int(oidp, &result, 0, req); + if (error || !req->newptr) + return (error); + + if(result == -1) { + return EINVAL; + } + bzero((char *)sfp_vpd_dump_buffer, TRANSCEIVER_DATA_SIZE); + + rc = oce_mbox_read_transrecv_data(sc, PAGE_NUM_A0); + if(rc) + return rc; + + rc = oce_mbox_read_transrecv_data(sc, PAGE_NUM_A2); + if(rc) + return rc; + + return rc; +} diff --git a/sys/dev/oce/oce_util.c b/sys/dev/oce/oce_util.c index 7b227ac..b71c02d 100644 --- a/sys/dev/oce/oce_util.c +++ b/sys/dev/oce/oce_util.c @@ -36,8 +36,10 @@ * Costa Mesa, CA 92626 */ + /* $FreeBSD$ */ + #include "oce_if.h" static void oce_dma_map_ring(void *arg, @@ -71,7 +73,8 @@ oce_dma_alloc(POCE_SOFTC sc, bus_size_t size, POCE_DMA_MEM dma, int flags) if (rc == 0) { rc = bus_dmamem_alloc(dma->tag, &dma->ptr, - BUS_DMA_NOWAIT | BUS_DMA_COHERENT, + BUS_DMA_NOWAIT | BUS_DMA_COHERENT | + BUS_DMA_ZERO, &dma->map); } |