Commit b48565f5 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 2015-12-05

This series contains updates to fm10k only.

Jacob provides the remaining fm10k patches in the series.  First change
ensures that all the logic regarding the setting of netdev features is
consolidated in one place of the driver.  Fixed an issue where an assumption
was being made on how many queues are available, especially when init_hw_vf()
errors out.  Fixed up an number of issues with init_hw() where failures
were not being handled properly or at all, so update the driver to check
returned error codes and respond appropriately.  Fixed up typecasting
issues found where either the incorrect typecast size was used or
explicitly typecast values.  Added additional debugging statistics and
rename statistic to better reflect its true value.  Added support for
ITR scaling based on PCIe link speed for fm10k.  Fixed up code comment
where "hardware" was misspelled.

v2: Dropped patches #1 and #10 from original submission, patch #1 was from
    Nick Krause and due to his past kernel interactions, dropping his patch.
    Patch #10 had questions and concerns from Tom Herbert which cannot be
    addressed at this time since the author (Jacob Keller) is currently on
    sabbatical, so dropping this patch for now until we can properly address
    Tom's questions and concerns.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents b82583ec 03d13a51
...@@ -164,14 +164,20 @@ struct fm10k_ring_container { ...@@ -164,14 +164,20 @@ struct fm10k_ring_container {
unsigned int total_packets; /* total packets processed this int */ unsigned int total_packets; /* total packets processed this int */
u16 work_limit; /* total work allowed per interrupt */ u16 work_limit; /* total work allowed per interrupt */
u16 itr; /* interrupt throttle rate value */ u16 itr; /* interrupt throttle rate value */
u8 itr_scale; /* ITR adjustment scaler based on PCI speed */
u8 count; /* total number of rings in vector */ u8 count; /* total number of rings in vector */
}; };
#define FM10K_ITR_MAX 0x0FFF /* maximum value for ITR */ #define FM10K_ITR_MAX 0x0FFF /* maximum value for ITR */
#define FM10K_ITR_10K 100 /* 100us */ #define FM10K_ITR_10K 100 /* 100us */
#define FM10K_ITR_20K 50 /* 50us */ #define FM10K_ITR_20K 50 /* 50us */
#define FM10K_ITR_40K 25 /* 25us */
#define FM10K_ITR_ADAPTIVE 0x8000 /* adaptive interrupt moderation flag */ #define FM10K_ITR_ADAPTIVE 0x8000 /* adaptive interrupt moderation flag */
#define ITR_IS_ADAPTIVE(itr) (!!(itr & FM10K_ITR_ADAPTIVE))
#define FM10K_TX_ITR_DEFAULT FM10K_ITR_40K
#define FM10K_RX_ITR_DEFAULT FM10K_ITR_20K
#define FM10K_ITR_ENABLE (FM10K_ITR_AUTOMASK | FM10K_ITR_MASK_CLEAR) #define FM10K_ITR_ENABLE (FM10K_ITR_AUTOMASK | FM10K_ITR_MASK_CLEAR)
static inline struct netdev_queue *txring_txq(const struct fm10k_ring *ring) static inline struct netdev_queue *txring_txq(const struct fm10k_ring *ring)
...@@ -484,7 +490,7 @@ void fm10k_netpoll(struct net_device *netdev); ...@@ -484,7 +490,7 @@ void fm10k_netpoll(struct net_device *netdev);
#endif #endif
/* Netdev */ /* Netdev */
struct net_device *fm10k_alloc_netdev(void); struct net_device *fm10k_alloc_netdev(const struct fm10k_info *info);
int fm10k_setup_rx_resources(struct fm10k_ring *); int fm10k_setup_rx_resources(struct fm10k_ring *);
int fm10k_setup_tx_resources(struct fm10k_ring *); int fm10k_setup_tx_resources(struct fm10k_ring *);
void fm10k_free_rx_resources(struct fm10k_ring *); void fm10k_free_rx_resources(struct fm10k_ring *);
......
...@@ -111,12 +111,14 @@ static const struct fm10k_stats fm10k_gstrings_pf_stats[] = { ...@@ -111,12 +111,14 @@ static const struct fm10k_stats fm10k_gstrings_pf_stats[] = {
static const struct fm10k_stats fm10k_gstrings_mbx_stats[] = { static const struct fm10k_stats fm10k_gstrings_mbx_stats[] = {
FM10K_MBX_STAT("mbx_tx_busy", tx_busy), FM10K_MBX_STAT("mbx_tx_busy", tx_busy),
FM10K_MBX_STAT("mbx_tx_oversized", tx_dropped), FM10K_MBX_STAT("mbx_tx_dropped", tx_dropped),
FM10K_MBX_STAT("mbx_tx_messages", tx_messages), FM10K_MBX_STAT("mbx_tx_messages", tx_messages),
FM10K_MBX_STAT("mbx_tx_dwords", tx_dwords), FM10K_MBX_STAT("mbx_tx_dwords", tx_dwords),
FM10K_MBX_STAT("mbx_tx_mbmem_pulled", tx_mbmem_pulled),
FM10K_MBX_STAT("mbx_rx_messages", rx_messages), FM10K_MBX_STAT("mbx_rx_messages", rx_messages),
FM10K_MBX_STAT("mbx_rx_dwords", rx_dwords), FM10K_MBX_STAT("mbx_rx_dwords", rx_dwords),
FM10K_MBX_STAT("mbx_rx_parse_err", rx_parse_err), FM10K_MBX_STAT("mbx_rx_parse_err", rx_parse_err),
FM10K_MBX_STAT("mbx_rx_mbmem_pushed", rx_mbmem_pushed),
}; };
#define FM10K_GLOBAL_STATS_LEN ARRAY_SIZE(fm10k_gstrings_global_stats) #define FM10K_GLOBAL_STATS_LEN ARRAY_SIZE(fm10k_gstrings_global_stats)
...@@ -699,12 +701,10 @@ static int fm10k_get_coalesce(struct net_device *dev, ...@@ -699,12 +701,10 @@ static int fm10k_get_coalesce(struct net_device *dev,
{ {
struct fm10k_intfc *interface = netdev_priv(dev); struct fm10k_intfc *interface = netdev_priv(dev);
ec->use_adaptive_tx_coalesce = ec->use_adaptive_tx_coalesce = ITR_IS_ADAPTIVE(interface->tx_itr);
!!(interface->tx_itr & FM10K_ITR_ADAPTIVE);
ec->tx_coalesce_usecs = interface->tx_itr & ~FM10K_ITR_ADAPTIVE; ec->tx_coalesce_usecs = interface->tx_itr & ~FM10K_ITR_ADAPTIVE;
ec->use_adaptive_rx_coalesce = ec->use_adaptive_rx_coalesce = ITR_IS_ADAPTIVE(interface->rx_itr);
!!(interface->rx_itr & FM10K_ITR_ADAPTIVE);
ec->rx_coalesce_usecs = interface->rx_itr & ~FM10K_ITR_ADAPTIVE; ec->rx_coalesce_usecs = interface->rx_itr & ~FM10K_ITR_ADAPTIVE;
return 0; return 0;
...@@ -729,10 +729,10 @@ static int fm10k_set_coalesce(struct net_device *dev, ...@@ -729,10 +729,10 @@ static int fm10k_set_coalesce(struct net_device *dev,
/* set initial values for adaptive ITR */ /* set initial values for adaptive ITR */
if (ec->use_adaptive_tx_coalesce) if (ec->use_adaptive_tx_coalesce)
tx_itr = FM10K_ITR_ADAPTIVE | FM10K_ITR_10K; tx_itr = FM10K_ITR_ADAPTIVE | FM10K_TX_ITR_DEFAULT;
if (ec->use_adaptive_rx_coalesce) if (ec->use_adaptive_rx_coalesce)
rx_itr = FM10K_ITR_ADAPTIVE | FM10K_ITR_20K; rx_itr = FM10K_ITR_ADAPTIVE | FM10K_RX_ITR_DEFAULT;
/* update interface */ /* update interface */
interface->tx_itr = tx_itr; interface->tx_itr = tx_itr;
......
...@@ -1094,11 +1094,11 @@ static void fm10k_tx_map(struct fm10k_ring *tx_ring, ...@@ -1094,11 +1094,11 @@ static void fm10k_tx_map(struct fm10k_ring *tx_ring,
netdev_tx_t fm10k_xmit_frame_ring(struct sk_buff *skb, netdev_tx_t fm10k_xmit_frame_ring(struct sk_buff *skb,
struct fm10k_ring *tx_ring) struct fm10k_ring *tx_ring)
{ {
u16 count = TXD_USE_COUNT(skb_headlen(skb));
struct fm10k_tx_buffer *first; struct fm10k_tx_buffer *first;
int tso;
u32 tx_flags = 0;
unsigned short f; unsigned short f;
u16 count = TXD_USE_COUNT(skb_headlen(skb)); u32 tx_flags = 0;
int tso;
/* need: 1 descriptor per page * PAGE_SIZE/FM10K_MAX_DATA_PER_TXD, /* need: 1 descriptor per page * PAGE_SIZE/FM10K_MAX_DATA_PER_TXD,
* + 1 desc for skb_headlen/FM10K_MAX_DATA_PER_TXD, * + 1 desc for skb_headlen/FM10K_MAX_DATA_PER_TXD,
...@@ -1363,10 +1363,10 @@ static bool fm10k_clean_tx_irq(struct fm10k_q_vector *q_vector, ...@@ -1363,10 +1363,10 @@ static bool fm10k_clean_tx_irq(struct fm10k_q_vector *q_vector,
**/ **/
static void fm10k_update_itr(struct fm10k_ring_container *ring_container) static void fm10k_update_itr(struct fm10k_ring_container *ring_container)
{ {
unsigned int avg_wire_size, packets; unsigned int avg_wire_size, packets, itr_round;
/* Only update ITR if we are using adaptive setting */ /* Only update ITR if we are using adaptive setting */
if (!(ring_container->itr & FM10K_ITR_ADAPTIVE)) if (!ITR_IS_ADAPTIVE(ring_container->itr))
goto clear_counts; goto clear_counts;
packets = ring_container->total_packets; packets = ring_container->total_packets;
...@@ -1375,18 +1375,44 @@ static void fm10k_update_itr(struct fm10k_ring_container *ring_container) ...@@ -1375,18 +1375,44 @@ static void fm10k_update_itr(struct fm10k_ring_container *ring_container)
avg_wire_size = ring_container->total_bytes / packets; avg_wire_size = ring_container->total_bytes / packets;
/* Add 24 bytes to size to account for CRC, preamble, and gap */ /* The following is a crude approximation of:
avg_wire_size += 24; * wmem_default / (size + overhead) = desired_pkts_per_int
* rate / bits_per_byte / (size + ethernet overhead) = pkt_rate
/* Don't starve jumbo frames */ * (desired_pkt_rate / pkt_rate) * usecs_per_sec = ITR value
if (avg_wire_size > 3000) *
avg_wire_size = 3000; * Assuming wmem_default is 212992 and overhead is 640 bytes per
* packet, (256 skb, 64 headroom, 320 shared info), we can reduce the
* formula down to
*
* (34 * (size + 24)) / (size + 640) = ITR
*
* We first do some math on the packet size and then finally bitshift
* by 8 after rounding up. We also have to account for PCIe link speed
* difference as ITR scales based on this.
*/
if (avg_wire_size <= 360) {
/* Start at 250K ints/sec and gradually drop to 77K ints/sec */
avg_wire_size *= 8;
avg_wire_size += 376;
} else if (avg_wire_size <= 1152) {
/* 77K ints/sec to 45K ints/sec */
avg_wire_size *= 3;
avg_wire_size += 2176;
} else if (avg_wire_size <= 1920) {
/* 45K ints/sec to 38K ints/sec */
avg_wire_size += 4480;
} else {
/* plateau at a limit of 38K ints/sec */
avg_wire_size = 6656;
}
/* Give a little boost to mid-size frames */ /* Perform final bitshift for division after rounding up to ensure
if ((avg_wire_size > 300) && (avg_wire_size < 1200)) * that the calculation will never get below a 1. The bit shift
avg_wire_size /= 3; * accounts for changes in the ITR due to PCIe link speed.
else */
avg_wire_size /= 2; itr_round = ACCESS_ONCE(ring_container->itr_scale) + 8;
avg_wire_size += (1 << itr_round) - 1;
avg_wire_size >>= itr_round;
/* write back value and retain adaptive flag */ /* write back value and retain adaptive flag */
ring_container->itr = avg_wire_size | FM10K_ITR_ADAPTIVE; ring_container->itr = avg_wire_size | FM10K_ITR_ADAPTIVE;
...@@ -1604,6 +1630,7 @@ static int fm10k_alloc_q_vector(struct fm10k_intfc *interface, ...@@ -1604,6 +1630,7 @@ static int fm10k_alloc_q_vector(struct fm10k_intfc *interface,
q_vector->tx.ring = ring; q_vector->tx.ring = ring;
q_vector->tx.work_limit = FM10K_DEFAULT_TX_WORK; q_vector->tx.work_limit = FM10K_DEFAULT_TX_WORK;
q_vector->tx.itr = interface->tx_itr; q_vector->tx.itr = interface->tx_itr;
q_vector->tx.itr_scale = interface->hw.mac.itr_scale;
q_vector->tx.count = txr_count; q_vector->tx.count = txr_count;
while (txr_count) { while (txr_count) {
...@@ -1632,6 +1659,7 @@ static int fm10k_alloc_q_vector(struct fm10k_intfc *interface, ...@@ -1632,6 +1659,7 @@ static int fm10k_alloc_q_vector(struct fm10k_intfc *interface,
/* save Rx ring container info */ /* save Rx ring container info */
q_vector->rx.ring = ring; q_vector->rx.ring = ring;
q_vector->rx.itr = interface->rx_itr; q_vector->rx.itr = interface->rx_itr;
q_vector->rx.itr_scale = interface->hw.mac.itr_scale;
q_vector->rx.count = rxr_count; q_vector->rx.count = rxr_count;
while (rxr_count) { while (rxr_count) {
......
...@@ -375,6 +375,8 @@ static void fm10k_mbx_write_copy(struct fm10k_hw *hw, ...@@ -375,6 +375,8 @@ static void fm10k_mbx_write_copy(struct fm10k_hw *hw,
if (!tail) if (!tail)
tail++; tail++;
mbx->tx_mbmem_pulled++;
/* write message to hardware FIFO */ /* write message to hardware FIFO */
fm10k_write_reg(hw, mbmem + tail++, *(head++)); fm10k_write_reg(hw, mbmem + tail++, *(head++));
} while (--len && --end); } while (--len && --end);
...@@ -459,6 +461,8 @@ static void fm10k_mbx_read_copy(struct fm10k_hw *hw, ...@@ -459,6 +461,8 @@ static void fm10k_mbx_read_copy(struct fm10k_hw *hw,
if (!head) if (!head)
head++; head++;
mbx->rx_mbmem_pushed++;
/* read message from hardware FIFO */ /* read message from hardware FIFO */
*(tail++) = fm10k_read_reg(hw, mbmem + head++); *(tail++) = fm10k_read_reg(hw, mbmem + head++);
} while (--len && --end); } while (--len && --end);
......
/* Intel Ethernet Switch Host Interface Driver /* Intel Ethernet Switch Host Interface Driver
* Copyright(c) 2013 - 2014 Intel Corporation. * Copyright(c) 2013 - 2015 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,
...@@ -291,8 +291,10 @@ struct fm10k_mbx_info { ...@@ -291,8 +291,10 @@ struct fm10k_mbx_info {
u64 tx_dropped; u64 tx_dropped;
u64 tx_messages; u64 tx_messages;
u64 tx_dwords; u64 tx_dwords;
u64 tx_mbmem_pulled;
u64 rx_messages; u64 rx_messages;
u64 rx_dwords; u64 rx_dwords;
u64 rx_mbmem_pushed;
u64 rx_parse_err; u64 rx_parse_err;
/* Buffer to store messages */ /* Buffer to store messages */
......
...@@ -1388,8 +1388,9 @@ static const struct net_device_ops fm10k_netdev_ops = { ...@@ -1388,8 +1388,9 @@ static const struct net_device_ops fm10k_netdev_ops = {
#define DEFAULT_DEBUG_LEVEL_SHIFT 3 #define DEFAULT_DEBUG_LEVEL_SHIFT 3
struct net_device *fm10k_alloc_netdev(void) struct net_device *fm10k_alloc_netdev(const struct fm10k_info *info)
{ {
netdev_features_t hw_features;
struct fm10k_intfc *interface; struct fm10k_intfc *interface;
struct net_device *dev; struct net_device *dev;
...@@ -1412,27 +1413,31 @@ struct net_device *fm10k_alloc_netdev(void) ...@@ -1412,27 +1413,31 @@ struct net_device *fm10k_alloc_netdev(void)
NETIF_F_TSO | NETIF_F_TSO |
NETIF_F_TSO6 | NETIF_F_TSO6 |
NETIF_F_TSO_ECN | NETIF_F_TSO_ECN |
NETIF_F_GSO_UDP_TUNNEL |
NETIF_F_RXHASH | NETIF_F_RXHASH |
NETIF_F_RXCSUM; NETIF_F_RXCSUM;
/* Only the PF can support VXLAN and NVGRE tunnel offloads */
if (info->mac == fm10k_mac_pf) {
dev->hw_enc_features = NETIF_F_IP_CSUM |
NETIF_F_TSO |
NETIF_F_TSO6 |
NETIF_F_TSO_ECN |
NETIF_F_GSO_UDP_TUNNEL |
NETIF_F_IPV6_CSUM |
NETIF_F_SG;
dev->features |= NETIF_F_GSO_UDP_TUNNEL;
}
/* all features defined to this point should be changeable */ /* all features defined to this point should be changeable */
dev->hw_features |= dev->features; hw_features = dev->features;
/* allow user to enable L2 forwarding acceleration */ /* allow user to enable L2 forwarding acceleration */
dev->hw_features |= NETIF_F_HW_L2FW_DOFFLOAD; hw_features |= NETIF_F_HW_L2FW_DOFFLOAD;
/* configure VLAN features */ /* configure VLAN features */
dev->vlan_features |= dev->features; dev->vlan_features |= dev->features;
/* configure tunnel offloads */
dev->hw_enc_features |= NETIF_F_IP_CSUM |
NETIF_F_TSO |
NETIF_F_TSO6 |
NETIF_F_TSO_ECN |
NETIF_F_GSO_UDP_TUNNEL |
NETIF_F_IPV6_CSUM;
/* we want to leave these both on as we cannot disable VLAN tag /* we want to leave these both on as we cannot disable VLAN tag
* insertion or stripping on the hardware since it is contained * insertion or stripping on the hardware since it is contained
* in the FTAG and not in the frame itself. * in the FTAG and not in the frame itself.
...@@ -1443,5 +1448,7 @@ struct net_device *fm10k_alloc_netdev(void) ...@@ -1443,5 +1448,7 @@ struct net_device *fm10k_alloc_netdev(void)
dev->priv_flags |= IFF_UNICAST_FLT; dev->priv_flags |= IFF_UNICAST_FLT;
dev->hw_features |= hw_features;
return dev; return dev;
} }
...@@ -159,13 +159,30 @@ static void fm10k_reinit(struct fm10k_intfc *interface) ...@@ -159,13 +159,30 @@ static void fm10k_reinit(struct fm10k_intfc *interface)
fm10k_mbx_free_irq(interface); fm10k_mbx_free_irq(interface);
/* free interrupts */
fm10k_clear_queueing_scheme(interface);
/* delay any future reset requests */ /* delay any future reset requests */
interface->last_reset = jiffies + (10 * HZ); interface->last_reset = jiffies + (10 * HZ);
/* reset and initialize the hardware so it is in a known state */ /* reset and initialize the hardware so it is in a known state */
err = hw->mac.ops.reset_hw(hw) ? : hw->mac.ops.init_hw(hw); err = hw->mac.ops.reset_hw(hw);
if (err) if (err) {
dev_err(&interface->pdev->dev, "reset_hw failed: %d\n", err);
goto reinit_err;
}
err = hw->mac.ops.init_hw(hw);
if (err) {
dev_err(&interface->pdev->dev, "init_hw failed: %d\n", err); dev_err(&interface->pdev->dev, "init_hw failed: %d\n", err);
goto reinit_err;
}
err = fm10k_init_queueing_scheme(interface);
if (err) {
dev_err(&interface->pdev->dev, "init_queueing_scheme failed: %d\n", err);
goto reinit_err;
}
/* reassociate interrupts */ /* reassociate interrupts */
fm10k_mbx_request_irq(interface); fm10k_mbx_request_irq(interface);
...@@ -193,6 +210,10 @@ static void fm10k_reinit(struct fm10k_intfc *interface) ...@@ -193,6 +210,10 @@ static void fm10k_reinit(struct fm10k_intfc *interface)
fm10k_iov_resume(interface->pdev); fm10k_iov_resume(interface->pdev);
reinit_err:
if (err)
netif_device_detach(netdev);
rtnl_unlock(); rtnl_unlock();
clear_bit(__FM10K_RESETTING, &interface->state); clear_bit(__FM10K_RESETTING, &interface->state);
...@@ -563,7 +584,7 @@ static void fm10k_configure_tx_ring(struct fm10k_intfc *interface, ...@@ -563,7 +584,7 @@ static void fm10k_configure_tx_ring(struct fm10k_intfc *interface,
/* store tail pointer */ /* store tail pointer */
ring->tail = &interface->uc_addr[FM10K_TDT(reg_idx)]; ring->tail = &interface->uc_addr[FM10K_TDT(reg_idx)];
/* reset ntu and ntc to place SW in sync with hardwdare */ /* reset ntu and ntc to place SW in sync with hardware */
ring->next_to_clean = 0; ring->next_to_clean = 0;
ring->next_to_use = 0; ring->next_to_use = 0;
...@@ -669,7 +690,7 @@ static void fm10k_configure_rx_ring(struct fm10k_intfc *interface, ...@@ -669,7 +690,7 @@ static void fm10k_configure_rx_ring(struct fm10k_intfc *interface,
/* store tail pointer */ /* store tail pointer */
ring->tail = &interface->uc_addr[FM10K_RDT(reg_idx)]; ring->tail = &interface->uc_addr[FM10K_RDT(reg_idx)];
/* reset ntu and ntc to place SW in sync with hardwdare */ /* reset ntu and ntc to place SW in sync with hardware */
ring->next_to_clean = 0; ring->next_to_clean = 0;
ring->next_to_use = 0; ring->next_to_use = 0;
ring->next_to_alloc = 0; ring->next_to_alloc = 0;
...@@ -859,7 +880,8 @@ static irqreturn_t fm10k_msix_mbx_vf(int __always_unused irq, void *data) ...@@ -859,7 +880,8 @@ static irqreturn_t fm10k_msix_mbx_vf(int __always_unused irq, void *data)
/* re-enable mailbox interrupt and indicate 20us delay */ /* re-enable mailbox interrupt and indicate 20us delay */
fm10k_write_reg(hw, FM10K_VFITR(FM10K_MBX_VECTOR), fm10k_write_reg(hw, FM10K_VFITR(FM10K_MBX_VECTOR),
FM10K_ITR_ENABLE | FM10K_MBX_INT_DELAY); FM10K_ITR_ENABLE | (FM10K_MBX_INT_DELAY >>
hw->mac.itr_scale));
/* service upstream mailbox */ /* service upstream mailbox */
if (fm10k_mbx_trylock(interface)) { if (fm10k_mbx_trylock(interface)) {
...@@ -1090,7 +1112,8 @@ static irqreturn_t fm10k_msix_mbx_pf(int __always_unused irq, void *data) ...@@ -1090,7 +1112,8 @@ static irqreturn_t fm10k_msix_mbx_pf(int __always_unused irq, void *data)
/* re-enable mailbox interrupt and indicate 20us delay */ /* re-enable mailbox interrupt and indicate 20us delay */
fm10k_write_reg(hw, FM10K_ITR(FM10K_MBX_VECTOR), fm10k_write_reg(hw, FM10K_ITR(FM10K_MBX_VECTOR),
FM10K_ITR_ENABLE | FM10K_MBX_INT_DELAY); FM10K_ITR_ENABLE | (FM10K_MBX_INT_DELAY >>
hw->mac.itr_scale));
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -1684,7 +1707,13 @@ static int fm10k_sw_init(struct fm10k_intfc *interface, ...@@ -1684,7 +1707,13 @@ static int fm10k_sw_init(struct fm10k_intfc *interface,
interface->last_reset = jiffies + (10 * HZ); interface->last_reset = jiffies + (10 * HZ);
/* reset and initialize the hardware so it is in a known state */ /* reset and initialize the hardware so it is in a known state */
err = hw->mac.ops.reset_hw(hw) ? : hw->mac.ops.init_hw(hw); err = hw->mac.ops.reset_hw(hw);
if (err) {
dev_err(&pdev->dev, "reset_hw failed: %d\n", err);
return err;
}
err = hw->mac.ops.init_hw(hw);
if (err) { if (err) {
dev_err(&pdev->dev, "init_hw failed: %d\n", err); dev_err(&pdev->dev, "init_hw failed: %d\n", err);
return err; return err;
...@@ -1722,13 +1751,6 @@ static int fm10k_sw_init(struct fm10k_intfc *interface, ...@@ -1722,13 +1751,6 @@ static int fm10k_sw_init(struct fm10k_intfc *interface,
pci_resource_len(pdev, 4)); pci_resource_len(pdev, 4));
hw->sw_addr = interface->sw_addr; hw->sw_addr = interface->sw_addr;
/* Only the PF can support VXLAN and NVGRE offloads */
if (hw->mac.type != fm10k_mac_pf) {
netdev->hw_enc_features = 0;
netdev->features &= ~NETIF_F_GSO_UDP_TUNNEL;
netdev->hw_features &= ~NETIF_F_GSO_UDP_TUNNEL;
}
/* initialize DCBNL interface */ /* initialize DCBNL interface */
fm10k_dcbnl_set_ops(netdev); fm10k_dcbnl_set_ops(netdev);
...@@ -1749,8 +1771,8 @@ static int fm10k_sw_init(struct fm10k_intfc *interface, ...@@ -1749,8 +1771,8 @@ static int fm10k_sw_init(struct fm10k_intfc *interface,
interface->rx_ring_count = FM10K_DEFAULT_RXD; interface->rx_ring_count = FM10K_DEFAULT_RXD;
/* set default interrupt moderation */ /* set default interrupt moderation */
interface->tx_itr = FM10K_ITR_10K; interface->tx_itr = FM10K_TX_ITR_DEFAULT;
interface->rx_itr = FM10K_ITR_ADAPTIVE | FM10K_ITR_20K; interface->rx_itr = FM10K_ITR_ADAPTIVE | FM10K_RX_ITR_DEFAULT;
/* initialize vxlan_port list */ /* initialize vxlan_port list */
INIT_LIST_HEAD(&interface->vxlan_port); INIT_LIST_HEAD(&interface->vxlan_port);
...@@ -1894,7 +1916,7 @@ static int fm10k_probe(struct pci_dev *pdev, ...@@ -1894,7 +1916,7 @@ static int fm10k_probe(struct pci_dev *pdev,
pci_set_master(pdev); pci_set_master(pdev);
pci_save_state(pdev); pci_save_state(pdev);
netdev = fm10k_alloc_netdev(); netdev = fm10k_alloc_netdev(fm10k_info_tbl[ent->driver_data]);
if (!netdev) { if (!netdev) {
err = -ENOMEM; err = -ENOMEM;
goto err_alloc_netdev; goto err_alloc_netdev;
...@@ -2071,8 +2093,10 @@ static int fm10k_resume(struct pci_dev *pdev) ...@@ -2071,8 +2093,10 @@ static int fm10k_resume(struct pci_dev *pdev)
/* reset hardware to known state */ /* reset hardware to known state */
err = hw->mac.ops.init_hw(&interface->hw); err = hw->mac.ops.init_hw(&interface->hw);
if (err) if (err) {
dev_err(&pdev->dev, "init_hw failed: %d\n", err);
return err; return err;
}
/* reset statistics starting values */ /* reset statistics starting values */
hw->mac.ops.rebind_hw_stats(hw, &interface->stats); hw->mac.ops.rebind_hw_stats(hw, &interface->stats);
...@@ -2185,6 +2209,9 @@ static pci_ers_result_t fm10k_io_error_detected(struct pci_dev *pdev, ...@@ -2185,6 +2209,9 @@ static pci_ers_result_t fm10k_io_error_detected(struct pci_dev *pdev,
if (netif_running(netdev)) if (netif_running(netdev))
fm10k_close(netdev); fm10k_close(netdev);
/* free interrupts */
fm10k_clear_queueing_scheme(interface);
fm10k_mbx_free_irq(interface); fm10k_mbx_free_irq(interface);
pci_disable_device(pdev); pci_disable_device(pdev);
...@@ -2248,11 +2275,21 @@ static void fm10k_io_resume(struct pci_dev *pdev) ...@@ -2248,11 +2275,21 @@ static void fm10k_io_resume(struct pci_dev *pdev)
int err = 0; int err = 0;
/* reset hardware to known state */ /* reset hardware to known state */
hw->mac.ops.init_hw(&interface->hw); err = hw->mac.ops.init_hw(&interface->hw);
if (err) {
dev_err(&pdev->dev, "init_hw failed: %d\n", err);
return;
}
/* reset statistics starting values */ /* reset statistics starting values */
hw->mac.ops.rebind_hw_stats(hw, &interface->stats); hw->mac.ops.rebind_hw_stats(hw, &interface->stats);
err = fm10k_init_queueing_scheme(interface);
if (err) {
dev_err(&interface->pdev->dev, "init_queueing_scheme failed: %d\n", err);
return;
}
/* reassociate interrupts */ /* reassociate interrupts */
fm10k_mbx_request_irq(interface); fm10k_mbx_request_irq(interface);
......
/* Intel Ethernet Switch Host Interface Driver /* Intel Ethernet Switch Host Interface Driver
* Copyright(c) 2013 - 2014 Intel Corporation. * Copyright(c) 2013 - 2015 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,
...@@ -150,19 +150,26 @@ static s32 fm10k_init_hw_pf(struct fm10k_hw *hw) ...@@ -150,19 +150,26 @@ static s32 fm10k_init_hw_pf(struct fm10k_hw *hw)
FM10K_TPH_RXCTRL_HDR_WROEN); FM10K_TPH_RXCTRL_HDR_WROEN);
} }
/* set max hold interval to align with 1.024 usec in all modes */ /* set max hold interval to align with 1.024 usec in all modes and
* store ITR scale
*/
switch (hw->bus.speed) { switch (hw->bus.speed) {
case fm10k_bus_speed_2500: case fm10k_bus_speed_2500:
dma_ctrl = FM10K_DMA_CTRL_MAX_HOLD_1US_GEN1; dma_ctrl = FM10K_DMA_CTRL_MAX_HOLD_1US_GEN1;
hw->mac.itr_scale = FM10K_TDLEN_ITR_SCALE_GEN1;
break; break;
case fm10k_bus_speed_5000: case fm10k_bus_speed_5000:
dma_ctrl = FM10K_DMA_CTRL_MAX_HOLD_1US_GEN2; dma_ctrl = FM10K_DMA_CTRL_MAX_HOLD_1US_GEN2;
hw->mac.itr_scale = FM10K_TDLEN_ITR_SCALE_GEN2;
break; break;
case fm10k_bus_speed_8000: case fm10k_bus_speed_8000:
dma_ctrl = FM10K_DMA_CTRL_MAX_HOLD_1US_GEN3; dma_ctrl = FM10K_DMA_CTRL_MAX_HOLD_1US_GEN3;
hw->mac.itr_scale = FM10K_TDLEN_ITR_SCALE_GEN3;
break; break;
default: default:
dma_ctrl = 0; dma_ctrl = 0;
/* just in case, assume Gen3 ITR scale */
hw->mac.itr_scale = FM10K_TDLEN_ITR_SCALE_GEN3;
break; break;
} }
...@@ -334,8 +341,8 @@ static s32 fm10k_update_xc_addr_pf(struct fm10k_hw *hw, u16 glort, ...@@ -334,8 +341,8 @@ static s32 fm10k_update_xc_addr_pf(struct fm10k_hw *hw, u16 glort,
((u32)mac[3] << 16) | ((u32)mac[3] << 16) |
((u32)mac[4] << 8) | ((u32)mac[4] << 8) |
((u32)mac[5])); ((u32)mac[5]));
mac_update.mac_upper = cpu_to_le16(((u32)mac[0] << 8) | mac_update.mac_upper = cpu_to_le16(((u16)mac[0] << 8) |
((u32)mac[1])); ((u16)mac[1]));
mac_update.vlan = cpu_to_le16(vid); mac_update.vlan = cpu_to_le16(vid);
mac_update.glort = cpu_to_le16(glort); mac_update.glort = cpu_to_le16(glort);
mac_update.action = add ? 0 : 1; mac_update.action = add ? 0 : 1;
...@@ -903,6 +910,13 @@ static s32 fm10k_iov_assign_default_mac_vlan_pf(struct fm10k_hw *hw, ...@@ -903,6 +910,13 @@ static s32 fm10k_iov_assign_default_mac_vlan_pf(struct fm10k_hw *hw,
fm10k_write_reg(hw, FM10K_TDBAL(vf_q_idx), tdbal); fm10k_write_reg(hw, FM10K_TDBAL(vf_q_idx), tdbal);
fm10k_write_reg(hw, FM10K_TDBAH(vf_q_idx), tdbah); fm10k_write_reg(hw, FM10K_TDBAH(vf_q_idx), tdbah);
/* Provide the VF the ITR scale, using software-defined fields in TDLEN
* to pass the information during VF initialization. See definition of
* FM10K_TDLEN_ITR_SCALE_SHIFT for more details.
*/
fm10k_write_reg(hw, FM10K_TDLEN(vf_q_idx), hw->mac.itr_scale <<
FM10K_TDLEN_ITR_SCALE_SHIFT);
err_out: err_out:
/* configure Queue control register */ /* configure Queue control register */
txqctl = ((u32)vf_vid << FM10K_TXQCTL_VID_SHIFT) & txqctl = ((u32)vf_vid << FM10K_TXQCTL_VID_SHIFT) &
...@@ -1035,6 +1049,12 @@ static s32 fm10k_iov_reset_resources_pf(struct fm10k_hw *hw, ...@@ -1035,6 +1049,12 @@ static s32 fm10k_iov_reset_resources_pf(struct fm10k_hw *hw,
for (i = queues_per_pool; i--;) { for (i = queues_per_pool; i--;) {
fm10k_write_reg(hw, FM10K_TDBAL(vf_q_idx + i), tdbal); fm10k_write_reg(hw, FM10K_TDBAL(vf_q_idx + i), tdbal);
fm10k_write_reg(hw, FM10K_TDBAH(vf_q_idx + i), tdbah); fm10k_write_reg(hw, FM10K_TDBAH(vf_q_idx + i), tdbah);
/* See definition of FM10K_TDLEN_ITR_SCALE_SHIFT for an
* explanation of how TDLEN is used.
*/
fm10k_write_reg(hw, FM10K_TDLEN(vf_q_idx + i),
hw->mac.itr_scale <<
FM10K_TDLEN_ITR_SCALE_SHIFT);
fm10k_write_reg(hw, FM10K_TQMAP(qmap_idx + i), vf_q_idx + i); fm10k_write_reg(hw, FM10K_TQMAP(qmap_idx + i), vf_q_idx + i);
fm10k_write_reg(hw, FM10K_RQMAP(qmap_idx + i), vf_q_idx + i); fm10k_write_reg(hw, FM10K_RQMAP(qmap_idx + i), vf_q_idx + i);
} }
...@@ -1212,7 +1232,7 @@ s32 fm10k_iov_msg_mac_vlan_pf(struct fm10k_hw *hw, u32 **results, ...@@ -1212,7 +1232,7 @@ s32 fm10k_iov_msg_mac_vlan_pf(struct fm10k_hw *hw, u32 **results,
set = !(vid & FM10K_VLAN_CLEAR); set = !(vid & FM10K_VLAN_CLEAR);
vid &= ~FM10K_VLAN_CLEAR; vid &= ~FM10K_VLAN_CLEAR;
err = fm10k_iov_select_vid(vf_info, vid); err = fm10k_iov_select_vid(vf_info, (u16)vid);
if (err < 0) if (err < 0)
return err; return err;
else else
...@@ -1242,7 +1262,7 @@ s32 fm10k_iov_msg_mac_vlan_pf(struct fm10k_hw *hw, u32 **results, ...@@ -1242,7 +1262,7 @@ s32 fm10k_iov_msg_mac_vlan_pf(struct fm10k_hw *hw, u32 **results,
if (err < 0) if (err < 0)
return err; return err;
else else
vlan = err; vlan = (u16)err;
/* notify switch of request for new unicast address */ /* notify switch of request for new unicast address */
err = hw->mac.ops.update_uc_addr(hw, vf_info->glort, err = hw->mac.ops.update_uc_addr(hw, vf_info->glort,
...@@ -1268,7 +1288,7 @@ s32 fm10k_iov_msg_mac_vlan_pf(struct fm10k_hw *hw, u32 **results, ...@@ -1268,7 +1288,7 @@ s32 fm10k_iov_msg_mac_vlan_pf(struct fm10k_hw *hw, u32 **results,
if (err < 0) if (err < 0)
return err; return err;
else else
vlan = err; vlan = (u16)err;
/* notify switch of request for new multicast address */ /* notify switch of request for new multicast address */
err = hw->mac.ops.update_mc_addr(hw, vf_info->glort, err = hw->mac.ops.update_mc_addr(hw, vf_info->glort,
......
/* Intel Ethernet Switch Host Interface Driver /* Intel Ethernet Switch Host Interface Driver
* Copyright(c) 2013 - 2014 Intel Corporation. * Copyright(c) 2013 - 2015 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,
...@@ -272,6 +272,20 @@ struct fm10k_hw; ...@@ -272,6 +272,20 @@ struct fm10k_hw;
#define FM10K_TDBAL(_n) ((0x40 * (_n)) + 0x8000) #define FM10K_TDBAL(_n) ((0x40 * (_n)) + 0x8000)
#define FM10K_TDBAH(_n) ((0x40 * (_n)) + 0x8001) #define FM10K_TDBAH(_n) ((0x40 * (_n)) + 0x8001)
#define FM10K_TDLEN(_n) ((0x40 * (_n)) + 0x8002) #define FM10K_TDLEN(_n) ((0x40 * (_n)) + 0x8002)
/* When fist initialized, VFs need to know the Interrupt Throttle Rate (ITR)
* scale which is based on the PCIe speed but the speed information in the PCI
* configuration space may not be accurate. The PF already knows the ITR scale
* but there is no defined method to pass that information from the PF to the
* VF. This is accomplished during VF initialization by temporarily co-opting
* the yet-to-be-used TDLEN register to have the PF store the ITR shift for
* the VF to retrieve before the VF needs to use the TDLEN register for its
* intended purpose, i.e. before the Tx resources are allocated.
*/
#define FM10K_TDLEN_ITR_SCALE_SHIFT 9
#define FM10K_TDLEN_ITR_SCALE_MASK 0x00000E00
#define FM10K_TDLEN_ITR_SCALE_GEN1 2
#define FM10K_TDLEN_ITR_SCALE_GEN2 1
#define FM10K_TDLEN_ITR_SCALE_GEN3 0
#define FM10K_TPH_TXCTRL(_n) ((0x40 * (_n)) + 0x8003) #define FM10K_TPH_TXCTRL(_n) ((0x40 * (_n)) + 0x8003)
#define FM10K_TPH_TXCTRL_DESC_TPHEN 0x00000020 #define FM10K_TPH_TXCTRL_DESC_TPHEN 0x00000020
#define FM10K_TPH_TXCTRL_DESC_RROEN 0x00000200 #define FM10K_TPH_TXCTRL_DESC_RROEN 0x00000200
...@@ -560,6 +574,7 @@ struct fm10k_mac_info { ...@@ -560,6 +574,7 @@ struct fm10k_mac_info {
bool get_host_state; bool get_host_state;
bool tx_ready; bool tx_ready;
u32 dglort_map; u32 dglort_map;
u8 itr_scale;
}; };
struct fm10k_swapi_table_info { struct fm10k_swapi_table_info {
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
static s32 fm10k_stop_hw_vf(struct fm10k_hw *hw) static s32 fm10k_stop_hw_vf(struct fm10k_hw *hw)
{ {
u8 *perm_addr = hw->mac.perm_addr; u8 *perm_addr = hw->mac.perm_addr;
u32 bal = 0, bah = 0; u32 bal = 0, bah = 0, tdlen;
s32 err; s32 err;
u16 i; u16 i;
...@@ -48,6 +48,9 @@ static s32 fm10k_stop_hw_vf(struct fm10k_hw *hw) ...@@ -48,6 +48,9 @@ static s32 fm10k_stop_hw_vf(struct fm10k_hw *hw)
((u32)perm_addr[2]); ((u32)perm_addr[2]);
} }
/* restore default itr_scale for next VF initialization */
tdlen = hw->mac.itr_scale << FM10K_TDLEN_ITR_SCALE_SHIFT;
/* The queues have already been disabled so we just need to /* The queues have already been disabled so we just need to
* update their base address registers * update their base address registers
*/ */
...@@ -56,6 +59,12 @@ static s32 fm10k_stop_hw_vf(struct fm10k_hw *hw) ...@@ -56,6 +59,12 @@ static s32 fm10k_stop_hw_vf(struct fm10k_hw *hw)
fm10k_write_reg(hw, FM10K_TDBAH(i), bah); fm10k_write_reg(hw, FM10K_TDBAH(i), bah);
fm10k_write_reg(hw, FM10K_RDBAL(i), bal); fm10k_write_reg(hw, FM10K_RDBAL(i), bal);
fm10k_write_reg(hw, FM10K_RDBAH(i), bah); fm10k_write_reg(hw, FM10K_RDBAH(i), bah);
/* Restore ITR scale in software-defined mechanism in TDLEN
* for next VF initialization. See definition of
* FM10K_TDLEN_ITR_SCALE_SHIFT for more details on the use of
* TDLEN here.
*/
fm10k_write_reg(hw, FM10K_TDLEN(i), tdlen);
} }
return 0; return 0;
...@@ -105,8 +114,10 @@ static s32 fm10k_init_hw_vf(struct fm10k_hw *hw) ...@@ -105,8 +114,10 @@ static s32 fm10k_init_hw_vf(struct fm10k_hw *hw)
/* verify we have at least 1 queue */ /* verify we have at least 1 queue */
if (!~fm10k_read_reg(hw, FM10K_TXQCTL(0)) || if (!~fm10k_read_reg(hw, FM10K_TXQCTL(0)) ||
!~fm10k_read_reg(hw, FM10K_RXQCTL(0))) !~fm10k_read_reg(hw, FM10K_RXQCTL(0))) {
return FM10K_ERR_NO_RESOURCES; err = FM10K_ERR_NO_RESOURCES;
goto reset_max_queues;
}
/* determine how many queues we have */ /* determine how many queues we have */
for (i = 1; tqdloc0 && (i < FM10K_MAX_QUEUES_POOL); i++) { for (i = 1; tqdloc0 && (i < FM10K_MAX_QUEUES_POOL); i++) {
...@@ -124,16 +135,28 @@ static s32 fm10k_init_hw_vf(struct fm10k_hw *hw) ...@@ -124,16 +135,28 @@ static s32 fm10k_init_hw_vf(struct fm10k_hw *hw)
/* shut down queues we own and reset DMA configuration */ /* shut down queues we own and reset DMA configuration */
err = fm10k_disable_queues_generic(hw, i); err = fm10k_disable_queues_generic(hw, i);
if (err) if (err)
return err; goto reset_max_queues;
/* record maximum queue count */ /* record maximum queue count */
hw->mac.max_queues = i; hw->mac.max_queues = i;
/* fetch default VLAN */ /* fetch default VLAN and ITR scale */
hw->mac.default_vid = (fm10k_read_reg(hw, FM10K_TXQCTL(0)) & hw->mac.default_vid = (fm10k_read_reg(hw, FM10K_TXQCTL(0)) &
FM10K_TXQCTL_VID_MASK) >> FM10K_TXQCTL_VID_SHIFT; FM10K_TXQCTL_VID_MASK) >> FM10K_TXQCTL_VID_SHIFT;
/* Read the ITR scale from TDLEN. See the definition of
* FM10K_TDLEN_ITR_SCALE_SHIFT for more information about how TDLEN is
* used here.
*/
hw->mac.itr_scale = (fm10k_read_reg(hw, FM10K_TDLEN(0)) &
FM10K_TDLEN_ITR_SCALE_MASK) >>
FM10K_TDLEN_ITR_SCALE_SHIFT;
return 0; return 0;
reset_max_queues:
hw->mac.max_queues = 0;
return err;
} }
/* This structure defines the attibutes to be parsed below */ /* This structure defines the attibutes to be parsed below */
......
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