* Re: netxen_nic: unregister_netdevice error
From: Jiri Pirko @ 2011-05-31 10:12 UTC (permalink / raw)
To: Eric Dumazet; +Cc: WeipingPan, open list:NETWORKING [GENERAL]
In-Reply-To: <1306835326.2809.1.camel@edumazet-laptop>
Tue, May 31, 2011 at 11:48:46AM CEST, eric.dumazet@gmail.com wrote:
>Le mardi 31 mai 2011 à 17:21 +0800, WeipingPan a écrit :
>> On 05/31/2011 02:15 PM, WeipingPan wrote:
>> > hi,
>> >
>> > When test bonding broadcast mode I met a problem.
>> > modprobe -r bonding will fail after I ping broadcast address.
>> >
>> > I find that the problem only shows up when I use netxen_nic driver.
>> > When use ixgbe and bn2x2 driver, no problem occurs.
>> >
>> > I use RHEL 6.2, kernel 2.6.32-131.0.15.el6.i686,
>> > Can anybody confirm this bug using 2.6.39 or upstream ?
>> >
>> > many thanks
>> > Weiping Pan
>> >
>> I got a machine to test the
>> upstream,55922c9d1b84b89cb946c777fddccb3247e7df2c
>> the problem disappears.
>>
>> many thanks
>> Weiping Pan
>
>Might be solved by commit fc75fc8339e772716744 or
>
>commit 332dd96f7ac15e937088fe11f15c (net/dst: dst_dev_event() called
>after other notifiers) and commit ef885afbf8a37689 ((net: use
>rcu_barrier() inrollback_registered_many)
Thanks, for suggestions Eric. We'll try those.
>
>
>
>
>
>--
>To unsubscribe from this list: send the line "unsubscribe netdev" in
>the body of a message to majordomo@vger.kernel.org
>More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: netxen_nic: unregister_netdevice error
From: Eric Dumazet @ 2011-05-31 9:48 UTC (permalink / raw)
To: WeipingPan; +Cc: open list:NETWORKING [GENERAL]
In-Reply-To: <4DE4B31A.3090201@gmail.com>
Le mardi 31 mai 2011 à 17:21 +0800, WeipingPan a écrit :
> On 05/31/2011 02:15 PM, WeipingPan wrote:
> > hi,
> >
> > When test bonding broadcast mode I met a problem.
> > modprobe -r bonding will fail after I ping broadcast address.
> >
> > I find that the problem only shows up when I use netxen_nic driver.
> > When use ixgbe and bn2x2 driver, no problem occurs.
> >
> > I use RHEL 6.2, kernel 2.6.32-131.0.15.el6.i686,
> > Can anybody confirm this bug using 2.6.39 or upstream ?
> >
> > many thanks
> > Weiping Pan
> >
> I got a machine to test the
> upstream,55922c9d1b84b89cb946c777fddccb3247e7df2c
> the problem disappears.
>
> many thanks
> Weiping Pan
Might be solved by commit fc75fc8339e772716744 or
commit 332dd96f7ac15e937088fe11f15c (net/dst: dst_dev_event() called
after other notifiers) and commit ef885afbf8a37689 ((net: use
rcu_barrier() inrollback_registered_many)
^ permalink raw reply
* Re: netxen_nic: unregister_netdevice error
From: WeipingPan @ 2011-05-31 9:21 UTC (permalink / raw)
To: open list:NETWORKING [GENERAL]
In-Reply-To: <4DE4877C.1070704@gmail.com>
On 05/31/2011 02:15 PM, WeipingPan wrote:
> hi,
>
> When test bonding broadcast mode I met a problem.
> modprobe -r bonding will fail after I ping broadcast address.
>
> I find that the problem only shows up when I use netxen_nic driver.
> When use ixgbe and bn2x2 driver, no problem occurs.
>
> I use RHEL 6.2, kernel 2.6.32-131.0.15.el6.i686,
> Can anybody confirm this bug using 2.6.39 or upstream ?
>
> many thanks
> Weiping Pan
>
I got a machine to test the
upstream,55922c9d1b84b89cb946c777fddccb3247e7df2c
the problem disappears.
many thanks
Weiping Pan
^ permalink raw reply
* Re: netxen_nic: unregister_netdevice error
From: Jiri Pirko @ 2011-05-31 9:19 UTC (permalink / raw)
To: WeipingPan; +Cc: open list:NETWORKING [GENERAL]
In-Reply-To: <4DE4877C.1070704@gmail.com>
So apparently this does not occur on 3.0.0-rc1
Tue, May 31, 2011 at 08:15:24AM CEST, panweiping3@gmail.com wrote:
>hi,
>
>When test bonding broadcast mode I met a problem.
>modprobe -r bonding will fail after I ping broadcast address.
>
>I find that the problem only shows up when I use netxen_nic driver.
>When use ixgbe and bn2x2 driver, no problem occurs.
>
>I use RHEL 6.2, kernel 2.6.32-131.0.15.el6.i686,
>Can anybody confirm this bug using 2.6.39 or upstream ?
>
>many thanks
>Weiping Pan
>
>
>The test script is followed.
>
>#test script start
>#!/bin/bash
>
>NETWORK_CARD0=eth1
>NETWORK_CARD1=eth2
>
>
>function broadcast_test()
>{
> modprobe bonding mode=broadcast miimon=100
> ifconfig bond0 192.168.8.2 netmask 255.255.255.0 up
> ifconfig $NETWORK_CARD0 down
> ifconfig $NETWORK_CARD1 down
> echo +$NETWORK_CARD0 > /sys/class/net/bond0/bonding/slaves
> echo +$NETWORK_CARD1 > /sys/class/net/bond0/bonding/slaves
> ping 192.168.8.255 -b -c 10
> modprobe -r bonding
>}
>
># main
>echo 0 >/proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
>modprobe -r bonding
>
>for i in `seq 1 10`
>do
> echo "*******************"
> echo "***iteration$i*****"
> echo -e "*******************\n\n"
> broadcast_test
>done
>#test script end
>
>
>Some information is followed.
>[root@hp-magnycours-01 ~]# uname -a
>Linux hp-magnycours-01.rhts.eng.bos.redhat.com
>2.6.32-131.0.15.el6.i686 #1 SMP Tue May 10 15:42:28 EDT 2011 i686
>i686 i386 GNU/Linux
>
>[root@hp-magnycours-01 ~]# cat /etc/redhat-release
>Red Hat Enterprise Linux Server release 6.1 (Santiago)
>
>[root@hp-magnycours-01 ~]# lspci |grep Ethernet
>04:00.0 Ethernet controller: NetXen Incorporated NX3031 Multifunction
>1/10-Gigabit Server Adapter (rev 42)
>04:00.1 Ethernet controller: NetXen Incorporated NX3031 Multifunction
>1/10-Gigabit Server Adapter (rev 42)
>04:00.2 Ethernet controller: NetXen Incorporated NX3031 Multifunction
>1/10-Gigabit Server Adapter (rev 42)
>04:00.3 Ethernet controller: NetXen Incorporated NX3031 Multifunction
>1/10-Gigabit Server Adapter (rev 42)
>
>[root@hp-magnycours-01 ~]# lsmod |grep net
>netxen_nic 83405 0
>
>[root@hp-magnycours-01 ~]# ifconfig -a
>eth0 Link encap:Ethernet HWaddr 1C:C1:DE:EE:28:F0
> inet addr:10.16.64.212 Bcast:10.16.71.255 Mask:255.255.248.0
> inet6 addr: fec0:0:a10:4000:1ec1:deff:feee:28f0/64 Scope:Site
> inet6 addr: fe80::1ec1:deff:feee:28f0/64 Scope:Link
> UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
> RX packets:13417 errors:0 dropped:0 overruns:0 frame:0
> TX packets:713 errors:0 dropped:0 overruns:0 carrier:0
> collisions:0 txqueuelen:1000
> RX bytes:1110663 (1.0 MiB) TX bytes:90272 (88.1 KiB)
> Interrupt:93
>
>eth1 Link encap:Ethernet HWaddr 1C:C1:DE:EE:28:F1
> BROADCAST MULTICAST MTU:1500 Metric:1
> RX packets:0 errors:0 dropped:0 overruns:0 frame:0
> TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
> collisions:0 txqueuelen:1000
> RX bytes:0 (0.0 b) TX bytes:0 (0.0 b)
> Interrupt:97
>
>eth2 Link encap:Ethernet HWaddr 1C:C1:DE:EE:28:F2
> BROADCAST MULTICAST MTU:1500 Metric:1
> RX packets:0 errors:0 dropped:0 overruns:0 frame:0
> TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
> collisions:0 txqueuelen:1000
> RX bytes:0 (0.0 b) TX bytes:0 (0.0 b)
> Interrupt:101
>
>eth3 Link encap:Ethernet HWaddr 1C:C1:DE:EE:28:F3
> BROADCAST MULTICAST MTU:1500 Metric:1
> RX packets:0 errors:0 dropped:0 overruns:0 frame:0
> TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
> collisions:0 txqueuelen:1000
> RX bytes:0 (0.0 b) TX bytes:0 (0.0 b)
> Interrupt:105
>
>lo Link encap:Local Loopback
> inet addr:127.0.0.1 Mask:255.0.0.0
> inet6 addr: ::1/128 Scope:Host
> UP LOOPBACK RUNNING MTU:16436 Metric:1
> RX packets:18 errors:0 dropped:0 overruns:0 frame:0
> TX packets:18 errors:0 dropped:0 overruns:0 carrier:0
> collisions:0 txqueuelen:0
> RX bytes:10557 (10.3 KiB) TX bytes:10557 (10.3 KiB)
>
>
>[root@hp-magnycours-01 ~]# ./test_bonding_broadcast.sh |tee log
>*******************
>***iteration1*****
>*******************
>
>
>WARNING: pinging broadcast address
>PING 192.168.8.255 (192.168.8.255) 56(84) bytes of data.
>64 bytes from 192.168.8.2: icmp_seq=1 ttl=64 time=0.041 ms
>64 bytes from 192.168.8.2: icmp_seq=2 ttl=64 time=0.029 ms
>64 bytes from 192.168.8.2: icmp_seq=3 ttl=64 time=0.027 ms
>64 bytes from 192.168.8.2: icmp_seq=4 ttl=64 time=0.026 ms
>64 bytes from 192.168.8.2: icmp_seq=5 ttl=64 time=0.030 ms
>64 bytes from 192.168.8.2: icmp_seq=6 ttl=64 time=0.024 ms
>64 bytes from 192.168.8.2: icmp_seq=7 ttl=64 time=0.024 ms
>64 bytes from 192.168.8.2: icmp_seq=8 ttl=64 time=0.023 ms
>64 bytes from 192.168.8.2: icmp_seq=9 ttl=64 time=0.024 ms
>64 bytes from 192.168.8.2: icmp_seq=10 ttl=64 time=0.023 ms
>
>--- 192.168.8.255 ping statistics ---
>10 packets transmitted, 10 received, 0% packet loss, time 9000ms
>rtt min/avg/max/mdev = 0.023/0.027/0.041/0.005 ms
>
>Message from syslogd@hp-magnycours-01 at May 25 04:07:22 ...
> kernel:unregister_netdevice: waiting for bond0 to become free. Usage
>count = 1
>
>Message from syslogd@hp-magnycours-01 at May 25 04:07:33 ...
> kernel:unregister_netdevice: waiting for bond0 to become free. Usage
>count = 1
>
>
>[root@hp-magnycours-01 ~]# dmesg
>Ethernet Channel Bonding Driver: v3.6.0 (September 26, 2009)
>bonding: MII link monitoring set to 100 ms
>ADDRCONF(NETDEV_UP): bond0: link is not ready
>bonding: bond0: Adding slave eth1.
>bonding: bond0: enslaving eth1 as an active interface with a down link.
>netxen_nic: eth1 NIC Link is up
>bonding: bond0: Adding slave eth2.
>bonding: bond0: enslaving eth2 as an active interface with a down link.
>netxen_nic: eth2 NIC Link is up
>bonding: bond0: link status definitely up for interface eth1.
>bonding: bond0: link status definitely up for interface eth2.
>ADDRCONF(NETDEV_CHANGE): bond0: link becomes ready
>bond0: IPv6 duplicate address fe80::1ec1:deff:feee:28f1 detected!
>bonding: bond0: released all slaves
>unregister_netdevice: waiting for bond0 to become free. Usage count = 1
>unregister_netdevice: waiting for bond0 to become free. Usage count = 1
>unregister_netdevice: waiting for bond0 to become free. Usage count = 1
>unregister_netdevice: waiting for bond0 to become free. Usage count = 1
>
>--
>To unsubscribe from this list: send the line "unsubscribe netdev" in
>the body of a message to majordomo@vger.kernel.org
>More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH net-next-2.6] be2net: Fallback to the older opcode if MCC_CREATE_EXT opcode is not supported on the card
From: Somnath Kotur @ 2011-05-31 14:22 UTC (permalink / raw)
To: netdev, davem; +Cc: Somnath Kotur
Instead of failing the init/probe code in the driver fallback to the older opcode
to ensure the driver is loaded thereby enabling users to upgrade the f/w to
whatever version is required.
Signed-off-by: Somnath Kotur <somnath.kotur@emulex.com>
---
drivers/net/benet/be_cmds.c | 65 +++++++++++++++++++++++++++++++++++++++++-
drivers/net/benet/be_cmds.h | 8 +++++
drivers/net/benet/be_main.c | 4 ++
3 files changed, 75 insertions(+), 2 deletions(-)
diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c
index 2463b1c..6c75f54 100644
--- a/drivers/net/benet/be_cmds.c
+++ b/drivers/net/benet/be_cmds.c
@@ -799,12 +799,12 @@ static u32 be_encoded_q_len(int q_len)
return len_encoded;
}
-int be_cmd_mccq_create(struct be_adapter *adapter,
+int be_cmd_mccq_ext_create(struct be_adapter *adapter,
struct be_queue_info *mccq,
struct be_queue_info *cq)
{
struct be_mcc_wrb *wrb;
- struct be_cmd_req_mcc_create *req;
+ struct be_cmd_req_mcc_ext_create *req;
struct be_dma_mem *q_mem = &mccq->dma_mem;
void *ctxt;
int status;
@@ -859,6 +859,67 @@ int be_cmd_mccq_create(struct be_adapter *adapter,
return status;
}
+int be_cmd_mccq_org_create(struct be_adapter *adapter,
+ struct be_queue_info *mccq,
+ struct be_queue_info *cq)
+{
+ struct be_mcc_wrb *wrb;
+ struct be_cmd_req_mcc_create *req;
+ struct be_dma_mem *q_mem = &mccq->dma_mem;
+ void *ctxt;
+ int status;
+
+ if (mutex_lock_interruptible(&adapter->mbox_lock))
+ return -1;
+
+ wrb = wrb_from_mbox(adapter);
+ req = embedded_payload(wrb);
+ ctxt = &req->context;
+
+ be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
+ OPCODE_COMMON_MCC_CREATE);
+
+ be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_MCC_CREATE, sizeof(*req));
+
+ req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
+
+ AMAP_SET_BITS(struct amap_mcc_context_be, valid, ctxt, 1);
+ AMAP_SET_BITS(struct amap_mcc_context_be, ring_size, ctxt,
+ be_encoded_q_len(mccq->len));
+ AMAP_SET_BITS(struct amap_mcc_context_be, cq_id, ctxt, cq->id);
+
+ be_dws_cpu_to_le(ctxt, sizeof(req->context));
+
+ be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
+
+ status = be_mbox_notify_wait(adapter);
+ if (!status) {
+ struct be_cmd_resp_mcc_create *resp = embedded_payload(wrb);
+ mccq->id = le16_to_cpu(resp->id);
+ mccq->created = true;
+ }
+
+ mutex_unlock(&adapter->mbox_lock);
+ return status;
+}
+
+int be_cmd_mccq_create(struct be_adapter *adapter,
+ struct be_queue_info *mccq,
+ struct be_queue_info *cq)
+{
+ int status;
+
+ status = be_cmd_mccq_ext_create(adapter, mccq, cq);
+ if (status && !lancer_chip(adapter)) {
+ dev_warn(&adapter->pdev->dev, "Upgrade to F/W ver 2.102.235.0 "
+ "or newer to avoid conflicting priorities between NIC "
+ "and FCoE traffic");
+ status = be_cmd_mccq_org_create(adapter, mccq, cq);
+ }
+ return status;
+}
+
int be_cmd_txq_create(struct be_adapter *adapter,
struct be_queue_info *txq,
struct be_queue_info *cq)
diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h
index 8148cc6..d08289e 100644
--- a/drivers/net/benet/be_cmds.h
+++ b/drivers/net/benet/be_cmds.h
@@ -434,6 +434,14 @@ struct be_cmd_req_mcc_create {
struct be_cmd_req_hdr hdr;
u16 num_pages;
u16 cq_id;
+ u8 context[sizeof(struct amap_mcc_context_be) / 8];
+ struct phys_addr pages[8];
+} __packed;
+
+struct be_cmd_req_mcc_ext_create {
+ struct be_cmd_req_hdr hdr;
+ u16 num_pages;
+ u16 cq_id;
u32 async_event_bitmap[1];
u8 context[sizeof(struct amap_mcc_context_be) / 8];
struct phys_addr pages[8];
diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c
index 4b5e0ed..4a034cc 100644
--- a/drivers/net/benet/be_main.c
+++ b/drivers/net/benet/be_main.c
@@ -3395,6 +3395,10 @@ static int __devinit be_probe(struct pci_dev *pdev,
}
dev_info(&pdev->dev, "%s port %d\n", nic_name(pdev), adapter->port_num);
+ /* By default all priorities are enabled.
+ Needed in case of no GRP5 evt support */
+ adapter->vlan_prio_bmap = 0xff;
+
schedule_delayed_work(&adapter->work, msecs_to_jiffies(100));
return 0;
--
1.5.6.1
^ permalink raw reply related
* [RFC/PATCH] sungem: Spring cleaning and GRO support
From: Benjamin Herrenschmidt @ 2011-05-31 7:59 UTC (permalink / raw)
To: David Miller; +Cc: netdev, R. Herbst, Brian Hamilton
Hi David !
For RFC only at this stage, see blow why.
This patch simplifies the logic and locking in sungem significantly:
- LLTX is gone, private tx lock is gone
- We don't poll the PHY while the interface is down
- The above allowed me to get rid of a pile of state flags
using the proper interface state provided by the networking
stack when needed
- Allocate the bulk of RX skbs at init time using GFP_KERNEL
- Fix a bug where the dev->features were set after register_netdev()
- Added GRO while at it
Now the results .... on a dual G5 machine with a 1000Mb link, no
measurable netperf difference on Rx and a 3% loss on Tx.
So taking the lock is the Tx path hurts... now the question is,
do we just ditch the patch and stick with LLTX or do we say too
bad, locks suck on power, code being simpler is still worth it
and we merge it (+/- more review & testing of course) ?
I've done some suspend/resume tests on a couple of powerbook,
tortured the link a bit and it seems to be solid.
Oh and David, I've bumped the version number (though it's more
or less pointless imho) and ditched the release date which I
really don't see the point of... let me know if you object.
Opinions ?
Cheers,
Ben.
Not-Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
drivers/net/sungem.c | 684 +++++++++++++++++++++++---------------------------
drivers/net/sungem.h | 20 --
2 files changed, 316 insertions(+), 388 deletions(-)
diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c
index ab59300..33cac54 100644
--- a/drivers/net/sungem.c
+++ b/drivers/net/sungem.c
@@ -10,25 +10,6 @@
* NAPI and NETPOLL support
* (C) 2004 by Eric Lemoine (eric.lemoine@gmail.com)
*
- * TODO:
- * - Now that the driver was significantly simplified, I need to rework
- * the locking. I'm sure we don't need _2_ spinlocks, and we probably
- * can avoid taking most of them for so long period of time (and schedule
- * instead). The main issues at this point are caused by the netdev layer
- * though:
- *
- * gem_change_mtu() and gem_set_multicast() are called with a read_lock()
- * help by net/core/dev.c, thus they can't schedule. That means they can't
- * call napi_disable() neither, thus force gem_poll() to keep a spinlock
- * where it could have been dropped. change_mtu especially would love also to
- * be able to msleep instead of horrid locked delays when resetting the HW,
- * but that read_lock() makes it impossible, unless I defer it's action to
- * the reset task, which means it'll be asynchronous (won't take effect until
- * the system schedules a bit).
- *
- * Also, it would probably be possible to also remove most of the long-life
- * locking in open/resume code path (gem_reinit_chip) by beeing more careful
- * about when we can start taking interrupts or get xmit() called...
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -95,12 +76,11 @@
SUPPORTED_Pause | SUPPORTED_Autoneg)
#define DRV_NAME "sungem"
-#define DRV_VERSION "0.98"
-#define DRV_RELDATE "8/24/03"
-#define DRV_AUTHOR "David S. Miller (davem@redhat.com)"
+#define DRV_VERSION "1.0"
+#define DRV_AUTHOR "David S. Miller <davem@redhat.com>"
static char version[] __devinitdata =
- DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " " DRV_AUTHOR "\n";
+ DRV_NAME ".c:v" DRV_VERSION " " DRV_AUTHOR "\n";
MODULE_AUTHOR(DRV_AUTHOR);
MODULE_DESCRIPTION("Sun GEM Gbit ethernet driver");
@@ -218,6 +198,7 @@ static inline void gem_disable_ints(struct gem *gp)
{
/* Disable all interrupts, including TXDONE */
writel(GREG_STAT_NAPI | GREG_STAT_TXDONE, gp->regs + GREG_IMASK);
+ (void)readl(gp->regs + GREG_IMASK); /* write posting */
}
static void gem_get_cell(struct gem *gp)
@@ -247,6 +228,29 @@ static void gem_put_cell(struct gem *gp)
#endif /* CONFIG_PPC_PMAC */
}
+static inline void gem_netif_stop(struct gem *gp)
+{
+ gp->dev->trans_start = jiffies; /* prevent tx timeout */
+ napi_disable(&gp->napi);
+ netif_tx_disable(gp->dev);
+}
+
+static inline void gem_netif_start(struct gem *gp)
+{
+ /* NOTE: unconditional netif_wake_queue is only
+ * appropriate so long as all callers are assured to
+ * have free tx slots.
+ */
+ netif_wake_queue(gp->dev);
+ napi_enable(&gp->napi);
+}
+
+static void gem_schedule_reset(struct gem *gp)
+{
+ gp->reset_task_pending = 1;
+ schedule_work(&gp->reset_task);
+}
+
static void gem_handle_mif_event(struct gem *gp, u32 reg_val, u32 changed_bits)
{
if (netif_msg_intr(gp))
@@ -640,8 +644,7 @@ static int gem_abnormal_irq(struct net_device *dev, struct gem *gp, u32 gem_stat
return 0;
do_reset:
- gp->reset_task_pending = 1;
- schedule_work(&gp->reset_task);
+ gem_schedule_reset(gp);
return 1;
}
@@ -650,10 +653,6 @@ static __inline__ void gem_tx(struct net_device *dev, struct gem *gp, u32 gem_st
{
int entry, limit;
- if (netif_msg_intr(gp))
- printk(KERN_DEBUG "%s: tx interrupt, gem_status: 0x%x\n",
- gp->dev->name, gem_status);
-
entry = gp->tx_old;
limit = ((gem_status & GREG_STAT_TXNR) >> GREG_STAT_TXNR_SHIFT);
while (entry != limit) {
@@ -697,13 +696,25 @@ static __inline__ void gem_tx(struct net_device *dev, struct gem *gp, u32 gem_st
}
dev->stats.tx_packets++;
- dev_kfree_skb_irq(skb);
+ dev_kfree_skb(skb);
}
gp->tx_old = entry;
- if (netif_queue_stopped(dev) &&
- TX_BUFFS_AVAIL(gp) > (MAX_SKB_FRAGS + 1))
- netif_wake_queue(dev);
+ /* Need to make the tx_old update visible to gem_start_xmit()
+ * before checking for netif_queue_stopped(). Without the
+ * memory barrier, there is a small possibility that gem_start_xmit()
+ * will miss it and cause the queue to be stopped forever.
+ */
+ smp_mb();
+
+ if (unlikely(netif_queue_stopped(dev) &&
+ TX_BUFFS_AVAIL(gp) > (MAX_SKB_FRAGS + 1))) {
+ netif_tx_lock(dev);
+ if (netif_queue_stopped(dev) &&
+ TX_BUFFS_AVAIL(gp) > (MAX_SKB_FRAGS + 1))
+ netif_wake_queue(dev);
+ netif_tx_unlock(dev);
+ }
}
static __inline__ void gem_post_rxds(struct gem *gp, int limit)
@@ -736,6 +747,22 @@ static __inline__ void gem_post_rxds(struct gem *gp, int limit)
}
}
+#define ALIGNED_RX_SKB_ADDR(addr) \
+ ((((unsigned long)(addr) + (64UL - 1UL)) & ~(64UL - 1UL)) - (unsigned long)(addr))
+static __inline__ struct sk_buff *gem_alloc_skb(struct net_device *dev, int size,
+ gfp_t gfp_flags)
+{
+ struct sk_buff *skb = alloc_skb(size + 64, gfp_flags);
+
+ if (likely(skb)) {
+ int offset = (int) ALIGNED_RX_SKB_ADDR(skb->data);
+ if (offset)
+ skb_reserve(skb, offset);
+ skb->dev = dev;
+ }
+ return skb;
+}
+
static int gem_rx(struct gem *gp, int work_to_do)
{
struct net_device *dev = gp->dev;
@@ -799,7 +826,7 @@ static int gem_rx(struct gem *gp, int work_to_do)
if (len > RX_COPY_THRESHOLD) {
struct sk_buff *new_skb;
- new_skb = gem_alloc_skb(RX_BUF_ALLOC_SIZE(gp), GFP_ATOMIC);
+ new_skb = gem_alloc_skb(dev, RX_BUF_ALLOC_SIZE(gp), GFP_ATOMIC);
if (new_skb == NULL) {
drops++;
goto drop_it;
@@ -808,7 +835,6 @@ static int gem_rx(struct gem *gp, int work_to_do)
RX_BUF_ALLOC_SIZE(gp),
PCI_DMA_FROMDEVICE);
gp->rx_skbs[entry] = new_skb;
- new_skb->dev = gp->dev;
skb_put(new_skb, (gp->rx_buf_sz + RX_OFFSET));
rxd->buffer = cpu_to_le64(pci_map_page(gp->pdev,
virt_to_page(new_skb->data),
@@ -820,7 +846,7 @@ static int gem_rx(struct gem *gp, int work_to_do)
/* Trim the original skb for the netif. */
skb_trim(skb, len);
} else {
- struct sk_buff *copy_skb = dev_alloc_skb(len + 2);
+ struct sk_buff *copy_skb = netdev_alloc_skb(dev, len + 2);
if (copy_skb == NULL) {
drops++;
@@ -842,7 +868,7 @@ static int gem_rx(struct gem *gp, int work_to_do)
skb->ip_summed = CHECKSUM_COMPLETE;
skb->protocol = eth_type_trans(skb, gp->dev);
- netif_receive_skb(skb);
+ napi_gro_receive(&gp->napi, skb);
dev->stats.rx_packets++;
dev->stats.rx_bytes += len;
@@ -865,28 +891,20 @@ static int gem_poll(struct napi_struct *napi, int budget)
{
struct gem *gp = container_of(napi, struct gem, napi);
struct net_device *dev = gp->dev;
- unsigned long flags;
int work_done;
- /*
- * NAPI locking nightmare: See comment at head of driver
- */
- spin_lock_irqsave(&gp->lock, flags);
-
work_done = 0;
do {
/* Handle anomalies */
- if (gp->status & GREG_STAT_ABNORMAL) {
- if (gem_abnormal_irq(dev, gp, gp->status))
- break;
+ if (unlikely(gp->status & GREG_STAT_ABNORMAL)) {
+ if (gem_abnormal_irq(dev, gp, gp->status)) {
+ napi_complete(napi);
+ return work_done;
+ }
}
/* Run TX completion thread */
- spin_lock(&gp->tx_lock);
gem_tx(dev, gp, gp->status);
- spin_unlock(&gp->tx_lock);
-
- spin_unlock_irqrestore(&gp->lock, flags);
/* Run RX thread. We don't use any locking here,
* code willing to do bad things - like cleaning the
@@ -898,16 +916,12 @@ static int gem_poll(struct napi_struct *napi, int budget)
if (work_done >= budget)
return work_done;
- spin_lock_irqsave(&gp->lock, flags);
-
gp->status = readl(gp->regs + GREG_STAT);
} while (gp->status & GREG_STAT_NAPI);
- __napi_complete(napi);
+ napi_complete(napi);
gem_enable_ints(gp);
- spin_unlock_irqrestore(&gp->lock, flags);
-
return work_done;
}
@@ -915,32 +929,23 @@ static irqreturn_t gem_interrupt(int irq, void *dev_id)
{
struct net_device *dev = dev_id;
struct gem *gp = netdev_priv(dev);
- unsigned long flags;
-
- /* Swallow interrupts when shutting the chip down, though
- * that shouldn't happen, we should have done free_irq() at
- * this point...
- */
- if (!gp->running)
- return IRQ_HANDLED;
-
- spin_lock_irqsave(&gp->lock, flags);
if (napi_schedule_prep(&gp->napi)) {
u32 gem_status = readl(gp->regs + GREG_STAT);
- if (gem_status == 0) {
+ if (unlikely(gem_status == 0)) {
napi_enable(&gp->napi);
- spin_unlock_irqrestore(&gp->lock, flags);
return IRQ_NONE;
}
+ if (netif_msg_intr(gp))
+ printk(KERN_DEBUG "%s: gem_interrupt() gem_status: 0x%x\n",
+ gp->dev->name, gem_status);
+
gp->status = gem_status;
gem_disable_ints(gp);
__napi_schedule(&gp->napi);
}
- spin_unlock_irqrestore(&gp->lock, flags);
-
/* If polling was disabled at the time we received that
* interrupt, we may return IRQ_HANDLED here while we
* should return IRQ_NONE. No big deal...
@@ -951,11 +956,12 @@ static irqreturn_t gem_interrupt(int irq, void *dev_id)
#ifdef CONFIG_NET_POLL_CONTROLLER
static void gem_poll_controller(struct net_device *dev)
{
- /* gem_interrupt is safe to reentrance so no need
- * to disable_irq here.
- */
- gem_interrupt(dev->irq, dev);
-}
+ struct gem *gp = netdev_priv(dev);
+
+ disable_irq(gp->pdev->irq);
+ gem_interrupt(gp->pdev->irq, dev);
+ enable_irq(gp->pdev->irq);
+
#endif
static void gem_tx_timeout(struct net_device *dev)
@@ -963,10 +969,7 @@ static void gem_tx_timeout(struct net_device *dev)
struct gem *gp = netdev_priv(dev);
netdev_err(dev, "transmit timed out, resetting\n");
- if (!gp->running) {
- netdev_err(dev, "hrm.. hw not running !\n");
- return;
- }
+
netdev_err(dev, "TX_STATE[%08x:%08x:%08x]\n",
readl(gp->regs + TXDMA_CFG),
readl(gp->regs + MAC_TXSTAT),
@@ -976,14 +979,9 @@ static void gem_tx_timeout(struct net_device *dev)
readl(gp->regs + MAC_RXSTAT),
readl(gp->regs + MAC_RXCFG));
- spin_lock_irq(&gp->lock);
- spin_lock(&gp->tx_lock);
-
- gp->reset_task_pending = 1;
- schedule_work(&gp->reset_task);
-
- spin_unlock(&gp->tx_lock);
- spin_unlock_irq(&gp->lock);
+ spin_lock(&gp->lock);
+ gem_schedule_reset(gp);
+ spin_unlock(&gp->lock);
}
static __inline__ int gem_intme(int entry)
@@ -1001,7 +999,6 @@ static netdev_tx_t gem_start_xmit(struct sk_buff *skb,
struct gem *gp = netdev_priv(dev);
int entry;
u64 ctrl;
- unsigned long flags;
ctrl = 0;
if (skb->ip_summed == CHECKSUM_PARTIAL) {
@@ -1013,21 +1010,12 @@ static netdev_tx_t gem_start_xmit(struct sk_buff *skb,
(csum_stuff_off << 21));
}
- if (!spin_trylock_irqsave(&gp->tx_lock, flags)) {
- /* Tell upper layer to requeue */
- return NETDEV_TX_LOCKED;
- }
- /* We raced with gem_do_stop() */
- if (!gp->running) {
- spin_unlock_irqrestore(&gp->tx_lock, flags);
- return NETDEV_TX_BUSY;
- }
-
- /* This is a hard error, log it. */
- if (TX_BUFFS_AVAIL(gp) <= (skb_shinfo(skb)->nr_frags + 1)) {
- netif_stop_queue(dev);
- spin_unlock_irqrestore(&gp->tx_lock, flags);
- netdev_err(dev, "BUG! Tx Ring full when queue awake!\n");
+ if (unlikely(TX_BUFFS_AVAIL(gp) <= (skb_shinfo(skb)->nr_frags + 1))) {
+ /* This is a hard error, log it. */
+ if (!netif_queue_stopped(dev)) {
+ netif_stop_queue(dev);
+ netdev_err(dev, "BUG! Tx Ring full when queue awake!\n");
+ }
return NETDEV_TX_BUSY;
}
@@ -1104,17 +1092,23 @@ static netdev_tx_t gem_start_xmit(struct sk_buff *skb,
}
gp->tx_new = entry;
- if (TX_BUFFS_AVAIL(gp) <= (MAX_SKB_FRAGS + 1))
+ if (unlikely(TX_BUFFS_AVAIL(gp) <= (MAX_SKB_FRAGS + 1))) {
netif_stop_queue(dev);
+ /* netif_stop_queue() must be done before checking
+ * checking tx index in TX_BUFFS_AVAIL() below, because
+ * in gem_tx(), we update tx_old before checking for
+ * netif_queue_stopped().
+ */
+ smp_mb();
+ if (TX_BUFFS_AVAIL(gp) > (MAX_SKB_FRAGS + 1))
+ netif_wake_queue(dev);
+ }
if (netif_msg_tx_queued(gp))
printk(KERN_DEBUG "%s: tx queued, slot %d, skblen %d\n",
dev->name, entry, skb->len);
mb();
writel(gp->tx_new, gp->regs + TXDMA_KICK);
- spin_unlock_irqrestore(&gp->tx_lock, flags);
-
- dev->trans_start = jiffies; /* NETIF_F_LLTX driver :( */
return NETDEV_TX_OK;
}
@@ -1184,7 +1178,6 @@ static void gem_pcs_reinit_adv(struct gem *gp)
#define STOP_TRIES 32
-/* Must be invoked under gp->lock and gp->tx_lock. */
static void gem_reset(struct gem *gp)
{
int limit;
@@ -1213,7 +1206,6 @@ static void gem_reset(struct gem *gp)
gem_pcs_reinit_adv(gp);
}
-/* Must be invoked under gp->lock and gp->tx_lock. */
static void gem_start_dma(struct gem *gp)
{
u32 val;
@@ -1236,8 +1228,7 @@ static void gem_start_dma(struct gem *gp)
writel(RX_RING_SIZE - 4, gp->regs + RXDMA_KICK);
}
-/* Must be invoked under gp->lock and gp->tx_lock. DMA won't be
- * actually stopped before about 4ms tho ...
+/* DMA won't be actually stopped before about 4ms tho ...
*/
static void gem_stop_dma(struct gem *gp)
{
@@ -1259,7 +1250,7 @@ static void gem_stop_dma(struct gem *gp)
}
-/* Must be invoked under gp->lock and gp->tx_lock. */
+/* Must be invoked under gp->lock */
// XXX dbl check what that function should do when called on PCS PHY
static void gem_begin_auto_negotiation(struct gem *gp, struct ethtool_cmd *ep)
{
@@ -1319,7 +1310,7 @@ start_aneg:
/* If we are asleep, we don't try to actually setup the PHY, we
* just store the settings
*/
- if (gp->asleep) {
+ if (!netif_device_present(gp->dev)) {
gp->phy_mii.autoneg = gp->want_autoneg = autoneg;
gp->phy_mii.speed = speed;
gp->phy_mii.duplex = duplex;
@@ -1345,8 +1336,6 @@ non_mii:
/* A link-up condition has occurred, initialize and enable the
* rest of the chip.
- *
- * Must be invoked under gp->lock and gp->tx_lock.
*/
static int gem_set_link_modes(struct gem *gp)
{
@@ -1375,7 +1364,11 @@ static int gem_set_link_modes(struct gem *gp)
netif_info(gp, link, gp->dev, "Link is up at %d Mbps, %s-duplex\n",
speed, (full_duplex ? "full" : "half"));
- if (!gp->running)
+ /* This can happen after the core makes netif_running true
+ * and before we've taken the lock & enabled the cell so
+ * guard against it here
+ */
+ if (!netif_running(gp->dev) || !netif_device_present(gp->dev))
return 0;
val = (MAC_TXCFG_EIPG0 | MAC_TXCFG_NGU);
@@ -1453,7 +1446,6 @@ static int gem_set_link_modes(struct gem *gp)
return 0;
}
-/* Must be invoked under gp->lock and gp->tx_lock. */
static int gem_mdio_link_not_up(struct gem *gp)
{
switch (gp->lstate) {
@@ -1501,13 +1493,14 @@ static int gem_mdio_link_not_up(struct gem *gp)
static void gem_link_timer(unsigned long data)
{
struct gem *gp = (struct gem *) data;
+ struct net_device *dev = gp->dev;
int restart_aneg = 0;
- if (gp->asleep)
+ spin_lock(&gp->lock);
+ if (!netif_running(dev) || !netif_device_present(dev)) {
+ spin_unlock(&gp->lock);
return;
-
- spin_lock_irq(&gp->lock);
- spin_lock(&gp->tx_lock);
+ }
gem_get_cell(gp);
/* If the reset task is still pending, we just
@@ -1528,7 +1521,7 @@ static void gem_link_timer(unsigned long data)
goto restart;
gp->lstate = link_up;
- netif_carrier_on(gp->dev);
+ netif_carrier_on(dev);
(void)gem_set_link_modes(gp);
}
goto restart;
@@ -1544,12 +1537,12 @@ static void gem_link_timer(unsigned long data)
gp->last_forced_speed = gp->phy_mii.speed;
gp->timer_ticks = 5;
if (netif_msg_link(gp))
- netdev_info(gp->dev,
+ netdev_info(dev,
"Got link after fallback, retrying autoneg once...\n");
gp->phy_mii.def->ops->setup_aneg(&gp->phy_mii, gp->phy_mii.advertising);
} else if (gp->lstate != link_up) {
gp->lstate = link_up;
- netif_carrier_on(gp->dev);
+ netif_carrier_on(dev);
if (gem_set_link_modes(gp))
restart_aneg = 1;
}
@@ -1559,11 +1552,11 @@ static void gem_link_timer(unsigned long data)
*/
if (gp->lstate == link_up) {
gp->lstate = link_down;
- netif_info(gp, link, gp->dev, "Link down\n");
- netif_carrier_off(gp->dev);
- gp->reset_task_pending = 1;
- schedule_work(&gp->reset_task);
- restart_aneg = 1;
+ netif_info(gp, link, dev, "Link down\n");
+ netif_carrier_off(dev);
+ gem_schedule_reset(gp);
+ /* The reset task will restart the timer */
+ goto out_unlock;
} else if (++gp->timer_ticks > 10) {
if (found_mii_phy(gp))
restart_aneg = gem_mdio_link_not_up(gp);
@@ -1579,11 +1572,9 @@ restart:
mod_timer(&gp->link_timer, jiffies + ((12 * HZ) / 10));
out_unlock:
gem_put_cell(gp);
- spin_unlock(&gp->tx_lock);
- spin_unlock_irq(&gp->lock);
+ spin_unlock(&gp->lock);
}
-/* Must be invoked under gp->lock and gp->tx_lock. */
static void gem_clean_rings(struct gem *gp)
{
struct gem_init_block *gb = gp->init_block;
@@ -1634,7 +1625,6 @@ static void gem_clean_rings(struct gem *gp)
}
}
-/* Must be invoked under gp->lock and gp->tx_lock. */
static void gem_init_rings(struct gem *gp)
{
struct gem_init_block *gb = gp->init_block;
@@ -1653,7 +1643,7 @@ static void gem_init_rings(struct gem *gp)
struct sk_buff *skb;
struct gem_rxd *rxd = &gb->rxd[i];
- skb = gem_alloc_skb(RX_BUF_ALLOC_SIZE(gp), GFP_ATOMIC);
+ skb = gem_alloc_skb(dev, RX_BUF_ALLOC_SIZE(gp), GFP_KERNEL);
if (!skb) {
rxd->buffer = 0;
rxd->status_word = 0;
@@ -1661,7 +1651,6 @@ static void gem_init_rings(struct gem *gp)
}
gp->rx_skbs[i] = skb;
- skb->dev = dev;
skb_put(skb, (gp->rx_buf_sz + RX_OFFSET));
dma_addr = pci_map_page(gp->pdev,
virt_to_page(skb->data),
@@ -1753,13 +1742,17 @@ static void gem_init_phy(struct gem *gp)
gp->lstate = link_down;
netif_carrier_off(gp->dev);
- /* Can I advertise gigabit here ? I'd need BCM PHY docs... */
- spin_lock_irq(&gp->lock);
+ /* Print things out */
+ if (gp->phy_type == phy_mii_mdio0 ||
+ gp->phy_type == phy_mii_mdio1)
+ netdev_info(gp->dev, "Found %s PHY\n",
+ gp->phy_mii.def ? gp->phy_mii.def->name : "no");
+
+ spin_lock_bh(&gp->lock);
gem_begin_auto_negotiation(gp, NULL);
- spin_unlock_irq(&gp->lock);
+ spin_unlock_bh(&gp->lock);
}
-/* Must be invoked under gp->lock and gp->tx_lock. */
static void gem_init_dma(struct gem *gp)
{
u64 desc_dma = (u64) gp->gblock_dvma;
@@ -1797,7 +1790,6 @@ static void gem_init_dma(struct gem *gp)
gp->regs + RXDMA_BLANK);
}
-/* Must be invoked under gp->lock and gp->tx_lock. */
static u32 gem_setup_multicast(struct gem *gp)
{
u32 rxcfg = 0;
@@ -1835,7 +1827,6 @@ static u32 gem_setup_multicast(struct gem *gp)
return rxcfg;
}
-/* Must be invoked under gp->lock and gp->tx_lock. */
static void gem_init_mac(struct gem *gp)
{
unsigned char *e = &gp->dev->dev_addr[0];
@@ -1918,7 +1909,6 @@ static void gem_init_mac(struct gem *gp)
writel(0, gp->regs + WOL_WAKECSR);
}
-/* Must be invoked under gp->lock and gp->tx_lock. */
static void gem_init_pause_thresholds(struct gem *gp)
{
u32 cfg;
@@ -2079,7 +2069,6 @@ static int gem_check_invariants(struct gem *gp)
return 0;
}
-/* Must be invoked under gp->lock and gp->tx_lock. */
static void gem_reinit_chip(struct gem *gp)
{
/* Reset the chip */
@@ -2100,11 +2089,9 @@ static void gem_reinit_chip(struct gem *gp)
}
-/* Must be invoked with no lock held. */
static void gem_stop_phy(struct gem *gp, int wol)
{
u32 mifcfg;
- unsigned long flags;
/* Let the chip settle down a bit, it seems that helps
* for sleep mode on some models
@@ -2150,15 +2137,9 @@ static void gem_stop_phy(struct gem *gp, int wol)
writel(0, gp->regs + RXDMA_CFG);
if (!wol) {
- spin_lock_irqsave(&gp->lock, flags);
- spin_lock(&gp->tx_lock);
gem_reset(gp);
writel(MAC_TXRST_CMD, gp->regs + MAC_TXRST);
writel(MAC_RXRST_CMD, gp->regs + MAC_RXRST);
- spin_unlock(&gp->tx_lock);
- spin_unlock_irqrestore(&gp->lock, flags);
-
- /* No need to take the lock here */
if (found_mii_phy(gp) && gp->phy_mii.def->ops->suspend)
gp->phy_mii.def->ops->suspend(&gp->phy_mii);
@@ -2175,51 +2156,42 @@ static void gem_stop_phy(struct gem *gp, int wol)
}
}
-
static int gem_do_start(struct net_device *dev)
{
struct gem *gp = netdev_priv(dev);
- unsigned long flags;
- spin_lock_irqsave(&gp->lock, flags);
- spin_lock(&gp->tx_lock);
+ /* In case the HW off or reinit generates stray
+ * interrupts.
+ */
+ spin_lock_bh(&gp->lock);
/* Enable the cell */
gem_get_cell(gp);
+ gem_disable_ints(gp);
+
+ spin_unlock_bh(&gp->lock);
/* Init & setup chip hardware */
gem_reinit_chip(gp);
- gp->running = 1;
-
- napi_enable(&gp->napi);
-
- if (gp->lstate == link_up) {
- netif_carrier_on(gp->dev);
- gem_set_link_modes(gp);
- }
-
- netif_wake_queue(gp->dev);
+ /* Detect & init PHY, start autoneg etc */
+ gem_init_phy(gp);
- spin_unlock(&gp->tx_lock);
- spin_unlock_irqrestore(&gp->lock, flags);
+ /* Restart NAPI & queues */
+ gem_netif_start(gp);
if (request_irq(gp->pdev->irq, gem_interrupt,
IRQF_SHARED, dev->name, (void *)dev)) {
netdev_err(dev, "failed to request irq !\n");
- spin_lock_irqsave(&gp->lock, flags);
- spin_lock(&gp->tx_lock);
-
napi_disable(&gp->napi);
-
- gp->running = 0;
+ netif_device_detach(dev);
gem_reset(gp);
gem_clean_rings(gp);
- gem_put_cell(gp);
- spin_unlock(&gp->tx_lock);
- spin_unlock_irqrestore(&gp->lock, flags);
+ spin_lock_bh(&gp->lock);
+ gem_put_cell(gp);
+ spin_unlock_bh(&gp->lock);
return -EAGAIN;
}
@@ -2230,22 +2202,19 @@ static int gem_do_start(struct net_device *dev)
static void gem_do_stop(struct net_device *dev, int wol)
{
struct gem *gp = netdev_priv(dev);
- unsigned long flags;
-
- spin_lock_irqsave(&gp->lock, flags);
- spin_lock(&gp->tx_lock);
-
- gp->running = 0;
-
- /* Stop netif queue */
- netif_stop_queue(dev);
- /* Make sure ints are disabled */
+ /* Stop NAPI and stop tx queue */
+ gem_netif_stop(gp);
+
+ /* Make sure ints are disabled. We don't care about
+ * synchronizing as NAPI is disabled, thus a stray
+ * interrupt will do nothing bad (our irq handler
+ * just schedules NAPI)
+ */
gem_disable_ints(gp);
- /* We can drop the lock now */
- spin_unlock(&gp->tx_lock);
- spin_unlock_irqrestore(&gp->lock, flags);
+ /* Stop the link timer */
+ del_timer_sync(&gp->link_timer);
/* If we are going to sleep with WOL */
gem_stop_dma(gp);
@@ -2260,11 +2229,14 @@ static void gem_do_stop(struct net_device *dev, int wol)
/* No irq needed anymore */
free_irq(gp->pdev->irq, (void *) dev);
+ /* Shut the PHY down eventually and setup WOL */
+ gem_stop_phy(gp, wol);
+
/* Cell not needed neither if no WOL */
if (!wol) {
- spin_lock_irqsave(&gp->lock, flags);
+ spin_lock_bh(&gp->lock);
gem_put_cell(gp);
- spin_unlock_irqrestore(&gp->lock, flags);
+ spin_unlock_bh(&gp->lock);
}
}
@@ -2274,29 +2246,38 @@ static void gem_reset_task(struct work_struct *work)
mutex_lock(&gp->pm_mutex);
- if (gp->opened)
- napi_disable(&gp->napi);
+ /* Skip the reset task if not opened or suspended */
+ if (!netif_running(gp->dev) || !netif_device_present(gp->dev)) {
+ mutex_unlock(&gp->pm_mutex);
+ return;
+ }
+
+ /* Stop the link timer */
+ del_timer_sync(&gp->link_timer);
- spin_lock_irq(&gp->lock);
- spin_lock(&gp->tx_lock);
+ /* Stop NAPI and tx */
+ gem_netif_stop(gp);
- if (gp->running) {
- netif_stop_queue(gp->dev);
+ /* Reset the chip & rings */
+ gem_reinit_chip(gp);
+ if (gp->lstate == link_up)
+ gem_set_link_modes(gp);
- /* Reset the chip & rings */
- gem_reinit_chip(gp);
- if (gp->lstate == link_up)
- gem_set_link_modes(gp);
- netif_wake_queue(gp->dev);
- }
+ /* Restart NAPI and Tx */
+ gem_netif_start(gp);
+ /* We are back ! */
gp->reset_task_pending = 0;
- spin_unlock(&gp->tx_lock);
- spin_unlock_irq(&gp->lock);
-
- if (gp->opened)
- napi_enable(&gp->napi);
+ /* If the link is not up, restart autoneg, else restart the
+ * polling timer
+ */
+ if (gp->lstate != link_up) {
+ spin_lock_bh(&gp->lock);
+ gem_begin_auto_negotiation(gp, NULL);
+ spin_unlock_bh(&gp->lock);
+ } else
+ mod_timer(&gp->link_timer, jiffies + ((12 * HZ) / 10));
mutex_unlock(&gp->pm_mutex);
}
@@ -2308,14 +2289,9 @@ static int gem_open(struct net_device *dev)
int rc = 0;
mutex_lock(&gp->pm_mutex);
-
- /* We need the cell enabled */
- if (!gp->asleep)
+ if (netif_device_present(dev))
rc = gem_do_start(dev);
- gp->opened = (rc == 0);
-
mutex_unlock(&gp->pm_mutex);
-
return rc;
}
@@ -2324,15 +2300,13 @@ static int gem_close(struct net_device *dev)
struct gem *gp = netdev_priv(dev);
mutex_lock(&gp->pm_mutex);
-
- napi_disable(&gp->napi);
-
- gp->opened = 0;
- if (!gp->asleep)
+ if (netif_device_present(dev))
gem_do_stop(dev, 0);
-
mutex_unlock(&gp->pm_mutex);
+ /* Ensure reset task is truely gone */
+ cancel_work_sync(&gp->reset_task);
+
return 0;
}
@@ -2341,59 +2315,54 @@ static int gem_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct gem *gp = netdev_priv(dev);
- unsigned long flags;
+ /* Lock the network stack first to avoid races with open/close */
+ rtnl_lock();
mutex_lock(&gp->pm_mutex);
+ /* Not running, mark ourselves non-present, no need for
+ * a lock here
+ */
+ if (!netif_running(dev)) {
+ netif_device_detach(dev);
+ goto bail;
+ }
netdev_info(dev, "suspending, WakeOnLan %s\n",
- (gp->wake_on_lan && gp->opened) ? "enabled" : "disabled");
+ (gp->wake_on_lan && netif_running(dev)) ?
+ "enabled" : "disabled");
- /* Keep the cell enabled during the entire operation */
- spin_lock_irqsave(&gp->lock, flags);
- spin_lock(&gp->tx_lock);
+ /* Keep the clocks enabled during the entire operation
+ * mark us !present under lock
+ */
+ spin_lock_bh(&gp->lock);
gem_get_cell(gp);
- spin_unlock(&gp->tx_lock);
- spin_unlock_irqrestore(&gp->lock, flags);
-
- /* If the driver is opened, we stop the MAC */
- if (gp->opened) {
- napi_disable(&gp->napi);
+ netif_device_detach(dev);
+ spin_unlock_bh(&gp->lock);
- /* Stop traffic, mark us closed */
- netif_device_detach(dev);
+ /* Switch off chip, remember WOL setting */
+ gp->asleep_wol = gp->wake_on_lan;
+ gem_do_stop(dev, gp->asleep_wol);
- /* Switch off MAC, remember WOL setting */
- gp->asleep_wol = gp->wake_on_lan;
- gem_do_stop(dev, gp->asleep_wol);
- } else
- gp->asleep_wol = 0;
-
- /* Mark us asleep */
- gp->asleep = 1;
- wmb();
+ /* Make sure bus master is disabled */
+ pci_disable_device(gp->pdev);
- /* Stop the link timer */
- del_timer_sync(&gp->link_timer);
+ /* Stop the HW clocks */
+ spin_lock_bh(&gp->lock);
+ gem_put_cell(gp);
+ spin_unlock_bh(&gp->lock);
+ bail:
/* Now we release the mutex to not block the reset task who
* can take it too. We are marked asleep, so there will be no
* conflict here
*/
mutex_unlock(&gp->pm_mutex);
- /* Wait for the pending reset task to complete */
- flush_work_sync(&gp->reset_task);
-
- /* Shut the PHY down eventually and setup WOL */
- gem_stop_phy(gp, gp->asleep_wol);
+ /* Wait for a pending reset task to complete */
+ cancel_work_sync(&gp->reset_task);
- /* Make sure bus master is disabled */
- pci_disable_device(gp->pdev);
-
- /* Release the cell, no need to take a lock at this point since
- * nothing else can happen now
- */
- gem_put_cell(gp);
+ /* Unlock the network stack */
+ rtnl_unlock();
return 0;
}
@@ -2402,17 +2371,26 @@ static int gem_resume(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct gem *gp = netdev_priv(dev);
- unsigned long flags;
-
- netdev_info(dev, "resuming\n");
+ /* See locking comment in gem_suspend */
+ rtnl_lock();
mutex_lock(&gp->pm_mutex);
+ /* Not running, mark ourselves present, no need for
+ * a lock here
+ */
+ if (!netif_running(dev)) {
+ netif_device_attach(dev);
+ goto bail;
+ }
+
/* Keep the cell enabled during the entire operation, no need to
* take a lock here tho since nothing else can happen while we are
* marked asleep
*/
+ spin_lock_bh(&gp->lock);
gem_get_cell(gp);
+ spin_unlock_bh(&gp->lock);
/* Make sure PCI access and bus master are enabled */
if (pci_enable_device(gp->pdev)) {
@@ -2430,25 +2408,12 @@ static int gem_resume(struct pci_dev *pdev)
gem_reset(gp);
/* Mark us woken up */
- gp->asleep = 0;
- wmb();
-
- /* Bring the PHY back. Again, lock is useless at this point as
- * nothing can be happening until we restart the whole thing
- */
- gem_init_phy(gp);
+ netif_device_attach(dev);
- /* If we were opened, bring everything back */
- if (gp->opened) {
- /* Restart MAC */
- gem_do_start(dev);
-
- /* Re-attach net device */
- netif_device_attach(dev);
- }
-
- spin_lock_irqsave(&gp->lock, flags);
- spin_lock(&gp->tx_lock);
+ /* Restart chip */
+ gem_do_start(dev);
+
+ spin_lock_bh(&gp->lock);
/* If we had WOL enabled, the cell clock was never turned off during
* sleep, so we end up beeing unbalanced. Fix that here
@@ -2460,11 +2425,10 @@ static int gem_resume(struct pci_dev *pdev)
* driver is open by gem_do_start().
*/
gem_put_cell(gp);
-
- spin_unlock(&gp->tx_lock);
- spin_unlock_irqrestore(&gp->lock, flags);
-
+ spin_unlock_bh(&gp->lock);
+ bail:
mutex_unlock(&gp->pm_mutex);
+ rtnl_unlock();
return 0;
}
@@ -2474,32 +2438,34 @@ static struct net_device_stats *gem_get_stats(struct net_device *dev)
{
struct gem *gp = netdev_priv(dev);
- spin_lock_irq(&gp->lock);
- spin_lock(&gp->tx_lock);
+ spin_lock_bh(&gp->lock);
/* I have seen this being called while the PM was in progress,
- * so we shield against this
+ * so we shield against this. Let's also not poke at registers
+ * while the reset task is going on.
*/
- if (gp->running) {
- dev->stats.rx_crc_errors += readl(gp->regs + MAC_FCSERR);
- writel(0, gp->regs + MAC_FCSERR);
+ if (!netif_device_present(dev) || gp->reset_task_pending)
+ goto bail;
+ gem_get_cell(gp);
- dev->stats.rx_frame_errors += readl(gp->regs + MAC_AERR);
- writel(0, gp->regs + MAC_AERR);
+ dev->stats.rx_crc_errors += readl(gp->regs + MAC_FCSERR);
+ writel(0, gp->regs + MAC_FCSERR);
- dev->stats.rx_length_errors += readl(gp->regs + MAC_LERR);
- writel(0, gp->regs + MAC_LERR);
+ dev->stats.rx_frame_errors += readl(gp->regs + MAC_AERR);
+ writel(0, gp->regs + MAC_AERR);
- dev->stats.tx_aborted_errors += readl(gp->regs + MAC_ECOLL);
- dev->stats.collisions +=
- (readl(gp->regs + MAC_ECOLL) +
- readl(gp->regs + MAC_LCOLL));
- writel(0, gp->regs + MAC_ECOLL);
- writel(0, gp->regs + MAC_LCOLL);
- }
+ dev->stats.rx_length_errors += readl(gp->regs + MAC_LERR);
+ writel(0, gp->regs + MAC_LERR);
- spin_unlock(&gp->tx_lock);
- spin_unlock_irq(&gp->lock);
+ dev->stats.tx_aborted_errors += readl(gp->regs + MAC_ECOLL);
+ dev->stats.collisions +=
+ (readl(gp->regs + MAC_ECOLL) + readl(gp->regs + MAC_LCOLL));
+ writel(0, gp->regs + MAC_ECOLL);
+ writel(0, gp->regs + MAC_LCOLL);
+
+ gem_put_cell(gp);
+ bail:
+ spin_unlock_bh(&gp->lock);
return &dev->stats;
}
@@ -2513,21 +2479,26 @@ static int gem_set_mac_address(struct net_device *dev, void *addr)
if (!is_valid_ether_addr(macaddr->sa_data))
return -EADDRNOTAVAIL;
+ memcpy(dev->dev_addr, macaddr->sa_data, dev->addr_len);
+
if (!netif_running(dev) || !netif_device_present(dev)) {
/* We'll just catch it later when the
* device is up'd or resumed.
*/
- memcpy(dev->dev_addr, macaddr->sa_data, dev->addr_len);
return 0;
}
+ /* Mutex synchronizes us vs. suspend/resume & reset task */
mutex_lock(&gp->pm_mutex);
- memcpy(dev->dev_addr, macaddr->sa_data, dev->addr_len);
- if (gp->running) {
- writel((e[4] << 8) | e[5], gp->regs + MAC_ADDR0);
- writel((e[2] << 8) | e[3], gp->regs + MAC_ADDR1);
- writel((e[0] << 8) | e[1], gp->regs + MAC_ADDR2);
- }
+
+ /* Better safe than sorry... */
+ if (WARN_ON(!gp->cell_enabled))
+ goto bail;
+
+ writel((e[4] << 8) | e[5], gp->regs + MAC_ADDR0);
+ writel((e[2] << 8) | e[3], gp->regs + MAC_ADDR1);
+ writel((e[0] << 8) | e[1], gp->regs + MAC_ADDR2);
+ bail:
mutex_unlock(&gp->pm_mutex);
return 0;
@@ -2539,15 +2510,16 @@ static void gem_set_multicast(struct net_device *dev)
u32 rxcfg, rxcfg_new;
int limit = 10000;
+ if (!netif_running(dev) || !netif_device_present(dev))
+ return;
- spin_lock_irq(&gp->lock);
- spin_lock(&gp->tx_lock);
+ /* BH already blocked by caller */
+ spin_lock(&gp->lock);
- if (!gp->running)
+ /* Better safe than sorry... */
+ if (gp->reset_task_pending || WARN_ON(!gp->cell_enabled))
goto bail;
- netif_stop_queue(dev);
-
rxcfg = readl(gp->regs + MAC_RXCFG);
rxcfg_new = gem_setup_multicast(gp);
#ifdef STRIP_FCS
@@ -2566,12 +2538,8 @@ static void gem_set_multicast(struct net_device *dev)
rxcfg |= rxcfg_new;
writel(rxcfg, gp->regs + MAC_RXCFG);
-
- netif_wake_queue(dev);
-
bail:
- spin_unlock(&gp->tx_lock);
- spin_unlock_irq(&gp->lock);
+ spin_unlock(&gp->lock);
}
/* Jumbo-grams don't seem to work :-( */
@@ -2597,17 +2565,20 @@ static int gem_change_mtu(struct net_device *dev, int new_mtu)
return 0;
}
+ /* Mutex synchronizes us vs. suspend/resume & reset task */
mutex_lock(&gp->pm_mutex);
- spin_lock_irq(&gp->lock);
- spin_lock(&gp->tx_lock);
dev->mtu = new_mtu;
- if (gp->running) {
- gem_reinit_chip(gp);
- if (gp->lstate == link_up)
- gem_set_link_modes(gp);
- }
- spin_unlock(&gp->tx_lock);
- spin_unlock_irq(&gp->lock);
+
+ /* Better safe than sorry... */
+ if (WARN_ON(!gp->cell_enabled))
+ goto bail;
+
+ gem_netif_stop(gp);
+ gem_reinit_chip(gp);
+ if (gp->lstate == link_up)
+ gem_set_link_modes(gp);
+ gem_netif_start(gp);
+ bail:
mutex_unlock(&gp->pm_mutex);
return 0;
@@ -2640,7 +2611,7 @@ static int gem_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
cmd->phy_address = 0; /* XXX fixed PHYAD */
/* Return current PHY settings */
- spin_lock_irq(&gp->lock);
+ spin_lock_bh(&gp->lock);
cmd->autoneg = gp->want_autoneg;
ethtool_cmd_speed_set(cmd, gp->phy_mii.speed);
cmd->duplex = gp->phy_mii.duplex;
@@ -2652,7 +2623,7 @@ static int gem_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
*/
if (cmd->advertising == 0)
cmd->advertising = cmd->supported;
- spin_unlock_irq(&gp->lock);
+ spin_unlock_bh(&gp->lock);
} else { // XXX PCS ?
cmd->supported =
(SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
@@ -2706,11 +2677,10 @@ static int gem_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
return -EINVAL;
/* Apply settings and restart link process. */
- spin_lock_irq(&gp->lock);
- gem_get_cell(gp);
- gem_begin_auto_negotiation(gp, cmd);
- gem_put_cell(gp);
- spin_unlock_irq(&gp->lock);
+ spin_lock_bh(&gp->lock);
+ if (netif_device_present(gp->dev) && !gp->reset_task_pending)
+ gem_begin_auto_negotiation(gp, cmd);
+ spin_unlock_bh(&gp->lock);
return 0;
}
@@ -2723,11 +2693,10 @@ static int gem_nway_reset(struct net_device *dev)
return -EINVAL;
/* Restart link process. */
- spin_lock_irq(&gp->lock);
- gem_get_cell(gp);
- gem_begin_auto_negotiation(gp, NULL);
- gem_put_cell(gp);
- spin_unlock_irq(&gp->lock);
+ spin_lock_bh(&gp->lock);
+ if (netif_device_present(gp->dev) && !gp->reset_task_pending)
+ gem_begin_auto_negotiation(gp, NULL);
+ spin_unlock_bh(&gp->lock);
return 0;
}
@@ -2791,24 +2760,19 @@ static int gem_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
struct gem *gp = netdev_priv(dev);
struct mii_ioctl_data *data = if_mii(ifr);
int rc = -EOPNOTSUPP;
- unsigned long flags;
/* Hold the PM mutex while doing ioctl's or we may collide
* with power management.
*/
mutex_lock(&gp->pm_mutex);
- spin_lock_irqsave(&gp->lock, flags);
- gem_get_cell(gp);
- spin_unlock_irqrestore(&gp->lock, flags);
-
switch (cmd) {
case SIOCGMIIPHY: /* Get address of MII PHY in use. */
data->phy_id = gp->mii_phy_addr;
/* Fallthrough... */
case SIOCGMIIREG: /* Read MII PHY register. */
- if (!gp->running)
+ if (!netif_device_present(dev) || gp->reset_task_pending)
rc = -EAGAIN;
else {
data->val_out = __phy_read(gp, data->phy_id & 0x1f,
@@ -2818,7 +2782,7 @@ static int gem_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
break;
case SIOCSMIIREG: /* Write MII PHY register. */
- if (!gp->running)
+ if (!netif_device_present(dev) || gp->reset_task_pending)
rc = -EAGAIN;
else {
__phy_write(gp, data->phy_id & 0x1f, data->reg_num & 0x1f,
@@ -2828,10 +2792,6 @@ static int gem_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
break;
};
- spin_lock_irqsave(&gp->lock, flags);
- gem_put_cell(gp);
- spin_unlock_irqrestore(&gp->lock, flags);
-
mutex_unlock(&gp->pm_mutex);
return rc;
@@ -3044,7 +3004,6 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
gp->msg_enable = DEFAULT_MSG;
spin_lock_init(&gp->lock);
- spin_lock_init(&gp->tx_lock);
mutex_init(&gp->pm_mutex);
init_timer(&gp->link_timer);
@@ -3122,14 +3081,11 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
/* Set that now, in case PM kicks in now */
pci_set_drvdata(pdev, dev);
- /* Detect & init PHY, start autoneg, we release the cell now
- * too, it will be managed by whoever needs it
- */
- gem_init_phy(gp);
-
- spin_lock_irq(&gp->lock);
- gem_put_cell(gp);
- spin_unlock_irq(&gp->lock);
+ /* We can do scatter/gather and HW checksum */
+ dev->hw_features = NETIF_F_SG | NETIF_F_HW_CSUM;
+ dev->features |= dev->hw_features | NETIF_F_RXCSUM;
+ if (pci_using_dac)
+ dev->features |= NETIF_F_HIGHDMA;
/* Register with kernel */
if (register_netdev(dev)) {
@@ -3138,20 +3094,12 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
goto err_out_free_consistent;
}
+ spin_lock_bh(&gp->lock);
+ gem_put_cell(gp);
+ spin_unlock_bh(&gp->lock);
+
netdev_info(dev, "Sun GEM (PCI) 10/100/1000BaseT Ethernet %pM\n",
dev->dev_addr);
-
- if (gp->phy_type == phy_mii_mdio0 ||
- gp->phy_type == phy_mii_mdio1)
- netdev_info(dev, "Found %s PHY\n",
- gp->phy_mii.def ? gp->phy_mii.def->name : "no");
-
- /* GEM can do it all... */
- dev->hw_features = NETIF_F_SG | NETIF_F_HW_CSUM;
- dev->features |= dev->hw_features | NETIF_F_RXCSUM | NETIF_F_LLTX;
- if (pci_using_dac)
- dev->features |= NETIF_F_HIGHDMA;
-
return 0;
err_out_free_consistent:
diff --git a/drivers/net/sungem.h b/drivers/net/sungem.h
index d225077..4a83147 100644
--- a/drivers/net/sungem.h
+++ b/drivers/net/sungem.h
@@ -974,16 +974,12 @@ enum link_state {
struct gem {
spinlock_t lock;
- spinlock_t tx_lock;
void __iomem *regs;
int rx_new, rx_old;
int tx_new, tx_old;
unsigned int has_wol : 1; /* chip supports wake-on-lan */
- unsigned int asleep : 1; /* chip asleep, protected by pm_mutex */
unsigned int asleep_wol : 1; /* was asleep with WOL enabled */
- unsigned int opened : 1; /* driver opened, protected by pm_mutex */
- unsigned int running : 1; /* chip running, protected by lock */
/* cell enable count, protected by lock */
int cell_enabled;
@@ -1033,20 +1029,4 @@ struct gem {
#define found_mii_phy(gp) ((gp->phy_type == phy_mii_mdio0 || gp->phy_type == phy_mii_mdio1) && \
gp->phy_mii.def && gp->phy_mii.def->ops)
-#define ALIGNED_RX_SKB_ADDR(addr) \
- ((((unsigned long)(addr) + (64UL - 1UL)) & ~(64UL - 1UL)) - (unsigned long)(addr))
-static __inline__ struct sk_buff *gem_alloc_skb(int size,
- gfp_t gfp_flags)
-{
- struct sk_buff *skb = alloc_skb(size + 64, gfp_flags);
-
- if (skb) {
- int offset = (int) ALIGNED_RX_SKB_ADDR(skb->data);
- if (offset)
- skb_reserve(skb, offset);
- }
-
- return skb;
-}
-
#endif /* _SUNGEM_H */
^ permalink raw reply related
* [PATCH] ftrace: tracepoint of net_dev_xmit sees freed skb and causes panic
From: Koki Sanagi @ 2011-05-31 7:48 UTC (permalink / raw)
To: linux-kernel
Cc: netdev, davem, nhorman, rostedt, mingo, fweisbec,
mathieu.desnoyers, tglx, kosaki.motohiro, izumi.taku,
kaneshige.kenji
Because there is a possibility that skb is kfree_skb()ed and zero cleared
after ndo_start_xmit, we should not see the contents of skb like skb->len and
skb->dev->name after ndo_start_xmit. But trace_net_dev_xmit does that
and causes panic by NULL pointer dereference.
This patch fixes trace_net_dev_xmit not to see the contents of skb directly.
If you want to reproduce this panic,
1. Get tracepoint of net_dev_xmit on
2. Create 2 guests on KVM
2. Make 2 guests use virtio_net
4. Execute netperf from one to another for a long time as a network burden
5. host will panic(It takes about 30 minutes)
Signed-off-by: Koki Sanagi <sanagi.koki@jp.fujitsu.com>
---
include/trace/events/net.h | 12 +++++++-----
net/core/dev.c | 7 +++++--
2 files changed, 12 insertions(+), 7 deletions(-)
diff --git a/include/trace/events/net.h b/include/trace/events/net.h
index 5f247f5..f99645d 100644
--- a/include/trace/events/net.h
+++ b/include/trace/events/net.h
@@ -12,22 +12,24 @@
TRACE_EVENT(net_dev_xmit,
TP_PROTO(struct sk_buff *skb,
- int rc),
+ int rc,
+ struct net_device *dev,
+ unsigned int skb_len),
- TP_ARGS(skb, rc),
+ TP_ARGS(skb, rc, dev, skb_len),
TP_STRUCT__entry(
__field( void *, skbaddr )
__field( unsigned int, len )
__field( int, rc )
- __string( name, skb->dev->name )
+ __string( name, dev->name )
),
TP_fast_assign(
__entry->skbaddr = skb;
- __entry->len = skb->len;
+ __entry->len = skb_len;
__entry->rc = rc;
- __assign_str(name, skb->dev->name);
+ __assign_str(name, dev->name);
),
TP_printk("dev=%s skbaddr=%p len=%u rc=%d",
diff --git a/net/core/dev.c b/net/core/dev.c
index d945379..f0e15df 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2089,6 +2089,7 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
{
const struct net_device_ops *ops = dev->netdev_ops;
int rc = NETDEV_TX_OK;
+ unsigned int skb_len;
if (likely(!skb->next)) {
u32 features;
@@ -2139,8 +2140,9 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
}
}
+ skb_len = skb->len;
rc = ops->ndo_start_xmit(skb, dev);
- trace_net_dev_xmit(skb, rc);
+ trace_net_dev_xmit(skb, rc, dev, skb_len);
if (rc == NETDEV_TX_OK)
txq_trans_update(txq);
return rc;
@@ -2160,8 +2162,9 @@ gso:
if (dev->priv_flags & IFF_XMIT_DST_RELEASE)
skb_dst_drop(nskb);
+ skb_len = nskb->len;
rc = ops->ndo_start_xmit(nskb, dev);
- trace_net_dev_xmit(nskb, rc);
+ trace_net_dev_xmit(nskb, rc, dev, skb_len);
if (unlikely(rc != NETDEV_TX_OK)) {
if (rc & ~NETDEV_TX_MASK)
goto out_kfree_gso_skb;
^ permalink raw reply related
* Re: [PATCH] bond_3ad.c: switch MAC_ADDRESS_COMPARE macro for compare_ether_addr()
From: walter harms @ 2011-05-31 7:17 UTC (permalink / raw)
To: aquini; +Cc: kernel-janitors, Jay Vosburgh, David Miller, Andy Gospodarek,
netdev
In-Reply-To: <20110531004418.GA22937@optiplex.tchesoft.com>
The intentions are good, the resultung code next to unreadable.
I do not know the rest of code so i can not suggest an alternative
way. You may like to experiment with local variables or even make
a special function.
re,
wh
Am 31.05.2011 02:44, schrieb Rafael Aquini:
> Converts all uses of MAC_ADDRESS_COMPARE macro to compare_ether_addr() and delete the macro.
>
> Signed-off-by: Rafael Aquini <aquini@linux.com>
> ---
> drivers/net/bonding/bond_3ad.c | 26 ++++++++++++++------------
> 1 files changed, 14 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
> index c7537abc..c2e0d66 100644
> --- a/drivers/net/bonding/bond_3ad.c
> +++ b/drivers/net/bonding/bond_3ad.c
> @@ -90,9 +90,6 @@
> #define AD_LINK_SPEED_BITMASK_10000MBPS 0x10
> //endalloun
>
> -// compare MAC addresses
> -#define MAC_ADDRESS_COMPARE(A, B) memcmp(A, B, ETH_ALEN)
> -
> static struct mac_addr null_mac_addr = { { 0, 0, 0, 0, 0, 0 } };
> static u16 ad_ticks_per_sec;
> static const int ad_delta_in_ticks = (AD_TIMER_INTERVAL * HZ) / 1000;
> @@ -469,7 +466,7 @@ static void __choose_matched(struct lacpdu *lacpdu, struct port *port)
> // check if all parameters are alike
> if (((ntohs(lacpdu->partner_port) == port->actor_port_number) &&
> (ntohs(lacpdu->partner_port_priority) == port->actor_port_priority) &&
> - !MAC_ADDRESS_COMPARE(&(lacpdu->partner_system), &(port->actor_system)) &&
> + !compare_ether_addr((const u8 *)&(lacpdu->partner_system), (const u8 *)&(port->actor_system)) &&
> (ntohs(lacpdu->partner_system_priority) == port->actor_system_priority) &&
> (ntohs(lacpdu->partner_key) == port->actor_oper_port_key) &&
> ((lacpdu->partner_state & AD_STATE_AGGREGATION) == (port->actor_oper_port_state & AD_STATE_AGGREGATION))) ||
> @@ -559,7 +556,8 @@ static void __update_selected(struct lacpdu *lacpdu, struct port *port)
> // check if any parameter is different
> if (ntohs(lacpdu->actor_port) != partner->port_number ||
> ntohs(lacpdu->actor_port_priority) != partner->port_priority ||
> - MAC_ADDRESS_COMPARE(&lacpdu->actor_system, &partner->system) ||
> + compare_ether_addr((const u8 *)&lacpdu->actor_system,
> + (const u8 *)&partner->system) ||
> ntohs(lacpdu->actor_system_priority) != partner->system_priority ||
> ntohs(lacpdu->actor_key) != partner->key ||
> (lacpdu->actor_state & AD_STATE_AGGREGATION) != (partner->port_state & AD_STATE_AGGREGATION)) {
> @@ -590,7 +588,8 @@ static void __update_default_selected(struct port *port)
> // check if any parameter is different
> if (admin->port_number != oper->port_number ||
> admin->port_priority != oper->port_priority ||
> - MAC_ADDRESS_COMPARE(&admin->system, &oper->system) ||
> + compare_ether_addr((const u8 *)&admin->system,
> + (const u8 *)&oper->system) ||
> admin->system_priority != oper->system_priority ||
> admin->key != oper->key ||
> (admin->port_state & AD_STATE_AGGREGATION)
> @@ -620,7 +619,8 @@ static void __update_ntt(struct lacpdu *lacpdu, struct port *port)
> // check if any parameter is different
> if ((ntohs(lacpdu->partner_port) != port->actor_port_number) ||
> (ntohs(lacpdu->partner_port_priority) != port->actor_port_priority) ||
> - MAC_ADDRESS_COMPARE(&(lacpdu->partner_system), &(port->actor_system)) ||
> + compare_ether_addr((const u8 *)&(lacpdu->partner_system),
> + (const u8 *)&(port->actor_system)) ||
> (ntohs(lacpdu->partner_system_priority) != port->actor_system_priority) ||
> (ntohs(lacpdu->partner_key) != port->actor_oper_port_key) ||
> ((lacpdu->partner_state & AD_STATE_LACP_ACTIVITY) != (port->actor_oper_port_state & AD_STATE_LACP_ACTIVITY)) ||
> @@ -1123,7 +1123,7 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port)
> break;
> case AD_RX_CURRENT:
> // detect loopback situation
> - if (!MAC_ADDRESS_COMPARE(&(lacpdu->actor_system), &(port->actor_system))) {
> + if (!compare_ether_addr((const u8 *)&(lacpdu->actor_system), (const u8 *)&(port->actor_system))) {
> // INFO_RECEIVED_LOOPBACK_FRAMES
> pr_err("%s: An illegal loopback occurred on adapter (%s).\n"
> "Check the configuration to verify that all adapters are connected to 802.3ad compliant switch ports\n",
> @@ -1331,11 +1331,11 @@ static void ad_port_selection_logic(struct port *port)
> }
> // check if current aggregator suits us
> if (((aggregator->actor_oper_aggregator_key == port->actor_oper_port_key) && // if all parameters match AND
> - !MAC_ADDRESS_COMPARE(&(aggregator->partner_system), &(port->partner_oper.system)) &&
> + !compare_ether_addr((const u8 *)&(aggregator->partner_system), (const u8 *)&(port->partner_oper.system)) &&
> (aggregator->partner_system_priority == port->partner_oper.system_priority) &&
> (aggregator->partner_oper_aggregator_key == port->partner_oper.key)
> ) &&
> - ((MAC_ADDRESS_COMPARE(&(port->partner_oper.system), &(null_mac_addr)) && // partner answers
> + ((compare_ether_addr((const u8 *)&(port->partner_oper.system), (const u8 *)&(null_mac_addr)) && // partner answers
> !aggregator->is_individual) // but is not individual OR
> )
> ) {
> @@ -1751,7 +1751,9 @@ static void ad_enable_collecting_distributing(struct port *port)
> */
> static void ad_disable_collecting_distributing(struct port *port)
> {
> - if (port->aggregator && MAC_ADDRESS_COMPARE(&(port->aggregator->partner_system), &(null_mac_addr))) {
> + if (port->aggregator &&
> + compare_ether_addr((const u8 *)&(port->aggregator->partner_system),
> + (const u8 *)&(null_mac_addr))) {
> pr_debug("Disabling port %d(LAG %d)\n",
> port->actor_port_number,
> port->aggregator->aggregator_identifier);
> @@ -1875,7 +1877,7 @@ static u16 aggregator_identifier;
> void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution, int lacp_fast)
> {
> // check that the bond is not initialized yet
> - if (MAC_ADDRESS_COMPARE(&(BOND_AD_INFO(bond).system.sys_mac_addr),
> + if (compare_ether_addr((const u8 *)&(BOND_AD_INFO(bond).system.sys_mac_addr),
> bond->dev->dev_addr)) {
>
> aggregator_identifier = 0;
^ permalink raw reply
* netxen_nic: unregister_netdevice error
From: WeipingPan @ 2011-05-31 6:15 UTC (permalink / raw)
To: open list:NETWORKING [GENERAL]
hi,
When test bonding broadcast mode I met a problem.
modprobe -r bonding will fail after I ping broadcast address.
I find that the problem only shows up when I use netxen_nic driver.
When use ixgbe and bn2x2 driver, no problem occurs.
I use RHEL 6.2, kernel 2.6.32-131.0.15.el6.i686,
Can anybody confirm this bug using 2.6.39 or upstream ?
many thanks
Weiping Pan
The test script is followed.
#test script start
#!/bin/bash
NETWORK_CARD0=eth1
NETWORK_CARD1=eth2
function broadcast_test()
{
modprobe bonding mode=broadcast miimon=100
ifconfig bond0 192.168.8.2 netmask 255.255.255.0 up
ifconfig $NETWORK_CARD0 down
ifconfig $NETWORK_CARD1 down
echo +$NETWORK_CARD0 > /sys/class/net/bond0/bonding/slaves
echo +$NETWORK_CARD1 > /sys/class/net/bond0/bonding/slaves
ping 192.168.8.255 -b -c 10
modprobe -r bonding
}
# main
echo 0 >/proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
modprobe -r bonding
for i in `seq 1 10`
do
echo "*******************"
echo "***iteration$i*****"
echo -e "*******************\n\n"
broadcast_test
done
#test script end
Some information is followed.
[root@hp-magnycours-01 ~]# uname -a
Linux hp-magnycours-01.rhts.eng.bos.redhat.com 2.6.32-131.0.15.el6.i686
#1 SMP Tue May 10 15:42:28 EDT 2011 i686 i686 i386 GNU/Linux
[root@hp-magnycours-01 ~]# cat /etc/redhat-release
Red Hat Enterprise Linux Server release 6.1 (Santiago)
[root@hp-magnycours-01 ~]# lspci |grep Ethernet
04:00.0 Ethernet controller: NetXen Incorporated NX3031 Multifunction
1/10-Gigabit Server Adapter (rev 42)
04:00.1 Ethernet controller: NetXen Incorporated NX3031 Multifunction
1/10-Gigabit Server Adapter (rev 42)
04:00.2 Ethernet controller: NetXen Incorporated NX3031 Multifunction
1/10-Gigabit Server Adapter (rev 42)
04:00.3 Ethernet controller: NetXen Incorporated NX3031 Multifunction
1/10-Gigabit Server Adapter (rev 42)
[root@hp-magnycours-01 ~]# lsmod |grep net
netxen_nic 83405 0
[root@hp-magnycours-01 ~]# ifconfig -a
eth0 Link encap:Ethernet HWaddr 1C:C1:DE:EE:28:F0
inet addr:10.16.64.212 Bcast:10.16.71.255 Mask:255.255.248.0
inet6 addr: fec0:0:a10:4000:1ec1:deff:feee:28f0/64 Scope:Site
inet6 addr: fe80::1ec1:deff:feee:28f0/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:13417 errors:0 dropped:0 overruns:0 frame:0
TX packets:713 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:1110663 (1.0 MiB) TX bytes:90272 (88.1 KiB)
Interrupt:93
eth1 Link encap:Ethernet HWaddr 1C:C1:DE:EE:28:F1
BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 b) TX bytes:0 (0.0 b)
Interrupt:97
eth2 Link encap:Ethernet HWaddr 1C:C1:DE:EE:28:F2
BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 b) TX bytes:0 (0.0 b)
Interrupt:101
eth3 Link encap:Ethernet HWaddr 1C:C1:DE:EE:28:F3
BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 b) TX bytes:0 (0.0 b)
Interrupt:105
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:18 errors:0 dropped:0 overruns:0 frame:0
TX packets:18 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:10557 (10.3 KiB) TX bytes:10557 (10.3 KiB)
[root@hp-magnycours-01 ~]# ./test_bonding_broadcast.sh |tee log
*******************
***iteration1*****
*******************
WARNING: pinging broadcast address
PING 192.168.8.255 (192.168.8.255) 56(84) bytes of data.
64 bytes from 192.168.8.2: icmp_seq=1 ttl=64 time=0.041 ms
64 bytes from 192.168.8.2: icmp_seq=2 ttl=64 time=0.029 ms
64 bytes from 192.168.8.2: icmp_seq=3 ttl=64 time=0.027 ms
64 bytes from 192.168.8.2: icmp_seq=4 ttl=64 time=0.026 ms
64 bytes from 192.168.8.2: icmp_seq=5 ttl=64 time=0.030 ms
64 bytes from 192.168.8.2: icmp_seq=6 ttl=64 time=0.024 ms
64 bytes from 192.168.8.2: icmp_seq=7 ttl=64 time=0.024 ms
64 bytes from 192.168.8.2: icmp_seq=8 ttl=64 time=0.023 ms
64 bytes from 192.168.8.2: icmp_seq=9 ttl=64 time=0.024 ms
64 bytes from 192.168.8.2: icmp_seq=10 ttl=64 time=0.023 ms
--- 192.168.8.255 ping statistics ---
10 packets transmitted, 10 received, 0% packet loss, time 9000ms
rtt min/avg/max/mdev = 0.023/0.027/0.041/0.005 ms
Message from syslogd@hp-magnycours-01 at May 25 04:07:22 ...
kernel:unregister_netdevice: waiting for bond0 to become free. Usage
count = 1
Message from syslogd@hp-magnycours-01 at May 25 04:07:33 ...
kernel:unregister_netdevice: waiting for bond0 to become free. Usage
count = 1
[root@hp-magnycours-01 ~]# dmesg
Ethernet Channel Bonding Driver: v3.6.0 (September 26, 2009)
bonding: MII link monitoring set to 100 ms
ADDRCONF(NETDEV_UP): bond0: link is not ready
bonding: bond0: Adding slave eth1.
bonding: bond0: enslaving eth1 as an active interface with a down link.
netxen_nic: eth1 NIC Link is up
bonding: bond0: Adding slave eth2.
bonding: bond0: enslaving eth2 as an active interface with a down link.
netxen_nic: eth2 NIC Link is up
bonding: bond0: link status definitely up for interface eth1.
bonding: bond0: link status definitely up for interface eth2.
ADDRCONF(NETDEV_CHANGE): bond0: link becomes ready
bond0: IPv6 duplicate address fe80::1ec1:deff:feee:28f1 detected!
bonding: bond0: released all slaves
unregister_netdevice: waiting for bond0 to become free. Usage count = 1
unregister_netdevice: waiting for bond0 to become free. Usage count = 1
unregister_netdevice: waiting for bond0 to become free. Usage count = 1
unregister_netdevice: waiting for bond0 to become free. Usage count = 1
^ permalink raw reply
* Re: Skipping past TCP lost packet in userspace
From: Josh Lehan @ 2011-05-31 4:12 UTC (permalink / raw)
To: Marcus D. Leech; +Cc: Josh Lehan, netdev
In-Reply-To: <4DE460E1.5020103@ripnet.com>
On 05/30/2011 08:30 PM, Marcus D. Leech wrote:
> This sounds like you want UDP, not TCP.
>
> Unless I'm misunderstanding what you want, you want a protocol that has
> a different "contract"
> than TCP. Doing what you want basically requires breaking TCP. That
> isn't going to happen.
Thanks. This wouldn't break the TCP protocol on the wire, though.
Instead, it would merely provide a way for a userspace application to
"peek" at the arrived data that's behind the missing packet. There's
already an ioctl() to peek at unread data, but it considers the missing
packet to be a barrier, and will not allow the application to see beyond it.
The reason for TCP is for maximum compatibility with firewalls, proxies,
and all the other annoyances of the modern commercialized Internet.
Using UDP would indeed solve this problem, but defeat the point of being
compatible. Using other exotic protocols such as SCTP or DCCP is a
nonstarter.
Josh Lehan
^ permalink raw reply
* Re: Skipping past TCP lost packet in userspace
From: Mikael Abrahamsson @ 2011-05-31 4:05 UTC (permalink / raw)
To: Josh Lehan; +Cc: netdev
In-Reply-To: <4DE44218.4070306@krellan.com>
On Mon, 30 May 2011, Josh Lehan wrote:
> Hello. I looked, but could not find an answer. Is there already an
> ioctl() or something like that in Linux, that would allow a userspace
> TCP socket to skip past a lost packet?
The basic operation of TCP is that it delivers a character stream to the
application. That requires TCP to make sure everything is in order and
nothing is missing.
If you want to do something else, you have to choose another protocol.
> Is there a way for a userspace program to prevent this needless stall?
That's like saying your body has all that needless blood.
--
Mikael Abrahamsson email: swmike@swm.pp.se
^ permalink raw reply
* Re: Skipping past TCP lost packet in userspace
From: Marcus D. Leech @ 2011-05-31 3:30 UTC (permalink / raw)
To: Josh Lehan; +Cc: netdev
In-Reply-To: <4DE44218.4070306@krellan.com>
>
> Hello. I looked, but could not find an answer. Is there already an
> ioctl() or something like that in Linux, that would allow a userspace
> TCP socket to skip past a lost packet?
>
> The kernel already will continue to queue up packets, and with TCP SACK,
> the kernel can acknowledge reception of further packets beyond the lost
> packet, allowing the queue to continue growing. However, all these
> queued packets won't be delivered to userspace until the original lost
> packet is received again, after it has been retransmitted.
>
> Is there a way for a userspace program to prevent this needless stall?
> It would be great if there was an ioctl() or similar call, that would
> tell the kernel that it's OK to leave a gap in the data stream, and
> resume supplying userspace with more data. An obvious application would
> be media streaming, and many high-level media protocols do their own
> block framing anyway, so resynchronization after the data gap would not
> be a problem.
>
> This sounds like something that would be a FAQ, and if so, please point
> me to the answer. Thank you!
>
>
This sounds like you want UDP, not TCP.
Unless I'm misunderstanding what you want, you want a protocol that has
a different "contract"
than TCP. Doing what you want basically requires breaking TCP. That
isn't going to happen.
--
Principal Investigator
Shirleys Bay Radio Astronomy Consortium
http://www.sbrac.org
^ permalink raw reply
* Skipping past TCP lost packet in userspace
From: Josh Lehan @ 2011-05-31 1:19 UTC (permalink / raw)
To: netdev
Hello. I looked, but could not find an answer. Is there already an
ioctl() or something like that in Linux, that would allow a userspace
TCP socket to skip past a lost packet?
The kernel already will continue to queue up packets, and with TCP SACK,
the kernel can acknowledge reception of further packets beyond the lost
packet, allowing the queue to continue growing. However, all these
queued packets won't be delivered to userspace until the original lost
packet is received again, after it has been retransmitted.
Is there a way for a userspace program to prevent this needless stall?
It would be great if there was an ioctl() or similar call, that would
tell the kernel that it's OK to leave a gap in the data stream, and
resume supplying userspace with more data. An obvious application would
be media streaming, and many high-level media protocols do their own
block framing anyway, so resynchronization after the data gap would not
be a problem.
This sounds like something that would be a FAQ, and if so, please point
me to the answer. Thank you!
Josh Lehan
^ permalink raw reply
* Re: [PATCH 15/15] ehea: Remove unused tcp_end field in send WQ
From: Benjamin Herrenschmidt @ 2011-05-31 1:16 UTC (permalink / raw)
To: Joe Perches
Cc: David Miller, anton, leitao, michael, jesse, bhutchings, netdev
In-Reply-To: <1305169927.6124.14.camel@Joe-Laptop>
On Wed, 2011-05-11 at 20:12 -0700, Joe Perches wrote:
> On Wed, 2011-05-11 at 23:06 -0400, David Miller wrote:
> > From: Joe Perches <joe@perches.com>
> > Date: Wed, 11 May 2011 19:31:13 -0700
> > > On Thu, 2011-05-12 at 10:52 +1000, Anton Blanchard wrote:
> > >> plain text document attachment (ehea_22.patch)
> > >> The tcp_end field is not actually used by the hardware, so there
> > >> is no need to set it.
> > >> +++ linux-net/drivers/net/ehea/ehea_qmr.h 2011-05-12 07:48:06.380382084 +1000
> > >> @@ -106,7 +106,7 @@ struct ehea_swqe {
> > >> u8 immediate_data_length;
> > >> u8 tcp_offset;
> > >> u8 reserved2;
> > >> - u16 tcp_end;
> > >> + u16 reserved2b;
> > >> u8 wrap_tag;
> > >> u8 descriptors; /* number of valid descriptors in WQE */
> > >> u16 reserved3;
> > > struct ehea_swqe isn't __packed. Shouldn't it be?
> > Please don't mark it __packed unless absolutely necessary :-)
>
> Isn't it read from hardware.
> If not, why reserve anything?
All the fields have the required alignment, so __packed shouldn't be
necessary but won't hurt either. Yes, it's a HW accessed structure.
Cheers,
Ben.
^ permalink raw reply
* Re: [PATCH] bond_3ad.c: switch MAC_ADDRESS_COMPARE macro for compare_ether_addr()
From: Ben Hutchings @ 2011-05-31 1:10 UTC (permalink / raw)
To: aquini; +Cc: kernel-janitors, Jay Vosburgh, David Miller, Andy Gospodarek,
netdev
In-Reply-To: <20110531004418.GA22937@optiplex.tchesoft.com>
On Mon, 2011-05-30 at 21:44 -0300, Rafael Aquini wrote:
> Converts all uses of MAC_ADDRESS_COMPARE macro to compare_ether_addr() and delete the macro.
[...]
Given all the casts you have to add, this doesn't seem like an
improvement.
How about replacing struct mac_addr with u8[ETH_ALEN] at the same time?
You should also be able to get rid of null_mac_addr and use
is_zero_ether_addr() instead.
Ben.
--
Ben Hutchings, Senior Software 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] bond_3ad.c: switch MAC_ADDRESS_COMPARE macro for compare_ether_addr()
From: Rafael Aquini @ 2011-05-31 0:44 UTC (permalink / raw)
To: kernel-janitors; +Cc: Jay Vosburgh, David Miller, Andy Gospodarek, netdev
Converts all uses of MAC_ADDRESS_COMPARE macro to compare_ether_addr() and delete the macro.
Signed-off-by: Rafael Aquini <aquini@linux.com>
---
drivers/net/bonding/bond_3ad.c | 26 ++++++++++++++------------
1 files changed, 14 insertions(+), 12 deletions(-)
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index c7537abc..c2e0d66 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -90,9 +90,6 @@
#define AD_LINK_SPEED_BITMASK_10000MBPS 0x10
//endalloun
-// compare MAC addresses
-#define MAC_ADDRESS_COMPARE(A, B) memcmp(A, B, ETH_ALEN)
-
static struct mac_addr null_mac_addr = { { 0, 0, 0, 0, 0, 0 } };
static u16 ad_ticks_per_sec;
static const int ad_delta_in_ticks = (AD_TIMER_INTERVAL * HZ) / 1000;
@@ -469,7 +466,7 @@ static void __choose_matched(struct lacpdu *lacpdu, struct port *port)
// check if all parameters are alike
if (((ntohs(lacpdu->partner_port) == port->actor_port_number) &&
(ntohs(lacpdu->partner_port_priority) == port->actor_port_priority) &&
- !MAC_ADDRESS_COMPARE(&(lacpdu->partner_system), &(port->actor_system)) &&
+ !compare_ether_addr((const u8 *)&(lacpdu->partner_system), (const u8 *)&(port->actor_system)) &&
(ntohs(lacpdu->partner_system_priority) == port->actor_system_priority) &&
(ntohs(lacpdu->partner_key) == port->actor_oper_port_key) &&
((lacpdu->partner_state & AD_STATE_AGGREGATION) == (port->actor_oper_port_state & AD_STATE_AGGREGATION))) ||
@@ -559,7 +556,8 @@ static void __update_selected(struct lacpdu *lacpdu, struct port *port)
// check if any parameter is different
if (ntohs(lacpdu->actor_port) != partner->port_number ||
ntohs(lacpdu->actor_port_priority) != partner->port_priority ||
- MAC_ADDRESS_COMPARE(&lacpdu->actor_system, &partner->system) ||
+ compare_ether_addr((const u8 *)&lacpdu->actor_system,
+ (const u8 *)&partner->system) ||
ntohs(lacpdu->actor_system_priority) != partner->system_priority ||
ntohs(lacpdu->actor_key) != partner->key ||
(lacpdu->actor_state & AD_STATE_AGGREGATION) != (partner->port_state & AD_STATE_AGGREGATION)) {
@@ -590,7 +588,8 @@ static void __update_default_selected(struct port *port)
// check if any parameter is different
if (admin->port_number != oper->port_number ||
admin->port_priority != oper->port_priority ||
- MAC_ADDRESS_COMPARE(&admin->system, &oper->system) ||
+ compare_ether_addr((const u8 *)&admin->system,
+ (const u8 *)&oper->system) ||
admin->system_priority != oper->system_priority ||
admin->key != oper->key ||
(admin->port_state & AD_STATE_AGGREGATION)
@@ -620,7 +619,8 @@ static void __update_ntt(struct lacpdu *lacpdu, struct port *port)
// check if any parameter is different
if ((ntohs(lacpdu->partner_port) != port->actor_port_number) ||
(ntohs(lacpdu->partner_port_priority) != port->actor_port_priority) ||
- MAC_ADDRESS_COMPARE(&(lacpdu->partner_system), &(port->actor_system)) ||
+ compare_ether_addr((const u8 *)&(lacpdu->partner_system),
+ (const u8 *)&(port->actor_system)) ||
(ntohs(lacpdu->partner_system_priority) != port->actor_system_priority) ||
(ntohs(lacpdu->partner_key) != port->actor_oper_port_key) ||
((lacpdu->partner_state & AD_STATE_LACP_ACTIVITY) != (port->actor_oper_port_state & AD_STATE_LACP_ACTIVITY)) ||
@@ -1123,7 +1123,7 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port)
break;
case AD_RX_CURRENT:
// detect loopback situation
- if (!MAC_ADDRESS_COMPARE(&(lacpdu->actor_system), &(port->actor_system))) {
+ if (!compare_ether_addr((const u8 *)&(lacpdu->actor_system), (const u8 *)&(port->actor_system))) {
// INFO_RECEIVED_LOOPBACK_FRAMES
pr_err("%s: An illegal loopback occurred on adapter (%s).\n"
"Check the configuration to verify that all adapters are connected to 802.3ad compliant switch ports\n",
@@ -1331,11 +1331,11 @@ static void ad_port_selection_logic(struct port *port)
}
// check if current aggregator suits us
if (((aggregator->actor_oper_aggregator_key == port->actor_oper_port_key) && // if all parameters match AND
- !MAC_ADDRESS_COMPARE(&(aggregator->partner_system), &(port->partner_oper.system)) &&
+ !compare_ether_addr((const u8 *)&(aggregator->partner_system), (const u8 *)&(port->partner_oper.system)) &&
(aggregator->partner_system_priority == port->partner_oper.system_priority) &&
(aggregator->partner_oper_aggregator_key == port->partner_oper.key)
) &&
- ((MAC_ADDRESS_COMPARE(&(port->partner_oper.system), &(null_mac_addr)) && // partner answers
+ ((compare_ether_addr((const u8 *)&(port->partner_oper.system), (const u8 *)&(null_mac_addr)) && // partner answers
!aggregator->is_individual) // but is not individual OR
)
) {
@@ -1751,7 +1751,9 @@ static void ad_enable_collecting_distributing(struct port *port)
*/
static void ad_disable_collecting_distributing(struct port *port)
{
- if (port->aggregator && MAC_ADDRESS_COMPARE(&(port->aggregator->partner_system), &(null_mac_addr))) {
+ if (port->aggregator &&
+ compare_ether_addr((const u8 *)&(port->aggregator->partner_system),
+ (const u8 *)&(null_mac_addr))) {
pr_debug("Disabling port %d(LAG %d)\n",
port->actor_port_number,
port->aggregator->aggregator_identifier);
@@ -1875,7 +1877,7 @@ static u16 aggregator_identifier;
void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution, int lacp_fast)
{
// check that the bond is not initialized yet
- if (MAC_ADDRESS_COMPARE(&(BOND_AD_INFO(bond).system.sys_mac_addr),
+ if (compare_ether_addr((const u8 *)&(BOND_AD_INFO(bond).system.sys_mac_addr),
bond->dev->dev_addr)) {
aggregator_identifier = 0;
--
1.7.4.4
--
Rafael Aquini <aquini@linux.com>
^ permalink raw reply related
* Re: [PATCH 2/2] net: make dev_disable_lro use physical device if passed a vlan dev (v2)
From: Neil Horman @ 2011-05-31 0:06 UTC (permalink / raw)
To: Ben Hutchings; +Cc: netdev, davem
In-Reply-To: <1306552263.2759.57.camel@bwh-desktop>
On Sat, May 28, 2011 at 04:11:03AM +0100, Ben Hutchings wrote:
> On Tue, 2011-05-24 at 14:31 -0400, Neil Horman wrote:
> > If the device passed into dev_disable_lro is a vlan, then repoint the dev
> > poniter so that we actually modify the underlying physical device.
> [...]
>
> Thanks Neil, this looks good.
>
> There seems to be a slightly weird bug remaining, in that NETIF_F_LRO
> may remain set on the VLAN device. But that's really cosmetic and
> should go away in 2.6.40 along with the old ethtool operations for
> offload setting.
>
> Ben.
>
Copy that, thanks Ben.
Neil
> --
> Ben Hutchings, Senior Software 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] uts: Make default hostname configurable, rather than always using "(none)"
From: Josh Triplett @ 2011-05-30 22:38 UTC (permalink / raw)
To: David Miller, netdev, Serge E. Hallyn, Andrew Morton,
Linus Torvalds
Cc: Kel Modderman, pkg-sysvinit-devel
The "hostname" tool falls back to setting the hostname to "localhost" if
/etc/hostname does not exist. Distribution init scripts have the same
fallback. However, if userspace never calls sethostname, such as when
booting with init=/bin/sh, or otherwise booting a minimal system without
the usual init scripts, the default hostname of "(none)" remains,
unhelpfully appearing in various places such as prompts
("root@(none):~#") and logs. Furthermore, "(none)" doesn't typically
resolve to anything useful.
Make the default hostname configurable. This removes the need for the
standard fallback, provides a useful default for systems that never call
sethostname, and makes minimal systems that much more useful with less
configuration. Distributions could choose to use "localhost" here to
avoid the fallback, while embedded systems may wish to use a specific
target hostname.
Signed-off-by: Josh Triplett <josh@joshtriplett.org>
---
Revised from my original patch that just changed the default to
"localhost"; this patch makes the default configurable, and leaves the
default default as "(none)".
include/linux/uts.h | 2 +-
init/Kconfig | 9 +++++++++
2 files changed, 10 insertions(+), 1 deletions(-)
diff --git a/include/linux/uts.h b/include/linux/uts.h
index 73eb1ed..6ddbd86 100644
--- a/include/linux/uts.h
+++ b/include/linux/uts.h
@@ -9,7 +9,7 @@
#endif
#ifndef UTS_NODENAME
-#define UTS_NODENAME "(none)" /* set by sethostname() */
+#define UTS_NODENAME CONFIG_DEFAULT_HOSTNAME /* set by sethostname() */
#endif
#ifndef UTS_DOMAINNAME
diff --git a/init/Kconfig b/init/Kconfig
index ebafac4..e0a22e4 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -204,6 +204,15 @@ config KERNEL_LZO
endchoice
+config DEFAULT_HOSTNAME
+ string "Default hostname"
+ default "(none)"
+ help
+ This option determines the default system hostname before userspace
+ calls sethostname(2). The kernel traditionally uses "(none)" here,
+ but you may wish to use a different default here to make a minimal
+ system more usable with less configuration.
+
config SWAP
bool "Support for paging of anonymous memory (swap)"
depends on MMU && BLOCK
--
1.7.5.3
^ permalink raw reply related
* Re: pull request: wireless-2.6 2011-05-27
From: David Miller @ 2011-05-30 20:26 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, netdev, linux-kernel
In-Reply-To: <20110527195008.GA5092@tuxdriver.com>
From: "John W. Linville" <linville@tuxdriver.com>
Date: Fri, 27 May 2011 15:50:08 -0400
> This is a quick batch of fixes intended for 2.6.40. They are all
> small(-ish), and several of them fix either build breakage or some
> sort of regression. At least one fixes an uninitialized variable
> that could potentially cause a crash.
>
> Please let me know if there are problems!
2.6.40, wtf is that? :-)
Just kidding, pulled, thanks!
^ permalink raw reply
* Re: Kernel crash after using new Intel NIC (igb)
From: Arun Sharma @ 2011-05-30 18:34 UTC (permalink / raw)
To: Ingo Molnar
Cc: Eric Dumazet, David Miller, Maximilian Engelhardt, linux-kernel,
netdev, StuStaNet Vorstand, Yann Dupont, Denys Fedoryshchenko,
Thomas Gleixner
In-Reply-To: <20110529123318.GB26627@elte.hu>
On 5/29/11 5:33 AM, Ingo Molnar wrote:
>
> * Eric Dumazet<eric.dumazet@gmail.com> wrote:
>
>> I asked Arun if he wanted to make this himself, because initial
>> idea was coming from him, not because I did not want to make it ;)
>
> Hey, fair enough and sorry about the fuss! :-)
Sounds like there is general consensus that such a cleanup would be
good. I'll try to post a patch that does this cleanup for all archs in
the next couple of days - but I won't have a way of testing it on
anything other than x86_64.
-Arun
^ permalink raw reply
* [PATCH] drivers/net/usb/catc.c: Fix potential deadlock in catc_ctrl_run()
From: Alexey Khoroshilov @ 2011-05-30 17:06 UTC (permalink / raw)
To: Greg Kroah-Hartman; +Cc: Alexey Khoroshilov, linux-usb, netdev, linux-kernel
In-Reply-To: <1306774878-5471-1-git-send-email-khoroshilov@ispras.ru>
Sorry, I missed a description in the previous mail.
catc_ctrl_run() calls usb_submit_urb() with GFP_KERNEL, while it is called from
catc_ctrl_async() and catc_ctrl_done() with catc->ctrl_lock spinlock held.
The patch replaces GFP_KERNEL with GFP_ATOMIC.
Found by Linux Driver Verification project (linuxtesting.org).
Signed-off-by: Alexey Khoroshilov <khoroshilov@ispras.ru>
---
drivers/net/usb/catc.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/net/usb/catc.c b/drivers/net/usb/catc.c
index d7221c4..8056f8a 100644
--- a/drivers/net/usb/catc.c
+++ b/drivers/net/usb/catc.c
@@ -495,7 +495,7 @@ static void catc_ctrl_run(struct catc *catc)
if (!q->dir && q->buf && q->len)
memcpy(catc->ctrl_buf, q->buf, q->len);
- if ((status = usb_submit_urb(catc->ctrl_urb, GFP_KERNEL)))
+ if ((status = usb_submit_urb(catc->ctrl_urb, GFP_ATOMIC)))
err("submit(ctrl_urb) status %d", status);
}
--
1.7.4.1
^ permalink raw reply related
* [PATCH] drivers/net/usb/catc.c: Fix potential deadlock in catc_ctrl_run()
From: Alexey Khoroshilov @ 2011-05-30 17:01 UTC (permalink / raw)
To: Greg Kroah-Hartman
Cc: Alexey Khoroshilov, linux-usb-u79uwXL29TY76Z2rM5mHXA,
netdev-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
The patch replaces GFP_KERNEL with GFP_ATOMIC.
Found by Linux Driver Verification project (linuxtesting.org).
Signed-off-by: Alexey Khoroshilov <khoroshilov-ufN2psIa012HXe+LvDLADg@public.gmane.org>
---
drivers/net/usb/catc.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/net/usb/catc.c b/drivers/net/usb/catc.c
index d7221c4..8056f8a 100644
--- a/drivers/net/usb/catc.c
+++ b/drivers/net/usb/catc.c
@@ -495,7 +495,7 @@ static void catc_ctrl_run(struct catc *catc)
if (!q->dir && q->buf && q->len)
memcpy(catc->ctrl_buf, q->buf, q->len);
- if ((status = usb_submit_urb(catc->ctrl_urb, GFP_KERNEL)))
+ if ((status = usb_submit_urb(catc->ctrl_urb, GFP_ATOMIC)))
err("submit(ctrl_urb) status %d", status);
}
--
1.7.4.1
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" 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: [ANNOUNCE]: Release of iptables-1.4.11
From: Jan Engelhardt @ 2011-05-30 10:18 UTC (permalink / raw)
To: Arkadiusz Miskiewicz
Cc: Pablo Neira Ayuso, Netfilter Development Mailinglist, NetDev
In-Reply-To: <201105301105.30036.a.miskiewicz@gmail.com>
On Monday 2011-05-30 11:05, Arkadiusz Miskiewicz wrote:
>On Friday 27 of May 2011, Pablo Neira Ayuso wrote:
>> On 27/05/11 09:52, Arkadiusz Miskiewicz wrote:
>
>> > /usr/include/xtables.h:395:23: note: expected ‘const struct option *’ but
>> > argument is of type ‘unsigned int *’
>> > m_xt.c:312:30: error: too few arguments to function
>> > ‘xtables_merge_options’ /usr/include/xtables.h:395:23: note: declared
>> > here
>> > make[1]: *** [m_xt.so] Błąd 1
>> > rm emp_ematch.lex.c emp_ematch.yacc.c
>>
>> Backward compatibility was broken in the following iptables commit:
>>
>> From 600f38db82548a683775fd89b6e136673e924097 Mon Sep 17 00:00:00 2001
>> From: Jan Engelhardt <jengelh@medozas.de>
>> Date: Fri, 29 Oct 2010 18:57:42 +0200
>> Subject: [PATCH] libxtables: change option precedence order to be intuitive
>
>Another bug seems to be in Makefile.am
>
> for i in ${v4_bin_links}; do ${LN_S} -f "${sbindir}/iptables-multi"
>"${DESTDIR}${bindir}/$$i"; done;
> for i in ${v4_sbin_links}; do ${LN_S} -f iptables-multi
>"${DESTDIR}${sbindir}/$$i"; done;
> for i in ${v6_sbin_links}; do ${LN_S} -f ip6tables-multi
>"${DESTDIR}${sbindir}/$$i"; done;
>
>These will point to nowhere since now there is xtables-multi only.
Patch created yesterday already; now sent out.
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH] sctp: stop pending timers and purge queues when peer restart asoc
From: Wei Yongjun @ 2011-05-30 9:23 UTC (permalink / raw)
To: David Miller, Vlad Yasevich; +Cc: lksctp, netdev@vger.kernel.org
If the peer restart the asoc, we should not only fail any unsent/unacked
data, but also stop the T3-rtx, SACK, T4-rto timers, and teardown ASCONF
queues.
Signed-off-by: Wei Yongjun <yjwei@cn.fujitsu.com>
---
include/net/sctp/command.h | 1 +
include/net/sctp/structs.h | 2 +-
net/sctp/associola.c | 23 ++++++++++++++---------
net/sctp/sm_sideeffect.c | 3 +++
net/sctp/sm_statefuns.c | 14 ++++++++++++--
5 files changed, 31 insertions(+), 12 deletions(-)
diff --git a/include/net/sctp/command.h b/include/net/sctp/command.h
index 2b44764..c1baee9 100644
--- a/include/net/sctp/command.h
+++ b/include/net/sctp/command.h
@@ -107,6 +107,7 @@ typedef enum {
SCTP_CMD_UPDATE_INITTAG, /* Update peer inittag */
SCTP_CMD_SEND_MSG, /* Send the whole use message */
SCTP_CMD_SEND_NEXT_ASCONF, /* Send the next ASCONF after ACK */
+ SCTP_CMD_PURGE_ASCONF_QUEUE, /* Purge all asconf queues.*/
SCTP_CMD_LAST
} sctp_verb_t;
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 795f488..7df327a 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -1993,7 +1993,7 @@ void sctp_assoc_clean_asconf_ack_cache(const struct sctp_association *asoc);
struct sctp_chunk *sctp_assoc_lookup_asconf_ack(
const struct sctp_association *asoc,
__be32 serial);
-
+void sctp_asconf_queue_teardown(struct sctp_association *asoc);
int sctp_cmp_addr_exact(const union sctp_addr *ss1,
const union sctp_addr *ss2);
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 525f97c..4a62888 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -444,15 +444,7 @@ void sctp_association_free(struct sctp_association *asoc)
asoc->peer.transport_count = 0;
- /* Free any cached ASCONF_ACK chunk. */
- sctp_assoc_free_asconf_acks(asoc);
-
- /* Free the ASCONF queue. */
- sctp_assoc_free_asconf_queue(asoc);
-
- /* Free any cached ASCONF chunk. */
- if (asoc->addip_last_asconf)
- sctp_chunk_free(asoc->addip_last_asconf);
+ sctp_asconf_queue_teardown(asoc);
/* AUTH - Free the endpoint shared keys */
sctp_auth_destroy_keys(&asoc->endpoint_shared_keys);
@@ -1646,3 +1638,16 @@ struct sctp_chunk *sctp_assoc_lookup_asconf_ack(
return NULL;
}
+
+void sctp_asconf_queue_teardown(struct sctp_association *asoc)
+{
+ /* Free any cached ASCONF_ACK chunk. */
+ sctp_assoc_free_asconf_acks(asoc);
+
+ /* Free the ASCONF queue. */
+ sctp_assoc_free_asconf_queue(asoc);
+
+ /* Free any cached ASCONF chunk. */
+ if (asoc->addip_last_asconf)
+ sctp_chunk_free(asoc->addip_last_asconf);
+}
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index d612ca1..534c2e5 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -1670,6 +1670,9 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
case SCTP_CMD_SEND_NEXT_ASCONF:
sctp_cmd_send_asconf(asoc);
break;
+ case SCTP_CMD_PURGE_ASCONF_QUEUE:
+ sctp_asconf_queue_teardown(asoc);
+ break;
default:
pr_warn("Impossible command: %u, %p\n",
cmd->verb, cmd->obj.ptr);
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 7f4a4f8..a297283 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -1718,11 +1718,21 @@ static sctp_disposition_t sctp_sf_do_dupcook_a(const struct sctp_endpoint *ep,
return SCTP_DISPOSITION_CONSUME;
}
- /* For now, fail any unsent/unacked data. Consider the optional
- * choice of resending of this data.
+ /* For now, stop pending T3-rtx and SACK timers, fail any unsent/unacked
+ * data. Consider the optional choice of resending of this data.
*/
+ sctp_add_cmd_sf(commands, SCTP_CMD_T3_RTX_TIMERS_STOP, SCTP_NULL());
+ sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
+ SCTP_TO(SCTP_EVENT_TIMEOUT_SACK));
sctp_add_cmd_sf(commands, SCTP_CMD_PURGE_OUTQUEUE, SCTP_NULL());
+ /* Stop pending T4-rto timer, teardown ASCONF queue, ASCONF-ACK queue
+ * and ASCONF-ACK cache.
+ */
+ sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
+ SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO));
+ sctp_add_cmd_sf(commands, SCTP_CMD_PURGE_ASCONF_QUEUE, SCTP_NULL());
+
repl = sctp_make_cookie_ack(new_asoc, chunk);
if (!repl)
goto nomem;
--
1.6.5.2
^ permalink raw reply related
* Re: [ANNOUNCE]: Release of iptables-1.4.11
From: Arkadiusz Miskiewicz @ 2011-05-30 9:05 UTC (permalink / raw)
To: Pablo Neira Ayuso, Netfilter Development Mailinglist; +Cc: NetDev
In-Reply-To: <4DDF912A.5070003@netfilter.org>
On Friday 27 of May 2011, Pablo Neira Ayuso wrote:
> On 27/05/11 09:52, Arkadiusz Miskiewicz wrote:
> > /usr/include/xtables.h:395:23: note: expected ‘const struct option *’ but
> > argument is of type ‘unsigned int *’
> > m_xt.c:312:30: error: too few arguments to function
> > ‘xtables_merge_options’ /usr/include/xtables.h:395:23: note: declared
> > here
> > make[1]: *** [m_xt.so] Błąd 1
> > rm emp_ematch.lex.c emp_ematch.yacc.c
>
> Backward compatibility was broken in the following iptables commit:
>
> From 600f38db82548a683775fd89b6e136673e924097 Mon Sep 17 00:00:00 2001
> From: Jan Engelhardt <jengelh@medozas.de>
> Date: Fri, 29 Oct 2010 18:57:42 +0200
> Subject: [PATCH] libxtables: change option precedence order to be intuitive
Another bug seems to be in Makefile.am
for i in ${v4_bin_links}; do ${LN_S} -f "${sbindir}/iptables-multi"
"${DESTDIR}${bindir}/$$i"; done;
for i in ${v4_sbin_links}; do ${LN_S} -f iptables-multi
"${DESTDIR}${sbindir}/$$i"; done;
for i in ${v6_sbin_links}; do ${LN_S} -f ip6tables-multi
"${DESTDIR}${sbindir}/$$i"; done;
These will point to nowhere since now there is xtables-multi only.
--
Arkadiusz Miśkiewicz PLD/Linux Team
arekm / maven.pl http://ftp.pld-linux.org/
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ 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