* Re: [PATCH] net: qmi_wwan: add Huawei E173
From: David Miller @ 2012-11-28 16:24 UTC (permalink / raw)
To: bjorn; +Cc: netdev, linux-usb, tschaefer
In-Reply-To: <1353859439-18260-1-git-send-email-bjorn@mork.no>
From: Bjørn Mork <bjorn@mork.no>
Date: Sun, 25 Nov 2012 17:03:59 +0100
> The Huawei E173 is a QMI/wwan device which normally appear
> as 12d1:1436 in Linux. The descriptors displayed in that
> mode will be picked up by cdc_ether. But the modem has
> another mode with a different device ID and a slightly
> different set of descriptors. This is the mode used by
> Windows like this:
>
> 3Modem: USB\VID_12D1&PID_140C&MI_00\6&3A1D2012&0&0000
> Networkcard: USB\VID_12D1&PID_140C&MI_01\6&3A1D2012&0&0001
> Appli.Inter: USB\VID_12D1&PID_140C&MI_02\6&3A1D2012&0&0002
> PC UI Inter: USB\VID_12D1&PID_140C&MI_03\6&3A1D2012&0&0003
>
> Reported-by: Thomas Schäfer <tschaefer@t-online.de>
> Signed-off-by: Bjørn Mork <bjorn@mork.no>
Applied.
^ permalink raw reply
* Re: [PATCH] bonding: make arp_ip_target parameter checks consistent with sysfs
From: David Miller @ 2012-11-28 16:23 UTC (permalink / raw)
To: nikolay; +Cc: netdev, andy, fubar
In-Reply-To: <1353759675-30511-1-git-send-email-nikolay@redhat.com>
From: Nikolay Aleksandrov <nikolay@redhat.com>
Date: Sat, 24 Nov 2012 13:21:15 +0100
> @@ -4706,12 +4706,14 @@ static int bond_check_params(struct bond_params *params)
> arp_ip_count++) {
> /* not complete check, but should be good enough to
> catch mistakes */
> - if (!isdigit(arp_ip_target[arp_ip_count][0])) {
> + __be32 ip = in_aton(arp_ip_target[arp_ip_count]);
> + if (!isdigit(arp_ip_target[arp_ip_count][0])
> + || ip == 0
> + || ip == htonl(INADDR_BROADCAST)) {
Please format this properly, put the connecting operators at the end,
not the beginning, of the lines of the if statement, like so:
if (!isdigit(arp_ip_target[arp_ip_count][0]) ||
ip == 0 ||
ip == htonl(INADDR_BROADCAST)) {
Where else did you see the layout you used? It's not a prevalent
construct, so as far as I can tell you came up with it on your own.
Please don't do this, and instead use existing practice as your guide.
Thanks.
^ permalink raw reply
* Re: TCP and reordering
From: David Woodhouse @ 2012-11-28 16:21 UTC (permalink / raw)
To: Eric Dumazet; +Cc: Vijay Subramanian, David Miller, saku, rick.jones2, netdev
In-Reply-To: <1354118982.14302.356.camel@edumazet-glaptop>
[-- Attachment #1: Type: text/plain, Size: 1045 bytes --]
On Wed, 2012-11-28 at 08:09 -0800, Eric Dumazet wrote:
> My point was that if you limit number of in flight packet to 1,
> its relatively easy to add glue in the priv dev data, so that you chain
> the destructor without adding yet another fields in all skbs.
Hm, true. I do think we'll need to be able to have at least two packets
in-flight though. There's a fair amount of network stack to be navigated
by a skb once we release it, in the PPPoE and especially L2TP cases. The
latency involved in that, if we only allow one packet at a time, will
surely be noticeable. You're basically guaranteeing that a 'TX done' IRQ
won't have another packet in the device's queue ready to send, and you
won't be able to saturate the uplink.
I suppose your principle applies even for more than one skb at a time;
we can have an array of {skb, old_destructor} tuples in our per-channel
private state, rather than having to keep it with the skb itself... but
that's slightly less simple.
I'll go and knock something up...
--
dwmw2
[-- Attachment #2: smime.p7s --]
[-- Type: application/x-pkcs7-signature, Size: 6171 bytes --]
^ permalink raw reply
* Re: [PATCH] bonding: fix race condition in bonding_store_slaves_active
From: David Miller @ 2012-11-28 16:21 UTC (permalink / raw)
To: nikolay; +Cc: netdev, andy, fubar
In-Reply-To: <1353759595-30452-1-git-send-email-nikolay@redhat.com>
Some bonding developer reviews would be appreciated.
^ permalink raw reply
* Re: [PATCH] bonding: fix miimon and arp_interval delayed work race conditions
From: David Miller @ 2012-11-28 16:21 UTC (permalink / raw)
To: nikolay; +Cc: netdev, andy, fubar
In-Reply-To: <1353759471-30323-1-git-send-email-nikolay@redhat.com>
Bonding folks, please review.
^ permalink raw reply
* Re: [PATCH] pkt_sched: QFQ Plus: fair-queueing service at DRR cost
From: David Miller @ 2012-11-28 16:20 UTC (permalink / raw)
To: paolo.valente; +Cc: jhs, shemminger, linux-kernel, netdev, rizzo, fchecconi
In-Reply-To: <20121123210319.GA15775@paolo-ThinkPad-W520>
From: Paolo Valente <paolo.valente@unimore.it>
Date: Fri, 23 Nov 2012 22:03:19 +0100
> This patch turns QFQ into QFQ+, a variant of QFQ that provides the
> following two benefits: 1) QFQ+ is faster than QFQ, 2) differently
> from QFQ, QFQ+ correctly schedules also non-leaves classes in a
> hierarchical setting. A detailed description of QFQ+, plus a
> performance comparison with DRR and QFQ, can be found in [1].
>
> [1] P. Valente, "Reducing the Execution Time of Fair-Queueing Schedulers"
> http://algo.ing.unimo.it/people/paolo/agg-sched/agg-sched.pdf
>
> Signed-off-by: Paolo Valente <paolo.valente@unimore.it>
Applied, thanks.
^ permalink raw reply
* Re: TCP and reordering
From: Benjamin LaHaise @ 2012-11-28 16:19 UTC (permalink / raw)
To: David Woodhouse
Cc: Eric Dumazet, Vijay Subramanian, David Miller, saku, rick.jones2,
netdev
In-Reply-To: <1354117635.21562.63.camel@shinybook.infradead.org>
On Wed, Nov 28, 2012 at 03:47:15PM +0000, David Woodhouse wrote:
> On Wed, 2012-11-28 at 04:52 -0800, Eric Dumazet wrote:
> > BQL is nice for high speed adapters.
>
> For adapters with hugely deep queues, surely? There's a massive
> correlation between the two, of course ??? but PPP over L2TP or PPPoE
> ought to be included in the classification, right?
Possibly, but there are many setups where PPPoE/L2TP do not connect to
the congested link directly.
> > For slow one, you always can stop the queue for each packet given to
> > start_xmit()
> >
> > And restart the queue at TX completion.
>
> Well yes, but only if we get notified of TX completion.
>
> It's simple enough for the tty-based channels, and we can do it with a
> vcc->pop() function for PPPoATM. But for PPPoE and L2TP, how do we do
> it? We can install a skb destructor... but then we're stomping on TSQ's
> use of the destructor by orphaning it too soon.
>
> I'm pondering something along the lines of
>
> if (skb->destructor) {
> newskb = skb_clone(skb, GFP_KERNEL);
> if (newskb) {
> skb_shinfo(newskb) = skb;
> skb = newskb;
> }
> }
> skb_orphan(skb);
> skb->destructor = ppp_chan_tx_completed;
>
>
> ... and then ppp_chan_tx_completed can also destroy the original skb
> (and hence invoke TSQ's destructor too) when the time comes. And in the
> (common?) case where we don't have an existing destructor, we don't
> bother with the skb_clone.
This sort of chaining of destructors is going to be very expensive in
terms of CPU cycles. If this does get implemented, please ensure there is
a way to turn it off. Specifically, I'm thinking of the access concetrator
roles for BRAS. In many wholesale ISP setups, there are many incoming
sessions coming in over a high speed link (gigabit or greater) for which
the access concentrator (LAC/LNS in L2TP speak) has no idea of the
bandwidth of the link actually facing the customer. Such systems are
usually operated in a way to avoid ever congesting the aggregation network.
In such setups, BQL on the L2TP/PPPoE interface only serves to increase CPU
overhead.
That said, if there is local congestion, the benefits of BQL would be
worthwhile to have.
> But I wish there was a nicer way to chain destructors. And no, I don't
> count what GSO does. We can't use the cb here anyway since we're passing
> it down the stack.
I think all the tunneling protocols are going to have the same problem
here, so it deserves some thought about how to tackle the issue in a
generic way without incurring a large amount of overhead. This exact
problem is one of the reasons multilink PPP often doesn't work well over
L2TP or PPPoE as compared to its behaviour over ttys.
-ben
--
"Thought is the essence of where you are now."
^ permalink raw reply
* Re: [PATCH 0/6] smsc75xx enhancements
From: David Miller @ 2012-11-28 16:17 UTC (permalink / raw)
To: steve.glendinning; +Cc: netdev
In-Reply-To: <1354118391-22666-1-git-send-email-steve.glendinning@shawell.net>
From: Steve Glendinning <steve.glendinning@shawell.net>
Date: Wed, 28 Nov 2012 15:59:44 +0000
> This patchset implements wake on PHY (link up or link down) and
> USB dynamic autosuspend for smsc75xx.
>
> Please consider all for net-next.
All applied, thanks Steve.
^ permalink raw reply
* Re: [PATCH net] net/mlx4_en: Can set maxrate only for TC0
From: David Miller @ 2012-11-28 16:16 UTC (permalink / raw)
To: amirv; +Cc: ogerlitz, oren, netdev
In-Reply-To: <1354102995-27305-1-git-send-email-amirv@mellanox.com>
From: Amir Vadai <amirv@mellanox.com>
Date: Wed, 28 Nov 2012 13:43:15 +0200
> Had a typo in memcpy.
>
> Signed-off-by: Amir Vadai <amirv@mellanox.com>
Applied.
^ permalink raw reply
* Re: [PATCH] sctp: Error in calculation of RTTvar
From: David Miller @ 2012-11-28 16:13 UTC (permalink / raw)
To: vyasevich; +Cc: netdev
In-Reply-To: <1354115909-24172-1-git-send-email-vyasevich@gmail.com>
From: vyasevich@gmail.com
Date: Wed, 28 Nov 2012 10:18:29 -0500
> From: Schoch Christian <e0326715@student.tuwien.ac.at>
>
> The calculation of RTTVAR involves the subtraction of two unsigned
> numbers which
> may causes rollover and results in very high values of RTTVAR when RTT > SRTT.
> With this patch it is possible to set RTOmin = 1 to get the minimum of RTO at
> 4 times the clock granularity.
>
> Change Notes:
>
> v2)
> *Replaced abs() by abs64() and long by __s64, changed patch
> description.
>
> Signed-off-by: Christian Schoch <e0326715@student.tuwien.ac.at>
> CC: Vlad Yasevich <vyasevich@gmail.com>
> CC: Sridhar Samudrala <sri@us.ibm.com>
> CC: Neil Horman <nhorman@tuxdriver.com>
> CC: linux-sctp@vger.kernel.org
> Acked-by: Vlad Yasevich <vyasevich@gmail.com>
> Acked-by: Neil Horman <nhorman@tuxdriver.com>
Applied, thanks.
^ permalink raw reply
* [patch net] team: fix hw_features setup
From: Jiri Pirko @ 2012-11-28 16:13 UTC (permalink / raw)
To: netdev; +Cc: davem
Do this in the same way bonding does. This fixed setup resolves performance
issues when using some cards with certain offloading.
Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
drivers/net/team/team.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index d44cca3..ad86660 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -1794,10 +1794,12 @@ static void team_setup(struct net_device *dev)
dev->features |= NETIF_F_LLTX;
dev->features |= NETIF_F_GRO;
- dev->hw_features = NETIF_F_HW_VLAN_TX |
+ dev->hw_features = TEAM_VLAN_FEATURES |
+ NETIF_F_HW_VLAN_TX |
NETIF_F_HW_VLAN_RX |
NETIF_F_HW_VLAN_FILTER;
+ dev->hw_features &= ~(NETIF_F_ALL_CSUM & ~NETIF_F_HW_CSUM);
dev->features |= dev->hw_features;
}
--
1.7.11.7
^ permalink raw reply related
* Re: [PATCH] sctp: fix -ENOMEM result with invalid user space pointer in sendto() syscall
From: David Miller @ 2012-11-28 16:12 UTC (permalink / raw)
To: tt.rantala; +Cc: linux-sctp, netdev, nhorman, vyasevich, sri, davej
In-Reply-To: <1353590596-12216-1-git-send-email-tt.rantala@gmail.com>
From: Tommi Rantala <tt.rantala@gmail.com>
Date: Thu, 22 Nov 2012 15:23:16 +0200
> Consider the following program, that sets the second argument to the
> sendto() syscall incorrectly:
...
> We get -ENOMEM:
>
> $ strace -e sendto ./demo
> sendto(3, NULL, 1, 0, {sa_family=AF_INET, sin_port=htons(11111), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 ENOMEM (Cannot allocate memory)
>
> Propagate the error code from sctp_user_addto_chunk(), so that we will
> tell user space what actually went wrong:
>
> $ strace -e sendto ./demo
> sendto(3, NULL, 1, 0, {sa_family=AF_INET, sin_port=htons(11111), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 EFAULT (Bad address)
>
> Noticed while running Trinity (the syscall fuzzer).
>
> Signed-off-by: Tommi Rantala <tt.rantala@gmail.com>
Applied.
^ permalink raw reply
* Re: [PATCH] sctp: fix memory leak in sctp_datamsg_from_user() when copy from user space fails
From: David Miller @ 2012-11-28 16:11 UTC (permalink / raw)
To: tt.rantala; +Cc: linux-sctp, netdev, nhorman, vyasevich, sri, davej
In-Reply-To: <1354024906-1925-1-git-send-email-tt.rantala@gmail.com>
From: Tommi Rantala <tt.rantala@gmail.com>
Date: Tue, 27 Nov 2012 16:01:46 +0200
> Trinity (the syscall fuzzer) discovered a memory leak in SCTP,
> reproducible e.g. with the sendto() syscall by passing invalid
> user space pointer in the second argument:
...
> As far as I can tell, the leak has been around since ~2003.
>
> Signed-off-by: Tommi Rantala <tt.rantala@gmail.com>
Applied.
^ permalink raw reply
* Re: [PATCH 0/6] qlcnic: refactor 82xx adapter driver
From: David Miller @ 2012-11-28 16:10 UTC (permalink / raw)
To: sony.chacko; +Cc: netdev, Dept_NX_Linux_NIC_Driver
In-Reply-To: <1354113271-23850-1-git-send-email-sony.chacko@qlogic.com>
From: Sony Chacko <sony.chacko@qlogic.com>
Date: Wed, 28 Nov 2012 09:34:25 -0500
> From: Sony Chacko <sony.chacko@qlogic.com>
>
> Refactor 82xx adapter driver to create new files for:
> Data path routines.
> Sysfs interface routines.
> Hardware register dump utility.
>
> We are refactoring the driver code to add support for a new adapter.
> Existing 82xx driver code has coding style issues.
> Each physical refactoring patch is followed by a seperate patch
> to fix the style issues in the newly created file.
>
> Patches in the series are listed below.
> 0001-qlcnic-create-file-qlcnic_io.c-for-datapath-routines.patch
> 0002-qlcnic-fix-coding-style-issues-in-qlcnic_io.c.patch
> 0003-qlcnic-create-file-qlcnic_sysfs.c-for-sysfs-routines.patch
> 0004-qlcnic-fix-style-issues-in-qlcnic_sysfs.c-file.patch
> 0005-qlcnic-create-file-qlcnic_minidump.c-for-dump-utilit.patch
> 0006-qlcnic-fix-coding-style-issues-in-qlcnic_minidump.c.patch
>
> Please apply to net-next.
All applied, thanks.
^ permalink raw reply
* Re: TCP and reordering
From: Eric Dumazet @ 2012-11-28 16:09 UTC (permalink / raw)
To: David Woodhouse
Cc: Vijay Subramanian, David Miller, saku, rick.jones2, netdev
In-Reply-To: <1354117635.21562.63.camel@shinybook.infradead.org>
On Wed, 2012-11-28 at 15:47 +0000, David Woodhouse wrote:
> On Wed, 2012-11-28 at 04:52 -0800, Eric Dumazet wrote:
> > BQL is nice for high speed adapters.
>
> For adapters with hugely deep queues, surely? There's a massive
> correlation between the two, of course — but PPP over L2TP or PPPoE
> ought to be included in the classification, right?
>
> > For slow one, you always can stop the queue for each packet given to
> > start_xmit()
> >
> > And restart the queue at TX completion.
>
> Well yes, but only if we get notified of TX completion.
>
> It's simple enough for the tty-based channels, and we can do it with a
> vcc->pop() function for PPPoATM. But for PPPoE and L2TP, how do we do
> it? We can install a skb destructor... but then we're stomping on TSQ's
> use of the destructor by orphaning it too soon.
>
> I'm pondering something along the lines of
>
> if (skb->destructor) {
> newskb = skb_clone(skb, GFP_KERNEL);
> if (newskb) {
> skb_shinfo(newskb) = skb;
> skb = newskb;
> }
> }
> skb_orphan(skb);
> skb->destructor = ppp_chan_tx_completed;
>
>
> ... and then ppp_chan_tx_completed can also destroy the original skb
> (and hence invoke TSQ's destructor too) when the time comes. And in the
> (common?) case where we don't have an existing destructor, we don't
> bother with the skb_clone.
>
> But I wish there was a nicer way to chain destructors. And no, I don't
> count what GSO does. We can't use the cb here anyway since we're passing
> it down the stack.
>
My point was that if you limit number of in flight packet to 1,
its relatively easy to add glue in the priv dev data, so that you chain
the destructor without adding yet another fields in all skbs.
At start_xmit() do the following instead of skb_orphan(skb)
if (skb->destructor) {
BUG_ON(priv->save_destructor);
priv->save_destructor = skb->destructor;
priv->save_sk = skb->sk;
skb->sk = &priv->fake_sk;
}
skb->destructor = my_destructor;
/* stop the queue */
...
}
void my_destructor(struct sk_buff *skb)
{
struct .... *priv = container_of(skb, struct ..., priv.fake_sk);
skb->sk = skb->save_sk;
priv->save_destructor(skb);
priv->save_destructor = NULL;
/* restart the queue */
...
}
Something like that.
^ permalink raw reply
* Re: [net-next 0/7][pull request] Intel Wired LAN Driver Updates
From: David Miller @ 2012-11-28 16:05 UTC (permalink / raw)
To: jeffrey.t.kirsher; +Cc: netdev, gospo, sassmann
In-Reply-To: <1354107978-24731-1-git-send-email-jeffrey.t.kirsher@intel.com>
From: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Date: Wed, 28 Nov 2012 05:06:11 -0800
> This series contains updates to igb, igbvf and ixgbe.
>
> The following are changes since commit 03f52a0a554210d5049eeed9f1bb29047dc807cb:
> ip6mr: Add sizeof verification to MRT6_ASSERT and MT6_PIM
> and are available in the git repository at:
> git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net-next master
Pulled, thanks Jeff.
^ permalink raw reply
* Re: [PATCH net-next 0/9] bnx2x: Link changes
From: David Miller @ 2012-11-28 16:03 UTC (permalink / raw)
To: yanivr; +Cc: netdev
In-Reply-To: <1354023996-3512-1-git-send-email-yanivr@broadcom.com>
From: "Yaniv Rosner" <yanivr@broadcom.com>
Date: Tue, 27 Nov 2012 15:46:27 +0200
> The following patch series describe some link changes.
> Please consider applying it to net-next.
All applied, thank you.
^ permalink raw reply
* [PATCH 6/6] smsc75xx: don't enable remote wakeup directly
From: Steve Glendinning @ 2012-11-28 15:59 UTC (permalink / raw)
To: netdev; +Cc: Steve Glendinning, Bjorn Mork
In-Reply-To: <1354118391-22666-1-git-send-email-steve.glendinning@shawell.net>
As pointed out by Bjorn Mork, the generic "usb" driver sets this
for us so no need to directly set it in this driver.
Signed-off-by: Steve Glendinning <steve.glendinning@shawell.net>
Cc: Bjorn Mork <bjorn@mork.no>
---
drivers/net/usb/smsc75xx.c | 43 ++++++++-----------------------------------
1 file changed, 8 insertions(+), 35 deletions(-)
diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c
index b852c48..1823806 100644
--- a/drivers/net/usb/smsc75xx.c
+++ b/drivers/net/usb/smsc75xx.c
@@ -61,7 +61,6 @@
#define SUSPEND_SUSPEND1 (0x02)
#define SUSPEND_SUSPEND2 (0x04)
#define SUSPEND_SUSPEND3 (0x08)
-#define SUSPEND_REMOTEWAKE (0x10)
#define SUSPEND_ALLMODES (SUSPEND_SUSPEND0 | SUSPEND_SUSPEND1 | \
SUSPEND_SUSPEND2 | SUSPEND_SUSPEND3)
@@ -172,26 +171,6 @@ static int __must_check smsc75xx_write_reg(struct usbnet *dev, u32 index,
return __smsc75xx_write_reg(dev, index, data, 0);
}
-static int smsc75xx_set_feature(struct usbnet *dev, u32 feature)
-{
- if (WARN_ON_ONCE(!dev))
- return -EINVAL;
-
- return usbnet_write_cmd_nopm(dev, USB_REQ_SET_FEATURE,
- USB_DIR_OUT | USB_RECIP_DEVICE,
- feature, 0, NULL, 0);
-}
-
-static int smsc75xx_clear_feature(struct usbnet *dev, u32 feature)
-{
- if (WARN_ON_ONCE(!dev))
- return -EINVAL;
-
- return usbnet_write_cmd_nopm(dev, USB_REQ_CLEAR_FEATURE,
- USB_DIR_OUT | USB_RECIP_DEVICE,
- feature, 0, NULL, 0);
-}
-
/* Loop until the read is completed with timeout
* called with phy_mutex held */
static __must_check int __smsc75xx_phy_wait_not_busy(struct usbnet *dev,
@@ -674,8 +653,13 @@ static int smsc75xx_ethtool_set_wol(struct net_device *net,
{
struct usbnet *dev = netdev_priv(net);
struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
+ int ret;
pdata->wolopts = wolinfo->wolopts & SUPPORTED_WAKE;
+
+ ret = device_set_wakeup_enable(&dev->udev->dev, pdata->wolopts);
+ check_warn_return(ret, "device_set_wakeup_enable error %d\n", ret);
+
return 0;
}
@@ -1263,9 +1247,7 @@ static int smsc75xx_enter_suspend0(struct usbnet *dev)
ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
check_warn_return(ret, "Error writing PMT_CTL\n");
- smsc75xx_set_feature(dev, USB_DEVICE_REMOTE_WAKEUP);
-
- pdata->suspend_flags |= SUSPEND_SUSPEND0 | SUSPEND_REMOTEWAKE;
+ pdata->suspend_flags |= SUSPEND_SUSPEND0;
return 0;
}
@@ -1292,9 +1274,7 @@ static int smsc75xx_enter_suspend1(struct usbnet *dev)
ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
check_warn_return(ret, "Error writing PMT_CTL\n");
- smsc75xx_set_feature(dev, USB_DEVICE_REMOTE_WAKEUP);
-
- pdata->suspend_flags |= SUSPEND_SUSPEND1 | SUSPEND_REMOTEWAKE;
+ pdata->suspend_flags |= SUSPEND_SUSPEND1;
return 0;
}
@@ -1349,9 +1329,7 @@ static int smsc75xx_enter_suspend3(struct usbnet *dev)
ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
check_warn_return(ret, "Error writing PMT_CTL\n");
- smsc75xx_set_feature(dev, USB_DEVICE_REMOTE_WAKEUP);
-
- pdata->suspend_flags |= SUSPEND_SUSPEND3 | SUSPEND_REMOTEWAKE;
+ pdata->suspend_flags |= SUSPEND_SUSPEND3;
return 0;
}
@@ -1651,11 +1629,6 @@ static int smsc75xx_resume(struct usb_interface *intf)
/* do this first to ensure it's cleared even in error case */
pdata->suspend_flags = 0;
- if (suspend_flags & SUSPEND_REMOTEWAKE) {
- ret = smsc75xx_clear_feature(dev, USB_DEVICE_REMOTE_WAKEUP);
- check_warn_return(ret, "Error disabling remote wakeup\n");
- }
-
if (suspend_flags & SUSPEND_ALLMODES) {
/* Disable wakeup sources */
ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
--
1.7.10.4
^ permalink raw reply related
* [PATCH 5/6] smsc75xx: add support for USB dynamic autosuspend
From: Steve Glendinning @ 2012-11-28 15:59 UTC (permalink / raw)
To: netdev; +Cc: Steve Glendinning
In-Reply-To: <1354118391-22666-1-git-send-email-steve.glendinning@shawell.net>
This patch adds support for USB dynamic autosuspend to the
smsc75xx driver. This saves virtually no power in the USB
device but enables power savings in upstream hosts and
the host CPU.
Note currently Linux doesn't automatically enable this
functionality by default for devices so to test this:
echo auto > /sys/bus/usb/devices/2-1.2/power/control
where 2-1.2 is the USB bus address of the LAN7500.
Signed-off-by: Steve Glendinning <steve.glendinning@shawell.net>
---
drivers/net/usb/smsc75xx.c | 123 ++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 119 insertions(+), 4 deletions(-)
diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c
index 649bf2a..b852c48 100644
--- a/drivers/net/usb/smsc75xx.c
+++ b/drivers/net/usb/smsc75xx.c
@@ -57,6 +57,14 @@
#define SUPPORTED_WAKE (WAKE_PHY | WAKE_UCAST | WAKE_BCAST | \
WAKE_MCAST | WAKE_ARP | WAKE_MAGIC)
+#define SUSPEND_SUSPEND0 (0x01)
+#define SUSPEND_SUSPEND1 (0x02)
+#define SUSPEND_SUSPEND2 (0x04)
+#define SUSPEND_SUSPEND3 (0x08)
+#define SUSPEND_REMOTEWAKE (0x10)
+#define SUSPEND_ALLMODES (SUSPEND_SUSPEND0 | SUSPEND_SUSPEND1 | \
+ SUSPEND_SUSPEND2 | SUSPEND_SUSPEND3)
+
#define check_warn(ret, fmt, args...) \
({ if (ret < 0) netdev_warn(dev->net, fmt, ##args); })
@@ -74,6 +82,7 @@ struct smsc75xx_priv {
struct mutex dataport_mutex;
spinlock_t rfe_ctl_lock;
struct work_struct set_multicast;
+ u8 suspend_flags;
};
struct usb_context {
@@ -1241,6 +1250,7 @@ static int smsc75xx_write_wuff(struct usbnet *dev, int filter, u32 wuf_cfg,
static int smsc75xx_enter_suspend0(struct usbnet *dev)
{
+ struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
u32 val;
int ret;
@@ -1255,11 +1265,14 @@ static int smsc75xx_enter_suspend0(struct usbnet *dev)
smsc75xx_set_feature(dev, USB_DEVICE_REMOTE_WAKEUP);
+ pdata->suspend_flags |= SUSPEND_SUSPEND0 | SUSPEND_REMOTEWAKE;
+
return 0;
}
static int smsc75xx_enter_suspend1(struct usbnet *dev)
{
+ struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
u32 val;
int ret;
@@ -1281,11 +1294,14 @@ static int smsc75xx_enter_suspend1(struct usbnet *dev)
smsc75xx_set_feature(dev, USB_DEVICE_REMOTE_WAKEUP);
+ pdata->suspend_flags |= SUSPEND_SUSPEND1 | SUSPEND_REMOTEWAKE;
+
return 0;
}
static int smsc75xx_enter_suspend2(struct usbnet *dev)
{
+ struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
u32 val;
int ret;
@@ -1298,6 +1314,45 @@ static int smsc75xx_enter_suspend2(struct usbnet *dev)
ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
check_warn_return(ret, "Error writing PMT_CTL\n");
+ pdata->suspend_flags |= SUSPEND_SUSPEND2;
+
+ return 0;
+}
+
+static int smsc75xx_enter_suspend3(struct usbnet *dev)
+{
+ struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
+ u32 val;
+ int ret;
+
+ ret = smsc75xx_read_reg_nopm(dev, FCT_RX_CTL, &val);
+ check_warn_return(ret, "Error reading FCT_RX_CTL\n");
+
+ if (val & FCT_RX_CTL_RXUSED) {
+ netdev_dbg(dev->net, "rx fifo not empty in autosuspend\n");
+ return -EBUSY;
+ }
+
+ ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, &val);
+ check_warn_return(ret, "Error reading PMT_CTL\n");
+
+ val &= ~(PMT_CTL_SUS_MODE | PMT_CTL_WUPS | PMT_CTL_PHY_RST);
+ val |= PMT_CTL_SUS_MODE_3 | PMT_CTL_RES_CLR_WKP_EN;
+
+ ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
+ check_warn_return(ret, "Error writing PMT_CTL\n");
+
+ /* clear wol status */
+ val &= ~PMT_CTL_WUPS;
+ val |= PMT_CTL_WUPS_WOL;
+
+ ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
+ check_warn_return(ret, "Error writing PMT_CTL\n");
+
+ smsc75xx_set_feature(dev, USB_DEVICE_REMOTE_WAKEUP);
+
+ pdata->suspend_flags |= SUSPEND_SUSPEND3 | SUSPEND_REMOTEWAKE;
+
return 0;
}
@@ -1338,6 +1393,38 @@ static int smsc75xx_link_ok_nopm(struct usbnet *dev)
return !!(ret & BMSR_LSTATUS);
}
+static int smsc75xx_autosuspend(struct usbnet *dev, u32 link_up)
+{
+ int ret;
+
+ if (!netif_running(dev->net)) {
+ /* interface is ifconfig down so fully power down hw */
+ netdev_dbg(dev->net, "autosuspend entering SUSPEND2\n");
+ return smsc75xx_enter_suspend2(dev);
+ }
+
+ if (!link_up) {
+ /* link is down so enter EDPD mode */
+ netdev_dbg(dev->net, "autosuspend entering SUSPEND1\n");
+
+ /* enable PHY wakeup events for if cable is attached */
+ ret = smsc75xx_enable_phy_wakeup_interrupts(dev,
+ PHY_INT_MASK_ANEG_COMP);
+ check_warn_return(ret, "error enabling PHY wakeup ints\n");
+
+ netdev_info(dev->net, "entering SUSPEND1 mode\n");
+ return smsc75xx_enter_suspend1(dev);
+ }
+
+ /* enable PHY wakeup events so we remote wakeup if cable is pulled */
+ ret = smsc75xx_enable_phy_wakeup_interrupts(dev,
+ PHY_INT_MASK_LINK_DOWN);
+ check_warn_return(ret, "error enabling PHY wakeup ints\n");
+
+ netdev_dbg(dev->net, "autosuspend entering SUSPEND3\n");
+ return smsc75xx_enter_suspend3(dev);
+}
+
static int smsc75xx_suspend(struct usb_interface *intf, pm_message_t message)
{
struct usbnet *dev = usb_get_intfdata(intf);
@@ -1348,9 +1435,20 @@ static int smsc75xx_suspend(struct usb_interface *intf, pm_message_t message)
ret = usbnet_suspend(intf, message);
check_warn_goto_done(ret, "usbnet_suspend error\n");
+ if (pdata->suspend_flags) {
+ netdev_warn(dev->net, "error during last resume\n");
+ pdata->suspend_flags = 0;
+ }
+
/* determine if link is up using only _nopm functions */
link_up = smsc75xx_link_ok_nopm(dev);
+ if (message.event == PM_EVENT_AUTO_SUSPEND) {
+ ret = smsc75xx_autosuspend(dev, link_up);
+ goto done;
+ }
+
+ /* if we get this far we're not autosuspending */
/* if no wol options set, or if link is down and we're not waking on
* PHY activity, enter lowest power SUSPEND2 mode
*/
@@ -1544,14 +1642,21 @@ static int smsc75xx_resume(struct usb_interface *intf)
{
struct usbnet *dev = usb_get_intfdata(intf);
struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
+ u8 suspend_flags = pdata->suspend_flags;
int ret;
u32 val;
- if (pdata->wolopts) {
- netdev_info(dev->net, "resuming from SUSPEND0\n");
+ netdev_dbg(dev->net, "resume suspend_flags=0x%02x\n", suspend_flags);
- smsc75xx_clear_feature(dev, USB_DEVICE_REMOTE_WAKEUP);
+ /* do this first to ensure it's cleared even in error case */
+ pdata->suspend_flags = 0;
+
+ if (suspend_flags & SUSPEND_REMOTEWAKE) {
+ ret = smsc75xx_clear_feature(dev, USB_DEVICE_REMOTE_WAKEUP);
+ check_warn_return(ret, "Error disabling remote wakeup\n");
+ }
+ if (suspend_flags & SUSPEND_ALLMODES) {
/* Disable wakeup sources */
ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
check_warn_return(ret, "Error reading WUCSR\n");
@@ -1571,7 +1676,9 @@ static int smsc75xx_resume(struct usb_interface *intf)
ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
check_warn_return(ret, "Error writing PMT_CTL\n");
- } else {
+ }
+
+ if (suspend_flags & SUSPEND_SUSPEND2) {
netdev_info(dev->net, "resuming from SUSPEND2\n");
ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, &val);
@@ -1727,6 +1834,12 @@ static struct sk_buff *smsc75xx_tx_fixup(struct usbnet *dev,
return skb;
}
+static int smsc75xx_manage_power(struct usbnet *dev, int on)
+{
+ dev->intf->needs_remote_wakeup = on;
+ return 0;
+}
+
static const struct driver_info smsc75xx_info = {
.description = "smsc75xx USB 2.0 Gigabit Ethernet",
.bind = smsc75xx_bind,
@@ -1736,6 +1849,7 @@ static const struct driver_info smsc75xx_info = {
.rx_fixup = smsc75xx_rx_fixup,
.tx_fixup = smsc75xx_tx_fixup,
.status = smsc75xx_status,
+ .manage_power = smsc75xx_manage_power,
.flags = FLAG_ETHER | FLAG_SEND_ZLP | FLAG_LINK_INTR,
};
@@ -1763,6 +1877,7 @@ static struct usb_driver smsc75xx_driver = {
.reset_resume = smsc75xx_resume,
.disconnect = usbnet_disconnect,
.disable_hub_initiated_lpm = 1,
+ .supports_autosuspend = 1,
};
module_usb_driver(smsc75xx_driver);
--
1.7.10.4
^ permalink raw reply related
* [PATCH 4/6] smsc75xx: fix error handling in suspend failure case
From: Steve Glendinning @ 2012-11-28 15:59 UTC (permalink / raw)
To: netdev; +Cc: Steve Glendinning
In-Reply-To: <1354118391-22666-1-git-send-email-steve.glendinning@shawell.net>
This patch ensures that if we fail to suspend the LAN7500 device
we call usbnet_resume before returning failure, instead of
leaving the usbnet driver in an unusable state.
Signed-off-by: Steve Glendinning <steve.glendinning@shawell.net>
---
drivers/net/usb/smsc75xx.c | 69 ++++++++++++++++++++++++--------------------
1 file changed, 38 insertions(+), 31 deletions(-)
diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c
index 3e3b101..649bf2a 100644
--- a/drivers/net/usb/smsc75xx.c
+++ b/drivers/net/usb/smsc75xx.c
@@ -1346,7 +1346,7 @@ static int smsc75xx_suspend(struct usb_interface *intf, pm_message_t message)
int ret;
ret = usbnet_suspend(intf, message);
- check_warn_return(ret, "usbnet_suspend error\n");
+ check_warn_goto_done(ret, "usbnet_suspend error\n");
/* determine if link is up using only _nopm functions */
link_up = smsc75xx_link_ok_nopm(dev);
@@ -1360,28 +1360,29 @@ static int smsc75xx_suspend(struct usb_interface *intf, pm_message_t message)
/* disable energy detect (link up) & wake up events */
ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
- check_warn_return(ret, "Error reading WUCSR\n");
+ check_warn_goto_done(ret, "Error reading WUCSR\n");
val &= ~(WUCSR_MPEN | WUCSR_WUEN);
ret = smsc75xx_write_reg_nopm(dev, WUCSR, val);
- check_warn_return(ret, "Error writing WUCSR\n");
+ check_warn_goto_done(ret, "Error writing WUCSR\n");
ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, &val);
- check_warn_return(ret, "Error reading PMT_CTL\n");
+ check_warn_goto_done(ret, "Error reading PMT_CTL\n");
val &= ~(PMT_CTL_ED_EN | PMT_CTL_WOL_EN);
ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
- check_warn_return(ret, "Error writing PMT_CTL\n");
+ check_warn_goto_done(ret, "Error writing PMT_CTL\n");
- return smsc75xx_enter_suspend2(dev);
+ ret = smsc75xx_enter_suspend2(dev);
+ goto done;
}
if (pdata->wolopts & WAKE_PHY) {
ret = smsc75xx_enable_phy_wakeup_interrupts(dev,
(PHY_INT_MASK_ANEG_COMP | PHY_INT_MASK_LINK_DOWN));
- check_warn_return(ret, "error enabling PHY wakeup ints\n");
+ check_warn_goto_done(ret, "error enabling PHY wakeup ints\n");
/* if link is down then configure EDPD and enter SUSPEND1,
* otherwise enter SUSPEND0 below
@@ -1393,7 +1394,7 @@ static int smsc75xx_suspend(struct usb_interface *intf, pm_message_t message)
/* enable energy detect power-down mode */
ret = smsc75xx_mdio_read_nopm(dev->net, mii->phy_id,
PHY_MODE_CTRL_STS);
- check_warn_return(ret, "Error reading PHY_MODE_CTRL_STS\n");
+ check_warn_goto_done(ret, "Error reading PHY_MODE_CTRL_STS\n");
ret |= MODE_CTRL_STS_EDPWRDOWN;
@@ -1401,7 +1402,8 @@ static int smsc75xx_suspend(struct usb_interface *intf, pm_message_t message)
PHY_MODE_CTRL_STS, ret);
/* enter SUSPEND1 mode */
- return smsc75xx_enter_suspend1(dev);
+ ret = smsc75xx_enter_suspend1(dev);
+ goto done;
}
}
@@ -1411,7 +1413,7 @@ static int smsc75xx_suspend(struct usb_interface *intf, pm_message_t message)
/* disable all filters */
for (i = 0; i < WUF_NUM; i++) {
ret = smsc75xx_write_reg_nopm(dev, WUF_CFGX + i * 4, 0);
- check_warn_return(ret, "Error writing WUF_CFGX\n");
+ check_warn_goto_done(ret, "Error writing WUF_CFGX\n");
}
if (pdata->wolopts & WAKE_MCAST) {
@@ -1421,7 +1423,7 @@ static int smsc75xx_suspend(struct usb_interface *intf, pm_message_t message)
val = WUF_CFGX_EN | WUF_CFGX_ATYPE_MULTICAST
| smsc_crc(mcast, 3);
ret = smsc75xx_write_wuff(dev, filter++, val, 0x0007);
- check_warn_return(ret, "Error writing wakeup filter\n");
+ check_warn_goto_done(ret, "Error writing wakeup filter\n");
}
if (pdata->wolopts & WAKE_ARP) {
@@ -1431,106 +1433,111 @@ static int smsc75xx_suspend(struct usb_interface *intf, pm_message_t message)
val = WUF_CFGX_EN | WUF_CFGX_ATYPE_ALL | (0x0C << 16)
| smsc_crc(arp, 2);
ret = smsc75xx_write_wuff(dev, filter++, val, 0x0003);
- check_warn_return(ret, "Error writing wakeup filter\n");
+ check_warn_goto_done(ret, "Error writing wakeup filter\n");
}
/* clear any pending pattern match packet status */
ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
- check_warn_return(ret, "Error reading WUCSR\n");
+ check_warn_goto_done(ret, "Error reading WUCSR\n");
val |= WUCSR_WUFR;
ret = smsc75xx_write_reg_nopm(dev, WUCSR, val);
- check_warn_return(ret, "Error writing WUCSR\n");
+ check_warn_goto_done(ret, "Error writing WUCSR\n");
netdev_info(dev->net, "enabling packet match detection\n");
ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
- check_warn_return(ret, "Error reading WUCSR\n");
+ check_warn_goto_done(ret, "Error reading WUCSR\n");
val |= WUCSR_WUEN;
ret = smsc75xx_write_reg_nopm(dev, WUCSR, val);
- check_warn_return(ret, "Error writing WUCSR\n");
+ check_warn_goto_done(ret, "Error writing WUCSR\n");
} else {
netdev_info(dev->net, "disabling packet match detection\n");
ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
- check_warn_return(ret, "Error reading WUCSR\n");
+ check_warn_goto_done(ret, "Error reading WUCSR\n");
val &= ~WUCSR_WUEN;
ret = smsc75xx_write_reg_nopm(dev, WUCSR, val);
- check_warn_return(ret, "Error writing WUCSR\n");
+ check_warn_goto_done(ret, "Error writing WUCSR\n");
}
/* disable magic, bcast & unicast wakeup sources */
ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
- check_warn_return(ret, "Error reading WUCSR\n");
+ check_warn_goto_done(ret, "Error reading WUCSR\n");
val &= ~(WUCSR_MPEN | WUCSR_BCST_EN | WUCSR_PFDA_EN);
ret = smsc75xx_write_reg_nopm(dev, WUCSR, val);
- check_warn_return(ret, "Error writing WUCSR\n");
+ check_warn_goto_done(ret, "Error writing WUCSR\n");
if (pdata->wolopts & WAKE_PHY) {
netdev_info(dev->net, "enabling PHY wakeup\n");
ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, &val);
- check_warn_return(ret, "Error reading PMT_CTL\n");
+ check_warn_goto_done(ret, "Error reading PMT_CTL\n");
/* clear wol status, enable energy detection */
val &= ~PMT_CTL_WUPS;
val |= (PMT_CTL_WUPS_ED | PMT_CTL_ED_EN);
ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
- check_warn_return(ret, "Error writing PMT_CTL\n");
+ check_warn_goto_done(ret, "Error writing PMT_CTL\n");
}
if (pdata->wolopts & WAKE_MAGIC) {
netdev_info(dev->net, "enabling magic packet wakeup\n");
ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
- check_warn_return(ret, "Error reading WUCSR\n");
+ check_warn_goto_done(ret, "Error reading WUCSR\n");
/* clear any pending magic packet status */
val |= WUCSR_MPR | WUCSR_MPEN;
ret = smsc75xx_write_reg_nopm(dev, WUCSR, val);
- check_warn_return(ret, "Error writing WUCSR\n");
+ check_warn_goto_done(ret, "Error writing WUCSR\n");
}
if (pdata->wolopts & WAKE_BCAST) {
netdev_info(dev->net, "enabling broadcast detection\n");
ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
- check_warn_return(ret, "Error reading WUCSR\n");
+ check_warn_goto_done(ret, "Error reading WUCSR\n");
val |= WUCSR_BCAST_FR | WUCSR_BCST_EN;
ret = smsc75xx_write_reg_nopm(dev, WUCSR, val);
- check_warn_return(ret, "Error writing WUCSR\n");
+ check_warn_goto_done(ret, "Error writing WUCSR\n");
}
if (pdata->wolopts & WAKE_UCAST) {
netdev_info(dev->net, "enabling unicast detection\n");
ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
- check_warn_return(ret, "Error reading WUCSR\n");
+ check_warn_goto_done(ret, "Error reading WUCSR\n");
val |= WUCSR_WUFR | WUCSR_PFDA_EN;
ret = smsc75xx_write_reg_nopm(dev, WUCSR, val);
- check_warn_return(ret, "Error writing WUCSR\n");
+ check_warn_goto_done(ret, "Error writing WUCSR\n");
}
/* enable receiver to enable frame reception */
ret = smsc75xx_read_reg_nopm(dev, MAC_RX, &val);
- check_warn_return(ret, "Failed to read MAC_RX: %d\n", ret);
+ check_warn_goto_done(ret, "Failed to read MAC_RX: %d\n", ret);
val |= MAC_RX_RXEN;
ret = smsc75xx_write_reg_nopm(dev, MAC_RX, val);
- check_warn_return(ret, "Failed to write MAC_RX: %d\n", ret);
+ check_warn_goto_done(ret, "Failed to write MAC_RX: %d\n", ret);
/* some wol options are enabled, so enter SUSPEND0 */
netdev_info(dev->net, "entering SUSPEND0 mode\n");
- return smsc75xx_enter_suspend0(dev);
+ ret = smsc75xx_enter_suspend0(dev);
+
+done:
+ if (ret)
+ usbnet_resume(intf);
+ return ret;
}
static int smsc75xx_resume(struct usb_interface *intf)
--
1.7.10.4
^ permalink raw reply related
* [PATCH 3/6] smsc75xx: support PHY wakeup source
From: Steve Glendinning @ 2012-11-28 15:59 UTC (permalink / raw)
To: netdev; +Cc: Steve Glendinning
In-Reply-To: <1354118391-22666-1-git-send-email-steve.glendinning@shawell.net>
This patch enables LAN7500 family devices to wake from suspend
on either link up or link down events.
It also adds _nopm versions of mdio access functions, so we can
safely call them from suspend and resume functions
Updated patch to add newlines to printk messages
Signed-off-by: Steve Glendinning <steve.glendinning@shawell.net>
---
drivers/net/usb/smsc75xx.c | 169 +++++++++++++++++++++++++++++++++++++++-----
1 file changed, 152 insertions(+), 17 deletions(-)
diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c
index c26aeba..3e3b101 100644
--- a/drivers/net/usb/smsc75xx.c
+++ b/drivers/net/usb/smsc75xx.c
@@ -54,7 +54,7 @@
#define USB_PRODUCT_ID_LAN7500 (0x7500)
#define USB_PRODUCT_ID_LAN7505 (0x7505)
#define RXW_PADDING 2
-#define SUPPORTED_WAKE (WAKE_UCAST | WAKE_BCAST | \
+#define SUPPORTED_WAKE (WAKE_PHY | WAKE_UCAST | WAKE_BCAST | \
WAKE_MCAST | WAKE_ARP | WAKE_MAGIC)
#define check_warn(ret, fmt, args...) \
@@ -185,14 +185,15 @@ static int smsc75xx_clear_feature(struct usbnet *dev, u32 feature)
/* Loop until the read is completed with timeout
* called with phy_mutex held */
-static int smsc75xx_phy_wait_not_busy(struct usbnet *dev)
+static __must_check int __smsc75xx_phy_wait_not_busy(struct usbnet *dev,
+ int in_pm)
{
unsigned long start_time = jiffies;
u32 val;
int ret;
do {
- ret = smsc75xx_read_reg(dev, MII_ACCESS, &val);
+ ret = __smsc75xx_read_reg(dev, MII_ACCESS, &val, in_pm);
check_warn_return(ret, "Error reading MII_ACCESS\n");
if (!(val & MII_ACCESS_BUSY))
@@ -202,7 +203,8 @@ static int smsc75xx_phy_wait_not_busy(struct usbnet *dev)
return -EIO;
}
-static int smsc75xx_mdio_read(struct net_device *netdev, int phy_id, int idx)
+static int __smsc75xx_mdio_read(struct net_device *netdev, int phy_id, int idx,
+ int in_pm)
{
struct usbnet *dev = netdev_priv(netdev);
u32 val, addr;
@@ -211,7 +213,7 @@ static int smsc75xx_mdio_read(struct net_device *netdev, int phy_id, int idx)
mutex_lock(&dev->phy_mutex);
/* confirm MII not busy */
- ret = smsc75xx_phy_wait_not_busy(dev);
+ ret = __smsc75xx_phy_wait_not_busy(dev, in_pm);
check_warn_goto_done(ret, "MII is busy in smsc75xx_mdio_read\n");
/* set the address, index & direction (read from PHY) */
@@ -220,13 +222,13 @@ static int smsc75xx_mdio_read(struct net_device *netdev, int phy_id, int idx)
addr = ((phy_id << MII_ACCESS_PHY_ADDR_SHIFT) & MII_ACCESS_PHY_ADDR)
| ((idx << MII_ACCESS_REG_ADDR_SHIFT) & MII_ACCESS_REG_ADDR)
| MII_ACCESS_READ | MII_ACCESS_BUSY;
- ret = smsc75xx_write_reg(dev, MII_ACCESS, addr);
+ ret = __smsc75xx_write_reg(dev, MII_ACCESS, addr, in_pm);
check_warn_goto_done(ret, "Error writing MII_ACCESS\n");
- ret = smsc75xx_phy_wait_not_busy(dev);
+ ret = __smsc75xx_phy_wait_not_busy(dev, in_pm);
check_warn_goto_done(ret, "Timed out reading MII reg %02X\n", idx);
- ret = smsc75xx_read_reg(dev, MII_DATA, &val);
+ ret = __smsc75xx_read_reg(dev, MII_DATA, &val, in_pm);
check_warn_goto_done(ret, "Error reading MII_DATA\n");
ret = (u16)(val & 0xFFFF);
@@ -236,8 +238,8 @@ done:
return ret;
}
-static void smsc75xx_mdio_write(struct net_device *netdev, int phy_id, int idx,
- int regval)
+static void __smsc75xx_mdio_write(struct net_device *netdev, int phy_id,
+ int idx, int regval, int in_pm)
{
struct usbnet *dev = netdev_priv(netdev);
u32 val, addr;
@@ -246,11 +248,11 @@ static void smsc75xx_mdio_write(struct net_device *netdev, int phy_id, int idx,
mutex_lock(&dev->phy_mutex);
/* confirm MII not busy */
- ret = smsc75xx_phy_wait_not_busy(dev);
+ ret = __smsc75xx_phy_wait_not_busy(dev, in_pm);
check_warn_goto_done(ret, "MII is busy in smsc75xx_mdio_write\n");
val = regval;
- ret = smsc75xx_write_reg(dev, MII_DATA, val);
+ ret = __smsc75xx_write_reg(dev, MII_DATA, val, in_pm);
check_warn_goto_done(ret, "Error writing MII_DATA\n");
/* set the address, index & direction (write to PHY) */
@@ -259,16 +261,39 @@ static void smsc75xx_mdio_write(struct net_device *netdev, int phy_id, int idx,
addr = ((phy_id << MII_ACCESS_PHY_ADDR_SHIFT) & MII_ACCESS_PHY_ADDR)
| ((idx << MII_ACCESS_REG_ADDR_SHIFT) & MII_ACCESS_REG_ADDR)
| MII_ACCESS_WRITE | MII_ACCESS_BUSY;
- ret = smsc75xx_write_reg(dev, MII_ACCESS, addr);
+ ret = __smsc75xx_write_reg(dev, MII_ACCESS, addr, in_pm);
check_warn_goto_done(ret, "Error writing MII_ACCESS\n");
- ret = smsc75xx_phy_wait_not_busy(dev);
+ ret = __smsc75xx_phy_wait_not_busy(dev, in_pm);
check_warn_goto_done(ret, "Timed out writing MII reg %02X\n", idx);
done:
mutex_unlock(&dev->phy_mutex);
}
+static int smsc75xx_mdio_read_nopm(struct net_device *netdev, int phy_id,
+ int idx)
+{
+ return __smsc75xx_mdio_read(netdev, phy_id, idx, 1);
+}
+
+static void smsc75xx_mdio_write_nopm(struct net_device *netdev, int phy_id,
+ int idx, int regval)
+{
+ __smsc75xx_mdio_write(netdev, phy_id, idx, regval, 1);
+}
+
+static int smsc75xx_mdio_read(struct net_device *netdev, int phy_id, int idx)
+{
+ return __smsc75xx_mdio_read(netdev, phy_id, idx, 0);
+}
+
+static void smsc75xx_mdio_write(struct net_device *netdev, int phy_id, int idx,
+ int regval)
+{
+ __smsc75xx_mdio_write(netdev, phy_id, idx, regval, 0);
+}
+
static int smsc75xx_wait_eeprom(struct usbnet *dev)
{
unsigned long start_time = jiffies;
@@ -1233,6 +1258,32 @@ static int smsc75xx_enter_suspend0(struct usbnet *dev)
return 0;
}
+static int smsc75xx_enter_suspend1(struct usbnet *dev)
+{
+ u32 val;
+ int ret;
+
+ ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, &val);
+ check_warn_return(ret, "Error reading PMT_CTL\n");
+
+ val &= ~(PMT_CTL_SUS_MODE | PMT_CTL_WUPS | PMT_CTL_PHY_RST);
+ val |= PMT_CTL_SUS_MODE_1;
+
+ ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
+ check_warn_return(ret, "Error writing PMT_CTL\n");
+
+ /* clear wol status, enable energy detection */
+ val &= ~PMT_CTL_WUPS;
+ val |= (PMT_CTL_WUPS_ED | PMT_CTL_ED_EN);
+
+ ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
+ check_warn_return(ret, "Error writing PMT_CTL\n");
+
+ smsc75xx_set_feature(dev, USB_DEVICE_REMOTE_WAKEUP);
+
+ return 0;
+}
+
static int smsc75xx_enter_suspend2(struct usbnet *dev)
{
u32 val;
@@ -1250,18 +1301,61 @@ static int smsc75xx_enter_suspend2(struct usbnet *dev)
return 0;
}
+static int smsc75xx_enable_phy_wakeup_interrupts(struct usbnet *dev, u16 mask)
+{
+ struct mii_if_info *mii = &dev->mii;
+ int ret;
+
+ netdev_dbg(dev->net, "enabling PHY wakeup interrupts\n");
+
+ /* read to clear */
+ ret = smsc75xx_mdio_read_nopm(dev->net, mii->phy_id, PHY_INT_SRC);
+ check_warn_return(ret, "Error reading PHY_INT_SRC\n");
+
+ /* enable interrupt source */
+ ret = smsc75xx_mdio_read_nopm(dev->net, mii->phy_id, PHY_INT_MASK);
+ check_warn_return(ret, "Error reading PHY_INT_MASK\n");
+
+ ret |= mask;
+
+ smsc75xx_mdio_write_nopm(dev->net, mii->phy_id, PHY_INT_MASK, ret);
+
+ return 0;
+}
+
+static int smsc75xx_link_ok_nopm(struct usbnet *dev)
+{
+ struct mii_if_info *mii = &dev->mii;
+ int ret;
+
+ /* first, a dummy read, needed to latch some MII phys */
+ ret = smsc75xx_mdio_read_nopm(dev->net, mii->phy_id, MII_BMSR);
+ check_warn_return(ret, "Error reading MII_BMSR\n");
+
+ ret = smsc75xx_mdio_read_nopm(dev->net, mii->phy_id, MII_BMSR);
+ check_warn_return(ret, "Error reading MII_BMSR\n");
+
+ return !!(ret & BMSR_LSTATUS);
+}
+
static int smsc75xx_suspend(struct usb_interface *intf, pm_message_t message)
{
struct usbnet *dev = usb_get_intfdata(intf);
struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
+ u32 val, link_up;
int ret;
- u32 val;
ret = usbnet_suspend(intf, message);
check_warn_return(ret, "usbnet_suspend error\n");
- /* if no wol options set, enter lowest power SUSPEND2 mode */
- if (!(pdata->wolopts & SUPPORTED_WAKE)) {
+ /* determine if link is up using only _nopm functions */
+ link_up = smsc75xx_link_ok_nopm(dev);
+
+ /* if no wol options set, or if link is down and we're not waking on
+ * PHY activity, enter lowest power SUSPEND2 mode
+ */
+ if (!(pdata->wolopts & SUPPORTED_WAKE) ||
+ !(link_up || (pdata->wolopts & WAKE_PHY))) {
netdev_info(dev->net, "entering SUSPEND2 mode\n");
/* disable energy detect (link up) & wake up events */
@@ -1284,6 +1378,33 @@ static int smsc75xx_suspend(struct usb_interface *intf, pm_message_t message)
return smsc75xx_enter_suspend2(dev);
}
+ if (pdata->wolopts & WAKE_PHY) {
+ ret = smsc75xx_enable_phy_wakeup_interrupts(dev,
+ (PHY_INT_MASK_ANEG_COMP | PHY_INT_MASK_LINK_DOWN));
+ check_warn_return(ret, "error enabling PHY wakeup ints\n");
+
+ /* if link is down then configure EDPD and enter SUSPEND1,
+ * otherwise enter SUSPEND0 below
+ */
+ if (!link_up) {
+ struct mii_if_info *mii = &dev->mii;
+ netdev_info(dev->net, "entering SUSPEND1 mode\n");
+
+ /* enable energy detect power-down mode */
+ ret = smsc75xx_mdio_read_nopm(dev->net, mii->phy_id,
+ PHY_MODE_CTRL_STS);
+ check_warn_return(ret, "Error reading PHY_MODE_CTRL_STS\n");
+
+ ret |= MODE_CTRL_STS_EDPWRDOWN;
+
+ smsc75xx_mdio_write_nopm(dev->net, mii->phy_id,
+ PHY_MODE_CTRL_STS, ret);
+
+ /* enter SUSPEND1 mode */
+ return smsc75xx_enter_suspend1(dev);
+ }
+ }
+
if (pdata->wolopts & (WAKE_MCAST | WAKE_ARP)) {
int i, filter = 0;
@@ -1350,6 +1471,20 @@ static int smsc75xx_suspend(struct usb_interface *intf, pm_message_t message)
ret = smsc75xx_write_reg_nopm(dev, WUCSR, val);
check_warn_return(ret, "Error writing WUCSR\n");
+ if (pdata->wolopts & WAKE_PHY) {
+ netdev_info(dev->net, "enabling PHY wakeup\n");
+
+ ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, &val);
+ check_warn_return(ret, "Error reading PMT_CTL\n");
+
+ /* clear wol status, enable energy detection */
+ val &= ~PMT_CTL_WUPS;
+ val |= (PMT_CTL_WUPS_ED | PMT_CTL_ED_EN);
+
+ ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
+ check_warn_return(ret, "Error writing PMT_CTL\n");
+ }
+
if (pdata->wolopts & WAKE_MAGIC) {
netdev_info(dev->net, "enabling magic packet wakeup\n");
ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
--
1.7.10.4
^ permalink raw reply related
* [PATCH 2/6] smsc75xx: refactor entering suspend modes
From: Steve Glendinning @ 2012-11-28 15:59 UTC (permalink / raw)
To: netdev; +Cc: Steve Glendinning
In-Reply-To: <1354118391-22666-1-git-send-email-steve.glendinning@shawell.net>
This patch splits out the logic for entering suspend modes
to separate functions, to reduce the complexity of the
smsc75xx_suspend function.
Signed-off-by: Steve Glendinning <steve.glendinning@shawell.net>
---
drivers/net/usb/smsc75xx.c | 62 +++++++++++++++++++++++++++-----------------
1 file changed, 38 insertions(+), 24 deletions(-)
diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c
index a36648b..c26aeba 100644
--- a/drivers/net/usb/smsc75xx.c
+++ b/drivers/net/usb/smsc75xx.c
@@ -1214,6 +1214,42 @@ static int smsc75xx_write_wuff(struct usbnet *dev, int filter, u32 wuf_cfg,
return 0;
}
+static int smsc75xx_enter_suspend0(struct usbnet *dev)
+{
+ u32 val;
+ int ret;
+
+ ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, &val);
+ check_warn_return(ret, "Error reading PMT_CTL\n");
+
+ val &= (~(PMT_CTL_SUS_MODE | PMT_CTL_PHY_RST));
+ val |= PMT_CTL_SUS_MODE_0 | PMT_CTL_WOL_EN | PMT_CTL_WUPS;
+
+ ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
+ check_warn_return(ret, "Error writing PMT_CTL\n");
+
+ smsc75xx_set_feature(dev, USB_DEVICE_REMOTE_WAKEUP);
+
+ return 0;
+}
+
+static int smsc75xx_enter_suspend2(struct usbnet *dev)
+{
+ u32 val;
+ int ret;
+
+ ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, &val);
+ check_warn_return(ret, "Error reading PMT_CTL\n");
+
+ val &= ~(PMT_CTL_SUS_MODE | PMT_CTL_WUPS | PMT_CTL_PHY_RST);
+ val |= PMT_CTL_SUS_MODE_2;
+
+ ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
+ check_warn_return(ret, "Error writing PMT_CTL\n");
+
+ return 0;
+}
+
static int smsc75xx_suspend(struct usb_interface *intf, pm_message_t message)
{
struct usbnet *dev = usb_get_intfdata(intf);
@@ -1245,17 +1281,7 @@ static int smsc75xx_suspend(struct usb_interface *intf, pm_message_t message)
ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
check_warn_return(ret, "Error writing PMT_CTL\n");
- /* enter suspend2 mode */
- ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, &val);
- check_warn_return(ret, "Error reading PMT_CTL\n");
-
- val &= ~(PMT_CTL_SUS_MODE | PMT_CTL_WUPS | PMT_CTL_PHY_RST);
- val |= PMT_CTL_SUS_MODE_2;
-
- ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
- check_warn_return(ret, "Error writing PMT_CTL\n");
-
- return 0;
+ return smsc75xx_enter_suspend2(dev);
}
if (pdata->wolopts & (WAKE_MCAST | WAKE_ARP)) {
@@ -1369,19 +1395,7 @@ static int smsc75xx_suspend(struct usb_interface *intf, pm_message_t message)
/* some wol options are enabled, so enter SUSPEND0 */
netdev_info(dev->net, "entering SUSPEND0 mode\n");
-
- ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, &val);
- check_warn_return(ret, "Error reading PMT_CTL\n");
-
- val &= (~(PMT_CTL_SUS_MODE | PMT_CTL_PHY_RST));
- val |= PMT_CTL_SUS_MODE_0 | PMT_CTL_WOL_EN | PMT_CTL_WUPS;
-
- ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
- check_warn_return(ret, "Error writing PMT_CTL\n");
-
- smsc75xx_set_feature(dev, USB_DEVICE_REMOTE_WAKEUP);
-
- return 0;
+ return smsc75xx_enter_suspend0(dev);
}
static int smsc75xx_resume(struct usb_interface *intf)
--
1.7.10.4
^ permalink raw reply related
* [PATCH 1/6] smsc75xx: check return code from smsc75xx_reset
From: Steve Glendinning @ 2012-11-28 15:59 UTC (permalink / raw)
To: netdev; +Cc: Steve Glendinning
In-Reply-To: <1354118391-22666-1-git-send-email-steve.glendinning@shawell.net>
This patch adds a missing check and error message if smsc75xx_reset
fails.
Signed-off-by: Steve Glendinning <steve.glendinning@shawell.net>
---
drivers/net/usb/smsc75xx.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c
index 953c4f4..a36648b 100644
--- a/drivers/net/usb/smsc75xx.c
+++ b/drivers/net/usb/smsc75xx.c
@@ -1163,6 +1163,7 @@ static int smsc75xx_bind(struct usbnet *dev, struct usb_interface *intf)
/* Init all registers */
ret = smsc75xx_reset(dev);
+ check_warn_return(ret, "smsc75xx_reset error %d\n", ret);
dev->net->netdev_ops = &smsc75xx_netdev_ops;
dev->net->ethtool_ops = &smsc75xx_ethtool_ops;
--
1.7.10.4
^ permalink raw reply related
* [PATCH 0/6] smsc75xx enhancements
From: Steve Glendinning @ 2012-11-28 15:59 UTC (permalink / raw)
To: netdev; +Cc: Steve Glendinning
This patchset implements wake on PHY (link up or link down) and
USB dynamic autosuspend for smsc75xx.
Please consider all for net-next.
Steve Glendinning (6):
smsc75xx: check return code from smsc75xx_reset
smsc75xx: refactor entering suspend modes
smsc75xx: support PHY wakeup source
smsc75xx: fix error handling in suspend failure case
smsc75xx: add support for USB dynamic autosuspend
smsc75xx: don't enable remote wakeup directly
drivers/net/usb/smsc75xx.c | 415 +++++++++++++++++++++++++++++++++++---------
1 file changed, 330 insertions(+), 85 deletions(-)
--
1.7.10.4
^ permalink raw reply
* RE: [E1000-devel] 82571EB: Detected Hardware Unit Hang
From: Fujinaka, Todd @ 2012-11-28 15:53 UTC (permalink / raw)
To: Joe Jin, Ben Hutchings
Cc: Mary Mcgrath, netdev@vger.kernel.org, e1000-devel@lists.sf.net,
linux-kernel@vger.kernel.org, linux-pci
In-Reply-To: <50B5CBD2.5020804@oracle.com>
The only EEPROM I know about or can speak to is the one attached to the 82571 and it doesn't set the MaxPayloadSize. That's done by the BIOS.
Todd Fujinaka
Technical Marketing Engineer
LAN Access Division (LAD)
Intel Corporation
todd.fujinaka@intel.com
(503) 712-4565
-----Original Message-----
From: Joe Jin [mailto:joe.jin@oracle.com]
Sent: Wednesday, November 28, 2012 12:31 AM
To: Ben Hutchings
Cc: Fujinaka, Todd; Mary Mcgrath; netdev@vger.kernel.org; e1000-devel@lists.sf.net; linux-kernel@vger.kernel.org; linux-pci
Subject: Re: [E1000-devel] 82571EB: Detected Hardware Unit Hang
On 11/28/12 02:10, Ben Hutchings wrote:
> On Tue, 2012-11-27 at 17:32 +0000, Fujinaka, Todd wrote:
>> Forgive me if I'm being too repetitious as I think some of this has
>> been mentioned in the past.
>>
>> We (and by we I mean the Ethernet part and driver) can only change
>> the advertised availability of a larger MaxPayloadSize. The size is
>> negotiated by both sides of the link when the link is established.
>> The driver should not change the size of the link as it would be
>> poking at registers outside of its scope and is controlled by the
>> upstream bridge (not us).
> [...]
>
> MaxPayloadSize (MPS) is not negotiated between devices but is
> programmed by the system firmware (at least for devices present at
> boot - the kernel may be responsible in case of hotplug). You can use
> the kernel parameter 'pci=pcie_bus_perf' (or one of several others) to
> set a policy that overrides this, but no policy will allow setting MPS
> above the device's MaxPayloadSizeSupported (MPSS).
>
Ben,
Unfortunately I'm using 3.0.x kernel and this is not included in the kernel.
So I'm trying to use ethtool modify it from eeprom to see if help or no.
Todd, I'll review all MaxPayload for all devices, but need to say if it mismatch, customer could not modify it from BIOS for there was not entry at there, to test it, we have to find how to verify if this is the root cause, so still need to find the offset in eeprom.
Thanks in advance,
Joe
^ 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