Skip to content

Commit

Permalink
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/gi…
Browse files Browse the repository at this point in the history
…t/jkirsher/net-next

Jeff Kirsher says:

====================
Intel Wired LAN Driver Updates

This series contains updates to i40e and pci_regs.h.

Anjali provides a patch to prevent messages from stray HMC events, except
at interrupt message level, and refactors the HMC error handling.

Catherine adds routines in probe to populate/check PCI bus speed and width,
then verify we are in a 8GT/s x8 PCIe slot and warn when we are not.

Shannon adds Wake-on-LAN support for i40e, fixes curly brace use as well as
return type for i40e_vsi_clear_rings().

Joseph implements receive offload for VXLAN for i40e, where the hardware
supports checksum offload/verification of the inner/outer header.

Mitch provides the bulk of the changes, where he refactors the VF reset
code so that it works on real hardware.  Then does code cleanup by
calling existing functions to enable and disable queues for VFs and
remove unused functions.  Removes a unnecessary log messages that are
seen at every VF reset, for example complaining about disabling queues
that are already disabled.  Fixes an error return when the VF asks to
add an invalid MAC address and if the VF sends a bad message, make it
more informative about what is actually going on.

Jesse refactors the LED function to flash LED lights correctly.

v2:
 - removed patch 5 "i40e: add set settings and pauseparam" based on
   feedback from Ben Hutchings, will re-work that patch for later
   submission
 - Added patch "i40e: Implementation of vxlan ndo's" from Joseph to
   address Or Gerlitz's questions and concerns.  This patch adds the
   implementation for the VXLAN ndo's and allows the hardware to do
   receive checksum offload for inner packets on the UDP ports that
   VXLAN notifies us about.
 - Added patch "i40e: using for_each_set_bit to simplify the code"
   from Wei Yongjun.  This patch uses for_each_set_bit() to simply
   the code.

v3:
 - fixed indentation issue in patch 11 based on feedback from
   Sergei Shtylyov.

Sorry for the delayed release of v4, it was delayed to the holidays.

v4:
 - Addressed Or Gerlitz's concerns about trying to get a hold of a mutex
   while holding a spin lock in patch 6 by executing the AQ commands from
   a subtask.
 - Addressed David Miller's Kconfig concerns by creating a Kconfig VXLAN
   option for i40e and wrapped appropriate code with the config option in
   patch 6.
 - Updated patch 7 based on the changes made in patch 6 in the above two
   bullets.

v5:
 - Added the patch to pci_regs.h based on David Miller's feedback to add
   PCI defines for speed and width
 - Updated patch 3 description to better explain the changes based on
   feedback from David Miller
 - Updated patch 4 to use the newly added defines to pci_regs.h instead
   of local defines
 - Updated patch 7 to use <net/vxlan.h> in the #include based on feedback
   from David Miller
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Jan 5, 2014
2 parents fbfcec6 + f4a1c5c commit 653864d
Show file tree
Hide file tree
Showing 13 changed files with 720 additions and 539 deletions.
13 changes: 13 additions & 0 deletions drivers/net/ethernet/intel/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,19 @@ config I40E
To compile this driver as a module, choose M here. The module
will be called i40e.

config I40E_VXLAN
bool "Virtual eXtensible Local Area Network Support"
default n
depends on I40E && VXLAN && !(I40E=y && VXLAN=m)
---help---
This allows one to create VXLAN virtual interfaces that provide
Layer 2 Networks over Layer 3 Networks. VXLAN is often used
to tunnel virtual network infrastructure in virtualized environments.
Say Y here if you want to use Virtual eXtensible Local Area Network
(VXLAN) in the driver.

If unsure, say N.

config I40EVF
tristate "Intel(R) XL710 X710 Virtual Function Ethernet support"
depends on PCI_MSI
Expand Down
13 changes: 12 additions & 1 deletion drivers/net/ethernet/intel/i40e/i40e.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#define _I40E_H_

