* Problems with tg3 on BCM5720
From: Dirkjan Ochtman @ 2012-09-26 13:48 UTC (permalink / raw)
To: netdev
Hi,
I hope this is the right list for this; please let me know if there is
some more appropriate venue for this kind of problem.
We have bought a Dell PowerEdge server recently with Broadcom ethernet
controllers:
01:00.0 Ethernet controller: Broadcom Corporation NetXtreme BCM5720
Gigabit Ethernet PCIe
01:00.1 Ethernet controller: Broadcom Corporation NetXtreme BCM5720
Gigabit Ethernet PCIe
02:00.0 Ethernet controller: Broadcom Corporation NetXtreme BCM5720
Gigabit Ethernet PCIe
02:00.1 Ethernet controller: Broadcom Corporation NetXtreme BCM5720
Gigabit Ethernet PCIe
Using the tg3 driver as provided by the 3.4.9 kernel (it's a distro
kernel, but I verified that there are no relevant patches on top of
the vanilla 3.4.9), networking works fine on a small VLAN. However,
we've run into trouble connecting one of the interfaces to switch run
by our data center vendor (the switch side works fine when connecting
with a laptop). The driver keeps erroring out with "transmit timed
out, resetting" (full syslog output is at [1]). This also keeps
happening when I use the latest tg3.{c,h} from torvalds/linux-2.6
(though I've had to revert a few things to make it compile inside the
3.4.9 kernel).
I've also run some tests with ethtool:
djc@jansky ~ $ sudo ethtool --test eth0
The test result is FAIL
The test extra info:
nvram test (online) 0
link test (online) 1
register test (offline) 0
memory test (offline) 0
mac loopback test (offline) 7
phy loopback test (offline) 7
ext loopback test (offline) 0
interrupt test (offline) 1
While I'd be happy to do more digging, at this point I'm out of ideas
on how to go about that.
Again, sorry if this is off-topic for this list, any help would be appreciated.
Cheers,
Dirkjan
[1] http://dirkjan.ochtman.nl/files/tg3-fail.txt
^ permalink raw reply
* Re: flow control handling in network driver
From: Ben Hutchings @ 2012-09-26 13:49 UTC (permalink / raw)
To: Rayagond K; +Cc: netdev
In-Reply-To: <CAJ3bTp4J4aLzPgDND6E6SMXZe05xnM7K9kHVCH7kD-=vYZNtHA@mail.gmail.com>
On Wed, 2012-09-26 at 14:48 +0530, Rayagond K wrote:
> Hi All,
>
> What is the use of two macros SUPPORTED_Pause and SUPPORTED_Asym_Pause
> which are defined in ethtool.h file.
>
> I have seen amny driver in lxr using above macros, for example tg3
> driver - uses these macros to advertise the phy capabilities.
>
> Flow control is MAC feature not PHY, hence when can one use above
> macros and what is the use of it. Should we use these macros to
> implement flow control in Ethernet driver ?
Ethernet autonegotiation includes flow control as well as speed and
duplex (and some other parameters). Any device that supports Ethernet
flow control and autonegotiation should set the supported flags
accordingly and check the advertised flags when programming the PHY for
autonegotiation. (This is complicated a bit by the separate ethtool
commands for flow control.)
Ben.
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply
* [PATCH] rtlwifi: use %*ph[C] to dump small buffers
From: Andy Shevchenko @ 2012-09-26 13:57 UTC (permalink / raw)
To: David S. Miller, linux-wireless-u79uwXL29TY76Z2rM5mHXA,
netdev-u79uwXL29TY76Z2rM5mHXA
Cc: Andy Shevchenko
Signed-off-by: Andy Shevchenko <andriy.shevchenko-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
---
drivers/net/wireless/rtlwifi/cam.c | 7 ++-----
drivers/net/wireless/rtlwifi/rtl8192ce/hw.c | 6 ++----
drivers/net/wireless/rtlwifi/rtl8192cu/hw.c | 6 ++----
3 files changed, 6 insertions(+), 13 deletions(-)
diff --git a/drivers/net/wireless/rtlwifi/cam.c b/drivers/net/wireless/rtlwifi/cam.c
index 5b4b4d4..6ba9f80 100644
--- a/drivers/net/wireless/rtlwifi/cam.c
+++ b/drivers/net/wireless/rtlwifi/cam.c
@@ -52,11 +52,8 @@ static void rtl_cam_program_entry(struct ieee80211_hw *hw, u32 entry_no,
u32 target_content = 0;
u8 entry_i;
- RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
- "key_cont_128:\n %x:%x:%x:%x:%x:%x\n",
- key_cont_128[0], key_cont_128[1],
- key_cont_128[2], key_cont_128[3],
- key_cont_128[4], key_cont_128[5]);
+ RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, "key_cont_128: %*ph\n",
+ 6, key_cont_128);
for (entry_i = 0; entry_i < CAM_CONTENT_COUNT; entry_i++) {
target_command = entry_i + CAM_CONTENT_COUNT * entry_no;
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
index 86d73b3..932780d 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
@@ -1918,10 +1918,8 @@ static void rtl92ce_update_hal_rate_mask(struct ieee80211_hw *hw,
(ratr_index << 28);
rate_mask[4] = macid | (shortgi ? 0x20 : 0x00) | 0x80;
RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG,
- "Rate_index:%x, ratr_val:%x, %x:%x:%x:%x:%x\n",
- ratr_index, ratr_bitmap,
- rate_mask[0], rate_mask[1], rate_mask[2], rate_mask[3],
- rate_mask[4]);
+ "Rate_index:%x, ratr_val:%x, %*phC\n",
+ ratr_index, ratr_bitmap, 5, rate_mask);
rtl92c_fill_h2c_cmd(hw, H2C_RA_MASK, 5, rate_mask);
if (macid != 0)
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
index 4bbb711..7554501 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
@@ -2169,10 +2169,8 @@ void rtl92cu_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level)
ratr_index << 28);
rate_mask[4] = macid | (shortgi ? 0x20 : 0x00) | 0x80;
RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG,
- "Rate_index:%x, ratr_val:%x, %x:%x:%x:%x:%x\n",
- ratr_index, ratr_bitmap,
- rate_mask[0], rate_mask[1], rate_mask[2], rate_mask[3],
- rate_mask[4]);
+ "Rate_index:%x, ratr_val:%x, %*phC\n",
+ ratr_index, ratr_bitmap, 5, rate_mask);
rtl92c_fill_h2c_cmd(hw, H2C_RA_MASK, 5, rate_mask);
}
--
1.7.10.4
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" 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 related
* Re: [PATCH net-next] net: use bigger pages in __netdev_alloc_frag
From: Eric Dumazet @ 2012-09-26 13:57 UTC (permalink / raw)
To: Benjamin LaHaise; +Cc: David Miller, netdev, Alexander Duyck
In-Reply-To: <20120926131110.GL10611@kvack.org>
On Wed, 2012-09-26 at 09:11 -0400, Benjamin LaHaise wrote:
> Hello Eric,
>
> On Wed, Sep 26, 2012 at 11:06:42AM +0200, Eric Dumazet wrote:
> > + int order;
> ...
> > + for (order = NETDEV_FRAG_PAGE_MAX_ORDER; ;) {
> > + gfp_t gfp = gfp_mask;
> > +
> > + if (order)
> > + gfp |= __GFP_COMP | __GFP_NOWARN;
> > + nc->frag.page = alloc_pages(gfp, order);
> > + if (likely(nc->frag.page))
> > + break;
> > + if (--order <= 0)
> > + goto end;
> > + }
>
> I think you probably intended the last if to be "if (--order < 0)", as
> otherwise the alloc will never be attempted with an order 0 page, which
> could harm systems suffering from extreme memory fragmentation. Cheers,
>
Indeed, thanks Ben !
^ permalink raw reply
* Re: [PATCH 5/5] smsc95xx: enable power saving mode during system suspend
From: Bjørn Mork @ 2012-09-26 14:23 UTC (permalink / raw)
To: Steve Glendinning; +Cc: netdev
In-Reply-To: <1348663224-30403-6-git-send-email-steve.glendinning@shawell.net>
Steve Glendinning <steve.glendinning@shawell.net> writes:
> +static int smsc95xx_suspend(struct usb_interface *intf, pm_message_t message)
> +{
> + struct usbnet *dev = usb_get_intfdata(intf);
> + int ret;
> + u32 val;
> +
> + BUG_ON(!dev);
That's not very user friendly. Why not just return here?
Bjørn
^ permalink raw reply
* [PATCH 1/2] smsc75xx: add explicit test that device is READY
From: Steve Glendinning @ 2012-09-26 14:30 UTC (permalink / raw)
To: netdev; +Cc: Steve Glendinning
This patch adds an explicit test that the READY bit is set on
the device when attempting to initialize it.
If this bit is clear then the device hasn't succesfully started
all its clocks, and this patch helps make the resulting logged
error more helpful.
Signed-off-by: Steve Glendinning <steve.glendinning@shawell.net>
---
drivers/net/usb/smsc75xx.c | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c
index 376143e..1f45f7b 100644
--- a/drivers/net/usb/smsc75xx.c
+++ b/drivers/net/usb/smsc75xx.c
@@ -756,6 +756,26 @@ static int smsc75xx_set_features(struct net_device *netdev,
return 0;
}
+static int smsc75xx_wait_ready(struct usbnet *dev)
+{
+ int timeout = 0;
+
+ do {
+ u32 buf;
+ int ret = smsc75xx_read_reg(dev, PMT_CTL, &buf);
+ check_warn_return(ret, "Failed to read PMT_CTL: %d", ret);
+
+ if (buf & PMT_CTL_DEV_RDY)
+ return 0;
+
+ msleep(10);
+ timeout++;
+ } while (timeout < 100);
+
+ netdev_warn(dev->net, "timeout waiting for device ready");
+ return -EIO;
+}
+
static int smsc75xx_reset(struct usbnet *dev)
{
struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
@@ -764,6 +784,9 @@ static int smsc75xx_reset(struct usbnet *dev)
netif_dbg(dev, ifup, dev->net, "entering smsc75xx_reset");
+ ret = smsc75xx_wait_ready(dev);
+ check_warn_return(ret, "device not ready in smsc75xx_reset");
+
ret = smsc75xx_read_reg(dev, HW_CFG, &buf);
check_warn_return(ret, "Failed to read HW_CFG: %d", ret);
--
1.7.9.5
^ permalink raw reply related
* [PATCH 2/2] smsc75xx: enable power saving mode during system suspend
From: Steve Glendinning @ 2012-09-26 14:30 UTC (permalink / raw)
To: netdev; +Cc: Steve Glendinning
In-Reply-To: <1348669827-10923-1-git-send-email-steve.glendinning@shawell.net>
This patch instructs the device to enter its lowest power SUSPEND2
state during system suspend.
This patch also explicitly wakes the device after resume, which
should address reports of the device not automatically coming
back after system suspend:
http://code.google.com/p/chromium-os/issues/detail?id=31871
Signed-off-by: Steve Glendinning <steve.glendinning@shawell.net>
---
drivers/net/usb/smsc75xx.c | 55 +++++++++++++++++++++++++++++++++++++++++---
1 file changed, 52 insertions(+), 3 deletions(-)
diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c
index 1f45f7b..83b9927 100644
--- a/drivers/net/usb/smsc75xx.c
+++ b/drivers/net/usb/smsc75xx.c
@@ -1106,6 +1106,55 @@ static void smsc75xx_unbind(struct usbnet *dev, struct usb_interface *intf)
}
}
+static int smsc75xx_suspend(struct usb_interface *intf, pm_message_t message)
+{
+ struct usbnet *dev = usb_get_intfdata(intf);
+ int ret;
+ u32 val;
+
+ BUG_ON(!dev);
+
+ ret = usbnet_suspend(intf, message);
+ check_warn_return(ret, "usbnet_suspend error");
+
+ netdev_info(dev->net, "entering SUSPEND2 mode");
+
+ ret = smsc75xx_read_reg(dev, PMT_CTL, &val);
+ check_warn_return(ret, "Error reading PMT_CTL");
+
+ val &= ~(PMT_CTL_SUS_MODE | PMT_CTL_WUPS | PMT_CTL_PHY_RST);
+ val |= PMT_CTL_SUS_MODE_2;
+
+ ret = smsc75xx_write_reg(dev, PMT_CTL, val);
+ check_warn_return(ret, "Error writing PMT_CTL");
+
+ return 0;
+}
+
+static int smsc75xx_resume(struct usb_interface *intf)
+{
+ struct usbnet *dev = usb_get_intfdata(intf);
+ int ret;
+ u32 val;
+
+ BUG_ON(!dev);
+
+ netdev_info(dev->net, "resuming from SUSPEND2");
+
+ ret = smsc75xx_read_reg(dev, PMT_CTL, &val);
+ check_warn_return(ret, "Error reading PMT_CTL");
+
+ val |= PMT_CTL_PHY_PWRUP;
+
+ ret = smsc75xx_write_reg(dev, PMT_CTL, val);
+ check_warn_return(ret, "Error writing PMT_CTL");
+
+ ret = smsc75xx_wait_ready(dev);
+ check_warn_return(ret, "device not ready in smsc75xx_resume");
+
+ return usbnet_resume(intf);
+}
+
static void smsc75xx_rx_csum_offload(struct usbnet *dev, struct sk_buff *skb,
u32 rx_cmd_a, u32 rx_cmd_b)
{
@@ -1274,9 +1323,9 @@ static struct usb_driver smsc75xx_driver = {
.name = SMSC_CHIPNAME,
.id_table = products,
.probe = usbnet_probe,
- .suspend = usbnet_suspend,
- .resume = usbnet_resume,
- .reset_resume = usbnet_resume,
+ .suspend = smsc75xx_suspend,
+ .resume = smsc75xx_resume,
+ .reset_resume = smsc75xx_resume,
.disconnect = usbnet_disconnect,
.disable_hub_initiated_lpm = 1,
};
--
1.7.9.5
^ permalink raw reply related
* Re: [patch v2 04/11] nf_conntrack_netlink: pass nf_conntrack_netlink module to netlink_dump_start
From: Pablo Neira Ayuso @ 2012-09-26 15:04 UTC (permalink / raw)
To: Gao feng
Cc: davem-fT/PcQaiUtIeIZ0/mPfg9Q, eric.dumazet-Re5JQEeQqe8AvxtiuMwx3w,
steffen.klassert-opNxpl+3fjRBDgjK7y7TUQ,
netfilter-devel-u79uwXL29TY76Z2rM5mHXA,
linux-rdma-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA,
linux-crypto-u79uwXL29TY76Z2rM5mHXA,
stephen.hemminger-ZtmgI6mnKB3QT0dZR+AlfA, jengelh-9+2X+4sQBs8
In-Reply-To: <5062F6A9.7020309-BthXqXjhjHXQFUHtdCDX3A@public.gmane.org>
On Wed, Sep 26, 2012 at 08:35:53PM +0800, Gao feng wrote:
> 于 2012年09月26日 17:58, Pablo Neira Ayuso 写道:
> > On Wed, Sep 26, 2012 at 05:42:31PM +0800, Gao feng wrote:
> >> Hi Pablo:
> >>
> >> 于 2012年09月26日 17:26, Pablo Neira Ayuso 写道:
> >>> On Wed, Sep 26, 2012 at 04:41:21PM +0800, Gao feng wrote:
> >>>> use proper netlink_dump_control.done and .module to avoid panic.
> >>>>
> >>>> Signed-off-by: Gao feng <gaofeng-BthXqXjhjHXQFUHtdCDX3A@public.gmane.org>
> >>>> ---
> >>>> net/netfilter/nf_conntrack_netlink.c | 8 ++++++++
> >>>> 1 files changed, 8 insertions(+), 0 deletions(-)
> >>>>
> >>>> diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
> >>>> index 9807f32..509a257 100644
> >>>> --- a/net/netfilter/nf_conntrack_netlink.c
> >>>> +++ b/net/netfilter/nf_conntrack_netlink.c
> >>>> @@ -706,6 +706,7 @@ static int ctnetlink_done(struct netlink_callback *cb)
> >>>> nf_ct_put((struct nf_conn *)cb->args[1]);
> >>>> if (cb->data)
> >>>> kfree(cb->data);
> >>>> + netlink_dump_done(cb);
> >>>
> >>> I think you can call netlink_dump_done from af_netlink.c:
> >>>
> >>> static int netlink_dump(struct sock *sk)
> >>> ...
> >>> if (cb->done) {
> >>> cb->done(cb);
> >>> netlink_dump_done(...);
> >>> }
> >>>
> >>> Thus, you don't need to change netlink_dump_control in every netlink
> >>> subsystem.
> >>
> >> because cb->done is called by netlink_sock_destruct too,it's very usefully
> >> when userspace program only send dump request to kernel without reading
> >> data from kernel.
> >
> > Then add that to netlink_sock_destruct as well. If possible, I prefer
> > if this remains in the netlink core to avoid leaking module refcount
> > if you forget to call netlink_dump_done.
>
> make sense, I will update it in next version.
> Thanks!
Great. Remove also netlink_dump_done and just use module_put instead
after cb->done. That new function you added is so small that there is
no way to justify its addition.
> >
> >>>
> >>>> return 0;
> >>>> }
> >>>>
> >>>> @@ -1022,6 +1023,7 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb,
> >>>> struct netlink_dump_control c = {
> >>>> .dump = ctnetlink_dump_table,
> >>>> .done = ctnetlink_done,
> >>>> + .module = THIS_MODULE,
> >>>
> >>> You can do something similar to:
> >>>
> >>> 9f00d97 netlink: hide struct module parameter in netlink_kernel_create
> >>>
> >>> by definiting netlink_dump_start as static inline and using
> >>> THIS_MODULE from there.
> >>>
> >>> If I'm not missing anything, with those two changes, you will not need
> >>> to modify any caller and it will result one single patch.
> >>>
> >>
> >> You can see the patch [11/11], THIS_MODULE in infiniband/core/cma.c
> >> means module rdma_cm,but we call netlink_dump_start in infiniband/core/netlink.c
> >
> > You can still use __netlink_dump_start for that case, which allows you
> > to specify a custom struct module * parameter. But for most cases,
> > netlink_dump_start (which hides THIS_MODULE) should be fine.
>
> I don't know how to deal with module_put in this way.
> and I think my way is simple enough.
Not sure what problem with module_put you're refering to.
I think you can make this patchset way smaller with the change I'm
proposing.
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" 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
* [PATCH 1/2] smsc95xx: add wol magic packet support
From: Steve Glendinning @ 2012-09-26 15:13 UTC (permalink / raw)
To: netdev; +Cc: Steve Glendinning
This patch enables wake from system suspend on magic packet.
Signed-off-by: Steve Glendinning <steve.glendinning@shawell.net>
---
drivers/net/usb/smsc95xx.c | 182 ++++++++++++++++++++++++++++++++++++++++++--
drivers/net/usb/smsc95xx.h | 5 ++
2 files changed, 180 insertions(+), 7 deletions(-)
diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
index 6c89a08..c04ba76 100644
--- a/drivers/net/usb/smsc95xx.c
+++ b/drivers/net/usb/smsc95xx.c
@@ -46,6 +46,7 @@
#define SMSC95XX_INTERNAL_PHY_ID (1)
#define SMSC95XX_TX_OVERHEAD (8)
#define SMSC95XX_TX_OVERHEAD_CSUM (12)
+#define SUPPORTED_WAKE (WAKE_MAGIC)
#define check_warn(ret, fmt, args...) \
({ if (ret < 0) netdev_warn(dev->net, fmt, ##args); })
@@ -60,6 +61,7 @@ struct smsc95xx_priv {
u32 mac_cr;
u32 hash_hi;
u32 hash_lo;
+ u32 wolopts;
spinlock_t mac_cr_lock;
};
@@ -125,6 +127,28 @@ static int __must_check smsc95xx_write_reg(struct usbnet *dev, u32 index,
return ret;
}
+static int smsc95xx_set_feature(struct usbnet *dev, u32 feature)
+{
+ BUG_ON(!dev);
+
+ cpu_to_le32s(&feature);
+
+ return usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
+ USB_REQ_SET_FEATURE, USB_RECIP_DEVICE, feature, 0, NULL, 0,
+ USB_CTRL_SET_TIMEOUT);
+}
+
+static int smsc95xx_clear_feature(struct usbnet *dev, u32 feature)
+{
+ BUG_ON(!dev);
+
+ cpu_to_le32s(&feature);
+
+ return usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
+ USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE, feature, 0, NULL, 0,
+ USB_CTRL_SET_TIMEOUT);
+}
+
/* Loop until the read is completed with timeout
* called with phy_mutex held */
static int __must_check smsc95xx_phy_wait_not_busy(struct usbnet *dev)
@@ -636,6 +660,26 @@ smsc95xx_ethtool_getregs(struct net_device *netdev, struct ethtool_regs *regs,
}
}
+static void smsc95xx_ethtool_get_wol(struct net_device *net,
+ struct ethtool_wolinfo *wolinfo)
+{
+ struct usbnet *dev = netdev_priv(net);
+ struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+
+ wolinfo->supported = SUPPORTED_WAKE;
+ wolinfo->wolopts = pdata->wolopts;
+}
+
+static int smsc95xx_ethtool_set_wol(struct net_device *net,
+ struct ethtool_wolinfo *wolinfo)
+{
+ struct usbnet *dev = netdev_priv(net);
+ struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+
+ pdata->wolopts = wolinfo->wolopts & SUPPORTED_WAKE;
+ return 0;
+}
+
static const struct ethtool_ops smsc95xx_ethtool_ops = {
.get_link = usbnet_get_link,
.nway_reset = usbnet_nway_reset,
@@ -649,6 +693,8 @@ static const struct ethtool_ops smsc95xx_ethtool_ops = {
.set_eeprom = smsc95xx_ethtool_set_eeprom,
.get_regs_len = smsc95xx_ethtool_getregslen,
.get_regs = smsc95xx_ethtool_getregs,
+ .get_wol = smsc95xx_ethtool_get_wol,
+ .set_wol = smsc95xx_ethtool_set_wol,
};
static int smsc95xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
@@ -1021,25 +1067,147 @@ static void smsc95xx_unbind(struct usbnet *dev, struct usb_interface *intf)
static int smsc95xx_suspend(struct usb_interface *intf, pm_message_t message)
{
struct usbnet *dev = usb_get_intfdata(intf);
+ struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
int ret;
u32 val;
- BUG_ON(!dev);
-
ret = usbnet_suspend(intf, message);
check_warn_return(ret, "usbnet_suspend error");
- netdev_info(dev->net, "entering SUSPEND2 mode");
+ /* if no wol options set, enter lowest power SUSPEND2 mode */
+ if (!(pdata->wolopts & SUPPORTED_WAKE)) {
+ netdev_info(dev->net, "entering SUSPEND2 mode");
+
+ /* disable energy detect (link up) & wake up events */
+ ret = smsc95xx_read_reg(dev, WUCSR, &val);
+ check_warn_return(ret, "Error reading WUCSR");
+
+ val &= ~(WUCSR_MPEN_ | WUCSR_WAKE_EN_);
+
+ ret = smsc95xx_write_reg(dev, WUCSR, val);
+ check_warn_return(ret, "Error writing WUCSR");
+
+ ret = smsc95xx_read_reg(dev, PM_CTRL, &val);
+ check_warn_return(ret, "Error reading PM_CTRL");
+
+ val &= ~(PM_CTL_ED_EN_ | PM_CTL_WOL_EN_);
+
+ ret = smsc95xx_write_reg(dev, PM_CTRL, val);
+ check_warn_return(ret, "Error writing PM_CTRL");
+
+ /* enter suspend2 mode */
+ ret = smsc95xx_read_reg(dev, PM_CTRL, &val);
+ check_warn_return(ret, "Error reading PM_CTRL");
+
+ val &= ~(PM_CTL_SUS_MODE_ | PM_CTL_WUPS_ | PM_CTL_PHY_RST_);
+ val |= PM_CTL_SUS_MODE_2;
+
+ ret = smsc95xx_write_reg(dev, PM_CTRL, val);
+ check_warn_return(ret, "Error writing PM_CTRL");
+
+ return 0;
+ }
+
+ if (pdata->wolopts & WAKE_MAGIC) {
+ /* clear any pending magic packet status */
+ ret = smsc95xx_read_reg(dev, WUCSR, &val);
+ check_warn_return(ret, "Error reading WUCSR");
+
+ val |= WUCSR_MPR_;
+
+ ret = smsc95xx_write_reg(dev, WUCSR, val);
+ check_warn_return(ret, "Error writing WUCSR");
+ }
+ /* enable/disable magic packup wake */
+ ret = smsc95xx_read_reg(dev, WUCSR, &val);
+ check_warn_return(ret, "Error reading WUCSR");
+
+ if (pdata->wolopts & WAKE_MAGIC) {
+ netdev_info(dev->net, "enabling magic packet wakeup");
+ val |= WUCSR_MPEN_;
+ } else {
+ netdev_info(dev->net, "disabling magic packet wakeup");
+ val &= ~WUCSR_MPEN_;
+ }
+
+ ret = smsc95xx_write_reg(dev, WUCSR, val);
+ check_warn_return(ret, "Error writing WUCSR");
+
+ /* enable wol wakeup source */
ret = smsc95xx_read_reg(dev, PM_CTRL, &val);
check_warn_return(ret, "Error reading PM_CTRL");
- val &= ~(PM_CTL_SUS_MODE_ | PM_CTL_WUPS_ | PM_CTL_PHY_RST_);
- val |= PM_CTL_SUS_MODE_2;
+ val |= PM_CTL_WOL_EN_;
ret = smsc95xx_write_reg(dev, PM_CTRL, val);
check_warn_return(ret, "Error writing PM_CTRL");
+ /* enable receiver */
+ smsc95xx_start_rx_path(dev);
+
+ /* some wol options are enabled, so enter SUSPEND0 */
+ netdev_info(dev->net, "entering SUSPEND0 mode");
+
+ ret = smsc95xx_read_reg(dev, PM_CTRL, &val);
+ check_warn_return(ret, "Error reading PM_CTRL");
+
+ val &= (~(PM_CTL_SUS_MODE_ | PM_CTL_WUPS_ | PM_CTL_PHY_RST_));
+ val |= PM_CTL_SUS_MODE_0;
+
+ ret = smsc95xx_write_reg(dev, PM_CTRL, val);
+ check_warn_return(ret, "Error writing PM_CTRL");
+
+ /* clear wol status */
+ val &= ~PM_CTL_WUPS_;
+ val |= PM_CTL_WUPS_WOL_;
+ ret = smsc95xx_write_reg(dev, PM_CTRL, val);
+ check_warn_return(ret, "Error writing PM_CTRL");
+
+ /* read back PM_CTRL */
+ ret = smsc95xx_read_reg(dev, PM_CTRL, &val);
+ check_warn_return(ret, "Error reading PM_CTRL");
+
+ smsc95xx_set_feature(dev, USB_DEVICE_REMOTE_WAKEUP);
+
+ return 0;
+}
+
+static int smsc95xx_resume(struct usb_interface *intf)
+{
+ struct usbnet *dev = usb_get_intfdata(intf);
+ struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+ int ret;
+ u32 val;
+
+ BUG_ON(!dev);
+
+ if (pdata->wolopts & WAKE_MAGIC) {
+ smsc95xx_clear_feature(dev, USB_DEVICE_REMOTE_WAKEUP);
+
+ /* Disable magic packup wake */
+ ret = smsc95xx_read_reg(dev, WUCSR, &val);
+ check_warn_return(ret, "Error reading WUCSR");
+
+ val &= ~WUCSR_MPEN_;
+
+ ret = smsc95xx_write_reg(dev, WUCSR, val);
+ check_warn_return(ret, "Error writing WUCSR");
+
+ /* clear wake-up status */
+ ret = smsc95xx_read_reg(dev, PM_CTRL, &val);
+ check_warn_return(ret, "Error reading PM_CTRL");
+
+ val &= ~PM_CTL_WOL_EN_;
+ val |= PM_CTL_WUPS_;
+
+ ret = smsc95xx_write_reg(dev, PM_CTRL, val);
+ check_warn_return(ret, "Error writing PM_CTRL");
+ }
+
+ return usbnet_resume(intf);
+ check_warn_return(ret, "usbnet_resume error");
+
return 0;
}
@@ -1306,8 +1474,8 @@ static struct usb_driver smsc95xx_driver = {
.id_table = products,
.probe = usbnet_probe,
.suspend = smsc95xx_suspend,
- .resume = usbnet_resume,
- .reset_resume = usbnet_resume,
+ .resume = smsc95xx_resume,
+ .reset_resume = smsc95xx_resume,
.disconnect = usbnet_disconnect,
.disable_hub_initiated_lpm = 1,
};
diff --git a/drivers/net/usb/smsc95xx.h b/drivers/net/usb/smsc95xx.h
index 89ad925..2ff9815 100644
--- a/drivers/net/usb/smsc95xx.h
+++ b/drivers/net/usb/smsc95xx.h
@@ -205,6 +205,11 @@
#define WUFF (0x128)
#define WUCSR (0x12C)
+#define WUCSR_GUE_ (0x00000200)
+#define WUCSR_WUFR_ (0x00000040)
+#define WUCSR_MPR_ (0x00000020)
+#define WUCSR_WAKE_EN_ (0x00000004)
+#define WUCSR_MPEN_ (0x00000002)
#define COE_CR (0x130)
#define Tx_COE_EN_ (0x00010000)
--
1.7.9.5
^ permalink raw reply related
* [PATCH 2/2] smsc75xx: add wol magic packet support
From: Steve Glendinning @ 2012-09-26 15:13 UTC (permalink / raw)
To: netdev; +Cc: Steve Glendinning
In-Reply-To: <1348672394-15191-1-git-send-email-steve.glendinning@shawell.net>
This patch enables wake from system suspend on magic packet.
Signed-off-by: Steve Glendinning <steve.glendinning@shawell.net>
---
drivers/net/usb/smsc75xx.c | 184 +++++++++++++++++++++++++++++++++++++++++---
1 file changed, 172 insertions(+), 12 deletions(-)
diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c
index 83b9927..a480c46 100644
--- a/drivers/net/usb/smsc75xx.c
+++ b/drivers/net/usb/smsc75xx.c
@@ -52,6 +52,7 @@
#define USB_PRODUCT_ID_LAN7500 (0x7500)
#define USB_PRODUCT_ID_LAN7505 (0x7505)
#define RXW_PADDING 2
+#define SUPPORTED_WAKE (WAKE_MAGIC)
#define check_warn(ret, fmt, args...) \
({ if (ret < 0) netdev_warn(dev->net, fmt, ##args); })
@@ -65,6 +66,7 @@
struct smsc75xx_priv {
struct usbnet *dev;
u32 rfe_ctl;
+ u32 wolopts;
u32 multicast_hash_table[DP_SEL_VHF_HASH_LEN];
struct mutex dataport_mutex;
spinlock_t rfe_ctl_lock;
@@ -135,6 +137,28 @@ static int __must_check smsc75xx_write_reg(struct usbnet *dev, u32 index,
return ret;
}
+static int smsc75xx_set_feature(struct usbnet *dev, u32 feature)
+{
+ BUG_ON(!dev);
+
+ cpu_to_le32s(&feature);
+
+ return usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
+ USB_REQ_SET_FEATURE, USB_RECIP_DEVICE, feature, 0, NULL, 0,
+ USB_CTRL_SET_TIMEOUT);
+}
+
+static int smsc75xx_clear_feature(struct usbnet *dev, u32 feature)
+{
+ BUG_ON(!dev);
+
+ cpu_to_le32s(&feature);
+
+ return usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
+ USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE, feature, 0, NULL, 0,
+ USB_CTRL_SET_TIMEOUT);
+}
+
/* Loop until the read is completed with timeout
* called with phy_mutex held */
static int smsc75xx_phy_wait_not_busy(struct usbnet *dev)
@@ -578,6 +602,26 @@ static int smsc75xx_ethtool_set_eeprom(struct net_device *netdev,
return smsc75xx_write_eeprom(dev, ee->offset, ee->len, data);
}
+static void smsc75xx_ethtool_get_wol(struct net_device *net,
+ struct ethtool_wolinfo *wolinfo)
+{
+ struct usbnet *dev = netdev_priv(net);
+ struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
+
+ wolinfo->supported = SUPPORTED_WAKE;
+ wolinfo->wolopts = pdata->wolopts;
+}
+
+static int smsc75xx_ethtool_set_wol(struct net_device *net,
+ struct ethtool_wolinfo *wolinfo)
+{
+ struct usbnet *dev = netdev_priv(net);
+ struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
+
+ pdata->wolopts = wolinfo->wolopts & SUPPORTED_WAKE;
+ return 0;
+}
+
static const struct ethtool_ops smsc75xx_ethtool_ops = {
.get_link = usbnet_get_link,
.nway_reset = usbnet_nway_reset,
@@ -589,6 +633,8 @@ static const struct ethtool_ops smsc75xx_ethtool_ops = {
.get_eeprom_len = smsc75xx_ethtool_get_eeprom_len,
.get_eeprom = smsc75xx_ethtool_get_eeprom,
.set_eeprom = smsc75xx_ethtool_set_eeprom,
+ .get_wol = smsc75xx_ethtool_get_wol,
+ .set_wol = smsc75xx_ethtool_set_wol,
};
static int smsc75xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
@@ -1109,45 +1155,159 @@ static void smsc75xx_unbind(struct usbnet *dev, struct usb_interface *intf)
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]);
int ret;
u32 val;
- BUG_ON(!dev);
-
ret = usbnet_suspend(intf, message);
check_warn_return(ret, "usbnet_suspend error");
- netdev_info(dev->net, "entering SUSPEND2 mode");
+ /* if no wol options set, enter lowest power SUSPEND2 mode */
+ if (!(pdata->wolopts & SUPPORTED_WAKE)) {
+ netdev_info(dev->net, "entering SUSPEND2 mode");
+
+ /* disable energy detect (link up) & wake up events */
+ ret = smsc75xx_read_reg(dev, WUCSR, &val);
+ check_warn_return(ret, "Error reading WUCSR");
+
+ val &= ~(WUCSR_MPEN | WUCSR_WUEN);
+
+ ret = smsc75xx_write_reg(dev, WUCSR, val);
+ check_warn_return(ret, "Error writing WUCSR");
+
+ ret = smsc75xx_read_reg(dev, PMT_CTL, &val);
+ check_warn_return(ret, "Error reading PMT_CTL");
+
+ val &= ~(PMT_CTL_ED_EN | PMT_CTL_WOL_EN);
+
+ ret = smsc75xx_write_reg(dev, PMT_CTL, val);
+ check_warn_return(ret, "Error writing PMT_CTL");
+
+ /* enter suspend2 mode */
+ ret = smsc75xx_read_reg(dev, PMT_CTL, &val);
+ check_warn_return(ret, "Error reading PMT_CTL");
+
+ val &= ~(PMT_CTL_SUS_MODE | PMT_CTL_WUPS | PMT_CTL_PHY_RST);
+ val |= PMT_CTL_SUS_MODE_2;
+
+ ret = smsc75xx_write_reg(dev, PMT_CTL, val);
+ check_warn_return(ret, "Error writing PMT_CTL");
+
+ return 0;
+ }
+
+ if (pdata->wolopts & WAKE_MAGIC) {
+ /* clear any pending magic packet status */
+ ret = smsc75xx_read_reg(dev, WUCSR, &val);
+ check_warn_return(ret, "Error reading WUCSR");
+
+ val |= WUCSR_MPR;
+
+ ret = smsc75xx_write_reg(dev, WUCSR, val);
+ check_warn_return(ret, "Error writing WUCSR");
+ }
+
+ /* enable/disable magic packup wake */
+ ret = smsc75xx_read_reg(dev, WUCSR, &val);
+ check_warn_return(ret, "Error reading WUCSR");
+
+ if (pdata->wolopts & WAKE_MAGIC) {
+ netdev_info(dev->net, "enabling magic packet wakeup");
+ val |= WUCSR_MPEN;
+ } else {
+ netdev_info(dev->net, "disabling magic packet wakeup");
+ val &= ~WUCSR_MPEN;
+ }
+
+ ret = smsc75xx_write_reg(dev, WUCSR, val);
+ check_warn_return(ret, "Error writing WUCSR");
+
+ /* enable wol wakeup source */
+ ret = smsc75xx_read_reg(dev, PMT_CTL, &val);
+ check_warn_return(ret, "Error reading PMT_CTL");
+
+ val |= PMT_CTL_WOL_EN;
+
+ ret = smsc75xx_write_reg(dev, PMT_CTL, val);
+ check_warn_return(ret, "Error writing PMT_CTL");
+
+ /* enable receiver */
+ ret = smsc75xx_read_reg(dev, MAC_RX, &val);
+ check_warn_return(ret, "Failed to read MAC_RX: %d", ret);
+
+ val |= MAC_RX_RXEN;
+
+ ret = smsc75xx_write_reg(dev, MAC_RX, val);
+ check_warn_return(ret, "Failed to write MAC_RX: %d", ret);
+
+ /* some wol options are enabled, so enter SUSPEND0 */
+ netdev_info(dev->net, "entering SUSPEND0 mode");
ret = smsc75xx_read_reg(dev, PMT_CTL, &val);
check_warn_return(ret, "Error reading PMT_CTL");
- val &= ~(PMT_CTL_SUS_MODE | PMT_CTL_WUPS | PMT_CTL_PHY_RST);
- val |= PMT_CTL_SUS_MODE_2;
+ val &= (~(PMT_CTL_SUS_MODE | PMT_CTL_WUPS | PMT_CTL_PHY_RST));
+ val |= PMT_CTL_SUS_MODE_0;
+
+ ret = smsc75xx_write_reg(dev, PMT_CTL, val);
+ check_warn_return(ret, "Error writing PMT_CTL");
+ /* clear wol status */
+ val &= ~PMT_CTL_WUPS;
+ val |= PMT_CTL_WUPS_WOL;
ret = smsc75xx_write_reg(dev, PMT_CTL, val);
check_warn_return(ret, "Error writing PMT_CTL");
+ /* read back PMT_CTL */
+ ret = smsc75xx_read_reg(dev, PMT_CTL, &val);
+ check_warn_return(ret, "Error reading PMT_CTL");
+
+ smsc75xx_set_feature(dev, USB_DEVICE_REMOTE_WAKEUP);
+
return 0;
}
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]);
int ret;
u32 val;
- BUG_ON(!dev);
+ if (pdata->wolopts & WAKE_MAGIC) {
+ netdev_info(dev->net, "resuming from SUSPEND0");
- netdev_info(dev->net, "resuming from SUSPEND2");
+ smsc75xx_clear_feature(dev, USB_DEVICE_REMOTE_WAKEUP);
- ret = smsc75xx_read_reg(dev, PMT_CTL, &val);
- check_warn_return(ret, "Error reading PMT_CTL");
+ /* Disable magic packup wake */
+ ret = smsc75xx_read_reg(dev, WUCSR, &val);
+ check_warn_return(ret, "Error reading WUCSR");
- val |= PMT_CTL_PHY_PWRUP;
+ val &= ~WUCSR_MPEN;
- ret = smsc75xx_write_reg(dev, PMT_CTL, val);
- check_warn_return(ret, "Error writing PMT_CTL");
+ ret = smsc75xx_write_reg(dev, WUCSR, val);
+ check_warn_return(ret, "Error writing WUCSR");
+
+ /* clear wake-up status */
+ ret = smsc75xx_read_reg(dev, PMT_CTL, &val);
+ check_warn_return(ret, "Error reading PMT_CTL");
+
+ val &= ~PMT_CTL_WOL_EN;
+ val |= PMT_CTL_WUPS;
+
+ ret = smsc75xx_write_reg(dev, PMT_CTL, val);
+ check_warn_return(ret, "Error writing PMT_CTL");
+ } else {
+ netdev_info(dev->net, "resuming from SUSPEND2");
+
+ ret = smsc75xx_read_reg(dev, PMT_CTL, &val);
+ check_warn_return(ret, "Error reading PMT_CTL");
+
+ val |= PMT_CTL_PHY_PWRUP;
+
+ ret = smsc75xx_write_reg(dev, PMT_CTL, val);
+ check_warn_return(ret, "Error writing PMT_CTL");
+ }
ret = smsc75xx_wait_ready(dev);
check_warn_return(ret, "device not ready in smsc75xx_resume");
--
1.7.9.5
^ permalink raw reply related
* Re: [PATCH 5/5] smsc95xx: enable power saving mode during system suspend
From: Steve Glendinning @ 2012-09-26 15:16 UTC (permalink / raw)
To: Bjørn Mork; +Cc: netdev
In-Reply-To: <87y5jw982o.fsf@nemi.mork.no>
On 26 September 2012 15:23, Bjørn Mork <bjorn@mork.no> wrote:
> Steve Glendinning <steve.glendinning@shawell.net> writes:
>
>> +static int smsc95xx_suspend(struct usb_interface *intf, pm_message_t message)
>> +{
>> + struct usbnet *dev = usb_get_intfdata(intf);
>> + int ret;
>> + u32 val;
>> +
>> + BUG_ON(!dev);
>
> That's not very user friendly. Why not just return here?
I hadn't thought that was a situation that could arise, is it? Would
this happen if the USB device was removed during suspend?
-Steve
^ permalink raw reply
* Re: [PATCH] smsc75xx: fix resume after device reset
From: Steve Glendinning @ 2012-09-26 15:35 UTC (permalink / raw)
To: netdev
In-Reply-To: <1348497779-10042-1-git-send-email-steve.glendinning@shawell.net>
Oops, missing signed-off line. Please let me know if you want me to
resubmit this patch.
Signed-off-by: Steve Glendinning <steve.glendinning@shawell.net>
-Steve
^ permalink raw reply
* Re: [PATCH 5/5] smsc95xx: enable power saving mode during system suspend
From: Bjørn Mork @ 2012-09-26 15:48 UTC (permalink / raw)
To: Steve Glendinning; +Cc: netdev
In-Reply-To: <CAKh2mn5tKowqjbvgWDSz52UF9qY9_ysAb23Pb-M_3wvCG=_R6w@mail.gmail.com>
Steve Glendinning <steve@shawell.net> writes:
> On 26 September 2012 15:23, Bjørn Mork <bjorn@mork.no> wrote:
>> Steve Glendinning <steve.glendinning@shawell.net> writes:
>>
>>> +static int smsc95xx_suspend(struct usb_interface *intf, pm_message_t message)
>>> +{
>>> + struct usbnet *dev = usb_get_intfdata(intf);
>>> + int ret;
>>> + u32 val;
>>> +
>>> + BUG_ON(!dev);
>>
>> That's not very user friendly. Why not just return here?
>
> I hadn't thought that was a situation that could arise, is it? Would
> this happen if the USB device was removed during suspend?
No, it should not happen. But then, why test at all?
Bjørn
^ permalink raw reply
* Re: [PATCH 5/5] smsc95xx: enable power saving mode during system suspend
From: Steve Glendinning @ 2012-09-26 15:58 UTC (permalink / raw)
To: Bjørn Mork; +Cc: netdev
In-Reply-To: <87txuk9453.fsf@nemi.mork.no>
>> I hadn't thought that was a situation that could arise, is it? Would
>> this happen if the USB device was removed during suspend?
>
> No, it should not happen. But then, why test at all?
I thought it was common practice to add these tests to document an
assumption the developer made that later code relies on? I had
assumed that the !dev condition should not be possible, hence the
simple BUG test. If it is possible then I agree - I definitely need
to handle this more gracefully.
In this case, asserting that dev is not NULL will make the code fail
loudly there instead of a few lines down when the netdev_info call
dereferences dev->net. Either way something bad will happen!
-Steve
^ permalink raw reply
* Re: [PATCH net-next] net: use bigger pages in __netdev_alloc_frag
From: Alexander Duyck @ 2012-09-26 16:00 UTC (permalink / raw)
To: Eric Dumazet; +Cc: David Miller, netdev
In-Reply-To: <1348650402.5093.176.camel@edumazet-glaptop>
On 09/26/2012 02:06 AM, Eric Dumazet wrote:
> From: Eric Dumazet <edumazet@google.com>
>
> We currently use percpu order-0 pages in __netdev_alloc_frag
> to deliver fragments used by __netdev_alloc_skb()
>
> Depending on NIC driver and arch being 32 or 64 bit, it allows a page to
> be split in several fragments (between 1 and 8), assuming PAGE_SIZE=4096
>
> Switching to bigger pages (32768 bytes for PAGE_SIZE=4096 case) allows :
>
> - Better filling of space (the ending hole overhead is less an issue)
>
> - Less calls to page allocator or accesses to page->_count
>
> - Could allow struct skb_shared_info futures changes without major
> performance impact.
>
> This patch implements a transparent fallback to smaller
> pages in case of memory pressure.
>
> It also uses a standard "struct page_frag" instead of a custom one.
>
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> Cc: Alexander Duyck <alexander.h.duyck@intel.com>
> ---
> net/core/skbuff.c | 46 ++++++++++++++++++++++++++++----------------
> 1 file changed, 30 insertions(+), 16 deletions(-)
>
> diff --git a/net/core/skbuff.c b/net/core/skbuff.c
> index 2ede3cf..4ab83ce 100644
> --- a/net/core/skbuff.c
> +++ b/net/core/skbuff.c
> @@ -340,43 +340,57 @@ struct sk_buff *build_skb(void *data, unsigned int frag_size)
> EXPORT_SYMBOL(build_skb);
>
> struct netdev_alloc_cache {
> - struct page *page;
> - unsigned int offset;
> - unsigned int pagecnt_bias;
> + struct page_frag frag;
> + /* we maintain a pagecount bias, so that we dont dirty cache line
> + * containing page->_count every time we allocate a fragment.
> + */
> + unsigned int pagecnt_bias;
> };
> static DEFINE_PER_CPU(struct netdev_alloc_cache, netdev_alloc_cache);
>
> -#define NETDEV_PAGECNT_BIAS (PAGE_SIZE / SMP_CACHE_BYTES)
> +#define NETDEV_FRAG_PAGE_MAX_ORDER get_order(32768)
> +#define NETDEV_FRAG_PAGE_MAX_SIZE (PAGE_SIZE << NETDEV_FRAG_PAGE_MAX_ORDER)
> +#define NETDEV_PAGECNT_MAX_BIAS NETDEV_FRAG_PAGE_MAX_SIZE
>
> static void *__netdev_alloc_frag(unsigned int fragsz, gfp_t gfp_mask)
> {
> struct netdev_alloc_cache *nc;
> void *data = NULL;
> + int order;
> unsigned long flags;
>
> local_irq_save(flags);
> nc = &__get_cpu_var(netdev_alloc_cache);
> - if (unlikely(!nc->page)) {
> + if (unlikely(!nc->frag.page)) {
> refill:
> - nc->page = alloc_page(gfp_mask);
> - if (unlikely(!nc->page))
> - goto end;
> + for (order = NETDEV_FRAG_PAGE_MAX_ORDER; ;) {
> + gfp_t gfp = gfp_mask;
> +
> + if (order)
> + gfp |= __GFP_COMP | __GFP_NOWARN;
> + nc->frag.page = alloc_pages(gfp, order);
> + if (likely(nc->frag.page))
> + break;
> + if (--order <= 0)
> + goto end;
> + }
> + nc->frag.size = PAGE_SIZE << order;
> recycle:
> - atomic_set(&nc->page->_count, NETDEV_PAGECNT_BIAS);
> - nc->pagecnt_bias = NETDEV_PAGECNT_BIAS;
> - nc->offset = 0;
> + atomic_set(&nc->frag.page->_count, NETDEV_PAGECNT_MAX_BIAS);
> + nc->pagecnt_bias = NETDEV_PAGECNT_MAX_BIAS;
> + nc->frag.offset = 0;
> }
>
> - if (nc->offset + fragsz > PAGE_SIZE) {
> + if (nc->frag.offset + fragsz > nc->frag.size) {
> /* avoid unnecessary locked operations if possible */
> - if ((atomic_read(&nc->page->_count) == nc->pagecnt_bias) ||
> - atomic_sub_and_test(nc->pagecnt_bias, &nc->page->_count))
> + if ((atomic_read(&nc->frag.page->_count) == nc->pagecnt_bias) ||
> + atomic_sub_and_test(nc->pagecnt_bias, &nc->frag.page->_count))
> goto recycle;
> goto refill;
> }
>
> - data = page_address(nc->page) + nc->offset;
> - nc->offset += fragsz;
> + data = page_address(nc->frag.page) + nc->frag.offset;
> + nc->frag.offset += fragsz;
> nc->pagecnt_bias--;
> end:
> local_irq_restore(flags);
>
>
One minor thought. Instead of tracking offset and size why not just
work from the top down instead of the bottom up?
So instead of starting with the frag offset at 0, why not start it at
PAGE_SIZE << order, and then work your way down to 0. That way you
don't need to track both size and offset.
Thanks,
Alex
^ permalink raw reply
* Re: [PATCH 02/11] inet_diag: pass inet_diag module to netlink_dump_start
From: Stephen Hemminger @ 2012-09-26 16:07 UTC (permalink / raw)
To: Gao feng
Cc: davem, netfilter-devel, linux-rdma, netdev, eric.dumazet, pablo,
steffen.klassert, linux-crypto, jengelh, stephen.hemminger
In-Reply-To: <1348635140-20225-2-git-send-email-gaofeng@cn.fujitsu.com>
On Wed, 26 Sep 2012 12:52:11 +0800
Gao feng <gaofeng@cn.fujitsu.com> wrote:
> struct netlink_dump_control c = {
> .dump = inet_diag_dump_compat,
> + .done = netlink_dump_done,
> + .module = THIS_MODULE,
> };
Since these are immutable, why the netlink_dump_control structures
on the stack (which requires code to generate at runtime), and instead
make them global
static const struct netlink_dump_control unix_diag_ctrl = {
...
^ permalink raw reply
* Re: [PATCH net-next] net: use bigger pages in __netdev_alloc_frag
From: Eric Dumazet @ 2012-09-26 16:14 UTC (permalink / raw)
To: Alexander Duyck; +Cc: David Miller, netdev
In-Reply-To: <50632681.40208@intel.com>
On Wed, 2012-09-26 at 09:00 -0700, Alexander Duyck wrote:
> One minor thought. Instead of tracking offset and size why not just
> work from the top down instead of the bottom up?
>
> So instead of starting with the frag offset at 0, why not start it at
> PAGE_SIZE << order, and then work your way down to 0. That way you
> don't need to track both size and offset.
>
How do you refill then ?
(ie setting xxx->offset back to PAGE_SIZE << order)
I am not sure we have direct access to a page order given a struct page
pointer.
I also like struct page_frag abstraction, because it might allow us
better code factorization with other frag allocators.
( skb_append_datato_frags(), sk_page_frag_refill(), ...)
^ permalink raw reply
* Re: [PATCH 5/5] smsc95xx: enable power saving mode during system suspend
From: Bjørn Mork @ 2012-09-26 16:17 UTC (permalink / raw)
To: Steve Glendinning; +Cc: netdev
In-Reply-To: <CAKh2mn4XLCPfTFySEvtZc56J+WM863JtnsjF2D-RyDJatoyAww@mail.gmail.com>
Steve Glendinning <steve@shawell.net> writes:
>>> I hadn't thought that was a situation that could arise, is it? Would
>>> this happen if the USB device was removed during suspend?
>>
>> No, it should not happen. But then, why test at all?
>
> I thought it was common practice to add these tests to document an
> assumption the developer made that later code relies on? I had
> assumed that the !dev condition should not be possible, hence the
> simple BUG test. If it is possible then I agree - I definitely need
> to handle this more gracefully.
>
> In this case, asserting that dev is not NULL will make the code fail
> loudly there instead of a few lines down when the netdev_info call
> dereferences dev->net. Either way something bad will happen!
Yes, but you are a lot less likely to know about it if you BUG out. The
user will be left with no other choice than hitting reset or poweroff.
What's the point of that?
If your driver crashes but the machine is left running, then the user
may forward the Oops to you. That's much more useful.
Bjørn
^ permalink raw reply
* Re: [PATCH net-next] net: use bigger pages in __netdev_alloc_frag
From: Alexander Duyck @ 2012-09-26 16:36 UTC (permalink / raw)
To: Eric Dumazet; +Cc: David Miller, netdev
In-Reply-To: <1348676085.5093.361.camel@edumazet-glaptop>
On 09/26/2012 09:14 AM, Eric Dumazet wrote:
> On Wed, 2012-09-26 at 09:00 -0700, Alexander Duyck wrote:
>
>> One minor thought. Instead of tracking offset and size why not just
>> work from the top down instead of the bottom up?
>>
>> So instead of starting with the frag offset at 0, why not start it at
>> PAGE_SIZE << order, and then work your way down to 0. That way you
>> don't need to track both size and offset.
>>
> How do you refill then ?
>
> (ie setting xxx->offset back to PAGE_SIZE << order)
>
> I am not sure we have direct access to a page order given a struct page
> pointer.
>
> I also like struct page_frag abstraction, because it might allow us
> better code factorization with other frag allocators.
>
> ( skb_append_datato_frags(), sk_page_frag_refill(), ...)
I forgot about the page recycling portion of it. I was still thinking
of the original implementation that had a fixed page order. You are
correct, with the page order being dynamic you will have to store size
somewhere.
Thanks,
Alex
^ permalink raw reply
* Re: [PATCH] rtlwifi: use %*ph[C] to dump small buffers
From: Joe Perches @ 2012-09-26 16:45 UTC (permalink / raw)
To: Andy Shevchenko, Larry Finger, Chaoming Li
Cc: David S. Miller, linux-wireless-u79uwXL29TY76Z2rM5mHXA,
netdev-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1348667852-5957-1-git-send-email-andriy.shevchenko-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
On Wed, 2012-09-26 at 16:57 +0300, Andy Shevchenko wrote:
> Signed-off-by: Andy Shevchenko <andriy.shevchenko-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
Hi Andy.
(adding Larry and Chaoming to cc's)
Please use scripts/get_maintainer.pl on your patches to
see who maintains these files so you can cc them.
One comment below, it looks like a possible endian bug.
(not in your patch)
> ---
> drivers/net/wireless/rtlwifi/cam.c | 7 ++-----
> drivers/net/wireless/rtlwifi/rtl8192ce/hw.c | 6 ++----
> drivers/net/wireless/rtlwifi/rtl8192cu/hw.c | 6 ++----
> 3 files changed, 6 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/net/wireless/rtlwifi/cam.c b/drivers/net/wireless/rtlwifi/cam.c
> index 5b4b4d4..6ba9f80 100644
> --- a/drivers/net/wireless/rtlwifi/cam.c
> +++ b/drivers/net/wireless/rtlwifi/cam.c
> @@ -52,11 +52,8 @@ static void rtl_cam_program_entry(struct ieee80211_hw *hw, u32 entry_no,
> u32 target_content = 0;
> u8 entry_i;
>
> - RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
> - "key_cont_128:\n %x:%x:%x:%x:%x:%x\n",
> - key_cont_128[0], key_cont_128[1],
> - key_cont_128[2], key_cont_128[3],
> - key_cont_128[4], key_cont_128[5]);
> + RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, "key_cont_128: %*ph\n",
> + 6, key_cont_128);
>
> for (entry_i = 0; entry_i < CAM_CONTENT_COUNT; entry_i++) {
> target_command = entry_i + CAM_CONTENT_COUNT * entry_no;
> diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
> index 86d73b3..932780d 100644
> --- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
> +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
> @@ -1918,10 +1918,8 @@ static void rtl92ce_update_hal_rate_mask(struct ieee80211_hw *hw,
> (ratr_index << 28);
> rate_mask[4] = macid | (shortgi ? 0x20 : 0x00) | 0x80;
> RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG,
> - "Rate_index:%x, ratr_val:%x, %x:%x:%x:%x:%x\n",
> - ratr_index, ratr_bitmap,
> - rate_mask[0], rate_mask[1], rate_mask[2], rate_mask[3],
> - rate_mask[4]);
> + "Rate_index:%x, ratr_val:%x, %*phC\n",
> + ratr_index, ratr_bitmap, 5, rate_mask);
> rtl92c_fill_h2c_cmd(hw, H2C_RA_MASK, 5, rate_mask);
>
> if (macid != 0)
> diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
> index 4bbb711..7554501 100644
> --- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
> +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
> @@ -2169,10 +2169,8 @@ void rtl92cu_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level)
> ratr_index << 28);
> rate_mask[4] = macid | (shortgi ? 0x20 : 0x00) | 0x80;
> RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG,
> - "Rate_index:%x, ratr_val:%x, %x:%x:%x:%x:%x\n",
> - ratr_index, ratr_bitmap,
> - rate_mask[0], rate_mask[1], rate_mask[2], rate_mask[3],
> - rate_mask[4]);
> + "Rate_index:%x, ratr_val:%x, %*phC\n",
> + ratr_index, ratr_bitmap, 5, rate_mask);
> rtl92c_fill_h2c_cmd(hw, H2C_RA_MASK, 5, rate_mask);
> }
>
rate_mask uses:
u32 ratr_bitmap = (u32) mac->basic_rates;
...
u8 rate_mask[5];
...
[sets ratr_bitmap as u32]
...
*(u32 *)&rate_mask = ((ratr_bitmap & 0x0fffffff) |
ratr_index << 28);
...
rtl92c_fill_h2c_cmd(hw, H2C_RA_MASK, 5, rate_mask);
Looks like a possible endian misuse to me.
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" 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
* [PATCH net-next v2] net: use bigger pages in __netdev_alloc_frag
From: Eric Dumazet @ 2012-09-26 16:46 UTC (permalink / raw)
To: Alexander Duyck; +Cc: David Miller, netdev, Benjamin LaHaise
In-Reply-To: <50632F06.1040306@intel.com>
From: Eric Dumazet <edumazet@google.com>
We currently use percpu order-0 pages in __netdev_alloc_frag
to deliver fragments used by __netdev_alloc_skb()
Depending on NIC driver and arch being 32 or 64 bit, it allows a page to
be split in several fragments (between 1 and 8), assuming PAGE_SIZE=4096
Switching to bigger pages (32768 bytes for PAGE_SIZE=4096 case) allows :
- Better filling of space (the ending hole overhead is less an issue)
- Less calls to page allocator or accesses to page->_count
- Could allow struct skb_shared_info futures changes without major
performance impact.
This patch implements a transparent fallback to smaller
pages in case of memory pressure.
It also uses a standard "struct page_frag" instead of a custom one.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Alexander Duyck <alexander.h.duyck@intel.com>
Cc: Benjamin LaHaise <bcrl@kvack.org>
---
v2 : fix the (--order <= 0) test, as Benjamin pointed out
net/core/skbuff.c | 46 ++++++++++++++++++++++++++++----------------
1 file changed, 30 insertions(+), 16 deletions(-)
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 2ede3cf..607a70f 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -340,43 +340,57 @@ struct sk_buff *build_skb(void *data, unsigned int frag_size)
EXPORT_SYMBOL(build_skb);
struct netdev_alloc_cache {
- struct page *page;
- unsigned int offset;
- unsigned int pagecnt_bias;
+ struct page_frag frag;
+ /* we maintain a pagecount bias, so that we dont dirty cache line
+ * containing page->_count every time we allocate a fragment.
+ */
+ unsigned int pagecnt_bias;
};
static DEFINE_PER_CPU(struct netdev_alloc_cache, netdev_alloc_cache);
-#define NETDEV_PAGECNT_BIAS (PAGE_SIZE / SMP_CACHE_BYTES)
+#define NETDEV_FRAG_PAGE_MAX_ORDER get_order(32768)
+#define NETDEV_FRAG_PAGE_MAX_SIZE (PAGE_SIZE << NETDEV_FRAG_PAGE_MAX_ORDER)
+#define NETDEV_PAGECNT_MAX_BIAS NETDEV_FRAG_PAGE_MAX_SIZE
static void *__netdev_alloc_frag(unsigned int fragsz, gfp_t gfp_mask)
{
struct netdev_alloc_cache *nc;
void *data = NULL;
+ int order;
unsigned long flags;
local_irq_save(flags);
nc = &__get_cpu_var(netdev_alloc_cache);
- if (unlikely(!nc->page)) {
+ if (unlikely(!nc->frag.page)) {
refill:
- nc->page = alloc_page(gfp_mask);
- if (unlikely(!nc->page))
- goto end;
+ for (order = NETDEV_FRAG_PAGE_MAX_ORDER; ;) {
+ gfp_t gfp = gfp_mask;
+
+ if (order)
+ gfp |= __GFP_COMP | __GFP_NOWARN;
+ nc->frag.page = alloc_pages(gfp, order);
+ if (likely(nc->frag.page))
+ break;
+ if (--order < 0)
+ goto end;
+ }
+ nc->frag.size = PAGE_SIZE << order;
recycle:
- atomic_set(&nc->page->_count, NETDEV_PAGECNT_BIAS);
- nc->pagecnt_bias = NETDEV_PAGECNT_BIAS;
- nc->offset = 0;
+ atomic_set(&nc->frag.page->_count, NETDEV_PAGECNT_MAX_BIAS);
+ nc->pagecnt_bias = NETDEV_PAGECNT_MAX_BIAS;
+ nc->frag.offset = 0;
}
- if (nc->offset + fragsz > PAGE_SIZE) {
+ if (nc->frag.offset + fragsz > nc->frag.size) {
/* avoid unnecessary locked operations if possible */
- if ((atomic_read(&nc->page->_count) == nc->pagecnt_bias) ||
- atomic_sub_and_test(nc->pagecnt_bias, &nc->page->_count))
+ if ((atomic_read(&nc->frag.page->_count) == nc->pagecnt_bias) ||
+ atomic_sub_and_test(nc->pagecnt_bias, &nc->frag.page->_count))
goto recycle;
goto refill;
}
- data = page_address(nc->page) + nc->offset;
- nc->offset += fragsz;
+ data = page_address(nc->frag.page) + nc->frag.offset;
+ nc->frag.offset += fragsz;
nc->pagecnt_bias--;
end:
local_irq_restore(flags);
^ permalink raw reply related
* [PATCH net-next] net: struct napi_struct fields reordering
From: Eric Dumazet @ 2012-09-26 17:07 UTC (permalink / raw)
To: David Miller; +Cc: netdev
From: Eric Dumazet <edumazet@google.com>
Remove two holes on 64bit arches, and put dev_list at the end of
napi_struct since its not used in fast path.
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
include/linux/netdevice.h | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 6c131f0..dd320bb 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -338,18 +338,16 @@ struct napi_struct {
unsigned long state;
int weight;
+ unsigned int gro_count;
int (*poll)(struct napi_struct *, int);
#ifdef CONFIG_NETPOLL
spinlock_t poll_lock;
int poll_owner;
#endif
-
- unsigned int gro_count;
-
struct net_device *dev;
- struct list_head dev_list;
struct sk_buff *gro_list;
struct sk_buff *skb;
+ struct list_head dev_list;
};
enum {
^ permalink raw reply related
* [PATCH] bnx2: Clean up remaining iounmap
From: Neil Horman @ 2012-09-26 17:22 UTC (permalink / raw)
To: netdev; +Cc: Neil Horman, Michael Chan, David S. Miller
commit c0357e975afdbbedab5c662d19bef865f02adc17 modified bnx2 to switch from
using ioremap/iounmap to pci_iomap/pci_iounmap. They missed a spot in the error
path of bnx2_init_one though. This patch just cleans that up.
Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
CC: Michael Chan <mcan@broadcom.com>
CC: "David S. Miller" <davem@davemloft.net>
---
drivers/net/ethernet/broadcom/bnx2.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c
index 79cebd8..e48312f 100644
--- a/drivers/net/ethernet/broadcom/bnx2.c
+++ b/drivers/net/ethernet/broadcom/bnx2.c
@@ -8564,7 +8564,7 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
return 0;
error:
- iounmap(bp->regview);
+ pci_iounmap(pdev, bp->regview);
pci_release_regions(pdev);
pci_disable_device(pdev);
pci_set_drvdata(pdev, NULL);
--
1.7.11.4
^ permalink raw reply related
* [PATCH 2/2] net: ti cpsw ethernet: set IFCTL_{A,B} bits for RMII mode
From: Daniel Mack @ 2012-09-26 17:24 UTC (permalink / raw)
To: netdev
Cc: devicetree-discuss, Daniel Mack, Mugunthan V N, Vaibhav Hiremath,
David S. Miller
In-Reply-To: <1348680268-8194-1-git-send-email-zonque@gmail.com>
For RMII mode operation in 100Mbps, the CPSW needs to set the
IFCTL_A / IFCTL_B bits in the MACCONTROL register.
Signed-off-by: Daniel Mack <zonque@gmail.com>
Cc: Mugunthan V N <mugunthanvnm@ti.com>
Cc: Vaibhav Hiremath <hvaibhav@ti.com>
Cc: David S. Miller <davem@davemloft.net>
---
drivers/net/ethernet/ti/cpsw.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 3d7594e..d88dbfa 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -386,6 +386,12 @@ static void _cpsw_adjust_link(struct cpsw_slave *slave,
mac_control |= BIT(7); /* GIGABITEN */
if (phy->duplex)
mac_control |= BIT(0); /* FULLDUPLEXEN */
+
+ /* set speed_in input in case RMII mode is used in >10Mbps */
+ if (phy->speed > 10 && slave->slave_num < 2 &&
+ phy->interface == PHY_INTERFACE_MODE_RMII)
+ mac_control |= BIT(15 + slave->slave_num);
+
*link = true;
} else {
mac_control = 0;
--
1.7.11.4
^ permalink raw reply related
* [PATCH 1/2] net: ti cpsw ethernet: allow reading phy interface mode from DT
From: Daniel Mack @ 2012-09-26 17:24 UTC (permalink / raw)
To: netdev
Cc: devicetree-discuss, Daniel Mack, Mugunthan V N, Vaibhav Hiremath,
David S. Miller
Allow users to specify the phy interface of the CPSW slaves. The new
node parameter is called "phy_if_mode" and is optional. The original
behaviour of the driver is preserved when not given.
Signed-off-by: Daniel Mack <zonque@gmail.com>
Cc: Mugunthan V N <mugunthanvnm@ti.com>
Cc: Vaibhav Hiremath <hvaibhav@ti.com>
Cc: David S. Miller <davem@davemloft.net>
---
Documentation/devicetree/bindings/net/cpsw.txt | 3 +++
drivers/net/ethernet/ti/cpsw.c | 3 +++
2 files changed, 6 insertions(+)
diff --git a/Documentation/devicetree/bindings/net/cpsw.txt b/Documentation/devicetree/bindings/net/cpsw.txt
index dcaabe9..d87f7d2 100644
--- a/Documentation/devicetree/bindings/net/cpsw.txt
+++ b/Documentation/devicetree/bindings/net/cpsw.txt
@@ -25,6 +25,8 @@ Required properties:
- slave_reg_ofs : Specifies slave register offset
- sliver_reg_ofs : Specifies slave sliver register offset
- phy_id : Specifies slave phy id
+- phy_if_mode : Specified slave phy interface mode (optional)
+ (one of the PHY_INTERFACE_MODE_* as numerical value)
- mac-address : Specifies slave MAC address
Optional properties:
@@ -62,6 +64,7 @@ Examples:
slave_reg_ofs = <0x208>;
sliver_reg_ofs = <0xd80>;
phy_id = "davinci_mdio.16:00";
+ phy_if_mode = <6>; /* PHY_INTERFACE_MODE_RGMII */
/* Filled in by U-Boot */
mac-address = [ 00 00 00 00 00 00 ];
};
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index aa78168..3d7594e 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -850,6 +850,9 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
}
slave_data->sliver_reg_ofs = prop;
+ if (!of_property_read_u32(slave_node, "phy_if_mode", &prop))
+ slave_data->phy_if = prop;
+
mac_addr = of_get_mac_address(slave_node);
if (mac_addr)
memcpy(slave_data->mac_addr, mac_addr, ETH_ALEN);
--
1.7.11.4
^ permalink raw reply related
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