From dc0915ff39cbb6bf86be22b6636d069196119d3e Mon Sep 17 00:00:00 2001 From: delphij Date: Mon, 30 Jun 2014 16:16:35 +0000 Subject: [PATCH] MFS r267944 (MFC r258941,267839): Apply vendor improvements to oce(4) driver: - Add support to 20Gbps, 25Gbps, 40Gbps devices; - Add support to control adaptive interrupt coalescing (AIC) via sysctl; - Improve support of BE3 devices; - Big endian support fixes; Many thanks to Emulex for their continued support of FreeBSD. Submitted by: Venkata Duvvuru Approved by: re (gjb) git-svn-id: svn://svn.freebsd.org/base/releng/9.3@268044 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f --- sys/dev/oce/oce_hw.c | 6 +----- sys/dev/oce/oce_hw.h | 41 ++++++++++++++++++++++++++++++---------- sys/dev/oce/oce_if.c | 38 +++++++++++++++++++++++++------------ sys/dev/oce/oce_if.h | 18 ++++++++---------- sys/dev/oce/oce_mbox.c | 23 ++++++++++++++-------- sys/dev/oce/oce_sysctl.c | 34 +++++++++++++++++++++++++++++++++ 6 files changed, 115 insertions(+), 45 deletions(-) diff --git a/sys/dev/oce/oce_hw.c b/sys/dev/oce/oce_hw.c index 7fc16b838..8d292880e 100644 --- a/sys/dev/oce/oce_hw.c +++ b/sys/dev/oce/oce_hw.c @@ -487,11 +487,7 @@ oce_hw_start(POCE_SOFTC sc) if_link_state_change(sc->ifp, LINK_STATE_DOWN); } - if (link.mac_speed > 0 && link.mac_speed < 5) - sc->link_speed = link.mac_speed; - else - sc->link_speed = 0; - + sc->link_speed = link.phys_port_speed; sc->qos_link_speed = (uint32_t )link.qos_link_speed * 10; rc = oce_start_mq(sc->mq); diff --git a/sys/dev/oce/oce_hw.h b/sys/dev/oce/oce_hw.h index 9f1a92a37..1ad3f7889 100644 --- a/sys/dev/oce/oce_hw.h +++ b/sys/dev/oce/oce_hw.h @@ -1023,7 +1023,7 @@ struct mbx_hdr { #define OCE_MBX_ADDL_STATUS(_MHDR) ((_MHDR)->u0.rsp.additional_status) #define OCE_MBX_STATUS(_MHDR) ((_MHDR)->u0.rsp.status) -/* [05] OPCODE_COMMON_QUERY_LINK_CONFIG */ +/* [05] OPCODE_COMMON_QUERY_LINK_CONFIG_V1 */ struct mbx_query_common_link_config { struct mbx_hdr hdr; union { @@ -1032,16 +1032,37 @@ struct mbx_query_common_link_config { } req; struct { - /* dw 0 */ - uint8_t physical_port; - uint8_t mac_duplex; - uint8_t mac_speed; - uint8_t mac_fault; - /* dw 1 */ - uint8_t mgmt_mac_duplex; - uint8_t mgmt_mac_speed; + #ifdef _BIG_ENDIAN + uint32_t physical_port_fault:8; + uint32_t physical_port_speed:8; + uint32_t link_duplex:8; + uint32_t pt:2; + uint32_t port_number:6; + + uint16_t qos_link_speed; + uint16_t rsvd0; + + uint32_t rsvd1:21; + uint32_t phys_fcv:1; + uint32_t phys_rxf:1; + uint32_t phys_txf:1; + uint32_t logical_link_status:8; + #else + uint32_t port_number:6; + uint32_t pt:2; + uint32_t link_duplex:8; + uint32_t physical_port_speed:8; + uint32_t physical_port_fault:8; + + uint16_t rsvd0; uint16_t qos_link_speed; - uint32_t logical_link_status; + + uint32_t logical_link_status:8; + uint32_t phys_txf:1; + uint32_t phys_rxf:1; + uint32_t phys_fcv:1; + uint32_t rsvd1:21; + #endif } rsp; } params; }; diff --git a/sys/dev/oce/oce_if.c b/sys/dev/oce/oce_if.c index bf848725e..350921c70 100644 --- a/sys/dev/oce/oce_if.c +++ b/sys/dev/oce/oce_if.c @@ -828,6 +828,21 @@ oce_media_status(struct ifnet *ifp, struct ifmediareq *req) req->ifm_active |= IFM_10G_SR | IFM_FDX; sc->speed = 10000; break; + case 5: /* 20 Gbps */ + req->ifm_active |= IFM_10G_SR | IFM_FDX; + sc->speed = 20000; + break; + case 6: /* 25 Gbps */ + req->ifm_active |= IFM_10G_SR | IFM_FDX; + sc->speed = 25000; + break; + case 7: /* 40 Gbps */ + req->ifm_active |= IFM_40G_SR4 | IFM_FDX; + sc->speed = 40000; + break; + default: + sc->speed = 0; + break; } return; @@ -1940,7 +1955,6 @@ done: /* Is there atleast one eq that needs to be modified? */ if(num) oce_mbox_eqd_modify_periodic(sc, set_eqd, num); - } static void oce_detect_hw_error(POCE_SOFTC sc) @@ -2140,11 +2154,6 @@ process_link_state(POCE_SOFTC sc, struct oce_async_cqe_link_state *acqe) sc->link_status = ASYNC_EVENT_LINK_DOWN; if_link_state_change(sc->ifp, LINK_STATE_DOWN); } - - /* Update speed */ - sc->link_speed = acqe->u0.s.speed; - sc->qos_link_speed = (uint32_t) acqe->u0.s.qos_link_speed * 10; - } @@ -2218,13 +2227,16 @@ setup_max_queues_want(POCE_SOFTC sc) (sc->function_mode & FNM_UMC_MODE) || (sc->function_mode & FNM_VNIC_MODE) || (!is_rss_enabled(sc)) || - (sc->flags & OCE_FLAGS_BE2)) { + IS_BE2(sc)) { sc->nrqs = 1; sc->nwqs = 1; } else { sc->nrqs = MIN(OCE_NCPUS, sc->nrssqs) + 1; sc->nwqs = MIN(OCE_NCPUS, sc->nrssqs); } + + if (IS_BE2(sc) && is_rss_enabled(sc)) + sc->nrqs = MIN(OCE_NCPUS, sc->nrssqs) + 1; } @@ -2238,6 +2250,9 @@ update_queues_got(POCE_SOFTC sc) sc->nrqs = 1; sc->nwqs = 1; } + + if (IS_BE2(sc)) + sc->nwqs = 1; } static int @@ -2329,18 +2344,17 @@ oce_get_config(POCE_SOFTC sc) max_rss = OCE_MAX_RSS; if (!IS_BE(sc)) { - rc = oce_get_func_config(sc); + rc = oce_get_profile_config(sc, max_rss); if (rc) { sc->nwqs = OCE_MAX_WQ; sc->nrssqs = max_rss; sc->nrqs = sc->nrssqs + 1; } } - else { - rc = oce_get_profile_config(sc); + else { /* For BE3 don't rely on fw for determining the resources */ sc->nrssqs = max_rss; sc->nrqs = sc->nrssqs + 1; - if (rc) - sc->nwqs = OCE_MAX_WQ; + sc->nwqs = OCE_MAX_WQ; + sc->max_vlans = MAX_VLANFILTER_SIZE; } } diff --git a/sys/dev/oce/oce_if.h b/sys/dev/oce/oce_if.h index 87d57b4d9..259a9ed01 100644 --- a/sys/dev/oce/oce_if.h +++ b/sys/dev/oce/oce_if.h @@ -759,14 +759,9 @@ struct oce_rq { }; 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; + uint8_t phys_port_speed; + uint8_t logical_link_status; uint16_t qos_link_speed; - uint32_t logical_link_status; }; @@ -882,8 +877,8 @@ typedef struct oce_softc { uint8_t hw_error; uint16_t qnq_debug_event; uint16_t qnqid; - uint16_t pvid; - uint16_t max_vlans; + uint32_t pvid; + uint32_t max_vlans; } OCE_SOFTC, *POCE_SOFTC; @@ -1055,7 +1050,7 @@ 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_profile_config(POCE_SOFTC sc, uint32_t max_rss); int oce_get_func_config(POCE_SOFTC sc); void mbx_common_req_hdr_init(struct mbx_hdr *hdr, uint8_t dom, @@ -1099,6 +1094,9 @@ extern uint32_t oce_max_rsp_handled; /* max responses */ #define OCE_ONE_PORT_EXT_LOOPBACK 0x2 #define OCE_NO_LOOPBACK 0xff +#undef IFM_40G_SR4 +#define IFM_40G_SR4 28 + #define atomic_inc_32(x) atomic_add_32(x, 1) #define atomic_dec_32(x) atomic_subtract_32(x, 1) diff --git a/sys/dev/oce/oce_mbox.c b/sys/dev/oce/oce_mbox.c index fbb24be6b..f3f772394 100644 --- a/sys/dev/oce/oce_mbox.c +++ b/sys/dev/oce/oce_mbox.c @@ -935,7 +935,7 @@ oce_get_link_status(POCE_SOFTC sc, struct link_status *link) bzero(&mbx, sizeof(struct oce_mbx)); - IS_XE201(sc) ? (version = OCE_MBX_VER_V1) : (version = OCE_MBX_VER_V0); + IS_BE2(sc) ? (version = OCE_MBX_VER_V0) : (version = OCE_MBX_VER_V1); fwcmd = (struct mbx_query_common_link_config *)&mbx.payload; mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, @@ -961,9 +961,9 @@ oce_get_link_status(POCE_SOFTC sc, struct link_status *link) goto error; } /* interpret response */ - bcopy(&fwcmd->params.rsp, link, sizeof(struct link_status)); - link->logical_link_status = HOST_32(link->logical_link_status); - link->qos_link_speed = HOST_16(link->qos_link_speed); + link->qos_link_speed = HOST_16(fwcmd->params.rsp.qos_link_speed); + link->phys_port_speed = fwcmd->params.rsp.physical_port_speed; + link->logical_link_status = fwcmd->params.rsp.logical_link_status; error: return rc; } @@ -2025,7 +2025,7 @@ oce_mbox_eqd_modify_periodic(POCE_SOFTC sc, struct oce_set_eqd *set_eqd, } int -oce_get_profile_config(POCE_SOFTC sc) +oce_get_profile_config(POCE_SOFTC sc, uint32_t max_rss) { struct oce_mbx mbx; struct mbx_common_get_profile_config *fwcmd; @@ -2050,7 +2050,7 @@ oce_get_profile_config(POCE_SOFTC sc) fwcmd = OCE_DMAPTR(&dma, struct mbx_common_get_profile_config); bzero(fwcmd, sizeof(struct mbx_common_get_profile_config)); - if (IS_BE3(sc)) + if (!IS_XE201(sc)) version = OCE_MBX_VER_V1; else version = OCE_MBX_VER_V0; @@ -2102,13 +2102,20 @@ oce_get_profile_config(POCE_SOFTC sc) goto error; } else { - sc->max_vlans = nic_desc->vlan_count; - sc->nwqs = HOST_32(nic_desc->txq_count); + sc->max_vlans = HOST_16(nic_desc->vlan_count); + sc->nwqs = HOST_16(nic_desc->txq_count); if (sc->nwqs) sc->nwqs = MIN(sc->nwqs, OCE_MAX_WQ); else sc->nwqs = OCE_MAX_WQ; + sc->nrssqs = HOST_16(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); diff --git a/sys/dev/oce/oce_sysctl.c b/sys/dev/oce/oce_sysctl.c index cbb51f142..0cafbbd84 100644 --- a/sys/dev/oce/oce_sysctl.c +++ b/sys/dev/oce/oce_sysctl.c @@ -44,6 +44,7 @@ static void copy_stats_to_sc_xe201(POCE_SOFTC sc); static void copy_stats_to_sc_be3(POCE_SOFTC sc); static void copy_stats_to_sc_be2(POCE_SOFTC sc); static int oce_sysctl_loopback(SYSCTL_HANDLER_ARGS); +static int oce_sys_aic_enable(SYSCTL_HANDLER_ARGS); static int oce_be3_fwupgrade(POCE_SOFTC sc, const struct firmware *fw); static int oce_skyhawk_fwupgrade(POCE_SOFTC sc, const struct firmware *fw); static int oce_sys_fwupgrade(SYSCTL_HANDLER_ARGS); @@ -131,6 +132,10 @@ oce_add_sysctls(POCE_SOFTC sc) CTLTYPE_STRING | CTLFLAG_RW, (void *)sc, 0, oce_sys_fwupgrade, "A", "Firmware ufi file"); + SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "aic_enable", + CTLTYPE_INT | CTLFLAG_RW, (void *)sc, 1, + oce_sys_aic_enable, "I", "aic flags"); + /* * Dumps Transceiver data * "sysctl dev.oce.0.sfp_vpd_dump=0" @@ -169,6 +174,35 @@ oce_loopback_test(struct oce_softc *sc, uint8_t loopback_type) return status; } +static int +oce_sys_aic_enable(SYSCTL_HANDLER_ARGS) +{ + int value = 0; + uint32_t status, vector; + POCE_SOFTC sc = (struct oce_softc *)arg1; + struct oce_aic_obj *aic; + + status = sysctl_handle_int(oidp, &value, 0, req); + if (status || !req->newptr) + return status; + + for (vector = 0; vector < sc->intr_count; vector++) { + aic = &sc->aic_obj[vector]; + + if (value == 0){ + aic->max_eqd = aic->min_eqd = aic->et_eqd = 0; + aic->enable = 0; + } + else { + aic->max_eqd = OCE_MAX_EQD; + aic->min_eqd = OCE_MIN_EQD; + aic->et_eqd = OCE_MIN_EQD; + aic->enable = TRUE; + } + } + return 0; +} + static int oce_sysctl_loopback(SYSCTL_HANDLER_ARGS) { -- 2.42.0