#include <net/tcp.h>
#include <net/udp.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/errno.h>
Expand Down Expand Up @@ -205,7 +206,13 @@ struct i40e_pf {
u16 rss_size_max; /* HW defined max RSS queues */
u16 fdir_pf_filter_count; /* num of guaranteed filters for this PF */
u8 atr_sample_rate;
bool wol_en;

#ifdef CONFIG_I40E_VXLAN
__be16 vxlan_ports[I40E_MAX_PF_UDP_OFFLOAD_PORTS];
u16 pending_vxlan_bitmap;

#endif
enum i40e_interrupt_policy int_policy;
u16 rx_itr_default;
u16 tx_itr_default;
Expand Down Expand Up @@ -237,7 +244,10 @@ struct i40e_pf {
#define I40E_FLAG_DCB_ENABLED (u64)(1 << 21)
#define I40E_FLAG_FDIR_ENABLED (u64)(1 << 22)
#define I40E_FLAG_FDIR_ATR_ENABLED (u64)(1 << 23)
#define I40E_FLAG_MFP_ENABLED (u64)(1 << 27)
#define I40E_FLAG_MFP_ENABLED (u64)(1 << 26)
#ifdef CONFIG_I40E_VXLAN
#define I40E_FLAG_VXLAN_FILTER_SYNC (u64)(1 << 27)
#endif

u16 num_tx_queues;
u16 num_rx_queues;
Expand Down Expand Up @@ -533,6 +543,7 @@ struct i40e_vsi *i40e_vsi_setup(struct i40e_pf *pf, u8 type,
int i40e_vsi_release(struct i40e_vsi *vsi);
struct i40e_vsi *i40e_vsi_lookup(struct i40e_pf *pf, enum i40e_vsi_type type,
struct i40e_vsi *start_vsi);
int i40e_vsi_control_rings(struct i40e_vsi *vsi, bool enable);
int i40e_reconfig_rss_queues(struct i40e_pf *pf, int queue_count);
struct i40e_veb *i40e_veb_setup(struct i40e_pf *pf, u16 flags, u16 uplink_seid,
u16 downlink_seid, u8 enabled_tc);
Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h
Original file line number Diff line number Diff line change
Expand Up @@ -1918,6 +1918,7 @@ struct i40e_aqc_add_udp_tunnel {
u8 protocol_index;
#define I40E_AQC_TUNNEL_TYPE_MAC 0x0
#define I40E_AQC_TUNNEL_TYPE_UDP 0x1
#define I40E_AQC_TUNNEL_TYPE_VXLAN 0x2
u8 reserved[12];
};

Expand Down
193 changes: 166 additions & 27 deletions drivers/net/ethernet/intel/i40e/i40e_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,38 @@ void i40e_clear_pxe_mode(struct i40e_hw *hw)
}
}

/**
* i40e_led_is_mine - helper to find matching led
* @hw: pointer to the hw struct
* @idx: index into GPIO registers
*
* returns: 0 if no match, otherwise the value of the GPIO_CTL register
*/
static u32 i40e_led_is_mine(struct i40e_hw *hw, int idx)
{
u32 gpio_val = 0;
u32 port;

if (!hw->func_caps.led[idx])
return 0;

gpio_val = rd32(hw, I40E_GLGEN_GPIO_CTL(idx));
port = (gpio_val & I40E_GLGEN_GPIO_CTL_PRT_NUM_MASK) >>
I40E_GLGEN_GPIO_CTL_PRT_NUM_SHIFT;

/* if PRT_NUM_NA is 1 then this LED is not port specific, OR
* if it is not our port then ignore
*/
if ((gpio_val & I40E_GLGEN_GPIO_CTL_PRT_NUM_NA_MASK) ||
(port != hw->port))
return 0;

return gpio_val;
}

#define I40E_LED0 22
#define I40E_LINK_ACTIVITY 0xC

/**
* i40e_led_get - return current on/off mode
* @hw: pointer to the hw struct
Expand All @@ -411,24 +443,20 @@ void i40e_clear_pxe_mode(struct i40e_hw *hw)
**/
u32 i40e_led_get(struct i40e_hw *hw)
{
u32 gpio_val = 0;
u32 mode = 0;
u32 port;
int i;

for (i = 0; i < I40E_HW_CAP_MAX_GPIO; i++) {
if (!hw->func_caps.led[i])
continue;

gpio_val = rd32(hw, I40E_GLGEN_GPIO_CTL(i));
port = (gpio_val & I40E_GLGEN_GPIO_CTL_PRT_NUM_MASK)
>> I40E_GLGEN_GPIO_CTL_PRT_NUM_SHIFT;
/* as per the documentation GPIO 22-29 are the LED
* GPIO pins named LED0..LED7
*/
for (i = I40E_LED0; i <= I40E_GLGEN_GPIO_CTL_MAX_INDEX; i++) {
u32 gpio_val = i40e_led_is_mine(hw, i);

if (port != hw->port)
if (!gpio_val)
continue;

mode = (gpio_val & I40E_GLGEN_GPIO_CTL_LED_MODE_MASK)
>> I40E_GLGEN_GPIO_CTL_INT_MODE_SHIFT;
mode = (gpio_val & I40E_GLGEN_GPIO_CTL_LED_MODE_MASK) >>
I40E_GLGEN_GPIO_CTL_LED_MODE_SHIFT;
break;
}

Expand All @@ -438,31 +466,41 @@ u32 i40e_led_get(struct i40e_hw *hw)
/**
* i40e_led_set - set new on/off mode
* @hw: pointer to the hw struct
* @mode: 0=off, else on (see EAS for mode details)
* @mode: 0=off, 0xf=on (else see manual for mode details)
* @blink: true if the LED should blink when on, false if steady
*
* if this function is used to turn on the blink it should
* be used to disable the blink when restoring the original state.
**/
void i40e_led_set(struct i40e_hw *hw, u32 mode)
void i40e_led_set(struct i40e_hw *hw, u32 mode, bool blink)
{
u32 gpio_val = 0;
u32 led_mode = 0;
u32 port;
int i;

for (i = 0; i < I40E_HW_CAP_MAX_GPIO; i++) {
if (!hw->func_caps.led[i])
continue;
if (mode & 0xfffffff0)
hw_dbg(hw, "invalid mode passed in %X\n", mode);

gpio_val = rd32(hw, I40E_GLGEN_GPIO_CTL(i));
port = (gpio_val & I40E_GLGEN_GPIO_CTL_PRT_NUM_MASK)
>> I40E_GLGEN_GPIO_CTL_PRT_NUM_SHIFT;
/* as per the documentation GPIO 22-29 are the LED
* GPIO pins named LED0..LED7
*/
for (i = I40E_LED0; i <= I40E_GLGEN_GPIO_CTL_MAX_INDEX; i++) {
u32 gpio_val = i40e_led_is_mine(hw, i);

if (port != hw->port)
if (!gpio_val)
continue;

led_mode = (mode << I40E_GLGEN_GPIO_CTL_LED_MODE_SHIFT) &
I40E_GLGEN_GPIO_CTL_LED_MODE_MASK;
gpio_val &= ~I40E_GLGEN_GPIO_CTL_LED_MODE_MASK;
gpio_val |= led_mode;
/* this & is a bit of paranoia, but serves as a range check */
gpio_val |= ((mode << I40E_GLGEN_GPIO_CTL_LED_MODE_SHIFT) &
I40E_GLGEN_GPIO_CTL_LED_MODE_MASK);

if (mode == I40E_LINK_ACTIVITY)
blink = false;

gpio_val |= (blink ? 1 : 0) <<
I40E_GLGEN_GPIO_CTL_LED_BLINK_SHIFT;

wr32(hw, I40E_GLGEN_GPIO_CTL(i), gpio_val);
break;
}
}

Expand Down Expand Up @@ -1670,6 +1708,63 @@ i40e_status i40e_aq_start_lldp(struct i40e_hw *hw,
return status;
}

/**
* i40e_aq_add_udp_tunnel
* @hw: pointer to the hw struct
* @udp_port: the UDP port to add
* @header_len: length of the tunneling header length in DWords
* @protocol_index: protocol index type
* @cmd_details: pointer to command details structure or NULL
**/
i40e_status i40e_aq_add_udp_tunnel(struct i40e_hw *hw,
u16 udp_port, u8 header_len,
u8 protocol_index, u8 *filter_index,
struct i40e_asq_cmd_details *cmd_details)
{
struct i40e_aq_desc desc;
struct i40e_aqc_add_udp_tunnel *cmd =
(struct i40e_aqc_add_udp_tunnel *)&desc.params.raw;
struct i40e_aqc_del_udp_tunnel_completion *resp =
(struct i40e_aqc_del_udp_tunnel_completion *)&desc.params.raw;
i40e_status status;

i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_add_udp_tunnel);

cmd->udp_port = cpu_to_le16(udp_port);
cmd->header_len = header_len;
cmd->protocol_index = protocol_index;

status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);

if (!status)
*filter_index = resp->index;

return status;
}

/**
* i40e_aq_del_udp_tunnel
* @hw: pointer to the hw struct
* @index: filter index
* @cmd_details: pointer to command details structure or NULL
**/
i40e_status i40e_aq_del_udp_tunnel(struct i40e_hw *hw, u8 index,
struct i40e_asq_cmd_details *cmd_details)
{
struct i40e_aq_desc desc;
struct i40e_aqc_remove_udp_tunnel *cmd =
(struct i40e_aqc_remove_udp_tunnel *)&desc.params.raw;
i40e_status status;

i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_del_udp_tunnel);

cmd->index = index;

status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);

return status;
}

