Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net-next

Jeff Kirsher says:

====================
Intel Wired LAN Driver Updates 2014-06-24

This series contains updates to i40e and i40evf.

Greg provides a patch to stop the VF device after setting its MAC address.
This is due to if the host VMM administrator has changed the VF device's MAC
address then the i40e driver needs to halt the VF device so that the
administrator will be forced to reload the VF driver so that the VF driver
will start using the newly assigned MAC address.

Shannon provides several patches for i40e, first makes prep_for_test() a
void function since the return value was being ignored for the most part
by all its callers.  Adds a log warning when the firmware's API minor/major
number is not what we expect to assist the user by informing them they
may need to update their NVM or SW.  Cleans up a stray print message
so that it is similar to other print messages.  Ensures to set the
WoL flag when setting LAA and allow the user to set LAA again.  So do
not short-circuit the LAA assignment when the driver thinks it has
already been done as it is possible that the user might want to force
the address setting again.  Provides a couple more LAA fixes to ensure
the LAA gets restored after resets.

Neerav provides a patch for i40e to add a PF reset when a malicious driver
event for the PF occurs.  As per the specification when the PF driver
receives a malicious driver event the queue that caused the event is
already stopped and it is expected that the function that owns the queue
will reset the queue, but in some cases it may not be possible to determine
the queue, so it is suggested to reset the whole function.

Carolyn fixes ethtool coalesce settings to allow 0 as a disable value and
adds message to user about invalid values.

Jesse removes a reserved type which was not removed from the code.

Catherine provides a patch to add the ability to enable/disable link from
set_link)restart_an() which will make it easy to toggle link without
calling set_phy_config() when no other link settings need to change.

Anjali provides a patch to ensure we do a PF reset on Tx hang and that
way we avoid any Malicious Driver Detect (MDD) events because of a Tx
queue disable failure.

v2:
 - fixed the un-needed return in patch 2 based on feedback from Sergei Shtylyov
 - added punctuation to print statements and code comment based on
   feedback from Sergei Shtylyov
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2014-06-25 17:55:45 -07:00
commit 0b2fda8965
11 changed files with 128 additions and 49 deletions

View File

@ -362,6 +362,7 @@ struct i40e_mac_filter {
bool is_vf; /* filter belongs to a VF */
bool is_netdev; /* filter belongs to a netdev */
bool changed; /* filter needs to be sync'd to the HW */
bool is_laa; /* filter is a Locally Administered Address */
};
struct i40e_veb {
@ -617,6 +618,7 @@ static inline void i40e_dbg_init(void) {}
static inline void i40e_dbg_exit(void) {}
#endif /* CONFIG_DEBUG_FS*/
void i40e_irq_dynamic_enable(struct i40e_vsi *vsi, int vector);
void i40e_irq_dynamic_disable(struct i40e_vsi *vsi, int vector);
void i40e_irq_dynamic_disable_icr0(struct i40e_pf *pf);
void i40e_irq_dynamic_enable_icr0(struct i40e_pf *pf);
int i40e_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd);

View File

@ -971,12 +971,14 @@ i40e_status i40e_aq_clear_pxe_mode(struct i40e_hw *hw,
/**
* i40e_aq_set_link_restart_an
* @hw: pointer to the hw struct
* @enable_link: if true: enable link, if false: disable link
* @cmd_details: pointer to command details structure or NULL
*
* Sets up the link and restarts the Auto-Negotiation over the link.
**/
i40e_status i40e_aq_set_link_restart_an(struct i40e_hw *hw,
struct i40e_asq_cmd_details *cmd_details)
bool enable_link,
struct i40e_asq_cmd_details *cmd_details)
{
struct i40e_aq_desc desc;
struct i40e_aqc_set_link_restart_an *cmd =
@ -987,6 +989,10 @@ i40e_status i40e_aq_set_link_restart_an(struct i40e_hw *hw,
i40e_aqc_opc_set_link_restart_an);
cmd->command = I40E_AQ_PHY_RESTART_AN;
if (enable_link)
cmd->command |= I40E_AQ_PHY_LINK_ENABLE;
else
cmd->command &= ~I40E_AQ_PHY_LINK_ENABLE;
status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);

View File

