diff --git a/Readme.md b/Readme.md index dffc3515753c..302911c71b8e 100644 --- a/Readme.md +++ b/Readme.md @@ -1,7 +1,7 @@ # Toshiba Electronic Devices & Storage Corporation TC956X PCIe Ethernet Host Driver -Release Date: 08 Nov 2021 +Release Date: 24 Nov 2021 -Release Version: V_01-00-21 : Limited-tested version +Release Version: V_01-00-22 : Limited-tested version TC956X PCIe EMAC driver is based on "Fedora 30, kernel-5.4.19". @@ -291,5 +291,9 @@ ethtool -s eth0 wol pg ## TC956X_Host_Driver_20211108_V_01-00-21: -(1) Skip queuing PHY Work during suspend and cancel any phy work if already queued. -(2) Restore Gen 3 Speed after resume. +1. Skip queuing PHY Work during suspend and cancel any phy work if already queued. +2. Restore Gen 3 Speed after resume. + +## TC956X_Host_Driver_20211124_V_01-00-22: + +1. Single port Suspend/Resume supported diff --git a/common.h b/common.h index 1d368298bed6..7f992e2624d3 100644 --- a/common.h +++ b/common.h @@ -61,6 +61,8 @@ * VERSION : 01-00-20 * 08 Nov 2021 : 1. Added macro for Maximum Port * VERSION : 01-00-21 + * 24 Nov 2021 : 1. Single Port Suspend/Resume supported + * VERSION : 01-00-22 */ #ifndef __COMMON_H__ @@ -89,13 +91,9 @@ /* Indepenedent Suspend/Resume Debug */ #undef TC956X_PM_DEBUG -#define TC956X_MAX_PORT 2 -/* Suspend-Resume Enum Counter */ -enum TC956X_INDEPENDENT_PORT_PM_SUSPEND { - NO_PORT_SUSPENDED = 0, /* Normal State */ - SINGLE_PORT_SUSPENDED, /* Only Single Port suspended */ - BOTH_PORT_SUSPENDED, /* Both Port suspended */ -}; +#define TC956X_MAX_PORT 2 +#define TC956X_ALL_MAC_PORT_SUSPENDED 0 /* All EMAC Port Suspended. To be used just after suspend and before resume. */ +#define TC956X_NO_MAC_DEVICE_IN_USE 0 /* No EMAC Port in use. To be used at probe and remove. */ /* Suspend-Resume Arguments */ enum TC956X_PORT_PM_STATE { diff --git a/tc956x_pci.c b/tc956x_pci.c index b161d4b5f84b..7c5610e0931a 100644 --- a/tc956x_pci.c +++ b/tc956x_pci.c @@ -84,6 +84,9 @@ 2. Cancel PHY Workqueue before suspend. 3. Restore Gen 3 Speed after resume. * VERSION : 01-00-21 + * 24 Nov 2021 : 1. Version update + 2. Single Port Suspend/Resume supported + * VERSION : 01-00-22 */ #include @@ -116,10 +119,10 @@ static unsigned int tc956x_port1_interface = ENABLE_SGMII_INTERFACE; unsigned int tc956x_port0_filter_phy_pause_frames = DISABLE; unsigned int tc956x_port1_filter_phy_pause_frames = DISABLE; -static const struct tc956x_version tc956x_drv_version = {0, 1, 0, 0, 2, 1}; +static const struct tc956x_version tc956x_drv_version = {0, 1, 0, 0, 2, 2}; -enum TC956X_INDEPENDENT_PORT_PM_SUSPEND tc956xmac_pm_suspend_counter = NO_PORT_SUSPENDED; -struct mutex tc956x_pm_suspend_lock; +static int tc956xmac_pm_usage_counter; /* Device Usage Counter */ +struct mutex tc956x_pm_suspend_lock; /* This mutex is shared between all available EMAC ports. */ /* * This struct is used to associate PCI Function of MAC controller on a board, @@ -2258,12 +2261,19 @@ static int tc956xmac_pci_probe(struct pci_dev *pdev, dev_dbg(&(pdev->dev), "%s : ltssm_data.ltssm_stop_status = %d\n", __func__, ltssm_data.ltssm_stop_status); } #endif /* TC956X_PCIE_LOGSTAT */ - mutex_init(&tc956x_pm_suspend_lock); + /* Initialize only once */ + if (tc956xmac_pm_usage_counter == TC956X_NO_MAC_DEVICE_IN_USE) + mutex_init(&tc956x_pm_suspend_lock); #ifdef DMA_OFFLOAD_ENABLE if (res.port_num == RM_PF0_ID) port0_pdev = pdev; #endif + mutex_lock(&tc956x_pm_suspend_lock); + /* Increment device usage counter */ + tc956xmac_pm_usage_counter++; + DBGPR_FUNC(&(pdev->dev), "%s : (Device Usage Count = [%d]) \n", __func__, tc956xmac_pm_usage_counter); + mutex_unlock(&tc956x_pm_suspend_lock); return ret; err_out_msi_failed: @@ -2345,61 +2355,19 @@ static void tc956xmac_pci_remove(struct pci_dev *pdev) pci_release_regions(pdev); pci_disable_device(pdev); - mutex_destroy(&tc956x_pm_suspend_lock); + + mutex_lock(&tc956x_pm_suspend_lock); + /* Decrement device usage counter */ + tc956xmac_pm_usage_counter--; + DBGPR_FUNC(&(pdev->dev), "%s : (Device Usage Count = [%d]) \n", __func__, tc956xmac_pm_usage_counter); + mutex_unlock(&tc956x_pm_suspend_lock); + /* Destroy Mutex only once */ + if (tc956xmac_pm_usage_counter == TC956X_NO_MAC_DEVICE_IN_USE) + mutex_destroy(&tc956x_pm_suspend_lock); DBGPR_FUNC(&(pdev->dev), "<--%s\n", __func__); } -/*! - * \brief API to increment port-wise suspend counter. - * - * \details This api will be called during suspend operation. - * This will set(increase) the tc956xmac_pm_set_counter based on - * number of times tc956x_pcie_suspend() is called as per following : - * If no port suspended - the api will set to Single Port Supended, - * If one port already suspended - the api will set to Single Port Supended, - * If both port suspended - the api will return error. - * - * \param[in] pdev - pointer to pci_dev structure. - * - * \return int - */ -static inline int tc956xmac_pm_set_counter(struct tc956xmac_priv *priv) -{ - if (tc956xmac_pm_suspend_counter == NO_PORT_SUSPENDED) - tc956xmac_pm_suspend_counter = SINGLE_PORT_SUSPENDED; - else if (tc956xmac_pm_suspend_counter == SINGLE_PORT_SUSPENDED) - tc956xmac_pm_suspend_counter = BOTH_PORT_SUSPENDED; - else /* if (tc956xmac_pm_suspend_counter == BOTH_PORT_SUSPENDED)*/ - return -1; - return tc956xmac_pm_suspend_counter; -} - -/*! - * \brief API to decrement port-wise suspend counter. - * - * \details This api will be called during resume operation. - * This will set(decrease) the tc956xmac_pm_set_counter based on - * number of times tc956x_pcie_resume() is called as per following : - * If both port suspended - the api will set to Single Port Supended, - * If one port is already suspended - the api will set to No Port Supended, - * If no port is suspended - on calling the api will return error. - * - * \param[in] pdev - pointer to pci_dev structure. - * - * \return int - */ -static inline int tc956xmac_pm_get_counter(struct tc956xmac_priv *priv) -{ - if (tc956xmac_pm_suspend_counter == BOTH_PORT_SUSPENDED) - tc956xmac_pm_suspend_counter = SINGLE_PORT_SUSPENDED; - else if (tc956xmac_pm_suspend_counter == SINGLE_PORT_SUSPENDED) - tc956xmac_pm_suspend_counter = NO_PORT_SUSPENDED; - else /* if (tc956xmac_pm_suspend_counter == NO_PORT_SUSPENDED) */ - return -1; - return tc956xmac_pm_suspend_counter; -} - /*! * \brief API to disable pci device. * @@ -2468,10 +2436,10 @@ static int tc956x_pcie_pm_enable_pci(struct pci_dev *pdev) */ static int tc956x_pcie_pm_pci(struct pci_dev *pdev, enum TC956X_PORT_PM_STATE state) { - static struct pci_dev *tc956x_pd = NULL, *tc956x_dsp_ep = NULL, *tc956x_port_pdev[2]; + static struct pci_dev *tc956x_pd = NULL, *tc956x_dsp_ep = NULL, *tc956x_port_pdev[2] = {NULL}; struct pci_bus *bus = NULL; - int ret = 0, i = 0; - if (tc956xmac_pm_suspend_counter > SINGLE_PORT_SUSPENDED) { + int ret = 0, i = 0, p = 0; + if (tc956xmac_pm_usage_counter == TC956X_ALL_MAC_PORT_SUSPENDED) { tc956x_dsp_ep = pci_upstream_bridge(pdev); bus = tc956x_dsp_ep->subordinate; @@ -2479,21 +2447,17 @@ static int tc956x_pcie_pm_pci(struct pci_dev *pdev, enum TC956X_PORT_PM_STATE st list_for_each_entry(tc956x_pd, &bus->devices, bus_list) tc956x_port_pdev[i++] = tc956x_pd; - /* Enter only if at least 1 Port Suspended */ - if (state == SUSPEND) { - ret = tc956x_pcie_pm_disable_pci(tc956x_port_pdev[0]); - if (ret < 0) - goto err; - ret = tc956x_pcie_pm_disable_pci(tc956x_port_pdev[1]); - if (ret < 0) - goto err; - } else if (state == RESUME) { - ret = tc956x_pcie_pm_enable_pci(tc956x_port_pdev[0]); - if (ret < 0) - goto err; - ret = tc956x_pcie_pm_enable_pci(tc956x_port_pdev[1]); - if (ret < 0) - goto err; + for (p = 0; ((p < i) && (tc956x_port_pdev[p] != NULL)); p++) { + /* Enter only if at least 1 Port Suspended */ + if (state == SUSPEND) { + ret = tc956x_pcie_pm_disable_pci(tc956x_port_pdev[p]); + if (ret < 0) + goto err; + } else if (state == RESUME) { + ret = tc956x_pcie_pm_enable_pci(tc956x_port_pdev[p]); + if (ret < 0) + goto err; + } } } err : @@ -2545,19 +2509,15 @@ static int tc956x_pcie_suspend(struct device *dev) mutex_lock(&tc956x_pm_suspend_lock); - /* Increment Suspend counter */ - ret = tc956xmac_pm_set_counter(priv); - if (ret < 0) { - DBGPR_FUNC(&(pdev->dev), "%s : (Both Ports Already Suspended ) \n", __func__); - goto err; - } else - DBGPR_FUNC(&(pdev->dev), "%s : (Number of Ports Suspended = [%d]) \n", __func__, ret); + /* Decrement device usage counter */ + tc956xmac_pm_usage_counter--; + DBGPR_FUNC(&(pdev->dev), "%s : (Number of Ports Left to Suspend = [%d]) \n", __func__, tc956xmac_pm_usage_counter); /* Call tc956xmac_suspend() */ tc956xmac_suspend(&pdev->dev); #ifdef DMA_OFFLOAD_ENABLE - if (tc956xmac_pm_suspend_counter > SINGLE_PORT_SUSPENDED) { + if (tc956xmac_pm_usage_counter == TC956X_ALL_MAC_PORT_SUSPENDED) { DBGPR_FUNC(&(pdev->dev), "%s : Port %d - Tamap Configuration", __func__, priv->port_num); /* Since TAMAP is common for Port0 and Port1, * Store CM3 TAMAP entries of one Port0*/ @@ -2818,7 +2778,7 @@ static int tc956x_pcie_resume(struct device *dev) goto err; } #ifdef TC956X_PCIE_GEN3_SETTING - if (tc956xmac_pm_suspend_counter > SINGLE_PORT_SUSPENDED) { + if (tc956xmac_pm_usage_counter == TC956X_ALL_MAC_PORT_SUSPENDED) { /* Reset Speed to Gen3 after resume */ DBGPR_FUNC(&(pdev->dev), "%s : Port %d - Set Speed to Gen3", __func__, priv->port_num); val = readl(priv->ioaddr + TC956X_GLUE_EFUSE_CTRL); @@ -2840,7 +2800,7 @@ static int tc956x_pcie_resume(struct device *dev) #endif /* Configure TA map registers */ - if (tc956xmac_pm_suspend_counter > SINGLE_PORT_SUSPENDED) { + if (tc956xmac_pm_usage_counter == TC956X_ALL_MAC_PORT_SUSPENDED) { DBGPR_FUNC(&(pdev->dev),"%s : Tamap Re-configuration", __func__); tc956x_config_tamap(&pdev->dev, priv->tc956x_BRIDGE_CFG_pci_base_addr); #ifdef DMA_OFFLOAD_ENABLE @@ -2864,15 +2824,9 @@ static int tc956x_pcie_resume(struct device *dev) writel(NEMACIOCTL_DEFAULT, priv->ioaddr + TC9563_CFG_NEMACIOCTL); } - /* Decrement Suspend counter */ - ret = tc956xmac_pm_get_counter(priv); - if (ret < 0) { - DBGPR_FUNC(&(pdev->dev), "%s : (Both Ports Already in Resume State ) \n", __func__); - goto err; - } else { - DBGPR_FUNC(&(pdev->dev), "%s : (Number of Ports left to Resume = [%d]) \n", __func__, ret); - ret = 0; - } + /* Increment device usage counter */ + tc956xmac_pm_usage_counter++; + DBGPR_FUNC(&(pdev->dev), "%s : (Number of Ports Resumed = [%d]) \n", __func__, tc956xmac_pm_usage_counter); priv->tc956x_port_pm_suspend = false; diff --git a/tc956xmac.h b/tc956xmac.h index 5b4f40c04257..b3b7faa37ccd 100644 --- a/tc956xmac.h +++ b/tc956xmac.h @@ -83,6 +83,9 @@ * VERSION : 01-00-20 * 08 Nov 2021 : 1. Version update * VERSION : 01-00-21 + * 24 Nov 2021 : 1. Version update + 2. Private member used instead of global for wol interrupt indication + * VERSION : 01-00-22 */ #ifndef __TC956XMAC_H__ @@ -135,7 +138,7 @@ #ifdef TC956X #define TC956X_RESOURCE_NAME "tc956x_pci-eth" -#define DRV_MODULE_VERSION "V_01-00-21" +#define DRV_MODULE_VERSION "V_01-00-22" #define TC956X_FW_MAX_SIZE (64*1024) #define ATR_AXI4_SLV_BASE 0x0800 @@ -588,6 +591,7 @@ struct tc956xmac_priv { bool is_sgmii_2p5g; /* For 2.5G SGMI, XPCS doesn't support AN. This flag is to identify 2.5G Speed for SGMII interface. */ u32 port_interface; /* Kernel module parameter variable for interface */ bool tc956x_port_pm_suspend; /* Port Suspend Status; True : port suspended, False : port resume */ + bool tc956xmac_pm_wol_interrupt; /* Port-wise flag for clearing interrupt after resume. */ #endif /* set to 1 when ptp offload is enabled, else 0. */ diff --git a/tc956xmac_main.c b/tc956xmac_main.c index 4673cb07e281..21fa4810dbd3 100644 --- a/tc956xmac_main.c +++ b/tc956xmac_main.c @@ -69,7 +69,9 @@ * VERSION : 01-00-20 * 08 Nov 2021 : 1. Skip queuing PHY Work during suspend. * VERSION : 01-00-21 - */ + * 24 Nov 2021 : 1. Private member used instead of global for wol interrupt indication + * VERSION : 01-00-22 +*/ #include #include @@ -219,7 +221,7 @@ static const struct config_parameter_list config_param_list[] = { }; static uint16_t mdio_bus_id; -static bool tc956xmac_pm_wol_interrupt[TC956X_MAX_PORT]; /* Port-wise flag for clearing interrupt after resume. */ + #define CONFIG_PARAM_NUM ARRAY_SIZE(config_param_list) int tc956xmac_rx_parser_configuration(struct tc956xmac_priv *); @@ -347,7 +349,7 @@ static irqreturn_t tc956xmac_wol_interrupt(int irq, void *dev_id) /* Set flag to clear interrupt after resume */ DBGPR_FUNC(priv->device, "%s\n", __func__); /* Set flag to indicate WOL interrupt trigger */ - tc956xmac_pm_wol_interrupt[priv->port_num] = true; + priv->tc956xmac_pm_wol_interrupt = true; return IRQ_HANDLED; } @@ -4243,7 +4245,7 @@ static int tc956xmac_open(struct net_device *dev) } } #endif - tc956xmac_pm_wol_interrupt[priv->port_num] = false; /* Initialize flag for PHY Work queue */ + priv->tc956xmac_pm_wol_interrupt = false; /* Initialize flag for PHY Work queue */ } tc956xmac_enable_all_queues(priv); tc956xmac_start_all_queues(priv); @@ -5809,7 +5811,7 @@ static irqreturn_t tc956xmac_interrupt(int irq, void *dev_id) /* Queue the work in system_wq */ if (priv->tc956x_port_pm_suspend == true) { KPRINT_INFO("%s : (Do not queue PHY Work during suspend. Set WOL Interrupt flag) \n", __func__); - tc956xmac_pm_wol_interrupt[priv->port_num] = true; + priv->tc956xmac_pm_wol_interrupt = true; } else { KPRINT_INFO("%s : (Queue PHY Work.) \n", __func__); queue_work(system_wq, &priv->emac_phy_work); @@ -10750,10 +10752,10 @@ int tc956xmac_resume(struct device *dev) rtnl_unlock(); clean_exit: - if (tc956xmac_pm_wol_interrupt[priv->port_num]) { + if (priv->tc956xmac_pm_wol_interrupt) { KPRINT_INFO("%s : Port %d Clearing WOL and queuing phy work", __func__, priv->port_num); /* Clear WOL Interrupt after resume, if WOL enabled */ - tc956xmac_pm_wol_interrupt[priv->port_num] = false; + priv->tc956xmac_pm_wol_interrupt = false; /* Queue the work in system_wq */ queue_work(system_wq, &priv->emac_phy_work); }