/**
* i40e_aq_delete_element - Delete switch element
* @hw: pointer to the hw struct
Expand Down Expand Up @@ -2029,3 +2124,47 @@ i40e_status i40e_set_filter_control(struct i40e_hw *hw,

return 0;
}
/**
* i40e_set_pci_config_data - store PCI bus info
* @hw: pointer to hardware structure
* @link_status: the link status word from PCI config space
*
* Stores the PCI bus info (speed, width, type) within the i40e_hw structure
**/
void i40e_set_pci_config_data(struct i40e_hw *hw, u16 link_status)
{
hw->bus.type = i40e_bus_type_pci_express;

switch (link_status & PCI_EXP_LNKSTA_NLW) {
case PCI_EXP_LNKSTA_NLW_X1:
hw->bus.width = i40e_bus_width_pcie_x1;
break;
case PCI_EXP_LNKSTA_NLW_X2:
hw->bus.width = i40e_bus_width_pcie_x2;
break;
case PCI_EXP_LNKSTA_NLW_X4:
hw->bus.width = i40e_bus_width_pcie_x4;
break;
case PCI_EXP_LNKSTA_NLW_X8:
hw->bus.width = i40e_bus_width_pcie_x8;
break;
default:
hw->bus.width = i40e_bus_width_unknown;
break;
}

switch (link_status & PCI_EXP_LNKSTA_CLS) {
case PCI_EXP_LNKSTA_CLS_2_5GB:
hw->bus.speed = i40e_bus_speed_2500;
break;
case PCI_EXP_LNKSTA_CLS_5_0GB:
hw->bus.speed = i40e_bus_speed_5000;
break;
case PCI_EXP_LNKSTA_CLS_8_0GB:
hw->bus.speed = i40e_bus_speed_8000;
break;
default:
hw->bus.speed = i40e_bus_speed_unknown;
break;
}
}
48 changes: 43 additions & 5 deletions drivers/net/ethernet/intel/i40e/i40e_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -844,8 +844,45 @@ static void i40e_diag_test(struct net_device *netdev,
static void i40e_get_wol(struct net_device *netdev,
struct ethtool_wolinfo *wol)
{
wol->supported = 0;
wol->wolopts = 0;
struct i40e_netdev_priv *np = netdev_priv(netdev);
struct i40e_pf *pf = np->vsi->back;
struct i40e_hw *hw = &pf->hw;
u16 wol_nvm_bits;

/* NVM bit on means WoL disabled for the port */
i40e_read_nvm_word(hw, I40E_SR_NVM_WAKE_ON_LAN, &wol_nvm_bits);
if ((1 << hw->port) & wol_nvm_bits) {
wol->supported = 0;
wol->wolopts = 0;
} else {
wol->supported = WAKE_MAGIC;
wol->wolopts = (pf->wol_en ? WAKE_MAGIC : 0);
}
}

static int i40e_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
{
struct i40e_netdev_priv *np = netdev_priv(netdev);
struct i40e_pf *pf = np->vsi->back;
struct i40e_hw *hw = &pf->hw;
u16 wol_nvm_bits;

/* NVM bit on means WoL disabled for the port */
i40e_read_nvm_word(hw, I40E_SR_NVM_WAKE_ON_LAN, &wol_nvm_bits);
if (((1 << hw->port) & wol_nvm_bits))
return -EOPNOTSUPP;

/* only magic packet is supported */
if (wol->wolopts && (wol->wolopts != WAKE_MAGIC))
return -EOPNOTSUPP;

/* is this a new value? */
if (pf->wol_en != !!wol->wolopts) {
pf->wol_en = !!wol->wolopts;
device_set_wakeup_enable(&pf->pdev->dev, pf->wol_en);
}

return 0;
}

static int i40e_nway_reset(struct net_device *netdev)
Expand Down Expand Up @@ -879,13 +916,13 @@ static int i40e_set_phys_id(struct net_device *netdev,
pf->led_status = i40e_led_get(hw);
return blink_freq;
case ETHTOOL_ID_ON:
i40e_led_set(hw, 0xF);
i40e_led_set(hw, 0xF, false);
break;
case ETHTOOL_ID_OFF:
i40e_led_set(hw, 0x0);
i40e_led_set(hw, 0x0, false);
break;
case ETHTOOL_ID_INACTIVE:
i40e_led_set(hw, pf->led_status);
i40e_led_set(hw, pf->led_status, false);
break;
}

Expand Down Expand Up @@ -1568,6 +1605,7 @@ static const struct ethtool_ops i40e_ethtool_ops = {
.nway_reset = i40e_nway_reset,
.get_link = ethtool_op_get_link,
.get_wol = i40e_get_wol,
.set_wol = i40e_set_wol,
.get_eeprom_len = i40e_get_eeprom_len,
.get_eeprom = i40e_get_eeprom,
.get_ringparam = i40e_get_ringparam,
Expand Down
Loading

0 comments on commit 653864d

Please sign in to comment.