@ -1027,9 +1027,10 @@ static int i40e_nway_reset(struct net_device *netdev)
struct i40e_netdev_priv *np = netdev_priv(netdev);
struct i40e_pf *pf = np->vsi->back;
struct i40e_hw *hw = &pf->hw;
bool link_up = hw->phy.link_info.link_info & I40E_AQ_LINK_UP;
i40e_status ret = 0;
ret = i40e_aq_set_link_restart_an(hw, NULL);
ret = i40e_aq_set_link_restart_an(hw, link_up, NULL);
if (ret) {
netdev_info(netdev, "link restart failed, aq_err=%d\n",
pf->hw.aq.asq_last_status);
@ -1105,17 +1106,36 @@ static int i40e_set_coalesce(struct net_device *netdev,
if (ec->tx_max_coalesced_frames_irq || ec->rx_max_coalesced_frames_irq)
vsi->work_limit = ec->tx_max_coalesced_frames_irq;
vector = vsi->base_vector;
if ((ec->rx_coalesce_usecs >= (I40E_MIN_ITR << 1)) &&
(ec->rx_coalesce_usecs <= (I40E_MAX_ITR << 1)))
(ec->rx_coalesce_usecs <= (I40E_MAX_ITR << 1))) {
vsi->rx_itr_setting = ec->rx_coalesce_usecs;
else
} else if (ec->rx_coalesce_usecs == 0) {
vsi->rx_itr_setting = ec->rx_coalesce_usecs;
i40e_irq_dynamic_disable(vsi, vector);
if (ec->use_adaptive_rx_coalesce)
netif_info(pf, drv, netdev,
"Rx-secs=0, need to disable adaptive-Rx for a complete disable\n");
} else {
netif_info(pf, drv, netdev,
"Invalid value, Rx-usecs range is 0, 8-8160\n");
return -EINVAL;
}
if ((ec->tx_coalesce_usecs >= (I40E_MIN_ITR << 1)) &&
(ec->tx_coalesce_usecs <= (I40E_MAX_ITR << 1)))
(ec->tx_coalesce_usecs <= (I40E_MAX_ITR << 1))) {
vsi->tx_itr_setting = ec->tx_coalesce_usecs;
else
} else if (ec->tx_coalesce_usecs == 0) {
vsi->tx_itr_setting = ec->tx_coalesce_usecs;
i40e_irq_dynamic_disable(vsi, vector);
if (ec->use_adaptive_tx_coalesce)
netif_info(pf, drv, netdev,
"Tx-secs=0, need to disable adaptive-Tx for a complete disable\n");
} else {
netif_info(pf, drv, netdev,
"Invalid value, Tx-usecs range is 0, 8-8160\n");
return -EINVAL;
}
if (ec->use_adaptive_rx_coalesce)
vsi->rx_itr_setting |= I40E_ITR_DYNAMIC;
@ -1127,7 +1147,6 @@ static int i40e_set_coalesce(struct net_device *netdev,
else
vsi->tx_itr_setting &= ~I40E_ITR_DYNAMIC;
vector = vsi->base_vector;
for (i = 0; i < vsi->num_q_vectors; i++, vector++) {
q_vector = vsi->q_vectors[i];
q_vector->rx.itr = ITR_TO_REG(vsi->rx_itr_setting);

View File

@ -39,7 +39,7 @@ static const char i40e_driver_string[] =
#define DRV_VERSION_MAJOR 0
#define DRV_VERSION_MINOR 4
#define DRV_VERSION_BUILD 13
#define DRV_VERSION_BUILD 17
#define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \
__stringify(DRV_VERSION_MINOR) "." \
__stringify(DRV_VERSION_BUILD) DRV_KERN
@ -278,7 +278,7 @@ static void i40e_tx_timeout(struct net_device *netdev)
pf->tx_timeout_count++;
if (time_after(jiffies, (pf->tx_timeout_last_recovery + HZ*20)))
pf->tx_timeout_recovery_level = 0;
pf->tx_timeout_recovery_level = 1;
pf->tx_timeout_last_recovery = jiffies;
netdev_info(netdev, "tx_timeout recovery level %d\n",
pf->tx_timeout_recovery_level);
@ -1327,9 +1327,6 @@ static int i40e_set_mac(struct net_device *netdev, void *p)
netdev_info(netdev, "set mac address=%pM\n", addr->sa_data);
if (ether_addr_equal(netdev->dev_addr, addr->sa_data))
return 0;
if (test_bit(__I40E_DOWN, &vsi->back->state) ||
test_bit(__I40E_RESET_RECOVERY_PENDING, &vsi->back->state))
return -EADDRNOTAVAIL;
@ -1337,7 +1334,7 @@ static int i40e_set_mac(struct net_device *netdev, void *p)
if (vsi->type == I40E_VSI_MAIN) {
i40e_status ret;
ret = i40e_aq_mac_address_write(&vsi->back->hw,
I40E_AQC_WRITE_TYPE_LAA_ONLY,
I40E_AQC_WRITE_TYPE_LAA_WOL,
addr->sa_data, NULL);
if (ret) {
netdev_info(netdev,
@ -1345,22 +1342,27 @@ static int i40e_set_mac(struct net_device *netdev, void *p)
ret);
return -EADDRNOTAVAIL;
}
ether_addr_copy(vsi->back->hw.mac.addr, addr->sa_data);
}
/* In order to be sure to not drop any packets, add the new address
* then delete the old one.
*/
f = i40e_add_filter(vsi, addr->sa_data, I40E_VLAN_ANY, false, false);
if (!f)
return -ENOMEM;
f = i40e_find_mac(vsi, addr->sa_data, false, true);
if (!f) {
/* In order to be sure to not drop any packets, add the
* new address first then delete the old one.
*/
f = i40e_add_filter(vsi, addr->sa_data, I40E_VLAN_ANY,
false, false);
if (!f)
return -ENOMEM;
i40e_sync_vsi_filters(vsi);
i40e_del_filter(vsi, netdev->dev_addr, I40E_VLAN_ANY, false, false);
i40e_sync_vsi_filters(vsi);
i40e_sync_vsi_filters(vsi);
i40e_del_filter(vsi, netdev->dev_addr, I40E_VLAN_ANY,
false, false);
i40e_sync_vsi_filters(vsi);
}
ether_addr_copy(netdev->dev_addr, addr->sa_data);
f->is_laa = true;
if (!ether_addr_equal(netdev->dev_addr, addr->sa_data))
ether_addr_copy(netdev->dev_addr, addr->sa_data);
return 0;
}
@ -2767,6 +2769,22 @@ void i40e_irq_dynamic_enable(struct i40e_vsi *vsi, int vector)
/* skip the flush */
}
/**
* i40e_irq_dynamic_disable - Disable default interrupt generation settings
* @vsi: pointer to a vsi
* @vector: enable a particular Hw Interrupt vector
**/
void i40e_irq_dynamic_disable(struct i40e_vsi *vsi, int vector)
{
struct i40e_pf *pf = vsi->back;
struct i40e_hw *hw = &pf->hw;
u32 val;
val = I40E_ITR_NONE << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT;
wr32(hw, I40E_PFINT_DYN_CTLN(vector - 1), val);
i40e_flush(hw);
}
/**
* i40e_msix_clean_rings - MSIX mode Interrupt Handler
* @irq: interrupt number
@ -5611,7 +5629,7 @@ static void i40e_fdir_teardown(struct i40e_pf *pf)
*
* Close up the VFs and other things in prep for pf Reset.
**/
static int i40e_prep_for_reset(struct i40e_pf *pf)
static void i40e_prep_for_reset(struct i40e_pf *pf)
{
struct i40e_hw *hw = &pf->hw;
i40e_status ret = 0;
@ -5619,7 +5637,7 @@ static int i40e_prep_for_reset(struct i40e_pf *pf)
clear_bit(__I40E_RESET_INTR_RECEIVED, &pf->state);
if (test_and_set_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state))
return 0;
return;
dev_dbg(&pf->pdev->dev, "Tearing down internal switch for reset\n");
@ -5636,13 +5654,10 @@ static int i40e_prep_for_reset(struct i40e_pf *pf)
/* call shutdown HMC */
if (hw->hmc.hmc_obj) {
ret = i40e_shutdown_lan_hmc(hw);
if (ret) {
if (ret)
dev_warn(&pf->pdev->dev,
"shutdown_lan_hmc failed: %d\n", ret);
clear_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state);
}
}
return ret;
}
/**
@ -5778,7 +5793,7 @@ static void i40e_reset_and_rebuild(struct i40e_pf *pf, bool reinit)
}
if (pf->vsi[pf->lan_vsi]->uplink_seid == pf->mac_seid) {
dev_info(&pf->pdev->dev, "attempting to rebuild PF VSI\n");
dev_dbg(&pf->pdev->dev, "attempting to rebuild PF VSI\n");
/* no VEB, so rebuild only the Main VSI */
ret = i40e_add_vsi(pf->vsi[pf->lan_vsi]);
if (ret) {
@ -5816,11 +5831,8 @@ end_core_reset:
**/
static void i40e_handle_reset_warning(struct i40e_pf *pf)
{
i40e_status ret;
ret = i40e_prep_for_reset(pf);
if (!ret)
i40e_reset_and_rebuild(pf, false);
i40e_prep_for_reset(pf);
i40e_reset_and_rebuild(pf, false);
}
/**
@ -5833,6 +5845,7 @@ static void i40e_handle_mdd_event(struct i40e_pf *pf)
{
struct i40e_hw *hw = &pf->hw;
bool mdd_detected = false;
bool pf_mdd_detected = false;
struct i40e_vf *vf;
u32 reg;
int i;
@ -5872,6 +5885,30 @@ static void i40e_handle_mdd_event(struct i40e_pf *pf)
mdd_detected = true;
}
if (mdd_detected) {
reg = rd32(hw, I40E_PF_MDET_TX);
if (reg & I40E_PF_MDET_TX_VALID_MASK) {
wr32(hw, I40E_PF_MDET_TX, 0xFFFF);
dev_info(&pf->pdev->dev,
"MDD TX event is for this function 0x%08x, requesting PF reset.\n",
reg);
pf_mdd_detected = true;
}
reg = rd32(hw, I40E_PF_MDET_RX);
if (reg & I40E_PF_MDET_RX_VALID_MASK) {
wr32(hw, I40E_PF_MDET_RX, 0xFFFF);
dev_info(&pf->pdev->dev,
"MDD RX event is for this function 0x%08x, requesting PF reset.\n",
reg);
pf_mdd_detected = true;
}
/* Queue belongs to the PF, initiate a reset */
if (pf_mdd_detected) {
set_bit(__I40E_PF_RESET_REQUESTED, &pf->state);
i40e_service_event_schedule(pf);
}
}
/* see if one of the VFs needs its hand slapped */
for (i = 0; i < pf->num_alloc_vfs && mdd_detected; i++) {
vf = &(pf->vf[i]);
@ -6789,6 +6826,8 @@ static int i40e_sw_init(struct i40e_pf *pf)
pf->irq_pile->num_entries = pf->hw.func_caps.num_msix_vectors;
pf->irq_pile->search_hint = 0;
pf->tx_timeout_recovery_level = 1;
mutex_init(&pf->switch_mutex);
sw_init_done:
@ -7342,6 +7381,12 @@ static int i40e_add_vsi(struct i40e_vsi *vsi)
list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) {
f->changed = true;
f_count++;
if (f->is_laa && vsi->type == I40E_VSI_MAIN) {
i40e_aq_mac_address_write(&vsi->back->hw,
I40E_AQC_WRITE_TYPE_LAA_WOL,
f->macaddr, NULL);
}
}
if (f_count) {
vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED;
@ -8614,6 +8659,20 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_pf_reset;
}
if (hw->aq.api_min_ver > I40E_FW_API_VERSION_MINOR)
dev_info(&pdev->dev,
"Note: FW API version %02x.%02x newer than expected %02x.%02x, recommend driver update.\n",
hw->aq.api_maj_ver, hw->aq.api_min_ver,
I40E_FW_API_VERSION_MAJOR, I40E_FW_API_VERSION_MINOR);
if (hw->aq.api_maj_ver < I40E_FW_API_VERSION_MAJOR ||
hw->aq.api_min_ver < (I40E_FW_API_VERSION_MINOR-1))
dev_info(&pdev->dev,
"Note: FW API version %02x.%02x older than expected %02x.%02x, recommend nvm update.\n",
hw->aq.api_maj_ver, hw->aq.api_min_ver,
I40E_FW_API_VERSION_MAJOR, I40E_FW_API_VERSION_MINOR);
i40e_verify_eeprom(pf);
/* Rev 0 hardware was never productized */
@ -8841,7 +8900,6 @@ static void i40e_remove(struct pci_dev *pdev)
{
struct i40e_pf *pf = pci_get_drvdata(pdev);
i40e_status ret_code;
u32 reg;
int i;
i40e_dbg_pf_exit(pf);
@ -8919,11 +8977,6 @@ static void i40e_remove(struct pci_dev *pdev)
kfree(pf->irq_pile);
kfree(pf->vsi);
/* force a PF reset to clean anything leftover */
reg = rd32(&pf->hw, I40E_PFGEN_CTRL);
wr32(&pf->hw, I40E_PFGEN_CTRL, (reg | I40E_PFGEN_CTRL_PFSWR_MASK));
i40e_flush(&pf->hw);
iounmap(pf->hw.hw_addr);
kfree(pf);
pci_release_selected_regions(pdev,

View File

@ -77,7 +77,8 @@ i40e_status i40e_aq_set_default_vsi(struct i40e_hw *hw, u16 vsi_id,
i40e_status i40e_aq_clear_pxe_mode(struct i40e_hw *hw,
struct i40e_asq_cmd_details *cmd_details);
i40e_status i40e_aq_set_link_restart_an(struct i40e_hw *hw,
struct i40e_asq_cmd_details *cmd_details);
bool enable_link,
struct i40e_asq_cmd_details *cmd_details);
i40e_status i40e_aq_get_link_info(struct i40e_hw *hw,
bool enable_lse, struct i40e_link_status *link,
struct i40e_asq_cmd_details *cmd_details);

View File

@ -75,7 +75,6 @@ enum i40e_dyn_idx_t {
((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_OTHER) | \
((u64)1 << I40E_FILTER_PCTYPE_FRAG_IPV4) | \
((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_UDP) | \
((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN) | \
((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_TCP) | \
((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_SCTP) | \
((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_OTHER) | \

View File

@ -878,7 +878,6 @@ enum i40e_filter_pctype {
I40E_FILTER_PCTYPE_FRAG_IPV4 = 36,
/* Note: Values 37-40 are reserved for future use */
I40E_FILTER_PCTYPE_NONF_IPV6_UDP = 41,
I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN = 42,
I40E_FILTER_PCTYPE_NONF_IPV6_TCP = 43,
I40E_FILTER_PCTYPE_NONF_IPV6_SCTP = 44,
I40E_FILTER_PCTYPE_NONF_IPV6_OTHER = 45,

View File

@ -2077,6 +2077,8 @@ int i40e_ndo_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
}
ether_addr_copy(vf->default_lan_addr.addr, mac);
vf->pf_set_mac = true;
/* Force the VF driver stop so it has to reload with new MAC address */
i40e_vc_disable_vf(pf, vf);
dev_info(&pf->pdev->dev, "Reload the VF driver to make this change effective.\n");
ret = 0;

View File

@ -75,7 +75,6 @@ enum i40e_dyn_idx_t {
((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_OTHER) | \
((u64)1 << I40E_FILTER_PCTYPE_FRAG_IPV4) | \
((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_UDP) | \
((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN) | \
((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_TCP) | \
((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_SCTP) | \
((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_OTHER) | \

View File

@ -878,7 +878,6 @@ enum i40e_filter_pctype {
I40E_FILTER_PCTYPE_FRAG_IPV4 = 36,
/* Note: Values 37-40 are reserved for future use */
I40E_FILTER_PCTYPE_NONF_IPV6_UDP = 41,
I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN = 42,
I40E_FILTER_PCTYPE_NONF_IPV6_TCP = 43,
I40E_FILTER_PCTYPE_NONF_IPV6_SCTP = 44,
I40E_FILTER_PCTYPE_NONF_IPV6_OTHER = 45,

View File

@ -36,7 +36,7 @@ char i40evf_driver_name[] = "i40evf";
static const char i40evf_driver_string[] =
"Intel(R) XL710 X710 Virtual Function Network Driver";
#define DRV_VERSION "0.9.35"
#define DRV_VERSION "0.9.36"
const char i40evf_driver_version[] = DRV_VERSION;
static const char i40evf_copyright[] =
"Copyright (c) 2013 - 2014 Intel Corporation.";