summaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c
diff options
context:
space:
mode:
authorAlexander Duyck <alexander.h.duyck@intel.com>2014-09-20 19:51:40 -0400
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2014-09-23 03:59:20 -0700
commit5cb8db4a4cbc6dff56959a6331e9d62fd461f719 (patch)
tree97048030bc0582a4a023e543c13e12cb6e5b4a53 /drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c
parentb651957c202cabc8d5abfc5ad1ddc2607daf6a4f (diff)
downloadblackbird-op-linux-5cb8db4a4cbc6dff56959a6331e9d62fd461f719.tar.gz
blackbird-op-linux-5cb8db4a4cbc6dff56959a6331e9d62fd461f719.zip
fm10k: Add support for VF
This patch provides the functions necessary to configure the VF making use of the same API pointers as the PF. Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c')
-rw-r--r--drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c114
1 files changed, 114 insertions, 0 deletions
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c b/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c
index 54e8ebd9fbe4..42beb89ae15d 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c
@@ -102,6 +102,17 @@ static const struct fm10k_stats fm10k_gstrings_stats[] = {
FM10K_NETDEV_STATS_LEN + \
FM10K_QUEUE_STATS_LEN)
+static const char fm10k_gstrings_test[][ETH_GSTRING_LEN] = {
+ "Mailbox test (on/offline)"
+};
+
+#define FM10K_TEST_LEN (sizeof(fm10k_gstrings_test) / ETH_GSTRING_LEN)
+
+enum fm10k_self_test_types {
+ FM10K_TEST_MBX,
+ FM10K_TEST_MAX = FM10K_TEST_LEN
+};
+
static void fm10k_get_strings(struct net_device *dev, u32 stringset,
u8 *data)
{
@@ -109,6 +120,10 @@ static void fm10k_get_strings(struct net_device *dev, u32 stringset,
int i;
switch (stringset) {
+ case ETH_SS_TEST:
+ memcpy(data, *fm10k_gstrings_test,
+ FM10K_TEST_LEN * ETH_GSTRING_LEN);
+ break;
case ETH_SS_STATS:
for (i = 0; i < FM10K_NETDEV_STATS_LEN; i++) {
memcpy(p, fm10k_gstrings_net_stats[i].stat_string,
@@ -138,6 +153,8 @@ static void fm10k_get_strings(struct net_device *dev, u32 stringset,
static int fm10k_get_sset_count(struct net_device *dev, int sset)
{
switch (sset) {
+ case ETH_SS_TEST:
+ return FM10K_TEST_LEN;
case ETH_SS_STATS:
return FM10K_STATS_LEN;
default:
@@ -288,6 +305,28 @@ static void fm10k_get_regs(struct net_device *netdev,
*(buff++) = fm10k_read_reg(hw, FM10K_ITR(i));
break;
+ case fm10k_mac_vf:
+ /* General VF registers */
+ *(buff++) = fm10k_read_reg(hw, FM10K_VFCTRL);
+ *(buff++) = fm10k_read_reg(hw, FM10K_VFINT_MAP);
+ *(buff++) = fm10k_read_reg(hw, FM10K_VFSYSTIME);
+
+ /* Interrupt Throttling Registers */
+ for (i = 0; i < 8; i++)
+ *(buff++) = fm10k_read_reg(hw, FM10K_VFITR(i));
+
+ fm10k_get_reg_vsi(hw, buff, 0);
+ buff += FM10K_REGS_LEN_VSI;
+
+ for (i = 0; i < FM10K_MAX_QUEUES_POOL; i++) {
+ if (i < hw->mac.max_queues)
+ fm10k_get_reg_q(hw, buff, i);
+ else
+ memset(buff, 0, sizeof(u32) * FM10K_REGS_LEN_Q);
+ buff += FM10K_REGS_LEN_Q;
+ }
+
+ break;
default:
return;
}
@@ -296,6 +335,8 @@ static void fm10k_get_regs(struct net_device *netdev,
/* If function above adds more registers these define need to be updated */
#define FM10K_REGS_LEN_PF \
(162 + (65 * FM10K_REGS_LEN_VSI) + (FM10K_MAX_QUEUES_PF * FM10K_REGS_LEN_Q))
+#define FM10K_REGS_LEN_VF \
+(11 + FM10K_REGS_LEN_VSI + (FM10K_MAX_QUEUES_POOL * FM10K_REGS_LEN_Q))
static int fm10k_get_regs_len(struct net_device *netdev)
{
@@ -305,6 +346,8 @@ static int fm10k_get_regs_len(struct net_device *netdev)
switch (hw->mac.type) {
case fm10k_mac_pf:
return FM10K_REGS_LEN_PF * sizeof(u32);
+ case fm10k_mac_vf:
+ return FM10K_REGS_LEN_VF * sizeof(u32);
default:
return 0;
}
@@ -734,6 +777,76 @@ static int fm10k_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
return ret;
}
+static int fm10k_mbx_test(struct fm10k_intfc *interface, u64 *data)
+{
+ struct fm10k_hw *hw = &interface->hw;
+ struct fm10k_mbx_info *mbx = &hw->mbx;
+ u32 attr_flag, test_msg[6];
+ unsigned long timeout;
+ int err;
+
+ /* For now this is a VF only feature */
+ if (hw->mac.type != fm10k_mac_vf)
+ return 0;
+
+ /* loop through both nested and unnested attribute types */
+ for (attr_flag = (1 << FM10K_TEST_MSG_UNSET);
+ attr_flag < (1 << (2 * FM10K_TEST_MSG_NESTED));
+ attr_flag += attr_flag) {
+ /* generate message to be tested */
+ fm10k_tlv_msg_test_create(test_msg, attr_flag);
+
+ fm10k_mbx_lock(interface);
+ mbx->test_result = FM10K_NOT_IMPLEMENTED;
+ err = mbx->ops.enqueue_tx(hw, mbx, test_msg);
+ fm10k_mbx_unlock(interface);
+
+ /* wait up to 1 second for response */
+ timeout = jiffies + HZ;
+ do {
+ if (err < 0)
+ goto err_out;
+
+ usleep_range(500, 1000);
+
+ fm10k_mbx_lock(interface);
+ mbx->ops.process(hw, mbx);
+ fm10k_mbx_unlock(interface);
+
+ err = mbx->test_result;
+ if (!err)
+ break;
+ } while (time_is_after_jiffies(timeout));
+
+ /* reporting errors */
+ if (err)
+ goto err_out;
+ }
+
+err_out:
+ *data = err < 0 ? (attr_flag) : (err > 0);
+ return err;
+}
+
+static void fm10k_self_test(struct net_device *dev,
+ struct ethtool_test *eth_test, u64 *data)
+{
+ struct fm10k_intfc *interface = netdev_priv(dev);
+ struct fm10k_hw *hw = &interface->hw;
+
+ memset(data, 0, sizeof(*data) * FM10K_TEST_LEN);
+
+ if (FM10K_REMOVED(hw)) {
+ netif_err(interface, drv, dev,
+ "Interface removed - test blocked\n");
+ eth_test->flags |= ETH_TEST_FL_FAILED;
+ return;
+ }
+
+ if (fm10k_mbx_test(interface, &data[FM10K_TEST_MBX]))
+ eth_test->flags |= ETH_TEST_FL_FAILED;
+}
+
static u32 fm10k_get_reta_size(struct net_device *netdev)
{
return FM10K_RETA_SIZE * FM10K_RETA_ENTRIES_PER_REG;
@@ -911,6 +1024,7 @@ static const struct ethtool_ops fm10k_ethtool_ops = {
.set_rxnfc = fm10k_set_rxnfc,
.get_regs = fm10k_get_regs,
.get_regs_len = fm10k_get_regs_len,
+ .self_test = fm10k_self_test,
.get_rxfh_indir_size = fm10k_get_reta_size,
.get_rxfh_key_size = fm10k_get_rssrk_size,
.get_rxfh = fm10k_get_rssh,
OpenPOWER on IntegriCloud