summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Peng <robinpeng@google.com>2020-02-20 16:33:37 +0800
committerRobin Peng <robinpeng@google.com>2020-02-20 16:33:37 +0800
commit65d1205259b4406acaf7f1b018c3bf60db2529ba (patch)
treec738a8d4d754409fb376efc8c1ceb85d015b20c8
parent346e30acf12d2c6970f6ae23c7152e2f15bd0f7a (diff)
parentd0c4566d6011f0d0172273185e11280bc1dd6665 (diff)
downloaddata-kernel-65d1205259b4406acaf7f1b018c3bf60db2529ba.tar.gz
Merge branch 'LA.UM.9.12.R1.10.00.00.597.022' into qcom-msm-4.19-7250
Change-Id: Ib2d4e487fedc8e99ecd7be8ad8cbc99052dcce06
-rw-r--r--drivers/emac-dwc-eqos/DWC_ETH_QOS_dev.c13
-rw-r--r--drivers/emac-dwc-eqos/DWC_ETH_QOS_mdio.c101
-rw-r--r--drivers/emac-dwc-eqos/DWC_ETH_QOS_platform.c12
-rw-r--r--drivers/emac-dwc-eqos/DWC_ETH_QOS_yheader.h2
-rw-r--r--drivers/rmnet/shs/rmnet_shs.h4
-rw-r--r--drivers/rmnet/shs/rmnet_shs_config.c6
-rwxr-xr-xdrivers/rmnet/shs/rmnet_shs_main.c19
7 files changed, 101 insertions, 56 deletions
diff --git a/drivers/emac-dwc-eqos/DWC_ETH_QOS_dev.c b/drivers/emac-dwc-eqos/DWC_ETH_QOS_dev.c
index 7ce0a31..b262b23 100644
--- a/drivers/emac-dwc-eqos/DWC_ETH_QOS_dev.c
+++ b/drivers/emac-dwc-eqos/DWC_ETH_QOS_dev.c
@@ -3126,7 +3126,7 @@ static INT set_promiscuous_mode(void)
static INT write_phy_regs(INT phy_id, INT phy_reg, INT phy_reg_data)
{
- ULONG RETRYCOUNT = 1000;
+ ULONG RETRYCOUNT = 5000;
ULONG vy_count;
volatile ULONG VARMAC_GMIIAR;
@@ -3139,7 +3139,7 @@ static INT write_phy_regs(INT phy_id, INT phy_reg, INT phy_reg_data)
return -Y_FAILURE;
vy_count++;
- mdelay(1);
+ udelay(200);
MAC_GMIIAR_RGRD(VARMAC_GMIIAR);
if (GET_VALUE(
@@ -3173,7 +3173,7 @@ static INT write_phy_regs(INT phy_id, INT phy_reg, INT phy_reg_data)
return -Y_FAILURE;
vy_count++;
- mdelay(1);
+ udelay(200);
MAC_GMIIAR_RGRD(VARMAC_GMIIAR);
if (GET_VALUE(
@@ -3197,7 +3197,7 @@ static INT write_phy_regs(INT phy_id, INT phy_reg, INT phy_reg_data)
static INT read_phy_regs(INT phy_id, INT phy_reg, INT *phy_reg_data)
{
- ULONG RETRYCOUNT = 1000;
+ ULONG RETRYCOUNT = 5000;
ULONG vy_count;
volatile ULONG VARMAC_GMIIAR;
ULONG VARMAC_GMIIDR;
@@ -3211,8 +3211,7 @@ static INT read_phy_regs(INT phy_id, INT phy_reg, INT *phy_reg_data)
return -Y_FAILURE;
vy_count++;
- mdelay(1);
-
+ udelay(200);
MAC_GMIIAR_RGRD(VARMAC_GMIIAR);
if (GET_VALUE(
VARMAC_GMIIAR, MAC_GMIIAR_GB_LPOS,
@@ -3243,7 +3242,7 @@ static INT read_phy_regs(INT phy_id, INT phy_reg, INT *phy_reg_data)
return -Y_FAILURE;
vy_count++;
- mdelay(1);
+ udelay(200);
MAC_GMIIAR_RGRD(VARMAC_GMIIAR);
if (GET_VALUE(
diff --git a/drivers/emac-dwc-eqos/DWC_ETH_QOS_mdio.c b/drivers/emac-dwc-eqos/DWC_ETH_QOS_mdio.c
index faac49e..defeef8 100644
--- a/drivers/emac-dwc-eqos/DWC_ETH_QOS_mdio.c
+++ b/drivers/emac-dwc-eqos/DWC_ETH_QOS_mdio.c
@@ -445,6 +445,43 @@ void dump_phy_registers(struct DWC_ETH_QOS_prv_data *pdata)
pr_alert("\n****************************************************\n");
}
+static void DWC_ETH_QOS_request_phy_wol(struct DWC_ETH_QOS_prv_data *pdata)
+{
+ pdata->phy_wol_supported = 0;
+ pdata->phy_wol_wolopts = 0;
+
+ /* Check if phydev is valid*/
+ /* Check and enable Wake-on-LAN functionality in PHY*/
+ if (pdata->phydev) {
+ struct ethtool_wolinfo wol = {.cmd = ETHTOOL_GWOL};
+ wol.supported = 0;
+ wol.wolopts= 0;
+
+ phy_ethtool_get_wol(pdata->phydev, &wol);
+ pdata->phy_wol_supported = wol.supported;
+
+ /* Try to enable supported Wake-on-LAN features in PHY*/
+ if (wol.supported) {
+
+ device_set_wakeup_capable(&pdata->pdev->dev, 1);
+
+ wol.cmd = ETHTOOL_SWOL;
+ wol.wolopts = wol.supported;
+
+ if (!phy_ethtool_set_wol(pdata->phydev, &wol)){
+ pdata->phy_wol_wolopts = wol.wolopts;
+
+ enable_irq_wake(pdata->phy_irq);
+
+ device_set_wakeup_enable(&pdata->pdev->dev, 1);
+ EMACDBG("Enabled WoL[0x%x] in %s\n", wol.wolopts,
+ pdata->phydev->drv->name);
+ pdata->wol_enabled = 1;
+ }
+ }
+ }
+}
+
/*!
* \brief API to enable or disable PHY hibernation mode
*
@@ -1007,6 +1044,9 @@ void DWC_ETH_QOS_adjust_link(struct net_device *dev)
}
#endif
+ if (pdata->phy_intr_en && !pdata->wol_enabled)
+ DWC_ETH_QOS_request_phy_wol(pdata);
+
if (pdata->ipa_enabled && netif_running(dev)) {
if (phydev->link == 1)
DWC_ETH_QOS_ipa_offload_event_handler(pdata, EV_PHY_LINK_UP);
@@ -1030,42 +1070,6 @@ void DWC_ETH_QOS_adjust_link(struct net_device *dev)
DBGPR_MDIO("<--DWC_ETH_QOS_adjust_link\n");
}
-static void DWC_ETH_QOS_request_phy_wol(struct DWC_ETH_QOS_prv_data *pdata)
-{
- pdata->phy_wol_supported = 0;
- pdata->phy_wol_wolopts = 0;
-
- /* Check if phydev is valid*/
- /* Check and enable Wake-on-LAN functionality in PHY*/
- if (pdata->phydev) {
- struct ethtool_wolinfo wol = {.cmd = ETHTOOL_GWOL};
- wol.supported = 0;
- wol.wolopts= 0;
-
- phy_ethtool_get_wol(pdata->phydev, &wol);
- pdata->phy_wol_supported = wol.supported;
-
- /* Try to enable supported Wake-on-LAN features in PHY*/
- if (wol.supported) {
-
- device_set_wakeup_capable(&pdata->pdev->dev, 1);
-
- wol.cmd = ETHTOOL_SWOL;
- wol.wolopts = wol.supported;
-
- if (!phy_ethtool_set_wol(pdata->phydev, &wol)){
- pdata->phy_wol_wolopts = wol.wolopts;
-
- enable_irq_wake(pdata->phy_irq);
-
- device_set_wakeup_enable(&pdata->pdev->dev, 1);
- EMACDBG("Enabled WoL[0x%x] in %s\n", wol.wolopts,
- pdata->phydev->drv->name);
- }
- }
- }
-}
-
bool DWC_ETH_QOS_is_phy_link_up(struct DWC_ETH_QOS_prv_data *pdata)
{
/* PHY driver initializes phydev->link=1.
@@ -1194,10 +1198,8 @@ static int DWC_ETH_QOS_init_phy(struct net_device *dev)
phydev->irq = PHY_IGNORE_INTERRUPT;
phydev->interrupts = PHY_INTERRUPT_ENABLED;
- if (phydev->drv->config_intr &&
- !phydev->drv->config_intr(phydev)){
- DWC_ETH_QOS_request_phy_wol(pdata);
- } else {
+ if (!(phydev->drv->config_intr &&
+ !phydev->drv->config_intr(phydev))){
EMACERR("Failed to configure PHY interrupts");
BUG();
}
@@ -1250,6 +1252,21 @@ int DWC_ETH_QOS_mdio_register(struct net_device *dev)
DBGPR_MDIO("-->DWC_ETH_QOS_mdio_register\n");
+ if (pdata->res_data->phy_addr != -1) {
+ phy_reg_read_status =
+ DWC_ETH_QOS_mdio_read_direct(pdata, pdata->res_data->phy_addr, MII_BMSR,
+ &mii_status);
+ if (phy_reg_read_status == 0) {
+ if (mii_status != 0x0000 && mii_status != 0xffff) {
+ phy_detected = 1;
+ phyaddr = pdata->res_data->phy_addr;
+ EMACINFO("skip_phy_detection (phyaddr)%d\n", phyaddr);
+ goto skip_phy_detection;
+ } else
+ EMACERR("Invlaid phy address specified in device tree\n");
+ }
+ }
+
/* find the phy ID or phy address which is connected to our MAC */
for (phyaddr = 0; phyaddr < 32; phyaddr++) {
@@ -1276,6 +1293,8 @@ int DWC_ETH_QOS_mdio_register(struct net_device *dev)
return -ENOLINK;
}
+ skip_phy_detection:
+
pdata->phyaddr = phyaddr;
pdata->bus_id = 0x1;
pdata->phy_intr_en = false;
@@ -1307,7 +1326,7 @@ int DWC_ETH_QOS_mdio_register(struct net_device *dev)
snprintf(new_bus->id, MII_BUS_ID_SIZE, "%s-%x", new_bus->name,
pdata->bus_id);
new_bus->priv = dev;
- new_bus->phy_mask = 0;
+ new_bus->phy_mask = ~(1 << phyaddr);
new_bus->parent = &pdata->pdev->dev;
ret = mdiobus_register(new_bus);
if (ret != 0) {
diff --git a/drivers/emac-dwc-eqos/DWC_ETH_QOS_platform.c b/drivers/emac-dwc-eqos/DWC_ETH_QOS_platform.c
index 9102457..4cff0e4 100644
--- a/drivers/emac-dwc-eqos/DWC_ETH_QOS_platform.c
+++ b/drivers/emac-dwc-eqos/DWC_ETH_QOS_platform.c
@@ -899,6 +899,16 @@ static int DWC_ETH_QOS_get_dts_config(struct platform_device *pdev)
dwc_eth_qos_res_data.is_pinctrl_names = true;
EMACDBG("qcom,pinctrl-names present\n");
}
+ dwc_eth_qos_res_data.phy_addr = -1;
+ if (of_property_read_bool(pdev->dev.of_node, "emac-phy-addr")) {
+ ret = of_property_read_u32(pdev->dev.of_node, "emac-phy-addr",
+ &dwc_eth_qos_res_data.phy_addr);
+ if (ret) {
+ EMACINFO("Pphy_addr not specified, using dynamic phy detection\n");
+ dwc_eth_qos_res_data.phy_addr = -1;
+ }
+ EMACINFO("phy_addr = %d\n", dwc_eth_qos_res_data.phy_addr);
+ }
return ret;
@@ -1470,6 +1480,8 @@ static int DWC_ETH_QOS_init_gpios(struct device *dev)
gpio_set_value(dwc_eth_qos_res_data.gpio_phy_reset, PHY_RESET_GPIO_HIGH);
EMACDBG("PHY is out of reset successfully\n");
+ /* Add delay of 50ms so that phy should get sufficient time*/
+ mdelay(50);
}
return ret;
diff --git a/drivers/emac-dwc-eqos/DWC_ETH_QOS_yheader.h b/drivers/emac-dwc-eqos/DWC_ETH_QOS_yheader.h
index ee29121..b0a1210 100644
--- a/drivers/emac-dwc-eqos/DWC_ETH_QOS_yheader.h
+++ b/drivers/emac-dwc-eqos/DWC_ETH_QOS_yheader.h
@@ -1584,6 +1584,7 @@ struct DWC_ETH_QOS_res_data {
unsigned int emac_hw_version_type;
bool early_eth_en;
bool pps_lpass_conn_en;
+ int phy_addr;
};
struct DWC_ETH_QOS_prv_ipa_data {
@@ -1878,6 +1879,7 @@ struct DWC_ETH_QOS_prv_data {
struct class* avb_class_b_class;
struct delayed_work ipv6_addr_assign_wq;
bool print_kpi;
+ bool wol_enabled;
};
struct ip_params {
diff --git a/drivers/rmnet/shs/rmnet_shs.h b/drivers/rmnet/shs/rmnet_shs.h
index f6ce09e..b7bf773 100644
--- a/drivers/rmnet/shs/rmnet_shs.h
+++ b/drivers/rmnet/shs/rmnet_shs.h
@@ -299,7 +299,7 @@ extern int (*rmnet_shs_skb_entry)(struct sk_buff *skb,
int rmnet_shs_is_lpwr_cpu(u16 cpu);
void rmnet_shs_cancel_table(void);
void rmnet_shs_rx_wq_init(void);
-void rmnet_shs_rx_wq_exit(void);
+unsigned int rmnet_shs_rx_wq_exit(void);
int rmnet_shs_get_mask_len(u8 mask);
int rmnet_shs_chk_and_flush_node(struct rmnet_shs_skbn_s *node,
@@ -314,7 +314,7 @@ void rmnet_shs_assign(struct sk_buff *skb, struct rmnet_port *port);
void rmnet_shs_flush_table(u8 is_force_flush, u8 ctxt);
void rmnet_shs_cpu_node_remove(struct rmnet_shs_skbn_s *node);
void rmnet_shs_init(struct net_device *dev, struct net_device *vnd);
-void rmnet_shs_exit(void);
+void rmnet_shs_exit(unsigned int cpu_switch);
void rmnet_shs_ps_on_hdlr(void *port);
void rmnet_shs_ps_off_hdlr(void *port);
void rmnet_shs_update_cpu_proc_q_all_cpus(void);
diff --git a/drivers/rmnet/shs/rmnet_shs_config.c b/drivers/rmnet/shs/rmnet_shs_config.c
index e6b4002..6a628dc 100644
--- a/drivers/rmnet/shs/rmnet_shs_config.c
+++ b/drivers/rmnet/shs/rmnet_shs_config.c
@@ -99,14 +99,16 @@ static int rmnet_shs_dev_notify_cb(struct notifier_block *nb,
* phy_dev is going down.
*/
if (!rmnet_vnd_total && rmnet_shs_cfg.rmnet_shs_init_complete) {
+ unsigned int cpu_switch;
+
pr_info("rmnet_shs deinit %s going down ", dev->name);
RCU_INIT_POINTER(rmnet_shs_skb_entry, NULL);
qmi_rmnet_ps_ind_deregister(rmnet_shs_cfg.port,
&rmnet_shs_cfg.rmnet_idl_ind_cb);
rmnet_shs_cancel_table();
- rmnet_shs_rx_wq_exit();
+ cpu_switch = rmnet_shs_rx_wq_exit();
rmnet_shs_wq_exit();
- rmnet_shs_exit();
+ rmnet_shs_exit(cpu_switch);
trace_rmnet_shs_high(RMNET_SHS_MODULE,
RMNET_SHS_MODULE_INIT_WQ,
0xDEF, 0xDEF, 0xDEF,
diff --git a/drivers/rmnet/shs/rmnet_shs_main.c b/drivers/rmnet/shs/rmnet_shs_main.c
index ae66460..2accd29 100755
--- a/drivers/rmnet/shs/rmnet_shs_main.c
+++ b/drivers/rmnet/shs/rmnet_shs_main.c
@@ -1359,14 +1359,25 @@ void rmnet_shs_rx_wq_init(void)
INIT_WORK(&shs_rx_work.work, rmnet_flush_buffered);
}
-void rmnet_shs_rx_wq_exit(void)
+unsigned int rmnet_shs_rx_wq_exit(void)
{
+ unsigned int cpu_switch = rmnet_shs_inst_rate_switch;
int i;
- for (i = 0; i < MAX_CPUS; i++)
+ /* Disable any further core_flush timer starts untill cleanup
+ * is complete.
+ */
+ rmnet_shs_inst_rate_switch = 0;
+
+ for (i = 0; i < MAX_CPUS; i++) {
+ hrtimer_cancel(&GET_CTIMER(i));
+
cancel_work_sync(&rmnet_shs_cfg.core_flush[i].work);
+ }
cancel_work_sync(&shs_rx_work.work);
+
+ return cpu_switch;
}
void rmnet_shs_ps_on_hdlr(void *port)
@@ -1724,7 +1735,7 @@ void rmnet_shs_assign(struct sk_buff *skb, struct rmnet_port *port)
/* Cancels the flushing timer if it has been armed
* Deregisters DL marker indications
*/
-void rmnet_shs_exit(void)
+void rmnet_shs_exit(unsigned int cpu_switch)
{
rmnet_shs_freq_exit();
rmnet_shs_cfg.dl_mrk_ind_cb.dl_hdr_handler = NULL;
@@ -1738,5 +1749,5 @@ void rmnet_shs_exit(void)
memset(&rmnet_shs_cfg, 0, sizeof(rmnet_shs_cfg));
rmnet_shs_cfg.port = NULL;
rmnet_shs_cfg.rmnet_shs_init_complete = 0;
-
+ rmnet_shs_inst_rate_switch = cpu_switch;
}