Skip to content

Commit

Permalink
Merge branch '40GbE' of git://git.kernel.org/pub/scm/linux/kernel/git…
Browse files Browse the repository at this point in the history
…/jkirsher/next-queue

Jeff Kirsher says:

====================
40GbE Intel Wired LAN Driver Updates 2016-04-05

This series contains updates to i40e and i40evf only.

Stefan converts dev_close() to ndo_stop() for ethtool offline self test,
since dev_close() causes IFF_UP to be cleared which will remove the
interface routes and addresses.

Alex bumps up the size of the transmit data buffer to 12K rather than 8K,
which provides a gain in throughput and a reduction in overhead for
putting together the frame.  Fixed an issue in the polling routines where
we were using bitwise operators to avoid the side effects of the
logical operators.  Then added support for bulk transmit clean for skbs.

Jesse fixed a sparse issue in the type casting in the transmit code and
fixed i40e_aq_set_phy_debug() to use i40e_status as a return code.

Catherine cleans up duplicated code.

Shannon fixed the cleaning up of the interrupt handling to clean up the
IRQs only if we actually got them set up.  Also fixed up the error
scenarios where we were trying to remove a non-existent timer or
worktask, which causes the kernel heartburn.

Mitch changes the notification of resets to the reset interrupt handler,
instead of the actual reset initiation code.  This allows the VFs to get
properly notified for all resets, including resets initiated by different
PFs on the same physical device.  Also moved the clearing of VFLR bit
after reset processing, instead of before which could lead to double
resets on VF init.  Fixed code comment to match the actual function name.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Apr 5, 2016
2 parents f1cc809 + 50f26a5 commit e43d15c
Show file tree
Hide file tree
Showing 11 changed files with 166 additions and 88 deletions.
3 changes: 1 addition & 2 deletions drivers/net/ethernet/intel/i40e/i40e.h
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,6 @@ struct i40e_fdir_filter {
#define I40E_DCB_PRIO_TYPE_STRICT 0
#define I40E_DCB_PRIO_TYPE_ETS 1
#define I40E_DCB_STRICT_PRIO_CREDITS 127
#define I40E_MAX_USER_PRIORITY 8
/* DCB per TC information data structure */
struct i40e_tc_info {
u16 qoffset; /* Queue offset from base queue */
Expand Down Expand Up @@ -811,6 +810,7 @@ int i40e_vlan_rx_kill_vid(struct net_device *netdev,
__always_unused __be16 proto, u16 vid);
#endif
int i40e_open(struct net_device *netdev);
int i40e_close(struct net_device *netdev);
int i40e_vsi_open(struct i40e_vsi *vsi);
void i40e_vlan_stripping_disable(struct i40e_vsi *vsi);
int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid);
Expand All @@ -823,7 +823,6 @@ bool i40e_is_vsi_in_vlan(struct i40e_vsi *vsi);
struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, u8 *macaddr,
bool is_vf, bool is_netdev);
#ifdef I40E_FCOE
int i40e_close(struct net_device *netdev);
int __i40e_setup_tc(struct net_device *netdev, u32 handle, __be16 proto,
struct tc_to_netdev *tc);
void i40e_netpoll(struct net_device *netdev);
Expand Down
12 changes: 9 additions & 3 deletions drivers/net/ethernet/intel/i40e/i40e_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -1901,13 +1901,13 @@ i40e_status i40e_aq_set_phy_int_mask(struct i40e_hw *hw,
*
* Reset the external PHY.
**/
enum i40e_status_code i40e_aq_set_phy_debug(struct i40e_hw *hw, u8 cmd_flags,
struct i40e_asq_cmd_details *cmd_details)
i40e_status i40e_aq_set_phy_debug(struct i40e_hw *hw, u8 cmd_flags,
struct i40e_asq_cmd_details *cmd_details)
{
struct i40e_aq_desc desc;
struct i40e_aqc_set_phy_debug *cmd =
(struct i40e_aqc_set_phy_debug *)&desc.params.raw;
enum i40e_status_code status;
i40e_status status;

i40e_fill_default_direct_cmd_desc(&desc,
i40e_aqc_opc_set_phy_debug);
Expand Down Expand Up @@ -2157,6 +2157,9 @@ i40e_status i40e_aq_update_vsi_params(struct i40e_hw *hw,
struct i40e_aq_desc desc;
struct i40e_aqc_add_get_update_vsi *cmd =
(struct i40e_aqc_add_get_update_vsi *)&desc.params.raw;
struct i40e_aqc_add_get_update_vsi_completion *resp =
(struct i40e_aqc_add_get_update_vsi_completion *)
&desc.params.raw;
i40e_status status;

i40e_fill_default_direct_cmd_desc(&desc,
Expand All @@ -2168,6 +2171,9 @@ i40e_status i40e_aq_update_vsi_params(struct i40e_hw *hw,
status = i40e_asq_send_command(hw, &desc, &vsi_ctx->info,
sizeof(vsi_ctx->info), cmd_details);

vsi_ctx->vsis_allocated = le16_to_cpu(resp->vsi_used);
vsi_ctx->vsis_unallocated = le16_to_cpu(resp->vsi_free);

return status;
}

Expand Down
4 changes: 2 additions & 2 deletions drivers/net/ethernet/intel/i40e/i40e_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -1714,7 +1714,7 @@ static void i40e_diag_test(struct net_device *netdev,
/* If the device is online then take it offline */
if (if_running)
/* indicate we're in test mode */
dev_close(netdev);
i40e_close(netdev);
else
/* This reset does not affect link - if it is
* changed to a type of reset that does affect
Expand Down Expand Up @@ -1743,7 +1743,7 @@ static void i40e_diag_test(struct net_device *netdev,
i40e_do_reset(pf, BIT(__I40E_PF_RESET_REQUESTED));

if (if_running)
dev_open(netdev);
i40e_open(netdev);
} else {
/* Online tests */
netif_info(pf, drv, netdev, "online testing starting\n");
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/intel/i40e/i40e_fcoe.c
Original file line number Diff line number Diff line change
Expand Up @@ -1371,7 +1371,7 @@ static netdev_tx_t i40e_fcoe_xmit_frame(struct sk_buff *skb,
if (i40e_chk_linearize(skb, count)) {
if (__skb_linearize(skb))
goto out_drop;
count = TXD_USE_COUNT(skb->len);
count = i40e_txd_use_count(skb->len);
tx_ring->tx_stats.tx_linearize++;
}

Expand Down
35 changes: 16 additions & 19 deletions drivers/net/ethernet/intel/i40e/i40e_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ static const char i40e_driver_string[] =
#define DRV_KERN "-k"

#define DRV_VERSION_MAJOR 1
#define DRV_VERSION_MINOR 4
#define DRV_VERSION_BUILD 25
#define DRV_VERSION_MINOR 5
#define DRV_VERSION_BUILD 1
#define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \
__stringify(DRV_VERSION_MINOR) "." \
__stringify(DRV_VERSION_BUILD) DRV_KERN
Expand Down Expand Up @@ -4164,7 +4164,7 @@ static void i40e_clear_interrupt_scheme(struct i40e_pf *pf)
int i;

i40e_stop_misc_vector(pf);
if (pf->flags & I40E_FLAG_MSIX_ENABLED) {
if (pf->flags & I40E_FLAG_MSIX_ENABLED && pf->msix_entries) {
synchronize_irq(pf->msix_entries[0].vector);
free_irq(pf->msix_entries[0].vector, pf);
}
Expand Down Expand Up @@ -5509,11 +5509,7 @@ static void i40e_fdir_filter_exit(struct i40e_pf *pf)
*
* Returns 0, this is not allowed to fail
**/
#ifdef I40E_FCOE
int i40e_close(struct net_device *netdev)
#else
static int i40e_close(struct net_device *netdev)
#endif
{
struct i40e_netdev_priv *np = netdev_priv(netdev);
struct i40e_vsi *vsi = np->vsi;
Expand All @@ -5538,8 +5534,6 @@ void i40e_do_reset(struct i40e_pf *pf, u32 reset_flags)

WARN_ON(in_interrupt());

if (i40e_check_asq_alive(&pf->hw))
i40e_vc_notify_reset(pf);

/* do the biggest reset indicated */
if (reset_flags & BIT_ULL(__I40E_GLOBAL_RESET_REQUESTED)) {
Expand Down Expand Up @@ -6377,7 +6371,7 @@ static void i40e_clean_adminq_subtask(struct i40e_pf *pf)
break;
default:
dev_info(&pf->pdev->dev,
"ARQ Error: Unknown event 0x%04x received\n",
"ARQ: Unknown event 0x%04x ignored\n",
opcode);
break;
}
Expand Down Expand Up @@ -6742,6 +6736,8 @@ static void 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;
if (i40e_check_asq_alive(&pf->hw))
i40e_vc_notify_reset(pf);

dev_dbg(&pf->pdev->dev, "Tearing down internal switch for reset\n");

Expand Down Expand Up @@ -10826,6 +10822,12 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
hw->bus.func = PCI_FUNC(pdev->devfn);
pf->instance = pfs_found;

/* set up the locks for the AQ, do this only once in probe
* and destroy them only once in remove
*/
mutex_init(&hw->aq.asq_mutex);
mutex_init(&hw->aq.arq_mutex);

if (debug != -1) {
pf->msg_enable = pf->hw.debug_mask;
pf->msg_enable = debug;
Expand Down Expand Up @@ -10871,12 +10873,6 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/* set up a default setting for link flow control */
pf->hw.fc.requested_mode = I40E_FC_NONE;

/* set up the locks for the AQ, do this only once in probe
* and destroy them only once in remove
*/
mutex_init(&hw->aq.asq_mutex);
mutex_init(&hw->aq.arq_mutex);

err = i40e_init_adminq(hw);
if (err) {
if (err == I40E_ERR_FIRMWARE_API_VERSION)
Expand Down Expand Up @@ -11269,7 +11265,6 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
kfree(pf->qp_pile);
err_sw_init:
err_adminq_setup:
(void)i40e_shutdown_adminq(hw);
err_pf_reset:
iounmap(hw->hw_addr);
err_ioremap:
Expand Down Expand Up @@ -11311,8 +11306,10 @@ static void i40e_remove(struct pci_dev *pdev)
/* no more scheduling of any task */
set_bit(__I40E_SUSPENDED, &pf->state);
set_bit(__I40E_DOWN, &pf->state);
del_timer_sync(&pf->service_timer);
cancel_work_sync(&pf->service_task);
if (pf->service_timer.data)
del_timer_sync(&pf->service_timer);
if (pf->service_task.func)
cancel_work_sync(&pf->service_task);

if (pf->flags & I40E_FLAG_SRIOV_ENABLED) {
i40e_free_vfs(pf);
Expand Down
49 changes: 30 additions & 19 deletions drivers/net/ethernet/intel/i40e/i40e_txrx.c
Original file line number Diff line number Diff line change
Expand Up @@ -636,19 +636,21 @@ u32 i40e_get_tx_pending(struct i40e_ring *ring, bool in_sw)

/**
* i40e_clean_tx_irq - Reclaim resources after transmit completes
* @tx_ring: tx ring to clean
* @budget: how many cleans we're allowed
* @vsi: the VSI we care about
* @tx_ring: Tx ring to clean
* @napi_budget: Used to determine if we are in netpoll
*
* Returns true if there's any budget left (e.g. the clean is finished)
**/
static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget)
static bool i40e_clean_tx_irq(struct i40e_vsi *vsi,
struct i40e_ring *tx_ring, int napi_budget)
{
u16 i = tx_ring->next_to_clean;
struct i40e_tx_buffer *tx_buf;
struct i40e_tx_desc *tx_head;
struct i40e_tx_desc *tx_desc;
unsigned int total_packets = 0;
unsigned int total_bytes = 0;
unsigned int total_bytes = 0, total_packets = 0;
unsigned int budget = vsi->work_limit;

tx_buf = &tx_ring->tx_bi[i];
tx_desc = I40E_TX_DESC(tx_ring, i);
Expand Down Expand Up @@ -678,7 +680,7 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget)
total_packets += tx_buf->gso_segs;

/* free the skb */
dev_consume_skb_any(tx_buf->skb);
napi_consume_skb(tx_buf->skb, napi_budget);

/* unmap skb header data */
dma_unmap_single(tx_ring->dev,
Expand Down Expand Up @@ -749,7 +751,7 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget)

if (budget &&
((j / (WB_STRIDE + 1)) == 0) && (j != 0) &&
!test_bit(__I40E_DOWN, &tx_ring->vsi->state) &&
!test_bit(__I40E_DOWN, &vsi->state) &&
(I40E_DESC_UNUSED(tx_ring) != tx_ring->count))
tx_ring->arm_wb = true;
}
Expand All @@ -767,7 +769,7 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget)
smp_mb();
if (__netif_subqueue_stopped(tx_ring->netdev,
tx_ring->queue_index) &&
!test_bit(__I40E_DOWN, &tx_ring->vsi->state)) {
!test_bit(__I40E_DOWN, &vsi->state)) {
netif_wake_subqueue(tx_ring->netdev,
tx_ring->queue_index);
++tx_ring->tx_stats.restart_queue;
Expand Down Expand Up @@ -1975,9 +1977,11 @@ int i40e_napi_poll(struct napi_struct *napi, int budget)
* budget and be more aggressive about cleaning up the Tx descriptors.
*/
i40e_for_each_ring(ring, q_vector->tx) {
clean_complete = clean_complete &&
i40e_clean_tx_irq(ring, vsi->work_limit);
arm_wb = arm_wb || ring->arm_wb;
if (!i40e_clean_tx_irq(vsi, ring, budget)) {
clean_complete = false;
continue;
}
arm_wb |= ring->arm_wb;
ring->arm_wb = false;
}

Expand All @@ -1999,8 +2003,9 @@ int i40e_napi_poll(struct napi_struct *napi, int budget)
cleaned = i40e_clean_rx_irq_1buf(ring, budget_per_ring);

work_done += cleaned;
/* if we didn't clean as many as budgeted, we must be done */
clean_complete = clean_complete && (budget_per_ring > cleaned);
/* if we clean as many as budgeted, we must not be done */
if (cleaned >= budget_per_ring)
clean_complete = false;
}

/* If work not completed, return budget and polling will return */
Expand Down Expand Up @@ -2300,7 +2305,8 @@ static int i40e_tso(struct i40e_ring *tx_ring, struct sk_buff *skb,

/* remove payload length from outer checksum */
paylen = (__force u16)l4.udp->check;
paylen += ntohs(1) * (u16)~(skb->len - l4_offset);
paylen += ntohs((__force __be16)1) *
(u16)~(skb->len - l4_offset);
l4.udp->check = ~csum_fold((__force __wsum)paylen);
}

Expand All @@ -2322,7 +2328,7 @@ static int i40e_tso(struct i40e_ring *tx_ring, struct sk_buff *skb,

/* remove payload length from inner checksum */
paylen = (__force u16)l4.tcp->check;
paylen += ntohs(1) * (u16)~(skb->len - l4_offset);
paylen += ntohs((__force __be16)1) * (u16)~(skb->len - l4_offset);
l4.tcp->check = ~csum_fold((__force __wsum)paylen);

/* compute length of segmentation header */
Expand Down Expand Up @@ -2717,19 +2723,23 @@ static inline void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,
tx_bi = first;

for (frag = &skb_shinfo(skb)->frags[0];; frag++) {
unsigned int max_data = I40E_MAX_DATA_PER_TXD_ALIGNED;

if (dma_mapping_error(tx_ring->dev, dma))
goto dma_error;

/* record length, and DMA address */
dma_unmap_len_set(tx_bi, len, size);
dma_unmap_addr_set(tx_bi, dma, dma);

/* align size to end of page */
max_data += -dma & (I40E_MAX_READ_REQ_SIZE - 1);
tx_desc->buffer_addr = cpu_to_le64(dma);

while (unlikely(size > I40E_MAX_DATA_PER_TXD)) {
tx_desc->cmd_type_offset_bsz =
build_ctob(td_cmd, td_offset,
I40E_MAX_DATA_PER_TXD, td_tag);
max_data, td_tag);

tx_desc++;
i++;
Expand All @@ -2740,9 +2750,10 @@ static inline void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,
i = 0;
}

dma += I40E_MAX_DATA_PER_TXD;
size -= I40E_MAX_DATA_PER_TXD;
dma += max_data;
size -= max_data;

max_data = I40E_MAX_DATA_PER_TXD_ALIGNED;
tx_desc->buffer_addr = cpu_to_le64(dma);
}

Expand Down Expand Up @@ -2892,7 +2903,7 @@ static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb,
if (i40e_chk_linearize(skb, count)) {
if (__skb_linearize(skb))
goto out_drop;
count = TXD_USE_COUNT(skb->len);
count = i40e_txd_use_count(skb->len);
tx_ring->tx_stats.tx_linearize++;
}

Expand Down
35 changes: 32 additions & 3 deletions drivers/net/ethernet/intel/i40e/i40e_txrx.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,10 +146,39 @@ enum i40e_dyn_idx_t {

#define I40E_MAX_BUFFER_TXD 8
#define I40E_MIN_TX_LEN 17
#define I40E_MAX_DATA_PER_TXD 8192

/* The size limit for a transmit buffer in a descriptor is (16K - 1).
* In order to align with the read requests we will align the value to
* the nearest 4K which represents our maximum read request size.
*/
#define I40E_MAX_READ_REQ_SIZE 4096
#define I40E_MAX_DATA_PER_TXD (16 * 1024 - 1)
#define I40E_MAX_DATA_PER_TXD_ALIGNED \
(I40E_MAX_DATA_PER_TXD & ~(I40E_MAX_READ_REQ_SIZE - 1))

/* This ugly bit of math is equivalent to DIV_ROUNDUP(size, X) where X is
* the value I40E_MAX_DATA_PER_TXD_ALIGNED. It is needed due to the fact
* that 12K is not a power of 2 and division is expensive. It is used to
* approximate the number of descriptors used per linear buffer. Note
* that this will overestimate in some cases as it doesn't account for the
* fact that we will add up to 4K - 1 in aligning the 12K buffer, however
* the error should not impact things much as large buffers usually mean
* we will use fewer descriptors then there are frags in an skb.
*/
static inline unsigned int i40e_txd_use_count(unsigned int size)
{
const unsigned int max = I40E_MAX_DATA_PER_TXD_ALIGNED;
const unsigned int reciprocal = ((1ull << 32) - 1 + (max / 2)) / max;
unsigned int adjust = ~(u32)0;

/* if we rounded up on the reciprocal pull down the adjustment */
if ((max * reciprocal) > adjust)
adjust = ~(u32)(reciprocal - 1);

return (u32)((((u64)size * reciprocal) + adjust) >> 32);
}

/* Tx Descriptors needed, worst case */
#define TXD_USE_COUNT(S) DIV_ROUND_UP((S), I40E_MAX_DATA_PER_TXD)
#define DESC_NEEDED (MAX_SKB_FRAGS + 4)
#define I40E_MIN_DESC_PENDING 4

Expand Down Expand Up @@ -377,7 +406,7 @@ static inline int i40e_xmit_descriptor_count(struct sk_buff *skb)
int count = 0, size = skb_headlen(skb);

for (;;) {
count += TXD_USE_COUNT(size);
count += i40e_txd_use_count(size);

if (!nr_frags--)
break;
Expand Down
Loading

0 comments on commit e43d15c

Please sign in to comment.