-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
drivers/net: enic: Move ethtool code to a separate file
This patch moves all enic ethtool hooks from enic_main.c to a new file enic_ethtool.c Signed-off-by: Neel Patel <neepatel@cisco.com> Signed-off-by: Christian Benvenuti <benve@cisco.com> Signed-off-by: Nishank Trivedi <nistrive@cisco.com> Signed-off-by: David S. Miller <davem@davemloft.net>
- Loading branch information
Neel Patel
authored and
David S. Miller
committed
Jul 25, 2013
1 parent
59ea52d
commit f13bbc2
Showing
5 changed files
with
309 additions
and
270 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
obj-$(CONFIG_ENIC) := enic.o | ||
|
||
enic-y := enic_main.o vnic_cq.o vnic_intr.o vnic_wq.o \ | ||
enic_res.o enic_dev.o enic_pp.o vnic_dev.o vnic_rq.o vnic_vic.o | ||
enic_res.o enic_dev.o enic_pp.o vnic_dev.o vnic_rq.o vnic_vic.o \ | ||
enic_ethtool.o | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,257 @@ | ||
/** | ||
* Copyright 2013 Cisco Systems, Inc. All rights reserved. | ||
* | ||
* This program is free software; you may redistribute it and/or modify | ||
* it under the terms of the GNU General Public License as published by | ||
* the Free Software Foundation; version 2 of the License. | ||
* | ||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
* SOFTWARE. | ||
* | ||
*/ | ||
|
||
#include <linux/netdevice.h> | ||
#include <linux/ethtool.h> | ||
|
||
#include "enic_res.h" | ||
#include "enic.h" | ||
#include "enic_dev.h" | ||
|
||
struct enic_stat { | ||
char name[ETH_GSTRING_LEN]; | ||
unsigned int index; | ||
}; | ||
|
||
#define ENIC_TX_STAT(stat) { \ | ||
.name = #stat, \ | ||
.index = offsetof(struct vnic_tx_stats, stat) / sizeof(u64) \ | ||
} | ||
|
||
#define ENIC_RX_STAT(stat) { \ | ||
.name = #stat, \ | ||
.index = offsetof(struct vnic_rx_stats, stat) / sizeof(u64) \ | ||
} | ||
|
||
static const struct enic_stat enic_tx_stats[] = { | ||
ENIC_TX_STAT(tx_frames_ok), | ||
ENIC_TX_STAT(tx_unicast_frames_ok), | ||
ENIC_TX_STAT(tx_multicast_frames_ok), | ||
ENIC_TX_STAT(tx_broadcast_frames_ok), | ||
ENIC_TX_STAT(tx_bytes_ok), | ||
ENIC_TX_STAT(tx_unicast_bytes_ok), | ||
ENIC_TX_STAT(tx_multicast_bytes_ok), | ||
ENIC_TX_STAT(tx_broadcast_bytes_ok), | ||
ENIC_TX_STAT(tx_drops), | ||
ENIC_TX_STAT(tx_errors), | ||
ENIC_TX_STAT(tx_tso), | ||
}; | ||
|
||
static const struct enic_stat enic_rx_stats[] = { | ||
ENIC_RX_STAT(rx_frames_ok), | ||
ENIC_RX_STAT(rx_frames_total), | ||
ENIC_RX_STAT(rx_unicast_frames_ok), | ||
ENIC_RX_STAT(rx_multicast_frames_ok), | ||
ENIC_RX_STAT(rx_broadcast_frames_ok), | ||
ENIC_RX_STAT(rx_bytes_ok), | ||
ENIC_RX_STAT(rx_unicast_bytes_ok), | ||
ENIC_RX_STAT(rx_multicast_bytes_ok), | ||
ENIC_RX_STAT(rx_broadcast_bytes_ok), | ||
ENIC_RX_STAT(rx_drop), | ||
ENIC_RX_STAT(rx_no_bufs), | ||
ENIC_RX_STAT(rx_errors), | ||
ENIC_RX_STAT(rx_rss), | ||
ENIC_RX_STAT(rx_crc_errors), | ||
ENIC_RX_STAT(rx_frames_64), | ||
ENIC_RX_STAT(rx_frames_127), | ||
ENIC_RX_STAT(rx_frames_255), | ||
ENIC_RX_STAT(rx_frames_511), | ||
ENIC_RX_STAT(rx_frames_1023), | ||
ENIC_RX_STAT(rx_frames_1518), | ||
ENIC_RX_STAT(rx_frames_to_max), | ||
}; | ||
|
||
static const unsigned int enic_n_tx_stats = ARRAY_SIZE(enic_tx_stats); | ||
static const unsigned int enic_n_rx_stats = ARRAY_SIZE(enic_rx_stats); | ||
|
||
static int enic_get_settings(struct net_device *netdev, | ||
struct ethtool_cmd *ecmd) | ||
{ | ||
struct enic *enic = netdev_priv(netdev); | ||
|
||
ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE); | ||
ecmd->advertising = (ADVERTISED_10000baseT_Full | ADVERTISED_FIBRE); | ||
ecmd->port = PORT_FIBRE; | ||
ecmd->transceiver = XCVR_EXTERNAL; | ||
|
||
if (netif_carrier_ok(netdev)) { | ||
ethtool_cmd_speed_set(ecmd, vnic_dev_port_speed(enic->vdev)); | ||
ecmd->duplex = DUPLEX_FULL; | ||
} else { | ||
ethtool_cmd_speed_set(ecmd, -1); | ||
ecmd->duplex = -1; | ||
} | ||
|
||
ecmd->autoneg = AUTONEG_DISABLE; | ||
|
||
return 0; | ||
} | ||
|
||
static void enic_get_drvinfo(struct net_device *netdev, | ||
struct ethtool_drvinfo *drvinfo) | ||
{ | ||
struct enic *enic = netdev_priv(netdev); | ||
struct vnic_devcmd_fw_info *fw_info; | ||
|
||
enic_dev_fw_info(enic, &fw_info); | ||
|
||
strlcpy(drvinfo->driver, DRV_NAME, sizeof(drvinfo->driver)); | ||
strlcpy(drvinfo->version, DRV_VERSION, sizeof(drvinfo->version)); | ||
strlcpy(drvinfo->fw_version, fw_info->fw_version, | ||
sizeof(drvinfo->fw_version)); | ||
strlcpy(drvinfo->bus_info, pci_name(enic->pdev), | ||
sizeof(drvinfo->bus_info)); | ||
} | ||
|
||
static void enic_get_strings(struct net_device *netdev, u32 stringset, | ||
u8 *data) | ||
{ | ||
unsigned int i; | ||
|
||
switch (stringset) { | ||
case ETH_SS_STATS: | ||
for (i = 0; i < enic_n_tx_stats; i++) { | ||
memcpy(data, enic_tx_stats[i].name, ETH_GSTRING_LEN); | ||
data += ETH_GSTRING_LEN; | ||
} | ||
for (i = 0; i < enic_n_rx_stats; i++) { | ||
memcpy(data, enic_rx_stats[i].name, ETH_GSTRING_LEN); | ||
data += ETH_GSTRING_LEN; | ||
} | ||
break; | ||
} | ||
} | ||
|
||
static int enic_get_sset_count(struct net_device *netdev, int sset) | ||
{ | ||
switch (sset) { | ||
case ETH_SS_STATS: | ||
return enic_n_tx_stats + enic_n_rx_stats; | ||
default: | ||
return -EOPNOTSUPP; | ||
} | ||
} | ||
|
||
static void enic_get_ethtool_stats(struct net_device *netdev, | ||
struct ethtool_stats *stats, u64 *data) | ||
{ | ||
struct enic *enic = netdev_priv(netdev); | ||
struct vnic_stats *vstats; | ||
unsigned int i; | ||
|
||
enic_dev_stats_dump(enic, &vstats); | ||
|
||
for (i = 0; i < enic_n_tx_stats; i++) | ||
*(data++) = ((u64 *)&vstats->tx)[enic_tx_stats[i].index]; | ||
for (i = 0; i < enic_n_rx_stats; i++) | ||
*(data++) = ((u64 *)&vstats->rx)[enic_rx_stats[i].index]; | ||
} | ||
|
||
static u32 enic_get_msglevel(struct net_device *netdev) | ||
{ | ||
struct enic *enic = netdev_priv(netdev); | ||
return enic->msg_enable; | ||
} | ||
|
||
static void enic_set_msglevel(struct net_device *netdev, u32 value) | ||
{ | ||
struct enic *enic = netdev_priv(netdev); | ||
enic->msg_enable = value; | ||
} | ||
|
||
static int enic_get_coalesce(struct net_device *netdev, | ||
struct ethtool_coalesce *ecmd) | ||
{ | ||
struct enic *enic = netdev_priv(netdev); | ||
|
||
ecmd->tx_coalesce_usecs = enic->tx_coalesce_usecs; | ||
ecmd->rx_coalesce_usecs = enic->rx_coalesce_usecs; | ||
|
||
return 0; | ||
} | ||
|
||
static int enic_set_coalesce(struct net_device *netdev, | ||
struct ethtool_coalesce *ecmd) | ||
{ | ||
struct enic *enic = netdev_priv(netdev); | ||
u32 tx_coalesce_usecs; | ||
u32 rx_coalesce_usecs; | ||
unsigned int i, intr; | ||
|
||
tx_coalesce_usecs = min_t(u32, ecmd->tx_coalesce_usecs, | ||
vnic_dev_get_intr_coal_timer_max(enic->vdev)); | ||
rx_coalesce_usecs = min_t(u32, ecmd->rx_coalesce_usecs, | ||
vnic_dev_get_intr_coal_timer_max(enic->vdev)); | ||
|
||
switch (vnic_dev_get_intr_mode(enic->vdev)) { | ||
case VNIC_DEV_INTR_MODE_INTX: | ||
if (tx_coalesce_usecs != rx_coalesce_usecs) | ||
return -EINVAL; | ||
|
||
intr = enic_legacy_io_intr(); | ||
vnic_intr_coalescing_timer_set(&enic->intr[intr], | ||
tx_coalesce_usecs); | ||
break; | ||
case VNIC_DEV_INTR_MODE_MSI: | ||
if (tx_coalesce_usecs != rx_coalesce_usecs) | ||
return -EINVAL; | ||
|
||
vnic_intr_coalescing_timer_set(&enic->intr[0], | ||
tx_coalesce_usecs); | ||
break; | ||
case VNIC_DEV_INTR_MODE_MSIX: | ||
for (i = 0; i < enic->wq_count; i++) { | ||
intr = enic_msix_wq_intr(enic, i); | ||
vnic_intr_coalescing_timer_set(&enic->intr[intr], | ||
tx_coalesce_usecs); | ||
} | ||
|
||
for (i = 0; i < enic->rq_count; i++) { | ||
intr = enic_msix_rq_intr(enic, i); | ||
vnic_intr_coalescing_timer_set(&enic->intr[intr], | ||
rx_coalesce_usecs); | ||
} | ||
|
||
break; | ||
default: | ||
break; | ||
} | ||
|
||
enic->tx_coalesce_usecs = tx_coalesce_usecs; | ||
enic->rx_coalesce_usecs = rx_coalesce_usecs; | ||
|
||
return 0; | ||
} | ||
|
||
static const struct ethtool_ops enic_ethtool_ops = { | ||
.get_settings = enic_get_settings, | ||
.get_drvinfo = enic_get_drvinfo, | ||
.get_msglevel = enic_get_msglevel, | ||
.set_msglevel = enic_set_msglevel, | ||
.get_link = ethtool_op_get_link, | ||
.get_strings = enic_get_strings, | ||
.get_sset_count = enic_get_sset_count, | ||
.get_ethtool_stats = enic_get_ethtool_stats, | ||
.get_coalesce = enic_get_coalesce, | ||
.set_coalesce = enic_set_coalesce, | ||
}; | ||
|
||
void enic_set_ethtool_ops(struct net_device *netdev) | ||
{ | ||
SET_ETHTOOL_OPS(netdev, &enic_ethtool_ops); | ||
} |
Oops, something went wrong.