ixgbe hardware supports enabling TX loopback for VF's through
the PFVMTXSW registers on the PF. Add a new mbox api enabling the
VF to set its respective PFVMTXSW bit via the PF.
Bump the mbox api to level 12.
VF loopback is enabled/disabled through the netdevice API.

Signed-off-by: Yotam Rubin <yo...@weka.io>
---
 drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h      |  4 ++
 drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c    | 28 ++++++++++++++
 drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c | 45 ++++++++++++++++++++++-
 drivers/net/ethernet/intel/ixgbevf/mbx.h          |  4 ++
 drivers/net/ethernet/intel/ixgbevf/vf.c           | 29 +++++++++++++++
 drivers/net/ethernet/intel/ixgbevf/vf.h           |  3 +-
 6 files changed, 110 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h 
b/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h
index a5cb755..43877ca 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h
@@ -73,6 +73,7 @@ enum ixgbe_pfvf_api_rev {
        ixgbe_mbox_api_10,      /* API version 1.0, linux/freebsd VF driver */
        ixgbe_mbox_api_20,      /* API version 2.0, solaris Phase1 VF driver */
        ixgbe_mbox_api_11,      /* API version 1.1, linux/freebsd VF driver */
+       ixgbe_mbox_api_12,      /* API version 1.2, linux/freebsd VF driver */
        /* This value should always be last */
        ixgbe_mbox_api_unknown, /* indicates that API version is not known */
 };
@@ -91,6 +92,9 @@ enum ixgbe_pfvf_api_rev {
 /* mailbox API, version 1.1 VF requests */
 #define IXGBE_VF_GET_QUEUES    0x09 /* get queue configuration */
 
+/* mailbox API, version 1.2 VF requests */
+#define IXGBE_VF_ENABLE_TX_LOOPBACK 0x0a
+
 /* GET_QUEUES return data indices within the mailbox */
 #define IXGBE_VF_TX_QUEUES     1       /* number of Tx queues supported */
 #define IXGBE_VF_RX_QUEUES     2       /* number of Rx queues supported */
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c 
b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
index 00f74bb..53d662d 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
@@ -429,6 +429,7 @@ static s32 ixgbe_set_vf_lpe(struct ixgbe_adapter *adapter, 
u32 *msgbuf, u32 vf)
 #endif /* CONFIG_FCOE */
                switch (adapter->vfinfo[vf].vf_api) {
                case ixgbe_mbox_api_11:
+               case ixgbe_mbox_api_12:
                        /*
                         * Version 1.1 supports jumbo frames on VFs if PF has
                         * jumbo frames enabled which means legacy VFs are
@@ -760,6 +761,28 @@ static int ixgbe_set_vf_mac_addr(struct ixgbe_adapter 
*adapter,
        return ixgbe_set_vf_mac(adapter, vf, new_mac) < 0;
 }
 
+static int ixgbe_set_vf_tx_loopback(struct ixgbe_adapter *adapter,
+                                   u32 *msgbuf, u32 vf)
+{
+       u8 *loopback_enabled;
+
+       switch (adapter->vfinfo[vf].vf_api) {
+       case ixgbe_mbox_api_12:
+               break;
+       default:
+               return -1;
+       }
+
+       if (!adapter->hw.mac.ops.set_tx_loopback) {
+               return -1;
+       }
+
+       loopback_enabled = ((u8 *)(&msgbuf[1]));
+       adapter->vfinfo[vf].tx_loopback_enabled = !!(*loopback_enabled);
+       adapter->hw.mac.ops.set_tx_loopback(&adapter->hw, *loopback_enabled, 
vf);
+       return 0;
+}
+
 static int ixgbe_find_vlvf_entry(struct ixgbe_hw *hw, u32 vlan)
 {
        u32 vlvf;
@@ -900,6 +923,7 @@ static int ixgbe_negotiate_vf_api(struct ixgbe_adapter 
*adapter,
        switch (api) {
        case ixgbe_mbox_api_10:
        case ixgbe_mbox_api_11:
+       case ixgbe_mbox_api_12:
                adapter->vfinfo[vf].vf_api = api;
                return 0;
        default:
@@ -923,6 +947,7 @@ static int ixgbe_get_vf_queues(struct ixgbe_adapter 
*adapter,
        switch (adapter->vfinfo[vf].vf_api) {
        case ixgbe_mbox_api_20:
        case ixgbe_mbox_api_11:
+       case ixgbe_mbox_api_12:
                break;
        default:
                return -1;
@@ -1006,6 +1031,9 @@ static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter 
*adapter, u32 vf)
        case IXGBE_VF_GET_QUEUES:
                retval = ixgbe_get_vf_queues(adapter, msgbuf, vf);
                break;
+       case IXGBE_VF_ENABLE_TX_LOOPBACK:
+               retval = ixgbe_set_vf_tx_loopback(adapter, msgbuf, vf);
+               break;
        default:
                e_err(drv, "Unhandled Msg %8.8x\n", msgbuf[0]);
                retval = IXGBE_ERR_MBX;
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c 
b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
index 4186981..43e48b8 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
@@ -2026,7 +2026,8 @@ static void ixgbevf_init_last_counter_stats(struct 
ixgbevf_adapter *adapter)
 static void ixgbevf_negotiate_api(struct ixgbevf_adapter *adapter)
 {
        struct ixgbe_hw *hw = &adapter->hw;
-       int api[] = { ixgbe_mbox_api_11,
+       int api[] = { ixgbe_mbox_api_12,
+                     ixgbe_mbox_api_11,
                      ixgbe_mbox_api_10,
                      ixgbe_mbox_api_unknown };
        int err = 0, idx = 0;
@@ -2288,6 +2289,18 @@ static int ixgbevf_acquire_msix_vectors(struct 
ixgbevf_adapter *adapter,
        return 0;
 }
 
+static int ixgbevf_set_tx_loopback(struct ixgbevf_adapter *adapter,
+                                  bool enabled)
+{
+       int err;
+
+       spin_lock_bh(&adapter->mbx_lock);
+       err = ixgbevf_enable_tx_loopback(&adapter->hw, enabled);
+       spin_unlock_bh(&adapter->mbx_lock);
+
+       return err;
+}
+
 /**
  * ixgbevf_set_num_queues - Allocate queues for device, feature dependent
  * @adapter: board private structure to initialize
@@ -2328,6 +2341,7 @@ static void ixgbevf_set_num_queues(struct ixgbevf_adapter 
*adapter)
 
                switch (hw->api_version) {
                case ixgbe_mbox_api_11:
+               case ixgbe_mbox_api_12:
                        adapter->num_rx_queues = rss;
                        adapter->num_tx_queues = rss;
                default:
@@ -3712,6 +3726,7 @@ static int ixgbevf_change_mtu(struct net_device *netdev, 
int new_mtu)
 
        switch (adapter->hw.api_version) {
        case ixgbe_mbox_api_11:
+       case ixgbe_mbox_api_12:
                max_possible_frame = IXGBE_MAX_JUMBO_FRAME_SIZE;
                break;
        default:
@@ -3735,6 +3750,23 @@ static int ixgbevf_change_mtu(struct net_device *netdev, 
int new_mtu)
        return 0;
 }
 
+static int ixgbevf_set_features(struct net_device *netdev,
+                               netdev_features_t features)
+{
+       struct ixgbevf_adapter *adapter = netdev_priv(netdev);
+       int err = 0;
+
+       if (features & NETIF_F_LOOPBACK)
+               err = ixgbevf_set_tx_loopback(adapter, true);
+       else if (netdev->hw_features & NETIF_F_LOOPBACK)
+               err = ixgbevf_set_tx_loopback(adapter, false);
+
+       if (!err)
+               netdev->features = features;
+
+       return err;
+}
+
 #ifdef CONFIG_NET_POLL_CONTROLLER
 /* Polling 'interrupt' - used by things like netconsole to send skbs
  * without having to re-enable interrupts. It's not called while
@@ -3883,6 +3915,7 @@ static const struct net_device_ops ixgbevf_netdev_ops = {
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = ixgbevf_set_mac,
        .ndo_change_mtu         = ixgbevf_change_mtu,
+       .ndo_set_features       = ixgbevf_set_features,
        .ndo_tx_timeout         = ixgbevf_tx_timeout,
        .ndo_vlan_rx_add_vid    = ixgbevf_vlan_rx_add_vid,
        .ndo_vlan_rx_kill_vid   = ixgbevf_vlan_rx_kill_vid,
@@ -4004,7 +4037,15 @@ static int ixgbevf_probe(struct pci_dev *pdev, const 
struct pci_device_id *ent)
                           NETIF_F_TSO6 |
                           NETIF_F_RXCSUM;
 
-       netdev->features = netdev->hw_features |
+       switch (hw->api_version) {
+       case ixgbe_mbox_api_12:
+               netdev->hw_features |= NETIF_F_LOOPBACK;
+               break;
+       default:
+               break;
+       }
+
+       netdev->features = (netdev->hw_features & (~NETIF_F_LOOPBACK)) |
                           NETIF_F_HW_VLAN_CTAG_TX |
                           NETIF_F_HW_VLAN_CTAG_RX |
                           NETIF_F_HW_VLAN_CTAG_FILTER;
diff --git a/drivers/net/ethernet/intel/ixgbevf/mbx.h 
b/drivers/net/ethernet/intel/ixgbevf/mbx.h
index 0bc3005..a094a01 100644
--- a/drivers/net/ethernet/intel/ixgbevf/mbx.h
+++ b/drivers/net/ethernet/intel/ixgbevf/mbx.h
@@ -86,6 +86,7 @@ enum ixgbe_pfvf_api_rev {
        ixgbe_mbox_api_10,      /* API version 1.0, linux/freebsd VF driver */
        ixgbe_mbox_api_20,      /* API version 2.0, solaris Phase1 VF driver */
        ixgbe_mbox_api_11,      /* API version 1.1, linux/freebsd VF driver */
+       ixgbe_mbox_api_12,      /* API version 1.2, linux/freebsd VF driver */
        /* This value should always be last */
        ixgbe_mbox_api_unknown, /* indicates that API version is not known */
 };
@@ -104,6 +105,9 @@ enum ixgbe_pfvf_api_rev {
 /* mailbox API, version 1.1 VF requests */
 #define IXGBE_VF_GET_QUEUE     0x09 /* get queue configuration */
 
+/* mailbox API, version 1.2 VF requests */
+#define IXGBE_VF_ENABLE_TX_LOOPBACK 0x0a
+
 /* GET_QUEUES return data indices within the mailbox */
 #define IXGBE_VF_TX_QUEUES     1       /* number of Tx queues supported */
 #define IXGBE_VF_RX_QUEUES     2       /* number of Rx queues supported */
diff --git a/drivers/net/ethernet/intel/ixgbevf/vf.c 
b/drivers/net/ethernet/intel/ixgbevf/vf.c
index cdb53be..82bda53 100644
--- a/drivers/net/ethernet/intel/ixgbevf/vf.c
+++ b/drivers/net/ethernet/intel/ixgbevf/vf.c
@@ -536,6 +536,35 @@ int ixgbevf_negotiate_api_version(struct ixgbe_hw *hw, int 
api)
        return err;
 }
 
+int ixgbevf_enable_tx_loopback(struct ixgbe_hw *hw, bool enabled)
+{
+       int err;
+       u32 msg[2];
+
+       switch (hw->api_version) {
+       case ixgbe_mbox_api_12:
+               break;
+       default:
+               return -1;
+       }
+
+       msg[0] = IXGBE_VF_ENABLE_TX_LOOPBACK;
+       msg[1] = enabled;
+       err = hw->mbx.ops.write_posted(hw, msg, 2);
+
+       if (!err)
+               err = hw->mbx.ops.read_posted(hw, msg, 2);
+
+       if (!err) {
+               msg[0] &= ~IXGBE_VT_MSGTYPE_CTS;
+               if (msg[0] !=
+                       (IXGBE_VF_ENABLE_TX_LOOPBACK | IXGBE_VT_MSGTYPE_ACK))
+                       return IXGBE_ERR_MBX;
+       }
+
+       return err;
+}
+
 int ixgbevf_get_queues(struct ixgbe_hw *hw, unsigned int *num_tcs,
                       unsigned int *default_tc)
 {
diff --git a/drivers/net/ethernet/intel/ixgbevf/vf.h 
b/drivers/net/ethernet/intel/ixgbevf/vf.h
index 5b17242..6ae29fb 100644
--- a/drivers/net/ethernet/intel/ixgbevf/vf.h
+++ b/drivers/net/ethernet/intel/ixgbevf/vf.h
@@ -87,7 +87,7 @@ struct ixgbe_mac_info {
        enum ixgbe_mac_type type;
 
        s32  mc_filter_type;
-
+       bool tx_loopback_enabled;
        bool get_link_status;
        u32  max_tx_queues;
        u32  max_rx_queues;
@@ -208,5 +208,6 @@ void ixgbevf_rlpml_set_vf(struct ixgbe_hw *hw, u16 
max_size);
 int ixgbevf_negotiate_api_version(struct ixgbe_hw *hw, int api);
 int ixgbevf_get_queues(struct ixgbe_hw *hw, unsigned int *num_tcs,
                       unsigned int *default_tc);
+int ixgbevf_enable_tx_loopback(struct ixgbe_hw *hw, bool enabled);
 #endif /* __IXGBE_VF_H__ */
 
-- 
1.9.1


------------------------------------------------------------------------------
Download BIRT iHub F-Type - The Free Enterprise-Grade BIRT Server
from Actuate! Instantly Supercharge Your Business Reports and Dashboards
with Interactivity, Sharing, Native Excel Exports, App Integration & more
Get technology previously reserved for billion-dollar corporations, FREE
http://pubads.g.doubleclick.net/gampad/clk?id=190641631&iu=/4140/ostg.clktrk
_______________________________________________
E1000-devel mailing list
E1000-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/e1000-devel
To learn more about Intel&#174; Ethernet, visit 
http://communities.intel.com/community/wired

Reply via email to