lists.openwall.net | lists / announce owl-users owl-dev john-users john-dev passwdqc-users yescrypt popa3d-users / oss-security kernel-hardening musl sabotage tlsify passwords / crypt-dev xvendor / Bugtraq Full-Disclosure linux-kernel linux-netdev linux-ext4 linux-hardening linux-cve-announce PHC | |
Open Source and information security mailing list archives
| ||
|
Message-Id: <20220810085532.246613-7-jiawenwu@trustnetic.com> Date: Wed, 10 Aug 2022 16:55:22 +0800 From: Jiawen Wu <jiawenwu@...stnetic.com> To: netdev@...r.kernel.org Cc: Jiawen Wu <jiawenwu@...stnetic.com> Subject: [RFC PATCH net-next 06/16] net: txgbe: Initialize service task Setup work queue, and initialize service task to process the following tasks. Signed-off-by: Jiawen Wu <jiawenwu@...stnetic.com> --- drivers/net/ethernet/wangxun/txgbe/txgbe.h | 17 +++ .../net/ethernet/wangxun/txgbe/txgbe_main.c | 124 +++++++++++++++++- 2 files changed, 137 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe.h b/drivers/net/ethernet/wangxun/txgbe/txgbe.h index d0ea817e2f42..397241df4078 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe.h +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe.h @@ -36,6 +36,8 @@ struct txgbe_adapter { struct net_device *netdev; struct pci_dev *pdev; + unsigned long state; + /* Tx fast path data */ int num_tx_queues; @@ -46,6 +48,9 @@ struct txgbe_adapter { struct txgbe_hw hw; u16 msg_enable; + struct timer_list service_timer; + struct work_struct service_task; + char eeprom_id[32]; bool netdev_registered; @@ -53,7 +58,19 @@ struct txgbe_adapter { }; +enum txgbe_state_t { + __TXGBE_TESTING, + __TXGBE_RESETTING, + __TXGBE_DOWN, + __TXGBE_HANGING, + __TXGBE_DISABLED, + __TXGBE_REMOVING, + __TXGBE_SERVICE_SCHED, + __TXGBE_SERVICE_INITED, +}; + /* needed by txgbe_main.c */ +void txgbe_service_event_schedule(struct txgbe_adapter *adapter); void txgbe_assign_netdev_ops(struct net_device *netdev); int txgbe_open(struct net_device *netdev); diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c index da5193c871b3..30bac8a049df 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c @@ -32,6 +32,8 @@ static const struct pci_device_id txgbe_pci_tbl[] = { #define DEFAULT_DEBUG_LEVEL_SHIFT 3 +static struct workqueue_struct *txgbe_wq; + static bool txgbe_is_sfp(struct txgbe_hw *hw); static void txgbe_check_minimum_link(struct txgbe_adapter *adapter) @@ -81,6 +83,24 @@ static inline int txgbe_enumerate_functions(struct txgbe_adapter *adapter) return physfns; } +void txgbe_service_event_schedule(struct txgbe_adapter *adapter) +{ + if (!test_bit(__TXGBE_DOWN, &adapter->state) && + !test_bit(__TXGBE_REMOVING, &adapter->state) && + !test_and_set_bit(__TXGBE_SERVICE_SCHED, &adapter->state)) + queue_work(txgbe_wq, &adapter->service_task); +} + +static void txgbe_service_event_complete(struct txgbe_adapter *adapter) +{ + if (WARN_ON(!test_bit(__TXGBE_SERVICE_SCHED, &adapter->state))) + return; + + /* flush memory to make sure state is correct before next watchdog */ + smp_mb__before_atomic(); + clear_bit(__TXGBE_SERVICE_SCHED, &adapter->state); +} + static void txgbe_remove_adapter(struct txgbe_hw *hw) { struct txgbe_adapter *adapter = container_of(hw, struct txgbe_adapter, hw); @@ -89,6 +109,8 @@ static void txgbe_remove_adapter(struct txgbe_hw *hw) return; hw->hw_addr = NULL; dev_info(&adapter->pdev->dev, "Adapter removed\n"); + if (test_bit(__TXGBE_SERVICE_INITED, &adapter->state)) + txgbe_service_event_schedule(adapter); } static bool txgbe_check_cfg_remove(struct txgbe_hw *hw, struct pci_dev *pdev) @@ -221,6 +243,10 @@ void txgbe_disable_device(struct txgbe_adapter *adapter) struct txgbe_hw *hw = &adapter->hw; u32 i; + /* signal that we are down to the interrupt handler */ + if (test_and_set_bit(__TXGBE_DOWN, &adapter->state)) + return; /* do nothing if already down */ + txgbe_disable_pcie_master(hw); /* disable receives */ TCALL(hw, mac.ops.disable_rx); @@ -228,6 +254,8 @@ void txgbe_disable_device(struct txgbe_adapter *adapter) netif_carrier_off(netdev); netif_tx_disable(netdev); + del_timer_sync(&adapter->service_timer); + if (hw->bus.lan_id == 0) wr32m(hw, TXGBE_MIS_PRB_CTL, TXGBE_MIS_PRB_CTL_LAN0_UP, 0); else if (hw->bus.lan_id == 1) @@ -320,6 +348,8 @@ static int txgbe_sw_init(struct txgbe_adapter *adapter) return err; } + set_bit(__TXGBE_DOWN, &adapter->state); + return 0; } @@ -391,7 +421,8 @@ static void txgbe_dev_shutdown(struct pci_dev *pdev, bool *enable_wake) txgbe_release_hw_control(adapter); - pci_disable_device(pdev); + if (!test_and_set_bit(__TXGBE_DISABLED, &adapter->state)) + pci_disable_device(pdev); } static void txgbe_shutdown(struct pci_dev *pdev) @@ -406,6 +437,41 @@ static void txgbe_shutdown(struct pci_dev *pdev) } } +static void txgbe_service_timer(struct timer_list *t) +{ + struct txgbe_adapter *adapter = from_timer(adapter, t, service_timer); + unsigned long next_event_offset; + + next_event_offset = HZ * 2; + + /* Reset the timer */ + mod_timer(&adapter->service_timer, next_event_offset + jiffies); + + txgbe_service_event_schedule(adapter); +} + +/** + * txgbe_service_task - manages and runs subtasks + * @work: pointer to work_struct containing our data + **/ +static void txgbe_service_task(struct work_struct *work) +{ + struct txgbe_adapter *adapter = container_of(work, + struct txgbe_adapter, + service_task); + if (TXGBE_REMOVED(adapter->hw.hw_addr)) { + if (!test_bit(__TXGBE_DOWN, &adapter->state)) { + rtnl_lock(); + txgbe_down(adapter); + rtnl_unlock(); + } + txgbe_service_event_complete(adapter); + return; + } + + txgbe_service_event_complete(adapter); +} + /** * txgbe_add_sanmac_netdev - Add the SAN MAC address to the corresponding * netdev->dev_addr_list @@ -479,6 +545,7 @@ static int txgbe_probe(struct pci_dev *pdev, struct txgbe_adapter *adapter = NULL; struct txgbe_hw *hw = NULL; struct net_device *netdev; + bool disable_dev = false; int err, expected_gts; u16 eeprom_verh = 0, eeprom_verl = 0, offset = 0; @@ -537,6 +604,7 @@ static int txgbe_probe(struct pci_dev *pdev, hw->hw_addr = adapter->io_addr; txgbe_assign_netdev_ops(netdev); + netdev->watchdog_timeo = 5 * HZ; strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); /* setup the private structure */ @@ -588,6 +656,12 @@ static int txgbe_probe(struct pci_dev *pdev, txgbe_mac_set_default_filter(adapter, hw->mac.perm_addr); + timer_setup(&adapter->service_timer, txgbe_service_timer, 0); + + INIT_WORK(&adapter->service_task, txgbe_service_task); + set_bit(__TXGBE_SERVICE_INITED, &adapter->state); + clear_bit(__TXGBE_SERVICE_SCHED, &adapter->state); + /* Save off EEPROM version number and Option Rom version which * together make a unique identify for the eeprom */ @@ -689,11 +763,13 @@ static int txgbe_probe(struct pci_dev *pdev, err_free_mac_table: kfree(adapter->mac_table); err_pci_release_regions: + disable_dev = !test_and_set_bit(__TXGBE_DISABLED, &adapter->state); pci_disable_pcie_error_reporting(pdev); pci_release_selected_regions(pdev, pci_select_bars(pdev, IORESOURCE_MEM)); err_pci_disable_dev: - pci_disable_device(pdev); + if (!adapter || disable_dev) + pci_disable_device(pdev); return err; } @@ -710,8 +786,11 @@ static void txgbe_remove(struct pci_dev *pdev) { struct txgbe_adapter *adapter = pci_get_drvdata(pdev); struct net_device *netdev; + bool disable_dev; netdev = adapter->netdev; + set_bit(__TXGBE_REMOVING, &adapter->state); + cancel_work_sync(&adapter->service_task); /* remove the added san mac */ txgbe_del_sanmac_netdev(netdev); @@ -727,10 +806,12 @@ static void txgbe_remove(struct pci_dev *pdev) pci_select_bars(pdev, IORESOURCE_MEM)); kfree(adapter->mac_table); + disable_dev = !test_and_set_bit(__TXGBE_DISABLED, &adapter->state); pci_disable_pcie_error_reporting(pdev); - pci_disable_device(pdev); + if (disable_dev) + pci_disable_device(pdev); } u16 txgbe_read_pci_cfg_word(struct txgbe_hw *hw, u32 reg) @@ -755,7 +836,42 @@ static struct pci_driver txgbe_driver = { .shutdown = txgbe_shutdown, }; -module_pci_driver(txgbe_driver); +/** + * txgbe_init_module - Driver Registration Routine + * + * txgbe_init_module is the first routine called when the driver is + * loaded. All it does is register with the PCI subsystem. + **/ +static int __init txgbe_init_module(void) +{ + int ret; + + txgbe_wq = create_singlethread_workqueue(txgbe_driver_name); + if (!txgbe_wq) { + pr_err("%s: Failed to create workqueue\n", txgbe_driver_name); + return -ENOMEM; + } + + ret = pci_register_driver(&txgbe_driver); + return ret; +} + +module_init(txgbe_init_module); + +/** + * txgbe_exit_module - Driver Exit Cleanup Routine + * + * txgbe_exit_module is called just before the driver is removed + * from memory. + **/ +static void __exit txgbe_exit_module(void) +{ + pci_unregister_driver(&txgbe_driver); + if (txgbe_wq) + destroy_workqueue(txgbe_wq); +} + +module_exit(txgbe_exit_module); MODULE_DEVICE_TABLE(pci, txgbe_pci_tbl); MODULE_AUTHOR("Beijing WangXun Technology Co., Ltd, <software@...stnetic.com>"); -- 2.27.0
Powered by blists - more mailing lists