aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordavem <davem>2001-12-05 04:39:37 +0000
committerdavem <davem>2001-12-05 04:39:37 +0000
commit35c12815a23df751403d388f281d77f6af9f4476 (patch)
tree7a58e5764ae791b542bca01b82b10b272c3b960f
parent529c28f2fb5232a15ab11363951592f815bc0748 (diff)
downloadnetdev-vger-cvs-35c12815a23df751403d388f281d77f6af9f4476.tar.gz
Merge mainline to 2.4.17-pre2
-rw-r--r--CREDITS7
-rw-r--r--Documentation/Configure.help21
-rw-r--r--Documentation/pm.txt4
-rw-r--r--Documentation/usb/philips.txt59
-rw-r--r--Documentation/usb/scanner.txt2
-rw-r--r--Documentation/video4linux/w9966.txt40
-rw-r--r--MAINTAINERS4
-rw-r--r--Makefile2
-rw-r--r--arch/i386/mm/init.c15
-rw-r--r--drivers/char/pcmcia/serial_cs.c47
-rw-r--r--drivers/char/serial.c18
-rw-r--r--drivers/ieee1394/hosts.c4
-rw-r--r--drivers/ieee1394/ieee1394_core.c2
-rw-r--r--drivers/ieee1394/nodemgr.c157
-rw-r--r--drivers/ieee1394/ohci1394.c85
-rw-r--r--drivers/ieee1394/pcilynx.c2
-rw-r--r--drivers/ieee1394/sbp2.c242
-rw-r--r--drivers/ieee1394/sbp2.h9
-rw-r--r--drivers/ieee1394/video1394.c64
-rw-r--r--drivers/ieee1394/video1394.h8
-rw-r--r--drivers/media/video/Config.in6
-rw-r--r--drivers/media/video/w9966.c142
-rw-r--r--drivers/net/irda/vlsi_ir.c6
-rw-r--r--drivers/net/pcmcia/Config.in2
-rw-r--r--drivers/net/pcmcia/axnet_cs.c216
-rw-r--r--drivers/net/pcmcia/netwave_cs.c3
-rw-r--r--drivers/parport/parport_cs.c77
-rw-r--r--drivers/pcmcia/cistpl.c4
-rw-r--r--drivers/pcmcia/cs.c8
-rw-r--r--drivers/pcmcia/cs_internal.h6
-rw-r--r--drivers/pcmcia/rsrc_mgr.c115
-rw-r--r--drivers/scsi/ide-scsi.c2
-rw-r--r--drivers/scsi/pcmcia/aha152x_stub.c72
-rw-r--r--drivers/scsi/pcmcia/fdomain_stub.c41
-rw-r--r--drivers/scsi/pcmcia/qlogic_stub.c38
-rw-r--r--drivers/sound/ad1848.c135
-rw-r--r--drivers/sound/ad1848_mixer.h210
-rw-r--r--drivers/usb/dabusb.c2
-rw-r--r--drivers/usb/dc2xx.c3
-rw-r--r--drivers/usb/hid-core.c2
-rw-r--r--drivers/usb/pwc-ctrl.c2
-rw-r--r--drivers/usb/pwc-if.c151
-rw-r--r--drivers/usb/pwc.h4
-rw-r--r--drivers/usb/scanner.c34
-rw-r--r--drivers/usb/scanner.h26
-rw-r--r--drivers/usb/serial/belkin_sa.c10
-rw-r--r--drivers/usb/serial/cyberjack.c2
-rw-r--r--drivers/usb/serial/empeg.c2
-rw-r--r--drivers/usb/serial/ftdi_sio.c6
-rw-r--r--drivers/usb/serial/io_edgeport.c11
-rw-r--r--drivers/usb/serial/keyspan.c6
-rw-r--r--drivers/usb/serial/keyspan.h30
-rw-r--r--drivers/usb/serial/mct_u232.c6
-rw-r--r--drivers/usb/serial/omninet.c2
-rw-r--r--drivers/usb/serial/usbserial.c6
-rw-r--r--drivers/usb/serial/visor.c4
-rw-r--r--drivers/usb/serial/whiteheat.c4
-rw-r--r--drivers/usb/usbnet.c5
-rw-r--r--fs/buffer.c1
-rw-r--r--fs/exec.c2
-rw-r--r--fs/ext2/super.c48
-rw-r--r--fs/inode.c2
-rw-r--r--fs/nls/nls_cp1251.c2
-rw-r--r--fs/nls/nls_cp1255.c2
-rw-r--r--fs/nls/nls_cp437.c2
-rw-r--r--fs/nls/nls_cp737.c2
-rw-r--r--fs/nls/nls_cp775.c2
-rw-r--r--fs/nls/nls_cp850.c2
-rw-r--r--fs/nls/nls_cp852.c2
-rw-r--r--fs/nls/nls_cp855.c2
-rw-r--r--fs/nls/nls_cp857.c2
-rw-r--r--fs/nls/nls_cp860.c2
-rw-r--r--fs/nls/nls_cp861.c2
-rw-r--r--fs/nls/nls_cp862.c2
-rw-r--r--fs/nls/nls_cp863.c2
-rw-r--r--fs/nls/nls_cp864.c2
-rw-r--r--fs/nls/nls_cp865.c2
-rw-r--r--fs/nls/nls_cp866.c2
-rw-r--r--fs/nls/nls_cp869.c2
-rw-r--r--fs/nls/nls_cp874.c2
-rw-r--r--fs/reiserfs/bitmap.c7
-rw-r--r--fs/reiserfs/inode.c24
-rw-r--r--fs/reiserfs/journal.c2
-rw-r--r--fs/reiserfs/stree.c92
-rw-r--r--include/asm-i386/pgalloc.h52
-rw-r--r--include/asm-ia64/pal.h8
-rw-r--r--include/asm-ia64/siginfo.h8
-rw-r--r--include/linux/reiserfs_fs_sb.h4
-rw-r--r--include/linux/slab.h1
-rw-r--r--include/net/irda/irlmp.h12
-rw-r--r--include/net/irda/irttp.h11
-rw-r--r--include/pcmcia/ciscode.h8
-rw-r--r--include/pcmcia/cs.h7
-rw-r--r--include/pcmcia/version.h6
-rw-r--r--init/main.c2
-rw-r--r--mm/slab.c8
-rw-r--r--net/irda/af_irda.c59
-rw-r--r--net/irda/iriap.c4
-rw-r--r--net/irda/irlap.c33
-rw-r--r--net/irda/irlap_event.c45
-rw-r--r--net/irda/irlmp.c11
-rw-r--r--net/irda/irlmp_event.c7
-rw-r--r--net/irda/irnet/irnet.h7
-rw-r--r--net/irda/irnet/irnet_irda.c17
-rw-r--r--net/irda/irsysctl.c59
-rw-r--r--net/irda/qos.c56
106 files changed, 1689 insertions, 1143 deletions
diff --git a/CREDITS b/CREDITS
index c498dc9ff..ae2ea995c 100644
--- a/CREDITS
+++ b/CREDITS
@@ -1634,6 +1634,13 @@ S: ul. Matemblewska 1B/10
S: 80-283 Gdansk
S: Poland
+N: Jakob Kemi
+E: jakob.kemi@telia.com
+D: V4L W9966 Webcam driver
+S: Forsbyvägen 33
+S: 74143 Knivsta
+S: Sweden
+
N: Gero Kuhlmann
E: gero@gkminix.han.de
D: mounting root via NFS
diff --git a/Documentation/Configure.help b/Documentation/Configure.help
index f2cf66155..f24201259 100644
--- a/Documentation/Configure.help
+++ b/Documentation/Configure.help
@@ -8650,6 +8650,19 @@ CONFIG_PCMCIA_PCNET
a module, say M here and read <file:Documentation/modules.txt>. If
unsure, say N.
+Asix AX88190 PCMCIA support
+CONFIG_PCMCIA_AXNET
+ Say Y here if you intend to attach an Asix AX88190-based PCMCIA
+ (PC-card) Fast Ethernet card to your computer. These cards are
+ nearly NE2000 compatible but need a separate driver due to a few
+ misfeatures.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called axnet_cs.o. If you want to compile it as
+ a module, say M here and read <file:Documentation/modules.txt>. If
+ unsure, say N.
+
New Media PCMCIA support
CONFIG_PCMCIA_NMCLAN
Say Y here if you intend to attach a New Media Ethernet or LiveWire
@@ -16891,8 +16904,8 @@ CONFIG_ACPI
can be downloaded from:
<http://developer.intel.com/technology/iapc/acpi/downloads.htm>.
- The ACPI mailing list may also be of interest:
- <http://phobos.fs.tum.de/acpi/index.html>.
+ The ACPI Sourceforge project may also be of interest:
+ <http://sf.net/projects/acpi/>
Enable ACPI 2.0 with errata 1.3
CONFIG_ACPI20
@@ -21411,7 +21424,7 @@ CONFIG_VIDEO_CQCAM
as a module (c-qcam.o).
Read <file:Documentation/video4linux/CQcam.txt> for more information.
-Winbond W9966CF Webcam Video For Linux
+W9966 Webcam (FlyCam Supra and others) Video For Linux
CONFIG_VIDEO_W9966
Video4linux driver for Winbond's w9966 based Webcams.
Currently tested with the LifeView FlyCam Supra.
@@ -21420,7 +21433,7 @@ CONFIG_VIDEO_W9966
This driver is also available as a module (w9966.o).
Check out <file:Documentation/video4linux/w9966.txt> and
- <file:Documentation/video4linux/w9966.c> for more information.
+ <file:drivers/media/video/w9966.c> for more information.
CPiA Video For Linux
CONFIG_VIDEO_CPIA
diff --git a/Documentation/pm.txt b/Documentation/pm.txt
index 3913cd46b..483d2a5d1 100644
--- a/Documentation/pm.txt
+++ b/Documentation/pm.txt
@@ -34,7 +34,7 @@ Go ahead and start both. If ACPI or APM is not available on your
system the associated daemon will exit gracefully.
apmd: http://worldvisions.ca/~apenwarr/apmd/
- acpid: http://phobos.fs.tum.de/acpi/
+ acpid: http://acpid.sf.net/
Driver Interface
----------------
@@ -260,7 +260,7 @@ proceed in the opposite direction.
Q: Who do I contact for additional information about
enabling power management for my specific driver/device?
-ACPI4Linux mailing list: acpi@phobos.fs.tum.de
+ACPI Development mailing list: acpi-devel@lists.sourceforge.net
System Interface
----------------
diff --git a/Documentation/usb/philips.txt b/Documentation/usb/philips.txt
index d48df51c3..16477ef62 100644
--- a/Documentation/usb/philips.txt
+++ b/Documentation/usb/philips.txt
@@ -1,5 +1,5 @@
This file contains some additional information for the Philips webcams.
-E-mail: webcam@smcc.demon.nl Last updated: 2001-07-27
+E-mail: webcam@smcc.demon.nl Last updated: 2001-09-24
The main webpage for the Philips driver is http://www.smcc.demon.nl/webcam/.
It contains a lot of extra information, a FAQ, and the binary plugin
@@ -13,11 +13,9 @@ You can build this code either into your kernel, or as a module. I recommend
the latter, since it makes troubleshooting a lot easier. The built-in
microphone is supported through the USB Audio class.
-(Taken from install.html)
-
When you load the module you can set some default settings for the
-camera; some programs depend on a particular image-size or -format. The
-options are:
+camera; some programs depend on a particular image-size or -format and
+don't know how to set it properly in the driver. The options are:
size
Can be one of 'sqcif', 'qsif', 'qcif', 'sif', 'cif' or
@@ -100,6 +98,57 @@ leds
750). For other cameras this command is silently ignored, and the LED
cannot be controlled.
+dev_hint
+ A long standing problem with USB devices is their dynamic nature: you
+ never know what device a camera gets assigned; it depends on module load
+ order, the hub configuration, the order in which devices are plugged in,
+ and the phase of the moon (i.e. it can be random). With this option you
+ can give the driver a hint as to what video device node (/dev/videoX) it
+ should use with a specific camera. This is also handy if you have two
+ cameras of the same model.
+
+ A camera is specified by its type (the number from the camera model,
+ like PCA645, PCVC750VC, etc) and optionally the serial number (visible
+ in /proc/bus/usb/devices). A hint consists of a string with the following
+ format:
+
+ [type[.serialnumber]:]node
+
+ The square brackets mean that both the type and the serialnumber are
+ optional, but a serialnumber cannot be specified without a type (which
+ would be rather pointless). The serialnumber is separated from the type
+ by a '.'; the node number by a ':'.
+
+ This somewhat cryptic syntax is best explained by a few examples:
+
+ dev_hint=3,5 The first detected cam gets assigned
+ /dev/video3, the second /dev/video5. Any
+ other cameras will get the first free
+ available slot (see below).
+
+ dev_hint=645:1,680=2 The PCA645 camera will get /dev/video1,
+ and a PCVC680 /dev/video2.
+
+ dev_hint=645.0123:3,645.4567:0 The PCA645 camera with serialnumber
+ 0123 goes to /dev/video3, the same
+ camera model with the 4567 serial
+ gets /dev/video0.
+
+ dev_hint=750:1,4,5,6 The PCVC750 camera will get /dev/video1, the
+ next 3 Philips cams will use /dev/video4
+ through /dev/video6.
+
+ Some points worth knowing:
+ - Serialnumbers are case sensitive and must be written full, including
+ leading zeroes (it's treated as a string).
+ - If a device node is already occupied, registration will fail and
+ the webcam is not available.
+ - You can have up to 64 video devices; be sure to make enough device
+ nodes in /dev if you want to spread the numbers (this does not apply
+ to devfs). After /dev/video9 comes /dev/video10 (not /dev/videoA).
+ - If a camera does not match any dev_hint, it will simply get assigned
+ the first available device node, just as it used to be.
+
trace
In order to better detect problems, it is now possible to turn on a
'trace' of some of the calls the module makes; it logs all items in your
diff --git a/Documentation/usb/scanner.txt b/Documentation/usb/scanner.txt
index 5f03dd670..e8d6945ee 100644
--- a/Documentation/usb/scanner.txt
+++ b/Documentation/usb/scanner.txt
@@ -83,7 +83,7 @@ If you intend to use more than one scanner at a time w/o devfs support:
`mknod /dev/usbscanner1 c 180 49`
.
.
- `mknod /dev/usbscanner15 180 63`
+ `mknod /dev/usbscanner15 c 180 63`
If you foresee using only one scanner it is best to:
diff --git a/Documentation/video4linux/w9966.txt b/Documentation/video4linux/w9966.txt
index d132c4301..e7ac33a7e 100644
--- a/Documentation/video4linux/w9966.txt
+++ b/Documentation/video4linux/w9966.txt
@@ -1,37 +1,33 @@
+W9966 Camera driver, written by Jakob Kemi (jakob.kemi@telia.com)
-W9966 Camera driver, written by Jakob Kemi (jakob.kemi@post.utfors.se)
+After a lot of work in softice & wdasm, reading .pdf-files and tiresome
+trial-and-error work I've finally got everything to work. I needed vision for a
+robotics project so I borrowed this camera from a friend and started hacking.
+Anyway I've converted my original code from the AVR 8bit RISC C/ASM code into
+a working Linux driver.
-Ok, after a lot of work in softice, wdasm, reading pdf-files
-and trial-and-error work I've finally got everything to work.
-Since I needed some vision for a robotics project I borrowed
-this camera from a friend and started hacking. Anyway I've
-converted my original code from the AVR 8bit RISC C/asm
-into a working linux driver. I would really appreciate _any_
-kind of feedback regarding this driver.
+To get it working simply configure your kernel to support
+parport, ieee1284, video4linux and w9966
-To get it working quickly configure your kernel
-to support parport, ieee1284, video4linux, experimental drivers
-and w9966
-
-If w9966 is statically linked it will perform aggressive probing
-for the camera. If built as a module you'll have more configuration options.
+If w9966 is statically linked it will always perform aggressive probing for
+the camera. If built as a module you'll have more configuration options.
Options:
-modprobe w9966.o pardev=parport0(or whatever) parmode=0 (0=auto, 1=ecp, 2=epp)
-
+ modprobe w9966.o pardev=parport0(or whatever) parmode=0 (0=auto, 1=ecp, 2=epp)
voila!
you can also type 'modinfo -p w9966.o' for option usage
(or checkout w9966.c)
-I've only tested it with custom built testprograms
-(http://hem.fyristorg.com/mogul/w9966.html) and with gqcam.
-(you'll need to tweak the code to qcam a bit to make it work,
-dimensions and such)
+The only thing to keep in mind is that the image format is in Y-U-Y-V format
+where every two pixels take 4 bytes. In SDL (www.libsdl.org) this format
+is called VIDEO_PALETTE_YUV422 (16 bpp).
+
+A minimal test application (with source) is available from:
+ http://hem.fyristorg.com/mogul/w9966.html
The slow framerate is due to missing DMA ECP read support in the
parport drivers. I might add working EPP support later.
Good luck!
-
- /Jakob
+ /Jakob Kemi
diff --git a/MAINTAINERS b/MAINTAINERS
index f352b586f..8e2f75c31 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -148,8 +148,8 @@ S: Supported
ACPI
P: Andy Grover
M: andrew.grover@intel.com
-L: acpi@phobos.fs.tum.de
-W: http://phobos.fs.tum.de/acpi/index.html
+L: acpi-devel@lists.sourceforge.net
+W: http://sf.net/projects/acpi/
S: Maintained
AD1816 SOUND DRIVER
diff --git a/Makefile b/Makefile
index 2d09bc675..6287f3704 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 4
SUBLEVEL = 17
-EXTRAVERSION =-pre1
+EXTRAVERSION =-pre2
KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c
index f0c3b00c0..bed1221ec 100644
--- a/arch/i386/mm/init.c
+++ b/arch/i386/mm/init.c
@@ -25,6 +25,7 @@
#include <linux/highmem.h>
#include <linux/pagemap.h>
#include <linux/bootmem.h>
+#include <linux/slab.h>
#include <asm/processor.h>
#include <asm/system.h>
@@ -596,3 +597,17 @@ void si_meminfo(struct sysinfo *val)
val->mem_unit = PAGE_SIZE;
return;
}
+
+#if defined(CONFIG_X86_PAE)
+struct kmem_cache_s *pae_pgd_cachep;
+void __init pgtable_cache_init(void)
+{
+ /*
+ * PAE pgds must be 16-byte aligned:
+ */
+ pae_pgd_cachep = kmem_cache_create("pae_pgd", 32, 0,
+ SLAB_HWCACHE_ALIGN | SLAB_MUST_HWCACHE_ALIGN, NULL, NULL);
+ if (!pae_pgd_cachep)
+ panic("init_pae(): Cannot alloc pae_pgd SLAB cache");
+}
+#endif /* CONFIG_X86_PAE */
diff --git a/drivers/char/pcmcia/serial_cs.c b/drivers/char/pcmcia/serial_cs.c
index 892f2c832..b9f628a01 100644
--- a/drivers/char/pcmcia/serial_cs.c
+++ b/drivers/char/pcmcia/serial_cs.c
@@ -2,7 +2,7 @@
A driver for PCMCIA serial devices
- serial_cs.c 1.123 2000/08/24 18:46:38
+ serial_cs.c 1.128 2001/10/18 12:18:35
The contents of this file are subject to the Mozilla Public
License Version 1.1 (the "License"); you may not use this file
@@ -19,8 +19,8 @@
are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
Alternatively, the contents of this file may be used under the
- terms of the GNU General Public License version 2 (the "GPL"), in which
- case the provisions of the GPL are applicable instead of the
+ terms of the GNU General Public License version 2 (the "GPL"), in
+ which case the provisions of the GPL are applicable instead of the
above. If you wish to allow the use of your version of this file
only under the terms of the GPL and not to allow others to use
your version of this file under the MPL, indicate your decision
@@ -44,6 +44,7 @@
#include <linux/major.h>
#include <asm/io.h>
#include <asm/system.h>
+#include <asm/byteorder.h>
#include <pcmcia/version.h>
#include <pcmcia/cs_types.h>
@@ -53,30 +54,32 @@
#include <pcmcia/ds.h>
#include <pcmcia/cisreg.h>
-#ifdef PCMCIA_DEBUG
-static int pc_debug = PCMCIA_DEBUG;
-MODULE_PARM(pc_debug, "i");
-#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
-static char *version =
-"serial_cs.c 1.123 2000/08/24 18:46:38 (David Hinds)";
-#else
-#define DEBUG(n, args...)
-#endif
-
/*====================================================================*/
-/* Parameters that can be set with 'insmod' */
+/* Module parameters */
+
+MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
+MODULE_DESCRIPTION("PCMCIA serial card driver");
+MODULE_LICENSE("Dual MPL/GPL");
+
+#define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
/* Bit map of interrupts to choose from */
-static u_int irq_mask = 0xdeb8;
+INT_MODULE_PARM(irq_mask, 0xdeb8);
static int irq_list[4] = { -1 };
+MODULE_PARM(irq_list, "1-4i");
/* Enable the speaker? */
-static int do_sound = 1;
+INT_MODULE_PARM(do_sound, 1);
-MODULE_PARM(irq_mask, "i");
-MODULE_PARM(irq_list, "1-4i");
-MODULE_PARM(do_sound, "i");
+#ifdef PCMCIA_DEBUG
+INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);
+#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
+static char *version =
+"serial_cs.c 1.128 2001/10/18 12:18:35 (David Hinds)";
+#else
+#define DEBUG(n, args...)
+#endif
/*====================================================================*/
@@ -93,6 +96,8 @@ static multi_id_t multi_id[] = {
{ MANFID_QUATECH, PRODID_QUATECH_DUAL_RS232, 2 },
{ MANFID_QUATECH, PRODID_QUATECH_DUAL_RS232_D1, 2 },
{ MANFID_QUATECH, PRODID_QUATECH_QUAD_RS232, 4 },
+ { MANFID_QUATECH, PRODID_QUATECH_DUAL_RS422, 2 },
+ { MANFID_QUATECH, PRODID_QUATECH_QUAD_RS422, 4 },
{ MANFID_SOCKET, PRODID_SOCKET_DUAL_RS232, 2 },
{ MANFID_INTEL, PRODID_INTEL_DUAL_RS232, 2 },
{ MANFID_NATINST, PRODID_NATINST_QUAD_RS232, 4 }
@@ -357,7 +362,6 @@ static int simple_config(dev_link_t *link)
found_port:
if (i != CS_SUCCESS) {
- printk(KERN_NOTICE "serial_cs: no usable port range found, giving up\n");
cs_error(link->handle, RequestIO, i);
return -1;
}
@@ -437,7 +441,6 @@ static int multi_config(dev_link_t *link)
i = CardServices(RequestIRQ, link->handle, &link->irq);
if (i != CS_SUCCESS) {
- printk(KERN_NOTICE "serial_cs: no usable port range found, giving up\n");
cs_error(link->handle, RequestIRQ, i);
link->irq.AssignedIRQ = 0;
}
@@ -663,5 +666,3 @@ static void __exit exit_serial_cs(void)
module_init(init_serial_cs);
module_exit(exit_serial_cs);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/char/serial.c b/drivers/char/serial.c
index dff867aae..d680bfd72 100644
--- a/drivers/char/serial.c
+++ b/drivers/char/serial.c
@@ -3133,6 +3133,10 @@ static int get_async_struct(int line, struct async_struct **ret_info)
* enables interrupts for a serial port, linking in its async structure into
* the IRQ chain. It also performs the serial-specific
* initialization for the tty structure.
+ *
+ * Note that on failure, we don't decrement the module use count - the tty
+ * later will call rs_close, which will decrement it for us as long as
+ * tty->driver_data is set non-NULL. --rmk
*/
static int rs_open(struct tty_struct *tty, struct file * filp)
{
@@ -3153,10 +3157,8 @@ static int rs_open(struct tty_struct *tty, struct file * filp)
}
tty->driver_data = info;
info->tty = tty;
- if (serial_paranoia_check(info, tty->device, "rs_open")) {
- MOD_DEC_USE_COUNT;
+ if (serial_paranoia_check(info, tty->device, "rs_open"))
return -ENODEV;
- }
#ifdef SERIAL_DEBUG_OPEN
printk("rs_open %s%d, count = %d\n", tty->driver.name, info->line,
@@ -3171,10 +3173,8 @@ static int rs_open(struct tty_struct *tty, struct file * filp)
*/
if (!tmp_buf) {
page = get_zeroed_page(GFP_KERNEL);
- if (!page) {
- MOD_DEC_USE_COUNT;
+ if (!page)
return -ENOMEM;
- }
if (tmp_buf)
free_page(page);
else
@@ -3188,7 +3188,6 @@ static int rs_open(struct tty_struct *tty, struct file * filp)
(info->flags & ASYNC_CLOSING)) {
if (info->flags & ASYNC_CLOSING)
interruptible_sleep_on(&info->close_wait);
- MOD_DEC_USE_COUNT;
#ifdef SERIAL_DO_RESTART
return ((info->flags & ASYNC_HUP_NOTIFY) ?
-EAGAIN : -ERESTARTSYS);
@@ -3201,10 +3200,8 @@ static int rs_open(struct tty_struct *tty, struct file * filp)
* Start up serial port
*/
retval = startup(info);
- if (retval) {
- MOD_DEC_USE_COUNT;
+ if (retval)
return retval;
- }
retval = block_til_ready(tty, filp, info);
if (retval) {
@@ -3212,7 +3209,6 @@ static int rs_open(struct tty_struct *tty, struct file * filp)
printk("rs_open returning after block_til_ready with %d\n",
retval);
#endif
- MOD_DEC_USE_COUNT;
return retval;
}
diff --git a/drivers/ieee1394/hosts.c b/drivers/ieee1394/hosts.c
index 01019edda..f33d5dfd8 100644
--- a/drivers/ieee1394/hosts.c
+++ b/drivers/ieee1394/hosts.c
@@ -170,11 +170,11 @@ static void shutdown_hosts(struct hpsb_host_template *tmpl)
list_for_each(hlh, &tmpl->hosts) {
host = list_entry(hlh, struct hpsb_host, list);
if (host->initialized) {
+ highlevel_remove_host(host);
+
host->initialized = 0;
abort_requests(host);
- highlevel_remove_host(host);
-
tmpl->release_host(host);
while (test_bit(0, &host->timeout_tq.sync)) {
schedule();
diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c
index 95ec4af66..a642b2468 100644
--- a/drivers/ieee1394/ieee1394_core.c
+++ b/drivers/ieee1394/ieee1394_core.c
@@ -318,7 +318,7 @@ void hpsb_selfid_received(struct hpsb_host *host, quadlet_t sid)
void hpsb_selfid_complete(struct hpsb_host *host, int phyid, int isroot)
{
- host->node_id = 0xffc0 | phyid;
+ host->node_id = LOCAL_BUS | phyid;
host->in_bus_reset = 0;
host->is_root = isroot;
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
index d32219154..d9b293e7d 100644
--- a/drivers/ieee1394/nodemgr.c
+++ b/drivers/ieee1394/nodemgr.c
@@ -359,7 +359,7 @@ static void nodemgr_call_policy(char *verb, struct unit_directory *ud)
kfree(buf);
kfree(envp);
if (value != 0)
- HPSB_DEBUG("NodeMgr: hotplug policy returned 0x%x", value);
+ HPSB_DEBUG("NodeMgr: hotplug policy returned %d", value);
}
#else
@@ -369,9 +369,8 @@ nodemgr_call_policy(char *verb, struct unit_directory *ud)
{
#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
HPSB_DEBUG("NodeMgr: nodemgr_call_policy(): hotplug not enabled");
-#else
- return;
#endif
+ return;
}
#endif /* CONFIG_HOTPLUG */
@@ -582,13 +581,13 @@ static void nodemgr_update_node(struct node_entry *ne, quadlet_t busoptions,
struct hpsb_host *host, nodeid_t nodeid)
{
struct list_head *lh;
+ struct unit_directory *ud;
- if (ne->nodeid != nodeid)
+ if (ne->nodeid != nodeid) {
HPSB_DEBUG("Node " NODE_BUS_FMT " changed to " NODE_BUS_FMT,
NODE_BUS_ARGS(ne->nodeid), NODE_BUS_ARGS(nodeid));
-
- ne->host = host;
- ne->nodeid = nodeid;
+ ne->nodeid = nodeid;
+ }
if (ne->busopt.generation != ((busoptions >> 4) & 0xf))
nodemgr_process_config_rom (ne, busoptions);
@@ -597,8 +596,6 @@ static void nodemgr_update_node(struct node_entry *ne, quadlet_t busoptions,
atomic_set(&ne->generation, get_hpsb_generation(ne->host));
list_for_each (lh, &ne->unit_directories) {
- struct unit_directory *ud;
-
ud = list_entry (lh, struct unit_directory, node_list);
if (ud->driver != NULL && ud->driver->update != NULL)
ud->driver->update(ud);
@@ -679,57 +676,76 @@ static void nodemgr_remove_node(struct node_entry *ne)
return;
}
+/* Used to schedule each nodes config rom probe */
+struct node_probe_task {
+ nodeid_t nodeid;
+ struct hpsb_host *host;
+ atomic_t *count;
+ struct tq_struct task;
+};
+
/* This is where we probe the nodes for their information and provided
* features. */
-static void nodemgr_node_probe(void *data)
+static void nodemgr_node_probe_one(void *__npt)
{
- struct hpsb_host *host = (struct hpsb_host *)data;
- struct selfid *sid = (struct selfid *)host->topology_map;
- struct list_head *lh, *next;
+ struct node_probe_task *npt = (struct node_probe_task *)__npt;
struct node_entry *ne;
- int nodecount = host->node_count;
- nodeid_t nodeid = LOCAL_BUS;
quadlet_t buffer[5];
octlet_t guid;
- unsigned long flags;
/* We need to detect when the ConfigROM's generation has changed,
* so we only update the node's info when it needs to be. */
- for (; nodecount; nodecount--, nodeid++, sid++) {
- /* Skip extended, and non-active node's */
- while (sid->extended)
- sid++;
- if (!sid->link_active)
- continue;
- if (read_businfo_block (host, nodeid, buffer, sizeof(buffer) >> 2))
- continue;
+ if (read_businfo_block (npt->host, npt->nodeid, buffer, sizeof(buffer) >> 2))
+ goto probe_complete;
- if (buffer[1] != IEEE1394_BUSID_MAGIC) {
- /* This isn't a 1394 device */
- HPSB_ERR("Node " NODE_BUS_FMT " isn't an IEEE 1394 device",
- NODE_BUS_ARGS(nodeid));
- continue;
- }
+ if (buffer[1] != IEEE1394_BUSID_MAGIC) {
+ /* This isn't a 1394 device */
+ HPSB_ERR("Node " NODE_BUS_FMT " isn't an IEEE 1394 device",
+ NODE_BUS_ARGS(npt->nodeid));
+ goto probe_complete;
+ }
- guid = ((u64)buffer[3] << 32) | buffer[4];
- ne = hpsb_guid_get_entry(guid);
+ guid = ((u64)buffer[3] << 32) | buffer[4];
+ ne = hpsb_guid_get_entry(guid);
- if (!ne)
- nodemgr_create_node(guid, buffer[2], host, nodeid);
- else
- nodemgr_update_node(ne, buffer[2], host, nodeid);
- }
+ if (!ne)
+ nodemgr_create_node(guid, buffer[2], npt->host, npt->nodeid);
+ else
+ nodemgr_update_node(ne, buffer[2], npt->host, npt->nodeid);
+
+probe_complete:
+ atomic_dec(npt->count);
+
+ kfree(npt);
+
+ return;
+}
+
+static void nodemgr_node_probe_cleanup(void *__npt)
+{
+ struct node_probe_task *npt = (struct node_probe_task *)__npt;
+ unsigned long flags;
+ struct list_head *lh, *next;
+ struct node_entry *ne;
+
+ /* If things aren't done yet, reschedule ourselves. */
+ if (atomic_read(npt->count)) {
+ schedule_task(&npt->task);
+ return;
+ }
+
+ kfree(npt->count);
/* Now check to see if we have any nodes that aren't referenced
* any longer. */
- write_lock_irqsave(&node_lock, flags);
+ write_lock_irqsave(&node_lock, flags);
for (lh = node_list.next; lh != &node_list; lh = next) {
ne = list_entry(lh, struct node_entry, list);
next = lh->next;
/* Only checking this host */
- if (ne->host != host)
+ if (ne->host != npt->host)
continue;
/* If the generation didn't get updated, then either the
@@ -741,9 +757,70 @@ static void nodemgr_node_probe(void *data)
}
write_unlock_irqrestore(&node_lock, flags);
+ kfree(npt);
+
return;
}
+static void nodemgr_node_probe(void *__host)
+{
+ struct hpsb_host *host = (struct hpsb_host *)__host;
+ int nodecount = host->node_count;
+ struct selfid *sid = (struct selfid *)host->topology_map;
+ nodeid_t nodeid = LOCAL_BUS;
+ struct node_probe_task *npt;
+ atomic_t *count;
+
+ count = kmalloc(sizeof (*count), GFP_KERNEL);
+
+ if (count == NULL) {
+ HPSB_ERR ("NodeMgr: out of memory in nodemgr_node_probe");
+ return;
+ }
+
+ atomic_set(count, 0);
+
+ for (; nodecount; nodecount--, nodeid++, sid++) {
+ while (sid->extended)
+ sid++;
+ if (!sid->link_active || nodeid == host->node_id)
+ continue;
+
+ npt = kmalloc(sizeof (*npt), GFP_KERNEL);
+
+ if (npt == NULL) {
+ HPSB_ERR ("NodeMgr: out of memory in nodemgr_node_probe");
+ break;
+ }
+
+ INIT_TQUEUE(&npt->task, nodemgr_node_probe_one, npt);
+ npt->host = host;
+ npt->nodeid = nodeid;
+ npt->count = count;
+
+ atomic_inc(count);
+
+ schedule_task(&npt->task);
+ }
+
+ /* Now schedule a task to clean things up after the node probes
+ * are done. */
+ npt = kmalloc (sizeof (*npt), GFP_KERNEL);
+
+ if (npt == NULL) {
+ HPSB_ERR ("NodeMgr: out of memory in nodemgr_node_probe");
+ return;
+ }
+
+ INIT_TQUEUE(&npt->task, nodemgr_node_probe_cleanup, npt);
+ npt->host = host;
+ npt->nodeid = 0;
+ npt->count = count;
+
+ schedule_task(&npt->task);
+
+ return;
+}
struct node_entry *hpsb_guid_get_entry(u64 guid)
{
@@ -864,7 +941,7 @@ static void nodemgr_remove_host(struct hpsb_host *host)
write_unlock_irqrestore(&node_lock, flags);
spin_lock_irqsave (&host_info_lock, flags);
- list_for_each(lh, &host_info_list) {
+ list_for_each_safe(lh, next, &host_info_list) {
struct host_info *hi = list_entry(lh, struct host_info, list);
if (hi->host == host) {
list_del(&hi->list);
diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c
index 88c9e4bd9..94200f895 100644
--- a/drivers/ieee1394/ohci1394.c
+++ b/drivers/ieee1394/ohci1394.c
@@ -106,16 +106,12 @@
#include <linux/init.h>
#ifdef CONFIG_ALL_PPC
-#include <asm/feature.h>
+#include <asm/machdep.h>
+#include <asm/pmac_feature.h>
#include <asm/prom.h>
#include <asm/pci-bridge.h>
#endif
-/* Revert to old bus reset algorithm that works on my Pismo until
- * the new one is fixed
- */
-#undef BUSRESET_WORKAROUND
-
#include "ieee1394.h"
#include "ieee1394_types.h"
#include "hosts.h"
@@ -175,7 +171,7 @@ static struct pci_device_id ohci1394_pci_tbl[] __devinitdata = {
MODULE_DEVICE_TABLE(pci, ohci1394_pci_tbl);
static char version[] __devinitdata =
- "v0.51 08/08/01 Ben Collins <bcollins@debian.org>";
+ "$Revision: 1.80 $ Ben Collins <bcollins@debian.org>";
/* Module Parameters */
MODULE_PARM(attempt_root,"i");
@@ -516,12 +512,9 @@ static int ohci_initialize(struct hpsb_host *host)
/* After enabling LPS, we need to wait for the connection
* between phy and link to be established. This should be
* signaled by the LPS bit becoming 1, but this happens
- * immediately. Instead we wait for reads from LinkControl to
- * give a valid result, i.e. not 0xffffffff. */
- while (reg_read(ohci, OHCI1394_LinkControlSet) == 0xffffffff) {
- DBGMSG(ohci->id, "waiting for phy-link connection");
- mdelay(2);
- }
+ * immediately. There seems to be no consistent way to wait
+ * for this, but 50ms seems to be enough. */
+ mdelay(50);
/* Set the bus number */
reg_write(ohci, OHCI1394_NodeID, 0x0000ffc0);
@@ -1131,11 +1124,7 @@ static void ohci_irq_handler(int irq, void *dev_id,
* selfIDComplete interrupt. */
spin_lock_irqsave(&ohci->event_lock, flags);
event = reg_read(ohci, OHCI1394_IntEventClear);
-#ifdef BUSRESET_WORKAROUND
- reg_write(ohci, OHCI1394_IntEventClear, event);
-#else
reg_write(ohci, OHCI1394_IntEventClear, event & ~OHCI1394_busReset);
-#endif
spin_unlock_irqrestore(&ohci->event_lock, flags);
if (!event) return;
@@ -1154,11 +1143,17 @@ static void ohci_irq_handler(int irq, void *dev_id,
* selfID phase, so we disable busReset interrupts, to
* avoid burying the cpu in interrupt requests. */
spin_lock_irqsave(&ohci->event_lock, flags);
-#ifdef BUSRESET_WORKAROUND
- reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_busReset);
-#else
reg_write(ohci, OHCI1394_IntMaskClear, OHCI1394_busReset);
-#endif
+ if (ohci->dev->vendor == PCI_VENDOR_ID_APPLE &&
+ ohci->dev->device == PCI_DEVICE_ID_APPLE_UNI_N_FW) {
+ udelay(10);
+ while(reg_read(ohci, OHCI1394_IntEventSet) & OHCI1394_busReset) {
+ reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_busReset);
+ spin_unlock_irqrestore(&ohci->event_lock, flags);
+ udelay(10);
+ spin_lock_irqsave(&ohci->event_lock, flags);
+ }
+ }
spin_unlock_irqrestore(&ohci->event_lock, flags);
if (!host->in_bus_reset) {
DBGMSG(ohci->id, "irq_handler: Bus reset requested%s",
@@ -1309,12 +1304,10 @@ static void ohci_irq_handler(int irq, void *dev_id,
/* Finally, we clear the busReset event and reenable
* the busReset interrupt. */
-#ifndef BUSRESET_WORKAROUND
spin_lock_irqsave(&ohci->event_lock, flags);
reg_write(ohci, OHCI1394_IntMaskSet, OHCI1394_busReset);
reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_busReset);
spin_unlock_irqrestore(&ohci->event_lock, flags);
-#endif
event &= ~OHCI1394_selfIDComplete;
}
@@ -1966,8 +1959,6 @@ static void ohci_init_config_rom(struct ti_ohci *ohci)
cf_put_keyval(&cr, 0x03, 0x00005e); /* Vendor ID */
cf_put_refer(&cr, 0x81, 2); /* Textual description unit */
cf_put_keyval(&cr, 0x0c, 0x0083c0); /* Node capabilities */
- cf_put_refer(&cr, 0xd1, 3); /* IPv4 unit directory */
- cf_put_refer(&cr, 0xd1, 4); /* IPv6 unit directory */
/* NOTE: Add other unit referers here, and append at bottom */
cf_unit_end(&cr);
@@ -1980,46 +1971,6 @@ static void ohci_init_config_rom(struct ti_ohci *ohci)
cf_put_4bytes(&cr, '9', '4', 0x0, 0x0);
cf_unit_end(&cr);
- /* IPv4 unit directory, RFC 2734 */
- cf_unit_begin(&cr, 3);
- cf_put_keyval(&cr, 0x12, 0x00005e); /* Unit spec ID */
- cf_put_refer(&cr, 0x81, 6); /* Textual description unit */
- cf_put_keyval(&cr, 0x13, 0x000001); /* Unit software version */
- cf_put_refer(&cr, 0x81, 7); /* Textual description unit */
- cf_unit_end(&cr);
-
- cf_unit_begin(&cr, 6);
- cf_put_keyval(&cr, 0, 0);
- cf_put_1quad(&cr, 0);
- cf_put_4bytes(&cr, 'I', 'A', 'N', 'A');
- cf_unit_end(&cr);
-
- cf_unit_begin(&cr, 7);
- cf_put_keyval(&cr, 0, 0);
- cf_put_1quad(&cr, 0);
- cf_put_4bytes(&cr, 'I', 'P', 'v', '4');
- cf_unit_end(&cr);
-
- /* IPv6 unit directory, draft-ietf-ipngwg-1394-01.txt */
- cf_unit_begin(&cr, 4);
- cf_put_keyval(&cr, 0x12, 0x00005e); /* Unit spec ID */
- cf_put_refer(&cr, 0x81, 8); /* Textual description unit */
- cf_put_keyval(&cr, 0x13, 0x000002); /* (Proposed) Unit software version */
- cf_put_refer(&cr, 0x81, 9); /* Textual description unit */
- cf_unit_end(&cr);
-
- cf_unit_begin(&cr, 8);
- cf_put_keyval(&cr, 0, 0);
- cf_put_1quad(&cr, 0);
- cf_put_4bytes(&cr, 'I', 'A', 'N', 'A');
- cf_unit_end(&cr);
-
- cf_unit_begin(&cr, 9);
- cf_put_keyval(&cr, 0, 0);
- cf_put_1quad(&cr, 0);
- cf_put_4bytes(&cr, 'I', 'P', 'v', '6');
- cf_unit_end(&cr);
-
ohci->csr_config_rom_length = cr.data - ohci->csr_config_rom_cpu;
}
@@ -2309,8 +2260,8 @@ static void remove_card(struct ti_ohci *ohci)
of_node = pci_device_to_OF_node(ohci->dev);
if (of_node) {
- feature_set_firewire_power(of_node, 0);
- feature_set_firewire_cable_power(of_node, 0);
+ pmac_call_feature(PMAC_FTR_1394_ENABLE, of_node, 0, 0);
+ pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, of_node, 0, 0);
}
}
#endif /* CONFIG_ALL_PPC */
diff --git a/drivers/ieee1394/pcilynx.c b/drivers/ieee1394/pcilynx.c
index 1038837ca..815176c8f 100644
--- a/drivers/ieee1394/pcilynx.c
+++ b/drivers/ieee1394/pcilynx.c
@@ -1637,8 +1637,8 @@ MODULE_DEVICE_TABLE(pci, pci_table);
static void __exit pcilynx_cleanup(void)
{
- pci_unregister_driver(&lynx_pcidriver);
hpsb_unregister_lowlevel(&lynx_template);
+ pci_unregister_driver(&lynx_pcidriver);
PRINT_G(KERN_INFO, "removed " PCILYNX_DRIVER_NAME " module");
}
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
index 888e918e5..fe95a129e 100644
--- a/drivers/ieee1394/sbp2.c
+++ b/drivers/ieee1394/sbp2.c
@@ -222,8 +222,25 @@
* when we register our driver. This change
* automtically adds hotplug support to the driver.
* Kristian Hogsberg <hogsberg@users.sf.net>
+ *
+ * 11/17/01 - Various bugfixes/cleanups:
+ * * Remember to logout of device in sbp2_disconnect.
+ * * If we fail to reconnect to a device after bus reset
+ * remember to release unit directory, so the ieee1394
+ * knows we no longer manage it.
+ * * Unregister scsi hosts in sbp2_remove_host when a
+ * hpsb_host goes away.
+ * * Remove stupid hack in sbp2_remove_host.
+ * * Switched to "manual" module initialization
+ * (i.e. not scsi_module.c) and moved sbp2_cleanup
+ * moved sbp2scsi_release to sbp2_module_ext. The
+ * release function is called once pr. registered
+ * scsi host, but sbp2_cleanup should only be called
+ * upon module unload. Moved much initialization
+ * from sbp2scsi_detect to sbp2_module_init.
+ * Kristian Hogsberg <hogsberg@users.sf.net>
*/
-
+
/*
@@ -244,6 +261,7 @@
#include <linux/proc_fs.h>
#include <linux/blk.h>
#include <linux/smp_lock.h>
+#include <linux/init.h>
#include <asm/current.h>
#include <asm/uaccess.h>
#include <asm/io.h>
@@ -395,7 +413,7 @@ static spinlock_t sbp2_host_info_lock = SPIN_LOCK_UNLOCKED;
* Globals
*/
-Scsi_Host_Template *global_scsi_tpnt = NULL;
+static Scsi_Host_Template scsi_driver_template;
static u8 sbp2_speedto_maxrec[] = { 0x7, 0x8, 0x9 };
@@ -671,13 +689,13 @@ static int sbp2util_create_command_orb_pool(struct scsi_id_instance_data *scsi_i
static void sbp2util_remove_command_orb_pool(struct scsi_id_instance_data *scsi_id,
struct sbp2scsi_host_info *hi)
{
- struct list_head *lh;
+ struct list_head *lh, *next;
struct sbp2_command_info *command;
unsigned long flags;
sbp2_spin_lock(&scsi_id->sbp2_command_orb_lock, flags);
if (!list_empty(&scsi_id->sbp2_command_orb_completed)) {
- list_for_each(lh, &scsi_id->sbp2_command_orb_completed) {
+ list_for_each_safe(lh, next, &scsi_id->sbp2_command_orb_completed) {
command = list_entry(lh, struct sbp2_command_info, list);
/* Release our generic DMA's */
@@ -868,7 +886,6 @@ void sbp2_cleanup(void)
hpsb_unregister_highlevel(sbp2_hl_handle);
sbp2_hl_handle = NULL;
}
- return;
}
static int sbp2_probe(struct unit_directory *ud)
@@ -889,8 +906,10 @@ static void sbp2_disconnect(struct unit_directory *ud)
SBP2_DEBUG("sbp2_disconnect");
hi = sbp2_find_host_info(ud->ne->host);
- if (hi != NULL)
- sbp2_remove_device(hi, scsi_id);
+ if (hi != NULL) {
+ sbp2_logout_device(hi, scsi_id);
+ sbp2_remove_device(hi, scsi_id);
+ }
}
static void sbp2_update(struct unit_directory *ud)
@@ -909,12 +928,10 @@ static void sbp2_update(struct unit_directory *ud)
*/
if (sbp2_login_device(hi, scsi_id)) {
- /* Login failed too... so, just mark him as
- * unvalidated, so that he gets cleaned up
- * later.
- */
+ /* Login failed too, just remove the device. */
SBP2_ERR("sbp2_reconnect_device failed!");
sbp2_remove_device(hi, scsi_id);
+ hpsb_release_unit_directory(ud);
return;
}
}
@@ -978,7 +995,10 @@ static void sbp2_add_host(struct hpsb_host *host)
sbp2_spin_unlock(&sbp2_host_info_lock, flags);
/* Register our host with the SCSI stack. */
- sbp2scsi_register_scsi_host(hi);
+ hi->scsi_host = scsi_register (&scsi_driver_template, sizeof(void *));
+ if (hi->scsi_host)
+ hi->scsi_host->hostdata[0] = (unsigned long)hi;
+ scsi_driver_template.present++;
return;
}
@@ -1003,13 +1023,12 @@ static struct sbp2scsi_host_info *sbp2_find_host_info(struct hpsb_host *host)
}
/*
- * This function is called when the host is removed
+ * This function is called when a host is removed.
*/
static void sbp2_remove_host(struct hpsb_host *host)
{
struct sbp2scsi_host_info *hi;
unsigned long flags;
- int i;
SBP2_DEBUG("sbp2_remove_host");
@@ -1017,22 +1036,11 @@ static void sbp2_remove_host(struct hpsb_host *host)
hi = sbp2_find_host_info(host);
if (hi != NULL) {
- /* Here's an annoying hack: we get a disconnect
- * callback for each device, so this loop shouldn't be
- * necessary. However, the sbp2 driver receives the
- * remove_host callback before the nodemgr, so when we
- * get the disconnect callback, we've already freed
- * the host. Thus, we free the devices here...
- */
- for (i = 0; i < SBP2SCSI_MAX_SCSI_IDS; i++) {
- if (hi->scsi_id[i] != NULL) {
- sbp2_logout_device(hi, hi->scsi_id[i]);
- sbp2_remove_device(hi, hi->scsi_id[i]);
- }
- }
sbp2util_remove_request_packet_pool(hi);
sbp2_host_count--;
list_del(&hi->list);
+ scsi_unregister(hi->scsi_host);
+ scsi_driver_template.present--;
kfree(hi);
}
else
@@ -1203,10 +1211,7 @@ alloc_fail_first:
*/
if (sbp2_login_device(hi, scsi_id)) {
- /*
- * Login failed... so, just mark him as unvalidated, so
- * that he gets cleaned up later.
- */
+ /* Login failed, just remove the device. */
SBP2_ERR("sbp2_login_device failed");
sbp2_remove_device(hi, scsi_id);
return -EBUSY;
@@ -1231,11 +1236,13 @@ alloc_fail_first:
}
/*
- * This function removes (cleans-up after) any unvalidated sbp2 devices
+ * This function removes an sbp2 device from the sbp2scsi_host_info struct.
*/
static void sbp2_remove_device(struct sbp2scsi_host_info *hi,
struct scsi_id_instance_data *scsi_id)
{
+ SBP2_DEBUG("sbp2_remove_device");
+
/* Complete any pending commands with selection timeout */
sbp2scsi_complete_all_commands(hi, scsi_id, DID_NO_CONNECT);
@@ -1276,8 +1283,7 @@ static void sbp2_remove_device(struct sbp2scsi_host_info *hi,
SBP2_DMA_FREE("single logout orb");
}
- SBP2_DEBUG("Unvalidated SBP-2 device removed, SCSI ID = %d",
- scsi_id->id);
+ SBP2_DEBUG("SBP-2 device removed, SCSI ID = %d", scsi_id->id);
hi->scsi_id[scsi_id->id] = NULL;
kfree(scsi_id);
}
@@ -1381,7 +1387,7 @@ static int sbp2_login_device(struct sbp2scsi_host_info *hi, struct scsi_id_insta
/*
* Check status
- */
+ */
if (STATUS_GET_RESP(scsi_id->status_block.ORB_offset_hi_misc) ||
STATUS_GET_DEAD_BIT(scsi_id->status_block.ORB_offset_hi_misc) ||
STATUS_GET_SBP_STATUS(scsi_id->status_block.ORB_offset_hi_misc)) {
@@ -1687,9 +1693,9 @@ static int sbp2_max_speed_and_size(struct sbp2scsi_host_info *hi, struct scsi_id
scsi_id->max_payload_size = min(sbp2_speedto_maxrec[scsi_id->speed_code],
(u8)(((be32_to_cpu(hi->host->csr.rom[2]) >> 12) & 0xf) - 1));
- SBP2_ERR("Node " NODE_BUS_FMT ": Max speed [%s] - Max payload [0x%02x/%u]",
+ SBP2_ERR("Node " NODE_BUS_FMT ": Max speed [%s] - Max payload [%u]",
NODE_BUS_ARGS(scsi_id->ne->nodeid), hpsb_speedto_str[scsi_id->speed_code],
- scsi_id->max_payload_size, 1 << ((u32)scsi_id->max_payload_size + 2));
+ 1 << ((u32)scsi_id->max_payload_size + 2));
return(0);
}
@@ -2860,127 +2866,111 @@ static int sbp2scsi_biosparam (Scsi_Disk *disk, kdev_t dev, int geom[])
return(0);
}
-/*
- * This routine is called at setup (init) and does nothing. Not used here. =)
- */
-void sbp2scsi_setup( char *str, int *ints)
-{
- SBP2_DEBUG("sbp2scsi_setup");
- return;
-}
-
-/*
- * This is our detection routine, and is where we init everything.
- */
static int sbp2scsi_detect (Scsi_Host_Template *tpnt)
{
SBP2_DEBUG("sbp2scsi_detect");
- global_scsi_tpnt = tpnt;
+ /*
+ * Call sbp2_init to register with the ieee1394 stack. This
+ * results in a callback to sbp2_add_host for each ieee1394
+ * host controller currently registered, and for each of those
+ * we register a scsi host with the scsi stack.
+ */
+ sbp2_init();
+
+ /* We return the number of hosts registered. */
+ return sbp2_host_count;
+}
+
+MODULE_AUTHOR("James Goodwin <jamesg@filanet.com>");
+MODULE_DESCRIPTION("IEEE-1394 SBP-2 protocol driver");
+MODULE_SUPPORTED_DEVICE(SBP2_DEVICE_NAME);
+MODULE_LICENSE("GPL");
+
+/* SCSI host template */
+static Scsi_Host_Template scsi_driver_template = {
+ name: "IEEE-1394 SBP-2 protocol driver",
+ detect: sbp2scsi_detect,
+ queuecommand: sbp2scsi_queuecommand,
+ abort: sbp2scsi_abort,
+ reset: sbp2scsi_reset,
+ bios_param: sbp2scsi_biosparam,
+ can_queue: SBP2SCSI_MAX_OUTSTANDING_CMDS,
+ this_id: -1,
+ sg_tablesize: SBP2_MAX_SG_ELEMENTS,
+ cmd_per_lun: SBP2SCSI_MAX_CMDS_PER_LUN,
+ use_clustering: SBP2_CLUSTERING,
+ emulated: 1,
+
+ module: THIS_MODULE,
+
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,26)
- global_scsi_tpnt->proc_name = SBP2_DEVICE_NAME;
+ proc_name: SBP2_DEVICE_NAME
#endif
+};
+
+static int sbp2_module_init(void)
+{
+ SBP2_DEBUG("sbp2_module_init");
+
/*
* Module load option for force one command at a time
*/
if (serialize_io) {
SBP2_ERR("Driver forced to serialize I/O (serialize_io = 1)");
- global_scsi_tpnt->can_queue = 1;
- global_scsi_tpnt->cmd_per_lun = 1;
+ scsi_driver_template.can_queue = 1;
+ scsi_driver_template.cmd_per_lun = 1;
}
/*
- * Module load option to limit max size of requests from the scsi drivers
+ * Module load option to limit max size of requests from the
+ * scsi drivers
*/
if (no_large_packets) {
- SBP2_ERR("Driver forced to limit max transfer size (no_large_packets = 1)");
- global_scsi_tpnt->sg_tablesize = 0x1f;
- global_scsi_tpnt->use_clustering = DISABLE_CLUSTERING;
+ SBP2_ERR("Driver forced to limit max transfer size "
+ "(no_large_packets = 1)");
+ scsi_driver_template.sg_tablesize = 0x1f;
+ scsi_driver_template.use_clustering = DISABLE_CLUSTERING;
}
if (mode_sense_hack) {
SBP2_ERR("Mode sense emulation enabled (mode_sense_hack = 1)");
}
- sbp2_init();
-
- if (!sbp2_host_count) {
- SBP2_ERR("Please load the lower level IEEE-1394 driver (e.g. ohci1394) before sbp2...");
+ /*
+ * Ideally we would register our scsi_driver_template with the
+ * scsi stack and after that register with the ieee1394 stack
+ * and process the add_host callbacks. However, the detect
+ * function in the scsi host template requires that we find at
+ * least one host, so we "nest" the registrations by calling
+ * sbp2_init from the detect function.
+ */
+ if (scsi_register_module(MODULE_SCSI_HA, &scsi_driver_template) ||
+ !scsi_driver_template.present) {
+ SBP2_ERR("Please load the lower level IEEE-1394 driver "
+ "(e.g. ohci1394) before sbp2...");
sbp2_cleanup();
+ return -ENODEV;
}
- /*
- * Since we are returning this count, it means that sbp2 must be
- * loaded "after" the host adapter module...
- */
- return(sbp2_host_count);
+ return 0;
}
-/*
- * This function is called from sbp2_add_host, and is where we register
- * our scsi host
- */
-static void sbp2scsi_register_scsi_host(struct sbp2scsi_host_info *hi)
+static void __exit sbp2_module_exit(void)
{
- struct Scsi_Host *shpnt = NULL;
-
- SBP2_DEBUG("sbp2scsi_register_scsi_host");
- SBP2_DEBUG("sbp2scsi_host_info = %p", hi);
+ SBP2_DEBUG("sbp2_module_exit");
/*
- * Let's register with the scsi stack
+ * On module unload we unregister with the ieee1394 stack
+ * which results in remove_host callbacks for all ieee1394
+ * host controllers. In the callbacks we unregister the
+ * corresponding scsi hosts.
*/
- if (global_scsi_tpnt) {
-
- shpnt = scsi_register (global_scsi_tpnt, sizeof(void *));
-
- /*
- * If successful, save off a context (to be used when SCSI
- * commands are received)
- */
- if (shpnt) {
- shpnt->hostdata[0] = (unsigned long)hi;
- }
- }
-
- return;
-}
-
-/* Called when our module is released */
-static int sbp2scsi_release(struct Scsi_Host *host)
-{
- SBP2_DEBUG("sbp2scsi_release");
sbp2_cleanup();
- return(0);
-}
-/* Called for contents of procfs */
-static const char *sbp2scsi_info (struct Scsi_Host *host)
-{
- return "IEEE-1394 SBP-2 protocol driver";
+ if (scsi_unregister_module(MODULE_SCSI_HA, &scsi_driver_template))
+ SBP2_ERR("sbp2_module_exit: couldn't unregister scsi driver");
}
-MODULE_AUTHOR("James Goodwin <jamesg@filanet.com>");
-MODULE_DESCRIPTION("IEEE-1394 SBP-2 protocol driver");
-MODULE_SUPPORTED_DEVICE(SBP2_DEVICE_NAME);
-MODULE_LICENSE("GPL");
-
-/* SCSI host template */
-static Scsi_Host_Template driver_template = {
- name: "IEEE1394 SBP-2",
- detect: sbp2scsi_detect,
- release: sbp2scsi_release,
- info: sbp2scsi_info,
- queuecommand: sbp2scsi_queuecommand,
- abort: sbp2scsi_abort,
- reset: sbp2scsi_reset,
- bios_param: sbp2scsi_biosparam,
- can_queue: SBP2SCSI_MAX_OUTSTANDING_CMDS,
- this_id: -1,
- sg_tablesize: SBP2_MAX_SG_ELEMENTS,
- cmd_per_lun: SBP2SCSI_MAX_CMDS_PER_LUN,
- use_clustering: SBP2_CLUSTERING,
- emulated: 1
-};
-
-#include "../scsi/scsi_module.c"
+module_init(sbp2_module_init);
+module_exit(sbp2_module_exit);
diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h
index 505c65a75..2a4996ec0 100644
--- a/drivers/ieee1394/sbp2.h
+++ b/drivers/ieee1394/sbp2.h
@@ -403,6 +403,13 @@ struct sbp2scsi_host_info {
spinlock_t sbp2_request_packet_lock;
/*
+ * This is the scsi host we register with the scsi mid level.
+ * We keep a reference to it here, so we can unregister it
+ * when the hpsb_host is removed.
+ */
+ struct Scsi_Host *scsi_host;
+
+ /*
* Lists keeping track of inuse/free sbp2_request_packets. These structures are
* used for sending out sbp2 command and agent reset packets. We initially create
* a pool of request packets so that we don't have to do any kmallocs while in critical
@@ -498,7 +505,6 @@ static int sbp2_max_speed_and_size(struct sbp2scsi_host_info *hi, struct scsi_id
/*
* Scsi interface related prototypes
*/
-static const char *sbp2scsi_info (struct Scsi_Host *host);
static int sbp2scsi_detect (Scsi_Host_Template *tpnt);
void sbp2scsi_setup(char *str, int *ints);
static int sbp2scsi_biosparam (Scsi_Disk *disk, kdev_t dev, int geom[]);
@@ -509,6 +515,5 @@ static void sbp2scsi_complete_all_commands(struct sbp2scsi_host_info *hi, struct
u32 status);
static void sbp2scsi_complete_command(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id,
u32 scsi_status, Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *));
-static void sbp2scsi_register_scsi_host(struct sbp2scsi_host_info *hi);
#endif /* SBP2_H */
diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c
index d3df29b05..f104ac404 100644
--- a/drivers/ieee1394/video1394.c
+++ b/drivers/ieee1394/video1394.c
@@ -47,6 +47,8 @@
#include <linux/types.h>
#include <linux/wrapper.h>
#include <linux/vmalloc.h>
+#include <linux/timex.h>
+#include <linux/mm.h>
#include "ieee1394.h"
#include "ieee1394_types.h"
@@ -95,6 +97,7 @@ struct dma_iso_ctx {
struct dma_cmd **ir_prg;
struct it_dma_prg **it_prg;
unsigned int *buffer_status;
+ struct timeval *buffer_time; /* time when the buffer was received */
unsigned int *last_used_cmd; /* For ISO Transmit with
variable sized packets only ! */
int ctrlClear;
@@ -102,8 +105,8 @@ struct dma_iso_ctx {
int cmdPtr;
int ctxMatch;
wait_queue_head_t waitq;
- spinlock_t lock;
- unsigned int syt_offset;
+ spinlock_t lock;
+ unsigned int syt_offset;
int flags;
};
@@ -304,6 +307,8 @@ static int free_dma_iso_ctx(struct dma_iso_ctx **d)
if ((*d)->buffer_status)
kfree((*d)->buffer_status);
+ if ((*d)->buffer_time)
+ kfree((*d)->buffer_time);
if ((*d)->last_used_cmd)
kfree((*d)->last_used_cmd);
if ((*d)->next_buffer)
@@ -437,6 +442,8 @@ alloc_dma_iso_ctx(struct ti_ohci *ohci, int type, int ctx, int num_desc,
d->buffer_status = kmalloc(d->num_desc * sizeof(unsigned int),
GFP_KERNEL);
+ d->buffer_time = kmalloc(d->num_desc * sizeof(struct timeval),
+ GFP_KERNEL);
d->last_used_cmd = kmalloc(d->num_desc * sizeof(unsigned int),
GFP_KERNEL);
d->next_buffer = kmalloc(d->num_desc * sizeof(int),
@@ -447,6 +454,11 @@ alloc_dma_iso_ctx(struct ti_ohci *ohci, int type, int ctx, int num_desc,
free_dma_iso_ctx(&d);
return NULL;
}
+ if (d->buffer_time == NULL) {
+ PRINT(KERN_ERR, ohci->id, "Failed to allocate buffer_time");
+ free_dma_iso_ctx(&d);
+ return NULL;
+ }
if (d->last_used_cmd == NULL) {
PRINT(KERN_ERR, ohci->id, "Failed to allocate last_used_cmd");
free_dma_iso_ctx(&d);
@@ -458,6 +470,7 @@ alloc_dma_iso_ctx(struct ti_ohci *ohci, int type, int ctx, int num_desc,
return NULL;
}
memset(d->buffer_status, 0, d->num_desc * sizeof(unsigned int));
+ memset(d->buffer_time, 0, d->num_desc * sizeof(struct timeval));
memset(d->last_used_cmd, 0, d->num_desc * sizeof(unsigned int));
memset(d->next_buffer, -1, d->num_desc * sizeof(int));
@@ -604,6 +617,7 @@ int wakeup_dma_ir_ctx(struct ti_ohci *ohci, struct dma_iso_ctx *d)
if (d->ir_prg[i][d->nb_cmd-1].status & 0xFFFF0000) {
reset_ir_status(d, i);
d->buffer_status[i] = VIDEO1394_BUFFER_READY;
+ get_fast_time(&d->buffer_time[i]);
}
}
spin_unlock(&d->lock);
@@ -876,9 +890,23 @@ static int video1394_ioctl(struct inode *inode, struct file *file,
if(copy_from_user(&v, (void *)arg, sizeof(v)))
return -EFAULT;
+
+ /* if channel < 0, find lowest available one */
+ if (v.channel < 0) {
+ mask = (u64)0x1;
+ for (i=0; i<ISO_CHANNELS; i++) {
+ if (!(ohci->ISO_channel_usage & mask)) {
+ v.channel = i;
+ PRINT(KERN_INFO, ohci->id, "Found free channel %d\n", i);
+ break;
+ }
+ mask = mask << 1;
+ }
+ }
+
if (v.channel<0 || v.channel>(ISO_CHANNELS-1)) {
PRINT(KERN_ERR, ohci->id,
- "Iso channel %d out of bound", v.channel);
+ "Iso channel %d out of bounds", v.channel);
return -EFAULT;
}
mask = (u64)0x1<<v.channel;
@@ -1092,6 +1120,7 @@ static int video1394_ioctl(struct inode *inode, struct file *file,
}
case VIDEO1394_LISTEN_WAIT_BUFFER:
+ case VIDEO1394_LISTEN_POLL_BUFFER:
{
struct video1394_wait v;
struct dma_iso_ctx *d;
@@ -1120,6 +1149,12 @@ static int video1394_ioctl(struct inode *inode, struct file *file,
d->buffer_status[v.buffer]=VIDEO1394_BUFFER_FREE;
break;
case VIDEO1394_BUFFER_QUEUED:
+ if (cmd == VIDEO1394_LISTEN_POLL_BUFFER) {
+ /* for polling, return error code EINTR */
+ spin_unlock_irqrestore(&d->lock, flags);
+ return -EINTR;
+ }
+
#if 1
while(d->buffer_status[v.buffer]!=
VIDEO1394_BUFFER_READY) {
@@ -1147,6 +1182,10 @@ static int video1394_ioctl(struct inode *inode, struct file *file,
return -EFAULT;
}
+ /* set time of buffer */
+ v.filltime = d->buffer_time[v.buffer];
+// printk("Buffer %d time %d\n", v.buffer, (d->buffer_time[v.buffer]).tv_usec);
+
/*
* Look ahead to see how many more buffers have been received
*/
@@ -1596,7 +1635,8 @@ static void video1394_remove_host (struct hpsb_host *host)
{
struct ti_ohci *ohci;
unsigned long flags;
- struct list_head *lh;
+ struct list_head *lh, *next;
+ struct video_card *p;
/* We only work with the OHCI-1394 driver */
if (strcmp(host->template->name, OHCI1394_DRIVER_NAME))
@@ -1605,14 +1645,11 @@ static void video1394_remove_host (struct hpsb_host *host)
ohci = (struct ti_ohci *)host->hostdata;
spin_lock_irqsave(&video1394_cards_lock, flags);
- if (!list_empty(&video1394_cards)) {
- struct video_card *p;
- list_for_each(lh, &video1394_cards) {
- p = list_entry(lh, struct video_card, list);
- if (p ->ohci == ohci) {
- remove_card(p);
- break;
- }
+ list_for_each_safe(lh, next, &video1394_cards) {
+ p = list_entry(lh, struct video_card, list);
+ if (p->ohci == ohci) {
+ remove_card(p);
+ break;
}
}
spin_unlock_irqrestore(&video1394_cards_lock, flags);
@@ -1652,7 +1689,7 @@ static void __exit video1394_exit_module (void)
devfs_unregister(devfs_handle);
devfs_unregister_chrdev(VIDEO1394_MAJOR, VIDEO1394_DRIVER_NAME);
- PRINT_G(KERN_INFO, "Removed " VIDEO1394_DRIVER_NAME " module\n");
+ PRINT_G(KERN_INFO, "Removed " VIDEO1394_DRIVER_NAME " module");
}
static int __init video1394_init_module (void)
@@ -1678,6 +1715,7 @@ static int __init video1394_init_module (void)
return -ENOMEM;
}
+ PRINT_G(KERN_INFO, "Installed " VIDEO1394_DRIVER_NAME " module");
return 0;
}
diff --git a/drivers/ieee1394/video1394.h b/drivers/ieee1394/video1394.h
index f352ac761..4ef8f2b5e 100644
--- a/drivers/ieee1394/video1394.h
+++ b/drivers/ieee1394/video1394.h
@@ -35,11 +35,12 @@ enum {
VIDEO1394_LISTEN_CHANNEL = 0,
VIDEO1394_UNLISTEN_CHANNEL,
VIDEO1394_LISTEN_QUEUE_BUFFER,
- VIDEO1394_LISTEN_WAIT_BUFFER,
+ VIDEO1394_LISTEN_WAIT_BUFFER, // wait until buffer is ready
VIDEO1394_TALK_CHANNEL,
VIDEO1394_UNTALK_CHANNEL,
VIDEO1394_TALK_QUEUE_BUFFER,
- VIDEO1394_TALK_WAIT_BUFFER
+ VIDEO1394_TALK_WAIT_BUFFER,
+ VIDEO1394_LISTEN_POLL_BUFFER // return immediately with -EINTR if not ready
};
#define VIDEO1394_SYNC_FRAMES 0x00000001
@@ -47,7 +48,7 @@ enum {
#define VIDEO1394_VARIABLE_PACKET_SIZE 0x00000004
struct video1394_mmap {
- unsigned int channel;
+ int channel; /* -1 to find an open channel in LISTEN/TALK */
unsigned int sync_tag;
unsigned int nb_buffers;
unsigned int buf_size;
@@ -69,6 +70,7 @@ struct video1394_queue_variable {
struct video1394_wait {
unsigned int channel;
unsigned int buffer;
+ struct timeval filltime; /* time of buffer full */
};
diff --git a/drivers/media/video/Config.in b/drivers/media/video/Config.in
index 4a4ed77a0..d6a2f9ee3 100644
--- a/drivers/media/video/Config.in
+++ b/drivers/media/video/Config.in
@@ -22,10 +22,8 @@ if [ "$CONFIG_PARPORT" != "n" ]; then
fi
fi
if [ "$CONFIG_PARPORT" != "n" ]; then
- if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
- if [ "$CONFIG_PARPORT_1284" != "n" ]; then
- dep_tristate ' Winbond W9966CF Webcam Video For Linux (EXPERIMENTAL)' CONFIG_VIDEO_W9966 $CONFIG_VIDEO_DEV $CONFIG_PARPORT
- fi
+ if [ "$CONFIG_PARPORT_1284" != "n" ]; then
+ dep_tristate ' W9966CF Webcam (FlyCam Supra and others) Video For Linux' CONFIG_VIDEO_W9966 $CONFIG_VIDEO_DEV $CONFIG_PARPORT
fi
fi
dep_tristate ' CPiA Video For Linux' CONFIG_VIDEO_CPIA $CONFIG_VIDEO_DEV
diff --git a/drivers/media/video/w9966.c b/drivers/media/video/w9966.c
index c5e67b48c..404a246ee 100644
--- a/drivers/media/video/w9966.c
+++ b/drivers/media/video/w9966.c
@@ -1,9 +1,7 @@
/*
Winbond w9966cf Webcam parport driver.
- Version 0.32
-
- Copyright (C) 2001 Jakob Kemi <jakob.kemi@post.utfors.se>
+ Copyright (C) 2001 Jakob Kemi <jakob.kemi@telia.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -21,33 +19,16 @@
*/
/*
Supported devices:
- *Lifeview FlyCam Supra (using the Philips saa7111a chip)
-
- Does any other model using the w9966 interface chip exist ?
+ * Lifeview FlyCam Supra (using the Philips saa7111a chip)
Todo:
-
- *Add a working EPP mode, since DMA ECP read isn't implemented
- in the parport drivers. (That's why it's so sloow)
-
- *Add support for other ccd-control chips than the saa7111
- please send me feedback on what kind of chips you have.
-
- *Add proper probing. I don't know what's wrong with the IEEE1284
- parport drivers but (IEEE1284_MODE_NIBBLE|IEEE1284_DEVICE_ID)
- and nibble read seems to be broken for some peripherals.
-
- *Add probing for onboard SRAM, port directions etc. (if possible)
-
- *Add support for the hardware compressed modes (maybe using v4l2)
-
- *Fix better support for the capture window (no skewed images, v4l
- interface to capt. window)
-
- *Probably some bugs that I don't know of
+ * Add a working EPP mode
+ * Support other ccd-control chips than the saa7111
+ (what combinations exists?)
+ * Add proper probing. IEEE1284 probing of w9966 chips haven't
+ worked since parport drivers changed in 2.4.x.
+ * Probe for onboard SRAM, port directions etc. (if possible)
- Please support me by sending feedback!
-
Changes:
Alan Cox: Removed RGB mode for kernel merge, added THIS_MODULE
@@ -59,6 +40,8 @@
#include <linux/delay.h>
#include <linux/videodev.h>
#include <linux/parport.h>
+#include <linux/types.h>
+#include <linux/slab.h>
//#define DEBUG // Undef me for production
@@ -99,43 +82,44 @@
#define W9966_I2C_W_CLOCK 0x01
struct w9966_dev {
- unsigned char dev_state;
- unsigned char i2c_state;
- unsigned short ppmode;
+ u8 dev_state;
+ u8 i2c_state;
+ int ppmode;
struct parport* pport;
struct pardevice* pdev;
struct video_device vdev;
- unsigned short width;
- unsigned short height;
- unsigned char brightness;
- signed char contrast;
- signed char color;
- signed char hue;
+ u16 width;
+ u16 height;
+ u8 brightness;
+ s8 contrast;
+ s8 color;
+ s8 hue;
+ u8* buffer;
};
/*
* Module specific properties
*/
-MODULE_AUTHOR("Jakob Kemi <jakob.kemi@post.utfors.se>");
-MODULE_DESCRIPTION("Winbond w9966cf WebCam driver (0.32)");
+MODULE_AUTHOR("Jakob Kemi <jakob.kemi@telia.com>");
+MODULE_DESCRIPTION("Winbond w9966cf WebCam driver (FlyCam Supra and others)");
MODULE_LICENSE("GPL");
-#ifdef MODULE
-static const char* pardev[] = {[0 ... W9966_MAXCAMS] = ""};
-#else
-static const char* pardev[] = {[0 ... W9966_MAXCAMS] = "aggressive"};
-#endif
-MODULE_PARM(pardev, "1-" __MODULE_STRING(W9966_MAXCAMS) "s");
-MODULE_PARM_DESC(pardev, "pardev: where to search for\n\
-\teach camera. 'aggressive' means brute-force search.\n\
-\tEg: >pardev=parport3,aggressive,parport2,parport1< would assign
-\tcam 1 to parport3 and search every parport for cam 2 etc...");
+static const char* pardev[] = {[0 ... W9966_MAXCAMS] = "auto"};
+MODULE_PARM(pardev, "0-" __MODULE_STRING(W9966_MAXCAMS) "s");
+MODULE_PARM_DESC(pardev,"\n\
+<auto|name|none[,...]> Where to find cameras.\n\
+ auto = probe all parports for camera\n\
+ name = name of parport (eg parport0)\n\
+ none = don't search for this camera\n\
+You can specify all cameras this way, for example:
+ pardev=parport2,auto,none,parport0 would search for cam1 on parport2, search\n\
+ for cam2 on all parports, skip cam3 and search for cam4 on parport0");
static int parmode = 0;
MODULE_PARM(parmode, "i");
-MODULE_PARM_DESC(parmode, "parmode: transfer mode (0=auto, 1=ecp, 2=epp");
+MODULE_PARM_DESC(parmode, "\n<0|1|2> transfer mode (0=auto, 1=ecp, 2=epp)");
static int video_nr = -1;
MODULE_PARM(video_nr, "i");
@@ -277,17 +261,23 @@ static int w9966_init(struct w9966_dev* cam, struct parport* port)
case 0:
if (port->modes & PARPORT_MODE_ECP)
cam->ppmode = IEEE1284_MODE_ECP;
- else if (port->modes & PARPORT_MODE_EPP)
- cam->ppmode = IEEE1284_MODE_EPP;
+/* else if (port->modes & PARPORT_MODE_EPP)
+ cam->ppmode = IEEE1284_MODE_EPP;*/
else
- cam->ppmode = IEEE1284_MODE_ECP;
+ cam->ppmode = IEEE1284_MODE_ECPSWE;
break;
case 1: // hw- or sw-ecp
- cam->ppmode = IEEE1284_MODE_ECP;
+ if (port->modes & PARPORT_MODE_ECP)
+ cam->ppmode = IEEE1284_MODE_ECP;
+ else
+ cam->ppmode = IEEE1284_MODE_ECPSWE;
break;
case 2: // hw- or sw-epp
- cam->ppmode = IEEE1284_MODE_EPP;
- break;
+ if (port->modes & PARPORT_MODE_EPP)
+ cam->ppmode = IEEE1284_MODE_EPP;
+ else
+ cam->ppmode = IEEE1284_MODE_EPPSWE;
+ break;
}
// Tell the parport driver that we exists
@@ -325,6 +315,8 @@ static int w9966_init(struct w9966_dev* cam, struct parport* port)
w9966_setState(cam, W9966_STATE_VDEV, W9966_STATE_VDEV);
+ cam->buffer = NULL;
+
// All ok
printk(
"w9966cf: Found and initialized a webcam on %s.\n",
@@ -337,6 +329,12 @@ static int w9966_init(struct w9966_dev* cam, struct parport* port)
// Terminate everything gracefully
static void w9966_term(struct w9966_dev* cam)
{
+// Delete allocated buffer if needed
+ if (cam->buffer != NULL) {
+ kfree(cam->buffer);
+ cam->buffer = NULL;
+ }
+
// Unregister from v4l
if (w9966_getState(cam, W9966_STATE_VDEV, W9966_STATE_VDEV)) {
video_unregister_device(&cam->vdev);
@@ -431,9 +429,9 @@ static int w9966_setup(struct w9966_dev* cam, int x1, int y1, int x2, int y2, in
{
unsigned int i;
unsigned int enh_s, enh_e;
- unsigned char scale_x, scale_y;
- unsigned char regs[0x1c];
- unsigned char saa7111_regs[] = {
+ u8 scale_x, scale_y;
+ u8 regs[0x1c];
+ u8 saa7111_regs[] = {
0x21, 0x00, 0xd8, 0x23, 0x00, 0x80, 0x80, 0x00,
0x88, 0x10, 0x80, 0x40, 0x40, 0x00, 0x01, 0x00,
0x48, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -664,6 +662,7 @@ static int w9966_rReg_i2c(struct w9966_dev* cam, int reg)
return data;
}
+
// Write a register to the i2c device.
// Expects claimed pdev. -1 on error
static int w9966_wReg_i2c(struct w9966_dev* cam, int reg, int data)
@@ -693,11 +692,23 @@ static int w9966_wReg_i2c(struct w9966_dev* cam, int reg, int data)
static int w9966_v4l_open(struct video_device *vdev, int flags)
{
+ struct w9966_dev *cam = (struct w9966_dev*)vdev->priv;
+ cam->buffer = (u8*)kmalloc(W9966_RBUFFER, GFP_KERNEL);
+
+ if (cam->buffer == NULL)
+ return -EFAULT;
+
return 0;
}
static void w9966_v4l_close(struct video_device *vdev)
{
+ struct w9966_dev *cam = (struct w9966_dev*)vdev->priv;
+
+ if (cam->buffer != NULL) {
+ kfree(cam->buffer);
+ cam->buffer = NULL;
+ }
}
static int w9966_v4l_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
@@ -920,13 +931,12 @@ static long w9966_v4l_read(struct video_device *vdev, char *buf, unsigned long c
while(dleft > 0)
{
unsigned long tsize = (dleft > W9966_RBUFFER) ? W9966_RBUFFER : dleft;
- unsigned char tbuf[W9966_RBUFFER];
- if (parport_read(cam->pport, tbuf, tsize) < tsize) {
+ if (parport_read(cam->pport, cam->buffer, tsize) < tsize) {
w9966_pdev_release(cam);
return -EFAULT;
}
- if (copy_to_user(dest, tbuf, tsize) != 0) {
+ if (copy_to_user(dest, cam->buffer, tsize) != 0) {
w9966_pdev_release(cam);
return -EFAULT;
}
@@ -948,14 +958,14 @@ static void w9966_attach(struct parport *port)
for (i = 0; i < W9966_MAXCAMS; i++)
{
+ if (strcmp(pardev[i], "none") == 0) // Skip if 'none'
+ continue;
if (w9966_cams[i].dev_state != 0) // Cam is already assigned
continue;
- if (
- strcmp(pardev[i], "aggressive") == 0 ||
- strcmp(pardev[i], port->name) == 0
- ) {
+ if (strcmp(pardev[i], "auto") == 0 ||
+ strcmp(pardev[i], port->name) == 0) {
if (w9966_init(&w9966_cams[i], port) != 0)
- w9966_term(&w9966_cams[i]);
+ w9966_term(&w9966_cams[i]);
break; // return
}
}
diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c
index 0627bd8e9..e46fe5293 100644
--- a/drivers/net/irda/vlsi_ir.c
+++ b/drivers/net/irda/vlsi_ir.c
@@ -2,7 +2,7 @@
*
* vlsi_ir.c: VLSI82C147 PCI IrDA controller driver for Linux
*
- * Version: 0.3, Sep 30, 2001
+ * Version: 0.3a, Nov 10, 2001
*
* Copyright (c) 2001 Martin Diehl
*
@@ -490,7 +490,7 @@ static int vlsi_set_baud(struct net_device *ndev)
if (mode == IFF_FIR)
config ^= IRENABLE_FIR_ON;
else if (mode == IFF_MIR)
- config ^= (IRENABLE_FIR_ON|IRENABLE_CRC16_ON);
+ config ^= (IRENABLE_MIR_ON|IRENABLE_CRC16_ON);
else
config ^= IRENABLE_SIR_ON;
@@ -877,6 +877,7 @@ static int vlsi_open(struct net_device *ndev)
idev->irlap = irlap_open(ndev,&idev->qos,hwname);
netif_start_queue(ndev);
+ outw(0, ndev->base_addr+VLSI_PIO_PROMPT); /* kick hw state machine */
printk(KERN_INFO "%s: device %s operational using (%d,%d) tx,rx-ring\n",
__FUNCTION__, ndev->name, ringsize[0], ringsize[1]);
@@ -1200,7 +1201,6 @@ vlsi_irda_probe(struct pci_dev *pdev, const struct pci_device_id *id)
int alloc_size;
- vlsi_reg_debug(0x3000, "vlsi initial state");
if (pci_enable_device(pdev))
goto out;
diff --git a/drivers/net/pcmcia/Config.in b/drivers/net/pcmcia/Config.in
index e4be90c3d..e3eccedcc 100644
--- a/drivers/net/pcmcia/Config.in
+++ b/drivers/net/pcmcia/Config.in
@@ -11,10 +11,10 @@ if [ "$CONFIG_NET_PCMCIA" = "y" ]; then
dep_tristate ' 3Com 3c574 PCMCIA support' CONFIG_PCMCIA_3C574 $CONFIG_PCMCIA
dep_tristate ' Fujitsu FMV-J18x PCMCIA support' CONFIG_PCMCIA_FMVJ18X $CONFIG_PCMCIA
dep_tristate ' NE2000 compatible PCMCIA support' CONFIG_PCMCIA_PCNET $CONFIG_PCMCIA
+ dep_tristate ' Asix AX88190 PCMCIA support' CONFIG_PCMCIA_AXNET $CONFIG_PCMCIA
dep_tristate ' New Media PCMCIA support' CONFIG_PCMCIA_NMCLAN $CONFIG_PCMCIA
dep_tristate ' SMC 91Cxx PCMCIA support' CONFIG_PCMCIA_SMC91C92 $CONFIG_PCMCIA
dep_tristate ' Xircom 16-bit PCMCIA support' CONFIG_PCMCIA_XIRC2PS $CONFIG_PCMCIA
- dep_tristate ' broken NS8390-cards support' CONFIG_PCMCIA_AXNET $CONFIG_PCMCIA
dep_tristate ' COM20020 ARCnet PCMCIA support' CONFIG_ARCNET_COM20020_CS $CONFIG_ARCNET_COM20020 $CONFIG_ARCNET $CONFIG_PCMCIA
if [ "$CONFIG_IBMTR" != "y" ]; then
dep_tristate ' IBM PCMCIA tokenring adapter support' CONFIG_PCMCIA_IBMTR $CONFIG_TR $CONFIG_PCMCIA
diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c
index 815823b79..ddd66f7a0 100644
--- a/drivers/net/pcmcia/axnet_cs.c
+++ b/drivers/net/pcmcia/axnet_cs.c
@@ -11,7 +11,7 @@
Copyright (C) 2001 David A. Hinds -- dahinds@users.sourceforge.net
- axnet_cs.c 1.11 2001/06/12 12:42:40
+ axnet_cs.c 1.24 2001/11/18 02:46:51
The network driver code is based on Donald Becker's NE2000 code:
@@ -20,7 +20,7 @@
Director, National Security Agency. This software may be used and
distributed according to the terms of the GNU General Public License,
incorporated herein by reference.
- Donald Becker may be reached at becker@cesdis1.gsfc.nasa.gov
+ Donald Becker may be reached at becker@scyld.com
======================================================================*/
@@ -33,12 +33,13 @@
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/delay.h>
+#include <linux/spinlock.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/byteorder.h>
#include <linux/netdevice.h>
-#include "ax8390.h"
+#include "../8390.h"
#include <pcmcia/version.h>
#include <pcmcia/cs_types.h>
@@ -51,7 +52,6 @@
#define AXNET_CMD 0x00
#define AXNET_DATAPORT 0x10 /* NatSemi-defined port window offset. */
#define AXNET_RESET 0x1f /* Issue a read to reset, a write to clear. */
-#define AXNET_MISC 0x18 /* For IBM CCAE and Socket EA cards */
#define AXNET_MII_EEP 0x14 /* Offset of MII access port */
#define AXNET_START_PG 0x40 /* First page of TX buffer */
@@ -59,26 +59,13 @@
#define AXNET_RDC_TIMEOUT 0x02 /* Max wait in jiffies for Tx RDC */
-#ifdef PCMCIA_DEBUG
-static int pc_debug = PCMCIA_DEBUG;
-MODULE_PARM(pc_debug, "i");
-#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
-static char *version =
-"axnet_cs.c 1.11 2001/06/12 12:42:40 (David Hinds)";
-#else
-#define DEBUG(n, args...)
-#endif
-
-#define DEV_KFREE_SKB(skb) dev_kfree_skb(skb);
-#define skb_tx_check(dev, skb)
-#define add_rx_bytes(stats, n) (stats)->rx_bytes += n;
-#define add_tx_bytes(stats, n) (stats)->tx_bytes += n;
-#define netif_mark_up(dev) do { } while (0)
-#define netif_mark_down(dev) do { } while (0)
-
/*====================================================================*/
-/* Parameters that can be set with 'insmod' */
+/* Module parameters */
+
+MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
+MODULE_DESCRIPTION("Asix AX88190 PCMCIA ethernet driver");
+MODULE_LICENSE("GPL");
#define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
@@ -87,9 +74,14 @@ INT_MODULE_PARM(irq_mask, 0xdeb8);
static int irq_list[4] = { -1 };
MODULE_PARM(irq_list, "1-4i");
-/* Ugh! Let the user hardwire the hardware address for queer cards */
-static int hw_addr[6] = { 0, /* ... */ };
-MODULE_PARM(hw_addr, "6i");
+#ifdef PCMCIA_DEBUG
+INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);
+#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
+static char *version =
+"axnet_cs.c 1.24 2001/11/18 02:46:51 (David Hinds)";
+#else
+#define DEBUG(n, args...)
+#endif
/*====================================================================*/
@@ -120,6 +112,11 @@ static void axnet_detach(dev_link_t *);
static dev_info_t dev_info = "axnet_cs";
static dev_link_t *dev_list;
+static int axdev_init(struct net_device *dev);
+static void AX88190_init(struct net_device *dev, int startp);
+static int ax_open(struct net_device *dev);
+static void ax_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+
/*====================================================================*/
typedef struct axnet_dev_t {
@@ -210,7 +207,7 @@ static dev_link_t *axnet_attach(void)
link->conf.Attributes = CONF_ENABLE_IRQ;
link->conf.IntType = INT_MEMORY_AND_IO;
- ethdev_init(dev);
+ axdev_init(dev);
dev->init = &axnet_init;
dev->open = &axnet_open;
dev->stop = &axnet_close;
@@ -302,7 +299,7 @@ static int get_prom(dev_link_t *link)
{0x00, EN0_RCNTHI},
{0x00, EN0_IMR}, /* Mask completion irq. */
{0xFF, EN0_ISR},
- {E8390_RXOFF, EN0_RXCR}, /* 0x20 Set to monitor */
+ {E8390_RXOFF|0x40, EN0_RXCR}, /* 0x60 Set to monitor */
{E8390_TXOFF, EN0_TXCR}, /* 0x02 and loopback mode. */
{0x10, EN0_RCNTLO},
{0x00, EN0_RCNTHI},
@@ -331,30 +328,6 @@ static int get_prom(dev_link_t *link)
/*======================================================================
- This should be totally unnecessary... but when we can't figure
- out the hardware address any other way, we'll let the user hard
- wire it when the module is initialized.
-
-======================================================================*/
-
-static int get_hwired(dev_link_t *link)
-{
- struct net_device *dev = link->priv;
- int i;
-
- for (i = 0; i < 6; i++)
- if (hw_addr[i] != 0) break;
- if (i == 6)
- return 0;
-
- for (i = 0; i < 6; i++)
- dev->dev_addr[i] = hw_addr[i];
-
- return 1;
-} /* get_hwired */
-
-/*======================================================================
-
axnet_config() is scheduled to run after a CARD_INSERTION event
is received, to configure the PCMCIA socket, and to make the
ethernet device available to the system.
@@ -419,7 +392,8 @@ static void axnet_config(dev_link_t *link)
CS_CHECK(GetTupleData, handle, &tuple);
CS_CHECK(ParseTuple, handle, &tuple, &parse);
link->conf.ConfigBase = parse.config.base;
- link->conf.Present = parse.config.rmask[0];
+ /* don't trust the CIS on this; Linksys got it wrong */
+ link->conf.Present = 0x63;
/* Configure card */
link->state |= DEV_CONFIG;
@@ -440,7 +414,7 @@ static void axnet_config(dev_link_t *link)
if ((cfg->index == 0) || (cfg->io.nwin == 0))
goto next_entry;
- link->conf.ConfigIndex = cfg->index;
+ link->conf.ConfigIndex = 0x05;
/* For multifunction cards, by convention, we configure the
network function with window 0, and serial with window 1 */
if (io->nwin > 1) {
@@ -480,9 +454,9 @@ static void axnet_config(dev_link_t *link)
goto failed;
}
- if (!get_prom(link) && !get_hwired(link)) {
- printk(KERN_NOTICE "axnet_cs: unable to read hardware net"
- " address for io base %#3lx\n", dev->base_addr);
+ if (!get_prom(link)) {
+ printk(KERN_NOTICE "axnet_cs: this is not an AX88190 card!\n");
+ printk(KERN_NOTICE "axnet_cs: use pcnet_cs instead.\n");
unregister_netdev(dev);
goto failed;
}
@@ -542,7 +516,7 @@ static void axnet_release(u_long arg)
if (link->open) {
DEBUG(1, "axnet_cs: release postponed, '%s' still open\n",
- info->node.dev_name);
+ ((axnet_dev_t *)(link->priv))->node.dev_name);
link->state |= DEV_STALE_CONFIG;
return;
}
@@ -602,7 +576,7 @@ static int axnet_event(event_t event, int priority,
CardServices(RequestConfiguration, link->handle, &link->conf);
if (link->open) {
axnet_reset_8390(&info->dev);
- NS8390_init(&info->dev, 1);
+ AX88190_init(&info->dev, 1);
netif_device_attach(&info->dev);
}
}
@@ -692,7 +666,7 @@ static int axnet_open(struct net_device *dev)
info->watchdog.expires = jiffies + HZ;
add_timer(&info->watchdog);
- return ei_open(dev);
+ return ax_open(dev);
} /* axnet_open */
/*====================================================================*/
@@ -708,7 +682,6 @@ static int axnet_close(struct net_device *dev)
link->open--;
netif_stop_queue(dev);
- netif_mark_down(dev);
del_timer(&info->watchdog);
if (link->state & DEV_STALE_CONFIG)
mod_timer(&link->release, jiffies + HZ/20);
@@ -755,7 +728,7 @@ static void ei_irq_wrapper(int irq, void *dev_id, struct pt_regs *regs)
{
axnet_dev_t *info = dev_id;
info->stale = 0;
- ei_interrupt(irq, dev_id, regs);
+ ax_interrupt(irq, dev_id, regs);
}
static void ei_watchdog(u_long arg)
@@ -807,7 +780,7 @@ static void ei_watchdog(u_long arg)
else
printk(KERN_INFO "%s: link partner did not autonegotiate\n",
dev->name);
- NS8390_init(dev, 1);
+ AX88190_init(dev, 1);
}
info->link_status = link;
}
@@ -944,10 +917,11 @@ module_exit(exit_axnet_cs);
This software may be used and distributed according to the terms
of the GNU General Public License, incorporated herein by reference.
- The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
- Center of Excellence in Space Data and Information Sciences
- Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
-
+ The author may be reached as becker@scyld.com, or C/O
+ Scyld Computing Corporation
+ 410 Severn Ave., Suite 210
+ Annapolis MD 21403
+
This is the chip-specific code for many 8390-based ethernet adaptors.
This is not a complete driver, it must be combined with board-specific
code such as ne.c, wd.c, 3c503.c, etc.
@@ -957,7 +931,6 @@ module_exit(exit_axnet_cs);
a simple innocent change. Please contact me or Donald if you think
you have found something that needs changing. -- PG
-
Changelog:
Paul Gortmaker : remove set_bit lock, other cleanups.
@@ -981,8 +954,8 @@ module_exit(exit_axnet_cs);
*/
-static const char *version =
- "8390.c:v1.10cvs 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
+static const char *version_8390 =
+ "8390.c:v1.10cvs 9/23/94 Donald Becker (becker@scyld.com)\n";
#include <asm/uaccess.h>
#include <asm/bitops.h>
@@ -1062,25 +1035,23 @@ static void do_set_multicast_list(struct net_device *dev);
* them.
*/
-
-
/**
- * ei_open - Open/initialize the board.
+ * ax_open - Open/initialize the board.
* @dev: network device to initialize
*
* This routine goes all-out, setting everything
* up anew at each open, even though many of these registers should only
* need to be set once at boot.
*/
-static int ei_open(struct net_device *dev)
+static int ax_open(struct net_device *dev)
{
unsigned long flags;
struct ei_device *ei_local = (struct ei_device *) dev->priv;
- /* This can't happen unless somebody forgot to call ethdev_init(). */
+ /* This can't happen unless somebody forgot to call axdev_init(). */
if (ei_local == NULL)
{
- printk(KERN_EMERG "%s: ei_open passed a non-existent device!\n", dev->name);
+ printk(KERN_EMERG "%s: ax_open passed a non-existent device!\n", dev->name);
return -ENXIO;
}
@@ -1099,10 +1070,9 @@ static int ei_open(struct net_device *dev)
*/
spin_lock_irqsave(&ei_local->page_lock, flags);
- NS8390_init(dev, 1);
+ AX88190_init(dev, 1);
/* Set the flag before we drop the lock, That way the IRQ arrives
after its set and we get no silly warnings */
- netif_mark_up(dev);
netif_start_queue(dev);
spin_unlock_irqrestore(&ei_local->page_lock, flags);
ei_local->irqlock = 0;
@@ -1110,27 +1080,6 @@ static int ei_open(struct net_device *dev)
}
/**
- * ei_close - shut down network device
- * @dev: network device to close
- *
- * Opposite of ei_open(). Only used when "ifconfig <devname> down" is done.
- */
-static int ei_close(struct net_device *dev)
-{
- unsigned long flags;
-
- /*
- * Hold the page lock during close
- */
-
- spin_lock_irqsave(&((struct ei_device *)dev->priv)->page_lock, flags);
- NS8390_init(dev, 0);
- spin_unlock_irqrestore(&((struct ei_device *)dev->priv)->page_lock, flags);
- netif_stop_queue(dev);
- return 0;
-}
-
-/**
* ei_tx_timeout - handle transmit time out condition
* @dev: network device which has apparently fallen asleep
*
@@ -1169,7 +1118,7 @@ void ei_tx_timeout(struct net_device *dev)
/* Try to restart the card. Perhaps the user has fixed something. */
ei_reset_8390(dev);
- NS8390_init(dev, 1);
+ AX88190_init(dev, 1);
spin_unlock(&ei_local->page_lock);
enable_irq(dev->irq);
@@ -1192,7 +1141,6 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev)
unsigned long flags;
netif_stop_queue(dev);
- skb_tx_check(dev, skb);
length = skb->len;
@@ -1205,7 +1153,6 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev)
outb_p(0x00, e8390_base + EN0_IMR);
spin_unlock_irqrestore(&ei_local->page_lock, flags);
-
/*
* Slow phase with lock held.
*/
@@ -1218,8 +1165,6 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev)
send_length = ETH_ZLEN < length ? length : ETH_ZLEN;
-#ifdef EI_PINGPONG
-
/*
* We have two Tx slots available for use. Find the first free
* slot, and then perform some sanity checks. With two Tx bufs,
@@ -1288,22 +1233,6 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev)
else
netif_start_queue(dev);
-#else /* EI_PINGPONG */
-
- /*
- * Only one Tx buffer in use. You need two Tx bufs to come close to
- * back-to-back transmits. Expect a 20 -> 25% performance hit on
- * reasonable hardware if you only use one Tx buffer.
- */
-
- ei_block_output(dev, length, skb->data, ei_local->tx_start_page);
- ei_local->txing = 1;
- NS8390_trigger_send(dev, send_length, ei_local->tx_start_page);
- dev->trans_start = jiffies;
- netif_stop_queue(dev);
-
-#endif /* EI_PINGPONG */
-
/* Turn 8390 interrupts back on. */
ei_local->irqlock = 0;
outb_p(ENISR_ALL, e8390_base + EN0_IMR);
@@ -1311,14 +1240,14 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev)
spin_unlock(&ei_local->page_lock);
enable_irq(dev->irq);
- DEV_KFREE_SKB (skb);
- add_tx_bytes(&ei_local->stat, send_length);
+ dev_kfree_skb (skb);
+ ei_local->stat.tx_bytes += send_length;
return 0;
}
/**
- * ei_interrupt - handle the interrupts from an 8390
+ * ax_interrupt - handle the interrupts from an 8390
* @irq: interrupt number
* @dev_id: a pointer to the net_device
* @regs: unused
@@ -1330,7 +1259,7 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev)
* needed.
*/
-static void ei_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+static void ax_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{
struct net_device *dev = dev_id;
long e8390_base;
@@ -1497,8 +1426,6 @@ static void ei_tx_intr(struct net_device *dev)
struct ei_device *ei_local = (struct ei_device *) dev->priv;
int status = inb(e8390_base + EN0_TSR);
-#ifdef EI_PINGPONG
-
/*
* There are two Tx buffers, see which one finished, and trigger
* the send of another one if it exists.
@@ -1541,13 +1468,6 @@ static void ei_tx_intr(struct net_device *dev)
// else printk(KERN_WARNING "%s: unexpected TX-done interrupt, lasttx=%d.\n",
// dev->name, ei_local->lasttx);
-#else /* EI_PINGPONG */
- /*
- * Single Tx buffer: mark it free so another packet can be loaded.
- */
- ei_local->txing = 0;
-#endif
-
/* Minimize Tx latency: update the statistics after we restart TXing. */
if (status & ENTSR_COL)
ei_local->stat.collisions++;
@@ -1655,7 +1575,7 @@ static void ei_receive(struct net_device *dev)
netif_rx(skb);
dev->last_rx = jiffies;
ei_local->stat.rx_packets++;
- add_rx_bytes(&ei_local->stat, pkt_len);
+ ei_local->stat.rx_bytes += pkt_len;
if (pkt_stat & ENRSR_PHY)
ei_local->stat.multicast++;
}
@@ -1801,11 +1721,11 @@ static void do_set_multicast_list(struct net_device *dev)
long e8390_base = dev->base_addr;
if(dev->flags&IFF_PROMISC)
- outb_p(E8390_RXCONFIG | 0x18, e8390_base + EN0_RXCR);
+ outb_p(E8390_RXCONFIG | 0x58, e8390_base + EN0_RXCR);
else if(dev->flags&IFF_ALLMULTI || dev->mc_list)
- outb_p(E8390_RXCONFIG | 0x08, e8390_base + EN0_RXCR);
+ outb_p(E8390_RXCONFIG | 0x48, e8390_base + EN0_RXCR);
else
- outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR);
+ outb_p(E8390_RXCONFIG | 0x40, e8390_base + EN0_RXCR);
}
/*
@@ -1813,28 +1733,30 @@ static void do_set_multicast_list(struct net_device *dev)
* be parallel to just about everything else. Its also fairly quick and
* not called too often. Must protect against both bh and irq users
*/
-
+
+#define dev_lock(dev) (((struct ei_device *)(dev)->priv)->page_lock)
+
static void set_multicast_list(struct net_device *dev)
{
unsigned long flags;
- spin_lock_irqsave(&((struct ei_device *)dev->priv)->page_lock, flags);
+ spin_lock_irqsave(&dev_lock(dev), flags);
do_set_multicast_list(dev);
- spin_unlock_irqrestore(&((struct ei_device *)dev->priv)->page_lock, flags);
+ spin_unlock_irqrestore(&dev_lock(dev), flags);
}
/**
- * ethdev_init - init rest of 8390 device struct
+ * axdev_init - init rest of 8390 device struct
* @dev: network device structure to init
*
* Initialize the rest of the 8390 device structure. Do NOT __init
* this, as it is used by 8390 based modular drivers too.
*/
-static int ethdev_init(struct net_device *dev)
+static int axdev_init(struct net_device *dev)
{
if (ei_debug > 1)
- printk(version);
+ printk(version_8390);
if (dev->priv == NULL)
{
@@ -1857,20 +1779,18 @@ static int ethdev_init(struct net_device *dev)
return 0;
}
-
-
/* This page of functions should be 8390 generic */
/* Follow National Semi's recommendations for initializing the "NIC". */
/**
- * NS8390_init - initialize 8390 hardware
+ * AX88190_init - initialize 8390 hardware
* @dev: network device to initialize
* @startp: boolean. non-zero value to initiate chip processing
*
* Must be called with lock held.
*/
-static void NS8390_init(struct net_device *dev, int startp)
+static void AX88190_init(struct net_device *dev, int startp)
{
axnet_dev_t *info = (axnet_dev_t *)dev;
long e8390_base = dev->base_addr;
@@ -1887,7 +1807,7 @@ static void NS8390_init(struct net_device *dev, int startp)
outb_p(0x00, e8390_base + EN0_RCNTLO);
outb_p(0x00, e8390_base + EN0_RCNTHI);
/* Set to monitor and loopback mode -- this is vital!. */
- outb_p(E8390_RXOFF, e8390_base + EN0_RXCR); /* 0x20 */
+ outb_p(E8390_RXOFF|0x40, e8390_base + EN0_RXCR); /* 0x60 */
outb_p(E8390_TXOFF, e8390_base + EN0_TXCR); /* 0x02 */
/* Set the transmit page and receive ring. */
outb_p(ei_local->tx_start_page, e8390_base + EN0_TPSR);
@@ -1931,7 +1851,7 @@ static void NS8390_init(struct net_device *dev, int startp)
outb_p(E8390_TXCONFIG | info->duplex_flag,
e8390_base + EN0_TXCR); /* xmit on. */
/* 3c503 TechMan says rxconfig only after the NIC is started. */
- outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR); /* rx on, */
+ outb_p(E8390_RXCONFIG | 0x40, e8390_base + EN0_RXCR); /* rx on, */
do_set_multicast_list(dev); /* (re)load the mcast table */
}
}
diff --git a/drivers/net/pcmcia/netwave_cs.c b/drivers/net/pcmcia/netwave_cs.c
index 8119f1193..1f4d51b17 100644
--- a/drivers/net/pcmcia/netwave_cs.c
+++ b/drivers/net/pcmcia/netwave_cs.c
@@ -200,6 +200,8 @@ MODULE_PARM(mem_speed, "i");
MODULE_PARM(irq_mask, "i");
MODULE_PARM(irq_list, "1-4i");
+MODULE_LICENSE("GPL");
+
/*====================================================================*/
/* PCMCIA (Card Services) related functions */
@@ -1597,4 +1599,3 @@ static void set_multicast_list(struct net_device *dev)
writeb(rcvMode, ramBase + NETWAVE_EREG_CB + 1);
writeb(NETWAVE_CMD_EOC, ramBase + NETWAVE_EREG_CB + 2);
}
-MODULE_LICENSE("GPL");
diff --git a/drivers/parport/parport_cs.c b/drivers/parport/parport_cs.c
index a489c355d..358a8de99 100644
--- a/drivers/parport/parport_cs.c
+++ b/drivers/parport/parport_cs.c
@@ -5,7 +5,7 @@
(specifically, for the Quatech SPP-100 EPP card: other cards will
probably require driver tweaks)
- parport_cs.c 1.20 2000/11/02 23:15:05
+ parport_cs.c 1.24 2001/10/13 14:04:05
The contents of this file are subject to the Mozilla Public
License Version 1.1 (the "License"); you may not use this file
@@ -57,32 +57,31 @@
#include <pcmcia/cisreg.h>
#include <pcmcia/ciscode.h>
-#ifdef PCMCIA_DEBUG
-static int pc_debug = PCMCIA_DEBUG;
-MODULE_PARM(pc_debug, "i");
-#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
-static char *version =
-"parport_cs.c 1.20 2000/11/02 23:15:05 (David Hinds)";
-#else
-#define DEBUG(n, args...)
-#endif
+/*====================================================================*/
-#ifndef VERSION
-#define VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
-#endif
+/* Module parameters */
-/*====================================================================*/
+MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
+MODULE_DESCRIPTION("PCMCIA parallel port card driver");
+MODULE_LICENSE("Dual MPL/GPL");
-/* Parameters that can be set with 'insmod' */
+#define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
/* Bit map of interrupts to choose from */
-static u_int irq_mask = 0xdeb8;
+INT_MODULE_PARM(irq_mask, 0xdeb8);
static int irq_list[4] = { -1 };
-static int epp_mode = 1;
-
-MODULE_PARM(irq_mask, "i");
MODULE_PARM(irq_list, "1-4i");
-MODULE_PARM(epp_mode, "i");
+
+INT_MODULE_PARM(epp_mode, 1);
+
+#ifdef PCMCIA_DEBUG
+INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);
+#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
+static char *version =
+"parport_cs.c 1.24 2001/10/13 14:04:05 (David Hinds)";
+#else
+#define DEBUG(n, args...)
+#endif
/*====================================================================*/
@@ -306,19 +305,6 @@ void parport_config(dev_link_t *link)
goto failed;
}
-#if (LINUX_VERSION_CODE < VERSION(2,3,6))
-#if (LINUX_VERSION_CODE >= VERSION(2,2,8))
- p->private_data = kmalloc(sizeof(struct parport_pc_private),
- GFP_KERNEL);
- ((struct parport_pc_private *)(p->private_data))->ctr = 0x0c;
-#endif
- parport_proc_register(p);
- p->flags |= PARPORT_FLAG_COMA;
- parport_pc_write_econtrol(p, 0x00);
- parport_pc_write_control(p, 0x0c);
- parport_pc_write_data(p, 0x00);
-#endif
-
p->modes |= PARPORT_MODE_PCSPP;
if (epp_mode)
p->modes |= PARPORT_MODE_TRISTATE | PARPORT_MODE_EPP;
@@ -364,14 +350,8 @@ void parport_cs_release(u_long arg)
if (info->ndev) {
struct parport *p = info->port;
-#if (LINUX_VERSION_CODE < VERSION(2,3,6))
- if (!(p->flags & PARPORT_FLAG_COMA))
- parport_quiesce(p);
-#endif
parport_proc_unregister(p);
-#if (LINUX_VERSION_CODE >= VERSION(2,2,8))
kfree(p->private_data);
-#endif
parport_unregister_port(p);
}
info->ndev = 0;
@@ -429,24 +409,6 @@ int parport_event(event_t event, int priority,
/*====================================================================*/
-#if (LINUX_VERSION_CODE < VERSION(2,3,6))
-
-static void inc_use_count(void)
-{
- MOD_INC_USE_COUNT;
- parport_pc_ops.inc_use_count();
-}
-
-static void dec_use_count(void)
-{
- MOD_DEC_USE_COUNT;
- parport_pc_ops.dec_use_count();
-}
-
-#endif
-
-/*====================================================================*/
-
static int __init init_parport_cs(void)
{
servinfo_t serv;
@@ -472,4 +434,3 @@ static void __exit exit_parport_cs(void)
module_init(init_parport_cs);
module_exit(exit_parport_cs);
-MODULE_LICENSE("Dual MPL/GPL");
diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c
index 2eb64a8f0..070c3f773 100644
--- a/drivers/pcmcia/cistpl.c
+++ b/drivers/pcmcia/cistpl.c
@@ -264,11 +264,11 @@ static int setup_cis_mem(socket_info_t *s)
(s->cis_mem.sys_start == 0)) {
int low = !(s->cap.features & SS_CAP_PAGE_REGS);
vs = s;
- validate_mem(cis_readable, checksum_match, low);
+ validate_mem(cis_readable, checksum_match, low, s);
s->cis_mem.sys_start = 0;
vs = NULL;
if (find_mem_region(&s->cis_mem.sys_start, s->cap.map_size,
- s->cap.map_size, low, "card services")) {
+ s->cap.map_size, low, "card services", s)) {
printk(KERN_NOTICE "cs: unable to map card memory!\n");
return CS_OUT_OF_RESOURCE;
}
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index 53927ece5..37136815d 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -809,7 +809,7 @@ static int alloc_io_space(socket_info_t *s, u_int attr, ioaddr_t *base,
return 1;
for (i = 0; i < MAX_IO_WIN; i++) {
if (s->io[i].NumPorts == 0) {
- if (find_io_region(base, num, align, name) == 0) {
+ if (find_io_region(base, num, align, name, s) == 0) {
s->io[i].Attributes = attr;
s->io[i].BasePort = *base;
s->io[i].NumPorts = s->io[i].InUse = num;
@@ -821,7 +821,7 @@ static int alloc_io_space(socket_info_t *s, u_int attr, ioaddr_t *base,
/* Try to extend top of window */
try = s->io[i].BasePort + s->io[i].NumPorts;
if ((*base == 0) || (*base == try))
- if (find_io_region(&try, num, 0, name) == 0) {
+ if (find_io_region(&try, num, 0, name, s) == 0) {
*base = try;
s->io[i].NumPorts += num;
s->io[i].InUse += num;
@@ -830,7 +830,7 @@ static int alloc_io_space(socket_info_t *s, u_int attr, ioaddr_t *base,
/* Try to extend bottom of window */
try = s->io[i].BasePort - num;
if ((*base == 0) || (*base == try))
- if (find_io_region(&try, num, 0, name) == 0) {
+ if (find_io_region(&try, num, 0, name, s) == 0) {
s->io[i].BasePort = *base = try;
s->io[i].NumPorts += num;
s->io[i].InUse += num;
@@ -1974,7 +1974,7 @@ int pcmcia_request_window(client_handle_t *handle, win_req_t *req, window_handle
find_mem_region(&win->base, win->size, align,
(req->Attributes & WIN_MAP_BELOW_1MB) ||
!(s->cap.features & SS_CAP_PAGE_REGS),
- (*handle)->dev_info))
+ (*handle)->dev_info, s))
return CS_IN_USE;
(*handle)->state |= CLIENT_WIN_REQ(w);
diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h
index 126506431..2844ac2af 100644
--- a/drivers/pcmcia/cs_internal.h
+++ b/drivers/pcmcia/cs_internal.h
@@ -238,11 +238,11 @@ int copy_memory(memory_handle_t handle, copy_op_t *req);
/* In rsrc_mgr */
void validate_mem(int (*is_valid)(u_long), int (*do_cksum)(u_long),
- int force_low);
+ int force_low, socket_info_t *s);
int find_io_region(ioaddr_t *base, ioaddr_t num, ioaddr_t align,
- char *name);
+ char *name, socket_info_t *s);
int find_mem_region(u_long *base, u_long num, u_long align,
- int force_low, char *name);
+ int force_low, char *name, socket_info_t *s);
int try_irq(u_int Attributes, int irq, int specific);
void undo_irq(u_int Attributes, int irq);
int adjust_resource_info(client_handle_t handle, adjust_t *adj);
diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c
index 5cfd31aac..d22ba8bae 100644
--- a/drivers/pcmcia/rsrc_mgr.c
+++ b/drivers/pcmcia/rsrc_mgr.c
@@ -44,6 +44,7 @@
#include <linux/ioport.h>
#include <linux/timer.h>
#include <linux/proc_fs.h>
+#include <linux/pci.h>
#include <asm/irq.h>
#include <asm/io.h>
@@ -103,8 +104,78 @@ static irq_info_t irq_table[NR_IRQS] = { { 0, 0, 0 }, /* etc */ };
======================================================================*/
-#define check_io_resource(b,n) check_resource(&ioport_resource, (b), (n))
-#define check_mem_resource(b,n) check_resource(&iomem_resource, (b), (n))
+static struct resource *resource_parent(unsigned long b, unsigned long n,
+ int flags, struct pci_dev *dev)
+{
+ struct resource res;
+
+ if (dev == NULL) {
+ if (flags & IORESOURCE_MEM)
+ return &iomem_resource;
+ return &ioport_resource;
+ }
+ res.start = b;
+ res.end = b + n - 1;
+ res.flags = flags;
+ return pci_find_parent_resource(dev, &res);
+}
+
+static inline int check_io_resource(unsigned long b, unsigned long n,
+ struct pci_dev *dev)
+{
+ return check_resource(resource_parent(b, n, IORESOURCE_IO, dev), b, n);
+}
+
+static inline int check_mem_resource(unsigned long b, unsigned long n,
+ struct pci_dev *dev)
+{
+ return check_resource(resource_parent(b, n, IORESOURCE_MEM, dev), b, n);
+}
+
+static struct resource *make_resource(unsigned long b, unsigned long n,
+ int flags, char *name)
+{
+ struct resource *res = kmalloc(sizeof(*res), GFP_KERNEL);
+
+ if (res) {
+ memset(res, 0, sizeof(*res));
+ res->name = name;
+ res->start = b;
+ res->end = b + n - 1;
+ res->flags = flags | IORESOURCE_BUSY;
+ }
+ return res;
+}
+
+static int request_io_resource(unsigned long b, unsigned long n,
+ char *name, struct pci_dev *dev)
+{
+ struct resource *res = make_resource(b, n, IORESOURCE_IO, name);
+ struct resource *pr = resource_parent(b, n, IORESOURCE_IO, dev);
+ int err = -ENOMEM;
+
+ if (res) {
+ err = request_resource(pr, res);
+ if (err)
+ kfree(res);
+ }
+ return err;
+}
+
+static int request_mem_resource(unsigned long b, unsigned long n,
+ char *name, struct pci_dev *dev)
+{
+ struct resource *res = make_resource(b, n, IORESOURCE_MEM, name);
+ struct resource *pr = resource_parent(b, n, IORESOURCE_MEM, dev);
+ int err = -ENOMEM;
+
+ if (res) {
+ err = request_resource(pr, res);
+ if (err)
+ kfree(res);
+ }
+ return err;
+}
/*======================================================================
@@ -194,7 +265,7 @@ static void do_io_probe(ioaddr_t base, ioaddr_t num)
}
memset(b, 0, 256);
for (i = base, most = 0; i < base+num; i += 8) {
- if (check_io_resource(i, 8))
+ if (check_io_resource(i, 8, NULL))
continue;
hole = inb(i);
for (j = 1; j < 8; j++)
@@ -207,7 +278,7 @@ static void do_io_probe(ioaddr_t base, ioaddr_t num)
bad = any = 0;
for (i = base; i < base+num; i += 8) {
- if (check_io_resource(i, 8))
+ if (check_io_resource(i, 8, NULL))
continue;
for (j = 0; j < 8; j++)
if (inb(i+j) != most) break;
@@ -247,7 +318,8 @@ static void do_io_probe(ioaddr_t base, ioaddr_t num)
======================================================================*/
static int do_mem_probe(u_long base, u_long num,
- int (*is_valid)(u_long), int (*do_cksum)(u_long))
+ int (*is_valid)(u_long), int (*do_cksum)(u_long),
+ socket_info_t *s)
{
u_long i, j, bad, fail, step;
@@ -258,13 +330,14 @@ static int do_mem_probe(u_long base, u_long num,
for (i = j = base; i < base+num; i = j + step) {
if (!fail) {
for (j = i; j < base+num; j += step)
- if ((check_mem_resource(j, step) == 0) && is_valid(j))
+ if ((check_mem_resource(j, step, s->cap.cb_dev) == 0) &&
+ is_valid(j))
break;
fail = ((i == base) && (j == base+num));
}
if (fail) {
for (j = i; j < base+num; j += 2*step)
- if ((check_mem_resource(j, 2*step) == 0) &&
+ if ((check_mem_resource(j, 2*step, s->cap.cb_dev) == 0) &&
do_cksum(j) && do_cksum(j+step))
break;
}
@@ -283,12 +356,12 @@ static int do_mem_probe(u_long base, u_long num,
static u_long inv_probe(int (*is_valid)(u_long),
int (*do_cksum)(u_long),
- resource_map_t *m)
+ resource_map_t *m, socket_info_t *s)
{
u_long ok;
if (m == &mem_db)
return 0;
- ok = inv_probe(is_valid, do_cksum, m->next);
+ ok = inv_probe(is_valid, do_cksum, m->next, s);
if (ok) {
if (m->base >= 0x100000)
sub_interval(&mem_db, m->base, m->num);
@@ -296,11 +369,11 @@ static u_long inv_probe(int (*is_valid)(u_long),
}
if (m->base < 0x100000)
return 0;
- return do_mem_probe(m->base, m->num, is_valid, do_cksum);
+ return do_mem_probe(m->base, m->num, is_valid, do_cksum, s);
}
void validate_mem(int (*is_valid)(u_long), int (*do_cksum)(u_long),
- int force_low)
+ int force_low, socket_info_t *s)
{
resource_map_t *m, *n;
static u_char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 };
@@ -310,7 +383,7 @@ void validate_mem(int (*is_valid)(u_long), int (*do_cksum)(u_long),
if (!probe_mem) return;
/* We do up to four passes through the list */
if (!force_low) {
- if (hi++ || (inv_probe(is_valid, do_cksum, mem_db.next) > 0))
+ if (hi++ || (inv_probe(is_valid, do_cksum, mem_db.next, s) > 0))
return;
printk(KERN_NOTICE "cs: warning: no high memory space "
"available!\n");
@@ -321,7 +394,7 @@ void validate_mem(int (*is_valid)(u_long), int (*do_cksum)(u_long),
/* Only probe < 1 MB */
if (m->base >= 0x100000) continue;
if ((m->base | m->num) & 0xffff) {
- ok += do_mem_probe(m->base, m->num, is_valid, do_cksum);
+ ok += do_mem_probe(m->base, m->num, is_valid, do_cksum, s);
continue;
}
/* Special probe for 64K-aligned block */
@@ -331,7 +404,7 @@ void validate_mem(int (*is_valid)(u_long), int (*do_cksum)(u_long),
if (ok >= mem_limit)
sub_interval(&mem_db, b, 0x10000);
else
- ok += do_mem_probe(b, 0x10000, is_valid, do_cksum);
+ ok += do_mem_probe(b, 0x10000, is_valid, do_cksum, s);
}
}
}
@@ -340,7 +413,7 @@ void validate_mem(int (*is_valid)(u_long), int (*do_cksum)(u_long),
#else /* CONFIG_ISA */
void validate_mem(int (*is_valid)(u_long), int (*do_cksum)(u_long),
- int force_low)
+ int force_low, socket_info_t *s)
{
resource_map_t *m;
static int done = 0;
@@ -348,7 +421,7 @@ void validate_mem(int (*is_valid)(u_long), int (*do_cksum)(u_long),
if (!probe_mem || done++)
return;
for (m = mem_db.next; m != &mem_db; m = m->next)
- if (do_mem_probe(m->base, m->num, is_valid, do_cksum))
+ if (do_mem_probe(m->base, m->num, is_valid, do_cksum, s))
return;
}
@@ -368,7 +441,7 @@ void validate_mem(int (*is_valid)(u_long), int (*do_cksum)(u_long),
======================================================================*/
int find_io_region(ioaddr_t *base, ioaddr_t num, ioaddr_t align,
- char *name)
+ char *name, socket_info_t *s)
{
ioaddr_t try;
resource_map_t *m;
@@ -378,9 +451,8 @@ int find_io_region(ioaddr_t *base, ioaddr_t num, ioaddr_t align,
for (try = (try >= m->base) ? try : try+align;
(try >= m->base) && (try+num <= m->base+m->num);
try += align) {
- if (check_io_resource(try, num) == 0) {
+ if (request_io_resource(try, num, name, s->cap.cb_dev) == 0) {
*base = try;
- request_region(try, num, name);
return 0;
}
if (!align) break;
@@ -390,7 +462,7 @@ int find_io_region(ioaddr_t *base, ioaddr_t num, ioaddr_t align,
}
int find_mem_region(u_long *base, u_long num, u_long align,
- int force_low, char *name)
+ int force_low, char *name, socket_info_t *s)
{
u_long try;
resource_map_t *m;
@@ -403,8 +475,7 @@ int find_mem_region(u_long *base, u_long num, u_long align,
for (try = (try >= m->base) ? try : try+align;
(try >= m->base) && (try+num <= m->base+m->num);
try += align) {
- if (check_mem_resource(try, num) == 0) {
- request_mem_region(try, num, name);
+ if (request_mem_resource(try, num, name, s->cap.cb_dev) == 0) {
*base = try;
return 0;
}
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
index 8f3231086..576cbdb9a 100644
--- a/drivers/scsi/ide-scsi.c
+++ b/drivers/scsi/ide-scsi.c
@@ -785,7 +785,7 @@ int idescsi_queue (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
rq->buffer = (char *) pc;
rq->bh = idescsi_dma_bh (drive, pc);
rq->cmd = IDESCSI_PC_RQ;
- spin_unlock(&io_request_lock);
+ spin_unlock_irq(&io_request_lock);
(void) ide_do_drive_cmd (drive, rq, ide_end);
spin_lock_irq(&io_request_lock);
return 0;
diff --git a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c
index 92b571b97..86260644c 100644
--- a/drivers/scsi/pcmcia/aha152x_stub.c
+++ b/drivers/scsi/pcmcia/aha152x_stub.c
@@ -5,7 +5,7 @@
This driver supports the Adaptec AHA-1460, the New Media Bus
Toaster, and the New Media Toast & Jam.
- aha152x_cs.c 1.54 2000/06/12 21:27:25
+ aha152x_cs.c 1.58 2001/10/13 00:08:51
The contents of this file are subject to the Mozilla Public
License Version 1.1 (the "License"); you may not use this file
@@ -22,8 +22,8 @@
are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
Alternatively, the contents of this file may be used under the
- terms of the GNU General Public License version 2 (the "GPL"), in which
- case the provisions of the GPL are applicable instead of the
+ terms of the GNU General Public License version 2 (the "GPL"), in
+ which case the provisions of the GPL are applicable instead of the
above. If you wish to allow the use of your version of this file
only under the terms of the GPL and not to allow others to use
your version of this file under the MPL, indicate your decision
@@ -57,42 +57,39 @@
#include <pcmcia/cistpl.h>
#include <pcmcia/ds.h>
-#ifdef PCMCIA_DEBUG
-static int pc_debug = PCMCIA_DEBUG;
-MODULE_PARM(pc_debug, "i");
-#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
-static char *version =
-"aha152x_cs.c 1.54 2000/06/12 21:27:25 (David Hinds)";
-#else
-#define DEBUG(n, args...)
-#endif
-
/*====================================================================*/
-/* Parameters that can be set with 'insmod' */
+/* Module parameters */
+
+MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
+MODULE_DESCRIPTION("Adaptec AHA152x-compatible PCMCIA SCSI driver");
+MODULE_LICENSE("Dual MPL/GPL");
-/* Bit map of interrupts to choose from */
-static u_int irq_mask = 0xdeb8;
static int irq_list[4] = { -1 };
+MODULE_PARM(irq_list, "1-4i");
-/* SCSI bus setup options */
-static int host_id = 7;
-static int reconnect = 1;
-static int parity = 1;
-static int synchronous = 0;
-static int reset_delay = 100;
-static int ext_trans = 0;
+#define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
-MODULE_PARM(irq_mask, "i");
-MODULE_PARM(irq_list, "1-4i");
-MODULE_PARM(host_id, "i");
-MODULE_PARM(reconnect, "i");
-MODULE_PARM(parity, "i");
-MODULE_PARM(synchronous, "i");
-MODULE_PARM(reset_delay, "i");
-MODULE_PARM(ext_trans, "i");
+INT_MODULE_PARM(irq_mask, 0xdeb8);
+INT_MODULE_PARM(host_id, 7);
+INT_MODULE_PARM(reconnect, 1);
+INT_MODULE_PARM(parity, 1);
+INT_MODULE_PARM(synchronous, 0);
+INT_MODULE_PARM(reset_delay, 100);
+INT_MODULE_PARM(ext_trans, 0);
-MODULE_LICENSE("Dual MPL/GPL");
+#ifdef AHA152X_DEBUG
+INT_MODULE_PARM(debug, 0);
+#endif
+
+#ifdef PCMCIA_DEBUG
+INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);
+#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
+static char *version =
+"aha152x_cs.c 1.58 2001/10/13 00:08:51 (David Hinds)";
+#else
+#define DEBUG(n, args...)
+#endif
/*====================================================================*/
@@ -277,7 +274,6 @@ static void aha152x_config_cs(dev_link_t *link)
release_region(link->io.BasePort1, link->io.NumPorts1);
/* Set configuration options for the aha152x driver */
- ints[0] = 7;
ints[1] = link->io.BasePort1;
ints[2] = link->irq.AssignedIRQ;
ints[3] = host_id;
@@ -285,9 +281,13 @@ static void aha152x_config_cs(dev_link_t *link)
ints[5] = parity;
ints[6] = synchronous;
ints[7] = reset_delay;
- if (ext_trans) {
- ints[8] = ext_trans; ints[0] = 8;
- }
+ ints[8] = ext_trans;
+#ifdef AHA152X_DEBUG
+ ints[9] = debug;
+ ints[0] = 9;
+#else
+ ints[0] = 8;
+#endif
aha152x_setup("PCMCIA setup", ints);
scsi_register_module(MODULE_SCSI_HA, &driver_template);
diff --git a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c
index 48cae1368..8dae5f4b1 100644
--- a/drivers/scsi/pcmcia/fdomain_stub.c
+++ b/drivers/scsi/pcmcia/fdomain_stub.c
@@ -2,7 +2,7 @@
A driver for Future Domain-compatible PCMCIA SCSI cards
- fdomain_cs.c 1.43 2000/06/12 21:27:25
+ fdomain_cs.c 1.47 2001/10/13 00:08:52
The contents of this file are subject to the Mozilla Public
License Version 1.1 (the "License"); you may not use this file
@@ -19,8 +19,8 @@
are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
Alternatively, the contents of this file may be used under the
- terms of the GNU General Public License version 2 (the "GPL"), in which
- case the provisions of the GPL are applicable instead of the
+ terms of the GNU General Public License version 2 (the "GPL"), in
+ which case the provisions of the GPL are applicable instead of the
above. If you wish to allow the use of your version of this file
only under the terms of the GPL and not to allow others to use
your version of this file under the MPL, indicate your decision
@@ -54,27 +54,30 @@
#include <pcmcia/cistpl.h>
#include <pcmcia/ds.h>
-#ifdef PCMCIA_DEBUG
-static int pc_debug = PCMCIA_DEBUG;
-MODULE_PARM(pc_debug, "i");
-#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
-static char *version =
-"fdomain_cs.c 1.43 2000/06/12 21:27:25 (David Hinds)";
-#else
-#define DEBUG(n, args...)
-#endif
-
/*====================================================================*/
-/* Parameters that can be set with 'insmod' */
+/* Module parameters */
+
+MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
+MODULE_DESCRIPTION("Future Domain PCMCIA SCSI driver");
+MODULE_LICENSE("Dual MPL/GPL");
+
+#define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
/* Bit map of interrupts to choose from */
-static u_int irq_mask = 0xdeb8;
+INT_MODULE_PARM(irq_mask, 0xdeb8);
static int irq_list[4] = { -1 };
-
-MODULE_PARM(irq_mask, "i");
MODULE_PARM(irq_list, "1-4i");
+#ifdef PCMCIA_DEBUG
+INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);
+#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
+static char *version =
+"fdomain_cs.c 1.47 2001/10/13 00:08:52 (David Hinds)";
+#else
+#define DEBUG(n, args...)
+#endif
+
/*====================================================================*/
typedef struct scsi_info_t {
@@ -212,6 +215,7 @@ static void fdomain_config(dev_link_t *link)
u_char tuple_data[64];
Scsi_Device *dev;
dev_node_t *node, **tail;
+ char str[16];
struct Scsi_Host *host;
DEBUG(0, "fdomain_config(0x%p)\n", link);
@@ -252,7 +256,8 @@ static void fdomain_config(dev_link_t *link)
ints[0] = 2;
ints[1] = link->io.BasePort1;
ints[2] = link->irq.AssignedIRQ;
- fdomain_setup("PCMCIA setup", ints);
+ sprintf(str, "%d,%d", link->io.BasePort1, link->irq.AssignedIRQ);
+ fdomain_setup(str, ints);
scsi_register_module(MODULE_SCSI_HA, &driver_template);
diff --git a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c
index 0d81e816d..be524f9da 100644
--- a/drivers/scsi/pcmcia/qlogic_stub.c
+++ b/drivers/scsi/pcmcia/qlogic_stub.c
@@ -2,7 +2,7 @@
A driver for the Qlogic SCSI card
- qlogic_cs.c 1.79 2000/06/12 21:27:26
+ qlogic_cs.c 1.83 2001/10/13 00:08:53
The contents of this file are subject to the Mozilla Public
License Version 1.1 (the "License"); you may not use this file
@@ -19,8 +19,8 @@
are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
Alternatively, the contents of this file may be used under the
- terms of the GNU General Public License version 2 (the "GPL"), in which
- case the provisions of the GPL are applicable instead of the
+ terms of the GNU General Public License version 2 (the "GPL"), in
+ which case the provisions of the GPL are applicable instead of the
above. If you wish to allow the use of your version of this file
only under the terms of the GPL and not to allow others to use
your version of this file under the MPL, indicate your decision
@@ -40,6 +40,7 @@
#include <linux/timer.h>
#include <linux/ioport.h>
#include <asm/io.h>
+#include <asm/byteorder.h>
#include <scsi/scsi.h>
#include <linux/major.h>
#include <linux/blk.h>
@@ -61,27 +62,30 @@
extern void qlogicfas_preset(int port, int irq);
-#ifdef PCMCIA_DEBUG
-static int pc_debug = PCMCIA_DEBUG;
-MODULE_PARM(pc_debug, "i");
-#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
-static char *version =
-"qlogic_cs.c 1.79 2000/06/12 21:27:26 (David Hinds)";
-#else
-#define DEBUG(n, args...)
-#endif
-
/*====================================================================*/
-/* Parameters that can be set with 'insmod' */
+/* Module parameters */
+
+MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
+MODULE_DESCRIPTION("Qlogic PCMCIA SCSI driver");
+MODULE_LICENSE("Dual MPL/GPL");
+
+#define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
/* Bit map of interrupts to choose from */
-static u_int irq_mask = 0xdeb8;
+INT_MODULE_PARM(irq_mask, 0xdeb8);
static int irq_list[4] = { -1 };
-
-MODULE_PARM(irq_mask, "i");
MODULE_PARM(irq_list, "1-4i");
+#ifdef PCMCIA_DEBUG
+INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);
+#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
+static char *version =
+"qlogic_cs.c 1.83 2001/10/13 00:08:53 (David Hinds)";
+#else
+#define DEBUG(n, args...)
+#endif
+
/*====================================================================*/
typedef struct scsi_info_t {
diff --git a/drivers/sound/ad1848.c b/drivers/sound/ad1848.c
index b1dbbba26..521ec9423 100644
--- a/drivers/sound/ad1848.c
+++ b/drivers/sound/ad1848.c
@@ -30,6 +30,12 @@
* Aki Laukkanen : added power management support
* Arnaldo C. de Melo : added missing restore_flags in ad1848_resume
* Miguel Freitas : added ISA PnP support
+ * Alan Cox : Added CS4236->4239 identification
+ * Daniel T. Cobra : Alernate config/mixer for later chips
+ * Alan Cox : Merged chip idents and config code
+ *
+ * TODO
+ * APM save restore assist code on IBM thinkpad
*
* Status:
* Tested. Believed fully functional.
@@ -57,7 +63,7 @@ typedef struct
int dual_dma; /* 1, when two DMA channels allocated */
int subtype;
unsigned char MCE_bit;
- unsigned char saved_regs[32];
+ unsigned char saved_regs[64]; /* Includes extended register space */
int debug_flag;
int audio_flags;
@@ -78,6 +84,9 @@ typedef struct
#define MD_IWAVE 7
#define MD_4235 8 /* Crystal Audio CS4235 */
#define MD_1845_SSCAPE 9 /* Ensoniq Soundscape PNP*/
+#define MD_4236 10 /* 4236 and higher */
+#define MD_42xB 11 /* CS 42xB */
+#define MD_4239 12 /* CS4239 */
/* Mixer parameters */
int recmask;
@@ -202,9 +211,22 @@ static int ad_read(ad1848_info * devc, int reg)
save_flags(flags);
cli();
- outb(((unsigned char) (reg & 0xff) | devc->MCE_bit), io_Index_Addr(devc));
- x = inb(io_Indexed_Data(devc));
-/* printk("(%02x<-%02x) ", reg|devc->MCE_bit, x); */
+
+ if(reg < 32)
+ {
+ outb(((unsigned char) (reg & 0xff) | devc->MCE_bit), io_Index_Addr(devc));
+ x = inb(io_Indexed_Data(devc));
+ }
+ else
+ {
+ int xreg, xra;
+
+ xreg = (reg & 0xff) - 32;
+ xra = (((xreg & 0x0f) << 4) & 0xf0) | 0x08 | ((xreg & 0x10) >> 2);
+ outb(((unsigned char) (23 & 0xff) | devc->MCE_bit), io_Index_Addr(devc));
+ outb(((unsigned char) (xra & 0xff)), io_Indexed_Data(devc));
+ x = inb(io_Indexed_Data(devc));
+ }
restore_flags(flags);
return x;
@@ -220,9 +242,22 @@ static void ad_write(ad1848_info * devc, int reg, int data)
save_flags(flags);
cli();
- outb(((unsigned char) (reg & 0xff) | devc->MCE_bit), io_Index_Addr(devc));
- outb(((unsigned char) (data & 0xff)), io_Indexed_Data(devc));
- /* printk("(%02x->%02x) ", reg|devc->MCE_bit, data); */
+
+ if(reg < 32)
+ {
+ outb(((unsigned char) (reg & 0xff) | devc->MCE_bit), io_Index_Addr(devc));
+ outb(((unsigned char) (data & 0xff)), io_Indexed_Data(devc));
+ }
+ else
+ {
+ int xreg, xra;
+
+ xreg = (reg & 0xff) - 32;
+ xra = (((xreg & 0x0f) << 4) & 0xf0) | 0x08 | ((xreg & 0x10) >> 2);
+ outb(((unsigned char) (23 & 0xff) | devc->MCE_bit), io_Index_Addr(devc));
+ outb(((unsigned char) (xra & 0xff)), io_Indexed_Data(devc));
+ outb((unsigned char) (data & 0xff), io_Indexed_Data(devc));
+ }
restore_flags(flags);
}
@@ -591,7 +626,13 @@ static void ad1848_mixer_reset(ad1848_info * devc)
devc->mix_devices = &(iwave_mix_devices[0]);
break;
+ case MD_42xB:
+ case MD_4239:
+ devc->mix_devices = &(cs42xb_mix_devices[0]);
+ devc->supported_devices = MODE3_MIXER_DEVICES;
+ break;
case MD_4232:
+ case MD_4236:
devc->supported_devices = MODE3_MIXER_DEVICES;
break;
@@ -1118,7 +1159,7 @@ static int ad1848_prepare_for_output(int dev, int bsize, int bcount)
}
old_fs = ad_read(devc, 8);
- if (devc->model == MD_4232)
+ if (devc->model == MD_4232 || devc->model >= MD_4236)
{
tmp = ad_read(devc, 16);
ad_write(devc, 16, tmp | 0x30);
@@ -1139,7 +1180,7 @@ static int ad1848_prepare_for_output(int dev, int bsize, int bcount)
while (timeout < 10000 && inb(devc->base) == 0x80)
timeout++;
- if (devc->model == MD_4232)
+ if (devc->model >= MD_4232)
ad_write(devc, 16, tmp & ~0x30);
ad_leave_MCE(devc); /*
@@ -1403,11 +1444,12 @@ static void ad1848_trigger(int dev, int state)
static void ad1848_init_hw(ad1848_info * devc)
{
int i;
+ int *init_values;
/*
* Initial values for the indirect registers of CS4248/AD1848.
*/
- static int init_values[] =
+ static int init_values_a[] =
{
0xa8, 0xa8, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00,
0x00, 0x0c, 0x02, 0x00, 0x8a, 0x01, 0x00, 0x00,
@@ -1417,6 +1459,31 @@ static void ad1848_init_hw(ad1848_info * devc)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
+ static int init_values_b[] =
+ {
+ /*
+ Values for the newer chips
+ Some of the register initialization values were changed. In
+ order to get rid of the click that preceded PCM playback,
+ calibration was disabled on the 10th byte. On that same byte,
+ dual DMA was enabled; on the 11th byte, ADC dithering was
+ enabled, since that is theoretically desirable; on the 13th
+ byte, Mode 3 was selected, to enable access to extended
+ registers.
+ */
+ 0xa8, 0xa8, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x00, 0xe0, 0x01, 0x00, 0x00,
+ 0x80, 0x00, 0x10, 0x10, 0x00, 0x00, 0x1f, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+ /*
+ * Select initialisation data
+ */
+
+ init_values = init_values_a;
+ if(devc->model >= MD_4236)
+ init_values = init_values_b;
for (i = 0; i < 16; i++)
ad_write(devc, i, init_values[i]);
@@ -1768,19 +1835,49 @@ int ad1848_detect(int io_base, int *ad_flags, int *osp)
else
{
switch (id & 0x1f) {
- case 3: /* CS4236/CS4235 */
+ case 3: /* CS4236/CS4235/CS42xB/CS4239 */
{
int xid;
ad_write(devc, 12, ad_read(devc, 12) | 0x60); /* switch to mode 3 */
ad_write(devc, 23, 0x9c); /* select extended register 25 */
xid = inb(io_Indexed_Data(devc));
ad_write(devc, 12, ad_read(devc, 12) & ~0x60); /* back to mode 0 */
- if ((xid & 0x1f) == 0x1d) {
- devc->chip_name = "CS4235";
- devc->model = MD_4235;
- } else {
- devc->chip_name = "CS4236";
- devc->model = MD_4232;
+ switch (xid & 0x1f)
+ {
+ case 0x00:
+ devc->chip_name = "CS4237B(B)";
+ devc->model = MD_42xB;
+ break;
+ case 0x08:
+ /* Seems to be a 4238 ?? */
+ devc->chip_name = "CS4238";
+ devc->model = MD_42xB;
+ break;
+ case 0x09:
+ devc->chip_name = "CS4238B";
+ devc->model = MD_42xB;
+ break;
+ case 0x0b:
+ devc->chip_name = "CS4236B";
+ devc->model = MD_4236;
+ break;
+ case 0x10:
+ devc->chip_name = "CS4237B";
+ devc->model = MD_42xB;
+ break;
+ case 0x1d:
+ devc->chip_name = "CS4235";
+ devc->model = MD_4235;
+ break;
+ case 0x1e:
+ devc->chip_name = "CS4239";
+ devc->model = MD_4239;
+ break;
+ default:
+ printk("Chip ident is %X.\n", xid&0x1F);
+ devc->chip_name = "CS42xx";
+ devc->model = MD_4232;
+ break;
}
}
break;
@@ -2747,6 +2844,10 @@ static int ad1848_resume(ad1848_info *devc)
save_flags(flags);
cli();
+
+ /* 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 */
/* store old mixer levels */
memcpy(mixer_levels, devc->levels, sizeof (mixer_levels));
diff --git a/drivers/sound/ad1848_mixer.h b/drivers/sound/ad1848_mixer.h
index fdd06e499..f9231c6cd 100644
--- a/drivers/sound/ad1848_mixer.h
+++ b/drivers/sound/ad1848_mixer.h
@@ -57,14 +57,14 @@
SOUND_MASK_OGAIN)
struct mixer_def {
- unsigned int regno:5; /* register number for volume */
+ unsigned int regno:6; /* register number for volume */
unsigned int polarity:1; /* volume polarity: 0=normal, 1=reversed */
unsigned int bitpos:3; /* position of bits in register for volume */
unsigned int nbits:3; /* number of bits in register for volume */
- unsigned int mutereg:5; /* register number for mute bit */
+ unsigned int mutereg:6; /* register number for mute bit */
unsigned int mutepol:1; /* mute polarity: 0=normal, 1=reversed */
unsigned int mutepos:4; /* position of mute bit in register */
- unsigned int recreg:5; /* register number for recording bit */
+ unsigned int recreg:6; /* register number for recording bit */
unsigned int recpol:1; /* recording polarity: 0=normal, 1=reversed */
unsigned int recpos:4; /* position of recording bit in register */
};
@@ -104,43 +104,69 @@ typedef mixer_ent mixer_ents[2];
rec_reg_r, rec_pola_r, rec_pos_r}}
static mixer_ents ad1848_mix_devices[32] = {
-MIX_ENT(SOUND_MIXER_VOLUME, 27, 1, 0, 4, 29, 1, 0, 4, 8),
-MIX_ENT(SOUND_MIXER_BASS, 0, 0, 0, 0, 0, 0, 0, 0, 8),
-MIX_ENT(SOUND_MIXER_TREBLE, 0, 0, 0, 0, 0, 0, 0, 0, 8),
-MIX_ENT(SOUND_MIXER_SYNTH, 4, 1, 0, 5, 5, 1, 0, 5, 7),
-MIX_ENT(SOUND_MIXER_PCM, 6, 1, 0, 6, 7, 1, 0, 6, 7),
-MIX_ENT(SOUND_MIXER_SPEAKER, 26, 1, 0, 4, 0, 0, 0, 0, 8),
-MIX_ENT(SOUND_MIXER_LINE, 18, 1, 0, 5, 19, 1, 0, 5, 7),
-MIX_ENT(SOUND_MIXER_MIC, 0, 0, 5, 1, 1, 0, 5, 1, 8),
-MIX_ENT(SOUND_MIXER_CD, 2, 1, 0, 5, 3, 1, 0, 5, 7),
-MIX_ENT(SOUND_MIXER_IMIX, 13, 1, 2, 6, 0, 0, 0, 0, 8),
-MIX_ENT(SOUND_MIXER_ALTPCM, 0, 0, 0, 0, 0, 0, 0, 0, 8),
-MIX_ENT(SOUND_MIXER_RECLEV, 0, 0, 0, 0, 0, 0, 0, 0, 8),
-MIX_ENT(SOUND_MIXER_IGAIN, 0, 0, 0, 4, 1, 0, 0, 4, 8),
-MIX_ENT(SOUND_MIXER_OGAIN, 0, 0, 0, 0, 0, 0, 0, 0, 8),
-MIX_ENT(SOUND_MIXER_LINE1, 2, 1, 0, 5, 3, 1, 0, 5, 7),
-MIX_ENT(SOUND_MIXER_LINE2, 4, 1, 0, 5, 5, 1, 0, 5, 7),
-MIX_ENT(SOUND_MIXER_LINE3, 18, 1, 0, 5, 19, 1, 0, 5, 7)
+ MIX_ENT(SOUND_MIXER_VOLUME, 27, 1, 0, 4, 29, 1, 0, 4, 8),
+ MIX_ENT(SOUND_MIXER_BASS, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT(SOUND_MIXER_TREBLE, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT(SOUND_MIXER_SYNTH, 4, 1, 0, 5, 5, 1, 0, 5, 7),
+ MIX_ENT(SOUND_MIXER_PCM, 6, 1, 0, 6, 7, 1, 0, 6, 7),
+ MIX_ENT(SOUND_MIXER_SPEAKER, 26, 1, 0, 4, 0, 0, 0, 0, 8),
+ MIX_ENT(SOUND_MIXER_LINE, 18, 1, 0, 5, 19, 1, 0, 5, 7),
+ MIX_ENT(SOUND_MIXER_MIC, 0, 0, 5, 1, 1, 0, 5, 1, 8),
+ MIX_ENT(SOUND_MIXER_CD, 2, 1, 0, 5, 3, 1, 0, 5, 7),
+ MIX_ENT(SOUND_MIXER_IMIX, 13, 1, 2, 6, 0, 0, 0, 0, 8),
+ MIX_ENT(SOUND_MIXER_ALTPCM, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT(SOUND_MIXER_RECLEV, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT(SOUND_MIXER_IGAIN, 0, 0, 0, 4, 1, 0, 0, 4, 8),
+ MIX_ENT(SOUND_MIXER_OGAIN, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT(SOUND_MIXER_LINE1, 2, 1, 0, 5, 3, 1, 0, 5, 7),
+ MIX_ENT(SOUND_MIXER_LINE2, 4, 1, 0, 5, 5, 1, 0, 5, 7),
+ MIX_ENT(SOUND_MIXER_LINE3, 18, 1, 0, 5, 19, 1, 0, 5, 7)
};
static mixer_ents iwave_mix_devices[32] = {
-MIX_ENT(SOUND_MIXER_VOLUME, 25, 1, 0, 5, 27, 1, 0, 5, 8),
-MIX_ENT(SOUND_MIXER_BASS, 0, 0, 0, 0, 0, 0, 0, 0, 8),
-MIX_ENT(SOUND_MIXER_TREBLE, 0, 0, 0, 0, 0, 0, 0, 0, 8),
-MIX_ENT(SOUND_MIXER_SYNTH, 4, 1, 0, 5, 5, 1, 0, 5, 7),
-MIX_ENT(SOUND_MIXER_PCM, 6, 1, 0, 6, 7, 1, 0, 6, 7),
-MIX_ENT(SOUND_MIXER_SPEAKER, 26, 1, 0, 4, 0, 0, 0, 0, 8),
-MIX_ENT(SOUND_MIXER_LINE, 18, 1, 0, 5, 19, 1, 0, 5, 7),
-MIX_ENT(SOUND_MIXER_MIC, 0, 0, 5, 1, 1, 0, 5, 1, 8),
-MIX_ENT(SOUND_MIXER_CD, 2, 1, 0, 5, 3, 1, 0, 5, 7),
-MIX_ENT(SOUND_MIXER_IMIX, 16, 1, 0, 5, 17, 1, 0, 5, 8),
-MIX_ENT(SOUND_MIXER_ALTPCM, 0, 0, 0, 0, 0, 0, 0, 0, 8),
-MIX_ENT(SOUND_MIXER_RECLEV, 0, 0, 0, 0, 0, 0, 0, 0, 8),
-MIX_ENT(SOUND_MIXER_IGAIN, 0, 0, 0, 4, 1, 0, 0, 4, 8),
-MIX_ENT(SOUND_MIXER_OGAIN, 0, 0, 0, 0, 0, 0, 0, 0, 8),
-MIX_ENT(SOUND_MIXER_LINE1, 2, 1, 0, 5, 3, 1, 0, 5, 7),
-MIX_ENT(SOUND_MIXER_LINE2, 4, 1, 0, 5, 5, 1, 0, 5, 7),
-MIX_ENT(SOUND_MIXER_LINE3, 18, 1, 0, 5, 19, 1, 0, 5, 7)
+ MIX_ENT(SOUND_MIXER_VOLUME, 25, 1, 0, 5, 27, 1, 0, 5, 8),
+ MIX_ENT(SOUND_MIXER_BASS, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT(SOUND_MIXER_TREBLE, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT(SOUND_MIXER_SYNTH, 4, 1, 0, 5, 5, 1, 0, 5, 7),
+ MIX_ENT(SOUND_MIXER_PCM, 6, 1, 0, 6, 7, 1, 0, 6, 7),
+ MIX_ENT(SOUND_MIXER_SPEAKER, 26, 1, 0, 4, 0, 0, 0, 0, 8),
+ MIX_ENT(SOUND_MIXER_LINE, 18, 1, 0, 5, 19, 1, 0, 5, 7),
+ MIX_ENT(SOUND_MIXER_MIC, 0, 0, 5, 1, 1, 0, 5, 1, 8),
+ MIX_ENT(SOUND_MIXER_CD, 2, 1, 0, 5, 3, 1, 0, 5, 7),
+ MIX_ENT(SOUND_MIXER_IMIX, 16, 1, 0, 5, 17, 1, 0, 5, 8),
+ MIX_ENT(SOUND_MIXER_ALTPCM, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT(SOUND_MIXER_RECLEV, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT(SOUND_MIXER_IGAIN, 0, 0, 0, 4, 1, 0, 0, 4, 8),
+ MIX_ENT(SOUND_MIXER_OGAIN, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT(SOUND_MIXER_LINE1, 2, 1, 0, 5, 3, 1, 0, 5, 7),
+ MIX_ENT(SOUND_MIXER_LINE2, 4, 1, 0, 5, 5, 1, 0, 5, 7),
+ MIX_ENT(SOUND_MIXER_LINE3, 18, 1, 0, 5, 19, 1, 0, 5, 7)
+};
+
+static mixer_ents cs42xb_mix_devices[32] = {
+ /* Digital master volume actually has seven bits, but we only use
+ six to avoid the discontinuity when the analog gain kicks in. */
+ MIX_ENT(SOUND_MIXER_VOLUME, 46, 1, 0, 6, 47, 1, 0, 6, 7),
+ MIX_ENT(SOUND_MIXER_BASS, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT(SOUND_MIXER_TREBLE, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT(SOUND_MIXER_SYNTH, 4, 1, 0, 5, 5, 1, 0, 5, 7),
+ MIX_ENT(SOUND_MIXER_PCM, 6, 1, 0, 6, 7, 1, 0, 6, 7),
+ MIX_ENT(SOUND_MIXER_SPEAKER, 26, 1, 0, 4, 0, 0, 0, 0, 8),
+ MIX_ENT(SOUND_MIXER_LINE, 18, 1, 0, 5, 19, 1, 0, 5, 7),
+ MIX_ENT(SOUND_MIXER_MIC, 34, 1, 0, 5, 35, 1, 0, 5, 7),
+ MIX_ENT(SOUND_MIXER_CD, 2, 1, 0, 5, 3, 1, 0, 5, 7),
+ /* For the IMIX entry, it was not possible to use the MIX_ENT macro
+ because the mute bit is in different positions for the two
+ channels and requires reverse polarity. */
+ [SOUND_MIXER_IMIX] = {{13, 1, 2, 6, 13, 1, 0, 0, 0, 8},
+ {42, 1, 0, 6, 42, 1, 7, 0, 0, 8}},
+ MIX_ENT(SOUND_MIXER_ALTPCM, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT(SOUND_MIXER_RECLEV, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT(SOUND_MIXER_IGAIN, 0, 0, 0, 4, 1, 0, 0, 4, 8),
+ MIX_ENT(SOUND_MIXER_OGAIN, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT(SOUND_MIXER_LINE1, 2, 1, 0, 5, 3, 1, 0, 5, 7),
+ MIX_ENT(SOUND_MIXER_LINE2, 4, 1, 0, 5, 5, 1, 0, 5, 7),
+ MIX_ENT(SOUND_MIXER_LINE3, 38, 1, 0, 6, 39, 1, 0, 6, 7)
};
/* OPTi 82C930 has somewhat different port addresses.
@@ -149,68 +175,68 @@ MIX_ENT(SOUND_MIXER_LINE3, 18, 1, 0, 5, 19, 1, 0, 5, 7)
* MIC is level of mic monitoring direct to output. Same for CD, LINE, etc.
*/
static mixer_ents c930_mix_devices[32] = {
-MIX_ENT(SOUND_MIXER_VOLUME, 22, 1, 1, 5, 23, 1, 1, 5, 7),
-MIX_ENT(SOUND_MIXER_BASS, 0, 0, 0, 0, 0, 0, 0, 0, 8),
-MIX_ENT(SOUND_MIXER_TREBLE, 0, 0, 0, 0, 0, 0, 0, 0, 8),
-MIX_ENT(SOUND_MIXER_SYNTH, 4, 1, 1, 4, 5, 1, 1, 4, 7),
-MIX_ENT(SOUND_MIXER_PCM, 6, 1, 0, 5, 7, 1, 0, 5, 7),
-MIX_ENT(SOUND_MIXER_SPEAKER, 22, 1, 1, 5, 23, 1, 1, 5, 7),
-MIX_ENT(SOUND_MIXER_LINE, 18, 1, 1, 4, 19, 1, 1, 4, 7),
-MIX_ENT(SOUND_MIXER_MIC, 20, 1, 1, 4, 21, 1, 1, 4, 7),
-MIX_ENT(SOUND_MIXER_CD, 2, 1, 1, 4, 3, 1, 1, 4, 7),
-MIX_ENT(SOUND_MIXER_IMIX, 0, 0, 0, 0, 0, 0, 0, 0, 8),
-MIX_ENT(SOUND_MIXER_ALTPCM, 0, 0, 0, 0, 0, 0, 0, 0, 8),
-MIX_ENT(SOUND_MIXER_RECLEV, 0, 0, 0, 0, 0, 0, 0, 0, 8),
-MIX_ENT(SOUND_MIXER_IGAIN, 0, 0, 0, 4, 1, 0, 0, 4, 8),
-MIX_ENT(SOUND_MIXER_OGAIN, 0, 0, 0, 0, 0, 0, 0, 0, 8),
-MIX_ENT(SOUND_MIXER_LINE1, 2, 1, 1, 4, 3, 1, 1, 4, 7),
-MIX_ENT(SOUND_MIXER_LINE2, 4, 1, 1, 4, 5, 1, 1, 4, 7),
-MIX_ENT(SOUND_MIXER_LINE3, 18, 1, 1, 4, 19, 1, 1, 4, 7)
+ MIX_ENT(SOUND_MIXER_VOLUME, 22, 1, 1, 5, 23, 1, 1, 5, 7),
+ MIX_ENT(SOUND_MIXER_BASS, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT(SOUND_MIXER_TREBLE, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT(SOUND_MIXER_SYNTH, 4, 1, 1, 4, 5, 1, 1, 4, 7),
+ MIX_ENT(SOUND_MIXER_PCM, 6, 1, 0, 5, 7, 1, 0, 5, 7),
+ MIX_ENT(SOUND_MIXER_SPEAKER, 22, 1, 1, 5, 23, 1, 1, 5, 7),
+ MIX_ENT(SOUND_MIXER_LINE, 18, 1, 1, 4, 19, 1, 1, 4, 7),
+ MIX_ENT(SOUND_MIXER_MIC, 20, 1, 1, 4, 21, 1, 1, 4, 7),
+ MIX_ENT(SOUND_MIXER_CD, 2, 1, 1, 4, 3, 1, 1, 4, 7),
+ MIX_ENT(SOUND_MIXER_IMIX, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT(SOUND_MIXER_ALTPCM, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT(SOUND_MIXER_RECLEV, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT(SOUND_MIXER_IGAIN, 0, 0, 0, 4, 1, 0, 0, 4, 8),
+ MIX_ENT(SOUND_MIXER_OGAIN, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT(SOUND_MIXER_LINE1, 2, 1, 1, 4, 3, 1, 1, 4, 7),
+ MIX_ENT(SOUND_MIXER_LINE2, 4, 1, 1, 4, 5, 1, 1, 4, 7),
+ MIX_ENT(SOUND_MIXER_LINE3, 18, 1, 1, 4, 19, 1, 1, 4, 7)
};
static mixer_ents spro_mix_devices[32] = {
-MIX_ENT (SOUND_MIXER_VOLUME, 19, 0, 4, 4, 19, 0, 0, 4, 8),
-MIX_ENT (SOUND_MIXER_BASS, 0, 0, 0, 0, 0, 0, 0, 0, 8),
-MIX_ENT (SOUND_MIXER_TREBLE, 0, 0, 0, 0, 0, 0, 0, 0, 8),
-MIX_ENT2(SOUND_MIXER_SYNTH, 4, 1, 1, 4, 23, 0, 3, 0, 0, 8,
- 5, 1, 1, 4, 23, 0, 3, 0, 0, 8),
-MIX_ENT (SOUND_MIXER_PCM, 6, 1, 1, 4, 7, 1, 1, 4, 8),
-MIX_ENT (SOUND_MIXER_SPEAKER, 18, 0, 3, 2, 0, 0, 0, 0, 8),
-MIX_ENT2(SOUND_MIXER_LINE, 20, 0, 4, 4, 17, 1, 4, 16, 0, 2,
- 20, 0, 0, 4, 17, 1, 3, 16, 0, 1),
-MIX_ENT2(SOUND_MIXER_MIC, 18, 0, 0, 3, 17, 1, 0, 16, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
-MIX_ENT2(SOUND_MIXER_CD, 21, 0, 4, 4, 17, 1, 2, 16, 0, 4,
- 21, 0, 0, 4, 17, 1, 1, 16, 0, 3),
-MIX_ENT (SOUND_MIXER_IMIX, 0, 0, 0, 0, 0, 0, 0, 0, 8),
-MIX_ENT (SOUND_MIXER_ALTPCM, 0, 0, 0, 0, 0, 0, 0, 0, 8),
-MIX_ENT (SOUND_MIXER_RECLEV, 0, 0, 0, 0, 0, 0, 0, 0, 8),
-MIX_ENT (SOUND_MIXER_IGAIN, 0, 0, 0, 0, 0, 0, 0, 0, 8),
-MIX_ENT (SOUND_MIXER_OGAIN, 17, 1, 6, 1, 0, 0, 0, 0, 8),
-/* This is external wavetable */
-MIX_ENT2(SOUND_MIXER_LINE1, 22, 0, 4, 4, 23, 1, 1, 23, 0, 4,
- 22, 0, 0, 4, 23, 1, 0, 23, 0, 5),
+ MIX_ENT (SOUND_MIXER_VOLUME, 19, 0, 4, 4, 19, 0, 0, 4, 8),
+ MIX_ENT (SOUND_MIXER_BASS, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT (SOUND_MIXER_TREBLE, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT2(SOUND_MIXER_SYNTH, 4, 1, 1, 4, 23, 0, 3, 0, 0, 8,
+ 5, 1, 1, 4, 23, 0, 3, 0, 0, 8),
+ MIX_ENT (SOUND_MIXER_PCM, 6, 1, 1, 4, 7, 1, 1, 4, 8),
+ MIX_ENT (SOUND_MIXER_SPEAKER, 18, 0, 3, 2, 0, 0, 0, 0, 8),
+ MIX_ENT2(SOUND_MIXER_LINE, 20, 0, 4, 4, 17, 1, 4, 16, 0, 2,
+ 20, 0, 0, 4, 17, 1, 3, 16, 0, 1),
+ MIX_ENT2(SOUND_MIXER_MIC, 18, 0, 0, 3, 17, 1, 0, 16, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
+ MIX_ENT2(SOUND_MIXER_CD, 21, 0, 4, 4, 17, 1, 2, 16, 0, 4,
+ 21, 0, 0, 4, 17, 1, 1, 16, 0, 3),
+ MIX_ENT (SOUND_MIXER_IMIX, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT (SOUND_MIXER_ALTPCM, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT (SOUND_MIXER_RECLEV, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT (SOUND_MIXER_IGAIN, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT (SOUND_MIXER_OGAIN, 17, 1, 6, 1, 0, 0, 0, 0, 8),
+ /* This is external wavetable */
+ MIX_ENT2(SOUND_MIXER_LINE1, 22, 0, 4, 4, 23, 1, 1, 23, 0, 4,
+ 22, 0, 0, 4, 23, 1, 0, 23, 0, 5),
};
static int default_mixer_levels[32] =
{
- 0x3232, /* Master Volume */
- 0x3232, /* Bass */
- 0x3232, /* Treble */
- 0x4b4b, /* FM */
- 0x3232, /* PCM */
- 0x1515, /* PC Speaker */
- 0x2020, /* Ext Line */
- 0x1010, /* Mic */
- 0x4b4b, /* CD */
- 0x0000, /* Recording monitor */
- 0x4b4b, /* Second PCM */
- 0x4b4b, /* Recording level */
- 0x4b4b, /* Input gain */
- 0x4b4b, /* Output gain */
- 0x2020, /* Line1 */
- 0x2020, /* Line2 */
- 0x1515 /* Line3 (usually line in)*/
+ 0x3232, /* Master Volume */
+ 0x3232, /* Bass */
+ 0x3232, /* Treble */
+ 0x4b4b, /* FM */
+ 0x3232, /* PCM */
+ 0x1515, /* PC Speaker */
+ 0x2020, /* Ext Line */
+ 0x1010, /* Mic */
+ 0x4b4b, /* CD */
+ 0x0000, /* Recording monitor */
+ 0x4b4b, /* Second PCM */
+ 0x4b4b, /* Recording level */
+ 0x4b4b, /* Input gain */
+ 0x4b4b, /* Output gain */
+ 0x2020, /* Line1 */
+ 0x2020, /* Line2 */
+ 0x1515 /* Line3 (usually line in)*/
};
#define LEFT_CHN 0
diff --git a/drivers/usb/dabusb.c b/drivers/usb/dabusb.c
index b552bf6c3..6607d8f9b 100644
--- a/drivers/usb/dabusb.c
+++ b/drivers/usb/dabusb.c
@@ -224,7 +224,7 @@ static int dabusb_alloc_buffers (pdabusb_t s)
err("kmalloc(sizeof(buff_t))==NULL");
goto err;
}
- memset (b, sizeof (buff_t), 0);
+ memset (b, 0, sizeof (buff_t));
b->s = s;
b->purb = usb_alloc_urb(packets);
if (!b->purb) {
diff --git a/drivers/usb/dc2xx.c b/drivers/usb/dc2xx.c
index 7e0587b10..e8549748a 100644
--- a/drivers/usb/dc2xx.c
+++ b/drivers/usb/dc2xx.c
@@ -112,12 +112,15 @@ static struct usb_device_id camera_table [] = {
/* These have a different application level protocol which
* is part of the Flashpoint "DigitaOS". That supports some
* non-camera devices, and some non-Kodak cameras.
+ * Use this driver to get USB and "OpenDis" to talk.
*/
{ USB_DEVICE(0x040a, 0x0100) }, // Kodak DC-220
{ USB_DEVICE(0x040a, 0x0110) }, // Kodak DC-260
{ USB_DEVICE(0x040a, 0x0111) }, // Kodak DC-265
{ USB_DEVICE(0x040a, 0x0112) }, // Kodak DC-290
{ USB_DEVICE(0xf003, 0x6002) }, // HP PhotoSmart C500
+ { USB_DEVICE(0x03f0, 0x4102) }, // HP PhotoSmart C618
+ { USB_DEVICE(0x0a17, 0x1001) }, // Pentax EI-200
/* Other USB devices may well work here too, so long as they
* just stick to half duplex bulk packet exchanges. That
diff --git a/drivers/usb/hid-core.c b/drivers/usb/hid-core.c
index 47d039e4f..0f462d8dd 100644
--- a/drivers/usb/hid-core.c
+++ b/drivers/usb/hid-core.c
@@ -1236,7 +1236,7 @@ static void* hid_probe(struct usb_device *dev, unsigned int ifnum,
c = "Device";
for (i = 0; i < hid->maxapplication; i++)
- if (IS_INPUT_APPLICATION(hid->application[i])) {
+ if ((hid->application[i] & 0xffff) < ARRAY_SIZE(hid_types)) {
c = hid_types[hid->application[i] & 0xffff];
break;
}
diff --git a/drivers/usb/pwc-ctrl.c b/drivers/usb/pwc-ctrl.c
index ed729fdc6..3d8eb253a 100644
--- a/drivers/usb/pwc-ctrl.c
+++ b/drivers/usb/pwc-ctrl.c
@@ -782,7 +782,7 @@ int pwc_camera_power(struct pwc_device *pdev, int power)
{
char buf;
- if (pdev->type < 675 || pdev->release < 6)
+ if (pdev->type < 675 || (pdev->type < 730 && pdev->release < 6))
return 0; /* Not supported by Nala or Timon < release 6 */
if (power)
diff --git a/drivers/usb/pwc-if.c b/drivers/usb/pwc-if.c
index 5325cafa1..7acd2d2be 100644
--- a/drivers/usb/pwc-if.c
+++ b/drivers/usb/pwc-if.c
@@ -91,6 +91,8 @@ static struct usb_driver pwc_driver =
disconnect: usb_pwc_disconnect, /* disconnect() */
};
+#define MAX_DEV_HINTS 10
+
static int default_size = PSZ_QCIF;
static int default_fps = 10;
static int default_palette = VIDEO_PALETTE_YUV420P; /* This format is understood by most tools */
@@ -99,13 +101,17 @@ static int default_mbufs = 2; /* Default number of mmap() buffers */
int pwc_trace = TRACE_MODULE | TRACE_FLOW | TRACE_PWCX;
static int power_save = 0;
static int led_on = 1, led_off = 0; /* defaults to LED that is on while in use */
-int pwc_preferred_compression = 2; /* 0..3 = uncompressed..high */
+ int pwc_preferred_compression = 2; /* 0..3 = uncompressed..high */
+static struct {
+ int type;
+ char serial_number[30];
+ int device_node;
+ struct pwc_device *pdev;
+} device_hint[MAX_DEV_HINTS];
static struct semaphore mem_lock;
static void *mem_leak = NULL; /* For delayed kfree()s. See below */
-static int video_nr = -1;
-
/***/
static int pwc_video_open(struct video_device *vdev, int mode);
@@ -647,7 +653,8 @@ static void pwc_isoc_handler(purb_t urb)
errmsg = "Unknown";
switch(urb->status) {
case -ENOSR: errmsg = "Buffer error (overrun)"; break;
- case -EPIPE: errmsg = "Babble/stalled (bad cable?)"; break;
+ case -EPIPE: errmsg = "Stalled (device not responding)"; break;
+ case -EOVERFLOW: errmsg = "Babble (bad cable?)"; break;
case -EPROTO: errmsg = "Bit-stuff error (bad cable?)"; break;
case -EILSEQ: errmsg = "CRC/Timeout"; break;
case -ETIMEDOUT: errmsg = "NAK (device does not respond)"; break;
@@ -765,6 +772,11 @@ static void pwc_isoc_handler(purb_t urb)
} /* .. flen < last_packet_size */
pdev->vlast_packet_size = flen;
} /* ..status == 0 */
+#ifdef PWC_DEBUG
+ /* This is normally not interesting to the user, unless you are really debugging something */
+ else
+ Trace(TRACE_FLOW, "Iso frame %d of USB has error %d\n", i, fst);
+#endif
}
if (awake)
wake_up_interruptible(&pdev->frameq);
@@ -1140,7 +1152,7 @@ static long pwc_video_read(struct video_device *vdev, char *buf, unsigned long c
return -ERESTARTSYS;
}
schedule();
- set_current_state(TASK_INTERRUPTIBLE);
+ set_current_state(TASK_INTERRUPTIBLE);
}
remove_wait_queue(&pdev->frameq, &wait);
set_current_state(TASK_RUNNING);
@@ -1595,7 +1607,9 @@ static void *usb_pwc_probe(struct usb_device *udev, unsigned int ifnum, const st
struct pwc_device *pdev = NULL;
struct video_device *vdev;
int vendor_id, product_id, type_id;
- int i;
+ int i, hint;
+ int video_nr = -1; /* default: use next available device */
+ char serial_number[30];
free_mem_leak();
@@ -1698,6 +1712,10 @@ static void *usb_pwc_probe(struct usb_device *udev, unsigned int ifnum, const st
}
else return NULL; /* Not Philips, Askey, Logitech or Samsung, for sure. */
+ memset(serial_number, 0, 30);
+ usb_string(udev, udev->descriptor.iSerialNumber, serial_number, 29);
+ Trace(TRACE_PROBE, "Device serial number is %s\n", serial_number);
+
if (udev->descriptor.bNumConfigurations > 1)
Info("Warning: more than 1 configuration available.\n");
@@ -1734,6 +1752,21 @@ static void *usb_pwc_probe(struct usb_device *udev, unsigned int ifnum, const st
pdev->release = udev->descriptor.bcdDevice;
Trace(TRACE_PROBE, "Release: %04x\n", pdev->release);
+
+ /* Now search device_hint[] table for a match, so we can hint a node number. */
+ for (hint = 0; hint < MAX_DEV_HINTS; hint++) {
+ if (((device_hint[hint].type == -1) || (device_hint[hint].type == pdev->type)) &&
+ (device_hint[hint].pdev == NULL)) {
+ /* so far, so good... try serial number */
+ if ((device_hint[hint].serial_number[0] == '*') || !strcmp(device_hint[hint].serial_number, serial_number)) {
+ /* match! */
+ video_nr = device_hint[hint].device_node;
+ Trace(TRACE_PROBE, "Found hint, will try to register as /dev/video%d\n", video_nr);
+ break;
+ }
+ }
+ }
+
i = video_register_device(vdev, VFL_TYPE_GRABBER, video_nr);
if (i < 0) {
Err("Failed to register as video device (%d).\n", i);
@@ -1743,6 +1776,9 @@ static void *usb_pwc_probe(struct usb_device *udev, unsigned int ifnum, const st
Trace(TRACE_PROBE, "Registered video struct at 0x%p.\n", vdev);
Info("Registered as /dev/video%d.\n", vdev->minor & 0x3F);
}
+ /* occupy slot */
+ if (hint < MAX_DEV_HINTS)
+ device_hint[hint].pdev = pdev;
#if 0
/* Shut down camera now (some people like the LED off) */
@@ -1762,6 +1798,7 @@ static void *usb_pwc_probe(struct usb_device *udev, unsigned int ifnum, const st
static void usb_pwc_disconnect(struct usb_device *udev, void *ptr)
{
struct pwc_device *pdev;
+ int hint;
lock_kernel();
free_mem_leak();
@@ -1815,12 +1852,31 @@ static void usb_pwc_disconnect(struct usb_device *udev, void *ptr)
pdev->vdev = NULL;
}
}
+
+ /* search device_hint[] table if we occupy a slot, by any chance */
+ for (hint = 0; hint < MAX_DEV_HINTS; hint++)
+ if (device_hint[hint].pdev == pdev)
+ device_hint[hint].pdev = NULL;
+
pdev->udev = NULL;
unlock_kernel();
kfree(pdev);
}
+/* *grunt* We have to do atoi ourselves :-( */
+static int pwc_atoi(char *s)
+{
+ int k = 0;
+
+ k = 0;
+ while (*s != '\0' && *s >= '0' && *s <= '9') {
+ k = 10 * k + (*s - '0');
+ s++;
+ }
+ return k;
+}
+
/*
* Initialization code & module stuff
@@ -1833,8 +1889,8 @@ static int mbufs = 0;
static int trace = -1;
static int compression = -1;
static int leds[2] = { -1, -1 };
+static char *dev_hint[10] = { };
-MODULE_PARM(video_nr, "i");
MODULE_PARM(size, "s");
MODULE_PARM_DESC(size, "Initial image size. One of sqcif, qsif, qcif, sif, cif, vga");
MODULE_PARM(fps, "i");
@@ -1851,13 +1907,16 @@ MODULE_PARM(compression, "i");
MODULE_PARM_DESC(compression, "Preferred compression quality. Range 0 (uncompressed) to 3 (high compression)");
MODULE_PARM(leds, "2i");
MODULE_PARM_DESC(leds, "LED on,off time in milliseconds");
+MODULE_PARM(dev_hint, "0-10s");
+MODULE_PARM_DESC(dev_hint, "Device node hints");
+
MODULE_DESCRIPTION("Philips USB webcam driver");
MODULE_AUTHOR("Nemosoft Unv. <nemosoft@smcc.demon.nl>");
MODULE_LICENSE("GPL");
static int __init usb_pwc_init(void)
{
- int s;
+ int i, sz;
char *sizenames[PSZ_MAX] = { "sqcif", "qsif", "qcif", "sif", "cif", "vga" };
Info("Philips PCA645/646 + PCVC675/680/690 + PCVC730/740/750 webcam module version " PWC_VERSION " loaded.\n");
@@ -1874,13 +1933,13 @@ static int __init usb_pwc_init(void)
if (size) {
/* string; try matching with array */
- for (s = 0; s < PSZ_MAX; s++) {
- if (!strcmp(sizenames[s], size)) { /* Found! */
- default_size = s;
+ for (sz = 0; sz < PSZ_MAX; sz++) {
+ if (!strcmp(sizenames[sz], size)) { /* Found! */
+ default_size = sz;
break;
}
}
- if (s == PSZ_MAX) {
+ if (sz == PSZ_MAX) {
Err("Size not recognized; try size=[sqcif | qsif | qcif | sif | cif | vga].\n");
return -EINVAL;
}
@@ -1921,6 +1980,74 @@ static int __init usb_pwc_init(void)
if (leds[1] >= 0)
led_off = leds[1] / 100;
+ /* Big device node whoopla. Basicly, it allows you to assign a
+ device node (/dev/videoX) to a camera, based on its type
+ & serial number. The format is [type[.serialnumber]:]node.
+
+ Any camera that isn't matched by these rules gets the next
+ available free device node.
+ */
+ for (i = 0; i < MAX_DEV_HINTS; i++) {
+ char *s, *colon, *dot;
+
+ /* This loop also initializes the array */
+ device_hint[i].pdev = NULL;
+ s = dev_hint[i];
+ if (s != NULL && *s != '\0') {
+ device_hint[i].type = -1; /* wildcard */
+ strcpy(device_hint[i].serial_number, "*");
+
+ /* parse string: chop at ':' & '/' */
+ colon = dot = s;
+ while (*colon != '\0' && *colon != ':')
+ colon++;
+ while (*dot != '\0' && *dot != '.')
+ dot++;
+ /* Few sanity checks */
+ if (*dot != '\0' && dot > colon) {
+ Err("Malformed camera hint: the colon must be after the dot.\n");
+ return -EINVAL;
+ }
+
+ if (*colon == '\0') {
+ /* No colon */
+ if (*dot != '\0') {
+ Err("Malformed camera hint: no colon + device node given.\n");
+ return -EINVAL;
+ }
+ else {
+ /* No type or serial number specified, just a number. */
+ device_hint[i].device_node = pwc_atoi(s);
+ }
+ }
+ else {
+ /* There's a colon, so we have at least a type and a device node */
+ device_hint[i].type = pwc_atoi(s);
+ device_hint[i].device_node = pwc_atoi(colon + 1);
+ if (*dot != '\0') {
+ /* There's a serial number as well */
+ int k;
+
+ dot++;
+ k = 0;
+ while (*dot != ':' && k < 29) {
+ device_hint[i].serial_number[k++] = *dot;
+ dot++;
+ }
+ device_hint[i].serial_number[k] = '\0';
+ }
+ }
+#ifdef PWC_DEBUG
+ Debug("device_hint[%d]:\n", i);
+ Debug(" type : %d\n", device_hint[i].type);
+ Debug(" serial# : %s\n", device_hint[i].serial_number);
+ Debug(" node : %d\n", device_hint[i].device_node);
+#endif
+ }
+ else
+ device_hint[i].type = 0; /* not filled */
+ } /* ..for MAX_DEV_HINTS */
+
init_MUTEX(&mem_lock);
Trace(TRACE_PROBE, "Registering driver at address 0x%p.\n", &pwc_driver);
return usb_register(&pwc_driver);
diff --git a/drivers/usb/pwc.h b/drivers/usb/pwc.h
index 054d369db..40bfb2784 100644
--- a/drivers/usb/pwc.h
+++ b/drivers/usb/pwc.h
@@ -60,8 +60,8 @@
/* Version block */
#define PWC_MAJOR 8
-#define PWC_MINOR 3
-#define PWC_VERSION "8.3"
+#define PWC_MINOR 4
+#define PWC_VERSION "8.4"
#define PWC_NAME "pwc"
/* Turn certain features on/off */
diff --git a/drivers/usb/scanner.c b/drivers/usb/scanner.c
index ed98f11f4..e686f6f42 100644
--- a/drivers/usb/scanner.c
+++ b/drivers/usb/scanner.c
@@ -278,6 +278,28 @@
* - Users are now notified to consult the Documentation/usb/scanner.txt
* for common error messages rather than the maintainer.
*
+ * 0.4.7 11/28/2001
+ * - Fixed typo in Documentation/scanner.txt. Thanks to
+ * Karel <karel.vervaeke@pandora.be> for pointing it out.
+ * - Added ID's for a Memorex 6136u. Thanks to Álvaro Gaspar de
+ * Valenzuela" <agaspard@utsi.edu>.
+ * - Added ID's for Agfa e25. Thanks to Heinrich
+ * Rust <Heinrich.Rust@gmx.de>. Also reported to work with
+ * Linux and SANE (?).
+ * - Added Canon FB620U, D646U, and 1220U ID's. Thanks to Paul
+ * Rensing <Paul_Rensing@StanfordAlumni.org>. For more info
+ * on Linux support for these models, contact
+ * salvestrini@users.sourceforge.net.
+ * - Added Plustek OpticPro UT12, OpticPro U24, KYE/Genius
+ * ColorPage-HR6 V2 ID's in addition to many "Unknown" models
+ * under those vendors. Thanks to
+ * Jaeger, Gerhard" <g.jaeger@earthling.net>. These scanner are
+ * apparently based upon the LM983x IC's.
+ * - Applied Frank's patch that addressed some locking and module
+ * referencing counts. Thanks to both
+ * Frank Zago <fzago@greshamstorage.com> and
+ * Oliver Neukum <520047054719-0001@t-online.de> for reviewing/testing.
+ *
* TODO
* - Performance
* - Select/poll methods
@@ -324,17 +346,16 @@ irq_scanner(struct urb *urb)
struct scn_usb_data *scn;
unsigned char *data;
scn = urb->context;
- down(&(scn->sem));
+
data = &scn->button;
data += 0; /* Keep gcc from complaining about unused var */
if (urb->status) {
- up(&(scn->sem));
return;
}
dbg("irq_scanner(%d): data:%x", scn->scn_minor, *data);
- up(&(scn->sem));
+
return;
}
@@ -358,6 +379,7 @@ open_scanner(struct inode * inode, struct file * file)
if (!p_scn_table[scn_minor]) {
up(&scn_mutex);
+ MOD_DEC_USE_COUNT;
err("open_scanner(%d): Unable to access minor data", scn_minor);
return -ENODEV;
}
@@ -939,6 +961,7 @@ probe_scanner(struct usb_device *dev, unsigned int ifnum,
/* Check to make sure that the last slot isn't already taken */
if (p_scn_table[scn_minor]) {
err("probe_scanner: No more minor devices remaining.");
+ up(&scn_mutex);
return NULL;
}
@@ -946,6 +969,7 @@ probe_scanner(struct usb_device *dev, unsigned int ifnum,
if (!(scn = kmalloc (sizeof (struct scn_usb_data), GFP_KERNEL))) {
err("probe_scanner: Out of memory.");
+ up(&scn_mutex);
return NULL;
}
memset (scn, 0, sizeof(struct scn_usb_data));
@@ -1028,9 +1052,11 @@ probe_scanner(struct usb_device *dev, unsigned int ifnum,
if (scn->devfs == NULL)
dbg("scanner%d: device node registration failed", scn_minor);
+ p_scn_table[scn_minor] = scn;
+
up(&scn_mutex);
- return p_scn_table[scn_minor] = scn;
+ return scn;
}
static void
diff --git a/drivers/usb/scanner.h b/drivers/usb/scanner.h
index ca10402fb..2b03ce8f6 100644
--- a/drivers/usb/scanner.h
+++ b/drivers/usb/scanner.h
@@ -86,12 +86,23 @@ static struct usb_device_id scanner_device_ids [] = {
{ USB_DEVICE(0x06bd, 0x2061) }, /* Another SnapScan 1212U (?)*/
{ USB_DEVICE(0x06bd, 0x0100) }, /* SnapScan Touch */
{ USB_DEVICE(0x06bd, 0x2091) }, /* SnapScan e20 */
+ { USB_DEVICE(0x06bd, 0x2095) }, /* SnapScan e25 */
{ USB_DEVICE(0x06bd, 0x2097) }, /* SnapScan e26 */
{ USB_DEVICE(0x06bd, 0x208d) }, /* Snapscan e40 */
+ /* Canon */
+ { USB_DEVICE(0x04a9, 0x2202) }, /* FB620U */
+ { USB_DEVICE(0x04a9, 0x220b) }, /* D646U */
+ { USB_DEVICE(0x04a9, 0x2207) }, /* 1220U */
/* Colorado -- See Primax/Colorado below */
/* Epson -- See Seiko/Epson below */
/* Genius */
{ USB_DEVICE(0x0458, 0x2001) }, /* ColorPage-Vivid Pro */
+ { USB_DEVICE(0x0458, 0x2007) }, /* ColorPage HR6 V2 */
+ { USB_DEVICE(0x0458, 0x2008) }, /* Unknown */
+ { USB_DEVICE(0x0458, 0x2009) }, /* Unknown */
+ { USB_DEVICE(0x0458, 0x2013) }, /* Unknown */
+ { USB_DEVICE(0x0458, 0x2015) }, /* Unknown */
+ { USB_DEVICE(0x0458, 0x2016) }, /* Unknown */
/* Hewlett Packard */
{ USB_DEVICE(0x03f0, 0x0205) }, /* 3300C */
{ USB_DEVICE(0x03f0, 0x0405) }, /* 3400C */
@@ -108,6 +119,8 @@ static struct usb_device_id scanner_device_ids [] = {
{ USB_DEVICE(0x0638, 0x0268) }, /* 1200U */
/* Lifetec */
{ USB_DEVICE(0x05d8, 0x4002) }, /* Lifetec LT9385 */
+ /* Memorex */
+ { USB_DEVICE(0x0461, 0x0346) }, /* 6136u - repackaged Primax ? */
/* Microtek -- No longer supported - Enable SCSI and USB Microtek in kernel config */
// { USB_DEVICE(0x05da, 0x0099) }, /* ScanMaker X6 - X6U */
// { USB_DEVICE(0x05da, 0x0094) }, /* Phantom 336CX - C3 */
@@ -128,6 +141,19 @@ static struct usb_device_id scanner_device_ids [] = {
{ USB_DEVICE(0x0400, 0x1001) }, /* BearPaw 2400 */
{ USB_DEVICE(0x055f, 0x0008) }, /* 1200 CU Plus */
{ USB_DEVICE(0x0ff5, 0x0010) }, /* BearPaw 1200F */
+ /* Plustek */
+ { USB_DEVICE(0x07b3, 0x0017) }, /* OpticPro UT12 */
+ { USB_DEVICE(0x07b3, 0x0011) }, /* OpticPro UT24 */
+ { USB_DEVICE(0x07b3, 0x0005) }, /* Unknown */
+ { USB_DEVICE(0x07b3, 0x0007) }, /* Unknown */
+ { USB_DEVICE(0x07b3, 0x000F) }, /* Unknown */
+ { USB_DEVICE(0x07b3, 0x0010) }, /* Unknown */
+ { USB_DEVICE(0x07b3, 0x0012) }, /* Unknown */
+ { USB_DEVICE(0x07b3, 0x0013) }, /* Unknown */
+ { USB_DEVICE(0x07b3, 0x0014) }, /* Unknown */
+ { USB_DEVICE(0x07b3, 0x0015) }, /* Unknown */
+ { USB_DEVICE(0x07b3, 0x0016) }, /* Unknown */
+ { USB_DEVICE(0x07b3, 0x0012) }, /* Unknown */
/* Primax/Colorado */
{ USB_DEVICE(0x0461, 0x0300) }, /* G2-300 #1 */
{ USB_DEVICE(0x0461, 0x0380) }, /* G2-600 #1 */
diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c
index 5bfa8be90..1191ecb95 100644
--- a/drivers/usb/serial/belkin_sa.c
+++ b/drivers/usb/serial/belkin_sa.c
@@ -140,7 +140,7 @@ static __devinitdata struct usb_device_id gocom232_table [] = {
MODULE_DEVICE_TABLE (usb, id_table_combined);
/* All of the device info needed for the Belkin dockstation serial converter */
-struct usb_serial_device_type belkin_dockstation_device = {
+static struct usb_serial_device_type belkin_dockstation_device = {
name: "Belkin F5U120-PC USB Serial Adapter",
id_table: belkin_dockstation_table, /* the Belkin F5U103 device */
needs_interrupt_in: MUST_HAVE, /* this device must have an interrupt in endpoint */
@@ -161,7 +161,7 @@ struct usb_serial_device_type belkin_dockstation_device = {
};
/* All of the device info needed for the Belkin serial converter */
-struct usb_serial_device_type belkin_sa_device = {
+static struct usb_serial_device_type belkin_sa_device = {
name: "Belkin F5U103 USB Serial Adapter",
id_table: belkin_sa_table, /* the Belkin F5U103 device */
needs_interrupt_in: MUST_HAVE, /* this device must have an interrupt in endpoint */
@@ -183,7 +183,7 @@ struct usb_serial_device_type belkin_sa_device = {
/* This driver also supports the "old" school Belkin single port adaptor */
-struct usb_serial_device_type belkin_old_device = {
+static struct usb_serial_device_type belkin_old_device = {
name: "Belkin USB Serial Adapter",
id_table: belkin_old_table, /* the old Belkin device */
needs_interrupt_in: MUST_HAVE, /* this device must have an interrupt in endpoint */
@@ -204,7 +204,7 @@ struct usb_serial_device_type belkin_old_device = {
};
/* this driver also works for the Peracom single port adapter */
-struct usb_serial_device_type peracom_device = {
+static struct usb_serial_device_type peracom_device = {
name: "Peracom single port USB Serial Adapter",
id_table: peracom_table, /* the Peracom device */
needs_interrupt_in: MUST_HAVE, /* this device must have an interrupt in endpoint */
@@ -225,7 +225,7 @@ struct usb_serial_device_type peracom_device = {
};
/* the GoHubs Go-COM232 device is the same as the Peracom single port adapter */
-struct usb_serial_device_type gocom232_device = {
+static struct usb_serial_device_type gocom232_device = {
name: "GO-COM232 USB Serial Converter",
id_table: gocom232_table, /* the GO-COM232 device */
needs_interrupt_in: MUST_HAVE, /* this device must have an interrupt in endpoint */
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
index c02505741..7c9d1f2b5 100644
--- a/drivers/usb/serial/cyberjack.c
+++ b/drivers/usb/serial/cyberjack.c
@@ -76,7 +76,7 @@ static __devinitdata struct usb_device_id id_table [] = {
MODULE_DEVICE_TABLE (usb, id_table);
-struct usb_serial_device_type cyberjack_device = {
+static struct usb_serial_device_type cyberjack_device = {
name: "Reiner SCT Cyberjack USB card reader",
id_table: id_table,
needs_interrupt_in: MUST_HAVE,
diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c
index b9799c000..a476bfab0 100644
--- a/drivers/usb/serial/empeg.c
+++ b/drivers/usb/serial/empeg.c
@@ -113,7 +113,7 @@ static __devinitdata struct usb_device_id id_table [] = {
MODULE_DEVICE_TABLE (usb, id_table);
-struct usb_serial_device_type empeg_device = {
+static struct usb_serial_device_type empeg_device = {
name: "Empeg",
id_table: id_table,
needs_interrupt_in: MUST_HAVE_NOT, /* must not have an interrupt in endpoint */
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index b5be01825..23aabea52 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -173,7 +173,7 @@ static void ftdi_sio_break_ctl (struct usb_serial_port *port, int break_state )
/* Should rename most ftdi_sio's to ftdi_ now since there are two devices
which share common code */
-struct usb_serial_device_type ftdi_sio_device = {
+static struct usb_serial_device_type ftdi_sio_device = {
name: "FTDI SIO",
id_table: id_table_sio,
needs_interrupt_in: MUST_HAVE_NOT,
@@ -196,7 +196,7 @@ struct usb_serial_device_type ftdi_sio_device = {
shutdown: ftdi_sio_shutdown,
};
-struct usb_serial_device_type ftdi_8U232AM_device = {
+static struct usb_serial_device_type ftdi_8U232AM_device = {
name: "FTDI 8U232AM",
id_table: id_table_8U232AM,
needs_interrupt_in: DONT_CARE,
@@ -660,7 +660,7 @@ static void ftdi_sio_read_bulk_callback (struct urb *urb)
} /* ftdi_sio_serial_read_bulk_callback */
-__u16 translate_baudrate_to_ftdi(unsigned int cflag, ftdi_type_t ftdi_type)
+static __u16 translate_baudrate_to_ftdi(unsigned int cflag, ftdi_type_t ftdi_type)
{ /* translate_baudrate_to_ftdi */
__u16 urb_value = ftdi_sio_b9600;
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index 9d898e892..4203f6fde 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -318,11 +318,6 @@ enum RXSTATE {
};
-/* the info for all of the devices that this driver supports */
-int EdgeportDevices[] = EDGEPORT_DEVICE_IDS;
-#define NUM_EDGEPORT_DEVICES (sizeof(EdgeportDevices) / sizeof(int))
-
-
/* Transmit Fifo
* This Transmit queue is an extension of the edgeport Rx buffer.
* The maximum amount of data buffered in both the edgeport
@@ -495,17 +490,15 @@ static void unicode_to_ascii (char *string, short *unicode, int unicode_size);
// ************************************************************************
// ************************************************************************
-// These functions should be in firmware.c
-
/************************************************************************
* *
- * update_edgeport_E2PROM() Compare current versions of *
+ * update_edgeport_E2PROM() Compare current versions of *
* Boot ROM and Manufacture *
* Descriptors with versions *
* embedded in this driver *
* *
************************************************************************/
-void update_edgeport_E2PROM (struct edgeport_serial *edge_serial)
+static void update_edgeport_E2PROM (struct edgeport_serial *edge_serial)
{
__u32 BootCurVer;
__u32 BootNewVer;
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
index 412d3d01e..d5dd6ca6c 100644
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -176,7 +176,7 @@ struct keyspan_port_private {
/* Functions used by new usb-serial code. */
-int keyspan_init (void)
+static int __init keyspan_init (void)
{
usb_serial_register (&keyspan_usa18x_pre_device);
usb_serial_register (&keyspan_usa19_pre_device);
@@ -201,7 +201,7 @@ int keyspan_init (void)
return 0;
}
-void keyspan_exit (void)
+static void __exit keyspan_exit (void)
{
usb_serial_deregister (&keyspan_usa18x_pre_device);
usb_serial_deregister (&keyspan_usa19_pre_device);
@@ -1089,7 +1089,7 @@ static urb_t *keyspan_setup_urb(struct usb_serial *serial, int endpoint,
return urb;
}
-struct callbacks {
+static struct callbacks {
void (*instat_callback)(urb_t *);
void (*glocont_callback)(urb_t *);
void (*indat_callback)(urb_t *);
diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h
index 9661f1776..e3e15967e 100644
--- a/drivers/usb/serial/keyspan.h
+++ b/drivers/usb/serial/keyspan.h
@@ -448,7 +448,7 @@ static __devinitdata struct usb_device_id keyspan_usa49w_ids[] = {
};
/* Structs for the devices, pre and post renumeration. */
-struct usb_serial_device_type keyspan_usa18x_pre_device = {
+static struct usb_serial_device_type keyspan_usa18x_pre_device = {
name: "Keyspan USA18X - (without firmware)",
id_table: keyspan_usa18x_pre_ids,
needs_interrupt_in: DONT_CARE,
@@ -461,7 +461,7 @@ struct usb_serial_device_type keyspan_usa18x_pre_device = {
startup: keyspan_fake_startup
};
-struct usb_serial_device_type keyspan_usa19_pre_device = {
+static struct usb_serial_device_type keyspan_usa19_pre_device = {
name: "Keyspan USA19 - (without firmware)",
id_table: keyspan_usa19_pre_ids,
needs_interrupt_in: DONT_CARE,
@@ -475,7 +475,7 @@ struct usb_serial_device_type keyspan_usa19_pre_device = {
};
-struct usb_serial_device_type keyspan_usa19w_pre_device = {
+static struct usb_serial_device_type keyspan_usa19w_pre_device = {
name: "Keyspan USA19W - (without firmware)",
id_table: keyspan_usa19w_pre_ids,
needs_interrupt_in: DONT_CARE,
@@ -489,7 +489,7 @@ struct usb_serial_device_type keyspan_usa19w_pre_device = {
};
-struct usb_serial_device_type keyspan_usa28_pre_device = {
+static struct usb_serial_device_type keyspan_usa28_pre_device = {
name: "Keyspan USA28 - (without firmware)",
id_table: keyspan_usa28_pre_ids,
needs_interrupt_in: DONT_CARE,
@@ -502,7 +502,7 @@ struct usb_serial_device_type keyspan_usa28_pre_device = {
startup: keyspan_fake_startup
};
-struct usb_serial_device_type keyspan_usa28x_pre_device = {
+static struct usb_serial_device_type keyspan_usa28x_pre_device = {
name: "Keyspan USA28X - (without firmware)",
id_table: keyspan_usa28x_pre_ids,
needs_interrupt_in: DONT_CARE,
@@ -515,7 +515,7 @@ struct usb_serial_device_type keyspan_usa28x_pre_device = {
startup: keyspan_fake_startup
};
-struct usb_serial_device_type keyspan_usa28xa_pre_device = {
+static struct usb_serial_device_type keyspan_usa28xa_pre_device = {
name: "Keyspan USA28XA - (without firmware)",
id_table: keyspan_usa28xa_pre_ids,
needs_interrupt_in: DONT_CARE,
@@ -528,7 +528,7 @@ struct usb_serial_device_type keyspan_usa28xa_pre_device = {
startup: keyspan_fake_startup
};
-struct usb_serial_device_type keyspan_usa28xb_pre_device = {
+static struct usb_serial_device_type keyspan_usa28xb_pre_device = {
name: "Keyspan USA28XB - (without firmware)",
id_table: keyspan_usa28xb_pre_ids,
needs_interrupt_in: DONT_CARE,
@@ -541,7 +541,7 @@ struct usb_serial_device_type keyspan_usa28xb_pre_device = {
startup: keyspan_fake_startup
};
-struct usb_serial_device_type keyspan_usa49w_pre_device = {
+static struct usb_serial_device_type keyspan_usa49w_pre_device = {
name: "Keyspan USA49W - (without firmware)",
id_table: keyspan_usa49w_pre_ids,
needs_interrupt_in: DONT_CARE,
@@ -554,7 +554,7 @@ struct usb_serial_device_type keyspan_usa49w_pre_device = {
startup: keyspan_fake_startup
};
-struct usb_serial_device_type keyspan_usa18x_device = {
+static struct usb_serial_device_type keyspan_usa18x_device = {
name: "Keyspan USA18X",
id_table: keyspan_usa18x_ids,
needs_interrupt_in: DONT_CARE,
@@ -580,7 +580,7 @@ struct usb_serial_device_type keyspan_usa18x_device = {
shutdown: keyspan_shutdown,
};
-struct usb_serial_device_type keyspan_usa19_device = {
+static struct usb_serial_device_type keyspan_usa19_device = {
name: "Keyspan USA19",
id_table: keyspan_usa19_ids,
needs_interrupt_in: DONT_CARE,
@@ -607,7 +607,7 @@ struct usb_serial_device_type keyspan_usa19_device = {
};
-struct usb_serial_device_type keyspan_usa19w_device = {
+static struct usb_serial_device_type keyspan_usa19w_device = {
name: "Keyspan USA19W",
id_table: keyspan_usa19w_ids,
needs_interrupt_in: DONT_CARE,
@@ -634,7 +634,7 @@ struct usb_serial_device_type keyspan_usa19w_device = {
};
-struct usb_serial_device_type keyspan_usa28_device = {
+static struct usb_serial_device_type keyspan_usa28_device = {
name: "Keyspan USA28",
id_table: keyspan_usa28_ids,
needs_interrupt_in: DONT_CARE,
@@ -652,7 +652,7 @@ struct usb_serial_device_type keyspan_usa28_device = {
};
-struct usb_serial_device_type keyspan_usa28x_device = {
+static struct usb_serial_device_type keyspan_usa28x_device = {
name: "Keyspan USA28X/XB",
id_table: keyspan_usa28x_ids,
needs_interrupt_in: DONT_CARE,
@@ -679,7 +679,7 @@ struct usb_serial_device_type keyspan_usa28x_device = {
};
-struct usb_serial_device_type keyspan_usa28xa_device = {
+static struct usb_serial_device_type keyspan_usa28xa_device = {
name: "Keyspan USA28XA",
id_table: keyspan_usa28xa_ids,
needs_interrupt_in: DONT_CARE,
@@ -706,7 +706,7 @@ struct usb_serial_device_type keyspan_usa28xa_device = {
};
-struct usb_serial_device_type keyspan_usa49w_device = {
+static struct usb_serial_device_type keyspan_usa49w_device = {
name: "Keyspan USA49W",
id_table: keyspan_usa49w_ids,
needs_interrupt_in: DONT_CARE,
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index a9fdf4a3a..6caac1bcd 100644
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -154,7 +154,7 @@ static __devinitdata struct usb_device_id mct_u232_du_h3sp_table [] = {
MODULE_DEVICE_TABLE (usb, id_table_combined);
-struct usb_serial_device_type mct_u232_device = {
+static struct usb_serial_device_type mct_u232_device = {
name: "Magic Control Technology USB-RS232",
id_table: mct_u232_table,
needs_interrupt_in: MUST_HAVE, /* 2 interrupt-in endpoints */
@@ -178,7 +178,7 @@ struct usb_serial_device_type mct_u232_device = {
shutdown: mct_u232_shutdown,
};
-struct usb_serial_device_type mct_u232_sitecom_device = {
+static struct usb_serial_device_type mct_u232_sitecom_device = {
name: "MCT/Sitecom USB-RS232",
id_table: mct_u232_sitecom_table,
needs_interrupt_in: MUST_HAVE, /* 2 interrupt-in endpoints */
@@ -202,7 +202,7 @@ struct usb_serial_device_type mct_u232_sitecom_device = {
shutdown: mct_u232_shutdown,
};
-struct usb_serial_device_type mct_u232_du_h3sp_device = {
+static struct usb_serial_device_type mct_u232_du_h3sp_device = {
name: "MCT/D-Link DU-H3SP USB BAY",
id_table: mct_u232_du_h3sp_table,
needs_interrupt_in: MUST_HAVE, /* 2 interrupt-in endpoints */
diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c
index 0a73ea0b1..07ee634b3 100644
--- a/drivers/usb/serial/omninet.c
+++ b/drivers/usb/serial/omninet.c
@@ -87,7 +87,7 @@ static __devinitdata struct usb_device_id id_table [] = {
MODULE_DEVICE_TABLE (usb, id_table);
-struct usb_serial_device_type zyxel_omninet_device = {
+static struct usb_serial_device_type zyxel_omninet_device = {
name: "ZyXEL - omni.net lcd plus usb",
id_table: id_table,
needs_interrupt_in: MUST_HAVE,
diff --git a/drivers/usb/serial/usbserial.c b/drivers/usb/serial/usbserial.c
index 41655a956..b492bb672 100644
--- a/drivers/usb/serial/usbserial.c
+++ b/drivers/usb/serial/usbserial.c
@@ -397,7 +397,7 @@ static struct termios * serial_termios_locked[SERIAL_TTY_MINORS];
static struct usb_serial *serial_table[SERIAL_TTY_MINORS]; /* initially all NULL */
-LIST_HEAD(usb_serial_driver_list);
+static LIST_HEAD(usb_serial_driver_list);
static struct usb_serial *get_serial_by_minor (int minor)
@@ -1433,7 +1433,7 @@ static struct tty_driver serial_tty_driver = {
};
-int usb_serial_init(void)
+static int __init usb_serial_init(void)
{
int i;
int result;
@@ -1473,7 +1473,7 @@ int usb_serial_init(void)
}
-void usb_serial_exit(void)
+static void __exit usb_serial_exit(void)
{
#ifdef CONFIG_USB_SERIAL_GENERIC
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index 98bcc37b6..8c2d37c7e 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -184,7 +184,7 @@ MODULE_DEVICE_TABLE (usb, id_table);
/* All of the device info needed for the Handspring Visor */
-struct usb_serial_device_type handspring_device = {
+static struct usb_serial_device_type handspring_device = {
name: "Handspring Visor",
id_table: visor_id_table,
needs_interrupt_in: MUST_HAVE_NOT, /* this device must not have an interrupt in endpoint */
@@ -210,7 +210,7 @@ struct usb_serial_device_type handspring_device = {
};
/* device info for the Palm 4.0 devices */
-struct usb_serial_device_type palm_4_0_device = {
+static struct usb_serial_device_type palm_4_0_device = {
name: "Palm 4.0",
id_table: palm_4_0_id_table,
needs_interrupt_in: MUST_HAVE_NOT, /* this device must not have an interrupt in endpoint */
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
index 2456e42eb..c8b1a9f9f 100644
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -131,7 +131,7 @@ static void whiteheat_unthrottle (struct usb_serial_port *port);
static int whiteheat_startup (struct usb_serial *serial);
static void whiteheat_shutdown (struct usb_serial *serial);
-struct usb_serial_device_type whiteheat_fake_device = {
+static struct usb_serial_device_type whiteheat_fake_device = {
name: "Connect Tech - WhiteHEAT - (prerenumeration)",
id_table: id_table_prerenumeration,
needs_interrupt_in: DONT_CARE, /* don't have to have an interrupt in endpoint */
@@ -144,7 +144,7 @@ struct usb_serial_device_type whiteheat_fake_device = {
startup: whiteheat_startup
};
-struct usb_serial_device_type whiteheat_device = {
+static struct usb_serial_device_type whiteheat_device = {
name: "Connect Tech - WhiteHEAT",
id_table: id_table_std,
needs_interrupt_in: DONT_CARE, /* don't have to have an interrupt in endpoint */
diff --git a/drivers/usb/usbnet.c b/drivers/usb/usbnet.c
index 96608c0d9..3e90b8b31 100644
--- a/drivers/usb/usbnet.c
+++ b/drivers/usb/usbnet.c
@@ -1870,6 +1870,11 @@ static const struct usb_device_id products [] = {
USB_DEVICE (0x0547, 0x2720), // AnchorChips defaults
driver_info: (unsigned long) &an2720_info,
},
+
+{
+ USB_DEVICE (0x0547, 0x2727), // Xircom PGUNET
+ driver_info: (unsigned long) &an2720_info,
+},
#endif
#ifdef CONFIG_USB_BELKIN
diff --git a/fs/buffer.c b/fs/buffer.c
index e0ba7b3d0..d1eb1e410 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -1036,6 +1036,7 @@ static int balance_dirty_state(void)
unsigned long dirty, tot, hard_dirty_limit, soft_dirty_limit;
dirty = size_buffers_type[BUF_DIRTY] >> PAGE_SHIFT;
+ dirty += size_buffers_type[BUF_LOCKED] >> PAGE_SHIFT;
tot = nr_free_buffer_pages();
dirty *= 100;
diff --git a/fs/exec.c b/fs/exec.c
index 6c36e768a..afd7577ab 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -586,7 +586,7 @@ mmap_failed:
flush_failed:
spin_lock_irq(&current->sigmask_lock);
if (current->sig != oldsig) {
- kfree(current->sig);
+ kmem_cache_free(sigact_cachep, current->sig);
current->sig = oldsig;
}
spin_unlock_irq(&current->sigmask_lock);
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index ee386b01e..e13a419bc 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -28,6 +28,8 @@
#include <asm/uaccess.h>
+static void ext2_sync_super(struct super_block *sb,
+ struct ext2_super_block *es);
static char error_buf[1024];
@@ -35,13 +37,13 @@ void ext2_error (struct super_block * sb, const char * function,
const char * fmt, ...)
{
va_list args;
+ struct ext2_super_block *es = EXT2_SB(sb)->s_es;
if (!(sb->s_flags & MS_RDONLY)) {
sb->u.ext2_sb.s_mount_state |= EXT2_ERROR_FS;
- sb->u.ext2_sb.s_es->s_state =
- cpu_to_le16(le16_to_cpu(sb->u.ext2_sb.s_es->s_state) | EXT2_ERROR_FS);
- mark_buffer_dirty(sb->u.ext2_sb.s_sbh);
- sb->s_dirt = 1;
+ es->s_state =
+ cpu_to_le16(le16_to_cpu(es->s_state) | EXT2_ERROR_FS);
+ ext2_sync_super(sb, es);
}
va_start (args, fmt);
vsprintf (error_buf, fmt, args);
@@ -124,8 +126,10 @@ void ext2_put_super (struct super_block * sb)
int i;
if (!(sb->s_flags & MS_RDONLY)) {
- sb->u.ext2_sb.s_es->s_state = le16_to_cpu(sb->u.ext2_sb.s_mount_state);
- mark_buffer_dirty(sb->u.ext2_sb.s_sbh);
+ struct ext2_super_block *es = EXT2_SB(sb)->s_es;
+
+ es->s_state = le16_to_cpu(EXT2_SB(sb)->s_mount_state);
+ ext2_sync_super(sb, es);
}
db_count = EXT2_SB(sb)->s_gdb_count;
for (i = 0; i < db_count; i++)
@@ -305,13 +309,10 @@ static int ext2_setup_super (struct super_block * sb,
(le32_to_cpu(es->s_lastcheck) + le32_to_cpu(es->s_checkinterval) <= CURRENT_TIME))
printk ("EXT2-fs warning: checktime reached, "
"running e2fsck is recommended\n");
- es->s_state = cpu_to_le16(le16_to_cpu(es->s_state) & ~EXT2_VALID_FS);
if (!(__s16) le16_to_cpu(es->s_max_mnt_count))
es->s_max_mnt_count = (__s16) cpu_to_le16(EXT2_DFL_MAX_MNT_COUNT);
es->s_mnt_count=cpu_to_le16(le16_to_cpu(es->s_mnt_count) + 1);
- es->s_mtime = cpu_to_le32(CURRENT_TIME);
- mark_buffer_dirty(sb->u.ext2_sb.s_sbh);
- sb->s_dirt = 1;
+ ext2_write_super(sb);
if (test_opt (sb, DEBUG))
printk ("[EXT II FS %s, %s, bs=%lu, fs=%lu, gc=%lu, "
"bpg=%lu, ipg=%lu, mo=%04lx]\n",
@@ -664,6 +665,15 @@ static void ext2_commit_super (struct super_block * sb,
sb->s_dirt = 0;
}
+static void ext2_sync_super(struct super_block *sb, struct ext2_super_block *es)
+{
+ es->s_wtime = cpu_to_le32(CURRENT_TIME);
+ mark_buffer_dirty(EXT2_SB(sb)->s_sbh);
+ ll_rw_block(WRITE, 1, &EXT2_SB(sb)->s_sbh);
+ wait_on_buffer(EXT2_SB(sb)->s_sbh);
+ sb->s_dirt = 0;
+}
+
/*
* In the second extended file system, it is not necessary to
* write the super block since we use a mapping of the
@@ -682,13 +692,14 @@ void ext2_write_super (struct super_block * sb)
if (!(sb->s_flags & MS_RDONLY)) {
es = sb->u.ext2_sb.s_es;
- ext2_debug ("setting valid to 0\n");
-
if (le16_to_cpu(es->s_state) & EXT2_VALID_FS) {
- es->s_state = cpu_to_le16(le16_to_cpu(es->s_state) & ~EXT2_VALID_FS);
+ ext2_debug ("setting valid to 0\n");
+ es->s_state = cpu_to_le16(le16_to_cpu(es->s_state) &
+ ~EXT2_VALID_FS);
es->s_mtime = cpu_to_le32(CURRENT_TIME);
- }
- ext2_commit_super (sb, es);
+ ext2_sync_super(sb, es);
+ } else
+ ext2_commit_super (sb, es);
}
sb->s_dirt = 0;
}
@@ -725,11 +736,7 @@ int ext2_remount (struct super_block * sb, int * flags, char * data)
*/
es->s_state = cpu_to_le16(sb->u.ext2_sb.s_mount_state);
es->s_mtime = cpu_to_le32(CURRENT_TIME);
- mark_buffer_dirty(sb->u.ext2_sb.s_sbh);
- sb->s_dirt = 1;
- ext2_commit_super (sb, es);
- }
- else {
+ } else {
int ret;
if ((ret = EXT2_HAS_RO_COMPAT_FEATURE(sb,
~EXT2_FEATURE_RO_COMPAT_SUPP))) {
@@ -747,6 +754,7 @@ int ext2_remount (struct super_block * sb, int * flags, char * data)
if (!ext2_setup_super (sb, es, 0))
sb->s_flags &= ~MS_RDONLY;
}
+ ext2_sync_super(sb, es);
return 0;
}
diff --git a/fs/inode.c b/fs/inode.c
index 32029994f..7132ee583 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -1187,6 +1187,8 @@ void __init inode_init(unsigned long mempages)
void update_atime (struct inode *inode)
{
+ if (inode->i_atime == CURRENT_TIME)
+ return;
if ( IS_NOATIME (inode) ) return;
if ( IS_NODIRATIME (inode) && S_ISDIR (inode->i_mode) ) return;
if ( IS_RDONLY (inode) ) return;
diff --git a/fs/nls/nls_cp1251.c b/fs/nls/nls_cp1251.c
index e51ada6fd..e432312e0 100644
--- a/fs/nls/nls_cp1251.c
+++ b/fs/nls/nls_cp1251.c
@@ -315,4 +315,4 @@ module_exit(exit_nls_cp1251)
* c-continued-brace-offset: 0
* End:
*/
-MODULE_LICENSE("BSD without advertising clause");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/nls_cp1255.c b/fs/nls/nls_cp1255.c
index cebbd9028..d6751422e 100644
--- a/fs/nls/nls_cp1255.c
+++ b/fs/nls/nls_cp1255.c
@@ -396,4 +396,4 @@ module_exit(exit_nls_cp1255)
* c-continued-brace-offset: 0
* End:
*/
-MODULE_LICENSE("BSD without advertising clause");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/nls_cp437.c b/fs/nls/nls_cp437.c
index a592fe8f1..bf433fee3 100644
--- a/fs/nls/nls_cp437.c
+++ b/fs/nls/nls_cp437.c
@@ -401,4 +401,4 @@ module_exit(exit_nls_cp437)
* c-continued-brace-offset: 0
* End:
*/
-MODULE_LICENSE("BSD without advertising clause");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/nls_cp737.c b/fs/nls/nls_cp737.c
index 53c65bc9f..7ef8871b7 100644
--- a/fs/nls/nls_cp737.c
+++ b/fs/nls/nls_cp737.c
@@ -364,4 +364,4 @@ module_exit(exit_nls_cp737)
* c-continued-brace-offset: 0
* End:
*/
-MODULE_LICENSE("BSD without advertising clause");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/nls_cp775.c b/fs/nls/nls_cp775.c
index f6f0686b8..f1742f124 100644
--- a/fs/nls/nls_cp775.c
+++ b/fs/nls/nls_cp775.c
@@ -333,4 +333,4 @@ module_exit(exit_nls_cp775)
* c-continued-brace-offset: 0
* End:
*/
-MODULE_LICENSE("BSD without advertising clause");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/nls_cp850.c b/fs/nls/nls_cp850.c
index c38e89d61..772e324da 100644
--- a/fs/nls/nls_cp850.c
+++ b/fs/nls/nls_cp850.c
@@ -329,4 +329,4 @@ module_exit(exit_nls_cp850)
* c-continued-brace-offset: 0
* End:
*/
-MODULE_LICENSE("BSD without advertising clause");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/nls_cp852.c b/fs/nls/nls_cp852.c
index 82260bbe7..48366f26b 100644
--- a/fs/nls/nls_cp852.c
+++ b/fs/nls/nls_cp852.c
@@ -351,4 +351,4 @@ module_exit(exit_nls_cp852)
* c-continued-brace-offset: 0
* End:
*/
-MODULE_LICENSE("BSD without advertising clause");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/nls_cp855.c b/fs/nls/nls_cp855.c
index 97f57690a..e95e89b46 100644
--- a/fs/nls/nls_cp855.c
+++ b/fs/nls/nls_cp855.c
@@ -313,4 +313,4 @@ module_exit(exit_nls_cp855)
* c-continued-brace-offset: 0
* End:
*/
-MODULE_LICENSE("BSD without advertising clause");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/nls_cp857.c b/fs/nls/nls_cp857.c
index 349ca7241..dc849b33b 100644
--- a/fs/nls/nls_cp857.c
+++ b/fs/nls/nls_cp857.c
@@ -315,4 +315,4 @@ module_exit(exit_nls_cp857)
* c-continued-brace-offset: 0
* End:
*/
-MODULE_LICENSE("BSD without advertising clause");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/nls_cp860.c b/fs/nls/nls_cp860.c
index 23da03086..b9a219341 100644
--- a/fs/nls/nls_cp860.c
+++ b/fs/nls/nls_cp860.c
@@ -378,4 +378,4 @@ module_exit(exit_nls_cp860)
* c-continued-brace-offset: 0
* End:
*/
-MODULE_LICENSE("BSD without advertising clause");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/nls_cp861.c b/fs/nls/nls_cp861.c
index fe03d1e97..91c839b89 100644
--- a/fs/nls/nls_cp861.c
+++ b/fs/nls/nls_cp861.c
@@ -401,4 +401,4 @@ module_exit(exit_nls_cp861)
* c-continued-brace-offset: 0
* End:
*/
-MODULE_LICENSE("BSD without advertising clause");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/nls_cp862.c b/fs/nls/nls_cp862.c
index 6c452204d..ef2999a0d 100644
--- a/fs/nls/nls_cp862.c
+++ b/fs/nls/nls_cp862.c
@@ -435,4 +435,4 @@ module_exit(exit_nls_cp862)
* c-continued-brace-offset: 0
* End:
*/
-MODULE_LICENSE("BSD without advertising clause");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/nls_cp863.c b/fs/nls/nls_cp863.c
index 51e62d1bb..1b4c6c04b 100644
--- a/fs/nls/nls_cp863.c
+++ b/fs/nls/nls_cp863.c
@@ -395,4 +395,4 @@ module_exit(exit_nls_cp863)
* c-continued-brace-offset: 0
* End:
*/
-MODULE_LICENSE("BSD without advertising clause");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/nls_cp864.c b/fs/nls/nls_cp864.c
index f4e6a804d..de5eac3d3 100644
--- a/fs/nls/nls_cp864.c
+++ b/fs/nls/nls_cp864.c
@@ -421,4 +421,4 @@ module_exit(exit_nls_cp864)
* c-continued-brace-offset: 0
* End:
*/
-MODULE_LICENSE("BSD without advertising clause");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/nls_cp865.c b/fs/nls/nls_cp865.c
index 63c004fc4..68d9e567f 100644
--- a/fs/nls/nls_cp865.c
+++ b/fs/nls/nls_cp865.c
@@ -401,4 +401,4 @@ module_exit(exit_nls_cp865)
* c-continued-brace-offset: 0
* End:
*/
-MODULE_LICENSE("BSD without advertising clause");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/nls_cp866.c b/fs/nls/nls_cp866.c
index 118a55e27..8860b2510 100644
--- a/fs/nls/nls_cp866.c
+++ b/fs/nls/nls_cp866.c
@@ -319,4 +319,4 @@ module_exit(exit_nls_cp866)
* c-continued-brace-offset: 0
* End:
*/
-MODULE_LICENSE("BSD without advertising clause");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/nls_cp869.c b/fs/nls/nls_cp869.c
index d65350383..dfa2bf5f3 100644
--- a/fs/nls/nls_cp869.c
+++ b/fs/nls/nls_cp869.c
@@ -329,4 +329,4 @@ module_exit(exit_nls_cp869)
* c-continued-brace-offset: 0
* End:
*/
-MODULE_LICENSE("BSD without advertising clause");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/nls/nls_cp874.c b/fs/nls/nls_cp874.c
index 061d68cc8..a40cf7b9a 100644
--- a/fs/nls/nls_cp874.c
+++ b/fs/nls/nls_cp874.c
@@ -287,4 +287,4 @@ module_exit(exit_nls_cp874)
* c-continued-brace-offset: 0
* End:
*/
-MODULE_LICENSE("BSD without advertising clause");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/fs/reiserfs/bitmap.c b/fs/reiserfs/bitmap.c
index 05afd10d9..ecf7fbc7e 100644
--- a/fs/reiserfs/bitmap.c
+++ b/fs/reiserfs/bitmap.c
@@ -103,6 +103,13 @@ void reiserfs_free_block (struct reiserfs_transaction_handle *th, unsigned long
get_bit_address (s, block, &nr, &offset);
+ if (nr >= sb_bmap_nr (rs)) {
+ reiserfs_warning ("vs-4075: reiserfs_free_block: "
+ "block %lu is out of range on %s\n",
+ block, bdevname(s->s_dev));
+ return;
+ }
+
/* mark it before we clear it, just in case */
journal_mark_freed(th, s, block) ;
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index aaa5b8ccf..0d93af1d8 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -1138,6 +1138,30 @@ void reiserfs_read_inode2 (struct inode * inode, void *p)
}
init_inode (inode, &path_to_sd);
+
+ /* It is possible that knfsd is trying to access inode of a file
+ that is being removed from the disk by some other thread. As we
+ update sd on unlink all that is required is to check for nlink
+ here. This bug was first found by Sizif when debugging
+ SquidNG/Butterfly, forgotten, and found again after Philippe
+ Gramoulle <philippe.gramoulle@mmania.com> reproduced it.
+
+ More logical fix would require changes in fs/inode.c:iput() to
+ remove inode from hash-table _after_ fs cleaned disk stuff up and
+ in iget() to return NULL if I_FREEING inode is found in
+ hash-table. */
+ /* Currently there is one place where it's ok to meet inode with
+ nlink==0: processing of open-unlinked and half-truncated files
+ during mount (fs/reiserfs/super.c:finish_unfinished()). */
+ if( ( inode -> i_nlink == 0 ) &&
+ ! inode -> i_sb -> u.reiserfs_sb.s_is_unlinked_ok ) {
+ reiserfs_warning( "vs-13075: reiserfs_read_inode2: "
+ "dead inode read from disk %K. "
+ "This is likely to be race with knfsd. Ignore\n",
+ &key );
+ make_bad_inode( inode );
+ }
+
reiserfs_check_path(&path_to_sd) ; /* init inode should be relsing */
}
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
index 879d9fe7a..2c71fd471 100644
--- a/fs/reiserfs/journal.c
+++ b/fs/reiserfs/journal.c
@@ -147,7 +147,7 @@ repeat:
}
bn = allocate_bitmap_node(p_s_sb) ;
if (!bn) {
- current->policy = SCHED_YIELD ;
+ current->policy |= SCHED_YIELD ;
schedule() ;
goto repeat ;
}
diff --git a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c
index 993e6fe1f..9a3eb670d 100644
--- a/fs/reiserfs/stree.c
+++ b/fs/reiserfs/stree.c
@@ -992,10 +992,6 @@ static char prepare_for_delete_or_cut(
struct item_head * p_le_ih = PATH_PITEM_HEAD(p_s_path);
struct buffer_head * p_s_bh = PATH_PLAST_BUFFER(p_s_path);
-#ifdef CONFIG_REISERFS_CHECK
- int n_repeat_counter = 0;
-#endif
-
/* Stat_data item. */
if ( is_statdata_le_ih (p_le_ih) ) {
@@ -1020,13 +1016,11 @@ static char prepare_for_delete_or_cut(
{
int n_unfm_number, /* Number of the item unformatted nodes. */
n_counter,
- n_retry, /* Set to one if there is unformatted node buffer in use. */
n_blk_size;
__u32 * p_n_unfm_pointer; /* Pointer to the unformatted node number. */
__u32 tmp;
struct item_head s_ih; /* Item header. */
char c_mode; /* Returned mode of the balance. */
- struct buffer_head * p_s_un_bh;
int need_research;
@@ -1099,8 +1093,8 @@ static char prepare_for_delete_or_cut(
// note: path could be changed, first line in for loop takes care
// of it
- for ( n_retry = 0, n_counter = *p_n_removed;
- n_counter < n_unfm_number; n_counter++, p_n_unfm_pointer-- ) {
+ for (n_counter = *p_n_removed;
+ n_counter < n_unfm_number; n_counter++, p_n_unfm_pointer-- ) {
if (item_moved (&s_ih, p_s_path)) {
need_research = 1 ;
@@ -1110,69 +1104,23 @@ static char prepare_for_delete_or_cut(
p_n_unfm_pointer > (__u32 *)B_I_PITEM(p_s_bh, &s_ih) + I_UNFM_NUM(&s_ih) - 1,
"vs-5265: pointer out of range");
- if ( ! get_block_num(p_n_unfm_pointer,0) ) { /* Hole, nothing to remove. */
- if ( ! n_retry )
+ /* Hole, nothing to remove. */
+ if ( ! get_block_num(p_n_unfm_pointer,0) ) {
(*p_n_removed)++;
- continue;
- }
- /* Search for the buffer in cache. */
- p_s_un_bh = get_hash_table(p_s_sb->s_dev, get_block_num(p_n_unfm_pointer,0), n_blk_size);
-
- if (p_s_un_bh) {
- mark_buffer_clean(p_s_un_bh) ;
- if (buffer_locked(p_s_un_bh)) {
- __wait_on_buffer(p_s_un_bh) ;
- }
- /* even if the item moves, the block number of the
- ** unformatted node we want to cut won't. So, it was
- ** safe to clean the buffer here, this block _will_
- ** get freed during this call to prepare_for_delete_or_cut
- */
- if ( item_moved (&s_ih, p_s_path) ) {
- need_research = 1;
- brelse(p_s_un_bh) ;
- break ;
- }
+ continue;
}
- if ( p_s_un_bh && block_in_use (p_s_un_bh)) {
- /* Block is locked or held more than by one holder and by
- journal. */
-#ifdef CONFIG_REISERFS_CHECK
- if (n_repeat_counter && (n_repeat_counter % 100000) == 0) {
- printk("prepare_for_delete, waiting on buffer %lu, b_count %d, %s%cJDIRTY %cJDIRTY_WAIT\n",
- p_s_un_bh->b_blocknr, atomic_read (&p_s_un_bh->b_count),
- buffer_locked (p_s_un_bh) ? "locked, " : "",
- buffer_journaled(p_s_un_bh) ? ' ' : '!',
- buffer_journal_dirty(p_s_un_bh) ? ' ' : '!') ;
-
- }
-#endif
- n_retry = 1;
- brelse (p_s_un_bh);
- continue;
- }
-
- if ( ! n_retry )
- (*p_n_removed)++;
-
- RFALSE( p_s_un_bh &&
- get_block_num(p_n_unfm_pointer, 0) != p_s_un_bh->b_blocknr,
- // note: minix_truncate allows that. As truncate is
- // protected by down (inode->i_sem), two truncates can not
- // co-exist
- "PAP-5280: blocks numbers are different");
+ (*p_n_removed)++;
tmp = get_block_num(p_n_unfm_pointer,0);
put_block_num(p_n_unfm_pointer, 0, 0);
journal_mark_dirty (th, p_s_sb, p_s_bh);
- bforget (p_s_un_bh);
inode->i_blocks -= p_s_sb->s_blocksize / 512;
reiserfs_free_block(th, tmp);
if ( item_moved (&s_ih, p_s_path) ) {
- need_research = 1;
- break ;
- }
+ need_research = 1;
+ break ;
+ }
}
/* a trick. If the buffer has been logged, this
@@ -1182,28 +1130,6 @@ static char prepare_for_delete_or_cut(
*/
reiserfs_restore_prepared_buffer(p_s_sb, p_s_bh);
- if ( n_retry ) {
- /* There is block in use. Wait, they should release it soon */
-
- RFALSE( *p_n_removed >= n_unfm_number, "PAP-5290: illegal case");
-#ifdef CONFIG_REISERFS_CHECK
- if ( !(++n_repeat_counter % 500000) ) {
- reiserfs_warning("PAP-5300: prepare_for_delete_or_cut: (pid %u): "
- "could not delete item %k in (%d) iterations. New file length %Lu. (inode %Ld), Still trying\n",
- current->pid, p_s_item_key, n_repeat_counter, n_new_file_length, inode->i_size);
- if (n_repeat_counter == 5000000) {
- print_block (PATH_PLAST_BUFFER(p_s_path), 3,
- PATH_LAST_POSITION (p_s_path) - 2, PATH_LAST_POSITION (p_s_path) + 2);
- reiserfs_panic(p_s_sb, "PAP-5305: prepare_for_delete_or_cut: key %k, new_file_length %Ld",
- p_s_item_key, n_new_file_length);
- }
- }
-#endif
-
- run_task_queue(&tq_disk);
- current->policy |= SCHED_YIELD;
- schedule();
- }
/* This loop can be optimized. */
} while ( (*p_n_removed < n_unfm_number || need_research) &&
search_for_position_by_key(p_s_sb, p_s_item_key, p_s_path) == POSITION_FOUND );
diff --git a/include/asm-i386/pgalloc.h b/include/asm-i386/pgalloc.h
index 11b5d8a75..988c26a75 100644
--- a/include/asm-i386/pgalloc.h
+++ b/include/asm-i386/pgalloc.h
@@ -18,15 +18,21 @@
* Allocate and free page tables.
*/
-#if CONFIG_X86_PAE
+#if defined (CONFIG_X86_PAE)
+/*
+ * We can't include <linux/slab.h> here, thus these uglinesses.
+ */
+struct kmem_cache_s;
+
+extern struct kmem_cache_s *pae_pgd_cachep;
+extern void *kmem_cache_alloc(struct kmem_cache_s *, int);
+extern void kmem_cache_free(struct kmem_cache_s *, void *);
-extern void *kmalloc(size_t, int);
-extern void kfree(const void *);
-static __inline__ pgd_t *get_pgd_slow(void)
+static inline pgd_t *get_pgd_slow(void)
{
int i;
- pgd_t *pgd = kmalloc(PTRS_PER_PGD * sizeof(pgd_t), GFP_KERNEL);
+ pgd_t *pgd = kmem_cache_alloc(pae_pgd_cachep, GFP_KERNEL);
if (pgd) {
for (i = 0; i < USER_PTRS_PER_PGD; i++) {
@@ -36,32 +42,36 @@ static __inline__ pgd_t *get_pgd_slow(void)
clear_page(pmd);
set_pgd(pgd + i, __pgd(1 + __pa(pmd)));
}
- memcpy(pgd + USER_PTRS_PER_PGD, swapper_pg_dir + USER_PTRS_PER_PGD, (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
+ memcpy(pgd + USER_PTRS_PER_PGD,
+ swapper_pg_dir + USER_PTRS_PER_PGD,
+ (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
}
return pgd;
out_oom:
for (i--; i >= 0; i--)
free_page((unsigned long)__va(pgd_val(pgd[i])-1));
- kfree(pgd);
+ kmem_cache_free(pae_pgd_cachep, pgd);
return NULL;
}
#else
-static __inline__ pgd_t *get_pgd_slow(void)
+static inline pgd_t *get_pgd_slow(void)
{
pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL);
if (pgd) {
memset(pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t));
- memcpy(pgd + USER_PTRS_PER_PGD, swapper_pg_dir + USER_PTRS_PER_PGD, (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
+ memcpy(pgd + USER_PTRS_PER_PGD,
+ swapper_pg_dir + USER_PTRS_PER_PGD,
+ (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
}
return pgd;
}
-#endif
+#endif /* CONFIG_X86_PAE */
-static __inline__ pgd_t *get_pgd_fast(void)
+static inline pgd_t *get_pgd_fast(void)
{
unsigned long *ret;
@@ -74,21 +84,21 @@ static __inline__ pgd_t *get_pgd_fast(void)
return (pgd_t *)ret;
}
-static __inline__ void free_pgd_fast(pgd_t *pgd)
+static inline void free_pgd_fast(pgd_t *pgd)
{
*(unsigned long *)pgd = (unsigned long) pgd_quicklist;
pgd_quicklist = (unsigned long *) pgd;
pgtable_cache_size++;
}
-static __inline__ void free_pgd_slow(pgd_t *pgd)
+static inline void free_pgd_slow(pgd_t *pgd)
{
-#if CONFIG_X86_PAE
+#if defined(CONFIG_X86_PAE)
int i;
for (i = 0; i < USER_PTRS_PER_PGD; i++)
free_page((unsigned long)__va(pgd_val(pgd[i])-1));
- kfree(pgd);
+ kmem_cache_free(pae_pgd_cachep, pgd);
#else
free_page((unsigned long)pgd);
#endif
@@ -104,7 +114,8 @@ static inline pte_t *pte_alloc_one(struct mm_struct *mm, unsigned long address)
return pte;
}
-static inline pte_t *pte_alloc_one_fast(struct mm_struct *mm, unsigned long address)
+static inline pte_t *pte_alloc_one_fast(struct mm_struct *mm,
+ unsigned long address)
{
unsigned long *ret;
@@ -116,7 +127,7 @@ static inline pte_t *pte_alloc_one_fast(struct mm_struct *mm, unsigned long addr
return (pte_t *)ret;
}
-static __inline__ void pte_free_fast(pte_t *pte)
+static inline void pte_free_fast(pte_t *pte)
{
*(unsigned long *)pte = (unsigned long) pte_quicklist;
pte_quicklist = (unsigned long *) pte;
@@ -128,14 +139,9 @@ static __inline__ void pte_free_slow(pte_t *pte)
free_page((unsigned long)pte);
}
-#define pte_free(pte) pte_free_fast(pte)
-#ifdef CONFIG_X86_PAE
-#define pgd_alloc(mm) get_pgd_slow()
+#define pte_free(pte) pte_free_slow(pte)
#define pgd_free(pgd) free_pgd_slow(pgd)
-#else
#define pgd_alloc(mm) get_pgd_fast()
-#define pgd_free(pgd) free_pgd_fast(pgd)
-#endif
/*
* allocating and freeing a pmd is trivial: the 1-entry pmd is
diff --git a/include/asm-ia64/pal.h b/include/asm-ia64/pal.h
index f429cdec4..26107d9e1 100644
--- a/include/asm-ia64/pal.h
+++ b/include/asm-ia64/pal.h
@@ -88,10 +88,10 @@
typedef s64 pal_status_t;
#define PAL_STATUS_SUCCESS 0 /* No error */
-#define PAL_STATUS_UNIMPLEMENTED -1 /* Unimplemented procedure */
-#define PAL_STATUS_EINVAL -2 /* Invalid argument */
-#define PAL_STATUS_ERROR -3 /* Error */
-#define PAL_STATUS_CACHE_INIT_FAIL -4 /* Could not initialize the
+#define PAL_STATUS_UNIMPLEMENTED (-1) /* Unimplemented procedure */
+#define PAL_STATUS_EINVAL (-2) /* Invalid argument */
+#define PAL_STATUS_ERROR (-3) /* Error */
+#define PAL_STATUS_CACHE_INIT_FAIL (-4) /* Could not initialize the
* specified level and type of
* cache without sideeffects
* and "restrict" was 1
diff --git a/include/asm-ia64/siginfo.h b/include/asm-ia64/siginfo.h
index dc801e5ab..c5972a262 100644
--- a/include/asm-ia64/siginfo.h
+++ b/include/asm-ia64/siginfo.h
@@ -119,11 +119,11 @@ typedef struct siginfo {
#define SI_USER 0 /* sent by kill, sigsend, raise */
#define SI_KERNEL 0x80 /* sent by the kernel from somewhere */
-#define SI_QUEUE -1 /* sent by sigqueue */
+#define SI_QUEUE (-1) /* sent by sigqueue */
#define SI_TIMER __SI_CODE(__SI_TIMER,-2) /* sent by timer expiration */
-#define SI_MESGQ -3 /* sent by real time mesq state change */
-#define SI_ASYNCIO -4 /* sent by AIO completion */
-#define SI_SIGIO -5 /* sent by queued SIGIO */
+#define SI_MESGQ (-3) /* sent by real time mesq state change */
+#define SI_ASYNCIO (-4) /* sent by AIO completion */
+#define SI_SIGIO (-5) /* sent by queued SIGIO */
#define SI_FROMUSER(siptr) ((siptr)->si_code <= 0)
#define SI_FROMKERNEL(siptr) ((siptr)->si_code > 0)
diff --git a/include/linux/reiserfs_fs_sb.h b/include/linux/reiserfs_fs_sb.h
index 1eee601a1..32109db40 100644
--- a/include/linux/reiserfs_fs_sb.h
+++ b/include/linux/reiserfs_fs_sb.h
@@ -420,6 +420,10 @@ struct reiserfs_sb_info
int s_bmaps_without_search;
int s_direct2indirect;
int s_indirect2direct;
+ /* set up when it's ok for reiserfs_read_inode2() to read from
+ disk inode with nlink==0. Currently this is only used during
+ finish_unfinished() processing at mount time */
+ int s_is_unlinked_ok;
reiserfs_proc_info_data_t s_proc_info_data;
struct proc_dir_entry *procdir;
};
diff --git a/include/linux/slab.h b/include/linux/slab.h
index efa8638d6..ffb09c61f 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -38,6 +38,7 @@ typedef struct kmem_cache_s kmem_cache_t;
#define SLAB_NO_REAP 0x00001000UL /* never reap from the cache */
#define SLAB_HWCACHE_ALIGN 0x00002000UL /* align objs on a h/w cache lines */
#define SLAB_CACHE_DMA 0x00004000UL /* use GFP_DMA memory */
+#define SLAB_MUST_HWCACHE_ALIGN 0x00008000UL /* force alignment */
/* flags passed to a constructor func */
#define SLAB_CTOR_CONSTRUCTOR 0x001UL /* if not set, then deconstructor */
diff --git a/include/net/irda/irlmp.h b/include/net/irda/irlmp.h
index aebf005ac..248c1b881 100644
--- a/include/net/irda/irlmp.h
+++ b/include/net/irda/irlmp.h
@@ -264,4 +264,16 @@ static inline int irlmp_get_lap_tx_queue_len(struct lsap_cb *self)
return IRLAP_GET_TX_QUEUE_LEN(self->lap->irlap);
}
+/* After doing a irlmp_dup(), this get one of the two socket back into
+ * a state where it's waiting incomming connections.
+ * Note : this can be used *only* if the socket is not yet connected
+ * (i.e. NO irlmp_connect_response() done on this socket).
+ * - Jean II */
+static inline void irlmp_listen(struct lsap_cb *self)
+{
+ self->dlsap_sel = LSAP_ANY;
+ self->lap = NULL;
+ self->lsap_state = LSAP_DISCONNECTED;
+}
+
#endif
diff --git a/include/net/irda/irttp.h b/include/net/irda/irttp.h
index a3193d758..d10874185 100644
--- a/include/net/irda/irttp.h
+++ b/include/net/irda/irttp.h
@@ -148,6 +148,17 @@ static __inline __u32 irttp_get_max_seg_size(struct tsap_cb *self)
return self->max_seg_size;
}
+/* After doing a irttp_dup(), this get one of the two socket back into
+ * a state where it's waiting incomming connections.
+ * Note : this can be used *only* if the socket is not yet connected
+ * (i.e. NO irttp_connect_response() done on this socket).
+ * - Jean II */
+static inline void irttp_listen(struct tsap_cb *self)
+{
+ irlmp_listen(self->lsap);
+ self->dtsap_sel = LSAP_ANY;
+}
+
extern struct irttp_cb *irttp;
#endif /* IRTTP_H */
diff --git a/include/pcmcia/ciscode.h b/include/pcmcia/ciscode.h
index 2e0a838f1..660b1f491 100644
--- a/include/pcmcia/ciscode.h
+++ b/include/pcmcia/ciscode.h
@@ -1,5 +1,5 @@
/*
- * ciscode.h 1.45 2000/08/12 02:08:23
+ * ciscode.h 1.48 2001/08/24 12:16:12
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
@@ -16,8 +16,8 @@
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
* Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License version 2 (the "GPL"), in which
- * case the provisions of the GPL are applicable instead of the
+ * terms of the GNU General Public License version 2 (the "GPL"), in
+ * which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use
* your version of this file under the MPL, indicate your decision by
@@ -104,6 +104,8 @@
#define PRODID_QUATECH_DUAL_RS232 0x0012
#define PRODID_QUATECH_DUAL_RS232_D1 0x0007
#define PRODID_QUATECH_QUAD_RS232 0x001b
+#define PRODID_QUATECH_DUAL_RS422 0x000e
+#define PRODID_QUATECH_QUAD_RS422 0x0045
#define MANFID_SMC 0x0108
#define PRODID_SMC_ETHER 0x0105
diff --git a/include/pcmcia/cs.h b/include/pcmcia/cs.h
index 2bd505c96..537e8c09e 100644
--- a/include/pcmcia/cs.h
+++ b/include/pcmcia/cs.h
@@ -1,5 +1,5 @@
/*
- * cs.h 1.71 2000/08/29 00:54:20
+ * cs.h 1.74 2001/10/04 03:15:22
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
@@ -16,8 +16,8 @@
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
* Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License version 2 (the "GPL"), in which
- * case the provisions of the GPL are applicable instead of the
+ * terms of the GNU General Public License version 2 (the "GPL"), in
+ * which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use
* your version of this file under the MPL, indicate your decision by
@@ -181,6 +181,7 @@ typedef struct config_req_t {
#define INT_MEMORY 0x01
#define INT_MEMORY_AND_IO 0x02
#define INT_CARDBUS 0x04
+#define INT_ZOOMED_VIDEO 0x08
/* For RequestIO and ReleaseIO */
typedef struct io_req_t {
diff --git a/include/pcmcia/version.h b/include/pcmcia/version.h
index eb88263fc..4053e4982 100644
--- a/include/pcmcia/version.h
+++ b/include/pcmcia/version.h
@@ -1,4 +1,4 @@
-/* version.h 1.94 2000/10/03 17:55:48 (David Hinds) */
+/* version.h 1.102 2001/08/29 23:13:22 (David Hinds) */
-#define CS_RELEASE "3.1.22"
-#define CS_RELEASE_CODE 0x3116
+#define CS_RELEASE "3.1.30"
+#define CS_RELEASE_CODE 0x311e
diff --git a/init/main.c b/init/main.c
index f0231bc9e..8a1e43209 100644
--- a/init/main.c
+++ b/init/main.c
@@ -591,6 +591,8 @@ asmlinkage void __init start_kernel(void)
#endif
mem_init();
kmem_cache_sizes_init();
+ pgtable_cache_init();
+
mempages = num_physpages;
fork_init(mempages);
diff --git a/mm/slab.c b/mm/slab.c
index 2dcf30add..7819a1984 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -109,9 +109,11 @@
#if DEBUG
# define CREATE_MASK (SLAB_DEBUG_INITIAL | SLAB_RED_ZONE | \
SLAB_POISON | SLAB_HWCACHE_ALIGN | \
- SLAB_NO_REAP | SLAB_CACHE_DMA)
+ SLAB_NO_REAP | SLAB_CACHE_DMA | \
+ SLAB_MUST_HWCACHE_ALIGN)
#else
-# define CREATE_MASK (SLAB_HWCACHE_ALIGN | SLAB_NO_REAP | SLAB_CACHE_DMA)
+# define CREATE_MASK (SLAB_HWCACHE_ALIGN | SLAB_NO_REAP | \
+ SLAB_CACHE_DMA | SLAB_MUST_HWCACHE_ALIGN)
#endif
/*
@@ -649,7 +651,7 @@ kmem_cache_create (const char *name, size_t size, size_t offset,
flags &= ~SLAB_POISON;
}
#if FORCED_DEBUG
- if (size < (PAGE_SIZE>>3))
+ if ((size < (PAGE_SIZE>>3)) && !(flags & SLAB_MUST_HWCACHE_ALIGN))
/*
* do not red zone large object, causes severe
* fragmentation.
diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c
index 45ef5f77a..da456b250 100644
--- a/net/irda/af_irda.c
+++ b/net/irda/af_irda.c
@@ -914,8 +914,7 @@ static int irda_accept(struct socket *sock, struct socket *newsock, int flags)
memcpy(&new->qos_tx, &self->qos_tx, sizeof(struct qos_info));
/* Clean up the original one to keep it in listen state */
- self->tsap->dtsap_sel = self->tsap->lsap->dlsap_sel = LSAP_ANY;
- self->tsap->lsap->lsap_state = LSAP_DISCONNECTED;
+ irttp_listen(self->tsap);
skb->sk = NULL;
skb->destructor = NULL;
@@ -1845,15 +1844,36 @@ static int irda_setsockopt(struct socket *sock, int level, int optname,
return -EFAULT;
}
- /* Find the object we target */
- ias_obj = irias_find_object(ias_opt->irda_class_name);
+ /* Find the object we target.
+ * If the user gives us an empty string, we use the object
+ * associated with this socket. This will workaround
+ * duplicated class name - Jean II */
+ if(ias_opt->irda_class_name[0] == '\0') {
+ if(self->ias_obj == NULL) {
+ kfree(ias_opt);
+ return -EINVAL;
+ }
+ ias_obj = self->ias_obj;
+ } else
+ ias_obj = irias_find_object(ias_opt->irda_class_name);
+
+ /* Only ROOT can mess with the global IAS database.
+ * Users can only add attributes to the object associated
+ * with the socket they own - Jean II */
+ if((!capable(CAP_NET_ADMIN)) &&
+ ((ias_obj == NULL) || (ias_obj != self->ias_obj))) {
+ kfree(ias_opt);
+ return -EPERM;
+ }
+
+ /* If the object doesn't exist, create it */
if(ias_obj == (struct ias_object *) NULL) {
/* Create a new object */
ias_obj = irias_new_object(ias_opt->irda_class_name,
jiffies);
}
- /* Do we have it already ? */
+ /* Do we have the attribute already ? */
if(irias_find_attrib(ias_obj, ias_opt->irda_attrib_name)) {
kfree(ias_opt);
return -EINVAL;
@@ -1927,13 +1947,28 @@ static int irda_setsockopt(struct socket *sock, int level, int optname,
return -EFAULT;
}
- /* Find the object we target */
- ias_obj = irias_find_object(ias_opt->irda_class_name);
+ /* Find the object we target.
+ * If the user gives us an empty string, we use the object
+ * associated with this socket. This will workaround
+ * duplicated class name - Jean II */
+ if(ias_opt->irda_class_name[0] == '\0')
+ ias_obj = self->ias_obj;
+ else
+ ias_obj = irias_find_object(ias_opt->irda_class_name);
if(ias_obj == (struct ias_object *) NULL) {
kfree(ias_opt);
return -EINVAL;
}
+ /* Only ROOT can mess with the global IAS database.
+ * Users can only del attributes from the object associated
+ * with the socket they own - Jean II */
+ if((!capable(CAP_NET_ADMIN)) &&
+ ((ias_obj == NULL) || (ias_obj != self->ias_obj))) {
+ kfree(ias_opt);
+ return -EPERM;
+ }
+
/* Find the attribute (in the object) we target */
ias_attr = irias_find_attrib(ias_obj,
ias_opt->irda_attrib_name);
@@ -2166,8 +2201,14 @@ bed:
return -EFAULT;
}
- /* Find the object we target */
- ias_obj = irias_find_object(ias_opt->irda_class_name);
+ /* Find the object we target.
+ * If the user gives us an empty string, we use the object
+ * associated with this socket. This will workaround
+ * duplicated class name - Jean II */
+ if(ias_opt->irda_class_name[0] == '\0')
+ ias_obj = self->ias_obj;
+ else
+ ias_obj = irias_find_object(ias_opt->irda_class_name);
if(ias_obj == (struct ias_object *) NULL) {
kfree(ias_opt);
return -EINVAL;
diff --git a/net/irda/iriap.c b/net/irda/iriap.c
index 5be3ccbc3..7909b30a0 100644
--- a/net/irda/iriap.c
+++ b/net/irda/iriap.c
@@ -800,9 +800,7 @@ static void iriap_connect_indication(void *instance, void *sap,
new->max_header_size = max_header_size;
/* Clean up the original one to keep it in listen state */
- self->lsap->dlsap_sel = LSAP_ANY;
- self->lsap->lsap_state = LSAP_DISCONNECTED;
- /* FIXME: refcount in irlmp might get wrong */
+ irlmp_listen(self->lsap);
iriap_do_server_event(new, IAP_LM_CONNECT_INDICATION, userdata);
}
diff --git a/net/irda/irlap.c b/net/irda/irlap.c
index b668545b4..aeb76abfc 100644
--- a/net/irda/irlap.c
+++ b/net/irda/irlap.c
@@ -51,6 +51,11 @@
hashbin_t *irlap = NULL;
int sysctl_slot_timeout = SLOT_TIMEOUT * 1000 / HZ;
+/* This is the delay of missed pf period before generating an event
+ * to the application. The spec mandate 3 seconds, but in some cases
+ * it's way too long. - Jean II */
+int sysctl_warn_noreply_time = 3;
+
extern void irlap_queue_xmit(struct irlap_cb *self, struct sk_buff *skb);
static void __irlap_close(struct irlap_cb *self);
@@ -527,22 +532,7 @@ void irlap_discovery_request(struct irlap_cb *self, discovery_t *discovery)
self->discovery_cmd = discovery;
info.discovery = discovery;
- /* Check if the slot timeout is within limits */
- if (sysctl_slot_timeout < 20) {
- ERROR(__FUNCTION__
- "(), to low value for slot timeout!\n");
- sysctl_slot_timeout = 20;
- }
- /*
- * Highest value is actually 8, but we allow higher since
- * some devices seems to require it.
- */
- if (sysctl_slot_timeout > 160) {
- ERROR(__FUNCTION__
- "(), to high value for slot timeout!\n");
- sysctl_slot_timeout = 160;
- }
-
+ /* sysctl_slot_timeout bounds are checked in irsysctl.c - Jean II */
self->slot_timeout = sysctl_slot_timeout * HZ / 1000;
irlap_do_event(self, DISCOVERY_REQUEST, NULL, &info);
@@ -931,9 +921,6 @@ void irlap_init_qos_capabilities(struct irlap_cb *self,
/* Set data size */
/*self->qos_rx.data_size.bits &= 0x03;*/
- /* Set disconnect time -> done properly in qos.c */
- /*self->qos_rx.link_disc_time.bits &= 0x07;*/
-
irda_qos_bits_to_value(&self->qos_rx);
}
@@ -1070,8 +1057,11 @@ void irlap_apply_connection_parameters(struct irlap_cb *self, int now)
/*
* Set N1 to 0 if Link Disconnect/Threshold Time = 3 and set it to
* 3 seconds otherwise. See page 71 in IrLAP for more details.
+ * Actually, it's not always 3 seconds, as we allow to set
+ * it via sysctl... Max maxtt is 500ms, and N1 need to be multiple
+ * of 2, so 1 second is minimum we can allow. - Jean II
*/
- if (self->qos_tx.link_disc_time.value == 3)
+ if (self->qos_tx.link_disc_time.value == sysctl_warn_noreply_time)
/*
* If we set N1 to 0, it will trigger immediately, which is
* not what we want. What we really want is to disable it,
@@ -1079,7 +1069,8 @@ void irlap_apply_connection_parameters(struct irlap_cb *self, int now)
*/
self->N1 = -2; /* Disable - Need to be multiple of 2*/
else
- self->N1 = 3000 / self->qos_rx.max_turn_time.value;
+ self->N1 = sysctl_warn_noreply_time * 1000 /
+ self->qos_rx.max_turn_time.value;
IRDA_DEBUG(4, "Setting N1 = %d\n", self->N1);
diff --git a/net/irda/irlap_event.c b/net/irda/irlap_event.c
index 70967c6d4..847eb1912 100644
--- a/net/irda/irlap_event.c
+++ b/net/irda/irlap_event.c
@@ -1405,30 +1405,29 @@ static int irlap_state_nrm_p(struct irlap_cb *self, IRLAP_EVENT event,
}
self->add_wait = FALSE;
- if ((self->retry_count < self->N2) &&
- (self->retry_count != self->N1)) {
-
+ /* N2 is the disconnect timer. Until we reach it, we retry */
+ if (self->retry_count < self->N2) {
+ /* Retry sending the pf bit to the secondary */
irlap_wait_min_turn_around(self, &self->qos_tx);
irlap_send_rr_frame(self, CMD_FRAME);
irlap_start_final_timer(self, self->final_timeout);
self->retry_count++;
-
IRDA_DEBUG(4, "irlap_state_nrm_p: FINAL_TIMER_EXPIRED:"
" retry_count=%d\n", self->retry_count);
- /* Keep state */
- } else if (self->retry_count == self->N1) {
- irlap_status_indication(self, STATUS_NO_ACTIVITY);
- irlap_wait_min_turn_around(self, &self->qos_tx);
- irlap_send_rr_frame(self, CMD_FRAME);
-
- irlap_start_final_timer(self, self->final_timeout);
- self->retry_count++;
- IRDA_DEBUG(4, "retry count = N1; retry_count=%d\n",
- self->retry_count);
+ /* Early warning event. I'm using a pretty liberal
+ * interpretation of the spec and generate an event
+ * every time the timer is multiple of N1 (and not
+ * only the first time). This allow application
+ * to know precisely if connectivity restart...
+ * Jean II */
+ if((self->retry_count % self->N1) == 0)
+ irlap_status_indication(self,
+ STATUS_NO_ACTIVITY);
+
/* Keep state */
- } else if (self->retry_count >= self->N2) {
+ } else {
irlap_apply_default_connection_parameters(self);
/* Always switch state before calling upper layers */
@@ -1991,6 +1990,7 @@ static int irlap_state_nrm_s(struct irlap_cb *self, IRLAP_EVENT event,
* Wait until retry_count * n matches negotiated threshold/
* disconnect time (note 2 in IrLAP p. 82)
*
+ * Similar to irlap_state_nrm_p() -> FINAL_TIMER_EXPIRED
* Note : self->wd_timeout = (self->final_timeout * 2),
* which explain why we use (self->N2 / 2) here !!!
* Jean II
@@ -1998,16 +1998,15 @@ static int irlap_state_nrm_s(struct irlap_cb *self, IRLAP_EVENT event,
IRDA_DEBUG(1, __FUNCTION__ "(), retry_count = %d\n",
self->retry_count);
- if ((self->retry_count < (self->N2 / 2)) &&
- (self->retry_count != (self->N1 / 2))) {
-
+ if (self->retry_count < (self->N2 / 2)) {
+ /* No retry, just wait for primary */
irlap_start_wd_timer(self, self->wd_timeout);
self->retry_count++;
- } else if (self->retry_count == (self->N1 / 2)) {
- irlap_status_indication(self, STATUS_NO_ACTIVITY);
- irlap_start_wd_timer(self, self->wd_timeout);
- self->retry_count++;
- } else if (self->retry_count >= (self->N2 / 2)) {
+
+ if((self->retry_count % (self->N1 / 2)) == 0)
+ irlap_status_indication(self,
+ STATUS_NO_ACTIVITY);
+ } else {
irlap_apply_default_connection_parameters(self);
/* Always switch state before calling upper layers */
diff --git a/net/irda/irlmp.c b/net/irda/irlmp.c
index 154b0e0b1..e056bf6f0 100644
--- a/net/irda/irlmp.c
+++ b/net/irda/irlmp.c
@@ -469,7 +469,12 @@ void irlmp_connect_indication(struct lsap_cb *self, struct sk_buff *skb)
IRDA_DEBUG(2, __FUNCTION__ "(), slsap_sel=%02x, dlsap_sel=%02x\n",
self->slsap_sel, self->dlsap_sel);
-
+
+ /* Note : self->lap is set in irlmp_link_data_indication(),
+ * (case CONNECT_CMD:) because we have no way to set it here.
+ * Similarly, self->dlsap_sel is usually set in irlmp_find_lsap().
+ * Jean II */
+
self->qos = *self->lap->qos;
max_seg_size = self->lap->qos->data_size.value-LMP_HEADER;
@@ -577,7 +582,9 @@ struct lsap_cb *irlmp_dup(struct lsap_cb *orig, void *instance)
/* Dup */
memcpy(new, orig, sizeof(struct lsap_cb));
new->notify.instance = instance;
-
+ /* new->lap = orig->lap; => done in the memcpy() */
+ /* new->slsap_sel = orig->slsap_sel; => done in the memcpy() */
+
init_timer(&new->watchdog_timer);
hashbin_insert(irlmp->unconnected_lsaps, (irda_queue_t *) new, (int) new,
diff --git a/net/irda/irlmp_event.c b/net/irda/irlmp_event.c
index 37def7763..3692a913d 100644
--- a/net/irda/irlmp_event.c
+++ b/net/irda/irlmp_event.c
@@ -407,12 +407,7 @@ static void irlmp_state_active(struct lap_cb *self, IRLMP_EVENT event,
* removed later and moved to the list of unconnected LSAPs
*/
if (HASHBIN_GET_SIZE(self->lsaps) > 0) {
- /* Make sure the timer has sensible value (the user
- * may have set it) - Jean II */
- if(sysctl_lap_keepalive_time < 100) /* 100ms */
- sysctl_lap_keepalive_time = 100;
- if(sysctl_lap_keepalive_time > 10000) /* 10s */
- sysctl_lap_keepalive_time = 10000;
+ /* Timer value is checked in irsysctl - Jean II */
irlmp_start_idle_timer(self, sysctl_lap_keepalive_time * HZ / 1000);
} else {
/* No more connections, so close IrLAP */
diff --git a/net/irda/irnet/irnet.h b/net/irda/irnet/irnet.h
index 4afc417b2..08ef7b33c 100644
--- a/net/irda/irnet/irnet.h
+++ b/net/irda/irnet/irnet.h
@@ -199,6 +199,13 @@
* o Avoid leaking discovery log and skb
* o Replace "self" with "server" in irnet_connect_indication() to
* better detect cut'n'paste error ;-)
+ *
+ * v9 - 29.11.01 - Jean II
+ * o Fix event generation in disconnect indication that I broke in v8
+ * It was always generation "No-Answer" because I was testing ttp_open
+ * just after clearing it. *blush*.
+ * o Use newly created irttp_listen() to fix potential crash when LAP
+ * destroyed before irnet module removed.
*/
/***************************** INCLUDES *****************************/
diff --git a/net/irda/irnet/irnet_irda.c b/net/irda/irnet/irnet_irda.c
index 9b85137da..b5e590576 100644
--- a/net/irda/irnet/irnet_irda.c
+++ b/net/irda/irnet/irnet_irda.c
@@ -830,8 +830,7 @@ irnet_connect_socket(irnet_socket * server,
#endif /* STREAM_COMPAT */
/* Clean up the original one to keep it in listen state */
- server->tsap->dtsap_sel = server->tsap->lsap->dlsap_sel = LSAP_ANY;
- server->tsap->lsap->lsap_state = LSAP_DISCONNECTED;
+ irttp_listen(server->tsap);
/* Send a connection response on the new socket */
irttp_connect_response(new->tsap, new->max_sdu_size_rx, NULL);
@@ -897,8 +896,7 @@ irnet_disconnect_server(irnet_socket * self,
self->saddr, self->daddr, self->rname);
/* Clean up the server to keep it in listen state */
- self->tsap->dtsap_sel = self->tsap->lsap->dlsap_sel = LSAP_ANY;
- self->tsap->lsap->lsap_state = LSAP_DISCONNECTED;
+ irttp_listen(self->tsap);
DEXIT(IRDA_SERV_TRACE, "\n");
return;
@@ -1081,7 +1079,8 @@ irnet_disconnect_indication(void * instance,
struct sk_buff *skb)
{
irnet_socket * self = (irnet_socket *) instance;
- int test = 0;
+ int test_open;
+ int test_connect;
DENTER(IRDA_TCB_TRACE, "(self=0x%X)\n", (unsigned int) self);
DASSERT(self != NULL, , IRDA_CB_ERROR, "Self is NULL !!!\n");
@@ -1091,23 +1090,23 @@ irnet_disconnect_indication(void * instance,
dev_kfree_skb(skb);
/* Prevent higher layer from accessing IrTTP */
- test = test_and_clear_bit(0, &self->ttp_open);
+ test_open = test_and_clear_bit(0, &self->ttp_open);
/* Not connecting anymore...
* (note : TSAP is open, so IAP callbacks are no longer pending...) */
- test |= test_and_clear_bit(0, &self->ttp_connect);
+ test_connect = test_and_clear_bit(0, &self->ttp_connect);
/* If both self->ttp_open and self->ttp_connect are NULL, it mean that we
* have a race condition with irda_irnet_destroy() or
* irnet_connect_indication(), so don't mess up tsap...
*/
- if(!test)
+ if(!(test_open || test_connect))
{
DERROR(IRDA_CB_ERROR, "Race condition detected...\n");
return;
}
/* If we were active, notify the control channel */
- if(test_bit(0, &self->ttp_open))
+ if(test_open)
irnet_post_event(self, IRNET_DISCONNECT_FROM,
self->saddr, self->daddr, self->rname);
else
diff --git a/net/irda/irsysctl.c b/net/irda/irsysctl.c
index 4a029a9d4..7a73ad8ed 100644
--- a/net/irda/irsysctl.c
+++ b/net/irda/irsysctl.c
@@ -10,6 +10,7 @@
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1997, 1999 Dag Brattli, All Rights Reserved.
+ * Copyright (c) 2000-2001 Jean Tourrilhes <jt@hpl.hp.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -32,24 +33,47 @@
#include <net/irda/irias_object.h>
#define NET_IRDA 412 /* Random number */
-enum { DISCOVERY=1, DEVNAME, DEBUG, SLOTS, DISCOVERY_TIMEOUT,
- SLOT_TIMEOUT, MAX_BAUD_RATE, MAX_INACTIVE_TIME, LAP_KEEPALIVE_TIME, };
+enum { DISCOVERY=1, DEVNAME, DEBUG, FAST_POLL, DISCOVERY_SLOTS,
+ DISCOVERY_TIMEOUT, SLOT_TIMEOUT, MAX_BAUD_RATE, MIN_TX_TURN_TIME,
+ MAX_NOREPLY_TIME, WARN_NOREPLY_TIME, LAP_KEEPALIVE_TIME };
extern int sysctl_discovery;
extern int sysctl_discovery_slots;
extern int sysctl_discovery_timeout;
-extern int sysctl_slot_timeout;
+extern int sysctl_slot_timeout; /* Candidate */
extern int sysctl_fast_poll_increase;
int sysctl_compression = 0;
extern char sysctl_devname[];
extern int sysctl_max_baud_rate;
-extern int sysctl_max_inactive_time;
+extern int sysctl_min_tx_turn_time;
+extern int sysctl_max_noreply_time;
+extern int sysctl_warn_noreply_time;
extern int sysctl_lap_keepalive_time;
#ifdef CONFIG_IRDA_DEBUG
extern unsigned int irda_debug;
#endif
+/* this is needed for the proc_dointvec_minmax - Jean II */
+static int max_discovery_slots = 16; /* ??? */
+static int min_discovery_slots = 1;
+/* IrLAP 6.13.2 says 25ms to 10+70ms - allow higher since some devices
+ * seems to require it. (from Dag's comment) */
+static int max_slot_timeout = 160;
+static int min_slot_timeout = 20;
+static int max_max_baud_rate = 16000000; /* See qos.c - IrLAP spec */
+static int min_max_baud_rate = 2400;
+static int max_min_tx_turn_time = 10000; /* See qos.c - IrLAP spec */
+static int min_min_tx_turn_time = 0;
+static int max_max_noreply_time = 40; /* See qos.c - IrLAP spec */
+static int min_max_noreply_time = 3;
+static int max_warn_noreply_time = 3; /* 3s == standard */
+static int min_warn_noreply_time = 1; /* 1s == min WD_TIMER */
+static int max_lap_keepalive_time = 10000; /* 10s */
+static int min_lap_keepalive_time = 100; /* 100us */
+/* For other sysctl, I've no idea of the range. Maybe Dag could help
+ * us on that - Jean II */
+
static int do_devname(ctl_table *table, int write, struct file *filp,
void *buffer, size_t *lenp)
{
@@ -77,21 +101,32 @@ static ctl_table irda_table[] = {
sizeof(int), 0644, NULL, &proc_dointvec },
#endif
#ifdef CONFIG_IRDA_FAST_RR
- { SLOTS, "fast_poll_increase", &sysctl_fast_poll_increase,
+ { FAST_POLL, "fast_poll_increase", &sysctl_fast_poll_increase,
sizeof(int), 0644, NULL, &proc_dointvec },
#endif
- { SLOTS, "discovery_slots", &sysctl_discovery_slots,
- sizeof(int), 0644, NULL, &proc_dointvec },
+ { DISCOVERY_SLOTS, "discovery_slots", &sysctl_discovery_slots,
+ sizeof(int), 0644, NULL, &proc_dointvec_minmax, &sysctl_intvec,
+ NULL, &min_discovery_slots, &max_discovery_slots },
{ DISCOVERY_TIMEOUT, "discovery_timeout", &sysctl_discovery_timeout,
sizeof(int), 0644, NULL, &proc_dointvec },
{ SLOT_TIMEOUT, "slot_timeout", &sysctl_slot_timeout,
- sizeof(int), 0644, NULL, &proc_dointvec },
+ sizeof(int), 0644, NULL, &proc_dointvec_minmax, &sysctl_intvec,
+ NULL, &min_slot_timeout, &max_slot_timeout },
{ MAX_BAUD_RATE, "max_baud_rate", &sysctl_max_baud_rate,
- sizeof(int), 0644, NULL, &proc_dointvec },
- { MAX_INACTIVE_TIME, "max_inactive_time", &sysctl_max_inactive_time,
- sizeof(int), 0644, NULL, &proc_dointvec },
+ sizeof(int), 0644, NULL, &proc_dointvec_minmax, &sysctl_intvec,
+ NULL, &min_max_baud_rate, &max_max_baud_rate },
+ { MIN_TX_TURN_TIME, "min_tx_turn_time", &sysctl_min_tx_turn_time,
+ sizeof(int), 0644, NULL, &proc_dointvec_minmax, &sysctl_intvec,
+ NULL, &min_min_tx_turn_time, &max_min_tx_turn_time },
+ { MAX_NOREPLY_TIME, "max_noreply_time", &sysctl_max_noreply_time,
+ sizeof(int), 0644, NULL, &proc_dointvec_minmax, &sysctl_intvec,
+ NULL, &min_max_noreply_time, &max_max_noreply_time },
+ { WARN_NOREPLY_TIME, "warn_noreply_time", &sysctl_warn_noreply_time,
+ sizeof(int), 0644, NULL, &proc_dointvec_minmax, &sysctl_intvec,
+ NULL, &min_warn_noreply_time, &max_warn_noreply_time },
{ LAP_KEEPALIVE_TIME, "lap_keepalive_time", &sysctl_lap_keepalive_time,
- sizeof(int), 0644, NULL, &proc_dointvec },
+ sizeof(int), 0644, NULL, &proc_dointvec_minmax, &sysctl_intvec,
+ NULL, &min_lap_keepalive_time, &max_lap_keepalive_time },
{ 0 }
};
diff --git a/net/irda/qos.c b/net/irda/qos.c
index c0422af4b..d59793700 100644
--- a/net/irda/qos.c
+++ b/net/irda/qos.c
@@ -51,7 +51,16 @@ int sysctl_max_baud_rate = 16000000;
* may want to keep the LAP alive longuer or shorter in case of link failure.
* Remember that the threshold time (early warning) is fixed to 3s...
*/
-int sysctl_max_inactive_time = 12;
+int sysctl_max_noreply_time = 12;
+/*
+ * Minimum turn time to be applied before transmitting to the peer.
+ * Nonzero values (usec) are used as lower limit to the per-connection
+ * mtt value which was announced by the other end during negotiation.
+ * Might be helpful if the peer device provides too short mtt.
+ * Default is 10 which means using the unmodified value given by the peer
+ * except if it's 0 (0 is likely a bug in the other stack).
+ */
+unsigned sysctl_min_tx_turn_time = 10;
static int irlap_param_baud_rate(void *instance, irda_param_t *param, int get);
static int irlap_param_link_disconnect(void *instance, irda_param_t *parm,
@@ -184,7 +193,6 @@ static inline __u32 byte_value(__u8 byte, __u32 *array)
* Function value_lower_bits (value, array)
*
* Returns a bit field marking all possibility lower than value.
- * We may need a "value_higher_bits" in the future...
*/
static inline int value_lower_bits(__u32 value, __u32 *array, int size, __u16 *field)
{
@@ -207,6 +215,33 @@ static inline int value_lower_bits(__u32 value, __u32 *array, int size, __u16 *f
return i;
}
+/*
+ * Function value_highest_bit (value, array)
+ *
+ * Returns a bit field marking the highest possibility lower than value.
+ */
+static inline int value_highest_bit(__u32 value, __u32 *array, int size, __u16 *field)
+{
+ int i;
+ __u16 mask = 0x1;
+ __u16 result = 0x0;
+
+ for (i=0; i < size; i++) {
+ /* Finished ? */
+ if (array[i] <= value)
+ break;
+ /* Shift mask */
+ mask <<= 1;
+ }
+ /* Set the current value to the bit field */
+ result |= mask;
+ /* Send back a valid index */
+ if(i >= size)
+ i = size - 1; /* Last item */
+ *field = result;
+ return i;
+}
+
/* -------------------------- MAIN CALLS -------------------------- */
/*
@@ -254,9 +289,9 @@ void irda_init_max_qos_capabilies(struct qos_info *qos)
sysctl_max_baud_rate = index_value(i, baud_rates);
/* Set configured max disc time */
- i = value_lower_bits(sysctl_max_inactive_time, link_disc_times, 8,
+ i = value_lower_bits(sysctl_max_noreply_time, link_disc_times, 8,
&qos->link_disc_time.bits);
- sysctl_max_inactive_time = index_value(i, link_disc_times);
+ sysctl_max_noreply_time = index_value(i, link_disc_times);
/* LSB is first byte, MSB is second byte */
qos->baud_rate.bits &= 0x03ff;
@@ -282,6 +317,19 @@ void irlap_adjust_qos_settings(struct qos_info *qos)
IRDA_DEBUG(2, __FUNCTION__ "()\n");
+ /*
+ * Make sure the mintt is sensible.
+ */
+ if (sysctl_min_tx_turn_time > qos->min_turn_time.value) {
+ int i;
+
+ /* We don't really need bits, but easier this way */
+ i = value_highest_bit(sysctl_min_tx_turn_time, min_turn_times,
+ 8, &qos->min_turn_time.bits);
+ sysctl_min_tx_turn_time = index_value(i, min_turn_times);
+ qos->min_turn_time.value = sysctl_min_tx_turn_time;
+ }
+
/*
* Not allowed to use a max turn time less than 500 ms if the baudrate
* is less than 115200