diff --git a/share/man/man4/oce.4 b/share/man/man4/oce.4 index ee3b33b6ffa6..51ac5ec9ae9d 100644 --- a/share/man/man4/oce.4 +++ b/share/man/man4/oce.4 @@ -1,4 +1,4 @@ -.\" Copyright (C) 2012 Emulex +.\" Copyright (C) 2013 Emulex .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without diff --git a/sys/dev/oce/oce_hw.c b/sys/dev/oce/oce_hw.c index 274c4d1e48a0..1cacb8c1c8aa 100644 --- a/sys/dev/oce/oce_hw.c +++ b/sys/dev/oce/oce_hw.c @@ -1,5 +1,5 @@ /*- - * Copyright (C) 2012 Emulex + * Copyright (C) 2013 Emulex * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -53,12 +53,12 @@ oce_POST(POCE_SOFTC sc) int tmo = 60000; /* read semaphore CSR */ - post_status.dw0 = OCE_READ_REG32(sc, csr, MPU_EP_SEMAPHORE(sc)); + post_status.dw0 = OCE_READ_CSR_MPU(sc, csr, MPU_EP_SEMAPHORE(sc)); /* if host is ready then wait for fw ready else send POST */ if (post_status.bits.stage <= POST_STAGE_AWAITING_HOST_RDY) { post_status.bits.stage = POST_STAGE_CHIP_RESET; - OCE_WRITE_REG32(sc, csr, MPU_EP_SEMAPHORE(sc), post_status.dw0); + OCE_WRITE_CSR_MPU(sc, csr, MPU_EP_SEMAPHORE(sc), post_status.dw0); } /* wait for FW ready */ @@ -68,7 +68,7 @@ oce_POST(POCE_SOFTC sc) DELAY(1000); - post_status.dw0 = OCE_READ_REG32(sc, csr, MPU_EP_SEMAPHORE(sc)); + post_status.dw0 = OCE_READ_CSR_MPU(sc, csr, MPU_EP_SEMAPHORE(sc)); if (post_status.bits.error) { device_printf(sc->dev, "POST failed: %x\n", post_status.dw0); @@ -129,7 +129,7 @@ oce_hw_init(POCE_SOFTC sc) if (rc) goto error; - if (IS_BE(sc) && (sc->flags & OCE_FLAGS_BE3)) { + if ((IS_BE(sc) && (sc->flags & OCE_FLAGS_BE3)) || IS_SH(sc)) { rc = oce_mbox_check_native_mode(sc); if (rc) goto error; @@ -258,7 +258,7 @@ oce_hw_pci_alloc(POCE_SOFTC sc) rr = PCIR_BAR(pci_cfg_barnum); - if (IS_BE(sc)) + if (IS_BE(sc) || IS_SH(sc)) sc->devcfg_res = bus_alloc_resource_any(sc->dev, SYS_RES_MEMORY, &rr, RF_ACTIVE|RF_SHAREABLE); @@ -298,7 +298,7 @@ oce_hw_pci_alloc(POCE_SOFTC sc) sc->flags |= OCE_FLAGS_VIRTUAL_PORT; /* Lancer has one BAR (CFG) but BE3 has three (CFG, CSR, DB) */ - if (IS_BE(sc)) { + if (IS_BE(sc) || IS_SH(sc)) { /* set up CSR region */ rr = PCIR_BAR(OCE_PCI_CSR_BAR); sc->csr_res = bus_alloc_resource_any(sc->dev, @@ -387,7 +387,7 @@ oce_create_nw_interface(POCE_SOFTC sc) } /* enable capabilities controlled via driver startup parameters */ - if (sc->rss_enable) + if (is_rss_enabled(sc)) capab_en_flags |= MBX_RX_IFACE_FLAGS_RSS; else { capab_en_flags &= ~MBX_RX_IFACE_FLAGS_RSS; @@ -447,9 +447,9 @@ oce_pci_soft_reset(POCE_SOFTC sc) int rc; mpu_ep_control_t ctrl; - ctrl.dw0 = OCE_READ_REG32(sc, csr, MPU_EP_CONTROL); + ctrl.dw0 = OCE_READ_CSR_MPU(sc, csr, MPU_EP_CONTROL); ctrl.bits.cpu_reset = 1; - OCE_WRITE_REG32(sc, csr, MPU_EP_CONTROL, ctrl.dw0); + OCE_WRITE_CSR_MPU(sc, csr, MPU_EP_CONTROL, ctrl.dw0); DELAY(50); rc=oce_POST(sc); diff --git a/sys/dev/oce/oce_hw.h b/sys/dev/oce/oce_hw.h index 43945dc763ed..66250c8a7ae1 100644 --- a/sys/dev/oce/oce_hw.h +++ b/sys/dev/oce/oce_hw.h @@ -1,5 +1,5 @@ /*- - * Copyright (C) 2012 Emulex + * Copyright (C) 2013 Emulex * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -63,8 +63,7 @@ #define MPU_EP_CONTROL 0 #define MPU_EP_SEMAPHORE_BE3 0xac #define MPU_EP_SEMAPHORE_XE201 0x400 -#define MPU_EP_SEMAPHORE(sc) \ - ((IS_BE(sc)) ? MPU_EP_SEMAPHORE_BE3 : MPU_EP_SEMAPHORE_XE201) +#define MPU_EP_SEMAPHORE_SH 0x94 #define PCICFG_INTR_CTRL 0xfc #define HOSTINTR_MASK (1 << 29) #define HOSTINTR_PFUNC_SHIFT 26 @@ -1998,6 +1997,79 @@ struct mbx_lowlevel_set_loopback_mode { } rsp; } params; }; +#define MAX_RESC_DESC 256 +#define RESC_DESC_SIZE 88 +#define ACTIVE_PROFILE 2 +#define NIC_RESC_DESC_TYPE_V0 0x41 +#define NIC_RESC_DESC_TYPE_V1 0x51 +/* OPCODE_COMMON_GET_FUNCTION_CONFIG */ +struct mbx_common_get_func_config { + struct mbx_hdr hdr; + union { + struct { + uint8_t rsvd; + uint8_t type; + uint16_t rsvd1; + } req; + struct { + uint32_t desc_count; + uint8_t resources[MAX_RESC_DESC * RESC_DESC_SIZE]; + } rsp; + } params; +}; + + +/* OPCODE_COMMON_GET_PROFILE_CONFIG */ + +struct mbx_common_get_profile_config { + struct mbx_hdr hdr; + union { + struct { + uint8_t rsvd; + uint8_t type; + uint16_t rsvd1; + } req; + struct { + uint32_t desc_count; + uint8_t resources[MAX_RESC_DESC * RESC_DESC_SIZE]; + } rsp; + } params; +}; + +struct oce_nic_resc_desc { + uint8_t desc_type; + uint8_t desc_len; + uint8_t rsvd1; + uint8_t flags; + uint8_t vf_num; + uint8_t rsvd2; + uint8_t pf_num; + uint8_t rsvd3; + uint16_t unicast_mac_count; + uint8_t rsvd4[6]; + uint16_t mcc_count; + uint16_t vlan_count; + uint16_t mcast_mac_count; + uint16_t txq_count; + uint16_t rq_count; + uint16_t rssq_count; + uint16_t lro_count; + uint16_t cq_count; + uint16_t toe_conn_count; + uint16_t eq_count; + uint32_t rsvd5; + uint32_t cap_flags; + uint8_t link_param; + uint8_t rsvd6[3]; + uint32_t bw_min; + uint32_t bw_max; + uint8_t acpi_params; + uint8_t wol_param; + uint16_t rsvd7; + uint32_t rsvd8[7]; + +}; + struct flash_file_hdr { uint8_t sign[52]; diff --git a/sys/dev/oce/oce_if.c b/sys/dev/oce/oce_if.c index 48cdb162563f..166828b1ed71 100644 --- a/sys/dev/oce/oce_if.c +++ b/sys/dev/oce/oce_if.c @@ -1,5 +1,5 @@ /*- - * Copyright (C) 2012 Emulex + * Copyright (C) 2013 Emulex * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -96,6 +96,7 @@ 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 void oce_get_config(POCE_SOFTC sc); static struct mbuf *oce_insert_vlan_tag(POCE_SOFTC sc, struct mbuf *m, boolean_t *complete); /* IP specific */ @@ -147,6 +148,7 @@ static uint32_t supportedDevices[] = { (PCI_VENDOR_EMULEX << 16) | PCI_PRODUCT_BE3, (PCI_VENDOR_EMULEX << 16) | PCI_PRODUCT_XE201, (PCI_VENDOR_EMULEX << 16) | PCI_PRODUCT_XE201_VF, + (PCI_VENDOR_EMULEX << 16) | PCI_PRODUCT_SH }; @@ -190,6 +192,9 @@ oce_probe(device_t dev) case PCI_PRODUCT_XE201_VF: sc->flags |= OCE_FLAGS_XE201; break; + case PCI_PRODUCT_SH: + sc->flags |= OCE_FLAGS_SH; + break; default: return ENXIO; } @@ -214,7 +219,6 @@ oce_attach(device_t dev) if (rc) return rc; - sc->rss_enable = oce_enable_rss; sc->tx_ring_size = OCE_TX_RING_SIZE; sc->rx_ring_size = OCE_RX_RING_SIZE; sc->rq_frag_size = OCE_RQ_BUF_SIZE; @@ -229,6 +233,8 @@ oce_attach(device_t dev) if (rc) goto pci_res_free; + oce_get_config(sc); + setup_max_queues_want(sc); rc = oce_setup_intr(sc); @@ -486,17 +492,18 @@ oce_multiq_start(struct ifnet *ifp, struct mbuf *m) int queue_index = 0; int status = 0; + if (!sc->link_status) + return ENXIO; + if ((m->m_flags & M_FLOWID) != 0) queue_index = m->m_pkthdr.flowid % sc->nwqs; - + wq = sc->wq[queue_index]; - if (TRY_LOCK(&wq->tx_lock)) { - status = oce_multiq_transmit(ifp, m, wq); - UNLOCK(&wq->tx_lock); - } else { - status = drbr_enqueue(ifp, wq->br, m); - } + LOCK(&wq->tx_lock); + status = oce_multiq_transmit(ifp, m, wq); + UNLOCK(&wq->tx_lock); + return status; } @@ -579,7 +586,7 @@ oce_setup_intr(POCE_SOFTC sc) int rc = 0, use_intx = 0; int vector = 0, req_vectors = 0; - if (sc->rss_enable) + if (is_rss_enabled(sc)) req_vectors = MAX((sc->nrqs - 1), sc->nwqs); else req_vectors = 1; @@ -778,7 +785,6 @@ oce_tx(POCE_SOFTC sc, struct mbuf **mpp, int wq_index) struct mbuf *m, *m_temp; struct oce_wq *wq = sc->wq[wq_index]; struct oce_packet_desc *pd; - uint32_t out; struct oce_nic_hdr_wqe *nichdr; struct oce_nic_frag_wqe *nicfrag; int num_wqes; @@ -816,20 +822,14 @@ oce_tx(POCE_SOFTC sc, struct mbuf **mpp, int wq_index) } } - out = wq->packets_out + 1; - if (out == OCE_WQ_PACKET_ARRAY_SIZE) - out = 0; - if (out == wq->packets_in) - return EBUSY; - - pd = &wq->pckts[wq->packets_out]; + pd = &wq->pckts[wq->pkt_desc_head]; retry: rc = bus_dmamap_load_mbuf_sg(wq->tag, pd->map, m, segs, &pd->nsegs, BUS_DMA_NOWAIT); if (rc == 0) { num_wqes = pd->nsegs + 1; - if (IS_BE(sc)) { + if (IS_BE(sc) || IS_SH(sc)) { /*Dummy required only for BE3.*/ if (num_wqes & 1) num_wqes++; @@ -838,10 +838,11 @@ oce_tx(POCE_SOFTC sc, struct mbuf **mpp, int wq_index) bus_dmamap_unload(wq->tag, pd->map); return EBUSY; } - + atomic_store_rel_int(&wq->pkt_desc_head, + (wq->pkt_desc_head + 1) % \ + OCE_WQ_PACKET_ARRAY_SIZE); bus_dmamap_sync(wq->tag, pd->map, BUS_DMASYNC_PREWRITE); pd->mbuf = m; - wq->packets_out = out; nichdr = RING_GET_PRODUCER_ITEM_VA(wq->ring, struct oce_nic_hdr_wqe); @@ -870,12 +871,12 @@ oce_tx(POCE_SOFTC sc, struct mbuf **mpp, int wq_index) nichdr->u0.s.lso = 1; nichdr->u0.s.lso_mss = m->m_pkthdr.tso_segsz; } - if (!IS_BE(sc)) + if (!IS_BE(sc) || !IS_SH(sc)) nichdr->u0.s.ipcs = 1; } RING_PUT(wq->ring, 1); - wq->ring->num_used++; + atomic_add_int(&wq->ring->num_used, 1); for (i = 0; i < pd->nsegs; i++) { nicfrag = @@ -887,7 +888,7 @@ oce_tx(POCE_SOFTC sc, struct mbuf **mpp, int wq_index) nicfrag->u0.s.frag_len = segs[i].ds_len; pd->wqe_idx = wq->ring->pidx; RING_PUT(wq->ring, 1); - wq->ring->num_used++; + atomic_add_int(&wq->ring->num_used, 1); } if (num_wqes > (pd->nsegs + 1)) { nicfrag = @@ -899,7 +900,7 @@ oce_tx(POCE_SOFTC sc, struct mbuf **mpp, int wq_index) nicfrag->u0.dw[3] = 0; pd->wqe_idx = wq->ring->pidx; RING_PUT(wq->ring, 1); - wq->ring->num_used++; + atomic_add_int(&wq->ring->num_used, 1); pd->nsegs++; } @@ -912,7 +913,7 @@ oce_tx(POCE_SOFTC sc, struct mbuf **mpp, int wq_index) 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; - OCE_WRITE_REG32(sc, db, PD_TXULP_DB, reg_value); + OCE_WRITE_REG32(sc, db, wq->db_offset, reg_value); } else if (rc == EFBIG) { if (retry_cnt == 0) { @@ -929,7 +930,7 @@ oce_tx(POCE_SOFTC sc, struct mbuf **mpp, int wq_index) return rc; else goto free_ret; - + return 0; free_ret: @@ -942,21 +943,14 @@ oce_tx(POCE_SOFTC sc, struct mbuf **mpp, int wq_index) static void oce_tx_complete(struct oce_wq *wq, uint32_t wqe_idx, uint32_t status) { - uint32_t in; struct oce_packet_desc *pd; POCE_SOFTC sc = (POCE_SOFTC) wq->parent; struct mbuf *m; - if (wq->packets_out == wq->packets_in) - device_printf(sc->dev, "WQ transmit descriptor missing\n"); - - in = wq->packets_in + 1; - if (in == OCE_WQ_PACKET_ARRAY_SIZE) - in = 0; - - pd = &wq->pckts[wq->packets_in]; - wq->packets_in = in; - wq->ring->num_used -= (pd->nsegs + 1); + pd = &wq->pckts[wq->pkt_desc_tail]; + atomic_store_rel_int(&wq->pkt_desc_tail, + (wq->pkt_desc_tail + 1) % OCE_WQ_PACKET_ARRAY_SIZE); + atomic_subtract_int(&wq->ring->num_used, pd->nsegs + 1); bus_dmamap_sync(wq->tag, pd->map, BUS_DMASYNC_POSTWRITE); bus_dmamap_unload(wq->tag, pd->map); @@ -964,6 +958,7 @@ oce_tx_complete(struct oce_wq *wq, uint32_t wqe_idx, uint32_t status) m_freem(m); pd->mbuf = NULL; + if (sc->ifp->if_drv_flags & IFF_DRV_OACTIVE) { if (wq->ring->num_used < (wq->ring->num_items / 2)) { sc->ifp->if_drv_flags &= ~(IFF_DRV_OACTIVE); @@ -1066,16 +1061,15 @@ oce_tx_task(void *arg, int npending) POCE_SOFTC sc = wq->parent; struct ifnet *ifp = sc->ifp; int rc = 0; - + #if __FreeBSD_version >= 800000 - if (TRY_LOCK(&wq->tx_lock)) { - rc = oce_multiq_transmit(ifp, NULL, wq); - if (rc) { - device_printf(sc->dev, - "TX[%d] restart failed\n", wq->queue_index); - } - UNLOCK(&wq->tx_lock); + LOCK(&wq->tx_lock); + rc = oce_multiq_transmit(ifp, NULL, wq); + if (rc) { + device_printf(sc->dev, + "TX[%d] restart failed\n", wq->queue_index); } + UNLOCK(&wq->tx_lock); #else oce_start(ifp); #endif @@ -1134,7 +1128,6 @@ oce_wq_handler(void *arg) struct oce_nic_tx_cqe *cqe; int num_cqes = 0; - LOCK(&wq->tx_lock); bus_dmamap_sync(cq->ring->dma.tag, cq->ring->dma.map, BUS_DMASYNC_POSTWRITE); cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring, struct oce_nic_tx_cqe); @@ -1158,7 +1151,6 @@ oce_wq_handler(void *arg) if (num_cqes) oce_arm_cq(sc, cq->cq_id, num_cqes, FALSE); - UNLOCK(&wq->tx_lock); return 0; } @@ -1233,7 +1225,7 @@ oce_rx(struct oce_rq *rq, uint32_t rqe_idx, struct oce_nic_rx_cqe *cqe) } /* Get vlan_tag value */ - if(IS_BE(sc)) + if(IS_BE(sc) || IS_SH(sc)) vtag = BSWAP_16(cqe->u0.s.vlan_tag); else vtag = cqe->u0.s.vlan_tag; @@ -1294,7 +1286,10 @@ oce_rx(struct oce_rq *rq, uint32_t rqe_idx, struct oce_nic_rx_cqe *cqe) m->m_pkthdr.rcvif = sc->ifp; #if __FreeBSD_version >= 800000 - m->m_pkthdr.flowid = rq->queue_index; + if (rq->queue_index) + m->m_pkthdr.flowid = (rq->queue_index - 1); + else + m->m_pkthdr.flowid = rq->queue_index; m->m_flags |= M_FLOWID; #endif /* This deternies if vlan tag is Valid */ @@ -1401,7 +1396,7 @@ oce_cqe_portid_valid(POCE_SOFTC sc, struct oce_nic_rx_cqe *cqe) struct oce_nic_rx_cqe_v1 *cqe_v1; int port_id = 0; - if (sc->be3_native && IS_BE(sc)) { + if (sc->be3_native && (IS_BE(sc) || IS_SH(sc))) { cqe_v1 = (struct oce_nic_rx_cqe_v1 *)cqe; port_id = cqe_v1->u0.s.port; if (sc->port_id != port_id) @@ -1547,7 +1542,6 @@ oce_rq_handler(void *arg) int num_cqes = 0, rq_buffers_used = 0; - LOCK(&rq->rx_lock); bus_dmamap_sync(cq->ring->dma.tag, cq->ring->dma.map, BUS_DMASYNC_POSTWRITE); cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring, struct oce_nic_rx_cqe); @@ -1594,8 +1588,6 @@ oce_rq_handler(void *arg) oce_alloc_rx_bufs(rq, (rq_buffers_used - 1)); } - UNLOCK(&rq->rx_lock); - return 0; } @@ -1889,7 +1881,7 @@ oce_local_timer(void *arg) oce_tx_restart(sc, sc->wq[i]); /* calculate and set the eq delay for optimal interrupt rate */ - if (IS_BE(sc)) + if (IS_BE(sc) || IS_SH(sc)) oce_eqd_set_periodic(sc); callout_reset(&sc->timer, hz, oce_local_timer, sc); @@ -2080,38 +2072,22 @@ oce_mq_handler(void *arg) static void setup_max_queues_want(POCE_SOFTC sc) { - int max_rss = 0; - /* Check if it is FLEX machine. Is so dont use RSS */ if ((sc->function_mode & FNM_FLEX10_MODE) || (sc->function_mode & FNM_UMC_MODE) || (sc->function_mode & FNM_VNIC_MODE) || - (!sc->rss_enable) || + (!is_rss_enabled(sc)) || (sc->flags & OCE_FLAGS_BE2)) { sc->nrqs = 1; sc->nwqs = 1; - sc->rss_enable = 0; - } else { - /* For multiq, our deisgn is to have TX rings equal to - RSS rings. So that we can pair up one RSS ring and TX - to a single intr, which improves CPU cache efficiency. - */ - if (IS_BE(sc) && (!sc->be3_native)) - max_rss = OCE_LEGACY_MODE_RSS; - else - max_rss = OCE_MAX_RSS; - - sc->nrqs = MIN(OCE_NCPUS, max_rss) + 1; /* 1 for def RX */ - sc->nwqs = MIN(OCE_NCPUS, max_rss); } - } static void update_queues_got(POCE_SOFTC sc) { - if (sc->rss_enable) { + if (is_rss_enabled(sc)) { sc->nrqs = sc->intr_count + 1; sc->nwqs = sc->intr_count; } else { @@ -2196,3 +2172,31 @@ oce_tx_asic_stall_verify(POCE_SOFTC sc, struct mbuf *m) } return FALSE; } + +static void +oce_get_config(POCE_SOFTC sc) +{ + int rc = 0; + uint32_t max_rss = 0; + + if ((IS_BE(sc) || IS_SH(sc)) && (!sc->be3_native)) + max_rss = OCE_LEGACY_MODE_RSS; + else + max_rss = OCE_MAX_RSS; + + if (!IS_BE(sc)) { + rc = oce_get_func_config(sc); + if (rc) { + sc->nwqs = OCE_MAX_WQ; + sc->nrssqs = max_rss; + sc->nrqs = sc->nrssqs + 1; + } + } + else { + rc = oce_get_profile_config(sc); + sc->nrssqs = max_rss; + sc->nrqs = sc->nrssqs + 1; + if (rc) + sc->nwqs = OCE_MAX_WQ; + } +} diff --git a/sys/dev/oce/oce_if.h b/sys/dev/oce/oce_if.h index ee684bd8f13c..83de17ba5342 100644 --- a/sys/dev/oce/oce_if.h +++ b/sys/dev/oce/oce_if.h @@ -1,5 +1,5 @@ /*- - * Copyright (C) 2012 Emulex + * Copyright (C) 2013 Emulex * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -97,11 +97,21 @@ #define PCI_PRODUCT_BE3 0x0710 /* BE3 network adapter */ #define PCI_PRODUCT_XE201 0xe220 /* XE201 network adapter */ #define PCI_PRODUCT_XE201_VF 0xe228 /* XE201 with VF in Lancer */ +#define PCI_PRODUCT_SH 0x0720 /* Skyhawk network adapter */ #define IS_BE(sc) (((sc->flags & OCE_FLAGS_BE3) | \ (sc->flags & OCE_FLAGS_BE2))? 1:0) +#define IS_BE3(sc) (sc->flags & OCE_FLAGS_BE3) +#define IS_BE2(sc) (sc->flags & OCE_FLAGS_BE2) #define IS_XE201(sc) ((sc->flags & OCE_FLAGS_XE201) ? 1:0) #define HAS_A0_CHIP(sc) ((sc->flags & OCE_FLAGS_HAS_A0_CHIP) ? 1:0) +#define IS_SH(sc) ((sc->flags & OCE_FLAGS_SH) ? 1 : 0) + +#define is_be_mode_mc(sc) ((sc->function_mode & FNM_FLEX10_MODE) || \ + (sc->function_mode & FNM_UMC_MODE) || \ + (sc->function_mode & FNM_VNIC_MODE)) +#define OCE_FUNCTION_CAPS_SUPER_NIC 0x40 +#define IS_PROFILE_SUPER_NIC(sc) (sc->function_caps & OCE_FUNCTION_CAPS_SUPER_NIC) /* proportion Service Level Interface queues */ @@ -113,8 +123,9 @@ extern int mp_ncpus; /* system's total active cpu cores */ #define OCE_NCPUS mp_ncpus /* This should be powers of 2. Like 2,4,8 & 16 */ -#define OCE_MAX_RSS 4 /* TODO: 8*/ +#define OCE_MAX_RSS 8 #define OCE_LEGACY_MODE_RSS 4 /* For BE3 Legacy mode*/ +#define is_rss_enabled(sc) ((sc->function_caps & FNC_RSS) && !is_be_mode_mc(sc)) #define OCE_MIN_RQ 1 #define OCE_MIN_WQ 1 @@ -149,6 +160,7 @@ extern int mp_ncpus; /* system's total active cpu cores */ #define RSS_ENABLE_IPV6 0x4 #define RSS_ENABLE_TCP_IPV6 0x8 +#define INDIRECTION_TABLE_ENTRIES 128 /* flow control definitions */ #define OCE_FC_NONE 0x00000000 @@ -194,6 +206,9 @@ extern int mp_ncpus; /* system's total active cpu cores */ for (i = 0, wq = sc->wq[0]; i < sc->nwqs; i++, wq = sc->wq[i]) #define for_all_rq_queues(sc, rq, i) \ for (i = 0, rq = sc->rq[0]; i < sc->nrqs; i++, rq = sc->rq[i]) +#define for_all_rss_queues(sc, rq, i) \ + for (i = 0, rq = sc->rq[i + 1]; i < (sc->nrqs - 1); \ + i++, rq = sc->rq[i + 1]) #define for_all_evnt_queues(sc, eq, i) \ for (i = 0, eq = sc->eq[0]; i < sc->neqs; i++, eq = sc->eq[i]) #define for_all_cq_queues(sc, cq, i) \ @@ -671,8 +686,8 @@ struct oce_wq { 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 pkt_desc_tail; + uint32_t pkt_desc_head; uint32_t wqm_used; boolean_t resched; uint32_t wq_free; @@ -685,6 +700,7 @@ struct oce_wq { struct oce_tx_queue_stats tx_stats; struct buf_ring *br; struct task txtask; + uint32_t db_offset; }; struct rq_config { @@ -765,6 +781,7 @@ struct link_status { #define OCE_FLAGS_BE3 0x00000200 #define OCE_FLAGS_XE201 0x00000400 #define OCE_FLAGS_BE2 0x00000800 +#define OCE_FLAGS_SH 0x00001000 #define OCE_DEV_BE2_CFG_BAR 1 #define OCE_DEV_CFG_BAR 0 @@ -833,11 +850,11 @@ typedef struct oce_softc { uint32_t ncqs; uint32_t nrqs; uint32_t nwqs; + uint32_t nrssqs; uint32_t tx_ring_size; uint32_t rx_ring_size; uint32_t rq_frag_size; - uint32_t rss_enable; uint32_t if_id; /* interface ID */ uint32_t nifs; /* number of adapter interfaces, 0 or 1 */ @@ -873,37 +890,47 @@ typedef struct oce_softc { * BE3: accesses three BAR spaces (CFG, CSR, DB) * Lancer: accesses one BAR space (CFG) **************************************************/ -#define OCE_READ_REG32(sc, space, o) \ +#define OCE_READ_CSR_MPU(sc, space, o) \ ((IS_BE(sc)) ? (bus_space_read_4((sc)->space##_btag, \ - (sc)->space##_bhandle,o)) \ - : (bus_space_read_4((sc)->devcfg_btag, \ - (sc)->devcfg_bhandle,o))) + (sc)->space##_bhandle,o)) \ + : (bus_space_read_4((sc)->devcfg_btag, \ + (sc)->devcfg_bhandle,o))) +#define OCE_READ_REG32(sc, space, o) \ + ((IS_BE(sc) || IS_SH(sc)) ? (bus_space_read_4((sc)->space##_btag, \ + (sc)->space##_bhandle,o)) \ + : (bus_space_read_4((sc)->devcfg_btag, \ + (sc)->devcfg_bhandle,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)->devcfg_btag, \ - (sc)->devcfg_bhandle,o))) + ((IS_BE(sc) || IS_SH(sc)) ? (bus_space_read_2((sc)->space##_btag, \ + (sc)->space##_bhandle,o)) \ + : (bus_space_read_2((sc)->devcfg_btag, \ + (sc)->devcfg_bhandle,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)->devcfg_btag, \ - (sc)->devcfg_bhandle,o))) + ((IS_BE(sc) || IS_SH(sc)) ? (bus_space_read_1((sc)->space##_btag, \ + (sc)->space##_bhandle,o)) \ + : (bus_space_read_1((sc)->devcfg_btag, \ + (sc)->devcfg_bhandle,o))) -#define OCE_WRITE_REG32(sc, space, o, v) \ +#define OCE_WRITE_CSR_MPU(sc, space, o, v) \ ((IS_BE(sc)) ? (bus_space_write_4((sc)->space##_btag, \ (sc)->space##_bhandle,o,v)) \ - : (bus_space_write_4((sc)->devcfg_btag, \ - (sc)->devcfg_bhandle,o,v))) + : (bus_space_write_4((sc)->devcfg_btag, \ + (sc)->devcfg_bhandle,o,v))) +#define OCE_WRITE_REG32(sc, space, o, v) \ + ((IS_BE(sc) || IS_SH(sc)) ? (bus_space_write_4((sc)->space##_btag, \ + (sc)->space##_bhandle,o,v)) \ + : (bus_space_write_4((sc)->devcfg_btag, \ + (sc)->devcfg_bhandle,o,v))) #define OCE_WRITE_REG16(sc, space, o, v) \ - ((IS_BE(sc)) ? (bus_space_write_2((sc)->space##_btag, \ + ((IS_BE(sc) || IS_SH(sc)) ? (bus_space_write_2((sc)->space##_btag, \ (sc)->space##_bhandle,o,v)) \ - : (bus_space_write_2((sc)->devcfg_btag, \ - (sc)->devcfg_bhandle,o,v))) + : (bus_space_write_2((sc)->devcfg_btag, \ + (sc)->devcfg_bhandle,o,v))) #define OCE_WRITE_REG8(sc, space, o, v) \ - ((IS_BE(sc)) ? (bus_space_write_1((sc)->space##_btag, \ + ((IS_BE(sc) || IS_SH(sc)) ? (bus_space_write_1((sc)->space##_btag, \ (sc)->space##_bhandle,o,v)) \ - : (bus_space_write_1((sc)->devcfg_btag, \ - (sc)->devcfg_bhandle,o,v))) + : (bus_space_write_1((sc)->devcfg_btag, \ + (sc)->devcfg_bhandle,o,v))) /*********************************************************** @@ -1024,6 +1051,8 @@ int oce_mbox_cq_create(struct oce_cq *cq, uint32_t ncoalesce, 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); +int oce_get_profile_config(POCE_SOFTC sc); +int oce_get_func_config(POCE_SOFTC sc); void mbx_common_req_hdr_init(struct mbx_hdr *hdr, uint8_t dom, uint8_t port, @@ -1072,6 +1101,9 @@ extern uint32_t oce_max_rsp_handled; /* max responses */ #define LE_64(x) htole64(x) #define LE_32(x) htole32(x) #define LE_16(x) htole16(x) +#define HOST_64(x) le64toh(x) +#define HOST_32(x) le32toh(x) +#define HOST_16(x) le16toh(x) #define DW_SWAP(x, l) #define IS_ALIGNED(x,a) ((x % a) == 0) #define ADDR_HI(x) ((uint32_t)((uint64_t)(x) >> 32)) @@ -1104,6 +1136,16 @@ static inline uint32_t oce_highbit(uint32_t x) return 0; } +static inline int MPU_EP_SEMAPHORE(POCE_SOFTC sc) +{ + if (IS_BE(sc)) + return MPU_EP_SEMAPHORE_BE3; + else if (IS_SH(sc)) + return MPU_EP_SEMAPHORE_SH; + else + return MPU_EP_SEMAPHORE_XE201; +} + #define TRANSCEIVER_DATA_NUM_ELE 64 #define TRANSCEIVER_DATA_SIZE 256 #define TRANSCEIVER_A0_SIZE 128 diff --git a/sys/dev/oce/oce_mbox.c b/sys/dev/oce/oce_mbox.c index 2db5934203df..9aab595e5629 100644 --- a/sys/dev/oce/oce_mbox.c +++ b/sys/dev/oce/oce_mbox.c @@ -1,5 +1,5 @@ /*- - * Copyright (C) 2012 Emulex + * Copyright (C) 2013 Emulex * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -727,12 +727,14 @@ oce_rss_itbl_init(POCE_SOFTC sc, struct mbx_config_nic_rss *fwcmd) { int i = 0, j = 0, rc = 0; uint8_t *tbl = fwcmd->params.req.cputable; + struct oce_rq *rq = NULL; - for (j = 0; j < sc->nrqs; j++) { - if (sc->rq[j]->cfg.is_rss_queue) { - tbl[i] = sc->rq[j]->rss_cpuid; - i = i + 1; + for (j = 0; j < INDIRECTION_TABLE_ENTRIES ; j += (sc->nrqs - 1)) { + for_all_rss_queues(sc, rq, i) { + if ((j + i) >= INDIRECTION_TABLE_ENTRIES) + break; + tbl[j + i] = rq->rss_cpuid; } } if (i == 0) { @@ -766,7 +768,7 @@ oce_config_nic_rss(POCE_SOFTC sc, uint32_t if_id, uint16_t enable_rss) bzero(&mbx, sizeof(struct oce_mbx)); - if (IS_XE201(sc)) { + if (IS_XE201(sc) || IS_SH(sc)) { version = OCE_MBX_VER_V1; fwcmd->params.req.enable_rss = RSS_ENABLE_UDP_IPV4 | RSS_ENABLE_UDP_IPV6; @@ -1674,8 +1676,11 @@ oce_mbox_create_wq(struct oce_wq *wq) if (IS_XE201(sc)) { version = OCE_MBX_VER_V1; fwcmd->params.req.if_id = sc->if_id; - } else - version = OCE_MBX_VER_V0; + } else if(IS_BE(sc)) + IS_PROFILE_SUPER_NIC(sc) ? (version = OCE_MBX_VER_V2) + : (version = OCE_MBX_VER_V0); + else + version = OCE_MBX_VER_V2; mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, MBX_SUBSYSTEM_NIC, @@ -1703,6 +1708,10 @@ oce_mbox_create_wq(struct oce_wq *wq) goto error; } wq->wq_id = LE_16(fwcmd->params.rsp.wq_id); + if (version == OCE_MBX_VER_V2) + wq->db_offset = LE_32(fwcmd->params.rsp.db_offset); + else + wq->db_offset = PD_TXULP_DB; error: return rc; @@ -1874,7 +1883,7 @@ oce_mbox_read_transrecv_data(POCE_SOFTC sc, uint32_t page_num) /* command post */ rc = oce_mbox_post(sc, &mbx, NULL); if (!rc) - rc = fwcmd->hdr.u0.rsp.status; + rc = fwcmd->hdr.u0.rsp.status; if (rc) { device_printf(sc->dev,"%s failed - cmd status: %d\n", __FUNCTION__, rc); @@ -1894,6 +1903,7 @@ oce_mbox_read_transrecv_data(POCE_SOFTC sc, uint32_t page_num) TRANSCEIVER_A2_SIZE); } error: + oce_dma_free(sc, &dma); return rc; } @@ -1935,10 +1945,193 @@ oce_mbox_eqd_modify_periodic(POCE_SOFTC sc, struct oce_set_eqd *set_eqd, rc = oce_mbox_post(sc, &mbx, NULL); if (!rc) - rc = fwcmd->hdr.u0.rsp.status; + rc = fwcmd->hdr.u0.rsp.status; if (rc) device_printf(sc->dev,"%s failed - cmd status: %d\n", __FUNCTION__, rc); } +int +oce_get_profile_config(POCE_SOFTC sc) +{ + struct oce_mbx mbx; + struct mbx_common_get_profile_config *fwcmd; + int rc = 0; + int version = 0; + struct oce_mq_sge *sgl; + OCE_DMA_MEM dma; + uint32_t desc_count = 0; + struct oce_nic_resc_desc *nic_desc = NULL; + int i; + boolean_t nic_desc_valid = FALSE; + if (IS_BE2(sc)) + return -1; + + /* Allocate DMA mem*/ + if (oce_dma_alloc(sc, sizeof(struct mbx_common_get_profile_config), + &dma, 0)) + return ENOMEM; + + /* Initialize MODIFY_EQ_DELAY ioctl header */ + fwcmd = OCE_DMAPTR(&dma, struct mbx_common_get_profile_config); + bzero(fwcmd, sizeof(struct mbx_common_get_profile_config)); + + if (IS_BE3(sc)) + version = OCE_MBX_VER_V1; + else + version = OCE_MBX_VER_V0; + + bzero(&mbx, sizeof(struct oce_mbx)); + mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, + MBX_SUBSYSTEM_COMMON, + OPCODE_COMMON_GET_PROFILE_CONFIG, + MBX_TIMEOUT_SEC, + sizeof(struct mbx_common_get_profile_config), + version); + /* fill rest of mbx */ + mbx.u0.s.embedded = 0; + mbx.payload_length = sizeof(struct mbx_common_get_profile_config); + 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.type = ACTIVE_PROFILE; + + /* 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; + } + + nic_desc = (struct oce_nic_resc_desc *) fwcmd->params.rsp.resources; + desc_count = HOST_32(fwcmd->params.rsp.desc_count); + for (i = 0; i < desc_count; i++) { + if ((nic_desc->desc_type == NIC_RESC_DESC_TYPE_V0) || + (nic_desc->desc_type == NIC_RESC_DESC_TYPE_V1)) { + nic_desc_valid = TRUE; + break; + } + nic_desc = (struct oce_nic_resc_desc *) \ + ((char *)nic_desc + nic_desc->desc_len); + } + if (!nic_desc_valid) { + rc = -1; + goto error; + } + else { + sc->nwqs = HOST_32(nic_desc->txq_count); + if (sc->nwqs) + sc->nwqs = MIN(sc->nwqs, OCE_MAX_WQ); + else + sc->nwqs = OCE_MAX_WQ; + + } +error: + oce_dma_free(sc, &dma); + return rc; + +} + +int +oce_get_func_config(POCE_SOFTC sc) +{ + struct oce_mbx mbx; + struct mbx_common_get_func_config *fwcmd; + int rc = 0; + int version = 0; + struct oce_mq_sge *sgl; + OCE_DMA_MEM dma; + uint32_t desc_count = 0; + struct oce_nic_resc_desc *nic_desc = NULL; + int i; + boolean_t nic_desc_valid = FALSE; + uint32_t max_rss = 0; + + if ((IS_BE(sc) || IS_SH(sc)) && (!sc->be3_native)) + max_rss = OCE_LEGACY_MODE_RSS; + else + max_rss = OCE_MAX_RSS; + + /* Allocate DMA mem*/ + if (oce_dma_alloc(sc, sizeof(struct mbx_common_get_func_config), + &dma, 0)) + return ENOMEM; + + /* Initialize MODIFY_EQ_DELAY ioctl header */ + fwcmd = OCE_DMAPTR(&dma, struct mbx_common_get_func_config); + bzero(fwcmd, sizeof(struct mbx_common_get_func_config)); + + if (IS_SH(sc)) + version = OCE_MBX_VER_V1; + else + version = OCE_MBX_VER_V0; + + bzero(&mbx, sizeof(struct oce_mbx)); + mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, + MBX_SUBSYSTEM_COMMON, + OPCODE_COMMON_GET_FUNCTION_CONFIG, + MBX_TIMEOUT_SEC, + sizeof(struct mbx_common_get_func_config), + version); + /* fill rest of mbx */ + mbx.u0.s.embedded = 0; + mbx.payload_length = sizeof(struct mbx_common_get_func_config); + 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); + + /* 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; + } + + nic_desc = (struct oce_nic_resc_desc *) fwcmd->params.rsp.resources; + desc_count = HOST_32(fwcmd->params.rsp.desc_count); + for (i = 0; i < desc_count; i++) { + if ((nic_desc->desc_type == NIC_RESC_DESC_TYPE_V0) || + (nic_desc->desc_type == NIC_RESC_DESC_TYPE_V1)) { + nic_desc_valid = TRUE; + break; + } + nic_desc = (struct oce_nic_resc_desc *) \ + ((char *)nic_desc + nic_desc->desc_len); + } + if (!nic_desc_valid) { + rc = -1; + goto error; + } + else { + sc->nwqs = HOST_32(nic_desc->txq_count); + if (sc->nwqs) + sc->nwqs = MIN(sc->nwqs, OCE_MAX_WQ); + else + sc->nwqs = OCE_MAX_WQ; + + sc->nrssqs = HOST_32(nic_desc->rssq_count); + if (sc->nrssqs) + sc->nrssqs = MIN(sc->nrssqs, max_rss); + else + sc->nrssqs = max_rss; + sc->nrqs = sc->nrssqs + 1; /* 1 for def RX */; + } +error: + oce_dma_free(sc, &dma); + return rc; + +} diff --git a/sys/dev/oce/oce_queue.c b/sys/dev/oce/oce_queue.c index 82972eeb6e20..fbf68fde3d1e 100644 --- a/sys/dev/oce/oce_queue.c +++ b/sys/dev/oce/oce_queue.c @@ -1,5 +1,5 @@ /*- - * Copyright (C) 2012 Emulex + * Copyright (C) 2013 Emulex * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -106,7 +106,7 @@ oce_queue_init_all(POCE_SOFTC sc) for_all_rq_queues(sc, rq, i) { sc->rq[i] = oce_rq_init(sc, sc->rx_ring_size, sc->rq_frag_size, OCE_MAX_JUMBO_FRAME_SIZE, - (i == 0) ? 0 : sc->rss_enable); + (i == 0) ? 0 : is_rss_enabled(sc)); if (!sc->rq[i]) goto error; } @@ -1225,7 +1225,7 @@ oce_start_rx(POCE_SOFTC sc) DELAY(1); /* RSS config */ - if (sc->rss_enable) { + if (is_rss_enabled(sc)) { rc = oce_config_nic_rss(sc, (uint8_t) sc->if_id, RSS_ENABLE); if (rc) goto error; diff --git a/sys/dev/oce/oce_sysctl.c b/sys/dev/oce/oce_sysctl.c index 66299418f118..7dad6195cb27 100644 --- a/sys/dev/oce/oce_sysctl.c +++ b/sys/dev/oce/oce_sysctl.c @@ -1,5 +1,5 @@ /*- - * Copyright (C) 2012 Emulex + * Copyright (C) 2013 Emulex * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -140,7 +140,7 @@ oce_add_sysctls(POCE_SOFTC sc) stats_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "stats", CTLFLAG_RD, NULL, "Ethernet Statistics"); - if (IS_BE(sc)) + if (IS_BE(sc) || IS_SH(sc)) oce_add_stats_sysctls_be3(sc, ctx, stats_node); else oce_add_stats_sysctls_xe201(sc, ctx, stats_node); @@ -223,7 +223,7 @@ oce_sys_fwupgrade(SYSCTL_HANDLER_ARGS) return ENOENT; } - if (IS_BE(sc)) { + if (IS_BE(sc) || IS_SH(sc)) { if ((sc->flags & OCE_FLAGS_BE2)) { device_printf(sc->dev, "Flashing not supported for BE2 yet.\n"); @@ -1270,7 +1270,7 @@ oce_stats_init(POCE_SOFTC sc) { int rc = 0, sz; - if (IS_BE(sc)) { + if (IS_BE(sc) || IS_SH(sc)) { if (sc->flags & OCE_FLAGS_BE2) sz = sizeof(struct mbx_get_nic_stats_v0); else @@ -1298,7 +1298,7 @@ oce_refresh_nic_stats(POCE_SOFTC sc) { int rc = 0, reset = 0; - if (IS_BE(sc)) { + if (IS_BE(sc) || IS_SH(sc)) { if (sc->flags & OCE_FLAGS_BE2) { rc = oce_mbox_get_nic_stats_v0(sc, &sc->stats_mem); if (!rc) diff --git a/sys/dev/oce/oce_util.c b/sys/dev/oce/oce_util.c index b71c02d522d7..eeca2f23bd35 100644 --- a/sys/dev/oce/oce_util.c +++ b/sys/dev/oce/oce_util.c @@ -1,5 +1,5 @@ /*- - * Copyright (C) 2012 Emulex + * Copyright (C) 2013 Emulex * All rights reserved. * * Redistribution and use in source and binary forms, with or without