From 479e2f445faf7a04d75f807b81b316ebc5b043ca Mon Sep 17 00:00:00 2001 From: Subbu Seetharaman Date: Sun, 2 Nov 2008 08:09:57 -0500 Subject: Staging: Add ServerEngines benet 10Gb ethernet driver Signed-off-by: Jeff Garzik Signed-off-by: Greg Kroah-Hartman --- drivers/staging/benet/be_ethtool.c | 348 +++++++++++++++++++++++++++++++++++++ 1 file changed, 348 insertions(+) create mode 100644 drivers/staging/benet/be_ethtool.c (limited to 'drivers/staging/benet/be_ethtool.c') diff --git a/drivers/staging/benet/be_ethtool.c b/drivers/staging/benet/be_ethtool.c new file mode 100644 index 00000000000..8c3ac90d2fe --- /dev/null +++ b/drivers/staging/benet/be_ethtool.c @@ -0,0 +1,348 @@ +/* + * Copyright (C) 2005 - 2008 ServerEngines + * All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. The full GNU General + * Public License is included in this distribution in the file called COPYING. + * + * Contact Information: + * linux-drivers@serverengines.com + * + * ServerEngines + * 209 N. Fair Oaks Ave + * Sunnyvale, CA 94085 + */ +/* + * be_ethtool.c + * + * This file contains various functions that ethtool can use + * to talk to the driver and the BE H/W. + */ + +#include "benet.h" + +#include + +static const char benet_gstrings_stats[][ETH_GSTRING_LEN] = { +/* net_device_stats */ + "rx_packets", + "tx_packets", + "rx_bytes", + "tx_bytes", + "rx_errors", + "tx_errors", + "rx_dropped", + "tx_dropped", + "multicast", + "collisions", + "rx_length_errors", + "rx_over_errors", + "rx_crc_errors", + "rx_frame_errors", + "rx_fifo_errors", + "rx_missed_errors", + "tx_aborted_errors", + "tx_carrier_errors", + "tx_fifo_errors", + "tx_heartbeat_errors", + "tx_window_errors", + "rx_compressed", + "tc_compressed", +/* BE driver Stats */ + "bes_tx_reqs", + "bes_tx_fails", + "bes_fwd_reqs", + "bes_tx_wrbs", + "bes_interrupts", + "bes_events", + "bes_tx_events", + "bes_rx_events", + "bes_tx_compl", + "bes_rx_compl", + "bes_ethrx_post_fail", + "bes_802_3_dropped_frames", + "bes_802_3_malformed_frames", + "bes_rx_misc_pkts", + "bes_eth_tx_rate", + "bes_eth_rx_rate", + "Num Packets collected", + "Num Times Flushed", +}; + +#define NET_DEV_STATS_LEN \ + (sizeof(struct net_device_stats)/sizeof(unsigned long)) + +#define BENET_STATS_LEN ARRAY_SIZE(benet_gstrings_stats) + +static void +be_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) +{ + struct be_net_object *pnob = netdev->priv; + struct be_adapter *adapter = pnob->adapter; + + strncpy(drvinfo->driver, be_driver_name, 32); + strncpy(drvinfo->version, be_drvr_ver, 32); + strncpy(drvinfo->fw_version, be_fw_ver, 32); + strcpy(drvinfo->bus_info, pci_name(adapter->pdev)); + drvinfo->testinfo_len = 0; + drvinfo->regdump_len = 0; + drvinfo->eedump_len = 0; +} + +static int +be_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) +{ + struct be_net_object *pnob = netdev->priv; + struct be_adapter *adapter = pnob->adapter; + + coalesce->rx_max_coalesced_frames = adapter->max_rx_coal; + + coalesce->rx_coalesce_usecs = adapter->cur_eqd; + coalesce->rx_coalesce_usecs_high = adapter->max_eqd; + coalesce->rx_coalesce_usecs_low = adapter->min_eqd; + + coalesce->tx_coalesce_usecs = adapter->cur_eqd; + coalesce->tx_coalesce_usecs_high = adapter->max_eqd; + coalesce->tx_coalesce_usecs_low = adapter->min_eqd; + + coalesce->use_adaptive_rx_coalesce = adapter->enable_aic; + coalesce->use_adaptive_tx_coalesce = adapter->enable_aic; + + return 0; +} + +/* + * This routine is used to set interrup coalescing delay *as well as* + * the number of pkts to coalesce for LRO. + */ +static int +be_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) +{ + struct be_net_object *pnob = netdev->priv; + struct be_adapter *adapter = pnob->adapter; + struct be_eq_object *eq_objectp; + u32 max, min, cur; + int status; + + adapter->max_rx_coal = coalesce->rx_max_coalesced_frames; + if (adapter->max_rx_coal >= BE_LRO_MAX_PKTS) + adapter->max_rx_coal = BE_LRO_MAX_PKTS; + + if (adapter->enable_aic == 0 && + coalesce->use_adaptive_rx_coalesce == 1) { + /* if AIC is being turned on now, start with an EQD of 0 */ + adapter->cur_eqd = 0; + } + adapter->enable_aic = coalesce->use_adaptive_rx_coalesce; + + /* round off to nearest multiple of 8 */ + max = (((coalesce->rx_coalesce_usecs_high + 4) >> 3) << 3); + min = (((coalesce->rx_coalesce_usecs_low + 4) >> 3) << 3); + cur = (((coalesce->rx_coalesce_usecs + 4) >> 3) << 3); + + if (adapter->enable_aic) { + /* accept low and high if AIC is enabled */ + if (max > MAX_EQD) + max = MAX_EQD; + if (min > max) + min = max; + adapter->max_eqd = max; + adapter->min_eqd = min; + if (adapter->cur_eqd > max) + adapter->cur_eqd = max; + if (adapter->cur_eqd < min) + adapter->cur_eqd = min; + } else { + /* accept specified coalesce_usecs only if AIC is disabled */ + if (cur > MAX_EQD) + cur = MAX_EQD; + eq_objectp = &pnob->event_q_obj; + status = + be_eq_modify_delay(&pnob->fn_obj, 1, &eq_objectp, &cur, + NULL, NULL, NULL); + if (status == BE_SUCCESS) + adapter->cur_eqd = cur; + } + return 0; +} + +static u32 be_get_rx_csum(struct net_device *netdev) +{ + struct be_net_object *pnob = netdev->priv; + struct be_adapter *adapter = pnob->adapter; + return adapter->rx_csum; +} + +static int be_set_rx_csum(struct net_device *netdev, uint32_t data) +{ + struct be_net_object *pnob = netdev->priv; + struct be_adapter *adapter = pnob->adapter; + + if (data) + adapter->rx_csum = 1; + else + adapter->rx_csum = 0; + + return 0; +} + +static void +be_get_strings(struct net_device *netdev, uint32_t stringset, uint8_t *data) +{ + switch (stringset) { + case ETH_SS_STATS: + memcpy(data, *benet_gstrings_stats, + sizeof(benet_gstrings_stats)); + break; + } +} + +static int be_get_stats_count(struct net_device *netdev) +{ + return BENET_STATS_LEN; +} + +static void +be_get_ethtool_stats(struct net_device *netdev, + struct ethtool_stats *stats, uint64_t *data) +{ + struct be_net_object *pnob = netdev->priv; + struct be_adapter *adapter = pnob->adapter; + int i; + + benet_get_stats(netdev); + + for (i = 0; i <= NET_DEV_STATS_LEN; i++) + data[i] = ((unsigned long *)&adapter->benet_stats)[i]; + + data[i] = adapter->be_stat.bes_tx_reqs; + data[i++] = adapter->be_stat.bes_tx_fails; + data[i++] = adapter->be_stat.bes_fwd_reqs; + data[i++] = adapter->be_stat.bes_tx_wrbs; + + data[i++] = adapter->be_stat.bes_ints; + data[i++] = adapter->be_stat.bes_events; + data[i++] = adapter->be_stat.bes_tx_events; + data[i++] = adapter->be_stat.bes_rx_events; + data[i++] = adapter->be_stat.bes_tx_compl; + data[i++] = adapter->be_stat.bes_rx_compl; + data[i++] = adapter->be_stat.bes_ethrx_post_fail; + data[i++] = adapter->be_stat.bes_802_3_dropped_frames; + data[i++] = adapter->be_stat.bes_802_3_malformed_frames; + data[i++] = adapter->be_stat.bes_rx_misc_pkts; + data[i++] = adapter->be_stat.bes_eth_tx_rate; + data[i++] = adapter->be_stat.bes_eth_rx_rate; + data[i++] = adapter->be_stat.bes_rx_coal; + data[i++] = adapter->be_stat.bes_rx_flush; + +} + +static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) +{ + ecmd->speed = SPEED_10000; + ecmd->duplex = DUPLEX_FULL; + ecmd->autoneg = AUTONEG_DISABLE; + return 0; +} + +/* Get the Ring parameters from the pnob */ +static void +be_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) +{ + struct be_net_object *pnob = netdev->priv; + + /* Pre Set Maxims */ + ring->rx_max_pending = pnob->rx_q_len; + ring->rx_mini_max_pending = ring->rx_mini_max_pending; + ring->rx_jumbo_max_pending = ring->rx_jumbo_max_pending; + ring->tx_max_pending = pnob->tx_q_len; + + /* Current hardware Settings */ + ring->rx_pending = atomic_read(&pnob->rx_q_posted); + ring->rx_mini_pending = ring->rx_mini_pending; + ring->rx_jumbo_pending = ring->rx_jumbo_pending; + ring->tx_pending = atomic_read(&pnob->tx_q_used); + +} + +static void +be_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *ecmd) +{ + struct be_net_object *pnob = netdev->priv; + bool rxfc, txfc; + int status; + + status = be_eth_get_flow_control(&pnob->fn_obj, &txfc, &rxfc); + if (status != BE_SUCCESS) { + dev_info(&netdev->dev, "Unable to get pause frame settings\n"); + /* return defaults */ + ecmd->rx_pause = 1; + ecmd->tx_pause = 0; + ecmd->autoneg = AUTONEG_ENABLE; + return; + } + + if (txfc == true) + ecmd->tx_pause = 1; + else + ecmd->tx_pause = 0; + + if (rxfc == true) + ecmd->rx_pause = 1; + else + ecmd->rx_pause = 0; + + ecmd->autoneg = AUTONEG_ENABLE; +} + +static int +be_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *ecmd) +{ + struct be_net_object *pnob = netdev->priv; + bool txfc, rxfc; + int status; + + if (ecmd->autoneg != AUTONEG_ENABLE) + return -EINVAL; + + if (ecmd->tx_pause) + txfc = true; + else + txfc = false; + + if (ecmd->rx_pause) + rxfc = true; + else + rxfc = false; + + status = be_eth_set_flow_control(&pnob->fn_obj, txfc, rxfc); + if (status != BE_SUCCESS) { + dev_info(&netdev->dev, "Unable to set pause frame settings\n"); + return -1; + } + return 0; +} + +struct ethtool_ops be_ethtool_ops = { + .get_settings = be_get_settings, + .get_drvinfo = be_get_drvinfo, + .get_link = ethtool_op_get_link, + .get_coalesce = be_get_coalesce, + .set_coalesce = be_set_coalesce, + .get_ringparam = be_get_ringparam, + .get_pauseparam = be_get_pauseparam, + .set_pauseparam = be_set_pauseparam, + .get_rx_csum = be_get_rx_csum, + .set_rx_csum = be_set_rx_csum, + .get_tx_csum = ethtool_op_get_tx_csum, + .set_tx_csum = ethtool_op_set_tx_csum, + .get_sg = ethtool_op_get_sg, + .set_sg = ethtool_op_set_sg, + .get_tso = ethtool_op_get_tso, + .set_tso = ethtool_op_set_tso, + .get_strings = be_get_strings, + .get_stats_count = be_get_stats_count, + .get_ethtool_stats = be_get_ethtool_stats, +}; -- cgit v1.2.3 From 0252e5c691fd54064212c74435c2255abf3778d5 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 5 Jan 2009 15:05:47 -0800 Subject: Staging: benet: fix up netdev->priv change netdev->priv is now gone, so fix up all of the build errors in the benet driver due to this change. Cc: Subbu Seetharaman Signed-off-by: Greg Kroah-Hartman --- drivers/staging/benet/be_ethtool.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers/staging/benet/be_ethtool.c') diff --git a/drivers/staging/benet/be_ethtool.c b/drivers/staging/benet/be_ethtool.c index 8c3ac90d2fe..027af85707a 100644 --- a/drivers/staging/benet/be_ethtool.c +++ b/drivers/staging/benet/be_ethtool.c @@ -79,7 +79,7 @@ static const char benet_gstrings_stats[][ETH_GSTRING_LEN] = { static void be_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) { - struct be_net_object *pnob = netdev->priv; + struct be_net_object *pnob = netdev_priv(netdev); struct be_adapter *adapter = pnob->adapter; strncpy(drvinfo->driver, be_driver_name, 32); @@ -94,7 +94,7 @@ be_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) static int be_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) { - struct be_net_object *pnob = netdev->priv; + struct be_net_object *pnob = netdev_priv(netdev); struct be_adapter *adapter = pnob->adapter; coalesce->rx_max_coalesced_frames = adapter->max_rx_coal; @@ -120,7 +120,7 @@ be_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) static int be_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) { - struct be_net_object *pnob = netdev->priv; + struct be_net_object *pnob = netdev_priv(netdev); struct be_adapter *adapter = pnob->adapter; struct be_eq_object *eq_objectp; u32 max, min, cur; @@ -170,14 +170,14 @@ be_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) static u32 be_get_rx_csum(struct net_device *netdev) { - struct be_net_object *pnob = netdev->priv; + struct be_net_object *pnob = netdev_priv(netdev); struct be_adapter *adapter = pnob->adapter; return adapter->rx_csum; } static int be_set_rx_csum(struct net_device *netdev, uint32_t data) { - struct be_net_object *pnob = netdev->priv; + struct be_net_object *pnob = netdev_priv(netdev); struct be_adapter *adapter = pnob->adapter; if (data) @@ -208,7 +208,7 @@ static void be_get_ethtool_stats(struct net_device *netdev, struct ethtool_stats *stats, uint64_t *data) { - struct be_net_object *pnob = netdev->priv; + struct be_net_object *pnob = netdev_priv(netdev); struct be_adapter *adapter = pnob->adapter; int i; @@ -251,7 +251,7 @@ static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) static void be_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) { - struct be_net_object *pnob = netdev->priv; + struct be_net_object *pnob = netdev_priv(netdev); /* Pre Set Maxims */ ring->rx_max_pending = pnob->rx_q_len; @@ -270,7 +270,7 @@ be_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) static void be_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *ecmd) { - struct be_net_object *pnob = netdev->priv; + struct be_net_object *pnob = netdev_priv(netdev); bool rxfc, txfc; int status; @@ -300,7 +300,7 @@ be_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *ecmd) static int be_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *ecmd) { - struct be_net_object *pnob = netdev->priv; + struct be_net_object *pnob = netdev_priv(netdev); bool txfc, rxfc; int status; -- cgit v1.2.3