diff options
Diffstat (limited to 'drivers/net/ethernet/emulex/benet/be_ethtool.c')
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_ethtool.c | 187 |
1 files changed, 96 insertions, 91 deletions
diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c index 802e5ddef8a..c1ff73cb0e6 100644 --- a/drivers/net/ethernet/emulex/benet/be_ethtool.c +++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c @@ -37,20 +37,46 @@ enum {DRVSTAT_TX, DRVSTAT_RX, DRVSTAT}; FIELDINFO(struct be_drv_stats, field) static const struct be_ethtool_stat et_stats[] = { - {DRVSTAT_INFO(tx_events)}, {DRVSTAT_INFO(rx_crc_errors)}, {DRVSTAT_INFO(rx_alignment_symbol_errors)}, {DRVSTAT_INFO(rx_pause_frames)}, {DRVSTAT_INFO(rx_control_frames)}, + /* Received packets dropped when the Ethernet length field + * is not equal to the actual Ethernet data length. + */ {DRVSTAT_INFO(rx_in_range_errors)}, + /* Received packets dropped when their length field is >= 1501 bytes + * and <= 1535 bytes. + */ {DRVSTAT_INFO(rx_out_range_errors)}, + /* Received packets dropped when they are longer than 9216 bytes */ {DRVSTAT_INFO(rx_frame_too_long)}, - {DRVSTAT_INFO(rx_address_match_errors)}, + /* Received packets dropped when they don't pass the unicast or + * multicast address filtering. + */ + {DRVSTAT_INFO(rx_address_mismatch_drops)}, + /* Received packets dropped when IP packet length field is less than + * the IP header length field. + */ {DRVSTAT_INFO(rx_dropped_too_small)}, + /* Received packets dropped when IP length field is greater than + * the actual packet length. + */ {DRVSTAT_INFO(rx_dropped_too_short)}, + /* Received packets dropped when the IP header length field is less + * than 5. + */ {DRVSTAT_INFO(rx_dropped_header_too_small)}, + /* Received packets dropped when the TCP header length field is less + * than 5 or the TCP header length + IP header length is more + * than IP packet length. + */ {DRVSTAT_INFO(rx_dropped_tcp_length)}, {DRVSTAT_INFO(rx_dropped_runt)}, + /* Number of received packets dropped when a fifo for descriptors going + * into the packet demux block overflows. In normal operation, this + * fifo must never overflow. + */ {DRVSTAT_INFO(rxpp_fifo_overflow_drop)}, {DRVSTAT_INFO(rx_input_fifo_overflow_drop)}, {DRVSTAT_INFO(rx_ip_checksum_errs)}, @@ -59,16 +85,35 @@ static const struct be_ethtool_stat et_stats[] = { {DRVSTAT_INFO(tx_pauseframes)}, {DRVSTAT_INFO(tx_controlframes)}, {DRVSTAT_INFO(rx_priority_pause_frames)}, + /* Received packets dropped when an internal fifo going into + * main packet buffer tank (PMEM) overflows. + */ {DRVSTAT_INFO(pmem_fifo_overflow_drop)}, {DRVSTAT_INFO(jabber_events)}, + /* Received packets dropped due to lack of available HW packet buffers + * used to temporarily hold the received packets. + */ {DRVSTAT_INFO(rx_drops_no_pbuf)}, - {DRVSTAT_INFO(rx_drops_no_txpb)}, + /* Received packets dropped due to input receive buffer + * descriptor fifo overflowing. + */ {DRVSTAT_INFO(rx_drops_no_erx_descr)}, + /* Packets dropped because the internal FIFO to the offloaded TCP + * receive processing block is full. This could happen only for + * offloaded iSCSI or FCoE trarffic. + */ {DRVSTAT_INFO(rx_drops_no_tpre_descr)}, + /* Received packets dropped when they need more than 8 + * receive buffers. This cannot happen as the driver configures + * 2048 byte receive buffers. + */ {DRVSTAT_INFO(rx_drops_too_many_frags)}, - {DRVSTAT_INFO(rx_drops_invalid_ring)}, {DRVSTAT_INFO(forwarded_packets)}, + /* Received packets dropped when the frame length + * is more than 9018 bytes + */ {DRVSTAT_INFO(rx_drops_mtu)}, + /* Number of packets dropped due to random early drop function */ {DRVSTAT_INFO(eth_red_drops)}, {DRVSTAT_INFO(be_on_die_temperature)} }; @@ -80,12 +125,17 @@ static const struct be_ethtool_stat et_stats[] = { static const struct be_ethtool_stat et_rx_stats[] = { {DRVSTAT_RX_INFO(rx_bytes)},/* If moving this member see above note */ {DRVSTAT_RX_INFO(rx_pkts)}, /* If moving this member see above note */ - {DRVSTAT_RX_INFO(rx_polls)}, - {DRVSTAT_RX_INFO(rx_events)}, {DRVSTAT_RX_INFO(rx_compl)}, {DRVSTAT_RX_INFO(rx_mcast_pkts)}, + /* Number of page allocation failures while posting receive buffers + * to HW. + */ {DRVSTAT_RX_INFO(rx_post_fail)}, + /* Recevied packets dropped due to skb allocation failure */ {DRVSTAT_RX_INFO(rx_drops_no_skbs)}, + /* Received packets dropped due to lack of available fetched buffers + * posted by the driver. + */ {DRVSTAT_RX_INFO(rx_drops_no_frags)} }; #define ETHTOOL_RXSTATS_NUM (ARRAY_SIZE(et_rx_stats)) @@ -97,9 +147,13 @@ static const struct be_ethtool_stat et_tx_stats[] = { {DRVSTAT_TX_INFO(tx_compl)}, /* If moving this member see above note */ {DRVSTAT_TX_INFO(tx_bytes)}, {DRVSTAT_TX_INFO(tx_pkts)}, + /* Number of skbs queued for trasmission by the driver */ {DRVSTAT_TX_INFO(tx_reqs)}, + /* Number of TX work request blocks DMAed to HW */ {DRVSTAT_TX_INFO(tx_wrbs)}, - {DRVSTAT_TX_INFO(tx_compl)}, + /* Number of times the TX queue was stopped due to lack + * of spaces in the TXQ. + */ {DRVSTAT_TX_INFO(tx_stops)} }; #define ETHTOOL_TXSTATS_NUM (ARRAY_SIZE(et_tx_stats)) @@ -232,86 +286,42 @@ be_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *buf) } } -static int -be_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) +static int be_get_coalesce(struct net_device *netdev, + struct ethtool_coalesce *et) { struct be_adapter *adapter = netdev_priv(netdev); - struct be_eq_obj *rx_eq = &adapter->rx_obj[0].rx_eq; - struct be_eq_obj *tx_eq = &adapter->tx_eq; + struct be_eq_obj *eqo = &adapter->eq_obj[0]; + - coalesce->rx_coalesce_usecs = rx_eq->cur_eqd; - coalesce->rx_coalesce_usecs_high = rx_eq->max_eqd; - coalesce->rx_coalesce_usecs_low = rx_eq->min_eqd; + et->rx_coalesce_usecs = eqo->cur_eqd; + et->rx_coalesce_usecs_high = eqo->max_eqd; + et->rx_coalesce_usecs_low = eqo->min_eqd; - coalesce->tx_coalesce_usecs = tx_eq->cur_eqd; - coalesce->tx_coalesce_usecs_high = tx_eq->max_eqd; - coalesce->tx_coalesce_usecs_low = tx_eq->min_eqd; + et->tx_coalesce_usecs = eqo->cur_eqd; + et->tx_coalesce_usecs_high = eqo->max_eqd; + et->tx_coalesce_usecs_low = eqo->min_eqd; - coalesce->use_adaptive_rx_coalesce = rx_eq->enable_aic; - coalesce->use_adaptive_tx_coalesce = tx_eq->enable_aic; + et->use_adaptive_rx_coalesce = eqo->enable_aic; + et->use_adaptive_tx_coalesce = eqo->enable_aic; return 0; } -/* - * This routine is used to set interrup coalescing delay +/* TX attributes are ignored. Only RX attributes are considered + * eqd cmd is issued in the worker thread. */ -static int -be_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) +static int be_set_coalesce(struct net_device *netdev, + struct ethtool_coalesce *et) { struct be_adapter *adapter = netdev_priv(netdev); - struct be_rx_obj *rxo; - struct be_eq_obj *rx_eq; - struct be_eq_obj *tx_eq = &adapter->tx_eq; - u32 rx_max, rx_min, rx_cur; - int status = 0, i; - u32 tx_cur; - - if (coalesce->use_adaptive_tx_coalesce == 1) - return -EINVAL; - - for_all_rx_queues(adapter, rxo, i) { - rx_eq = &rxo->rx_eq; - - if (!rx_eq->enable_aic && coalesce->use_adaptive_rx_coalesce) - rx_eq->cur_eqd = 0; - rx_eq->enable_aic = coalesce->use_adaptive_rx_coalesce; - - rx_max = coalesce->rx_coalesce_usecs_high; - rx_min = coalesce->rx_coalesce_usecs_low; - rx_cur = coalesce->rx_coalesce_usecs; - - if (rx_eq->enable_aic) { - if (rx_max > BE_MAX_EQD) - rx_max = BE_MAX_EQD; - if (rx_min > rx_max) - rx_min = rx_max; - rx_eq->max_eqd = rx_max; - rx_eq->min_eqd = rx_min; - if (rx_eq->cur_eqd > rx_max) - rx_eq->cur_eqd = rx_max; - if (rx_eq->cur_eqd < rx_min) - rx_eq->cur_eqd = rx_min; - } else { - if (rx_cur > BE_MAX_EQD) - rx_cur = BE_MAX_EQD; - if (rx_eq->cur_eqd != rx_cur) { - status = be_cmd_modify_eqd(adapter, rx_eq->q.id, - rx_cur); - if (!status) - rx_eq->cur_eqd = rx_cur; - } - } - } - - tx_cur = coalesce->tx_coalesce_usecs; - - if (tx_cur > BE_MAX_EQD) - tx_cur = BE_MAX_EQD; - if (tx_eq->cur_eqd != tx_cur) { - status = be_cmd_modify_eqd(adapter, tx_eq->q.id, tx_cur); - if (!status) - tx_eq->cur_eqd = tx_cur; + struct be_eq_obj *eqo; + int i; + + for_all_evt_queues(adapter, eqo, i) { + eqo->enable_aic = et->use_adaptive_rx_coalesce; + eqo->max_eqd = min(et->rx_coalesce_usecs_high, BE_MAX_EQD); + eqo->min_eqd = min(et->rx_coalesce_usecs_low, eqo->max_eqd); + eqo->eqd = et->rx_coalesce_usecs; } return 0; @@ -590,26 +600,16 @@ be_set_phys_id(struct net_device *netdev, return 0; } -static bool -be_is_wol_supported(struct be_adapter *adapter) -{ - if (!be_physfn(adapter)) - return false; - else - return true; -} static void be_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) { struct be_adapter *adapter = netdev_priv(netdev); - if (be_is_wol_supported(adapter)) - wol->supported = WAKE_MAGIC; - - if (adapter->wol) - wol->wolopts = WAKE_MAGIC; - else + if (be_is_wol_supported(adapter)) { + wol->supported |= WAKE_MAGIC; + wol->wolopts |= WAKE_MAGIC; + } else wol->wolopts = 0; memset(&wol->sopass, 0, sizeof(wol->sopass)); } @@ -620,9 +620,14 @@ be_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) struct be_adapter *adapter = netdev_priv(netdev); if (wol->wolopts & ~WAKE_MAGIC) - return -EINVAL; + return -EOPNOTSUPP; + + if (!be_is_wol_supported(adapter)) { + dev_warn(&adapter->pdev->dev, "WOL not supported\n"); + return -EOPNOTSUPP; + } - if ((wol->wolopts & WAKE_MAGIC) && be_is_wol_supported(adapter)) + if (wol->wolopts & WAKE_MAGIC) adapter->wol = true; else adapter->wol = false; |