All of lore.kernel.org
 help / color / mirror / Atom feed
* Re: procps 2.x vs. procps 3.x
From: Brandon Low @ 2002-12-13  2:09 UTC (permalink / raw)
  To: Dan Kegel; +Cc: linux-kernel
In-Reply-To: <3DF93D89.3000704@ixiacom.com>

Well at Gentoo, we are kinda using both right now.  We've noticed
some querkiness with the 3.x series where TOP will miss certain
characters in output, but the 3.x series is much prettier and
feature rich than the 2.x series.  On the other hand, 2.x is 
consistently more up to date with kernel changes since RML and Riel
maintain it and are intimately familiar with current kernel
development.  

For the moment, we are on 2.x in stable and 3.x in unstable,
awaiting fixage for the minor querks of 3.x before switching up 
to 3.x for the stable.

Hope that helps,

Brandon Low
Gentoo Linux Kernel Release Manager


On Thu, 12/12/02 at 17:53:13 -0800, Dan Kegel wrote:
> Albert Cahalan wrote in message "[ANNOUNCE] procps 3.1.3":
> > This release includes user selection in top, the sysctl -e
> > option needed to support the Red Hat 8.0 boot scripts, and
> > the use of /proc/*/wchan on recent 2.5.xx kernels.
> > 
> > For those of you still upgrading from procps 2.0.xx releases,
> > you can expect:
>  > ...
> > There's a procps-feedback@lists.sf.net mailing list you can
> > use for feature requests, bug reports, and so on. Use it!
> 
> and
> 
> Robert Love wrote in message "[announce] procps 2.0.11":
> > Rik and I are pleased to announce version 2.0.11 of procps, the package
> > that contains ps, top, free, vmstat, etc.
> > 
> > Newer versions of procps are required for 2.5 kernels.
>  > ...
> > 
> > Procps discussion, bugs, and patches are welcome at:
> > 	procps-list@redhat.com
> 
> Which one should distributions use?
> Or is that a matter of taste?
> 
> - Dan
> 
> 
> 
> 
> 
> 
> -
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply

* Re: Setting standard arguments
From: axel @ 2002-12-13  1:55 UTC (permalink / raw)
  To: dashielljt; +Cc: linux-newbie
In-Reply-To: <Pine.LNX.4.50.0212122045250.902-100000@athame.gmpexpress.net>

Hi dashielljt!

On Thu, 12 Dec 2002, dashielljt wrote:

> Never heard of that package and I have slackware 8.0 going on his machine.
> It's not in the man pages, is it even part of traditional slackware full
> install?  If not, you do best to check its documentation and faq file if
> one exists.

Well it's not about checkinstall. Checkinstall is not part of Slackware, it
just creates slackware packages from source builds to help keep you system
in order. Please take a look at it, in case you build software from source
packages. It's very useful. (http://asic-linux.com.mx/~izto/checkinstall/).

No, my question was targeted at doing such thing in general. Calling a
program which is called with a set of standard arguments given to it.
Because quite often you use the same options when calling some program.

Best regards,
Axel
-
To unsubscribe from this list: send the line "unsubscribe linux-newbie" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.linux-learn.org/faqs

^ permalink raw reply

* Re: [ANNOUNCE] kexec-tools-1.8
From: Dave Hansen @ 2002-12-13  2:00 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: Linux Kernel Mailing List, Suparna Bhattacharya, Martin J. Bligh
In-Reply-To: <m18yz7y2qh.fsf@frodo.biederman.org>

I got around to trying it on a NUMA-Q again.  It makes it well into 
the kernel this time.  I've been getting some strange CPU numbering 
problems, but that was happening to a lesser extent before I threw 
kexec in there.

Right now it's dying in the memory allocator, but that is probably 
just something that didn't get initialized right, or some cross-quad 
memory that isn't set up right.

I would really like to see this go into 2.5.  The fact that it gets 
this far on something as exotic as a NUMA-Q is a tribute to its 
maturity.
-- 
Dave Hansen
haveblue@us.ibm.com


^ permalink raw reply

* [PATCH] 2.4.20-rmap15b
From: Rik van Riel @ 2002-12-13  1:51 UTC (permalink / raw)
  To: linux-mm; +Cc: linux-kernel

Many changes, mostly backported from 2.5 by Ben LaHaise and
fixed up a bit more by myself. It all appears to work, but
more testing is appropriate.

The second maintenance release of the 15th version of the reverse
mapping based VM is now available.
This is an attempt at making a more robust and flexible VM
subsystem, while cleaning up a lot of code at the same time.
The patch is available from:

           http://surriel.com/patches/2.4/2.4.20-rmap15b
and        http://linuxvm.bkbits.net/


My big TODO items for a next release are:
  - finetune the O(1) VM code for strange corner cases


rmap 15b:
  - adjust anon/cache work table                          (me)
  - make active_age_bias a per-active list thing          (me)
  - don't wake up kswapd early from mark_page_accessed    (me)
  - make sure pte-chains are cacheline aligned with PAE   (me, Andrew Morton)
  - change some O(1) VM thresholds                        (me)
  - fix pte-highmem backport                              (me)
  - 2.5 backport: pte-highmem                             (Ben LaHaise)
  - 2.5 backport: large cacheline aligned pte-chains      (Ben LaHaise)
  - 2.5 backport: direct pte pointers                     (Ben LaHaise)
  - undo __find_pagecache_page braindamage		  (Christoph Hellwig)
rmap 15a:
  - more agressive freeing for higher order allocations   (me)
  - export __find_pagecache_page, find_get_page define    (me, Christoph, Arjan)
  - make memory statistics SMP safe again                 (me)
  - make page aging slow down again when needed           (Andrew Morton)
  - first stab at fine-tuning arjan's O(1) VM             (me)
  - split active list in cache / working set              (me)
  - fix SMP locking in arjan's O(1) VM                    (me)
rmap 15:
  - small code cleanups and spelling fixes for O(1) VM    (me)
  - O(1) page launder, O(1) page aging                    (Arjan van de Ven)
  - resync code with -ac (12 small patches)               (me)
rmap 14c:
  - fold page_over_rsslimit() into page_referenced()      (me)
  - 2.5 backport: get pte_chains from the slab cache      (William Lee Irwin)
  - remove dead code from page_launder_zone()             (me)
  - make OOM detection a bit more agressive               (me)
rmap 14b:
  - don't unmap pages not in pagecache (ext3 & reiser)    (Andrew Morton, me)
  - clean up mark_page_accessed a bit                     (me)
  - Alpha NUMA fix for Ingo's per-cpu pages               (Flavio Leitner, me)
  - remove explicit low latency schedule zap_page_range   (Robert Love)
  - fix OOM stuff for good, hopefully                     (me)
rmap 14a:
  - Ingo Molnar's per-cpu pages (SMP speedup)             (Christoph Hellwig)
  - fix SMP bug in page_launder_zone (rmap14 only)        (Arjan van de Ven)
  - semicolon day, fix typo in rmap.c w/ DEBUG_RMAP       (Craig Kulesa)
  - remove unneeded pte_chain_unlock/lock pair vmscan.c   (Craig Kulesa)
  - low latency zap_page_range also without preempt       (Arjan van de Ven)
  - do some throughput tuning for kswapd/page_launder     (me)
  - don't allocate swap space for pages we're not writing (me)
rmap 14:
  - get rid of stalls during swapping, hopefully          (me)
  - low latency zap_page_range                            (Robert Love)
rmap 13c:
  - add wmb() to wakeup_memwaiters                        (Arjan van de Ven)
  - remap_pmd_range now calls pte_alloc with full address (Paul Mackerras)
  - #ifdef out pte_chain_lock/unlock on UP machines       (Andrew Morton)
  - un-BUG() truncate_complete_page, the race is expected (Andrew Morton, me)
  - remove NUMA changes from rmap13a                      (Christoph Hellwig)
rmap 13b:
  - prevent PF_MEMALLOC recursion for higher order allocs (Arjan van de Ven, me)
  - fix small SMP race, PG_lru                            (Hugh Dickins)
rmap 13a:
  - NUMA changes for page_address                         (Samuel Ortiz)
  - replace vm.freepages with simpler kswapd_minfree      (Christoph Hellwig)
rmap 13:
  - rename touch_page to mark_page_accessed and uninline  (Christoph Hellwig)
  - NUMA bugfix for __alloc_pages                         (William Irwin)
  - kill __find_page                                      (Christoph Hellwig)
  - make pte_chain_freelist per zone                      (William Irwin)
  - protect pte_chains by per-page lock bit               (William Irwin)
  - minor code cleanups                                   (me)
rmap 12i:
  - slab cleanup                                          (Christoph Hellwig)
  - remove references to compiler.h from mm/*             (me)
  - move rmap to marcelo's bk tree                        (me)
  - minor cleanups                                        (me)
rmap 12h:
  - hopefully fix OOM detection algorithm                 (me)
  - drop pte quicklist in anticipation of pte-highmem     (me)
  - replace andrea's highmem emulation by ingo's one      (me)
  - improve rss limit checking                            (Nick Piggin)
rmap 12g:
  - port to armv architecture                             (David Woodhouse)
  - NUMA fix to zone_table initialisation                 (Samuel Ortiz)
  - remove init_page_count                                (David Miller)
rmap 12f:
  - for_each_pgdat macro                                  (William Lee Irwin)
  - put back EXPORT(__find_get_page) for modular rd       (me)
  - make bdflush and kswapd actually start queued disk IO (me)
rmap 12e
  - RSS limit fix, the limit can be 0 for some reason     (me)
  - clean up for_each_zone define to not need pgdata_t    (William Lee Irwin)
  - fix i810_dma bug introduced with page->wait removal   (William Lee Irwin)
rmap 12d:
  - fix compiler warning in rmap.c                        (Roger Larsson)
  - read latency improvement   (read-latency2)            (Andrew Morton)
rmap 12c:
  - fix small balancing bug in page_launder_zone          (Nick Piggin)
  - wakeup_kswapd / wakeup_memwaiters code fix            (Arjan van de Ven)
  - improve RSS limit enforcement                         (me)
rmap 12b:
  - highmem emulation (for debugging purposes)            (Andrea Arcangeli)
  - ulimit RSS enforcement when memory gets tight         (me)
  - sparc64 page->virtual quickfix                        (Greg Procunier)
rmap 12a:
  - fix the compile warning in buffer.c                   (me)
  - fix divide-by-zero on highmem initialisation  DOH!    (me)
  - remove the pgd quicklist (suspicious ...)             (DaveM, me)
rmap 12:
  - keep some extra free memory on large machines         (Arjan van de Ven, me)
  - higher-order allocation bugfix                        (Adrian Drzewiecki)
  - nr_free_buffer_pages() returns inactive + free mem    (me)
  - pages from unused objects directly to inactive_clean  (me)
  - use fast pte quicklists on non-pae machines           (Andrea Arcangeli)
  - remove sleep_on from wakeup_kswapd                    (Arjan van de Ven)
  - page waitqueue cleanup                                (Christoph Hellwig)
rmap 11c:
  - oom_kill race locking fix                             (Andres Salomon)
  - elevator improvement                                  (Andrew Morton)
  - dirty buffer writeout speedup (hopefully ;))          (me)
  - small documentation updates                           (me)
  - page_launder() never does synchronous IO, kswapd
    and the processes calling it sleep on higher level    (me)
  - deadlock fix in touch_page()                          (me)
rmap 11b:
  - added low latency reschedule points in vmscan.c       (me)
  - make i810_dma.c include mm_inline.h too               (William Lee Irwin)
  - wake up kswapd sleeper tasks on OOM kill so the
    killed task can continue on its way out               (me)
  - tune page allocation sleep point a little             (me)
rmap 11a:
  - don't let refill_inactive() progress count for OOM    (me)
  - after an OOM kill, wait 5 seconds for the next kill   (me)
  - agpgart_be fix for hashed waitqueues                  (William Lee Irwin)
rmap 11:
  - fix stupid logic inversion bug in wakeup_kswapd()     (Andrew Morton)
  - fix it again in the morning                           (me)
  - add #ifdef BROKEN_PPC_PTE_ALLOC_ONE to rmap.h, it
    seems PPC calls pte_alloc() before mem_map[] init     (me)
  - disable the debugging code in rmap.c ... the code
    is working and people are running benchmarks          (me)
  - let the slab cache shrink functions return a value
    to help prevent early OOM killing                     (Ed Tomlinson)
  - also, don't call the OOM code if we have enough
    free pages                                            (me)
  - move the call to lru_cache_del into __free_pages_ok   (Ben LaHaise)
  - replace the per-page waitqueue with a hashed
    waitqueue, reduces size of struct page from 64
    bytes to 52 bytes (48 bytes on non-highmem machines)  (William Lee Irwin)
rmap 10:
  - fix the livelock for real (yeah right), turned out
    to be a stupid bug in page_launder_zone()             (me)
  - to make sure the VM subsystem doesn't monopolise
    the CPU, let kswapd and some apps sleep a bit under
    heavy stress situations                               (me)
  - let __GFP_HIGH allocations dig a little bit deeper
    into the free page pool, the SCSI layer seems fragile (me)
rmap 9:
  - improve comments all over the place                   (Michael Cohen)
  - don't panic if page_remove_rmap() cannot find the
    rmap in question, it's possible that the memory was
    PG_reserved and belonging to a driver, but the driver
    exited and cleared the PG_reserved bit                (me)
  - fix the VM livelock by replacing > by >= in a few
    critical places in the pageout code                   (me)
  - treat the reclaiming of an inactive_clean page like
    allocating a new page, calling try_to_free_pages()
    and/or fixup_freespace() if required                  (me)
  - when low on memory, don't make things worse by
    doing swapin_readahead                                (me)
rmap 8:
  - add ANY_ZONE to the balancing functions to improve
    kswapd's balancing a bit                              (me)
  - regularize some of the maximum loop bounds in
    vmscan.c for cosmetic purposes                        (William Lee Irwin)
  - move page_address() to architecture-independent
    code, now the removal of page->virtual is portable    (William Lee Irwin)
  - speed up free_area_init_core() by doing a single
    pass over the pages and not using atomic ops          (William Lee Irwin)
  - documented the buddy allocator in page_alloc.c        (William Lee Irwin)
rmap 7:
  - clean up and document vmscan.c                        (me)
  - reduce size of page struct, part one                  (William Lee Irwin)
  - add rmap.h for other archs (untested, not for ARM)    (me)
rmap 6:
  - make the active and inactive_dirty list per zone,
    this is finally possible because we can free pages
    based on their physical address                       (William Lee Irwin)
  - cleaned up William's code a bit                       (me)
  - turn some defines into inlines and move those to
    mm_inline.h (the includes are a mess ...)             (me)
  - improve the VM balancing a bit                        (me)
  - add back inactive_target to /proc/meminfo             (me)
rmap 5:
  - fixed recursive buglet, introduced by directly
    editing the patch for making rmap 4 ;)))              (me)
rmap 4:
  - look at the referenced bits in page tables            (me)
rmap 3:
  - forgot one FASTCALL definition                        (me)
rmap 2:
  - teach try_to_unmap_one() about mremap()               (me)
  - don't assign swap space to pages with buffers         (me)
  - make the rmap.c functions FASTCALL / inline           (me)
rmap 1:
  - fix the swap leak in rmap 0                           (Dave McCracken)
rmap 0:
  - port of reverse mapping VM to 2.4.16                  (me)

Rik
-- 
Bravely reimplemented by the knights who say "NIH".
http://www.surriel.com/		http://guru.conectiva.com/
Current spamtrap:  <a href=mailto:"october@surriel.com">october@surriel.com</a>
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/

^ permalink raw reply

* procps 2.x vs. procps 3.x
From: Dan Kegel @ 2002-12-13  1:53 UTC (permalink / raw)
  To: linux-kernel

Albert Cahalan wrote in message "[ANNOUNCE] procps 3.1.3":
> This release includes user selection in top, the sysctl -e
> option needed to support the Red Hat 8.0 boot scripts, and
> the use of /proc/*/wchan on recent 2.5.xx kernels.
> 
> For those of you still upgrading from procps 2.0.xx releases,
> you can expect:
 > ...
> There's a procps-feedback@lists.sf.net mailing list you can
> use for feature requests, bug reports, and so on. Use it!

and

Robert Love wrote in message "[announce] procps 2.0.11":
> Rik and I are pleased to announce version 2.0.11 of procps, the package
> that contains ps, top, free, vmstat, etc.
> 
> Newer versions of procps are required for 2.5 kernels.
 > ...
> 
> Procps discussion, bugs, and patches are welcome at:
> 	procps-list@redhat.com

Which one should distributions use?
Or is that a matter of taste?

- Dan







^ permalink raw reply

* Re: Setting standard arguments
From: dashielljt @ 2002-12-13  1:47 UTC (permalink / raw)
  To: axel; +Cc: linux-newbie
In-Reply-To: <20021212161921.GA10853@neon.pearbough.net>

Never heard of that package and I have slackware 8.0 going on his machine.
It's not in the man pages, is it even part of traditional slackware full
install?  If not, you do best to check its documentation and faq file if
one exists.

Jude <dashielljt(at)gmpexpress-dot-net>

-
To unsubscribe from this list: send the line "unsubscribe linux-newbie" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.linux-learn.org/faqs

^ permalink raw reply

* Re: [PATCH] tcpv4: convert /proc/net/tcp to seq_file
From: Anders Gustafsson @ 2002-12-13  1:53 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo, David S. Miller,
	Linux Kernel Mailing List
In-Reply-To: <20021124020046.GA29645@conectiva.com.br>

Hi!

My netstat -nl on my a 2.5.51 machine seems to have caused some infinite loop
in listening_get_next. sysrq+t saying:

netstat       R current      0  4157   2742                     (NOTLB)
Call Trace:
 [<c0109ff1>] do_IRQ+0xbd/0x138
 [<c0108ab8>] common_interrupt+0x18/0x20
 [<c02257f0>] listening_get_next+0x180/0x1c4
 [<c0225b68>] tcp_seq_next+0x40/0xa0
 [<c0158408>] seq_read+0x1d4/0x28c
     
Machine is ipv4+6. And there are services listening on both. The 5 entries
that it managed to print were ipv4 entries only.

--
Anders Gustafsson - andersg@0x63.nu - http://0x63.nu/

On Sun, Nov 24, 2002 at 12:00:46AM -0200, Arnaldo Carvalho de Melo wrote:
> +static void *listening_get_next(struct seq_file *seq, void *cur)
> +{
> +	struct tcp_opt *tp;
> +	struct sock *sk = cur;
> +	struct tcp_iter_state* st = seq->private;
> +
> +	if (st->state == TCP_SEQ_STATE_OPENREQ) {
> +		struct open_request *req = cur;
> +
> +	       	tp = tcp_sk(st->syn_wait_sk);
> +		req = req->dl_next;
> +		while (1) {
> +			while (req) {
> +				++st->num;
> +				if (TCP_INET_FAMILY(req->class->family)) {
> +					cur = req;
> +					goto out;
> +				}
> +				req = req->dl_next;
> +			}
> +			if (++st->sbucket >= TCP_SYNQ_HSIZE)
> +				break;
> +get_req:
> +			req = tp->listen_opt->syn_table[st->sbucket];
> +		}
> +		sk	  = st->syn_wait_sk->next;
> +		st->state = TCP_SEQ_STATE_LISTENING;
> +		read_unlock_bh(&tp->syn_wait_lock);
> +	} else
> +		sk = sk->next;
> +get_sk:
> +	while (sk) {
> +		if (TCP_INET_FAMILY(sk->family)) {
> +			cur = sk;
> +			goto out;
> +		}
> +	       	tp = tcp_sk(sk);
> +		read_lock_bh(&tp->syn_wait_lock);
> +		if (tp->listen_opt && tp->listen_opt->qlen) {
> +			st->uid		= sock_i_uid(sk);
> +			st->syn_wait_sk = sk;
> +			st->state	= TCP_SEQ_STATE_OPENREQ;
> +			st->sbucket	= 0;
> +			goto get_req;
> +		}
> +		read_unlock_bh(&tp->syn_wait_lock);
> +	}
> +	if (++st->bucket < TCP_LHTABLE_SIZE) {
> +		sk = tcp_listening_hash[st->bucket];
> +		goto get_sk;
> +	}
> +	cur = NULL;
> +out:
> +	return cur;
> +}



^ permalink raw reply

* [PATCH] 2.4.20-rmap15b
From: Rik van Riel @ 2002-12-13  1:51 UTC (permalink / raw)
  To: linux-mm; +Cc: linux-kernel

Many changes, mostly backported from 2.5 by Ben LaHaise and
fixed up a bit more by myself. It all appears to work, but
more testing is appropriate.

The second maintenance release of the 15th version of the reverse
mapping based VM is now available.
This is an attempt at making a more robust and flexible VM
subsystem, while cleaning up a lot of code at the same time.
The patch is available from:

           http://surriel.com/patches/2.4/2.4.20-rmap15b
and        http://linuxvm.bkbits.net/


My big TODO items for a next release are:
  - finetune the O(1) VM code for strange corner cases


rmap 15b:
  - adjust anon/cache work table                          (me)
  - make active_age_bias a per-active list thing          (me)
  - don't wake up kswapd early from mark_page_accessed    (me)
  - make sure pte-chains are cacheline aligned with PAE   (me, Andrew Morton)
  - change some O(1) VM thresholds                        (me)
  - fix pte-highmem backport                              (me)
  - 2.5 backport: pte-highmem                             (Ben LaHaise)
  - 2.5 backport: large cacheline aligned pte-chains      (Ben LaHaise)
  - 2.5 backport: direct pte pointers                     (Ben LaHaise)
  - undo __find_pagecache_page braindamage		  (Christoph Hellwig)
rmap 15a:
  - more agressive freeing for higher order allocations   (me)
  - export __find_pagecache_page, find_get_page define    (me, Christoph, Arjan)
  - make memory statistics SMP safe again                 (me)
  - make page aging slow down again when needed           (Andrew Morton)
  - first stab at fine-tuning arjan's O(1) VM             (me)
  - split active list in cache / working set              (me)
  - fix SMP locking in arjan's O(1) VM                    (me)
rmap 15:
  - small code cleanups and spelling fixes for O(1) VM    (me)
  - O(1) page launder, O(1) page aging                    (Arjan van de Ven)
  - resync code with -ac (12 small patches)               (me)
rmap 14c:
  - fold page_over_rsslimit() into page_referenced()      (me)
  - 2.5 backport: get pte_chains from the slab cache      (William Lee Irwin)
  - remove dead code from page_launder_zone()             (me)
  - make OOM detection a bit more agressive               (me)
rmap 14b:
  - don't unmap pages not in pagecache (ext3 & reiser)    (Andrew Morton, me)
  - clean up mark_page_accessed a bit                     (me)
  - Alpha NUMA fix for Ingo's per-cpu pages               (Flávio Leitner, me)
  - remove explicit low latency schedule zap_page_range   (Robert Love)
  - fix OOM stuff for good, hopefully                     (me)
rmap 14a:
  - Ingo Molnar's per-cpu pages (SMP speedup)             (Christoph Hellwig)
  - fix SMP bug in page_launder_zone (rmap14 only)        (Arjan van de Ven)
  - semicolon day, fix typo in rmap.c w/ DEBUG_RMAP       (Craig Kulesa)
  - remove unneeded pte_chain_unlock/lock pair vmscan.c   (Craig Kulesa)
  - low latency zap_page_range also without preempt       (Arjan van de Ven)
  - do some throughput tuning for kswapd/page_launder     (me)
  - don't allocate swap space for pages we're not writing (me)
rmap 14:
  - get rid of stalls during swapping, hopefully          (me)
  - low latency zap_page_range                            (Robert Love)
rmap 13c:
  - add wmb() to wakeup_memwaiters                        (Arjan van de Ven)
  - remap_pmd_range now calls pte_alloc with full address (Paul Mackerras)
  - #ifdef out pte_chain_lock/unlock on UP machines       (Andrew Morton)
  - un-BUG() truncate_complete_page, the race is expected (Andrew Morton, me)
  - remove NUMA changes from rmap13a                      (Christoph Hellwig)
rmap 13b:
  - prevent PF_MEMALLOC recursion for higher order allocs (Arjan van de Ven, me)
  - fix small SMP race, PG_lru                            (Hugh Dickins)
rmap 13a:
  - NUMA changes for page_address                         (Samuel Ortiz)
  - replace vm.freepages with simpler kswapd_minfree      (Christoph Hellwig)
rmap 13:
  - rename touch_page to mark_page_accessed and uninline  (Christoph Hellwig)
  - NUMA bugfix for __alloc_pages                         (William Irwin)
  - kill __find_page                                      (Christoph Hellwig)
  - make pte_chain_freelist per zone                      (William Irwin)
  - protect pte_chains by per-page lock bit               (William Irwin)
  - minor code cleanups                                   (me)
