From 8f4c5c9fb87aa113f33ddeb4028fb0de8e18311d Mon Sep 17 00:00:00 2001 From: John Fastabend Date: Thu, 16 Jan 2014 02:30:05 -0800 Subject: [PATCH 1/6] ixgbe: reinit_locked() should be called with rtnl_lock ixgbe_service_task() is calling ixgbe_reinit_locked() without the rtnl_lock being held. This is because it is being called from a worker thread and not a rtnl netlink or dcbnl path. Add rtnl_{un}lock() semantics. I found this during code review. Signed-off-by: John Fastabend Tested-by: Phil Schmitt Signed-off-by: Aaron Brown Signed-off-by: David S. Miller --- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 3ca59d21d0b2..b445ad121de1 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -6392,7 +6392,9 @@ static void ixgbe_reset_subtask(struct ixgbe_adapter *adapter) netdev_err(adapter->netdev, "Reset adapter\n"); adapter->tx_timeout_count++; + rtnl_lock(); ixgbe_reinit_locked(adapter); + rtnl_unlock(); } /** From e689e72823e73361147849c416e5da5c4bcc8ddf Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Thu, 16 Jan 2014 02:30:06 -0800 Subject: [PATCH 2/6] ixgbevf: set the disable state when ixgbevf_qv_disable is called The ixgbevf_qv_disable function used by CONFIG_NET_RX_BUSY_POLL is broken, because it does not properly set the IXGBEVF_QV_STATE_DISABLED bit, indicating that the q_vector should be disabled (and preventing future locks from obtaining the vector). This patch corrects the issue by setting the disable state. Signed-off-by: Jacob Keller Tested-by: Phil Schmitt Signed-off-by: Aaron Brown Signed-off-by: David S. Miller --- drivers/net/ethernet/intel/ixgbevf/ixgbevf.h | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h index bb76e96f8278..d7cec1d59821 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h @@ -260,6 +260,7 @@ static inline bool ixgbevf_qv_disable(struct ixgbevf_q_vector *q_vector) spin_lock_bh(&q_vector->lock); if (q_vector->state & IXGBEVF_QV_OWNED) rc = false; + q_vector->state |= IXGBEVF_QV_STATE_DISABLED; spin_unlock_bh(&q_vector->lock); return rc; } From 27ae296716e527e5e5f0b54bc92739a2864d2b9a Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Thu, 16 Jan 2014 02:30:07 -0800 Subject: [PATCH 3/6] ixgbevf: use pci drvdata correctly in ixgbevf_suspend() We had set the pci driver-specific data in ixgbevf_probe() as a type of struct net_device, so we should use it as netdev in ixgbevf_suspend(). Signed-off-by: Wei Yongjun Tested-by: Phil Schmitt Signed-off-by: Aaron Brown Signed-off-by: David S. Miller --- drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c index a5d31674ff42..74af295ae019 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c @@ -3222,8 +3222,8 @@ static int ixgbevf_suspend(struct pci_dev *pdev, pm_message_t state) #ifdef CONFIG_PM static int ixgbevf_resume(struct pci_dev *pdev) { - struct ixgbevf_adapter *adapter = pci_get_drvdata(pdev); - struct net_device *netdev = adapter->netdev; + struct net_device *netdev = pci_get_drvdata(pdev); + struct ixgbevf_adapter *adapter = netdev_priv(netdev); u32 err; pci_set_power_state(pdev, PCI_D0); From 87e70ab9088fc81e02bffa30e71eb1a18891608b Mon Sep 17 00:00:00 2001 From: Don Skidmore Date: Thu, 16 Jan 2014 02:30:08 -0800 Subject: [PATCH 4/6] ixgbevf: Convert ring storage form pointer to an array to array of pointers This will change how we store rings arrays in the adapter sturct. We use to have a pointer to an array now we will be using an array of pointers. This will allow us to support multiple queues on muliple nodes at some point we would be able to reallocate the rings so that each is on a local node if needed. Signed-off-by: Alexander Duyck Signed-off-by: Don Skidmore Tested-by: Phil Schmitt Signed-off-by: Aaron Brown Signed-off-by: David S. Miller --- drivers/net/ethernet/intel/ixgbevf/ethtool.c | 30 ++-- drivers/net/ethernet/intel/ixgbevf/ixgbevf.h | 4 +- .../net/ethernet/intel/ixgbevf/ixgbevf_main.c | 150 ++++++++++-------- 3 files changed, 98 insertions(+), 86 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgbevf/ethtool.c b/drivers/net/ethernet/intel/ixgbevf/ethtool.c index 54d9acef9c4e..515ba4e29760 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ethtool.c +++ b/drivers/net/ethernet/intel/ixgbevf/ethtool.c @@ -286,9 +286,9 @@ static int ixgbevf_set_ringparam(struct net_device *netdev, if (!netif_running(adapter->netdev)) { for (i = 0; i < adapter->num_tx_queues; i++) - adapter->tx_ring[i].count = new_tx_count; + adapter->tx_ring[i]->count = new_tx_count; for (i = 0; i < adapter->num_rx_queues; i++) - adapter->rx_ring[i].count = new_rx_count; + adapter->rx_ring[i]->count = new_rx_count; adapter->tx_ring_count = new_tx_count; adapter->rx_ring_count = new_rx_count; goto clear_reset; @@ -303,7 +303,7 @@ static int ixgbevf_set_ringparam(struct net_device *netdev, for (i = 0; i < adapter->num_tx_queues; i++) { /* clone ring and setup updated count */ - tx_ring[i] = adapter->tx_ring[i]; + tx_ring[i] = *adapter->tx_ring[i]; tx_ring[i].count = new_tx_count; err = ixgbevf_setup_tx_resources(adapter, &tx_ring[i]); if (!err) @@ -329,7 +329,7 @@ static int ixgbevf_set_ringparam(struct net_device *netdev, for (i = 0; i < adapter->num_rx_queues; i++) { /* clone ring and setup updated count */ - rx_ring[i] = adapter->rx_ring[i]; + rx_ring[i] = *adapter->rx_ring[i]; rx_ring[i].count = new_rx_count; err = ixgbevf_setup_rx_resources(adapter, &rx_ring[i]); if (!err) @@ -352,9 +352,8 @@ static int ixgbevf_set_ringparam(struct net_device *netdev, /* Tx */ if (tx_ring) { for (i = 0; i < adapter->num_tx_queues; i++) { - ixgbevf_free_tx_resources(adapter, - &adapter->tx_ring[i]); - adapter->tx_ring[i] = tx_ring[i]; + ixgbevf_free_tx_resources(adapter, adapter->tx_ring[i]); + *adapter->tx_ring[i] = tx_ring[i]; } adapter->tx_ring_count = new_tx_count; @@ -365,9 +364,8 @@ static int ixgbevf_set_ringparam(struct net_device *netdev, /* Rx */ if (rx_ring) { for (i = 0; i < adapter->num_rx_queues; i++) { - ixgbevf_free_rx_resources(adapter, - &adapter->rx_ring[i]); - adapter->rx_ring[i] = rx_ring[i]; + ixgbevf_free_rx_resources(adapter, adapter->rx_ring[i]); + *adapter->rx_ring[i] = rx_ring[i]; } adapter->rx_ring_count = new_rx_count; @@ -413,15 +411,15 @@ static void ixgbevf_get_ethtool_stats(struct net_device *netdev, tx_yields = 0, tx_cleaned = 0, tx_missed = 0; for (i = 0; i < adapter->num_rx_queues; i++) { - rx_yields += adapter->rx_ring[i].bp_yields; - rx_cleaned += adapter->rx_ring[i].bp_cleaned; - rx_yields += adapter->rx_ring[i].bp_yields; + rx_yields += adapter->rx_ring[i]->bp_yields; + rx_cleaned += adapter->rx_ring[i]->bp_cleaned; + rx_yields += adapter->rx_ring[i]->bp_yields; } for (i = 0; i < adapter->num_tx_queues; i++) { - tx_yields += adapter->tx_ring[i].bp_yields; - tx_cleaned += adapter->tx_ring[i].bp_cleaned; - tx_yields += adapter->tx_ring[i].bp_yields; + tx_yields += adapter->tx_ring[i]->bp_yields; + tx_cleaned += adapter->tx_ring[i]->bp_cleaned; + tx_yields += adapter->tx_ring[i]->bp_yields; } adapter->bp_rx_yields = rx_yields; diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h index d7cec1d59821..0547e40980cb 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h @@ -327,7 +327,7 @@ struct ixgbevf_adapter { u32 eims_other; /* TX */ - struct ixgbevf_ring *tx_ring; /* One per active queue */ + struct ixgbevf_ring *tx_ring[MAX_TX_QUEUES]; /* One per active queue */ int num_tx_queues; u64 restart_queue; u64 hw_csum_tx_good; @@ -337,7 +337,7 @@ struct ixgbevf_adapter { u32 tx_timeout_count; /* RX */ - struct ixgbevf_ring *rx_ring; /* One per active queue */ + struct ixgbevf_ring *rx_ring[MAX_TX_QUEUES]; /* One per active queue */ int num_rx_queues; u64 hw_csum_rx_error; u64 hw_rx_no_dma_resources; diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c index 74af295ae019..202fc47e00d2 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c @@ -848,8 +848,8 @@ static inline void map_vector_to_rxq(struct ixgbevf_adapter *a, int v_idx, { struct ixgbevf_q_vector *q_vector = a->q_vector[v_idx]; - a->rx_ring[r_idx].next = q_vector->rx.ring; - q_vector->rx.ring = &a->rx_ring[r_idx]; + a->rx_ring[r_idx]->next = q_vector->rx.ring; + q_vector->rx.ring = a->rx_ring[r_idx]; q_vector->rx.count++; } @@ -858,8 +858,8 @@ static inline void map_vector_to_txq(struct ixgbevf_adapter *a, int v_idx, { struct ixgbevf_q_vector *q_vector = a->q_vector[v_idx]; - a->tx_ring[t_idx].next = q_vector->tx.ring; - q_vector->tx.ring = &a->tx_ring[t_idx]; + a->tx_ring[t_idx]->next = q_vector->tx.ring; + q_vector->tx.ring = a->tx_ring[t_idx]; q_vector->tx.count++; } @@ -1100,7 +1100,7 @@ static void ixgbevf_configure_tx(struct ixgbevf_adapter *adapter) /* Setup the HW Tx Head and Tail descriptor pointers */ for (i = 0; i < adapter->num_tx_queues; i++) { - struct ixgbevf_ring *ring = &adapter->tx_ring[i]; + struct ixgbevf_ring *ring = adapter->tx_ring[i]; j = ring->reg_idx; tdba = ring->dma; tdlen = ring->count * sizeof(union ixgbe_adv_tx_desc); @@ -1130,7 +1130,7 @@ static void ixgbevf_configure_srrctl(struct ixgbevf_adapter *adapter, int index) struct ixgbe_hw *hw = &adapter->hw; u32 srrctl; - rx_ring = &adapter->rx_ring[index]; + rx_ring = adapter->rx_ring[index]; srrctl = IXGBE_SRRCTL_DROP_EN; @@ -1188,7 +1188,7 @@ static void ixgbevf_set_rx_buffer_len(struct ixgbevf_adapter *adapter) rx_buf_len = IXGBEVF_RXBUFFER_10K; for (i = 0; i < adapter->num_rx_queues; i++) - adapter->rx_ring[i].rx_buf_len = rx_buf_len; + adapter->rx_ring[i]->rx_buf_len = rx_buf_len; } /** @@ -1212,7 +1212,7 @@ static void ixgbevf_configure_rx(struct ixgbevf_adapter *adapter) /* Setup the HW Rx Head and Tail Descriptor Pointers and * the Base and Length of the Rx Descriptor Ring */ for (i = 0; i < adapter->num_rx_queues; i++) { - struct ixgbevf_ring *ring = &adapter->rx_ring[i]; + struct ixgbevf_ring *ring = adapter->rx_ring[i]; rdba = ring->dma; j = ring->reg_idx; rdlen = ring->count * sizeof(union ixgbe_adv_rx_desc); @@ -1389,7 +1389,7 @@ static int ixgbevf_configure_dcb(struct ixgbevf_adapter *adapter) if (num_tcs > 1) { /* update default Tx ring register index */ - adapter->tx_ring[0].reg_idx = def_q; + adapter->tx_ring[0]->reg_idx = def_q; /* we need as many queues as traffic classes */ num_rx_queues = num_tcs; @@ -1421,7 +1421,7 @@ static void ixgbevf_configure(struct ixgbevf_adapter *adapter) ixgbevf_configure_tx(adapter); ixgbevf_configure_rx(adapter); for (i = 0; i < adapter->num_rx_queues; i++) { - struct ixgbevf_ring *ring = &adapter->rx_ring[i]; + struct ixgbevf_ring *ring = adapter->rx_ring[i]; ixgbevf_alloc_rx_buffers(adapter, ring, ixgbevf_desc_unused(ring)); } @@ -1429,24 +1429,23 @@ static void ixgbevf_configure(struct ixgbevf_adapter *adapter) #define IXGBEVF_MAX_RX_DESC_POLL 10 static void ixgbevf_rx_desc_queue_enable(struct ixgbevf_adapter *adapter, - int rxr) + struct ixgbevf_ring *ring) { struct ixgbe_hw *hw = &adapter->hw; int wait_loop = IXGBEVF_MAX_RX_DESC_POLL; u32 rxdctl; - int j = adapter->rx_ring[rxr].reg_idx; + u8 reg_idx = ring->reg_idx; do { usleep_range(1000, 2000); - rxdctl = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(j)); + rxdctl = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(reg_idx)); } while (--wait_loop && !(rxdctl & IXGBE_RXDCTL_ENABLE)); if (!wait_loop) hw_dbg(hw, "RXDCTL.ENABLE queue %d not set while polling\n", - rxr); + reg_idx); - ixgbevf_release_rx_desc(&adapter->rx_ring[rxr], - (adapter->rx_ring[rxr].count - 1)); + ixgbevf_release_rx_desc(ring, ring->count - 1); } static void ixgbevf_disable_rx_queue(struct ixgbevf_adapter *adapter, @@ -1541,7 +1540,7 @@ static void ixgbevf_up_complete(struct ixgbevf_adapter *adapter) u32 txdctl, rxdctl; for (i = 0; i < adapter->num_tx_queues; i++) { - j = adapter->tx_ring[i].reg_idx; + j = adapter->tx_ring[i]->reg_idx; txdctl = IXGBE_READ_REG(hw, IXGBE_VFTXDCTL(j)); /* enable WTHRESH=8 descriptors, to encourage burst writeback */ txdctl |= (8 << 16); @@ -1549,14 +1548,14 @@ static void ixgbevf_up_complete(struct ixgbevf_adapter *adapter) } for (i = 0; i < adapter->num_tx_queues; i++) { - j = adapter->tx_ring[i].reg_idx; + j = adapter->tx_ring[i]->reg_idx; txdctl = IXGBE_READ_REG(hw, IXGBE_VFTXDCTL(j)); txdctl |= IXGBE_TXDCTL_ENABLE; IXGBE_WRITE_REG(hw, IXGBE_VFTXDCTL(j), txdctl); } for (i = 0; i < num_rx_rings; i++) { - j = adapter->rx_ring[i].reg_idx; + j = adapter->rx_ring[i]->reg_idx; rxdctl = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(j)); rxdctl |= IXGBE_RXDCTL_ENABLE | IXGBE_RXDCTL_VME; if (hw->mac.type == ixgbe_mac_X540_vf) { @@ -1565,7 +1564,7 @@ static void ixgbevf_up_complete(struct ixgbevf_adapter *adapter) IXGBE_RXDCTL_RLPML_EN); } IXGBE_WRITE_REG(hw, IXGBE_VFRXDCTL(j), rxdctl); - ixgbevf_rx_desc_queue_enable(adapter, i); + ixgbevf_rx_desc_queue_enable(adapter, adapter->rx_ring[i]); } ixgbevf_configure_msix(adapter); @@ -1686,7 +1685,7 @@ static void ixgbevf_clean_all_rx_rings(struct ixgbevf_adapter *adapter) int i; for (i = 0; i < adapter->num_rx_queues; i++) - ixgbevf_clean_rx_ring(adapter, &adapter->rx_ring[i]); + ixgbevf_clean_rx_ring(adapter, adapter->rx_ring[i]); } /** @@ -1698,7 +1697,7 @@ static void ixgbevf_clean_all_tx_rings(struct ixgbevf_adapter *adapter) int i; for (i = 0; i < adapter->num_tx_queues; i++) - ixgbevf_clean_tx_ring(adapter, &adapter->tx_ring[i]); + ixgbevf_clean_tx_ring(adapter, adapter->tx_ring[i]); } void ixgbevf_down(struct ixgbevf_adapter *adapter) @@ -1713,7 +1712,7 @@ void ixgbevf_down(struct ixgbevf_adapter *adapter) /* disable all enabled rx queues */ for (i = 0; i < adapter->num_rx_queues; i++) - ixgbevf_disable_rx_queue(adapter, &adapter->rx_ring[i]); + ixgbevf_disable_rx_queue(adapter, adapter->rx_ring[i]); netif_tx_disable(netdev); @@ -1734,7 +1733,7 @@ void ixgbevf_down(struct ixgbevf_adapter *adapter) /* disable transmits in the hardware now that interrupts are off */ for (i = 0; i < adapter->num_tx_queues; i++) { - j = adapter->tx_ring[i].reg_idx; + j = adapter->tx_ring[i]->reg_idx; txdctl = IXGBE_READ_REG(hw, IXGBE_VFTXDCTL(j)); IXGBE_WRITE_REG(hw, IXGBE_VFTXDCTL(j), (txdctl & ~IXGBE_TXDCTL_ENABLE)); @@ -1875,40 +1874,50 @@ static void ixgbevf_set_num_queues(struct ixgbevf_adapter *adapter) **/ static int ixgbevf_alloc_queues(struct ixgbevf_adapter *adapter) { - int i; + struct ixgbevf_ring *ring; + int rx = 0, tx = 0; - adapter->tx_ring = kcalloc(adapter->num_tx_queues, - sizeof(struct ixgbevf_ring), GFP_KERNEL); - if (!adapter->tx_ring) - goto err_tx_ring_allocation; + for (; tx < adapter->num_tx_queues; tx++) { + ring = kzalloc(sizeof(*ring), GFP_KERNEL); + if (!ring) + goto err_allocation; - adapter->rx_ring = kcalloc(adapter->num_rx_queues, - sizeof(struct ixgbevf_ring), GFP_KERNEL); - if (!adapter->rx_ring) - goto err_rx_ring_allocation; + ring->dev = &adapter->pdev->dev; + ring->netdev = adapter->netdev; + ring->count = adapter->tx_ring_count; + ring->queue_index = tx; + ring->reg_idx = tx; - for (i = 0; i < adapter->num_tx_queues; i++) { - adapter->tx_ring[i].count = adapter->tx_ring_count; - adapter->tx_ring[i].queue_index = i; - /* reg_idx may be remapped later by DCB config */ - adapter->tx_ring[i].reg_idx = i; - adapter->tx_ring[i].dev = &adapter->pdev->dev; - adapter->tx_ring[i].netdev = adapter->netdev; + adapter->tx_ring[tx] = ring; } - for (i = 0; i < adapter->num_rx_queues; i++) { - adapter->rx_ring[i].count = adapter->rx_ring_count; - adapter->rx_ring[i].queue_index = i; - adapter->rx_ring[i].reg_idx = i; - adapter->rx_ring[i].dev = &adapter->pdev->dev; - adapter->rx_ring[i].netdev = adapter->netdev; + for (; rx < adapter->num_rx_queues; rx++) { + ring = kzalloc(sizeof(*ring), GFP_KERNEL); + if (!ring) + goto err_allocation; + + ring->dev = &adapter->pdev->dev; + ring->netdev = adapter->netdev; + + ring->count = adapter->rx_ring_count; + ring->queue_index = rx; + ring->reg_idx = rx; + + adapter->rx_ring[rx] = ring; } return 0; -err_rx_ring_allocation: - kfree(adapter->tx_ring); -err_tx_ring_allocation: +err_allocation: + while (tx) { + kfree(adapter->tx_ring[--tx]); + adapter->tx_ring[tx] = NULL; + } + + while (rx) { + kfree(adapter->rx_ring[--rx]); + adapter->rx_ring[rx] = NULL; + } return -ENOMEM; } @@ -2099,6 +2108,17 @@ err_set_interrupt: **/ static void ixgbevf_clear_interrupt_scheme(struct ixgbevf_adapter *adapter) { + int i; + + for (i = 0; i < adapter->num_tx_queues; i++) { + kfree(adapter->tx_ring[i]); + adapter->tx_ring[i] = NULL; + } + for (i = 0; i < adapter->num_rx_queues; i++) { + kfree(adapter->rx_ring[i]); + adapter->rx_ring[i] = NULL; + } + adapter->num_tx_queues = 0; adapter->num_rx_queues = 0; @@ -2229,11 +2249,11 @@ void ixgbevf_update_stats(struct ixgbevf_adapter *adapter) for (i = 0; i < adapter->num_rx_queues; i++) { adapter->hw_csum_rx_error += - adapter->rx_ring[i].hw_csum_rx_error; + adapter->rx_ring[i]->hw_csum_rx_error; adapter->hw_csum_rx_good += - adapter->rx_ring[i].hw_csum_rx_good; - adapter->rx_ring[i].hw_csum_rx_error = 0; - adapter->rx_ring[i].hw_csum_rx_good = 0; + adapter->rx_ring[i]->hw_csum_rx_good; + adapter->rx_ring[i]->hw_csum_rx_error = 0; + adapter->rx_ring[i]->hw_csum_rx_good = 0; } } @@ -2413,10 +2433,8 @@ static void ixgbevf_free_all_tx_resources(struct ixgbevf_adapter *adapter) int i; for (i = 0; i < adapter->num_tx_queues; i++) - if (adapter->tx_ring[i].desc) - ixgbevf_free_tx_resources(adapter, - &adapter->tx_ring[i]); - + if (adapter->tx_ring[i]->desc) + ixgbevf_free_tx_resources(adapter, adapter->tx_ring[i]); } /** @@ -2471,7 +2489,7 @@ static int ixgbevf_setup_all_tx_resources(struct ixgbevf_adapter *adapter) int i, err = 0; for (i = 0; i < adapter->num_tx_queues; i++) { - err = ixgbevf_setup_tx_resources(adapter, &adapter->tx_ring[i]); + err = ixgbevf_setup_tx_resources(adapter, adapter->tx_ring[i]); if (!err) continue; hw_dbg(&adapter->hw, @@ -2533,7 +2551,7 @@ static int ixgbevf_setup_all_rx_resources(struct ixgbevf_adapter *adapter) int i, err = 0; for (i = 0; i < adapter->num_rx_queues; i++) { - err = ixgbevf_setup_rx_resources(adapter, &adapter->rx_ring[i]); + err = ixgbevf_setup_rx_resources(adapter, adapter->rx_ring[i]); if (!err) continue; hw_dbg(&adapter->hw, @@ -2577,9 +2595,8 @@ static void ixgbevf_free_all_rx_resources(struct ixgbevf_adapter *adapter) int i; for (i = 0; i < adapter->num_rx_queues; i++) - if (adapter->rx_ring[i].desc) - ixgbevf_free_rx_resources(adapter, - &adapter->rx_ring[i]); + if (adapter->rx_ring[i]->desc) + ixgbevf_free_rx_resources(adapter, adapter->rx_ring[i]); } /** @@ -3069,7 +3086,7 @@ static int ixgbevf_xmit_frame(struct sk_buff *skb, struct net_device *netdev) return NETDEV_TX_OK; } - tx_ring = &adapter->tx_ring[r_idx]; + tx_ring = adapter->tx_ring[r_idx]; /* * need: 1 descriptor per page * PAGE_SIZE/IXGBE_MAX_DATA_PER_TXD, @@ -3282,7 +3299,7 @@ static struct rtnl_link_stats64 *ixgbevf_get_stats(struct net_device *netdev, stats->multicast = adapter->stats.vfmprc - adapter->stats.base_vfmprc; for (i = 0; i < adapter->num_rx_queues; i++) { - ring = &adapter->rx_ring[i]; + ring = adapter->rx_ring[i]; do { start = u64_stats_fetch_begin_bh(&ring->syncp); bytes = ring->total_bytes; @@ -3293,7 +3310,7 @@ static struct rtnl_link_stats64 *ixgbevf_get_stats(struct net_device *netdev, } for (i = 0; i < adapter->num_tx_queues; i++) { - ring = &adapter->tx_ring[i]; + ring = adapter->tx_ring[i]; do { start = u64_stats_fetch_begin_bh(&ring->syncp); bytes = ring->total_bytes; @@ -3528,9 +3545,6 @@ static void ixgbevf_remove(struct pci_dev *pdev) hw_dbg(&adapter->hw, "Remove complete\n"); - kfree(adapter->tx_ring); - kfree(adapter->rx_ring); - free_netdev(netdev); pci_disable_device(pdev); From de02decb33e176c1befc4d0f19c11a334b31f1ea Mon Sep 17 00:00:00 2001 From: Don Skidmore Date: Thu, 16 Jan 2014 02:30:09 -0800 Subject: [PATCH 5/6] ixgbevf: create function for all of ring init This patch creates new functions for ring initialization, ixgbevf_configure_tx_ring() and ixgbevf_configure_rx_ring(). The work done in these function previously was spread between several other functions and this change should hopefully lead to greater readability and make the code more like ixgbe. This patch also moves the placement of some older functions to avoid having to write prototypes. It also promotes a couple of debug messages to errors. Signed-off-by: Alexander Duyck Signed-off-by: Don Skidmore Tested-by: Phil Schmitt Signed-off-by: Aaron Brown Signed-off-by: David S. Miller --- drivers/net/ethernet/intel/ixgbevf/defines.h | 17 + .../net/ethernet/intel/ixgbevf/ixgbevf_main.c | 303 ++++++++++-------- 2 files changed, 183 insertions(+), 137 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgbevf/defines.h b/drivers/net/ethernet/intel/ixgbevf/defines.h index 3147795bd135..5426b2dee6a6 100644 --- a/drivers/net/ethernet/intel/ixgbevf/defines.h +++ b/drivers/net/ethernet/intel/ixgbevf/defines.h @@ -277,4 +277,21 @@ struct ixgbe_adv_tx_context_desc { #define IXGBE_ERR_RESET_FAILED -2 #define IXGBE_ERR_INVALID_ARGUMENT -3 +/* Transmit Config masks */ +#define IXGBE_TXDCTL_ENABLE 0x02000000 /* Ena specific Tx Queue */ +#define IXGBE_TXDCTL_SWFLSH 0x04000000 /* Tx Desc. wr-bk flushing */ +#define IXGBE_TXDCTL_WTHRESH_SHIFT 16 /* shift to WTHRESH bits */ + +#define IXGBE_DCA_RXCTRL_DESC_DCA_EN (1 << 5) /* Rx Desc enable */ +#define IXGBE_DCA_RXCTRL_HEAD_DCA_EN (1 << 6) /* Rx Desc header ena */ +#define IXGBE_DCA_RXCTRL_DATA_DCA_EN (1 << 7) /* Rx Desc payload ena */ +#define IXGBE_DCA_RXCTRL_DESC_RRO_EN (1 << 9) /* Rx rd Desc Relax Order */ +#define IXGBE_DCA_RXCTRL_DATA_WRO_EN (1 << 13) /* Rx wr data Relax Order */ +#define IXGBE_DCA_RXCTRL_HEAD_WRO_EN (1 << 15) /* Rx wr header RO */ + +#define IXGBE_DCA_TXCTRL_DESC_DCA_EN (1 << 5) /* DCA Tx Desc enable */ +#define IXGBE_DCA_TXCTRL_DESC_RRO_EN (1 << 9) /* Tx rd Desc Relax Order */ +#define IXGBE_DCA_TXCTRL_DESC_WRO_EN (1 << 11) /* Tx Desc writeback RO bit */ +#define IXGBE_DCA_TXCTRL_DATA_RRO_EN (1 << 13) /* Tx rd data Relax Order */ + #endif /* _IXGBEVF_DEFINES_H_ */ diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c index 202fc47e00d2..6cf41207a31d 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c @@ -1086,6 +1086,70 @@ static inline void ixgbevf_irq_enable(struct ixgbevf_adapter *adapter) IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, adapter->eims_enable_mask); } +/** + * ixgbevf_configure_tx_ring - Configure 82599 VF Tx ring after Reset + * @adapter: board private structure + * @ring: structure containing ring specific data + * + * Configure the Tx descriptor ring after a reset. + **/ +static void ixgbevf_configure_tx_ring(struct ixgbevf_adapter *adapter, + struct ixgbevf_ring *ring) +{ + struct ixgbe_hw *hw = &adapter->hw; + u64 tdba = ring->dma; + int wait_loop = 10; + u32 txdctl = IXGBE_TXDCTL_ENABLE; + u8 reg_idx = ring->reg_idx; + + /* disable queue to avoid issues while updating state */ + IXGBE_WRITE_REG(hw, IXGBE_VFTXDCTL(reg_idx), IXGBE_TXDCTL_SWFLSH); + IXGBE_WRITE_FLUSH(hw); + + IXGBE_WRITE_REG(hw, IXGBE_VFTDBAL(reg_idx), tdba & DMA_BIT_MASK(32)); + IXGBE_WRITE_REG(hw, IXGBE_VFTDBAH(reg_idx), tdba >> 32); + IXGBE_WRITE_REG(hw, IXGBE_VFTDLEN(reg_idx), + ring->count * sizeof(union ixgbe_adv_tx_desc)); + + /* disable head writeback */ + IXGBE_WRITE_REG(hw, IXGBE_VFTDWBAH(reg_idx), 0); + IXGBE_WRITE_REG(hw, IXGBE_VFTDWBAL(reg_idx), 0); + + /* enable relaxed ordering */ + IXGBE_WRITE_REG(hw, IXGBE_VFDCA_TXCTRL(reg_idx), + (IXGBE_DCA_TXCTRL_DESC_RRO_EN | + IXGBE_DCA_TXCTRL_DATA_RRO_EN)); + + /* reset head and tail pointers */ + IXGBE_WRITE_REG(hw, IXGBE_VFTDH(reg_idx), 0); + IXGBE_WRITE_REG(hw, IXGBE_VFTDT(reg_idx), 0); + ring->tail = hw->hw_addr + IXGBE_VFTDT(reg_idx); + + /* reset ntu and ntc to place SW in sync with hardwdare */ + ring->next_to_clean = 0; + ring->next_to_use = 0; + + /* In order to avoid issues WTHRESH + PTHRESH should always be equal + * to or less than the number of on chip descriptors, which is + * currently 40. + */ + txdctl |= (8 << 16); /* WTHRESH = 8 */ + + /* Setting PTHRESH to 32 both improves performance */ + txdctl |= (1 << 8) | /* HTHRESH = 1 */ + 32; /* PTHRESH = 32 */ + + IXGBE_WRITE_REG(hw, IXGBE_VFTXDCTL(reg_idx), txdctl); + + /* poll to verify queue is enabled */ + do { + usleep_range(1000, 2000); + txdctl = IXGBE_READ_REG(hw, IXGBE_VFTXDCTL(reg_idx)); + } while (--wait_loop && !(txdctl & IXGBE_TXDCTL_ENABLE)); + if (!wait_loop) + pr_err("Could not enable Tx Queue %d\n", reg_idx); +} + /** * ixgbevf_configure_tx - Configure 82599 VF Transmit Unit after Reset * @adapter: board private structure @@ -1094,32 +1158,11 @@ static inline void ixgbevf_irq_enable(struct ixgbevf_adapter *adapter) **/ static void ixgbevf_configure_tx(struct ixgbevf_adapter *adapter) { - u64 tdba; - struct ixgbe_hw *hw = &adapter->hw; - u32 i, j, tdlen, txctrl; + u32 i; /* Setup the HW Tx Head and Tail descriptor pointers */ - for (i = 0; i < adapter->num_tx_queues; i++) { - struct ixgbevf_ring *ring = adapter->tx_ring[i]; - j = ring->reg_idx; - tdba = ring->dma; - tdlen = ring->count * sizeof(union ixgbe_adv_tx_desc); - IXGBE_WRITE_REG(hw, IXGBE_VFTDBAL(j), - (tdba & DMA_BIT_MASK(32))); - IXGBE_WRITE_REG(hw, IXGBE_VFTDBAH(j), (tdba >> 32)); - IXGBE_WRITE_REG(hw, IXGBE_VFTDLEN(j), tdlen); - IXGBE_WRITE_REG(hw, IXGBE_VFTDH(j), 0); - IXGBE_WRITE_REG(hw, IXGBE_VFTDT(j), 0); - ring->tail = hw->hw_addr + IXGBE_VFTDT(j); - ring->next_to_clean = 0; - ring->next_to_use = 0; - /* Disable Tx Head Writeback RO bit, since this hoses - * bookkeeping if things aren't delivered in order. - */ - txctrl = IXGBE_READ_REG(hw, IXGBE_VFDCA_TXCTRL(j)); - txctrl &= ~IXGBE_DCA_TXCTRL_TX_WB_RO_EN; - IXGBE_WRITE_REG(hw, IXGBE_VFDCA_TXCTRL(j), txctrl); - } + for (i = 0; i < adapter->num_tx_queues; i++) + ixgbevf_configure_tx_ring(adapter, adapter->tx_ring[i]); } #define IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT 2 @@ -1191,6 +1234,92 @@ static void ixgbevf_set_rx_buffer_len(struct ixgbevf_adapter *adapter) adapter->rx_ring[i]->rx_buf_len = rx_buf_len; } +#define IXGBEVF_MAX_RX_DESC_POLL 10 +static void ixgbevf_disable_rx_queue(struct ixgbevf_adapter *adapter, + struct ixgbevf_ring *ring) +{ + struct ixgbe_hw *hw = &adapter->hw; + int wait_loop = IXGBEVF_MAX_RX_DESC_POLL; + u32 rxdctl; + u8 reg_idx = ring->reg_idx; + + rxdctl = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(reg_idx)); + rxdctl &= ~IXGBE_RXDCTL_ENABLE; + + /* write value back with RXDCTL.ENABLE bit cleared */ + IXGBE_WRITE_REG(hw, IXGBE_VFRXDCTL(reg_idx), rxdctl); + + /* the hardware may take up to 100us to really disable the rx queue */ + do { + udelay(10); + rxdctl = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(reg_idx)); + } while (--wait_loop && (rxdctl & IXGBE_RXDCTL_ENABLE)); + + if (!wait_loop) + pr_err("RXDCTL.ENABLE queue %d not cleared while polling\n", + reg_idx); +} + +static void ixgbevf_rx_desc_queue_enable(struct ixgbevf_adapter *adapter, + struct ixgbevf_ring *ring) +{ + struct ixgbe_hw *hw = &adapter->hw; + int wait_loop = IXGBEVF_MAX_RX_DESC_POLL; + u32 rxdctl; + u8 reg_idx = ring->reg_idx; + + do { + usleep_range(1000, 2000); + rxdctl = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(reg_idx)); + } while (--wait_loop && !(rxdctl & IXGBE_RXDCTL_ENABLE)); + + if (!wait_loop) + pr_err("RXDCTL.ENABLE queue %d not set while polling\n", + reg_idx); +} + +static void ixgbevf_configure_rx_ring(struct ixgbevf_adapter *adapter, + struct ixgbevf_ring *ring) +{ + struct ixgbe_hw *hw = &adapter->hw; + u64 rdba = ring->dma; + u32 rxdctl; + u8 reg_idx = ring->reg_idx; + + /* disable queue to avoid issues while updating state */ + rxdctl = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(reg_idx)); + ixgbevf_disable_rx_queue(adapter, ring); + + IXGBE_WRITE_REG(hw, IXGBE_VFRDBAL(reg_idx), rdba & DMA_BIT_MASK(32)); + IXGBE_WRITE_REG(hw, IXGBE_VFRDBAH(reg_idx), rdba >> 32); + IXGBE_WRITE_REG(hw, IXGBE_VFRDLEN(reg_idx), + ring->count * sizeof(union ixgbe_adv_rx_desc)); + + /* enable relaxed ordering */ + IXGBE_WRITE_REG(hw, IXGBE_VFDCA_RXCTRL(reg_idx), + IXGBE_DCA_RXCTRL_DESC_RRO_EN); + + /* reset head and tail pointers */ + IXGBE_WRITE_REG(hw, IXGBE_VFRDH(reg_idx), 0); + IXGBE_WRITE_REG(hw, IXGBE_VFRDT(reg_idx), 0); + ring->tail = hw->hw_addr + IXGBE_VFRDT(reg_idx); + + /* reset ntu and ntc to place SW in sync with hardwdare */ + ring->next_to_clean = 0; + ring->next_to_use = 0; + + ixgbevf_configure_srrctl(adapter, reg_idx); + + /* prevent DMA from exceeding buffer space available */ + rxdctl &= ~IXGBE_RXDCTL_RLPMLMASK; + rxdctl |= ring->rx_buf_len | IXGBE_RXDCTL_RLPML_EN; + rxdctl |= IXGBE_RXDCTL_ENABLE | IXGBE_RXDCTL_VME; + IXGBE_WRITE_REG(hw, IXGBE_VFRXDCTL(reg_idx), rxdctl); + + ixgbevf_rx_desc_queue_enable(adapter, ring); + ixgbevf_alloc_rx_buffers(adapter, ring, ixgbevf_desc_unused(ring)); +} + /** * ixgbevf_configure_rx - Configure 82599 VF Receive Unit after Reset * @adapter: board private structure @@ -1199,10 +1328,7 @@ static void ixgbevf_set_rx_buffer_len(struct ixgbevf_adapter *adapter) **/ static void ixgbevf_configure_rx(struct ixgbevf_adapter *adapter) { - u64 rdba; - struct ixgbe_hw *hw = &adapter->hw; - int i, j; - u32 rdlen; + int i; ixgbevf_setup_psrtype(adapter); @@ -1211,23 +1337,8 @@ static void ixgbevf_configure_rx(struct ixgbevf_adapter *adapter) /* Setup the HW Rx Head and Tail Descriptor Pointers and * the Base and Length of the Rx Descriptor Ring */ - for (i = 0; i < adapter->num_rx_queues; i++) { - struct ixgbevf_ring *ring = adapter->rx_ring[i]; - rdba = ring->dma; - j = ring->reg_idx; - rdlen = ring->count * sizeof(union ixgbe_adv_rx_desc); - IXGBE_WRITE_REG(hw, IXGBE_VFRDBAL(j), - (rdba & DMA_BIT_MASK(32))); - IXGBE_WRITE_REG(hw, IXGBE_VFRDBAH(j), (rdba >> 32)); - IXGBE_WRITE_REG(hw, IXGBE_VFRDLEN(j), rdlen); - IXGBE_WRITE_REG(hw, IXGBE_VFRDH(j), 0); - IXGBE_WRITE_REG(hw, IXGBE_VFRDT(j), 0); - ring->tail = hw->hw_addr + IXGBE_VFRDT(j); - ring->next_to_clean = 0; - ring->next_to_use = 0; - - ixgbevf_configure_srrctl(adapter, j); - } + for (i = 0; i < adapter->num_rx_queues; i++) + ixgbevf_configure_rx_ring(adapter, adapter->rx_ring[i]); } static int ixgbevf_vlan_rx_add_vid(struct net_device *netdev, @@ -1409,68 +1520,14 @@ static int ixgbevf_configure_dcb(struct ixgbevf_adapter *adapter) static void ixgbevf_configure(struct ixgbevf_adapter *adapter) { - struct net_device *netdev = adapter->netdev; - int i; - ixgbevf_configure_dcb(adapter); - ixgbevf_set_rx_mode(netdev); + ixgbevf_set_rx_mode(adapter->netdev); ixgbevf_restore_vlan(adapter); ixgbevf_configure_tx(adapter); ixgbevf_configure_rx(adapter); - for (i = 0; i < adapter->num_rx_queues; i++) { - struct ixgbevf_ring *ring = adapter->rx_ring[i]; - ixgbevf_alloc_rx_buffers(adapter, ring, - ixgbevf_desc_unused(ring)); - } -} - -#define IXGBEVF_MAX_RX_DESC_POLL 10 -static void ixgbevf_rx_desc_queue_enable(struct ixgbevf_adapter *adapter, - struct ixgbevf_ring *ring) -{ - struct ixgbe_hw *hw = &adapter->hw; - int wait_loop = IXGBEVF_MAX_RX_DESC_POLL; - u32 rxdctl; - u8 reg_idx = ring->reg_idx; - - do { - usleep_range(1000, 2000); - rxdctl = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(reg_idx)); - } while (--wait_loop && !(rxdctl & IXGBE_RXDCTL_ENABLE)); - - if (!wait_loop) - hw_dbg(hw, "RXDCTL.ENABLE queue %d not set while polling\n", - reg_idx); - - ixgbevf_release_rx_desc(ring, ring->count - 1); -} - -static void ixgbevf_disable_rx_queue(struct ixgbevf_adapter *adapter, - struct ixgbevf_ring *ring) -{ - struct ixgbe_hw *hw = &adapter->hw; - int wait_loop = IXGBEVF_MAX_RX_DESC_POLL; - u32 rxdctl; - u8 reg_idx = ring->reg_idx; - - rxdctl = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(reg_idx)); - rxdctl &= ~IXGBE_RXDCTL_ENABLE; - - /* write value back with RXDCTL.ENABLE bit cleared */ - IXGBE_WRITE_REG(hw, IXGBE_VFRXDCTL(reg_idx), rxdctl); - - /* the hardware may take up to 100us to really disable the rx queue */ - do { - udelay(10); - rxdctl = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(reg_idx)); - } while (--wait_loop && (rxdctl & IXGBE_RXDCTL_ENABLE)); - - if (!wait_loop) - hw_dbg(hw, "RXDCTL.ENABLE queue %d not cleared while polling\n", - reg_idx); } static void ixgbevf_save_reset_stats(struct ixgbevf_adapter *adapter) @@ -1535,37 +1592,6 @@ static void ixgbevf_up_complete(struct ixgbevf_adapter *adapter) { struct net_device *netdev = adapter->netdev; struct ixgbe_hw *hw = &adapter->hw; - int i, j = 0; - int num_rx_rings = adapter->num_rx_queues; - u32 txdctl, rxdctl; - - for (i = 0; i < adapter->num_tx_queues; i++) { - j = adapter->tx_ring[i]->reg_idx; - txdctl = IXGBE_READ_REG(hw, IXGBE_VFTXDCTL(j)); - /* enable WTHRESH=8 descriptors, to encourage burst writeback */ - txdctl |= (8 << 16); - IXGBE_WRITE_REG(hw, IXGBE_VFTXDCTL(j), txdctl); - } - - for (i = 0; i < adapter->num_tx_queues; i++) { - j = adapter->tx_ring[i]->reg_idx; - txdctl = IXGBE_READ_REG(hw, IXGBE_VFTXDCTL(j)); - txdctl |= IXGBE_TXDCTL_ENABLE; - IXGBE_WRITE_REG(hw, IXGBE_VFTXDCTL(j), txdctl); - } - - for (i = 0; i < num_rx_rings; i++) { - j = adapter->rx_ring[i]->reg_idx; - rxdctl = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(j)); - rxdctl |= IXGBE_RXDCTL_ENABLE | IXGBE_RXDCTL_VME; - if (hw->mac.type == ixgbe_mac_X540_vf) { - rxdctl &= ~IXGBE_RXDCTL_RLPMLMASK; - rxdctl |= ((netdev->mtu + ETH_HLEN + ETH_FCS_LEN) | - IXGBE_RXDCTL_RLPML_EN); - } - IXGBE_WRITE_REG(hw, IXGBE_VFRXDCTL(j), rxdctl); - ixgbevf_rx_desc_queue_enable(adapter, adapter->rx_ring[i]); - } ixgbevf_configure_msix(adapter); @@ -1704,8 +1730,7 @@ void ixgbevf_down(struct ixgbevf_adapter *adapter) { struct net_device *netdev = adapter->netdev; struct ixgbe_hw *hw = &adapter->hw; - u32 txdctl; - int i, j; + int i; /* signal that we are down to the interrupt handler */ set_bit(__IXGBEVF_DOWN, &adapter->state); @@ -1733,10 +1758,10 @@ void ixgbevf_down(struct ixgbevf_adapter *adapter) /* disable transmits in the hardware now that interrupts are off */ for (i = 0; i < adapter->num_tx_queues; i++) { - j = adapter->tx_ring[i]->reg_idx; - txdctl = IXGBE_READ_REG(hw, IXGBE_VFTXDCTL(j)); - IXGBE_WRITE_REG(hw, IXGBE_VFTXDCTL(j), - (txdctl & ~IXGBE_TXDCTL_ENABLE)); + u8 reg_idx = adapter->tx_ring[i]->reg_idx; + + IXGBE_WRITE_REG(hw, IXGBE_VFTXDCTL(reg_idx), + IXGBE_TXDCTL_SWFLSH); } netif_carrier_off(netdev); @@ -2416,6 +2441,10 @@ void ixgbevf_free_tx_resources(struct ixgbevf_adapter *adapter, vfree(tx_ring->tx_buffer_info); tx_ring->tx_buffer_info = NULL; + /* if not set, then don't free */ + if (!tx_ring->desc) + return; + dma_free_coherent(&pdev->dev, tx_ring->size, tx_ring->desc, tx_ring->dma); From d3cec927ef9f5783b5658e27401425fda4a2d4d9 Mon Sep 17 00:00:00 2001 From: Don Skidmore Date: Thu, 16 Jan 2014 02:30:10 -0800 Subject: [PATCH 6/6] ixgbe: Fix incorrect logic for fixed fiber eeprom write In this code we wanted to set the bit in IXGBE_SFF_SOFT_RS_SELECT_MASK to the value in rs. So we really needed a logical or rather than an and, this patch makes that change. Signed-off-by: Don Skidmore Tested-by: Phil Schmitt Signed-off-by: Aaron Brown Signed-off-by: David S. Miller --- drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c index 007a0083a636..edda6814108c 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c @@ -626,7 +626,7 @@ static void ixgbe_set_fiber_fixed_speed(struct ixgbe_hw *hw, goto out; } - eeprom_data = (eeprom_data & ~IXGBE_SFF_SOFT_RS_SELECT_MASK) & rs; + eeprom_data = (eeprom_data & ~IXGBE_SFF_SOFT_RS_SELECT_MASK) | rs; status = hw->phy.ops.write_i2c_byte(hw, IXGBE_SFF_SFF_8472_OSCB, IXGBE_I2C_EEPROM_DEV_ADDR2,