[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <50B55C46.9090400@free.fr>
Date: Wed, 28 Nov 2012 01:35:18 +0100
From: Stéphane ANCELOT <sancelot@...e.fr>
To: Francois Romieu <romieu@...zoreil.com>
CC: David Laight <David.Laight@...LAB.COM>,
Stéphane ANCELOT
<sancelot@...alliance.com>, netdev@...r.kernel.org,
Hayes Wang <hayeswang@...ltek.com>
Subject: Re: RTL 8169 linux driver question
On 27/11/2012 23:46, Francois Romieu wrote:
> David Laight <David.Laight@...LAB.COM> :
>> Stéphane ANCELOT <sancelot@...e.fr> :
>>> I had problem with it, my application sends a frame that is immediately
>>> transmitted back by some slaves, there was abnormally 100us lost
>>> between the send and receive call.
>>>
>>> Finally I found it was coming from the following register setup in the
>>> driver :
>>>
>>> RTL_W16(IntrMitigate, 0x5151);
>>>
>>> Can you give me some details about it, since I do not have the RTL8169
>>> programming guide.
>> That sounds like an 'interrupt mitigation' setting - which will cause
>> RX interrupts to be delayed a short time in order to reduce the
>> interrupt load on the kernel.
>>
>> There is usually an 'ethtool' setting to disable interrupt mitigation.
> Something like the patch below against net-next could help once I will
> have tested it.
>
> I completely guessed the Tx usec scale factor at gigabit speed (125 us,
> 100 us, disabled, who knows ?) and I have no idea which specific chipsets
> it should work with.
using 0x5151 value at 100mb FDX, I know it introduced exactly 100us
delay (Tx+Rx).
> Hayes, may I expect some hindsight regarding:
> 1 - the availability of the IntrMitigate (0xe2) register through the
> 8169, 8168 and 810x line of chipsets
> 2 - the Tx timer unit at gigabit speed
>
> It would save me some time.*
Hayes, it would have spared myself a lot of time ;-)
Have a look at what is driving this r8169 component :
http://www.youtube.com/watch?v=wj30CeAFwuk&feature=plcp
A question to nic components developers : I do not understand what
competitive advantage keeping these things like a secret....
These things are mostly boring for people and oem like myself at
Numalliance.
Regards,
Stephane Ancelot
> diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
> index 248f883..2623b73 100644
> --- a/drivers/net/ethernet/realtek/r8169.c
> +++ b/drivers/net/ethernet/realtek/r8169.c
> @@ -349,6 +349,12 @@ enum rtl_registers {
> RxMaxSize = 0xda,
> CPlusCmd = 0xe0,
> IntrMitigate = 0xe2,
> +
> +#define RTL_COALESCE_MASK 0x0f
> +#define RTL_COALESCE_SHIFT 4
> +#define RTL_COALESCE_T_MAX (RTL_COALESCE_MASK)
> +#define RTL_COALESCE_FRAME_MAX (RTL_COALESCE_MASK << 2)
> +
> RxDescAddrLow = 0xe4,
> RxDescAddrHigh = 0xe8,
> EarlyTxThres = 0xec, /* 8169. Unit of 32 bytes. */
> @@ -1997,10 +2003,121 @@ static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data)
> }
> }
>
> +static struct rtl_coalesce_scale {
> + u32 speed;
> + /* Rx / Tx */
> + u16 usecs[2];
> +} rtl_coalesce_info[] = {
> + { .speed = SPEED_10, .usecs = { 8000, 10000 } },
> + { .speed = SPEED_100, .usecs = { 1000, 1000 } },
> + { .speed = SPEED_1000, .usecs = { 125, 125 } }
> +};
> +
> +static struct rtl_coalesce_scale *rtl_coalesce_scale(struct net_device *dev)
> +{
> + struct ethtool_cmd ecmd;
> + int rc, i;
> +
> + rc = rtl8169_get_settings(dev, &ecmd);
> + if (rc < 0)
> + return ERR_PTR(rc);
> +
> + for (i = 0; i < ARRAY_SIZE(rtl_coalesce_info); i++) {
> + if (ethtool_cmd_speed(&ecmd) == rtl_coalesce_info[i].speed)
> + return rtl_coalesce_info + i;
> + }
> +
> + return ERR_PTR(-EINVAL);
> +}
> +
> +static int rtl_get_coalesce(struct net_device *dev, struct ethtool_coalesce *ec)
> +{
> + struct rtl8169_private *tp = netdev_priv(dev);
> + void __iomem *ioaddr = tp->mmio_addr;
> + struct rtl_coalesce_scale *scale;
> + struct {
> + u32 *max_frames;
> + u32 *usecs;
> + } coal_settings [] = {
> + { &ec->rx_max_coalesced_frames, &ec->rx_coalesce_usecs },
> + { &ec->tx_max_coalesced_frames, &ec->tx_coalesce_usecs }
> + }, *p = coal_settings;
> + int i;
> + u16 w;
> +
> + memset(ec, 0, sizeof(*ec));
> +
> + for (w = RTL_R16(IntrMitigate); w; w >>= RTL_COALESCE_SHIFT, p++) {
> + *p->max_frames = (w & RTL_COALESCE_MASK) << 2;
> + w >>= RTL_COALESCE_SHIFT;
> + *p->usecs = w & RTL_COALESCE_MASK;
> + }
> +
> + /* Except for null parameeters, the meaning of coalescing parameters
> + * depends on the link speed.
> + */
> + scale = rtl_coalesce_scale(dev);
> + if (PTR_ERR(scale) && (p != coal_settings))
> + return PTR_ERR(scale);
> +
> + for (i = 0; i < 2; i++) {
> + p = coal_settings + i;
> + *p->usecs *= scale->usecs[i];
> + if (!*p->usecs && !*p->max_frames)
> + *p->max_frames = 1;
> + }
> +
> + return 0;
> +}
> +
> +static int rtl_set_coalesce(struct net_device *dev, struct ethtool_coalesce *ec)
> +{
> + struct rtl8169_private *tp = netdev_priv(dev);
> + void __iomem *ioaddr = tp->mmio_addr;
> + struct rtl_coalesce_scale *scale;
> + struct {
> + u32 frames;
> + u32 usecs;
> + } coal_settings [] = {
> + { ec->rx_max_coalesced_frames, ec->rx_coalesce_usecs },
> + { ec->tx_max_coalesced_frames, ec->tx_coalesce_usecs }
> + }, *p = coal_settings;
> + int i, rc;
> + u16 w = 0;
> +
> + scale = rtl_coalesce_scale(dev);
> + rc = PTR_ERR(scale);
> +
> + for (i = 0; i < 2; i++) {
> + u32 units;
> +
> + if (!p->usecs && p->frames == 1)
> + continue;
> + if (rc < 0)
> + goto out;
> +
> + units = p->usecs / scale->usecs[i];
> + if (units > RTL_COALESCE_T_MAX || p->usecs % scale->usecs[i] ||
> + p->frames > RTL_COALESCE_FRAME_MAX || p->frames % 4)
> + return -EINVAL;
> +
> + w <<= RTL_COALESCE_SHIFT;
> + w |= units;
> + w <<= RTL_COALESCE_SHIFT;
> + w |= p->frames >> 2;
> + }
> +
> + RTL_W16(IntrMitigate, swab16(w));
> +out:
> + return rc;
> +}
> +
> static const struct ethtool_ops rtl8169_ethtool_ops = {
> .get_drvinfo = rtl8169_get_drvinfo,
> .get_regs_len = rtl8169_get_regs_len,
> .get_link = ethtool_op_get_link,
> + .get_coalesce = rtl_get_coalesce,
> + .set_coalesce = rtl_set_coalesce,
> .get_settings = rtl8169_get_settings,
> .set_settings = rtl8169_set_settings,
> .get_msglevel = rtl8169_get_msglevel,
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists