| /* |
| * CDDL HEADER START |
| * |
| * The contents of this file are subject to the terms of the |
| * Common Development and Distribution License (the "License"). |
| * You may not use this file except in compliance with the License. |
| * |
| * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE |
| * or http://www.opensolaris.org/os/licensing. |
| * See the License for the specific language governing permissions |
| * and limitations under the License. |
| * |
| * When distributing Covered Code, include this CDDL HEADER in each |
| * file and include the License file at usr/src/OPENSOLARIS.LICENSE. |
| * If applicable, add the following below this CDDL HEADER, with the |
| * fields enclosed by brackets "[]" replaced with your own identifying |
| * information: Portions Copyright [yyyy] [name of copyright owner] |
| * |
| * CDDL HEADER END |
| */ |
| |
| /* |
| * Copyright 2014 QLogic Corporation |
| * The contents of this file are subject to the terms of the |
| * QLogic End User License (the "License"). |
| * You may not use this file except in compliance with the License. |
| * |
| * You can obtain a copy of the License at |
| * http://www.qlogic.com/Resources/Documents/DriverDownloadHelp/ |
| * QLogic_End_User_Software_License.txt |
| * See the License for the specific language governing permissions |
| * and limitations under the License. |
| */ |
| |
| /* |
| * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. |
| * Copyright (c) 2017, Joyent, Inc. |
| */ |
| |
| #include "bnxe.h" |
| |
| #include <sys/mac.h> |
| #include <sys/mac_ether.h> |
| #include <sys/dlpi.h> |
| |
| #if !(defined(__S11) || defined(__S12)) |
| #define mri_driver mr_driver |
| #define mri_start mr_start |
| #define mri_stop mr_stop |
| #define mri_intr mr_intr |
| #define mri_poll mr_poll |
| #define mri_tx mr_send |
| #define mgi_driver mrg_driver |
| #define mgi_start mrg_start |
| #define mgi_stop mrg_stop |
| #define mgi_count mrg_count |
| #define mgi_addmac mrg_addmac |
| #define mgi_remmac mrg_addmac |
| #define mr_gaddring mr_gadd_ring |
| #define mr_gremring mr_grem_ring |
| #endif /* not __S11 or __S12 */ |
| |
| /* |
| * Reconfiguring the network devices parameters require net_config |
| * privilege starting Solaris 10. Only root user is allowed to |
| * update device parameter in Solaris 9 and earlier version. Following |
| * declaration allows single binary image to run on all OS versions. |
| */ |
| extern int secpolicy_net_config(const cred_t *, boolean_t); |
| extern int drv_priv(cred_t *); |
| #pragma weak secpolicy_net_config |
| #pragma weak drv_priv |
| |
| #ifdef MC_SETPROP |
| |
| char * bnxeLink_priv_props[] = |
| { |
| "_adv_2500fdx_cap", |
| "_en_2500fdx_cap", |
| "_adv_txpause_cap", |
| "_en_txpause_cap", |
| "_txpause", |
| "_adv_rxpause_cap", |
| "_en_rxpause_cap", |
| "_rxpause", |
| "_autoneg_flow", |
| "_checksum", |
| "_num_rings", |
| "_rx_descs", |
| "_rx_free_reclaim", |
| "_rx_copy_threshold", |
| "_tx_descs", |
| "_tx_free_reclaim", |
| "_tx_copy_threshold", |
| "_tx_ring_policy", |
| "_interrupt_coalesce", |
| "_rx_interrupt_coalesce_usec", |
| "_tx_interrupt_coalesce_usec", |
| "_disable_msix", |
| "_l2_fw_flow_ctrl", |
| "_autogreeen_enable", |
| "_lso_enable", |
| "_log_enable", |
| "_fcoe_enable", |
| NULL |
| }; |
| |
| #endif /* MC_SETPROP */ |
| |
| |
| static int BnxeMacStats(void * pArg, |
| uint_t stat, |
| uint64_t * pVal) |
| { |
| um_device_t * pUM = (um_device_t *)pArg; |
| lm_device_t * pLM; |
| b10_l2_chip_statistics_t b10_l2_stats; |
| int idx, rc = 0; |
| |
| if ((pUM == NULL) || (pVal == NULL)) |
| { |
| return EINVAL; |
| } |
| |
| pLM = &pUM->lm_dev; |
| |
| BNXE_LOCK_ENTER_GLD(pUM); |
| |
| if (!pUM->plumbed) |
| { |
| BNXE_LOCK_EXIT_GLD(pUM); |
| return EAGAIN; |
| } |
| |
| *pVal = 0; |
| |
| switch (stat) |
| { |
| case MAC_STAT_IFSPEED: |
| *pVal = (pUM->props.link_speed * 1000000ULL); |
| break; |
| |
| case MAC_STAT_MULTIRCV: |
| lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats, |
| L2_CHIP_STATISTICS_VER_NUM_1); |
| *pVal = b10_l2_stats.IfHCInMulticastPkts; |
| break; |
| |
| case MAC_STAT_BRDCSTRCV: |
| lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats, |
| L2_CHIP_STATISTICS_VER_NUM_1); |
| *pVal = b10_l2_stats.IfHCInBroadcastPkts; |
| break; |
| |
| case MAC_STAT_MULTIXMT: |
| lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats, |
| L2_CHIP_STATISTICS_VER_NUM_1); |
| *pVal = b10_l2_stats.IfHCOutMulticastPkts; |
| break; |
| |
| case MAC_STAT_BRDCSTXMT: |
| lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats, |
| L2_CHIP_STATISTICS_VER_NUM_1); |
| *pVal = b10_l2_stats.IfHCOutBroadcastPkts; |
| break; |
| |
| case MAC_STAT_NORCVBUF: |
| lm_get_stats(pLM, LM_STATS_RCV_NO_BUFFER_DROP, (u64_t *)pVal); |
| break; |
| |
| case MAC_STAT_NOXMTBUF: |
| *pVal = 0; |
| LM_FOREACH_TSS_IDX(pLM, idx) |
| { |
| *pVal += pUM->txq[idx].txRecycle; |
| } |
| break; |
| |
| case MAC_STAT_IERRORS: |
| case ETHER_STAT_MACRCV_ERRORS: |
| lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats, |
| L2_CHIP_STATISTICS_VER_NUM_1); |
| *pVal = b10_l2_stats.IfInErrors; |
| break; |
| |
| case MAC_STAT_OERRORS: |
| /* XXX not available */ |
| break; |
| |
| case MAC_STAT_COLLISIONS: |
| lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats, |
| L2_CHIP_STATISTICS_VER_NUM_1); |
| *pVal = b10_l2_stats.EtherStatsCollisions; |
| break; |
| |
| case MAC_STAT_RBYTES: |
| lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats, |
| L2_CHIP_STATISTICS_VER_NUM_1); |
| *pVal = b10_l2_stats.IfHCInOctets; |
| break; |
| |
| case MAC_STAT_IPACKETS: |
| lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats, |
| L2_CHIP_STATISTICS_VER_NUM_1); |
| *pVal = b10_l2_stats.IfHCInPkts; |
| break; |
| |
| case MAC_STAT_OBYTES: |
| lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats, |
| L2_CHIP_STATISTICS_VER_NUM_1); |
| *pVal = b10_l2_stats.IfHCOutOctets; |
| break; |
| |
| case MAC_STAT_OPACKETS: |
| lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats, |
| L2_CHIP_STATISTICS_VER_NUM_1); |
| *pVal = b10_l2_stats.IfHCOutPkts; |
| break; |
| |
| case ETHER_STAT_ALIGN_ERRORS: |
| lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats, |
| L2_CHIP_STATISTICS_VER_NUM_1); |
| *pVal = b10_l2_stats.Dot3StatsAlignmentErrors; |
| break; |
| |
| case ETHER_STAT_FCS_ERRORS: |
| lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats, |
| L2_CHIP_STATISTICS_VER_NUM_1); |
| *pVal = b10_l2_stats.Dot3StatsFCSErrors; |
| break; |
| |
| case ETHER_STAT_FIRST_COLLISIONS: |
| lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats, |
| L2_CHIP_STATISTICS_VER_NUM_1); |
| *pVal = b10_l2_stats.Dot3StatsSingleCollisionFrames; |
| break; |
| |
| case ETHER_STAT_MULTI_COLLISIONS: |
| lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats, |
| L2_CHIP_STATISTICS_VER_NUM_1); |
| *pVal = b10_l2_stats.Dot3StatsMultipleCollisionFrames; |
| break; |
| |
| case ETHER_STAT_DEFER_XMTS: |
| lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats, |
| L2_CHIP_STATISTICS_VER_NUM_1); |
| *pVal = b10_l2_stats.Dot3StatsDeferredTransmissions; |
| break; |
| |
| case ETHER_STAT_TX_LATE_COLLISIONS: |
| lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats, |
| L2_CHIP_STATISTICS_VER_NUM_1); |
| *pVal = b10_l2_stats.Dot3StatsLateCollisions; |
| break; |
| |
| case ETHER_STAT_EX_COLLISIONS: |
| lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats, |
| L2_CHIP_STATISTICS_VER_NUM_1); |
| *pVal = b10_l2_stats.Dot3StatsExcessiveCollisions; |
| break; |
| |
| case ETHER_STAT_MACXMT_ERRORS: |
| lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats, |
| L2_CHIP_STATISTICS_VER_NUM_1); |
| *pVal = b10_l2_stats.Dot3StatsInternalMacTransmitErrors; |
| break; |
| |
| case ETHER_STAT_CARRIER_ERRORS: |
| lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats, |
| L2_CHIP_STATISTICS_VER_NUM_1); |
| *pVal = b10_l2_stats.Dot3StatsCarrierSenseErrors; |
| break; |
| |
| case ETHER_STAT_TOOLONG_ERRORS: |
| lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats, |
| L2_CHIP_STATISTICS_VER_NUM_1); |
| *pVal = b10_l2_stats.EtherStatsOverrsizePkts; |
| break; |
| |
| #if (MAC_VERSION > 1) |
| case ETHER_STAT_TOOSHORT_ERRORS: |
| lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats, |
| L2_CHIP_STATISTICS_VER_NUM_1); |
| *pVal = b10_l2_stats.EtherStatsUndersizePkts; |
| break; |
| #endif |
| |
| case ETHER_STAT_XCVR_ADDR: |
| *pVal = pLM->vars.phy_addr; |
| break; |
| |
| case ETHER_STAT_XCVR_ID: |
| *pVal = 0; |
| break; |
| |
| case ETHER_STAT_XCVR_INUSE: |
| switch (pUM->props.link_speed) |
| { |
| case 0: /* no speed then status is down */ |
| *pVal = XCVR_NONE; |
| break; |
| |
| case 1000: |
| *pVal = XCVR_1000X; |
| break; |
| |
| case 100: |
| *pVal = XCVR_100X; |
| break; |
| |
| case 10: |
| *pVal = XCVR_10; |
| break; |
| |
| default: |
| /* catches 2500/10000 */ |
| *pVal = XCVR_UNDEFINED; |
| } |
| break; |
| |
| #if (MAC_VERSION > 1) |
| case ETHER_STAT_CAP_10GFDX: |
| *pVal = 1; |
| break; |
| #endif |
| |
| case ETHER_STAT_CAP_1000FDX: |
| *pVal = 1; |
| break; |
| |
| #if 0 |
| case ETHER_STAT_CAP_1000HDX: |
| //*pVal = linkconf->param_1000hdx; |
| *pVal = 0; |
| break; |
| #endif |
| |
| case ETHER_STAT_CAP_100FDX: |
| //*pVal = linkconf->param_100fdx; |
| *pVal = 1; |
| break; |
| |
| case ETHER_STAT_CAP_100HDX: |
| //*pVal = linkconf->param_100hdx; |
| *pVal = 1; |
| break; |
| |
| case ETHER_STAT_CAP_10FDX: |
| //*pVal = linkconf->param_10fdx; |
| *pVal = 1; |
| break; |
| |
| case ETHER_STAT_CAP_10HDX: |
| //*pVal = linkconf->param_10hdx; |
| *pVal = 1; |
| break; |
| |
| case ETHER_STAT_CAP_ASMPAUSE: |
| *pVal = 1; |
| break; |
| |
| case ETHER_STAT_CAP_PAUSE: |
| *pVal = 1; |
| break; |
| |
| case ETHER_STAT_CAP_AUTONEG: |
| *pVal = 1; |
| break; |
| |
| #if (MAC_VERSION > 1) |
| case ETHER_STAT_CAP_REMFAULT: |
| *pVal = 1; |
| break; |
| #endif |
| |
| #if (MAC_VERSION > 1) |
| case ETHER_STAT_ADV_CAP_10GFDX: |
| *pVal = pUM->curcfg.lnkcfg.param_10000fdx; |
| break; |
| #endif |
| |
| case ETHER_STAT_ADV_CAP_1000FDX: |
| *pVal = pUM->curcfg.lnkcfg.param_1000fdx; |
| break; |
| |
| #if 0 |
| case ETHER_STAT_ADV_CAP_1000HDX: |
| //*pVal = pUM->curcfg.lnkcfg.param_1000hdx; |
| *pVal = 0; |
| break; |
| #endif |
| |
| case ETHER_STAT_ADV_CAP_100FDX: |
| *pVal = pUM->curcfg.lnkcfg.param_100fdx; |
| break; |
| |
| case ETHER_STAT_ADV_CAP_100HDX: |
| *pVal = pUM->curcfg.lnkcfg.param_100hdx; |
| break; |
| |
| case ETHER_STAT_ADV_CAP_10FDX: |
| *pVal = pUM->curcfg.lnkcfg.param_10fdx; |
| break; |
| |
| case ETHER_STAT_ADV_CAP_10HDX: |
| *pVal = pUM->curcfg.lnkcfg.param_10hdx; |
| break; |
| |
| case ETHER_STAT_ADV_CAP_ASMPAUSE: |
| *pVal = 1; |
| break; |
| |
| case ETHER_STAT_ADV_CAP_PAUSE: |
| *pVal = 1; |
| break; |
| |
| case ETHER_STAT_ADV_CAP_AUTONEG: |
| *pVal = pUM->curcfg.lnkcfg.link_autoneg; |
| break; |
| |
| #if (MAC_VERSION > 1) |
| case ETHER_STAT_ADV_REMFAULT: |
| *pVal = 1; |
| break; |
| #endif |
| |
| #if 0 /* LP caps not supported */ |
| #if (MAC_VERSION > 1) |
| case ETHER_STAT_LP_CAP_10GFDX: |
| *pVal = pUM->remote.param_10000fdx; |
| break; |
| #endif |
| |
| case ETHER_STAT_LP_CAP_1000FDX: |
| *pVal = pUM->remote.param_1000fdx; |
| break; |
| |
| #if 0 |
| case ETHER_STAT_LP_CAP_1000HDX: |
| //*pVal = pUM->remote.param_1000hdx; |
| *pVal = 0; |
| break; |
| #endif |
| |
| case ETHER_STAT_LP_CAP_100FDX: |
| *pVal = pUM->remote.param_100fdx; |
| break; |
| |
| case ETHER_STAT_LP_CAP_100HDX: |
| *pVal = pUM->remote.param_100hdx; |
| break; |
| |
| case ETHER_STAT_LP_CAP_10FDX: |
| *pVal = pUM->remote.param_10fdx; |
| break; |
| |
| case ETHER_STAT_LP_CAP_10HDX: |
| *pVal = pUM->remote.param_10hdx; |
| break; |
| |
| #if 0 |
| case ETHER_STAT_LP_CAP_ASMPAUSE: |
| /* XXX implement LP_ASYM_PAUSE stat */ |
| break; |
| |
| case ETHER_STAT_LP_CAP_PAUSE: |
| /* XXX implement LP_PAUSE stat */ |
| break; |
| #endif |
| |
| case ETHER_STAT_LP_CAP_AUTONEG: |
| *pVal = pUM->remote.link_autoneg; |
| break; |
| |
| case ETHER_STAT_LP_REMFAULT: |
| /* XXX implement LP_REMFAULT stat */ |
| break; |
| #endif /* LP caps not supported */ |
| |
| #if 0 |
| case ETHER_STAT_LINK_ASMPAUSE: |
| /* XXX implement ASMPAUSE stat */ |
| break; |
| |
| case ETHER_STAT_LINK_PAUSE: |
| /* XXX implement PAUSE stat */ |
| break; |
| #endif |
| |
| case ETHER_STAT_LINK_AUTONEG: |
| *pVal = pUM->curcfg.lnkcfg.link_autoneg; |
| break; |
| |
| case ETHER_STAT_LINK_DUPLEX: |
| *pVal = (pUM->props.link_duplex == B_TRUE) ? |
| LINK_DUPLEX_FULL : LINK_DUPLEX_HALF; |
| break; |
| |
| default: |
| rc = ENOTSUP; |
| } |
| |
| BNXE_LOCK_EXIT_GLD(pUM); |
| |
| return rc; |
| } |
| |
| |
| |
| /* |
| * This routine is called by GLD to enable device for packet reception and |
| * enable interrupts. |
| */ |
| static int BnxeMacStart(void * pArg) |
| { |
| um_device_t * pUM = (um_device_t *)pArg; |
| |
| BNXE_LOCK_ENTER_GLD(pUM); |
| |
| if (pUM->plumbed) |
| { |
| /* already started */ |
| BNXE_LOCK_EXIT_GLD(pUM); |
| return EAGAIN; |
| } |
| |
| /* Always report the initial link state as unknown. */ |
| mac_link_update(pUM->pMac, LINK_STATE_UNKNOWN); |
| |
| if (BnxeHwStartL2(pUM)) |
| { |
| BNXE_LOCK_EXIT_GLD(pUM); |
| return EIO; |
| } |
| |
| atomic_swap_32(&pUM->plumbed, B_TRUE); |
| |
| mutex_enter(&bnxeLoaderMutex); |
| bnxeNumPlumbed++; |
| mutex_exit(&bnxeLoaderMutex); |
| |
| BNXE_LOCK_EXIT_GLD(pUM); |
| |
| return 0; |
| } |
| |
| |
| /* |
| * This routine stops packet reception by clearing RX MASK register. Also |
| * interrupts are disabled for this device. |
| */ |
| static void BnxeMacStop(void * pArg) |
| { |
| um_device_t * pUM = (um_device_t *)pArg; |
| |
| BNXE_LOCK_ENTER_GLD(pUM); |
| |
| if (pUM->plumbed) |
| { |
| atomic_swap_32(&pUM->plumbed, B_FALSE); |
| |
| BnxeHwStopL2(pUM); |
| |
| /* Report the link state back to unknown. */ |
| mac_link_update(pUM->pMac, LINK_STATE_UNKNOWN); |
| |
| mutex_enter(&bnxeLoaderMutex); |
| bnxeNumPlumbed--; |
| mutex_exit(&bnxeLoaderMutex); |
| } |
| |
| BNXE_LOCK_EXIT_GLD(pUM); |
| } |
| |
| /* (flag) TRUE = on, FALSE = off */ |
| static int BnxeMacPromiscuous(void * pArg, |
| boolean_t flag) |
| { |
| um_device_t * pUM = (um_device_t *)pArg; |
| |
| BNXE_LOCK_ENTER_GLD(pUM); |
| |
| if (!pUM->plumbed) |
| { |
| BNXE_LOCK_EXIT_GLD(pUM); |
| return EAGAIN; |
| } |
| |
| if (flag) |
| { |
| pUM->devParams.rx_filter_mask[LM_CLI_IDX_NDIS] |= |
| LM_RX_MASK_PROMISCUOUS_MODE; |
| } |
| else |
| { |
| pUM->devParams.rx_filter_mask[LM_CLI_IDX_NDIS] &= |
| ~LM_RX_MASK_PROMISCUOUS_MODE; |
| } |
| |
| BNXE_LOCK_ENTER_HWINIT(pUM); |
| |
| if (BnxeRxMask(pUM, LM_CLI_IDX_NDIS, |
| pUM->devParams.rx_filter_mask[LM_CLI_IDX_NDIS]) < 0) |
| { |
| BNXE_LOCK_EXIT_HWINIT(pUM); |
| BNXE_LOCK_EXIT_GLD(pUM); |
| return ECANCELED; |
| } |
| |
| BNXE_LOCK_EXIT_HWINIT(pUM); |
| |
| BNXE_LOCK_EXIT_GLD(pUM); |
| |
| return 0; |
| } |
| |
| |
| /* |
| * This function is used to enable or disable multicast packet reception for |
| * particular multicast addresses. |
| * (flag) TRUE = add, FALSE = remove |
| */ |
| static int BnxeMacMulticast(void * pArg, |
| boolean_t flag, |
| const uint8_t * pMcastAddr) |
| { |
| um_device_t * pUM = (um_device_t *)pArg; |
| int rc; |
| |
| BNXE_LOCK_ENTER_GLD(pUM); |
| |
| if (!pUM->plumbed) |
| { |
| BNXE_LOCK_EXIT_GLD(pUM); |
| return EAGAIN; |
| } |
| |
| BNXE_LOCK_ENTER_HWINIT(pUM); |
| rc = BnxeMulticast(pUM, LM_CLI_IDX_NDIS, flag, pMcastAddr, B_TRUE); |
| BNXE_LOCK_EXIT_HWINIT(pUM); |
| |
| BNXE_LOCK_EXIT_GLD(pUM); |
| |
| return rc; |
| } |
| |
| |
| #ifdef BNXE_RINGS |
| |
| #if (defined(__S11) || defined(__S12)) && !defined(ILLUMOS) |
| static int BnxeRxRingGroupAddMac(void * groupHandle, |
| const uint8_t * pMacAddr, |
| uint64_t flags) |
| #else |
| static int BnxeRxRingGroupAddMac(void * groupHandle, |
| const uint8_t * pMacAddr) |
| #endif |
| { |
| RxQueueGroup * pRxQGroup = (RxQueueGroup *)groupHandle; |
| um_device_t * pUM = (um_device_t *)pRxQGroup->pUM; |
| //u32_t idx = pRxQGroup->idx; |
| int rc; |
| |
| #if (defined(__S11) || defined(__S12)) && !defined(ILLUMOS) |
| _NOTE(ARGUNUSED(flags)) |
| #endif |
| |
| BNXE_LOCK_ENTER_GLD(pUM); |
| |
| if (!pUM->plumbed) |
| { |
| BNXE_LOCK_EXIT_GLD(pUM); |
| return ECANCELED; |
| } |
| |
| /* Validate MAC address */ |
| if (IS_ETH_MULTICAST(pMacAddr)) |
| { |
| BnxeLogWarn(pUM, "Cannot program a mcast/bcast address as a MAC Address."); |
| BNXE_LOCK_EXIT_GLD(pUM); |
| return EINVAL; |
| } |
| |
| if (pUM->ucastTableLen == LM_MAX_UC_TABLE_SIZE) |
| { |
| BNXE_LOCK_EXIT_GLD(pUM); |
| return ENOMEM; |
| } |
| |
| BNXE_LOCK_ENTER_HWINIT(pUM); |
| |
| COPY_ETH_ADDRESS(pMacAddr, pUM->lm_dev.params.mac_addr); |
| |
| rc = BnxeMacAddress(pUM, LM_CLI_IDX_NDIS, B_TRUE, |
| pUM->lm_dev.params.mac_addr); |
| |
| BNXE_LOCK_EXIT_HWINIT(pUM); |
| |
| if (rc < 0) |
| { |
| BNXE_LOCK_EXIT_GLD(pUM); |
| return ECANCELED; |
| } |
| |
| pUM->ucastTableLen++; |
| |
| BNXE_LOCK_EXIT_GLD(pUM); |
| return 0; |
| } |
| |
| |
| static int BnxeRxRingGroupRemMac(void * groupHandle, |
| const uint8_t * pMacAddr) |
| { |
| RxQueueGroup * pRxQGroup = (RxQueueGroup *)groupHandle; |
| um_device_t * pUM = (um_device_t *)pRxQGroup->pUM; |
| //u32_t idx = pRxQGroup->idx; |
| int rc; |
| |
| BNXE_LOCK_ENTER_GLD(pUM); |
| |
| if (!pUM->plumbed) |
| { |
| BNXE_LOCK_EXIT_GLD(pUM); |
| return ECANCELED; |
| } |
| |
| if (pUM->ucastTableLen == 0) |
| { |
| BNXE_LOCK_EXIT_GLD(pUM); |
| return EINVAL; |
| } |
| |
| BNXE_LOCK_ENTER_HWINIT(pUM); |
| |
| if (!IS_ETH_ADDRESS_EQUAL(pMacAddr, pUM->lm_dev.params.mac_addr)) |
| { |
| BnxeLogWarn(pUM, "Deleting MAC address that doesn't match default"); |
| /* XXX */ |
| } |
| |
| rc = BnxeMacAddress(pUM, LM_CLI_IDX_NDIS, B_FALSE, |
| pUM->lm_dev.params.mac_addr); |
| |
| memset(pUM->lm_dev.params.mac_addr, 0, sizeof(pUM->lm_dev.params.mac_addr)); |
| |
| BNXE_LOCK_EXIT_HWINIT(pUM); |
| |
| if (rc < 0) |
| { |
| BNXE_LOCK_EXIT_GLD(pUM); |
| return ECANCELED; |
| } |
| |
| pUM->ucastTableLen--; |
| |
| BNXE_LOCK_EXIT_GLD(pUM); |
| return 0; |
| } |
| |
| |
| static mblk_t * BnxeTxRingSend(void * ringHandle, |
| mblk_t * pMblk) |
| { |
| TxQueue * pTxQ = (TxQueue *)ringHandle; |
| um_device_t * pUM = (um_device_t *)pTxQ->pUM; |
| u32_t idx = pTxQ->idx; |
| mblk_t * pNextMblk; |
| int rc; |
| |
| while (pMblk) |
| { |
| pNextMblk = pMblk->b_next; |
| pMblk->b_next = NULL; |
| |
| rc = BnxeTxSendMblk(pUM, idx, pMblk, 0, 0); |
| |
| if (rc == BNXE_TX_GOODXMIT) |
| { |
| pMblk = pNextMblk; |
| continue; |
| } |
| else if (rc == BNXE_TX_DEFERPKT) |
| { |
| pMblk = pNextMblk; |
| } |
| else |
| { |
| pMblk->b_next = pNextMblk; |
| } |
| |
| break; |
| } |
| |
| return pMblk; |
| } |
| |
| #endif /* BNXE_RINGS */ |
| |
| |
| static int BnxeMacUnicast(void * pArg, |
| const uint8_t * pMacAddr) |
| { |
| um_device_t * pUM = (um_device_t *)pArg; |
| int rc; |
| |
| BNXE_LOCK_ENTER_GLD(pUM); |
| |
| if (!pUM->plumbed) |
| { |
| memcpy(pUM->gldMac, pMacAddr, ETHERNET_ADDRESS_SIZE); |
| BNXE_LOCK_EXIT_GLD(pUM); |
| return 0; |
| } |
| |
| /* Validate MAC address */ |
| if (IS_ETH_MULTICAST(pMacAddr)) |
| { |
| BnxeLogWarn(pUM, "Cannot program a mcast/bcast address as a MAC Address."); |
| BNXE_LOCK_EXIT_GLD(pUM); |
| return EINVAL; |
| } |
| |
| BNXE_LOCK_ENTER_HWINIT(pUM); |
| |
| COPY_ETH_ADDRESS(pMacAddr, pUM->lm_dev.params.mac_addr); |
| |
| rc = BnxeMacAddress(pUM, LM_CLI_IDX_NDIS, B_TRUE, |
| pUM->lm_dev.params.mac_addr); |
| |
| BNXE_LOCK_EXIT_HWINIT(pUM); |
| |
| if (rc < 0) |
| { |
| BNXE_LOCK_EXIT_GLD(pUM); |
| return EAGAIN; |
| } |
| |
| BNXE_LOCK_EXIT_GLD(pUM); |
| return 0; |
| } |
| |
| |
| static mblk_t * BnxeMacTx(void * pArg, |
| mblk_t * pMblk) |
| { |
| um_device_t * pUM = (um_device_t *)pArg; |
| mblk_t * pNextMblk; |
| int ring, rc; |
| |
| BNXE_LOCK_ENTER_GLDTX(pUM, RW_READER); |
| |
| if (!pUM->plumbed) |
| { |
| freemsgchain(pMblk); |
| BNXE_LOCK_EXIT_GLDTX(pUM); |
| |
| return NULL; |
| } |
| |
| while (pMblk) |
| { |
| ring = BnxeRouteTxRing(pUM, pMblk); |
| |
| pNextMblk = pMblk->b_next; |
| pMblk->b_next = NULL; |
| |
| //rc = BnxeTxSendMblk(pUM, NDIS_CID(&pUM->lm_dev), pMblk, 0, 0); |
| rc = BnxeTxSendMblk(pUM, ring, pMblk, 0, 0); |
| |
| if (rc == BNXE_TX_GOODXMIT) |
| { |
| pMblk = pNextMblk; |
| continue; |
| } |
| else if (rc == BNXE_TX_DEFERPKT) |
| { |
| pMblk = pNextMblk; |
| } |
| else |
| { |
| pMblk->b_next = pNextMblk; |
| } |
| |
| break; |
| } |
| |
| BNXE_LOCK_EXIT_GLDTX(pUM); |
| |
| return pMblk; |
| } |
| |
| |
| #ifdef MC_RESOURCES |
| |
| static void BnxeBlank(void * pArg, |
| time_t tick_cnt, |
| uint_t pkt_cnt) |
| { |
| um_device_t * pUM = (um_device_t *)pArg; |
| |
| if (!pUM->plumbed) |
| { |
| return; |
| } |
| |
| /* XXX |
| * Need to dynamically reconfigure the hw with new interrupt |
| * coalescing params... |
| */ |
| } |
| |
| |
| static void BnxeMacResources(void * pArg) |
| { |
| um_device_t * pUM = (um_device_t *)pArg; |
| mac_rx_fifo_t mrf; |
| int idx; |
| |
| mrf.mrf_type = MAC_RX_FIFO; |
| mrf.mrf_blank = BnxeBlank; |
| mrf.mrf_arg = (void *)pUM; |
| mrf.mrf_normal_blank_time = 25; |
| mrf.mrf_normal_pkt_count = 8; |
| |
| LM_FOREACH_RSS_IDX(&pUM->lm_dev, idx) |
| { |
| pUM->macRxResourceHandles[idx] = |
| mac_resource_add(pUM->pMac, (mac_resource_t *)&mrf); |
| } |
| } |
| |
| #endif /* MC_RESOURCES */ |
| |
| |
| static boolean_t BnxeReadReg(um_device_t * pUM, |
| struct bnxe_reg_data * pData) |
| { |
| if (pData->offset & 0x3) |
| { |
| BnxeLogWarn(pUM, "Invalid register offset for GIOCBNXEREG ioctl"); |
| return B_FALSE; |
| } |
| |
| LM_BAR_RD32_OFFSET(&pUM->lm_dev, 0, pData->offset, &pData->value); |
| |
| return B_TRUE; |
| } |
| |
| |
| static boolean_t BnxeWriteReg(um_device_t * pUM, |
| struct bnxe_reg_data * pData) |
| { |
| if (pData->offset & 0x3) |
| { |
| BnxeLogWarn(pUM, "Invalid register offset for SIOCBNXEREG ioctl"); |
| return B_FALSE; |
| } |
| |
| LM_BAR_WR32_OFFSET(&pUM->lm_dev, 0, pData->offset, pData->value); |
| |
| return B_TRUE; |
| } |
| |
| |
| static boolean_t BnxeReadNvm(um_device_t * pUM, |
| struct bnxe_nvram_data * pData) |
| { |
| if (pData->offset & 0x3) |
| { |
| BnxeLogWarn(pUM, "Invalid register offset for GIOCBNXENVRM ioctl"); |
| return B_FALSE; |
| } |
| |
| if (lm_nvram_read(&pUM->lm_dev, |
| pData->offset, |
| pData->value, |
| (pData->num_of_u32 * sizeof(u32_t))) != |
| LM_STATUS_SUCCESS) |
| { |
| return B_FALSE; |
| } |
| |
| return B_TRUE; |
| } |
| |
| |
| static boolean_t BnxeWriteNvm(um_device_t * pUM, |
| struct bnxe_nvram_data * pData) |
| { |
| if (pData->offset & 0x3) |
| { |
| BnxeLogWarn(pUM, "Invalid register offset for SIOCBNXENVRM ioctl"); |
| return B_FALSE; |
| } |
| |
| if (lm_nvram_write(&pUM->lm_dev, |
| pData->offset, |
| pData->value, |
| (pData->num_of_u32 * sizeof(u32_t))) != |
| LM_STATUS_SUCCESS) |
| { |
| return B_FALSE; |
| } |
| |
| return B_TRUE; |
| } |
| |
| |
| static boolean_t BnxeReadPciCfg(um_device_t * pUM, |
| struct bnxe_reg_data * pData) |
| { |
| pData->value = pci_config_get32(pUM->pPciCfg, (off_t)pData->offset); |
| return B_TRUE; |
| } |
| |
| typedef enum { |
| STATS_SHOW_TYPE_NUM, |
| STATS_SHOW_TYPE_STR, |
| STATS_SHOW_TYPE_CNT, |
| STATS_SHOW_TYPE_MAX |
| } stats_show_type_t; |
| |
| typedef union _b10_stats_show_data_t |
| { |
| u32_t op; /* ioctl sub-commond */ |
| |
| struct |
| { |
| u32_t num; /* return number of stats */ |
| u32_t len; /* length of each string item */ |
| } desc; |
| |
| /* variable length... */ |
| char str[1]; /* holds names of desc.num stats, each desc.len in length */ |
| |
| struct |
| { |
| b10_l2_chip_statistics_v2_t l2_chip_stats; |
| b10_l4_chip_statistics_t l4_chip_stats; |
| b10_l2_driver_statistics_t l2_drv_stats; |
| b10_l4_driver_statistics_t l4_drv_stats; |
| } cnt; |
| } b10_stats_show_data_t; |
| |
| |
| static boolean_t BnxeStatsShow(um_device_t * pUM, |
| b10_stats_show_data_t * pStats, |
| u32_t statsLen) |
| { |
| stats_show_type_t op; |
| const size_t stats_size = sizeof(pStats->cnt); |
| |
| /* |
| * All stats names MUST conform to STATS_STR_LEN length!!! |
| */ |
| |
| #define STATS_STR_LEN 39 |
| |
| /* XXX |
| * Note: these strings must be updated whenever any of |
| * b10_l2_chip_statistics_t, b10_l4_chip_statistics_t, |
| * b10_l2_driver_statistics_t or b10_l4_driver_statistics_t |
| * are changed, or additional statistics are required. |
| */ |
| |
| const char p_stat_str[] = |
| |
| // b10_l2_chip_statistics_t |
| |
| "l2_chip_stats_ver_num\0 " |
| "IfHCInOctets\0 " |
| "IfHCInBadOctets\0 " |
| "IfHCOutOctets\0 " |
| "IfHCOutBadOctets\0 " |
| "IfHCOutPkts\0 " |
| "IfHCInPkts\0 " |
| "IfHCInUcastPkts\0 " |
| "IfHCInMulticastPkts\0 " |
| "IfHCInBroadcastPkts\0 " |
| "IfHCOutUcastPkts\0 " |
| "IfHCOutMulticastPkts\0 " |
| "IfHCOutBroadcastPkts\0 " |
| "IfHCInUcastOctets\0 " |
| "IfHCInMulticastOctets\0 " |
| "IfHCInBroadcastOctets\0 " |
| "IfHCOutUcastOctets\0 " |
| "IfHCOutMulticastOctets\0 " |
| "IfHCOutBroadcastOctets\0 " |
| "IfHCOutDiscards\0 " |
| "IfHCInFalseCarrierErrors\0 " |
| "Dot3StatsInternalMacTransmitErrors\0 " |
| "Dot3StatsCarrierSenseErrors\0 " |
| "Dot3StatsFCSErrors\0 " |
| "Dot3StatsAlignmentErrors\0 " |
| "Dot3StatsSingleCollisionFrames\0 " |
| "Dot3StatsMultipleCollisionFrames\0 " |
| "Dot3StatsDeferredTransmissions\0 " |
| "Dot3StatsExcessiveCollisions\0 " |
| "Dot3StatsLateCollisions\0 " |
| "EtherStatsCollisions\0 " |
| "EtherStatsFragments\0 " |
| "EtherStatsJabbers\0 " |
| "EtherStatsUndersizePkts\0 " |
| "EtherStatsOverrsizePkts\0 " |
| "EtherStatsPktsTx64Octets\0 " |
| "EtherStatsPktsTx65Octetsto127Octets\0 " |
| "EtherStatsPktsTx128Octetsto255Octets\0 " |
| "EtherStatsPktsTx256Octetsto511Octets\0 " |
| "EtherStatsPktsTx512Octetsto1023Octets\0 " |
| "EtherStatsPktsTx1024Octetsto1522Octets\0" |
| "EtherStatsPktsTxOver1522Octets\0 " |
| "XonPauseFramesReceived\0 " |
| "XoffPauseFramesReceived\0 " |
| "OutXonSent\0 " |
| "OutXoffSent\0 " |
| "FlowControlDone\0 " |
| "MacControlFramesReceived\0 " |
| "XoffStateEntered\0 " |
| "IfInFramesL2FilterDiscards\0 " |
| "IfInTTL0Discards\0 " |
| "IfInxxOverflowDiscards\0 " |
| "IfInMBUFDiscards\0 " |
| "IfInErrors\0 " |
| "IfInErrorsOctets\0 " |
| "IfInNoBrbBuffer\0 " |
| |
| "Nig_brb_packet\0 " |
| "Nig_brb_truncate\0 " |
| "Nig_flow_ctrl_discard\0 " |
| "Nig_flow_ctrl_octets\0 " |
| "Nig_flow_ctrl_packet\0 " |
| "Nig_mng_discard\0 " |
| "Nig_mng_octet_inp\0 " |
| "Nig_mng_octet_out\0 " |
| "Nig_mng_packet_inp\0 " |
| "Nig_mng_packet_out\0 " |
| "Nig_pbf_octets\0 " |
| "Nig_pbf_packet\0 " |
| "Nig_safc_inp\0 " |
| |
| "Tx_Lpi_Count\0 " // This counter counts the number of timers the debounced version of EEE link idle is asserted |
| |
| // b10_l4_chip_statistics_t |
| |
| "l4_chip_stats_ver_num\0 " |
| "NoTxCqes\0 " |
| "InTCP4Segments\0 " |
| "OutTCP4Segments\0 " |
| "RetransmittedTCP4Segments\0 " |
| "InTCP4Errors\0 " |
| "InIP4Receives\0 " |
| "InIP4HeaderErrors\0 " |
| "InIP4Discards\0 " |
| "InIP4Delivers\0 " |
| "InIP4Octets\0 " |
| "OutIP4Octets\0 " |
| "InIP4TruncatedPackets\0 " |
| "InTCP6Segments\0 " |
| "OutTCP6Segments\0 " |
| "RetransmittedTCP6Segments\0 " |
| "InTCP6Errors\0 " |
| "InIP6Receives\0 " |
| "InIP6HeaderErrors\0 " |
| "InIP6Discards\0 " |
| "InIP6Delivers\0 " |
| "InIP6Octets\0 " |
| "OutIP6Octets\0 " |
| "InIP6TruncatedPackets\0 " |
| |
| // b10_l2_driver_statistics_t |
| |
| "l2_driver_stats_ver_num\0 " |
| "RxIPv4FragCount\0 " |
| "RxIpCsErrorCount\0 " |
| "RxTcpCsErrorCount\0 " |
| "RxLlcSnapCount\0 " |
| "RxPhyErrorCount\0 " |
| "RxIpv6ExtCount\0 " |
| "TxNoL2Bd\0 " |
| "TxNoSqWqe\0 " |
| "TxL2AssemblyBufUse\0 " |
| |
| // b10_l4_driver_statistics_t |
| |
| "l4_driver_stats_ver_num\0 " |
| "CurrentlyIpv4Established\0 " |
| "OutIpv4Resets\0 " |
| "OutIpv4Fin\0 " |
| "InIpv4Reset\0 " |
| "InIpv4Fin\0 " |
| "CurrentlyIpv6Established\0 " |
| "OutIpv6Resets\0 " |
| "OutIpv6Fin\0 " |
| "InIpv6Reset\0 " |
| "InIpv6Fin\0 " |
| "RxIndicateReturnPendingCnt\0 " |
| "RxIndicateReturnDoneCnt\0 " |
| "RxActiveGenBufCnt\0 " |
| "TxNoL4Bd\0 " |
| "TxL4AssemblyBufUse\0 " |
| |
| ; |
| |
| ASSERT_STATIC((sizeof(p_stat_str) / STATS_STR_LEN) == |
| (stats_size / sizeof(u64_t))); |
| |
| op = *((stats_show_type_t *)pStats); |
| |
| switch (op) |
| { |
| case STATS_SHOW_TYPE_NUM: |
| |
| if (statsLen < sizeof(pStats->desc)) |
| { |
| return B_FALSE; |
| } |
| |
| pStats->desc.num = (stats_size / sizeof(u64_t)); |
| pStats->desc.len = STATS_STR_LEN; |
| |
| return B_TRUE; |
| |
| case STATS_SHOW_TYPE_STR: |
| |
| if (statsLen != sizeof(p_stat_str)) |
| { |
| return B_FALSE; |
| } |
| |
| memcpy(pStats->str, p_stat_str, sizeof(p_stat_str)); |
| |
| return B_TRUE; |
| |
| case STATS_SHOW_TYPE_CNT: |
| |
| if (statsLen != stats_size) |
| { |
| return B_FALSE; |
| } |
| |
| lm_stats_get_l2_chip_stats(&pUM->lm_dev, |
| &pStats->cnt.l2_chip_stats, |
| L2_CHIP_STATISTICS_VER_NUM_2); |
| |
| lm_stats_get_l4_chip_stats(&pUM->lm_dev, |
| &pStats->cnt.l4_chip_stats); |
| |
| lm_stats_get_l2_driver_stats(&pUM->lm_dev |
| ,&pStats->cnt.l2_drv_stats); |
| |
| lm_stats_get_l4_driver_stats(&pUM->lm_dev, |
| &pStats->cnt.l4_drv_stats); |
| |
| return B_TRUE; |
| |
| default: |
| |
| return B_FALSE; |
| } |
| } |
| |
| static void BnxeMacIoctl(void * pArg, |
| queue_t * pQ, |
| mblk_t * pMblk) |
| { |
| um_device_t * pUM = (um_device_t *)pArg; |
| struct iocblk * pIoctl; |
| int rc; |
| |
| if ((pQ == NULL) || (pMblk == NULL)) |
| { |
| return; |
| } |
| |
| if (pMblk->b_datap->db_type != M_IOCTL) |
| { |
| miocnak(pQ, pMblk, 0, EINVAL); |
| return; |
| } |
| |
| pIoctl = (struct iocblk *)pMblk->b_rptr; |
| |
| BNXE_LOCK_ENTER_GLD(pUM); |
| |
| switch (pIoctl->ioc_cmd) |
| { |
| case GIOCBNXELLDP: |
| |
| if ((pIoctl->ioc_count != sizeof(b10_lldp_params_get_t)) || |
| (pMblk->b_cont == NULL) || (pMblk->b_cont->b_rptr == NULL) || |
| (miocpullup(pMblk, sizeof(b10_lldp_params_get_t)) < 0)) |
| { |
| miocnak(pQ, pMblk, 0, EINVAL); |
| break; |
| } |
| |
| if (((b10_lldp_params_get_t *)pMblk->b_cont->b_rptr)->ver_num != |
| LLDP_PARAMS_VER_NUM) |
| { |
| miocnak(pQ, pMblk, 0, EINVAL); |
| break; |
| } |
| |
| if (lm_dcbx_lldp_read_params(&pUM->lm_dev, |
| (b10_lldp_params_get_t *)pMblk->b_cont->b_rptr) != |
| LM_STATUS_SUCCESS) |
| { |
| miocnak(pQ, pMblk, 0, |
| (!IS_DCB_ENABLED(&pUM->lm_dev)) ? ENOTSUP : EINVAL); |
| break; |
| } |
| |
| miocack(pQ, pMblk, pIoctl->ioc_count, 0); |
| break; |
| |
| case GIOCBNXEDCBX: |
| |
| if ((pIoctl->ioc_count != sizeof(b10_dcbx_params_get_t)) || |
| (pMblk->b_cont == NULL) || (pMblk->b_cont->b_rptr == NULL) || |
| (miocpullup(pMblk, sizeof(b10_dcbx_params_get_t)) < 0)) |
| { |
| miocnak(pQ, pMblk, 0, EINVAL); |
| break; |
| } |
| |
| if (((b10_dcbx_params_get_t *)pMblk->b_cont->b_rptr)->ver_num != |
| DCBX_PARAMS_VER_NUM) |
| { |
| miocnak(pQ, pMblk, 0, EINVAL); |
| break; |
| } |
| |
| if (lm_dcbx_read_params(&pUM->lm_dev, |
| (b10_dcbx_params_get_t *)pMblk->b_cont->b_rptr) != |
| LM_STATUS_SUCCESS) |
| { |
| miocnak(pQ, pMblk, 0, |
| (!IS_DCB_ENABLED(&pUM->lm_dev)) ? ENOTSUP : EINVAL); |
| break; |
| } |
| |
| miocack(pQ, pMblk, pIoctl->ioc_count, 0); |
| break; |
| |
| case SIOCBNXEDCBX: |
| |
| /* XXX */ |
| miocnak(pQ, pMblk, 0, EINVAL); |
| break; |
| |
| case GIOCBNXEREG: |
| |
| if ((pIoctl->ioc_count != sizeof(struct bnxe_reg_data)) || |
| (pMblk->b_cont == NULL) || (pMblk->b_cont->b_rptr == NULL) || |
| (miocpullup(pMblk, sizeof(struct bnxe_reg_data)) < 0)) |
| { |
| miocnak(pQ, pMblk, 0, EINVAL); |
| break; |
| } |
| |
| if (!BnxeReadReg(pUM, (struct bnxe_reg_data *)pMblk->b_cont->b_rptr)) |
| { |
| miocnak(pQ, pMblk, 0, EINVAL); |
| } |
| else |
| { |
| miocack(pQ, pMblk, pIoctl->ioc_count, 0); |
| } |
| |
| break; |
| |
| case SIOCBNXEREG: |
| |
| if ((pIoctl->ioc_count != sizeof(struct bnxe_reg_data)) || |
| (pMblk->b_cont == NULL) || (pMblk->b_cont->b_rptr == NULL) || |
| (miocpullup(pMblk, sizeof(struct bnxe_reg_data)) < 0)) |
| { |
| miocnak(pQ, pMblk, 0, EINVAL); |
| break; |
| } |
| |
| if (!BnxeWriteReg(pUM, (struct bnxe_reg_data *)pMblk->b_cont->b_rptr)) |
| { |
| miocnak(pQ, pMblk, 0, EINVAL); |
| } |
| else |
| { |
| miocack(pQ, pMblk, pIoctl->ioc_count, 0); |
| } |
| |
| break; |
| |
| case GIOCBNXENVRM: |
| |
| if ((pIoctl->ioc_count < sizeof(struct bnxe_nvram_data)) || |
| (pMblk->b_cont == NULL) || (pMblk->b_cont->b_rptr == NULL) || |
| (miocpullup(pMblk, pIoctl->ioc_count) < 0)) |
| { |
| miocnak(pQ, pMblk, 0, EINVAL); |
| break; |
| } |
| |
| if (!BnxeReadNvm(pUM, (struct bnxe_nvram_data *)pMblk->b_cont->b_rptr)) |
| { |
| miocnak(pQ, pMblk, 0, EINVAL); |
| } |
| else |
| { |
| miocack(pQ, pMblk, pIoctl->ioc_count, 0); |
| } |
| |
| break; |
| |
| case SIOCBNXENVRM: |
| |
| if ((pIoctl->ioc_count < sizeof(struct bnxe_nvram_data)) || |
| (pMblk->b_cont == NULL) || (pMblk->b_cont->b_rptr == NULL) || |
| (miocpullup(pMblk, pIoctl->ioc_count) < 0)) |
| { |
| miocnak(pQ, pMblk, 0, EINVAL); |
| break; |
| } |
| |
| if (!BnxeWriteNvm(pUM, (struct bnxe_nvram_data *)pMblk->b_cont->b_rptr)) |
| { |
| miocnak(pQ, pMblk, 0, EINVAL); |
| } |
| else |
| { |
| miocack(pQ, pMblk, pIoctl->ioc_count, 0); |
| } |
| |
| break; |
| |
| case GIOCBNXEPCI: |
| |
| if ((pIoctl->ioc_count != sizeof(struct bnxe_reg_data)) || |
| (pMblk->b_cont == NULL) || (pMblk->b_cont->b_rptr == NULL) || |
| (miocpullup(pMblk, sizeof(struct bnxe_reg_data)) < 0)) |
| { |
| miocnak(pQ, pMblk, 0, EINVAL); |
| break; |
| } |
| |
| if (!BnxeReadPciCfg(pUM, (struct bnxe_reg_data *)pMblk->b_cont->b_rptr)) |
| { |
| miocnak(pQ, pMblk, 0, EINVAL); |
| } |
| else |
| { |
| miocack(pQ, pMblk, pIoctl->ioc_count, 0); |
| } |
| |
| break; |
| |
| case GIOCBNXESTATS: |
| |
| /* min size = sizeof(op) in b10_stats_show_data_t */ |
| if ((pIoctl->ioc_count < sizeof(u32_t)) || |
| (pMblk->b_cont == NULL) || (pMblk->b_cont->b_rptr == NULL) || |
| (miocpullup(pMblk, pIoctl->ioc_count) < 0)) |
| { |
| miocnak(pQ, pMblk, 0, EINVAL); |
| break; |
| } |
| |
| if (!BnxeStatsShow(pUM, |
| (b10_stats_show_data_t *)pMblk->b_cont->b_rptr, |
| pIoctl->ioc_count)) |
| { |
| miocnak(pQ, pMblk, 0, EINVAL); |
| } |
| else |
| { |
| miocack(pQ, pMblk, pIoctl->ioc_count, 0); |
| } |
| |
| break; |
| |
| default: |
| |
| miocnak(pQ, pMblk, 0, EINVAL); |
| break; |
| } |
| |
| BNXE_LOCK_EXIT_GLD(pUM); |
| } |
| |
| |
| #ifdef BNXE_RINGS |
| |
| #if (defined(__S11) || defined(__S12)) && !defined(ILLUMOS) |
| static mblk_t * BnxeRxRingPoll(void * ringHandle, |
| int numBytes, |
| int numPkts) |
| #else |
| static mblk_t * BnxeRxRingPoll(void * ringHandle, |
| int numBytes) |
| #endif |
| { |
| RxQueue * pRxQ = (RxQueue *)ringHandle; |
| um_device_t * pUM = (um_device_t *)pRxQ->pUM; |
| u32_t idx = pRxQ->idx; |
| mblk_t * pMblk = NULL; |
| boolean_t pktsRxed = 0; |
| boolean_t pktsTxed = 0; |
| |
| #if (defined(__S11) || defined(__S12)) && !defined(ILLUMOS) |
| _NOTE(ARGUNUSED(numPkts)) |
| #endif |
| |
| if (numBytes <= 0) |
| { |
| return NULL; |
| } |
| |
| if (pRxQ->inPollMode == B_FALSE) |
| { |
| BnxeLogWarn(pUM, "Polling on ring %d when NOT in poll mode!", idx); |
| return NULL; |
| } |
| |
| BNXE_LOCK_ENTER_INTR(pUM, idx); |
| |
| pRxQ->pollCnt++; |
| |
| BnxePollRxRing(pUM, idx, &pktsRxed, &pktsTxed); |
| |
| if (pktsTxed) BnxeTxRingProcess(pUM, idx); |
| if (pktsRxed) pMblk = BnxeRxRingProcess(pUM, idx, TRUE, numBytes); |
| |
| /* |
| * This is here for the off chance that all rings are in polling |
| * mode and the default interrupt hasn't fired recently to handle |
| * the sq. |
| */ |
| lm_sq_post_pending(&pUM->lm_dev); |
| |
| BNXE_LOCK_EXIT_INTR(pUM, idx); |
| |
| return pMblk; |
| } |
| |
| |
| static int BnxeRxRingStart(mac_ring_driver_t ringHandle |
| #if defined(__S11) || defined(__S12) |
| , uint64_t genNumber |
| #endif |
| ) |
| { |
| RxQueue * pRxQ = (RxQueue *)ringHandle; |
| um_device_t * pUM = (um_device_t *)pRxQ->pUM; |
| u32_t idx = pRxQ->idx; |
| |
| BnxeLogDbg(pUM, "Starting Rx Ring %d", idx); |
| |
| BNXE_LOCK_ENTER_RX(pUM, idx); |
| #if defined(__S11) || defined(__S12) |
| pRxQ->genNumber = genNumber; |
| #endif |
| pRxQ->inPollMode = B_FALSE; |
| pRxQ->intrDisableCnt = 0; |
| pRxQ->intrEnableCnt = 0; |
| pRxQ->pollCnt = 0; |
| BNXE_LOCK_EXIT_RX(pUM, idx); |
| |
| return 0; |
| } |
| |
| |
| #if defined(__S11) || defined(__S12) |
| |
| static int BnxeRingStat(mac_ring_driver_t ringHandle, |
| uint_t stat, |
| uint64_t * val) |
| { |
| RxQueue * pRxQ = (RxQueue *)ringHandle; |
| um_device_t * pUM = (um_device_t *)pRxQ->pUM; |
| |
| switch (stat) |
| { |
| case MAC_STAT_OERRORS: |
| case MAC_STAT_OBYTES: |
| case MAC_STAT_OPACKETS: |
| case MAC_STAT_IERRORS: |
| case MAC_STAT_RBYTES: /* MAC_STAT_IBYTES */ |
| case MAC_STAT_IPACKETS: |
| default: |
| return ENOTSUP; |
| } |
| |
| return 0; |
| } |
| |
| #endif /* __S11 or __S12 */ |
| |
| |
| #if defined(__S11) || defined(__S12) |
| static int BnxeRxRingIntrEnable(mac_ring_driver_t ringHandle) |
| #else |
| static int BnxeRxRingIntrEnable(mac_intr_handle_t ringHandle) |
| #endif |
| { |
| RxQueue * pRxQ = (RxQueue *)ringHandle; |
| um_device_t * pUM = (um_device_t *)pRxQ->pUM; |
| |
| BnxeLogDbg(pUM, "Enabling Interrupt for Rx Ring %d", pRxQ->idx); |
| |
| /* polling not allowed on LM_NON_RSS_SB when overlapped with FCoE */ |
| if ((pRxQ->idx == LM_NON_RSS_SB(&pUM->lm_dev)) && |
| CLIENT_BOUND(pUM, LM_CLI_IDX_FCOE) && |
| (pUM->rssIntr.intrCount == LM_MAX_RSS_CHAINS(&pUM->lm_dev))) |
| { |
| return 0; /* ok, already enabled */ |
| } |
| |
| BnxeIntrIguSbEnable(pUM, pRxQ->idx, B_FALSE); |
| |
| return 0; |
| } |
| |
| |
| #if defined(__S11) || defined(__S12) |
| static int BnxeRxRingIntrDisable(mac_ring_driver_t ringHandle) |
| #else |
| static int BnxeRxRingIntrDisable(mac_intr_handle_t ringHandle) |
| #endif |
| { |
| RxQueue * pRxQ = (RxQueue *)ringHandle; |
| um_device_t * pUM = (um_device_t *)pRxQ->pUM; |
| |
| BnxeLogDbg(pUM, "Disabling Interrupt for Rx Ring %d", pRxQ->idx); |
| |
| /* polling not allowed on LM_NON_RSS_SB when overlapped with FCoE */ |
| if ((pRxQ->idx == LM_NON_RSS_SB(&pUM->lm_dev)) && |
| CLIENT_BOUND(pUM, LM_CLI_IDX_FCOE) && |
| (pUM->rssIntr.intrCount == LM_MAX_RSS_CHAINS(&pUM->lm_dev))) |
| { |
| return -1; /* NO, keep enabled! */ |
| } |
| |
| BnxeIntrIguSbDisable(pUM, pRxQ->idx, B_FALSE); |
| |
| return 0; |
| } |
| |
| |
| /* callback function for MAC layer to register rings */ |
| static void BnxeFillRing(void * arg, |
| mac_ring_type_t ringType, |
| const int ringGroupIndex, |
| const int ringIndex, |
| mac_ring_info_t * pRingInfo, |
| mac_ring_handle_t ringHandle) |
| { |
| um_device_t * pUM = (um_device_t *)arg; |
| RxQueue * pRxQ; |
| TxQueue * pTxQ; |
| |
| switch (ringType) |
| { |
| case MAC_RING_TYPE_RX: |
| |
| BnxeLogInfo(pUM, "Initializing Rx Ring %d (Ring Group %d)", |
| ringIndex, ringGroupIndex); |
| |
| ASSERT(ringGroupIndex == 0); |
| ASSERT(ringIndex < pUM->devParams.numRings); |
| |
| pRxQ = &pUM->rxq[ringIndex]; |
| pRxQ->ringHandle = ringHandle; |
| |
| pRingInfo->mri_driver = (mac_ring_driver_t)pRxQ; |
| pRingInfo->mri_start = BnxeRxRingStart; |
| pRingInfo->mri_stop = NULL; |
| #if defined(__S11) || defined(__S12) |
| pRingInfo->mri_stat = BnxeRingStat; |
| #endif |
| pRingInfo->mri_poll = BnxeRxRingPoll; |
| |
| #if !(defined(__S11) || defined(__S12)) |
| pRingInfo->mri_intr.mi_handle = (mac_intr_handle_t)pRxQ; |
| #endif |
| pRingInfo->mri_intr.mi_enable = (mac_intr_enable_t)BnxeRxRingIntrEnable; |
| pRingInfo->mri_intr.mi_disable = (mac_intr_disable_t)BnxeRxRingIntrDisable; |
| |
| break; |
| |
| case MAC_RING_TYPE_TX: |
| |
| BnxeLogInfo(pUM, "Initializing Tx Ring %d (Ring Group %d)", |
| ringIndex, ringGroupIndex); |
| |
| ASSERT(ringGroupIndex == 0); |
| ASSERT(ringIndex < pUM->devParams.numRings); |
| |
| pTxQ = &pUM->txq[ringIndex]; |
| pTxQ->ringHandle = ringHandle; |
| |
| pRingInfo->mri_driver = (mac_ring_driver_t)pTxQ; |
| pRingInfo->mri_start = NULL; |
| pRingInfo->mri_stop = NULL; |
| #if defined(__S11) || defined(__S12) |
| pRingInfo->mri_stat = BnxeRingStat; |
| #endif |
| pRingInfo->mri_tx = (mac_ring_send_t)BnxeTxRingSend; |
| |
| break; |
| |
| default: |
| break; |
| } |
| } |
| |
| |
| /* callback function for MAC layer to register groups */ |
| static void BnxeFillGroup(void * arg, |
| mac_ring_type_t ringType, |
| const int ringGroupIndex, |
| mac_group_info_t * pGroupInfo, |
| mac_group_handle_t groupHandle) |
| { |
| um_device_t * pUM = (um_device_t *)arg; |
| RxQueueGroup * pRxQGroup; |
| |
| switch (ringType) |
| { |
| case MAC_RING_TYPE_RX: |
| |
| BnxeLogInfo(pUM, "Initializing Rx Group %d", ringGroupIndex); |
| |
| pRxQGroup = &pUM->rxqGroup[ringGroupIndex]; |
| pRxQGroup->groupHandle = groupHandle; |
| |
| pGroupInfo->mgi_driver = (mac_group_driver_t)pRxQGroup; |
| pGroupInfo->mgi_start = NULL; |
| pGroupInfo->mgi_stop = NULL; |
| pGroupInfo->mgi_addmac = BnxeRxRingGroupAddMac; |
| pGroupInfo->mgi_remmac = BnxeRxRingGroupRemMac; |
| pGroupInfo->mgi_count = (pUM->devParams.numRings / |
| USER_OPTION_RX_RING_GROUPS_DEFAULT); |
| #if (defined(__S11) || defined(__S12)) && !defined(ILLUMOS) |
| pGroupInfo->mgi_flags = MAC_GROUP_DEFAULT; |
| #endif |
| |
| break; |
| |
| case MAC_RING_TYPE_TX: |
| default: |
| break; |
| } |
| } |
| |
| #endif /* BNXE_RINGS */ |
| |
| |
| static boolean_t BnxeMacGetCapability(void * pArg, |
| mac_capab_t capability, |
| void * pCapabilityData) |
| { |
| um_device_t * pUM = (um_device_t *)pArg; |
| mac_capab_lso_t * pCapLSO; |
| mac_capab_rings_t * pCapRings; |
| |
| switch (capability) |
| { |
| case MAC_CAPAB_HCKSUM: |
| |
| *((u32_t *)pCapabilityData) = 0; |
| |
| if (pUM->devParams.enabled_oflds & |
| (LM_OFFLOAD_TX_IP_CKSUM | LM_OFFLOAD_RX_IP_CKSUM)) |
| { |
| *((u32_t *)pCapabilityData) |= HCKSUM_IPHDRCKSUM; |
| } |
| |
| if (pUM->devParams.enabled_oflds & |
| (LM_OFFLOAD_TX_TCP_CKSUM | LM_OFFLOAD_TX_UDP_CKSUM | |
| LM_OFFLOAD_RX_TCP_CKSUM | LM_OFFLOAD_RX_UDP_CKSUM)) |
| { |
| *((u32_t *)pCapabilityData) |= HCKSUM_INET_PARTIAL; |
| } |
| |
| break; |
| |
| case MAC_CAPAB_LSO: |
| |
| pCapLSO = (mac_capab_lso_t *)pCapabilityData; |
| |
| if (pUM->devParams.lsoEnable) |
| { |
| pCapLSO->lso_flags = LSO_TX_BASIC_TCP_IPV4; |
| pCapLSO->lso_basic_tcp_ipv4.lso_max = BNXE_LSO_MAXLEN; |
| break; |
| } |
| |
| return B_FALSE; |
| |
| #ifdef BNXE_RINGS |
| |
| case MAC_CAPAB_RINGS: |
| |
| if (!pUM->devParams.numRings) |
| { |
| return B_FALSE; |
| } |
| |
| pCapRings = (mac_capab_rings_t *)pCapabilityData; |
| |
| #if (defined(__S11) || defined(__S12)) && !defined(ILLUMOS) |
| pCapRings->mr_version = MAC_RINGS_VERSION_1; |
| pCapRings->mr_flags = MAC_RINGS_FLAGS_NONE; |
| #endif |
| pCapRings->mr_group_type = MAC_GROUP_TYPE_STATIC; |
| pCapRings->mr_rnum = pUM->devParams.numRings; |
| pCapRings->mr_rget = BnxeFillRing; |
| pCapRings->mr_gaddring = NULL; |
| pCapRings->mr_gremring = NULL; |
| #if (defined(__S11) || defined(__S12)) && !defined(ILLUMOS) |
| pCapRings->mr_ggetringtc = NULL; |
| #endif |
| |
| switch (pCapRings->mr_type) |
| { |
| case MAC_RING_TYPE_RX: |
| |
| pCapRings->mr_gnum = USER_OPTION_RX_RING_GROUPS_DEFAULT; |
| pCapRings->mr_gget = BnxeFillGroup; |
| break; |
| |
| case MAC_RING_TYPE_TX: |
| |
| #if (defined(__S11) || defined(__S12)) && !defined(ILLUMOS) |
| pCapRings->mr_gnum = 1; |
| #else |
| pCapRings->mr_gnum = 0; |
| #endif |
| pCapRings->mr_gget = NULL; |
| break; |
| |
| default: |
| |
| return B_FALSE; |
| } |
| |
| break; |
| |
| #endif /* BNXE_RINGS */ |
| |
| #if !(defined(__S11) || defined(__S12)) |
| |
| case MAC_CAPAB_POLL: |
| |
| /* |
| * There's nothing for us to fill in, simply returning B_TRUE stating |
| * that we support polling is sufficient. |
| */ |
| break; |
| |
| #endif /* not __S11 or __S12 */ |
| |
| #if defined(ILLUMOS) |
| case MAC_CAPAB_TRANSCEIVER: |
| return bnxe_fill_transceiver(pUM, pCapabilityData); |
| #endif |
| |
| default: |
| |
| return B_FALSE; |
| } |
| |
| return B_TRUE; |
| } |
| |
| |
| #ifdef MC_SETPROP |
| |
| static int BnxeSetPrivateProperty(um_device_t * pUM, |
| const char * pr_name, |
| uint_t pr_valsize, |
| const void * pr_val) |
| { |
| int err = 0; |
| long result; |
| |
| if (strcmp(pr_name, "_en_2500fdx_cap") == 0) |
| { |
| if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) |
| { |
| return EINVAL; |
| } |
| |
| if ((result > 1) || (result < 0)) |
| { |
| return EINVAL; |
| } |
| |
| pUM->hwinit.lnkcfg.param_2500fdx = (uint32_t)result; |
| pUM->curcfg.lnkcfg.param_2500fdx = (uint32_t)result; |
| if (pUM->plumbed) BnxeUpdatePhy(pUM); |
| } |
| else if (strcmp(pr_name, "_en_txpause_cap") == 0) |
| { |
| if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) |
| { |
| return EINVAL; |
| } |
| |
| if ((result > 1) || (result < 0)) |
| { |
| return EINVAL; |
| } |
| |
| pUM->hwinit.lnkcfg.param_txpause = (uint32_t)result; |
| pUM->curcfg.lnkcfg.param_txpause = (uint32_t)result; |
| if (pUM->plumbed) BnxeUpdatePhy(pUM); |
| } |
| else if (strcmp(pr_name, "_en_rxpause_cap") == 0) |
| { |
| if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) |
| { |
| return EINVAL; |
| } |
| |
| if ((result > 1) || (result < 0)) |
| { |
| return EINVAL; |
| } |
| |
| pUM->hwinit.lnkcfg.param_rxpause = (uint32_t)result; |
| pUM->curcfg.lnkcfg.param_rxpause = (uint32_t)result; |
| if (pUM->plumbed) BnxeUpdatePhy(pUM); |
| } |
| else if (strcmp(pr_name, "_autoneg_flow") == 0) |
| { |
| if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) |
| { |
| return EINVAL; |
| } |
| |
| if ((result > 1) || (result < 0)) |
| { |
| return EINVAL; |
| } |
| |
| pUM->hwinit.flow_autoneg = (uint32_t)result; |
| pUM->curcfg.flow_autoneg = (uint32_t)result; |
| if (pUM->plumbed) BnxeUpdatePhy(pUM); |
| } |
| else if (strcmp(pr_name, "_checksum") == 0) |
| { |
| if (pUM->plumbed) |
| { |
| return EBUSY; |
| } |
| |
| if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) |
| { |
| return EINVAL; |
| } |
| |
| switch (result) |
| { |
| case USER_OPTION_CKSUM_NONE: |
| |
| pUM->devParams.enabled_oflds = LM_OFFLOAD_NONE; |
| break; |
| |
| case USER_OPTION_CKSUM_L3: |
| |
| pUM->devParams.enabled_oflds = (LM_OFFLOAD_TX_IP_CKSUM | |
| LM_OFFLOAD_RX_IP_CKSUM); |
| break; |
| |
| case USER_OPTION_CKSUM_L3_L4: |
| |
| pUM->devParams.enabled_oflds = (LM_OFFLOAD_TX_IP_CKSUM | |
| LM_OFFLOAD_RX_IP_CKSUM | |
| LM_OFFLOAD_TX_TCP_CKSUM | |
| LM_OFFLOAD_RX_TCP_CKSUM | |
| LM_OFFLOAD_TX_UDP_CKSUM | |
| LM_OFFLOAD_RX_UDP_CKSUM); |
| break; |
| |
| default: |
| |
| return EINVAL; |
| } |
| |
| pUM->devParams.checksum = (uint32_t)result; |
| } |
| else if (strcmp(pr_name, "_tx_ring_policy") == 0) |
| { |
| if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) |
| { |
| return EINVAL; |
| } |
| |
| switch (result) |
| { |
| case BNXE_ROUTE_RING_NONE: |
| case BNXE_ROUTE_RING_TCPUDP: |
| case BNXE_ROUTE_RING_DEST_MAC: |
| case BNXE_ROUTE_RING_MSG_PRIO: |
| |
| break; |
| |
| default: |
| |
| return EINVAL; |
| } |
| |
| pUM->devParams.routeTxRingPolicy = (uint32_t)result; |
| } |
| else if (strcmp(pr_name, "_num_rings") == 0) |
| { |
| if (pUM->plumbed) |
| { |
| return EBUSY; |
| } |
| |
| if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) |
| { |
| return EINVAL; |
| } |
| |
| if ((result < USER_OPTION_NUM_RINGS_MIN) || |
| (result > USER_OPTION_NUM_RINGS_MAX)) |
| { |
| return EINVAL; |
| } |
| |
| pUM->devParams.numRings = (uint32_t)result; |
| } |
| else if (strcmp(pr_name, "_rx_descs") == 0) |
| { |
| if (pUM->plumbed) |
| { |
| return EBUSY; |
| } |
| |
| if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) |
| { |
| return EINVAL; |
| } |
| |
| if ((result < USER_OPTION_BDS_MIN) || (result > USER_OPTION_BDS_MAX)) |
| { |
| return EINVAL; |
| } |
| |
| pUM->devParams.numRxDesc[LM_CLI_IDX_NDIS] = (uint32_t)result; |
| } |
| else if (strcmp(pr_name, "_rx_free_reclaim") == 0) |
| { |
| if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) |
| { |
| return EINVAL; |
| } |
| |
| if ((result < USER_OPTION_BDS_MIN) || (result > USER_OPTION_BDS_MAX)) |
| { |
| return EINVAL; |
| } |
| |
| pUM->devParams.maxRxFree = (uint32_t)result; |
| } |
| else if (strcmp(pr_name, "_tx_descs") == 0) |
| { |
| if (pUM->plumbed) |
| { |
| return EBUSY; |
| } |
| |
| if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) |
| { |
| return EINVAL; |
| } |
| |
| if ((result < USER_OPTION_BDS_MIN) || (result > USER_OPTION_BDS_MAX)) |
| { |
| return EINVAL; |
| } |
| |
| pUM->devParams.numTxDesc[LM_CLI_IDX_NDIS] = (uint32_t)result; |
| } |
| else if (strcmp(pr_name, "_tx_free_reclaim") == 0) |
| { |
| if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) |
| { |
| return EINVAL; |
| } |
| |
| if ((result < USER_OPTION_BDS_MIN) || (result > USER_OPTION_BDS_MAX)) |
| { |
| return EINVAL; |
| } |
| |
| pUM->devParams.maxTxFree = (uint32_t)result; |
| } |
| else if (strcmp(pr_name, "_rx_copy_threshold") == 0) |
| { |
| if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) |
| { |
| return EINVAL; |
| } |
| |
| pUM->devParams.rxCopyThreshold = (uint32_t)result; |
| } |
| else if (strcmp(pr_name, "_tx_copy_threshold") == 0) |
| { |
| if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) |
| { |
| return EINVAL; |
| } |
| |
| pUM->devParams.txCopyThreshold = (uint32_t)result; |
| } |
| else if (strcmp(pr_name, "_interrupt_coalesce") == 0) |
| { |
| if (pUM->plumbed) |
| { |
| return EBUSY; |
| } |
| |
| if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) |
| { |
| return EINVAL; |
| } |
| |
| if ((result > 1) || (result < 0)) |
| { |
| return EINVAL; |
| } |
| |
| pUM->devParams.intrCoalesce = (uint32_t)result; |
| } |
| else if (strcmp(pr_name, "_rx_interrupt_coalesce_usec") == 0) |
| { |
| if (pUM->plumbed) |
| { |
| return EBUSY; |
| } |
| |
| if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) |
| { |
| return EINVAL; |
| } |
| |
| if ((result < USER_OPTION_INTR_COALESCE_MIN) || |
| (result < USER_OPTION_INTR_COALESCE_MAX)) |
| { |
| return EINVAL; |
| } |
| |
| pUM->devParams.intrRxPerSec = (uint32_t)(1000000 / result); |
| } |
| else if (strcmp(pr_name, "_tx_interrupt_coalesce_usec") == 0) |
| { |
| if (pUM->plumbed) |
| { |
| return EBUSY; |
| } |
| |
| if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) |
| { |
| return EINVAL; |
| } |
| |
| if ((result < USER_OPTION_INTR_COALESCE_MIN) || |
| (result < USER_OPTION_INTR_COALESCE_MAX)) |
| { |
| return EINVAL; |
| } |
| |
| pUM->devParams.intrTxPerSec = (uint32_t)(1000000 / result); |
| } |
| else if (strcmp(pr_name, "_disable_msix") == 0) |
| { |
| if (pUM->plumbed) |
| { |
| return EBUSY; |
| } |
| |
| if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) |
| { |
| return EINVAL; |
| } |
| |
| if ((result > 1) || (result < 0)) |
| { |
| return EINVAL; |
| } |
| |
| pUM->devParams.disableMsix = (uint32_t)result; |
| } |
| else if (strcmp(pr_name, "_l2_fw_flow_ctrl") == 0) |
| { |
| if (pUM->plumbed) |
| { |
| return EBUSY; |
| } |
| |
| if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) |
| { |
| return EINVAL; |
| } |
| |
| if ((result > 1) || (result < 0)) |
| { |
| return EINVAL; |
| } |
| |
| pUM->devParams.l2_fw_flow_ctrl = (uint32_t)result; |
| } |
| else if (strcmp(pr_name, "_autogreeen_enable") == 0) |
| { |
| if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) |
| { |
| return EINVAL; |
| } |
| |
| if ((result > 1) || (result < 0)) |
| { |
| return EINVAL; |
| } |
| |
| pUM->devParams.autogreeenEnable = (uint32_t)result; |
| if (pUM->plumbed) BnxeUpdatePhy(pUM); |
| } |
| else if (strcmp(pr_name, "_lso_enable") == 0) |
| { |
| if (pUM->plumbed) |
| { |
| return EBUSY; |
| } |
| |
| if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) |
| { |
| return EINVAL; |
| } |
| |
| if ((result > 1) || (result < 0)) |
| { |
| return EINVAL; |
| } |
| |
| pUM->devParams.lsoEnable = (uint32_t)result; |
| } |
| else if (strcmp(pr_name, "_log_enable") == 0) |
| { |
| if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) |
| { |
| return EINVAL; |
| } |
| |
| if ((result > 1) || (result < 0)) |
| { |
| return EINVAL; |
| } |
| |
| pUM->devParams.logEnable = (uint32_t)result; |
| } |
| else if (strcmp(pr_name, "_fcoe_enable") == 0) |
| { |
| if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) |
| { |
| return EINVAL; |
| } |
| |
| if ((result > 1) || (result < 0)) |
| { |
| return EINVAL; |
| } |
| |
| pUM->devParams.fcoeEnable = (uint32_t)result; |
| |
| if (BNXE_FCOE(pUM)) |
| { |
| BnxeFcoeStartStop(pUM); |
| } |
| } |
| else |
| { |
| err = ENOTSUP; |
| } |
| |
| return err; |
| } |
| |
| |
| static int BnxeMacSetProperty(void * barg, |
| const char * pr_name, |
| mac_prop_id_t pr_num, |
| uint_t pr_valsize, |
| const void * pr_val) |
| { |
| um_device_t * pUM = barg; |
| boolean_t reprogram = B_FALSE; |
| boolean_t rxpause; |
| boolean_t txpause; |
| uint32_t mtu; |
| link_flowctrl_t fl; |
| int err = 0; |
| |
| BNXE_LOCK_ENTER_GLD(pUM); |
| |
| switch (pr_num) |
| { |
| /* read-only props */ |
| case MAC_PROP_STATUS: |
| case MAC_PROP_SPEED: |
| case MAC_PROP_DUPLEX: |
| |
| case MAC_PROP_ADV_10GFDX_CAP: |
| case MAC_PROP_ADV_1000FDX_CAP: |
| case MAC_PROP_ADV_1000HDX_CAP: |
| case MAC_PROP_ADV_100FDX_CAP: |
| case MAC_PROP_ADV_100HDX_CAP: |
| case MAC_PROP_ADV_10FDX_CAP: |
| case MAC_PROP_ADV_10HDX_CAP: |
| case MAC_PROP_ADV_100T4_CAP: |
| |
| case MAC_PROP_EN_1000HDX_CAP: |
| case MAC_PROP_EN_100T4_CAP: |
| |
| default: |
| |
| err = ENOTSUP; |
| break; |
| |
| case MAC_PROP_EN_10GFDX_CAP: |
| |
| pUM->hwinit.lnkcfg.param_10000fdx = *(uint8_t *)pr_val; |
| pUM->curcfg.lnkcfg.param_10000fdx = *(uint8_t *)pr_val; |
| reprogram = B_TRUE; |
| break; |
| |
| case MAC_PROP_EN_1000FDX_CAP: |
| |
| pUM->hwinit.lnkcfg.param_1000fdx = *(uint8_t *)pr_val; |
| pUM->curcfg.lnkcfg.param_1000fdx = *(uint8_t *)pr_val; |
| reprogram = B_TRUE; |
| break; |
| |
| case MAC_PROP_EN_100FDX_CAP: |
| |
| pUM->hwinit.lnkcfg.param_100fdx = *(uint8_t *)pr_val; |
| pUM->curcfg.lnkcfg.param_100fdx = *(uint8_t *)pr_val; |
| reprogram = B_TRUE; |
| break; |
| |
| case MAC_PROP_EN_100HDX_CAP: |
| |
| pUM->hwinit.lnkcfg.param_100hdx = *(uint8_t *)pr_val; |
| pUM->curcfg.lnkcfg.param_100hdx = *(uint8_t *)pr_val; |
| reprogram = B_TRUE; |
| break; |
| |
| case MAC_PROP_EN_10FDX_CAP: |
| |
| pUM->hwinit.lnkcfg.param_10fdx = *(uint8_t *)pr_val; |
| pUM->curcfg.lnkcfg.param_10fdx = *(uint8_t *)pr_val; |
| reprogram = B_TRUE; |
| break; |
| |
| case MAC_PROP_EN_10HDX_CAP: |
| |
| pUM->hwinit.lnkcfg.param_10hdx = *(uint8_t *)pr_val; |
| pUM->curcfg.lnkcfg.param_10hdx = *(uint8_t *)pr_val; |
| reprogram = B_TRUE; |
| break; |
| |
| case MAC_PROP_AUTONEG: |
| |
| pUM->hwinit.lnkcfg.link_autoneg = *(uint8_t *)pr_val; |
| pUM->curcfg.lnkcfg.link_autoneg = *(uint8_t *)pr_val; |
| reprogram = B_TRUE; |
| break; |
| |
| case MAC_PROP_FLOWCTRL: |
| |
| bcopy(pr_val, &fl, sizeof(fl)); |
| |
| switch (fl) |
| { |
| case LINK_FLOWCTRL_NONE: |
| |
| rxpause = B_FALSE; |
| txpause = B_FALSE; |
| break; |
| |
| case LINK_FLOWCTRL_RX: |
| |
| rxpause = B_TRUE; |
| txpause = B_FALSE; |
| break; |
| |
| case LINK_FLOWCTRL_TX: |
| |
| rxpause = B_FALSE; |
| txpause = B_TRUE; |
| break; |
| |
| case LINK_FLOWCTRL_BI: |
| |
| rxpause = B_TRUE; |
| txpause = B_TRUE; |
| break; |
| |
| default: |
| |
| err = ENOTSUP; |
| break; |
| } |
| |
| if (err == 0) |
| { |
| pUM->hwinit.lnkcfg.param_rxpause = rxpause; |
| pUM->hwinit.lnkcfg.param_txpause = txpause; |
| pUM->curcfg.lnkcfg.param_rxpause = rxpause; |
| pUM->curcfg.lnkcfg.param_txpause = txpause; |
| reprogram = B_TRUE; |
| } |
| |
| break; |
| |
| case MAC_PROP_MTU: |
| |
| if (pUM->plumbed) |
| { |
| err = EBUSY; |
| break; |
| } |
| |
| bcopy(pr_val, &mtu, sizeof (mtu)); |
| |
| if ((mtu < USER_OPTION_MTU_MIN) || (mtu > USER_OPTION_MTU_MAX)) |
| { |
| err = EINVAL; |
| break; |
| } |
| |
| if (pUM->devParams.mtu[LM_CLI_IDX_NDIS] == mtu) |
| { |
| break; |
| } |
| |
| pUM->devParams.mtu[LM_CLI_IDX_NDIS] = mtu; |
| err = mac_maxsdu_update(pUM->pMac, pUM->devParams.mtu[LM_CLI_IDX_NDIS]); |
| pUM->lm_dev.params.mtu[LM_CLI_IDX_NDIS] = pUM->devParams.mtu[LM_CLI_IDX_NDIS]; |
| break; |
| |
| case MAC_PROP_PRIVATE: |
| |
| err = BnxeSetPrivateProperty(pUM, pr_name, pr_valsize, pr_val); |
| break; |
| } |
| |
| if (!err && reprogram) |
| { |
| if (pUM->plumbed) BnxeUpdatePhy(pUM); |
| } |
| |
| BNXE_LOCK_EXIT_GLD(pUM); |
| return err; |
| } |
| |
| #endif /* MC_SETPROP */ |
| |
| |
| #ifdef MC_GETPROP |
| |
| static int BnxeGetPrivateProperty(um_device_t * pUM, |
| const char * pr_name, |
| uint_t pr_valsize, |
| void * pr_val) |
| { |
| BnxeLinkCfg * lnk_cfg = &pUM->curcfg.lnkcfg; |
| BnxeLinkCfg * hw_cfg = &pUM->hwinit.lnkcfg; |
| int value; |
| int err = 0; |
| |
| if (strcmp(pr_name, "_adv_2500fdx_cap") == 0) |
| { |
| value = lnk_cfg->param_2500fdx; |
| } |
| else if (strcmp(pr_name, "_en_2500fdx_cap") == 0) |
| { |
| value = hw_cfg->param_2500fdx; |
| } |
| else if (strcmp(pr_name, "_adv_txpause_cap") == 0) |
| { |
| value = lnk_cfg->param_txpause; |
| } |
| else if (strcmp(pr_name, "_en_txpause_cap") == 0) |
| { |
| value = hw_cfg->param_txpause; |
| } |
| else if (strcmp(pr_name, "_txpause") == 0) |
| { |
| value = pUM->props.link_txpause; |
| } |
| else if (strcmp(pr_name, "_adv_rxpause_cap") == 0) |
| { |
| value = lnk_cfg->param_rxpause; |
| } |
| else if (strcmp(pr_name, "_en_rxpause_cap") == 0) |
| { |
| value = hw_cfg->param_rxpause; |
| } |
| else if (strcmp(pr_name, "_rxpause") == 0) |
| { |
| value = pUM->props.link_rxpause; |
| } |
| else if (strcmp(pr_name, "_autoneg_flow") == 0) |
| { |
| value = pUM->hwinit.flow_autoneg; |
| } |
| else if (strcmp(pr_name, "_checksum") == 0) |
| { |
| value = pUM->devParams.checksum; |
| } |
| else if (strcmp(pr_name, "_tx_ring_policy") == 0) |
| { |
| value = pUM->devParams.routeTxRingPolicy; |
| } |
| else if (strcmp(pr_name, "_num_rings") == 0) |
| { |
| value = pUM->devParams.numRings; |
| } |
| else if (strcmp(pr_name, "_rx_descs") == 0) |
| { |
| value = pUM->devParams.numRxDesc[LM_CLI_IDX_NDIS]; |
| } |
| else if (strcmp(pr_name, "_rx_free_reclaim") == 0) |
| { |
| value = pUM->devParams.maxRxFree; |
| } |
| else if (strcmp(pr_name, "_tx_descs") == 0) |
| { |
| value = pUM->devParams.numTxDesc[LM_CLI_IDX_NDIS]; |
| } |
| else if (strcmp(pr_name, "_tx_free_reclaim") == 0) |
| { |
| value = pUM->devParams.maxTxFree; |
| } |
| else if (strcmp(pr_name, "_rx_copy_threshold") == 0) |
| { |
| value = pUM->devParams.rxCopyThreshold; |
| } |
| else if (strcmp(pr_name, "_tx_copy_threshold") == 0) |
| { |
| value = pUM->devParams.txCopyThreshold; |
| } |
| else if (strcmp(pr_name, "_interrupt_coalesce") == 0) |
| { |
| value = pUM->devParams.intrCoalesce; |
| } |
| else if (strcmp(pr_name, "_rx_interrupt_coalesce_usec") == 0) |
| { |
| value = pUM->devParams.intrRxPerSec; |
| } |
| else if (strcmp(pr_name, "_tx_interrupt_coalesce_usec") == 0) |
| { |
| value = pUM->devParams.intrTxPerSec; |
| } |
| else if (strcmp(pr_name, "_disable_msix") == 0) |
| { |
| value = pUM->devParams.disableMsix; |
| } |
| else if (strcmp(pr_name, "_l2_fw_flow_ctrl") == 0) |
| { |
| value = pUM->devParams.l2_fw_flow_ctrl; |
| } |
| else if (strcmp(pr_name, "_autogreeen_enable") == 0) |
| { |
| value = pUM->devParams.autogreeenEnable; |
| } |
| else if (strcmp(pr_name, "_lso_enable") == 0) |
| { |
| value = pUM->devParams.lsoEnable; |
| } |
| else if (strcmp(pr_name, "_log_enable") == 0) |
| { |
| value = pUM->devParams.logEnable; |
| } |
| else if (strcmp(pr_name, "_fcoe_enable") == 0) |
| { |
| value = pUM->devParams.fcoeEnable; |
| } |
| else |
| { |
| err = ENOTSUP; |
| } |
| |
| if (!err) |
| { |
| (void)snprintf(pr_val, pr_valsize, "%d", value); |
| } |
| |
| return err; |
| } |
| |
| |
| static int BnxeMacGetProperty(void * barg, |
| const char * pr_name, |
| mac_prop_id_t pr_num, |
| uint_t pr_valsize, |
| void * pr_val) |
| { |
| um_device_t * pUM = barg; |
| link_flowctrl_t link_flowctrl; |
| link_state_t link_state; |
| link_duplex_t link_duplex; |
| uint64_t link_speed; |
| BnxeLinkCfg * lnk_cfg = &pUM->curcfg.lnkcfg; |
| BnxeLinkCfg * hw_cfg = &pUM->hwinit.lnkcfg; |
| |
| switch (pr_num) |
| { |
| case MAC_PROP_MTU: |
| |
| ASSERT(pr_valsize >= sizeof(u32_t)); |
| |
| bcopy(&pUM->devParams.mtu[LM_CLI_IDX_NDIS], pr_val, sizeof(u32_t)); |
| break; |
| |
| case MAC_PROP_DUPLEX: |
| |
| ASSERT(pr_valsize >= sizeof(link_duplex_t)); |
| |
| link_duplex = pUM->props.link_duplex ? |
| LINK_DUPLEX_FULL : LINK_DUPLEX_HALF; |
| bcopy(&link_duplex, pr_val, sizeof(link_duplex_t)); |
| break; |
| |
| case MAC_PROP_SPEED: |
| |
| ASSERT(pr_valsize >= sizeof(link_speed)); |
| |
| link_speed = (pUM->props.link_speed * 1000000ULL); |
| bcopy(&link_speed, pr_val, sizeof(link_speed)); |
| break; |
| |
| case MAC_PROP_STATUS: |
| |
| ASSERT(pr_valsize >= sizeof(link_state_t)); |
| |
| link_state = pUM->props.link_speed ? |
| LINK_STATE_UP : LINK_STATE_DOWN; |
| bcopy(&link_state, pr_val, sizeof(link_state_t)); |
| break; |
| |
| case MAC_PROP_AUTONEG: |
| |
| *(uint8_t *)pr_val = lnk_cfg->link_autoneg; |
| break; |
| |
| case MAC_PROP_FLOWCTRL: |
| |
| ASSERT(pr_valsize >= sizeof(link_flowctrl_t)); |
| |
| if (!lnk_cfg->param_rxpause && !lnk_cfg->param_txpause) |
| { |
| link_flowctrl = LINK_FLOWCTRL_NONE; |
| } |
| if (lnk_cfg->param_rxpause && !lnk_cfg->param_txpause) |
| { |
| link_flowctrl = LINK_FLOWCTRL_RX; |
| } |
| if (!lnk_cfg->param_rxpause && lnk_cfg->param_txpause) |
| { |
| link_flowctrl = LINK_FLOWCTRL_TX; |
| } |
| if (lnk_cfg->param_rxpause && lnk_cfg->param_txpause) |
| { |
| link_flowctrl = LINK_FLOWCTRL_BI; |
| } |
| |
| bcopy(&link_flowctrl, pr_val, sizeof(link_flowctrl_t)); |
| break; |
| |
| case MAC_PROP_ADV_10GFDX_CAP: |
| |
| *(uint8_t *)pr_val = lnk_cfg->param_10000fdx; |
| break; |
| |
| case MAC_PROP_EN_10GFDX_CAP: |
| |
| *(uint8_t *)pr_val = hw_cfg->param_10000fdx; |
| break; |
| |
| case MAC_PROP_ADV_1000FDX_CAP: |
| |
| *(uint8_t *)pr_val = lnk_cfg->param_1000fdx; |
| break; |
| |
| case MAC_PROP_EN_1000FDX_CAP: |
| |
| *(uint8_t *)pr_val = hw_cfg->param_1000fdx; |
| break; |
| |
| case MAC_PROP_ADV_1000HDX_CAP: |
| case MAC_PROP_EN_1000HDX_CAP: |
| |
| *(uint8_t *)pr_val = 0; |
| break; |
| |
| case MAC_PROP_ADV_100FDX_CAP: |
| |
| *(uint8_t *)pr_val = lnk_cfg->param_100fdx; |
| break; |
| |
| case MAC_PROP_EN_100FDX_CAP: |
| |
| *(uint8_t *)pr_val = hw_cfg->param_100fdx; |
| break; |
| |
| case MAC_PROP_ADV_100HDX_CAP: |
| |
| *(uint8_t *)pr_val = lnk_cfg->param_100hdx; |
| break; |
| |
| case MAC_PROP_EN_100HDX_CAP: |
| |
| *(uint8_t *)pr_val = hw_cfg->param_100hdx; |
| break; |
| |
| case MAC_PROP_ADV_100T4_CAP: |
| case MAC_PROP_EN_100T4_CAP: |
| |
| *(uint8_t *)pr_val = 0; |
| break; |
| |
| case MAC_PROP_ADV_10FDX_CAP: |
| |
| *(uint8_t *)pr_val = lnk_cfg->param_10fdx; |
| break; |
| |
| case MAC_PROP_EN_10FDX_CAP: |
| |
| *(uint8_t *)pr_val = hw_cfg->param_10fdx; |
| break; |
| |
| case MAC_PROP_ADV_10HDX_CAP: |
| |
| *(uint8_t *)pr_val = lnk_cfg->param_10hdx; |
| break; |
| |
| case MAC_PROP_EN_10HDX_CAP: |
| |
| *(uint8_t *)pr_val = hw_cfg->param_10hdx; |
| break; |
| |
| case MAC_PROP_PRIVATE: |
| |
| return BnxeGetPrivateProperty(pUM, |
| pr_name, |
| pr_valsize, |
| pr_val); |
| |
| default: |
| |
| return ENOTSUP; |
| } |
| |
| return 0; |
| } |
| |
| #endif /* MC_GETPROP */ |
| |
| |
| #ifdef MC_PROPINFO |
| |
| static void BnxeMacPrivatePropertyInfo(um_device_t * pUM, |
| const char * pr_name, |
| mac_prop_info_handle_t prh) |
| { |
| char valstr[64]; |
| BnxeLinkCfg * default_cfg = &bnxeLinkCfg; |
| int default_val; |
| |
| bzero(valstr, sizeof (valstr)); |
| |
| if ((strcmp(pr_name, "_adv_2500fdx_cap") == 0) || |
| (strcmp(pr_name, "_adv_txpause_cap") == 0) || |
| (strcmp(pr_name, "_txpause") == 0) || |
| (strcmp(pr_name, "_adv_rxpause_cap") == 0) || |
| (strcmp(pr_name, "_rxpause") == 0) || |
| (strcmp(pr_name, "_checksum") == 0) || |
| (strcmp(pr_name, "_num_rings") == 0) || |
| (strcmp(pr_name, "_rx_descs") == 0) || |
| (strcmp(pr_name, "_tx_descs") == 0) || |
| (strcmp(pr_name, "_interrupt_coalesce") == 0) || |
| (strcmp(pr_name, "_rx_interrupt_coalesce_usec") == 0) || |
| (strcmp(pr_name, "_tx_interrupt_coalesce_usec") == 0) || |
| (strcmp(pr_name, "_disable_msix") == 0) || |
| (strcmp(pr_name, "_l2_fw_flow_ctrl") == 0) || |
| (strcmp(pr_name, "_lso_enable") == 0)) |
| { |
| mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); |
| return; |
| } |
| |
| if (strcmp(pr_name, "_autoneg_flow") == 0) |
| { |
| default_val = B_TRUE; |
| } |
| else if (strcmp(pr_name, "_tx_ring_policy") == 0) |
| { |
| default_val = BNXE_ROUTE_RING_TCPUDP; |
| } |
| else if (strcmp(pr_name, "_rx_free_reclaim") == 0) |
| { |
| default_val = USER_OPTION_RX_MAX_FREE_DEFAULT; |
| } |
| else if (strcmp(pr_name, "_tx_free_reclaim") == 0) |
| { |
| default_val = USER_OPTION_TX_MAX_FREE_DEFAULT; |
| } |
| else if (strcmp(pr_name, "_rx_copy_threshold") == 0) |
| { |
| default_val = USER_OPTION_RX_DCOPY_THRESH_DEFAULT; |
| } |
| else if (strcmp(pr_name, "_tx_copy_threshold") == 0) |
| { |
| default_val = USER_OPTION_TX_DCOPY_THRESH_DEFAULT; |
| } |
| else if (strcmp(pr_name, "_autogreeen_enable") == 0) |
| { |
| default_val = B_TRUE; |
| } |
| else if (strcmp(pr_name, "_log_enable") == 0) |
| { |
| default_val = B_TRUE; |
| } |
| else if (strcmp(pr_name, "_fcoe_enable") == 0) |
| { |
| default_val = B_TRUE; |
| } |
| else |
| { |
| return; |
| } |
| |
| snprintf(valstr, sizeof (valstr), "%d", default_val); |
| mac_prop_info_set_default_str(prh, valstr); |
| } |
| |
| |
| static void BnxeMacPropertyInfo(void * barg, |
| const char * pr_name, |
| mac_prop_id_t pr_num, |
| mac_prop_info_handle_t prh) |
| { |
| um_device_t * pUM = barg; |
| link_flowctrl_t link_flowctrl; |
| BnxeLinkCfg * default_cfg = &bnxeLinkCfg; |
| |
| switch (pr_num) |
| { |
| case MAC_PROP_STATUS: |
| case MAC_PROP_SPEED: |
| case MAC_PROP_DUPLEX: |
| |
| case MAC_PROP_ADV_10GFDX_CAP: |
| case MAC_PROP_ADV_1000FDX_CAP: |
| case MAC_PROP_ADV_1000HDX_CAP: |
| case MAC_PROP_ADV_100FDX_CAP: |
| case MAC_PROP_ADV_100HDX_CAP: |
| case MAC_PROP_ADV_100T4_CAP: |
| case MAC_PROP_ADV_10FDX_CAP: |
| case MAC_PROP_ADV_10HDX_CAP: |
| |
| case MAC_PROP_EN_1000HDX_CAP: |
| case MAC_PROP_EN_100T4_CAP: |
| |
| mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); |
| break; |
| |
| case MAC_PROP_EN_10GFDX_CAP: |
| |
| mac_prop_info_set_default_uint8(prh, default_cfg->param_10000fdx); |
|