Commit 5c5e0ad3 authored by David S. Miller's avatar David S. Miller

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

Jeff Kirsher says:

====================
Intel Wired LAN Driver Updates 2015-04-03

This series contains updates to i40e and i40evf only.

Anjali provides a fix for verifying outer UDP receive checksum.  Also
adds helpful information to display when figuring out the cause of
HMC errors.

Mitch provides a fix to prevent a malicious or buggy VF driver from
sending an invalid index into the VSI array which could panic the host.
Cleans up the code where a function was moved, but the message did
not follow.  Adds protection to the VLAN filter list, same as the
MAC filter list, to protect from corruption if the watchdog happens
to run at the same time as a VLAN filter is being added/deleted.

Jesse changes several memcpy() statements to struct assignments which
are type safe and preferable.  Fixed a bug when skb allocation fails,
where we should not continue using the skb pointer.  Also fixed a void
function in FCoE which should not be returning anything.

Greg fixes both i40e and i40evf to set the Ethernet protocol correctly
when transmit VLAN offloads are disabled.

Shannon fixes up VLAN messages when ports are added or removed, which
were giving bogus index info.  Also aligned the message text style
with other messages in the driver.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents e79d8429 42d255ce
...@@ -628,6 +628,7 @@ extern const char i40e_driver_name[]; ...@@ -628,6 +628,7 @@ extern const char i40e_driver_name[];
extern const char i40e_driver_version_str[]; extern const char i40e_driver_version_str[];
void i40e_do_reset_safe(struct i40e_pf *pf, u32 reset_flags); void i40e_do_reset_safe(struct i40e_pf *pf, u32 reset_flags);
void i40e_do_reset(struct i40e_pf *pf, u32 reset_flags); void i40e_do_reset(struct i40e_pf *pf, u32 reset_flags);
struct i40e_vsi *i40e_find_vsi_from_id(struct i40e_pf *pf, u16 id);
void i40e_update_stats(struct i40e_vsi *vsi); void i40e_update_stats(struct i40e_vsi *vsi);
void i40e_update_eth_stats(struct i40e_vsi *vsi); void i40e_update_eth_stats(struct i40e_vsi *vsi);
struct rtnl_link_stats64 *i40e_get_vsi_stats_struct(struct i40e_vsi *vsi); struct rtnl_link_stats64 *i40e_get_vsi_stats_struct(struct i40e_vsi *vsi);
......
...@@ -178,6 +178,10 @@ void i40e_dcbnl_set_all(struct i40e_vsi *vsi) ...@@ -178,6 +178,10 @@ void i40e_dcbnl_set_all(struct i40e_vsi *vsi)
if (!(pf->flags & I40E_FLAG_DCB_ENABLED)) if (!(pf->flags & I40E_FLAG_DCB_ENABLED))
return; return;
/* MFP mode but not an iSCSI PF so return */
if ((pf->flags & I40E_FLAG_MFP_ENABLED) && !(pf->hw.func_caps.iscsi))
return;
dcbxcfg = &hw->local_dcbx_config; dcbxcfg = &hw->local_dcbx_config;
/* Set up all the App TLVs if DCBx is negotiated */ /* Set up all the App TLVs if DCBx is negotiated */
...@@ -282,6 +286,10 @@ void i40e_dcbnl_flush_apps(struct i40e_pf *pf, ...@@ -282,6 +286,10 @@ void i40e_dcbnl_flush_apps(struct i40e_pf *pf,
struct i40e_dcb_app_priority_table app; struct i40e_dcb_app_priority_table app;
int i; int i;
/* MFP mode but not an iSCSI PF so return */
if ((pf->flags & I40E_FLAG_MFP_ENABLED) && !(pf->hw.func_caps.iscsi))
return;
for (i = 0; i < old_cfg->numapps; i++) { for (i = 0; i < old_cfg->numapps; i++) {
app = old_cfg->app[i]; app = old_cfg->app[i];
/* The APP is not available anymore delete it */ /* The APP is not available anymore delete it */
......
...@@ -1306,8 +1306,7 @@ static void i40e_fcoe_tx_map(struct i40e_ring *tx_ring, ...@@ -1306,8 +1306,7 @@ static void i40e_fcoe_tx_map(struct i40e_ring *tx_ring,
/* MACLEN is ether header length in words not bytes */ /* MACLEN is ether header length in words not bytes */
td_offset |= (maclen >> 1) << I40E_TX_DESC_LENGTH_MACLEN_SHIFT; td_offset |= (maclen >> 1) << I40E_TX_DESC_LENGTH_MACLEN_SHIFT;
return i40e_tx_map(tx_ring, skb, first, tx_flags, hdr_len, i40e_tx_map(tx_ring, skb, first, tx_flags, hdr_len, td_cmd, td_offset);
td_cmd, td_offset);
} }
/** /**
......
...@@ -38,8 +38,8 @@ static const char i40e_driver_string[] = ...@@ -38,8 +38,8 @@ static const char i40e_driver_string[] =
#define DRV_KERN "-k" #define DRV_KERN "-k"
#define DRV_VERSION_MAJOR 1 #define DRV_VERSION_MAJOR 1
#define DRV_VERSION_MINOR 2 #define DRV_VERSION_MINOR 3
#define DRV_VERSION_BUILD 43 #define DRV_VERSION_BUILD 1
#define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \ #define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \
__stringify(DRV_VERSION_MINOR) "." \ __stringify(DRV_VERSION_MINOR) "." \
__stringify(DRV_VERSION_BUILD) DRV_KERN __stringify(DRV_VERSION_BUILD) DRV_KERN
...@@ -249,6 +249,22 @@ static int i40e_put_lump(struct i40e_lump_tracking *pile, u16 index, u16 id) ...@@ -249,6 +249,22 @@ static int i40e_put_lump(struct i40e_lump_tracking *pile, u16 index, u16 id)
return count; return count;
} }
/**
* i40e_find_vsi_from_id - searches for the vsi with the given id
* @pf - the pf structure to search for the vsi
* @id - id of the vsi it is searching for
**/
struct i40e_vsi *i40e_find_vsi_from_id(struct i40e_pf *pf, u16 id)
{
int i;
for (i = 0; i < pf->num_alloc_vsi; i++)
if (pf->vsi[i] && (pf->vsi[i]->id == id))
return pf->vsi[i];
return NULL;
}
/** /**
* i40e_service_event_schedule - Schedule the service task to wake up * i40e_service_event_schedule - Schedule the service task to wake up
* @pf: board private structure * @pf: board private structure
...@@ -1969,7 +1985,7 @@ void i40e_vlan_stripping_enable(struct i40e_vsi *vsi) ...@@ -1969,7 +1985,7 @@ void i40e_vlan_stripping_enable(struct i40e_vsi *vsi)
I40E_AQ_VSI_PVLAN_EMOD_STR_BOTH; I40E_AQ_VSI_PVLAN_EMOD_STR_BOTH;
ctxt.seid = vsi->seid; ctxt.seid = vsi->seid;
memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info)); ctxt.info = vsi->info;
ret = i40e_aq_update_vsi_params(&vsi->back->hw, &ctxt, NULL); ret = i40e_aq_update_vsi_params(&vsi->back->hw, &ctxt, NULL);
if (ret) { if (ret) {
dev_info(&vsi->back->pdev->dev, dev_info(&vsi->back->pdev->dev,
...@@ -1998,7 +2014,7 @@ void i40e_vlan_stripping_disable(struct i40e_vsi *vsi) ...@@ -1998,7 +2014,7 @@ void i40e_vlan_stripping_disable(struct i40e_vsi *vsi)
I40E_AQ_VSI_PVLAN_EMOD_NOTHING; I40E_AQ_VSI_PVLAN_EMOD_NOTHING;
ctxt.seid = vsi->seid; ctxt.seid = vsi->seid;
memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info)); ctxt.info = vsi->info;
ret = i40e_aq_update_vsi_params(&vsi->back->hw, &ctxt, NULL); ret = i40e_aq_update_vsi_params(&vsi->back->hw, &ctxt, NULL);
if (ret) { if (ret) {
dev_info(&vsi->back->pdev->dev, dev_info(&vsi->back->pdev->dev,
...@@ -2282,7 +2298,7 @@ int i40e_vsi_add_pvid(struct i40e_vsi *vsi, u16 vid) ...@@ -2282,7 +2298,7 @@ int i40e_vsi_add_pvid(struct i40e_vsi *vsi, u16 vid)
I40E_AQ_VSI_PVLAN_EMOD_STR; I40E_AQ_VSI_PVLAN_EMOD_STR;
ctxt.seid = vsi->seid; ctxt.seid = vsi->seid;
memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info)); ctxt.info = vsi->info;
aq_ret = i40e_aq_update_vsi_params(&vsi->back->hw, &ctxt, NULL); aq_ret = i40e_aq_update_vsi_params(&vsi->back->hw, &ctxt, NULL);
if (aq_ret) { if (aq_ret) {
dev_info(&vsi->back->pdev->dev, dev_info(&vsi->back->pdev->dev,
...@@ -3197,6 +3213,9 @@ static irqreturn_t i40e_intr(int irq, void *data) ...@@ -3197,6 +3213,9 @@ static irqreturn_t i40e_intr(int irq, void *data)
if (icr0 & I40E_PFINT_ICR0_HMC_ERR_MASK) { if (icr0 & I40E_PFINT_ICR0_HMC_ERR_MASK) {
icr0 &= ~I40E_PFINT_ICR0_HMC_ERR_MASK; icr0 &= ~I40E_PFINT_ICR0_HMC_ERR_MASK;
dev_info(&pf->pdev->dev, "HMC error interrupt\n"); dev_info(&pf->pdev->dev, "HMC error interrupt\n");
dev_info(&pf->pdev->dev, "HMC error info 0x%x, HMC error data 0x%x\n",
rd32(hw, I40E_PFHMC_ERRORINFO),
rd32(hw, I40E_PFHMC_ERRORDATA));
} }
if (icr0 & I40E_PFINT_ICR0_TIMESYNC_MASK) { if (icr0 & I40E_PFINT_ICR0_TIMESYNC_MASK) {
...@@ -4392,7 +4411,7 @@ static int i40e_vsi_config_tc(struct i40e_vsi *vsi, u8 enabled_tc) ...@@ -4392,7 +4411,7 @@ static int i40e_vsi_config_tc(struct i40e_vsi *vsi, u8 enabled_tc)
ctxt.pf_num = vsi->back->hw.pf_id; ctxt.pf_num = vsi->back->hw.pf_id;
ctxt.vf_num = 0; ctxt.vf_num = 0;
ctxt.uplink_seid = vsi->uplink_seid; ctxt.uplink_seid = vsi->uplink_seid;
memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info)); ctxt.info = vsi->info;
i40e_vsi_setup_queue_map(vsi, &ctxt, enabled_tc, false); i40e_vsi_setup_queue_map(vsi, &ctxt, enabled_tc, false);
/* Update the VSI after updating the VSI queue-mapping information */ /* Update the VSI after updating the VSI queue-mapping information */
...@@ -5220,9 +5239,8 @@ static int i40e_handle_lldp_event(struct i40e_pf *pf, ...@@ -5220,9 +5239,8 @@ static int i40e_handle_lldp_event(struct i40e_pf *pf,
goto exit; goto exit;
} }
memset(&tmp_dcbx_cfg, 0, sizeof(tmp_dcbx_cfg));
/* Store the old configuration */ /* Store the old configuration */
memcpy(&tmp_dcbx_cfg, &hw->local_dcbx_config, sizeof(tmp_dcbx_cfg)); tmp_dcbx_cfg = hw->local_dcbx_config;
/* Reset the old DCBx configuration data */ /* Reset the old DCBx configuration data */
memset(&hw->local_dcbx_config, 0, sizeof(hw->local_dcbx_config)); memset(&hw->local_dcbx_config, 0, sizeof(hw->local_dcbx_config));
...@@ -5782,11 +5800,9 @@ static void i40e_handle_link_event(struct i40e_pf *pf, ...@@ -5782,11 +5800,9 @@ static void i40e_handle_link_event(struct i40e_pf *pf,
struct i40e_hw *hw = &pf->hw; struct i40e_hw *hw = &pf->hw;
struct i40e_aqc_get_link_status *status = struct i40e_aqc_get_link_status *status =
(struct i40e_aqc_get_link_status *)&e->desc.params.raw; (struct i40e_aqc_get_link_status *)&e->desc.params.raw;
struct i40e_link_status *hw_link_info = &hw->phy.link_info;
/* save off old link status information */ /* save off old link status information */
memcpy(&pf->hw.phy.link_info_old, hw_link_info, hw->phy.link_info_old = hw->phy.link_info;
sizeof(pf->hw.phy.link_info_old));
/* Do a new status request to re-enable LSE reporting /* Do a new status request to re-enable LSE reporting
* and load new status information into the hw struct * and load new status information into the hw struct
...@@ -6608,7 +6624,6 @@ static void i40e_sync_vxlan_filters_subtask(struct i40e_pf *pf) ...@@ -6608,7 +6624,6 @@ static void i40e_sync_vxlan_filters_subtask(struct i40e_pf *pf)
{ {
struct i40e_hw *hw = &pf->hw; struct i40e_hw *hw = &pf->hw;
i40e_status ret; i40e_status ret;
u8 filter_index;
__be16 port; __be16 port;
int i; int i;
...@@ -6621,22 +6636,20 @@ static void i40e_sync_vxlan_filters_subtask(struct i40e_pf *pf) ...@@ -6621,22 +6636,20 @@ static void i40e_sync_vxlan_filters_subtask(struct i40e_pf *pf)
if (pf->pending_vxlan_bitmap & (1 << i)) { if (pf->pending_vxlan_bitmap & (1 << i)) {
pf->pending_vxlan_bitmap &= ~(1 << i); pf->pending_vxlan_bitmap &= ~(1 << i);
port = pf->vxlan_ports[i]; port = pf->vxlan_ports[i];
ret = port ? if (port)
i40e_aq_add_udp_tunnel(hw, ntohs(port), ret = i40e_aq_add_udp_tunnel(hw, ntohs(port),
I40E_AQC_TUNNEL_TYPE_VXLAN, I40E_AQC_TUNNEL_TYPE_VXLAN,
&filter_index, NULL) NULL, NULL);
: i40e_aq_del_udp_tunnel(hw, i, NULL); else
ret = i40e_aq_del_udp_tunnel(hw, i, NULL);
if (ret) { if (ret) {
dev_info(&pf->pdev->dev, "Failed to execute AQ command for %s port %d with index %d\n", dev_info(&pf->pdev->dev,
port ? "adding" : "deleting", "%s vxlan port %d, index %d failed, err %d, aq_err %d\n",
ntohs(port), port ? i : i); port ? "add" : "delete",
ntohs(port), i, ret,
pf->hw.aq.asq_last_status);
pf->vxlan_ports[i] = 0; pf->vxlan_ports[i] = 0;
} else {
dev_info(&pf->pdev->dev, "%s port %d with AQ command with index %d\n",
port ? "Added" : "Deleted",
ntohs(port), port ? i : filter_index);
} }
} }
} }
...@@ -7829,7 +7842,8 @@ static void i40e_add_vxlan_port(struct net_device *netdev, ...@@ -7829,7 +7842,8 @@ static void i40e_add_vxlan_port(struct net_device *netdev,
/* Check if port already exists */ /* Check if port already exists */
if (idx < I40E_MAX_PF_UDP_OFFLOAD_PORTS) { if (idx < I40E_MAX_PF_UDP_OFFLOAD_PORTS) {
netdev_info(netdev, "Port %d already offloaded\n", ntohs(port)); netdev_info(netdev, "vxlan port %d already offloaded\n",
ntohs(port));
return; return;
} }
...@@ -7837,7 +7851,7 @@ static void i40e_add_vxlan_port(struct net_device *netdev, ...@@ -7837,7 +7851,7 @@ static void i40e_add_vxlan_port(struct net_device *netdev,
next_idx = i40e_get_vxlan_port_idx(pf, 0); next_idx = i40e_get_vxlan_port_idx(pf, 0);
if (next_idx == I40E_MAX_PF_UDP_OFFLOAD_PORTS) { if (next_idx == I40E_MAX_PF_UDP_OFFLOAD_PORTS) {
netdev_info(netdev, "Maximum number of UDP ports reached, not adding port %d\n", netdev_info(netdev, "maximum number of vxlan UDP ports reached, not adding port %d\n",
ntohs(port)); ntohs(port));
return; return;
} }
...@@ -7845,8 +7859,9 @@ static void i40e_add_vxlan_port(struct net_device *netdev, ...@@ -7845,8 +7859,9 @@ static void i40e_add_vxlan_port(struct net_device *netdev,
/* New port: add it and mark its index in the bitmap */ /* New port: add it and mark its index in the bitmap */
pf->vxlan_ports[next_idx] = port; pf->vxlan_ports[next_idx] = port;
pf->pending_vxlan_bitmap |= (1 << next_idx); pf->pending_vxlan_bitmap |= (1 << next_idx);
pf->flags |= I40E_FLAG_VXLAN_FILTER_SYNC; pf->flags |= I40E_FLAG_VXLAN_FILTER_SYNC;
dev_info(&pf->pdev->dev, "adding vxlan port %d\n", ntohs(port));
} }
/** /**
...@@ -7874,12 +7889,13 @@ static void i40e_del_vxlan_port(struct net_device *netdev, ...@@ -7874,12 +7889,13 @@ static void i40e_del_vxlan_port(struct net_device *netdev,
* and make it pending * and make it pending
*/ */
pf->vxlan_ports[idx] = 0; pf->vxlan_ports[idx] = 0;
pf->pending_vxlan_bitmap |= (1 << idx); pf->pending_vxlan_bitmap |= (1 << idx);
pf->flags |= I40E_FLAG_VXLAN_FILTER_SYNC; pf->flags |= I40E_FLAG_VXLAN_FILTER_SYNC;
dev_info(&pf->pdev->dev, "deleting vxlan port %d\n",
ntohs(port));
} else { } else {
netdev_warn(netdev, "Port %d was not found, not deleting\n", netdev_warn(netdev, "vxlan port %d was not found, not deleting\n",
ntohs(port)); ntohs(port));
} }
} }
...@@ -8269,7 +8285,7 @@ static int i40e_add_vsi(struct i40e_vsi *vsi) ...@@ -8269,7 +8285,7 @@ static int i40e_add_vsi(struct i40e_vsi *vsi)
ret, pf->hw.aq.asq_last_status); ret, pf->hw.aq.asq_last_status);
return -ENOENT; return -ENOENT;
} }
memcpy(&vsi->info, &ctxt.info, sizeof(ctxt.info)); vsi->info = ctxt.info;
vsi->info.valid_sections = 0; vsi->info.valid_sections = 0;
vsi->seid = ctxt.seid; vsi->seid = ctxt.seid;
...@@ -8403,7 +8419,7 @@ static int i40e_add_vsi(struct i40e_vsi *vsi) ...@@ -8403,7 +8419,7 @@ static int i40e_add_vsi(struct i40e_vsi *vsi)
ret = -ENOENT; ret = -ENOENT;
goto err; goto err;
} }
memcpy(&vsi->info, &ctxt.info, sizeof(ctxt.info)); vsi->info = ctxt.info;
vsi->info.valid_sections = 0; vsi->info.valid_sections = 0;
vsi->seid = ctxt.seid; vsi->seid = ctxt.seid;
vsi->id = ctxt.vsi_number; vsi->id = ctxt.vsi_number;
...@@ -10210,6 +10226,8 @@ static int i40e_suspend(struct pci_dev *pdev, pm_message_t state) ...@@ -10210,6 +10226,8 @@ static int i40e_suspend(struct pci_dev *pdev, pm_message_t state)
set_bit(__I40E_DOWN, &pf->state); set_bit(__I40E_DOWN, &pf->state);
del_timer_sync(&pf->service_timer); del_timer_sync(&pf->service_timer);
cancel_work_sync(&pf->service_task); cancel_work_sync(&pf->service_task);
i40e_fdir_teardown(pf);
rtnl_lock(); rtnl_lock();
i40e_prep_for_reset(pf); i40e_prep_for_reset(pf);
rtnl_unlock(); rtnl_unlock();
......
...@@ -1565,8 +1565,11 @@ static int i40e_clean_rx_irq_ps(struct i40e_ring *rx_ring, int budget) ...@@ -1565,8 +1565,11 @@ static int i40e_clean_rx_irq_ps(struct i40e_ring *rx_ring, int budget)
if (likely(!skb)) { if (likely(!skb)) {
skb = netdev_alloc_skb_ip_align(rx_ring->netdev, skb = netdev_alloc_skb_ip_align(rx_ring->netdev,
rx_ring->rx_hdr_len); rx_ring->rx_hdr_len);
if (!skb) if (!skb) {
rx_ring->rx_stats.alloc_buff_failed++; rx_ring->rx_stats.alloc_buff_failed++;
break;
}
/* initialize queue mapping */ /* initialize queue mapping */
skb_record_rx_queue(skb, rx_ring->queue_index); skb_record_rx_queue(skb, rx_ring->queue_index);
/* we are reusing so sync this buffer for CPU use */ /* we are reusing so sync this buffer for CPU use */
...@@ -2054,6 +2057,19 @@ static int i40e_tx_prepare_vlan_flags(struct sk_buff *skb, ...@@ -2054,6 +2057,19 @@ static int i40e_tx_prepare_vlan_flags(struct sk_buff *skb,
__be16 protocol = skb->protocol; __be16 protocol = skb->protocol;
u32 tx_flags = 0; u32 tx_flags = 0;
if (protocol == htons(ETH_P_8021Q) &&
!(tx_ring->netdev->features & NETIF_F_HW_VLAN_CTAG_TX)) {
/* When HW VLAN acceleration is turned off by the user the
* stack sets the protocol to 8021q so that the driver
* can take any steps required to support the SW only
* VLAN handling. In our case the driver doesn't need
* to take any further steps so just set the protocol
* to the encapsulated ethertype.
*/
skb->protocol = vlan_get_protocol(skb);
goto out;
}
/* if we have a HW VLAN tag being added, default to the HW one */ /* if we have a HW VLAN tag being added, default to the HW one */
if (skb_vlan_tag_present(skb)) { if (skb_vlan_tag_present(skb)) {
tx_flags |= skb_vlan_tag_get(skb) << I40E_TX_FLAGS_VLAN_SHIFT; tx_flags |= skb_vlan_tag_get(skb) << I40E_TX_FLAGS_VLAN_SHIFT;
......
...@@ -88,7 +88,7 @@ struct i40e_vf { ...@@ -88,7 +88,7 @@ struct i40e_vf {
* When assigned, these will be non-zero, because VSI 0 is always * When assigned, these will be non-zero, because VSI 0 is always
* the main LAN VSI for the PF. * the main LAN VSI for the PF.
*/ */
u8 lan_vsi_index; /* index into PF struct */ u8 lan_vsi_idx; /* index into PF struct */
u8 lan_vsi_id; /* ID as used by firmware */ u8 lan_vsi_id; /* ID as used by firmware */
u8 num_queue_pairs; /* num of qps assigned to VF vsis */ u8 num_queue_pairs; /* num of qps assigned to VF vsis */
......
...@@ -915,9 +915,7 @@ static inline void i40e_rx_checksum(struct i40e_vsi *vsi, ...@@ -915,9 +915,7 @@ static inline void i40e_rx_checksum(struct i40e_vsi *vsi,
* so the total length of IPv4 header is IHL*4 bytes * so the total length of IPv4 header is IHL*4 bytes
* The UDP_0 bit *may* bet set if the *inner* header is UDP * The UDP_0 bit *may* bet set if the *inner* header is UDP
*/ */
if (ipv4_tunnel && if (ipv4_tunnel) {
(decoded.inner_prot != I40E_RX_PTYPE_INNER_PROT_UDP) &&
!(rx_status & (1 << I40E_RX_DESC_STATUS_UDP_0_SHIFT))) {
skb->transport_header = skb->mac_header + skb->transport_header = skb->mac_header +
sizeof(struct ethhdr) + sizeof(struct ethhdr) +
(ip_hdr(skb)->ihl * 4); (ip_hdr(skb)->ihl * 4);
...@@ -927,15 +925,19 @@ static inline void i40e_rx_checksum(struct i40e_vsi *vsi, ...@@ -927,15 +925,19 @@ static inline void i40e_rx_checksum(struct i40e_vsi *vsi,
skb->protocol == htons(ETH_P_8021AD)) skb->protocol == htons(ETH_P_8021AD))
? VLAN_HLEN : 0; ? VLAN_HLEN : 0;
rx_udp_csum = udp_csum(skb); if ((ip_hdr(skb)->protocol == IPPROTO_UDP) &&
iph = ip_hdr(skb); (udp_hdr(skb)->check != 0)) {
csum = csum_tcpudp_magic( rx_udp_csum = udp_csum(skb);
iph->saddr, iph->daddr, iph = ip_hdr(skb);
(skb->len - skb_transport_offset(skb)), csum = csum_tcpudp_magic(iph->saddr, iph->daddr,
IPPROTO_UDP, rx_udp_csum); (skb->len -
skb_transport_offset(skb)),
IPPROTO_UDP, rx_udp_csum);
if (udp_hdr(skb)->check != csum) if (udp_hdr(skb)->check != csum)
goto checksum_fail; goto checksum_fail;
} /* else its GRE and so no outer UDP header */
} }
skb->ip_summed = CHECKSUM_UNNECESSARY; skb->ip_summed = CHECKSUM_UNNECESSARY;
...@@ -1038,8 +1040,11 @@ static int i40e_clean_rx_irq_ps(struct i40e_ring *rx_ring, int budget) ...@@ -1038,8 +1040,11 @@ static int i40e_clean_rx_irq_ps(struct i40e_ring *rx_ring, int budget)
if (likely(!skb)) { if (likely(!skb)) {
skb = netdev_alloc_skb_ip_align(rx_ring->netdev, skb = netdev_alloc_skb_ip_align(rx_ring->netdev,
rx_ring->rx_hdr_len); rx_ring->rx_hdr_len);
if (!skb) if (!skb) {
rx_ring->rx_stats.alloc_buff_failed++; rx_ring->rx_stats.alloc_buff_failed++;
break;
}
/* initialize queue mapping */ /* initialize queue mapping */
skb_record_rx_queue(skb, rx_ring->queue_index); skb_record_rx_queue(skb, rx_ring->queue_index);
/* we are reusing so sync this buffer for CPU use */ /* we are reusing so sync this buffer for CPU use */
...@@ -1365,6 +1370,19 @@ static int i40e_tx_prepare_vlan_flags(struct sk_buff *skb, ...@@ -1365,6 +1370,19 @@ static int i40e_tx_prepare_vlan_flags(struct sk_buff *skb,
__be16 protocol = skb->protocol; __be16 protocol = skb->protocol;
u32 tx_flags = 0; u32 tx_flags = 0;
if (protocol == htons(ETH_P_8021Q) &&
!(tx_ring->netdev->features & NETIF_F_HW_VLAN_CTAG_TX)) {
/* When HW VLAN acceleration is turned off by the user the
* stack sets the protocol to 8021q so that the driver
* can take any steps required to support the SW only
* VLAN handling. In our case the driver doesn't need
* to take any further steps so just set the protocol
* to the encapsulated ethertype.
*/
skb->protocol = vlan_get_protocol(skb);
goto out;
}
/* if we have a HW VLAN tag being added, default to the HW one */ /* if we have a HW VLAN tag being added, default to the HW one */
if (skb_vlan_tag_present(skb)) { if (skb_vlan_tag_present(skb)) {
tx_flags |= skb_vlan_tag_get(skb) << I40E_TX_FLAGS_VLAN_SHIFT; tx_flags |= skb_vlan_tag_get(skb) << I40E_TX_FLAGS_VLAN_SHIFT;
...@@ -1381,6 +1399,7 @@ static int i40e_tx_prepare_vlan_flags(struct sk_buff *skb, ...@@ -1381,6 +1399,7 @@ static int i40e_tx_prepare_vlan_flags(struct sk_buff *skb,
tx_flags |= I40E_TX_FLAGS_SW_VLAN; tx_flags |= I40E_TX_FLAGS_SW_VLAN;
} }
out:
*flags = tx_flags; *flags = tx_flags;
return 0; return 0;
} }
......
...@@ -664,13 +664,21 @@ i40evf_vlan_filter *i40evf_find_vlan(struct i40evf_adapter *adapter, u16 vlan) ...@@ -664,13 +664,21 @@ i40evf_vlan_filter *i40evf_find_vlan(struct i40evf_adapter *adapter, u16 vlan)
static struct static struct
i40evf_vlan_filter *i40evf_add_vlan(struct i40evf_adapter *adapter, u16 vlan) i40evf_vlan_filter *i40evf_add_vlan(struct i40evf_adapter *adapter, u16 vlan)
{ {
struct i40evf_vlan_filter *f; struct i40evf_vlan_filter *f = NULL;
int count = 50;
while (test_and_set_bit(__I40EVF_IN_CRITICAL_TASK,
&adapter->crit_section)) {
udelay(1);
if (--count == 0)
goto out;
}
f = i40evf_find_vlan(adapter, vlan); f = i40evf_find_vlan(adapter, vlan);
if (!f) { if (!f) {
f = kzalloc(sizeof(*f), GFP_ATOMIC); f = kzalloc(sizeof(*f), GFP_ATOMIC);
if (!f) if (!f)
return NULL; goto clearout;
f->vlan = vlan; f->vlan = vlan;
...@@ -680,6 +688,9 @@ i40evf_vlan_filter *i40evf_add_vlan(struct i40evf_adapter *adapter, u16 vlan) ...@@ -680,6 +688,9 @@ i40evf_vlan_filter *i40evf_add_vlan(struct i40evf_adapter *adapter, u16 vlan)
adapter->aq_required |= I40EVF_FLAG_AQ_ADD_VLAN_FILTER; adapter->aq_required |= I40EVF_FLAG_AQ_ADD_VLAN_FILTER;
} }
clearout:
clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section);
out:
return f; return f;
} }
...@@ -691,12 +702,21 @@ i40evf_vlan_filter *i40evf_add_vlan(struct i40evf_adapter *adapter, u16 vlan) ...@@ -691,12 +702,21 @@ i40evf_vlan_filter *i40evf_add_vlan(struct i40evf_adapter *adapter, u16 vlan)
static void i40evf_del_vlan(struct i40evf_adapter *adapter, u16 vlan) static void i40evf_del_vlan(struct i40evf_adapter *adapter, u16 vlan)
{ {
struct i40evf_vlan_filter *f; struct i40evf_vlan_filter *f;
int count = 50;
while (test_and_set_bit(__I40EVF_IN_CRITICAL_TASK,
&adapter->crit_section)) {
udelay(1);
if (--count == 0)
return;
}
f = i40evf_find_vlan(adapter, vlan); f = i40evf_find_vlan(adapter, vlan);
if (f) { if (f) {
f->remove = true; f->remove = true;
adapter->aq_required |= I40EVF_FLAG_AQ_DEL_VLAN_FILTER; adapter->aq_required |= I40EVF_FLAG_AQ_DEL_VLAN_FILTER;
} }
clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section);
} }
/** /**
...@@ -1415,41 +1435,22 @@ static void i40evf_watchdog_task(struct work_struct *work) ...@@ -1415,41 +1435,22 @@ static void i40evf_watchdog_task(struct work_struct *work)
} }
/** /**
* next_queue - increment to next available tx queue * i40evf_configure_rss - Prepare for RSS
* @adapter: board private structure
* @j: queue counter
*
* Helper function for RSS programming to increment through available
* queus. Returns the next queue value.
**/
static int next_queue(struct i40evf_adapter *adapter, int j)
{
j += 1;
return j >= adapter->num_active_queues ? 0 : j;
}
/**
* i40evf_configure_rss - Prepare for RSS if used
* @adapter: board private structure * @adapter: board private structure
**/ **/
static void i40evf_configure_rss(struct i40evf_adapter *adapter) static void i40evf_configure_rss(struct i40evf_adapter *adapter)
{ {
u32 rss_key[I40E_VFQF_HKEY_MAX_INDEX + 1]; u32 rss_key[I40E_VFQF_HKEY_MAX_INDEX + 1];
struct i40e_hw *hw = &adapter->hw; struct i40e_hw *hw = &adapter->hw;
u32 cqueue = 0;
u32 lut = 0; u32 lut = 0;
int i, j; int i, j;
u64 hena; u64 hena;
/* No RSS for single queue. */
if (adapter->num_active_queues == 1) {
wr32(hw, I40E_VFQF_HENA(0), 0);
wr32(hw, I40E_VFQF_HENA(1), 0);
return;
}
/* Hash type is configured by the PF - we just supply the key */ /* Hash type is configured by the PF - we just supply the key */
netdev_rss_key_fill(rss_key, sizeof(rss_key)); netdev_rss_key_fill(rss_key, sizeof(rss_key));
/* Fill out hash function seed */
for (i = 0; i <= I40E_VFQF_HKEY_MAX_INDEX; i++) for (i = 0; i <= I40E_VFQF_HKEY_MAX_INDEX; i++)
wr32(hw, I40E_VFQF_HKEY(i), rss_key[i]); wr32(hw, I40E_VFQF_HKEY(i), rss_key[i]);
...@@ -1459,16 +1460,14 @@ static void i40evf_configure_rss(struct i40evf_adapter *adapter) ...@@ -1459,16 +1460,14 @@ static void i40evf_configure_rss(struct i40evf_adapter *adapter)
wr32(hw, I40E_VFQF_HENA(1), (u32)(hena >> 32)); wr32(hw, I40E_VFQF_HENA(1), (u32)(hena >> 32));
/* Populate the LUT with max no. of queues in round robin fashion */ /* Populate the LUT with max no. of queues in round robin fashion */
j = adapter->num_active_queues;
for (i = 0; i <= I40E_VFQF_HLUT_MAX_INDEX; i++) { for (i = 0; i <= I40E_VFQF_HLUT_MAX_INDEX; i++) {
j = next_queue(adapter, j); lut = 0;
lut = j; for (j = 0; j < 4; j++) {
j = next_queue(adapter, j); if (cqueue == adapter->vsi_res->num_queue_pairs)
lut |= j << 8; cqueue = 0;
j = next_queue(adapter, j); lut |= ((cqueue) << (8 * j));
lut |= j << 16; cqueue++;
j = next_queue(adapter, j); }
lut |= j << 24;
wr32(hw, I40E_VFQF_HLUT(i), lut); wr32(hw, I40E_VFQF_HLUT(i), lut);
} }
i40e_flush(hw); i40e_flush(hw);
......
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