rmap 12i:
  - slab cleanup                                          (Christoph Hellwig)
  - remove references to compiler.h from mm/*             (me)
  - move rmap to marcelo's bk tree                        (me)
  - minor cleanups                                        (me)
rmap 12h:
  - hopefully fix OOM detection algorithm                 (me)
  - drop pte quicklist in anticipation of pte-highmem     (me)
  - replace andrea's highmem emulation by ingo's one      (me)
  - improve rss limit checking                            (Nick Piggin)
rmap 12g:
  - port to armv architecture                             (David Woodhouse)
  - NUMA fix to zone_table initialisation                 (Samuel Ortiz)
  - remove init_page_count                                (David Miller)
rmap 12f:
  - for_each_pgdat macro                                  (William Lee Irwin)
  - put back EXPORT(__find_get_page) for modular rd       (me)
  - make bdflush and kswapd actually start queued disk IO (me)
rmap 12e
  - RSS limit fix, the limit can be 0 for some reason     (me)
  - clean up for_each_zone define to not need pgdata_t    (William Lee Irwin)
  - fix i810_dma bug introduced with page->wait removal   (William Lee Irwin)
rmap 12d:
  - fix compiler warning in rmap.c                        (Roger Larsson)
  - read latency improvement   (read-latency2)            (Andrew Morton)
rmap 12c:
  - fix small balancing bug in page_launder_zone          (Nick Piggin)
  - wakeup_kswapd / wakeup_memwaiters code fix            (Arjan van de Ven)
  - improve RSS limit enforcement                         (me)
rmap 12b:
  - highmem emulation (for debugging purposes)            (Andrea Arcangeli)
  - ulimit RSS enforcement when memory gets tight         (me)
  - sparc64 page->virtual quickfix                        (Greg Procunier)
rmap 12a:
  - fix the compile warning in buffer.c                   (me)
  - fix divide-by-zero on highmem initialisation  DOH!    (me)
  - remove the pgd quicklist (suspicious ...)             (DaveM, me)
rmap 12:
  - keep some extra free memory on large machines         (Arjan van de Ven, me)
  - higher-order allocation bugfix                        (Adrian Drzewiecki)
  - nr_free_buffer_pages() returns inactive + free mem    (me)
  - pages from unused objects directly to inactive_clean  (me)
  - use fast pte quicklists on non-pae machines           (Andrea Arcangeli)
  - remove sleep_on from wakeup_kswapd                    (Arjan van de Ven)
  - page waitqueue cleanup                                (Christoph Hellwig)
rmap 11c:
  - oom_kill race locking fix                             (Andres Salomon)
  - elevator improvement                                  (Andrew Morton)
  - dirty buffer writeout speedup (hopefully ;))          (me)
  - small documentation updates                           (me)
  - page_launder() never does synchronous IO, kswapd
    and the processes calling it sleep on higher level    (me)
  - deadlock fix in touch_page()                          (me)
rmap 11b:
  - added low latency reschedule points in vmscan.c       (me)
  - make i810_dma.c include mm_inline.h too               (William Lee Irwin)
  - wake up kswapd sleeper tasks on OOM kill so the
    killed task can continue on its way out               (me)
  - tune page allocation sleep point a little             (me)
rmap 11a:
  - don't let refill_inactive() progress count for OOM    (me)
  - after an OOM kill, wait 5 seconds for the next kill   (me)
  - agpgart_be fix for hashed waitqueues                  (William Lee Irwin)
rmap 11:
  - fix stupid logic inversion bug in wakeup_kswapd()     (Andrew Morton)
  - fix it again in the morning                           (me)
  - add #ifdef BROKEN_PPC_PTE_ALLOC_ONE to rmap.h, it
    seems PPC calls pte_alloc() before mem_map[] init     (me)
  - disable the debugging code in rmap.c ... the code
    is working and people are running benchmarks          (me)
  - let the slab cache shrink functions return a value
    to help prevent early OOM killing                     (Ed Tomlinson)
  - also, don't call the OOM code if we have enough
    free pages                                            (me)
  - move the call to lru_cache_del into __free_pages_ok   (Ben LaHaise)
  - replace the per-page waitqueue with a hashed
    waitqueue, reduces size of struct page from 64
    bytes to 52 bytes (48 bytes on non-highmem machines)  (William Lee Irwin)
rmap 10:
  - fix the livelock for real (yeah right), turned out
    to be a stupid bug in page_launder_zone()             (me)
  - to make sure the VM subsystem doesn't monopolise
    the CPU, let kswapd and some apps sleep a bit under
    heavy stress situations                               (me)
  - let __GFP_HIGH allocations dig a little bit deeper
    into the free page pool, the SCSI layer seems fragile (me)
rmap 9:
  - improve comments all over the place                   (Michael Cohen)
  - don't panic if page_remove_rmap() cannot find the
    rmap in question, it's possible that the memory was
    PG_reserved and belonging to a driver, but the driver
    exited and cleared the PG_reserved bit                (me)
  - fix the VM livelock by replacing > by >= in a few
    critical places in the pageout code                   (me)
  - treat the reclaiming of an inactive_clean page like
    allocating a new page, calling try_to_free_pages()
    and/or fixup_freespace() if required                  (me)
  - when low on memory, don't make things worse by
    doing swapin_readahead                                (me)
rmap 8:
  - add ANY_ZONE to the balancing functions to improve
    kswapd's balancing a bit                              (me)
  - regularize some of the maximum loop bounds in
    vmscan.c for cosmetic purposes                        (William Lee Irwin)
  - move page_address() to architecture-independent
    code, now the removal of page->virtual is portable    (William Lee Irwin)
  - speed up free_area_init_core() by doing a single
    pass over the pages and not using atomic ops          (William Lee Irwin)
  - documented the buddy allocator in page_alloc.c        (William Lee Irwin)
rmap 7:
  - clean up and document vmscan.c                        (me)
  - reduce size of page struct, part one                  (William Lee Irwin)
  - add rmap.h for other archs (untested, not for ARM)    (me)
rmap 6:
  - make the active and inactive_dirty list per zone,
    this is finally possible because we can free pages
    based on their physical address                       (William Lee Irwin)
  - cleaned up William's code a bit                       (me)
  - turn some defines into inlines and move those to
    mm_inline.h (the includes are a mess ...)             (me)
  - improve the VM balancing a bit                        (me)
  - add back inactive_target to /proc/meminfo             (me)
rmap 5:
  - fixed recursive buglet, introduced by directly
    editing the patch for making rmap 4 ;)))              (me)
rmap 4:
  - look at the referenced bits in page tables            (me)
rmap 3:
  - forgot one FASTCALL definition                        (me)
rmap 2:
  - teach try_to_unmap_one() about mremap()               (me)
  - don't assign swap space to pages with buffers         (me)
  - make the rmap.c functions FASTCALL / inline           (me)
rmap 1:
  - fix the swap leak in rmap 0                           (Dave McCracken)
rmap 0:
  - port of reverse mapping VM to 2.4.16                  (me)

Rik
-- 
Bravely reimplemented by the knights who say "NIH".
http://www.surriel.com/		http://guru.conectiva.com/
Current spamtrap:  <a href=mailto:"october@surriel.com">october@surriel.com</a>

^ permalink raw reply

* Linux/alpha vs. 2.4.20 and ISO9660 vs long file names
From: Stephen Williams @ 2002-12-13  1:49 UTC (permalink / raw)
  To: linux-kernel

I don't know if this is an alpha-specific problem, but I am having
some troubles with the off-the-shelf 2.4.20 kernel on a RedHat 7.2
system (upgraded from 7.1).

For some reason, ls is having trouble with long file names on the
disk. I follow with strace, and getdents64 is returning the right
number of entries, but then ls tries to lstat a truncated name.
I can't say of the getdirent64 is trundating the name, but it seems
likely.

The ls program itself is likely fine because I don't see this
problem when running 2.4.18. Also, other programs that get directory
listings have troubles with the longer file names on ISO CDROMS.
Furthermore, shorter file names (still longer then 8 characters)
work fine.

P.S. I'm not subscribed to the list. Please CC me.

-- 
Steve Williams                "The woods are lovely, dark and deep.
steve at icarus.com           But I have promises to keep,
steve at picturel.com         and lines to code before I sleep,
http://www.picturel.com       And lines to code before I sleep."



^ permalink raw reply

* [PATCH][2.5][CFT] ad1848 PnP updates + fixes
From: Zwane Mwaikambo @ 2002-12-13  1:51 UTC (permalink / raw)
  To: Linux Kernel; +Cc: Adam Belay

I tried not to leak too many 'fixes' in there, but some stuff got into the
way of debugging. I've tested this on;

ad1848/cs4248 codec driver Copyright (C) by Hannu Savolainen 1993-1996
pnp: the driver 'ad1848' has been registered
ad1848: No ISAPnP cards found, trying standard ones...
pnp: the driver 'opl3sa2' has been registered
pnp: pnp: match found with the PnP device '00:01.00' and the driver
'opl3sa2'
pnp: the device '00:01.00' has been activated
opl3sa2: chipset version = 0x3
opl3sa2: Found OPL3-SA3 (YMF715B or YMF719B)
<OPL3-SA3> at 0x100 irq 5 dma 1,3
<MS Sound System (CS4231)> at 0xe84 irq 5 dma 1,3
<MPU-401 0.0  Midi interface #1> at 0x300 irq 5
opl3sa2: 1 PnP card(s) found.

Index: linux-2.5.51/sound/oss/ad1848.c
===================================================================
RCS file: /build/cvsroot/linux-2.5.51/sound/oss/ad1848.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 ad1848.c
--- linux-2.5.51/sound/oss/ad1848.c	10 Dec 2002 12:48:01 -0000	1.1.1.1
+++ linux-2.5.51/sound/oss/ad1848.c	13 Dec 2002 01:19:49 -0000
@@ -33,6 +33,7 @@
  * Alan Cox		: Added CS4236->4239 identification
  * Daniel T. Cobra	: Alernate config/mixer for later chips
  * Alan Cox		: Merged chip idents and config code
+ * Zwane Mwaikambo	: Converted to 2.5 PnP API
  *
  * TODO
  *		APM save restore assist code on IBM thinkpad
@@ -47,7 +48,6 @@
 #include <linux/module.h>
 #include <linux/stddef.h>
 #include <linux/pm.h>
-#include <linux/isapnp.h>
 #include <linux/pnp.h>
 #include <linux/spinlock.h>

@@ -107,6 +107,9 @@

 	/* Power management */
 	struct		pm_dev *pmdev;
+#ifdef CONFIG_PNP
+	struct pnp_dev	*pnp_dev;
+#endif
 } ad1848_info;

 typedef struct ad1848_port_info
@@ -180,9 +183,6 @@

 #ifdef CONFIG_PNP
 static int isapnp	= 1;
-static int isapnpjump	= 0;
-static int reverse	= 0;
-
 static int audio_activated = 0;
 #else
 static int isapnp	= 0;
@@ -207,17 +207,15 @@
 static void ad1848_tmr_reprogram(int dev);
 #endif

+/* has to be called with devc->lock held */
 static int ad_read(ad1848_info * devc, int reg)
 {
-	unsigned long flags;
 	int x;
 	int timeout = 900000;

 	while (timeout > 0 && inb(devc->base) == 0x80)	/*Are we initializing */
 		timeout--;

-	spin_lock_irqsave(&devc->lock,flags);
-
 	if(reg < 32)
 	{
 		outb(((unsigned char) (reg & 0xff) | devc->MCE_bit), io_Index_Addr(devc));
@@ -233,21 +231,18 @@
 		outb(((unsigned char) (xra & 0xff)), io_Indexed_Data(devc));
 		x = inb(io_Indexed_Data(devc));
 	}
-	spin_unlock_irqrestore(&devc->lock,flags);

 	return x;
 }

+/* has to be called with the devc->lock held */
 static void ad_write(ad1848_info * devc, int reg, int data)
 {
-	unsigned long flags;
 	int timeout = 900000;

 	while (timeout > 0 && inb(devc->base) == 0x80)	/* Are we initializing */
 		timeout--;

-	spin_lock_irqsave(&devc->lock,flags);
-
 	if(reg < 32)
 	{
 		outb(((unsigned char) (reg & 0xff) | devc->MCE_bit), io_Index_Addr(devc));
@@ -263,7 +258,6 @@
 		outb(((unsigned char) (xra & 0xff)), io_Indexed_Data(devc));
 		outb((unsigned char) (data & 0xff), io_Indexed_Data(devc));
 	}
-	spin_unlock_irqrestore(&devc->lock,flags);
 }

 static void wait_for_calibration(ad1848_info * devc)
@@ -307,10 +301,7 @@
 	 */

 	for (i = 6; i < 8; i++)
-	{
 		prev = devc->saved_regs[i] = ad_read(devc, i);
-	}
-
 }

 static void ad_unmute(ad1848_info * devc)
@@ -319,37 +310,28 @@

 static void ad_enter_MCE(ad1848_info * devc)
 {
-	unsigned long flags;
 	int timeout = 1000;
 	unsigned short prev;

 	while (timeout > 0 && inb(devc->base) == 0x80)	/*Are we initializing */
 		timeout--;

-	spin_lock_irqsave(&devc->lock,flags);
-
 	devc->MCE_bit = 0x40;
 	prev = inb(io_Index_Addr(devc));
 	if (prev & 0x40)
-	{
-		spin_unlock_irqrestore(&devc->lock,flags);
 		return;
-	}
+
 	outb((devc->MCE_bit), io_Index_Addr(devc));
-	spin_unlock_irqrestore(&devc->lock,flags);
 }

 static void ad_leave_MCE(ad1848_info * devc)
 {
-	unsigned long flags;
 	unsigned char prev, acal;
 	int timeout = 1000;

 	while (timeout > 0 && inb(devc->base) == 0x80)	/*Are we initializing */
 		timeout--;

-	spin_lock_irqsave(&devc->lock,flags);
-
 	acal = ad_read(devc, 9);

 	devc->MCE_bit = 0x00;
@@ -357,14 +339,11 @@
 	outb((0x00), io_Index_Addr(devc));	/* Clear the MCE bit */

 	if ((prev & 0x40) == 0)	/* Not in MCE mode */
-	{
-		spin_unlock_irqrestore(&devc->lock,flags);
 		return;
-	}
+
 	outb((0x00), io_Index_Addr(devc));	/* Clear the MCE bit */
 	if (acal & 0x08)	/* Auto calibration is enabled */
 		wait_for_calibration(devc);
-	spin_unlock_irqrestore(&devc->lock,flags);
 }

 static int ad1848_set_recmask(ad1848_info * devc, int mask)
@@ -527,7 +506,9 @@
 {
 	int regoffs, muteregoffs;
 	unsigned char val, muteval;
+	unsigned long flags;

+	spin_lock_irqsave(&devc->lock, flags);
 	regoffs = devc->mix_devices[dev][channel].regno;
 	muteregoffs = devc->mix_devices[dev][channel].mutereg;
 	val = ad_read(devc, regoffs);
@@ -545,6 +526,7 @@
 		ad_write(devc, muteregoffs, muteval);
 		devc->saved_regs[muteregoffs] = muteval;
 	}
+	spin_unlock_irqrestore(&devc->lock, flags);
 }

 static int ad1848_mixer_set(ad1848_info * devc, int dev, int value)
@@ -600,7 +582,8 @@
 {
 	int i;
 	char name[32];
-
+	unsigned long flags;
+
 	devc->mix_devices = &(ad1848_mix_devices[0]);

 	sprintf(name, "%s_%d", devc->chip_name, nr_ad1848_devs);
@@ -661,7 +644,8 @@
 		if (devc->supported_devices & (1 << i))
 			ad1848_mixer_set(devc, i, devc->levels[i]);
 	}
-
+
+	spin_lock_irqsave(&devc->lock, flags);
 	ad1848_set_recmask(devc, SOUND_MASK_MIC);

 	devc->mixer_output_port = devc->levels[31] | AUDIO_HEADPHONE | AUDIO_LINE_OUT;
@@ -679,13 +663,15 @@
 		/* Enable surround mode and SB16 mixer */
 		ad_write(devc, 16, 0x60);
 	}
