* Re: [PATCH net-2.6] llc: fix a device refcount imbalance
From: Maxim Levitsky @ 2010-12-09 3:46 UTC (permalink / raw)
To: David Miller
Cc: eric.dumazet, linux1394-devel, stefanr, netdev, kuznet, jmorris,
kaber, opurdila, stable
In-Reply-To: <20101208.095920.229730656.davem@davemloft.net>
On Wed, 2010-12-08 at 09:59 -0800, David Miller wrote:
> From: Eric Dumazet <eric.dumazet@gmail.com>
> Date: Sun, 05 Dec 2010 13:03:26 +0100
>
> > [PATCH net-2.6] llc: fix a device refcount imbalance
> >
> > commit abf9d537fea225 (llc: add support for SO_BINDTODEVICE) added one
> > refcount imbalance in llc_ui_bind(), because dev_getbyhwaddr() doesnt
> > take a reference on device, while dev_get_by_index() does.
> >
> > Fix this using RCU locking. And since an RCU conversion will be done for
> > 2.6.38 for dev_getbyhwaddr(), put the rcu_read_lock/unlock exactly at
> > their final place.
> >
> > Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
>
> Applied and queued up for -stable.
Hi,
Could I kindly ask if my patch is accepted?
Best regards,
Maxim Levitsky
^ permalink raw reply
* [PATCH] Fix 2.6.34-rc1 regression in disable_ipv6 support
From: Eric W. Biederman @ 2010-12-09 4:16 UTC (permalink / raw)
To: David Miller
Cc: Brian Haley, netdev, Mahesh Kelkar, Lorenzo Colitti,
YOSHIFUJI Hideaki, Stephen Hemminger, stable
In-Reply-To: <m1ipz3d46m.fsf@fess.ebiederm.org>
In a number of instances it is desirable to have systems that run with
ipv6 disabled, but where enabling ipv6 remains an option. This
has been broken since 2.6.34-rc1.
The problem is failure mode is that after
# ip link set lo up
# echo 1 > /proc/sys/net/ipv6/conf/lo/disable_ipv6
# echo 0 > /proc/sys/net/ipv6/conf/lo/disable_ipv6
# ping6 ::1
The ping and anything similar operations that use the
ipv6 loopback address fail with network not reachable.
This failure mode appears to start with:
commit dc2b99f71ef477a31020511876ab4403fb7c4420
Author: stephen hemminger <shemminger@vyatta.com>
Date: Mon Feb 8 19:48:05 2010 +0000
IPv6: keep permanent addresses on admin down
Permanent IPV6 addresses should not be removed when the link is
set to admin down, only when device is removed.
When link is lost permanent addresses should be marked as tentative
so that when link comes back they are subject to duplicate address
detection (if DAD was enabled for that address).
Other routing systems keep manually configured IPv6 addresses
when link is set down.
Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Keeping ipv6 addresses on network interfaces when we bring those
interfaces down is not the fundamental problem. The real problem is
that there is something about routes and route-caches that make local
ipv6 address unreachable after the loopback interface is brought down,
and then brought up again, and it has been that way since at least
2.6.32.
Finding the real bug is beyond me right now, but fixing the regression
in disable_ipv6 is simple. We can just delete ::1 when we bring down
the loopback interface, and it will be restored automatically when we
bring the loopback interface back up.
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
---
Index: linux-2.6.37-rc5.x86_64/net/ipv6/addrconf.c
===================================================================
--- linux-2.6.37-rc5.x86_64.orig/net/ipv6/addrconf.c
+++ linux-2.6.37-rc5.x86_64/net/ipv6/addrconf.c
@@ -2727,6 +2727,7 @@ static int addrconf_ifdown(struct net_de
/* If just doing link down, and address is permanent
and not link-local, then retain it. */
if (!how &&
+ !ipv6_addr_loopback(&ifa->addr) &&
(ifa->flags&IFA_F_PERMANENT) &&
!(ipv6_addr_type(&ifa->addr) & IPV6_ADDR_LINKLOCAL)) {
list_move_tail(&ifa->if_list, &keep_list);
^ permalink raw reply
* Re: NULL dereference in econet AUN-over-UDP receive
From: Nelson Elhage @ 2010-12-09 4:18 UTC (permalink / raw)
To: David Miller; +Cc: eric.dumazet, netdev
In-Reply-To: <20101208.180215.193709862.davem@davemloft.net>
Yep, that fixes the crash.
Tested-by: Nelson Elhage <nelhage@ksplice.com>
On Wed, Dec 8, 2010 at 9:02 PM, David Miller <davem@davemloft.net> wrote:
> From: Eric Dumazet <eric.dumazet@gmail.com>
> Date: Thu, 09 Dec 2010 02:37:47 +0100
>
>> Le mercredi 08 décembre 2010 à 19:30 -0500, Nelson Elhage a écrit :
>>> While testing one of my econet reproducers on a patched kernel, I triggered a
>>> NULL pointer dereference in the econet AUN-over-UDP receive path. Upon further
>>> investigation, I now suspect that this code path hasn't worked at all in years.
>>>
>>> A copy of the oops is below for your reference, but here's my analysis:
>>>
>>> When aun_data_available receives a data packet (ah->code == 2), it calls
>>> aun_incoming to process the skb. The start of aun_incoming looks like:
>>>
>>> static void aun_incoming(struct sk_buff *skb, struct aunhdr *ah, size_t len)
>>> {
>>> struct iphdr *ip = ip_hdr(skb);
>>> unsigned char stn = ntohl(ip->saddr) & 0xff;
>>> struct sock *sk = NULL;
>>> struct sk_buff *newskb;
>>> ---> struct ec_device *edev = skb->dev->ec_ptr;
>>>
>>
>> This can be changed to use skb_dst(skb)->dev instead
>>
>> struct dst *dst = skb_dst(skb);
>>
>> if (dst) {
>> dev = dst->dev;
>> ...
>> }
>
> Nelson please test if this patch fixes your crash:
>
> econet: Fix crash in aun_incoming().
>
> Unconditional use of skb->dev won't work here,
> try to fetch the econet device via skb_dst()->dev
> instead.
>
> Suggested by Eric Dumazet.
>
> Reported-by: Nelson Elhage <nelhage@ksplice.com>
> Signed-off-by: David S. Miller <davem@davemloft.net>
>
> diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c
> index f180371..15dcc1a 100644
> --- a/net/econet/af_econet.c
> +++ b/net/econet/af_econet.c
> @@ -851,9 +851,13 @@ static void aun_incoming(struct sk_buff *skb, struct aunhdr *ah, size_t len)
> {
> struct iphdr *ip = ip_hdr(skb);
> unsigned char stn = ntohl(ip->saddr) & 0xff;
> + struct dst_entry *dst = skb_dst(skb);
> + struct ec_device *edev = NULL;
> struct sock *sk = NULL;
> struct sk_buff *newskb;
> - struct ec_device *edev = skb->dev->ec_ptr;
> +
> + if (dst)
> + edev = dst->dev->ec_ptr;
>
> if (! edev)
> goto bad;
>
^ permalink raw reply
* Re: NULL dereference in econet AUN-over-UDP receive
From: David Miller @ 2010-12-09 4:50 UTC (permalink / raw)
To: nelhage; +Cc: eric.dumazet, netdev
In-Reply-To: <AANLkTimdN2LkEpyWV0bsdfVVvnsQOaLGYmm_0ostrjFM@mail.gmail.com>
From: Nelson Elhage <nelhage@ksplice.com>
Date: Wed, 8 Dec 2010 23:18:22 -0500
> Yep, that fixes the crash.
>
> Tested-by: Nelson Elhage <nelhage@ksplice.com>
THanks for testing.
^ permalink raw reply
* [PATCH v2] atm: correct sysfs 'device' link creation and parent relationships
From: Dan Williams @ 2010-12-09 5:40 UTC (permalink / raw)
To: David Miller; +Cc: kay.sievers, netdev, duncan.sands, linux-usb, chas
In-Reply-To: <1291854831.16839.12.camel@dcbw.foobar.com>
The ATM subsystem was incorrectly creating the 'device' link for ATM
nodes in sysfs. This led to incorrect device/parent relationships
exposed by sysfs and udev. Instead of rolling the 'device' link by hand
in the generic ATM code, pass each ATM driver's bus device down to the
sysfs code and let sysfs do this stuff correctly.
Signed-off-by: Dan Williams <dcbw@redhat.com>
---
v2: passes an x86-64 allmodconfig build of net-next-2.6 which it didn't
do the first time because I'm an idiot
diff --git a/drivers/atm/adummy.c b/drivers/atm/adummy.c
index 46b9476..f9b983a 100644
--- a/drivers/atm/adummy.c
+++ b/drivers/atm/adummy.c
@@ -154,7 +154,7 @@ static int __init adummy_init(void)
err = -ENOMEM;
goto out;
}
- atm_dev = atm_dev_register(DEV_LABEL, &adummy_ops, -1, NULL);
+ atm_dev = atm_dev_register(DEV_LABEL, NULL, &adummy_ops, -1, NULL);
if (!atm_dev) {
printk(KERN_ERR DEV_LABEL ": atm_dev_register() failed\n");
err = -ENODEV;
diff --git a/drivers/atm/ambassador.c b/drivers/atm/ambassador.c
index a33896a..ffe9b65 100644
--- a/drivers/atm/ambassador.c
+++ b/drivers/atm/ambassador.c
@@ -2244,7 +2244,8 @@ static int __devinit amb_probe(struct pci_dev *pci_dev, const struct pci_device_
goto out_reset;
}
- dev->atm_dev = atm_dev_register (DEV_LABEL, &amb_ops, -1, NULL);
+ dev->atm_dev = atm_dev_register (DEV_LABEL, &pci_dev->dev, &amb_ops, -1,
+ NULL);
if (!dev->atm_dev) {
PRINTD (DBG_ERR, "failed to register Madge ATM adapter");
err = -EINVAL;
diff --git a/drivers/atm/atmtcp.c b/drivers/atm/atmtcp.c
index b910181..2b464b6 100644
--- a/drivers/atm/atmtcp.c
+++ b/drivers/atm/atmtcp.c
@@ -366,7 +366,7 @@ static int atmtcp_create(int itf,int persist,struct atm_dev **result)
if (!dev_data)
return -ENOMEM;
- dev = atm_dev_register(DEV_LABEL,&atmtcp_v_dev_ops,itf,NULL);
+ dev = atm_dev_register(DEV_LABEL,NULL,&atmtcp_v_dev_ops,itf,NULL);
if (!dev) {
kfree(dev_data);
return itf == -1 ? -ENOMEM : -EBUSY;
diff --git a/drivers/atm/eni.c b/drivers/atm/eni.c
index 97c5898..c495fae 100644
--- a/drivers/atm/eni.c
+++ b/drivers/atm/eni.c
@@ -2244,7 +2244,7 @@ static int __devinit eni_init_one(struct pci_dev *pci_dev,
&zeroes);
if (!cpu_zeroes) goto out1;
}
- dev = atm_dev_register(DEV_LABEL,&ops,-1,NULL);
+ dev = atm_dev_register(DEV_LABEL, &pci_dev->dev, &ops, -1, NULL);
if (!dev) goto out2;
pci_set_drvdata(pci_dev, dev);
eni_dev->pci_dev = pci_dev;
diff --git a/drivers/atm/firestream.c b/drivers/atm/firestream.c
index 5d86bb8..7d912ba 100644
--- a/drivers/atm/firestream.c
+++ b/drivers/atm/firestream.c
@@ -1911,7 +1911,7 @@ static int __devinit firestream_init_one (struct pci_dev *pci_dev,
fs_dev, sizeof (struct fs_dev));
if (!fs_dev)
goto err_out;
- atm_dev = atm_dev_register("fs", &ops, -1, NULL);
+ atm_dev = atm_dev_register("fs", &pci_dev->dev, &ops, -1, NULL);
if (!atm_dev)
goto err_out_free_fs_dev;
diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c
index c097619..44f7785 100644
--- a/drivers/atm/fore200e.c
+++ b/drivers/atm/fore200e.c
@@ -2567,14 +2567,14 @@ release:
static int __devinit
-fore200e_register(struct fore200e* fore200e)
+fore200e_register(struct fore200e* fore200e, struct device *parent)
{
struct atm_dev* atm_dev;
DPRINTK(2, "device %s being registered\n", fore200e->name);
- atm_dev = atm_dev_register(fore200e->bus->proc_name, &fore200e_ops, -1,
- NULL);
+ atm_dev = atm_dev_register(fore200e->bus->proc_name, parent, &fore200e_ops,
+ -1, NULL);
if (atm_dev == NULL) {
printk(FORE200E "unable to register device %s\n", fore200e->name);
return -ENODEV;
@@ -2594,9 +2594,9 @@ fore200e_register(struct fore200e* fore200e)
static int __devinit
-fore200e_init(struct fore200e* fore200e)
+fore200e_init(struct fore200e* fore200e, struct device *parent)
{
- if (fore200e_register(fore200e) < 0)
+ if (fore200e_register(fore200e, parent) < 0)
return -ENODEV;
if (fore200e->bus->configure(fore200e) < 0)
@@ -2662,7 +2662,7 @@ static int __devinit fore200e_sba_probe(struct platform_device *op,
sprintf(fore200e->name, "%s-%d", bus->model_name, index);
- err = fore200e_init(fore200e);
+ err = fore200e_init(fore200e, &op->dev);
if (err < 0) {
fore200e_shutdown(fore200e);
kfree(fore200e);
@@ -2740,7 +2740,7 @@ fore200e_pca_detect(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent
sprintf(fore200e->name, "%s-%d", bus->model_name, index);
- err = fore200e_init(fore200e);
+ err = fore200e_init(fore200e, &pci_dev->dev);
if (err < 0) {
fore200e_shutdown(fore200e);
goto out_free;
diff --git a/drivers/atm/he.c b/drivers/atm/he.c
index 801e8b6..6cf59bf 100644
--- a/drivers/atm/he.c
+++ b/drivers/atm/he.c
@@ -366,7 +366,7 @@ he_init_one(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent)
goto init_one_failure;
}
- atm_dev = atm_dev_register(DEV_LABEL, &he_ops, -1, NULL);
+ atm_dev = atm_dev_register(DEV_LABEL, &pci_dev->dev, &he_ops, -1, NULL);
if (!atm_dev) {
err = -ENODEV;
goto init_one_failure;
diff --git a/drivers/atm/horizon.c b/drivers/atm/horizon.c
index a957904..24761e1 100644
--- a/drivers/atm/horizon.c
+++ b/drivers/atm/horizon.c
@@ -2733,7 +2733,8 @@ static int __devinit hrz_probe(struct pci_dev *pci_dev, const struct pci_device_
PRINTD(DBG_INFO, "found Madge ATM adapter (hrz) at: IO %x, IRQ %u, MEM %p",
iobase, irq, membase);
- dev->atm_dev = atm_dev_register(DEV_LABEL, &hrz_ops, -1, NULL);
+ dev->atm_dev = atm_dev_register(DEV_LABEL, &pci_dev->dev, &hrz_ops, -1,
+ NULL);
if (!(dev->atm_dev)) {
PRINTD(DBG_ERR, "failed to register Madge ATM adapter");
err = -EINVAL;
diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c
index bce5732..bfb7fee 100644
--- a/drivers/atm/idt77252.c
+++ b/drivers/atm/idt77252.c
@@ -3698,7 +3698,8 @@ idt77252_init_one(struct pci_dev *pcidev, const struct pci_device_id *id)
goto err_out_iounmap;
}
- dev = atm_dev_register("idt77252", &idt77252_ops, -1, NULL);
+ dev = atm_dev_register("idt77252", &pcidev->dev, &idt77252_ops, -1,
+ NULL);
if (!dev) {
printk("%s: can't register atm device\n", card->name);
err = -EIO;
diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c
index 9309d47..7292540 100644
--- a/drivers/atm/iphase.c
+++ b/drivers/atm/iphase.c
@@ -3172,7 +3172,7 @@ static int __devinit ia_init_one(struct pci_dev *pdev,
ret = -ENODEV;
goto err_out_free_iadev;
}
- dev = atm_dev_register(DEV_LABEL, &ops, -1, NULL);
+ dev = atm_dev_register(DEV_LABEL, &pdev->dev, &ops, -1, NULL);
if (!dev) {
ret = -ENOMEM;
goto err_out_disable_dev;
diff --git a/drivers/atm/lanai.c b/drivers/atm/lanai.c
index 930051d..52880c8 100644
--- a/drivers/atm/lanai.c
+++ b/drivers/atm/lanai.c
@@ -2588,7 +2588,7 @@ static int __devinit lanai_init_one(struct pci_dev *pci,
return -ENOMEM;
}
- atmdev = atm_dev_register(DEV_LABEL, &ops, -1, NULL);
+ atmdev = atm_dev_register(DEV_LABEL, &pci->dev, &ops, -1, NULL);
if (atmdev == NULL) {
printk(KERN_ERR DEV_LABEL
": couldn't register atm device!\n");
diff --git a/drivers/atm/nicstar.c b/drivers/atm/nicstar.c
index 2f3516b..6b313ee 100644
--- a/drivers/atm/nicstar.c
+++ b/drivers/atm/nicstar.c
@@ -771,7 +771,8 @@ static int __devinit ns_init_card(int i, struct pci_dev *pcidev)
}
/* Register device */
- card->atmdev = atm_dev_register("nicstar", &atm_ops, -1, NULL);
+ card->atmdev = atm_dev_register("nicstar", &card->pcidev->dev, &atm_ops,
+ -1, NULL);
if (card->atmdev == NULL) {
printk("nicstar%d: can't register device.\n", i);
error = 17;
diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c
index 2e08c99..73fb1c4 100644
--- a/drivers/atm/solos-pci.c
+++ b/drivers/atm/solos-pci.c
@@ -166,7 +166,7 @@ static irqreturn_t solos_irq(int irq, void *dev_id);
static struct atm_vcc* find_vcc(struct atm_dev *dev, short vpi, int vci);
static int list_vccs(int vci);
static void release_vccs(struct atm_dev *dev);
-static int atm_init(struct solos_card *);
+static int atm_init(struct solos_card *, struct device *);
static void atm_remove(struct solos_card *);
static int send_command(struct solos_card *card, int dev, const char *buf, size_t size);
static void solos_bh(unsigned long);
@@ -1210,7 +1210,7 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id)
if (db_firmware_upgrade)
flash_upgrade(card, 3);
- err = atm_init(card);
+ err = atm_init(card, &dev->dev);
if (err)
goto out_free_irq;
@@ -1233,7 +1233,7 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id)
return err;
}
-static int atm_init(struct solos_card *card)
+static int atm_init(struct solos_card *card, struct device *parent)
{
int i;
@@ -1244,7 +1244,7 @@ static int atm_init(struct solos_card *card)
skb_queue_head_init(&card->tx_queue[i]);
skb_queue_head_init(&card->cli_queue[i]);
- card->atmdev[i] = atm_dev_register("solos-pci", &fpga_ops, -1, NULL);
+ card->atmdev[i] = atm_dev_register("solos-pci", parent, &fpga_ops, -1, NULL);
if (!card->atmdev[i]) {
dev_err(&card->dev->dev, "Could not register ATM device %d\n", i);
atm_remove(card);
diff --git a/drivers/atm/zatm.c b/drivers/atm/zatm.c
index 4e885d2..6249179 100644
--- a/drivers/atm/zatm.c
+++ b/drivers/atm/zatm.c
@@ -1597,7 +1597,7 @@ static int __devinit zatm_init_one(struct pci_dev *pci_dev,
goto out;
}
- dev = atm_dev_register(DEV_LABEL, &ops, -1, NULL);
+ dev = atm_dev_register(DEV_LABEL, &pci_dev->dev, &ops, -1, NULL);
if (!dev)
goto out_free;
diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c
index 05bf5a2..989e16e 100644
--- a/drivers/usb/atm/usbatm.c
+++ b/drivers/usb/atm/usbatm.c
@@ -951,7 +951,9 @@ static int usbatm_atm_init(struct usbatm_data *instance)
* condition: callbacks we register can be executed at once, before we have
* initialized the struct atm_dev. To protect against this, all callbacks
* abort if atm_dev->dev_data is NULL. */
- atm_dev = atm_dev_register(instance->driver_name, &usbatm_atm_devops, -1, NULL);
+ atm_dev = atm_dev_register(instance->driver_name,
+ &instance->usb_intf->dev, &usbatm_atm_devops,
+ -1, NULL);
if (!atm_dev) {
usb_err(instance, "%s: failed to register ATM device!\n", __func__);
return -1;
@@ -966,14 +968,6 @@ static int usbatm_atm_init(struct usbatm_data *instance)
/* temp init ATM device, set to 128kbit */
atm_dev->link_rate = 128 * 1000 / 424;
- ret = sysfs_create_link(&atm_dev->class_dev.kobj,
- &instance->usb_intf->dev.kobj, "device");
- if (ret) {
- atm_err(instance, "%s: sysfs_create_link failed: %d\n",
- __func__, ret);
- goto fail_sysfs;
- }
-
if (instance->driver->atm_start && ((ret = instance->driver->atm_start(instance, atm_dev)) < 0)) {
atm_err(instance, "%s: atm_start failed: %d!\n", __func__, ret);
goto fail;
@@ -992,8 +986,6 @@ static int usbatm_atm_init(struct usbatm_data *instance)
return 0;
fail:
- sysfs_remove_link(&atm_dev->class_dev.kobj, "device");
- fail_sysfs:
instance->atm_dev = NULL;
atm_dev_deregister(atm_dev); /* usbatm_atm_dev_close will eventually be called */
return ret;
@@ -1329,7 +1321,6 @@ void usbatm_usb_disconnect(struct usb_interface *intf)
/* ATM finalize */
if (instance->atm_dev) {
- sysfs_remove_link(&instance->atm_dev->class_dev.kobj, "device");
atm_dev_deregister(instance->atm_dev);
instance->atm_dev = NULL;
}
diff --git a/include/linux/atmdev.h b/include/linux/atmdev.h
index a8e4e83..475f8c4 100644
--- a/include/linux/atmdev.h
+++ b/include/linux/atmdev.h
@@ -427,8 +427,10 @@ extern rwlock_t vcc_sklist_lock;
#define ATM_SKB(skb) (((struct atm_skb_data *) (skb)->cb))
-struct atm_dev *atm_dev_register(const char *type,const struct atmdev_ops *ops,
- int number,unsigned long *flags); /* number == -1: pick first available */
+struct atm_dev *atm_dev_register(const char *type, struct device *parent,
+ const struct atmdev_ops *ops,
+ int number, /* -1 == pick first available */
+ unsigned long *flags);
struct atm_dev *atm_dev_lookup(int number);
void atm_dev_deregister(struct atm_dev *dev);
diff --git a/net/atm/atm_sysfs.c b/net/atm/atm_sysfs.c
index 799c631..f7fa67c 100644
--- a/net/atm/atm_sysfs.c
+++ b/net/atm/atm_sysfs.c
@@ -143,12 +143,13 @@ static struct class atm_class = {
.dev_uevent = atm_uevent,
};
-int atm_register_sysfs(struct atm_dev *adev)
+int atm_register_sysfs(struct atm_dev *adev, struct device *parent)
{
struct device *cdev = &adev->class_dev;
int i, j, err;
cdev->class = &atm_class;
+ cdev->parent = parent;
dev_set_drvdata(cdev, adev);
dev_set_name(cdev, "%s%d", adev->type, adev->number);
diff --git a/net/atm/resources.c b/net/atm/resources.c
index d29e582..23f45ce 100644
--- a/net/atm/resources.c
+++ b/net/atm/resources.c
@@ -74,8 +74,9 @@ struct atm_dev *atm_dev_lookup(int number)
}
EXPORT_SYMBOL(atm_dev_lookup);
-struct atm_dev *atm_dev_register(const char *type, const struct atmdev_ops *ops,
- int number, unsigned long *flags)
+struct atm_dev *atm_dev_register(const char *type, struct device *parent,
+ const struct atmdev_ops *ops, int number,
+ unsigned long *flags)
{
struct atm_dev *dev, *inuse;
@@ -115,7 +116,7 @@ struct atm_dev *atm_dev_register(const char *type, const struct atmdev_ops *ops,
goto out_fail;
}
- if (atm_register_sysfs(dev) < 0) {
+ if (atm_register_sysfs(dev, parent) < 0) {
pr_err("atm_register_sysfs failed for dev %s\n", type);
atm_proc_dev_deregister(dev);
goto out_fail;
diff --git a/net/atm/resources.h b/net/atm/resources.h
index 126fb18..521431e 100644
--- a/net/atm/resources.h
+++ b/net/atm/resources.h
@@ -42,6 +42,6 @@ static inline void atm_proc_dev_deregister(struct atm_dev *dev)
#endif /* CONFIG_PROC_FS */
-int atm_register_sysfs(struct atm_dev *adev);
+int atm_register_sysfs(struct atm_dev *adev, struct device *parent);
void atm_unregister_sysfs(struct atm_dev *adev);
#endif
^ permalink raw reply related
* Re: Behaviour of ETHTOOL_GLINK for an interface that's down
From: Dan Williams @ 2010-12-09 5:47 UTC (permalink / raw)
To: Ben Hutchings; +Cc: netdev, sf-linux-drivers
In-Reply-To: <1291672786.5405.23.camel@bwh-desktop>
On Mon, 2010-12-06 at 21:59 +0000, Ben Hutchings wrote:
> ETHTOOL_GLINK is yet another ethtool operation that has unclear
> semantics that results in differing behaviour when the interface is
> down.
>
> The two reasonable semantics I can see are:
> 1. Report whether the host has a working link, i.e. netif_running() &&
> netif_carrier_on().
> 2. Report whether the port has a working link. For hardware interfaces,
> poll the PHY or firmware unless the port is powered-off. For software
> interfaces, report whether the interface could plausibly pass traffic.
>
> The default implementation (ethtool_op_get_link) uses
> netif_carrier_ok(), implementing the rather unreasonable semantics:
> 3. Report whether the port had a working link when the interface was
> last up.
>
> At least one driver works around this by setting carrier off in its
> ndo_stop() operation.
>
> Here's a small sample of driver behaviours:
>
> bnx2: (1)
> bnx2x: (1) (I think)
> cxgb3: (1) (but also (2) because PHY is powered off)
> e1000e: (2)
> gianfar: (3)
> igb: (2)
> ixgbe: (1)
> niu: (3)
> sfc: (3) (approximately)
> sky2: (3)
> tg3: (3) (but also (1) due to setting carrier off in tg3_close())
>
> DaveM said that Network Manager may require (2), although I don't think
> this is correct. At least the current version brings all managed
> interfaces up whether or not they have link-up already.
NM has used netlink + IFF_RUNNING (not ethtool) for a few years for
actual carrier detection. Ethtool (and MII ioctls) are called as a
"best effort" method of determining that the device actually *has*
carrier detection at all, since if the device has gone to the trouble to
implement either MII or ethtool, it probably also has carrier detection.
But ethtool isn't actually used to determine carrier status in NM. It's
netlink all the way down.
Dan
^ permalink raw reply
* [PATCH] net: Abstract away all dst_entry metrics accesses.
From: David Miller @ 2010-12-09 5:48 UTC (permalink / raw)
To: netdev
Use helper functions to hide all direct accesses, especially writes,
to dst_entry metrics values.
This will allow us to:
1) More easily change how the metrics are stored.
2) Implement COW for metrics.
In particular this will help us put metrics into the inetpeer
cache if that is what we end up doing. We can make the _metrics
member a pointer instead of an array, initially have it point
at the read-only metrics in the FIB, and then on the first set
grab an inetpeer entry and point the _metrics member there.
Signed-off-by: David S. Miller <davem@davemloft.net>
---
include/net/dst.h | 26 +++++++++++++++--
net/bridge/br_device.c | 2 +-
net/bridge/br_netfilter.c | 2 +-
net/decnet/dn_route.c | 13 ++++-----
net/ipv4/ip_gre.c | 2 +-
net/ipv4/route.c | 55 ++++++++++++++++++++-----------------
net/ipv4/tcp_input.c | 22 +++++++++------
net/ipv6/ndisc.c | 5 ++-
net/ipv6/route.c | 66 +++++++++++++++++++++++++-------------------
net/xfrm/xfrm_policy.c | 6 ++--
10 files changed, 118 insertions(+), 81 deletions(-)
diff --git a/include/net/dst.h b/include/net/dst.h
index a5bd726..85dee3a 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -70,7 +70,7 @@ struct dst_entry {
struct dst_ops *ops;
- u32 metrics[RTAX_MAX];
+ u32 _metrics[RTAX_MAX];
#ifdef CONFIG_NET_CLS_ROUTE
__u32 tclassid;
@@ -106,7 +106,27 @@ struct dst_entry {
static inline u32
dst_metric(const struct dst_entry *dst, int metric)
{
- return dst->metrics[metric-1];
+ return dst->_metrics[metric-1];
+}
+
+static inline void dst_metric_set(struct dst_entry *dst, int metric, u32 val)
+{
+ dst->_metrics[metric-1] = val;
+}
+
+static inline void dst_import_metrics(struct dst_entry *dst, const u32 *src_metrics)
+{
+ memcpy(dst->_metrics, src_metrics, RTAX_MAX * sizeof(u32));
+}
+
+static inline void dst_copy_metrics(struct dst_entry *dest, const struct dst_entry *src)
+{
+ dst_import_metrics(dest, src->_metrics);
+}
+
+static inline u32 *dst_metrics_ptr(struct dst_entry *dst)
+{
+ return dst->_metrics;
}
static inline u32
@@ -134,7 +154,7 @@ static inline unsigned long dst_metric_rtt(const struct dst_entry *dst, int metr
static inline void set_dst_metric_rtt(struct dst_entry *dst, int metric,
unsigned long rtt)
{
- dst->metrics[metric-1] = jiffies_to_msecs(rtt);
+ dst_metric_set(dst, metric, jiffies_to_msecs(rtt));
}
static inline u32
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index 17cb0b6..5564435 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -141,7 +141,7 @@ static int br_change_mtu(struct net_device *dev, int new_mtu)
#ifdef CONFIG_BRIDGE_NETFILTER
/* remember the MTU in the rtable for PMTU */
- br->fake_rtable.dst.metrics[RTAX_MTU - 1] = new_mtu;
+ dst_metric_set(&br->fake_rtable.dst, RTAX_MTU, new_mtu);
#endif
return 0;
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index 6e13920..16f5c33 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -124,7 +124,7 @@ void br_netfilter_rtable_init(struct net_bridge *br)
atomic_set(&rt->dst.__refcnt, 1);
rt->dst.dev = br->dev;
rt->dst.path = &rt->dst;
- rt->dst.metrics[RTAX_MTU - 1] = 1500;
+ dst_metric_set(&rt->dst, RTAX_MTU, 1500);
rt->dst.flags = DST_NOXFRM;
rt->dst.ops = &fake_dst_ops;
}
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index 8280e43..e2e9268 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -240,13 +240,13 @@ static void dn_dst_update_pmtu(struct dst_entry *dst, u32 mtu)
if (dst_metric(dst, RTAX_MTU) > mtu && mtu >= min_mtu) {
if (!(dst_metric_locked(dst, RTAX_MTU))) {
- dst->metrics[RTAX_MTU-1] = mtu;
+ dst_metric_set(dst, RTAX_MTU, mtu);
dst_set_expires(dst, dn_rt_mtu_expires);
}
if (!(dst_metric_locked(dst, RTAX_ADVMSS))) {
u32 mss = mtu - DN_MAX_NSP_DATA_HEADER;
if (dst_metric(dst, RTAX_ADVMSS) > mss)
- dst->metrics[RTAX_ADVMSS-1] = mss;
+ dst_metric_set(dst, RTAX_ADVMSS, mss);
}
}
}
@@ -806,8 +806,7 @@ static int dn_rt_set_next_hop(struct dn_route *rt, struct dn_fib_res *res)
if (DN_FIB_RES_GW(*res) &&
DN_FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK)
rt->rt_gateway = DN_FIB_RES_GW(*res);
- memcpy(rt->dst.metrics, fi->fib_metrics,
- sizeof(rt->dst.metrics));
+ dst_import_metrics(&rt->dst, fi->fib_metrics);
}
rt->rt_type = res->type;
@@ -820,11 +819,11 @@ static int dn_rt_set_next_hop(struct dn_route *rt, struct dn_fib_res *res)
if (dst_metric(&rt->dst, RTAX_MTU) == 0 ||
dst_metric(&rt->dst, RTAX_MTU) > rt->dst.dev->mtu)
- rt->dst.metrics[RTAX_MTU-1] = rt->dst.dev->mtu;
+ dst_metric_set(&rt->dst, RTAX_MTU, rt->dst.dev->mtu);
mss = dn_mss_from_pmtu(dev, dst_mtu(&rt->dst));
if (dst_metric(&rt->dst, RTAX_ADVMSS) == 0 ||
dst_metric(&rt->dst, RTAX_ADVMSS) > mss)
- rt->dst.metrics[RTAX_ADVMSS-1] = mss;
+ dst_metric_set(&rt->dst, RTAX_ADVMSS, mss);
return 0;
}
@@ -1502,7 +1501,7 @@ static int dn_rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq,
RTA_PUT(skb, RTA_PREFSRC, 2, &rt->rt_local_src);
if (rt->rt_daddr != rt->rt_gateway)
RTA_PUT(skb, RTA_GATEWAY, 2, &rt->rt_gateway);
- if (rtnetlink_put_metrics(skb, rt->dst.metrics) < 0)
+ if (rtnetlink_put_metrics(skb, dst_metrics_ptr(&rt->dst)) < 0)
goto rtattr_failure;
expires = rt->dst.expires ? rt->dst.expires - jiffies : 0;
if (rtnl_put_cacheinfo(skb, &rt->dst, 0, 0, 0, expires,
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 258c98d..ff4e7a4 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -818,7 +818,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
!ipv4_is_multicast(tunnel->parms.iph.daddr)) ||
rt6->rt6i_dst.plen == 128) {
rt6->rt6i_flags |= RTF_MODIFIED;
- skb_dst(skb)->metrics[RTAX_MTU-1] = mtu;
+ dst_metric_set(skb_dst(skb), RTAX_MTU, mtu);
}
}
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 3843c2d..26ac396 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1686,11 +1686,14 @@ unsigned short ip_rt_frag_needed(struct net *net, struct iphdr *iph,
if (mtu < dst_mtu(&rth->dst)) {
dst_confirm(&rth->dst);
if (mtu < ip_rt_min_pmtu) {
+ u32 lock = dst_metric(&rth->dst,
+ RTAX_LOCK);
mtu = ip_rt_min_pmtu;
- rth->dst.metrics[RTAX_LOCK-1] |=
- (1 << RTAX_MTU);
+ lock |= (1 << RTAX_MTU);
+ dst_metric_set(&rth->dst, RTAX_LOCK,
+ lock);
}
- rth->dst.metrics[RTAX_MTU-1] = mtu;
+ dst_metric_set(&rth->dst, RTAX_MTU, mtu);
dst_set_expires(&rth->dst,
ip_rt_mtu_expires);
}
@@ -1708,10 +1711,11 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu)
if (dst_mtu(dst) > mtu && mtu >= 68 &&
!(dst_metric_locked(dst, RTAX_MTU))) {
if (mtu < ip_rt_min_pmtu) {
+ u32 lock = dst_metric(dst, RTAX_LOCK);
mtu = ip_rt_min_pmtu;
- dst->metrics[RTAX_LOCK-1] |= (1 << RTAX_MTU);
+ dst_metric_set(dst, RTAX_LOCK, lock | (1 << RTAX_MTU));
}
- dst->metrics[RTAX_MTU-1] = mtu;
+ dst_metric_set(dst, RTAX_MTU, mtu);
dst_set_expires(dst, ip_rt_mtu_expires);
call_netevent_notifiers(NETEVENT_PMTU_UPDATE, dst);
}
@@ -1796,36 +1800,37 @@ static void set_class_tag(struct rtable *rt, u32 tag)
static void rt_set_nexthop(struct rtable *rt, struct fib_result *res, u32 itag)
{
+ struct dst_entry *dst = &rt->dst;
struct fib_info *fi = res->fi;
if (fi) {
if (FIB_RES_GW(*res) &&
FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK)
rt->rt_gateway = FIB_RES_GW(*res);
- memcpy(rt->dst.metrics, fi->fib_metrics,
- sizeof(rt->dst.metrics));
+ dst_import_metrics(dst, fi->fib_metrics);
if (fi->fib_mtu == 0) {
- rt->dst.metrics[RTAX_MTU-1] = rt->dst.dev->mtu;
- if (dst_metric_locked(&rt->dst, RTAX_MTU) &&
+ dst_metric_set(dst, RTAX_MTU, dst->dev->mtu);
+ if (dst_metric_locked(dst, RTAX_MTU) &&
rt->rt_gateway != rt->rt_dst &&
- rt->dst.dev->mtu > 576)
- rt->dst.metrics[RTAX_MTU-1] = 576;
+ dst->dev->mtu > 576)
+ dst_metric_set(dst, RTAX_MTU, 576);
}
#ifdef CONFIG_NET_CLS_ROUTE
- rt->dst.tclassid = FIB_RES_NH(*res).nh_tclassid;
+ dst->tclassid = FIB_RES_NH(*res).nh_tclassid;
#endif
} else
- rt->dst.metrics[RTAX_MTU-1]= rt->dst.dev->mtu;
-
- if (dst_metric(&rt->dst, RTAX_HOPLIMIT) == 0)
- rt->dst.metrics[RTAX_HOPLIMIT-1] = sysctl_ip_default_ttl;
- if (dst_mtu(&rt->dst) > IP_MAX_MTU)
- rt->dst.metrics[RTAX_MTU-1] = IP_MAX_MTU;
- if (dst_metric(&rt->dst, RTAX_ADVMSS) == 0)
- rt->dst.metrics[RTAX_ADVMSS-1] = max_t(unsigned int, rt->dst.dev->mtu - 40,
- ip_rt_min_advmss);
- if (dst_metric(&rt->dst, RTAX_ADVMSS) > 65535 - 40)
- rt->dst.metrics[RTAX_ADVMSS-1] = 65535 - 40;
+ dst_metric_set(dst, RTAX_MTU, dst->dev->mtu);
+
+ if (dst_metric(dst, RTAX_HOPLIMIT) == 0)
+ dst_metric_set(dst, RTAX_HOPLIMIT, sysctl_ip_default_ttl);
+ if (dst_mtu(dst) > IP_MAX_MTU)
+ dst_metric_set(dst, RTAX_MTU, IP_MAX_MTU);
+ if (dst_metric(dst, RTAX_ADVMSS) == 0)
+ dst_metric_set(dst, RTAX_ADVMSS,
+ max_t(unsigned int, dst->dev->mtu - 40,
+ ip_rt_min_advmss));
+ if (dst_metric(dst, RTAX_ADVMSS) > 65535 - 40)
+ dst_metric_set(dst, RTAX_ADVMSS, 65535 - 40);
#ifdef CONFIG_NET_CLS_ROUTE
#ifdef CONFIG_IP_MULTIPLE_TABLES
@@ -2720,7 +2725,7 @@ static int ipv4_dst_blackhole(struct net *net, struct rtable **rp, struct flowi
new->__use = 1;
new->input = dst_discard;
new->output = dst_discard;
- memcpy(new->metrics, ort->dst.metrics, RTAX_MAX*sizeof(u32));
+ dst_copy_metrics(new, &ort->dst);
new->dev = ort->dst.dev;
if (new->dev)
@@ -2827,7 +2832,7 @@ static int rt_fill_info(struct net *net,
if (rt->rt_dst != rt->rt_gateway)
NLA_PUT_BE32(skb, RTA_GATEWAY, rt->rt_gateway);
- if (rtnetlink_put_metrics(skb, rt->dst.metrics) < 0)
+ if (rtnetlink_put_metrics(skb, dst_metrics_ptr(&rt->dst)) < 0)
goto nla_put_failure;
if (rt->fl.mark)
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 6d8ab1c..824e8c8 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -734,7 +734,7 @@ void tcp_update_metrics(struct sock *sk)
* Reset our results.
*/
if (!(dst_metric_locked(dst, RTAX_RTT)))
- dst->metrics[RTAX_RTT - 1] = 0;
+ dst_metric_set(dst, RTAX_RTT, 0);
return;
}
@@ -776,34 +776,38 @@ void tcp_update_metrics(struct sock *sk)
if (dst_metric(dst, RTAX_SSTHRESH) &&
!dst_metric_locked(dst, RTAX_SSTHRESH) &&
(tp->snd_cwnd >> 1) > dst_metric(dst, RTAX_SSTHRESH))
- dst->metrics[RTAX_SSTHRESH-1] = tp->snd_cwnd >> 1;
+ dst_metric_set(dst, RTAX_SSTHRESH, tp->snd_cwnd >> 1);
if (!dst_metric_locked(dst, RTAX_CWND) &&
tp->snd_cwnd > dst_metric(dst, RTAX_CWND))
- dst->metrics[RTAX_CWND - 1] = tp->snd_cwnd;
+ dst_metric_set(dst, RTAX_CWND, tp->snd_cwnd);
} else if (tp->snd_cwnd > tp->snd_ssthresh &&
icsk->icsk_ca_state == TCP_CA_Open) {
/* Cong. avoidance phase, cwnd is reliable. */
if (!dst_metric_locked(dst, RTAX_SSTHRESH))
- dst->metrics[RTAX_SSTHRESH-1] =
- max(tp->snd_cwnd >> 1, tp->snd_ssthresh);
+ dst_metric_set(dst, RTAX_SSTHRESH,
+ max(tp->snd_cwnd >> 1, tp->snd_ssthresh));
if (!dst_metric_locked(dst, RTAX_CWND))
- dst->metrics[RTAX_CWND-1] = (dst_metric(dst, RTAX_CWND) + tp->snd_cwnd) >> 1;
+ dst_metric_set(dst, RTAX_CWND,
+ (dst_metric(dst, RTAX_CWND) +
+ tp->snd_cwnd) >> 1);
} else {
/* Else slow start did not finish, cwnd is non-sense,
ssthresh may be also invalid.
*/
if (!dst_metric_locked(dst, RTAX_CWND))
- dst->metrics[RTAX_CWND-1] = (dst_metric(dst, RTAX_CWND) + tp->snd_ssthresh) >> 1;
+ dst_metric_set(dst, RTAX_CWND,
+ (dst_metric(dst, RTAX_CWND) +
+ tp->snd_ssthresh) >> 1);
if (dst_metric(dst, RTAX_SSTHRESH) &&
!dst_metric_locked(dst, RTAX_SSTHRESH) &&
tp->snd_ssthresh > dst_metric(dst, RTAX_SSTHRESH))
- dst->metrics[RTAX_SSTHRESH-1] = tp->snd_ssthresh;
+ dst_metric_set(dst, RTAX_SSTHRESH, tp->snd_ssthresh);
}
if (!dst_metric_locked(dst, RTAX_REORDERING)) {
if (dst_metric(dst, RTAX_REORDERING) < tp->reordering &&
tp->reordering != sysctl_tcp_reordering)
- dst->metrics[RTAX_REORDERING-1] = tp->reordering;
+ dst_metric_set(dst, RTAX_REORDERING, tp->reordering);
}
}
}
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index e18f841..2342545 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -1259,7 +1259,8 @@ static void ndisc_router_discovery(struct sk_buff *skb)
if (ra_msg->icmph.icmp6_hop_limit) {
in6_dev->cnf.hop_limit = ra_msg->icmph.icmp6_hop_limit;
if (rt)
- rt->dst.metrics[RTAX_HOPLIMIT-1] = ra_msg->icmph.icmp6_hop_limit;
+ dst_metric_set(&rt->dst, RTAX_HOPLIMIT,
+ ra_msg->icmph.icmp6_hop_limit);
}
skip_defrtr:
@@ -1377,7 +1378,7 @@ skip_linkparms:
in6_dev->cnf.mtu6 = mtu;
if (rt)
- rt->dst.metrics[RTAX_MTU-1] = mtu;
+ dst_metric_set(&rt->dst, RTAX_MTU, mtu);
rt6_mtu_change(skb->dev, mtu);
}
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 026caef..4aed081 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -129,7 +129,6 @@ static struct rt6_info ip6_null_entry_template = {
.__use = 1,
.obsolete = -1,
.error = -ENETUNREACH,
- .metrics = { [RTAX_HOPLIMIT - 1] = 255, },
.input = ip6_pkt_discard,
.output = ip6_pkt_discard_out,
},
@@ -150,7 +149,6 @@ static struct rt6_info ip6_prohibit_entry_template = {
.__use = 1,
.obsolete = -1,
.error = -EACCES,
- .metrics = { [RTAX_HOPLIMIT - 1] = 255, },
.input = ip6_pkt_prohibit,
.output = ip6_pkt_prohibit_out,
},
@@ -166,7 +164,6 @@ static struct rt6_info ip6_blk_hole_entry_template = {
.__use = 1,
.obsolete = -1,
.error = -EINVAL,
- .metrics = { [RTAX_HOPLIMIT - 1] = 255, },
.input = dst_discard,
.output = dst_discard,
},
@@ -844,7 +841,7 @@ int ip6_dst_blackhole(struct sock *sk, struct dst_entry **dstp, struct flowi *fl
new->input = dst_discard;
new->output = dst_discard;
- memcpy(new->metrics, ort->dst.metrics, RTAX_MAX*sizeof(u32));
+ dst_copy_metrics(new, &ort->dst);
new->dev = ort->dst.dev;
if (new->dev)
dev_hold(new->dev);
@@ -928,10 +925,12 @@ static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu)
if (mtu < dst_mtu(dst) && rt6->rt6i_dst.plen == 128) {
rt6->rt6i_flags |= RTF_MODIFIED;
if (mtu < IPV6_MIN_MTU) {
+ u32 features = dst_metric(dst, RTAX_FEATURES);
mtu = IPV6_MIN_MTU;
- dst->metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG;
+ features |= RTAX_FEATURE_ALLFRAG;
+ dst_metric_set(dst, RTAX_FEATURES, features);
}
- dst->metrics[RTAX_MTU-1] = mtu;
+ dst_metric_set(dst, RTAX_MTU, mtu);
call_netevent_notifiers(NETEVENT_PMTU_UPDATE, dst);
}
}
@@ -989,9 +988,9 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
rt->rt6i_idev = idev;
rt->rt6i_nexthop = neigh;
atomic_set(&rt->dst.__refcnt, 1);
- rt->dst.metrics[RTAX_HOPLIMIT-1] = 255;
- rt->dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(rt->rt6i_dev);
- rt->dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, dst_mtu(&rt->dst));
+ dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 255);
+ dst_metric_set(&rt->dst, RTAX_MTU, ipv6_get_mtu(rt->rt6i_dev));
+ dst_metric_set(&rt->dst, RTAX_ADVMSS, ipv6_advmss(net, dst_mtu(&rt->dst)));
rt->dst.output = ip6_output;
#if 0 /* there's no chance to use these for ndisc */
@@ -1305,17 +1304,17 @@ install_route:
goto out;
}
- rt->dst.metrics[type - 1] = nla_get_u32(nla);
+ dst_metric_set(&rt->dst, type, nla_get_u32(nla));
}
}
}
if (dst_metric(&rt->dst, RTAX_HOPLIMIT) == 0)
- rt->dst.metrics[RTAX_HOPLIMIT-1] = -1;
+ dst_metric_set(&rt->dst, RTAX_HOPLIMIT, -1);
if (!dst_mtu(&rt->dst))
- rt->dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(dev);
+ dst_metric_set(&rt->dst, RTAX_MTU, ipv6_get_mtu(dev));
if (!dst_metric(&rt->dst, RTAX_ADVMSS))
- rt->dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, dst_mtu(&rt->dst));
+ dst_metric_set(&rt->dst, RTAX_ADVMSS, ipv6_advmss(net, dst_mtu(&rt->dst)));
rt->dst.dev = dev;
rt->rt6i_idev = idev;
rt->rt6i_table = table;
@@ -1541,9 +1540,9 @@ void rt6_redirect(struct in6_addr *dest, struct in6_addr *src,
ipv6_addr_copy(&nrt->rt6i_gateway, (struct in6_addr*)neigh->primary_key);
nrt->rt6i_nexthop = neigh_clone(neigh);
/* Reset pmtu, it may be better */
- nrt->dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(neigh->dev);
- nrt->dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dev_net(neigh->dev),
- dst_mtu(&nrt->dst));
+ dst_metric_set(&nrt->dst, RTAX_MTU, ipv6_get_mtu(neigh->dev));
+ dst_metric_set(&nrt->dst, RTAX_ADVMSS, ipv6_advmss(dev_net(neigh->dev),
+ dst_mtu(&nrt->dst)));
if (ip6_ins_rt(nrt))
goto out;
@@ -1602,9 +1601,12 @@ static void rt6_do_pmtu_disc(struct in6_addr *daddr, struct in6_addr *saddr,
would return automatically.
*/
if (rt->rt6i_flags & RTF_CACHE) {
- rt->dst.metrics[RTAX_MTU-1] = pmtu;
- if (allfrag)
- rt->dst.metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG;
+ dst_metric_set(&rt->dst, RTAX_MTU, pmtu);
+ if (allfrag) {
+ u32 features = dst_metric(&rt->dst, RTAX_FEATURES);
+ features |= RTAX_FEATURE_ALLFRAG;
+ dst_metric_set(&rt->dst, RTAX_FEATURES, features);
+ }
dst_set_expires(&rt->dst, net->ipv6.sysctl.ip6_rt_mtu_expires);
rt->rt6i_flags |= RTF_MODIFIED|RTF_EXPIRES;
goto out;
@@ -1621,9 +1623,12 @@ static void rt6_do_pmtu_disc(struct in6_addr *daddr, struct in6_addr *saddr,
nrt = rt6_alloc_clone(rt, daddr);
if (nrt) {
- nrt->dst.metrics[RTAX_MTU-1] = pmtu;
- if (allfrag)
- nrt->dst.metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG;
+ dst_metric_set(&nrt->dst, RTAX_MTU, pmtu);
+ if (allfrag) {
+ u32 features = dst_metric(&nrt->dst, RTAX_FEATURES);
+ features |= RTAX_FEATURE_ALLFRAG;
+ dst_metric_set(&nrt->dst, RTAX_FEATURES, features);
+ }
/* According to RFC 1981, detecting PMTU increase shouldn't be
* happened within 5 mins, the recommended timer is 10 mins.
@@ -1674,7 +1679,7 @@ static struct rt6_info * ip6_rt_copy(struct rt6_info *ort)
rt->dst.input = ort->dst.input;
rt->dst.output = ort->dst.output;
- memcpy(rt->dst.metrics, ort->dst.metrics, RTAX_MAX*sizeof(u32));
+ dst_copy_metrics(&rt->dst, &ort->dst);
rt->dst.error = ort->dst.error;
rt->dst.dev = ort->dst.dev;
if (rt->dst.dev)
@@ -1966,9 +1971,9 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
rt->dst.output = ip6_output;
rt->rt6i_dev = net->loopback_dev;
rt->rt6i_idev = idev;
- rt->dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(rt->rt6i_dev);
- rt->dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, dst_mtu(&rt->dst));
- rt->dst.metrics[RTAX_HOPLIMIT-1] = -1;
+ dst_metric_set(&rt->dst, RTAX_MTU, ipv6_get_mtu(rt->rt6i_dev));
+ dst_metric_set(&rt->dst, RTAX_ADVMSS, ipv6_advmss(net, dst_mtu(&rt->dst)));
+ dst_metric_set(&rt->dst, RTAX_HOPLIMIT, -1);
rt->dst.obsolete = -1;
rt->rt6i_flags = RTF_UP | RTF_NONEXTHOP;
@@ -2068,8 +2073,8 @@ static int rt6_mtu_change_route(struct rt6_info *rt, void *p_arg)
(dst_mtu(&rt->dst) >= arg->mtu ||
(dst_mtu(&rt->dst) < arg->mtu &&
dst_mtu(&rt->dst) == idev->cnf.mtu6))) {
- rt->dst.metrics[RTAX_MTU-1] = arg->mtu;
- rt->dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, arg->mtu);
+ dst_metric_set(&rt->dst, RTAX_MTU, arg->mtu);
+ dst_metric_set(&rt->dst, RTAX_ADVMSS, ipv6_advmss(net, arg->mtu));
}
return 0;
}
@@ -2295,7 +2300,7 @@ static int rt6_fill_node(struct net *net,
NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf);
}
- if (rtnetlink_put_metrics(skb, rt->dst.metrics) < 0)
+ if (rtnetlink_put_metrics(skb, dst_metrics_ptr(&rt->dst)) < 0)
goto nla_put_failure;
if (rt->dst.neighbour)
@@ -2686,6 +2691,7 @@ static int __net_init ip6_route_net_init(struct net *net)
net->ipv6.ip6_null_entry->dst.path =
(struct dst_entry *)net->ipv6.ip6_null_entry;
net->ipv6.ip6_null_entry->dst.ops = &net->ipv6.ip6_dst_ops;
+ dst_metric_set(&net->ipv6.ip6_null_entry->dst, RTAX_HOPLIMIT, 255);
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template,
@@ -2696,6 +2702,7 @@ static int __net_init ip6_route_net_init(struct net *net)
net->ipv6.ip6_prohibit_entry->dst.path =
(struct dst_entry *)net->ipv6.ip6_prohibit_entry;
net->ipv6.ip6_prohibit_entry->dst.ops = &net->ipv6.ip6_dst_ops;
+ dst_metric_set(&net->ipv6.ip6_prohibit_entry->dst, RTAX_HOPLIMIT, 255);
net->ipv6.ip6_blk_hole_entry = kmemdup(&ip6_blk_hole_entry_template,
sizeof(*net->ipv6.ip6_blk_hole_entry),
@@ -2705,6 +2712,7 @@ static int __net_init ip6_route_net_init(struct net *net)
net->ipv6.ip6_blk_hole_entry->dst.path =
(struct dst_entry *)net->ipv6.ip6_blk_hole_entry;
net->ipv6.ip6_blk_hole_entry->dst.ops = &net->ipv6.ip6_dst_ops;
+ dst_metric_set(&net->ipv6.ip6_blk_hole_entry->dst, RTAX_HOPLIMIT, 255);
#endif
net->ipv6.sysctl.flush_delay = 0;
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 044e778..6e50ccd 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1433,7 +1433,7 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
}
xdst->route = dst;
- memcpy(&dst1->metrics, &dst->metrics, sizeof(dst->metrics));
+ dst_copy_metrics(dst1, dst);
if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) {
family = xfrm[i]->props.family;
@@ -2271,7 +2271,7 @@ static void xfrm_init_pmtu(struct dst_entry *dst)
if (pmtu > route_mtu_cached)
pmtu = route_mtu_cached;
- dst->metrics[RTAX_MTU-1] = pmtu;
+ dst_metric_set(dst, RTAX_MTU, pmtu);
} while ((dst = dst->next));
}
@@ -2349,7 +2349,7 @@ static int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *first,
mtu = xfrm_state_mtu(dst->xfrm, mtu);
if (mtu > last->route_mtu_cached)
mtu = last->route_mtu_cached;
- dst->metrics[RTAX_MTU-1] = mtu;
+ dst_metric_set(dst, RTAX_MTU, mtu);
if (last == first)
break;
--
1.7.3.2
^ permalink raw reply related
* Re: Behaviour of ETHTOOL_GLINK for an interface that's down
From: Dan Williams @ 2010-12-09 6:02 UTC (permalink / raw)
To: Ben Hutchings; +Cc: netdev, sf-linux-drivers
In-Reply-To: <1291873629.24551.7.camel@dcbw.foobar.com>
On Wed, 2010-12-08 at 23:47 -0600, Dan Williams wrote:
> On Mon, 2010-12-06 at 21:59 +0000, Ben Hutchings wrote:
> > ETHTOOL_GLINK is yet another ethtool operation that has unclear
> > semantics that results in differing behaviour when the interface is
> > down.
> >
> > The two reasonable semantics I can see are:
> > 1. Report whether the host has a working link, i.e. netif_running() &&
> > netif_carrier_on().
> > 2. Report whether the port has a working link. For hardware interfaces,
> > poll the PHY or firmware unless the port is powered-off. For software
> > interfaces, report whether the interface could plausibly pass traffic.
> >
> > The default implementation (ethtool_op_get_link) uses
> > netif_carrier_ok(), implementing the rather unreasonable semantics:
> > 3. Report whether the port had a working link when the interface was
> > last up.
> >
> > At least one driver works around this by setting carrier off in its
> > ndo_stop() operation.
> >
> > Here's a small sample of driver behaviours:
> >
> > bnx2: (1)
> > bnx2x: (1) (I think)
> > cxgb3: (1) (but also (2) because PHY is powered off)
> > e1000e: (2)
> > gianfar: (3)
> > igb: (2)
> > ixgbe: (1)
> > niu: (3)
> > sfc: (3) (approximately)
> > sky2: (3)
> > tg3: (3) (but also (1) due to setting carrier off in tg3_close())
> >
> > DaveM said that Network Manager may require (2), although I don't think
> > this is correct. At least the current version brings all managed
> > interfaces up whether or not they have link-up already.
>
> NM has used netlink + IFF_RUNNING (not ethtool) for a few years for
> actual carrier detection. Ethtool (and MII ioctls) are called as a
> "best effort" method of determining that the device actually *has*
> carrier detection at all, since if the device has gone to the trouble to
> implement either MII or ethtool, it probably also has carrier detection.
>
> But ethtool isn't actually used to determine carrier status in NM. It's
> netlink all the way down.
And as a follow-on, yes, NM does bring all devices it is allowed to
manager IFF_UP because that's the only way (at this point) that we can
guarantee functional carrier detect from the card. I'd love it if that
weren't the case, and if we could have some indicator that the driver
could do carrier detect while in a lower-power state and !IFF_UP, but we
don't have that yet.
Dan
^ permalink raw reply
* Re: [stable] [STABLE 2.6.32 PATCH] net: release dst entry while cache-hot for GSO case too
From: avagin @ 2010-12-09 6:43 UTC (permalink / raw)
To: Greg KH
Cc: Greg Kroah-Hartman, krkumar2, avagin, eric.dumazet, netdev, mjt,
David Miller, stable
In-Reply-To: <20101208230536.GA8062@kroah.com>
[-- Attachment #1: Type: text/plain, Size: 288 bytes --]
I add the patch in attachments
On 12/09/2010 02:05 AM, Greg KH wrote:
> On Thu, Dec 09, 2010 at 01:47:41AM +0300, avagin@gmail.com wrote:
>> Hi Greg,
>>
>> This patch is acked by David S. Miller. Greg, maybe you can commit it?
>
> What specific patch please?
>
> confused,
>
> greg k-h
[-- Attachment #2: Attached Message --]
[-- Type: message/rfc822, Size: 3214 bytes --]
From: Andrey Vagin <avagin@openvz.org>
To: stable@kernel.org
Cc: netdev@vger.kernel.org, Krishna Kumar <krkumar2@in.ibm.com>, "David S. Miller" <davem@davemloft.net>, Andrey Vagin <avagin@openvz.org>
Subject: [STABLE 2.6.32 PATCH] net: release dst entry while cache-hot for GSO case too
Date: Mon, 11 Oct 2010 19:20:13 +0400
Message-ID: <1286810413-30238-1-git-send-email-avagin@openvz.org>
From: Krishna Kumar <krkumar2@in.ibm.com>
commit 068a2de57ddf4f472e32e7af868613c574ad1d88 upstream.
Non-GSO code drops dst entry for performance reasons, but
the same is missing for GSO code. Drop dst while cache-hot
for GSO case too.
Note: Without this patch the kernel may oops if used bridged veth
devices. A bridge set skb->dst = fake_dst_ops, veth transfers this skb
to netif_receive_skb...ip_rcv_finish and it calls dst_input(skb), but
fake_dst_ops->input = NULL -> Oops
Signed-off-by: Krishna Kumar <krkumar2@in.ibm.com>
Acked-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Andrey Vagin <avagin@openvz.org>
---
net/core/dev.c | 8 ++++++++
1 files changed, 8 insertions(+), 0 deletions(-)
diff --git a/net/core/dev.c b/net/core/dev.c
index 915d0ae..c325ab6 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1747,6 +1747,14 @@ gso:
skb->next = nskb->next;
nskb->next = NULL;
+
+ /*
+ * If device doesnt need nskb->dst, release it right now while
+ * its hot in this cpu cache
+ */
+ if (dev->priv_flags & IFF_XMIT_DST_RELEASE)
+ skb_dst_drop(nskb);
+
rc = ops->ndo_start_xmit(nskb, dev);
if (unlikely(rc != NETDEV_TX_OK)) {
nskb->next = skb->next;
--
1.7.2.1
^ permalink raw reply related
* Re: [PATCH] net: Abstract away all dst_entry metrics accesses.
From: Eric Dumazet @ 2010-12-09 7:18 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <20101208.214834.226775385.davem@davemloft.net>
Le mercredi 08 décembre 2010 à 21:48 -0800, David Miller a écrit :
> Use helper functions to hide all direct accesses, especially writes,
> to dst_entry metrics values.
>
> This will allow us to:
>
> 1) More easily change how the metrics are stored.
>
> 2) Implement COW for metrics.
>
> In particular this will help us put metrics into the inetpeer
> cache if that is what we end up doing. We can make the _metrics
> member a pointer instead of an array, initially have it point
> at the read-only metrics in the FIB, and then on the first set
> grab an inetpeer entry and point the _metrics member there.
>
> Signed-off-by: David S. Miller <davem@davemloft.net>
Very exciting, thanks David !
Acked-by: Eric Dumazet <eric.dumazet@gmail.com>
^ permalink raw reply
* Re: [v3 PATCH 1/2] bonding: sync netpoll code with bridge
From: Cong Wang @ 2010-12-09 7:33 UTC (permalink / raw)
To: Neil Horman
Cc: linux-kernel, Jiri Pirko, netdev, David S. Miller,
Eric W. Biederman, Herbert Xu, bonding-devel, Jay Vosburgh,
Stephen Hemminger
In-Reply-To: <20101208135746.GD11454@hmsreliant.think-freely.org>
On 12/08/10 21:57, Neil Horman wrote:
> On Wed, Dec 08, 2010 at 02:52:08AM -0500, Amerigo Wang wrote:
>> - bond_for_each_slave(bond, slave, i) {
>> - if ((slave->dev->priv_flags& IFF_DISABLE_NETPOLL) ||
>> - !slave->dev->netdev_ops->ndo_poll_controller)
>> - ret = false;
>> + np = kmalloc(sizeof(*np), GFP_KERNEL);
>> + err = -ENOMEM;
>> + if (!np)
>> + goto out;
>> +
>> + np->dev = slave->dev;
>> + err = __netpoll_setup(np);
> Setting up our own netpoll instance on each slave worries me a bit. The
> implication here is that, by doing so, some frames will get entirely processed
> by the slave. Most notably arp frames. That means anything that gets queued up
> to the arp_tx queue in __netpoll_rx will get processed during that poll event,
> and responded to with the mac of the slave device, rather than with the mac of
> the bond device, which isn't always what you want. I think if you go with this
> route, you'll need to add code to netpoll_poll_dev, right before the call to
> service_arp_queue, to check if IFF_SLAVE is set in priv_flags, and move the list
> to the master device, or some such.
Good point! Will fix it.
>
> It also seems like you'll want to zero out the other fields in the netpoll
> structure. Leaving garbage in them will be bad. Most notably here I'm looking
> at the rx_hook field. If its non-null we're going to add a bogus pointer to the
> rx_np list and call off into space at some point.
>
Ouch! I remember I really used kzalloc() here, don't know
why kmalloc() gets into the final patch. Odd, I need to double check
the patch. :-/
<...>
>> +static void __bond_netpoll_cleanup(struct bonding *bond)
>> +{
>> struct slave *slave;
>> int i;
>>
>> - bond_for_each_slave(bond, slave, i) {
>> - if (slave->dev&& IS_UP(slave->dev))
>> - netpoll_poll_dev(slave->dev);
>> - }
>> + bond_for_each_slave(bond, slave, i)
>> + if (slave->dev)
> Why are you checking slave->dev here? If the dev pointer has been set to NULL
> here it would seem we're not holding on to dev long enough. If we enabled
> netpoll with a dev pointer and lost it somewhere along the way, we're going to
> leak that struct netpoll memory that we allocated.
>
Hmm, seems you are right, read_lock should guarantee every slave on the list
has the right ->dev... But I think I should keep that IS_UP() checking...
<...>
>>
>> /* close slave before restoring its mac address */
>> dev_close(slave_dev);
>> @@ -2061,6 +2098,7 @@ static int bond_release_and_destroy(struct net_device *bond_dev,
>>
>> ret = bond_release(bond_dev, slave_dev);
>> if ((ret == 0)&& (bond->slave_cnt == 0)) {
>> + bond_dev->priv_flags |= IFF_DISABLE_NETPOLL;
> Why are you setting IFF_DISABLE_NETPOLL here? That seems unnecessecary
>
It gets removed in patch 2/2. :)
Thanks for review!
^ permalink raw reply
* Re: [v3 PATCH 1/2] bonding: sync netpoll code with bridge
From: Cong Wang @ 2010-12-09 7:40 UTC (permalink / raw)
To: Neil Horman
Cc: linux-kernel, Jiri Pirko, netdev, David S. Miller,
Eric W. Biederman, Herbert Xu, bonding-devel, Jay Vosburgh,
Stephen Hemminger
In-Reply-To: <4D008643.5040500@redhat.com>
On 12/09/10 15:33, Cong Wang wrote:
>>>
>>> /* close slave before restoring its mac address */
>>> dev_close(slave_dev);
>>> @@ -2061,6 +2098,7 @@ static int bond_release_and_destroy(struct
>>> net_device *bond_dev,
>>>
>>> ret = bond_release(bond_dev, slave_dev);
>>> if ((ret == 0)&& (bond->slave_cnt == 0)) {
>>> + bond_dev->priv_flags |= IFF_DISABLE_NETPOLL;
>> Why are you setting IFF_DISABLE_NETPOLL here? That seems unnecessecary
>>
>
> It gets removed in patch 2/2. :)
Oops! I misread IFF_DISABLE_NETPOLL as IFF_IN_NETPOLL...
I think there is a small window between bond_release() and unregister_netdevice(),
setting this could prevent netpoll is setup again on this bond?
^ permalink raw reply
* Does any person or organize enage in optimizing the tcp protocol stack ?
From: tingwei liu @ 2010-12-09 8:58 UTC (permalink / raw)
To: netdev
Does any person or organize enage in optimizing the tcp protocol stack ?
Thanks for any response.
^ permalink raw reply
* [PATCH] phy: add the IC+ IP1001 driver
From: Peppe CAVALLARO @ 2010-12-09 9:05 UTC (permalink / raw)
To: netdev@vger.kernel.org; +Cc: Peppe CAVALLARO
This patch adds the IC+ IP1001 (Gigabit Ethernet Transceiver) driver.
I've had to add an additional delay (2ns) to adjust RX clock phase at
GMII/ RGMII interface (according to the PHY data-sheet). This helps to
have the RGMII working on some ST platforms.
Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
drivers/net/phy/Kconfig | 2 +-
drivers/net/phy/icplus.c | 59 ++++++++++++++++++++++++++++++++++++++++++----
2 files changed, 55 insertions(+), 6 deletions(-)
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index cb3d13e..35fda5a 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -64,7 +64,7 @@ config BCM63XX_PHY
config ICPLUS_PHY
tristate "Drivers for ICPlus PHYs"
---help---
- Currently supports the IP175C PHY.
+ Currently supports the IP175C and IP1001 PHYs.
config REALTEK_PHY
tristate "Drivers for Realtek PHYs"
diff --git a/drivers/net/phy/icplus.c b/drivers/net/phy/icplus.c
index c1d2d25..9a09e24 100644
--- a/drivers/net/phy/icplus.c
+++ b/drivers/net/phy/icplus.c
@@ -30,7 +30,7 @@
#include <asm/irq.h>
#include <asm/uaccess.h>
-MODULE_DESCRIPTION("ICPlus IP175C PHY driver");
+MODULE_DESCRIPTION("ICPlus IP175C/IC1001 PHY drivers");
MODULE_AUTHOR("Michael Barkowski");
MODULE_LICENSE("GPL");
@@ -89,6 +89,33 @@ static int ip175c_config_init(struct phy_device *phydev)
return 0;
}
+static int ip1001_config_init(struct phy_device *phydev)
+{
+ int err, value;
+
+ /* Software Reset PHY */
+ value = phy_read(phydev, MII_BMCR);
+ value |= BMCR_RESET;
+ err = phy_write(phydev, MII_BMCR, value);
+ if (err < 0)
+ return err;
+
+ do {
+ value = phy_read(phydev, MII_BMCR);
+ } while (value & BMCR_RESET);
+
+ /* Additional delay (2ns) used to adjust RX clock phase
+ * at GMII/ RGMII interface */
+ value = phy_read(phydev, 16);
+ value |= 0x3;
+
+ err = phy_write(phydev, 16, value);
+ if (err < 0)
+ return err;
+
+ return err;
+}
+
static int ip175c_read_status(struct phy_device *phydev)
{
if (phydev->addr == 4) /* WAN port */
@@ -121,21 +148,43 @@ static struct phy_driver ip175c_driver = {
.driver = { .owner = THIS_MODULE,},
};
-static int __init ip175c_init(void)
+static struct phy_driver ip1001_driver = {
+ .phy_id = 0x02430d90,
+ .name = "ICPlus IP1001",
+ .phy_id_mask = 0x0ffffff0,
+ .features = PHY_GBIT_FEATURES | SUPPORTED_Pause |
+ SUPPORTED_Asym_Pause,
+ .config_init = &ip1001_config_init,
+ .config_aneg = &genphy_config_aneg,
+ .read_status = &genphy_read_status,
+ .suspend = genphy_suspend,
+ .resume = genphy_resume,
+ .driver = { .owner = THIS_MODULE,},
+};
+
+static int __init icplus_init(void)
{
+ int ret = 0;
+
+ ret = phy_driver_register(&ip1001_driver);
+ if (ret < 0)
+ return -ENODEV;
+
return phy_driver_register(&ip175c_driver);
}
-static void __exit ip175c_exit(void)
+static void __exit icplus_exit(void)
{
+ phy_driver_unregister(&ip1001_driver);
phy_driver_unregister(&ip175c_driver);
}
-module_init(ip175c_init);
-module_exit(ip175c_exit);
+module_init(icplus_init);
+module_exit(icplus_exit);
static struct mdio_device_id __maybe_unused icplus_tbl[] = {
{ 0x02430d80, 0x0ffffff0 },
+ { 0x02430d90, 0x0ffffff0 },
{ }
};
--
1.5.5.6
^ permalink raw reply related
* [PATCH 1/2] via-velocity: set sleep speed to 10Mbps for powersaving.
From: Francois Romieu @ 2010-12-09 9:26 UTC (permalink / raw)
To: David Miller; +Cc: netdev, DavidLv, ShirleyHu, AndersMa
Signed-off-by: David Lv <DavidLv@viatech.com.cn>
Acked-by: Francois Romieu <romieu@fr.zoreil.com>
---
drivers/net/via-velocity.c | 67 ++++++++++++++++++++++++++++++++------------
drivers/net/via-velocity.h | 3 ++
2 files changed, 52 insertions(+), 18 deletions(-)
diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c
index cab96ad..95accb9 100644
--- a/drivers/net/via-velocity.c
+++ b/drivers/net/via-velocity.c
@@ -334,6 +334,15 @@ VELOCITY_PARAM(speed_duplex, "Setting the speed and duplex mode");
*/
VELOCITY_PARAM(ValPktLen, "Receiving or Drop invalid 802.3 frame");
+/* sleep_speed_10M[] is used for setting wol speed forced 10M
+ 0: Disable (default)
+ 1: Enable
+*/
+#define SLEEP_SPEED_DEF 0
+#define SLEEP_SPEED_DISABLE 0
+#define SLEEP_SPEED_ENABLE 1
+VELOCITY_PARAM(sleep_speed_10M, "Sleep Speed Forced 10M");
+
#define WOL_OPT_DEF 0
#define WOL_OPT_MIN 0
#define WOL_OPT_MAX 7
@@ -487,6 +496,8 @@ static void __devinit velocity_get_options(struct velocity_opt *opts, int index,
velocity_set_bool_opt(&opts->flags, IP_byte_align[index], IP_ALIG_DEF, VELOCITY_FLAGS_IP_ALIGN, "IP_byte_align", devname);
velocity_set_bool_opt(&opts->flags, ValPktLen[index], VAL_PKT_LEN_DEF, VELOCITY_FLAGS_VAL_PKT_LEN, "ValPktLen", devname);
velocity_set_int_opt((int *) &opts->spd_dpx, speed_duplex[index], MED_LNK_MIN, MED_LNK_MAX, MED_LNK_DEF, "Media link mode", devname);
+ velocity_set_int_opt((int *) &opts->sleep_speed_10m, sleep_speed_10M[index],
+ SLEEP_SPEED_DISABLE, SLEEP_SPEED_ENABLE, SLEEP_SPEED_DEF, "Sleep Speed Forced 10M", devname);
velocity_set_int_opt((int *) &opts->wol_opts, wol_opts[index], WOL_OPT_MIN, WOL_OPT_MAX, WOL_OPT_DEF, "Wake On Lan options", devname);
opts->numrx = (opts->numrx & ~3);
}
@@ -2513,9 +2524,6 @@ static int velocity_close(struct net_device *dev)
if (dev->irq != 0)
free_irq(dev->irq, dev);
- /* Power down the chip */
- pci_set_power_state(vptr->pdev, PCI_D3hot);
-
velocity_free_rings(vptr);
vptr->flags &= (~VELOCITY_FLAGS_OPENED);
@@ -2925,6 +2933,9 @@ static int velocity_set_wol(struct velocity_info *vptr)
struct mac_regs __iomem *regs = vptr->mac_regs;
static u8 buf[256];
int i;
+ u8 CHIPGCR;
+ u16 ANAR;
+ u8 GCR;
static u32 mask_pattern[2][4] = {
{0x00203000, 0x000003C0, 0x00000000, 0x0000000}, /* ARP */
@@ -2968,23 +2979,46 @@ static int velocity_set_wol(struct velocity_info *vptr)
writew(0x0FFF, ®s->WOLSRClr);
- if (vptr->mii_status & VELOCITY_AUTONEG_ENABLE) {
- if (PHYID_GET_PHY_ID(vptr->phy_id) == PHYID_CICADA_CS8201)
- MII_REG_BITS_ON(AUXCR_MDPPS, MII_NCONFIG, vptr->mac_regs);
+ if ((VELOCITY_SLEEP_SPEED_10M == vptr->options.sleep_speed_10m) &&
+ !(vptr->mii_status & (VELOCITY_SPEED_10 | VELOCITY_DUPLEX_FULL))) {
+ // set force MAC mode bit */
+ BYTE_REG_BITS_ON(CHIPGCR_FCMODE, ®s->CHIPGCR);
- MII_REG_BITS_OFF(ADVERTISE_1000FULL | ADVERTISE_1000HALF, MII_CTRL1000, vptr->mac_regs);
- }
+ CHIPGCR = readb(®s->CHIPGCR);
+ CHIPGCR &= ~CHIPGCR_FCGMII;
+ CHIPGCR |= CHIPGCR_FCFDX;
+ writeb(CHIPGCR, ®s->CHIPGCR);
+ if (vptr->rev_id < REV_ID_VT3216_A0)
+ BYTE_REG_BITS_OFF(TCR_TB2BDIS, ®s->TCR);
+
+ velocity_mii_read(vptr->mac_regs, MII_ADVERTISE, &ANAR);
+ ANAR &= ~(ADVERTISE_100HALF | ADVERTISE_100FULL | ADVERTISE_10HALF);
+ ANAR |= ADVERTISE_10FULL;
+ velocity_mii_write(vptr->mac_regs, MII_ADVERTISE, ANAR);
+
+ MII_REG_BITS_OFF(ADVERTISE_1000FULL | ADVERTISE_1000HALF,
+ MII_CTRL1000, vptr->mac_regs);
- if (vptr->mii_status & VELOCITY_SPEED_1000)
MII_REG_BITS_ON(BMCR_ANRESTART, MII_BMCR, vptr->mac_regs);
- BYTE_REG_BITS_ON(CHIPGCR_FCMODE, ®s->CHIPGCR);
+ } else {
+ if (vptr->mii_status & VELOCITY_AUTONEG_ENABLE) {
+ if (PHYID_GET_PHY_ID(vptr->phy_id) == PHYID_CICADA_CS8201)
+ MII_REG_BITS_ON(AUXCR_MDPPS, MII_NCONFIG, vptr->mac_regs);
- {
- u8 GCR;
- GCR = readb(®s->CHIPGCR);
- GCR = (GCR & ~CHIPGCR_FCGMII) | CHIPGCR_FCFDX;
- writeb(GCR, ®s->CHIPGCR);
+ MII_REG_BITS_OFF(ADVERTISE_1000FULL | ADVERTISE_1000HALF, MII_CTRL1000, vptr->mac_regs);
+ }
+
+ if (vptr->mii_status & VELOCITY_SPEED_1000)
+ MII_REG_BITS_ON(BMCR_ANRESTART, MII_BMCR, vptr->mac_regs);
+
+ BYTE_REG_BITS_ON(CHIPGCR_FCMODE, ®s->CHIPGCR);
+
+ {
+ GCR = readb(®s->CHIPGCR);
+ GCR = (GCR & ~CHIPGCR_FCGMII) | CHIPGCR_FCFDX;
+ writeb(GCR, ®s->CHIPGCR);
+ }
}
BYTE_REG_BITS_OFF(ISR_PWEI, ®s->ISR);
@@ -3029,9 +3063,6 @@ static int velocity_suspend(struct pci_dev *pdev, pm_message_t state)
struct velocity_info *vptr = netdev_priv(dev);
unsigned long flags;
- if (!netif_running(vptr->dev))
- return 0;
-
netif_device_detach(vptr->dev);
spin_lock_irqsave(&vptr->lock, flags);
diff --git a/drivers/net/via-velocity.h b/drivers/net/via-velocity.h
index aa2e69b..b5316ff 100644
--- a/drivers/net/via-velocity.h
+++ b/drivers/net/via-velocity.h
@@ -1358,6 +1358,8 @@ enum velocity_msg_level {
#define VELOCITY_FLAGS_FLOW_CTRL 0x01000000UL
+#define VELOCITY_SLEEP_SPEED_10M 1
+
/*
* Flags for driver status
*/
@@ -1426,6 +1428,7 @@ struct velocity_opt {
int txqueue_timer;
int tx_intsup;
int rx_intsup;
+ int sleep_speed_10m;
u32 flags;
};
--
1.7.3.2
^ permalink raw reply related
* [PATCH 2/2] via-velocity: fix the WOL bug on 1000M full duplex forced mode
From: Francois Romieu @ 2010-12-09 9:27 UTC (permalink / raw)
To: David Miller; +Cc: netdev, DavidLv, ShirleyHu, AndersMa
The VIA velocity card can't be waken up by WOL tool on 1000M full
duplex forced mode. This patch fixes the bug.
Signed-off-by: David Lv <DavidLv@viatech.com.cn>
Acked-by: Francois Romieu <romieu@fr.zoreil.com>
---
drivers/net/via-velocity.c | 18 ++++++++++--------
1 files changed, 10 insertions(+), 8 deletions(-)
diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c
index 95accb9..052b344 100644
--- a/drivers/net/via-velocity.c
+++ b/drivers/net/via-velocity.c
@@ -3001,16 +3001,18 @@ static int velocity_set_wol(struct velocity_info *vptr)
MII_REG_BITS_ON(BMCR_ANRESTART, MII_BMCR, vptr->mac_regs);
- } else {
- if (vptr->mii_status & VELOCITY_AUTONEG_ENABLE) {
- if (PHYID_GET_PHY_ID(vptr->phy_id) == PHYID_CICADA_CS8201)
- MII_REG_BITS_ON(AUXCR_MDPPS, MII_NCONFIG, vptr->mac_regs);
+ } else if (SPD_DPX_1000_FULL != vptr->options.spd_dpx) {
+ if (SPD_DPX_AUTO == vptr->options.spd_dpx) {
+ if (vptr->mii_status & VELOCITY_AUTONEG_ENABLE) {
+ if (PHYID_GET_PHY_ID(vptr->phy_id) == PHYID_CICADA_CS8201)
+ MII_REG_BITS_ON(AUXCR_MDPPS, MII_NCONFIG, vptr->mac_regs);
- MII_REG_BITS_OFF(ADVERTISE_1000FULL | ADVERTISE_1000HALF, MII_CTRL1000, vptr->mac_regs);
- }
+ MII_REG_BITS_OFF(ADVERTISE_1000FULL | ADVERTISE_1000HALF, MII_CTRL1000, vptr->mac_regs);
+ }
- if (vptr->mii_status & VELOCITY_SPEED_1000)
- MII_REG_BITS_ON(BMCR_ANRESTART, MII_BMCR, vptr->mac_regs);
+ if (vptr->mii_status & VELOCITY_SPEED_1000)
+ MII_REG_BITS_ON(BMCR_ANRESTART, MII_BMCR, vptr->mac_regs);
+ }
BYTE_REG_BITS_ON(CHIPGCR_FCMODE, ®s->CHIPGCR);
--
1.7.3.2
^ permalink raw reply related
* Re: [PATCH, post-2.6.36 regression fix] r8169: Fix runtime power management
From: Francois Romieu @ 2010-12-09 9:28 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: David Miller, Matthew Garrett, netdev, LKML,
Linux-pm mailing list
In-Reply-To: <201012090232.14375.rjw@sisk.pl>
Rafael J. Wysocki <rjw@sisk.pl> :
[...]
> I noticed that one of the post-2.6.36 patches broke runtime PM of the
> r8169 on my MSI Wind test machine in such a way that the link was not
> brought up after reconnecting the network cable.
>
> In the process of debugging the issue I realized that we only should
> invoke the runtime PM functions in rtl8169_check_link_status() when
> link change is reported and if we do so, the problem goes away.
> Moreover, this allows rtl8169_runtime_idle() to be simplified quite
> a bit.
>
> Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Francois Romieu <romieu@fr.zoreil.com>
--
Ueimor
^ permalink raw reply
* Re: Does any person or organize enage in optimizing the tcp protocol stack ?
From: Eric Dumazet @ 2010-12-09 9:45 UTC (permalink / raw)
To: tingwei liu; +Cc: netdev
In-Reply-To: <AANLkTi=YGHSG_BWoTyyDJLSKhgWAp8OVz7f01DGbgESe@mail.gmail.com>
Le jeudi 09 décembre 2010 à 16:58 +0800, tingwei liu a écrit :
> Does any person or organize enage in optimizing the tcp protocol stack ?
>
Basically everybody reading this list is involved into optimizing
things, tcp stack for example.
^ permalink raw reply
* [PATCH] netfilter: don't need to initialize instance_table
From: Changli Gao @ 2010-12-09 10:10 UTC (permalink / raw)
To: Patrick McHardy; +Cc: David S. Miller, netfilter-devel, netdev, Changli Gao
Since instance_table is a static array, and has been zeroed already, we
don't need to take CPU cycles to initialize it.
Signed-off-by: Changli Gao <xiaosuo@gmail.com>
---
net/netfilter/nfnetlink_queue.c | 3 ---
1 file changed, 3 deletions(-)
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index 68e67d1..9c80d6f 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -893,9 +893,6 @@ static int __init nfnetlink_queue_init(void)
{
int i, status = -ENOMEM;
- for (i = 0; i < INSTANCE_BUCKETS; i++)
- INIT_HLIST_HEAD(&instance_table[i]);
-
netlink_register_notifier(&nfqnl_rtnl_notifier);
status = nfnetlink_subsys_register(&nfqnl_subsys);
if (status < 0) {
^ permalink raw reply related
* Re: (Lack of) specification for RX n-tuple filtering
From: Vladislav Zolotarov @ 2010-12-09 10:31 UTC (permalink / raw)
To: Ben Hutchings
Cc: David Miller, dm@chelsio.com, peter.p.waskiewicz.jr@intel.com,
netdev@vger.kernel.org
In-Reply-To: <1291829364.2560.24.camel@bwh-desktop>
> > It's not the same, this whole ordering thing you expect in netfilter
> > land is simply not present in these hardware implementations.
> >
> > The hardware does a parallel TCAM match lookup, and whatever matches
> > is used.
>
> I think the match with the lowest index wins, which is why it's possible
> to specify the rule's index (location) with ETHTOOL_SRXCLSRLINS and why
> Peter defined new commands without that for use with the ixgbe driver.
>
Ben, practically, with the current ethtool userspace implementation it
seems like there is no way to specify the CAM index of the rule in the
n-tuple interface, is it? So, the decision on the index is up to the
vendor thus creating an uncertainty space.
And I guess it's exactly what Dimitris meant talking about the index -
he said "a rule index", u say "a CAM index" while generally we are
talking about the same thing. U r referring the ETHTOOL_SRXCLSRLINS but
it has no user space interface yet and it's unclear when it will, while
n-tuple is already there. We can't remove the existing user space
interfaces - I agree. Then let's not adding the interfaces interfering
with the existing ones. This immediately implies that
ETHTOOL_SRXCLSRLINS shell never see light in a userland as a separate
interface and n-tuple user interface should be properly extended to
implement the missing ETHTOOL_SRXCLSRLINS functionality.
Pls., comment.
thanks,
vlad
^ permalink raw reply
* Re: [PATCH 6/7] e1000e: cleanup: swap arguments to avoid checkpatch errors
From: Florian Mickler @ 2010-12-09 10:34 UTC (permalink / raw)
To: Ben Hutchings
Cc: Asbjoern Sloth Toennesen, e1000-devel, netdev, Jeff Kirsher,
linux-kernel, Andrew Morton
In-Reply-To: <1291865548.19763.1.camel@localhost>
On Thu, 09 Dec 2010 03:32:28 +0000
Ben Hutchings <bhutchings@solarflare.com> wrote:
> On Thu, 2010-12-09 at 02:40 +0000, Asbjoern Sloth Toennesen wrote:
> > Swap argument order in order to avoid checkpatch treating it as an
> > unary operation, instead of an binary one, and obtain consistency
> > with the 3 other similar assignments in netdev.c (tdlen & rdlen).
> >
> > This patch fixes 3 checkpatch errors.
>
> You have got to be kidding. If the checkpatch warning offends you, fix
> the bug in checkpatch instead of changing perfectly good code.
>
> Ben.
That bug is fixed already:
https://patchwork.kernel.org/patch/299172/
Andrew picked it up.
Regards,
Flo
^ permalink raw reply
* Adding Support for SG,GSO,GRO
From: Govindarajan, Sriramakrishnan @ 2010-12-09 10:33 UTC (permalink / raw)
To: netdev@vger.kernel.org
Hi
We have a NAPI compliant driver(net/drivers/davinci_emac.c), that does well at 10/100Mbps loads. Now the same controller/driver is used for 1000Mbps
mode as well, where the CPU gets saturated easily
Internally the module supports scatter gather DMA(which is currently not
exercised) but there is no HW checksum support.
To specifically implement GRO, GSO support would it be sufficient to add
SG support to the driver? Are there other means of increasing the throughput
and decreasing the CPU loading?
Any pointers to reference implementation for adding SG/GRO/GSO support will be helpful.
Regards
Sriram
^ permalink raw reply
* Re: ctnetlink loop
From: Pablo Neira Ayuso @ 2010-12-09 10:39 UTC (permalink / raw)
To: David Miller, netfilter-devel, netdev
In-Reply-To: <20101208203121.GB23668@mail.eitzenberger.org>
On 08/12/10 21:31, Holger Eitzenberger wrote:
> Hi,
>
>> Holger, this replay -EAGAIN loop in nfnetlink processing was added by
>> Pablo to handle module loading properly, I think. So it might not be
>> safe to just unilaterally remove it.
>
> thanks for your reply!
>
> Pablo, do we really need the replay loop really?
Yes, we need it for the on-demand module loading.
> I now have several
> boxes with problems due to this replay. 'perf report' always gives me
> something like:
>
> 18.88% ulogd [kernel]
> [k] __nla_put
> 10.73% ulogd [kernel]
> [k] nla_parse
> 8.72% ulogd [kernel]
> [k] __nla_reserve
> 6.64% ulogd [kernel]
> [k] nla_put
> 5.14% ulogd [kernel]
> [k] validate_nla
> 5.03% ulogd [kernel]
> [k] pskb_expand_head
> 4.92% ulogd [kernel]
> [k] ctnetlink_fill_info [nf_conntrack_netlink]
> 3.07% ulogd [kernel]
> [k] skb_put
> 3.03% ulogd [kernel]
> [k] ctnetlink_dump_counters [nf_conntrack
>
> And 'strace' shows me that ulogd is stuck in its 'select' call.
Sorry, I missed your previous emails. Why do you think that this related
to -EAGAIN in nfnetlink?
^ permalink raw reply
* Re: [PATCH v2 0/3] bonding: add the debugfs interface to see RLB hash table
From: Taku Izumi @ 2010-12-09 10:43 UTC (permalink / raw)
To: Jay Vosburgh; +Cc: netdev@vger.kernel.org, eric.dumazet, shemminger
In-Reply-To: <3778.1291840382@death>
Hi Jay,
> After applying your patches to net-next-2.6, I'm seeing the
> following crash when executing "rmmod bonding":
>
> BUG: unable to handle kernel paging request at 6b6b6b9f
> IP: [<c0201f11>] debugfs_remove_recursive+0x1e/0x11a
> *pde = 00000000
> Oops: 0000 [#1] PREEMPT SMP
> last sysfs file: /sys/devices/virtual/net/bond0/flags
> Modules linked in: bonding(-) ipv6 mperf microcode loop tg3 e1000 libphy sworks_agp agpgart edd ext3 mbcache jbd pata_serverworks mptspi mptscsih mptbase [last unloaded: speedstep_lib]
>
> Pid: 5237, comm: rmmod Not tainted 2.6.37-rc1-cur+ #11 /eserver xSeries 335 -[8676GBX]-
> EIP: 0060:[<c0201f11>] EFLAGS: 00010202 CPU: 2
> EIP is at debugfs_remove_recursive+0x1e/0x11a
> EAX: 6b6b6b6b EBX: f4d99480 ECX: 00000000 EDX: f3d5a5d4
> ESI: f4d99950 EDI: f2d445b8 EBP: f4d03eb8 ESP: f4d03ea8
> DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068
> Process rmmod (pid: 5237, ti=f4d02000 task=f3d5a240 task.ti=f4d02000)
> Stack:
> f4d03ec0 f4d99480 f4d99950 f4d99000 f4d03ec0 f801dc05 f4d03ef4 f8015c5b
> c0156ab6 f4d03ed8 c0134ff0 f4d9949c f4d03ee4 c037ec67 f4d99150 f4d03ef4
> f4d99000 f4d03f20 f4d99000 f4d03f08 c030eafe f4d03f20 c0ce4140 f80233a4
> Call Trace:
> [<f801dc05>] ? bond_debug_unregister+0xe/0x10 [bonding]
> [<f8015c5b>] ? bond_uninit+0x324/0x36d [bonding]
> [<c0156ab6>] ? trace_hardirqs_on+0xb/0xd
> [<c0134ff0>] ? local_bh_enable_ip+0x97/0xae
> [<c037ec67>] ? _raw_spin_unlock_bh+0x2f/0x32
> [<c030eafe>] ? rollback_registered_many+0x187/0x1fb
> [<c030eb81>] ? unregister_netdevice_many+0xf/0x4d
> [<c0318890>] ? __rtnl_link_unregister+0x56/0x8a
> [<c0318f45>] ? rtnl_link_unregister+0x19/0x21
> [<f801e32d>] ? bonding_exit+0x30/0x3c [bonding]
> [<c0162ddc>] ? sys_delete_module+0x184/0x1dc
> [<c01555fe>] ? put_lock_stats+0xd/0x22
> [<c0155708>] ? lock_release_holdtime+0xf5/0xfa
> [<c01a8fa3>] ? sys_munmap+0x39/0x3f
> [<c037f098>] ? restore_all_notrace+0x0/0x18
> [<c010294c>] ? sysenter_do_call+0x12/0x32
> Code: fc ff 89 d8 e8 27 77 fc ff 5b 5e 5d c3 55 89 e5 57 89 c7 56 53 83 ec 04 85 c0 0f 84 01 01 00 00 8b 40 40 85 c0 0f 84 f6 00 00 00<83> 78 34 00 0f 84 ec 00 00 00 8b 47 34 31 d2 89 fe 05 a4 00 00
> EIP: [<c0201f11>] debugfs_remove_recursive+0x1e/0x11a SS:ESP 0068:f4d03ea8
> CR2: 000000006b6b6b9f
> ---[ end trace e274f539dfd6ed30 ]---
>
> This happens regardless of activity; e.g., "insmod bonding
> mode=balance-alb" followed immediately by "rmmod bonding" generates the
> above.
>
> Any thoughts?
Thank you for testing. I could reproduce a similar crash.
I'm debugging now...
Best regards,
Taku izumi
^ permalink raw reply
* Re: Adding Support for SG,GSO,GRO
From: Eric Dumazet @ 2010-12-09 10:50 UTC (permalink / raw)
To: Govindarajan, Sriramakrishnan; +Cc: netdev@vger.kernel.org
In-Reply-To: <FCCFB4CDC6E5564B9182F639FC356087035F21D9F9@dbde02.ent.ti.com>
Le jeudi 09 décembre 2010 à 16:03 +0530, Govindarajan, Sriramakrishnan a
écrit :
> Hi
> We have a NAPI compliant driver(net/drivers/davinci_emac.c), that does well at 10/100Mbps loads. Now the same controller/driver is used for 1000Mbps
> mode as well, where the CPU gets saturated easily
>
> Internally the module supports scatter gather DMA(which is currently not
> exercised) but there is no HW checksum support.
>
> To specifically implement GRO, GSO support would it be sufficient to add
> SG support to the driver? Are there other means of increasing the throughput
> and decreasing the CPU loading?
>
> Any pointers to reference implementation for adding SG/GRO/GSO support will be helpful.
Adding GRO is pretty easy, since you already are NAPI.
call
napi_gro_receive(&adapter->napi, skb)
instead of
netif_receive_skb(skb);
(
Take commit 6a08d194ee4080 as an example of such conversion
http://git.kernel.org/?p=linux/kernel/git/davem/net-next-2.6.git;a=commitdiff;h=6a08d194ee40806e0ccd5f36ed768e64cbfc979f
^ 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