Skip to content

Commit 8c5c7ab

Browse files
NetanelBelgazaldavem330
authored andcommitted
net: ena: add power management ops to the ENA driver
Signed-off-by: Netanel Belgazal <netanel@amazon.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent dbeaf1e commit 8c5c7ab

File tree

3 files changed

+95
-27
lines changed

3 files changed

+95
-27
lines changed

drivers/net/ethernet/amazon/ena/ena_ethtool.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ struct ena_stats {
6060

6161
static const struct ena_stats ena_stats_global_strings[] = {
6262
ENA_STAT_GLOBAL_ENTRY(tx_timeout),
63+
ENA_STAT_GLOBAL_ENTRY(suspend),
64+
ENA_STAT_GLOBAL_ENTRY(resume),
6365
ENA_STAT_GLOBAL_ENTRY(wd_expired),
6466
ENA_STAT_GLOBAL_ENTRY(interface_up),
6567
ENA_STAT_GLOBAL_ENTRY(interface_down),

drivers/net/ethernet/amazon/ena/ena_netdev.c

Lines changed: 90 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2529,38 +2529,31 @@ static int ena_enable_msix_and_set_admin_interrupts(struct ena_adapter *adapter,
25292529
return rc;
25302530
}
25312531

2532-
static void ena_fw_reset_device(struct work_struct *work)
2532+
static void ena_destroy_device(struct ena_adapter *adapter)
25332533
{
2534-
struct ena_com_dev_get_features_ctx get_feat_ctx;
2535-
struct ena_adapter *adapter =
2536-
container_of(work, struct ena_adapter, reset_task);
25372534
struct net_device *netdev = adapter->netdev;
25382535
struct ena_com_dev *ena_dev = adapter->ena_dev;
2539-
struct pci_dev *pdev = adapter->pdev;
2540-
bool dev_up, wd_state;
2541-
int rc;
2542-
2543-
if (unlikely(!test_bit(ENA_FLAG_TRIGGER_RESET, &adapter->flags))) {
2544-
dev_err(&pdev->dev,
2545-
"device reset schedule while reset bit is off\n");
2546-
return;
2547-
}
2536+
bool dev_up;
25482537

25492538
netif_carrier_off(netdev);
25502539

25512540
del_timer_sync(&adapter->timer_service);
25522541

2553-
rtnl_lock();
2554-
25552542
dev_up = test_bit(ENA_FLAG_DEV_UP, &adapter->flags);
2543+
adapter->dev_up_before_reset = dev_up;
2544+
25562545
ena_com_set_admin_running_state(ena_dev, false);
25572546

2558-
/* After calling ena_close the tx queues and the napi
2559-
* are disabled so no one can interfere or touch the
2560-
* data structures
2561-
*/
25622547
ena_close(netdev);
25632548

2549+
/* Before releasing the ENA resources, a device reset is required.
2550+
* (to prevent the device from accessing them).
2551+
* In case the reset flag is set and the device is up, ena_close
2552+
* already perform the reset, so it can be skipped.
2553+
*/
2554+
if (!(test_bit(ENA_FLAG_TRIGGER_RESET, &adapter->flags) && dev_up))
2555+
ena_com_dev_reset(adapter->ena_dev, adapter->reset_reason);
2556+
25642557
ena_free_mgmnt_irq(adapter);
25652558

25662559
ena_disable_msix(adapter);
@@ -2574,9 +2567,17 @@ static void ena_fw_reset_device(struct work_struct *work)
25742567
ena_com_mmio_reg_read_request_destroy(ena_dev);
25752568

25762569
adapter->reset_reason = ENA_REGS_RESET_NORMAL;
2570+
25772571
clear_bit(ENA_FLAG_TRIGGER_RESET, &adapter->flags);
2572+
}
25782573

2579-
/* Finish with the destroy part. Start the init part */
2574+
static int ena_restore_device(struct ena_adapter *adapter)
2575+
{
2576+
struct ena_com_dev_get_features_ctx get_feat_ctx;
2577+
struct ena_com_dev *ena_dev = adapter->ena_dev;
2578+
struct pci_dev *pdev = adapter->pdev;
2579+
bool wd_state;
2580+
int rc;
25802581

25812582
rc = ena_device_init(ena_dev, adapter->pdev, &get_feat_ctx, &wd_state);
25822583
if (rc) {
@@ -2598,7 +2599,7 @@ static void ena_fw_reset_device(struct work_struct *work)
25982599
goto err_device_destroy;
25992600
}
26002601
/* If the interface was up before the reset bring it up */
2601-
if (dev_up) {
2602+
if (adapter->dev_up_before_reset) {
26022603
rc = ena_up(adapter);
26032604
if (rc) {
26042605
dev_err(&pdev->dev, "Failed to create I/O queues\n");
@@ -2607,24 +2608,38 @@ static void ena_fw_reset_device(struct work_struct *work)
26072608
}
26082609

26092610
mod_timer(&adapter->timer_service, round_jiffies(jiffies + HZ));
2610-
2611-
rtnl_unlock();
2612-
26132611
dev_err(&pdev->dev, "Device reset completed successfully\n");
26142612

2615-
return;
2613+
return rc;
26162614
err_disable_msix:
26172615
ena_free_mgmnt_irq(adapter);
26182616
ena_disable_msix(adapter);
26192617
err_device_destroy:
26202618
ena_com_admin_destroy(ena_dev);
26212619
err:
2622-
rtnl_unlock();
2623-
26242620
clear_bit(ENA_FLAG_DEVICE_RUNNING, &adapter->flags);
26252621

26262622
dev_err(&pdev->dev,
26272623
"Reset attempt failed. Can not reset the device\n");
2624+
2625+
return rc;
2626+
}
2627+
2628+
static void ena_fw_reset_device(struct work_struct *work)
2629+
{
2630+
struct ena_adapter *adapter =
2631+
container_of(work, struct ena_adapter, reset_task);
2632+
struct pci_dev *pdev = adapter->pdev;
2633+
2634+
if (unlikely(!test_bit(ENA_FLAG_TRIGGER_RESET, &adapter->flags))) {
2635+
dev_err(&pdev->dev,
2636+
"device reset schedule while reset bit is off\n");
2637+
return;
2638+
}
2639+
rtnl_lock();
2640+
ena_destroy_device(adapter);
2641+
ena_restore_device(adapter);
2642+
rtnl_unlock();
26282643
}
26292644

26302645
static int check_missing_comp_in_queue(struct ena_adapter *adapter,
@@ -3378,11 +3393,59 @@ static void ena_remove(struct pci_dev *pdev)
33783393
vfree(ena_dev);
33793394
}
33803395

3396+
#ifdef CONFIG_PM
3397+
/* ena_suspend - PM suspend callback
3398+
* @pdev: PCI device information struct
3399+
* @state:power state
3400+
*/
3401+
static int ena_suspend(struct pci_dev *pdev, pm_message_t state)
3402+
{
3403+
struct ena_adapter *adapter = pci_get_drvdata(pdev);
3404+
3405+
u64_stats_update_begin(&adapter->syncp);
3406+
adapter->dev_stats.suspend++;
3407+
u64_stats_update_end(&adapter->syncp);
3408+
3409+
rtnl_lock();
3410+
if (unlikely(test_bit(ENA_FLAG_TRIGGER_RESET, &adapter->flags))) {
3411+
dev_err(&pdev->dev,
3412+
"ignoring device reset request as the device is being suspended\n");
3413+
clear_bit(ENA_FLAG_TRIGGER_RESET, &adapter->flags);
3414+
}
3415+
ena_destroy_device(adapter);
3416+
rtnl_unlock();
3417+
return 0;
3418+
}
3419+
3420+
/* ena_resume - PM resume callback
3421+
* @pdev: PCI device information struct
3422+
*
3423+
*/
3424+
static int ena_resume(struct pci_dev *pdev)
3425+
{
3426+
struct ena_adapter *adapter = pci_get_drvdata(pdev);
3427+
int rc;
3428+
3429+
u64_stats_update_begin(&adapter->syncp);
3430+
adapter->dev_stats.resume++;
3431+
u64_stats_update_end(&adapter->syncp);
3432+
3433+
rtnl_lock();
3434+
rc = ena_restore_device(adapter);
3435+
rtnl_unlock();
3436+
return rc;
3437+
}
3438+
#endif
3439+
33813440
static struct pci_driver ena_pci_driver = {
33823441
.name = DRV_MODULE_NAME,
33833442
.id_table = ena_pci_tbl,
33843443
.probe = ena_probe,
33853444
.remove = ena_remove,
3445+
#ifdef CONFIG_PM
3446+
.suspend = ena_suspend,
3447+
.resume = ena_resume,
3448+
#endif
33863449
.sriov_configure = ena_sriov_configure,
33873450
};
33883451

drivers/net/ethernet/amazon/ena/ena_netdev.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,8 @@ struct ena_ring {
257257

258258
struct ena_stats_dev {
259259
u64 tx_timeout;
260+
u64 suspend;
261+
u64 resume;
260262
u64 wd_expired;
261263
u64 interface_up;
262264
u64 interface_down;
@@ -327,6 +329,7 @@ struct ena_adapter {
327329
struct timer_list timer_service;
328330

329331
bool wd_state;
332+
bool dev_up_before_reset;
330333
unsigned long last_keep_alive_jiffies;
331334

332335
struct u64_stats_sync syncp;

0 commit comments

Comments
 (0)