* [PATCH 2/2] netxen: Fix interrupt handling for multiport adapters
From: dhananjay @ 2007-07-20 19:07 UTC (permalink / raw)
To: netdev; +Cc: rob
In-Reply-To: <20070720190749.535704712@netxen.com>
[-- Attachment #1: intr.patch --]
[-- Type: text/plain, Size: 2562 bytes --]
This patch fixes masking of interrupts on multiport adapters. Also disables
interrupts upon ifdown interface. The wrong mask could result in interrupt
flood after interface is down.
Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
Index: netdev-2.6/drivers/net/netxen/netxen_nic_main.c
===================================================================
--- netdev-2.6.orig/drivers/net/netxen/netxen_nic_main.c
+++ netdev-2.6/drivers/net/netxen/netxen_nic_main.c
@@ -930,6 +930,8 @@ static int netxen_nic_close(struct net_d
netif_carrier_off(netdev);
netif_stop_queue(netdev);
+ netxen_nic_disable_int(adapter);
+
cmd_buff = adapter->cmd_buf_arr;
for (i = 0; i < adapter->max_tx_desc_count; i++) {
buffrag = cmd_buff->frag_array;
@@ -1243,28 +1245,12 @@ static int
netxen_handle_int(struct netxen_adapter *adapter, struct net_device *netdev)
{
u32 ret = 0;
- u32 our_int = 0;
DPRINTK(INFO, "Entered handle ISR\n");
adapter->stats.ints++;
- if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) {
- our_int = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR));
- /* not our interrupt */
- if ((our_int & (0x80 << adapter->portnum)) == 0)
- return ret;
- }
-
netxen_nic_disable_int(adapter);
- if (adapter->intr_scheme == INTR_SCHEME_PERPORT) {
- /* claim interrupt */
- if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) {
- writel(our_int & ~((u32)(0x80 << adapter->portnum)),
- NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR));
- }
- }
-
if (netxen_nic_rx_has_work(adapter) || netxen_nic_tx_has_work(adapter)) {
if (netif_rx_schedule_prep(netdev)) {
/*
@@ -1298,6 +1284,7 @@ irqreturn_t netxen_intr(int irq, void *d
{
struct netxen_adapter *adapter;
struct net_device *netdev;
+ u32 our_int = 0;
if (unlikely(!irq)) {
return IRQ_NONE; /* Not our interrupt */
@@ -1305,7 +1292,22 @@ irqreturn_t netxen_intr(int irq, void *d
adapter = (struct netxen_adapter *)data;
netdev = adapter->netdev;
- /* process our status queue (for all 4 ports) */
+
+ if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) {
+ our_int = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR));
+ /* not our interrupt */
+ if ((our_int & (0x80 << adapter->portnum)) == 0)
+ return IRQ_NONE;
+ }
+
+ if (adapter->intr_scheme == INTR_SCHEME_PERPORT) {
+ /* claim interrupt */
+ if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) {
+ writel(our_int & ~((u32)(0x80 << adapter->portnum)),
+ NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR));
+ }
+ }
+
if (netif_running(netdev))
netxen_handle_int(adapter, netdev);
--
^ permalink raw reply
* [PATCH 0/2] netxen: bug fixes for multiport adapters
From: dhananjay @ 2007-07-20 19:07 UTC (permalink / raw)
To: netdev; +Cc: rob
These patches include fix for problem with 2nd port of multiport adapters
on IBM blades. Also improves interrupt handling for multiport adapters
avoiding interrupt flood after interrupt is down.
Generated against upstream-fixes.
drivers/net/netxen/netxen_nic.h | 3 +-
drivers/net/netxen/netxen_nic_main.c | 85 +++++++++++++++---------------
2 files changed, 43 insertions(+), 45 deletions(-)
--
^ permalink raw reply
* [PATCH 1/2] netxen: IMEZ multiport card 2nd port issue, dma watchdog fix
From: dhananjay @ 2007-07-20 19:07 UTC (permalink / raw)
To: netdev; +Cc: rob, Wen Xiong
In-Reply-To: <20070720190749.535704712@netxen.com>
[-- Attachment #1: dma.patch --]
[-- Type: text/plain, Size: 4409 bytes --]
This fixes issue with 2nd port of multiport adapter that the MAC address
is reset by firmware in PCI probe. This patch also fixes a bug that PCI
resources are not released if dma watchdog shutdown failed. The dma watchdog
poll messages during module unload are also suppressed.
Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
Signed-off-by: Wen Xiong <wenxiong@us.ibm.com>
Index: netdev-2.6/drivers/net/netxen/netxen_nic_main.c
===================================================================
--- netdev-2.6.orig/drivers/net/netxen/netxen_nic_main.c
+++ netdev-2.6/drivers/net/netxen/netxen_nic_main.c
@@ -46,7 +46,7 @@ MODULE_DESCRIPTION("NetXen Multi port (1
MODULE_LICENSE("GPL");
MODULE_VERSION(NETXEN_NIC_LINUX_VERSIONID);
-char netxen_nic_driver_name[] = "netxen-nic";
+char netxen_nic_driver_name[] = "netxen_nic";
static char netxen_nic_driver_string[] = "NetXen Network Driver version "
NETXEN_NIC_LINUX_VERSIONID;
@@ -785,19 +785,18 @@ static void __devexit netxen_nic_remove(
if (adapter->portnum == 0) {
if (init_firmware_done) {
- dma_watchdog_shutdown_request(adapter);
- msleep(100);
i = 100;
- while ((dma_watchdog_shutdown_poll_result(adapter) != 1) && i) {
- printk(KERN_INFO "dma_watchdog_shutdown_poll still in progress\n");
+ do {
+ if (dma_watchdog_shutdown_request(adapter) == 1)
+ break;
msleep(100);
- i--;
- }
-
- if (i == 0) {
- printk(KERN_ERR "dma_watchdog_shutdown_request failed\n");
- return;
- }
+ if (dma_watchdog_shutdown_poll_result(adapter) == 1)
+ break;
+ } while (--i);
+
+ if (i == 0)
+ printk(KERN_ERR "%s: dma_watchdog_shutdown failed\n",
+ netdev->name);
/* clear the register for future unloads/loads */
writel(0, NETXEN_CRB_NORMALIZE(adapter, NETXEN_CAM_RAM(0x1fc)));
@@ -805,12 +804,11 @@ static void __devexit netxen_nic_remove(
readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE)));
/* leave the hw in the same state as reboot */
+ netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE);
writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE));
- if (netxen_pinit_from_rom(adapter, 0))
- return;
+ netxen_pinit_from_rom(adapter, 0);
msleep(1);
- if (netxen_load_firmware(adapter))
- return;
+ netxen_load_firmware(adapter);
netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE);
}
@@ -819,22 +817,21 @@ static void __devexit netxen_nic_remove(
printk(KERN_INFO "State: 0x%0x\n",
readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE)));
- dma_watchdog_shutdown_request(adapter);
- msleep(100);
i = 100;
- while ((dma_watchdog_shutdown_poll_result(adapter) != 1) && i) {
- printk(KERN_INFO "dma_watchdog_shutdown_poll still in progress\n");
+ do {
+ if (dma_watchdog_shutdown_request(adapter) == 1)
+ break;
msleep(100);
- i--;
- }
+ if (dma_watchdog_shutdown_poll_result(adapter) == 1)
+ break;
+ } while (--i);
if (i) {
netxen_free_adapter_offload(adapter);
} else {
- printk(KERN_ERR "failed to dma shutdown\n");
- return;
+ printk(KERN_ERR "%s: dma_watchdog_shutdown failed\n",
+ netdev->name);
}
-
}
iounmap(adapter->ahw.db_base);
@@ -898,8 +895,6 @@ static int netxen_nic_open(struct net_de
/* Done here again so that even if phantom sw overwrote it,
* we set it */
- if (adapter->macaddr_set)
- adapter->macaddr_set(adapter, netdev->dev_addr);
if (adapter->init_port
&& adapter->init_port(adapter, adapter->portnum) != 0) {
del_timer_sync(&adapter->watchdog_timer);
@@ -907,6 +902,8 @@ static int netxen_nic_open(struct net_de
netxen_nic_driver_name, adapter->portnum);
return -EIO;
}
+ if (adapter->macaddr_set)
+ adapter->macaddr_set(adapter, netdev->dev_addr);
netxen_nic_set_link_parameters(adapter);
Index: netdev-2.6/drivers/net/netxen/netxen_nic.h
===================================================================
--- netdev-2.6.orig/drivers/net/netxen/netxen_nic.h
+++ netdev-2.6/drivers/net/netxen/netxen_nic.h
@@ -1179,8 +1179,7 @@ dma_watchdog_shutdown_poll_result(struct
NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), &ctrl, 4))
printk(KERN_ERR "failed to read dma watchdog status\n");
- return ((netxen_get_dma_watchdog_enabled(ctrl) == 0) &&
- (netxen_get_dma_watchdog_disabled(ctrl) == 0));
+ return (netxen_get_dma_watchdog_enabled(ctrl) == 0);
}
static inline int
--
^ permalink raw reply
* Re: tg3 issues
From: Michael Chan @ 2007-07-20 19:34 UTC (permalink / raw)
To: patric; +Cc: Neil Horman, netdev
In-Reply-To: <46A0E9D7.7020904@imperialnet.org>
On Fri, 2007-07-20 at 18:59 +0200, patric wrote:
> Thanks... That's a confirmation on what i suspected.. I think i'll dig
> into the code instead and try to figure out some way of making it work a
> bit better for my setup atleast...
> I'll post a patch later if i get something working... Btw, do you have
> any timings on how long it takes for the cards to get a lock on the link?
>
Serdes link comes up very fast. The clause 37 autoneg involves going
through a few states and exchanging base pages and optional next pages.
Each state completes in 10 msec, so the whole autoneg should complete in
roughly 100 msec or so. But because it is done in software for these
older cards, it can take much longer because it can get out-of-sync.
^ permalink raw reply
* [ofa-general] Re: [PATCH 05/10] sch_generic.c changes.
From: Patrick McHardy @ 2007-07-20 18:16 UTC (permalink / raw)
To: Krishna Kumar
Cc: johnpol, Robert.Olsson, peter.p.waskiewicz.jr, herbert, gaagaan,
kumarkr, rdreier, mcarlson, netdev, jagana, general, mchan, tgraf,
jeff, hadi, davem, sri
In-Reply-To: <20070720063249.26341.125.sendpatchset@localhost.localdomain>
Krishna Kumar wrote:
> +static inline int get_skb(struct net_device *dev, struct Qdisc *q,
> + struct sk_buff_head *blist,
> + struct sk_buff **skbp)
> +{
> + if (likely(!blist) || (!skb_queue_len(blist) && qdisc_qlen(q) <= 1)) {
> + return likely((*skbp = dev_dequeue_skb(dev, q)) != NULL);
> + } else {
> + int max = dev->tx_queue_len - skb_queue_len(blist);
I'm assuming the driver will simply leave excess packets in the
blist for the next run. The check for tx_queue_len is wrong though,
its only a default which can be overriden and some qdiscs don't
care for it at all.
> + struct sk_buff *skb;
> +
> + while (max > 0 && (skb = dev_dequeue_skb(dev, q)) != NULL)
> + max -= dev_add_skb_to_blist(skb, dev);
> +
> + *skbp = NULL;
> + return 1; /* we have atleast one skb in blist */
> + }
> +}
> -void __qdisc_run(struct net_device *dev)
> +void __qdisc_run(struct net_device *dev, struct sk_buff_head *blist)
And the patches should really be restructured so this change is
in the same patch changing the header and the caller, for example.
> {
> do {
> - if (!qdisc_restart(dev))
> + if (!qdisc_restart(dev, blist))
> break;
> } while (!netif_queue_stopped(dev));
>
> -
> 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
* [ofa-general] Re: [PATCH 03/10] dev.c changes.
From: Sridhar Samudrala @ 2007-07-20 17:44 UTC (permalink / raw)
To: Krishna Kumar
Cc: johnpol, Robert.Olsson, peter.p.waskiewicz.jr, herbert, gaagaan,
kumarkr, rdreier, mcarlson, kaber, jagana, general, netdev, tgraf,
jeff, hadi, davem, mchan
In-Reply-To: <20070720063227.26341.91868.sendpatchset@localhost.localdomain>
On Fri, 2007-07-20 at 12:02 +0530, Krishna Kumar wrote:
> Changes in dev.c to support batching : add dev_add_skb_to_blist,
> register_netdev recognizes batch aware drivers, and net_tx_action is
> the sole user of batching.
>
> Signed-off-by: Krishna Kumar <krkumar2@in.ibm.com>
> ---
> dev.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
> 1 files changed, 74 insertions(+), 3 deletions(-)
>
> diff -ruNp org/net/core/dev.c new/net/core/dev.c
> --- org/net/core/dev.c 2007-07-20 07:49:28.000000000 +0530
> +++ new/net/core/dev.c 2007-07-20 08:31:35.000000000 +0530
<snip>
> @@ -1566,7 +1605,7 @@ gso:
> /* reset queue_mapping to zero */
> skb->queue_mapping = 0;
> rc = q->enqueue(skb, q);
> - qdisc_run(dev);
> + qdisc_run(dev, NULL);
OK. So you are passing a NULL blist here. However, i am
not sure why batching is not used in this situation.
Thanks
Sridhar
> spin_unlock(&dev->queue_lock);
>
> rc = rc == NET_XMIT_BYPASS ? NET_XMIT_SUCCESS : rc;
> @@ -1763,7 +1802,11 @@ static void net_tx_action(struct softirq
> clear_bit(__LINK_STATE_SCHED, &dev->state);
>
> if (spin_trylock(&dev->queue_lock)) {
> - qdisc_run(dev);
> + /*
> + * Try to send out all skbs if batching is
> + * enabled.
> + */
> + qdisc_run(dev, dev->skb_blist);
> spin_unlock(&dev->queue_lock);
> } else {
> netif_schedule(dev);
> @@ -3397,6 +3440,28 @@ int register_netdevice(struct net_device
> }
> }
>
> + if (dev->features & NETIF_F_BATCH_SKBS) {
> + if (!dev->hard_start_xmit_batch ||
> + dev->tx_queue_len < MIN_QUEUE_LEN_BATCH) {
> + /*
> + * Batch TX requires API support in driver plus have
> + * a minimum sized queue.
> + */
> + printk(KERN_ERR "%s: Dropping NETIF_F_BATCH_SKBS "
> + "since no API support or queue len "
> + "is smaller than %d.\n",
> + dev->name, MIN_QUEUE_LEN_BATCH);
> + dev->features &= ~NETIF_F_BATCH_SKBS;
> + } else {
> + dev->skb_blist = kmalloc(sizeof *dev->skb_blist,
> + GFP_KERNEL);
> + if (dev->skb_blist) {
> + skb_queue_head_init(dev->skb_blist);
> + dev->tx_queue_len >>= 1;
> + }
> + }
> + }
> +
> /*
> * nil rebuild_header routine,
> * that should be never called and used as just bug trap.
> @@ -3732,10 +3797,16 @@ void unregister_netdevice(struct net_dev
>
> synchronize_net();
>
> + /* Deallocate batching structure */
> + if (dev->skb_blist) {
> + skb_queue_purge(dev->skb_blist);
> + kfree(dev->skb_blist);
> + dev->skb_blist = NULL;
> + }
> +
> /* Shutdown queueing discipline. */
> dev_shutdown(dev);
>
> -
> /* Notify protocols, that we are about to destroy
> this device. They should clean all the things.
> */
^ permalink raw reply
* [ofa-general] Re: [PATCH 02/10] Networking include file changes.
From: Sridhar Samudrala @ 2007-07-20 17:25 UTC (permalink / raw)
To: Krishna Kumar
Cc: johnpol, Robert.Olsson, herbert, gaagaan, kumarkr, rdreier,
peter.p.waskiewicz.jr, mcarlson, kaber, jagana, general, netdev,
tgraf, jeff, hadi, davem, mchan
In-Reply-To: <20070720063216.26341.80316.sendpatchset@localhost.localdomain>
On Fri, 2007-07-20 at 12:02 +0530, Krishna Kumar wrote:
> Networking include file changes for batching.
>
> Signed-off-by: Krishna Kumar <krkumar2@in.ibm.com>
> ---
> linux/netdevice.h | 10 ++++++++++
> net/pkt_sched.h | 6 +++---
> 2 files changed, 13 insertions(+), 3 deletions(-)
>
> diff -ruNp org/include/linux/netdevice.h new/include/linux/netdevice.h
> --- org/include/linux/netdevice.h 2007-07-20 07:49:28.000000000 +0530
> +++ new/include/linux/netdevice.h 2007-07-20 08:30:55.000000000 +0530
> @@ -264,6 +264,8 @@ enum netdev_state_t
> __LINK_STATE_QDISC_RUNNING,
> };
>
> +/* Minimum length of device hardware queue for batching to work */
> +#define MIN_QUEUE_LEN_BATCH 16
>
> /*
> * This structure holds at boot time configured netdevice settings. They
> @@ -340,6 +342,7 @@ struct net_device
> #define NETIF_F_VLAN_CHALLENGED 1024 /* Device cannot handle VLAN packets */
> #define NETIF_F_GSO 2048 /* Enable software GSO. */
> #define NETIF_F_LLTX 4096 /* LockLess TX */
> +#define NETIF_F_BATCH_SKBS 8192 /* Driver supports batch skbs API */
> #define NETIF_F_MULTI_QUEUE 16384 /* Has multiple TX/RX queues */
>
> /* Segmentation offload features */
> @@ -452,6 +455,8 @@ struct net_device
> struct Qdisc *qdisc_sleeping;
> struct list_head qdisc_list;
> unsigned long tx_queue_len; /* Max frames per queue allowed */
> + unsigned long xmit_slots; /* Device free slots */
> + struct sk_buff_head *skb_blist; /* List of batch skbs */
>
> /* Partially transmitted GSO packet. */
> struct sk_buff *gso_skb;
> @@ -472,6 +477,9 @@ struct net_device
> void *priv; /* pointer to private data */
> int (*hard_start_xmit) (struct sk_buff *skb,
> struct net_device *dev);
> + int (*hard_start_xmit_batch) (struct net_device
> + *dev);
> +
> /* These may be needed for future network-power-down code. */
> unsigned long trans_start; /* Time (in jiffies) of last Tx */
>
> @@ -832,6 +840,8 @@ extern int dev_set_mac_address(struct n
> struct sockaddr *);
> extern int dev_hard_start_xmit(struct sk_buff *skb,
> struct net_device *dev);
> +extern int dev_add_skb_to_blist(struct sk_buff *skb,
> + struct net_device *dev);
>
> extern void dev_init(void);
>
> diff -ruNp org/include/net/pkt_sched.h new/include/net/pkt_sched.h
> --- org/include/net/pkt_sched.h 2007-07-20 07:49:28.000000000 +0530
> +++ new/include/net/pkt_sched.h 2007-07-20 08:30:22.000000000 +0530
> @@ -80,13 +80,13 @@ extern struct qdisc_rate_table *qdisc_ge
> struct rtattr *tab);
> extern void qdisc_put_rtab(struct qdisc_rate_table *tab);
>
> -extern void __qdisc_run(struct net_device *dev);
> +extern void __qdisc_run(struct net_device *dev, struct sk_buff_head *blist);
Why do we need this additional 'blist' argument?
Is this different from dev->skb_blist?
>
> -static inline void qdisc_run(struct net_device *dev)
> +static inline void qdisc_run(struct net_device *dev, struct sk_buff_head *blist)
> {
> if (!netif_queue_stopped(dev) &&
> !test_and_set_bit(__LINK_STATE_QDISC_RUNNING, &dev->state))
> - __qdisc_run(dev);
> + __qdisc_run(dev, blist);
> }
>
> extern int tc_classify_compat(struct sk_buff *skb, struct tcf_proto *tp,
^ permalink raw reply
* Re: tg3 issues
From: patric @ 2007-07-20 16:59 UTC (permalink / raw)
To: Michael Chan; +Cc: Neil Horman, netdev
In-Reply-To: <1184866465.10854.45.camel@dell>
Michael Chan wrote:
> On Thu, 2007-07-19 at 15:24 +0200, patric wrote:
>
>
>> Just a hypothetical question. If the 2 network cards starts the
>> autonegotiation would it be possible that they get into a loop where
>> they are chasing each others state? Maybe a fix could be to add a sleep
>> of a random length that would enable them to catch up? Maybe you know if
>> any of the fiber-cards so support running without flowcontrol too since
>> the cards don't seem to be able to get a link with flowcontrol turned
>> off at least in this setup.
>>
>>
>>
>
> The old 5701 fiber NICs do not support autonegotiation in hardware so it
> is done "by hand" in the driver. It is not the most robust way of doing
> autoneg and what you described is totally possible. You might want to
> try disabling autoneg to see if it works any better. There is only one
> possible speed in fiber and autoneg is really only used to negotiate
> flow control. Some switch ports will not link up if the link partner
> does not do autoneg though.
>
> You have to use ethtool in initrd to turn off autoneg or just modify the
> driver to disable autoneg.
>
>
>
Thanks... That's a confirmation on what i suspected.. I think i'll dig
into the code instead and try to figure out some way of making it work a
bit better for my setup atleast...
I'll post a patch later if i get something working... Btw, do you have
any timings on how long it takes for the cards to get a lock on the link?
Thanks for your input!
/Patric
^ permalink raw reply
* Re: [PATCH] [updated] PHY fixed driver: rework release path and update phy_id notation
From: Scott Wood @ 2007-07-20 16:47 UTC (permalink / raw)
To: Andrew Morton; +Cc: netdev, linux-kernel, Jeff Garzik, linuxppc-dev
In-Reply-To: <20070720005702.b2b644e7.akpm@linux-foundation.org>
On Fri, Jul 20, 2007 at 12:57:02AM -0700, Andrew Morton wrote:
> On Fri, 20 Jul 2007 11:50:39 +0400 Vitaly Bordug <vitb@kernel.crashing.org> wrote:
> > On Thu, 19 Jul 2007 23:23:37 -0700
> > Andrew Morton wrote:
> > > Shouldn't these be runtime options (ie: module parameters)?
> > >
> > I thought about it but this thing is more like the one that will never tend/required to change while\
> > configured.. Will add if you see it appropriate though.
>
> 99% of users don't compile their own kernels: their vendor will have to
> make this decision for them, and it sounds like any decision which they
> make will be wrong for some of their users?
This is mostly of use on embedded hardware where the kernel will be
rebuilt by someone who knows the hardware... That said, I don't see why
it needs to be configured at all. Couldn't it use an idr table instead?
-Scott
^ permalink raw reply
* [patch 2/3] netdev: i82596 Ethernet needs <asm/cacheflush.h>
From: Geert Uytterhoeven @ 2007-07-20 16:40 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-m68k, linux-kernel, Jeff Garzik, netdev
In-Reply-To: <20070720164043.523003359@mail.of.borg>
[-- Attachment #1: m68k-82596-needs-asm-cacheflush.diff --]
[-- Type: text/plain, Size: 1042 bytes --]
netdev: i82596 Ethernet needs <asm/cacheflush.h> on m68k
drivers/net/82596.c: In function 'init_rx_bufs':
drivers/net/82596.c:552: error: implicit declaration of function 'cache_clear'
drivers/net/82596.c: In function 'i596_start_xmit':
drivers/net/82596.c:1104: error: implicit declaration of function 'cache_push'
The driver still compiles on ia32 (CONFIG_APRICOT=y)
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
---
drivers/net/82596.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/net/82596.c
+++ b/drivers/net/82596.c
@@ -57,6 +57,7 @@
#include <asm/io.h>
#include <asm/dma.h>
#include <asm/pgtable.h>
+#include <asm/cacheflush.h>
static char version[] __initdata =
"82596.c $Revision: 1.5 $\n";
--
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply
* Re: [PATCH] SMSC LAN911x and LAN921x vendor driver
From: Steve.Glendinning @ 2007-07-20 16:22 UTC (permalink / raw)
To: Jeff Garzik
Cc: Bahadir Balban, Bill Gatliff, Dustin Mcintire, ian.saturley,
netdev
In-Reply-To: <469E9648.6050209@garzik.org>
Hi Jeff,
> Where is the hard_start_xmit/TX-completion locking?
The entire PIO Tx operation is performed within hard_start_xmit, so should
be covered by netif_tx_lock.
Regards,
--
Steve Glendinning
SMSC GmbH
m: +44 777 933 9124
e: steve.glendinning@smsc.com
^ permalink raw reply
* [ofa-general] Re: [PATCH 04/10] net-sysfs.c changes.
From: Stephen Hemminger @ 2007-07-20 16:22 UTC (permalink / raw)
To: Patrick McHardy
Cc: jagana, herbert, gaagaan, Robert.Olsson, kumarkr, rdreier,
peter.p.waskiewicz.jr, hadi, mcarlson, jeff, general, mchan,
tgraf, netdev, johnpol, davem, sri
In-Reply-To: <46A09ACF.20805@trash.net>
On Fri, 20 Jul 2007 13:21:51 +0200
Patrick McHardy <kaber@trash.net> wrote:
> Krishna Kumar2 wrote:
> > Patrick McHardy <kaber@trash.net> wrote on 07/20/2007 03:37:20 PM:
> >
> >
> >
> >> rtnetlink support seems more important than sysfs to me.
> >>
> >
> > Thanks, I will add that as a patch. The reason to add to sysfs is that
> > it is easier to change for a user (and similar to tx_queue_len).
> >
>
But since batching is so similar to TSO, i really should be part of the
flags and controlled by ethtool like other offload flags.
^ permalink raw reply
* Re: [GENETLINK]: Question: global lock (genl_mutex) possible refinement?
From: Richard MUSIL @ 2007-07-20 16:15 UTC (permalink / raw)
To: Patrick McHardy; +Cc: netdev
In-Reply-To: <46A0BFFF.5020000@trash.net>
Patrick McHardy wrote:
> [ Please quote and break your lines appropriately ]
Oops, sorry for that, definitely was not intentional :(.
> Export the lock/unlock/.. functions. You'll also need a new version
> similar to __rtnl_unlock.
Patrick, you might feel, I am not reading your lines, but in fact I do.
The problem is that I do not feel competent to follow/propose such
changes. So what I propose here (in included patch) is the least change
scenario, which I can think of and on which I feel safe.
If there are some other changes required, as you suggested for example
exporting lock from genetlink module, I hope authors of genetlink will
comment on that. Currently, I do not see any reason for that, but this
could be due to my limited knowledge.
--
Richard
>From a02ef65329fa33591247f9f3a39f2917afe1ce89 Mon Sep 17 00:00:00 2001
From: Richard Musil <richard.musil@st.com>
Date: Fri, 20 Jul 2007 17:44:20 +0200
Subject: [PATCH] Added separate mutex for syncing the access to family
list (registration, unregistration, ops, etc.)
This change allows family/ops registration/unregistration in 'doit',
'dumpit' message handlers both which hold message sync. mutex. Original
version used only one global mutex for both managing the families and
processing the messages and led to lock when message processing handler
tried to change families.
---
net/netlink/genetlink.c | 38 +++++++++++++++++++++++++-------------
1 files changed, 25 insertions(+), 13 deletions(-)
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index b9ab62f..5ee18eb 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -38,6 +38,18 @@ static void genl_unlock(void)
genl_sock->sk_data_ready(genl_sock, 0);
}
+static DEFINE_MUTEX(genl_fam_mutex); /* serialization for family list management */
+
+static inline void genl_fam_lock(void)
+{
+ mutex_lock(&genl_fam_mutex);
+}
+
+static inline genl_fam_unlock(void)
+{
+ mutex_unlock(&genl_fam_mutex);
+}
+
#define GENL_FAM_TAB_SIZE 16
#define GENL_FAM_TAB_MASK (GENL_FAM_TAB_SIZE - 1)
@@ -150,9 +162,9 @@ int genl_register_ops(struct genl_family *family, struct genl_ops *ops)
if (ops->policy)
ops->flags |= GENL_CMD_CAP_HASPOL;
- genl_lock();
+ genl_fam_lock();
list_add_tail(&ops->ops_list, &family->ops_list);
- genl_unlock();
+ genl_fam_unlock();
genl_ctrl_event(CTRL_CMD_NEWOPS, ops);
err = 0;
@@ -180,16 +192,16 @@ int genl_unregister_ops(struct genl_family *family, struct genl_ops *ops)
{
struct genl_ops *rc;
- genl_lock();
+ genl_fam_lock();
list_for_each_entry(rc, &family->ops_list, ops_list) {
if (rc == ops) {
list_del(&ops->ops_list);
- genl_unlock();
+ genl_fam_unlock();
genl_ctrl_event(CTRL_CMD_DELOPS, ops);
return 0;
}
}
- genl_unlock();
+ genl_fam_unlock();
return -ENOENT;
}
@@ -217,7 +229,7 @@ int genl_register_family(struct genl_family *family)
INIT_LIST_HEAD(&family->ops_list);
- genl_lock();
+ genl_fam_lock();
if (genl_family_find_byname(family->name)) {
err = -EEXIST;
@@ -251,14 +263,14 @@ int genl_register_family(struct genl_family *family)
family->attrbuf = NULL;
list_add_tail(&family->family_list, genl_family_chain(family->id));
- genl_unlock();
+ genl_fam_unlock();
genl_ctrl_event(CTRL_CMD_NEWFAMILY, family);
return 0;
errout_locked:
- genl_unlock();
+ genl_fam_unlock();
errout:
return err;
}
@@ -275,7 +287,7 @@ int genl_unregister_family(struct genl_family *family)
{
struct genl_family *rc;
- genl_lock();
+ genl_fam_lock();
list_for_each_entry(rc, genl_family_chain(family->id), family_list) {
if (family->id != rc->id || strcmp(rc->name, family->name))
@@ -283,14 +295,14 @@ int genl_unregister_family(struct genl_family *family)
list_del(&rc->family_list);
INIT_LIST_HEAD(&family->ops_list);
- genl_unlock();
+ genl_fam_unlock();
kfree(family->attrbuf);
genl_ctrl_event(CTRL_CMD_DELFAMILY, family);
return 0;
}
- genl_unlock();
+ genl_fam_unlock();
return -ENOENT;
}
@@ -425,7 +437,7 @@ static int ctrl_dumpfamily(struct sk_buff *skb, struct netlink_callback *cb)
int fams_to_skip = cb->args[1];
if (chains_to_skip != 0)
- genl_lock();
+ genl_fam_lock();
for (i = 0; i < GENL_FAM_TAB_SIZE; i++) {
if (i < chains_to_skip)
@@ -445,7 +457,7 @@ static int ctrl_dumpfamily(struct sk_buff *skb, struct netlink_callback *cb)
errout:
if (chains_to_skip != 0)
- genl_unlock();
+ genl_fam_unlock();
cb->args[0] = i;
cb->args[1] = n;
--
1.5.1.6
^ permalink raw reply related
* Re: [PATCH 1/1] Allow LSM to use IP address/port number.
From: Patrick McHardy @ 2007-07-20 15:44 UTC (permalink / raw)
To: James Morris; +Cc: Tetsuo Handa, shemminger, netdev, linux-security-module
In-Reply-To: <Line.LNX.4.64.0707201124070.7319@d.namei>
James Morris wrote:
> On Sat, 21 Jul 2007, Tetsuo Handa wrote:
>
>
>> I can't use netfilter infrastructure because
>> it is too early to know who the recipant process of the packet is.
>>
>
> I think the way forward on this is to re-visit the idea of providing a
> proper solution for the incoming packet/user match problem.
>
> I posted one possible solution a couple of years ago (skfilter):
> http://lwn.net/Articles/157137/
>
> I think there has been some recent discussion by netfilter developers
> about this issue, so perhaps you could talk to them (cd'd Patrick)
>
Even with socket filters netfilter doesn't know the final receipient
process, that is not known until it calls recvmsg and the data is read,
which is too late for netfilter.
Quoting Tetsuo:
> > So, my approach is not using security context associated with a socket
> > but security context associated with a process.
Isn't the socket context derived from the process context?
^ permalink raw reply
* [RFC 1/1] lro: Generic Large Receive Offload for TCP traffic
From: Jan-Bernd Themann @ 2007-07-20 15:41 UTC (permalink / raw)
To: netdev
Cc: Thomas Klein, Jan-Bernd Themann, linux-kernel, linux-ppc,
Christoph Raisch, Marcus Eder, Stefan Roscher, David Miller
Generic LRO patch
Signed-off-by: Jan-Bernd Themann <themann@de.ibm.com>
---
include/linux/inet_lro.h | 154 +++++++++++++
net/ipv4/inet_lro.c | 549 ++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 703 insertions(+), 0 deletions(-)
create mode 100644 include/linux/inet_lro.h
create mode 100644 net/ipv4/inet_lro.c
diff --git a/include/linux/inet_lro.h b/include/linux/inet_lro.h
new file mode 100644
index 0000000..2680ecf
--- /dev/null
+++ b/include/linux/inet_lro.h
@@ -0,0 +1,154 @@
+/*
+ * linux/include/linux/inet_lro.h
+ *
+ * Large Receive Offload (ipv4 / tcp)
+ *
+ * (C) Copyright IBM Corp. 2007
+ *
+ * Authors:
+ * Jan-Bernd Themann <themann@de.ibm.com>
+ * Christoph Raisch <raisch@de.ibm.com>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __INET_LRO_H_
+#define __INET_LRO_H_
+
+#include <net/ip.h>
+#include <net/tcp.h>
+
+#define LRO_IPV4 1
+#define LRO_TCP 2
+
+/*
+ * LRO descriptor for a tcp session
+ */
+struct net_lro_desc {
+ struct sk_buff *parent;
+ struct sk_buff *last_skb;
+ struct skb_frag_struct *next_frag;
+ struct iphdr *iph;
+ struct tcphdr *tcph;
+ struct vlan_group *vgrp;
+ __wsum data_csum;
+ u32 tcp_rcv_tsecr;
+ u32 tcp_rcv_tsval;
+ u32 tcp_ack;
+ u32 tcp_next_seq;
+ u32 skb_tot_frags_len;
+ u16 ip_tot_len;
+ u16 tcp_saw_tstamp; /* timestamps enabled */
+ u16 tcp_window;
+ u16 vlan_tag;
+ int pkt_aggr_cnt; /* counts aggregated packets */
+ int vlan_packet;
+ int active;
+};
+
+/*
+ * Large Receive Offload (LRO) Manager
+ *
+ * Fields must be set by driver
+ */
+
+struct net_lro_mgr {
+ struct net_device *dev; /* Required for receive in page mode */
+ u32 ip_summed; /* Options to be set in generated SKB in page mode */
+ int max_desc; /* Max number of LRO descriptors */
+ int max_aggr; /* Max number of LRO packets to be aggregated */
+
+ struct net_lro_desc *lro_arr; /* Array of LRO descriptors */
+
+ /*
+ * Optimized driver functions
+ *
+ * get_skb_header: returns tcp and ip header for packet in SKB
+ */
+ int (*get_skb_header)(struct sk_buff *skb, void **ip_hdr,
+ void **tcpudp_hdr, u64 *hdr_flags, void *priv);
+
+ /*
+ * get_frag_header: returns mac, tcp and ip header for packet in SKB
+ *
+ * @hdr_flags: Indicate what kind of LRO has to be done
+ * (IPv4/IPv6/TCP/UDP)
+ */
+ int (*get_frag_header)(struct skb_frag_struct *frag, void **mac_hdr,
+ void **ip_hdr, void **tcpudp_hdr, u64 *hdr_flags,
+ void *priv);
+};
+
+/*
+ * Processes a SKB
+ *
+ * @lro_mgr: LRO manager to use
+ * @skb: SKB to aggregate
+ * @priv: Private data that may be used by driver functions
+ * (for example get_tcp_ip_hdr)
+ */
+
+void lro_receive_skb(struct net_lro_mgr *lro_mgr,
+ struct sk_buff *skb,
+ void *priv);
+
+/*
+ * Processes a SKB with VLAN HW acceleration support
+ */
+
+void lro_vlan_hwaccel_receive_skb(struct net_lro_mgr *lro_mgr,
+ struct sk_buff *skb,
+ struct vlan_group *vgrp,
+ u16 vlan_tag,
+ void *priv);
+
+/*
+ * Processes a fragment list
+ *
+ * This functions aggregate fragments and generate SKBs do pass
+ * the packets to the stack.
+ *
+ * @lro_mgr: LRO manager to use
+ * @frags: Fragment to be processed. Must contain entire header in first
+ * element.
+ * @len: Length of received data
+ * @true_size: Actual size of memory the fragment is consuming
+ * @priv: Private data that may be used by driver functions
+ * (for example get_tcp_ip_hdr)
+ */
+
+void lro_receive_frags(struct net_lro_mgr *lro_mgr,
+ struct skb_frag_struct *frags,
+ int len, int true_size, void *priv);
+
+void lro_vlan_hwaccel_receive_frags(struct net_lro_mgr *lro_mgr,
+ struct skb_frag_struct *frags,
+ int len,
+ int true_size,
+ struct vlan_group *vgrp,
+ u16 vlan_tag,
+ void *priv);
+
+/*
+ * Forward all aggregated SKBs held by lro_mgr to network stack
+ */
+
+void lro_flush_all(struct net_lro_mgr *lro_mgr);
+
+void lro_flush_pkt(struct net_lro_mgr *lro_mgr,
+ struct iphdr *iph, struct tcphdr *tcph);
+
+#endif
diff --git a/net/ipv4/inet_lro.c b/net/ipv4/inet_lro.c
new file mode 100644
index 0000000..9eac24d
--- /dev/null
+++ b/net/ipv4/inet_lro.c
@@ -0,0 +1,549 @@
+/*
+ * linux/net/ipv4/inet_lro.c
+ *
+ * Large Receive Offload (ipv4 / tcp)
+ *
+ * (C) Copyright IBM Corp. 2007
+ *
+ * Authors:
+ * Jan-Bernd Themann <themann@de.ibm.com>
+ * Christoph Raisch <raisch@de.ibm.com>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#include <linux/module.h>
+#include <linux/if_vlan.h>
+
+#include <linux/inet_lro.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jan-Bernd Themann <themann@de.ibm.com>");
+MODULE_DESCRIPTION("Large Receive Offload (ipv4 / tcp)");
+
+#define TCP_HDR_LEN(tcph) (tcph->doff << 2)
+#define IP_HDR_LEN(iph) (iph->ihl << 2)
+#define TCP_PAYLOAD_LENGTH(iph, tcph) \
+(ntohs(iph->tot_len) - IP_HDR_LEN(iph) - TCP_HDR_LEN(tcph))
+
+#define IPH_LEN_WO_OPTIONS 5
+#define TCPH_LEN_WO_OPTIONS 5
+#define TCPH_LEN_W_TIMESTAMP 8
+
+/*
+ * Basic tcp checks whether packet is suitable for LRO
+ */
+
+static int lro_tcp_ip_check(struct iphdr *iph, struct tcphdr *tcph,
+ int len, struct net_lro_desc *lro_desc)
+{
+ /* check ip header: packet length */
+ if (ntohs(iph->tot_len) > len)
+ return -1;
+
+ if (TCP_PAYLOAD_LENGTH(iph, tcph) == 0)
+ return -1;
+
+ if (iph->ihl != IPH_LEN_WO_OPTIONS)
+ return -1;
+
+ if (tcph->cwr || tcph->ece || tcph->urg || !tcph->ack
+ || tcph->rst || tcph->syn || tcph->fin)
+ return -1;
+
+ if (INET_ECN_is_ce(ipv4_get_dsfield(iph)))
+ return -1;
+
+ if (tcph->doff != TCPH_LEN_WO_OPTIONS
+ && tcph->doff != TCPH_LEN_W_TIMESTAMP)
+ return -1;
+
+ /* check tcp options (only timestamp allowed) */
+ if (tcph->doff == TCPH_LEN_W_TIMESTAMP) {
+ u32 *topt = (u32 *)(tcph + 1);
+
+ if (*topt != htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16)
+ | (TCPOPT_TIMESTAMP << 8)
+ | TCPOLEN_TIMESTAMP))
+ return -1;
+
+ /* timestamp should be in right order */
+ topt++;
+ if (lro_desc && after(ntohl(lro_desc->tcp_rcv_tsval),
+ ntohl(*topt)))
+ return -1;
+
+ /* timestamp reply should not be zero */
+ topt++;
+ if (*topt == 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+static void lro_update_tcp_ip_header(struct net_lro_desc *lro_desc)
+{
+ struct iphdr *iph = lro_desc->iph;
+ struct tcphdr *tcph = lro_desc->tcph;
+ u32 *p;
+ __wsum tcp_hdr_csum;
+
+ tcph->ack_seq = lro_desc->tcp_ack;
+ tcph->window = lro_desc->tcp_window;
+
+ if (lro_desc->tcp_saw_tstamp) {
+ p = (u32 *)(tcph + 1);
+ *(p+2) = lro_desc->tcp_rcv_tsecr;
+ }
+
+ iph->tot_len = htons(lro_desc->ip_tot_len);
+
+ iph->check = 0;
+ iph->check = ip_fast_csum((u8 *)lro_desc->iph, iph->ihl);
+
+ tcph->check = 0;
+ tcp_hdr_csum = csum_partial((u8 *)tcph, TCP_HDR_LEN(tcph), 0);
+ lro_desc->data_csum = csum_add(lro_desc->data_csum, tcp_hdr_csum);
+ tcph->check = csum_tcpudp_magic(iph->saddr, iph->daddr,
+ htons(lro_desc->ip_tot_len) -
+ IP_HDR_LEN(iph), IPPROTO_TCP,
+ lro_desc->data_csum);
+
+}
+
+static __wsum lro_tcp_data_csum(struct iphdr *iph, struct tcphdr *tcph, int len)
+{
+ __wsum tcp_csum;
+ __wsum tcp_hdr_csum;
+ __wsum tcp_ps_hdr_csum;
+
+ tcp_csum = ~csum_unfold(tcph->check);
+ tcp_hdr_csum = csum_partial((u8 *)tcph, TCP_HDR_LEN(tcph), tcp_csum);
+
+ tcp_ps_hdr_csum = csum_tcpudp_nofold(iph->saddr, iph->daddr,
+ len + TCP_HDR_LEN(tcph),
+ IPPROTO_TCP, 0);
+
+ return csum_sub(csum_sub(tcp_csum, tcp_hdr_csum),
+ tcp_ps_hdr_csum);
+
+}
+
+static void lro_init_desc(struct net_lro_desc *lro_desc, struct sk_buff *skb,
+ struct iphdr *iph, struct tcphdr *tcph,
+ u16 vlan_tag, struct vlan_group *vgrp)
+{
+ int nr_frags;
+ u32 *ptr;
+ u32 tcp_data_len = TCP_PAYLOAD_LENGTH(iph, tcph);
+
+ nr_frags = skb_shinfo(skb)->nr_frags;
+ lro_desc->parent = skb;
+ lro_desc->next_frag = &(skb_shinfo(skb)->frags[nr_frags]);
+ lro_desc->iph = iph;
+ lro_desc->tcph = tcph;
+ lro_desc->tcp_next_seq = ntohl(tcph->seq) + tcp_data_len;
+ lro_desc->tcp_ack = ntohl(tcph->ack_seq);
+ lro_desc->tcp_window = tcph->window;
+
+ lro_desc->pkt_aggr_cnt = 1;
+ lro_desc->ip_tot_len = ntohs(iph->tot_len);
+
+ if (tcph->doff == 8) {
+ ptr = (u32 *)(tcph+1);
+ lro_desc->tcp_saw_tstamp = 1;
+ lro_desc->tcp_rcv_tsval = *(ptr+1);
+ lro_desc->tcp_rcv_tsecr = *(ptr+2);
+ }
+
+ lro_desc->vgrp = vgrp;
+ lro_desc->vlan_tag = vlan_tag;
+ lro_desc->active = 1;
+
+ lro_desc->data_csum = lro_tcp_data_csum(iph, tcph,
+ tcp_data_len);
+}
+
+static inline void lro_clear_desc(struct net_lro_desc *lro_desc)
+{
+ memset(lro_desc, 0, sizeof(struct net_lro_desc));
+}
+
+static void lro_add_common(struct net_lro_desc *lro_desc, struct iphdr *iph,
+ struct tcphdr *tcph, int tcp_data_len)
+{
+ struct sk_buff *parent = lro_desc->parent;
+ u32 *topt;
+
+ lro_desc->pkt_aggr_cnt++;
+ lro_desc->ip_tot_len += tcp_data_len;
+ lro_desc->tcp_next_seq += tcp_data_len;
+ lro_desc->tcp_window = tcph->window;
+ lro_desc->tcp_ack = tcph->ack_seq;
+
+ /* don't update tcp_rcv_tsval, would not work with PAWS */
+ if (lro_desc->tcp_saw_tstamp) {
+ topt = (u32 *) (tcph + 1);
+ lro_desc->tcp_rcv_tsecr = *(topt + 2);
+ }
+
+ parent->len += tcp_data_len;
+ parent->data_len += tcp_data_len;
+
+ lro_desc->data_csum = csum_add(lro_desc->data_csum,
+ lro_tcp_data_csum(iph, tcph,
+ tcp_data_len));
+ return;
+}
+
+static void lro_add_packet(struct net_lro_desc *lro_desc, struct sk_buff *skb,
+ struct iphdr *iph, struct tcphdr *tcph)
+{
+ struct sk_buff *parent = lro_desc->parent;
+ int tcp_data_len = TCP_PAYLOAD_LENGTH(iph, tcph);
+
+ lro_add_common(lro_desc, iph, tcph, tcp_data_len);
+
+ skb_pull(skb, (skb->len - tcp_data_len));
+ parent->truesize += skb->truesize;
+
+ if (lro_desc->last_skb)
+ lro_desc->last_skb->next = skb;
+ else
+ skb_shinfo(parent)->frag_list = skb;
+
+ lro_desc->last_skb = skb;
+ return;
+}
+
+static void lro_add_frags(struct net_lro_desc *lro_desc,
+ int len, int hlen, int truesize,
+ struct skb_frag_struct *skb_frags,
+ struct iphdr *iph, struct tcphdr *tcph)
+{
+ struct sk_buff *skb = lro_desc->parent;
+ int tcp_data_len = TCP_PAYLOAD_LENGTH(iph, tcph);
+
+ lro_add_common(lro_desc, iph, tcph, tcp_data_len);
+
+ skb->truesize += truesize;
+
+ skb_frags[0].page_offset += hlen;
+ skb_frags[0].size -= hlen;
+
+ while (tcp_data_len > 0) {
+ *(lro_desc->next_frag) = *skb_frags;
+ tcp_data_len -= skb_frags->size;
+ lro_desc->next_frag++;
+ skb_frags++;
+ skb_shinfo(skb)->nr_frags++;
+ }
+
+ return;
+}
+
+static int lro_check_tcp_conn(struct net_lro_desc *lro_desc,
+ struct iphdr *iph,
+ struct tcphdr *tcph)
+{
+ if ((lro_desc->iph->saddr != iph->saddr)
+ || (lro_desc->iph->daddr != iph->daddr)
+ || (lro_desc->tcph->source != tcph->source)
+ || (lro_desc->tcph->dest != tcph->dest))
+ return -1;
+ return 0;
+}
+
+static struct net_lro_desc *lro_get_desc(struct net_lro_mgr *mgr,
+ struct net_lro_desc *lro_arr,
+ struct iphdr *iph,
+ struct tcphdr *tcph)
+{
+ struct net_lro_desc *lro_desc = NULL;
+ struct net_lro_desc *tmp;
+ int max_desc = mgr->max_desc;
+ int i;
+
+ for (i = 0; i < max_desc; i++) {
+ tmp = &lro_arr[i];
+ if (tmp->active)
+ if (!lro_check_tcp_conn(tmp, iph, tcph)) {
+ lro_desc = tmp;
+ goto out;
+ }
+ }
+
+ for (i = 0; i < max_desc; i++) {
+ if(!lro_arr[i].active) {
+ lro_desc = &lro_arr[i];
+ goto out;
+ }
+ }
+
+out:
+ return lro_desc;
+}
+
+static void lro_flush(struct net_lro_desc *lro_desc)
+{
+ if (lro_desc->pkt_aggr_cnt > 1)
+ lro_update_tcp_ip_header(lro_desc);
+
+ if (lro_desc->vgrp)
+ vlan_hwaccel_receive_skb(lro_desc->parent, lro_desc->vgrp,
+ lro_desc->vlan_tag);
+ else
+ netif_receive_skb(lro_desc->parent);
+
+ lro_clear_desc(lro_desc);
+}
+
+void lro_flush_all(struct net_lro_mgr *lro_mgr)
+{
+ int i;
+ struct net_lro_desc *lro_desc = lro_mgr->lro_arr;
+
+ for (i = 0; i < lro_mgr->max_desc; i++) {
+ if (lro_desc[i].active)
+ lro_flush(&lro_desc[i]);
+ }
+}
+EXPORT_SYMBOL(lro_flush_all);
+
+int __lro_proc_skb(struct net_lro_mgr *lro_mgr, struct sk_buff *skb,
+ struct vlan_group *vgrp, u16 vlan_tag, void *priv)
+{
+ struct net_lro_desc *lro_desc;
+ struct iphdr *iph;
+ struct tcphdr *tcph;
+ u64 flags;
+
+ if (!lro_mgr->get_skb_header
+ || lro_mgr->get_skb_header(skb, (void *)&iph, (void *)&tcph,
+ &flags, priv))
+ goto out;
+
+ if (!(flags & LRO_IPV4) || !(flags & LRO_TCP))
+ goto out;
+
+ lro_desc = lro_get_desc(lro_mgr, lro_mgr->lro_arr, iph, tcph);
+ if (!lro_desc)
+ goto out;
+
+ if (!lro_desc->active) { /* start new lro session */
+ if (lro_tcp_ip_check(iph, tcph, skb->len, NULL))
+ goto out;
+
+ lro_init_desc(lro_desc, skb, iph, tcph, vlan_tag, vgrp);
+ return 0;
+ }
+
+ if (lro_desc->tcp_next_seq != ntohl(tcph->seq))
+ goto out2;
+
+ if (lro_tcp_ip_check(iph, tcph, skb->len, lro_desc))
+ goto out2;
+
+ lro_add_packet(lro_desc, skb, iph, tcph);
+
+ if (lro_desc->pkt_aggr_cnt >= lro_mgr->max_aggr)
+ lro_flush(lro_desc);
+
+ return 0;
+
+out2: /* send aggregated SKBs to stack */
+ lro_flush(lro_desc);
+
+out: /* Original SKB has to be posted to stack */
+ return 1;
+}
+
+void lro_receive_skb(struct net_lro_mgr *lro_mgr,
+ struct sk_buff *skb,
+ void *priv)
+{
+ if (__lro_proc_skb(lro_mgr, skb, NULL, 0, priv))
+ netif_receive_skb(skb);
+}
+EXPORT_SYMBOL(lro_receive_skb);
+
+void lro_vlan_hwaccel_receive_skb(struct net_lro_mgr *lro_mgr,
+ struct sk_buff *skb,
+ struct vlan_group *vgrp,
+ u16 vlan_tag,
+ void *priv)
+{
+ if (__lro_proc_skb(lro_mgr, skb, vgrp, vlan_tag, priv))
+ vlan_hwaccel_receive_skb(skb, vgrp, vlan_tag);
+}
+EXPORT_SYMBOL(lro_vlan_hwaccel_receive_skb);
+
+#define LRO_MIN_PG_HLEN 80
+
+struct sk_buff *lro_gen_skb(struct net_lro_mgr *lro_mgr,
+ struct skb_frag_struct *frags,
+ int len, int true_size,
+ void *mac_hdr,
+ int hlen)
+{
+ struct sk_buff *skb;
+ struct skb_frag_struct *skb_frags;
+ int data_len = len;
+
+ skb = netdev_alloc_skb(lro_mgr->dev, hlen);
+ if (!skb)
+ return NULL;
+
+ skb->len = len;
+ skb->data_len = len - hlen;
+ skb->truesize += true_size;
+ skb->tail += hlen;
+
+ memcpy(skb->data, mac_hdr, hlen);
+
+ skb_frags = skb_shinfo(skb)->frags;
+ while (data_len > 0) {
+ *skb_frags = *frags;
+ data_len -= frags->size;
+ skb_frags++;
+ frags++;
+ skb_shinfo(skb)->nr_frags++;
+ }
+
+ skb_shinfo(skb)->frags[0].page_offset += hlen;
+ skb_shinfo(skb)->frags[0].size -= hlen;
+
+ skb->ip_summed = lro_mgr->ip_summed;
+ skb->protocol = eth_type_trans(skb, lro_mgr->dev);
+ return skb;
+}
+
+struct sk_buff *__lro_proc_segment(struct net_lro_mgr *lro_mgr,
+ struct skb_frag_struct *frags,
+ int len, int true_size,
+ struct vlan_group *vgrp,
+ u16 vlan_tag, void *priv)
+{
+ struct net_lro_desc *lro_desc;
+ struct iphdr *iph;
+ struct tcphdr *tcph;
+ struct sk_buff *skb;
+ void *mac_hdr;
+ u64 flags;
+ int hdr_len = 0;
+
+ if (!lro_mgr->get_frag_header
+ || lro_mgr->get_frag_header(frags, (void *)&mac_hdr, (void *)&iph,
+ (void *)&tcph, &flags, priv)) {
+ mac_hdr = page_address(frags->page) + frags->page_offset;
+ goto out1;
+ }
+
+ if (!(flags & LRO_IPV4) || !(flags & LRO_TCP))
+ goto out1;
+
+ lro_desc = lro_get_desc(lro_mgr, lro_mgr->lro_arr, iph, tcph);
+ if (!lro_desc)
+ goto out1;
+
+ hdr_len = (int)((void *)(tcph) + TCP_HDR_LEN(tcph) - mac_hdr);
+
+ if (!lro_desc->active) { /* start new lro session */
+ if (lro_tcp_ip_check(iph, tcph, len, NULL))
+ goto out1;
+
+ skb = lro_gen_skb(lro_mgr, frags,
+ len, true_size, mac_hdr,
+ max(hdr_len, LRO_MIN_PG_HLEN));
+ if (!skb)
+ goto out;
+
+ iph = (void *)(skb->data);
+ tcph = (void *)((u8 *)skb->data + IP_HDR_LEN(iph));
+
+ lro_init_desc(lro_desc, skb, iph, tcph, 0, NULL);
+ return 0;
+ }
+
+ if (lro_desc->tcp_next_seq != ntohl(tcph->seq))
+ goto out2;
+
+ if (lro_tcp_ip_check(iph, tcph, len, lro_desc))
+ goto out2;
+
+ lro_add_frags(lro_desc, len, hdr_len, true_size, frags, iph, tcph);
+
+ if ((skb_shinfo(lro_desc->parent)->nr_frags >= lro_mgr->max_aggr) ||
+ lro_desc->parent->len > 65535) /* good idea? */
+ lro_flush(lro_desc);
+
+ return NULL;
+
+out2: /* send aggregated packets to the stack */
+ lro_flush(lro_desc);
+
+out1: /* Original packet has to be posted to the stack */
+ skb = lro_gen_skb(lro_mgr, frags,
+ len, true_size, mac_hdr,
+ max(hdr_len, LRO_MIN_PG_HLEN));
+out:
+ return skb;
+}
+
+void lro_receive_frags(struct net_lro_mgr *lro_mgr,
+ struct skb_frag_struct *frags,
+ int len, int true_size, void *priv)
+{
+ struct sk_buff *skb;
+
+ skb = __lro_proc_segment(lro_mgr, frags, len, true_size, NULL, 0, priv);
+ if(skb)
+ netif_receive_skb(skb);
+}
+
+EXPORT_SYMBOL(lro_receive_frags);
+
+void lro_vlan_hwaccel_receive_frags(struct net_lro_mgr *lro_mgr,
+ struct skb_frag_struct *frags,
+ int len,
+ int true_size,
+ struct vlan_group *vgrp,
+ u16 vlan_tag,
+ void *priv)
+{
+ struct sk_buff *skb;
+
+ skb = __lro_proc_segment(lro_mgr, frags, len, true_size, vgrp,
+ vlan_tag, priv);
+ if(skb)
+ vlan_hwaccel_receive_skb(skb, vgrp, vlan_tag);
+}
+
+EXPORT_SYMBOL(lro_vlan_hwaccel_receive_frags);
+
+void lro_flush_pkt(struct net_lro_mgr *lro_mgr,
+ struct iphdr *iph, struct tcphdr *tcph)
+{
+ struct net_lro_desc *lro_desc;
+
+ lro_desc = lro_get_desc(lro_mgr, lro_mgr->lro_arr, iph, tcph);
+ if (lro_desc->active)
+ lro_flush(lro_desc);
+}
+
+EXPORT_SYMBOL(lro_flush_pkt);
--
1.5.2
^ permalink raw reply related
* [RFC 0/1] lro: Generic Large Receive Offload for TCP traffic
From: Jan-Bernd Themann @ 2007-07-20 15:41 UTC (permalink / raw)
To: netdev
Cc: Thomas Klein, Jeff Garzik, Jan-Bernd Themann, linux-kernel,
linux-ppc, Christoph Raisch, Marcus Eder, Stefan Roscher,
David Miller
Hi,
Thanks a lot for your comments so far.
This generic LRO patch differs from the last one in several points.
A new interface for a "receive in pages" mode has been added and tested
with an eHEA prototype. Seems to work well.
Does this extended interface seem to be sufficient?
Below some more explanations:
Thanks,
Jan-Bernd
Changes to http://www.spinics.net/lists/netdev/msg35490.html :
- Interfaces are changed to allow later support for IPv6 / UDP
- New interface to support "receive in pages"
- TCP checksums are updated properly
- TCP packets with push flag are aggregated now
- Timestamps are now compared using after()
The additional interface to support "receive in pages":
void lro_receive_frags(struct net_lro_mgr *lro_mgr,
struct skb_frag_struct *frags,
int len, int true_size, void *priv);
void lro_vlan_hwaccel_receive_frags(struct net_lro_mgr *lro_mgr,
struct skb_frag_struct *frags,
int len,
int true_size,
struct vlan_group *vgrp,
u16 vlan_tag,
void *priv);
These functions generate SKBs only for the first packet of an
LRO session. The next fragment list to be aggregated will be
added in the fragment list of that SKB.
The reason why this is a smart approach is described in:
http://www.spinics.net/lists/netdev/msg35634.html
All other packets that do not match the LRO requirements are
put in an SKB and sent to the stack.
Packets that are received in an extra buffer (small packets) and
thus not in an skb fragment can be sent by the driver to the stack
after flushing the appropriate LRO sessions:
void lro_flush_pkt(struct net_lro_mgr *lro_mgr,
struct iphdr *iph, struct tcphdr *tcph);
or
void lro_flush_all(struct net_lro_mgr *lro_mgr);
^ permalink raw reply
* Re: [PATCH 1/1] Allow LSM to use IP address/port number.
From: James Morris @ 2007-07-20 15:28 UTC (permalink / raw)
To: Tetsuo Handa; +Cc: shemminger, netdev, linux-security-module, Patrick McHardy
In-Reply-To: <200707210011.HBI60217.FUNOWSFPGEt@I-love.SAKURA.ne.jp>
On Sat, 21 Jul 2007, Tetsuo Handa wrote:
> I can't use netfilter infrastructure because
> it is too early to know who the recipant process of the packet is.
I think the way forward on this is to re-visit the idea of providing a
proper solution for the incoming packet/user match problem.
I posted one possible solution a couple of years ago (skfilter):
http://lwn.net/Articles/157137/
I think there has been some recent discussion by netfilter developers
about this issue, so perhaps you could talk to them (cd'd Patrick).
- James
--
James Morris
<jmorris@namei.org>
^ permalink raw reply
* Re: [PATCH] sky2 breakage
From: Stephen Hemminger @ 2007-07-20 15:11 UTC (permalink / raw)
To: Al Viro; +Cc: Linus Torvalds, jgarzik, netdev
In-Reply-To: <20070720150733.GG21668@ftp.linux.org.uk>
On Fri, 20 Jul 2007 16:07:33 +0100
Al Viro <viro@ftp.linux.org.uk> wrote:
> Doing |= 1 << 19 to 16bit unsigned is not particulary useful;
> that register is 32bit, unlike the ones dealt with in the rest of
> function, so we need u32 variable here.
>
> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Yes, thanks. This only applies to the YUKON_EX hardware support
that is new (post 2.6.22), and no one but me has the boards yet,
so not a big impact.
^ permalink raw reply
* [PATCH 1/1] Allow LSM to use IP address/port number.
From: Tetsuo Handa @ 2007-07-20 15:11 UTC (permalink / raw)
To: jmorris, shemminger; +Cc: netdev, linux-security-module
In-Reply-To: <Line.LNX.4.64.0707091940450.10029@d.namei>
Hello.
> > Isn't it better to hook into existing netfilter infrastructure somehow?
> Yes, it has been suggested several times.
I want to use a process's context who issued
accept()/recv()/recvfrom()/recvmsg()/read() requests.
But Stephen Smalley said at http://marc.info/?l=linux-security-module&m=118459899017487&w=2 that
> The socket can be inherited by a child task or passed via local IPC to
> an unrelated task, and then used by those other tasks. It isn't tied to
> the original allocating task's lifecycle in any way, nor is it
> guaranteed to only be used by that original allocating task. It can
> exist in zero, one or many tasks' file tables and still be receiving
> data, and can go from completely disassociated (i.e. not present in any
> tasks' file tables) to being associated.
I can't use netfilter infrastructure because
it is too early to know who the recipant process of the packet is.
The only chance to perform ip/port based filtering
using ACLs associated with the recipant process of the packet
is post-accept() and post-recvmsg().
Therefore, I re-post my patch again.
Regards.
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
---
include/linux/security.h | 44 +++++++++++++++++++++++++++++++++++++-------
net/socket.c | 42 ++++++++++++++++++++++++++++++++++++------
security/dummy.c | 13 ++++++++++---
3 files changed, 83 insertions(+), 16 deletions(-)
diff -upr a/include/linux/security.h b/include/linux/security.h
--- a/include/linux/security.h 2007-07-20 22:55:38.000000000 +0900
+++ b/include/linux/security.h 2007-07-20 23:15:58.000000000 +0900
@@ -749,8 +749,12 @@ struct request_sock;
* @socket_post_accept:
* This hook allows a security module to copy security
* information into the newly created socket's inode.
+ * This hook also allows a security module to filter connections
+ * from unwanted peers.
+ * The connection will be aborted if this hook returns nonzero.
* @sock contains the listening socket structure.
* @newsock contains the newly created server socket for connection.
+ * Return 0 if permission is granted.
* @socket_sendmsg:
* Check permission before transmitting a message to another socket.
* @sock contains the socket structure.
@@ -764,6 +768,15 @@ struct request_sock;
* @size contains the size of message structure.
* @flags contains the operational flags.
* Return 0 if permission is granted.
+ * @socket_post_recvmsg:
+ * Check peer's address after receiving a message from a socket.
+ * This hook allows a security module to filter messages
+ * from unwanted peers.
+ * @sock contains the socket structure.
+ * @msg contains the message structure.
+ * @size contains the size of message structure.
+ * @flags contains the operational flags.
+ * Return 0 if permission is granted.
* @socket_getsockname:
* Check permission before the local address (name) of the socket object
* @sock is retrieved.
@@ -1345,12 +1358,14 @@ struct security_operations {
struct sockaddr * address, int addrlen);
int (*socket_listen) (struct socket * sock, int backlog);
int (*socket_accept) (struct socket * sock, struct socket * newsock);
- void (*socket_post_accept) (struct socket * sock,
- struct socket * newsock);
+ int (*socket_post_accept) (struct socket *sock,
+ struct socket *newsock);
int (*socket_sendmsg) (struct socket * sock,
struct msghdr * msg, int size);
int (*socket_recvmsg) (struct socket * sock,
struct msghdr * msg, int size, int flags);
+ int (*socket_post_recvmsg) (struct socket *sock, struct msghdr *msg,
+ int size, int flags);
int (*socket_getsockname) (struct socket * sock);
int (*socket_getpeername) (struct socket * sock);
int (*socket_getsockopt) (struct socket * sock, int level, int optname);
@@ -2860,10 +2875,10 @@ static inline int security_socket_accept
return security_ops->socket_accept(sock, newsock);
}
-static inline void security_socket_post_accept(struct socket * sock,
- struct socket * newsock)
+static inline int security_socket_post_accept(struct socket *sock,
+ struct socket *newsock)
{
- security_ops->socket_post_accept(sock, newsock);
+ return security_ops->socket_post_accept(sock, newsock);
}
static inline int security_socket_sendmsg(struct socket * sock,
@@ -2879,6 +2894,13 @@ static inline int security_socket_recvms
return security_ops->socket_recvmsg(sock, msg, size, flags);
}
+static inline int security_socket_post_recvmsg(struct socket *sock,
+ struct msghdr *msg,
+ int size, int flags)
+{
+ return security_ops->socket_post_recvmsg(sock, msg, size, flags);
+}
+
static inline int security_socket_getsockname(struct socket * sock)
{
return security_ops->socket_getsockname(sock);
@@ -3023,9 +3045,10 @@ static inline int security_socket_accept
return 0;
}
-static inline void security_socket_post_accept(struct socket * sock,
- struct socket * newsock)
+static inline int security_socket_post_accept(struct socket *sock,
+ struct socket *newsock)
{
+ return 0;
}
static inline int security_socket_sendmsg(struct socket * sock,
@@ -3041,6 +3064,13 @@ static inline int security_socket_recvms
return 0;
}
+static inline int security_socket_post_recvmsg(struct socket *sock,
+ struct msghdr *msg,
+ int size, int flags)
+{
+ return 0;
+}
+
static inline int security_socket_getsockname(struct socket * sock)
{
return 0;
diff -upr a/net/socket.c b/net/socket.c
--- a/net/socket.c 2007-07-20 22:55:53.000000000 +0900
+++ b/net/socket.c 2007-07-21 00:05:18.000000000 +0900
@@ -635,7 +635,19 @@ static inline int __sock_recvmsg(struct
if (err)
return err;
- return sock->ops->recvmsg(iocb, sock, msg, size, flags);
+ err = sock->ops->recvmsg(iocb, sock, msg, size, flags);
+ /*
+ * Filter messages from unwanted peers.
+ * To be exact, this hook can't filter messages,
+ * this hook just returns an error code.
+ */
+ if (err >= 0) {
+ int ret;
+ ret = security_socket_post_recvmsg(sock, msg, size, flags);
+ if (ret)
+ err = ret;
+ }
+ return err;
}
int sock_recvmsg(struct socket *sock, struct msghdr *msg,
@@ -648,8 +660,17 @@ int sock_recvmsg(struct socket *sock, st
init_sync_kiocb(&iocb, NULL);
iocb.private = &siocb;
ret = __sock_recvmsg(&iocb, sock, msg, size, flags);
- if (-EIOCBQUEUED == ret)
+ if (-EIOCBQUEUED == ret) {
ret = wait_on_sync_kiocb(&iocb);
+ /* I can now check security_socket_post_recvmsg(). */
+ if (ret >= 0) {
+ int err;
+ err = security_socket_post_recvmsg(sock, msg, size,
+ flags);
+ if (err)
+ ret = err;
+ }
+ }
return ret;
}
@@ -712,12 +733,14 @@ static ssize_t do_sock_read(struct msghd
struct socket *sock = file->private_data;
size_t size = 0;
int i;
+ /* only for security_socket_post_recvmsg() */
+ char address[MAX_SOCK_ADDR];
for (i = 0; i < nr_segs; i++)
size += iov[i].iov_len;
- msg->msg_name = NULL;
- msg->msg_namelen = 0;
+ msg->msg_name = address;
+ msg->msg_namelen = sizeof(address);
msg->msg_control = NULL;
msg->msg_controllen = 0;
msg->msg_iov = (struct iovec *)iov;
@@ -1437,13 +1460,16 @@ asmlinkage long sys_accept(int fd, struc
goto out_fd;
}
+ /* Filter connections from unwanted peers like TCP Wrapper. */
+ err = security_socket_post_accept(sock, newsock);
+ if (err)
+ goto out_fd;
+
/* File flags are not inherited via accept() unlike another OSes. */
fd_install(newfd, newfile);
err = newfd;
- security_socket_post_accept(sock, newsock);
-
out_put:
fput_light(sock->file, fput_needed);
out:
@@ -1937,6 +1963,10 @@ asmlinkage long sys_recvmsg(int fd, stru
goto out_freeiov;
total_len = err;
+ /* only for security_socket_post_recvmsg() */
+ msg_sys.msg_name = addr;
+ msg_sys.msg_namelen = sizeof(addr);
+
cmsg_ptr = (unsigned long)msg_sys.msg_control;
msg_sys.msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT);
diff -upr a/security/dummy.c b/security/dummy.c
--- a/security/dummy.c 2007-07-20 22:55:54.000000000 +0900
+++ b/security/dummy.c 2007-07-20 23:15:22.000000000 +0900
@@ -741,10 +741,10 @@ static int dummy_socket_accept (struct s
return 0;
}
-static void dummy_socket_post_accept (struct socket *sock,
- struct socket *newsock)
+static int dummy_socket_post_accept(struct socket *sock,
+ struct socket *newsock)
{
- return;
+ return 0;
}
static int dummy_socket_sendmsg (struct socket *sock, struct msghdr *msg,
@@ -759,6 +759,12 @@ static int dummy_socket_recvmsg (struct
return 0;
}
+static int dummy_socket_post_recvmsg(struct socket *sock, struct msghdr *msg,
+ int size, int flags)
+{
+ return 0;
+}
+
static int dummy_socket_getsockname (struct socket *sock)
{
return 0;
@@ -1096,6 +1102,7 @@ void security_fixup_ops (struct security
set_to_dummy_if_null(ops, socket_post_accept);
set_to_dummy_if_null(ops, socket_sendmsg);
set_to_dummy_if_null(ops, socket_recvmsg);
+ set_to_dummy_if_null(ops, socket_post_recvmsg);
set_to_dummy_if_null(ops, socket_getsockname);
set_to_dummy_if_null(ops, socket_getpeername);
set_to_dummy_if_null(ops, socket_setsockopt);
^ permalink raw reply
* Re: [PATCH 1/1] netxen: Load firmware during probe, dma watchdog fix.
From: Dhananjay Phadke @ 2007-07-20 14:43 UTC (permalink / raw)
To: netdev; +Cc: dhananjay, rob, Milan Bag, Wen Xiong
In-Reply-To: <20070719091131.467737478@netxen.com>
Please ignore this patch. There's one more patch in the series. I will
send them together.
Thanks,
-Dhananjay
^ permalink raw reply
* Re: [GENETLINK]: Question: global lock (genl_mutex) possible refinement?
From: Patrick McHardy @ 2007-07-20 14:00 UTC (permalink / raw)
To: Richard MUSIL; +Cc: netdev
In-Reply-To: <46A0BF7F.80001@st.com>
[ Please quote and break your lines appropriately ]
Richard MUSIL wrote:
> Patrick McHardy wrote:
>>
>>The usual way to do this for auto-loading of modules that register
>>things that take a mutex that is already held during netlink queue
>>processing, like qdiscs, classifiers, .. is:
>>
>>- look for <qdisc/classifier/...>, if not found:
>>- drop mutex (using the __ unlock variant to avoid reentering queue
>>processing)
>>- perform module loading (which takes the mutex and registers itself)
>>- grab mutex again
>>- look for <qdisc/classifier/...> again
>>- if not found return -ENOENT
>>- if found drop reference, return -EAGAIN
>>
>>The caller is changed to handle -EAGAIN by replaying the entire
>>request. Your problem sounds very similar, look at net/sched/sch_api.c
>>for an example.
>
>
> The aforementioned mutex is local to genetlink module, so I cannot temporarily drop it, call the stuff and grab it again (which was mine original thought too).
Export the lock/unlock/.. functions. You'll also need a new version
similar to __rtnl_unlock.
^ permalink raw reply
* Re: [GENETLINK]: Question: global lock (genl_mutex) possible refinement?
From: Richard MUSIL @ 2007-07-20 13:58 UTC (permalink / raw)
To: netdev; +Cc: Patrick McHardy
In-Reply-To: <46A0B6DE.1080904@trash.net>
Patrick McHardy wrote:
> Richard MUSIL wrote:
>> I am currently trying to write a module which communicates with user
>> space using NETLINK_GENERIC. This module (dev_mgr) manages virtual
>> devices which are also supposed to use genetlink for communication
>> with user space.
>>
>> I want to do something like that:
>> dev_mgr <- receives message from user space to create new device
>> dev_mgr inside 'doit' handler:
>> 1. creates device
>> 2. registers new genetlink family for the device
>> 3. returns family name and id to user
>>
>> This should work similarly for device removal.
>>
>> After few reboots I found out that 2. blocks on genl_mutex, since this
>> mutex is already acquired when genl_register_family is called (by
>> genl_rcv).
>>
>> I do not see why registering new family (when processing message for
>> another family) should be a problem. In fact from genl_lock and
>> genl_trylock occurrence it seems that genl_mutex is mostly used for
>> syncing access to family list and also for message processing.
>> Since I am not (yet) familiar enough with (ge)netlink internals I am
>> asking:
>> Would it make sense to split the mutex into two, one for family list
>> and one for messaging, so it would be possible to change families when
>> processing the message?
>>
>> Simple split could introduce possible danger of user removing family
>> inside processing of the message for this particular family, but would
>> this really be a danger?
>>
>
> The usual way to do this for auto-loading of modules that register
> things that take a mutex that is already held during netlink queue
> processing, like qdiscs, classifiers, .. is:
>
> - look for <qdisc/classifier/...>, if not found:
> - drop mutex (using the __ unlock variant to avoid reentering queue
> processing)
> - perform module loading (which takes the mutex and registers itself)
> - grab mutex again
> - look for <qdisc/classifier/...> again
> - if not found return -ENOENT
> - if found drop reference, return -EAGAIN
>
> The caller is changed to handle -EAGAIN by replaying the entire
> request. Your problem sounds very similar, look at net/sched/sch_api.c
> for an example.
The aforementioned mutex is local to genetlink module, so I cannot temporarily drop it, call the stuff and grab it again (which was mine original thought too).
In fact the only way to go around (without changing the genetlink) seems to schedule the family registration to some other context outside message processing. But this would be clearly much more complex than doing it directly in message handler and also a bit against "ease of use" which genetlink is supposed to offer.
My question was if its really necessary to sync both message processing and genetlink family management on one primitive. I believe it is not, but I would rather be happy if someone who maintains it confirm this theory. Meanwhile I am going to do quick mod to genetlink and if it goes well, post the patch, which seems to be quite simple.
--
Richard
^ permalink raw reply
* Re: [GENETLINK]: Question: global lock (genl_mutex) possible refinement?
From: Patrick McHardy @ 2007-07-20 13:21 UTC (permalink / raw)
To: Richard MUSIL; +Cc: netdev
In-Reply-To: <46A0B017.4080505@st.com>
Richard MUSIL wrote:
> I am currently trying to write a module which communicates with user space using NETLINK_GENERIC. This module (dev_mgr) manages virtual devices which are also supposed to use genetlink for communication with user space.
>
> I want to do something like that:
> dev_mgr <- receives message from user space to create new device
> dev_mgr inside 'doit' handler:
> 1. creates device
> 2. registers new genetlink family for the device
> 3. returns family name and id to user
>
> This should work similarly for device removal.
>
> After few reboots I found out that 2. blocks on genl_mutex, since this mutex is already acquired when genl_register_family is called (by genl_rcv).
>
> I do not see why registering new family (when processing message for another family) should be a problem. In fact from genl_lock and genl_trylock occurrence it seems that genl_mutex is mostly used for syncing access to family list and also for message processing.
> Since I am not (yet) familiar enough with (ge)netlink internals I am asking:
> Would it make sense to split the mutex into two, one for family list and one for messaging, so it would be possible to change families when processing the message?
>
> Simple split could introduce possible danger of user removing family inside processing of the message for this particular family, but would this really be a danger?
>
The usual way to do this for auto-loading of modules that register
things that take a mutex that is already held during netlink queue
processing, like qdiscs, classifiers, .. is:
- look for <qdisc/classifier/...>, if not found:
- drop mutex (using the __ unlock variant to avoid reentering queue
processing)
- perform module loading (which takes the mutex and registers itself)
- grab mutex again
- look for <qdisc/classifier/...> again
- if not found return -ENOENT
- if found drop reference, return -EAGAIN
The caller is changed to handle -EAGAIN by replaying the entire
request. Your problem sounds very similar, look at net/sched/sch_api.c
for an example.
^ permalink raw reply
* [GENETLINK]: Question: global lock (genl_mutex) possible refinement?
From: Richard MUSIL @ 2007-07-20 12:52 UTC (permalink / raw)
To: netdev
I am currently trying to write a module which communicates with user space using NETLINK_GENERIC. This module (dev_mgr) manages virtual devices which are also supposed to use genetlink for communication with user space.
I want to do something like that:
dev_mgr <- receives message from user space to create new device
dev_mgr inside 'doit' handler:
1. creates device
2. registers new genetlink family for the device
3. returns family name and id to user
This should work similarly for device removal.
After few reboots I found out that 2. blocks on genl_mutex, since this mutex is already acquired when genl_register_family is called (by genl_rcv).
I do not see why registering new family (when processing message for another family) should be a problem. In fact from genl_lock and genl_trylock occurrence it seems that genl_mutex is mostly used for syncing access to family list and also for message processing.
Since I am not (yet) familiar enough with (ge)netlink internals I am asking:
Would it make sense to split the mutex into two, one for family list and one for messaging, so it would be possible to change families when processing the message?
Simple split could introduce possible danger of user removing family inside processing of the message for this particular family, but would this really be a danger?
--
Richard
^ permalink raw reply
* Re: [PATCH] IP_VS should depend on EXPERIMENTAL ?
From: Robert P. J. Day @ 2007-07-20 13:04 UTC (permalink / raw)
To: Gabriel C; +Cc: Linux Kernel Mailing List, netdev
In-Reply-To: <46A0AB44.70009@googlemail.com>
On Fri, 20 Jul 2007, Gabriel C wrote:
> Robert P. J. Day wrote:
> > this has *nothing* to do with the aforementioned maturity levels.
> > i understand entirely the inconsistency above. what i'm
> > suggesting is that it might very well be more appropriate to *drop
> > the dependency* rather than munge the prompt to add the qualifier.
>
> This is a thing the author/maintainer/subsystem maintainer should and need do.
>
> They know when something is not EXPERIMENTAL anymore.
agreed (sort of). all i'm saying (and after this, i'll shut the heck
up about it) is that, if you find a Kconfig entry of the form:
config FUBAR
prompt "whatever"
depends on ... && EXPERIMENTAL
and you want to make that selection consistent, you have two
possibilities:
1) add "(EXPERIMENTAL)" to the prompt to match the dependency, or
2) drop the dependency on EXPERIMENTAL to match the prompt
i contend that, *for now*, it's a better investment in time to find
entries like that that are *clearly* not experimental any more, and
drop the dependency. not only will that make it consistent, but it's
unlikely that you'll ever have to *revert* that decision.
OTOH, it's quite possible that, after you add the prompt suffix of
"(EXPERIMENTAL)" for consistency, the feature maintainer might come by
tomorrow and say something like, "nah, that feature's been around for
years, it's as stable as it gets," and will undo the patch you just
made, wasting your time and effort.
lastly, i'm not convinced that it's *only* the feature maintainer
that can make that decision. surely, there's enough clever people
here who can look at any given feature and say, "yeah, i've been using
that for years, it's rock solid, it's stupid to keep that dependent on
EXPERIMENTAL."
all i'm saying is, if you want to put some time in here, it's better
invested in *removing* what are clearly ridiculous dependencies on
EXPERIMENTAL, rather than *adding* even more of that labelling to the
tree.
rday
p.s. even if a given Kconfig entry *is* consistent, as in:
config SNAFU
bool "... (EXPERIMENTAL)"
depends on ... && EXPERIMENTAL
...
it's clear that there's a pile of *that* stuff for which all
references to EXPERIMENTAL can be dropped. all in all, given the
possible cleanup here, i'm thinking that going in and *adding* more
EXPERIMENTAL clutter to the Kconfig files is going in exactly the
wrong direction.
--
========================================================================
Robert P. J. Day
Linux Consulting, Training and Annoying Kernel Pedantry
Waterloo, Ontario, CANADA
http://fsdev.net/wiki/index.php?title=Main_Page
========================================================================
^ 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