[PATCH 2/2] netdev/fec: fix performance impact from mdio poll operation
Eric Miao
eric.miao at canonical.com
Tue Apr 13 22:57:19 UTC 2010
On Wed, Apr 14, 2010 at 5:37 AM, Bryan Wu <bryan.wu at canonical.com> wrote:
> On 04/13/2010 12:09 PM, Andy Whitcroft wrote:
>> On Thu, Apr 08, 2010 at 02:44:59PM +0800, Bryan Wu wrote:
>>> BugLink: http://bugs.launchpad.net/bugs/546649
>>> BugLink: http://bugs.launchpad.net/bugs/457878
>>>
>>> After introducing phylib supporting, users experienced performace drop. That is
>>> because of the mdio polling operation of phylib. Use msleep to replace the busy
>>> waiting cpu_relax() and remove the warning message.
>>>
>>> Signed-off-by: Bryan Wu<bryan.wu at canonical.com>
>>> ---
>>> drivers/net/fec.c | 45 +++++++++++++++++++++------------------------
>>> 1 files changed, 21 insertions(+), 24 deletions(-)
>>>
>>> diff --git a/drivers/net/fec.c b/drivers/net/fec.c
>>> index 53240d3..2280373 100644
>>> --- a/drivers/net/fec.c
>>> +++ b/drivers/net/fec.c
>>> @@ -216,7 +216,7 @@ static void fec_stop(struct net_device *dev);
>>> #define FEC_MMFR_TA (2<< 16)
>>> #define FEC_MMFR_DATA(v) (v& 0xffff)
>>>
>>> -#define FEC_MII_TIMEOUT 10000
>>> +#define FEC_MII_TIMEOUT 10
>>>
>>> /* Transmitter timeout */
>>> #define TX_TIMEOUT (2 * HZ)
>>> @@ -624,13 +624,29 @@ spin_unlock:
>>> /*
>>> * NOTE: a MII transaction is during around 25 us, so polling it...
>>> */
>>> -static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
>>> +static int fec_enet_mdio_poll(struct fec_enet_private *fep)
>>> {
>>> - struct fec_enet_private *fep = bus->priv;
>>> int timeout = FEC_MII_TIMEOUT;
>>>
>>> fep->mii_timeout = 0;
>>>
>>> + /* wait for end of transfer */
>>> + while (!(readl(fep->hwp + FEC_IEVENT)& FEC_ENET_MII)) {
>>> + msleep(1);
>>> + if (timeout--< 0) {
>>> + fep->mii_timeout = 1;
>>> + break;
>>> + }
>>> + }
>>> +
This is ugly, I'd suggest wait_event_timeout(), though the response
time will be worse instead.
msleep(1) is almost equivalent on a system with HZ == 100.
>>> + return 0;
>>> +}
>>> +
>>> +static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
>>> +{
>>> + struct fec_enet_private *fep = bus->priv;
>>> +
>>> +
>>> /* clear MII end of transfer bit*/
>>> writel(FEC_ENET_MII, fep->hwp + FEC_IEVENT);
>>>
>>> @@ -639,15 +655,7 @@ static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
>>> FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(regnum) |
>>> FEC_MMFR_TA, fep->hwp + FEC_MII_DATA);
>>>
>>> - /* wait for end of transfer */
>>> - while (!(readl(fep->hwp + FEC_IEVENT)& FEC_ENET_MII)) {
>>> - cpu_relax();
>>> - if (timeout--< 0) {
>>> - fep->mii_timeout = 1;
>>> - printk(KERN_ERR "FEC: MDIO read timeout\n");
>>> - return -ETIMEDOUT;
>>> - }
>>> - }
I think polling will instead improve the performance (by waiting less once
the event happens), why is it causing performance drop instead?
>>> + fec_enet_mdio_poll(fep);
>>
>> You have pulled out this timeout loop, but in the replacement there is
>> not indication that it has timed-out. In the old code we would have
>> returned -ETIMEDOUT and not touched MII_DATA (below). In the new we
>> will timeout, mark mii_timeout but not return an indication of that, not
>> would we note it here, and so we would drop through and touch MII_DATA.
>> Is this an intentional change of semantics?
>>
>
> Since the timeout thing is not an error just a warning, the caller in phylib
> timer will call this function shortly and normally ignore the negative return
> value. I just looked up this busy timeout things in drivers/net/.
>
returning -1 is always a bad idea, -1 means -EPERM, which is strongly
undesirable. -ETIMEDOUT, I'd say, is a lot better in any sense.
> drivers/net/davinci_emac.c:
> it uses endless loop:
> /* Wait until mdio is ready for next command */
> #define MDIO_WAIT_FOR_USER_ACCESS\
> while ((emac_mdio_read((MDIO_USERACCESS(0))) &\
> MDIO_USERACCESS_GO) != 0)
>
>
> drivers/net/au1000_eth.c
> it returns -1 when timeout
>
> drivers/net/arm/at91_ether.c
> it is the same as us, don't return any thing if timeout.
>
> So actually, I am not sure about the return value requirement for this function.
> And I found several timeout warning when we do large file transfer. The hardware
> is not perfect.
>
> But I will try to check the return value of the poll function, and let you guys
> know the result.
>
> Thanks,
> -Bryan
>
> --
> kernel-team mailing list
> kernel-team at lists.ubuntu.com
> https://lists.ubuntu.com/mailman/listinfo/kernel-team
>
More information about the kernel-team
mailing list