Netdev List
 help / color / mirror / Atom feed
* Re: [patch 1/7] typhoon section fix
From: David Miller @ 2008-02-10  7:40 UTC (permalink / raw)
  To: akpm; +Cc: jeff, netdev, sam
In-Reply-To: <200802081120.m18BK6cL021623@imap1.linux-foundation.org>

From: akpm@linux-foundation.org
Date: Fri, 08 Feb 2008 03:11:13 -0800

> From: Andrew Morton <akpm@linux-foundation.org>
> 
> gcc-3.4.4 on powerpc:
> 
> drivers/net/typhoon.c:137: error: version causes a section type conflict
> 
> Cc: Jeff Garzik <jeff@garzik.org>
> Cc: Sam Ravnborg <sam@ravnborg.org>
> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

Applied.

^ permalink raw reply

* Re: [PATCH] isdn: fix section mismatch warning for ISACVer
From: David Miller @ 2008-02-10  7:29 UTC (permalink / raw)
  To: sam; +Cc: netdev, jeff, jgarzik
In-Reply-To: <1202500804-32020-2-git-send-email-sam@ravnborg.org>

From: Sam Ravnborg <sam@ravnborg.org>
Date: Fri,  8 Feb 2008 21:00:02 +0100

> Fix following warnings:
> WARNING: drivers/isdn/hisax/built-in.o(.text+0x19723): Section mismatch in reference from the function ISACVersion() to the variable .devinit.data:ISACVer
> WARNING: drivers/isdn/hisax/built-in.o(.text+0x2005b): Section mismatch in reference from the function setup_avm_a1_pcmcia() to the function .devinit.text:setup_isac()
> 
> ISACVer were only used from function annotated __devinit
> so add same annotation to ISACVer.
> One af the fererencing functions missed __devinit so add it
> and kill an additional warning.
> 
> Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
> Acked-by: Karsten Keil <kkeil@suse.de>
> Cc: Jeff Garzik <jgarzik@pobox.com>
> Cc: David Miller <davem@davemloft.net>

Also applied, thanks a lot Sam!

^ permalink raw reply

* Re: [PATCH] isdn: fix section mismatch warnings from hisax_cs_setup_card
From: David Miller @ 2008-02-10  7:29 UTC (permalink / raw)
  To: sam; +Cc: netdev, jeff, jgarzik
In-Reply-To: <1202500804-32020-1-git-send-email-sam@ravnborg.org>

From: Sam Ravnborg <sam@ravnborg.org>
Date: Fri,  8 Feb 2008 21:00:01 +0100

> Fix the following warnings:
 ...
> 
> checkcard() are the only user of hisax_cs_setup_card().
> And checkcard is only used during init or when hot plugging
> ISDN devices. So annotate hisax_cs_setup_card() with __devinit.
> checkcard() is used by exported functions so it cannot be
> annotated __devinit. Annotate it with __ref so modpost
> ignore references to _devinit section.
> 
> Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
> Acked-by: Karsten Keil <kkeil@suse.de>
> Cc: Jeff Garzik <jgarzik@pobox.com>
> Cc: David Miller <davem@davemloft.net>

Applied.

^ permalink raw reply

* Re: [PATCH] isdn: fix section mismatch warnings in isac.c and isar.c
From: David Miller @ 2008-02-10  7:28 UTC (permalink / raw)
  To: sam; +Cc: netdev, jeff, jgarzik
In-Reply-To: <1202500804-32020-3-git-send-email-sam@ravnborg.org>

From: Sam Ravnborg <sam@ravnborg.org>
Date: Fri,  8 Feb 2008 21:00:03 +0100

> Fix the following warnings:
 ...
> 
> initisar(), initisac() and clear_pending_isac_ints()
> were all used via a cardmsg fnction - which may be called
> ouside __devinit context.
> So remove the bogus __devinit annotation of the
> above three functions to fix the warnings.
> 
> Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
> Acked-by: Karsten Keil <kkeil@suse.de>
> Cc: Jeff Garzik <jgarzik@pobox.com>
> Cc: David Miller <davem@davemloft.net>

Applied.

^ permalink raw reply

* Re: [PATCH] isdn: fix section mismatch warning in hfc_sx.c
From: David Miller @ 2008-02-10  7:27 UTC (permalink / raw)
  To: sam; +Cc: netdev, jeff, jgarzik
In-Reply-To: <1202500804-32020-4-git-send-email-sam@ravnborg.org>

From: Sam Ravnborg <sam@ravnborg.org>
Date: Fri,  8 Feb 2008 21:00:04 +0100

> Fix the following warning:
> WARNING: drivers/isdn/hisax/built-in.o(.text+0x35818): Section mismatch in reference from the function hfcsx_card_msg() to the function .devinit.text:inithfcsx()
> 
> hfcsx_card_msg() may be called outside __devinit context.
> Following the program logic is looks like the CARD_INIT branch
> will only be taken under __devinit context but to be consistent
> remove the __devinit annotation of inithfcsx() so we
> do not mix non-__devinit and __devinit code.
> 
> Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
> Acked-by: Karsten Keil <kkeil@suse.de>
> Cc: Jeff Garzik <jgarzik@pobox.com>
> Cc: David Miller <davem@davemloft.net>

Applied.

^ permalink raw reply

* Re: [PKT_SCHED] ematch: tcf_em_destroy robustness
From: David Miller @ 2008-02-10  7:27 UTC (permalink / raw)
  To: shemminger; +Cc: netdev
In-Reply-To: <20080208104832.690e140e@extreme>

From: Stephen Hemminger <shemminger@vyatta.com>
Date: Fri, 8 Feb 2008 10:48:32 -0800

> Make the code in tcf_em_tree_destroy more robust and cleaner:
>  * Don't need to cast pointer to kfree() or avoid passing NULL.
>  * After freeing the tree, clear the pointer to avoid possible problems
> from repeated free.
> 
> Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>

Applied, thanks.

^ permalink raw reply

* Re: [PKT_SCHED] deinline functions in meta match
From: David Miller @ 2008-02-10  7:26 UTC (permalink / raw)
  To: shemminger; +Cc: netdev
In-Reply-To: <20080208095557.15cee30f@extreme>

From: Stephen Hemminger <shemminger@vyatta.com>
Date: Fri, 8 Feb 2008 09:55:57 -0800

> A couple of functions in meta match don't need to be inline.
> 
> Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>

Applied.

^ permalink raw reply

* Re: [PATCH 2/2][SCTP]: Convert sctp_dbg_objcnt to seq files.
From: David Miller @ 2008-02-10  7:25 UTC (permalink / raw)
  To: vladislav.yasevich; +Cc: xemul, lksctp-developers, netdev
In-Reply-To: <47AC6E87.5050905@hp.com>

From: Vlad Yasevich <vladislav.yasevich@hp.com>
Date: Fri, 08 Feb 2008 10:00:23 -0500

> Pavel Emelyanov wrote:
> > This makes the code use a good proc API and the text ~50 bytes shorter.
> > 
> > Signed-off-by: Pavel Emelyanov <xemul@openvz.org>
> 
> Acked-by: Vlad Yasevich <vladislav.yasevich@hp.com>

Applied.

^ permalink raw reply

* Re: [PATCH 1/2][SCTP]: Use snmp_fold_field instead of a homebrew analogue.
From: David Miller @ 2008-02-10  7:24 UTC (permalink / raw)
  To: vladislav.yasevich; +Cc: xemul, lksctp-developers, netdev
In-Reply-To: <47AC6E6A.4000101@hp.com>

From: Vlad Yasevich <vladislav.yasevich@hp.com>
Date: Fri, 08 Feb 2008 09:59:54 -0500

> Pavel Emelyanov wrote:
> > SCPT already depends in INET, so this doesn't create additional
> > dependencies.
> > 
> > Signed-off-by: Pavel Emelyanov <xemul@openvz.org>
> 
> Acked-by: Vlad Yasevich <vladislav.yasevich@hp.com>

Applied.

^ permalink raw reply

* Re: [PATCH] [IGMP]: Optimize kfree_skb in igmp_rcv.
From: David Miller @ 2008-02-10  7:22 UTC (permalink / raw)
  To: den; +Cc: netdev, devel
In-Reply-To: <1202480057-23367-1-git-send-email-den@openvz.org>

From: "Denis V. Lunev" <den@openvz.org>
Date: Fri,  8 Feb 2008 17:14:17 +0300

> Merge error paths inside igmp_rcv.
> 
> Signed-off-by: Denis V. Lunev <den@openvz.org>

Applied, but this kind of cleanup is borderline during this
time period.  Please queue such things up for when I open up
net-2.6.26, thanks.

Find some bugs to fix instead :-)

^ permalink raw reply

* Re: [PATCH 2/2][KEY]: Convert net/pfkey to use seq files.
From: David Miller @ 2008-02-10  7:21 UTC (permalink / raw)
  To: xemul; +Cc: herbert, netdev
In-Reply-To: <47AC478E.3070507@openvz.org>

From: Pavel Emelyanov <xemul@openvz.org>
Date: Fri, 08 Feb 2008 15:14:06 +0300

> The seq files API disposes the caller of the difficulty of
> checking file position, the length of data to produce and
> the size of provided buffer.
> 
> Signed-off-by: Pavel Emelyanov <xemul@openvz.org>

Applied, but this kind of stuff is borderline wrt. the
"no new features" declaration.

Please queue future instances of this kind of stuff for when I open up
net-2.6.26, thanks.

^ permalink raw reply

* Re: [PATCH 1/2][KEY]: Clean up proc files creation a bit.
From: David Miller @ 2008-02-10  7:19 UTC (permalink / raw)
  To: xemul; +Cc: herbert, netdev
In-Reply-To: <47AC46F4.60405@openvz.org>

From: Pavel Emelyanov <xemul@openvz.org>
Date: Fri, 08 Feb 2008 15:11:32 +0300

> Mainly this removes ifdef-s from inside the ipsec_pfkey_init.
> 
> Signed-off-by: Pavel Emelyanov <xemul@openvz.org>

Applied.

^ permalink raw reply

* Re: [patch 7/7] pppol2tp: fix printk warnings
From: David Miller @ 2008-02-10  7:18 UTC (permalink / raw)
  To: akpm; +Cc: jeff, netdev
In-Reply-To: <200802081120.m18BK9QQ021642@imap1.linux-foundation.org>

From: akpm@linux-foundation.org
Date: Fri, 08 Feb 2008 03:11:17 -0800

> From: Andrew Morton <akpm@linux-foundation.org>
 ...
> Not all platforms implement u64 with unsigned long long.  eg: powerpc.
> 
> Cc: Jeff Garzik <jeff@garzik.org>
> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

Applied.

^ permalink raw reply

* Re: [patch 4/7] bnx2.c section fix
From: David Miller @ 2008-02-10  7:17 UTC (permalink / raw)
  To: akpm; +Cc: jeff, netdev, sam
In-Reply-To: <200802081120.m18BK8HR021632@imap1.linux-foundation.org>

From: akpm@linux-foundation.org
Date: Fri, 08 Feb 2008 03:11:15 -0800

> From: Andrew Morton <akpm@linux-foundation.org>
> 
> gcc-3.4.4 on powerpc:
> 
> drivers/net/bnx2.c:67: error: version causes a section type conflict
> 
> Cc: Jeff Garzik <jeff@garzik.org>
> Cc: Sam Ravnborg <sam@ravnborg.org>
> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

Applied.

^ permalink raw reply

* Re: [patch 3/7] bnx2x section fix
From: David Miller @ 2008-02-10  7:16 UTC (permalink / raw)
  To: akpm; +Cc: jeff, netdev, sam
In-Reply-To: <200802081120.m18BK73F021629@imap1.linux-foundation.org>

From: akpm@linux-foundation.org
Date: Fri, 08 Feb 2008 03:11:15 -0800

> From: Andrew Morton <akpm@linux-foundation.org>
> 
> gcc-3.4.4 on powerpc:
> 
> drivers/net/bnx2x.c:73: error: version causes a section type conflict
> 
> Cc: Jeff Garzik <jeff@garzik.org>
> Cc: Sam Ravnborg <sam@ravnborg.org>
> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

Applied.

^ permalink raw reply

* Re: [PATCH] [resend] 3c509: convert to isa_driver and pnp_driver v4
From: Christoph Hellwig @ 2008-02-10  5:18 UTC (permalink / raw)
  To: Ondrej Zary; +Cc: Stephen Hemminger, linux-kernel, netdev
In-Reply-To: <200802100110.09301.linux@rainbow-software.org>

On Sun, Feb 10, 2008 at 01:10:07AM +0100, Ondrej Zary wrote:
> > > +typedef enum { EL3_ISA, EL3_PNP, EL3_MCA, EL3_EISA } el3_cardtype;
> > > +
> >
> > No typedef please (see checkpatch)
> 
> Is there any standard way to solve this without a typedef? I added 
> el3_dev_fill() function which fills that card type value according to a 
> parameter passed to it. "int" could be used instead and "#define EL3_ISA 
> 0", "#define EL3_PNP 1" - but I think that's ugly.

enum el3_cardtype {
	EL3_ISA,
	EL3_PNP,
	EL3_MCA,
	EL3_EISA,
};

> > >  struct el3_private {
> > >  	struct net_device_stats stats;
> >
> > Use network device stats in net_device now
> 
> OK, looks like the driver will need some more patches.

While I agree with Stephens comment that this driver should be using
the stats in net_device that's totally out of scope for this patch.
As you're the defacto maintainer of this driver now it would be nice
if you could submit another one for it.

> > > -	struct net_device *next_dev;
> > >  	spinlock_t lock;
> > >  	/* skb send-queue */
> > >  	int head, size;
> > >  	struct sk_buff *queue[SKB_QUEUE_SIZE];
> >
> > What about sk_buff_head (linked list instead)?
> 
> I don't know anything about this, maybe in next patch.

Yes, separate patch please.


^ permalink raw reply

* Re: [RFC] ipvs: Cleanup sync daemon code
From: Christoph Hellwig @ 2008-02-10  4:59 UTC (permalink / raw)
  To: Sven Wegener; +Cc: netdev, linux-kernel
In-Reply-To: <Pine.LNX.4.64.0802100029150.15729@titan.stealer.net>

On Sun, Feb 10, 2008 at 12:38:11AM +0100, Sven Wegener wrote:
>  struct ip_vs_sync_thread_data {
> -	struct completion *startup;
> +	struct completion *startup; /* set to NULL once completed */

This is not needed anmore.  kthread_run guarantees that the newly
creates thread is run before returning to the caller.

> +/* wait queue for master sync daemon */
> +static DECLARE_WAIT_QUEUE_HEAD(sync_master_wait);

I don't think you need this one either.  You can use wake_up_process
on the task_struct pointer instead.

>  	spin_lock(&ip_vs_sync_lock);
>  	list_add_tail(&sb->list, &ip_vs_sync_queue);
> +	if (++ip_vs_sync_count == 10)
> +		wake_up_interruptible(&sync_master_wait);
>  	spin_unlock(&ip_vs_sync_lock);
>  }

> -static int sync_thread(void *startup)
> +static int sync_thread(void *data)

Btw, it might make sense to remove sync_thread and just call the
master and backup threads directly.
> +void __init ip_vs_sync_init(void)
> +{
> +	/* set up multicast address */
> +	mcast_addr.sin_family = AF_INET;
> +	mcast_addr.sin_port = htons(IP_VS_SYNC_PORT);
> +	mcast_addr.sin_addr.s_addr = htonl(IP_VS_SYNC_GROUP);
>  }

Why can't this be initialized at compile time by:

static struct sockaddr_in mcast_addr = {
	.sin_family		= AF_INET,
	.sin_port		= htons(IP_VS_SYNC_PORT),
	.sin_addr.s_addr	= htonl(IP_VS_SYNC_GROUP),
}

(the hton* might need __constant_hton* also I'm not sure without trying)


^ permalink raw reply

* Re: [RFC] ipvs: Cleanup sync daemon code
From: Simon Horman @ 2008-02-10  1:27 UTC (permalink / raw)
  To: Sven Wegener; +Cc: netdev, linux-kernel
In-Reply-To: <Pine.LNX.4.64.0802100029150.15729@titan.stealer.net>

On Sun, Feb 10, 2008 at 12:38:11AM +0100, Sven Wegener wrote:
> Hi all,
>
> I'd like to get your feedback on this:
>
> - Use kthread_run instead of doing a double-fork via kernel_thread()
>
> - Return proper error codes to user-space on failures
>
> Currently ipvsadm --start-daemon with an invalid --mcast-interface will  
> silently suceed. With these changes we get an appropriate "No such 
> device" error.
>
> - Use wait queues for both master and backup thread
>
> Instead of doing an endless loop with sleeping for one second, we now use 
> wait queues. The master sync daemon has its own wait queue and gets woken 
> up when we have enough data to sent and also at a regular interval. The  
> backup sync daemon sits on the wait queue of the mcast socket and gets  
> woken up as soon as we have data to process.

Hi Sven,

This looks good to me, assuming that its tested and works.

A few minor things:

In sb_queue_tail() master loop is woken up if
the ip_vs_sync_count reaches 10, which seems a bit arbitary.

Perhaps its just my mail reader, but the patch seemed a bit screwy when
I saved it to a file. I this fixed the problem I was seeing using s/^  / /

Unfortuantely/Fortunately I am about to leave for a few days skiing,
so if I am quiet you will know why.

Acked-by: Simon Horman <horms@verge.net.au>

-- 
Horms


^ permalink raw reply

* [solved] Re: Bug? Kernels 2.6.2x drops TCP packets over wireless (independentofcard used)
From: Marcin Koziej @ 2008-02-10  1:00 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: netdev
In-Reply-To: <47AB5AD6.3010100@cosmosbay.com>

Dnia 7 lutego 2008 20:24 Eric Dumazet <dada1@cosmosbay.com> napisał(a):
> Typical window scaling problem here... (well, for previous traces, with 
> wscaling of 5, since with wscale 2 it seems to work), you probably have a 
> buggy router or something...
> 
> http://lwn.net/Articles/92727/
> 
> Try :
> 
> # echo 0 >/proc/sys/net/ipv4/tcp_window_scaling
> 
> And retry to connect to this ftp server
> 
> You could alternativly play with /proc/sys/net/ipv4/tcp_rmem
> 
> # echo "4096 8192 50000" >/proc/sys/net/ipv4/tcp_rmem

Thanks! That solves the problem! Now I read about TCP window scaling and I understand the issue, but I wouldn't figure/google that out myself! 
Thank You for Your time!

m.


^ permalink raw reply

* Re: [PATCH] [resend] 3c509: convert to isa_driver and pnp_driver v4
From: Ondrej Zary @ 2008-02-10  0:10 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: linux-kernel, netdev
In-Reply-To: <20080209134805.29cbc8ae@extreme>

On Saturday 09 February 2008 22:48:05 Stephen Hemminger wrote:
> On Sat, 9 Feb 2008 22:33:07 +0100
>
> Ondrej Zary <linux@rainbow-software.org> wrote:
> > Hello,
> > this patch converts 3c509 driver to isa_driver and pnp_driver. The result
> > is that autoloading using udev and hibernation works with ISA PnP cards.
> > It also adds hibernation support for non-PnP ISA cards.
> >
> > xcvr module parameter was removed as its value was not used.
> >
> > Tested using 3 ISA cards in various combinations of PnP and non-PnP
> > modes. EISA and MCA only compile-tested.
> >
> > Signed-off-by: Ondrej Zary <linux@rainbow-software.org>
> >
> > --- linux-2.6.24-orig/drivers/net/3c509.c	2008-01-27 19:48:19.000000000
> > +0100 +++ linux-2.6.24-pentium/drivers/net/3c509.c	2008-02-07
> > 17:58:45.000000000 +0100 @@ -54,25 +54,24 @@
> >  		v1.19a 28Oct2002 Davud Ruggiero <jdr@farfalle.com>
> >  			- Increase *read_eeprom udelay to workaround oops with 2 cards.
> >  		v1.19b 08Nov2002 Marc Zyngier <maz@wild-wind.fr.eu.org>
> > -		    - Introduce driver model for EISA cards.
> > +			- Introduce driver model for EISA cards.
> > +		v1.20  04Feb2008 Ondrej Zary <linux@rainbow-software.org>
> > +			- convert to isa_driver and pnp_driver and some cleanups
> >  */
>
> Don't bother with comment, kernel uses git change log to figure out
> who to blame.
>
> >  #define DRV_NAME	"3c509"
> > -#define DRV_VERSION	"1.19b"
> > -#define DRV_RELDATE	"08Nov2002"
> > +#define DRV_VERSION	"1.20"
> > +#define DRV_RELDATE	"04Feb2008"
> >
> >  /* A few values that may be tweaked. */
> >
> >  /* Time in jiffies before concluding the transmitter is hung. */
> >  #define TX_TIMEOUT  (400*HZ/1000)
> > -/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
> > -static int max_interrupt_work = 10;
> >
> >  #include <linux/module.h>
> > -#ifdef CONFIG_MCA
> >  #include <linux/mca.h>
> > -#endif
> > -#include <linux/isapnp.h>
> > +#include <linux/isa.h>
> > +#include <linux/pnp.h>
> >  #include <linux/string.h>
> >  #include <linux/interrupt.h>
> >  #include <linux/errno.h>
> > @@ -97,10 +96,6 @@
> >
> >  static char version[] __initdata = DRV_NAME ".c:" DRV_VERSION " "
> > DRV_RELDATE " becker@scyld.com\n";
> >
> > -#if defined(CONFIG_PM) && (defined(CONFIG_MCA) || defined(CONFIG_EISA))
> > -#define EL3_SUSPEND
> > -#endif
> > -
> >  #ifdef EL3_DEBUG
> >  static int el3_debug = EL3_DEBUG;
> >  #else
> > @@ -111,6 +106,7 @@
> >   * a global variable so that the mca/eisa probe routines can increment
> >   * it */
> >  static int el3_cards = 0;
> > +#define EL3_MAX_CARDS 8
> >
> >  /* To minimize the size of the driver source I only define operating
> >     constants if they are used several times.  You'll need the manual
> > @@ -119,7 +115,7 @@
> >  #define EL3_DATA 0x00
> >  #define EL3_CMD 0x0e
> >  #define EL3_STATUS 0x0e
> > -#define	 EEPROM_READ 0x80
> > +#define	EEPROM_READ 0x80
> >
> >  #define EL3_IO_EXTENT	16
> >
> > @@ -168,23 +164,31 @@
> >   */
> >  #define SKB_QUEUE_SIZE	64
> >
> > +typedef enum { EL3_ISA, EL3_PNP, EL3_MCA, EL3_EISA } el3_cardtype;
> > +
>
> No typedef please (see checkpatch)

Is there any standard way to solve this without a typedef? I added 
el3_dev_fill() function which fills that card type value according to a 
parameter passed to it. "int" could be used instead and "#define EL3_ISA 
0", "#define EL3_PNP 1" - but I think that's ugly.

>
> >  struct el3_private {
> >  	struct net_device_stats stats;
>
> Use network device stats in net_device now

OK, looks like the driver will need some more patches.

> > -	struct net_device *next_dev;
> >  	spinlock_t lock;
> >  	/* skb send-queue */
> >  	int head, size;
> >  	struct sk_buff *queue[SKB_QUEUE_SIZE];
>
> What about sk_buff_head (linked list instead)?

I don't know anything about this, maybe in next patch.

>
> > -	enum {
> > -		EL3_MCA,
> > -		EL3_PNP,
> > -		EL3_EISA,
> > -	} type;						/* type of device */
> > -	struct device *dev;
> > +	el3_cardtype type;
> >  };
> > -static int id_port __initdata = 0x110;	/* Start with 0x110 to avoid new
> > sound cards.*/ -static struct net_device *el3_root_dev;
> > +static int id_port;
> > +static int current_tag;
> > +static struct net_device *el3_devs[EL3_MAX_CARDS];
>
> I know is only ISA, but having a limit seems silly, can't the device just
> use allocated space like other drivers.

EL3_MAX_CARDS is also used as a parameter to isa_register_driver(). The irq[] 
array (see below) is limited to 8 devices too. And finally, the card itself 
can use one of 8 different IRQs (3,5,7,2/9,10,11,12,15). So I think that it's 
not worth adding more code to support more cards.
The original driver will do bad things with more than 8 cards too - read 
beyond the end of irq[] array.

> > +
> > +/* Parameters that may be passed into the module. */
> > +static int debug = -1;
> > +static int irq[] = {-1, -1, -1, -1, -1, -1, -1, -1};
> > +/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
> > +static int max_interrupt_work = 10;
> > +#ifdef CONFIG_PNP
> > +static int nopnp;
> > +#endif

-- 
Ondrej Zary

^ permalink raw reply

* [PATCH][AX25] af_ax25: remove sock lock in ax25_info_show()
From: Jarek Poplawski @ 2008-02-09 23:50 UTC (permalink / raw)
  To: David Miller
  Cc: Bernard Pidoux F6BVP, Ralf Baechle DL5RB, Jann Traschewski,
	netdev
In-Reply-To: <47ADF4A2.6070705@free.fr>

On Sat, Feb 09, 2008 at 07:44:50PM +0100, Bernard Pidoux F6BVP wrote:
> Hi,
>
> With AX25 patches applied I still get this possible circular locking  
> message.

IMHO this warning could happen earlier too...

Thanks,
Jarek P.

-------------->

Subject: [AX25] af_ax25: remove sock lock in ax25_info_show()
 
This lockdep warning:

> =======================================================
> [ INFO: possible circular locking dependency detected ]
> 2.6.24 #3
> -------------------------------------------------------
> swapper/0 is trying to acquire lock:
>  (ax25_list_lock){-+..}, at: [<f91dd3b1>] ax25_destroy_socket+0x171/0x1f0 [ax25]
> 
> but task is already holding lock:
>  (slock-AF_AX25){-+..}, at: [<f91dbabc>] ax25_std_heartbeat_expiry+0x1c/0xe0 [ax25]
> 
> which lock already depends on the new lock.
...

shows that ax25_list_lock and slock-AF_AX25 are taken in different
order: ax25_info_show() takes slock (bh_lock_sock(ax25->sk)) while
ax25_list_lock is held, so reversely to other functions. To fix this
the sock lock should be moved to ax25_info_start(), but since it's
only for reading proc info it seems this is not necessary (e.g.
ax25_send_to_raw() does similar reading without this lock too). So,
this patch removes this lock to avoid deadlock possibility.


Reported-by: Bernard Pidoux F6BVP <f6bvp@free.fr>
Signed-off-by: Jarek Poplawski <jarkao2@gmail.com>

---

 net/ax25/af_ax25.c |    2 --
 1 files changed, 0 insertions(+), 2 deletions(-)

diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index 94b2b1b..68b5171 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -1924,12 +1924,10 @@ static int ax25_info_show(struct seq_file *seq, void *v)
 		   ax25->paclen);
 
 	if (ax25->sk != NULL) {
-		bh_lock_sock(ax25->sk);
 		seq_printf(seq," %d %d %ld\n",
 			   atomic_read(&ax25->sk->sk_wmem_alloc),
 			   atomic_read(&ax25->sk->sk_rmem_alloc),
 			   ax25->sk->sk_socket != NULL ? SOCK_INODE(ax25->sk->sk_socket)->i_ino : 0L);
-		bh_unlock_sock(ax25->sk);
 	} else {
 		seq_puts(seq, " * * *\n");
 	}

^ permalink raw reply related

* [RFC] ipvs: Cleanup sync daemon code
From: Sven Wegener @ 2008-02-09 23:38 UTC (permalink / raw)
  To: netdev; +Cc: linux-kernel

Hi all,

I'd like to get your feedback on this:

- Use kthread_run instead of doing a double-fork via kernel_thread()

- Return proper error codes to user-space on failures

Currently ipvsadm --start-daemon with an invalid --mcast-interface will 
silently suceed. With these changes we get an appropriate "No such device" 
error.

- Use wait queues for both master and backup thread

Instead of doing an endless loop with sleeping for one second, we now use 
wait queues. The master sync daemon has its own wait queue and gets woken 
up when we have enough data to sent and also at a regular interval. The 
backup sync daemon sits on the wait queue of the mcast socket and gets 
woken up as soon as we have data to process.

diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index 56f3c94..519bd96 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -890,6 +890,7 @@ extern char ip_vs_backup_mcast_ifn[IP_VS_IFNAME_MAXLEN];
  extern int start_sync_thread(int state, char *mcast_ifn, __u8 syncid);
  extern int stop_sync_thread(int state);
  extern void ip_vs_sync_conn(struct ip_vs_conn *cp);
+extern void ip_vs_sync_init(void);


  /*
diff --git a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c
index 963981a..0ccee4b 100644
--- a/net/ipv4/ipvs/ip_vs_core.c
+++ b/net/ipv4/ipvs/ip_vs_core.c
@@ -1071,6 +1071,8 @@ static int __init ip_vs_init(void)
  {
  	int ret;

+	ip_vs_sync_init();
+
  	ret = ip_vs_control_init();
  	if (ret < 0) {
  		IP_VS_ERR("can't setup control.\n");
diff --git a/net/ipv4/ipvs/ip_vs_sync.c b/net/ipv4/ipvs/ip_vs_sync.c
index 948378d..36063d3 100644
--- a/net/ipv4/ipvs/ip_vs_sync.c
+++ b/net/ipv4/ipvs/ip_vs_sync.c
@@ -29,6 +29,9 @@
  #include <linux/in.h>
  #include <linux/igmp.h>                 /* for ip_mc_join_group */
  #include <linux/udp.h>
+#include <linux/kthread.h>
+#include <linux/wait.h>
+#include <linux/err.h>

  #include <net/ip.h>
  #include <net/sock.h>
@@ -68,7 +71,8 @@ struct ip_vs_sync_conn_options {
  };

  struct ip_vs_sync_thread_data {
-	struct completion *startup;
+	struct completion *startup; /* set to NULL once completed */
+	int *retval; /* only valid until startup is completed */
  	int state;
  };

@@ -123,9 +127,10 @@ struct ip_vs_sync_buff {
  };


-/* the sync_buff list head and the lock */
+/* the sync_buff list head, the lock and the counter */
  static LIST_HEAD(ip_vs_sync_queue);
  static DEFINE_SPINLOCK(ip_vs_sync_lock);
+static unsigned int ip_vs_sync_count;

  /* current sync_buff for accepting new conn entries */
  static struct ip_vs_sync_buff   *curr_sb = NULL;
@@ -140,6 +145,13 @@ volatile int ip_vs_backup_syncid = 0;
  char ip_vs_master_mcast_ifn[IP_VS_IFNAME_MAXLEN];
  char ip_vs_backup_mcast_ifn[IP_VS_IFNAME_MAXLEN];

+/* sync daemon tasks */
+static struct task_struct *sync_master_thread;
+static struct task_struct *sync_backup_thread;
+
+/* wait queue for master sync daemon */
+static DECLARE_WAIT_QUEUE_HEAD(sync_master_wait);
+
  /* multicast addr */
  static struct sockaddr_in mcast_addr;

@@ -148,6 +160,8 @@ static inline void sb_queue_tail(struct ip_vs_sync_buff *sb)
  {
  	spin_lock(&ip_vs_sync_lock);
  	list_add_tail(&sb->list, &ip_vs_sync_queue);
+	if (++ip_vs_sync_count == 10)
+		wake_up_interruptible(&sync_master_wait);
  	spin_unlock(&ip_vs_sync_lock);
  }

@@ -163,6 +177,7 @@ static inline struct ip_vs_sync_buff * sb_dequeue(void)
  				struct ip_vs_sync_buff,
  				list);
  		list_del(&sb->list);
