* [PATCH net-next] net/core: move vlan_depth out of while loop in skb_network_protocol()
From: roy.qing.li @ 2013-03-12 6:30 UTC (permalink / raw)
To: netdev
From: Li RongQing <roy.qing.li@gmail.com>
move vlan_depth out of while loop, or else vlan_depth always is ETH_HLEN,
can not be increased, and lead to infinite loop when frame has two vlan headers.
Signed-off-by: Li RongQing <roy.qing.li@gmail.com>
---
net/core/dev.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/core/dev.c b/net/core/dev.c
index 90cee5b..35a6a6e 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2211,9 +2211,9 @@ EXPORT_SYMBOL(skb_checksum_help);
__be16 skb_network_protocol(struct sk_buff *skb)
{
__be16 type = skb->protocol;
+ int vlan_depth = ETH_HLEN;
while (type == htons(ETH_P_8021Q)) {
- int vlan_depth = ETH_HLEN;
struct vlan_hdr *vh;
if (unlikely(!pskb_may_pull(skb, vlan_depth + VLAN_HLEN)))
--
1.7.10.4
^ permalink raw reply related
* Re: [PATCH net-next 2/2] mv643xx_eth with 88E1318S: support Wake on LAN
From: Andrew Lunn @ 2013-03-12 5:59 UTC (permalink / raw)
To: Michael Stapelberg
Cc: netdev, Lennert Buytenhek, Andrew Lunn, Thomas Petazzoni
In-Reply-To: <1363045162-16606-2-git-send-email-michael@stapelberg.de>
On Tue, Mar 12, 2013 at 12:39:22AM +0100, Michael Stapelberg wrote:
> This has been tested on a qnap TS-119P II. Note that enabling WOL with
> "ethtool -s eth0 wol g" is not enough; you also need to tell the PIC
> microcontroller inside the qnap that WOL should be enabled by sending
> 0xF2 with qcontrol(1) and you have to disable EUP ("Energy-using
> Products", a European power-saving thing) by sending 0xF4.
>
> Signed-off-by: Michael Stapelberg <michael@stapelberg.de>
> ---
> drivers/net/ethernet/marvell/mv643xx_eth.c | 32 +++++++
> drivers/net/phy/marvell.c | 127 ++++++++++++++++++++++++++++
> 2 files changed, 159 insertions(+)
>
> diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c
> index 2914050..64a405e 100644
> --- a/drivers/net/ethernet/marvell/mv643xx_eth.c
> +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c
> @@ -20,6 +20,8 @@
> * Copyright (C) 2007-2008 Marvell Semiconductor
> * Lennert Buytenhek <buytenh@marvell.com>
> *
> + * Copyright (C) 2013 Michael Stapelberg <michael@stapelberg.de>
> + *
> * This program is free software; you can redistribute it and/or
> * modify it under the terms of the GNU General Public License
> * as published by the Free Software Foundation; either version 2
> @@ -1484,6 +1486,34 @@ mv643xx_eth_get_settings_phyless(struct mv643xx_eth_private *mp,
> return 0;
> }
>
> +static void
> +mv643xx_eth_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
> +{
> + struct mv643xx_eth_private *mp = netdev_priv(dev);
> + wol->supported = 0;
> + wol->wolopts = 0;
> + if (mp->phy)
> + phy_ethtool_get_wol(mp->phy, wol);
> +}
> +
> +static int
> +mv643xx_eth_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
> +{
> + struct mv643xx_eth_private *mp = netdev_priv(dev);
> + int err;
> +
> + if (mp->phy == NULL)
> + return -EOPNOTSUPP;
> +
> + err = phy_ethtool_set_wol(mp->phy, wol);
> + /* Given that mv643xx_eth works without the marvell-specific PHY driver,
> + * this debugging hint is useful to have.
> + */
> + if (err == -EOPNOTSUPP)
> + netdev_info(dev, "The PHY does not support set_wol, was CONFIG_MARVELL_PHY enabled?\n");
> + return err;
Hi Michael
I would not have this netdev_info() message. Only a few boxes are
going to have a PHY with this capability, so printing when it does not
is rather annoying. Either just return the error code, or make it a
netdev_dbg().
Andrew
^ permalink raw reply
* [PATCH 09/18] driver: isdn: hisax: remove cast for kmalloc/kzalloc return value
From: Zhang Yanfei @ 2013-03-12 5:15 UTC (permalink / raw)
To: Karsten Keil, Andrew Morton; +Cc: netdev, linux-kernel@vger.kernel.org
In-Reply-To: <513EB23D.7020303@cn.fujitsu.com>
remove cast for kmalloc/kzalloc return value.
Signed-off-by: Zhang Yanfei <zhangyanfei@cn.fujitsu.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Karsten Keil <isdn@linux-pingi.de>
Cc: netdev@vger.kernel.org
---
drivers/isdn/hisax/fsm.c | 2 +-
drivers/isdn/hisax/hfc_sx.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/isdn/hisax/fsm.c b/drivers/isdn/hisax/fsm.c
index 1bb2910..c7a9471 100644
--- a/drivers/isdn/hisax/fsm.c
+++ b/drivers/isdn/hisax/fsm.c
@@ -26,7 +26,7 @@ FsmNew(struct Fsm *fsm, struct FsmNode *fnlist, int fncount)
{
int i;
- fsm->jumpmatrix = (FSMFNPTR *)
+ fsm->jumpmatrix =
kzalloc(sizeof(FSMFNPTR) * fsm->state_count * fsm->event_count, GFP_KERNEL);
if (!fsm->jumpmatrix)
return -ENOMEM;
diff --git a/drivers/isdn/hisax/hfc_sx.c b/drivers/isdn/hisax/hfc_sx.c
index 90f34ae..dc4574f 100644
--- a/drivers/isdn/hisax/hfc_sx.c
+++ b/drivers/isdn/hisax/hfc_sx.c
@@ -1479,7 +1479,7 @@ int setup_hfcsx(struct IsdnCard *card)
release_region(cs->hw.hfcsx.base, 2);
return (0);
}
- if (!(cs->hw.hfcsx.extra = (void *)
+ if (!(cs->hw.hfcsx.extra =
kmalloc(sizeof(struct hfcsx_extra), GFP_ATOMIC))) {
release_region(cs->hw.hfcsx.base, 2);
printk(KERN_WARNING "HFC-SX: unable to allocate memory\n");
--
1.7.1
^ permalink raw reply related
* [PATCH 08/18] driver: isdn: capi: remove cast for kmalloc return value
From: Zhang Yanfei @ 2013-03-12 5:13 UTC (permalink / raw)
To: Karsten Keil, Andrew Morton; +Cc: netdev, linux-kernel@vger.kernel.org
In-Reply-To: <513EB23D.7020303@cn.fujitsu.com>
remove cast for kmalloc return value.
Signed-off-by: Zhang Yanfei <zhangyanfei@cn.fujitsu.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Karsten Keil <isdn@linux-pingi.de>
Cc: netdev@vger.kernel.org
---
drivers/isdn/capi/capidrv.c | 3 +--
1 files changed, 1 insertions(+), 2 deletions(-)
diff --git a/drivers/isdn/capi/capidrv.c b/drivers/isdn/capi/capidrv.c
index 832bc80..cc9f192 100644
--- a/drivers/isdn/capi/capidrv.c
+++ b/drivers/isdn/capi/capidrv.c
@@ -469,8 +469,7 @@ static int capidrv_add_ack(struct capidrv_ncci *nccip,
{
struct ncci_datahandle_queue *n, **pp;
- n = (struct ncci_datahandle_queue *)
- kmalloc(sizeof(struct ncci_datahandle_queue), GFP_ATOMIC);
+ n = kmalloc(sizeof(struct ncci_datahandle_queue), GFP_ATOMIC);
if (!n) {
printk(KERN_ERR "capidrv: kmalloc ncci_datahandle failed\n");
return -1;
--
1.7.1
^ permalink raw reply related
* Re: [net-next.git 4/9] stmmac: add the support for PTP hw clock driver
From: Rayagond K @ 2013-03-12 4:43 UTC (permalink / raw)
To: Richard Cochran; +Cc: Giuseppe CAVALLARO, netdev, bh74.an
In-Reply-To: <20130311185536.GA2409@netboy.at.omicron.at>
On Tue, Mar 12, 2013 at 12:25 AM, Richard Cochran
<richardcochran@gmail.com> wrote:
> On Sun, Mar 10, 2013 at 08:37:24PM +0530, Rayagond K wrote:
>> On Sun, Mar 10, 2013 at 5:40 PM, Richard Cochran <richardcochran@gmail.com>wrote:
>
>> > Don't you need locking here to protect against concurrent callers of
>> > config_addend?
>> >
>>
>> Yes we need locking here too, will add it.
>>
>> But I can see no locking in this function in other two driver'e
>> ppt_ixp46x.c and gianfar_ptp.c. So I just followed these two driver.
>
> Those two drivers don't need locking, because setting the addend
> register is a single 32 bit write operation in both cases.
>
> In your driver, setting the addend involves a sequence of writes and
> reads, in addition to polling a status bit, so you do need to
> serialize access to those registers.
Okay, will take lock in our driver. Thank you.
>
> Thanks,
> Richard
^ permalink raw reply
* Re: [PATCH linux-next v3] SUNRPC: rpcrdma_register_default_external: Dynamically allocate ib_phys_buf
From: Tom Tucker @ 2013-03-12 3:40 UTC (permalink / raw)
To: Tim Gardner
Cc: J. Bruce Fields, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
Trond Myklebust, David S. Miller, Tom Tucker, Haggai Eran,
Or Gerlitz, Shani Michaeli, linux-nfs-u79uwXL29TY76Z2rM5mHXA,
netdev-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <513E989E.8060206-Z7WLFzj8eWMS+FvcfC7Uqw@public.gmane.org>
Ah....Ok
On 3/11/13 9:53 PM, Tim Gardner wrote:
> On 03/11/2013 05:02 PM, Tom Tucker wrote:
>> On 3/11/13 4:25 PM, J. Bruce Fields wrote:
>
> <snip>
>
>>> Looks good to me; wish we could get it tested....
>>
>> I will test it. Tim could you please send me a final version that you'd
>> like tested as a single message?
>>
>
> I'm a little confused about what you are asking. I think v3 of the patch
> is the final version (unless you find bugs with it).
>
>> Would someone (like Tim maybe ... hint hint) look at tearing out all
>> those dead registration strategies? I don't think we need or will ever
>> use bounce-buffers, memory windows, or mlnx fmr. The only two that are
>> used and tested are all-phys and FRMR (the default).
>>
>
> Dunno if I'll get time for that. I had a one day window where I could
> hack out some simple patches. Now I'm back to the usual grindstone.
>
> rtg
--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH linux-next v3] SUNRPC: rpcrdma_register_default_external: Dynamically allocate ib_phys_buf
From: Tim Gardner @ 2013-03-12 2:53 UTC (permalink / raw)
To: Tom Tucker
Cc: J. Bruce Fields, linux-kernel, Trond Myklebust, David S. Miller,
Tom Tucker, Haggai Eran, Or Gerlitz, Shani Michaeli, linux-nfs,
netdev
In-Reply-To: <513E6271.3060107@opengridcomputing.com>
On 03/11/2013 05:02 PM, Tom Tucker wrote:
> On 3/11/13 4:25 PM, J. Bruce Fields wrote:
<snip>
>> Looks good to me; wish we could get it tested....
>
> I will test it. Tim could you please send me a final version that you'd
> like tested as a single message?
>
I'm a little confused about what you are asking. I think v3 of the patch
is the final version (unless you find bugs with it).
> Would someone (like Tim maybe ... hint hint) look at tearing out all
> those dead registration strategies? I don't think we need or will ever
> use bounce-buffers, memory windows, or mlnx fmr. The only two that are
> used and tested are all-phys and FRMR (the default).
>
Dunno if I'll get time for that. I had a one day window where I could
hack out some simple patches. Now I'm back to the usual grindstone.
rtg
--
Tim Gardner tim.gardner@canonical.com
^ permalink raw reply
* Re: [PATCH] mv643xx_eth: Fix a possible deadlock upon ifdown
From: Lennert Buytenhek @ 2013-03-12 2:49 UTC (permalink / raw)
To: Alexander Holler; +Cc: Lubomir Rintel, netdev, linux-kernel, Lubomir Rintel
In-Reply-To: <5130E5A5.90303@ahsoftware.de>
On Fri, Mar 01, 2013 at 06:30:13PM +0100, Alexander Holler wrote:
> >>From: Lubomir Rintel <lubo.rintel@gooddata.com>
> >>
> >>=================================
> >>[ INFO: inconsistent lock state ]
> >>3.7.0-6.luboskovo.fc19.armv5tel.kirkwood #1 Tainted: G W
> >>---------------------------------
> >>inconsistent {IN-SOFTIRQ-W} -> {SOFTIRQ-ON-W} usage.
> >>NetworkManager/337 [HC0[0]:SC0[0]:HE1:SE1] takes:
> >> (_xmit_ETHER#2){+.?...}, at: [<bf07adfc>] txq_reclaim+0x54/0x264 [mv643xx_eth]
>
> I get the same annoying warning when the MTU gets changed (through dhcp).
That is actually an issue.
> >Maybe I'm not reading it right, but I doubt that this is an actual
> >deadlock or that the patch is needed.
> >
> >txq_reclaim() indeed doesn't disable BHs, but that's because it's
> >always called in BH context. Almost always -- the only exception is
> >txq_deinit(), called from ->ndo_stop(), but by that time we've
> >already napi_disable()'d and netif_carrier_off()'d and free_irq()'d.
>
> Agreed. I've just read me through that too and don't think a
> deadlock is possible.
>
> >How to explain that to lockdep, though, I don't know.
>
> The patch helps with that. ;)
It fixes a bug (the MTU change thing) and a non-bug (the lockdep
warning) at the expense of slowing down the much more common path,
and I don't like it for that reason.
Can you make a __txq_reclaim() which is basically txq_reclaim()
without grabbing the tx queue lock, and then move the lock grabbing
to the caller?
E.g. make __txq_reclaim() have two callers, txq_reclaim() and
txq_reclaim_bh(), and then use the appropriate wrapper depending on
the context. (tx queue lock but no BH disable when called from
mv643xx_eth_poll(), tx queue lock plus BH disable for MTU change,
and no locking at all when called from ->ndo_stop(). Something
like that.)
^ permalink raw reply
* Re: [PATCH] sctp: don't break the loop while meeting the active_path so as to find the matched transport
From: Xufeng Zhang @ 2013-03-12 2:24 UTC (permalink / raw)
To: Neil Horman
Cc: Xufeng Zhang, vyasevich, davem, linux-sctp, netdev, linux-kernel
In-Reply-To: <20130311133121.GD12682@hmsreliant.think-freely.org>
>>
>> Thanks for your review, Neil!
>>
>> I know what you mean, yes, it's most probably that the searched TSN was
>> transmitted in the currently active_path, but what should we do if not.
>>
>> Check the comment in sctp_assoc_lookup_tsn() function:
>> /* Let's be hopeful and check the active_path first. */
>> /* If not found, go search all the other transports. */
>>
>> It has checked the active_path first and then traverse all the other
>> transports in
>> the transport_addr_list except the active_path.
>>
>> So what I want to fix here is the inconsistency between the function
>> should do and
>> the code actually does.
>>
> I understand what you're doing, and I agree that the fix is functional
> (Hence
> my "This works" statement in my last note). What I'm suggesting is that,
> since
> you're messing about in that code anyway that you clean it up while your at
> it,
> so that we don't need to have the if (transport == active) check at all.
> We
> trade in some extra work in a non-critical path (sctp_assoc_set_primary),
> for
> the removal of an extra for loop operation and a conditional check in a
> much
> hotter path. Something like this (completely untested), is what I was
> thinking
Aha, seems I have some misunderstanding previously, now I got your point.
Yeah, it's better to do the clean up by this way, and this fix looks fine to me,
but I didn't have a test case to test this, actually this problem was detected
by code review, so I would like to leave the rest of this work to
determine by you.
Thank you very much for your clarification!
Thanks,
Xufeng
>
>
> diff --git a/net/sctp/associola.c b/net/sctp/associola.c
> index 43cd0dd..8ae873c 100644
> --- a/net/sctp/associola.c
> +++ b/net/sctp/associola.c
> @@ -505,6 +505,9 @@ void sctp_assoc_set_primary(struct sctp_association
> *asoc,
>
> asoc->peer.primary_path = transport;
>
> + list_del_rcu(&transport->transports);
> + list_add_rcu(&transport->transports, &asoc->peer.transport_addr_list);
> +
> /* Set a default msg_name for events. */
> memcpy(&asoc->peer.primary_addr, &transport->ipaddr,
> sizeof(union sctp_addr));
> @@ -1040,7 +1043,6 @@ struct sctp_chunk *sctp_get_ecne_prepend(struct
> sctp_association *asoc)
> struct sctp_transport *sctp_assoc_lookup_tsn(struct sctp_association
> *asoc,
> __u32 tsn)
> {
> - struct sctp_transport *active;
> struct sctp_transport *match;
> struct sctp_transport *transport;
> struct sctp_chunk *chunk;
> @@ -1057,29 +1059,16 @@ struct sctp_transport *sctp_assoc_lookup_tsn(struct
> sctp_association *asoc,
> * The general strategy is to search each transport's transmitted
> * list. Return which transport this TSN lives on.
> *
> - * Let's be hopeful and check the active_path first.
> - * Another optimization would be to know if there is only one
> - * outbound path and not have to look for the TSN at all.
> + * Note, that sctp_assoc_set_primary does a move to front operation
> + * on the active_path transport, so this code implicitly checks
> + * the active_path first, as we most commonly expect to find our TSN
> + * there.
> *
> */
>
> - active = asoc->peer.active_path;
> -
> - list_for_each_entry(chunk, &active->transmitted,
> - transmitted_list) {
> -
> - if (key == chunk->subh.data_hdr->tsn) {
> - match = active;
> - goto out;
> - }
> - }
> -
> - /* If not found, go search all the other transports. */
> list_for_each_entry(transport, &asoc->peer.transport_addr_list,
> transports) {
>
> - if (transport == active)
> - break;
> list_for_each_entry(chunk, &transport->transmitted,
> transmitted_list) {
> if (key == chunk->subh.data_hdr->tsn) {
>
^ permalink raw reply
* Re: [PATCH] phydev: Add sysctl variable for polling interval of phy
From: 송은봉 @ 2013-03-12 2:21 UTC (permalink / raw)
To: Florian Fainelli
Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, bhutchings
Hello.
>Hello,
>On 03/11/2013 12:44 AM, EUNBONG SONG wrote:
>This patch should be submitted according to the rules described in:
>https://www.kernel.org/doc/Documentation/SubmittingPatches
Sorry, i made a mistake. so i rewrite the patches here.
---
drivers/net/phy/phy.c | 4 +++-
drivers/net/phy/phy_device.c | 43 ++++++++++++++++++++++++++++++++++++++++++
include/linux/phy.h | 1 -
3 files changed, 46 insertions(+), 2 deletions(-)
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index ef9ea92..11b773d 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -42,6 +42,8 @@
#include <asm/irq.h>
#include <asm/uaccess.h>
+extern unsigned int sysctl_phy_poll_interval;
+
/**
* phy_print_status - Convenience function to print out the current phy status
* @phydev: the phy_device struct
@@ -966,7 +968,7 @@ void phy_state_machine(struct work_struct *work)
if (err < 0)
phy_error(phydev);
- schedule_delayed_work(&phydev->state_queue, PHY_STATE_TIME * HZ);
+ schedule_delayed_work(&phydev->state_queue, msecs_to_jiffies(sysctl_phy_poll_interval));
}
static inline void mmd_phy_indirect(struct mii_bus *bus, int prtad, int devad,
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 3657b4a..4ed5368 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -33,6 +33,7 @@
#include <linux/mii.h>
#include <linux/ethtool.h>
#include <linux/phy.h>
+#include <linux/sysctl.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -42,6 +43,45 @@ MODULE_DESCRIPTION("PHY library");
MODULE_AUTHOR("Andy Fleming");
MODULE_LICENSE("GPL");
+unsigned int sysctl_phy_poll_interval = 1000;
+static unsigned int min_phy_poll_interval = 1;
+static unsigned int max_phy_poll_interval = 10000;
+
+static struct ctl_table_header *phy_table_header;
+
+static ctl_table phy_table[] = {
+ {
+ .procname = "phy_poll_interval",
+ .data = &sysctl_phy_poll_interval,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_minmax,
+ .extra1 = &min_phy_poll_interval,
+ .extra2 = &max_phy_poll_interval,
+ },
+ { }
+};
+
+static ctl_table phy_dir_table[] = {
+ {
+ .procname = "phy",
+ .maxlen = 0,
+ .mode = 0555,
+ .child = phy_table,
+ },
+ {}
+};
+
+static ctl_table phy_root_table[] = {
+ {
+ .procname = "dev",
+ .maxlen = 0,
+ .mode = 0555,
+ .child = phy_dir_table,
+ },
+ {}
+};
+
void phy_device_free(struct phy_device *phydev)
{
put_device(&phydev->dev);
@@ -1134,6 +1174,8 @@ static int __init phy_init(void)
if (rc)
mdio_bus_exit();
+ phy_table_header = register_sysctl_table(phy_root_table);
+
return rc;
}
@@ -1141,6 +1183,7 @@ static void __exit phy_exit(void)
{
phy_driver_unregister(&genphy_driver);
mdio_bus_exit();
+ unregister_sysctl_table(phy_table_header);
}
subsys_initcall(phy_init);
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 33999ad..0cbc1fe 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -68,7 +68,6 @@ typedef enum {
#define PHY_INIT_TIMEOUT 100000
-#define PHY_STATE_TIME 1
#define PHY_FORCE_TIMEOUT 10
#define PHY_AN_TIMEOUT 10
>Besides that, I do not think that a system-wide knob here is
>appropriate, you may rather introduce a new ethtool ioctl() to change
>the PHY device polling interval on a per-PHY device basis.
This patch follows current phy driver flow, "PHY_STATE_TIME" is system-wide variable for phy polling
interval. So i just replace "PHY_STATE_TIME" variable to sysctl variable.
And I think it's better as a system-wide variable, because we usually expect all phys has same reponse-time
to the change of state.
>Having said that don't your devices support a dedicated PHY interrupt
>line? This would definitively be the way to get better latency with
>respect to PHY events reported back to the host.
I usually do not interrupt because if phy state goes down, there are so many jobs for this.
For example, remove arp table entries for this port, remove all routing table entries for this port .
If we plug and unplug the physical port in very rapid speed, there could be so many interrupt events.
And this is not what we want.
>1 millisecond sounds like we are going to eat up a lot of CPU time
>polling PHY registers. Do you need that much reactivity?
I agree with you, 1 milliseconds is very harmful to cpu. But it's just a minimum value not a default value.
Actually, i'm not sure which minimum and maximum value is best. So i just take wide range.
Thanks
------- Original Message -------
Sender : Florian Fainelli<florian@openwrt.org>
Date : 2013-03-11 19:45 (GMT+09:00)
Title : Re: Fwd: [PATCH] phydev: Add sysctl variable for polling interval of phy
Hello,
On 03/11/2013 12:44 AM, EUNBONG SONG wrote:
>
> From d55a22be52e5a768409aa0999d6636cdfc369676 Mon Sep 17 00:00:00 2001
> From: eunbonsong
> Date: Sun, 10 Mar 2013 04:57:39 -0700
> Subject: [PATCH] phydev: Add sysctl variable for polling interval of phy state
>
> This adds a dev.phy.phy_poll_interval sysctl variable. This value is represented in milliseconds.
> And phy_state_machine() is scheduled as this variable.
> I think HZ is enough for PC. But sometimes especially in network devices
> such as switches,routers, needs more granularity for detecting phy state change.
This patch should be submitted according to the rules described in:
https://www.kernel.org/doc/Documentation/SubmittingPatches
Besides that, I do not think that a system-wide knob here is
appropriate, you may rather introduce a new ethtool ioctl() to change
the PHY device polling interval on a per-PHY device basis.
Having said that don't your devices support a dedicated PHY interrupt
line? This would definitively be the way to get better latency with
respect to PHY events reported back to the host.
>
>
> ---
> drivers/net/phy/phy.c | 4 +++-
> drivers/net/phy/phy_device.c | 43 ++++++++++++++++++++++++++++++++++++++++++
> include/linux/phy.h | 1 -
> 3 files changed, 46 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
> index ef9ea92..126a69f 100644
> --- a/drivers/net/phy/phy.c
> +++ b/drivers/net/phy/phy.c
> @@ -42,6 +42,8 @@
> #include
> #include
>
> +extern unsigned long sysctl_phy_poll_interval;
> +
> /**
> * phy_print_status - Convenience function to print out the current phy status
> * @phydev: the phy_device struct
> @@ -966,7 +968,7 @@ void phy_state_machine(struct work_struct *work)
> if (err < 0)
> phy_error(phydev);
>
> - schedule_delayed_work(&phydev->state_queue, PHY_STATE_TIME * HZ);
> + schedule_delayed_work(&phydev->state_queue, msecs_to_jiffies(sysctl_phy_poll_interval));
> }
>
> static inline void mmd_phy_indirect(struct mii_bus *bus, int prtad, int devad,
> diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
> index 3657b4a..c2697e2 100644
> --- a/drivers/net/phy/phy_device.c
> +++ b/drivers/net/phy/phy_device.c
> @@ -33,6 +33,7 @@
> #include
> #include
> #include
> +#include
>
> #include
> #include
> @@ -42,6 +43,45 @@ MODULE_DESCRIPTION("PHY library");
> MODULE_AUTHOR("Andy Fleming");
> MODULE_LICENSE("GPL");
>
> +unsigned long sysctl_phy_poll_interval = 1000;
> +static unsigned long min_phy_poll_interval = 1;
> +static unsigned long max_phy_poll_interval = 10000;
1 millisecond sounds like we are going to eat up a lot of CPU time
polling PHY registers. Do you need that much reactivity?
--
Florian
^ permalink raw reply related
* linux-next: manual merge of the net-next tree with Linus' tree
From: Stephen Rothwell @ 2013-03-12 0:33 UTC (permalink / raw)
To: David Miller, netdev
Cc: linux-next, linux-kernel, Konstantin Khlebnikov, Jeff Kirsher,
Bruce Allan
[-- Attachment #1: Type: text/plain, Size: 589 bytes --]
Hi all,
Today's linux-next merge of the net-next tree got a conflict in
drivers/net/ethernet/intel/e1000e/netdev.c between commits 4e0855dff094
("e1000e: fix pci-device enable-counter balance") and 66148babe728
("e1000e: fix runtime power management transitions") from Linus' tree and
commit f0ff439872e1 ("e1000e: cleanup CODE_INDENT checkpatch errors")
from the net-next tree.
The former removed the line fixed by the latter, so I did that and can
carry the fix as necessary (no action is required).
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply
* [PATCH net-next 1/2] phy: add set_wol/get_wol functions
From: Michael Stapelberg @ 2013-03-11 23:56 UTC (permalink / raw)
To: netdev; +Cc: Lennert Buytenhek, Andrew Lunn, Thomas Petazzoni,
Michael Stapelberg
This allows ethernet drivers (such as the mv643xx_eth) to support
Wake on LAN on platforms where PHY registers have to be configured
for Wake on LAN (e.g. the Marvell Kirkwood based qnap TS-119P II).
Signed-off-by: Michael Stapelberg <michael@stapelberg.de>
---
drivers/net/phy/phy.c | 16 ++++++++++++++++
include/linux/phy.h | 10 ++++++++++
2 files changed, 26 insertions(+)
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index ef9ea92..298b4c2 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -1188,3 +1188,19 @@ int phy_ethtool_set_eee(struct phy_device *phydev, struct ethtool_eee *data)
return 0;
}
EXPORT_SYMBOL(phy_ethtool_set_eee);
+
+int phy_ethtool_set_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol)
+{
+ if (phydev->drv->set_wol)
+ return phydev->drv->set_wol(phydev, wol);
+
+ return -EOPNOTSUPP;
+}
+EXPORT_SYMBOL(phy_ethtool_set_wol);
+
+void phy_ethtool_get_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol)
+{
+ if (phydev->drv->get_wol)
+ phydev->drv->get_wol(phydev, wol);
+}
+EXPORT_SYMBOL(phy_ethtool_get_wol);
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 33999ad..9e11039 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -455,6 +455,14 @@ struct phy_driver {
*/
void (*txtstamp)(struct phy_device *dev, struct sk_buff *skb, int type);
+ /* Some devices (e.g. qnap TS-119P II) require PHY register changes to
+ * enable Wake on LAN, so set_wol is provided to be called in the
+ * ethernet driver's set_wol function. */
+ int (*set_wol)(struct phy_device *dev, struct ethtool_wolinfo *wol);
+
+ /* See set_wol, but for checking whether Wake on LAN is enabled. */
+ void (*get_wol)(struct phy_device *dev, struct ethtool_wolinfo *wol);
+
struct device_driver driver;
};
#define to_phy_driver(d) container_of(d, struct phy_driver, driver)
@@ -560,6 +568,8 @@ int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable);
int phy_get_eee_err(struct phy_device *phydev);
int phy_ethtool_set_eee(struct phy_device *phydev, struct ethtool_eee *data);
int phy_ethtool_get_eee(struct phy_device *phydev, struct ethtool_eee *data);
+int phy_ethtool_set_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol);
+void phy_ethtool_get_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol);
int __init mdio_bus_init(void);
void mdio_bus_exit(void);
--
1.7.10.4
^ permalink raw reply related
* [PATCH net-next 2/2] mv643xx_eth with 88E1318S: support Wake on LAN
From: Michael Stapelberg @ 2013-03-11 23:56 UTC (permalink / raw)
To: netdev; +Cc: Lennert Buytenhek, Andrew Lunn, Thomas Petazzoni,
Michael Stapelberg
In-Reply-To: <1363046205-17239-1-git-send-email-michael@stapelberg.de>
This has been tested on a qnap TS-119P II. Note that enabling WOL with
"ethtool -s eth0 wol g" is not enough; you also need to tell the PIC
microcontroller inside the qnap that WOL should be enabled by sending
0xF2 with qcontrol(1) and you have to disable EUP ("Energy-using
Products", a European power-saving thing) by sending 0xF4.
Signed-off-by: Michael Stapelberg <michael@stapelberg.de>
---
drivers/net/ethernet/marvell/mv643xx_eth.c | 32 +++++++
drivers/net/phy/marvell.c | 127 ++++++++++++++++++++++++++++
2 files changed, 159 insertions(+)
diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c
index 2914050..64a405e 100644
--- a/drivers/net/ethernet/marvell/mv643xx_eth.c
+++ b/drivers/net/ethernet/marvell/mv643xx_eth.c
@@ -20,6 +20,8 @@
* Copyright (C) 2007-2008 Marvell Semiconductor
* Lennert Buytenhek <buytenh@marvell.com>
*
+ * Copyright (C) 2013 Michael Stapelberg <michael@stapelberg.de>
+ *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
@@ -1484,6 +1486,34 @@ mv643xx_eth_get_settings_phyless(struct mv643xx_eth_private *mp,
return 0;
}
+static void
+mv643xx_eth_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+ struct mv643xx_eth_private *mp = netdev_priv(dev);
+ wol->supported = 0;
+ wol->wolopts = 0;
+ if (mp->phy)
+ phy_ethtool_get_wol(mp->phy, wol);
+}
+
+static int
+mv643xx_eth_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+ struct mv643xx_eth_private *mp = netdev_priv(dev);
+ int err;
+
+ if (mp->phy == NULL)
+ return -EOPNOTSUPP;
+
+ err = phy_ethtool_set_wol(mp->phy, wol);
+ /* Given that mv643xx_eth works without the marvell-specific PHY driver,
+ * this debugging hint is useful to have.
+ */
+ if (err == -EOPNOTSUPP)
+ netdev_info(dev, "The PHY does not support set_wol, was CONFIG_MARVELL_PHY enabled?\n");
+ return err;
+}
+
static int
mv643xx_eth_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
@@ -1665,6 +1695,8 @@ static const struct ethtool_ops mv643xx_eth_ethtool_ops = {
.get_ethtool_stats = mv643xx_eth_get_ethtool_stats,
.get_sset_count = mv643xx_eth_get_sset_count,
.get_ts_info = ethtool_op_get_ts_info,
+ .get_wol = mv643xx_eth_get_wol,
+ .set_wol = mv643xx_eth_set_wol,
};
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index 22dec9c..b05ac6e 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -7,6 +7,8 @@
*
* Copyright (c) 2004 Freescale Semiconductor, Inc.
*
+ * Copyright (c) 2013 Michael Stapelberg <michael@stapelberg.de>
+ *
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
@@ -80,6 +82,28 @@
#define MII_88E1318S_PHY_MSCR1_REG 16
#define MII_88E1318S_PHY_MSCR1_PAD_ODD BIT(6)
+/* Copper Specific Interrupt Enable Register */
+#define MII_88E1318S_PHY_CSIER 0x12
+/* WOL Event Interrupt Enable */
+#define MII_88E1318S_PHY_CSIER_WOL_EIE BIT(7)
+
+/* LED Timer Control Register */
+#define MII_88E1318S_PHY_LED_PAGE 0x03
+#define MII_88E1318S_PHY_LED_TCR 0x12
+#define MII_88E1318S_PHY_LED_TCR_FORCE_INT BIT(15)
+#define MII_88E1318S_PHY_LED_TCR_INTn_ENABLE BIT(7)
+#define MII_88E1318S_PHY_LED_TCR_INT_ACTIVE_LOW BIT(11)
+
+/* Magic Packet MAC address registers */
+#define MII_88E1318S_PHY_MAGIC_PACKET_WORD2 0x17
+#define MII_88E1318S_PHY_MAGIC_PACKET_WORD1 0x18
+#define MII_88E1318S_PHY_MAGIC_PACKET_WORD0 0x19
+
+#define MII_88E1318S_PHY_WOL_PAGE 0x11
+#define MII_88E1318S_PHY_WOL_CTRL 0x10
+#define MII_88E1318S_PHY_WOL_CTRL_CLEAR_WOL_STATUS BIT(12)
+#define MII_88E1318S_PHY_WOL_CTRL_MAGIC_PACKET_MATCH_ENABLE BIT(14)
+
#define MII_88E1121_PHY_LED_CTRL 16
#define MII_88E1121_PHY_LED_PAGE 3
#define MII_88E1121_PHY_LED_DEF 0x0030
@@ -696,6 +720,107 @@ static int m88e1121_did_interrupt(struct phy_device *phydev)
return 0;
}
+static void m88e1318_get_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol)
+{
+ wol->supported = WAKE_MAGIC;
+ wol->wolopts = 0;
+
+ if (phy_write(phydev, MII_MARVELL_PHY_PAGE,
+ MII_88E1318S_PHY_WOL_PAGE) < 0)
+ return;
+
+ if (phy_read(phydev, MII_88E1318S_PHY_WOL_CTRL) &
+ MII_88E1318S_PHY_WOL_CTRL_MAGIC_PACKET_MATCH_ENABLE)
+ wol->wolopts |= WAKE_MAGIC;
+
+ if (phy_write(phydev, MII_MARVELL_PHY_PAGE, 0x00) < 0)
+ return;
+}
+
+static int m88e1318_set_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol)
+{
+ int err, oldpage, temp;
+
+ oldpage = phy_read(phydev, MII_MARVELL_PHY_PAGE);
+
+ if (wol->wolopts & WAKE_MAGIC) {
+ /* Explicitly switch to page 0x00, just to be sure */
+ err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 0x00);
+ if (err < 0)
+ return err;
+
+ /* Enable the WOL interrupt */
+ temp = phy_read(phydev, MII_88E1318S_PHY_CSIER);
+ temp |= MII_88E1318S_PHY_CSIER_WOL_EIE;
+ err = phy_write(phydev, MII_88E1318S_PHY_CSIER, temp);
+ if (err < 0)
+ return err;
+
+ err = phy_write(phydev, MII_MARVELL_PHY_PAGE,
+ MII_88E1318S_PHY_LED_PAGE);
+ if (err < 0)
+ return err;
+
+ /* Setup LED[2] as interrupt pin (active low) */
+ temp = phy_read(phydev, MII_88E1318S_PHY_LED_TCR);
+ temp &= ~MII_88E1318S_PHY_LED_TCR_FORCE_INT;
+ temp |= MII_88E1318S_PHY_LED_TCR_INTn_ENABLE;
+ temp |= MII_88E1318S_PHY_LED_TCR_INT_ACTIVE_LOW;
+ err = phy_write(phydev, MII_88E1318S_PHY_LED_TCR, temp);
+ if (err < 0)
+ return err;
+
+ err = phy_write(phydev, MII_MARVELL_PHY_PAGE,
+ MII_88E1318S_PHY_WOL_PAGE);
+ if (err < 0)
+ return err;
+
+ /* Store the device address for the magic packet */
+ err = phy_write(phydev, MII_88E1318S_PHY_MAGIC_PACKET_WORD2,
+ ((phydev->attached_dev->dev_addr[5] << 8) |
+ phydev->attached_dev->dev_addr[4]));
+ if (err < 0)
+ return err;
+ err = phy_write(phydev, MII_88E1318S_PHY_MAGIC_PACKET_WORD1,
+ ((phydev->attached_dev->dev_addr[3] << 8) |
+ phydev->attached_dev->dev_addr[2]));
+ if (err < 0)
+ return err;
+ err = phy_write(phydev, MII_88E1318S_PHY_MAGIC_PACKET_WORD0,
+ ((phydev->attached_dev->dev_addr[1] << 8) |
+ phydev->attached_dev->dev_addr[0]));
+ if (err < 0)
+ return err;
+
+ /* Clear WOL status and enable magic packet matching */
+ temp = phy_read(phydev, MII_88E1318S_PHY_WOL_CTRL);
+ temp |= MII_88E1318S_PHY_WOL_CTRL_CLEAR_WOL_STATUS;
+ temp |= MII_88E1318S_PHY_WOL_CTRL_MAGIC_PACKET_MATCH_ENABLE;
+ err = phy_write(phydev, MII_88E1318S_PHY_WOL_CTRL, temp);
+ if (err < 0)
+ return err;
+ } else {
+ err = phy_write(phydev, MII_MARVELL_PHY_PAGE,
+ MII_88E1318S_PHY_WOL_PAGE);
+ if (err < 0)
+ return err;
+
+ /* Clear WOL status and disable magic packet matching */
+ temp = phy_read(phydev, MII_88E1318S_PHY_WOL_CTRL);
+ temp |= MII_88E1318S_PHY_WOL_CTRL_CLEAR_WOL_STATUS;
+ temp &= ~MII_88E1318S_PHY_WOL_CTRL_MAGIC_PACKET_MATCH_ENABLE;
+ err = phy_write(phydev, MII_88E1318S_PHY_WOL_CTRL, temp);
+ if (err < 0)
+ return err;
+ }
+
+ err = phy_write(phydev, MII_MARVELL_PHY_PAGE, oldpage);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
static struct phy_driver marvell_drivers[] = {
{
.phy_id = MARVELL_PHY_ID_88E1101,
@@ -772,6 +897,8 @@ static struct phy_driver marvell_drivers[] = {
.ack_interrupt = &marvell_ack_interrupt,
.config_intr = &marvell_config_intr,
.did_interrupt = &m88e1121_did_interrupt,
+ .get_wol = &m88e1318_get_wol,
+ .set_wol = &m88e1318_set_wol,
.driver = { .owner = THIS_MODULE },
},
{
--
1.7.10.4
^ permalink raw reply related
* Re: [PATCH] print_rate: use knowledge in rate_suffix table for human readable rates.
From: Stephen Hemminger @ 2013-03-12 0:00 UTC (permalink / raw)
To: Vimalkumar; +Cc: netdev, shemminger, eric.dumazet
In-Reply-To: <1362885998-14292-1-git-send-email-j.vimal@gmail.com>
On Sat, 9 Mar 2013 19:26:38 -0800
Vimalkumar <j.vimal@gmail.com> wrote:
>
> Signed-off-by: Vimalkumar <j.vimal@gmail.com>
> ---
> tc/tc_util.c | 26 ++++++++++++--------------
> 1 files changed, 12 insertions(+), 14 deletions(-)
>
> diff --git a/tc/tc_util.c b/tc/tc_util.c
> index 0939536..6e68d87 100644
> --- a/tc/tc_util.c
> +++ b/tc/tc_util.c
> @@ -139,7 +139,8 @@ static const struct rate_suffix {
> { "GBps", 8000000000. },
> { "TiBps", 8.*1024.*1024.*1024.*1024. },
> { "TBps", 8000000000000. },
> - { NULL }
> + { NULL },
> + { NULL },
> };
>
>
> @@ -171,21 +172,18 @@ void print_rate(char *buf, int len, __u64 rate)
> {
> double tmp = (double)rate*8;
> extern int use_iec;
> + int start = 0;
> + const struct rate_suffix *s;
>
> if (use_iec) {
> - if (tmp >= 1000.0*1024.0*1024.0)
> - snprintf(buf, len, "%.0fMibit", tmp/(1024.0*1024.0));
> - else if (tmp >= 1000.0*1024)
> - snprintf(buf, len, "%.0fKibit", tmp/1024);
> - else
> - snprintf(buf, len, "%.0fbit", tmp);
> - } else {
> - if (tmp >= 1000.0*1000000.0)
> - snprintf(buf, len, "%.0fMbit", tmp/1000000.0);
> - else if (tmp >= 1000.0 * 1000.0)
> - snprintf(buf, len, "%.0fKbit", tmp/1000.0);
> - else
> - snprintf(buf, len, "%.0fbit", tmp);
> + start = 1;
> + }
> +
> + snprintf(buf, len, "%.0fbit", tmp);
> + for (s = &suffixes[start]; s->name; s += 2) {
> + if (tmp >= s->scale) {
> + snprintf(buf, len, "%.3f%s", tmp / s->scale, s->name);
> + }
> }
> }
>
Sorry, can't accept this because your patch loses functionality.
The iec flag was added for those people who
prefer iec (1024 bit) intervals. Your patch gets rid of that.
^ permalink raw reply
* [PATCH net] bridge: reserve space for IFLA_BRPORT_FAST_LEAVE
From: Stephen Hemminger @ 2013-03-11 23:52 UTC (permalink / raw)
To: David Miller; +Cc: netdev
The bridge multicast fast leave feature was added sufficient space
was not reserved in the netlink message. This means the flag may be
lost in netlink events and results of queries.
Found by observation while looking up some netlink stuff for discussion with Vlad.
Problem introduced by commit c2d3babfafbb9f6629cfb47139758e59a5eb0d80
Author: David S. Miller <davem@davemloft.net>
Date: Wed Dec 5 16:24:45 2012 -0500
bridge: implement multicast fast leave
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
Should go to net and stable for 3.8.X
--- a/net/bridge/br_netlink.c 2013-03-07 18:12:53.885287247 -0800
+++ b/net/bridge/br_netlink.c 2013-03-11 16:44:34.759166273 -0700
@@ -29,6 +29,7 @@ static inline size_t br_port_info_size(v
+ nla_total_size(1) /* IFLA_BRPORT_MODE */
+ nla_total_size(1) /* IFLA_BRPORT_GUARD */
+ nla_total_size(1) /* IFLA_BRPORT_PROTECT */
+ + nla_total_size(1) /* IFLA_BRPORT_FAST_LEAVE */
+ 0;
}
^ permalink raw reply
* RE
From: Ivor plenty @ 2013-03-11 23:38 UTC (permalink / raw)
I am Ivor plenty of Ivor Loan Firm.I give out loan at 1% interest rate.If interested,Apply now.
^ permalink raw reply
* Re: [PATCH linux-next v3] SUNRPC: rpcrdma_register_default_external: Dynamically allocate ib_phys_buf
From: Tom Tucker @ 2013-03-11 23:02 UTC (permalink / raw)
To: J. Bruce Fields
Cc: Tim Gardner, linux-kernel-u79uwXL29TY76Z2rM5mHXA, Trond Myklebust,
David S. Miller, Tom Tucker, Haggai Eran, Or Gerlitz,
Shani Michaeli, linux-nfs-u79uwXL29TY76Z2rM5mHXA,
netdev-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20130311212535.GG642-uC3wQj2KruNg9hUCZPvPmw@public.gmane.org>
On 3/11/13 4:25 PM, J. Bruce Fields wrote:
> On Mon, Mar 11, 2013 at 03:15:08PM -0600, Tim Gardner wrote:
>> rpcrdma_register_default_external() is several frames into the call stack which
>> goes deeper yet. You run the risk of stack corruption by declaring such a large
>> automatic variable, so move the array of 'struct ib_phys_buf' objects into the
>> transport structure 'struct rpcrdma_xprt' (which is dynamically allocated) in
>> order to silence the frame-larger-than warning. Access to each struct
>> rpcrdma_xprt is serialized by XPRT_LOCKED in xprt_reserve_xprt(), so there is
>> no danger of multiple accessors to the array of struct ib_phys_buf objects.
>>
>> net/sunrpc/xprtrdma/verbs.c: In function 'rpcrdma_register_default_external':
>> net/sunrpc/xprtrdma/verbs.c:1774:1: warning: the frame size of 1056 bytes is larger than 1024 bytes [-Wframe-larger-than=]
>>
>> gcc version 4.6.3
>>
>> Cc: Trond Myklebust <Trond.Myklebust-HgOvQuBEEgTQT0dZR+AlfA@public.gmane.org>
>> Cc: "J. Bruce Fields" <bfields-uC3wQj2KruNg9hUCZPvPmw@public.gmane.org>
>> Cc: "David S. Miller" <davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org>
>> Cc: Tom Tucker <tom-/Yg/VP3ZvrM@public.gmane.org>
>> Cc: Haggai Eran <haggaie-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
>> Cc: Or Gerlitz <ogerlitz-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
>> Cc: Shani Michaeli <shanim-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
>> Cc: linux-nfs-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
>> Cc: netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
>> Signed-off-by: Tim Gardner <tim.gardner-Z7WLFzj8eWMS+FvcfC7Uqw@public.gmane.org>
>> ---
>> v1 - Use kmalloc() to dynamically allocate and free the array of 'struct
>> ib_phys_buf' objects
>>
>> v2 - Move the array of 'struct ib_phys_buf' objects into struct rpcrdma_req
>> and pass this request down through rpcrdma_register_external() and
>> rpcrdma_register_default_external(). This is less overhead then using
>> kmalloc() and requires no extra error checking as the allocation burden is
>> shifted to the transport client.
>>
>> v3 - Move the array of 'struct ib_phys_buf' objects into struct rpcrdma_xprt.
>> Pass a pointer to this transport structure into rpcrdma_register_default_external().
>> This is less overhead then using kmalloc() and requires no extra error checking
>> as the allocation burden is shifted to the transport client.
> Looks good to me; wish we could get it tested....
I will test it. Tim could you please send me a final version that you'd
like tested as a single message?
Would someone (like Tim maybe ... hint hint) look at tearing out all those
dead registration strategies? I don't think we need or will ever use
bounce-buffers, memory windows, or mlnx fmr. The only two that are used
and tested are all-phys and FRMR (the default).
Tom
> In future if we do decide to also increase the size of that array we may
> need to allocate it separately from struct rpcrdma_xprt itself, which
> looks already fairly large without it; on x86_64:
>
> $ gdb net/sunrpc/xprtrdma/xprtrdma.ko
> ...
> (gdb) p sizeof(struct rpcrdma_xprt)
> $1 = 2912
>
> But that shouldn't be a big deal to do.
>
> --b.
>
>> net/sunrpc/xprtrdma/verbs.c | 10 ++++++----
>> net/sunrpc/xprtrdma/xprt_rdma.h | 5 ++++-
>> 2 files changed, 10 insertions(+), 5 deletions(-)
>>
>> diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c
>> index 93726560..c7aa3da 100644
>> --- a/net/sunrpc/xprtrdma/verbs.c
>> +++ b/net/sunrpc/xprtrdma/verbs.c
>> @@ -1730,13 +1730,14 @@ rpcrdma_deregister_memwin_external(struct rpcrdma_mr_seg *seg,
>> }
>>
>> static int
>> -rpcrdma_register_default_external(struct rpcrdma_mr_seg *seg,
>> - int *nsegs, int writing, struct rpcrdma_ia *ia)
>> +rpcrdma_register_default_external(struct rpcrdma_xprt *r_xprt,
>> + struct rpcrdma_mr_seg *seg, int *nsegs, int writing,
>> + struct rpcrdma_ia *ia)
>> {
>> int mem_priv = (writing ? IB_ACCESS_REMOTE_WRITE :
>> IB_ACCESS_REMOTE_READ);
>> struct rpcrdma_mr_seg *seg1 = seg;
>> - struct ib_phys_buf ipb[RPCRDMA_MAX_DATA_SEGS];
>> + struct ib_phys_buf *ipb = r_xprt->ipb;
>> int len, i, rc = 0;
>>
>> if (*nsegs > RPCRDMA_MAX_DATA_SEGS)
>> @@ -1827,7 +1828,8 @@ rpcrdma_register_external(struct rpcrdma_mr_seg *seg,
>>
>> /* Default registration each time */
>> default:
>> - rc = rpcrdma_register_default_external(seg, &nsegs, writing, ia);
>> + rc = rpcrdma_register_default_external(r_xprt, seg, &nsegs,
>> + writing, ia);
>> break;
>> }
>> if (rc)
>> diff --git a/net/sunrpc/xprtrdma/xprt_rdma.h b/net/sunrpc/xprtrdma/xprt_rdma.h
>> index cc1445d..d7b440f 100644
>> --- a/net/sunrpc/xprtrdma/xprt_rdma.h
>> +++ b/net/sunrpc/xprtrdma/xprt_rdma.h
>> @@ -269,7 +269,8 @@ struct rpcrdma_stats {
>> * for convenience. This structure need not be visible externally.
>> *
>> * It is allocated and initialized during mount, and released
>> - * during unmount.
>> + * during unmount. Access to this structure is serialized by XPRT_LOCKED
>> + * in xprt_reserve_xprt().
>> */
>> struct rpcrdma_xprt {
>> struct rpc_xprt xprt;
>> @@ -279,6 +280,8 @@ struct rpcrdma_xprt {
>> struct rpcrdma_create_data_internal rx_data;
>> struct delayed_work rdma_connect;
>> struct rpcrdma_stats rx_stats;
>> + /* temp work array */
>> + struct ib_phys_buf ipb[RPCRDMA_MAX_DATA_SEGS];
>> };
>>
>> #define rpcx_to_rdmax(x) container_of(x, struct rpcrdma_xprt, xprt)
>> --
>> 1.7.9.5
>>
--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 1/2] tcp: Tail loss probe (TLP)
From: Yuchung Cheng @ 2013-03-11 22:47 UTC (permalink / raw)
To: Nandita Dukkipati
Cc: David S. Miller, Neal Cardwell, Eric Dumazet, netdev,
Ilpo Jarvinen, Tom Herbert
In-Reply-To: <1363032044-27315-1-git-send-email-nanditad@google.com>
On Mon, Mar 11, 2013 at 4:00 PM, Nandita Dukkipati <nanditad@google.com> wrote:
> This patch series implement the Tail loss probe (TLP) algorithm described
> in http://tools.ietf.org/html/draft-dukkipati-tcpm-tcp-loss-probe-01. The
> first patch implements the basic algorithm.
>
> TLP's goal is to reduce tail latency of short transactions. It achieves
> this by converting retransmission timeouts (RTOs) occuring due
> to tail losses (losses at end of transactions) into fast recovery.
> TLP transmits one packet in two round-trips when a connection is in
> Open state and isn't receiving any ACKs. The transmitted packet, aka
> loss probe, can be either new or a retransmission. When there is tail
> loss, the ACK from a loss probe triggers FACK/early-retransmit based
> fast recovery, thus avoiding a costly RTO. In the absence of loss,
> there is no change in the connection state.
>
> PTO stands for probe timeout. It is a timer event indicating
> that an ACK is overdue and triggers a loss probe packet. The PTO value
> is set to max(2*SRTT, 10ms) and is adjusted to account for delayed
> ACK timer when there is only one oustanding packet.
>
> TLP Algorithm
>
> On transmission of new data in Open state:
> -> packets_out > 1: schedule PTO in max(2*SRTT, 10ms).
> -> packets_out == 1: schedule PTO in max(2*RTT, 1.5*RTT + 200ms)
> -> PTO = min(PTO, RTO)
>
> Conditions for scheduling PTO:
> -> Connection is in Open state.
> -> Connection is either cwnd limited or no new data to send.
> -> Number of probes per tail loss episode is limited to one.
> -> Connection is SACK enabled.
>
> When PTO fires:
> new_segment_exists:
> -> transmit new segment.
> -> packets_out++. cwnd remains same.
>
> no_new_packet:
> -> retransmit the last segment.
> Its ACK triggers FACK or early retransmit based recovery.
>
> ACK path:
> -> rearm RTO at start of ACK processing.
> -> reschedule PTO if need be.
>
> In addition, the patch includes a small variation to the Early Retransmit
> (ER) algorithm, such that ER and TLP together can in principle recover any
> N-degree of tail loss through fast recovery. TLP is controlled by the same
> sysctl as ER, tcp_early_retrans sysctl.
> tcp_early_retrans==0; disables TLP and ER.
> ==1; enables RFC5827 ER.
> ==2; delayed ER.
> ==3; TLP and delayed ER. [DEFAULT]
> ==4; TLP only.
>
> The TLP patch series have been extensively tested on Google Web servers.
> It is most effective for short Web trasactions, where it reduced RTOs by 15%
> and improved HTTP response time (average by 6%, 99th percentile by 10%).
> The transmitted probes account for <0.5% of the overall transmissions.
>
> Signed-off-by: Nandita Dukkipati <nanditad@google.com>
> ---
Acked-by: Yuchung Cheng <ycheng@google.com>
> Documentation/networking/ip-sysctl.txt | 8 ++-
> include/linux/tcp.h | 1 -
> include/net/inet_connection_sock.h | 5 +-
> include/net/tcp.h | 6 +-
> include/uapi/linux/snmp.h | 1 +
> net/ipv4/inet_diag.c | 4 +-
> net/ipv4/proc.c | 1 +
> net/ipv4/sysctl_net_ipv4.c | 4 +-
> net/ipv4/tcp_input.c | 24 ++++---
> net/ipv4/tcp_ipv4.c | 4 +-
> net/ipv4/tcp_output.c | 128 +++++++++++++++++++++++++++++++--
> net/ipv4/tcp_timer.c | 13 ++--
> 12 files changed, 171 insertions(+), 28 deletions(-)
>
> diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
> index dc2dc87..1cae6c3 100644
> --- a/Documentation/networking/ip-sysctl.txt
> +++ b/Documentation/networking/ip-sysctl.txt
> @@ -190,7 +190,9 @@ tcp_early_retrans - INTEGER
> Enable Early Retransmit (ER), per RFC 5827. ER lowers the threshold
> for triggering fast retransmit when the amount of outstanding data is
> small and when no previously unsent data can be transmitted (such
> - that limited transmit could be used).
> + that limited transmit could be used). Also controls the use of
> + Tail loss probe (TLP) that converts RTOs occuring due to tail
> + losses into fast recovery (draft-dukkipati-tcpm-tcp-loss-probe-01).
> Possible values:
> 0 disables ER
> 1 enables ER
> @@ -198,7 +200,9 @@ tcp_early_retrans - INTEGER
> by a fourth of RTT. This mitigates connection falsely
> recovers when network has a small degree of reordering
> (less than 3 packets).
> - Default: 2
> + 3 enables delayed ER and TLP.
> + 4 enables TLP only.
> + Default: 3
>
> tcp_ecn - INTEGER
> Control use of Explicit Congestion Notification (ECN) by TCP.
> diff --git a/include/linux/tcp.h b/include/linux/tcp.h
> index 515c374..01860d7 100644
> --- a/include/linux/tcp.h
> +++ b/include/linux/tcp.h
> @@ -201,7 +201,6 @@ struct tcp_sock {
> unused : 1;
> u8 repair_queue;
> u8 do_early_retrans:1,/* Enable RFC5827 early-retransmit */
> - early_retrans_delayed:1, /* Delayed ER timer installed */
> syn_data:1, /* SYN includes data */
> syn_fastopen:1, /* SYN includes Fast Open option */
> syn_data_acked:1;/* data in SYN is acked by SYN-ACK */
> diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h
> index 1832927..de2c785 100644
> --- a/include/net/inet_connection_sock.h
> +++ b/include/net/inet_connection_sock.h
> @@ -133,6 +133,8 @@ struct inet_connection_sock {
> #define ICSK_TIME_RETRANS 1 /* Retransmit timer */
> #define ICSK_TIME_DACK 2 /* Delayed ack timer */
> #define ICSK_TIME_PROBE0 3 /* Zero window probe timer */
> +#define ICSK_TIME_EARLY_RETRANS 4 /* Early retransmit timer */
> +#define ICSK_TIME_LOSS_PROBE 5 /* Tail loss probe timer */
>
> static inline struct inet_connection_sock *inet_csk(const struct sock *sk)
> {
> @@ -222,7 +224,8 @@ static inline void inet_csk_reset_xmit_timer(struct sock *sk, const int what,
> when = max_when;
> }
>
> - if (what == ICSK_TIME_RETRANS || what == ICSK_TIME_PROBE0) {
> + if (what == ICSK_TIME_RETRANS || what == ICSK_TIME_PROBE0 ||
> + what == ICSK_TIME_EARLY_RETRANS || what == ICSK_TIME_LOSS_PROBE) {
> icsk->icsk_pending = what;
> icsk->icsk_timeout = jiffies + when;
> sk_reset_timer(sk, &icsk->icsk_retransmit_timer, icsk->icsk_timeout);
> diff --git a/include/net/tcp.h b/include/net/tcp.h
> index a2baa5e..ab9f947 100644
> --- a/include/net/tcp.h
> +++ b/include/net/tcp.h
> @@ -543,6 +543,8 @@ extern bool tcp_syn_flood_action(struct sock *sk,
> extern void tcp_push_one(struct sock *, unsigned int mss_now);
> extern void tcp_send_ack(struct sock *sk);
> extern void tcp_send_delayed_ack(struct sock *sk);
> +extern void tcp_send_loss_probe(struct sock *sk);
> +extern bool tcp_schedule_loss_probe(struct sock *sk);
>
> /* tcp_input.c */
> extern void tcp_cwnd_application_limited(struct sock *sk);
> @@ -873,8 +875,8 @@ static inline void tcp_enable_fack(struct tcp_sock *tp)
> static inline void tcp_enable_early_retrans(struct tcp_sock *tp)
> {
> tp->do_early_retrans = sysctl_tcp_early_retrans &&
> - !sysctl_tcp_thin_dupack && sysctl_tcp_reordering == 3;
> - tp->early_retrans_delayed = 0;
> + sysctl_tcp_early_retrans < 4 && !sysctl_tcp_thin_dupack &&
> + sysctl_tcp_reordering == 3;
> }
>
> static inline void tcp_disable_early_retrans(struct tcp_sock *tp)
> diff --git a/include/uapi/linux/snmp.h b/include/uapi/linux/snmp.h
> index b49eab8..290bed6 100644
> --- a/include/uapi/linux/snmp.h
> +++ b/include/uapi/linux/snmp.h
> @@ -202,6 +202,7 @@ enum
> LINUX_MIB_TCPFORWARDRETRANS, /* TCPForwardRetrans */
> LINUX_MIB_TCPSLOWSTARTRETRANS, /* TCPSlowStartRetrans */
> LINUX_MIB_TCPTIMEOUTS, /* TCPTimeouts */
> + LINUX_MIB_TCPLOSSPROBES, /* TCPLossProbes */
> LINUX_MIB_TCPRENORECOVERYFAIL, /* TCPRenoRecoveryFail */
> LINUX_MIB_TCPSACKRECOVERYFAIL, /* TCPSackRecoveryFail */
> LINUX_MIB_TCPSCHEDULERFAILED, /* TCPSchedulerFailed */
> diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c
> index 7afa2c3..8620408 100644
> --- a/net/ipv4/inet_diag.c
> +++ b/net/ipv4/inet_diag.c
> @@ -158,7 +158,9 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
>
> #define EXPIRES_IN_MS(tmo) DIV_ROUND_UP((tmo - jiffies) * 1000, HZ)
>
> - if (icsk->icsk_pending == ICSK_TIME_RETRANS) {
> + if (icsk->icsk_pending == ICSK_TIME_RETRANS ||
> + icsk->icsk_pending == ICSK_TIME_EARLY_RETRANS ||
> + icsk->icsk_pending == ICSK_TIME_LOSS_PROBE) {
> r->idiag_timer = 1;
> r->idiag_retrans = icsk->icsk_retransmits;
> r->idiag_expires = EXPIRES_IN_MS(icsk->icsk_timeout);
> diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
> index 32030a2..4c35911 100644
> --- a/net/ipv4/proc.c
> +++ b/net/ipv4/proc.c
> @@ -224,6 +224,7 @@ static const struct snmp_mib snmp4_net_list[] = {
> SNMP_MIB_ITEM("TCPForwardRetrans", LINUX_MIB_TCPFORWARDRETRANS),
> SNMP_MIB_ITEM("TCPSlowStartRetrans", LINUX_MIB_TCPSLOWSTARTRETRANS),
> SNMP_MIB_ITEM("TCPTimeouts", LINUX_MIB_TCPTIMEOUTS),
> + SNMP_MIB_ITEM("TCPLossProbes", LINUX_MIB_TCPLOSSPROBES),
> SNMP_MIB_ITEM("TCPRenoRecoveryFail", LINUX_MIB_TCPRENORECOVERYFAIL),
> SNMP_MIB_ITEM("TCPSackRecoveryFail", LINUX_MIB_TCPSACKRECOVERYFAIL),
> SNMP_MIB_ITEM("TCPSchedulerFailed", LINUX_MIB_TCPSCHEDULERFAILED),
> diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
> index 960fd29..cca4550 100644
> --- a/net/ipv4/sysctl_net_ipv4.c
> +++ b/net/ipv4/sysctl_net_ipv4.c
> @@ -28,7 +28,7 @@
>
> static int zero;
> static int one = 1;
> -static int two = 2;
> +static int four = 4;
> static int tcp_retr1_max = 255;
> static int ip_local_port_range_min[] = { 1, 1 };
> static int ip_local_port_range_max[] = { 65535, 65535 };
> @@ -760,7 +760,7 @@ static struct ctl_table ipv4_table[] = {
> .mode = 0644,
> .proc_handler = proc_dointvec_minmax,
> .extra1 = &zero,
> - .extra2 = &two,
> + .extra2 = &four,
> },
> {
> .procname = "udp_mem",
> diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
> index 0d9bdac..b794f89 100644
> --- a/net/ipv4/tcp_input.c
> +++ b/net/ipv4/tcp_input.c
> @@ -98,7 +98,7 @@ int sysctl_tcp_frto_response __read_mostly;
> int sysctl_tcp_thin_dupack __read_mostly;
>
> int sysctl_tcp_moderate_rcvbuf __read_mostly = 1;
> -int sysctl_tcp_early_retrans __read_mostly = 2;
> +int sysctl_tcp_early_retrans __read_mostly = 3;
>
> #define FLAG_DATA 0x01 /* Incoming frame contained data. */
> #define FLAG_WIN_UPDATE 0x02 /* Incoming ACK was a window update. */
> @@ -2150,15 +2150,16 @@ static bool tcp_pause_early_retransmit(struct sock *sk, int flag)
> * max(RTT/4, 2msec) unless ack has ECE mark, no RTT samples
> * available, or RTO is scheduled to fire first.
> */
> - if (sysctl_tcp_early_retrans < 2 || (flag & FLAG_ECE) || !tp->srtt)
> + if (sysctl_tcp_early_retrans < 2 || sysctl_tcp_early_retrans > 3 ||
> + (flag & FLAG_ECE) || !tp->srtt)
> return false;
>
> delay = max_t(unsigned long, (tp->srtt >> 5), msecs_to_jiffies(2));
> if (!time_after(inet_csk(sk)->icsk_timeout, (jiffies + delay)))
> return false;
>
> - inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, delay, TCP_RTO_MAX);
> - tp->early_retrans_delayed = 1;
> + inet_csk_reset_xmit_timer(sk, ICSK_TIME_EARLY_RETRANS, delay,
> + TCP_RTO_MAX);
> return true;
> }
>
> @@ -2321,7 +2322,7 @@ static bool tcp_time_to_recover(struct sock *sk, int flag)
> * interval if appropriate.
> */
> if (tp->do_early_retrans && !tp->retrans_out && tp->sacked_out &&
> - (tp->packets_out == (tp->sacked_out + 1) && tp->packets_out < 4) &&
> + (tp->packets_out >= (tp->sacked_out + 1) && tp->packets_out < 4) &&
> !tcp_may_send_now(sk))
> return !tcp_pause_early_retransmit(sk, flag);
>
> @@ -3081,6 +3082,7 @@ static void tcp_cong_avoid(struct sock *sk, u32 ack, u32 in_flight)
> */
> void tcp_rearm_rto(struct sock *sk)
> {
> + const struct inet_connection_sock *icsk = inet_csk(sk);
> struct tcp_sock *tp = tcp_sk(sk);
>
> /* If the retrans timer is currently being used by Fast Open
> @@ -3094,12 +3096,13 @@ void tcp_rearm_rto(struct sock *sk)
> } else {
> u32 rto = inet_csk(sk)->icsk_rto;
> /* Offset the time elapsed after installing regular RTO */
> - if (tp->early_retrans_delayed) {
> + if (icsk->icsk_pending == ICSK_TIME_EARLY_RETRANS ||
> + icsk->icsk_pending == ICSK_TIME_LOSS_PROBE) {
> struct sk_buff *skb = tcp_write_queue_head(sk);
> const u32 rto_time_stamp = TCP_SKB_CB(skb)->when + rto;
> s32 delta = (s32)(rto_time_stamp - tcp_time_stamp);
> /* delta may not be positive if the socket is locked
> - * when the delayed ER timer fires and is rescheduled.
> + * when the retrans timer fires and is rescheduled.
> */
> if (delta > 0)
> rto = delta;
> @@ -3107,7 +3110,6 @@ void tcp_rearm_rto(struct sock *sk)
> inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, rto,
> TCP_RTO_MAX);
> }
> - tp->early_retrans_delayed = 0;
> }
>
> /* This function is called when the delayed ER timer fires. TCP enters
> @@ -3601,7 +3603,8 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
> if (after(ack, tp->snd_nxt))
> goto invalid_ack;
>
> - if (tp->early_retrans_delayed)
> + if (icsk->icsk_pending == ICSK_TIME_EARLY_RETRANS ||
> + icsk->icsk_pending == ICSK_TIME_LOSS_PROBE)
> tcp_rearm_rto(sk);
>
> if (after(ack, prior_snd_una))
> @@ -3678,6 +3681,9 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
> if (dst)
> dst_confirm(dst);
> }
> +
> + if (icsk->icsk_pending == ICSK_TIME_RETRANS)
> + tcp_schedule_loss_probe(sk);
> return 1;
>
> no_queue:
> diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
> index 8cdee12..b7ab868 100644
> --- a/net/ipv4/tcp_ipv4.c
> +++ b/net/ipv4/tcp_ipv4.c
> @@ -2703,7 +2703,9 @@ static void get_tcp4_sock(struct sock *sk, struct seq_file *f, int i, int *len)
> __u16 srcp = ntohs(inet->inet_sport);
> int rx_queue;
>
> - if (icsk->icsk_pending == ICSK_TIME_RETRANS) {
> + if (icsk->icsk_pending == ICSK_TIME_RETRANS ||
> + icsk->icsk_pending == ICSK_TIME_EARLY_RETRANS ||
> + icsk->icsk_pending == ICSK_TIME_LOSS_PROBE) {
> timer_active = 1;
> timer_expires = icsk->icsk_timeout;
> } else if (icsk->icsk_pending == ICSK_TIME_PROBE0) {
> diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
> index e2b4461..beb63db 100644
> --- a/net/ipv4/tcp_output.c
> +++ b/net/ipv4/tcp_output.c
> @@ -74,6 +74,7 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle,
> /* Account for new data that has been sent to the network. */
> static void tcp_event_new_data_sent(struct sock *sk, const struct sk_buff *skb)
> {
> + struct inet_connection_sock *icsk = inet_csk(sk);
> struct tcp_sock *tp = tcp_sk(sk);
> unsigned int prior_packets = tp->packets_out;
>
> @@ -85,7 +86,8 @@ static void tcp_event_new_data_sent(struct sock *sk, const struct sk_buff *skb)
> tp->frto_counter = 3;
>
> tp->packets_out += tcp_skb_pcount(skb);
> - if (!prior_packets || tp->early_retrans_delayed)
> + if (!prior_packets || icsk->icsk_pending == ICSK_TIME_EARLY_RETRANS ||
> + icsk->icsk_pending == ICSK_TIME_LOSS_PROBE)
> tcp_rearm_rto(sk);
> }
>
> @@ -1959,6 +1961,9 @@ static int tcp_mtu_probe(struct sock *sk)
> * snd_up-64k-mss .. snd_up cannot be large. However, taking into
> * account rare use of URG, this is not a big flaw.
> *
> + * Send at most one packet when push_one > 0. Temporarily ignore
> + * cwnd limit to force at most one packet out when push_one == 2.
> +
> * Returns true, if no segments are in flight and we have queued segments,
> * but cannot send anything now because of SWS or another problem.
> */
> @@ -1994,8 +1999,13 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle,
> goto repair; /* Skip network transmission */
>
> cwnd_quota = tcp_cwnd_test(tp, skb);
> - if (!cwnd_quota)
> - break;
> + if (!cwnd_quota) {
> + if (push_one == 2)
> + /* Force out a loss probe pkt. */
> + cwnd_quota = 1;
> + else
> + break;
> + }
>
> if (unlikely(!tcp_snd_wnd_test(tp, skb, mss_now)))
> break;
> @@ -2049,10 +2059,120 @@ repair:
> if (likely(sent_pkts)) {
> if (tcp_in_cwnd_reduction(sk))
> tp->prr_out += sent_pkts;
> +
> + /* Send one loss probe per tail loss episode. */
> + if (push_one != 2)
> + tcp_schedule_loss_probe(sk);
> tcp_cwnd_validate(sk);
> return false;
> }
> - return !tp->packets_out && tcp_send_head(sk);
> + return (push_one == 2) || (!tp->packets_out && tcp_send_head(sk));
> +}
> +
> +bool tcp_schedule_loss_probe(struct sock *sk)
> +{
> + struct inet_connection_sock *icsk = inet_csk(sk);
> + struct tcp_sock *tp = tcp_sk(sk);
> + u32 timeout, tlp_time_stamp, rto_time_stamp;
> + u32 rtt = tp->srtt >> 3;
> +
> + if (WARN_ON(icsk->icsk_pending == ICSK_TIME_EARLY_RETRANS))
> + return false;
> + /* No consecutive loss probes. */
> + if (WARN_ON(icsk->icsk_pending == ICSK_TIME_LOSS_PROBE)) {
> + tcp_rearm_rto(sk);
> + return false;
> + }
> + /* Don't do any loss probe on a Fast Open connection before 3WHS
> + * finishes.
> + */
> + if (sk->sk_state == TCP_SYN_RECV)
> + return false;
> +
> + /* TLP is only scheduled when next timer event is RTO. */
> + if (icsk->icsk_pending != ICSK_TIME_RETRANS)
> + return false;
> +
> + /* Schedule a loss probe in 2*RTT for SACK capable connections
> + * in Open state, that are either limited by cwnd or application.
> + */
> + if (sysctl_tcp_early_retrans < 3 || !rtt || !tp->packets_out ||
> + !tcp_is_sack(tp) || inet_csk(sk)->icsk_ca_state != TCP_CA_Open)
> + return false;
> +
> + if ((tp->snd_cwnd > tcp_packets_in_flight(tp)) &&
> + tcp_send_head(sk))
> + return false;
> +
> + /* Probe timeout is at least 1.5*rtt + TCP_DELACK_MAX to account
> + * for delayed ack when there's one outstanding packet.
> + */
> + timeout = rtt << 1;
> + if (tp->packets_out == 1)
> + timeout = max_t(u32, timeout,
> + (rtt + (rtt >> 1) + TCP_DELACK_MAX));
> + timeout = max_t(u32, timeout, msecs_to_jiffies(10));
> +
> + /* If RTO is shorter, just schedule TLP in its place. */
> + tlp_time_stamp = tcp_time_stamp + timeout;
> + rto_time_stamp = (u32)inet_csk(sk)->icsk_timeout;
> + if ((s32)(tlp_time_stamp - rto_time_stamp) > 0) {
> + s32 delta = rto_time_stamp - tcp_time_stamp;
> + if (delta > 0)
> + timeout = delta;
> + }
> +
> + inet_csk_reset_xmit_timer(sk, ICSK_TIME_LOSS_PROBE, timeout,
> + TCP_RTO_MAX);
> + return true;
> +}
> +
> +/* When probe timeout (PTO) fires, send a new segment if one exists, else
> + * retransmit the last segment.
> + */
> +void tcp_send_loss_probe(struct sock *sk)
> +{
> + struct sk_buff *skb;
> + int pcount;
> + int mss = tcp_current_mss(sk);
> + int err = -1;
> +
> + if (tcp_send_head(sk) != NULL) {
> + err = tcp_write_xmit(sk, mss, TCP_NAGLE_OFF, 2, GFP_ATOMIC);
> + goto rearm_timer;
> + }
> +
> + /* Retransmit last segment. */
> + skb = tcp_write_queue_tail(sk);
> + if (WARN_ON(!skb))
> + goto rearm_timer;
> +
> + pcount = tcp_skb_pcount(skb);
> + if (WARN_ON(!pcount))
> + goto rearm_timer;
> +
> + if ((pcount > 1) && (skb->len > (pcount - 1) * mss)) {
> + if (unlikely(tcp_fragment(sk, skb, (pcount - 1) * mss, mss)))
> + goto rearm_timer;
> + skb = tcp_write_queue_tail(sk);
> + }
> +
> + if (WARN_ON(!skb || !tcp_skb_pcount(skb)))
> + goto rearm_timer;
> +
> + /* Probe with zero data doesn't trigger fast recovery. */
> + if (skb->len > 0)
> + err = __tcp_retransmit_skb(sk, skb);
> +
> +rearm_timer:
> + inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
> + inet_csk(sk)->icsk_rto,
> + TCP_RTO_MAX);
> +
> + if (likely(!err))
> + NET_INC_STATS_BH(sock_net(sk),
> + LINUX_MIB_TCPLOSSPROBES);
> + return;
> }
>
> /* Push out any pending frames which were held back due to
> diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
> index b78aac3..ecd61d5 100644
> --- a/net/ipv4/tcp_timer.c
> +++ b/net/ipv4/tcp_timer.c
> @@ -342,10 +342,6 @@ void tcp_retransmit_timer(struct sock *sk)
> struct tcp_sock *tp = tcp_sk(sk);
> struct inet_connection_sock *icsk = inet_csk(sk);
>
> - if (tp->early_retrans_delayed) {
> - tcp_resume_early_retransmit(sk);
> - return;
> - }
> if (tp->fastopen_rsk) {
> WARN_ON_ONCE(sk->sk_state != TCP_SYN_RECV &&
> sk->sk_state != TCP_FIN_WAIT1);
> @@ -495,13 +491,20 @@ void tcp_write_timer_handler(struct sock *sk)
> }
>
> event = icsk->icsk_pending;
> - icsk->icsk_pending = 0;
>
> switch (event) {
> + case ICSK_TIME_EARLY_RETRANS:
> + tcp_resume_early_retransmit(sk);
> + break;
> + case ICSK_TIME_LOSS_PROBE:
> + tcp_send_loss_probe(sk);
> + break;
> case ICSK_TIME_RETRANS:
> + icsk->icsk_pending = 0;
> tcp_retransmit_timer(sk);
> break;
> case ICSK_TIME_PROBE0:
> + icsk->icsk_pending = 0;
> tcp_probe_timer(sk);
> break;
> }
> --
> 1.8.1.3
>
^ permalink raw reply
* Re: r8169 regression: UDP packets dropped intermittantly
From: Jonathan Woithe @ 2013-03-11 22:18 UTC (permalink / raw)
To: Francois Romieu; +Cc: netdev, Jonathan Woithe
In-Reply-To: <20130311000216.GA31808@zoreil.com>
This is following up on my response from a few days ago.
On Mon, Mar 11, 2013 at 01:02:16AM +0100, Francois Romieu wrote:
> Jonathan Woithe <jwoithe@atrad.com.au> :
> [...]
> > While we can rely on the retry system to paper over this regression, the
> > behaviour of earlier kernels suggests that there is a real issue at play.
> > Is there any chance that this can be looked at ?
> :
> Take it for what it's worth but I don't test much with PREEMPT, NOHZ or
> SLUB and I never tried all those at the same time.
I have now run tests to address this comment. Starting with the kernel
config I originally posted:
* turn off CONFIG_NO_HZ: problem still present.
* then turn off PREEMPT settings: problem still present.
* then change from SLUB to SLAB allocator: problem still present.
In conclusion, the problem still shows when the kernel is configured to use
SLAB without PREEMPT and NOHZ.
Regards
jonathan
^ permalink raw reply
* [PATCH] batman-adv: verify tt len does not exceed packet len
From: Antonio Quartulli @ 2013-03-11 22:12 UTC (permalink / raw)
To: davem; +Cc: netdev, b.a.t.m.a.n, Marek Lindner, Antonio Quartulli
In-Reply-To: <1363039948-27190-1-git-send-email-ordex@autistici.org>
From: Marek Lindner <lindner_marek@yahoo.de>
batadv_iv_ogm_process() accesses the packet using the tt_num_changes
attribute regardless of the real packet len (assuming the length check
was done before). Therefore a length check is needed to avoid reading
random memory.
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
Signed-off-by: Antonio Quartulli <ordex@autistici.org>
---
net/batman-adv/bat_iv_ogm.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
index a0b253e..a5bb0a7 100644
--- a/net/batman-adv/bat_iv_ogm.c
+++ b/net/batman-adv/bat_iv_ogm.c
@@ -1288,7 +1288,8 @@ static int batadv_iv_ogm_receive(struct sk_buff *skb,
batadv_ogm_packet = (struct batadv_ogm_packet *)packet_buff;
/* unpack the aggregated packets and process them one by one */
- do {
+ while (batadv_iv_ogm_aggr_packet(buff_pos, packet_len,
+ batadv_ogm_packet->tt_num_changes)) {
tt_buff = packet_buff + buff_pos + BATADV_OGM_HLEN;
batadv_iv_ogm_process(ethhdr, batadv_ogm_packet, tt_buff,
@@ -1299,8 +1300,7 @@ static int batadv_iv_ogm_receive(struct sk_buff *skb,
packet_pos = packet_buff + buff_pos;
batadv_ogm_packet = (struct batadv_ogm_packet *)packet_pos;
- } while (batadv_iv_ogm_aggr_packet(buff_pos, packet_len,
- batadv_ogm_packet->tt_num_changes));
+ }
kfree_skb(skb);
return NET_RX_SUCCESS;
--
1.8.1.5
^ permalink raw reply related
* pull request: batman-adv 2013-03-11
From: Antonio Quartulli @ 2013-03-11 22:12 UTC (permalink / raw)
To: davem; +Cc: netdev, b.a.t.m.a.n
Hello David,
This is a single fix intended for net/linux-3.9 brought by Marek Lindner.
It ensures that the incoming originator message parsing routine does not
try to read beyond the packet boundary causing it to process random data.
This bug is in since a while..Please, consider sending this patch to stable.
Please pull or let me know if there is any problem!
Thank you,
Antonio
The following changes since commit 7c6baa304b841673d3a55ea4fcf9a5cbf7a1674b:
Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip (2013-03-11 07:54:29 -0700)
are available in the git repository at:
git://git.open-mesh.org/linux-merge.git tags/batman-adv-fix-for-davem
for you to fetch changes up to b47506d91259c29b9c75c404737eb6525556f9b4:
batman-adv: verify tt len does not exceed packet len (2013-03-11 22:59:47 +0100)
----------------------------------------------------------------
Included changes ares:
- fix packet parsing routine to avoid to read beyond the packet boundary
----------------------------------------------------------------
Marek Lindner (1):
batman-adv: verify tt len does not exceed packet len
net/batman-adv/bat_iv_ogm.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
^ permalink raw reply
* [PATCH] iproute2: Document the -D and -I options
From: Eric W. Biederman @ 2013-03-11 21:59 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: netdev, Larry Baker
While looking into a sysctl regression in decnet on old kernels I
discovered this omission in the iproute2 documentation.
I can't imagine anyone's muscle memory remembering the longer forms.
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
---
ip/ip.c | 1 +
man/man8/ip.8 | 10 ++++++++++
2 files changed, 11 insertions(+), 0 deletions(-)
diff --git a/ip/ip.c b/ip/ip.c
index c3ff627..e10ddb2 100644
--- a/ip/ip.c
+++ b/ip/ip.c
@@ -48,6 +48,7 @@ static void usage(void)
" netns | l2tp | tcp_metrics }\n"
" OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] | -r[esolve] |\n"
" -f[amily] { inet | inet6 | ipx | dnet | bridge | link } |\n"
+" -4 | -6 | -I | -D | -B | -0 |\n"
" -l[oops] { maximum-addr-flush-attempts } |\n"
" -o[neline] | -t[imestamp] | -b[atch] [filename] |\n"
" -rc[vbuf] [size]}\n");
diff --git a/man/man8/ip.8 b/man/man8/ip.8
index 881e1ff..37f9988 100644
--- a/man/man8/ip.8
+++ b/man/man8/ip.8
@@ -82,6 +82,16 @@ shortcut for
.BR "\-family bridge" .
.TP
+.B \-D
+shortcut for
+.BR "\-family decnet" .
+
+.TP
+.B \-I
+shortcut for
+.BR "\-family ipx" .
+
+.TP
.B \-0
shortcut for
.BR "\-family link" .
--
1.7.5.4
^ permalink raw reply related
* Re: [PATCH 2/2] tcp: TLP loss detection.
From: Neal Cardwell @ 2013-03-11 21:38 UTC (permalink / raw)
To: Nandita Dukkipati
Cc: David S. Miller, Yuchung Cheng, Eric Dumazet, Netdev,
Ilpo Jarvinen, Tom Herbert
In-Reply-To: <1363032044-27315-2-git-send-email-nanditad@google.com>
On Mon, Mar 11, 2013 at 4:00 PM, Nandita Dukkipati <nanditad@google.com> wrote:
> This is the second of the TLP patch series; it augments the basic TLP
> algorithm with a loss detection scheme.
>
> This patch implements a mechanism for loss detection when a Tail
> loss probe retransmission plugs a hole thereby masking packet loss
> from the sender. The loss detection algorithm relies on counting
> TLP dupacks as outlined in Sec. 3 of:
> http://tools.ietf.org/html/draft-dukkipati-tcpm-tcp-loss-probe-01
>
> The basic idea is: Sender keeps track of TLP "episode" upon
> retransmission of a TLP packet. An episode ends when the sender receives
> an ACK above the SND.NXT (tracked by tlp_high_seq) at the time of the
> episode. We want to make sure that before the episode ends the sender
> receives a "TLP dupack", indicating that the TLP retransmission was
> unnecessary, so there was no loss/hole that needed plugging. If the
> sender gets no TLP dupack before the end of the episode, then it reduces
> ssthresh and the congestion window, because the TLP packet arriving at
> the receiver probably plugged a hole.
>
> Signed-off-by: Nandita Dukkipati <nanditad@google.com>
Acked-by: Neal Cardwell <ncardwell@google.com>
neal
^ permalink raw reply
* Re: [PATCH 1/2] tcp: Tail loss probe (TLP)
From: Neal Cardwell @ 2013-03-11 21:37 UTC (permalink / raw)
To: Nandita Dukkipati
Cc: David S. Miller, Yuchung Cheng, Eric Dumazet, Netdev,
Ilpo Jarvinen, Tom Herbert
In-Reply-To: <1363032044-27315-1-git-send-email-nanditad@google.com>
On Mon, Mar 11, 2013 at 4:00 PM, Nandita Dukkipati <nanditad@google.com> wrote:
> This patch series implement the Tail loss probe (TLP) algorithm described
> in http://tools.ietf.org/html/draft-dukkipati-tcpm-tcp-loss-probe-01. The
> first patch implements the basic algorithm.
>
> TLP's goal is to reduce tail latency of short transactions. It achieves
> this by converting retransmission timeouts (RTOs) occuring due
> to tail losses (losses at end of transactions) into fast recovery.
> TLP transmits one packet in two round-trips when a connection is in
> Open state and isn't receiving any ACKs. The transmitted packet, aka
> loss probe, can be either new or a retransmission. When there is tail
> loss, the ACK from a loss probe triggers FACK/early-retransmit based
> fast recovery, thus avoiding a costly RTO. In the absence of loss,
> there is no change in the connection state.
>
> PTO stands for probe timeout. It is a timer event indicating
> that an ACK is overdue and triggers a loss probe packet. The PTO value
> is set to max(2*SRTT, 10ms) and is adjusted to account for delayed
> ACK timer when there is only one oustanding packet.
>
> TLP Algorithm
>
> On transmission of new data in Open state:
> -> packets_out > 1: schedule PTO in max(2*SRTT, 10ms).
> -> packets_out == 1: schedule PTO in max(2*RTT, 1.5*RTT + 200ms)
> -> PTO = min(PTO, RTO)
>
> Conditions for scheduling PTO:
> -> Connection is in Open state.
> -> Connection is either cwnd limited or no new data to send.
> -> Number of probes per tail loss episode is limited to one.
> -> Connection is SACK enabled.
>
> When PTO fires:
> new_segment_exists:
> -> transmit new segment.
> -> packets_out++. cwnd remains same.
>
> no_new_packet:
> -> retransmit the last segment.
> Its ACK triggers FACK or early retransmit based recovery.
>
> ACK path:
> -> rearm RTO at start of ACK processing.
> -> reschedule PTO if need be.
>
> In addition, the patch includes a small variation to the Early Retransmit
> (ER) algorithm, such that ER and TLP together can in principle recover any
> N-degree of tail loss through fast recovery. TLP is controlled by the same
> sysctl as ER, tcp_early_retrans sysctl.
> tcp_early_retrans==0; disables TLP and ER.
> ==1; enables RFC5827 ER.
> ==2; delayed ER.
> ==3; TLP and delayed ER. [DEFAULT]
> ==4; TLP only.
>
> The TLP patch series have been extensively tested on Google Web servers.
> It is most effective for short Web trasactions, where it reduced RTOs by 15%
> and improved HTTP response time (average by 6%, 99th percentile by 10%).
> The transmitted probes account for <0.5% of the overall transmissions.
>
> Signed-off-by: Nandita Dukkipati <nanditad@google.com>
> ---
Acked-by: Neal Cardwell <ncardwell@google.com>
neal
^ permalink raw reply
* Re: [PATCH v5 25/44] tty: Fix recursive deadlock in tty_perform_flush()
From: Peter Hurley @ 2013-03-11 21:36 UTC (permalink / raw)
To: Peter Hurley
Cc: Greg Kroah-Hartman, Jiri Slaby, Sasha Levin, Dave Jones,
Sebastian Andrzej Siewior, Shawn Guo, linux-kernel, linux-serial,
Paul Mackerras, linux-ppp, netdev
In-Reply-To: <1363034704-28036-26-git-send-email-peter@hurleysoftware.com>
[ +cc Paul Mackerras, linux-ppp, netdev ]
I neglected to cc the proper folks. Sorry about that.
Regards,
Peter Hurley
On Mon, 2013-03-11 at 16:44 -0400, Peter Hurley wrote:
> tty_perform_flush() can deadlock when called while holding
> a line discipline reference. By definition, all ldisc drivers
> hold a ldisc reference, so calls originating from ldisc drivers
> must not block for a ldisc reference.
>
> The deadlock can occur when:
> CPU 0 | CPU 1
> |
> tty_ldisc_ref(tty) |
> .... | <line discipline halted>
> tty_ldisc_ref_wait(tty) |
> |
>
> CPU 0 cannot progess because it cannot obtain an ldisc reference
> with the line discipline has been halted (thus no new references
> are granted).
> CPU 1 cannot progress because an outstanding ldisc reference
> has not been released.
>
> An in-tree call-tree audit of tty_perform_flush() [1] shows 5
> ldisc drivers calling tty_perform_flush() indirectly via
> n_tty_ioctl_helper() and 2 ldisc drivers calling directly.
> A single tty driver safely uses the function.
>
> [1]
> Recursive usage:
>
> /* These functions are line discipline ioctls and thus
> * recursive wrt line discipline references */
>
> tty_perform_flush() - ./drivers/tty/tty_ioctl.c
> n_tty_ioctl_helper()
> hci_uart_tty_ioctl(default) - drivers/bluetooth/hci_ldisc.c (N_HCI)
> n_hdlc_tty_ioctl(default) - drivers/tty/n_hdlc.c (N_HDLC)
> gsmld_ioctl(default) - drivers/tty/n_gsm.c (N_GSM0710)
> n_tty_ioctl(default) - drivers/tty/n_tty.c (N_TTY)
> gigaset_tty_ioctl(default) - drivers/isdn/gigaset/ser-gigaset.c (N_GIGASET_M101)
> ppp_synctty_ioctl(TCFLSH) - drivers/net/ppp/pps_synctty.c
> ppp_asynctty_ioctl(TCFLSH) - drivers/net/ppp/ppp_async.c
>
> Non-recursive use:
>
> tty_perform_flush() - drivers/tty/tty_ioctl.c
> ipw_ioctl(TCFLSH) - drivers/tty/ipwireless/tty.c
> /* This function is a tty i/o ioctl method, which
> * is invoked by tty_ioctl() */
>
> Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
> ---
> drivers/net/ppp/ppp_async.c | 2 +-
> drivers/net/ppp/ppp_synctty.c | 2 +-
> drivers/tty/tty_ioctl.c | 28 +++++++++++++++++++---------
> 3 files changed, 21 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/net/ppp/ppp_async.c b/drivers/net/ppp/ppp_async.c
> index a031f6b..9c889e0 100644
> --- a/drivers/net/ppp/ppp_async.c
> +++ b/drivers/net/ppp/ppp_async.c
> @@ -314,7 +314,7 @@ ppp_asynctty_ioctl(struct tty_struct *tty, struct file *file,
> /* flush our buffers and the serial port's buffer */
> if (arg == TCIOFLUSH || arg == TCOFLUSH)
> ppp_async_flush_output(ap);
> - err = tty_perform_flush(tty, arg);
> + err = n_tty_ioctl_helper(tty, file, cmd, arg);
> break;
>
> case FIONREAD:
> diff --git a/drivers/net/ppp/ppp_synctty.c b/drivers/net/ppp/ppp_synctty.c
> index 1a12033..bdf3b13 100644
> --- a/drivers/net/ppp/ppp_synctty.c
> +++ b/drivers/net/ppp/ppp_synctty.c
> @@ -355,7 +355,7 @@ ppp_synctty_ioctl(struct tty_struct *tty, struct file *file,
> /* flush our buffers and the serial port's buffer */
> if (arg == TCIOFLUSH || arg == TCOFLUSH)
> ppp_sync_flush_output(ap);
> - err = tty_perform_flush(tty, arg);
> + err = n_tty_ioctl_helper(tty, file, cmd, arg);
> break;
>
> case FIONREAD:
> diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c
> index d58b92c..935b032 100644
> --- a/drivers/tty/tty_ioctl.c
> +++ b/drivers/tty/tty_ioctl.c
> @@ -1086,14 +1086,12 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
> }
> EXPORT_SYMBOL_GPL(tty_mode_ioctl);
>
> -int tty_perform_flush(struct tty_struct *tty, unsigned long arg)
> +
> +/* Caller guarantees ldisc reference is held */
> +static int __tty_perform_flush(struct tty_struct *tty, unsigned long arg)
> {
> - struct tty_ldisc *ld;
> - int retval = tty_check_change(tty);
> - if (retval)
> - return retval;
> + struct tty_ldisc *ld = tty->ldisc;
>
> - ld = tty_ldisc_ref_wait(tty);
> switch (arg) {
> case TCIFLUSH:
> if (ld && ld->ops->flush_buffer) {
> @@ -1111,12 +1109,24 @@ int tty_perform_flush(struct tty_struct *tty, unsigned long arg)
> tty_driver_flush_buffer(tty);
> break;
> default:
> - tty_ldisc_deref(ld);
> return -EINVAL;
> }
> - tty_ldisc_deref(ld);
> return 0;
> }
> +
> +int tty_perform_flush(struct tty_struct *tty, unsigned long arg)
> +{
> + struct tty_ldisc *ld;
> + int retval = tty_check_change(tty);
> + if (retval)
> + return retval;
> +
> + ld = tty_ldisc_ref_wait(tty);
> + retval = __tty_perform_flush(tty, arg);
> + if (ld)
> + tty_ldisc_deref(ld);
> + return retval;
> +}
> EXPORT_SYMBOL_GPL(tty_perform_flush);
>
> int n_tty_ioctl_helper(struct tty_struct *tty, struct file *file,
> @@ -1155,7 +1165,7 @@ int n_tty_ioctl_helper(struct tty_struct *tty, struct file *file,
> }
> return 0;
> case TCFLSH:
> - return tty_perform_flush(tty, arg);
> + return __tty_perform_flush(tty, arg);
> default:
> /* Try the mode commands */
> return tty_mode_ioctl(tty, file, cmd, arg);
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox