[PATCH] drivers/net/: ll_temac_main.c & ll_temac.h: Adding ethtool interface

Grant Likely grant.likely at secretlab.ca
Fri Aug 27 05:26:22 EST 2010


On Thu, Aug 26, 2010 at 12:13 PM, Ville Sundell
<ville.sundell at digilent.ro> wrote:
> This patch adds an interface to the ethtool subsystem and
> implements read/write functionality for handling settings with the
> ethtool_cmd structure. "Speed" is the only setting implemented so far.
> Other settings (like reading the duplex value) can be easily implemented
> later on.
>
> One can read the speed of the link by reading /sys/class/net/eth0/speed.
> It seems that you can't write to /sys/class/net/eth0/speed, so the
> "ethtool" command line utility must be used to set the speed.
>
> So far, it is tested only in the DMA mode, since I don't have hardware
> with DCR available.
>
> Signed-off-by: Ville Sundell <ville.sundell at digilent.ro>

The ll_temac driver uses phylib.  The Ethtool ops should then also be
implemented using phylib and not by writing to the ll_temac registers
directly.  Otherwise changes to the ll_temac speed will not be
reflected in the PHY.

g.


> ---
>
> When using a non-static PHY and 100Mbit connection in Temac, the speed
> is not changed and stays at the reset value (1000Mbit). This leads to a
> situation where data is not sent or received correctly since
> temac_adjust_link() is not called due to lack of static PHY.  Therefore
> the link speed retains the reset value.
>
> There is also no possibility to read or set the link speed from the user
> space.
>
> The patch is done against the newest version of ll_temac_main.cc and
> ll_temac.h of the linux-next tree.
>
> Thanks to Michal Simek for his feedback on this patch!
>
> Regards,
> Ville Sundell
> Digilent Inc.
>
>  drivers/net/ll_temac.h      |    3 ++
>  drivers/net/ll_temac_main.c |   76 +++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 79 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/net/ll_temac.h b/drivers/net/ll_temac.h
> index 522abe2..ddd00cc 100644
> --- a/drivers/net/ll_temac.h
> +++ b/drivers/net/ll_temac.h
> @@ -247,6 +247,9 @@ This option defaults to enabled (set) */
>  #define XTE_EMCFG_LINKSPD_10           0x00000000 /* 10 Mbit LINKSPD_MASK */
>  #define XTE_EMCFG_LINKSPD_100          (1 << 30)  /* 100 Mbit LINKSPD_MASK */
>  #define XTE_EMCFG_LINKSPD_1000         (1 << 31)  /* 1000 Mbit LINKSPD_MASK */
> +#define XTE_EMCFG_LINKSPD_NA           0xC0000000 /* For undefined speed */
> +
> +#define TEMAC_SPEED_NA                 0 /* To indicate XTE_EMCFG_LINKSPD_NA */
>
>  #define XTE_GMIC_OFFSET                        0x00000320 /* RGMII/SGMII config */
>  #define XTE_MC_OFFSET                  0x00000340 /* MDIO configuration */
> diff --git a/drivers/net/ll_temac_main.c b/drivers/net/ll_temac_main.c
> index bdf2149..ae08fd4 100644
> --- a/drivers/net/ll_temac_main.c
> +++ b/drivers/net/ll_temac_main.c
> @@ -951,6 +951,81 @@ static const struct attribute_group temac_attr_group = {
>        .attrs = temac_device_attrs,
>  };
>
> +/* Ethtool interface implementation
> + * SETTINGS
> + * With the following functions below, you can
> + * read and set following settings:
> + * Speed:
> + *     Speed of the TEMAC controller is indicated by two most significant bits
> + *     in the XTE_EMCFG_OFFSET register in the follwoing way:
> + *     00 = 10 Mbit connection
> + *     01 = 100 Mbit connection
> + *     10 = 1000 Mbit connection
> + *     11 = Undefined connection speed
> +*/
> +
> +static int temac_get_settings(struct net_device *ndev, struct ethtool_cmd *cmd)
> +{
> +       struct temac_local *lp = netdev_priv(ndev);
> +       u32 reg = temac_indirect_in32(lp, XTE_EMCFG_OFFSET);
> +
> +       switch (reg & XTE_EMCFG_LINKSPD_MASK) {
> +       case XTE_EMCFG_LINKSPD_10:
> +               cmd->speed = SPEED_10;
> +               break;
> +       case XTE_EMCFG_LINKSPD_100:
> +               cmd->speed = SPEED_100;
> +               break;
> +       case XTE_EMCFG_LINKSPD_1000:
> +               cmd->speed = SPEED_1000;
> +               break;
> +       default:
> +               cmd->speed = TEMAC_SPEED_NA; /* Undefined speed */
> +               break;
> +       }
> +
> +       /* TODO: Insert more setting reading code here */
> +
> +       return 0;
> +}
> +
> +static int temac_set_settings(struct net_device *ndev, struct ethtool_cmd *cmd)
> +{
> +       struct temac_local *lp = netdev_priv(ndev);
> +       u32 reg = temac_indirect_in32(lp, XTE_EMCFG_OFFSET);
> +
> +       reg &= ~XTE_EMCFG_LINKSPD_MASK;
> +       switch (cmd->speed) {
> +       case SPEED_10:
> +               reg |= XTE_EMCFG_LINKSPD_10;
> +               break;
> +       case SPEED_100:
> +               reg |= XTE_EMCFG_LINKSPD_100;
> +               break;
> +       case SPEED_1000:
> +               reg |= XTE_EMCFG_LINKSPD_1000;
> +               break;
> +       default:
> +               reg |= XTE_EMCFG_LINKSPD_NA; /* Undefined speed */
> +               break;
> +       }
> +
> +       /* TODO: Insert more setting writing code here */
> +
> +       temac_indirect_out32(lp, XTE_EMCFG_OFFSET, reg);
> +
> +       return 0;
> +}
> +
> +/*
> + * Defining the ethtool operations.
> + * This will be passed to the ethtool subsystem in the probe function
> + */
> +static const struct ethtool_ops temac_ethtool_ops = {
> +       .get_settings = temac_get_settings,
> +       .set_settings = temac_set_settings,
> +};
> +
>  static int __init
>  temac_of_probe(struct platform_device *op, const struct of_device_id *match)
>  {
> @@ -970,6 +1045,7 @@ temac_of_probe(struct platform_device *op, const struct of_device_id *match)
>        ether_setup(ndev);
>        dev_set_drvdata(&op->dev, ndev);
>        SET_NETDEV_DEV(ndev, &op->dev);
> +       SET_ETHTOOL_OPS(ndev, &temac_ethtool_ops);
>        ndev->flags &= ~IFF_MULTICAST;  /* clear multicast */
>        ndev->features = NETIF_F_SG | NETIF_F_FRAGLIST;
>        ndev->netdev_ops = &temac_netdev_ops;
>
>
>



-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.


More information about the devicetree-discuss mailing list