+		ip_vs_sync_count--;
  	}
  	spin_unlock_bh(&ip_vs_sync_lock);

@@ -536,14 +551,17 @@ static int bind_mcastif_addr(struct socket *sock, char *ifname)
  static struct socket * make_send_sock(void)
  {
  	struct socket *sock;
+	int result;

  	/* First create a socket */
-	if (sock_create_kern(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock) < 0) {
+	result = sock_create_kern(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock);
+	if (result < 0) {
  		IP_VS_ERR("Error during creation of socket; terminating\n");
-		return NULL;
+		return ERR_PTR(result);
  	}

-	if (set_mcast_if(sock->sk, ip_vs_master_mcast_ifn) < 0) {
+	result = set_mcast_if(sock->sk, ip_vs_master_mcast_ifn);
+	if (result < 0) {
  		IP_VS_ERR("Error setting outbound mcast interface\n");
  		goto error;
  	}
@@ -551,14 +569,16 @@ static struct socket * make_send_sock(void)
  	set_mcast_loop(sock->sk, 0);
  	set_mcast_ttl(sock->sk, 1);

-	if (bind_mcastif_addr(sock, ip_vs_master_mcast_ifn) < 0) {
+	result = bind_mcastif_addr(sock, ip_vs_master_mcast_ifn);
+	if (result < 0) {
  		IP_VS_ERR("Error binding address of the mcast interface\n");
  		goto error;
  	}

-	if (sock->ops->connect(sock,
-			       (struct sockaddr*)&mcast_addr,
-			       sizeof(struct sockaddr), 0) < 0) {
+	result = sock->ops->connect(sock,
+			(struct sockaddr *) &mcast_addr,
+			sizeof(struct sockaddr), 0);
+	if (result < 0) {
  		IP_VS_ERR("Error connecting to the multicast addr\n");
  		goto error;
  	}
@@ -567,7 +587,7 @@ static struct socket * make_send_sock(void)

    error:
  	sock_release(sock);
-	return NULL;
+	return ERR_PTR(result);
  }


@@ -577,27 +597,31 @@ static struct socket * make_send_sock(void)
  static struct socket * make_receive_sock(void)
  {
  	struct socket *sock;
+	int result;

  	/* First create a socket */
-	if (sock_create_kern(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock) < 0) {
+	result = sock_create_kern(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock);
+	if (result < 0) {
  		IP_VS_ERR("Error during creation of socket; terminating\n");
-		return NULL;
+		return ERR_PTR(result);
  	}

  	/* it is equivalent to the REUSEADDR option in user-space */
  	sock->sk->sk_reuse = 1;

-	if (sock->ops->bind(sock,
-			    (struct sockaddr*)&mcast_addr,
-			    sizeof(struct sockaddr)) < 0) {
+	result = sock->ops->bind(sock,
+			(struct sockaddr *) &mcast_addr,
+			sizeof(struct sockaddr));
+	if (result < 0) {
  		IP_VS_ERR("Error binding to the multicast addr\n");
  		goto error;
  	}

  	/* join the multicast group */
-	if (join_mcast_group(sock->sk,
-			     (struct in_addr*)&mcast_addr.sin_addr,
-			     ip_vs_backup_mcast_ifn) < 0) {
+	result = join_mcast_group(sock->sk,
+			(struct in_addr *) &mcast_addr.sin_addr,
+			ip_vs_backup_mcast_ifn);
+	if (result < 0) {
  		IP_VS_ERR("Error joining to the multicast group\n");
  		goto error;
  	}
@@ -606,7 +630,7 @@ static struct socket * make_receive_sock(void)

    error:
  	sock_release(sock);
-	return NULL;
+	return ERR_PTR(result);
  }


@@ -664,30 +688,32 @@ ip_vs_receive(struct socket *sock, char *buffer, const size_t buflen)
  }


-static DECLARE_WAIT_QUEUE_HEAD(sync_wait);
-static pid_t sync_master_pid = 0;
-static pid_t sync_backup_pid = 0;
-
-static DECLARE_WAIT_QUEUE_HEAD(stop_sync_wait);
-static int stop_master_sync = 0;
-static int stop_backup_sync = 0;
-
-static void sync_master_loop(void)
+static int sync_master_loop(struct ip_vs_sync_thread_data *tinfo)
  {
  	struct socket *sock;
  	struct ip_vs_sync_buff *sb;

  	/* create the sending multicast socket */
  	sock = make_send_sock();
-	if (!sock)
-		return;
+	if (IS_ERR(sock))
+		return PTR_ERR(sock);
+
+	/* signal that we are up and running */
+	*tinfo->retval = 0;
+	complete(tinfo->startup);
+	tinfo->startup = NULL;
+	tinfo->retval = NULL;

  	IP_VS_INFO("sync thread started: state = MASTER, mcast_ifn = %s, "
  		   "syncid = %d\n",
  		   ip_vs_master_mcast_ifn, ip_vs_master_syncid);

-	for (;;) {
-		while ((sb=sb_dequeue())) {
+	while (!kthread_should_stop()) {
+		wait_event_interruptible_timeout(sync_master_wait,
+				!list_empty(&ip_vs_sync_queue)
+				|| kthread_should_stop(), HZ);
+
+		while ((sb = sb_dequeue())) {
  			ip_vs_send_sync_msg(sock, sb->mesg);
  			ip_vs_sync_buff_release(sb);
  		}
@@ -697,17 +723,11 @@ static void sync_master_loop(void)
  			ip_vs_send_sync_msg(sock, sb->mesg);
  			ip_vs_sync_buff_release(sb);
  		}
-
-		if (stop_master_sync)
-			break;
-
-		msleep_interruptible(1000);
  	}

  	/* clean up the sync_buff queue */
-	while ((sb=sb_dequeue())) {
+	while ((sb = sb_dequeue()))
  		ip_vs_sync_buff_release(sb);
-	}

  	/* clean up the current sync_buff */
  	if ((sb = get_curr_sync_buff(0))) {
@@ -716,30 +736,44 @@ static void sync_master_loop(void)

  	/* release the sending multicast socket */
  	sock_release(sock);
+
+	return 0;
  }


-static void sync_backup_loop(void)
+static int sync_backup_loop(struct ip_vs_sync_thread_data *tinfo)
  {
  	struct socket *sock;
  	char *buf;
-	int len;
+	int result = 0, len;

  	if (!(buf = kmalloc(sync_recv_mesg_maxlen, GFP_ATOMIC))) {
  		IP_VS_ERR("sync_backup_loop: kmalloc error\n");
-		return;
+		return -ENOMEM;
  	}

  	/* create the receiving multicast socket */
  	sock = make_receive_sock();
-	if (!sock)
+	if (IS_ERR(sock)) {
+		result = PTR_ERR(sock);
  		goto out;
+	}
+
+	/* signal that we are up and running */
+	*tinfo->retval = 0;
+	complete(tinfo->startup);
+	tinfo->startup = NULL;
+	tinfo->retval = NULL;

  	IP_VS_INFO("sync thread started: state = BACKUP, mcast_ifn = %s, "
  		   "syncid = %d\n",
  		   ip_vs_backup_mcast_ifn, ip_vs_backup_syncid);

-	for (;;) {
+	while (!kthread_should_stop()) {
+		wait_event_interruptible(*sock->sk->sk_sleep,
+				!skb_queue_empty(&(sock->sk->sk_receive_queue))
+				|| kthread_should_stop());
+
  		/* do you have data now? */
  		while (!skb_queue_empty(&(sock->sk->sk_receive_queue))) {
  			if ((len =
@@ -754,11 +788,6 @@ static void sync_backup_loop(void)
  			ip_vs_process_message(buf, len);
  			local_bh_enable();
  		}
-
-		if (stop_backup_sync)
-			break;
-
-		msleep_interruptible(1000);
  	}

  	/* release the sending multicast socket */
@@ -766,216 +795,156 @@ static void sync_backup_loop(void)

    out:
  	kfree(buf);
-}

-
-static void set_sync_pid(int sync_state, pid_t sync_pid)
-{
-	if (sync_state == IP_VS_STATE_MASTER)
-		sync_master_pid = sync_pid;
-	else if (sync_state == IP_VS_STATE_BACKUP)
-		sync_backup_pid = sync_pid;
+	return result;
  }

-static void set_stop_sync(int sync_state, int set)
-{
-	if (sync_state == IP_VS_STATE_MASTER)
-		stop_master_sync = set;
-	else if (sync_state == IP_VS_STATE_BACKUP)
-		stop_backup_sync = set;
-	else {
-		stop_master_sync = set;
-		stop_backup_sync = set;
-	}
-}

-static int sync_thread(void *startup)
+static int sync_thread(void *data)
  {
-	DECLARE_WAITQUEUE(wait, current);
-	mm_segment_t oldmm;
-	int state;
-	const char *name;
-	struct ip_vs_sync_thread_data *tinfo = startup;
+	struct ip_vs_sync_thread_data *tinfo = data;
+	int result;

  	/* increase the module use count */
  	ip_vs_use_count_inc();

-	if (ip_vs_sync_state & IP_VS_STATE_MASTER && !sync_master_pid) {
-		state = IP_VS_STATE_MASTER;
-		name = "ipvs_syncmaster";
-	} else if (ip_vs_sync_state & IP_VS_STATE_BACKUP && !sync_backup_pid) {
-		state = IP_VS_STATE_BACKUP;
-		name = "ipvs_syncbackup";
-	} else {
-		IP_VS_BUG();
-		ip_vs_use_count_dec();
-		return -EINVAL;
-	}
-
-	daemonize(name);
-
-	oldmm = get_fs();
-	set_fs(KERNEL_DS);
-
-	/* Block all signals */
-	spin_lock_irq(&current->sighand->siglock);
-	siginitsetinv(&current->blocked, 0);
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-
  	/* set the maximum length of sync message */
-	set_sync_mesg_maxlen(state);
-
-	/* set up multicast address */
-	mcast_addr.sin_family = AF_INET;
-	mcast_addr.sin_port = htons(IP_VS_SYNC_PORT);
-	mcast_addr.sin_addr.s_addr = htonl(IP_VS_SYNC_GROUP);
-
-	add_wait_queue(&sync_wait, &wait);
-
-	set_sync_pid(state, task_pid_nr(current));
-	complete(tinfo->startup);
-
-	/*
-	 * once we call the completion queue above, we should
-	 * null out that reference, since its allocated on the
-	 * stack of the creating kernel thread
-	 */
-	tinfo->startup = NULL;
+	set_sync_mesg_maxlen(tinfo->state);

  	/* processing master/backup loop here */
-	if (state == IP_VS_STATE_MASTER)
-		sync_master_loop();
-	else if (state == IP_VS_STATE_BACKUP)
-		sync_backup_loop();
+	if (tinfo->state == IP_VS_STATE_MASTER)
+		result = sync_master_loop(tinfo);
+	else if (tinfo->state == IP_VS_STATE_BACKUP)
+		result = sync_backup_loop(tinfo);
  	else IP_VS_BUG();

-	remove_wait_queue(&sync_wait, &wait);
-
-	/* thread exits */
+	/* signal startup failure */
+	if (tinfo->startup) {
+		*tinfo->retval = result;
+		complete(tinfo->startup);
+		tinfo->startup = NULL;
+	}

  	/*
  	 * If we weren't explicitly stopped, then we
  	 * exited in error, and should undo our state
  	 */
-	if ((!stop_master_sync) && (!stop_backup_sync))
-		ip_vs_sync_state -= tinfo->state;
+	if (!kthread_should_stop())
+		ip_vs_sync_state &= ~tinfo->state;

-	set_sync_pid(state, 0);
  	IP_VS_INFO("sync thread stopped!\n");

-	set_fs(oldmm);
-
  	/* decrease the module use count */
  	ip_vs_use_count_dec();

-	set_stop_sync(state, 0);
-	wake_up(&stop_sync_wait);
-
  	/*
  	 * we need to free the structure that was allocated
  	 * for us in start_sync_thread
  	 */
  	kfree(tinfo);
-	return 0;
-}

-
-static int fork_sync_thread(void *startup)
-{
-	pid_t pid;
-
-	/* fork the sync thread here, then the parent process of the
-	   sync thread is the init process after this thread exits. */
-  repeat:
-	if ((pid = kernel_thread(sync_thread, startup, 0)) < 0) {
-		IP_VS_ERR("could not create sync_thread due to %d... "
-			  "retrying.\n", pid);
-		msleep_interruptible(1000);
-		goto repeat;
-	}
-
-	return 0;
+	return result;
  }


  int start_sync_thread(int state, char *mcast_ifn, __u8 syncid)
  {
  	DECLARE_COMPLETION_ONSTACK(startup);
-	pid_t pid;
  	struct ip_vs_sync_thread_data *tinfo;
-
-	if ((state == IP_VS_STATE_MASTER && sync_master_pid) ||
-	    (state == IP_VS_STATE_BACKUP && sync_backup_pid))
-		return -EEXIST;
-
-	/*
-	 * Note that tinfo will be freed in sync_thread on exit
-	 */
-	tinfo = kmalloc(sizeof(struct ip_vs_sync_thread_data), GFP_KERNEL);
-	if (!tinfo)
-		return -ENOMEM;
+	struct task_struct **realtask, *task;
+	int retval = -ENOMEM;
+	char *name;

  	IP_VS_DBG(7, "%s: pid %d\n", __FUNCTION__, task_pid_nr(current));
  	IP_VS_DBG(7, "Each ip_vs_sync_conn entry need %Zd bytes\n",
  		  sizeof(struct ip_vs_sync_conn));

-	ip_vs_sync_state |= state;
  	if (state == IP_VS_STATE_MASTER) {
+		if (sync_master_thread)
+			return -EEXIST;
+
  		strlcpy(ip_vs_master_mcast_ifn, mcast_ifn,
  			sizeof(ip_vs_master_mcast_ifn));
  		ip_vs_master_syncid = syncid;
-	} else {
+		realtask = &sync_master_thread;
+		name = "ipvs_syncmaster";
+	} else if (state == IP_VS_STATE_BACKUP) {
+		if (sync_backup_thread)
+			return -EEXIST;
+
  		strlcpy(ip_vs_backup_mcast_ifn, mcast_ifn,
  			sizeof(ip_vs_backup_mcast_ifn));
  		ip_vs_backup_syncid = syncid;
+		realtask = &sync_backup_thread;
+		name = "ipvs_syncbackup";
+	} else {
+		return -EINVAL;
  	}

+	/*
+	 * Note that tinfo will be freed in sync_thread on exit
+	 */
+	tinfo = kmalloc(sizeof(struct ip_vs_sync_thread_data), GFP_KERNEL);
+	if (!tinfo)
+		return -ENOMEM;
+
  	tinfo->state = state;
  	tinfo->startup = &startup;
+	tinfo->retval = &retval;

-  repeat:
-	if ((pid = kernel_thread(fork_sync_thread, tinfo, 0)) < 0) {
-		IP_VS_ERR("could not create fork_sync_thread due to %d... "
-			  "retrying.\n", pid);
-		msleep_interruptible(1000);
-		goto repeat;
+	task = kthread_run(sync_thread, tinfo, name);
+	if (IS_ERR(task)) {
+		kfree(tinfo);
+		return PTR_ERR(task);
  	}

+	/* wait for startup */
  	wait_for_completion(&startup);

-	return 0;
+	if (retval == 0) {
+		*realtask = task;
+		ip_vs_sync_state |= state;
+	}
+
+	return retval;
  }


  int stop_sync_thread(int state)
  {
-	DECLARE_WAITQUEUE(wait, current);
-
-	if ((state == IP_VS_STATE_MASTER && !sync_master_pid) ||
-	    (state == IP_VS_STATE_BACKUP && !sync_backup_pid))
-		return -ESRCH;
+	int result = -EINVAL;

  	IP_VS_DBG(7, "%s: pid %d\n", __FUNCTION__, task_pid_nr(current));
-	IP_VS_INFO("stopping sync thread %d ...\n",
-		   (state == IP_VS_STATE_MASTER) ?
-		   sync_master_pid : sync_backup_pid);
-
-	__set_current_state(TASK_UNINTERRUPTIBLE);
-	add_wait_queue(&stop_sync_wait, &wait);
-	set_stop_sync(state, 1);
-	ip_vs_sync_state -= state;
-	wake_up(&sync_wait);
-	schedule();
-	__set_current_state(TASK_RUNNING);
-	remove_wait_queue(&stop_sync_wait, &wait);
-
-	/* Note: no need to reap the sync thread, because its parent
-	   process is the init process */
-
-	if ((state == IP_VS_STATE_MASTER && stop_master_sync) ||
-	    (state == IP_VS_STATE_BACKUP && stop_backup_sync))
-		IP_VS_BUG();

-	return 0;
+	if (state == IP_VS_STATE_MASTER) {
+		if (!sync_master_thread)
+			return -ESRCH;
+
+		IP_VS_INFO("stopping master sync thread %d ...\n",
+			   task_pid_nr(sync_master_thread));
+
+		ip_vs_sync_state &= ~IP_VS_STATE_MASTER;
+		result = kthread_stop(sync_master_thread);
+		sync_master_thread = NULL;
+	} else if (state == IP_VS_STATE_BACKUP) {
+		if (!sync_backup_thread)
+			return -ESRCH;
+
+		IP_VS_INFO("stopping backup sync thread %d ...\n",
+			   task_pid_nr(sync_backup_thread));
+
+		ip_vs_sync_state &= ~IP_VS_STATE_BACKUP;
+		result = kthread_stop(sync_backup_thread);
+		sync_backup_thread = NULL;
+	}
+
+	return result;
+}
+
+void __init ip_vs_sync_init(void)
+{
+	/* set up multicast address */
+	mcast_addr.sin_family = AF_INET;
+	mcast_addr.sin_port = htons(IP_VS_SYNC_PORT);
+	mcast_addr.sin_addr.s_addr = htonl(IP_VS_SYNC_GROUP);
  }

^ permalink raw reply related

* Re: [PATCH] [resend] 3c509: convert to isa_driver and pnp_driver v4
From: Stephen Hemminger @ 2008-02-09 21:48 UTC (permalink / raw)
  To: linux-kernel; +Cc: netdev
In-Reply-To: <200802092233.10239.linux@rainbow-software.org>

On Sat, 9 Feb 2008 22:33:07 +0100
Ondrej Zary <linux@rainbow-software.org> wrote:

> Hello,
> this patch converts 3c509 driver to isa_driver and pnp_driver. The result is 
> that autoloading using udev and hibernation works with ISA PnP cards. It also 
> adds hibernation support for non-PnP ISA cards.
> 
> xcvr module parameter was removed as its value was not used.
> 
> Tested using 3 ISA cards in various combinations of PnP and non-PnP modes. 
> EISA and MCA only compile-tested.
> 
> Signed-off-by: Ondrej Zary <linux@rainbow-software.org>
> 
> --- linux-2.6.24-orig/drivers/net/3c509.c	2008-01-27 19:48:19.000000000 +0100
> +++ linux-2.6.24-pentium/drivers/net/3c509.c	2008-02-07 17:58:45.000000000 +0100
> @@ -54,25 +54,24 @@
>  		v1.19a 28Oct2002 Davud Ruggiero <jdr@farfalle.com>
>  			- Increase *read_eeprom udelay to workaround oops with 2 cards.
>  		v1.19b 08Nov2002 Marc Zyngier <maz@wild-wind.fr.eu.org>
> -		    - Introduce driver model for EISA cards.
> +			- Introduce driver model for EISA cards.
> +		v1.20  04Feb2008 Ondrej Zary <linux@rainbow-software.org>
> +			- convert to isa_driver and pnp_driver and some cleanups
>  */

Don't bother with comment, kernel uses git change log to figure out
who to blame.


>  #define DRV_NAME	"3c509"
> -#define DRV_VERSION	"1.19b"
> -#define DRV_RELDATE	"08Nov2002"
> +#define DRV_VERSION	"1.20"
> +#define DRV_RELDATE	"04Feb2008"
>  
>  /* A few values that may be tweaked. */
>  
>  /* Time in jiffies before concluding the transmitter is hung. */
>  #define TX_TIMEOUT  (400*HZ/1000)
> -/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
> -static int max_interrupt_work = 10;
>  
>  #include <linux/module.h>
> -#ifdef CONFIG_MCA
>  #include <linux/mca.h>
> -#endif
> -#include <linux/isapnp.h>
> +#include <linux/isa.h>
> +#include <linux/pnp.h>
>  #include <linux/string.h>
>  #include <linux/interrupt.h>
>  #include <linux/errno.h>
> @@ -97,10 +96,6 @@
>  
>  static char version[] __initdata = DRV_NAME ".c:" DRV_VERSION " " DRV_RELDATE " becker@scyld.com\n";
>  
> -#if defined(CONFIG_PM) && (defined(CONFIG_MCA) || defined(CONFIG_EISA))
> -#define EL3_SUSPEND
> -#endif
> -
>  #ifdef EL3_DEBUG
>  static int el3_debug = EL3_DEBUG;
>  #else
> @@ -111,6 +106,7 @@
>   * a global variable so that the mca/eisa probe routines can increment
>   * it */
>  static int el3_cards = 0;
> +#define EL3_MAX_CARDS 8
>  
>  /* To minimize the size of the driver source I only define operating
>     constants if they are used several times.  You'll need the manual
> @@ -119,7 +115,7 @@
>  #define EL3_DATA 0x00
>  #define EL3_CMD 0x0e
>  #define EL3_STATUS 0x0e
> -#define	 EEPROM_READ 0x80
> +#define	EEPROM_READ 0x80
>  
>  #define EL3_IO_EXTENT	16
>  
> @@ -168,23 +164,31 @@
>   */
>  #define SKB_QUEUE_SIZE	64
>  
> +typedef enum { EL3_ISA, EL3_PNP, EL3_MCA, EL3_EISA } el3_cardtype;
> +

No typedef please (see checkpatch)

>  struct el3_private {
>  	struct net_device_stats stats;

Use network device stats in net_device now
> -	struct net_device *next_dev;
>  	spinlock_t lock;
>  	/* skb send-queue */
>  	int head, size;
>  	struct sk_buff *queue[SKB_QUEUE_SIZE];

What about sk_buff_head (linked list instead)?
> -	enum {
> -		EL3_MCA,
> -		EL3_PNP,
> -		EL3_EISA,
> -	} type;						/* type of device */
> -	struct device *dev;
> +	el3_cardtype type;
>  };
> -static int id_port __initdata = 0x110;	/* Start with 0x110 to avoid new sound cards.*/
> -static struct net_device *el3_root_dev;
> +static int id_port;
> +static int current_tag;
> +static struct net_device *el3_devs[EL3_MAX_CARDS];

I know is only ISA, but having a limit seems silly, can't the device just
use allocated space like other drivers.

> +
> +/* Parameters that may be passed into the module. */
> +static int debug = -1;
> +static int irq[] = {-1, -1, -1, -1, -1, -1, -1, -1};
> +/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
> +static int max_interrupt_work = 10;
> +#ifdef CONFIG_PNP
> +static int nopnp;
> +#endif
>  


-- 
Stephen Hemminger <stephen.hemminger@vyatta.com>

^ permalink raw reply

* [PATCH] [resend] 3c509: convert to isa_driver and pnp_driver v4
From: Ondrej Zary @ 2008-02-09 21:33 UTC (permalink / raw)
  To: maz; +Cc: Jeff Garzik, netdev, Linux Kernel, Andrew Morton
In-Reply-To: <wrphcglx9w0.fsf@hina.wild-wind.fr.eu.org>

Hello,
this patch converts 3c509 driver to isa_driver and pnp_driver. The result is 
that autoloading using udev and hibernation works with ISA PnP cards. It also 
adds hibernation support for non-PnP ISA cards.

xcvr module parameter was removed as its value was not used.

Tested using 3 ISA cards in various combinations of PnP and non-PnP modes. 
EISA and MCA only compile-tested.

Signed-off-by: Ondrej Zary <linux@rainbow-software.org>

--- linux-2.6.24-orig/drivers/net/3c509.c	2008-01-27 19:48:19.000000000 +0100
+++ linux-2.6.24-pentium/drivers/net/3c509.c	2008-02-07 17:58:45.000000000 +0100
@@ -54,25 +54,24 @@
 		v1.19a 28Oct2002 Davud Ruggiero <jdr@farfalle.com>
 			- Increase *read_eeprom udelay to workaround oops with 2 cards.
 		v1.19b 08Nov2002 Marc Zyngier <maz@wild-wind.fr.eu.org>
-		    - Introduce driver model for EISA cards.
+			- Introduce driver model for EISA cards.
+		v1.20  04Feb2008 Ondrej Zary <linux@rainbow-software.org>
+			- convert to isa_driver and pnp_driver and some cleanups
 */
 
 #define DRV_NAME	"3c509"
-#define DRV_VERSION	"1.19b"
-#define DRV_RELDATE	"08Nov2002"
+#define DRV_VERSION	"1.20"
+#define DRV_RELDATE	"04Feb2008"
 
 /* A few values that may be tweaked. */
 
 /* Time in jiffies before concluding the transmitter is hung. */
 #define TX_TIMEOUT  (400*HZ/1000)
-/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
-static int max_interrupt_work = 10;
 
 #include <linux/module.h>
-#ifdef CONFIG_MCA
 #include <linux/mca.h>
-#endif
-#include <linux/isapnp.h>
+#include <linux/isa.h>
+#include <linux/pnp.h>
 #include <linux/string.h>
 #include <linux/interrupt.h>
 #include <linux/errno.h>
@@ -97,10 +96,6 @@
 
 static char version[] __initdata = DRV_NAME ".c:" DRV_VERSION " " DRV_RELDATE " becker@scyld.com\n";
 
-#if defined(CONFIG_PM) && (defined(CONFIG_MCA) || defined(CONFIG_EISA))
-#define EL3_SUSPEND
-#endif
-
 #ifdef EL3_DEBUG
 static int el3_debug = EL3_DEBUG;
 #else
@@ -111,6 +106,7 @@
  * a global variable so that the mca/eisa probe routines can increment
  * it */
 static int el3_cards = 0;
+#define EL3_MAX_CARDS 8
 
 /* To minimize the size of the driver source I only define operating
    constants if they are used several times.  You'll need the manual
@@ -119,7 +115,7 @@
 #define EL3_DATA 0x00
 #define EL3_CMD 0x0e
 #define EL3_STATUS 0x0e
-#define	 EEPROM_READ 0x80
+#define	EEPROM_READ 0x80
 
 #define EL3_IO_EXTENT	16
 
@@ -168,23 +164,31 @@
  */
 #define SKB_QUEUE_SIZE	64
 
+typedef enum { EL3_ISA, EL3_PNP, EL3_MCA, EL3_EISA } el3_cardtype;
+
 struct el3_private {
 	struct net_device_stats stats;
-	struct net_device *next_dev;
 	spinlock_t lock;
 	/* skb send-queue */
 	int head, size;
 	struct sk_buff *queue[SKB_QUEUE_SIZE];
-	enum {
-		EL3_MCA,
-		EL3_PNP,
-		EL3_EISA,
-	} type;						/* type of device */
-	struct device *dev;
+	el3_cardtype type;
 };
-static int id_port __initdata = 0x110;	/* Start with 0x110 to avoid new sound cards.*/
-static struct net_device *el3_root_dev;
+static int id_port;
+static int current_tag;
+static struct net_device *el3_devs[EL3_MAX_CARDS];
+
+/* Parameters that may be passed into the module. */
+static int debug = -1;
+static int irq[] = {-1, -1, -1, -1, -1, -1, -1, -1};
+/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
+static int max_interrupt_work = 10;
+#ifdef CONFIG_PNP
+static int nopnp;
+#endif
 
+static int __init el3_common_init(struct net_device *dev);
+static void el3_common_remove (struct net_device *dev);
 static ushort id_read_eeprom(int index);
 static ushort read_eeprom(int ioaddr, int index);
 static int el3_open(struct net_device *dev);
@@ -199,23 +203,277 @@
 static void el3_down(struct net_device *dev);
 static void el3_up(struct net_device *dev);
 static const struct ethtool_ops ethtool_ops;
-#ifdef EL3_SUSPEND
+#ifdef CONFIG_PM
 static int el3_suspend(struct device *, pm_message_t);
 static int el3_resume(struct device *);
-#else
-#define el3_suspend NULL
-#define el3_resume NULL
 #endif
 
 
 /* generic device remove for all device types */
-#if defined(CONFIG_EISA) || defined(CONFIG_MCA)
 static int el3_device_remove (struct device *device);
-#endif
 #ifdef CONFIG_NET_POLL_CONTROLLER
 static void el3_poll_controller(struct net_device *dev);
 #endif
 
+/* Return 0 on success, 1 on error, 2 when found already detected PnP card */
+static int el3_isa_id_sequence(__be16 *phys_addr)
+{
+	short lrs_state = 0xff;
+	int i;
+
+	/* ISA boards are detected by sending the ID sequence to the
+	   ID_PORT.  We find cards past the first by setting the 'current_tag'
+	   on cards as they are found.  Cards with their tag set will not
+	   respond to subsequent ID sequences. */
+
+	outb(0x00, id_port);
+	outb(0x00, id_port);
+	for (i = 0; i < 255; i++) {
+		outb(lrs_state, id_port);
+		lrs_state <<= 1;
+		lrs_state = lrs_state & 0x100 ? lrs_state ^ 0xcf : lrs_state;
+	}
+	/* For the first probe, clear all board's tag registers. */
+	if (current_tag == 0)
+		outb(0xd0, id_port);
+	else				/* Otherwise kill off already-found boards. */
+		outb(0xd8, id_port);
+	if (id_read_eeprom(7) != 0x6d50)
+		return 1;
+	/* Read in EEPROM data, which does contention-select.
+	   Only the lowest address board will stay "on-line".
+	   3Com got the byte order backwards. */
+	for (i = 0; i < 3; i++)
+		phys_addr[i] = htons(id_read_eeprom(i));
+#ifdef CONFIG_PNP
+	if (!nopnp) {
+		/* The ISA PnP 3c509 cards respond to the ID sequence too.
+		   This check is needed in order not to register them twice. */
+		for (i = 0; i < el3_cards; i++) {
+			struct el3_private *lp = netdev_priv(el3_devs[i]);
+			if (lp->type == EL3_PNP && !memcmp(phys_addr, el3_devs[i]->dev_addr, ETH_ALEN)) {
+				if (el3_debug > 3)
+					printk(KERN_DEBUG "3c509 with address %02x %02x %02x %02x %02x %02x was found by ISAPnP\n",
+						phys_addr[0] & 0xff, phys_addr[0] >> 8,
+						phys_addr[1] & 0xff, phys_addr[1] >> 8,
+						phys_addr[2] & 0xff, phys_addr[2] >> 8);
+				/* Set the adaptor tag so that the next card can be found. */
+				outb(0xd0 + ++current_tag, id_port);
+				return 2;
+			}
+		}
+	}
+#endif /* CONFIG_PNP */
+	return 0;
+
+}
+
+static void __devinit el3_dev_fill(struct net_device *dev, __be16 *phys_addr,
+			           int ioaddr, int irq, int if_port,
+			           el3_cardtype type)
+{
+	struct el3_private *lp = netdev_priv(dev);
+
+	memcpy(dev->dev_addr, phys_addr, ETH_ALEN);
+	dev->base_addr = ioaddr;
+	dev->irq = irq;
+	dev->if_port = if_port;
+	lp->type = type;
+}
+
+static int __devinit el3_isa_match(struct device *pdev,
+				   unsigned int ndev)
+{
+	struct net_device *dev;
+	int ioaddr, isa_irq, if_port, err;
+	unsigned int iobase;
+	__be16 phys_addr[3];
+
+	while ((err = el3_isa_id_sequence(phys_addr)) == 2)
+		;	/* Skip to next card when PnP card found */
+	if (err == 1)
+		return 0;
+
+	iobase = id_read_eeprom(8);
+	if_port = iobase >> 14;
+	ioaddr = 0x200 + ((iobase & 0x1f) << 4);
+	if (irq[el3_cards] > 1 && irq[el3_cards] < 16)
+		isa_irq = irq[el3_cards];
+	else
+		isa_irq = id_read_eeprom(9) >> 12;
+
+	dev = alloc_etherdev(sizeof (struct el3_private));
+	if (!dev)
+		return -ENOMEM;
+
+	netdev_boot_setup_check(dev);
+
+	if (!request_region(ioaddr, EL3_IO_EXTENT, "3c509-isa")) {
+		free_netdev(dev);
+		return 0;
+	}
+
+	/* Set the adaptor tag so that the next card can be found. */
+	outb(0xd0 + ++current_tag, id_port);
+
+	/* Activate the adaptor at the EEPROM location. */
+	outb((ioaddr >> 4) | 0xe0, id_port);
+
+	EL3WINDOW(0);
+	if (inw(ioaddr) != 0x6d50) {
+		free_netdev(dev);
+		return 0;
+	}
+
+	/* Free the interrupt so that some other card can use it. */
+	outw(0x0f00, ioaddr + WN0_IRQ);
+
+	el3_dev_fill(dev, phys_addr, ioaddr, isa_irq, if_port, EL3_ISA);
+	dev_set_drvdata(pdev, dev);
+	if (el3_common_init(dev)) {
+		free_netdev(dev);
+		return 0;
+	}
+
+	el3_devs[el3_cards++] = dev;
+	return 1;
+}
+
+static int __devexit el3_isa_remove(struct device *pdev,
+				    unsigned int ndev)
+{
+	el3_device_remove(pdev);
+	dev_set_drvdata(pdev, NULL);
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int el3_isa_suspend(struct device *dev, unsigned int n,
+			   pm_message_t state)
+{
+	current_tag = 0;
+	return el3_suspend(dev, state);
+}
+
+static int el3_isa_resume(struct device *dev, unsigned int n)
+{
+	struct net_device *ndev = dev_get_drvdata(dev);
+	int ioaddr = ndev->base_addr, err;
+	__be16 phys_addr[3];
+
+	while ((err = el3_isa_id_sequence(phys_addr)) == 2)
+		;	/* Skip to next card when PnP card found */
+	if (err == 1)
+		return 0;
+	/* Set the adaptor tag so that the next card can be found. */
+	outb(0xd0 + ++current_tag, id_port);
+	/* Enable the card */
+	outb((ioaddr >> 4) | 0xe0, id_port);
+	EL3WINDOW(0);
+	if (inw(ioaddr) != 0x6d50)
+		return 1;
+	/* Free the interrupt so that some other card can use it. */
+	outw(0x0f00, ioaddr + WN0_IRQ);
+	return el3_resume(dev);
+}
+#endif
+
+static struct isa_driver el3_isa_driver = {
+	.match		= el3_isa_match,
+	.remove		= __devexit_p(el3_isa_remove),
+#ifdef CONFIG_PM
+	.suspend	= el3_isa_suspend,
+	.resume		= el3_isa_resume,
+#endif
+	.driver		= {
+		.name	= "3c509"
+	},
+};
+static int isa_registered;
+
+#ifdef CONFIG_PNP
+static struct pnp_device_id el3_pnp_ids[] = {
+	{ .id = "TCM5090" }, /* 3Com Etherlink III (TP) */
+	{ .id = "TCM5091" }, /* 3Com Etherlink III */
+	{ .id = "TCM5094" }, /* 3Com Etherlink III (combo) */
+	{ .id = "TCM5095" }, /* 3Com Etherlink III (TPO) */
+	{ .id = "TCM5098" }, /* 3Com Etherlink III (TPC) */
+	{ .id = "PNP80f7" }, /* 3Com Etherlink III compatible */
+	{ .id = "PNP80f8" }, /* 3Com Etherlink III compatible */
+	{ .id = "" }
+};
+MODULE_DEVICE_TABLE(pnp, el3_pnp_ids);
+
+static int __devinit el3_pnp_probe(struct pnp_dev *pdev,
+				    const struct pnp_device_id *id)
+{
+	short i;
+	int ioaddr, irq, if_port;
+	u16 phys_addr[3];
+	struct net_device *dev = NULL;
+	int err;
+
+	ioaddr = pnp_port_start(pdev, 0);
+	if (!request_region(ioaddr, EL3_IO_EXTENT, "3c509-pnp"))
+		return -EBUSY;
+	irq = pnp_irq(pdev, 0);
+	EL3WINDOW(0);
+	for (i = 0; i < 3; i++)
+		phys_addr[i] = htons(read_eeprom(ioaddr, i));
+	if_port = read_eeprom(ioaddr, 8) >> 14;
+	dev = alloc_etherdev(sizeof (struct el3_private));
+	if (!dev) {
+		release_region(ioaddr, EL3_IO_EXTENT);
+		return -ENOMEM;
+	}
+	SET_NETDEV_DEV(dev, &pdev->dev);
+	netdev_boot_setup_check(dev);
+
+	el3_dev_fill(dev, phys_addr, ioaddr, irq, if_port, EL3_PNP);
+	pnp_set_drvdata (pdev, dev);
+	err = el3_common_init(dev);
+
+	if (err) {
+		pnp_set_drvdata (pdev, NULL);
+		free_netdev(dev);
+		return err;
+	}
+
+	el3_devs[el3_cards++] = dev;
+	return 0;
+}
+
+static void __devexit el3_pnp_remove(struct pnp_dev *pdev)
+{
+	el3_common_remove(pnp_get_drvdata(pdev));
+	pnp_set_drvdata(pdev, NULL);
+}
+
+#ifdef CONFIG_PM
+static int el3_pnp_suspend(struct pnp_dev *pdev, pm_message_t state)
+{
+	return el3_suspend(&pdev->dev, state);
+}
+
+static int el3_pnp_resume(struct pnp_dev *pdev)
+{
+	return el3_resume(&pdev->dev);
+}
+#endif
+
+static struct pnp_driver el3_pnp_driver = {
+	.name		= "3c509",
+	.id_table	= el3_pnp_ids,
+	.probe		= el3_pnp_probe,
+	.remove		= __devexit_p(el3_pnp_remove),
+#ifdef CONFIG_PM
+	.suspend	= el3_pnp_suspend,
+	.resume		= el3_pnp_resume,
+#endif
+};
+static int pnp_registered;
+#endif /* CONFIG_PNP */
+
 #ifdef CONFIG_EISA
 static struct eisa_device_id el3_eisa_ids[] = {
 		{ "TCM5092" },
@@ -230,13 +488,14 @@
 static struct eisa_driver el3_eisa_driver = {
 		.id_table = el3_eisa_ids,
 		.driver   = {
-				.name    = "3c509",
+				.name    = "3c579",
 				.probe   = el3_eisa_probe,
 				.remove  = __devexit_p (el3_device_remove),
 				.suspend = el3_suspend,
 				.resume  = el3_resume,
 		}
 };
+static int eisa_registered;
 #endif
 
 #ifdef CONFIG_MCA
@@ -271,45 +530,9 @@
 				.resume  = el3_resume,
 		},
 };
+static int mca_registered;
 #endif /* CONFIG_MCA */
 
-#if defined(__ISAPNP__)
-static struct isapnp_device_id el3_isapnp_adapters[] __initdata = {
-	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
-		ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5090),
-		(long) "3Com Etherlink III (TP)" },
-	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
-		ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5091),
-		(long) "3Com Etherlink III" },
-	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
-		ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5094),
-		(long) "3Com Etherlink III (combo)" },
-	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
-		ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5095),
-		(long) "3Com Etherlink III (TPO)" },
-	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
-		ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5098),
-		(long) "3Com Etherlink III (TPC)" },
-	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
-		ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_FUNCTION(0x80f7),
-		(long) "3Com Etherlink III compatible" },
-	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
-		ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_FUNCTION(0x80f8),
-		(long) "3Com Etherlink III compatible" },
-	{ }	/* terminate list */
-};
-
-static __be16 el3_isapnp_phys_addr[8][3];
-static int nopnp;
-#endif /* __ISAPNP__ */
-
-/* With the driver model introduction for EISA devices, both init
- * and cleanup have been split :
- * - EISA devices probe/remove starts in el3_eisa_probe/el3_device_remove
- * - MCA/ISA still use el3_probe
- *
- * Both call el3_common_init/el3_common_remove. */
-
 static int __init el3_common_init(struct net_device *dev)
 {
 	struct el3_private *lp = netdev_priv(dev);
@@ -360,231 +583,11 @@
 
 static void el3_common_remove (struct net_device *dev)
 {
-	struct el3_private *lp = netdev_priv(dev);
-
-	(void) lp;				/* Keep gcc quiet... */
-#if defined(__ISAPNP__)
-	if (lp->type == EL3_PNP)
-		pnp_device_detach(to_pnp_dev(lp->dev));
-#endif
-
 	unregister_netdev (dev);
 	release_region(dev->base_addr, EL3_IO_EXTENT);
 	free_netdev (dev);
 }
 
-static int __init el3_probe(int card_idx)
-{
-	struct net_device *dev;
-	struct el3_private *lp;
-	short lrs_state = 0xff, i;
-	int ioaddr, irq, if_port;
-	__be16 phys_addr[3];
-	static int current_tag;
-	int err = -ENODEV;
-#if defined(__ISAPNP__)
-	static int pnp_cards;
-	struct pnp_dev *idev = NULL;
-	int pnp_found = 0;
-
-	if (nopnp == 1)
-		goto no_pnp;
-
-	for (i=0; el3_isapnp_adapters[i].vendor != 0; i++) {
-		int j;
-		while ((idev = pnp_find_dev(NULL,
-					    el3_isapnp_adapters[i].vendor,
-					    el3_isapnp_adapters[i].function,
-					    idev))) {
-			if (pnp_device_attach(idev) < 0)
-				continue;
-			if (pnp_activate_dev(idev) < 0) {
-__again:
-				pnp_device_detach(idev);
-				continue;
-			}
-			if (!pnp_port_valid(idev, 0) || !pnp_irq_valid(idev, 0))
-				goto __again;
-			ioaddr = pnp_port_start(idev, 0);
-			if (!request_region(ioaddr, EL3_IO_EXTENT, "3c509 PnP")) {
-				pnp_device_detach(idev);
-				return -EBUSY;
-			}
-			irq = pnp_irq(idev, 0);
-			if (el3_debug > 3)
-				printk ("ISAPnP reports %s at i/o 0x%x, irq %d\n",
-					(char*) el3_isapnp_adapters[i].driver_data, ioaddr, irq);
-			EL3WINDOW(0);
-			for (j = 0; j < 3; j++)
-				el3_isapnp_phys_addr[pnp_cards][j] =
-					phys_addr[j] =
-						htons(read_eeprom(ioaddr, j));
-			if_port = read_eeprom(ioaddr, 8) >> 14;
-			dev = alloc_etherdev(sizeof (struct el3_private));
-			if (!dev) {
-					release_region(ioaddr, EL3_IO_EXTENT);
-					pnp_device_detach(idev);
-					return -ENOMEM;
-			}
-
-			SET_NETDEV_DEV(dev, &idev->dev);
-			pnp_cards++;
-
-			netdev_boot_setup_check(dev);
-			pnp_found = 1;
-			goto found;
-		}
-	}
-no_pnp:
-#endif /* __ISAPNP__ */
-
-	/* Select an open I/O location at 0x1*0 to do contention select. */
-	for ( ; id_port < 0x200; id_port += 0x10) {
-		if (!request_region(id_port, 1, "3c509"))
-			continue;
-		outb(0x00, id_port);
-		outb(0xff, id_port);
-		if (inb(id_port) & 0x01){
-			release_region(id_port, 1);
-			break;
-		} else
-			release_region(id_port, 1);
-	}
-	if (id_port >= 0x200) {
-		/* Rare -- do we really need a warning? */
-		printk(" WARNING: No I/O port available for 3c509 activation.\n");
-		return -ENODEV;
-	}
-
-	/* Next check for all ISA bus boards by sending the ID sequence to the
-	   ID_PORT.  We find cards past the first by setting the 'current_tag'
-	   on cards as they are found.  Cards with their tag set will not
-	   respond to subsequent ID sequences. */
-
-	outb(0x00, id_port);
-	outb(0x00, id_port);
-	for(i = 0; i < 255; i++) {
-		outb(lrs_state, id_port);
-		lrs_state <<= 1;
-		lrs_state = lrs_state & 0x100 ? lrs_state ^ 0xcf : lrs_state;
-	}
-
-	/* For the first probe, clear all board's tag registers. */
-	if (current_tag == 0)
-		outb(0xd0, id_port);
-	else				/* Otherwise kill off already-found boards. */
-		outb(0xd8, id_port);
-
-	if (id_read_eeprom(7) != 0x6d50) {
-		return -ENODEV;
-	}
-
-	/* Read in EEPROM data, which does contention-select.
-	   Only the lowest address board will stay "on-line".
-	   3Com got the byte order backwards. */
-	for (i = 0; i < 3; i++) {
-		phys_addr[i] = htons(id_read_eeprom(i));
-	}
-
-#if defined(__ISAPNP__)
-	if (nopnp == 0) {
-		/* The ISA PnP 3c509 cards respond to the ID sequence.
-		   This check is needed in order not to register them twice. */
-		for (i = 0; i < pnp_cards; i++) {
-			if (phys_addr[0] == el3_isapnp_phys_addr[i][0] &&
-			    phys_addr[1] == el3_isapnp_phys_addr[i][1] &&
-			    phys_addr[2] == el3_isapnp_phys_addr[i][2])
-			{
-				if (el3_debug > 3)
-					printk("3c509 with address %02x %02x %02x %02x %02x %02x was found by ISAPnP\n",
-						phys_addr[0] & 0xff, phys_addr[0] >> 8,
-						phys_addr[1] & 0xff, phys_addr[1] >> 8,
-						phys_addr[2] & 0xff, phys_addr[2] >> 8);
-				/* Set the adaptor tag so that the next card can be found. */
-				outb(0xd0 + ++current_tag, id_port);
-				goto no_pnp;
-			}
-		}
-	}
-#endif /* __ISAPNP__ */
-
-	{
-		unsigned int iobase = id_read_eeprom(8);
-		if_port = iobase >> 14;
-		ioaddr = 0x200 + ((iobase & 0x1f) << 4);
-	}
-	irq = id_read_eeprom(9) >> 12;
-
-	dev = alloc_etherdev(sizeof (struct el3_private));
-	if (!dev)
-		return -ENOMEM;
-
-	netdev_boot_setup_check(dev);
-
-	/* Set passed-in IRQ or I/O Addr. */
-	if (dev->irq > 1  &&  dev->irq < 16)
-			irq = dev->irq;
-
-	if (dev->base_addr) {
-		if (dev->mem_end == 0x3c509 	/* Magic key */
-		    && dev->base_addr >= 0x200  &&  dev->base_addr <= 0x3e0)
-			ioaddr = dev->base_addr & 0x3f0;
-		else if (dev->base_addr != ioaddr)
-			goto out;
-	}
-
-	if (!request_region(ioaddr, EL3_IO_EXTENT, "3c509")) {
-		err = -EBUSY;
-		goto out;
-	}
-
-	/* Set the adaptor tag so that the next card can be found. */
-	outb(0xd0 + ++current_tag, id_port);
-
-	/* Activate the adaptor at the EEPROM location. */
-	outb((ioaddr >> 4) | 0xe0, id_port);
-
-	EL3WINDOW(0);
-	if (inw(ioaddr) != 0x6d50)
-		goto out1;
-
-	/* Free the interrupt so that some other card can use it. */
-	outw(0x0f00, ioaddr + WN0_IRQ);
-
-#if defined(__ISAPNP__)
- found:							/* PNP jumps here... */
-#endif /* __ISAPNP__ */
-
-	memcpy(dev->dev_addr, phys_addr, sizeof(phys_addr));
-	dev->base_addr = ioaddr;
-	dev->irq = irq;
-	dev->if_port = if_port;
-	lp = netdev_priv(dev);
-#if defined(__ISAPNP__)
-	lp->dev = &idev->dev;
-	if (pnp_found)
-		lp->type = EL3_PNP;
-#endif
-	err = el3_common_init(dev);
-
-	if (err)
-		goto out1;
-
-	el3_cards++;
-	lp->next_dev = el3_root_dev;
-	el3_root_dev = dev;
-	return 0;
-
-out1:
-#if defined(__ISAPNP__)
-	if (idev)
-		pnp_device_detach(idev);
-#endif
-out:
-	free_netdev(dev);
-	return err;
-}
-
 #ifdef CONFIG_MCA
 static int __init el3_mca_probe(struct device *device)
 {
@@ -596,7 +599,6 @@
 	 * redone for multi-card detection by ZP Gu (zpg@castle.net)
 	 * now works as a module */
 
-	struct el3_private *lp;
 	short i;
 	int ioaddr, irq, if_port;
 	u16 phys_addr[3];
@@ -613,7 +615,7 @@
 	irq = pos5 & 0x0f;
 
 
-	printk("3c529: found %s at slot %d\n",
+	printk(KERN_INFO "3c529: found %s at slot %d\n",
 		   el3_mca_adapter_names[mdev->index], slot + 1);
 
 	/* claim the slot */
@@ -626,7 +628,7 @@
 	irq = mca_device_transform_irq(mdev, irq);
 	ioaddr = mca_device_transform_ioport(mdev, ioaddr);
 	if (el3_debug > 2) {
-			printk("3c529: irq %d  ioaddr 0x%x  ifport %d\n", irq, ioaddr, if_port);
+			printk(KERN_DEBUG "3c529: irq %d  ioaddr 0x%x  ifport %d\n", irq, ioaddr, if_port);
 	}
 	EL3WINDOW(0);
 	for (i = 0; i < 3; i++) {
@@ -641,13 +643,7 @@
 
 	netdev_boot_setup_check(dev);
 
-	memcpy(dev->dev_addr, phys_addr, sizeof(phys_addr));
-	dev->base_addr = ioaddr;
-	dev->irq = irq;
-	dev->if_port = if_port;
-	lp = netdev_priv(dev);
-	lp->dev = device;
-	lp->type = EL3_MCA;
+	el3_dev_fill(dev, phys_addr, ioaddr, irq, if_port, EL3_MCA);
 	device->driver_data = dev;
 	err = el3_common_init(dev);
 
@@ -657,7 +653,7 @@
 		return -ENOMEM;
 	}
 
-	el3_cards++;
+	el3_devs[el3_cards++] = dev;
 	return 0;
 }
 
@@ -666,7 +662,6 @@
 #ifdef CONFIG_EISA
 static int __init el3_eisa_probe (struct device *device)
 {
-	struct el3_private *lp;
 	short i;
 	int ioaddr, irq, if_port;
 	u16 phys_addr[3];
@@ -678,7 +673,7 @@
 	edev = to_eisa_device (device);
 	ioaddr = edev->base_addr;
 
-	if (!request_region(ioaddr, EL3_IO_EXTENT, "3c509"))
+	if (!request_region(ioaddr, EL3_IO_EXTENT, "3c579-eisa"))
 		return -EBUSY;
 
 	/* Change the register set to the configuration window 0. */
@@ -700,13 +695,7 @@
 
 	netdev_boot_setup_check(dev);
 
-	memcpy(dev->dev_addr, phys_addr, sizeof(phys_addr));
-	dev->base_addr = ioaddr;
-	dev->irq = irq;
-	dev->if_port = if_port;
-	lp = netdev_priv(dev);
-	lp->dev = device;
-	lp->type = EL3_EISA;
+	el3_dev_fill(dev, phys_addr, ioaddr, irq, if_port, EL3_EISA);
 	eisa_set_drvdata (edev, dev);
 	err = el3_common_init(dev);
 
@@ -716,12 +705,11 @@
 		return err;
 	}
 
-	el3_cards++;
+	el3_devs[el3_cards++] = dev;
 	return 0;
 }
 #endif
 
-#if defined(CONFIG_EISA) || defined(CONFIG_MCA)
 /* This remove works for all device types.
  *
  * The net dev must be stored in the driver_data field */
@@ -734,7 +722,6 @@
 	el3_common_remove (dev);
 	return 0;
 }
