All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Stéphane ANCELOT" <sancelot@free.fr>
To: Francois Romieu <romieu@fr.zoreil.com>
Cc: "David Laight" <David.Laight@ACULAB.COM>,
	"Stéphane ANCELOT" <sancelot@numalliance.com>,
	netdev@vger.kernel.org, "Hayes Wang" <hayeswang@realtek.com>
Subject: Re: RTL 8169  linux driver question
Date: Wed, 28 Nov 2012 01:35:18 +0100	[thread overview]
Message-ID: <50B55C46.9090400@free.fr> (raw)
In-Reply-To: <20121127224605.GA10228@electric-eye.fr.zoreil.com>

On 27/11/2012 23:46, Francois Romieu wrote:
> David Laight <David.Laight@ACULAB.COM> :
>> Stéphane ANCELOT <sancelot@free.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,

  reply	other threads:[~2012-11-28  0:35 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <50AFC971.7010103@free.fr>
2012-11-23 19:14 ` Fwd: Re: RTL 8169 linux driver question Stéphane ANCELOT
2012-11-23 19:20   ` Francois Romieu
2012-11-26  7:35     ` Stéphane ANCELOT
2012-11-26  9:15   ` David Laight
2012-11-27 22:46     ` Francois Romieu
2012-11-28  0:35       ` Stéphane ANCELOT [this message]
2012-11-28  2:32       ` hayeswang
2012-11-28  9:33       ` David Laight
2012-11-28 23:18         ` Francois Romieu
2017-09-27 20:30           ` RTL8169 vs low-latency (was: Re: Re: RTL 8169 linux driver question) Kirill Smelkov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=50B55C46.9090400@free.fr \
    --to=sancelot@free.fr \
    --cc=David.Laight@ACULAB.COM \
    --cc=hayeswang@realtek.com \
    --cc=netdev@vger.kernel.org \
    --cc=romieu@fr.zoreil.com \
    --cc=sancelot@numalliance.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.