Commit af14827f authored by David S. Miller's avatar David S. Miller

Merge branch '100GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/next-queue

Jeff Kirsher says:

====================
100GbE Intel Wired LAN Driver Updates 2017-10-03

This series contains updates to fm10k only.

Jake provides majority of the changes in this series, starting with using
fm10k_prepare_for_reset() if we lose PCIe link.  Before we would detach
the device and close the netdev, which left a lot of items still active,
such as the Tx/Rx resources.  This could cause problems where register
reads would return potentially invalid values and would result in unknown
driver behavior, so call fm10k_prepare_for_reset() much like we do for
suspend/resume cycles.  This will attempt to shutdown as much as possible
to prevent possible issues.  Then replaced the PCI specific legacy power
management hooks with the new generic power management hooks for both
suspend and hibernate.  Introduced a workqueue item which monitors a
queue of MAC and VLAN requests since a large number of MAC address or
VLAN updates at once can overload the mailbox with too many messages at
once.  Fixed a cppcheck warning by properly declaring the min_rate and
max_rate variables in the declaration and definition for .ndo_set_vf_bw,
rather than using "unused" for the minimum rates.

Joe Perches fixes the backward logic when using net_ratelimit().
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 6c557001 3e256ac5
...@@ -248,6 +248,29 @@ struct fm10k_udp_port { ...@@ -248,6 +248,29 @@ struct fm10k_udp_port {
__be16 port; __be16 port;
}; };
enum fm10k_macvlan_request_type {
FM10K_UC_MAC_REQUEST,
FM10K_MC_MAC_REQUEST,
FM10K_VLAN_REQUEST
};
struct fm10k_macvlan_request {
enum fm10k_macvlan_request_type type;
struct list_head list;
union {
struct fm10k_mac_request {
u8 addr[ETH_ALEN];
u16 glort;
u16 vid;
} mac;
struct fm10k_vlan_request {
u32 vid;
u8 vsi;
} vlan;
};
bool set;
};
/* one work queue for entire driver */ /* one work queue for entire driver */
extern struct workqueue_struct *fm10k_workqueue; extern struct workqueue_struct *fm10k_workqueue;
...@@ -270,11 +293,15 @@ enum fm10k_flags_t { ...@@ -270,11 +293,15 @@ enum fm10k_flags_t {
enum fm10k_state_t { enum fm10k_state_t {
__FM10K_RESETTING, __FM10K_RESETTING,
__FM10K_RESET_DETACHED,
__FM10K_RESET_SUSPENDED,
__FM10K_DOWN, __FM10K_DOWN,
__FM10K_SERVICE_SCHED, __FM10K_SERVICE_SCHED,
__FM10K_SERVICE_REQUEST, __FM10K_SERVICE_REQUEST,
__FM10K_SERVICE_DISABLE, __FM10K_SERVICE_DISABLE,
__FM10K_MBX_LOCK, __FM10K_MACVLAN_SCHED,
__FM10K_MACVLAN_REQUEST,
__FM10K_MACVLAN_DISABLE,
__FM10K_LINK_DOWN, __FM10K_LINK_DOWN,
__FM10K_UPDATING_STATS, __FM10K_UPDATING_STATS,
/* This value must be last and determines the BITMAP size */ /* This value must be last and determines the BITMAP size */
...@@ -344,6 +371,8 @@ struct fm10k_intfc { ...@@ -344,6 +371,8 @@ struct fm10k_intfc {
struct fm10k_hw_stats stats; struct fm10k_hw_stats stats;
struct fm10k_hw hw; struct fm10k_hw hw;
/* Mailbox lock */
spinlock_t mbx_lock;
u32 __iomem *uc_addr; u32 __iomem *uc_addr;
u32 __iomem *sw_addr; u32 __iomem *sw_addr;
u16 msg_enable; u16 msg_enable;
...@@ -365,6 +394,12 @@ struct fm10k_intfc { ...@@ -365,6 +394,12 @@ struct fm10k_intfc {
struct list_head vxlan_port; struct list_head vxlan_port;
struct list_head geneve_port; struct list_head geneve_port;
/* MAC/VLAN update queue */
struct list_head macvlan_requests;
struct delayed_work macvlan_task;
/* MAC/VLAN update queue lock */
spinlock_t macvlan_lock;
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
struct dentry *dbg_intfc; struct dentry *dbg_intfc;
#endif /* CONFIG_DEBUG_FS */ #endif /* CONFIG_DEBUG_FS */
...@@ -384,23 +419,17 @@ struct fm10k_intfc { ...@@ -384,23 +419,17 @@ struct fm10k_intfc {
static inline void fm10k_mbx_lock(struct fm10k_intfc *interface) static inline void fm10k_mbx_lock(struct fm10k_intfc *interface)
{ {
/* busy loop if we cannot obtain the lock as some calls spin_lock(&interface->mbx_lock);
* such as ndo_set_rx_mode may be made in atomic context
*/
while (test_and_set_bit(__FM10K_MBX_LOCK, interface->state))
udelay(20);
} }
static inline void fm10k_mbx_unlock(struct fm10k_intfc *interface) static inline void fm10k_mbx_unlock(struct fm10k_intfc *interface)
{ {
/* flush memory to make sure state is correct */ spin_unlock(&interface->mbx_lock);
smp_mb__before_atomic();
clear_bit(__FM10K_MBX_LOCK, interface->state);
} }
static inline int fm10k_mbx_trylock(struct fm10k_intfc *interface) static inline int fm10k_mbx_trylock(struct fm10k_intfc *interface)
{ {
return !test_and_set_bit(__FM10K_MBX_LOCK, interface->state); return spin_trylock(&interface->mbx_lock);
} }
/* fm10k_test_staterr - test bits in Rx descriptor status and error fields */ /* fm10k_test_staterr - test bits in Rx descriptor status and error fields */
...@@ -490,6 +519,7 @@ void fm10k_up(struct fm10k_intfc *interface); ...@@ -490,6 +519,7 @@ void fm10k_up(struct fm10k_intfc *interface);
void fm10k_down(struct fm10k_intfc *interface); void fm10k_down(struct fm10k_intfc *interface);
void fm10k_update_stats(struct fm10k_intfc *interface); void fm10k_update_stats(struct fm10k_intfc *interface);
void fm10k_service_event_schedule(struct fm10k_intfc *interface); void fm10k_service_event_schedule(struct fm10k_intfc *interface);
void fm10k_macvlan_schedule(struct fm10k_intfc *interface);
void fm10k_update_rx_drop_en(struct fm10k_intfc *interface); void fm10k_update_rx_drop_en(struct fm10k_intfc *interface);
#ifdef CONFIG_NET_POLL_CONTROLLER #ifdef CONFIG_NET_POLL_CONTROLLER
void fm10k_netpoll(struct net_device *netdev); void fm10k_netpoll(struct net_device *netdev);
...@@ -510,6 +540,12 @@ void fm10k_reset_rx_state(struct fm10k_intfc *); ...@@ -510,6 +540,12 @@ void fm10k_reset_rx_state(struct fm10k_intfc *);
int fm10k_setup_tc(struct net_device *dev, u8 tc); int fm10k_setup_tc(struct net_device *dev, u8 tc);
int fm10k_open(struct net_device *netdev); int fm10k_open(struct net_device *netdev);
int fm10k_close(struct net_device *netdev); int fm10k_close(struct net_device *netdev);
int fm10k_queue_vlan_request(struct fm10k_intfc *interface, u32 vid,
u8 vsi, bool set);
int fm10k_queue_mac_request(struct fm10k_intfc *interface, u16 glort,
const unsigned char *addr, u16 vid, bool set);
void fm10k_clear_macvlan_queue(struct fm10k_intfc *interface,
u16 glort, bool vlans);
/* Ethtool */ /* Ethtool */
void fm10k_set_ethtool_ops(struct net_device *dev); void fm10k_set_ethtool_ops(struct net_device *dev);
...@@ -526,8 +562,8 @@ s32 fm10k_iov_update_pvid(struct fm10k_intfc *interface, u16 glort, u16 pvid); ...@@ -526,8 +562,8 @@ s32 fm10k_iov_update_pvid(struct fm10k_intfc *interface, u16 glort, u16 pvid);
int fm10k_ndo_set_vf_mac(struct net_device *netdev, int vf_idx, u8 *mac); int fm10k_ndo_set_vf_mac(struct net_device *netdev, int vf_idx, u8 *mac);
int fm10k_ndo_set_vf_vlan(struct net_device *netdev, int fm10k_ndo_set_vf_vlan(struct net_device *netdev,
int vf_idx, u16 vid, u8 qos, __be16 vlan_proto); int vf_idx, u16 vid, u8 qos, __be16 vlan_proto);
int fm10k_ndo_set_vf_bw(struct net_device *netdev, int vf_idx, int rate, int fm10k_ndo_set_vf_bw(struct net_device *netdev, int vf_idx,
int unused); int __always_unused min_rate, int max_rate);
int fm10k_ndo_get_vf_config(struct net_device *netdev, int fm10k_ndo_get_vf_config(struct net_device *netdev,
int vf_idx, struct ifla_vf_info *ivi); int vf_idx, struct ifla_vf_info *ivi);
......
...@@ -35,10 +35,133 @@ static s32 fm10k_iov_msg_error(struct fm10k_hw *hw, u32 **results, ...@@ -35,10 +35,133 @@ static s32 fm10k_iov_msg_error(struct fm10k_hw *hw, u32 **results,
return fm10k_tlv_msg_error(hw, results, mbx); return fm10k_tlv_msg_error(hw, results, mbx);
} }
/**
* fm10k_iov_msg_queue_mac_vlan - Message handler for MAC/VLAN request from VF
* @hw: Pointer to hardware structure
* @results: Pointer array to message, results[0] is pointer to message
* @mbx: Pointer to mailbox information structure
*
* This function is a custom handler for MAC/VLAN requests from the VF. The
* assumption is that it is acceptable to directly hand off the message from
* the VF to the PF's switch manager. However, we use a MAC/VLAN message
* queue to avoid overloading the mailbox when a large number of requests
* come in.
**/
static s32 fm10k_iov_msg_queue_mac_vlan(struct fm10k_hw *hw, u32 **results,
struct fm10k_mbx_info *mbx)
{
struct fm10k_vf_info *vf_info = (struct fm10k_vf_info *)mbx;
struct fm10k_intfc *interface = hw->back;
u8 mac[ETH_ALEN];
u32 *result;
int err = 0;
bool set;
u16 vlan;
u32 vid;
/* we shouldn't be updating rules on a disabled interface */
if (!FM10K_VF_FLAG_ENABLED(vf_info))
err = FM10K_ERR_PARAM;
if (!err && !!results[FM10K_MAC_VLAN_MSG_VLAN]) {
result = results[FM10K_MAC_VLAN_MSG_VLAN];
/* record VLAN id requested */
err = fm10k_tlv_attr_get_u32(result, &vid);
if (err)
return err;
set = !(vid & FM10K_VLAN_CLEAR);
vid &= ~FM10K_VLAN_CLEAR;
/* if the length field has been set, this is a multi-bit
* update request. For multi-bit requests, simply disallow
* them when the pf_vid has been set. In this case, the PF
* should have already cleared the VLAN_TABLE, and if we
* allowed them, it could allow a rogue VF to receive traffic
* on a VLAN it was not assigned. In the single-bit case, we
* need to modify requests for VLAN 0 to use the default PF or
* SW vid when assigned.
*/
if (vid >> 16) {
/* prevent multi-bit requests when PF has
* administratively set the VLAN for this VF
*/
if (vf_info->pf_vid)
return FM10K_ERR_PARAM;
} else {
err = fm10k_iov_select_vid(vf_info, (u16)vid);
if (err < 0)
return err;
vid = err;
}
/* update VSI info for VF in regards to VLAN table */
err = hw->mac.ops.update_vlan(hw, vid, vf_info->vsi, set);
}
if (!err && !!results[FM10K_MAC_VLAN_MSG_MAC]) {
result = results[FM10K_MAC_VLAN_MSG_MAC];
/* record unicast MAC address requested */
err = fm10k_tlv_attr_get_mac_vlan(result, mac, &vlan);
if (err)
return err;
/* block attempts to set MAC for a locked device */
if (is_valid_ether_addr(vf_info->mac) &&
!ether_addr_equal(mac, vf_info->mac))
return FM10K_ERR_PARAM;
set = !(vlan & FM10K_VLAN_CLEAR);
vlan &= ~FM10K_VLAN_CLEAR;
err = fm10k_iov_select_vid(vf_info, vlan);
if (err < 0)
return err;
vlan = (u16)err;
/* Add this request to the MAC/VLAN queue */
err = fm10k_queue_mac_request(interface, vf_info->glort,
mac, vlan, set);
}
if (!err && !!results[FM10K_MAC_VLAN_MSG_MULTICAST]) {
result = results[FM10K_MAC_VLAN_MSG_MULTICAST];
/* record multicast MAC address requested */
err = fm10k_tlv_attr_get_mac_vlan(result, mac, &vlan);
if (err)
return err;
/* verify that the VF is allowed to request multicast */
if (!(vf_info->vf_flags & FM10K_VF_FLAG_MULTI_ENABLED))
return FM10K_ERR_PARAM;
set = !(vlan & FM10K_VLAN_CLEAR);
vlan &= ~FM10K_VLAN_CLEAR;
err = fm10k_iov_select_vid(vf_info, vlan);
if (err < 0)
return err;
vlan = (u16)err;
/* Add this request to the MAC/VLAN queue */
err = fm10k_queue_mac_request(interface, vf_info->glort,
mac, vlan, set);
}
return err;
}
static const struct fm10k_msg_data iov_mbx_data[] = { static const struct fm10k_msg_data iov_mbx_data[] = {
FM10K_TLV_MSG_TEST_HANDLER(fm10k_tlv_msg_test), FM10K_TLV_MSG_TEST_HANDLER(fm10k_tlv_msg_test),
FM10K_VF_MSG_MSIX_HANDLER(fm10k_iov_msg_msix_pf), FM10K_VF_MSG_MSIX_HANDLER(fm10k_iov_msg_msix_pf),
FM10K_VF_MSG_MAC_VLAN_HANDLER(fm10k_iov_msg_mac_vlan_pf), FM10K_VF_MSG_MAC_VLAN_HANDLER(fm10k_iov_msg_queue_mac_vlan),
FM10K_VF_MSG_LPORT_STATE_HANDLER(fm10k_iov_msg_lport_state_pf), FM10K_VF_MSG_LPORT_STATE_HANDLER(fm10k_iov_msg_lport_state_pf),
FM10K_TLV_MSG_ERROR_HANDLER(fm10k_iov_msg_error), FM10K_TLV_MSG_ERROR_HANDLER(fm10k_iov_msg_error),
}; };
...@@ -126,8 +249,10 @@ s32 fm10k_iov_mbx(struct fm10k_intfc *interface) ...@@ -126,8 +249,10 @@ s32 fm10k_iov_mbx(struct fm10k_intfc *interface)
hw->mbx.ops.process(hw, &hw->mbx); hw->mbx.ops.process(hw, &hw->mbx);
/* verify port mapping is valid, if not reset port */ /* verify port mapping is valid, if not reset port */
if (vf_info->vf_flags && !fm10k_glort_valid_pf(hw, glort)) if (vf_info->vf_flags && !fm10k_glort_valid_pf(hw, glort)) {
hw->iov.ops.reset_lport(hw, vf_info); hw->iov.ops.reset_lport(hw, vf_info);
fm10k_clear_macvlan_queue(interface, glort, false);
}
/* reset VFs that have mailbox timed out */ /* reset VFs that have mailbox timed out */
if (!mbx->timeout) { if (!mbx->timeout) {
...@@ -190,6 +315,7 @@ void fm10k_iov_suspend(struct pci_dev *pdev) ...@@ -190,6 +315,7 @@ void fm10k_iov_suspend(struct pci_dev *pdev)
hw->iov.ops.reset_resources(hw, vf_info); hw->iov.ops.reset_resources(hw, vf_info);
hw->iov.ops.reset_lport(hw, vf_info); hw->iov.ops.reset_lport(hw, vf_info);
fm10k_clear_macvlan_queue(interface, vf_info->glort, false);
} }
} }
...@@ -414,6 +540,8 @@ static inline void fm10k_reset_vf_info(struct fm10k_intfc *interface, ...@@ -414,6 +540,8 @@ static inline void fm10k_reset_vf_info(struct fm10k_intfc *interface,
/* disable LPORT for this VF which clears switch rules */ /* disable LPORT for this VF which clears switch rules */
hw->iov.ops.reset_lport(hw, vf_info); hw->iov.ops.reset_lport(hw, vf_info);
fm10k_clear_macvlan_queue(interface, vf_info->glort, false);
/* assign new MAC+VLAN for this VF */ /* assign new MAC+VLAN for this VF */
hw->iov.ops.assign_default_mac_vlan(hw, vf_info); hw->iov.ops.assign_default_mac_vlan(hw, vf_info);
...@@ -485,7 +613,7 @@ int fm10k_ndo_set_vf_vlan(struct net_device *netdev, int vf_idx, u16 vid, ...@@ -485,7 +613,7 @@ int fm10k_ndo_set_vf_vlan(struct net_device *netdev, int vf_idx, u16 vid,
} }
int fm10k_ndo_set_vf_bw(struct net_device *netdev, int vf_idx, int fm10k_ndo_set_vf_bw(struct net_device *netdev, int vf_idx,
int __always_unused unused, int rate) int __always_unused min_rate, int max_rate)
{ {
struct fm10k_intfc *interface = netdev_priv(netdev); struct fm10k_intfc *interface = netdev_priv(netdev);
struct fm10k_iov_data *iov_data = interface->iov_data; struct fm10k_iov_data *iov_data = interface->iov_data;
...@@ -496,14 +624,15 @@ int fm10k_ndo_set_vf_bw(struct net_device *netdev, int vf_idx, ...@@ -496,14 +624,15 @@ int fm10k_ndo_set_vf_bw(struct net_device *netdev, int vf_idx,
return -EINVAL; return -EINVAL;
/* rate limit cannot be less than 10Mbs or greater than link speed */ /* rate limit cannot be less than 10Mbs or greater than link speed */
if (rate && ((rate < FM10K_VF_TC_MIN) || rate > FM10K_VF_TC_MAX)) if (max_rate &&
(max_rate < FM10K_VF_TC_MIN || max_rate > FM10K_VF_TC_MAX))
return -EINVAL; return -EINVAL;
/* store values */ /* store values */
iov_data->vf_info[vf_idx].rate = rate; iov_data->vf_info[vf_idx].rate = max_rate;
/* update hardware configuration */ /* update hardware configuration */
hw->iov.ops.configure_tc(hw, vf_idx, rate); hw->iov.ops.configure_tc(hw, vf_idx, max_rate);
return 0; return 0;
} }
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
#include "fm10k.h" #include "fm10k.h"
#define DRV_VERSION "0.21.7-k" #define DRV_VERSION "0.22.1-k"
#define DRV_SUMMARY "Intel(R) Ethernet Switch Host Interface Driver" #define DRV_SUMMARY "Intel(R) Ethernet Switch Host Interface Driver"
const char fm10k_driver_version[] = DRV_VERSION; const char fm10k_driver_version[] = DRV_VERSION;
char fm10k_driver_name[] = "fm10k"; char fm10k_driver_name[] = "fm10k";
...@@ -806,9 +806,10 @@ static int fm10k_tso(struct fm10k_ring *tx_ring, ...@@ -806,9 +806,10 @@ static int fm10k_tso(struct fm10k_ring *tx_ring,
tx_desc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size); tx_desc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
return 1; return 1;
err_vxlan: err_vxlan:
tx_ring->netdev->features &= ~NETIF_F_GSO_UDP_TUNNEL; tx_ring->netdev->features &= ~NETIF_F_GSO_UDP_TUNNEL;
if (!net_ratelimit()) if (net_ratelimit())
netdev_err(tx_ring->netdev, netdev_err(tx_ring->netdev,
"TSO requested for unsupported tunnel, disabling offload\n"); "TSO requested for unsupported tunnel, disabling offload\n");
return -1; return -1;
......
...@@ -1186,7 +1186,7 @@ s32 fm10k_iov_msg_msix_pf(struct fm10k_hw *hw, u32 **results, ...@@ -1186,7 +1186,7 @@ s32 fm10k_iov_msg_msix_pf(struct fm10k_hw *hw, u32 **results,
* Will report an error if the VLAN ID is out of range. For VID = 0, it will * Will report an error if the VLAN ID is out of range. For VID = 0, it will
* return either the pf_vid or sw_vid depending on which one is set. * return either the pf_vid or sw_vid depending on which one is set.
*/ */
static s32 fm10k_iov_select_vid(struct fm10k_vf_info *vf_info, u16 vid) s32 fm10k_iov_select_vid(struct fm10k_vf_info *vf_info, u16 vid)
{ {
if (!vid) if (!vid)
return vf_info->pf_vid ? vf_info->pf_vid : vf_info->sw_vid; return vf_info->pf_vid ? vf_info->pf_vid : vf_info->sw_vid;
......
/* Intel(R) Ethernet Switch Host Interface Driver /* Intel(R) Ethernet Switch Host Interface Driver
* Copyright(c) 2013 - 2016 Intel Corporation. * Copyright(c) 2013 - 2017 Intel Corporation.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
...@@ -114,6 +114,7 @@ extern const struct fm10k_tlv_attr fm10k_err_msg_attr[]; ...@@ -114,6 +114,7 @@ extern const struct fm10k_tlv_attr fm10k_err_msg_attr[];
#define FM10K_PF_MSG_ERR_HANDLER(msg, func) \ #define FM10K_PF_MSG_ERR_HANDLER(msg, func) \
FM10K_MSG_HANDLER(FM10K_PF_MSG_ID_##msg, fm10k_err_msg_attr, func) FM10K_MSG_HANDLER(FM10K_PF_MSG_ID_##msg, fm10k_err_msg_attr, func)
s32 fm10k_iov_select_vid(struct fm10k_vf_info *vf_info, u16 vid);
s32 fm10k_iov_msg_msix_pf(struct fm10k_hw *, u32 **, struct fm10k_mbx_info *); s32 fm10k_iov_msg_msix_pf(struct fm10k_hw *, u32 **, struct fm10k_mbx_info *);
s32 fm10k_iov_msg_mac_vlan_pf(struct fm10k_hw *, u32 **, s32 fm10k_iov_msg_mac_vlan_pf(struct fm10k_hw *, u32 **,
struct fm10k_mbx_info *); struct fm10k_mbx_info *);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment