提交 b9ef4ab3 编写于 作者: D David S. Miller

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

Jeff Kirsher says:

====================
40GbE Intel Wired LAN Driver Updates 2017-02-18

This series contains updates to i40e and i40evf only.

Alan fixes a bug in which the driver is unable to exit overflow
promiscuous mode after having added "too many" mac filters.  Ractored
the '%*ph' printk format specifier to instead use the print_hex_dump().

Josh adds enabling multicast magic packet wakeup by adding calls to
the mac_address_write admin q function during power down to update the
PRTPM_SAH/SAL registers with the MC_MAG_EN bit.

Jake remove a duplicate call i40e_update_link_info(), since it does not
need to call it twice.  Fixes and issue where we calculating the wrong
switch id on big endian platforms.  Avoided sparse warning, by doing a
typecast to ensure the value is of the type expected by
csum_replace_by_diff().

Mitch fixes a memory leak by freeing resources during i40e_remove().
Cleans up some code confusion by adding a proper code comment.

Carolyn fixes a bug introduced with the addition of the per queue ITR
feature support in ethtool.  Cleans up a duplicate device id from the
PCI table.

Harshitha fixes a bug which causes the 'Link Detected' field in
ethtool to report the correct link status.

Benjamin Poirier from SuSE applies a fix ec13ee80 ("virtio_net:
 invoke softirqs after __napi_schedule") to i40e driver as well.
====================
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
......@@ -348,6 +348,8 @@ struct i40e_pf {
#define I40E_FLAG_TRUE_PROMISC_SUPPORT BIT_ULL(51)
#define I40E_FLAG_HAVE_CRT_RETIMER BIT_ULL(52)
#define I40E_FLAG_PTP_L4_CAPABLE BIT_ULL(53)
#define I40E_FLAG_WOL_MC_MAGIC_PKT_WAKE BIT_ULL(54)
#define I40E_FLAG_TEMP_LINK_POLLING BIT_ULL(55)
/* tracks features that get auto disabled by errors */
u64 auto_disable_flags;
......
......@@ -538,6 +538,8 @@ I40E_CHECK_STRUCT_LEN(24, i40e_aqc_mac_address_read_data);
/* Manage MAC Address Write Command (0x0108) */
struct i40e_aqc_mac_address_write {
__le16 command_flags;
#define I40E_AQC_MC_MAG_EN 0x0100
#define I40E_AQC_WOL_PRESERVE_ON_PFR 0x0200
#define I40E_AQC_WRITE_TYPE_LAA_ONLY 0x0000
#define I40E_AQC_WRITE_TYPE_LAA_WOL 0x4000
#define I40E_AQC_WRITE_TYPE_PORT 0x8000
......
......@@ -300,7 +300,6 @@ void i40e_debug_aq(struct i40e_hw *hw, enum i40e_debug_mask mask, void *desc,
struct i40e_aq_desc *aq_desc = (struct i40e_aq_desc *)desc;
u16 len;
u8 *buf = (u8 *)buffer;
u16 i = 0;
if ((!(mask & hw->debug_mask)) || (desc == NULL))
return;
......@@ -328,12 +327,18 @@ void i40e_debug_aq(struct i40e_hw *hw, enum i40e_debug_mask mask, void *desc,
if (buf_len < len)
len = buf_len;
/* write the full 16-byte chunks */
for (i = 0; i < (len - 16); i += 16)
i40e_debug(hw, mask, "\t0x%04X %16ph\n", i, buf + i);
/* write whatever's left over without overrunning the buffer */
if (i < len)
i40e_debug(hw, mask, "\t0x%04X %*ph\n",
i, len - i, buf + i);
if (hw->debug_mask & mask) {
char prefix[20];
snprintf(prefix, 20,
"i40e %02x:%02x.%x: \t0x",
hw->bus.bus_id,
hw->bus.device,
hw->bus.func);
print_hex_dump(KERN_INFO, prefix, DUMP_PREFIX_OFFSET,
16, 1, buf, len, false);
}
}
}
......
......@@ -974,7 +974,7 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
struct i40e_dcbx_config *r_cfg =
&pf->hw.remote_dcbx_config;
int i, ret;
u32 switch_id;
u16 switch_id;
bw_data = kzalloc(sizeof(
struct i40e_aqc_query_port_ets_config_resp),
......@@ -986,7 +986,8 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
vsi = pf->vsi[pf->lan_vsi];
switch_id =
vsi->info.switch_id & I40E_AQ_VSI_SW_ID_MASK;
le16_to_cpu(vsi->info.switch_id) &
I40E_AQ_VSI_SW_ID_MASK;
ret = i40e_aq_query_port_ets_config(&pf->hw,
switch_id,
......
......@@ -77,7 +77,6 @@ static const struct pci_device_id i40e_pci_tbl[] = {
{PCI_VDEVICE(INTEL, I40E_DEV_ID_QSFP_C), 0},
{PCI_VDEVICE(INTEL, I40E_DEV_ID_10G_BASE_T), 0},
{PCI_VDEVICE(INTEL, I40E_DEV_ID_10G_BASE_T4), 0},
{PCI_VDEVICE(INTEL, I40E_DEV_ID_20G_KR2), 0},
{PCI_VDEVICE(INTEL, I40E_DEV_ID_KX_X722), 0},
{PCI_VDEVICE(INTEL, I40E_DEV_ID_QSFP_X722), 0},
{PCI_VDEVICE(INTEL, I40E_DEV_ID_SFP_X722), 0},
......@@ -1254,6 +1253,7 @@ static int i40e_correct_mac_vlan_filters(struct i40e_vsi *vsi,
struct hlist_head *tmp_del_list,
int vlan_filters)
{
s16 pvid = le16_to_cpu(vsi->info.pvid);
struct i40e_mac_filter *f, *add_head;
struct i40e_new_mac_filter *new;
struct hlist_node *h;
......@@ -1275,8 +1275,8 @@ static int i40e_correct_mac_vlan_filters(struct i40e_vsi *vsi,
/* Update the filters about to be added in place */
hlist_for_each_entry(new, tmp_add_list, hlist) {
if (vsi->info.pvid && new->f->vlan != vsi->info.pvid)
new->f->vlan = vsi->info.pvid;
if (pvid && new->f->vlan != pvid)
new->f->vlan = pvid;
else if (vlan_filters && new->f->vlan == I40E_VLAN_ANY)
new->f->vlan = 0;
else if (!vlan_filters && new->f->vlan == 0)
......@@ -1290,12 +1290,12 @@ static int i40e_correct_mac_vlan_filters(struct i40e_vsi *vsi,
* order to avoid duplicating code for adding the new filter
* then deleting the old filter.
*/
if ((vsi->info.pvid && f->vlan != vsi->info.pvid) ||
if ((pvid && f->vlan != pvid) ||
(vlan_filters && f->vlan == I40E_VLAN_ANY) ||
(!vlan_filters && f->vlan == 0)) {
/* Determine the new vlan we will be adding */
if (vsi->info.pvid)
new_vlan = vsi->info.pvid;
if (pvid)
new_vlan = pvid;
else if (vlan_filters)
new_vlan = 0;
else
......@@ -1447,18 +1447,20 @@ void __i40e_del_filter(struct i40e_vsi *vsi, struct i40e_mac_filter *f)
if (!f)
return;
/* If the filter was never added to firmware then we can just delete it
* directly and we don't want to set the status to remove or else an
* admin queue command will unnecessarily fire.
*/
if ((f->state == I40E_FILTER_FAILED) ||
(f->state == I40E_FILTER_NEW)) {
/* this one never got added by the FW. Just remove it,
* no need to sync anything.
*/
hash_del(&f->hlist);
kfree(f);
} else {
f->state = I40E_FILTER_REMOVE;
vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED;
vsi->back->flags |= I40E_FLAG_FILTER_SYNC;
}
vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED;
vsi->back->flags |= I40E_FLAG_FILTER_SYNC;
}
/**
......@@ -4683,8 +4685,10 @@ static void i40e_detect_recover_hung_queue(int q_idx, struct i40e_vsi *vsi)
*/
if ((!tx_pending_hw) && i40e_get_tx_pending(tx_ring, true) &&
(!(val & I40E_PFINT_DYN_CTLN_INTENA_MASK))) {
local_bh_disable();
if (napi_reschedule(&tx_ring->q_vector->napi))
tx_ring->tx_stats.tx_lost_interrupt++;
local_bh_enable();
}
}
......@@ -6350,7 +6354,16 @@ static void i40e_link_event(struct i40e_pf *pf)
old_link = (pf->hw.phy.link_info_old.link_info & I40E_AQ_LINK_UP);
status = i40e_get_link_status(&pf->hw, &new_link);
if (status) {
/* On success, disable temp link polling */
if (status == I40E_SUCCESS) {
if (pf->flags & I40E_FLAG_TEMP_LINK_POLLING)
pf->flags &= ~I40E_FLAG_TEMP_LINK_POLLING;
} else {
/* Enable link polling temporarily until i40e_get_link_status
* returns I40E_SUCCESS
*/
pf->flags |= I40E_FLAG_TEMP_LINK_POLLING;
dev_dbg(&pf->pdev->dev, "couldn't get link state, status: %d\n",
status);
return;
......@@ -6402,7 +6415,8 @@ static void i40e_watchdog_subtask(struct i40e_pf *pf)
return;
pf->service_timer_previous = jiffies;
if (pf->flags & I40E_FLAG_LINK_POLLING_ENABLED)
if ((pf->flags & I40E_FLAG_LINK_POLLING_ENABLED) ||
(pf->flags & I40E_FLAG_TEMP_LINK_POLLING))
i40e_link_event(pf);
/* Update the stats for active netdevs so the network stack
......@@ -8813,16 +8827,17 @@ static int i40e_sw_init(struct i40e_pf *pf)
}
#endif /* CONFIG_PCI_IOV */
if (pf->hw.mac.type == I40E_MAC_X722) {
pf->flags |= I40E_FLAG_RSS_AQ_CAPABLE |
I40E_FLAG_128_QP_RSS_CAPABLE |
I40E_FLAG_HW_ATR_EVICT_CAPABLE |
I40E_FLAG_OUTER_UDP_CSUM_CAPABLE |
I40E_FLAG_WB_ON_ITR_CAPABLE |
I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE |
I40E_FLAG_NO_PCI_LINK_CHECK |
I40E_FLAG_USE_SET_LLDP_MIB |
I40E_FLAG_GENEVE_OFFLOAD_CAPABLE |
I40E_FLAG_PTP_L4_CAPABLE;
pf->flags |= I40E_FLAG_RSS_AQ_CAPABLE
| I40E_FLAG_128_QP_RSS_CAPABLE
| I40E_FLAG_HW_ATR_EVICT_CAPABLE
| I40E_FLAG_OUTER_UDP_CSUM_CAPABLE
| I40E_FLAG_WB_ON_ITR_CAPABLE
| I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE
| I40E_FLAG_NO_PCI_LINK_CHECK
| I40E_FLAG_USE_SET_LLDP_MIB
| I40E_FLAG_GENEVE_OFFLOAD_CAPABLE
| I40E_FLAG_PTP_L4_CAPABLE
| I40E_FLAG_WOL_MC_MAGIC_PKT_WAKE;
} else if ((pf->hw.aq.api_maj_ver > 1) ||
((pf->hw.aq.api_maj_ver == 1) &&
(pf->hw.aq.api_min_ver > 4))) {
......@@ -10758,7 +10773,6 @@ static int i40e_setup_pf_switch(struct i40e_pf *pf, bool reinit)
i40e_pf_config_rss(pf);
/* fill in link information and enable LSE reporting */
i40e_update_link_info(&pf->hw);
i40e_link_event(pf);
/* Initialize user-specific link properties */
......@@ -11738,6 +11752,53 @@ static void i40e_pci_error_resume(struct pci_dev *pdev)
rtnl_unlock();
}
/**
* i40e_enable_mc_magic_wake - enable multicast magic packet wake up
* using the mac_address_write admin q function
* @pf: pointer to i40e_pf struct
**/
static void i40e_enable_mc_magic_wake(struct i40e_pf *pf)
{
struct i40e_hw *hw = &pf->hw;
i40e_status ret;
u8 mac_addr[6];
u16 flags = 0;
/* Get current MAC address in case it's an LAA */
if (pf->vsi[pf->lan_vsi] && pf->vsi[pf->lan_vsi]->netdev) {
ether_addr_copy(mac_addr,
pf->vsi[pf->lan_vsi]->netdev->dev_addr);
} else {
dev_err(&pf->pdev->dev,
"Failed to retrieve MAC address; using default\n");
ether_addr_copy(mac_addr, hw->mac.addr);
}
/* The FW expects the mac address write cmd to first be called with
* one of these flags before calling it again with the multicast
* enable flags.
*/
flags = I40E_AQC_WRITE_TYPE_LAA_WOL;
if (hw->func_caps.flex10_enable && hw->partition_id != 1)
flags = I40E_AQC_WRITE_TYPE_LAA_ONLY;
ret = i40e_aq_mac_address_write(hw, flags, mac_addr, NULL);
if (ret) {
dev_err(&pf->pdev->dev,
"Failed to update MAC address registers; cannot enable Multicast Magic packet wake up");
return;
}
flags = I40E_AQC_MC_MAG_EN
| I40E_AQC_WOL_PRESERVE_ON_PFR
| I40E_AQC_WRITE_TYPE_UPDATE_MC_MAG;
ret = i40e_aq_mac_address_write(hw, flags, mac_addr, NULL);
if (ret)
dev_err(&pf->pdev->dev,
"Failed to enable Multicast Magic Packet wake up\n");
}
/**
* i40e_shutdown - PCI callback for shutting down
* @pdev: PCI device information struct
......@@ -11760,6 +11821,9 @@ static void i40e_shutdown(struct pci_dev *pdev)
cancel_work_sync(&pf->service_task);
i40e_fdir_teardown(pf);
if (pf->wol_en && (pf->flags & I40E_FLAG_WOL_MC_MAGIC_PKT_WAKE))
i40e_enable_mc_magic_wake(pf);
rtnl_lock();
i40e_prep_for_reset(pf);
rtnl_unlock();
......@@ -11791,6 +11855,9 @@ static int i40e_suspend(struct pci_dev *pdev, pm_message_t state)
set_bit(__I40E_SUSPENDED, &pf->state);
set_bit(__I40E_DOWN, &pf->state);
if (pf->wol_en && (pf->flags & I40E_FLAG_WOL_MC_MAGIC_PKT_WAKE))
i40e_enable_mc_magic_wake(pf);
rtnl_lock();
i40e_prep_for_reset(pf);
rtnl_unlock();
......
......@@ -1864,14 +1864,14 @@ static u32 i40e_buildreg_itr(const int type, const u16 itr)
/* a small macro to shorten up some long lines */
#define INTREG I40E_PFINT_DYN_CTLN
static inline int get_rx_itr_enabled(struct i40e_vsi *vsi, int idx)
static inline int get_rx_itr(struct i40e_vsi *vsi, int idx)
{
return !!(vsi->rx_rings[idx]->rx_itr_setting);
return vsi->rx_rings[idx]->rx_itr_setting;
}
static inline int get_tx_itr_enabled(struct i40e_vsi *vsi, int idx)
static inline int get_tx_itr(struct i40e_vsi *vsi, int idx)
{
return !!(vsi->tx_rings[idx]->tx_itr_setting);
return vsi->tx_rings[idx]->tx_itr_setting;
}
/**
......@@ -1897,8 +1897,8 @@ static inline void i40e_update_enable_itr(struct i40e_vsi *vsi,
*/
rxval = txval = i40e_buildreg_itr(I40E_ITR_NONE, 0);
rx_itr_setting = get_rx_itr_enabled(vsi, idx);
tx_itr_setting = get_tx_itr_enabled(vsi, idx);
rx_itr_setting = get_rx_itr(vsi, idx);
tx_itr_setting = get_tx_itr(vsi, idx);
if (q_vector->itr_countdown > 0 ||
(!ITR_IS_DYNAMIC(rx_itr_setting) &&
......@@ -2335,7 +2335,8 @@ static int i40e_tso(struct i40e_tx_buffer *first, u8 *hdr_len,
/* remove payload length from outer checksum */
paylen = skb->len - l4_offset;
csum_replace_by_diff(&l4.udp->check, htonl(paylen));
csum_replace_by_diff(&l4.udp->check,
(__force __wsum)htonl(paylen));
}
/* reset pointers to inner headers */
......@@ -2356,7 +2357,7 @@ static int i40e_tso(struct i40e_tx_buffer *first, u8 *hdr_len,
/* remove payload length from inner checksum */
paylen = skb->len - l4_offset;
csum_replace_by_diff(&l4.tcp->check, htonl(paylen));
csum_replace_by_diff(&l4.tcp->check, (__force __wsum)htonl(paylen));
/* compute length of segmentation header */
*hdr_len = (l4.tcp->doff * 4) + l4_offset;
......
......@@ -304,7 +304,6 @@ void i40evf_debug_aq(struct i40e_hw *hw, enum i40e_debug_mask mask, void *desc,
{
struct i40e_aq_desc *aq_desc = (struct i40e_aq_desc *)desc;
u8 *buf = (u8 *)buffer;
u16 i = 0;
if ((!(mask & hw->debug_mask)) || (desc == NULL))
return;
......@@ -332,12 +331,18 @@ void i40evf_debug_aq(struct i40e_hw *hw, enum i40e_debug_mask mask, void *desc,
if (buf_len < len)
len = buf_len;
/* write the full 16-byte chunks */
for (i = 0; i < (len - 16); i += 16)
i40e_debug(hw, mask, "\t0x%04X %16ph\n", i, buf + i);
/* write whatever's left over without overrunning the buffer */
if (i < len)
i40e_debug(hw, mask, "\t0x%04X %*ph\n",
i, len - i, buf + i);
if (hw->debug_mask & mask) {
char prefix[20];
snprintf(prefix, 20,
"i40evf %02x:%02x.%x: \t0x",
hw->bus.bus_id,
hw->bus.device,
hw->bus.func);
print_hex_dump(KERN_INFO, prefix, DUMP_PREFIX_OFFSET,
16, 1, buf, len, false);
}
}
}
......
......@@ -1324,18 +1324,18 @@ static u32 i40e_buildreg_itr(const int type, const u16 itr)
/* a small macro to shorten up some long lines */
#define INTREG I40E_VFINT_DYN_CTLN1
static inline int get_rx_itr_enabled(struct i40e_vsi *vsi, int idx)
static inline int get_rx_itr(struct i40e_vsi *vsi, int idx)
{
struct i40evf_adapter *adapter = vsi->back;
return !!(adapter->rx_rings[idx].rx_itr_setting);
return adapter->rx_rings[idx].rx_itr_setting;
}
static inline int get_tx_itr_enabled(struct i40e_vsi *vsi, int idx)
static inline int get_tx_itr(struct i40e_vsi *vsi, int idx)
{
struct i40evf_adapter *adapter = vsi->back;
return !!(adapter->tx_rings[idx].tx_itr_setting);
return adapter->tx_rings[idx].tx_itr_setting;
}
/**
......@@ -1361,8 +1361,8 @@ static inline void i40e_update_enable_itr(struct i40e_vsi *vsi,
*/
rxval = txval = i40e_buildreg_itr(I40E_ITR_NONE, 0);
rx_itr_setting = get_rx_itr_enabled(vsi, idx);
tx_itr_setting = get_tx_itr_enabled(vsi, idx);
rx_itr_setting = get_rx_itr(vsi, idx);
tx_itr_setting = get_tx_itr(vsi, idx);
if (q_vector->itr_countdown > 0 ||
(!ITR_IS_DYNAMIC(rx_itr_setting) &&
......@@ -1629,7 +1629,8 @@ static int i40e_tso(struct i40e_tx_buffer *first, u8 *hdr_len,
/* remove payload length from outer checksum */
paylen = skb->len - l4_offset;
csum_replace_by_diff(&l4.udp->check, htonl(paylen));
csum_replace_by_diff(&l4.udp->check,
(__force __wsum)htonl(paylen));
}
/* reset pointers to inner headers */
......@@ -1650,7 +1651,7 @@ static int i40e_tso(struct i40e_tx_buffer *first, u8 *hdr_len,
/* remove payload length from inner checksum */
paylen = skb->len - l4_offset;
csum_replace_by_diff(&l4.tcp->check, htonl(paylen));
csum_replace_by_diff(&l4.tcp->check, (__force __wsum)htonl(paylen));
/* compute length of segmentation header */
*hdr_len = (l4.tcp->doff * 4) + l4_offset;
......
......@@ -2153,6 +2153,11 @@ static int i40evf_close(struct net_device *netdev)
adapter->state = __I40EVF_DOWN_PENDING;
i40evf_free_traffic_irqs(adapter);
/* We explicitly don't free resources here because the hardware is
* still active and can DMA into memory. Resources are cleared in
* i40evf_virtchnl_completion() after we get confirmation from the PF
* driver that the rings have been stopped.
*/
return 0;
}
......@@ -2871,7 +2876,8 @@ static void i40evf_remove(struct pci_dev *pdev)
i40evf_request_reset(adapter);
msleep(50);
}
i40evf_free_all_tx_resources(adapter);
i40evf_free_all_rx_resources(adapter);
i40evf_misc_irq_disable(adapter);
i40evf_free_misc_irq(adapter);
i40evf_reset_interrupt_capability(adapter);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册