+	spin_unlock_irqrestore(&devc->lock, flags);
 }

 static int ad1848_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg)
 {
 	ad1848_info *devc = mixer_devs[dev]->devc;
+	unsigned long flags;
 	int val;
-
+
 	if (cmd == SOUND_MIXER_PRIVATE1)
 	{
 		if (get_user(val, (int *)arg))
@@ -697,10 +683,12 @@
 			devc->mixer_output_port = val;
 			val |= AUDIO_HEADPHONE | AUDIO_LINE_OUT;	/* Always on */
 			devc->mixer_output_port = val;
+			spin_lock_irqsave(&devc->lock, flags);
 			if (val & AUDIO_SPEAKER)
 				ad_write(devc, 26, ad_read(devc, 26) & ~0x40);	/* Unmute mono out */
 			else
 				ad_write(devc, 26, ad_read(devc, 26) | 0x40);		/* Mute mono out */
+			spin_unlock_irqrestore(&devc->lock, flags);
 		}
 		val = devc->mixer_output_port;
 		return put_user(val, (int *)arg);
@@ -720,7 +708,9 @@
 				case SOUND_MIXER_RECSRC:
 					if (get_user(val, (int *)arg))
 						return -EFAULT;
+					spin_lock_irqsave(&devc->lock, flags);
 					val = ad1848_set_recmask(devc, val);
+					spin_unlock_irqrestore(&devc->lock, flags);
 					break;

 				default:
@@ -977,7 +967,7 @@
 {
 	ad1848_info    *devc;
 	ad1848_port_info *portc;
-	unsigned long   flags;
+	unsigned long flags;

 	if (dev < 0 || dev >= num_audiodevs)
 		return -ENXIO;
@@ -985,18 +975,16 @@
 	devc = (ad1848_info *) audio_devs[dev]->devc;
 	portc = (ad1848_port_info *) audio_devs[dev]->portc;

-	spin_lock_irqsave(&devc->lock,flags);
-	if (portc->open_mode || (devc->open_mode & mode))
-	{
-		spin_unlock_irqrestore(&devc->lock,flags);
+	spin_lock_irqsave(&devc->lock, flags);
+	if (portc->open_mode || (devc->open_mode & mode)) {
+		spin_unlock_irqrestore(&devc->lock, flags);
 		return -EBUSY;
 	}
 	devc->dual_dma = 0;

 	if (audio_devs[dev]->flags & DMA_DUPLEX)
-	{
 		devc->dual_dma = 1;
-	}
+
 	devc->intr_active = 0;
 	devc->audio_mode = 0;
 	devc->open_mode |= mode;
@@ -1007,10 +995,10 @@
 		devc->record_dev = dev;
 	if (mode & OPEN_WRITE)
 		devc->playback_dev = dev;
-	spin_unlock_irqrestore(&devc->lock,flags);
 /*
  * Mute output until the playback really starts. This decreases clicking (hope so).
  */
+	spin_unlock_irqrestore(&devc->lock, flags);
 	ad_mute(devc);

 	return 0;
@@ -1018,23 +1006,24 @@

 static void ad1848_close(int dev)
 {
-	unsigned long   flags;
 	ad1848_info    *devc = (ad1848_info *) audio_devs[dev]->devc;
 	ad1848_port_info *portc = (ad1848_port_info *) audio_devs[dev]->portc;
+	unsigned long flags;

 	DEB(printk("ad1848_close(void)\n"));
-
-	spin_lock_irqsave(&devc->lock,flags);
-
+
+	spin_lock_irqsave(&devc->lock, flags);
 	devc->intr_active = 0;
+	spin_unlock_irqrestore(&devc->lock, flags);
+
 	ad1848_halt(dev);

+	spin_lock_irqsave(&devc->lock, flags);
 	devc->audio_mode = 0;
 	devc->open_mode &= ~portc->open_mode;
 	portc->open_mode = 0;
-
+	spin_unlock_irqrestore(&devc->lock, flags);
 	ad_unmute(devc);
-	spin_unlock_irqrestore(&devc->lock,flags);
 }

 static void ad1848_output_block(int dev, unsigned long buf, int count, int intrflag)
@@ -1111,13 +1100,10 @@
 	}
 	spin_lock_irqsave(&devc->lock,flags);

-	if (devc->model == MD_1848)
-	{
+	if (devc->model == MD_1848) {
 		  ad_write(devc, 15, (unsigned char) (cnt & 0xff));
 		  ad_write(devc, 14, (unsigned char) ((cnt >> 8) & 0xff));
-	}
-	else
-	{
+	} else {
 		  ad_write(devc, 31, (unsigned char) (cnt & 0xff));
 		  ad_write(devc, 30, (unsigned char) ((cnt >> 8) & 0xff));
 	}
@@ -1336,9 +1322,8 @@
 	if (!(ad_read(devc, 9) & 0x02))
 		return;		/* Capture not enabled */

-	spin_lock_irqsave(&devc->lock,flags);
-
 	ad_mute(devc);
+	spin_lock_irqsave(&devc->lock,flags);

 	{
 		int             tmout;
@@ -1372,9 +1357,9 @@
 	if (!(ad_read(devc, 9) & 0x01))
 		return;		/* Playback not enabled */

+	ad_mute(devc);
 	spin_lock_irqsave(&devc->lock,flags);

-	ad_mute(devc);
 	{
 		int             tmout;

@@ -1404,35 +1389,28 @@
 {
 	ad1848_info    *devc = (ad1848_info *) audio_devs[dev]->devc;
 	ad1848_port_info *portc = (ad1848_port_info *) audio_devs[dev]->portc;
-	unsigned long   flags;
 	unsigned char   tmp, old;

-	spin_lock_irqsave(&devc->lock,flags);
 	state &= devc->audio_mode;
-
 	tmp = old = ad_read(devc, 9);

-	if (portc->open_mode & OPEN_READ)
-	{
+	if (portc->open_mode & OPEN_READ) {
 		  if (state & PCM_ENABLE_INPUT)
 			  tmp |= 0x02;
 		  else
 			  tmp &= ~0x02;
 	}
-	if (portc->open_mode & OPEN_WRITE)
-	{
+	if (portc->open_mode & OPEN_WRITE) {
 		if (state & PCM_ENABLE_OUTPUT)
 			tmp |= 0x01;
 		else
 			tmp &= ~0x01;
 	}
 	/* ad_mute(devc); */
-	if (tmp != old)
-	{
+	if (tmp != old) {
 		  ad_write(devc, 9, tmp);
 		  ad_unmute(devc);
 	}
-	spin_unlock_irqrestore(&devc->lock,flags);
 }

 static void ad1848_init_hw(ad1848_info * devc)
@@ -1580,11 +1558,7 @@
 		printk(KERN_ERR "ad1848 - Too many audio devices\n");
 		return 0;
 	}
-	if (check_region(io_base, 4))
-	{
-		printk(KERN_ERR "ad1848.c: Port %x not free.\n", io_base);
-		return 0;
-	}
+
 	devc->base = io_base;
 	devc->irq_ok = 0;
 	devc->timer_running = 0;
@@ -1969,7 +1943,6 @@

 	ad1848_port_info *portc = NULL;

-	spin_lock_init(&devc->lock);
 	devc->irq = (irq > 0) ? irq : 0;
 	devc->open_mode = 0;
 	devc->timer_ticks = 0;
@@ -2039,17 +2012,14 @@

 	ad1848_init_hw(devc);

-	if (irq > 0)
-	{
+	if (irq > 0) {
 		devc->dev_no = my_dev;
-		if (request_irq(devc->irq, adintr, 0, devc->name, (void *)my_dev) < 0)
-		{
+		if (request_irq(devc->irq, adintr, 0, devc->name, (void *)my_dev) < 0) {
 			printk(KERN_WARNING "ad1848: Unable to allocate IRQ\n");
 			/* Don't free it either then.. */
 			devc->irq = 0;
 		}
-		if (capabilities[devc->model].flags & CAP_F_TIMER)
-		{
+		if (capabilities[devc->model].flags & CAP_F_TIMER) {
 #ifndef CONFIG_SMP
 			int x;
 			unsigned char tmp = ad_read(devc, 16);
@@ -2066,8 +2036,7 @@

 			if (devc->timer_ticks == 0)
 				printk(KERN_WARNING "ad1848: Interrupt test failed (IRQ%d)\n", irq);
-			else
-			{
+			else {
 				DDB(printk("Interrupt test OK\n"));
 				devc->irq_ok = 1;
 			}
@@ -2086,8 +2055,7 @@
 		ad1848_tmr_install(my_dev);
 #endif

-	if (!share_dma)
-	{
+	if (!share_dma) {
 		if (sound_alloc_dma(dma_playback, devc->name))
 			printk(KERN_WARNING "ad1848.c: Can't allocate DMA%d\n", dma_playback);

@@ -2100,8 +2068,7 @@
 				     dev_name,
 				     &ad1848_mixer_operations,
 				     sizeof(struct mixer_operations),
-				     devc)) >= 0)
-	{
+				     devc)) >= 0) {
 		audio_devs[my_dev]->mixer_dev = e;
 		if (owner)
 			mixer_devs[e]->owner = owner;
@@ -2112,6 +2079,7 @@
 int ad1848_control(int cmd, int arg)
 {
 	ad1848_info *devc;
+	unsigned long flags;

 	if (nr_ad1848_devs < 1)
 		return -ENODEV;
@@ -2123,9 +2091,11 @@
 		case AD1848_SET_XTAL:	/* Change clock frequency of AD1845 (only ) */
 			if (devc->model != MD_1845 || devc->model != MD_1845_SSCAPE)
 				return -EINVAL;
+			spin_lock_irqsave(&devc->lock, flags);
 			ad_enter_MCE(devc);
 			ad_write(devc, 29, (ad_read(devc, 29) & 0x1f) | (arg << 5));
 			ad_leave_MCE(devc);
+			spin_unlock_irqrestore(&devc->lock, flags);
 			break;

 		case AD1848_MIXER_REROUTE:
@@ -2171,23 +2141,19 @@
 	int i, mixer, dev = 0;
 	ad1848_info *devc = NULL;

-	for (i = 0; devc == NULL && i < nr_ad1848_devs; i++)
-	{
-		if (adev_info[i].base == io_base)
-		{
+	for (i = 0; devc == NULL && i < nr_ad1848_devs; i++) {
+		if (adev_info[i].base == io_base) {
 			devc = &adev_info[i];
 			dev = devc->dev_no;
 		}
 	}

-	if (devc != NULL)
-	{
+	if (devc != NULL) {
 		if(audio_devs[dev]->portc!=NULL)
 			kfree(audio_devs[dev]->portc);
 		release_region(devc->base, 4);

-		if (!share_dma)
-		{
+		if (!share_dma) {
 			if (devc->irq > 0) /* There is no point in freeing irq, if it wasn't allocated */
 				free_irq(devc->irq, (void *)devc->dev_no);

@@ -2198,12 +2164,14 @@

 		}
 		mixer = audio_devs[devc->dev_no]->mixer_dev;
-		if(mixer>=0)
+		if (mixer>=0)
 			sound_unload_mixerdev(mixer);

 		if (devc->pmdev)
 			pm_unregister(devc->pmdev);
-
+#ifdef CONFIG_PNP
+		put_device(&devc->pnp_dev->dev);
+#endif
 		nr_ad1848_devs--;
 		for ( ; i < nr_ad1848_devs ; i++)
 			adev_info[i] = adev_info[i+1];
@@ -2223,6 +2191,7 @@

 	dev = (int)dev_id;
 	devc = (ad1848_info *) audio_devs[dev]->devc;
+	spin_lock(&devc->lock);

 interrupt_again:		/* Jump back here if int status doesn't reset */

@@ -2237,18 +2206,12 @@
 	{
 		if (devc->model == MD_C930)
 		{		/* 82C930 has interrupt status register in MAD16 register MC11 */
-
-			spin_lock(&devc->lock);
-
 			/* 0xe0e is C930 address port
 			 * 0xe0f is C930 data port
 			 */
 			outb(11, 0xe0e);
 			c930_stat = inb(0xe0f);
 			outb((~c930_stat), 0xe0f);
-
-			spin_unlock(&devc->lock);
-
 			alt_stat = (c930_stat << 2) & 0x30;
 		}
 		else if (devc->model != MD_1848)
@@ -2285,6 +2248,7 @@
 	{
 		  goto interrupt_again;
 	}
+	spin_unlock(&devc->lock);
 }

 /*
@@ -2524,11 +2488,6 @@

 	DDB(printk("Entered probe_ms_sound(%x, %d)\n", hw_config->io_base, hw_config->card_subtype));

-	if (check_region(hw_config->io_base, 8))
-	{
-		printk(KERN_ERR "MSS: I/O port conflict\n");
-		return 0;
-	}
 	if (hw_config->card_subtype == 1)	/* Has no IRQ/DMA registers */
 	{
 		/* check_opl3(0x388, hw_config); */
@@ -2723,8 +2682,6 @@
 	unsigned long   xtal_nsecs;	/* nanoseconds per xtal oscillator tick */
 	unsigned long   divider;

-	spin_lock_irqsave(&devc->lock,flags);
-
 	/*
 	 * Length of the timer interval (in nanoseconds) depends on the
 	 * selected crystal oscillator. Check this from bit 0x01 of I8.
@@ -2751,6 +2708,7 @@
 	if (divider > 65535)	/* Overflow check */
 		divider = 65535;

+	spin_lock_irqsave(&devc->lock,flags);
 	ad_write(devc, 21, (divider >> 8) & 0xff);	/* Set upper bits */
 	ad_write(devc, 20, divider & 0xff);	/* Set lower bits */
 	ad_write(devc, 16, ad_read(devc, 16) | 0x40);	/* Start the timer */
@@ -2819,13 +2777,8 @@

 static int ad1848_suspend(ad1848_info *devc)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&devc->lock,flags);
-
 	ad_mute(devc);

-	spin_unlock_irqrestore(&devc->lock,flags);
 	return 0;
 }

@@ -2833,9 +2786,8 @@
 {
 	unsigned long flags;
 	int mixer_levels[32], i;
-
-	spin_lock_irqsave(&devc->lock,flags);

+	local_irq_save(flags);
 	/* Thinkpad is a bit more of PITA than normal. The BIOS tends to
 	   restore it in a different config to the one we use.  Need to
 	   fix this somehow */
@@ -2860,7 +2812,7 @@
 		bits = interrupt_bits[devc->irq];
 		if (bits == -1) {
 			printk(KERN_ERR "MSS: Bad IRQ %d\n", devc->irq);
-			spin_unlock_irqrestore(&devc->lock,flags);
+			local_irq_restore(flags);
 			return -1;
 		}

@@ -2875,7 +2827,7 @@
 		outb((bits | dma_bits[devc->dma1] | dma2_bit), config_port);
 	}

-	spin_unlock_irqrestore(&devc->lock,flags);
+	local_irq_restore(flags);
 	return 0;
 }

@@ -2924,13 +2876,7 @@

 #ifdef CONFIG_PNP
 MODULE_PARM(isapnp,	"i");
-MODULE_PARM(isapnpjump,	"i");
-MODULE_PARM(reverse,	"i");
 MODULE_PARM_DESC(isapnp,	"When set to 0, Plug & Play support will be disabled");
-MODULE_PARM_DESC(isapnpjump,	"Jumps to a specific slot in the driver's PnP table. Use the source, Luke.");
-MODULE_PARM_DESC(reverse,	"When set to 1, will reverse ISAPnP search order");
-
-struct pnp_dev	*ad1848_dev  = NULL;

 /* Please add new entries at the end of the table */
 static struct {
@@ -2952,10 +2898,12 @@
                 ISAPNP_ANY_ID, ISAPNP_ANY_ID,
 		ISAPNP_VENDOR('C','S','C'), ISAPNP_FUNCTION(0x0100),
 		0, 0, 0, 1, 0},
-        {"OPL3-SA2 WSS mode",
+        /* This is handled by the opl3sa2 driver
+	{"OPL3-SA2 WSS mode",
         	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
 		ISAPNP_VENDOR('Y','M','H'), ISAPNP_FUNCTION(0x0021),
                 1, 0, 0, 1, 1},
+	*/
 	{"Advanced Gravis InterWave Audio",
 		ISAPNP_VENDOR('G','R','V'), ISAPNP_DEVICE(0x0001),
 		ISAPNP_VENDOR('G','R','V'), ISAPNP_FUNCTION(0x0000),
@@ -2963,137 +2911,81 @@
 	{0}
 };

-static struct isapnp_device_id id_table[] __devinitdata = {
-	{	ISAPNP_VENDOR('C','M','I'), ISAPNP_DEVICE(0x0001),
-		ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001), 0 },
-        {       ISAPNP_ANY_ID, ISAPNP_ANY_ID,
-		ISAPNP_VENDOR('C','S','C'), ISAPNP_FUNCTION(0x0000), 0 },
-        {       ISAPNP_ANY_ID, ISAPNP_ANY_ID,
-		ISAPNP_VENDOR('C','S','C'), ISAPNP_FUNCTION(0x0100), 0 },
-        {       ISAPNP_ANY_ID, ISAPNP_ANY_ID,
-		ISAPNP_VENDOR('Y','M','H'), ISAPNP_FUNCTION(0x0021), 0 },
-	{	ISAPNP_VENDOR('G','R','V'), ISAPNP_DEVICE(0x0001),
-		ISAPNP_VENDOR('G','R','V'), ISAPNP_FUNCTION(0x0000), 0 },
-	{0}
+static const struct pnp_device_id ad1848_id_table[] __devinitdata = {
+	{.id = "CMI0001" },
+	{.id = "@@@0001" },
+	{.id = "CSC0000" },
+	{.id = "CSC0100" },
+	/* {.id = "YMH0021" }, */
+	{.id = "GRV0001" },
+	{.id = "GRV0000" },
+	{.id = ""}
 };

-MODULE_DEVICE_TABLE(isapnp, id_table);
+MODULE_DEVICE_TABLE(pnp, ad1848_id_table);

-static struct pnp_dev *activate_dev(char *devname, char *resname, struct pnp_dev *dev)
+static int ad1848_isapnp_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *dev_id)
 {
-	int err;
+	ad1848_info *priv;
+	int mss_io_index, irq_index, dma_index, dma2_index;

-	/* Device already active? Let's use it */
-	if(dev->active)
-		return(dev);
+	if (nr_ad1848_devs >= MAX_AUDIO_DEV)
+		return -ENOSPC;

-	if((err = pnp_activate_dev(dev)) < 0) {
-		printk(KERN_ERR "ad1848: %s %s config failed (out of resources?)[%d]\n", devname, resname, err);
+	priv = &adev_info[nr_ad1848_devs];
+	priv->pnp_dev = pnp_dev;
+	get_device(&pnp_dev->dev);
+
+	mss_io_index = ad1848_isapnp_list[nr_ad1848_devs].mss_io;
+	irq_index = ad1848_isapnp_list[nr_ad1848_devs].irq;
+	dma_index = ad1848_isapnp_list[nr_ad1848_devs].dma;
+	dma2_index = ad1848_isapnp_list[nr_ad1848_devs].dma2;
+
+	cfg.io_base = pnp_dev->resource[mss_io_index].start;
+	cfg.irq = pnp_dev->irq_resource[irq_index].start;
+	cfg.dma = pnp_dev->dma_resource[dma_index].start;

-		pnp_disable_dev(dev);
+	if (dma2_index != -1)
+		cfg.dma2 = pnp_dev->dma_resource[dma2_index].start;
+	else
+		cfg.dma2 = -1;

-		return(NULL);
-	}
+	printk(KERN_NOTICE "ad1848: ISAPnP reports '%s' at i/o %#x, irq %d, dma %d, %d\n",
+		pnp_dev->name, cfg.io_base, cfg.irq, cfg.dma, cfg.dma2);
 	audio_activated = 1;
-	return(dev);
-}
-
-static struct pnp_dev *ad1848_init_generic(struct pnp_card *bus, struct address_info *hw_config, int slot)
-{
-
-	/* Configure Audio device */
-	if((ad1848_dev = pnp_find_dev(bus, ad1848_isapnp_list[slot].vendor, ad1848_isapnp_list[slot].function, NULL)))
-	{
-		if((ad1848_dev = activate_dev(ad1848_isapnp_list[slot].name, "ad1848", ad1848_dev)))
-		{
-			get_device(&ad1848_dev->dev);
-			hw_config->io_base 	= ad1848_dev->resource[ad1848_isapnp_list[slot].mss_io].start;
-			hw_config->irq 		= ad1848_dev->irq_resource[ad1848_isapnp_list[slot].irq].start;
-			hw_config->dma 		= ad1848_dev->dma_resource[ad1848_isapnp_list[slot].dma].start;
-			if(ad1848_isapnp_list[slot].dma2 != -1)
-				hw_config->dma2 = ad1848_dev->dma_resource[ad1848_isapnp_list[slot].dma2].start;
-			else
-				hw_config->dma2 = -1;
-                        hw_config->card_subtype = ad1848_isapnp_list[slot].type;
-		} else
-			return(NULL);
-	} else
-		return(NULL);

-	return(ad1848_dev);
-}
-
-static int __init ad1848_isapnp_init(struct address_info *hw_config, struct pnp_card *bus, int slot)
-{
-	char *busname = bus->name[0] ? bus->name : ad1848_isapnp_list[slot].name;
-
-	/* Initialize this baby. */
-
-	if(ad1848_init_generic(bus, hw_config, slot)) {
-		/* We got it. */
-
-		printk(KERN_NOTICE "ad1848: ISAPnP reports '%s' at i/o %#x, irq %d, dma %d, %d\n",
-		       busname,
-		       hw_config->io_base, hw_config->irq, hw_config->dma,
-		       hw_config->dma2);
-		return 1;
-	}
 	return 0;
 }

-static int __init ad1848_isapnp_probe(struct address_info *hw_config)
-{
-	static int first = 1;
-	int i;
-
-	/* Count entries in sb_isapnp_list */
-	for (i = 0; ad1848_isapnp_list[i].card_vendor != 0; i++);
-	i--;
-
-	/* Check and adjust isapnpjump */
-	if( isapnpjump < 0 || isapnpjump > i) {
-		isapnpjump = reverse ? i : 0;
-		printk(KERN_ERR "ad1848: Valid range for isapnpjump is 0-%d. Adjusted to %d.\n", i, isapnpjump);
-	}
-
-	if(!first || !reverse)
-		i = isapnpjump;
-	first = 0;
-	while(ad1848_isapnp_list[i].card_vendor != 0) {
-		static struct pnp_card *bus = NULL;
-
-		while ((bus = pnp_find_card(
-				ad1848_isapnp_list[i].card_vendor,
-				ad1848_isapnp_list[i].card_device,
-				bus))) {
-
-			if(ad1848_isapnp_init(hw_config, bus, i)) {
-				isapnpjump = i; /* start next search from here */
-				return 0;
-			}
-		}
-		i += reverse ? -1 : 1;
-	}
-
-	return -ENODEV;
-}
+static struct pnp_driver ad1848_driver = {
+	.name		= "ad1848",
+	.id_table	= ad1848_id_table,
+	.probe		= ad1848_isapnp_probe,
+};
 #endif


 static int __init init_ad1848(void)
 {
+	int i;
 	printk(KERN_INFO "ad1848/cs4248 codec driver Copyright (C) by Hannu Savolainen 1993-1996\n");

+	for (i = 0; i < MAX_AUDIO_DEV; i++)
+		spin_lock_init(&adev_info[i].lock);
+
 #ifdef CONFIG_PNP
-	if(isapnp && (ad1848_isapnp_probe(&cfg) < 0) ) {
-		printk(KERN_NOTICE "ad1848: No ISAPnP cards found, trying standard ones...\n");
-		isapnp = 0;
+	if (isapnp) {	/* FIXME I don't think this override can work anymore... -Zwane */
+		/* On return our settings are in cfg */
+		pnp_register_driver(&ad1848_driver);
+		if (audio_activated == 0) {
+			printk(KERN_NOTICE "ad1848: No ISAPnP cards found, trying standard ones...\n");
+			isapnp = 0;
+		}
 	}
 #endif

-	if(io != -1) {
-	        if( isapnp == 0 )
-	        {
+	if (io != -1) {
+	        if ( isapnp == 0 ) {
 			if(irq == -1 || dma == -1) {
 				printk(KERN_WARNING "ad1848: must give I/O , IRQ and DMA.\n");
 				return -EINVAL;
@@ -3106,7 +2998,7 @@
 			cfg.card_subtype = type;
 	        }

-		if(!probe_ms_sound(&cfg))
+		if (!probe_ms_sound(&cfg))
 			return -ENODEV;
 		attach_ms_sound(&cfg, THIS_MODULE);
 		loaded = 1;
@@ -3116,15 +3008,23 @@

 static void __exit cleanup_ad1848(void)
 {
-	if(loaded)
+	if (loaded)
 		unload_ms_sound(&cfg);

 #ifdef CONFIG_PNP
-	if(ad1848_dev){
-		if(audio_activated)
-			pnp_disable_dev(ad1848_dev);
-		put_device(&ad1848_dev->dev);
+{
+	ad1848_info *p;
+
+	if (audio_activated == 0)
+		return;
+
+	while (--nr_ad1848_devs >= 0) {
+		p = &adev_info[nr_ad1848_devs];
+		pnp_disable_dev(p->pnp_dev);	/* XXX Should this be done here? */
+		put_device(&p->pnp_dev->dev);
 	}
+	pnp_unregister_driver(&ad1848_driver);
+}
 #endif
 }


-- 
function.linuxpower.ca

^ permalink raw reply

* Proposal:  Alan Cox dev_printk() with advanced logging support
From: Larry Kessler @ 2002-12-13  1:40 UTC (permalink / raw)
  To: linux-kernel mailing list
  Cc: Alan Cox, Rusty Russell, Richard J Moore, Werner Almesberger,
	James Keniston

Abstract:

The goals of this proposal are to: 
(1) provide a consistent method for identifying which device printk() messages 
    are referring to; and, 
(2) when you need advanced logging capabilities, a way to enable them without
    having to modify any device driver that's already using existing macros
    dev_err(), dev_info(), dev_warn(), or dev_dbg(), and without altering the
    contents of /var/log/messages at all.

(some editorial liberties were taken when combining Alan's comments from 
several notes...)

In September, Alan Cox wrote in response to my last logging proposal...

> We have a problem about consistently reporting which device. So
> dev_printk(dev, ...) is printk that formats up the device info for you.
[SNIP]
> Why not just start with
>
>        dev_printk(dev, KERN_ERR "Exploded mysteriously");
>
> and a few notification type things people can add eg
>
>        dev_failed(dev);
>        dev_offline(dev);
>
> much like we keep network status. 
[SNIP]
> Its also easy to use and happens to pass a device pointer into the
> places you want it for more detailed logging
[SNIP]
> We don't (modify printk behavior). We add an extra helper that builds 
> on it in a totally logical fashion. The existing one doesnt break, its
> merely something to be polished when needed by the folks who care
[SNIP]
> ...you end up with a set
> of patches you add over time. I would note however that the default
> dev_printk() routine that just reformats up as
>
>   <level>%s: message
>
> ...That gives you the infrastructure to know what is going on. 

Currently dev_printk() is not in the kernel, but the following
logging macros were added in 2.5 (in include/linux/device.h)...

  #ifdef DEBUG
  #define dev_dbg(dev, format, arg...)            \
         printk (KERN_DEBUG "%s %s: " format ,   \
                 (dev).driver->name , (dev).bus_id , ## arg)
  #else
  #define dev_dbg(dev, format, arg...) do {} while (0)
  #endif

  #define dev_err(dev, format, arg...)            \
         printk (KERN_ERR "%s %s: " format ,     \
                 (dev).driver->name , (dev).bus_id , ## arg)
  #define dev_info(dev, format, arg...)           \
         printk (KERN_INFO "%s %s: " format ,    \
                 (dev).driver->name , (dev).bus_id , ## arg)
  #define dev_warn(dev, format, arg...)           \
         printk (KERN_WARNING "%s %s: " format , \
                 (dev).driver->name , (dev).bus_id , ## arg)

The version of dev_printk() being proposed here is essentially a
generalized version of these macros, with a small change to Alan's 
version so that driver name and bus_id are prepended to the 
message...

  #define dev_printk(sev, dev, format, arg...) \
      printk(sev "%s %s: " format, (dev).driver->name, (dev).bus_id, ##arg)
 
Then the logging macros in device.h can be re-written like this...
   #define dev_err(dev, format, arg...)           \
         dev_printk(KERN_ERR, (dev), format, ## arg)
..and so on.  
 
Since network devices don't currently use the device model, a similar 
macro, possibly called netdev_printk(), which takes struct net_device as the 
dev argument, will be needed as well. 

But for now, here's the second part of the dev_printk() proposal...


Advanced Logging
----------------

(Note:  For folks who have commented on previous LKML postings about
 logging, and don't see your issues addressed here, _please_ see the
 "_not_ addressed" list at the very bottom ;-)

As Alan pointed-out...
    
> (dev_printk)...happens to pass a device pointer into the
> places you want it for more detailed logging 

So what features are desirable for advanced, detailed logging ?
Here are the features that I (and other like-minded folks) think
are important ...

Inside dev_printk(), and completely transparent to device drivers
that would be using dev_printk(), when CONFIG_EVLOG=yes...

(1) As "more detailed" implies, additional event data from the device struct
    is logged than is written to printk.  The initial proposed event data...
      driver->name  (also written to printk)
      bus_id        (also written to printk)
      addr 
      name  
      power_state
          
    Additionally, event data is "tagged" with attribute names to provide
    a more precise way of singling-out events in the log.  For the members of 
    the device struct, assigned names would be dev_driver_name, dev_bus_id,
    dev_addr, etc.

    As the device struct continues to evolve, it will become more clear which
    device attributes are appropriate to log.

(2) Instead of vsnprintf-ing the format string like printk(), the format
    string and args are kept separately in the event record, which provides
    numerous ways of formatting and displaying kernel events in user-space,
    including translation into different languages.  This will be referred
    to later as a PRINTF-format event record.

    Optional formatting templates, which would be automatically generated 
    during kernel build, offer several choices:

    <1> if templates are not applied, default printf-style formatting is
        displayed.

    <2> if the default auto-generated template is used, user-space utils can
        select event records using attribute names like dev_name,
        dev_power_state, etc; and, using command-line options, manipulate very 
        precisely how event data is displayed (very detailed, or very compact, 
        and in what order, etc.).

    <3> The default templates can be copied and modified, and based on 
        environment variable settings, the modified templates will be applied to 
        the event data, instead of the default auto-gen'd templates. 

(3) A unique, automatically generated "reference code" for every call to 
    dev_printk() provides a precise and accurate way to associate formatting
    templates with event records from dev_printk(), drive automated processing
    and analysis of events, etc.

(4) EXACTLY the same message is written to printk()'s ring buffer as if EVLOG 
    was not configured. 

Here's how dev_printk() would look with event logging added...

 #ifdef CONFIG_EVLOG
  #define dev_printk(sev, dev, format, arg...) \
 	printkat(sev "{dev_driver}%s {dev_bus_id}%s: " format \
	"{{dev_addr}%p{dev_name}%s{dev_power}%d{dev_state}%d}", \
	(dev).driver->name, (dev).bus_id, ##arg, \
	&(dev), (dev).name, (dev).power_state, (dev)->saved_state)
 #else
  /* Log via printk only, adding just the driver name and bus ID. */
  #define dev_printk(sev, dev, format, arg...) \
        printk(sev "%s %s: " format, (dev).driver->name, (dev).bus_id, ##arg)
 #endif /* !CONFIG_EVLOG */

Curly braces in the arglist to printkat() are used in the following ways...

{dev_driver} - in this case "dev_driver" will become the attribute name
               utilized by event logging.  "{dev_driver}" will NOT appear
               in the printk message, nor will any other attribute name
               enclosed in curly braces.

{{           - any attributes appearing AFTER this will not appear in the
               printk message (not even the values) and will not display with
               evlog commands unless explicitly specified.  These are
               referred to as "hidden attributes". 

Werner Almesberger suggested some additional creative ways of using curly
braces, but these can be proposed and added over time depending upon 
reponses and comments on the "simple" usage described above.

The printkat() macro inside dev_printk() looks like this...

  #ifndef EVL_FACILITY_NAME
  #ifdef KBUILD_MODNAME
  #define EVL_FACILITY_NAME KBUILD_MODNAME
  #else
  #define EVL_FACILITY_NAME kern
  #endif
  #endif

  /* returns CRC32 of s1, s2 and s3... */
  extern int evl_gen_event_type(const char *s1, const char *s2, const char *s3);

  /*
   * Bloat doesn't matter: this doesn't end up in vmlinux.
   * function and file are required for computation of CRC32, which is
   * part of the "reference code" uniquely identifying a call to dev_printk()
   */
  struct log_position {
     int line;
     char function[64 - sizeof(int)];
     char file[128];
  };
 
  #define _LOG_POS { __LINE__, __FUNCTION__, __FILE__ }
 
  /*
   * Information about a printkat() message.
   * Again, bloat doesn't matter: this doesn't end up in vmlinux.
   * Note that, because of default alignment in the .log section,
   * sizeof(struct log_info) should be a multiple of 32.
   */
  struct log_info {
     char format[128+64];
     char facility[64];
     struct log_position pos;
  };
 
  #define printkat(fmt, ...) \
  ({ \
     static struct log_info __attribute__((section(".log"),unused)) ___ \
        = { fmt, __stringify(EVL_FACILITY_NAME), _LOG_POS }; \
     __printkat(__stringify(EVL_FACILITY_NAME), \
        evl_gen_event_type(__FILE__, __FUNCTION__, fmt), \
        fmt, ##__VA_ARGS__); \
  })
 
The printkat macro is based on macros contributed by Rusty Russell
and stores static details into the .log section in the .o file that can 
then be extracted by a user-space utility to create formatting templates. 
Note that the combination of CRC32 from EVL_FACILITY_NAME and CRC32 
returned from evl_gen_event_type() provides you with an 8-byte reference 
code, as previously mentioned above. 

The __printkat() function, called from the printkat() macro, looks like 
this...

  /*
   * fmt and subsequent args are as with printk.  Log the message to printk
   * (via vprintk), and (if EVLOG is configured) also to evlog as a
   * PRINTF-format record.  Strip {id}s from the message, and also
   * anything following "{{".
   */
  /*ARGSUSED*/
  int __printkat(const char *facname, int evtype, const char *fmt, ...)
  {
         int status;
         unsigned long flags;
         va_list args;
  
         va_start(args, fmt);
  #ifdef CONFIG_EVLOG
         spin_lock_irqsave(&printkat_lock, flags);
         status = evl_printkat(facname, evtype, printkat_buf, fmt, args);
         (void) vprintk(printkat_buf, args);
         spin_unlock_irqrestore(&printkat_lock, flags);
  #else
         /* EVLOG disabled.  Just call printk, stripping {id}s as needed. */
         if (strstr(fmt, "}%") || strstr(fmt, "{{")) {
              spin_lock_irqsave(&printkat_lock, flags);
  /*   
              evl_unbrace(printkat_buf, fmt, POSIX_LOG_ENTRY_MAXLEN);
              status = vprintk(printkat_buf, args);
              spin_unlock_irqrestore(&printkat_lock, flags);
         } else {
                 status = vprintk(fmt, args);
         }
  #endif
         va_end(args);
         return status;
  }

evl_printkat(), called from __printkat()...
     (1) creates a PRINTF-format event record, as previously mentioned,
         where the format string and attributes (including hidden ones) 
         are stored separately in the event record.
     (2) calls vprintk() to store the "normal" printk message into the
         printk ring buffer _without_ attribute names enclosed in curly 
         braces and _without_ hidden attributes after "{{".

evl_unbrace(), also called from __printkat(), strips-out attribute names
in curly braces, and strips-off hidden attributes after "{{".

I am not showing evl_printk() or evl_unbrace() details, or any other event logging 
code because discussions about event record content, structure, buffering of event
records, event buffer size, etc. etc. will be discussed and the issues hammered out 
later.  Although, everything described here has been implemented and tested.

To illustrate, assume this dummy sample code...
  .
  .
  dev_printk(KERN_ALERT, dummy.dev,
           "Device %s is bad!  %d things are in danger!\n",
            dummy.name, dummy.things);
  .
  .
  
The printk message written to /var/log/messages might be...

  Nov 14 13:40:14 localhost kernel: dummy_driver 01:02.3: Device dummy is bad!  5 things are in danger!

The default event display from the "evlview" command might be...

  recid=11, size=158, format=PRINTF, event_type=0xb2958e8c, facility=dev_dummy, 
  severity=ALERT, uid=root, gid=root, pid=3193, pgrp=3193, 
  time=Thu 14 Nov 2002 01:40:14 PM PST, flags=0x2 (KERNEL), thread=0x0, 
  processor=0, host=localhost
  drivers/misc/dev_dummy.c:dev_dummy_init_module:72
  dummy_driver 01:02.3: Device dummy is bad!  5 things are in danger!

The event display from "evlview -m" is identical to printk...
  
  Nov 14 13:40:14 localhost kernel: dummy_driver 01:02.3: Device dummy is bad! 5 things are in danger!

The default formatting template, which is generated by a userspace utility that 
extracts the information from the .log section in the dev_dummy.o file would 
look like this...

  facility "dev_dummy"
  event_type 0xb2958e8c
    /* Raw format = "<1>{dev_driver}%s {dev_bus_id}%s: Device %s is bad!  %d things are in                        danger!\n{{dev_addr}%p{dev_name}%s{dev_power}%d{dev_state}%d}" */
  const {
        string file = "drivers/misc/dev_dummy.c";
        string function = "dev_dummy_init_module";
        int line = 72;
  }
  attributes {
        string fmt;
        int __argsz;
        string dev_driver "%s";
        string dev_bus_id "%s";
        string s3 "%s";
        int d1 "%d";
        address dev_addr "%p";
        string dev_name "%s";
        int dev_power "%d";
        unsigned char dev_saved_state "%d";
  }
  format
  %file%:%function%:%line%
  %fmt:printk%
  END

By copying the template and modifying just the "format" section of the template
to expose "hidden attributes"...

   format string
   "%file%:%function%:%line%"
   "\n%fmt:printk%"
   "\n-----------------------------------"
   "\ndriver = %dev_driver%"
   "\nbus_id = %dev_bus_id%"
   "\naddr   = %dev_addr%"
   "\nname   = %dev_name%"
   "\npower  = %dev_power%"
   "\nsaved_state  = %dev_saved_state%"
   "\n-----------------------------------"
   END

...and setting environment variables to use the modified template, the event 
display from "evlview" now looks like this...

   recid=11, size=158, format=PRINTF, event_type=0xb2958e8c, facility=dev_dummy, 
   severity=ALERT, uid=root, gid=root, pid=3193, pgrp=3193, 
   time=Thu 14 Nov 2002 01:40:14 PM PST, flags=0x2 (KERNEL), thread=0x0, 
   processor=0, host=localhost
   drivers/misc/dev_dummy.c:dev_dummy_init_module:72
   dummy_driver 01:02.3: Device dummy is bad!  5 things are in danger!
   -----------------------------------
   driver = dummy_driver
   bus_id = 01:02.3
   addr   = 0xd0873f80
   name   = Dummy Corp. dummy device model X57
   power  = 0
   saved_state  = 2
   ----------------------------------

BTW, evlview also has options to query on attribute names, even hidden 
ones, and offers an option to display event attributes similar to what
is displayed above (by providing a modified template).

In summary, what this proposal for dev_printk() provides is...

(1) a consistent method for identifying which device printk() messages are 
    referring to.

(2) when you need advanced logging capabilities, a way to enable them without
    having to modify any device driver that's already using dev_printk(), or
    dev_err(), dev_info(), dev_warn(), or dev_dbg(), and without altering the
    content of /var/log/messages at all.

What is _not_ addressed by this proposal are a number of other issues raised
in the past, that still need addressing.  For example...

1) (from Jeff Garzik) There's little or no stanardization of messages across
   different (but similar) devices.

2) (from Jeff Garzik and Greg KH) There's little or no guidance about what device
   specific details are most useful for Problem Determination, Sys Administration,
   etc.

   However, consistently identifying which device, plus state info from the device
   struct, plus other info. like source file, function name, and line number,
   provided with event logging, should certainly be useful in some cases. 
   As the device struct continues to evolve, it will become more clear which
   device attributes are appropriate to log.

3) (from Greg KH) But what happens when the attributes, and events change on every 
   kernel release ?   Who generates new templates, and who will update translations, 
   or even do them in the first place ? 

   Clearly, a user-space utility is required for merging customized templates with
   newer kernel versions.  The Distros, or anyone else 
   interested in post-processing of events in customized ways, will demand these
   utilities.  We could probably write them rather quickly (in a week or less).

4) (from Andrey Savochkin) One of the most important things is handling of log
   messages split over multiple printks, and possibly, multiple lines.  The 
   user-level log management system should be notified that such a dump is just
   a single long piece of information, spread over multiple lines.

   Certainly, variations on dev_printk() can be developed (like netdev_printk(), 
   for example), and although its not addressed explicitly here, this proposal does
   not preclude the handling of multi-line messages/events.

^ permalink raw reply

* [PATCH][2.5] Resurrect some ISAPNP macros
From: Zwane Mwaikambo @ 2002-12-13  1:43 UTC (permalink / raw)
  To: Linux Kernel; +Cc: Adam Belay

Hi Adam,
	I think these macros are worth having around, they come in handy
whilst converting drivers.

Cheers,
	Zwane

Index: linux-2.5.51/include/linux/pnp.h
===================================================================
RCS file: /build/cvsroot/linux-2.5.51/include/linux/pnp.h,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 pnp.h
--- linux-2.5.51/include/linux/pnp.h	10 Dec 2002 12:47:35 -0000	1.1.1.1
+++ linux-2.5.51/include/linux/pnp.h	11 Dec 2002 23:12:06 -0000
@@ -23,6 +23,16 @@
 #define DEVICE_COUNT_RESOURCE	12
 #define MAX_DEVICES		8

+#define ISAPNP_ANY_ID		0xffff
+#define ISAPNP_VENDOR(a,b,c)	(((((a)-'A'+1)&0x3f)<<2)|\
+				((((b)-'A'+1)&0x18)>>3)|((((b)-'A'+1)&7)<<13)|\
+				((((c)-'A'+1)&0x1f)<<8))
+#define ISAPNP_DEVICE(x)	((((x)&0xf000)>>8)|\
+				 (((x)&0x0f00)>>8)|\
+				 (((x)&0x00f0)<<8)|\
+				 (((x)&0x000f)<<8))
+#define ISAPNP_FUNCTION(x)	ISAPNP_DEVICE(x)
+
 struct pnp_resource;
 struct pnp_protocol;
 struct pnp_id;

-- 
function.linuxpower.ca

^ permalink raw reply

* Re: 2.5.51 ide module problem (fwd)
From: Rusty Russell @ 2002-12-13  1:35 UTC (permalink / raw)
  To: Alan Cox
  Cc: Jeff Chua, Adam J. Richter, Linux Kernel Mailing List, torvalds,
	axboe, linux-ide, Patrick Mochel
In-Reply-To: <1039696707.21192.11.camel@irongate.swansea.linux.org.uk>

In message <1039696707.21192.11.camel@irongate.swansea.linux.org.uk> you write:
> The module changes basically left me unable to do any further 2.5.5x
> work at an acceptable rate. My time is now allocated to other projects
> until January. At that point hopefully the module stuff will be usable
> again, parameters will work etc and I can go back to work on 2.5.

That's disappointing.  However, I can completely relate to your
frustration with the lack of module parameters.  Linus are you
listening? 8) Hopefully he's back today and will take patches, and
then I can look forward to some bug reports from you...

The patches I have queued for Linus are:
1) Param support
2) /lib/modules directory structure & depmod reversion
3) module's init calls request_module loop fix (bttv and parport do
   this in some configs).

> Rusty is right that the ide stuff has dependancy loops right now. His
> new module stuff shouldn't have crashed but the fundamental work to be
> done is in the IDE layer. There are also some locking problems to
> address before modular IDE becomes useful.

Also, my stress_modules script gave the following warning then oops
from ide-cd on 2.5.51 SMP x86 (IDE is built-in):

Dec 12 11:05:36 mingo kernel: Badness in kobject_register at lib/kobject.c:113
Dec 12 11:05:37 mingo kernel: Call Trace:
Dec 12 11:05:37 mingo kernel:  [<d0968fec>] ide_cdrom_driver+0x4c/0xd4 [ide_cd]
Dec 12 11:05:37 mingo kernel:  [<c01a5745>] kobject_register+0x39/0x50
Dec 12 11:05:37 mingo kernel:  [<c01b2352>] bus_add_driver+0x7a/0xc8
Dec 12 11:05:37 mingo kernel:  [<d0969010>] ide_cdrom_driver+0x70/0xd4 [ide_cd]
Dec 12 11:05:37 mingo kernel:  [<d0969000>] ide_cdrom_driver+0x60/0xd4 [ide_cd]
Dec 12 11:05:37 mingo kernel:  [<d0968fa0>] ide_cdrom_driver+0x0/0xd4 [ide_cd]
Dec 12 11:05:37 mingo kernel:  [<d0968fec>] ide_cdrom_driver+0x4c/0xd4 [ide_cd]
Dec 12 11:05:37 mingo kernel:  [<c01dc239>] ata_attach+0xfd/0x2d0
Dec 12 11:05:37 mingo kernel:  [<d0969010>] ide_cdrom_driver+0x70/0xd4 [ide_cd]
Dec 12 11:05:37 mingo kernel:  [<c01b2776>] driver_register+0x3e/0x44
Dec 12 11:05:37 mingo kernel:  [<d0968fec>] ide_cdrom_driver+0x4c/0xd4 [ide_cd]
Dec 12 11:05:37 mingo kernel:  [<c01dd305>] ide_register_driver+0x1c9/0x1d4
Dec 12 11:05:37 mingo kernel:  [<d0968fec>] ide_cdrom_driver+0x4c/0xd4 [ide_cd]
Dec 12 11:05:37 mingo kernel:  [<d096618a>] ide_cdrom_init+0xa/0x10 [ide_cd]
Dec 12 11:05:37 mingo kernel:  [<d0968fa0>] ide_cdrom_driver+0x0/0xd4 [ide_cd]
Dec 12 11:05:37 mingo kernel:  [<c01307a3>] sys_init_module+0x183/0x210
Dec 12 11:05:37 mingo kernel:  [<c0108f73>] syscall_call+0x7/0xb
Dec 12 11:05:44 mingo kernel: Unable to handle kernel paging request at virtual address d0969024
Dec 12 11:05:44 mingo kernel:  printing eip:
Dec 12 11:05:44 mingo kernel: c01a56c5
Dec 12 11:05:44 mingo kernel: *pde = 0ff09067
Dec 12 11:05:44 mingo kernel: *pte = 00000000
Dec 12 11:05:44 mingo kernel: Oops: 0002
Dec 12 11:05:44 mingo kernel: CPU:    1
Dec 12 11:05:44 mingo kernel: EIP:    0060:[<c01a56c5>]    Not tainted
Dec 12 11:05:44 mingo kernel: EFLAGS: 00010246
Dec 12 11:05:44 mingo kernel: EIP is at kobject_add+0x85/0xcc
Dec 12 11:05:44 mingo kernel: eax: d08fd024   ebx: c02c4fe8   ecx: d0969024   edx: c02c4fe0
Dec 12 11:05:44 mingo kernel: esi: d08fd010   edi: c02c4fb8   ebp: 00000000   esp: ccf67f38
Dec 12 11:05:44 mingo kernel: ds: 0068   es: 0068   ss: 0068
Dec 12 11:05:44 mingo kernel: Process modprobe (pid: 2977, threadinfo=ccf66000 task=ccfb2d20)
Dec 12 11:05:44 mingo kernel: Stack: d08fd010 d08fcdf4 d08fd020 d08fcfec c01a5721 d08fd010 d08fd010 c02c4f60 
Dec 12 11:05:44 mingo kernel:        c01b2352 d08fd010 d08fd000 d08fcfa0 ccf67fa0 d08fcfec c01dc239 d08fd010 
Dec 12 11:05:44 mingo kernel:        c02c4f94 c01b2776 d08fcfec c036dc94 c01dd305 d08fcfec d083f000 c0291534 
Dec 12 11:05:44 mingo kernel: Call Trace:
Dec 12 11:05:44 mingo kernel:  [<d08fd010>] ide_cdrom_driver+0x70/0xd4 [ide_cd]
Dec 12 11:05:44 mingo kernel:  [<d08fcdf4>] sense_data_texts+0x263c/0x2728 [ide_cd]
Dec 12 11:05:44 mingo kernel:  [<d08fd020>] ide_cdrom_driver+0x80/0xd4 [ide_cd]
Dec 12 11:05:44 mingo kernel:  [<d08fcfec>] ide_cdrom_driver+0x4c/0xd4 [ide_cd]
Dec 12 11:05:44 mingo kernel:  [<c01a5721>] kobject_register+0x15/0x50
Dec 12 11:05:44 mingo kernel:  [<d08fd010>] ide_cdrom_driver+0x70/0xd4 [ide_cd]
Dec 12 11:05:44 mingo kernel:  [<d08fd010>] ide_cdrom_driver+0x70/0xd4 [ide_cd]
Dec 12 11:05:44 mingo kernel:  [<c01b2352>] bus_add_driver+0x7a/0xc8
Dec 12 11:05:44 mingo kernel:  [<d08fd010>] ide_cdrom_driver+0x70/0xd4 [ide_cd]
Dec 12 11:05:44 mingo kernel:  [<d08fd000>] ide_cdrom_driver+0x60/0xd4 [ide_cd]
Dec 12 11:05:44 mingo kernel:  [<d08fcfa0>] ide_cdrom_driver+0x0/0xd4 [ide_cd]
Dec 12 11:05:44 mingo kernel:  [<d08fcfec>] ide_cdrom_driver+0x4c/0xd4 [ide_cd]
Dec 12 11:05:44 mingo kernel:  [<c01dc239>] ata_attach+0xfd/0x2d0
Dec 12 11:05:44 mingo kernel:  [<d08fd010>] ide_cdrom_driver+0x70/0xd4 [ide_cd]
Dec 12 11:05:44 mingo kernel:  [<c01b2776>] driver_register+0x3e/0x44
Dec 12 11:05:44 mingo kernel:  [<d08fcfec>] ide_cdrom_driver+0x4c/0xd4 [ide_cd]
Dec 12 11:05:44 mingo kernel:  [<c01dd305>] ide_register_driver+0x1c9/0x1d4
Dec 12 11:05:44 mingo kernel:  [<d08fcfec>] ide_cdrom_driver+0x4c/0xd4 [ide_cd]
Dec 12 11:05:44 mingo kernel:  [<d08fa18a>] ide_cdrom_init+0xa/0x10 [ide_cd]
Dec 12 11:05:44 mingo kernel:  [<d08fcfa0>] ide_cdrom_driver+0x0/0xd4 [ide_cd]
Dec 12 11:05:44 mingo kernel:  [<c01307a3>] sys_init_module+0x183/0x210
Dec 12 11:05:44 mingo kernel:  [<c0108f73>] syscall_call+0x7/0xb
Dec 12 11:05:44 mingo kernel: 
Dec 12 11:05:44 mingo kernel: Code: 89 01 57 e8 3b 01 00 00 89 46 1c 83 c4 04 89 d8 ba ff ff 00 

Hope that helps!
Rusty.
--
  Anyone who quotes me in their sig is an idiot. -- Rusty Russell.

^ permalink raw reply

* [PATCH][2.5] x86_summit typo(?)
From: Zwane Mwaikambo @ 2002-12-13  1:43 UTC (permalink / raw)
  To: Linux Kernel; +Cc: Martin Bligh

Hi,
	This looks like a typo judging from the code in
arch/i386/mach-summit

Index: linux-2.5.51-bochs/arch/i386/kernel/mpparse.c
===================================================================
RCS file: /build/cvsroot/linux-2.5.51/arch/i386/kernel/mpparse.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 mpparse.c
--- linux-2.5.51-bochs/arch/i386/kernel/mpparse.c	10 Dec 2002 12:46:46 -0000	1.1.1.1
+++ linux-2.5.51-bochs/arch/i386/kernel/mpparse.c	12 Dec 2002 04:40:26 -0000
@@ -70,7 +70,7 @@
 /* Bitmask of physically existing CPUs */
 unsigned long phys_cpu_present_map;

-int summit_x86 = 0;
+int x86_summit = 0;
 u8 raw_phys_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };

 /*

-- 
function.linuxpower.ca

^ permalink raw reply

* [PATCH][2.5][RFC] Using xAPIC apic address space on !Summit
From: Zwane Mwaikambo @ 2002-12-13  1:44 UTC (permalink / raw)
  To: Martin Bligh; +Cc: James Cleverdon, John Stultz, Linux Kernel

Hi,
	I've got an 32x SMP system which has an xAPIC but utilises flat
addressing. This patch is to rename what was formerly x86_summit to
x86_xapic (just to avoid confusion) and then select mask depending on
that.

Untested/uncompiled patch

Index: linux-2.5.51/include/asm-i386/apic.h
===================================================================
RCS file: /build/cvsroot/linux-2.5.51/include/asm-i386/apic.h,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 apic.h
--- linux-2.5.51/include/asm-i386/apic.h	10 Dec 2002 12:47:44 -0000	1.1.1.1
+++ linux-2.5.51/include/asm-i386/apic.h	12 Dec 2002 17:10:51 -0000
@@ -90,6 +90,7 @@
 extern int check_nmi_watchdog (void);
 extern void enable_NMI_through_LVT0 (void * dummy);

+extern int x86_xapic;
 extern unsigned int nmi_watchdog;
 #define NMI_NONE	0
 #define NMI_IO_APIC	1
Index: linux-2.5.51/include/asm-i386/apicdef.h
===================================================================
RCS file: /build/cvsroot/linux-2.5.51/include/asm-i386/apicdef.h,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 apicdef.h
--- linux-2.5.51/include/asm-i386/apicdef.h	10 Dec 2002 12:47:44 -0000	1.1.1.1
+++ linux-2.5.51/include/asm-i386/apicdef.h	12 Dec 2002 03:22:59 -0000
@@ -9,10 +9,11 @@
  */

 #define		APIC_DEFAULT_PHYS_BASE	0xfee00000
-
+extern int x86_xapic;
+#define		APIC_BROADCAST_ID     (x86_xapic ? 0xFF : 0x0F)
 #define		APIC_ID		0x20
-#define			APIC_ID_MASK		(0x0F<<24)
-#define			GET_APIC_ID(x)		(((x)>>24)&0x0F)
+#define			APIC_ID_MASK		(APIC_BROADCAST_ID<<24)
+#define			GET_APIC_ID(x)		(((x)>>24)&APIC_BROADCAST_ID)
 #define		APIC_LVR	0x30
 #define			APIC_LVR_MASK		0xFF00FF
 #define			GET_APIC_VERSION(x)	((x)&0xFF)
Index: linux-2.5.51/arch/i386/kernel/apic.c
===================================================================
RCS file: /build/cvsroot/linux-2.5.51/arch/i386/kernel/apic.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 apic.c
--- linux-2.5.51/arch/i386/kernel/apic.c	10 Dec 2002 12:46:46 -0000	1.1.1.1
+++ linux-2.5.51/arch/i386/kernel/apic.c	12 Dec 2002 17:08:26 -0000
@@ -33,6 +33,8 @@
 #include <asm/arch_hooks.h>
 #include "mach_apic.h"

+int x86_xapic;
+
 void __init apic_intr_init(void)
 {
 #ifdef CONFIG_SMP
Index: linux-2.5.51/arch/i386/kernel/io_apic.c
===================================================================
RCS file: /build/cvsroot/linux-2.5.51/arch/i386/kernel/io_apic.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 io_apic.c
--- linux-2.5.51/arch/i386/kernel/io_apic.c	10 Dec 2002 12:46:46 -0000	1.1.1.1
+++ linux-2.5.51/arch/i386/kernel/io_apic.c	12 Dec 2002 16:08:04 -0000
@@ -1147,7 +1147,7 @@

 	if (clustered_apic_mode)
 		/* We don't have a good way to do this yet - hack */
-		phys_id_present_map = (u_long) 0xf;
+		phys_id_present_map = (u_long) APIC_BROADCAST_ID;
 	/*
 	 * Set the IOAPIC ID to the value stored in the MPC table.
 	 */
@@ -1177,10 +1177,10 @@
 					mp_ioapics[apic].mpc_apicid)) {
 			printk(KERN_ERR "BIOS bug, IO-APIC#%d ID %d is already used!...\n",
 				apic, mp_ioapics[apic].mpc_apicid);
-			for (i = 0; i < 0xf; i++)
+			for (i = 0; i < APIC_BROADCAST_ID; i++)
 				if (!(phys_id_present_map & (1 << i)))
 					break;
-			if (i >= 0xf)
+			if (i >= APIC_BROADCAST_ID)
 				panic("Max APIC ID exceeded!\n");
 			printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n",
 				i);
Index: linux-2.5.51/arch/i386/kernel/mpparse.c
===================================================================
RCS file: /build/cvsroot/linux-2.5.51/arch/i386/kernel/mpparse.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 mpparse.c
--- linux-2.5.51/arch/i386/kernel/mpparse.c	10 Dec 2002 12:46:46 -0000	1.1.1.1
+++ linux-2.5.51/arch/i386/kernel/mpparse.c	12 Dec 2002 17:07:39 -0000
@@ -67,10 +67,9 @@
 /* Internal processor count */
 static unsigned int __initdata num_processors;

-/* Bitmask of physically existing CPUs */
+/* Bitmask of physically present CPUs and IOAPICs */
 unsigned long phys_cpu_present_map;

-int summit_x86 = 0;
 u8 raw_phys_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };

 /*
@@ -394,7 +393,7 @@
 	str[12]=0;
 	printk("Product ID: %s ",str);

-	summit_check(oem, str);
+	smp_hardware_check(oem, str);

 	printk("APIC at: 0x%lX\n",mpc->mpc_lapic);

Index: linux-2.5.51/arch/i386/mach-generic/mach_apic.h
===================================================================
RCS file: /build/cvsroot/linux-2.5.51/arch/i386/mach-generic/mach_apic.h,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 mach_apic.h
--- linux-2.5.51/arch/i386/mach-generic/mach_apic.h	10 Dec 2002 12:46:46 -0000	1.1.1.1
+++ linux-2.5.51/arch/i386/mach-generic/mach_apic.h	12 Dec 2002 03:49:07 -0000
@@ -17,11 +17,15 @@
  #define TARGET_CPUS 0x01
 #endif

-#define APIC_BROADCAST_ID      0x0F
 #define check_apicid_used(bitmap, apicid) (bitmap & (1 << apicid))

-static inline void summit_check(char *oem, char *productid)
+static inline void smp_hardware_check(char *oem, char *productid)
 {
+	unsigned long ver, reg = apic_read(APIC_LVR);
+
+	ver = GET_APIC_VERSION(reg);
+	if (ver == 0x14)
+		x86_xapic = 1;
 }

 static inline void clustered_apic_check(void)
Index: linux-2.5.51/arch/i386/mach-summit/mach_apic.h
===================================================================
RCS file: /build/cvsroot/linux-2.5.51/arch/i386/mach-summit/mach_apic.h,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 mach_apic.h
--- linux-2.5.51/arch/i386/mach-summit/mach_apic.h	10 Dec 2002 12:46:46 -0000	1.1.1.1
+++ linux-2.5.51/arch/i386/mach-summit/mach_apic.h	12 Dec 2002 03:49:20 -0000
@@ -1,8 +1,6 @@
 #ifndef __ASM_MACH_APIC_H
 #define __ASM_MACH_APIC_H

-extern int x86_summit;
-
 #define XAPIC_DEST_CPUS_MASK    0x0Fu
 #define XAPIC_DEST_CLUSTER_MASK 0xF0u

@@ -13,34 +11,33 @@
 {
 	unsigned long id;

-	if (x86_summit)
+	if (x86_xapic)
 		id = xapic_phys_to_log_apicid(hard_smp_processor_id());
 	else
 		id = 1UL << smp_processor_id();
 	return ((old & ~APIC_LDR_MASK) | SET_APIC_LOGICAL_ID(id));
 }

-#define APIC_DFR_VALUE	(x86_summit ? APIC_DFR_CLUSTER : APIC_DFR_FLAT)
-#define TARGET_CPUS	(x86_summit ? XAPIC_DEST_CPUS_MASK : cpu_online_map)
+#define APIC_DFR_VALUE	(x86_xapic ? APIC_DFR_CLUSTER : APIC_DFR_FLAT)
+#define TARGET_CPUS	(x86_xapic ? XAPIC_DEST_CPUS_MASK : cpu_online_map)

-#define APIC_BROADCAST_ID     (x86_summit ? 0xFF : 0x0F)
 #define check_apicid_used(bitmap, apicid) (0)

-static inline void summit_check(char *oem, char *productid)
+static inline void smp_hardware_check(char *oem, char *productid)
 {
 	if (!strncmp(oem, "IBM ENSW", 8) && !strncmp(str, "VIGIL SMP", 9))
-		x86_summit = 1;
+		x86_xapic = 1;
 }

 static inline void clustered_apic_check(void)
 {
 	printk("Enabling APIC mode:  %s.  Using %d I/O APICs\n",
-		(x86_summit ? "Summit" : "Flat"), nr_ioapics);
+		(x86_xapic ? "Summit" : "Flat"), nr_ioapics);
 }

 static inline int cpu_present_to_apicid(int mps_cpu)
 {
-	if (x86_summit)
+	if (x86_xapic)
 		return (int) raw_phys_apicid[mps_cpu];
 	else
 		return mps_cpu;
@@ -48,7 +45,7 @@

 static inline unsigned long apicid_to_phys_cpu_present(int apicid)
 {
-	if (x86_summit)
+	if (x86_xapic)
 		return (1ul << (((apicid >> 4) << 2) | (apicid & 0x3)));
 	else
 		return (1ul << apicid);

^ permalink raw reply

* [PATCH][2.5] OSS ad1848 initialisation order
From: Zwane Mwaikambo @ 2002-12-13  1:43 UTC (permalink / raw)
  To: Linux Kernel; +Cc: Linus Torvalds

I need to initialise the ad1848 driver before attempting attach/probe from
dependent drivers (e.g. opl3sa2)

Please apply,

Index: linux-2.5.51/sound/oss/Makefile
===================================================================
RCS file: /build/cvsroot/linux-2.5.51/sound/oss/Makefile,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 Makefile
--- linux-2.5.51/sound/oss/Makefile	10 Dec 2002 12:48:01 -0000	1.1.1.1
+++ linux-2.5.51/sound/oss/Makefile	12 Dec 2002 07:42:42 -0000
@@ -24,8 +24,8 @@
 obj-$(CONFIG_SOUND_SSCAPE)	+= sscape.o ad1848.o mpu401.o
 obj-$(CONFIG_SOUND_MAD16)	+= mad16.o ad1848.o sb_lib.o uart401.o
 obj-$(CONFIG_SOUND_CS4232)	+= cs4232.o uart401.o
-obj-$(CONFIG_SOUND_OPL3SA2)	+= opl3sa2.o ad1848.o mpu401.o
 obj-$(CONFIG_SOUND_MSS)		+= ad1848.o
+obj-$(CONFIG_SOUND_OPL3SA2)	+= opl3sa2.o ad1848.o mpu401.o
 obj-$(CONFIG_SOUND_PAS)		+= pas2.o sb.o sb_lib.o uart401.o
 obj-$(CONFIG_SOUND_SB)		+= sb.o sb_lib.o uart401.o
 obj-$(CONFIG_SOUND_WAVEFRONT)	+= wavefront.o

-- 
function.linuxpower.ca

^ permalink raw reply

* [PATCH][2.5][CFT] OSS opl3sa2 pnp fixes + merge
From: Zwane Mwaikambo @ 2002-12-13  1:42 UTC (permalink / raw)
  To: Linux Kernel; +Cc: Adam Belay

I decided to do this in one sweep since there were a number of fixes in
2.4 which needed merging anyway. I haven't been able to test modular
case yet. I've tested this in conjunction with the ad1848 pnp fixes on
the following hardware;

ad1848/cs4248 codec driver Copyright (C) by Hannu Savolainen 1993-1996
pnp: the driver 'ad1848' has been registered
ad1848: No ISAPnP cards found, trying standard ones...
pnp: the driver 'opl3sa2' has been registered
pnp: pnp: match found with the PnP device '00:01.00' and the driver
'opl3sa2'
pnp: the device '00:01.00' has been activated
opl3sa2: chipset version = 0x3
opl3sa2: Found OPL3-SA3 (YMF715B or YMF719B)
<OPL3-SA3> at 0x100 irq 5 dma 1,3
<MS Sound System (CS4231)> at 0xe84 irq 5 dma 1,3
<MPU-401 0.0  Midi interface #1> at 0x300 irq 5
opl3sa2: 1 PnP card(s) found.

Index: linux-2.5.51/sound/oss/opl3sa2.c
===================================================================
RCS file: /build/cvsroot/linux-2.5.51/sound/oss/opl3sa2.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 opl3sa2.c
--- linux-2.5.51/sound/oss/opl3sa2.c	10 Dec 2002 12:48:01 -0000	1.1.1.1
+++ linux-2.5.51/sound/oss/opl3sa2.c	13 Dec 2002 00:35:11 -0000
@@ -56,7 +56,9 @@
  * Scott Murray            Some small cleanups to the init code output.
  *                         (Jan 7, 2001)
  * Zwane Mwaikambo	   Added PM support. (Dec 4 2001)
- *
+ * Zwane Mwaikambo	   Code, data structure cleanups. (Feb 15 2002)
+ * Zwane Mwaikambo	   Free resources during auxiliary device probe
+ * 			   failures (Apr 29 2002)
  * Adam Belay              Converted driver to new PnP Layer (Oct 12, 2002)
  */

@@ -66,11 +68,15 @@
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/pm.h>
+#include <linux/delay.h>
 #include "sound_config.h"

 #include "ad1848.h"
 #include "mpu401.h"

+#define OPL3SA2_MODULE_NAME	"opl3sa2"
+#define PFX			OPL3SA2_MODULE_NAME ": "
+
 /* Useful control port indexes: */
 #define OPL3SA2_PM	     0x01
 #define OPL3SA2_SYS_CTRL     0x02
@@ -91,9 +97,10 @@
 #define DEFAULT_TIMBRE 0

 /* Power saving modes */
-#define OPL3SA2_PM_MODE1	0x05
-#define OPL3SA2_PM_MODE2	0x04
-#define OPL3SA2_PM_MODE3	0x03
+#define OPL3SA2_PM_MODE0	0x00
+#define OPL3SA2_PM_MODE1	0x04	/* PSV */
+#define OPL3SA2_PM_MODE2	0x05	/* PSV | PDX */
+#define OPL3SA2_PM_MODE3	0x27	/* ADOWN | PSV | PDN | PDX */

 /* For checking against what the card returns: */
 #define VERSION_UNKNOWN 0
@@ -107,6 +114,7 @@
 #define CHIPSET_UNKNOWN -1
 #define CHIPSET_OPL3SA2 0
 #define CHIPSET_OPL3SA3 1
+static const char *CHIPSET_TABLE[] = {"OPL3-SA2", "OPL3-SA3"};

 #ifdef CONFIG_PNP
 #define OPL3SA2_CARDS_MAX 4
@@ -117,40 +125,42 @@
 /* This should be pretty obvious */
 static int opl3sa2_cards_num; /* = 0 */

-/* What's my version(s)? */
-static int chipset[OPL3SA2_CARDS_MAX] = { CHIPSET_UNKNOWN };
-
-/* Oh well, let's just cache the name(s) */
-static char chipset_name[OPL3SA2_CARDS_MAX][12];
+typedef struct {
+	/* device resources */
+	unsigned short cfg_port;
+	struct address_info cfg;
+	struct address_info cfg_mss;
+	struct address_info cfg_mpu;

-/* Where's my mixer(s)? */
-static int opl3sa2_mixer[OPL3SA2_CARDS_MAX] = { -1 };
+#ifdef CONFIG_PNP
+	/* PnP Stuff */
+	struct pnp_dev* pdev;
+	int activated;			/* Whether said devices have been activated */
+#endif

-/* Bag o' mixer data */
-typedef struct opl3sa2_mixerdata_tag {
-	unsigned short cfg_port;
-	unsigned short padding;
-	unsigned char  reg;
-	unsigned int   in_suspend;
-	struct pm_dev  *pmdev;
-	unsigned int   card;
-	unsigned int   volume_l;
-	unsigned int   volume_r;
-	unsigned int   mic;
-	unsigned int   bass_l;
-	unsigned int   bass_r;
-	unsigned int   treble_l;
-	unsigned int   treble_r;
-	unsigned int   wide_l;
-	unsigned int   wide_r;
-} opl3sa2_mixerdata;
-static opl3sa2_mixerdata opl3sa2_data[OPL3SA2_CARDS_MAX];
-
-static struct address_info cfg[OPL3SA2_CARDS_MAX];
-static struct address_info cfg_mss[OPL3SA2_CARDS_MAX];
-static struct address_info cfg_mpu[OPL3SA2_CARDS_MAX];
+#ifdef CONFIG_PM
+	unsigned int	in_suspend;
+	struct pm_dev	*pmdev;
+#endif
+	unsigned int	card;
+	int		chipset;	/* What's my version(s)? */
+	char		*chipset_name;
+
+	/* mixer data */
+	int		mixer;
+	unsigned int	volume_l;
+	unsigned int	volume_r;
+	unsigned int	mic;
+	unsigned int	bass_l;
+	unsigned int	bass_r;
+	unsigned int	treble_l;
+	unsigned int	treble_r;
+	unsigned int	wide_l;
+	unsigned int	wide_r;
+} opl3sa2_state_t;
+static opl3sa2_state_t opl3sa2_state[OPL3SA2_CARDS_MAX];

-static spinlock_t	lock=SPIN_LOCK_UNLOCKED;
+static spinlock_t opl3sa2_lock = SPIN_LOCK_UNLOCKED;

 /* Our parameters */
 static int __initdata io	= -1;
@@ -236,12 +246,11 @@
 	*data = inb(port + 1);
 }

-
 /*
  * All of the mixer functions...
  */

-static void opl3sa2_set_volume(opl3sa2_mixerdata* devc, int left, int right)
+static void opl3sa2_set_volume(opl3sa2_state_t* devc, int left, int right)
 {
 	static unsigned char scale[101] = {
 		0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e,
@@ -276,7 +285,7 @@
 }


-static void opl3sa2_set_mic(opl3sa2_mixerdata* devc, int level)
+static void opl3sa2_set_mic(opl3sa2_state_t* devc, int level)
 {
 	unsigned char vol = 0x1F;

@@ -291,7 +300,7 @@
 }


-static void opl3sa3_set_bass(opl3sa2_mixerdata* devc, int left, int right)
+static void opl3sa3_set_bass(opl3sa2_state_t* devc, int left, int right)
 {
 	unsigned char bass;

@@ -302,7 +311,7 @@
 }


-static void opl3sa3_set_treble(opl3sa2_mixerdata* devc, int left, int right)
+static void opl3sa3_set_treble(opl3sa2_state_t* devc, int left, int right)
 {
 	unsigned char treble;

@@ -313,7 +322,7 @@
 }


-static void opl3sa3_set_wide(opl3sa2_mixerdata* devc, int left, int right)
+static void opl3sa3_set_wide(opl3sa2_state_t* devc, int left, int right)
 {
 	unsigned char wide;

@@ -324,7 +333,7 @@
 }


-static void opl3sa2_mixer_reset(opl3sa2_mixerdata* devc, int card)
+static void opl3sa2_mixer_reset(opl3sa2_state_t* devc)
 {
 	if(devc) {
 		opl3sa2_set_volume(devc, DEFAULT_VOLUME, DEFAULT_VOLUME);
@@ -333,7 +342,7 @@
 		opl3sa2_set_mic(devc, DEFAULT_MIC);
 		devc->mic = DEFAULT_MIC;

-		if(chipset[card] == CHIPSET_OPL3SA3) {
+		if(devc->chipset == CHIPSET_OPL3SA3) {
 			opl3sa3_set_bass(devc, DEFAULT_TIMBRE, DEFAULT_TIMBRE);
 			devc->bass_l = devc->bass_r = DEFAULT_TIMBRE;
 			opl3sa3_set_treble(devc, DEFAULT_TIMBRE, DEFAULT_TIMBRE);
@@ -343,13 +352,13 @@
 }


-static void opl3sa2_mixer_restore(opl3sa2_mixerdata* devc, int card)
+static void opl3sa2_mixer_restore(opl3sa2_state_t* devc)
 {
 	if (devc) {
 		opl3sa2_set_volume(devc, devc->volume_l, devc->volume_r);
 		opl3sa2_set_mic(devc, devc->mic);

-		if (chipset[card] == CHIPSET_OPL3SA3) {
+		if (devc->chipset == CHIPSET_OPL3SA3) {
 			opl3sa3_set_bass(devc, devc->bass_l, devc->bass_r);
 			opl3sa3_set_treble(devc, devc->treble_l, devc->treble_r);
 		}
@@ -391,7 +400,7 @@
 {
 	int cmdf = cmd & 0xff;

-	opl3sa2_mixerdata* devc = (opl3sa2_mixerdata*) mixer_devs[dev]->devc;
+	opl3sa2_state_t* devc = &opl3sa2_state[dev];

 	switch(cmdf) {
 		case SOUND_MIXER_VOLUME:
@@ -474,7 +483,7 @@
 {
 	int cmdf = cmd & 0xff;

-	opl3sa2_mixerdata* devc = (opl3sa2_mixerdata*) mixer_devs[dev]->devc;
+	opl3sa2_state_t* devc = &opl3sa2_state[dev];

 	switch(cmdf) {
 		case SOUND_MIXER_BASS:
@@ -584,9 +593,9 @@
 }


-static inline void __init attach_opl3sa2_mpu(struct address_info* hw_config)
+static inline int __init attach_opl3sa2_mpu(struct address_info* hw_config)
 {
-	attach_mpu401(hw_config, THIS_MODULE);
+	return attach_mpu401(hw_config, THIS_MODULE);
 }


@@ -617,7 +626,7 @@
 			AD1848_REROUTE(SOUND_MIXER_LINE3, SOUND_MIXER_LINE);
 		}
 		else {
-			printk(KERN_ERR "opl3sa2: MSS mixer not installed?\n");
+			printk(KERN_ERR PFX "MSS mixer not installed?\n");
 		}
 	}
 }
@@ -634,15 +643,14 @@
 	unsigned char misc;
 	unsigned char tmp;
 	unsigned char version;
-	char tag;

 	/*
-	 * Verify that the I/O port range is free.
+	 * Try and allocate our I/O port range.
 	 */
-	if(check_region(hw_config->io_base, 2)) {
-		printk(KERN_ERR "opl3sa2: Control I/O port %#x not free\n",
+	if(!request_region(hw_config->io_base, 2, OPL3SA2_MODULE_NAME)) {
+		printk(KERN_ERR PFX "Control I/O port %#x not free\n",
 		       hw_config->io_base);
-		return 0;
+		goto out_nodev;
 	}

 	/*
@@ -653,9 +661,9 @@
 	opl3sa2_write(hw_config->io_base, OPL3SA2_MISC, misc ^ 0x07);
 	opl3sa2_read(hw_config->io_base, OPL3SA2_MISC, &tmp);
 	if(tmp != misc) {
-		printk(KERN_ERR "opl3sa2: Control I/O port %#x is not a YMF7xx chipset!\n",
+		printk(KERN_ERR PFX "Control I/O port %#x is not a YMF7xx chipset!\n",
 		       hw_config->io_base);
-		return 0;
+		goto out_region;
 	}

 	/*
@@ -666,9 +674,9 @@
 	opl3sa2_read(hw_config->io_base, OPL3SA2_MIC, &tmp);
 	if((tmp & 0x9f) != 0x8a) {
 		printk(KERN_ERR
-		       "opl3sa2: Control I/O port %#x is not a YMF7xx chipset!\n",
+		       PFX "Control I/O port %#x is not a YMF7xx chipset!\n",
 		       hw_config->io_base);
-		return 0;
+		goto out_region;
 	}
 	opl3sa2_write(hw_config->io_base, OPL3SA2_MIC, tmp);

@@ -679,56 +687,54 @@
 	 * of the miscellaneous register.
 	 */
 	version = misc & 0x07;
-	printk(KERN_DEBUG "opl3sa2: chipset version = %#x\n", version);
+	printk(KERN_DEBUG PFX "chipset version = %#x\n", version);
 	switch(version) {
 		case 0:
-			chipset[card] = CHIPSET_UNKNOWN;
-			tag = '?'; /* silence compiler warning */
+			opl3sa2_state[card].chipset = CHIPSET_UNKNOWN;
 			printk(KERN_ERR
-			       "opl3sa2: Unknown Yamaha audio controller version\n");
+			       PFX "Unknown Yamaha audio controller version\n");
 			break;

 		case VERSION_YMF711:
-			chipset[card] = CHIPSET_OPL3SA2;
-			tag = '2';
-			printk(KERN_INFO "opl3sa2: Found OPL3-SA2 (YMF711)\n");
+			opl3sa2_state[card].chipset = CHIPSET_OPL3SA2;
+			printk(KERN_INFO PFX "Found OPL3-SA2 (YMF711)\n");
 			break;

 		case VERSION_YMF715:
-			chipset[card] = CHIPSET_OPL3SA3;
-			tag = '3';
+			opl3sa2_state[card].chipset = CHIPSET_OPL3SA3;
 			printk(KERN_INFO
-			       "opl3sa2: Found OPL3-SA3 (YMF715 or YMF719)\n");
+			       PFX "Found OPL3-SA3 (YMF715 or YMF719)\n");
 			break;

 		case VERSION_YMF715B:
-			chipset[card] = CHIPSET_OPL3SA3;
-			tag = '3';
+			opl3sa2_state[card].chipset = CHIPSET_OPL3SA3;
 			printk(KERN_INFO
-			       "opl3sa2: Found OPL3-SA3 (YMF715B or YMF719B)\n");
+			       PFX "Found OPL3-SA3 (YMF715B or YMF719B)\n");
 			break;

 		case VERSION_YMF715E:
 		default:
-			chipset[card] = CHIPSET_OPL3SA3;
-			tag = '3';
+			opl3sa2_state[card].chipset = CHIPSET_OPL3SA3;
 			printk(KERN_INFO
-			       "opl3sa2: Found OPL3-SA3 (YMF715E or YMF719E)\n");
+			       PFX "Found OPL3-SA3 (YMF715E or YMF719E)\n");
 			break;
 	}

-	if(chipset[card] != CHIPSET_UNKNOWN) {
+	if(opl3sa2_state[card].chipset != CHIPSET_UNKNOWN) {
 		/* Generate a pretty name */
-		sprintf(chipset_name[card], "OPL3-SA%c", tag);
-		return 1;
+		opl3sa2_state[card].chipset_name = (char *)CHIPSET_TABLE[opl3sa2_state[card].chipset];
+		return 0;
 	}
-	return 0;
+
+out_region:
+	release_region(hw_config->io_base, 2);
+out_nodev:
+	return -ENODEV;
 }


 static void __init attach_opl3sa2(struct address_info* hw_config, int card)
 {
-   	request_region(hw_config->io_base, 2, chipset_name[card]);

 	/* Initialize IRQ configuration to IRQ-B: -, IRQ-A: WSS+MPU+OPL3 */
 	opl3sa2_write(hw_config->io_base, OPL3SA2_IRQ_CONFIG, 0x0d);
@@ -748,30 +754,28 @@
 static void __init attach_opl3sa2_mixer(struct address_info *hw_config, int card)
 {
 	struct mixer_operations* mixer_operations;
-	opl3sa2_mixerdata* devc;
+	opl3sa2_state_t* devc = &opl3sa2_state[card];

 	/* Install master mixer */
-	if(chipset[card] == CHIPSET_OPL3SA3) {
+	if(devc->chipset == CHIPSET_OPL3SA3) {
 		mixer_operations = &opl3sa3_mixer_operations;
 	}
 	else {
 		mixer_operations = &opl3sa2_mixer_operations;
 	}

-	if((devc = &opl3sa2_data[card])) {
-		devc->cfg_port = hw_config->io_base;
-
-		opl3sa2_mixer[card] = sound_install_mixer(MIXER_DRIVER_VERSION,
-							  mixer_operations->name,
-							  mixer_operations,
-							  sizeof(struct mixer_operations),
-							  devc);
-		if(opl3sa2_mixer[card] < 0) {
-			printk(KERN_ERR "opl3sa2: Could not install %s master mixer\n",
-				 mixer_operations->name);
-		}
-		else
-			opl3sa2_mixer_reset(devc, card);
+	devc->cfg_port = hw_config->io_base;
+	devc->mixer = sound_install_mixer(MIXER_DRIVER_VERSION,
+					  mixer_operations->name,
+					  mixer_operations,
+					  sizeof(struct mixer_operations),
+					  devc);
+	if(devc->mixer < 0) {
+		printk(KERN_ERR PFX "Could not install %s master mixer\n",
+			 mixer_operations->name);
+	}
+	else {
+			opl3sa2_mixer_reset(devc);
 	}
 }

@@ -799,13 +803,12 @@
 	 */
 	if(ymode >= 0 && ymode <= 3) {
 		unsigned char sys_ctrl;
-
 		opl3sa2_read(hw_config->io_base, OPL3SA2_SYS_CTRL, &sys_ctrl);
 		sys_ctrl = (sys_ctrl & 0xcf) | ((ymode & 3) << 4);
 		opl3sa2_write(hw_config->io_base, OPL3SA2_SYS_CTRL, sys_ctrl);
 	}
 	else {
-		printk(KERN_ERR "opl3sa2: not setting ymode, it must be one of 0,1,2,3\n");
+		printk(KERN_ERR PFX "not setting ymode, it must be one of 0,1,2,3\n");
 	}
 }

@@ -820,7 +823,7 @@
 		opl3sa2_write(hw_config->io_base, OPL3SA2_MISC, misc);
 	}
 	else {
-		printk(KERN_ERR "opl3sa2: not setting loopback, it must be either 0 or 1\n");
+		printk(KERN_ERR PFX "not setting loopback, it must be either 0 or 1\n");
 	}
 }

@@ -831,50 +834,54 @@
 	release_region(hw_config->io_base, 2);

 	/* Unload mixer */
-	if(opl3sa2_mixer[card] >= 0)
-		sound_unload_mixerdev(opl3sa2_mixer[card]);
+	if(opl3sa2_state[card].mixer >= 0)
+		sound_unload_mixerdev(opl3sa2_state[card].mixer);
 }

 #ifdef CONFIG_PNP
-struct pnp_id pnp_opl3sa2_list[] = {
+struct pnp_device_id pnp_opl3sa2_list[] = {
 	{.id = "YMH0021", .driver_data = 0},
 	{.id = ""}
 };

 MODULE_DEVICE_TABLE(pnp, pnp_opl3sa2_list);

-static int opl3sa2_pnp_probe(struct pnp_dev *dev, const struct pnp_id *dev_id)
+static int opl3sa2_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
 {
 	int card = opl3sa2_cards_num;
+
+	/* we don't actually want to return an error as the user may have specified
+	   no multiple card search
+	*/
 	if (opl3sa2_cards_num == OPL3SA2_CARDS_MAX)
 		return 0;
 	opl3sa2_activated[card] = 1;

 	/* Our own config: */
-	cfg[card].io_base = dev->resource[4].start;
-	cfg[card].irq     = dev->irq_resource[0].start;
-	cfg[card].dma     = dev->dma_resource[0].start;
-	cfg[card].dma2    = dev->dma_resource[1].start;
+	opl3sa2_state[card].cfg.io_base = dev->resource[4].start;
+	opl3sa2_state[card].cfg.irq     = dev->irq_resource[0].start;
+	opl3sa2_state[card].cfg.dma     = dev->dma_resource[0].start;
+	opl3sa2_state[card].cfg.dma2    = dev->dma_resource[1].start;

 	/* The MSS config: */
-	cfg_mss[card].io_base      = dev->resource[1].start;
-	cfg_mss[card].irq          = dev->irq_resource[0].start;
-	cfg_mss[card].dma          = dev->dma_resource[0].start;
-	cfg_mss[card].dma2         = dev->dma_resource[1].start;
-	cfg_mss[card].card_subtype = 1; /* No IRQ or DMA setup */
-
-	cfg_mpu[card].io_base       = dev->resource[3].start;
-	cfg_mpu[card].irq           = dev->irq_resource[0].start;
-	cfg_mpu[card].dma           = -1;
-	cfg_mpu[card].dma2          = -1;
-	cfg_mpu[card].always_detect = 1; /* It's there, so use shared IRQs */
+	opl3sa2_state[card].cfg_mss.io_base      = dev->resource[1].start;
+	opl3sa2_state[card].cfg_mss.irq          = dev->irq_resource[0].start;
+	opl3sa2_state[card].cfg_mss.dma          = dev->dma_resource[0].start;
+	opl3sa2_state[card].cfg_mss.dma2         = dev->dma_resource[1].start;
+	opl3sa2_state[card].cfg_mss.card_subtype = 1; /* No IRQ or DMA setup */
+
+	opl3sa2_state[card].cfg_mpu.io_base       = dev->resource[3].start;
+	opl3sa2_state[card].cfg_mpu.irq           = dev->irq_resource[0].start;
+	opl3sa2_state[card].cfg_mpu.dma           = -1;
+	opl3sa2_state[card].cfg_mpu.dma2          = -1;
+	opl3sa2_state[card].cfg_mpu.always_detect = 1; /* It's there, so use shared IRQs */

 	/* Call me paranoid: */
-	opl3sa2_clear_slots(&cfg[card]);
-	opl3sa2_clear_slots(&cfg_mss[card]);
-	opl3sa2_clear_slots(&cfg_mpu[card]);
+	opl3sa2_clear_slots(&opl3sa2_state[card].cfg);
+	opl3sa2_clear_slots(&opl3sa2_state[card].cfg_mss);
+	opl3sa2_clear_slots(&opl3sa2_state[card].cfg_mpu);

-	opl3sa2_dev[card] = dev;
+	opl3sa2_state[card].pdev = dev;
 	opl3sa2_cards_num++;

 	return 0;
@@ -890,19 +897,20 @@

 /* End of component functions */

+#ifdef CONFIG_PM
 /* Power Management support functions */
-static int opl3sa2_suspend(struct pm_dev *pdev, unsigned char pm_mode)
+static int opl3sa2_suspend(struct pm_dev *pdev, unsigned int pm_mode)
 {
 	unsigned long flags;
-	opl3sa2_mixerdata *p;
+	opl3sa2_state_t *p;

 	if (!pdev)
 		return -EINVAL;

-	spin_lock_irqsave(&lock,flags);
+	spin_lock_irqsave(&opl3sa2_lock,flags);
+
+	p = (opl3sa2_state_t *) pdev->data;

-	p = (opl3sa2_mixerdata *) pdev->data;
-	p->in_suspend = 1;
 	switch (pm_mode) {
 	case 1:
 		pm_mode = OPL3SA2_PM_MODE1;
@@ -914,35 +922,38 @@
 		pm_mode = OPL3SA2_PM_MODE3;
 		break;
 	default:
-		pm_mode = OPL3SA2_PM_MODE3;
-		break;
+		/* we don't know howto handle this... */
+		spin_unlock_irqrestore(&opl3sa2_lock, flags);
+		return -EBUSY;
 	}

+	p->in_suspend = 1;
 	/* its supposed to automute before suspending, so we wont bother */
-	opl3sa2_read(p->cfg_port, OPL3SA2_PM, &p->reg);
-	opl3sa2_write(p->cfg_port, OPL3SA2_PM, p->reg | pm_mode);
+	opl3sa2_write(p->cfg_port, OPL3SA2_PM, pm_mode);
+	/* wait a while for the clock oscillator to stabilise */
+	mdelay(10);

-	spin_unlock_irqrestore(&lock,flags);
+	spin_unlock_irqrestore(&opl3sa2_lock,flags);
 	return 0;
 }

 static int opl3sa2_resume(struct pm_dev *pdev)
 {
 	unsigned long flags;
-	opl3sa2_mixerdata *p;
+	opl3sa2_state_t *p;

 	if (!pdev)
 		return -EINVAL;

-	p = (opl3sa2_mixerdata *) pdev->data;
-	spin_lock_irqsave(&lock,flags);
+	p = (opl3sa2_state_t *) pdev->data;
+	spin_lock_irqsave(&opl3sa2_lock,flags);

 	/* I don't think this is necessary */
-	opl3sa2_write(p->cfg_port, OPL3SA2_PM, p->reg);
-	opl3sa2_mixer_restore(p, p->card);
+	opl3sa2_write(p->cfg_port, OPL3SA2_PM, OPL3SA2_PM_MODE0);
+	opl3sa2_mixer_restore(p);
 	p->in_suspend = 0;

-	spin_unlock_irqrestore(&lock,flags);
+	spin_unlock_irqrestore(&opl3sa2_lock,flags);
 	return 0;
 }

@@ -959,6 +970,7 @@
 	}
 	return 0;
 }
+#endif

 /*
  * Install OPL3-SA2 based card(s).
@@ -967,8 +979,7 @@
  */
 static int __init init_opl3sa2(void)
 {
-        int card;
-	int max;
+        int card, max;

 	/* Sanitize isapnp and multiple settings */
 	isapnp = isapnp != 0 ? 1 : 0;
@@ -993,51 +1004,55 @@
 		if(!isapnp) {
 			if(io == -1 || irq == -1 || dma == -1 ||
 			   dma2 == -1 || mss_io == -1) {
-				printk(KERN_ERR
-				       "opl3sa2: io, mss_io, irq, dma, and dma2 must be set\n");
+				printk(KERN_ERR PFX
+					"io, mss_io, irq, dma, and dma2 must be set\n");
 				return -EINVAL;
-				opl3sa2_cards_num++;
 			}
-
+
+			opl3sa2_cards_num++;
 			/*
 			 * Our own config:
 			 * (NOTE: IRQ and DMA aren't used, so they're set to
 			 *  give pretty output from conf_printf. :)
 			 */
-			cfg[card].io_base = io;
-			cfg[card].irq     = irq;
-			cfg[card].dma     = dma;
-			cfg[card].dma2    = dma2;
+			opl3sa2_state[card].cfg.io_base = io;
+			opl3sa2_state[card].cfg.irq     = irq;
+			opl3sa2_state[card].cfg.dma     = dma;
+			opl3sa2_state[card].cfg.dma2    = dma2;

 			/* The MSS config: */
-			cfg_mss[card].io_base      = mss_io;
-			cfg_mss[card].irq          = irq;
-			cfg_mss[card].dma          = dma;
-			cfg_mss[card].dma2         = dma2;
-			cfg_mss[card].card_subtype = 1; /* No IRQ or DMA setup */
-
-			cfg_mpu[card].io_base       = mpu_io;
-			cfg_mpu[card].irq           = irq;
-			cfg_mpu[card].dma           = -1;
-			cfg_mpu[card].always_detect = 1; /* Use shared IRQs */
+			opl3sa2_state[card].cfg_mss.io_base      = mss_io;
+			opl3sa2_state[card].cfg_mss.irq          = irq;
+			opl3sa2_state[card].cfg_mss.dma          = dma;
+			opl3sa2_state[card].cfg_mss.dma2         = dma2;
+			opl3sa2_state[card].cfg_mss.card_subtype = 1; /* No IRQ or DMA setup */
+
+			opl3sa2_state[card].cfg_mpu.io_base       = mpu_io;
+			opl3sa2_state[card].cfg_mpu.irq           = irq;
+			opl3sa2_state[card].cfg_mpu.dma           = -1;
+			opl3sa2_state[card].cfg_mpu.always_detect = 1; /* Use shared IRQs */

 			/* Call me paranoid: */
-			opl3sa2_clear_slots(&cfg[card]);
-			opl3sa2_clear_slots(&cfg_mss[card]);
-			opl3sa2_clear_slots(&cfg_mpu[card]);
+			opl3sa2_clear_slots(&opl3sa2_state[card].cfg);
+			opl3sa2_clear_slots(&opl3sa2_state[card].cfg_mss);
+			opl3sa2_clear_slots(&opl3sa2_state[card].cfg_mpu);
 		}
+
+		if (probe_opl3sa2(&opl3sa2_state[card].cfg, card))
+			return -ENODEV;

-		if(!probe_opl3sa2(&cfg[card], card) ||
-		   !probe_opl3sa2_mss(&cfg_mss[card])) {
+		if(!probe_opl3sa2_mss(&opl3sa2_state[card].cfg_mss)) {
 			/*
 			 * If one or more cards are already registered, don't
 			 * return an error but print a warning.  Note, this
 			 * should never really happen unless the hardware or
 			 * ISA PnP screwed up.
 			 */
+			release_region(opl3sa2_state[card].cfg.io_base, 2);
+
 			if(opl3sa2_cards_num) {
 				printk(KERN_WARNING
-				       "opl3sa2: There was a problem probing one "
+				       PFX "There was a problem probing one "
 				       " of the ISA PNP cards, continuing\n");
 				opl3sa2_cards_num--;
 				continue;
@@ -1045,47 +1060,54 @@
 				return -ENODEV;
 		}

-		attach_opl3sa2(&cfg[card], card);
-		conf_printf(chipset_name[card], &cfg[card]);
-		attach_opl3sa2_mss(&cfg_mss[card]);
-		attach_opl3sa2_mixer(&cfg[card], card);
+		attach_opl3sa2(&opl3sa2_state[card].cfg, card);
+		conf_printf(opl3sa2_state[card].chipset_name, &opl3sa2_state[card].cfg);
+		attach_opl3sa2_mixer(&opl3sa2_state[card].cfg, card);
+		attach_opl3sa2_mss(&opl3sa2_state[card].cfg_mss);
+
+		/* ewww =) */
+		opl3sa2_state[card].card = card;

-		opl3sa2_data[card].card = card;
+#ifdef CONFIG_PM
 		/* register our power management capabilities */
-		opl3sa2_data[card].pmdev = pm_register(PM_ISA_DEV, card, opl3sa2_pm_callback);
-		if (opl3sa2_data[card].pmdev)
-			opl3sa2_data[card].pmdev->data = &opl3sa2_data[card];
+		opl3sa2_state[card].pmdev = pm_register(PM_ISA_DEV, card, opl3sa2_pm_callback);
+		if (opl3sa2_state[card].pmdev)
+			opl3sa2_state[card].pmdev->data = &opl3sa2_state[card];
+#endif

 		/*
 		 * Set the Yamaha 3D enhancement mode (aka Ymersion) if asked to and
 		 * it's supported.
 		 */
 		if(ymode != -1) {
-			if(chipset[card] == CHIPSET_OPL3SA2) {
+			if(opl3sa2_state[card].chipset == CHIPSET_OPL3SA2) {
 				printk(KERN_ERR
-				       "opl3sa2: ymode not supported on OPL3-SA2\n");
+				       PFX "ymode not supported on OPL3-SA2\n");
 			}
 			else {
-				opl3sa2_set_ymode(&cfg[card], ymode);
+				opl3sa2_set_ymode(&opl3sa2_state[card].cfg, ymode);
 			}
 		}


 		/* Set A/D input to Mono loopback if asked to. */
 		if(loopback != -1) {
-			opl3sa2_set_loopback(&cfg[card], loopback);
+			opl3sa2_set_loopback(&opl3sa2_state[card].cfg, loopback);
 		}

-		/* Attach MPU if we've been asked to do so */
-		if(cfg_mpu[card].io_base != -1) {
-			if(probe_opl3sa2_mpu(&cfg_mpu[card])) {
-				attach_opl3sa2_mpu(&cfg_mpu[card]);
+		/* Attach MPU if we've been asked to do so, failure isn't fatal */
+		if(opl3sa2_state[card].cfg_mpu.io_base != -1) {
+			if(probe_opl3sa2_mpu(&opl3sa2_state[card].cfg_mpu)) {
+				if (attach_opl3sa2_mpu(&opl3sa2_state[card].cfg_mpu)) {
+					printk(KERN_ERR PFX "failed to attach MPU401\n");
+					opl3sa2_state[card].cfg_mpu.slots[1] = -1;
+				}
 			}
 		}
 	}

 	if(isapnp) {
-		printk(KERN_NOTICE "opl3sa2: %d PnP card(s) found.\n", opl3sa2_cards_num);
+		printk(KERN_NOTICE PFX "%d PnP card(s) found.\n", opl3sa2_cards_num);
 	}

 	return 0;
@@ -1100,14 +1122,14 @@
 	int card;

 	for(card = 0; card < opl3sa2_cards_num; card++) {
-		if (opl3sa2_data[card].pmdev)
-			pm_unregister(opl3sa2_data[card].pmdev);
+		if (opl3sa2_state[card].pmdev)
+			pm_unregister(opl3sa2_state[card].pmdev);

-	        if(cfg_mpu[card].slots[1] != -1) {
-			unload_opl3sa2_mpu(&cfg_mpu[card]);
+	        if(opl3sa2_state[card].cfg_mpu.slots[1] != -1) {
+			unload_opl3sa2_mpu(&opl3sa2_state[card].cfg_mpu);
 		}
-		unload_opl3sa2_mss(&cfg_mss[card]);
-		unload_opl3sa2(&cfg[card], card);
+		unload_opl3sa2_mss(&opl3sa2_state[card].cfg_mss);
+		unload_opl3sa2(&opl3sa2_state[card].cfg, card);

 #ifdef CONFIG_PNP
 		pnp_unregister_driver(&opl3sa2_driver);
--
function.linuxpower.ca


^ permalink raw reply

* [PANIC] 2.5.51: probably NFS-related
From: Ted Phelps @ 2002-12-13  1:30 UTC (permalink / raw)
  To: linux-kernel


Hello,

I generated the following panic on an NFS server machine (i586,
linux-2.5.51, SCSI HDD, Adaptec 29160 Host Adapter) whilst mounting
and unmounting an network filesystem on a client machine
(sparc-sun-solaris-2.8).  The backtrace doesn't seem to indicate
anything NFS-specific, but I'm inclined to suspect the NFS code due to
timing and previous troubles with NFSv3 between these machines.

Here's what I was doing on the client:

$ mount -o proto=udp,vers=2 192.168.0.1:/mnt/src /mnt/src
$ ls /mnt/src/bigdir
$ umount /mnt/src

$ mount -o proto=tcp,vers=2 192.168.0.1:/mnt/src /mnt/src
$ ls /mnt/src/bigdir
$ umount /mnt/src

$ mount -o proto=tcp,vers=3 192.168.0.1:/mnt/src /mnt/src
$ ls /mnt/src/bigdir
<<BOOM>>

/mnt/src/bigdir has 143 files in it, over 2K worth of filenames.


I have been unable to use with NFSv3 (UDP or TCP) to mount partitions
on the Solaris machine when the server is running 2.5.50 or 2.5.51.
The filesystem mounts, but listing /mnt/src/bigdir usually generates
the following error:

NFS readdirplus failed for server 192.168.0.1: error 2 (RPC: Can't decode result)

I can provide tcpdump output if that helps...

Thanks,
-Ted


ksymoops 2.4.8 on i586 2.4.19.  Options used
     -v /scratch/build/linux/linux-2.5.51/vmlinux (specified)
     -K (specified)
     -L (specified)
     -o /lib/modules/2.5.51/kernel (specified)
     -m /boot/System.map-2.5.51 (specified)

No modules in ksyms, skipping objects
Unable to handle kernel paging request at virtual address 2c6b6369
*pde = 00000000
Oops: 0002
CPU:    0
EIP:    0060:[<c012e3c1>]    Not tainted
Using defaults from ksymoops -t elf32-i386 -a i386
EFLAGS: 00010012
eax: 6e6e6f43   ebx: c74ea020   ecx: c74ea0e0   edx: 2c6b6369
esi: c13e7460   edi: 00000000   ebp: c0375ef0   esp: c0375ed4
ds: 0068   es: 0068   ss: 0068
Stack: c13e746c c13e747c 00000008 c1337010 c13e7460 c1337000 00000008 c0375f2c 
       c012e609 c13e7460 c1337010 00000008 c1331f8c c0374000 c0374000 c0374000 
       c0374000 c1337010 c13e74c8 c03dba9c c012dc60 00000000 c0375f34 c012dc68 
Call Trace:
 [<c012e609>] cache_reap+0x1a9/0x270
 [<c012dc60>] reap_timer_fnc+0x0/0x30
 [<c012dc68>] reap_timer_fnc+0x8/0x30
 [<c011d553>] __run_timers+0x83/0x170
 [<c01197e9>] do_softirq+0xa9/0xb0
 [<c010a835>] do_IRQ+0x125/0x150
 [<c0107130>] default_idle+0x0/0x40
 [<c0109418>] common_interrupt+0x18/0x20
 [<c0107130>] default_idle+0x0/0x40
 [<c0107158>] default_idle+0x28/0x40
 [<c01071dd>] cpu_idle+0x2d/0x40
 [<c0105000>] _stext+0x0/0x30
Code: 89 02 89 50 04 8b 43 0c 31 d2 29 c1 89 c8 f7 76 30 89 c1 8b 


>>EIP; c012e3c1 <__free_block+61/100>   <=====

>>ebp; c0375ef0 <init_thread_union+1ef0/2000>
>>esp; c0375ed4 <init_thread_union+1ed4/2000>

Trace; c012e609 <cache_reap+1a9/270>
Trace; c012dc60 <reap_timer_fnc+0/30>
Trace; c012dc68 <reap_timer_fnc+8/30>
Trace; c011d553 <__run_timers+83/170>
Trace; c01197e9 <do_softirq+a9/b0>
Trace; c010a835 <do_IRQ+125/150>
Trace; c0107130 <default_idle+0/40>
Trace; c0109418 <common_interrupt+18/20>
Trace; c0107130 <default_idle+0/40>
Trace; c0107158 <default_idle+28/40>
Trace; c01071dd <cpu_idle+2d/40>
Trace; c0105000 <_stext+0/0>

Code;  c012e3c1 <__free_block+61/100>
00000000 <_EIP>:
Code;  c012e3c1 <__free_block+61/100>   <=====
   0:   89 02                     mov    %eax,(%edx)   <=====
Code;  c012e3c3 <__free_block+63/100>
   2:   89 50 04                  mov    %edx,0x4(%eax)
Code;  c012e3c6 <__free_block+66/100>
   5:   8b 43 0c                  mov    0xc(%ebx),%eax
Code;  c012e3c9 <__free_block+69/100>
   8:   31 d2                     xor    %edx,%edx
Code;  c012e3cb <__free_block+6b/100>
   a:   29 c1                     sub    %eax,%ecx
Code;  c012e3cd <__free_block+6d/100>
   c:   89 c8                     mov    %ecx,%eax
Code;  c012e3cf <__free_block+6f/100>
   e:   f7 76 30                  divl   0x30(%esi)
Code;  c012e3d2 <__free_block+72/100>
  11:   89 c1                     mov    %eax,%ecx
Code;  c012e3d4 <__free_block+74/100>
  13:   8b 00                     mov    (%eax),%eax

 <0>Kernel panic: Aiee, killing interrupt handler!
       c012e609 c13e7460 c1337010 00000008 c1331f8c c0374000 c0374000 c0374000 
      c012e609 c13e7460 c1337010 00000008 c1331f8c c0374000 c0374000 c0374000 
      c012e609 c13e7460 c1337010 00000008 c1331f8c c0374000 c0374000 c0374000 
      c012e609 c13e7460 c1337010 00000008 c1331f8c c0374000 c0374000 c0374000 
      c012e609 c13e7460 c1337010 00000008 c1331f8c c0374000 c0374000 c0374000 
      c012e609 c13e7460 c1337010 00000008 c1331f8c c0374000 c0374000 c0374000 
      c012e609 c13e7460 c1337010 00000008 c1331f8c c0374000 c0374000 c0374000 
      c012e609 c13e7460 c1337010 00000008 c1331f8c c0374000 c0374000 c0374000 
      c012e609 c13e7460 c1337010 00000008 c1331f8c c0374000 c0374000 c0374000 
      c012e609 c13e7460 c1337010 00000008 c1331f8c c0374000 c0374000 c0374000 
      c012e609 c13e7460 c1337010 00000008 c1331f8c c0374000 c0374000 c0374000 
      c012e609 c13e7460 c1337010 00000008 c1331f8c c0374000 c0374000 c0374000 
      c012e609 c13e7460 c1337010 00000008 c1331f8c c0374000 c0374000 c037400

^ permalink raw reply

* Re: 2.5.51 nanosleep fails
From: Stephen Rothwell @ 2002-12-13  1:29 UTC (permalink / raw)
  To: jim.houston; +Cc: md, julie.n.fleischer, linux-kernel, torvalds
In-Reply-To: <200212122227.gBCMRkT10652@linux.local>

Hi All,

On Thu, 12 Dec 2002 17:27:46 -0500 Jim Houston <jim.houston@attbi.com> wrote:
>
> The problem is that nanosleep didn't check for the NULL pointer
> case and always tries to copy out the remaining time.  The attached
> patch will fix this problem.

Equivalent fix for the compatibility layer ...

Not compiled, not tested (I need to get a 64 bit machine ...)

Obviously correct (hopefully) :-)
-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/

diff -ruN 2.5.51/kernel/compat.c 2.5.51-ns/kernel/compat.c
--- 2.5.51/kernel/compat.c	2002-12-10 15:10:41.000000000 +1100
+++ 2.5.51-ns/kernel/compat.c	2002-12-13 12:12:00.000000000 +1100
@@ -21,8 +21,7 @@
 static long compat_nanosleep_restart(struct restart_block *restart)
 {
 	unsigned long expire = restart->arg0, now = jiffies;
-	struct timespec *rmtp = (struct timespec *) restart->arg1;
-	long ret;
+	struct compat_timespec *rmtp;
 
 	/* Did it expire while we handled signals? */
 	if (!time_after(expire, now))
@@ -30,22 +29,22 @@
 
 	current->state = TASK_INTERRUPTIBLE;
 	expire = schedule_timeout(expire - now);
+	if (expire == 0)
+		return 0;
 
-	ret = 0;
-	if (expire) {
+	rmtp = (struct compat_timespec *)restart->arg1;
+	if (rmtp) {
 		struct compat_timespec ct;
 		struct timespec t;
 
 		jiffies_to_timespec(expire, &t);
 		ct.tv_sec = t.tv_sec;
 		ct.tv_nsec = t.tv_nsec;
-
-		ret = -ERESTART_RESTARTBLOCK;
 		if (copy_to_user(rmtp, &ct, sizeof(ct)))
-			ret = -EFAULT;
-		/* The 'restart' block is already filled in */
+			return -EFAULT;
 	}
-	return ret;
+	/* The 'restart' block is already filled in */
+	return -ERESTART_RESTARTBLOCK;
 }
 
 asmlinkage long compat_sys_nanosleep(struct compat_timespec *rqtp,
@@ -53,8 +52,8 @@
 {
 	struct compat_timespec ct;
 	struct timespec t;
+	struct restart_block *restart;
 	unsigned long expire;
-	s32 ret;
 
 	if (copy_from_user(&ct, rqtp, sizeof(ct)))
 		return -EFAULT;
@@ -67,25 +66,21 @@
 	expire = timespec_to_jiffies(&t) + (t.tv_sec || t.tv_nsec);
 	current->state = TASK_INTERRUPTIBLE;
 	expire = schedule_timeout(expire);
+	if (expire == 0)
+		return 0;
 
-	ret = 0;
-	if (expire) {
-		struct restart_block *restart;
-
+	if (rmtp) {
 		jiffies_to_timespec(expire, &t);
 		ct.tv_sec = t.tv_sec;
 		ct.tv_nsec = t.tv_nsec;
-
 		if (copy_to_user(rmtp, &ct, sizeof(ct)))
 			return -EFAULT;
-
-		restart = &current_thread_info()->restart_block;
-		restart->fn = compat_nanosleep_restart;
-		restart->arg0 = jiffies + expire;
-		restart->arg1 = (unsigned long) rmtp;
-		ret = -ERESTART_RESTARTBLOCK;
 	}
-	return ret;
+	restart = &current_thread_info()->restart_block;
+	restart->fn = compat_nanosleep_restart;
+	restart->arg0 = jiffies + expire;
+	restart->arg1 = (unsigned long) rmtp;
+	return -ERESTART_RESTARTBLOCK;
 }
 
 /*

^ permalink raw reply

* dmfs for 2.5.51
From: Greg KH @ 2002-12-13  1:26 UTC (permalink / raw)
  To: lvm-devel, linux-kernel

Hi,

Here's a patch against 2.5.51 with a updated dmfs.  It contains the two
patches at:
http://people.sistina.com/~thornber/patches/2.5-unstable/2.5.50/2.5.50-dmfs-1/00012.patch
and
http://people.sistina.com/~thornber/patches/2.5-unstable/2.5.50/2.5.50-dmfs-1/00013.patch
with the following modifications:
	- fixed locking type mismatch (trying to call spin_lock on a
	  rw_semaphore).
	- fixed compile time warnings with the dbg() macro (something
	  better should be used here, I just commented it out...)
	- changed the dev file to print out the kdev value, not be the
	  actual block device.

With regards to the last change, I didn't follow the way the other files
operate with their complex page creation structure, as this is only a
simple one line file.  If the lvm developers want me to change this, I
will.  If not, I would argue that a number of the other files created
should be changed to use this simpler format.  Or is there some reason
for creating these lists of pages that I'm missing?

Comments welcome.

thanks,

greg k-h


diff -Nru a/Documentation/filesystems/dmfs.txt b/Documentation/filesystems/dmfs.txt
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/filesystems/dmfs.txt	Thu Dec 12 17:24:06 2002
@@ -0,0 +1,74 @@
+Overview
+--------
+
+dmfs is a little custom filesystem used as a user interface to the
+device-mapper driver.  The directory heirarchy follows this pattern:
+
+/
+  <namespace1>/
+    <device name1>/
+      table
+      suspend
+      status
+      devices
+      dev
+    <device name2>/
+    ...
+
+  <namespace2>
+   ...
+
+
+Examples
+--------
+
+Example commands will make things a bit clearer:
+
+- To mount the filesystem
+
+  mount -r dmfs none /dev/mapper
+
+- Create a namespace for LVM
+
+  cd /dev/mapper
+  mkdir LVM
+  cd LVM
+
+- Create a new device, that is a linear catenation of parts of 2
+  disks.
+
+  mkdir vg0-music
+  cd vg0-music
+  echo -e "0 56 linear /dev/hda3 0\n56 102344 linear /dev/hda4 0" > table
+
+- Remind yourself what table is running
+
+  cat table
+
+- The 'dev' file should now have appeared.  It shows the major/minor value
+  that you can use to mount your new device.
+
+- To suspend the device
+
+  echo -n 1 > suspend
+
+- To resume
+
+  echo -n 0 > suspend
+
+- To find out the status of the targets in the table
+
+  cat status
+
+- Which sub devices are in use ?
+
+  cat devices
+
+- You may hard link device directories between different namespaces to
+  create aliases (eg, LVM likes to associate a unique id with every
+  device as well as giving it a more human readable name).
+
+  cd /dev/mapper
+  mkdir UUID
+  cd UUID
+  ln ../LVM/vg0-music Qmd96y-771S-Esbb-Zp6u-8xo9-Cfmt-YvndHY
diff -Nru a/drivers/md/Kconfig b/drivers/md/Kconfig
--- a/drivers/md/Kconfig	Thu Dec 12 17:24:06 2002
+++ b/drivers/md/Kconfig	Thu Dec 12 17:24:06 2002
@@ -145,5 +145,18 @@
 
 	  If unsure, say N.
 
+config BLK_DEV_DM_FS
+	tristate "Filesystem interface (experimental)"
+	depends on BLK_DEV_DM
+	depends on EXPERIMENTAL
+	---help---
+	  Ram-based filesytem for controlling device-mapper.  Can co-exist
+	  with the ioctl interface.
+
+	  If you want to compile this as a module, say M here and read 
+	  <file:Documentation/modules.txt>.  The module will be called dm-fs.o.
+
+	  If unsure, say N.
+
 endmenu
 
diff -Nru a/drivers/md/Makefile b/drivers/md/Makefile
--- a/drivers/md/Makefile	Thu Dec 12 17:24:06 2002
+++ b/drivers/md/Makefile	Thu Dec 12 17:24:06 2002
@@ -3,8 +3,7 @@
 #
 
 export-objs	:= md.o xor.o dm-table.o dm-target.o
-dm-mod-objs	:= dm.o dm-table.o dm-target.o dm-linear.o dm-stripe.o \
-		   dm-ioctl.o
+dm-mod-objs	:= dm.o dm-table.o dm-target.o dm-linear.o dm-stripe.o
 
 # Note: link order is important.  All raid personalities
 # and xor.o must come before md.o, as they each initialise 
@@ -17,7 +16,8 @@
 obj-$(CONFIG_MD_RAID5)		+= raid5.o xor.o
 obj-$(CONFIG_MD_MULTIPATH)	+= multipath.o
 obj-$(CONFIG_BLK_DEV_MD)	+= md.o
-obj-$(CONFIG_BLK_DEV_DM)	+= dm-mod.o
+obj-$(CONFIG_BLK_DEV_DM)	+= dm-mod.o dm-ioctl.o
+obj-$(CONFIG_BLK_DEV_DM_FS)	+= dm-fs.o
 
 include $(TOPDIR)/Rules.make
 
diff -Nru a/drivers/md/dm-fs.c b/drivers/md/dm-fs.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/md/dm-fs.c	Thu Dec 12 17:24:06 2002
@@ -0,0 +1,1237 @@
+/*
+ * Copyright (C) 2002 Sistina Software (UK) Limited.
+ *
+ * This file is released under the GPL.
+ *
+ * Filesystem interface to device-mapper:
+ *
+ * You can only mkdir in the top directory, every directory you
+ * create equates to a device.  The device dir will contain 5
+ * files:
+ *
+ * <dev>/table
+ * <dev>/status
+ * <dev>/suspend
+ * <dev>/devices
+ * <dev>/dev - The value of the new device node
+ */
+
+#include "dm.h"
+
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/ctype.h>
+#include <linux/vmalloc.h>
+#include <linux/namei.h>
+#include <linux/init.h>
+#include <asm/uaccess.h>
+
+#define dbg(x...) //DMWARN(## x)
+
+/*-----------------------------------------------------------------
+ * Each device directory has an associate dmfs_dir struct.
+ *---------------------------------------------------------------*/
+struct dmfs_dir {
+	atomic_t holders;
+
+	spinlock_t lock;
+	struct mapped_device *md;
+
+	struct dentry *table_dentry;
+	struct dentry *status_dentry;
+	struct dentry *suspend_dentry;
+	struct dentry *subdevs_dentry;
+	struct dentry *dev_dentry;
+};
+
+static int create_file(const char *name, mode_t mode, dev_t dev,
+		       struct dentry *parent,
+		       struct file_operations *fops, struct dentry **dentry);
+static void dmfs_dir_destroy(struct dmfs_dir *dd);
+static struct inode *dmfs_get_inode(struct super_block *sb, int mode, int dev);
+static int create_dev_files(struct dmfs_dir *dd);
+
+static inline void dmfs_get_dir(struct dmfs_dir *dd)
+{
+	atomic_inc(&dd->holders);
+}
+
+static inline void dmfs_put_dir(struct dmfs_dir *dd)
+{
+	if (atomic_dec_and_test(&dd->holders))
+		dmfs_dir_destroy(dd);
+}
+
+/*-----------------------------------------------------------------
+ * Manage a set of pages for storing a file.
+ *---------------------------------------------------------------*/
+struct dmfs_file {
+	struct dmfs_dir *owner;
+	atomic_t holders;
+
+	/* The lock protects len, and the pages list/contents */
+	spinlock_t lock;
+	struct list_head pages;
+	loff_t len;
+};
+
+static struct dmfs_file *file_alloc(struct dmfs_dir *owner)
+{
+	struct dmfs_file *f;
+
+	f = kmalloc(sizeof(*f), GFP_KERNEL);
+	if (f) {
+		dmfs_get_dir(owner);
+		f->owner = owner;
+		atomic_set(&f->holders, 1);
+		f->lock = SPIN_LOCK_UNLOCKED;
+		f->len = 0;
+		INIT_LIST_HEAD(&f->pages);
+	}
+
+	return f;
+}
+
+static inline void file_get(struct dmfs_file *f)
+{
+	atomic_inc(&f->holders);
+}
+
+static void file_put(struct dmfs_file *f)
+{
+	struct list_head *pos, *n;
+
+	if (atomic_dec_and_test(&f->holders)) {
+		dbg("destroying dmfs_file");
+		dmfs_put_dir(f->owner);
+
+		list_for_each_safe (pos, n, &f->pages) {
+			struct page *p = list_entry(pos, struct page, list);
+			__free_page(p);
+		}
+		kfree(f);
+	}
+}
+
+/*
+ * Returns the page from the list that has data starting at the
+ * offset 'len'.  If 'fill' is true then extra pages may be allocated.
+ */
+static struct page *find_page(struct dmfs_file *f, loff_t len, int fill)
+{
+	struct page *p = NULL;
+	struct list_head *pos;
+
+	/*
+	 * Find the right page.
+	 */
+	list_for_each (pos, &f->pages) {
+		if (len < PAGE_SIZE) {
+			p = list_entry(pos, struct page, list);
+			break;
+		}
+
+		len -= PAGE_SIZE;
+	}
+
+	if (!p && fill) {
+		/* we need to allocate new pages */
+		do {
+			void *addr = (void *) __get_free_page(GFP_KERNEL);
+			if (!addr)
+				return NULL;
+
+			p = virt_to_page(addr);
+			list_add_tail(&p->list, &f->pages);
+			len -= PAGE_SIZE;
+
+		} while (len > 0);
+	}
+
+	return p;
+}
+
+/*
+ * This function moves data in or out of the pages that make up
+ * our table file.
+ */
+typedef ssize_t (*io_actor)(char *file_buff, char *client_buff, size_t count);
+
+static ssize_t __io(struct dmfs_file *f, loff_t start,
+		    char *buff, size_t count, int fill, io_actor fn)
+{
+	ssize_t r;
+	size_t page_offset;
+	struct page *p;
+	char *data;
+
+	p = find_page(f, start, fill);
+	if (!p)
+		return 0;	/* no data */
+
+	page_offset = start & (PAGE_SIZE - 1);
+	data = page_address(p) + page_offset;
+
+	/* stay in this page */
+	if (count > (PAGE_SIZE - page_offset))
+		count = PAGE_SIZE - page_offset;
+
+	/* stay in this file */
+	if (!fill && (count > (f->len - start)))
+		count = f->len - start;
+
+	r = fn(data, buff, count);
+	if (r < 0)
+		return r;
+
+	/* have we lengthened the file ? */
+	if (f->len < (start + r))
+		f->len = start + r;
+
+	return r;
+}
+
+/*
+ * Keeps resubmitting until there is an error, or all the io has
+ * completed.
+ */
+static ssize_t file_io(struct dmfs_file *f, loff_t start,
+		       char *buff, size_t count, int fill, io_actor fn)
+{
+	size_t this_io, total = 0;
+
+	spin_lock(&f->lock);
+	do {
+		this_io = __io(f, start, buff, count - total, fill, fn);
+		if (this_io < 0) {
+			total = this_io;
+			break;
+		}
+
+		total += this_io;
+		start += this_io;
+
+	} while (this_io && (total != count));
+
+	spin_unlock(&f->lock);
+
+	return total;
+}
+
+static ssize_t user_read_fn(char *file_buff, char *client_buff, size_t count)
+{
+	return copy_to_user(client_buff, file_buff, count) ? -EFAULT : count;
+}
+
+static ssize_t user_write_fn(char *file_buff, char *client_buff, size_t count)
+{
+	return copy_from_user(file_buff, client_buff, count) ? -EFAULT : count;
+}
+
+static ssize_t kernel_read_fn(char *file_buff, char *client_buff, size_t count)
+{
+	memcpy(client_buff, file_buff, count);
+	return count;
+}
+
+static ssize_t kernel_write_fn(char *file_buff, char *client_buff,
+			       size_t count)
+{
+	memcpy(file_buff, client_buff, count);
+	return count;
+}
+
+/*-----------------------------------------------------------------
+ * Protect accessing the dd->md field with a spin lock, taking
+ * care to increment the md's reference count whilst still within
+ * the lock.
+ *---------------------------------------------------------------*/
+static inline struct mapped_device *get_dm_from_dir(struct dmfs_dir *dd)
+{
+	struct mapped_device *md;
+
+	spin_lock(&dd->lock);
+	md = dd->md;
+	if (md)
+		dm_get(md);
+	spin_unlock(&dd->lock);
+
+	return md;
+}
+
+static inline void set_dm_in_dir(struct dmfs_dir *dd,
+				 struct mapped_device *md)
+{
+	spin_lock(&dd->lock);
+	if (dd->md)
+		dm_put(dd->md);
+	dm_get(md);
+	dd->md = md;
+	spin_lock(&dd->lock);
+}
+
+/*-----------------------------------------------------------------
+ * File ops for the 'table' file, we keep the last successfully
+ * parsed table (ie. the one that's running) in the
+ * inode->u.generic_ip, and the table being loaded in
+ * file->private_data.
+ *---------------------------------------------------------------*/
+static spinlock_t _table_lock = SPIN_LOCK_UNLOCKED;
+static struct dmfs_file *get_old_table(struct file *file)
+{
+	struct dmfs_file *f;
+
+	spin_lock(&_table_lock);
+	f = file->f_dentry->d_inode->u.generic_ip;
+	if (f)
+		file_get(f);
+	spin_unlock(&_table_lock);
+
+	return f;
+}
+
+static void set_old_table(struct file *file, struct dmfs_file *f)
+{
+	struct dmfs_file *old;
+
+	spin_lock(&_table_lock);
+	old = file->f_dentry->d_inode->u.generic_ip;
+	if (old)
+		file_put(old);
+
+	file_get(f);
+	file->f_dentry->d_inode->u.generic_ip = f;
+	spin_unlock(&_table_lock);
+}
+
+/*
+ * Gets the dmfs_dir from the inode of the parent directory of
+ * file.
+ */
+static inline struct dmfs_dir *lookup_dmfs_dir(struct file *file)
+{
+	return file->f_dentry->d_parent->d_inode->u.generic_ip;
+}
+
+/*
+ * Create a struct table_file to read the new table into.
+ */
+static int table_open(struct inode *inode, struct file *file)
+{
+	struct dmfs_dir *dd = lookup_dmfs_dir(file);
+	struct dmfs_file *f;
+
+	f = file_alloc(dd);
+	if (!f)
+		return -ENOMEM;
+
+	file->private_data = f;
+	return 0;
+}
+
+static ssize_t table_read(struct file *file,
+			  char *buf, size_t count, loff_t *offset)
+{
+	ssize_t r = 0;
+	struct dmfs_file *f = get_old_table(file);
+
+	/* has a table been successfully bound ? */
+	if (f) {
+		r = file_io(f, *offset, buf, count, 0, user_read_fn);
+		if (r > 0)
+			*offset += r;
+
+		file_put(f);
+	}
+
+	return r;
+}
+
+static ssize_t table_write(struct file *file, const char *ubuff,
+			   size_t count, loff_t *offset)
+{
+	ssize_t r;
+	struct dmfs_file *f = file->private_data;
+
+	r = file_io(f, *offset, (char *) ubuff, count, 1, user_write_fn);
+	if (r > 0)
+		*offset += r;
+
+	return r;
+}
+
+static int parse_line(struct dm_table *table, char *line)
+{
+	int r, pos;
+	sector_t start, len;
+	char target[32];
+
+	dbg("parsing '%s'", line);
+	r = sscanf(line, SECTOR_FORMAT " " SECTOR_FORMAT " %32s%n",
+		   &start, &len, target, &pos);
+	if (r != 3) {
+		DMERR("badly formed target line: %s", line);
+		return -EINVAL;
+	}
+
+	line += pos;
+
+	/* Add the target to the table */
+	if (dm_table_add_target(table, target, start, len, line)) {
+		DMERR("internal error adding target to table");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static char *eat_space(char *str)
+{
+	int comment = 0;
+
+	while (*str) {
+		if (*str == '#')
+			comment = 1;
+
+		if (!isspace(*str) && !comment)
+			break;
+
+		str++;
+	}
+
+	return str;
+}
+
+static int get_line(struct dmfs_file *f, loff_t offset,
+		    char *buffer, size_t buffer_len)
+{
+	int n, i;
+
+	n = file_io(f, offset, buffer, buffer_len, 0, kernel_read_fn);
+	if (n <= 0)
+		return n;
+
+	for (i = 0; i < n; i++) {
+		if (buffer[i] == '\n') {
+			buffer[i] = '\0';
+			return (i + 1);
+		}
+	}
+
+	/* the last line might not have a newline */
+	if (i < buffer_len) {
+		buffer[i] = '\0';
+		return i;
+	}
+
+	return -EIO;
+}
+
+#define LINE_SIZE 512
+static int parse_table(struct dmfs_file *f, struct dm_table **result)
+{
+	int r;
+	struct dm_table *table = NULL;
+	loff_t offset = 0;
+	char *buffer, *line;
+
+	/* allocate a little buffer for building the lines up in */
+	buffer = kmalloc(LINE_SIZE, GFP_KERNEL);
+	if (!buffer) {
+		DMERR("couldn't allocate line buffer");
+		return -ENOMEM;
+	}
+
+	r = dm_table_create(&table, FMODE_READ | FMODE_WRITE);
+	if (r) {
+		DMERR("couldn't create table");
+		goto out;
+	}
+
+	while (1) {
+		r = get_line(f, offset, buffer, LINE_SIZE);
+		if (r == 0)
+			break;
+
+		else if (r < 0)
+			goto out;
+
+		offset += r;
+		line = eat_space(buffer);
+		if (!*line)
+			continue;
+
+		r = parse_line(table, line);
+		if (r)
+			goto out;
+	}
+	r = dm_table_complete(table);
+
+ out:
+	if (r && table) {
+		dm_table_put(table);
+		table = NULL;
+	}
+
+	kfree(buffer);
+	*result = table;
+	return r;
+}
+
+/*
+ * When the table file is closed for a write we try and parse the
+ * new table.  If we successfully parse the new table we swap it
+ * with the old one.
+ */
+static int table_release(struct inode *inode, struct file *file)
+{
+	int r = 0;
+	struct mapped_device *md = NULL;
+	struct dm_table *table;
+	struct dmfs_file *f = file->private_data;
+	struct dmfs_dir *dd;
+
+	/*
+	 * We're only interested if the user has written
+	 * something to the table.
+	 */
+	if (!f->len)
+		goto out;
+
+	/* parse new table */
+	r = parse_table(f, &table);
+	if (r)
+		goto out;
+
+	dd = f->owner;
+	md = get_dm_from_dir(dd);
+	if (md) {
+		/* swap tables */
+		r = dm_swap_table(md, table);
+		if (r)
+			goto out;
+		dbg("new table swapped in");
+	} else {
+		r = dm_create(-1, table, &md);
+		if (r)
+			goto out;
+		set_dm_in_dir(dd, md);
+		dbg("device created");
+
+		r = create_dev_files(dd);
+		if (r)
+			goto out;
+	}
+
+	/*
+	 * The new table becomes the old table.
+	 */
+	set_old_table(file, f);
+
+ out:
+	if (md)
+		dm_put(md);
+
+	if (table)
+		dm_table_put(table);
+
+	file_put(f);
+	return r;
+}
+
+static struct file_operations _table_fops = {
+	.open = table_open,
+	.read =	table_read,
+	.write = table_write,
+	.release = table_release,
+};
+
+/*-----------------------------------------------------------------
+ * File ops for the 'suspend' file
+ *---------------------------------------------------------------*/
+static ssize_t suspend_read(struct file *file,
+			    char *buf, size_t count, loff_t *offset)
+{
+	struct dmfs_dir *dd = lookup_dmfs_dir(file);
+	struct mapped_device *md;
+
+	/* this file is only 1 char long */
+	if ((*offset != 0) || !count)
+		return 0;
+
+	/* has a table been loaded yet ? */
+	md = get_dm_from_dir(dd);
+	if (!md)
+		return 0;
+
+	if (copy_to_user(buf, dm_suspended(md) ? "1" : "0", 1))
+		return -EFAULT;
+	dm_put(md);
+
+	(*offset)++;
+	return 1;
+}
+
+static ssize_t suspend_write(struct file *file, const char *ubuff,
+			     size_t count, loff_t *offset)
+{
+	struct dmfs_dir *dd = lookup_dmfs_dir(file);
+	struct mapped_device *md;
+	char sus_p;
+
+	/* this file is only 1 char long */
+	if ((*offset != 0) || !count)
+		return 0;
+
+	if (copy_from_user(&sus_p, ubuff, 1))
+		return -EFAULT;
+
+	/* has a table been loaded yet ? */
+	md = get_dm_from_dir(dd);
+	if (!md)
+		return 0;
+
+	switch (sus_p) {
+	case '0':
+		dm_resume(md);
+		break;
+
+	case '1':
+		dm_suspend(md);
+		break;
+
+	default:
+		DMERR("badly formed input to suspend file");
+	}
+	dm_put(md);
+	(*offset)++;
+	return 1;
+}
+
+static struct file_operations _suspend_fops = {
+	.read = suspend_read,
+	.write = suspend_write
+};
+
+/*-----------------------------------------------------------------
+ * File ops for the 'status' file.  A snapshot of the status is
+ * generated when the file is opened and freed when the file is
+ * closed.  In addition the poll method will wait until an event
+ * occurs where upon it will regenerate the status file.
+ *---------------------------------------------------------------*/
+static int generate_status(struct dmfs_file *f, struct mapped_device *md)
+{
+	int i, num_targets, r = 0;
+	ssize_t this_write;
+	loff_t offset = 0;
+	struct dm_target *ti;
+	struct dm_table *table = dm_get_table(md);
+	static char buffer[1024];
+
+	/* Get all the target info */
+	num_targets = dm_table_get_num_targets(table);
+	for (i = 0; i < num_targets; i++) {
+		ti = dm_table_get_target(table, i);
+
+		r = snprintf(buffer, sizeof(buffer),
+			     SECTOR_FORMAT " " SECTOR_FORMAT " %s ",
+			     ti->begin, ti->len, ti->type->name);
+		if (r < 0) {
+			DMERR("status too long for buffer");
+			break;
+		}
+
+		/* Get the status/table string from the target driver */
+		if (ti->type->status)
+			ti->type->status(ti, STATUSTYPE_INFO,
+					 buffer + r, sizeof(buffer) - r);
+
+		/* write the status line to the status file */
+		r = 0;
+		this_write = file_io(f, offset, buffer,
+				     strlen(buffer), 1, kernel_write_fn);
+		if (this_write < 0) {
+			r = this_write;
+			break;
+		}
+		offset += this_write;
+
+		/* write a newline */
+		this_write = file_io(f, offset, "\n", 1, 1, kernel_write_fn);
+		if (this_write < 0) {
+			r = this_write;
+			break;
+		}
+		offset += this_write;
+	}
+
+	dm_table_put(table);
+	return r;
+}
+
+static int status_open(struct inode *inode, struct file *file)
+{
+	int r;
+	struct dmfs_dir *dd = lookup_dmfs_dir(file);
+	struct mapped_device *md;
+	struct dmfs_file *f;
+
+	md = get_dm_from_dir(dd);
+	if (!md)
+		return -ENXIO;
+
+	f = file_alloc(dd);
+	if (!f) {
+		dm_put(md);
+		return -ENOMEM;
+	}
+
+	r = generate_status(f, md);
+	if (r) {
+		dm_put(md);
+		file_put(f);
+		return r;
+	}
+
+	dm_put(md);
+	file->private_data = f;
+	return r;
+}
+#if 0
+static unsigned int status_poll(struct file *file,
+				struct poll_table_struct *pts)
+{
+	struct mapped_device *md;
+	struct dm_table *table;
+	DECLARE_WAITQUEUE(wq, current);
+
+	md = get_dm_from_dir(dd);
+	if (!md)
+		return -ENXIO;
+
+	table = dm_get_table(md);
+	dm_put(md);
+
+	/*
+	 * Wait for a notification event
+	 */
+	set_current_state(TASK_INTERRUPTIBLE);
+	dm_table_add_wait_queue(table, &wq);
+	dm_table_put(table);
+
+	yield();
+	set_current_state(TASK_RUNNING);
+
+	/* FIXME: regenerate the status file */
+	return 0;
+}
+#endif
+static ssize_t status_read(struct file *file,
+			   char *buf, size_t count, loff_t *offset)
+{
+	ssize_t r;
+	struct dmfs_file *f = file->private_data;
+
+	r = file_io(f, *offset, buf, count, 0, user_read_fn);
+	if (r > 0)
+		*offset += r;
+
+	return r;
+}
+
+static int status_release(struct inode *inode, struct file *file)
+{
+	struct dmfs_file *f = file->private_data;
+	file_put(f);
+	return 0;
+}
+
+static struct file_operations _status_fops = {
+	.open = status_open,
+	/*.poll = status_poll,*/
+	.read = status_read,
+	.release = status_release,
+};
+
+/*-----------------------------------------------------------------
+ * File ops for the 'devices' file
+ *---------------------------------------------------------------*/
+static int generate_subdevs(struct dmfs_file *file, struct mapped_device *md)
+{
+	static char buffer[1024];
+
+	int r = 0;
+	ssize_t this_write;
+	loff_t offset = 0;
+	struct dm_table *table = dm_get_table(md);
+	struct list_head *pos;
+
+	/* Get all the device info */
+	list_for_each(pos, dm_table_get_devices(table)) {
+		struct dm_dev *dd = list_entry(pos, struct dm_dev, list);
+
+		snprintf(buffer, sizeof(buffer), "%d:%d\n",
+			 MAJOR(dd->bdev->bd_dev), MINOR(dd->bdev->bd_dev));
+
+		this_write = file_io(file, offset, buffer,
+				     strlen(buffer), 1, kernel_write_fn);
+		if (this_write < 0) {
+			r = this_write;
+			break;
+		}
+
+		offset += this_write;
+	}
+
+	dm_table_put(table);
+	return r;
+}
+
+static int subdevs_open(struct inode *inode, struct file *file)
+{
+	int r;
+	struct dmfs_dir *dd = lookup_dmfs_dir(file);
+	struct mapped_device *md;
+	struct dmfs_file *f;
+
+	f = file_alloc(dd);
+	if (!f)
+		return -ENOMEM;
+
+	md = get_dm_from_dir(dd);
+	if (!md) {
+		file_put(f);
+		return -ENXIO;
+	}
+
+	r = generate_subdevs(f, md);
+	if (r) {
+		dm_put(md);
+		file_put(f);
+		return r;
+	}
+
+	dm_put(md);
+	file->private_data = f;
+	return r;
+}
+
+static ssize_t subdevs_read(struct file *file,
+			    char *buf, size_t count, loff_t *offset)
+{
+	ssize_t r;
+	struct dmfs_file *f = file->private_data;
+	r = file_io(f, *offset, buf, count, 0, user_read_fn);
+	if (r > 0)
+		*offset += r;
+
+	return r;
+}
+
+static int subdevs_release(struct inode *inode, struct file *file)
+{
+	file_put((struct dmfs_file *) file->private_data);
+	return 0;
+}
+
+static struct file_operations _subdevs_fops = {
+	.open = subdevs_open,
+	.read = subdevs_read,
+	.release = subdevs_release,
+};
+
+/*-----------------------------------------------------------------
+ * File ops for the 'dev' file
+ *---------------------------------------------------------------*/
+static int dev_open(struct inode *inode, struct file *file)
+{
+	return 0;
+}
+
+static ssize_t dev_read(struct file *file,
+			    char *buf, size_t count, loff_t *offset)
+{
+	struct dmfs_dir *dd;
+	struct gendisk *disk;
+	kdev_t kdev;
+	unsigned char *page;
+	int retval;
+	int len;
+	
+	if (*offset < 0)
+		return -EINVAL;
+	if (count <= 0)
+		return 0;
+	if (*offset != 0)
+		return 0;
+
+	page = (unsigned char *)__get_free_page(GFP_KERNEL);
+	if (!page)
+		return -ENOMEM;
+
+	dd = lookup_dmfs_dir(file);
+	disk = dm_disk(dd->md);
+	kdev = mk_kdev(disk->major, disk->first_minor);
+	
+	len = sprintf(page, "%x\n", kdev.value);
+	if (copy_to_user (buf, page, len)) {
+		return -EFAULT;
+		goto exit;
+	}
+	*offset += len;
+	retval = len;
+
+exit:
+	free_page((unsigned long)page);
+	return retval;
+}
+
+static struct file_operations _dev_fops = {
+	.open = dev_open,
+	.read = dev_read,
+};
+
+/*-----------------------------------------------------------------
+ * Directory ops
+ *---------------------------------------------------------------*/
+static int create_file(const char *name, mode_t mode, dev_t dev,
+		       struct dentry *parent,
+		       struct file_operations *fops, struct dentry **dentry)
+{
+	struct dentry *d = NULL;
+	struct qstr qstr;
+	int r;
+
+	*dentry = NULL;
+	qstr.name = name;
+	qstr.len = strlen(name);
+	qstr.hash = full_name_hash(name,qstr.len);
+
+	parent = dget(parent);
+
+	down(&parent->d_inode->i_sem);
+
+	d = lookup_hash(&qstr,parent);
+
+	r = PTR_ERR(d);
+	if (!IS_ERR(d)) {
+		switch(mode & S_IFMT) {
+		case 0:
+		case S_IFREG:
+			r = vfs_create(parent->d_inode, d, mode);
+			break;
+
+		case S_IFBLK:
+			r = vfs_mknod(parent->d_inode, d, mode, dev);
+			break;
+
+		default:
+			DMERR("cannot create special files\n");
+		}
+
+
+		if (fops)
+			d->d_inode->i_fop = fops;
+		*dentry = d;
+	}
+	up(&parent->d_inode->i_sem);
+	dput(parent);
+	return r;
+}
+
+static inline int positive(struct dentry *dentry)
+{
+	return dentry->d_inode && !d_unhashed(dentry);
+}
+
+static void __remove_file(struct dentry *d)
+{
+	struct dentry *parent = d->d_parent;
+
+	if (!parent || !parent->d_inode)
+		return;
+
+	/*
+	 * The parent inode will already be locked when we get in
+	 * here.
+	 */
+	if (positive(d)) {
+		if (d->d_inode)
+			vfs_unlink(parent->d_inode, d);
+
+		dput(d);
+	}
+}
+
+static void remove_file(struct dentry *d)
+{
+	if (d)
+		__remove_file(d);
+}
+
+static void dmfs_dir_destroy(struct dmfs_dir *dd)
+{
+	dbg("destroying dmfs_dir %p", dd);
+	if (dd->md)
+		dm_put(dd->md);
+
+	remove_file(dd->table_dentry);
+	remove_file(dd->status_dentry);
+	remove_file(dd->suspend_dentry);
+	remove_file(dd->subdevs_dentry);
+	remove_file(dd->dev_dentry);
+	kfree(dd);
+}
+
+static int create_dev_files(struct dmfs_dir *dd)
+{
+	const mode_t mode = S_IFREG | 0755;
+	struct dentry *dir_dentry = dd->table_dentry->d_parent;
+	int r;
+
+	r = create_file("suspend", mode, 0, dir_dentry,
+			&_suspend_fops, &dd->suspend_dentry);
+	if (r) {
+		dbg("couldn't create suspend file");
+		goto out;
+	}
+
+	r = create_file("status", mode, 0, dir_dentry,
+			&_status_fops, &dd->status_dentry);
+	if (r) {
+		dbg("couldn't create status file");
+		goto out;
+	}
+
+	r = create_file("devices", mode, 0, dir_dentry,
+			&_subdevs_fops, &dd->subdevs_dentry);
+	if (r) {
+		dbg("couldn't create devices file");
+		goto out;
+	}
+
+	r = create_file("dev", mode, 0, dir_dentry,
+			&_dev_fops, &dd->subdevs_dentry);
+	if (r) {
+		dbg("couldn't create dev file");
+		goto out;
+	}
+	
+
+ out:
+	return r;
+}
+
+static struct dmfs_dir *dmfs_dir_create(struct dentry *dir_dentry)
+{
+	int r;
+	struct dmfs_dir *dd;
+	mode_t mode = S_IFREG | 0755;
+
+	dd = kmalloc(sizeof(*dd), GFP_KERNEL);
+	if (!dd)
+		return NULL;
+
+	memset(dd, 0, sizeof(*dd));
+	dd->lock = SPIN_LOCK_UNLOCKED;
+
+	r = create_file("table", mode, 0, dir_dentry,
+			&_table_fops, &dd->table_dentry);
+	if (r) {
+		dmfs_dir_destroy(dd);
+		return NULL;
+	}
+
+	return dd;
+}
+
+static int dmfs_mknod(struct inode *dir, struct dentry *dentry,
+		      int mode, dev_t dev)
+{
+	struct inode *inode;
+
+	inode = dmfs_get_inode(dir->i_sb, mode, dev);
+	if (!inode)
+		return -ENOSPC;
+
+	d_instantiate(dentry, inode);
+	dget(dentry);		/* Extra count - pin the dentry in core */
+	return 0;
+}
+
+static int dmfs_create(struct inode *dir, struct dentry *dentry, int mode)
+{
+	return dmfs_mknod(dir, dentry, mode | S_IFREG, 0);
+}
+
+static struct inode_operations _devdir_iops = {
+	.create = dmfs_create,
+	.lookup	= simple_lookup,
+	.mknod = dmfs_mknod,
+};
+
+static struct inode *dmfs_get_inode(struct super_block *sb, int mode, int dev)
+{
+	struct inode *inode = new_inode(sb);
+
+	if (inode) {
+		inode->i_mode = mode;
+		inode->i_uid = current->fsuid;
+		inode->i_gid = current->fsgid;
+		inode->i_blksize = PAGE_CACHE_SIZE;
+		inode->i_blocks = 0;
+		inode->i_rdev = NODEV;
+		inode->i_atime =
+			inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+		switch (mode & S_IFMT) {
+		default:
+			init_special_inode(inode, mode, dev);
+			break;
+
+		case S_IFREG:
+			inode->i_fop = &simple_dir_operations;
+			break;
+
+		case S_IFDIR:
+			inode->i_op = &_devdir_iops;
+			inode->i_fop = &simple_dir_operations;
+
+			/*
+			 * Directory inodes start off with
+			 * i_nlink == 2 (for "." entry).
+			 */
+			inode->i_nlink++;
+			break;
+		}
+	}
+
+	return inode;
+}
+
+static int dmfs_namespace_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+{
+	int r;
+	struct dmfs_dir *n;
+
+	r = dmfs_mknod(dir, dentry, S_IFDIR | mode, 0);
+	if (r)
+		return r;
+
+	n = dmfs_dir_create(dentry);
+	if (!n) {
+		/* FIXME: check this */
+		dput(dentry);
+		return -ENOMEM;
+	}
+
+	dentry->d_inode->u.generic_ip = n;
+	dir->i_nlink++;
+	return 0;
+}
+
+static int dmfs_namespace_rmdir(struct inode *inode, struct dentry *d)
+{
+	struct dmfs_dir *dd = d->d_inode->u.generic_ip;
+
+	dbg("dmfs_root_rmdir, freeing %p", dd);
+	dmfs_put_dir(dd);
+
+	d->d_inode->i_nlink--;
+	simple_unlink(inode, d);
+	inode->i_nlink--;
+	return 0;
+}
+
+static struct inode_operations _namespace_iops = {
+	.lookup = simple_lookup,
+	.unlink = simple_unlink,
+	.mkdir = dmfs_namespace_mkdir,
+	.rmdir = dmfs_namespace_rmdir,
+	.rename = simple_rename,
+};
+
+static int dmfs_root_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+{
+	int r;
+
+	r = dmfs_mknod(dir, dentry, S_IFDIR | mode, 0);
+	if (r)
+		return r;
+
+	dentry->d_inode->i_op = &_namespace_iops;
+	dir->i_nlink++;
+	return 0;
+}
+
+static struct inode_operations _root_iops = {
+	.lookup = simple_lookup,
+	.unlink = simple_unlink,
+	.mkdir = dmfs_root_mkdir,
+	.rmdir = simple_rmdir,
+	.rename = simple_rename,
+};
+
+/*-----------------------------------------------------------------
+ * super operations
+ *---------------------------------------------------------------*/
+/* Random magic number */
+#define DMFS_MAGIC 0x23112671
+
+static struct super_operations _dmfs_super_ops = {
+	statfs:         simple_statfs,
+	delete_inode:   generic_delete_inode,
+};
+
+static int dmfs_fill_super(struct super_block *sb, void *data, int silent)
+{
+	struct inode *inode;
+	struct dentry *root;
+
+	sb->s_blocksize = PAGE_CACHE_SIZE;
+	sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
+	sb->s_magic = DMFS_MAGIC;
+	sb->s_op = &_dmfs_super_ops;
+	inode = dmfs_get_inode(sb, S_IFDIR | 0755, 0);
+	if (!inode) {
+		DMERR("%s: could not get inode!\n",__FUNCTION__);
+		return -ENOMEM;
+	}
+
+	/* You can only make directories in the root dir */
+	inode->i_op = &_root_iops;
+
+	root = d_alloc_root(inode);
+	if (!root) {
+		DMERR("%s: could not get root dentry!\n",__FUNCTION__);
+		iput(inode);
+		return -ENOMEM;
+	}
+	sb->s_root = root;
+	return 0;
+}
+
+static struct super_block *dmfs_get_sb(struct file_system_type *fs_type,
+				       int flags, char *dev_name, void *data)
+{
+	return get_sb_single(fs_type, flags, data, dmfs_fill_super);
+}
+
+static struct file_system_type _dmfs_type = {
+	.name = "dmfs",
+	.get_sb	= dmfs_get_sb,
+	.kill_sb = kill_litter_super,
+};
+
+static int dm_interface_init(void)
+{
+	return register_filesystem(&_dmfs_type);
+}
+
+static void dm_interface_exit(void)
+{
+	unregister_filesystem(&_dmfs_type);
+}
+
+module_init(dm_interface_init);
+module_exit(dm_interface_exit);
diff -Nru a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
--- a/drivers/md/dm-ioctl.c	Thu Dec 12 17:24:06 2002
+++ b/drivers/md/dm-ioctl.c	Thu Dec 12 17:24:06 2002
@@ -1073,7 +1073,7 @@
 /*
  * Create misc character device and link to DM_DIR/control.
  */
-int __init dm_interface_init(void)
+static int dm_interface_init(void)
 {
 	int r;
 
@@ -1105,7 +1105,7 @@
 	return r;
 }
 
-void dm_interface_exit(void)
+static void dm_interface_exit(void)
 {
 	dm_hash_exit();
 
@@ -1114,3 +1114,6 @@
 	if (misc_deregister(&_dm_misc) < 0)
 		DMERR("misc_deregister failed for control device");
 }
+
+module_init(dm_interface_init);
+module_exit(dm_interface_exit);
diff -Nru a/drivers/md/dm.c b/drivers/md/dm.c
--- a/drivers/md/dm.c	Thu Dec 12 17:24:06 2002
+++ b/drivers/md/dm.c	Thu Dec 12 17:24:06 2002
@@ -125,7 +125,6 @@
 	xx(dm_target)
 	xx(dm_linear)
 	xx(dm_stripe)
-	xx(dm_interface)
 #undef xx
 };
 
diff -Nru a/drivers/md/dm.h b/drivers/md/dm.h
--- a/drivers/md/dm.h	Thu Dec 12 17:24:06 2002
+++ b/drivers/md/dm.h	Thu Dec 12 17:24:06 2002
@@ -130,13 +130,6 @@
 }
 
 /*
- * The device-mapper can be driven through one of two interfaces;
- * ioctl or filesystem, depending which patch you have applied.
- */
-int dm_interface_init(void);
-void dm_interface_exit(void);
-
-/*
  * Targets for linear and striped mappings
  */
 int dm_linear_init(void);

^ permalink raw reply

* New large block device patch available (against 2.4.21-pre1)
From: Peter Chubb @ 2002-12-13  1:25 UTC (permalink / raw)
  To: linux-kernel


I've updated the large block device patch to fix the incorrect size
reporting for large SCSI discs, and to match 2.4.21-pre1.

This patch is almost completely untested --- I no longer have access
to any large disc machines --- please let me know how you get on with it.

Patch at:
      http://www.gelato.unsw.edu.au/patches/2.4.21-pre1-lbd.patch

--
Dr Peter Chubb				    peterc@gelato.unsw.edu.au
You are lost in a maze of BitKeeper repositories, all almost the same.

^ permalink raw reply

* [LARTC] Sch_teql or multilink def. gw?
From: Steen Suder, privat @ 2002-12-13  1:15 UTC (permalink / raw)
  To: lartc

I'm to build a "bundlerbox" spanning over two or more DSLlines as 
outlined in the <http://www.ssi.bg/~ja/nano.txt>.

The idea is to multiplex a LAN over e.g. four cheap DSLs, SNATing it in 
the action. The DSLs are from different ISPs, but all equal in speed 
(2048/512Kb/s).

Now, it has come to my attention that there exist a tc-module called 
sch_teql.

As I understand it sch_teql + SNAT on each device will functionally be 
the same as the

"ip rule add prio 222 table 222
ip route add default table 222 proto static \
		nexthop via GWE1 dev IFE1 \
		nexthop via GWE2 dev IFE2" -thing from nano.txt.

Which one is the better one in terms of overall performance, usability 
and stability seen from a users perspective?

I know that there has been several questions regarding "cheap 
line"-multiplexing, but I couldn't a definitive answer to my question.

Either that or I havn't really understood what sch_teql does and how it 
could be utilized.

Another, though related question:

The multilink def. gw-example above does gw-selection on a per-session 
basis, as I've understood it.
The keyword "equalize" as in
"ip route add default equalize nexthop via gateway.number.1.ip \
	dev eth0 nexthop via gateway.number.2.ip dev eth1"

chooses routes on per-packet basis.
Can they both be used for my "box"? Why/Why not?

-- 
Steen Suder

_______________________________________________
LARTC mailing list / LARTC@mailman.ds9a.nl
http://mailman.ds9a.nl/mailman/listinfo/lartc HOWTO: http://lartc.org/

^ permalink raw reply

* Re: pci-skeleton duplex check
From: Donald Becker @ 2002-12-13  1:18 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: Roger Luethi, netdev, Linux Kernel Mailing List
In-Reply-To: <3DF90208.3010208@pobox.com>

On Thu, 12 Dec 2002, Jeff Garzik wrote:
> Donald Becker wrote:
> > On Thu, 12 Dec 2002, Jeff Garzik wrote:
> >>Donald Becker wrote:
> 	[[ I don't know why I bother. The people that now control what
> 	   goes into the kernel would rather put in random patches from
> 	   other people than accept a correct fix from me. ]]
> I'm sure you'll continue making snide comments on every mailing list you 
> maintain, but the fact remains:
> I would much rather accept a fix from you.

Perhaps we have a different idea of "fix".

You want are looking for a patch to modifications you have made to code
I have written.  In the meantime I have been providing working code, and
have been updating that code to work with new hardware.  So a fix is the
working, continuously maintained version of the driver. 

To put an admittedly simplified spin on it, you are saying "I want you
to tell me what I have broken when I changed this", and to continuously
monitor and test your changes, made for unknown reasons on a very
divergent source base.

> > The drivers in the kernel are now heavily modified and have significantly
> > diverged from my version.  Sure, you are fine with having someone else
> > do the difficult and unrewarding debugging and maintenance work, while
> > you work on just the latest cool hardware, change the interfaces and are
> > concerned only with the current kernel version.
> 
> While I disagree with this assessment, I think we can safely draw the 
> conclusion that the problem is _not_ people ignoring your patches, or 
> preferring other patches over yours.

I can point to specific instances.  Just looking at the drivers in the
kernel, it is clear that this has happened.

> > A good example is the tulip driver.  You repeatedly restructured my
...
> I take responsibility for fixing it, I just haven't fixed it yet :)

> > It's easy to make the first few patches, when you don't have to deal
> > with reversion testing, many different models, and have an unlimited
> > sandbox where it doesn't matter if a specific release works or not.

I think that these two statements fit well together.


> > But
> > it takes a huge of work to keep a stable, traceable driver development
> > process that works with many different kernel versions and hardware
> > environments.
> 
> We're slowly getting there, in terms of regression and stress testing.

But it existed before, and was discarded!
Yes, the kernel is now _returning_ to a stable state while making
improvements.  But there was a period of time when interface stability
and detailed correctness was thrown away in favor of many inexperienced
people quickly and repeatedly restructuring interfaces without
understanding the underlying requirements.

I could mention VM, but I'll go back to one that had a very large direct
impacted on me: CardBus.  CardBus is a difficult case of hot-swap PCI --
the device can go away without warning, and it's usually implemented on
machines where suspend and resume must work correctly.  We had perhaps
the best operational implementation in the industry, and I had written
about half of the CardBus drivers.  Yet my proven interface
implementation was completely discarded in favor one that needed to be
repeatedly changed as the requirements were slowly understood. 

> I would love to integrate your drivers directly, but they don't come 
> anywhere close to using current kernel APIs.  The biggie of biggies is 
> not using the pci_driver API.  So, given that we cannot directly merge 

Yup, that is just what I was talking about.  Let me continue: 

The result is that today other systems now have progressed to a great
implementation of suspend/resume, while Linux distributions now default
to unloading and reloading drivers to avoid various suspend bugs.  And
when the driver cannot be unloaded because some part of the networking
stack is holding the interface, things go horribly wrong...

You might be able to naysay the individual details, but the end
technical result is clear.

> your drivers, and you don't send patches to kernel developers, what is 
> the next best alternative?  (a) let kernel net drivers bitrot, or (b) 
> maintain them as best we can without Don Becker patches?  I say that "b" 
> is far better than "a" for Linux users.

Or perhaps recognizing that when someone that has been a significant,
continuous contributer since the early days of Linux says "this is
screwed up", they might have a point.  When Linux suddenly had thousands
of people wanting to submit patches, that didn't means that there were
more people that could understand, implement and maintain complex
systems.

-- 
Donald Becker				becker@scyld.com
Scyld Computing Corporation		http://www.scyld.com
410 Severn Ave. Suite 210		Scyld Beowulf cluster system
Annapolis MD 21403			410-990-9993



^ permalink raw reply

* Re: Is the scsi-misc-2.5 BK tree corrupted?
From: SL Baur @ 2002-12-13  1:11 UTC (permalink / raw)
  To: James Bottomley; +Cc: linux-scsi
In-Reply-To: <200212121419.gBCEJWp02105@localhost.localdomain>

James Bottomley writes:

> I have noticed BK do this periodically on other trees (most notably
> the linux ones).  It seems to be related to some type of backup
> program that bkbits runs.  I usually just wait a while and try
> again, which has worked so far.

O.K.  I can live with that.  I did retry it yesterday a couple of
times, maybe I didn't wait long enough.  It works now.  Thanks for the
clue.


^ permalink raw reply

* Re: PROBLEM: dvd-drive no longer works (2.4.20)
From: Brendon Higgins @ 2002-12-13  1:04 UTC (permalink / raw)
  To: black666; +Cc: linux-kernel
In-Reply-To: <200212122305.32825.black666@inode.at>

On Fri, 13 Dec 2002 8:05 am, you wrote:
> Same here. I also have a MSI KT3 Ultra2 and the same problem with 2.4.20
>
> The -ac1 patch helped because it booted just fine and I had dma on my
> harddisk. But then I had problems mounting my dvd drive ... I'll try
> the new -ac2 patch today, let's see if it makes any difference.

Let me know if it helps. I'm currently using the Debian sources, though I've 
tried the original sources also, and besides failing to mount root (initrd, 
etc - don't ask) the error messages were still there. Even so, I'm able to 
have DMA on my HDs without any problems, it seems.

> Btw: I think it depends what cd/dvd drive you have. I've heard from
> other people with MSI KT3 Ultra2 who have no problem with 2.4.20
> (without ac1 patch) and dma on disks plus dvd/cd/cdrw.

I have two drives, one a CD-RW, the other a DVD. Both my DVD drive and my 
CD-RW drive complain during boot (though the DVD drive has many more 
messages). The DVD won't work, but my CD-RW drive still manages to end up 
working through scd0 (it used to work on scd1, though).

Peace,
Brendon


^ permalink raw reply


This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.