-#endif
 
 /* Read a word from the EEPROM using the regular EEPROM access register.
    Assume that we are in register window zero.
@@ -749,7 +736,7 @@
 }
 
 /* Read a word from the EEPROM when in the ISA ID probe state. */
-static ushort __init id_read_eeprom(int index)
+static ushort id_read_eeprom(int index)
 {
 	int bit, word = 0;
 
@@ -765,7 +752,7 @@
 		word = (word << 1) + (inb(id_port) & 0x01);
 
 	if (el3_debug > 3)
-		printk("  3c509 EEPROM word %d %#4.4x.\n", index, word);
+		printk(KERN_DEBUG "  3c509 EEPROM word %d %#4.4x.\n", index, word);
 
 	return word;
 }
@@ -787,13 +774,13 @@
 
 	EL3WINDOW(0);
 	if (el3_debug > 3)
-		printk("%s: Opening, IRQ %d	 status@%x %4.4x.\n", dev->name,
+		printk(KERN_DEBUG "%s: Opening, IRQ %d	 status@%x %4.4x.\n", dev->name,
 			   dev->irq, ioaddr + EL3_STATUS, inw(ioaddr + EL3_STATUS));
 
 	el3_up(dev);
 
 	if (el3_debug > 3)
-		printk("%s: Opened 3c509  IRQ %d  status %4.4x.\n",
+		printk(KERN_DEBUG "%s: Opened 3c509  IRQ %d  status %4.4x.\n",
 			   dev->name, dev->irq, inw(ioaddr + EL3_STATUS));
 
 	return 0;
@@ -806,7 +793,7 @@
 	int ioaddr = dev->base_addr;
 
 	/* Transmitter timeout, serious problems. */
-	printk("%s: transmit timed out, Tx_status %2.2x status %4.4x "
+	printk(KERN_WARNING "%s: transmit timed out, Tx_status %2.2x status %4.4x "
 		   "Tx FIFO room %d.\n",
 		   dev->name, inb(ioaddr + TX_STATUS), inw(ioaddr + EL3_STATUS),
 		   inw(ioaddr + TX_FREE));
@@ -831,7 +818,7 @@
 	lp->stats.tx_bytes += skb->len;
 
 	if (el3_debug > 4) {
-		printk("%s: el3_start_xmit(length = %u) called, status %4.4x.\n",
+		printk(KERN_DEBUG "%s: el3_start_xmit(length = %u) called, status %4.4x.\n",
 			   dev->name, skb->len, inw(ioaddr + EL3_STATUS));
 	}
 #if 0
@@ -840,7 +827,7 @@
 		ushort status = inw(ioaddr + EL3_STATUS);
 		if (status & 0x0001 		/* IRQ line active, missed one. */
 			&& inw(ioaddr + EL3_STATUS) & 1) { 			/* Make sure. */
-			printk("%s: Missed interrupt, status then %04x now %04x"
+			printk(KERN_DEBUG "%s: Missed interrupt, status then %04x now %04x"
 				   "  Tx %2.2x Rx %4.4x.\n", dev->name, status,
 				   inw(ioaddr + EL3_STATUS), inb(ioaddr + TX_STATUS),
 				   inw(ioaddr + RX_STATUS));
@@ -914,7 +901,7 @@
 
 	if (el3_debug > 4) {
 		status = inw(ioaddr + EL3_STATUS);
-		printk("%s: interrupt, status %4.4x.\n", dev->name, status);
+		printk(KERN_DEBUG "%s: interrupt, status %4.4x.\n", dev->name, status);
 	}
 
 	while ((status = inw(ioaddr + EL3_STATUS)) &
@@ -925,7 +912,7 @@
 
 		if (status & TxAvailable) {
 			if (el3_debug > 5)
-				printk("	TX room bit was handled.\n");
+				printk(KERN_DEBUG "	TX room bit was handled.\n");
 			/* There's room in the FIFO for a full-sized packet. */
 			outw(AckIntr | TxAvailable, ioaddr + EL3_CMD);
 			netif_wake_queue (dev);
@@ -964,7 +951,7 @@
 		}
 
 		if (--i < 0) {
-			printk("%s: Infinite loop in interrupt, status %4.4x.\n",
+			printk(KERN_ERR "%s: Infinite loop in interrupt, status %4.4x.\n",
 				   dev->name, status);
 			/* Clear all interrupts. */
 			outw(AckIntr | 0xFF, ioaddr + EL3_CMD);
@@ -975,7 +962,7 @@
 	}
 
 	if (el3_debug > 4) {
-		printk("%s: exiting interrupt, status %4.4x.\n", dev->name,
+		printk(KERN_DEBUG "%s: exiting interrupt, status %4.4x.\n", dev->name,
 			   inw(ioaddr + EL3_STATUS));
 	}
 	spin_unlock(&lp->lock);
@@ -1450,7 +1437,7 @@
 }
 
 /* Power Management support functions */
-#ifdef EL3_SUSPEND
+#ifdef CONFIG_PM
 
 static int
 el3_suspend(struct device *pdev, pm_message_t state)
@@ -1500,79 +1487,102 @@
 	return 0;
 }
 
-#endif /* EL3_SUSPEND */
-
-/* Parameters that may be passed into the module. */
-static int debug = -1;
-static int irq[] = {-1, -1, -1, -1, -1, -1, -1, -1};
-static int xcvr[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
+#endif /* CONFIG_PM */
 
 module_param(debug,int, 0);
 module_param_array(irq, int, NULL, 0);
-module_param_array(xcvr, int, NULL, 0);
 module_param(max_interrupt_work, int, 0);
 MODULE_PARM_DESC(debug, "debug level (0-6)");
 MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)");
-MODULE_PARM_DESC(xcvr,"transceiver(s) (0=internal, 1=external)");
 MODULE_PARM_DESC(max_interrupt_work, "maximum events handled per interrupt");
-#if defined(__ISAPNP__)
+#ifdef CONFIG_PNP
 module_param(nopnp, int, 0);
 MODULE_PARM_DESC(nopnp, "disable ISA PnP support (0-1)");
-MODULE_DEVICE_TABLE(isapnp, el3_isapnp_adapters);
-#endif	/* __ISAPNP__ */
-MODULE_DESCRIPTION("3Com Etherlink III (3c509, 3c509B) ISA/PnP ethernet driver");
+#endif	/* CONFIG_PNP */
+MODULE_DESCRIPTION("3Com Etherlink III (3c509, 3c509B, 3c529, 3c579) ethernet driver");
 MODULE_LICENSE("GPL");
 
 static int __init el3_init_module(void)
 {
 	int ret = 0;
-	el3_cards = 0;
 
 	if (debug >= 0)
 		el3_debug = debug;
 
-	el3_root_dev = NULL;
-	while (el3_probe(el3_cards) == 0) {
-		if (irq[el3_cards] > 1)
-			el3_root_dev->irq = irq[el3_cards];
-		if (xcvr[el3_cards] >= 0)
-			el3_root_dev->if_port = xcvr[el3_cards];
-		el3_cards++;
+#ifdef CONFIG_PNP
+	if (!nopnp) {
+		ret = pnp_register_driver(&el3_pnp_driver);
+		if (!ret)
+			pnp_registered = 1;
+	}
+#endif
+	/* Select an open I/O location at 0x1*0 to do ISA contention select. */
+	/* Start with 0x110 to avoid some sound cards.*/
+	for (id_port = 0x110 ; id_port < 0x200; id_port += 0x10) {
+		if (!request_region(id_port, 1, "3c509-control"))
+			continue;
+		outb(0x00, id_port);
+		outb(0xff, id_port);
+		if (inb(id_port) & 0x01)
+			break;
+		else
+			release_region(id_port, 1);
+	}
+	if (id_port >= 0x200) {
+		id_port = 0;
+		printk(KERN_ERR "No I/O port available for 3c509 activation.\n");
+	} else {
+		ret = isa_register_driver(&el3_isa_driver, EL3_MAX_CARDS);
+		if (!ret)
+			isa_registered = 1;
 	}
-
 #ifdef CONFIG_EISA
 	ret = eisa_driver_register(&el3_eisa_driver);
+	if (!ret)
+		eisa_registered = 1;
 #endif
 #ifdef CONFIG_MCA
-	{
-		int err = mca_register_driver(&el3_mca_driver);
-		if (ret == 0)
-			ret = err;
-	}
+	ret = mca_register_driver(&el3_mca_driver);
+	if (!ret)
+		mca_registered = 1;
+#endif
+
+#ifdef CONFIG_PNP
+	if (pnp_registered)
+		ret = 0;
+#endif
+	if (isa_registered)
+		ret = 0;
+#ifdef CONFIG_EISA
+	if (eisa_registered)
+		ret = 0;
+#endif
+#ifdef CONFIG_MCA
+	if (mca_registered)
+		ret = 0;
 #endif
 	return ret;
 }
 
 static void __exit el3_cleanup_module(void)
 {
-	struct net_device *next_dev;
-
-	while (el3_root_dev) {
-		struct el3_private *lp = netdev_priv(el3_root_dev);
-
-		next_dev = lp->next_dev;
-		el3_common_remove (el3_root_dev);
-		el3_root_dev = next_dev;
-	}
-
+#ifdef CONFIG_PNP
+	if (pnp_registered)
+		pnp_unregister_driver(&el3_pnp_driver);
+#endif
+	if (isa_registered)
+		isa_unregister_driver(&el3_isa_driver);
+	if (id_port)
+		release_region(id_port, 1);
 #ifdef CONFIG_EISA
-	eisa_driver_unregister (&el3_eisa_driver);
+	if (eisa_registered)
+		eisa_driver_unregister (&el3_eisa_driver);
 #endif
 #ifdef CONFIG_MCA
-	mca_unregister_driver(&el3_mca_driver);
+	if (mca_registered)
+		mca_unregister_driver(&el3_mca_driver);
 #endif
 }
 
 module_init (el3_init_module);
 module_exit (el3_cleanup_module);
-


-- 
Ondrej Zary

^ permalink raw reply

* Re: [PATCH][AX25] ax25_ds_timer: use mod_timer instead of add_timer
From: Jarek Poplawski @ 2008-02-09 19:39 UTC (permalink / raw)
  To: Bernard Pidoux F6BVP
  Cc: Ralf Baechle DL5RB, Jann Traschewski, Linux Netdev List
In-Reply-To: <47ADF4A2.6070705@free.fr>

On Sat, Feb 09, 2008 at 07:44:50PM +0100, Bernard Pidoux F6BVP wrote:
> Hi,
>
> With AX25 patches applied I still get this possible circular locking  
> message.

Hi Bernard,

Could you confirm which exactly patches did you try? Is this vanilla
2.6.24 plus these two: ax25_timer and ax25_ds_timer or something more?
And I'm not sure what do you mean by "still": the warning came back
just after these last patches? At least these timer patches don't seem
to change anything around locking?

Thanks for testing this,
Jarek P.

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox