|
@@ -76,7 +76,7 @@ MODULE_DEVICE_TABLE(pci, ena_pci_tbl);
|
|
|
|
|
|
static int ena_rss_init_default(struct ena_adapter *adapter);
|
|
|
static void check_for_admin_com_state(struct ena_adapter *adapter);
|
|
|
-static void ena_destroy_device(struct ena_adapter *adapter);
|
|
|
+static void ena_destroy_device(struct ena_adapter *adapter, bool graceful);
|
|
|
static int ena_restore_device(struct ena_adapter *adapter);
|
|
|
|
|
|
static void ena_tx_timeout(struct net_device *dev)
|
|
@@ -461,7 +461,7 @@ static inline int ena_alloc_rx_page(struct ena_ring *rx_ring,
|
|
|
return -ENOMEM;
|
|
|
}
|
|
|
|
|
|
- dma = dma_map_page(rx_ring->dev, page, 0, PAGE_SIZE,
|
|
|
+ dma = dma_map_page(rx_ring->dev, page, 0, ENA_PAGE_SIZE,
|
|
|
DMA_FROM_DEVICE);
|
|
|
if (unlikely(dma_mapping_error(rx_ring->dev, dma))) {
|
|
|
u64_stats_update_begin(&rx_ring->syncp);
|
|
@@ -478,7 +478,7 @@ static inline int ena_alloc_rx_page(struct ena_ring *rx_ring,
|
|
|
rx_info->page_offset = 0;
|
|
|
ena_buf = &rx_info->ena_buf;
|
|
|
ena_buf->paddr = dma;
|
|
|
- ena_buf->len = PAGE_SIZE;
|
|
|
+ ena_buf->len = ENA_PAGE_SIZE;
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
@@ -495,7 +495,7 @@ static void ena_free_rx_page(struct ena_ring *rx_ring,
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- dma_unmap_page(rx_ring->dev, ena_buf->paddr, PAGE_SIZE,
|
|
|
+ dma_unmap_page(rx_ring->dev, ena_buf->paddr, ENA_PAGE_SIZE,
|
|
|
DMA_FROM_DEVICE);
|
|
|
|
|
|
__free_page(page);
|
|
@@ -551,14 +551,9 @@ static int ena_refill_rx_bufs(struct ena_ring *rx_ring, u32 num)
|
|
|
rx_ring->qid, i, num);
|
|
|
}
|
|
|
|
|
|
- if (likely(i)) {
|
|
|
- /* Add memory barrier to make sure the desc were written before
|
|
|
- * issue a doorbell
|
|
|
- */
|
|
|
- wmb();
|
|
|
- ena_com_write_sq_doorbell(rx_ring->ena_com_io_sq, true);
|
|
|
- mmiowb();
|
|
|
- }
|
|
|
+ /* ena_com_write_sq_doorbell issues a wmb() */
|
|
|
+ if (likely(i))
|
|
|
+ ena_com_write_sq_doorbell(rx_ring->ena_com_io_sq);
|
|
|
|
|
|
rx_ring->next_to_use = next_to_use;
|
|
|
|
|
@@ -916,10 +911,10 @@ static struct sk_buff *ena_rx_skb(struct ena_ring *rx_ring,
|
|
|
do {
|
|
|
dma_unmap_page(rx_ring->dev,
|
|
|
dma_unmap_addr(&rx_info->ena_buf, paddr),
|
|
|
- PAGE_SIZE, DMA_FROM_DEVICE);
|
|
|
+ ENA_PAGE_SIZE, DMA_FROM_DEVICE);
|
|
|
|
|
|
skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, rx_info->page,
|
|
|
- rx_info->page_offset, len, PAGE_SIZE);
|
|
|
+ rx_info->page_offset, len, ENA_PAGE_SIZE);
|
|
|
|
|
|
netif_dbg(rx_ring->adapter, rx_status, rx_ring->netdev,
|
|
|
"rx skb updated. len %d. data_len %d\n",
|
|
@@ -1900,7 +1895,7 @@ static int ena_close(struct net_device *netdev)
|
|
|
"Destroy failure, restarting device\n");
|
|
|
ena_dump_stats_to_dmesg(adapter);
|
|
|
/* rtnl lock already obtained in dev_ioctl() layer */
|
|
|
- ena_destroy_device(adapter);
|
|
|
+ ena_destroy_device(adapter, false);
|
|
|
ena_restore_device(adapter);
|
|
|
}
|
|
|
|
|
@@ -2112,12 +2107,6 @@ static netdev_tx_t ena_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|
|
tx_ring->next_to_use = ENA_TX_RING_IDX_NEXT(next_to_use,
|
|
|
tx_ring->ring_size);
|
|
|
|
|
|
- /* This WMB is aimed to:
|
|
|
- * 1 - perform smp barrier before reading next_to_completion
|
|
|
- * 2 - make sure the desc were written before trigger DB
|
|
|
- */
|
|
|
- wmb();
|
|
|
-
|
|
|
/* stop the queue when no more space available, the packet can have up
|
|
|
* to sgl_size + 2. one for the meta descriptor and one for header
|
|
|
* (if the header is larger than tx_max_header_size).
|
|
@@ -2136,10 +2125,11 @@ static netdev_tx_t ena_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|
|
* stop the queue but meanwhile clean_tx_irq updates
|
|
|
* next_to_completion and terminates.
|
|
|
* The queue will remain stopped forever.
|
|
|
- * To solve this issue this function perform rmb, check
|
|
|
- * the wakeup condition and wake up the queue if needed.
|
|
|
+ * To solve this issue add a mb() to make sure that
|
|
|
+ * netif_tx_stop_queue() write is vissible before checking if
|
|
|
+ * there is additional space in the queue.
|
|
|
*/
|
|
|
- smp_rmb();
|
|
|
+ smp_mb();
|
|
|
|
|
|
if (ena_com_sq_empty_space(tx_ring->ena_com_io_sq)
|
|
|
> ENA_TX_WAKEUP_THRESH) {
|
|
@@ -2151,8 +2141,10 @@ static netdev_tx_t ena_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|
|
}
|
|
|
|
|
|
if (netif_xmit_stopped(txq) || !skb->xmit_more) {
|
|
|
- /* trigger the dma engine */
|
|
|
- ena_com_write_sq_doorbell(tx_ring->ena_com_io_sq, false);
|
|
|
+ /* trigger the dma engine. ena_com_write_sq_doorbell()
|
|
|
+ * has a mb
|
|
|
+ */
|
|
|
+ ena_com_write_sq_doorbell(tx_ring->ena_com_io_sq);
|
|
|
u64_stats_update_begin(&tx_ring->syncp);
|
|
|
tx_ring->tx_stats.doorbells++;
|
|
|
u64_stats_update_end(&tx_ring->syncp);
|
|
@@ -2550,12 +2542,15 @@ err_disable_msix:
|
|
|
return rc;
|
|
|
}
|
|
|
|
|
|
-static void ena_destroy_device(struct ena_adapter *adapter)
|
|
|
+static void ena_destroy_device(struct ena_adapter *adapter, bool graceful)
|
|
|
{
|
|
|
struct net_device *netdev = adapter->netdev;
|
|
|
struct ena_com_dev *ena_dev = adapter->ena_dev;
|
|
|
bool dev_up;
|
|
|
|
|
|
+ if (!test_bit(ENA_FLAG_DEVICE_RUNNING, &adapter->flags))
|
|
|
+ return;
|
|
|
+
|
|
|
netif_carrier_off(netdev);
|
|
|
|
|
|
del_timer_sync(&adapter->timer_service);
|
|
@@ -2563,7 +2558,8 @@ static void ena_destroy_device(struct ena_adapter *adapter)
|
|
|
dev_up = test_bit(ENA_FLAG_DEV_UP, &adapter->flags);
|
|
|
adapter->dev_up_before_reset = dev_up;
|
|
|
|
|
|
- ena_com_set_admin_running_state(ena_dev, false);
|
|
|
+ if (!graceful)
|
|
|
+ ena_com_set_admin_running_state(ena_dev, false);
|
|
|
|
|
|
if (test_bit(ENA_FLAG_DEV_UP, &adapter->flags))
|
|
|
ena_down(adapter);
|
|
@@ -2591,6 +2587,7 @@ static void ena_destroy_device(struct ena_adapter *adapter)
|
|
|
adapter->reset_reason = ENA_REGS_RESET_NORMAL;
|
|
|
|
|
|
clear_bit(ENA_FLAG_TRIGGER_RESET, &adapter->flags);
|
|
|
+ clear_bit(ENA_FLAG_DEVICE_RUNNING, &adapter->flags);
|
|
|
}
|
|
|
|
|
|
static int ena_restore_device(struct ena_adapter *adapter)
|
|
@@ -2635,6 +2632,7 @@ static int ena_restore_device(struct ena_adapter *adapter)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ set_bit(ENA_FLAG_DEVICE_RUNNING, &adapter->flags);
|
|
|
mod_timer(&adapter->timer_service, round_jiffies(jiffies + HZ));
|
|
|
dev_err(&pdev->dev, "Device reset completed successfully\n");
|
|
|
|
|
@@ -2665,7 +2663,7 @@ static void ena_fw_reset_device(struct work_struct *work)
|
|
|
return;
|
|
|
}
|
|
|
rtnl_lock();
|
|
|
- ena_destroy_device(adapter);
|
|
|
+ ena_destroy_device(adapter, false);
|
|
|
ena_restore_device(adapter);
|
|
|
rtnl_unlock();
|
|
|
}
|
|
@@ -3409,30 +3407,24 @@ static void ena_remove(struct pci_dev *pdev)
|
|
|
netdev->rx_cpu_rmap = NULL;
|
|
|
}
|
|
|
#endif /* CONFIG_RFS_ACCEL */
|
|
|
-
|
|
|
- unregister_netdev(netdev);
|
|
|
del_timer_sync(&adapter->timer_service);
|
|
|
|
|
|
cancel_work_sync(&adapter->reset_task);
|
|
|
|
|
|
- /* Reset the device only if the device is running. */
|
|
|
- if (test_bit(ENA_FLAG_DEVICE_RUNNING, &adapter->flags))
|
|
|
- ena_com_dev_reset(ena_dev, adapter->reset_reason);
|
|
|
+ unregister_netdev(netdev);
|
|
|
|
|
|
- ena_free_mgmnt_irq(adapter);
|
|
|
+ /* If the device is running then we want to make sure the device will be
|
|
|
+ * reset to make sure no more events will be issued by the device.
|
|
|
+ */
|
|
|
+ if (test_bit(ENA_FLAG_DEVICE_RUNNING, &adapter->flags))
|
|
|
+ set_bit(ENA_FLAG_TRIGGER_RESET, &adapter->flags);
|
|
|
|
|
|
- ena_disable_msix(adapter);
|
|
|
+ rtnl_lock();
|
|
|
+ ena_destroy_device(adapter, true);
|
|
|
+ rtnl_unlock();
|
|
|
|
|
|
free_netdev(netdev);
|
|
|
|
|
|
- ena_com_mmio_reg_read_request_destroy(ena_dev);
|
|
|
-
|
|
|
- ena_com_abort_admin_commands(ena_dev);
|
|
|
-
|
|
|
- ena_com_wait_for_abort_completion(ena_dev);
|
|
|
-
|
|
|
- ena_com_admin_destroy(ena_dev);
|
|
|
-
|
|
|
ena_com_rss_destroy(ena_dev);
|
|
|
|
|
|
ena_com_delete_debug_area(ena_dev);
|
|
@@ -3467,7 +3459,7 @@ static int ena_suspend(struct pci_dev *pdev, pm_message_t state)
|
|
|
"ignoring device reset request as the device is being suspended\n");
|
|
|
clear_bit(ENA_FLAG_TRIGGER_RESET, &adapter->flags);
|
|
|
}
|
|
|
- ena_destroy_device(adapter);
|
|
|
+ ena_destroy_device(adapter, true);
|
|
|
rtnl_unlock();
|
|
|
return 0;
|
|
|
}
|