net: stmmac: boot up KPI changes

Read early ethernet dtsi flag to enable this feature.
Disable autoneg and configure MAC and PHY with 100 Mbps
link speed.
Read MAC addr, IPv4 and IPv6 addresses from kernel cmd
line parameters in order to assign these to ethernet
interface.

Change-Id: Ibeeebb73b4cbbd0950a1bff065297c4e58be671d
Acked-by: Abhishek Chauhan <abchauha@qti.qualcomm.com>
Signed-off-by: Sunil Paidimarri <hisunil@codeaurora.org>
This commit is contained in:
Sunil Paidimarri 2020-02-04 09:40:48 -08:00 committed by Gerrit - the friendly Code Review server
parent 91aa9b064a
commit 8f76fef083
8 changed files with 522 additions and 11 deletions

View File

@ -209,3 +209,9 @@ Todo
----
Add more DRM drivers.
eipv4= [KNL] Sets ipv4 address at boot up for early ethernet.
eipv6= [KNL] Sets ipv6 address at boot up for early ethernet.
ermac= [KNL] Sets mac address at boot up for early ethernet.

View File

@ -5010,3 +5010,9 @@
xirc2ps_cs= [NET,PCMCIA]
Format:
<irq>,<irq_mask>,<io>,<full_duplex>,<do_sound>,<lockup_hack>[,<irq2>[,<irq3>[,<irq4>]]]
eipv4= [KNL] Sets ipv4 address at boot up for early ethernet.
eipv6= [KNL] Sets ipv6 address at boot up for early ethernet.
ermac= [KNL] Sets mac address at boot up for early ethernet.

View File

@ -22,6 +22,8 @@
#include <linux/tcp.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/rtnetlink.h>
#include "stmmac.h"
#include "stmmac_platform.h"
#include "dwmac-qcom-ethqos.h"
@ -33,10 +35,13 @@ bool phy_intr_en;
struct qcom_ethqos *pethqos;
struct emac_emb_smmu_cb_ctx emac_emb_smmu_ctx = {0};
static unsigned char dev_addr[ETH_ALEN] = {
0, 0x55, 0x7b, 0xb5, 0x7d, 0xf7};
void *ipc_emac_log_ctxt;
static struct qmp_pkt pkt;
static char qmp_buf[MAX_QMP_MSG_SIZE + 1] = {0};
static struct ip_params pparams = {"", "", "", ""};
static inline unsigned int dwmac_qcom_get_eth_type(unsigned char *buf)
{
@ -208,6 +213,169 @@ int ethqos_handle_prv_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
return ret;
}
static int __init set_early_ethernet_ipv4(char *ipv4_addr_in)
{
int ret = 1;
pparams.is_valid_ipv4_addr = false;
if (!ipv4_addr_in)
return ret;
strlcpy(pparams.ipv4_addr_str,
ipv4_addr_in, sizeof(pparams.ipv4_addr_str));
ETHQOSDBG("Early ethernet IPv4 addr: %s\n", pparams.ipv4_addr_str);
ret = in4_pton(pparams.ipv4_addr_str, -1,
(u8 *)&pparams.ipv4_addr.s_addr, -1, NULL);
if (ret != 1 || pparams.ipv4_addr.s_addr == 0) {
ETHQOSERR("Invalid ipv4 address programmed: %s\n",
ipv4_addr_in);
return ret;
}
pparams.is_valid_ipv4_addr = true;
return ret;
}
__setup("eipv4=", set_early_ethernet_ipv4);
static int __init set_early_ethernet_ipv6(char *ipv6_addr_in)
{
int ret = 1;
pparams.is_valid_ipv6_addr = false;
if (!ipv6_addr_in)
return ret;
strlcpy(pparams.ipv6_addr_str,
ipv6_addr_in, sizeof(pparams.ipv6_addr_str));
ETHQOSDBG("Early ethernet IPv6 addr: %s\n", pparams.ipv6_addr_str);
ret = in6_pton(pparams.ipv6_addr_str, -1,
(u8 *)&pparams.ipv6_addr.ifr6_addr.s6_addr32, -1, NULL);
if (ret != 1 || !pparams.ipv6_addr.ifr6_addr.s6_addr32) {
ETHQOSERR("Invalid ipv6 address programmed: %s\n",
ipv6_addr_in);
return ret;
}
pparams.is_valid_ipv6_addr = true;
return ret;
}
__setup("eipv6=", set_early_ethernet_ipv6);
static int __init set_early_ethernet_mac(char *mac_addr)
{
int ret = 1;
bool valid_mac = false;
pparams.is_valid_mac_addr = false;
if (!mac_addr)
return ret;
valid_mac = mac_pton(mac_addr, pparams.mac_addr);
if (!valid_mac)
goto fail;
valid_mac = is_valid_ether_addr(pparams.mac_addr);
if (!valid_mac)
goto fail;
pparams.is_valid_mac_addr = true;
return ret;
fail:
ETHQOSERR("Invalid Mac address programmed: %s\n", mac_addr);
return ret;
}
__setup("ermac=", set_early_ethernet_mac);
static int qcom_ethqos_add_ipaddr(struct ip_params *ip_info,
struct net_device *dev)
{
int res = 0;
struct ifreq ir;
struct sockaddr_in *sin = (void *)&ir.ifr_ifru.ifru_addr;
struct net *net = dev_net(dev);
if (!net || !net->genl_sock || !net->genl_sock->sk_socket) {
ETHQOSINFO("Sock is null, unable to assign ipv4 address\n");
return res;
}
/*For valid Ipv4 address*/
memset(&ir, 0, sizeof(ir));
memcpy(&sin->sin_addr.s_addr, &ip_info->ipv4_addr,
sizeof(sin->sin_addr.s_addr));
strlcpy(ir.ifr_ifrn.ifrn_name,
dev->name, sizeof(ir.ifr_ifrn.ifrn_name));
sin->sin_family = AF_INET;
sin->sin_port = 0;
res = inet_ioctl(net->genl_sock->sk_socket,
SIOCSIFADDR, (unsigned long)(void *)&ir);
if (res) {
ETHQOSERR("can't setup IPv4 address!: %d\r\n", res);
} else {
ETHQOSINFO("Assigned IPv4 address: %s\r\n",
ip_info->ipv4_addr_str);
#ifdef CONFIG_MSM_BOOT_TIME_MARKER
place_marker("M - Etherent Assigned IPv4 address");
#endif
}
return res;
}
static int qcom_ethqos_add_ipv6addr(struct ip_params *ip_info,
struct net_device *dev)
{
int ret = -EFAULT;
struct in6_ifreq ir6;
char *prefix;
struct net *net = dev_net(dev);
/*For valid IPv6 address*/
if (!net || !net->genl_sock || !net->genl_sock->sk_socket)
ETHQOSERR("Sock is null, unable to assign ipv6 address\n");
if (!net->ipv6.devconf_dflt) {
ETHQOSERR("ipv6.devconf_dflt is null, schedule wq\n");
schedule_delayed_work(&pethqos->ipv6_addr_assign_wq,
msecs_to_jiffies(1000));
return ret;
}
memset(&ir6, 0, sizeof(ir6));
memcpy(&ir6, &ip_info->ipv6_addr, sizeof(struct in6_ifreq));
ir6.ifr6_ifindex = dev->ifindex;
prefix = strnchr(ip_info->ipv6_addr_str,
strlen(ip_info->ipv6_addr_str), '/');
if (!prefix) {
ir6.ifr6_prefixlen = 0;
} else {
kstrtoul(prefix + 1, 0, (unsigned long *)&ir6.ifr6_prefixlen);
if (ir6.ifr6_prefixlen > 128)
ir6.ifr6_prefixlen = 0;
}
ret = inet6_ioctl(net->genl_sock->sk_socket,
SIOCSIFADDR, (unsigned long)(void *)&ir6);
if (ret) {
ETHQOSDBG("Can't setup IPv6 address!\r\n");
} else {
ETHQOSDBG("Assigned IPv6 address: %s\r\n",
ip_info->ipv6_addr_str);
#ifdef CONFIG_MSM_BOOT_TIME_MARKER
place_marker("M - Ethernet Assigned IPv6 address");
#endif
}
return ret;
}
static int rgmii_readl(struct qcom_ethqos *ethqos, unsigned int offset)
{
return readl(ethqos->rgmii_base + offset);
@ -1270,6 +1438,37 @@ static void qcom_ethqos_phy_resume_clks(struct qcom_ethqos *ethqos)
ETHQOSINFO("Exit\n");
}
static void qcom_ethqos_bringup_iface(struct work_struct *work)
{
struct platform_device *pdev = NULL;
struct net_device *ndev = NULL;
struct qcom_ethqos *ethqos =
container_of(work, struct qcom_ethqos, early_eth);
ETHQOSINFO("entry\n");
if (!ethqos)
return;
pdev = ethqos->pdev;
if (!pdev)
return;
ndev = platform_get_drvdata(pdev);
if (!ndev || netif_running(ndev))
return;
rtnl_lock();
if (dev_change_flags(ndev, ndev->flags | IFF_UP) < 0)
ETHQOSINFO("ERROR\n");
rtnl_unlock();
ETHQOSINFO("exit\n");
}
void qcom_ethqos_request_phy_wol(struct plat_stmmacenet_data *plat)
{
struct qcom_ethqos *ethqos = plat->bsp_priv;
@ -1317,6 +1516,104 @@ void qcom_ethqos_request_phy_wol(struct plat_stmmacenet_data *plat)
}
}
static void ethqos_is_ipv4_NW_stack_ready(struct work_struct *work)
{
struct delayed_work *dwork;
struct qcom_ethqos *ethqos;
struct platform_device *pdev = NULL;
struct net_device *ndev = NULL;
int ret;
ETHQOSINFO("\n");
dwork = container_of(work, struct delayed_work, work);
ethqos = container_of(dwork, struct qcom_ethqos, ipv4_addr_assign_wq);
if (!ethqos)
return;
pdev = ethqos->pdev;
if (!pdev)
return;
ndev = platform_get_drvdata(pdev);
ret = qcom_ethqos_add_ipaddr(&pparams, ndev);
if (ret)
return;
cancel_delayed_work_sync(&ethqos->ipv4_addr_assign_wq);
flush_delayed_work(&ethqos->ipv4_addr_assign_wq);
}
static void ethqos_is_ipv6_NW_stack_ready(struct work_struct *work)
{
struct delayed_work *dwork;
struct qcom_ethqos *ethqos;
struct platform_device *pdev = NULL;
struct net_device *ndev = NULL;
int ret;
ETHQOSINFO("\n");
dwork = container_of(work, struct delayed_work, work);
ethqos = container_of(dwork, struct qcom_ethqos, ipv6_addr_assign_wq);
if (!ethqos)
return;
pdev = ethqos->pdev;
if (!pdev)
return;
ndev = platform_get_drvdata(pdev);
ret = qcom_ethqos_add_ipv6addr(&pparams, ndev);
if (ret)
return;
cancel_delayed_work_sync(&ethqos->ipv6_addr_assign_wq);
flush_delayed_work(&ethqos->ipv6_addr_assign_wq);
}
static int ethqos_set_early_eth_param(struct stmmac_priv *priv,
struct qcom_ethqos *ethqos)
{
int ret = 0;
if (priv->plat && priv->plat->mdio_bus_data)
priv->plat->mdio_bus_data->phy_mask =
priv->plat->mdio_bus_data->phy_mask | DUPLEX_FULL | SPEED_100;
priv->plat->max_speed = SPEED_100;
priv->early_eth = ethqos->early_eth_enabled;
qcom_ethqos_add_ipaddr(&pparams, priv->dev);
if (pparams.is_valid_ipv4_addr) {
INIT_DELAYED_WORK(&ethqos->ipv4_addr_assign_wq,
ethqos_is_ipv4_NW_stack_ready);
ret = qcom_ethqos_add_ipaddr(&pparams, priv->dev);
if (ret)
schedule_delayed_work(&ethqos->ipv4_addr_assign_wq,
msecs_to_jiffies(1000));
}
if (pparams.is_valid_ipv6_addr) {
INIT_DELAYED_WORK(&ethqos->ipv6_addr_assign_wq,
ethqos_is_ipv6_NW_stack_ready);
ret = qcom_ethqos_add_ipv6addr(&pparams, priv->dev);
if (ret)
schedule_delayed_work(&ethqos->ipv6_addr_assign_wq,
msecs_to_jiffies(1000));
}
if (pparams.is_valid_mac_addr) {
ether_addr_copy(dev_addr, pparams.mac_addr);
memcpy(priv->dev->dev_addr, dev_addr, ETH_ALEN);
}
return ret;
}
static int qcom_ethqos_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
@ -1328,12 +1625,17 @@ static int qcom_ethqos_probe(struct platform_device *pdev)
struct stmmac_priv *priv;
int ret;
#ifdef CONFIG_MSM_BOOT_TIME_MARKER
place_marker("M - Ethernet probe start");
#endif
ipc_emac_log_ctxt = ipc_log_context_create(IPCLOG_STATE_PAGES,
"emac", 0);
if (!ipc_emac_log_ctxt)
ETHQOSERR("Error creating logging context for emac\n");
ETHQOSINFO("Error creating logging context for emac\n");
else
ETHQOSDBG("IPC logging has been enabled for emac\n");
ETHQOSINFO("IPC logging has been enabled for emac\n");
if (of_device_is_compatible(pdev->dev.of_node,
"qcom,emac-smmu-embedded"))
return emac_emb_smmu_cb_probe(pdev);
@ -1358,7 +1660,6 @@ static int qcom_ethqos_probe(struct platform_device *pdev)
return PTR_ERR(plat_dat);
}
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rgmii");
ethqos->rgmii_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(ethqos->rgmii_base)) {
@ -1379,6 +1680,22 @@ static int qcom_ethqos_probe(struct platform_device *pdev)
if (ret)
goto err_mem;
/*Initialize Early ethernet to false*/
ethqos->early_eth_enabled = false;
/*Check for valid mac, ip address to enable Early eth*/
if (pparams.is_valid_mac_addr &&
(pparams.is_valid_ipv4_addr || pparams.is_valid_ipv6_addr)) {
/* For 1000BASE-T mode, auto-negotiation is required and
* always used to establish a link.
* Configure phy and MAC in 100Mbps mode with autoneg
* disable as link up takes more time with autoneg
* enabled.
*/
ethqos->early_eth_enabled = 1;
ETHQOSINFO("Early ethernet is enabled\n");
}
ethqos->speed = SPEED_10;
ethqos_update_rgmii_clk_and_bus_cfg(ethqos, SPEED_10);
ethqos_set_func_clk_en(ethqos);
@ -1460,11 +1777,22 @@ static int qcom_ethqos_probe(struct platform_device *pdev)
ndev = dev_get_drvdata(&ethqos->pdev->dev);
priv = netdev_priv(ndev);
if (ethqos->early_eth_enabled) {
/* Initialize work*/
INIT_WORK(&ethqos->early_eth,
qcom_ethqos_bringup_iface);
/* Queue the work*/
queue_work(system_wq, &ethqos->early_eth);
/*Set early eth parameters*/
ethqos_set_early_eth_param(priv, ethqos);
}
#ifdef CONFIG_ETH_IPA_OFFLOAD
ethqos->ipa_enabled = true;
priv->rx_queue[IPA_DMA_RX_CH].skip_sw = true;
priv->tx_queue[IPA_DMA_TX_CH].skip_sw = true;
ethqos_ipa_offload_event_handler(ethqos, EV_PROBE_INIT);
priv->hw->mac->map_mtl_to_dma(priv->hw, 0, 1); //change
#endif
return ret;
@ -1590,7 +1918,59 @@ static struct platform_driver qcom_ethqos_driver = {
.of_match_table = of_match_ptr(qcom_ethqos_match),
},
};
module_platform_driver(qcom_ethqos_driver);
static int __init qcom_ethqos_init_module(void)
{
int ret = 0;
ETHQOSINFO("\n");
ret = platform_driver_register(&qcom_ethqos_driver);
if (ret < 0) {
ETHQOSINFO("qcom-ethqos: Driver registration failed");
return ret;
}
ETHQOSINFO("\n");
return ret;
}
static void __exit qcom_ethqos_exit_module(void)
{
ETHQOSINFO("\n");
platform_driver_unregister(&qcom_ethqos_driver);
if (!ipc_emac_log_ctxt)
ipc_log_context_destroy(ipc_emac_log_ctxt);
ETHQOSINFO("\n");
}
/*!
* \brief Macro to register the driver registration function.
*
* \details A module always begin with either the init_module or the function
* you specify with module_init call. This is the entry function for modules;
* it tells the kernel what functionality the module provides and sets up the
* kernel to run the module's functions when they're needed. Once it does this,
* entry function returns and the module does nothing until the kernel wants
* to do something with the code that the module provides.
*/
module_init(qcom_ethqos_init_module)
/*!
* \brief Macro to register the driver un-registration function.
*
* \details All modules end by calling either cleanup_module or the function
* you specify with the module_exit call. This is the exit function for modules;
* it undoes whatever entry function did. It unregisters the functionality
* that the entry function registered.
*/
module_exit(qcom_ethqos_exit_module)
MODULE_DESCRIPTION("Qualcomm Technologies, Inc. ETHQOS driver");
MODULE_LICENSE("GPL v2");

View File

@ -18,8 +18,20 @@
#include <linux/mailbox/qmp.h>
#include <linux/mailbox_controller.h>
#include <linux/inetdevice.h>
#include <linux/inet.h>
#include <net/addrconf.h>
#include <net/ipv6.h>
#include <net/inet_common.h>
#include <linux/uaccess.h>
extern void *ipc_emac_log_ctxt;
#define QCOM_ETH_QOS_MAC_ADDR_LEN 6
#define QCOM_ETH_QOS_MAC_ADDR_STR_LEN 18
#define IPCLOG_STATE_PAGES 50
#define MAX_QMP_MSG_SIZE 96
#define __FILENAME__ (strrchr(__FILE__, '/') ? \
@ -397,12 +409,20 @@ struct qcom_ethqos {
struct mbox_chan *qmp_mbox_chan;
struct mbox_client *qmp_mbox_client;
struct work_struct qmp_mailbox_work;
/* early ethernet parameters */
struct work_struct early_eth;
struct delayed_work ipv4_addr_assign_wq;
struct delayed_work ipv6_addr_assign_wq;
bool early_eth_enabled;
int disable_ctile_pc;
u32 emac_mem_base;
u32 emac_mem_size;
bool ipa_enabled;
/* Key Performance Indicators */
bool print_kpi;
};
struct pps_cfg {
@ -430,6 +450,19 @@ struct pps_info {
int channel_no;
};
struct ip_params {
unsigned char mac_addr[QCOM_ETH_QOS_MAC_ADDR_LEN];
bool is_valid_mac_addr;
char link_speed[32];
bool is_valid_link_speed;
char ipv4_addr_str[32];
struct in_addr ipv4_addr;
bool is_valid_ipv4_addr;
char ipv6_addr_str[48];
struct in6_ifreq ipv6_addr;
bool is_valid_ipv6_addr;
};
int ethqos_init_reqgulators(struct qcom_ethqos *ethqos);
void ethqos_disable_regulators(struct qcom_ethqos *ethqos);
int ethqos_init_gpio(struct qcom_ethqos *ethqos);

View File

@ -45,6 +45,15 @@ static struct ethqos_prv_ipa_data eth_ipa_ctx;
static void __ipa_eth_free_msg(void *buff, u32 len, u32 type) {}
static inline void *ethqos_get_priv(struct qcom_ethqos *ethqos)
{
struct platform_device *pdev = ethqos->pdev;
struct net_device *dev = platform_get_drvdata(pdev);
struct stmmac_priv *priv = netdev_priv(dev);
return priv;
}
static int eth_ipa_send_msg(struct qcom_ethqos *ethqos,
enum ipa_peripheral_event event)
{
@ -981,10 +990,12 @@ static void ethqos_configure_ipa_rx_dma_channel(unsigned int QINX,
static int ethqos_init_offload(struct qcom_ethqos *ethqos)
{
struct stmmac_priv *priv = ethqos_get_priv(ethqos);
ETHQOSDBG("\n");
ethqos_configure_ipa_tx_dma_channel(IPA_DMA_TX_CH, ethqos);
MTL_RQDCM0R_RGWR(0x3020100);
priv->hw->mac->map_mtl_to_dma(priv->hw, 0, 0);
ethqos_configure_ipa_rx_dma_channel(IPA_DMA_RX_CH, ethqos);
ETHQOSDBG("\n");

View File

@ -29,6 +29,10 @@
#include "common.h"
#include <linux/ptp_clock_kernel.h>
#include <linux/reset.h>
#ifdef CONFIG_MSM_BOOT_TIME_MARKER
#include <soc/qcom/boot_stats.h>
#endif
#include "dwmac-qcom-ipa-offload.h"
struct stmmac_resources {
void __iomem *addr;
@ -143,7 +147,8 @@ struct stmmac_priv {
void __iomem *mmcaddr;
void __iomem *ptpaddr;
u32 mss;
bool boot_kpi;
bool early_eth;
#ifdef CONFIG_DEBUG_FS
struct dentry *dbgfs_dir;
struct dentry *dbgfs_rings_status;

View File

@ -50,7 +50,7 @@
#include <linux/reset.h>
#include <linux/of_mdio.h>
#include "dwmac1000.h"
#include "dwmac-qcom-ipa-offload.h"
#define STMMAC_ALIGN(x) __ALIGN_KERNEL(x, SMP_CACHE_BYTES)
#define TSO_MAX_BUFF_SIZE (SZ_16K - 1)
@ -868,6 +868,12 @@ static void stmmac_adjust_link(struct net_device *dev)
ethqos_ipa_offload_event_handler(priv,
EV_PHY_LINK_DOWN);
}
#ifdef CONFIG_MSM_BOOT_TIME_MARKER
if (phydev->link == 1 && !priv->boot_kpi) {
place_marker("M - Ethernet is Ready.Link is UP");
priv->boot_kpi = true;
}
#endif
if (phydev->is_pseudo_fixed_link)
/* Stop PHY layer to call the hook to adjust the link in case
@ -906,6 +912,30 @@ static void stmmac_check_pcs_mode(struct stmmac_priv *priv)
}
}
static void stmmac_set_speed100(struct phy_device *phydev)
{
u16 bmcr_val, ctrl1000_val, adv_val;
/* Disable 1000M mode */
ctrl1000_val = phy_read(phydev, MII_CTRL1000);
ctrl1000_val &= ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL);
phy_write(phydev, MII_CTRL1000, ctrl1000_val);
/* Disable 100M mode */
adv_val = phy_read(phydev, MII_ADVERTISE);
adv_val &= ~(ADVERTISE_100HALF);
phy_write(phydev, MII_ADVERTISE, adv_val);
/* Disable autoneg */
bmcr_val = phy_read(phydev, MII_BMCR);
bmcr_val &= ~(BMCR_ANENABLE);
phy_write(phydev, MII_BMCR, bmcr_val);
bmcr_val = phy_read(phydev, MII_BMCR);
bmcr_val |= BMCR_ANRESTART;
phy_write(phydev, MII_BMCR, bmcr_val);
}
/**
* stmmac_init_phy - PHY initialization
* @dev: net device structure
@ -924,6 +954,7 @@ static int stmmac_init_phy(struct net_device *dev)
int interface = priv->plat->interface;
int max_speed = priv->plat->max_speed;
priv->oldlink = false;
priv->boot_kpi = false;
priv->speed = SPEED_UNKNOWN;
priv->oldduplex = DUPLEX_UNKNOWN;
@ -950,6 +981,8 @@ static int stmmac_init_phy(struct net_device *dev)
return PTR_ERR(phydev);
}
pr_info(" qcom-ethqos: %s early eth setting stmmac init\n",
__func__);
/* Stop Advertising 1000BASE Capability if interface is not GMII */
if ((interface == PHY_INTERFACE_MODE_MII) ||
@ -967,6 +1000,29 @@ static int stmmac_init_phy(struct net_device *dev)
SUPPORTED_100baseT_Half |
SUPPORTED_10baseT_Half);
/* Early ethernet settings to bring up link in 100M,
* Auto neg Off with full duplex link.
*/
if (max_speed == SPEED_100 && priv->early_eth) {
phydev->autoneg = AUTONEG_DISABLE;
phydev->speed = SPEED_100;
phydev->duplex = DUPLEX_FULL;
phydev->supported =
SUPPORTED_100baseT_Full | SUPPORTED_TP | SUPPORTED_MII |
SUPPORTED_10baseT_Full;
phydev->supported &= ~SUPPORTED_Autoneg;
phydev->advertising = phydev->supported;
phydev->advertising &= ~ADVERTISED_Autoneg;
phy_set_max_speed(phydev, SPEED_100);
pr_info(" qcom-ethqos: %s early eth setting successful\n",
__func__);
stmmac_set_speed100(phydev);
}
/*
* Broken HW is sometimes missing the pull-up resistor on the
* MDIO line, which results in reads to non-existent devices returning
@ -987,15 +1043,17 @@ static int stmmac_init_phy(struct net_device *dev)
phydev->irq = PHY_POLL;
if (phy_intr_en) {
phydev->irq = PHY_IGNORE_INTERRUPT;
phydev->interrupts = PHY_INTERRUPT_ENABLED;
if (phydev->drv->config_intr &&
!phydev->drv->config_intr(phydev)) {
pr_debug(" qcom-ethqos: %s config_phy_intr successful\n",
__func__);
qcom_ethqos_request_phy_wol(priv->plat);
phydev->irq = PHY_IGNORE_INTERRUPT;
phydev->interrupts = PHY_INTERRUPT_ENABLED;
} else {
pr_alert("Unable to register PHY IRQ\n");
phydev->irq = PHY_POLL;
}
qcom_ethqos_request_phy_wol(priv->plat);
}
phy_attached_info(phydev);
return 0;
@ -1894,6 +1952,10 @@ static void stmmac_tx_clean(struct stmmac_priv *priv, u32 queue)
} else {
priv->dev->stats.tx_packets++;
priv->xstats.tx_pkt_n++;
#ifdef CONFIG_MSM_BOOT_TIME_MARKER
if (priv->dev->stats.tx_packets == 1)
place_marker("M - Ethernet first packet transmitted");
#endif
}
stmmac_get_tx_hwtstamp(priv, p, skb);
}
@ -3566,6 +3628,11 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
napi_gro_receive(&rx_q->napi, skb);
priv->dev->stats.rx_packets++;
#ifdef CONFIG_MSM_BOOT_TIME_MARKER
if (priv->dev->stats.rx_packets == 1)
place_marker("M - Ethernet first packet received");
#endif
priv->dev->stats.rx_bytes += frame_len;
}
entry = next_entry;

View File

@ -139,6 +139,9 @@ int stmmac_mdio_reset(struct mii_bus *bus)
unsigned int mii_address = priv->hw->mii.addr;
struct stmmac_mdio_bus_data *data = priv->plat->mdio_bus_data;
if (priv->early_eth)
return 0;
#ifdef CONFIG_OF
if (priv->device->of_node) {
if (data->reset_gpio < 0) {