Merge rsync://rsync.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
authorLinus Torvalds <torvalds@ppc970.osdl.org>
Wed, 29 Jun 2005 04:24:32 +0000 (21:24 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Wed, 29 Jun 2005 04:24:32 +0000 (21:24 -0700)
144 files changed:
Documentation/SubmittingDrivers
Documentation/SubmittingPatches
Documentation/kernel-parameters.txt
Documentation/video4linux/API.html
Documentation/video4linux/CARDLIST.cx88
Documentation/video4linux/CARDLIST.saa7134
Documentation/video4linux/CARDLIST.tuner
Documentation/video4linux/README.saa7134
MAINTAINERS
arch/arm/Kconfig
arch/arm/mach-s3c2410/irq.c
arch/arm/oprofile/Makefile
arch/arm/oprofile/backtrace.c [new file with mode: 0644]
arch/arm/oprofile/init.c
arch/arm/oprofile/op_arm_model.h
arch/i386/boot/tools/build.c
arch/i386/kernel/acpi/boot.c
arch/i386/pci/common.c
arch/i386/pci/irq.c
arch/i386/pci/legacy.c
arch/i386/pci/mmconfig.c
arch/i386/pci/numa.c
arch/i386/pci/pci.h
arch/ia64/kernel/acpi.c
arch/ia64/kernel/iosapic.c
arch/ia64/pci/pci.c
arch/ppc/kernel/pci.c
arch/ppc64/kernel/irq.c
arch/ppc64/kernel/pci.c
arch/sparc/Kconfig
arch/x86_64/pci/mmconfig.c
drivers/acpi/container.c
drivers/acpi/pci_bind.c
drivers/acpi/pci_root.c
drivers/acpi/processor_core.c
drivers/acpi/scan.c
drivers/base/firmware_class.c
drivers/block/cciss.c
drivers/block/ll_rw_blk.c
drivers/char/agp/amd64-agp.c
drivers/char/ipmi/ipmi_msghandler.c
drivers/char/moxa.c
drivers/char/rio/rio_linux.c
drivers/char/rtc.c
drivers/char/tipar.c
drivers/char/tty_ioctl.c
drivers/char/vt_ioctl.c
drivers/char/watchdog/ixp2000_wdt.c
drivers/char/watchdog/ixp4xx_wdt.c
drivers/isdn/hardware/eicon/dadapter.c
drivers/isdn/hisax/hfc4s8s_l1.c
drivers/isdn/hysdn/hycapi.c
drivers/isdn/hysdn/hysdn_boot.c
drivers/isdn/hysdn/hysdn_defs.h
drivers/isdn/hysdn/hysdn_init.c
drivers/isdn/hysdn/hysdn_proclog.c
drivers/md/md.c
drivers/media/video/Makefile
drivers/media/video/bttv-driver.c
drivers/media/video/bttvp.h
drivers/media/video/mt20xx.c
drivers/media/video/tda8290.c
drivers/media/video/tda9887.c
drivers/media/video/tea5767.c [new file with mode: 0644]
drivers/media/video/tuner-core.c
drivers/media/video/tuner-simple.c
drivers/message/fusion/mptfc.c
drivers/message/fusion/mptscsih.c
drivers/message/fusion/mptscsih.h
drivers/message/fusion/mptspi.c
drivers/net/e100.c
drivers/net/via-rhine.c
drivers/parisc/dino.c
drivers/parisc/lba_pci.c
drivers/pci/bus.c
drivers/pci/hotplug/Makefile
drivers/pci/hotplug/acpiphp.h
drivers/pci/hotplug/acpiphp_core.c
drivers/pci/hotplug/acpiphp_glue.c
drivers/pci/hotplug/acpiphp_pci.c [deleted file]
drivers/pci/hotplug/acpiphp_res.c [deleted file]
drivers/pci/hotplug/cpqphp_core.c
drivers/pci/msi.c
drivers/pci/msi.h
drivers/pci/pci-sysfs.c
drivers/pci/probe.c
drivers/pci/proc.c
drivers/pci/remove.c
drivers/pci/setup-bus.c
drivers/scsi/3w-9xxx.c
drivers/scsi/3w-xxxx.c
drivers/scsi/ipr.c
drivers/scsi/megaraid.c
drivers/scsi/scsi_lib.c
fs/aio.c
fs/buffer.c
fs/char_dev.c
fs/ext3/balloc.c
fs/ext3/file.c
fs/ext3/super.c
fs/nfs/nfs3acl.c
fs/nfsd/vfs.c
fs/udf/namei.c
include/acpi/acpi_bus.h
include/acpi/acpi_drivers.h
include/asm-alpha/pci.h
include/asm-arm/arch-s3c2410/audio.h [new file with mode: 0644]
include/asm-arm/pci.h
include/asm-frv/pci.h
include/asm-i386/pci.h
include/asm-ia64/iosapic.h
include/asm-ia64/pci.h
include/asm-mips/pci.h
include/asm-parisc/pci.h
include/asm-ppc/pci.h
include/asm-ppc64/byteorder.h
include/asm-ppc64/pci.h
include/asm-sh/pci.h
include/asm-sh64/pci.h
include/asm-sparc/pci.h
include/asm-sparc64/pci.h
include/asm-v850/pci.h
include/asm-x86_64/pci.h
include/linux/acpi.h
include/linux/blkdev.h
include/linux/byteorder/swabb.h
include/linux/i2c-dev.h
include/linux/irq.h
include/linux/pci.h
include/linux/pci_ids.h
include/linux/usb_ch9.h
include/linux/videodev2.h
include/linux/writeback.h
include/linux/xattr_acl.h [deleted file]
include/media/tuner.h
init/main.c
kernel/irq/autoprobe.c
kernel/irq/handle.c
kernel/irq/spurious.c
kernel/itimer.c
kernel/kexec.c
kernel/sched.c
mm/page-writeback.c
mm/vmscan.c

index de3b252..c3cca92 100644 (file)
@@ -13,13 +13,14 @@ Allocating Device Numbers
 -------------------------
 
 Major and minor numbers for block and character devices are allocated
-by the Linux assigned name and number authority (currently better
-known as H Peter Anvin). The site is http://www.lanana.org/. This
+by the Linux assigned name and number authority (currently this is
+Torben Mathiasen). The site is http://www.lanana.org/. This
 also deals with allocating numbers for devices that are not going to
 be submitted to the mainstream kernel.
+See Documentation/devices.txt for more information on this.
 
-If you don't use assigned numbers then when you device is submitted it will
-get given an assigned number even if that is different from values you may
+If you don't use assigned numbers then when your device is submitted it will
+be given an assigned number even if that is different from values you may
 have shipped to customers before.
 
 Who To Submit Drivers To
@@ -32,7 +33,8 @@ Linux 2.2:
        If the code area has a general maintainer then please submit it to
        the maintainer listed in MAINTAINERS in the kernel file. If the
        maintainer does not respond or you cannot find the appropriate
-       maintainer then please contact Alan Cox <alan@lxorguk.ukuu.org.uk>
+       maintainer then please contact the 2.2 kernel maintainer:
+       Marc-Christian Petersen <m.c.p@wolk-project.de>.
 
 Linux 2.4:
        The same rules apply as 2.2. The final contact point for Linux 2.4
@@ -48,7 +50,7 @@ What Criteria Determine Acceptance
 
 Licensing:     The code must be released to us under the
                GNU General Public License. We don't insist on any kind
-               of exclusively GPL licensing, and if you wish the driver
+               of exclusive GPL licensing, and if you wish the driver
                to be useful to other communities such as BSD you may well
                wish to release under multiple licenses.
 
index 4d1f41b..6761a7b 100644 (file)
@@ -35,7 +35,7 @@ not in any lower subdirectory.
 
 To create a patch for a single file, it is often sufficient to do:
 
-       SRCTREE= linux-2.4
+       SRCTREE= linux-2.6
        MYFILE=  drivers/net/mydriver.c
 
        cd $SRCTREE
@@ -48,17 +48,18 @@ To create a patch for multiple files, you should unpack a "vanilla",
 or unmodified kernel source tree, and generate a diff against your
 own source tree.  For example:
 
-       MYSRC= /devel/linux-2.4
+       MYSRC= /devel/linux-2.6
 
-       tar xvfz linux-2.4.0-test11.tar.gz
-       mv linux linux-vanilla
-       wget http://www.moses.uklinux.net/patches/dontdiff
-       diff -uprN -X dontdiff linux-vanilla $MYSRC > /tmp/patch
-       rm -f dontdiff
+       tar xvfz linux-2.6.12.tar.gz
+       mv linux-2.6.12 linux-2.6.12-vanilla
+       diff -uprN -X linux-2.6.12-vanilla/Documentation/dontdiff \
+               linux-2.6.12-vanilla $MYSRC > /tmp/patch
 
 "dontdiff" is a list of files which are generated by the kernel during
 the build process, and should be ignored in any diff(1)-generated
-patch.  dontdiff is maintained by Tigran Aivazian <tigran@veritas.com>
+patch.  The "dontdiff" file is included in the kernel tree in
+2.6.12 and later.  For earlier kernel versions, you can get it
+from <http://www.xenotime.net/linux/doc/dontdiff>.
 
 Make sure your patch does not include any extra files which do not
 belong in a patch submission.  Make sure to review your patch -after-
@@ -66,18 +67,20 @@ generated it with diff(1), to ensure accuracy.
 
 If your changes produce a lot of deltas, you may want to look into
 splitting them into individual patches which modify things in
-logical stages, this will facilitate easier reviewing by other
+logical stages.  This will facilitate easier reviewing by other
 kernel developers, very important if you want your patch accepted.
-There are a number of scripts which can aid in this;
+There are a number of scripts which can aid in this:
 
 Quilt:
 http://savannah.nongnu.org/projects/quilt
 
 Randy Dunlap's patch scripts:
-http://developer.osdl.org/rddunlap/scripts/patching-scripts.tgz
+http://www.xenotime.net/linux/scripts/patching-scripts-002.tar.gz
 
 Andrew Morton's patch scripts:
-http://www.zip.com.au/~akpm/linux/patches/patch-scripts-0.16
+http://www.zip.com.au/~akpm/linux/patches/patch-scripts-0.20
+
+
 
 2) Describe your changes.
 
@@ -163,6 +166,8 @@ patches. Trivial patches must qualify for one of the following rules:
  since people copy, as long as it's trivial)
  Any fix by the author/maintainer of the file. (ie. patch monkey
  in re-transmission mode)
+URL: <http://www.kernel.org/pub/linux/kernel/people/rusty/trivial/>
+
 
 
 
@@ -291,6 +296,17 @@ now, but you can do this to mark internal company procedures or just
 point out some special detail about the sign-off. 
 
 
+
+12) More references for submitting patches
+
+Andrew Morton, "The perfect patch" (tpp).
+  <http://www.zip.com.au/~akpm/linux/patches/stuff/tpp.txt>
+
+Jeff Garzik, "Linux kernel patch submission format."
+  <http://linux.yyz.us/patch-format.html>
+
+
+
 -----------------------------------
 SECTION 2 - HINTS, TIPS, AND TRICKS
 -----------------------------------
@@ -359,7 +375,5 @@ and 'extern __inline__'.
 4) Don't over-design.
 
 Don't try to anticipate nebulous future cases which may or may not
-be useful:  "Make it as simple as you can, and no simpler"
-
-
+be useful:  "Make it as simple as you can, and no simpler."
 
index 89cd417..67e99f1 100644 (file)
@@ -437,6 +437,10 @@ running once the system is up.
                        Format: {"of[f]" | "sk[ipmbr]"}
                        See comment in arch/i386/boot/edd.S
 
+       edd             [EDD]
+                       Format: {"of[f]" | "sk[ipmbr]"}
+                       See comment in arch/i386/boot/edd.S
+
        eicon=          [HW,ISDN] 
                        Format: <id>,<membase>,<irq>
 
@@ -622,6 +626,17 @@ running once the system is up.
        ips=            [HW,SCSI] Adaptec / IBM ServeRAID controller
                        See header of drivers/scsi/ips.c.
 
+       irqfixup        [HW]
+                       When an interrupt is not handled search all handlers
+                       for it. Intended to get systems with badly broken
+                       firmware running.
+
+       irqpoll         [HW]
+                       When an interrupt is not handled search all handlers
+                       for it. Also check all handlers each timer
+                       interrupt. Intended to get systems with badly broken
+                       firmware running.
+
        isapnp=         [ISAPNP]
                        Format: <RDP>, <reset>, <pci_scan>, <verbosity>
 
@@ -1030,6 +1045,10 @@ running once the system is up.
                irqmask=0xMMMM          [IA-32] Set a bit mask of IRQs allowed to be assigned
                                        automatically to PCI devices. You can make the kernel
                                        exclude IRQs of your ISA cards this way.
+               pirqaddr=0xAAAAA        [IA-32] Specify the physical address
+                                       of the PIRQ table (normally generated
+                                       by the BIOS) if it is outside the
+                                       F0000h-100000h range.
                lastbus=N               [IA-32] Scan all buses till bus #N. Can be useful
                                        if the kernel is unable to find your secondary buses
                                        and you want to tell it explicitly which ones they are.
index 4b3d8f6..441407b 100644 (file)
-<HTML><HEAD>
-<TITLE>Video4Linux Kernel API Reference v0.1:19990430</TITLE>
-</HEAD>
-<! Revision History: >
-<!   4/30/1999 - Fred Gleason (fredg@wava.com)>
-<! Documented extensions for the Radio Data System (RDS) extensions >
-<BODY bgcolor="#ffffff">
-<H3>Devices</H3>
-Video4Linux provides the following sets of device files. These live on the
-character device formerly known as "/dev/bttv". /dev/bttv should be a
-symlink to /dev/video0 for most people. 
-<P>
-<TABLE>
-<TR><TH>Device Name</TH><TH>Minor Range</TH><TH>Function</TH>
-<TR><TD>/dev/video</TD><TD>0-63</TD><TD>Video Capture Interface</TD>
-<TR><TD>/dev/radio</TD><TD>64-127</TD><TD>AM/FM Radio Devices</TD>
-<TR><TD>/dev/vtx</TD><TD>192-223</TD><TD>Teletext Interface Chips</TD>
-<TR><TD>/dev/vbi</TD><TD>224-239</TD><TD>Raw VBI Data (Intercast/teletext)</TD>
-</TABLE>
-<P>
-Video4Linux programs open and scan the devices to find what they are looking
-for. Capability queries define what each interface supports. The 
-described API is only defined for video capture cards. The relevant subset
-applies to radio cards. Teletext interfaces talk the existing VTX API.
-<P>
-<H3>Capability Query Ioctl</H3>
-The <B>VIDIOCGCAP</B> ioctl call is used to obtain the capability
-information for a video device. The <b>struct video_capability</b> object
-passed to the ioctl is completed and returned. It contains the following
-information
-<P>
-<TABLE>
-<TR><TD><b>name[32]</b><TD>Canonical name for this interface</TD>
-<TR><TD><b>type</b><TD>Type of interface</TD>
-<TR><TD><b>channels</b><TD>Number of radio/tv channels if appropriate</TD>
-<TR><TD><b>audios</b><TD>Number of audio devices if appropriate</TD>
-<TR><TD><b>maxwidth</b><TD>Maximum capture width in pixels</TD>
-<TR><TD><b>maxheight</b><TD>Maximum capture height in pixels</TD>
-<TR><TD><b>minwidth</b><TD>Minimum capture width in pixels</TD>
-<TR><TD><b>minheight</b><TD>Minimum capture height in pixels</TD>
-</TABLE>
-<P>
-The type field lists the capability flags for the device. These are
-as follows
-<P>
-<TABLE>
-<TR><TH>Name</TH><TH>Description</TH>
-<TR><TD><b>VID_TYPE_CAPTURE</b><TD>Can capture to memory</TD>
-<TR><TD><b>VID_TYPE_TUNER</b><TD>Has a tuner of some form</TD>
-<TR><TD><b>VID_TYPE_TELETEXT</b><TD>Has teletext capability</TD>
-<TR><TD><b>VID_TYPE_OVERLAY</b><TD>Can overlay its image onto the frame buffer</TD>
-<TR><TD><b>VID_TYPE_CHROMAKEY</b><TD>Overlay is Chromakeyed</TD>
-<TR><TD><b>VID_TYPE_CLIPPING</b><TD>Overlay clipping is supported</TD>
-<TR><TD><b>VID_TYPE_FRAMERAM</b><TD>Overlay overwrites frame buffer memory</TD>
-<TR><TD><b>VID_TYPE_SCALES</b><TD>The hardware supports image scaling</TD>
-<TR><TD><b>VID_TYPE_MONOCHROME</b><TD>Image capture is grey scale only</TD>
-<TR><TD><b>VID_TYPE_SUBCAPTURE</b><TD>Capture can be of only part of the image</TD>
-</TABLE>
-<P>
-The minimum and maximum sizes listed for a capture device do not imply all
-that all height/width ratios or sizes within the range are possible. A
-request to set a size will be honoured by the largest available capture
-size whose capture is no large than the requested rectangle in either
-direction. For example the quickcam has 3 fixed settings. 
-<P>
-<H3>Frame Buffer</H3>
-Capture cards that drop data directly onto the frame buffer must be told the
-base address of the frame buffer, its size and organisation. This is a 
-privileged ioctl and one that eventually X itself should set.
-<P>
-The <b>VIDIOCSFBUF</b> ioctl sets the frame buffer parameters for a capture
-card. If the card does not do direct writes to the frame buffer then this
-ioctl will be unsupported. The <b>VIDIOCGFBUF</b> ioctl returns the
-currently used parameters. The structure used in both cases is a 
-<b>struct video_buffer</b>.
-<P>
-<TABLE>
-<TR><TD><b>void *base</b></TD><TD>Base physical address of the buffer</TD>
-<TR><TD><b>int height</b></TD><TD>Height of the frame buffer</TD>
-<TR><TD><b>int width</b></TD><TD>Width of the frame buffer</TD>
-<TR><TD><b>int depth</b></TD><TD>Depth of the frame buffer</TD>
-<TR><TD><b>int bytesperline</b></TD><TD>Number of bytes of memory between the start of two adjacent lines</TD>
-</TABLE>
-<P>
-Note that these values reflect the physical layout of the frame buffer. 
-The visible area may be smaller. In fact under XFree86 this is commonly the
-case. XFree86 DGA can provide the parameters required to set up this ioctl.
-Setting the base address to NULL indicates there is no physical frame buffer
-access.
-<P>
-<H3>Capture Windows</H3>
-The capture area is described by a <b>struct video_window</b>. This defines
-a capture area and the clipping information if relevant. The 
-<b>VIDIOCGWIN</b> ioctl recovers the current settings and the 
-<b>VIDIOCSWIN</b> sets new values. A successful call to <b>VIDIOCSWIN</b> 
-indicates that a suitable set of parameters have been chosen. They do not
-indicate that exactly what was requested was granted. The program should
-call <b>VIDIOCGWIN</b> to check if the nearest match was suitable. The
-<b>struct video_window</b> contains the following fields.
-<P>
-<TABLE>
-<TR><TD><b>x</b><TD>The X co-ordinate specified in X windows format.</TD>
-<TR><TD><b>y</b><TD>The Y co-ordinate specified in X windows format.</TD>
-<TR><TD><b>width</b><TD>The width of the image capture.</TD>
-<TR><TD><b>height</b><TD>The height of the image capture.</TD>
-<TR><TD><b>chromakey</b><TD>A host order RGB32 value for the chroma key.</TD>
-<TR><TD><b>flags</b><TD>Additional capture flags.</TD>
-<TR><TD><b>clips</b><TD>A list of clipping rectangles. <em>(Set only)</em></TD>
-<TR><TD><b>clipcount</b><TD>The number of clipping rectangles. <em>(Set only)</em></TD>
-</TABLE>
-<P>
-Clipping rectangles are passed as an array. Each clip consists of the following
-fields available to the user.
-<P>
-<TABLE>
-<TR><TD><b>x</b></TD><TD>X co-ordinate of rectangle to skip</TD>
-<TR><TD><b>y</b></TD><TD>Y co-ordinate of rectangle to skip</TD>
-<TR><TD><b>width</b></TD><TD>Width of rectangle to skip</TD>
-<TR><TD><b>height</b></TD><TD>Height of rectangle to skip</TD>
-</TABLE>
-<P>
-Merely setting the window does not enable capturing. Overlay capturing
-(i.e. PCI-PCI transfer to the frame buffer of the video card)
-is activated by passing the <b>VIDIOCCAPTURE</b> ioctl a value of 1, and
-disabled by passing it a value of 0. 
-<P>
-Some capture devices can capture a subfield of the image they actually see.
-This is indicated when VIDEO_TYPE_SUBCAPTURE is defined.
-The video_capture describes the time and special subfields to capture.
-The video_capture structure contains the following fields.
-<P>
-<TABLE>
-<TR><TD><b>x</b></TD><TD>X co-ordinate of source rectangle to grab</TD>
-<TR><TD><b>y</b></TD><TD>Y co-ordinate of source rectangle to grab</TD>
-<TR><TD><b>width</b></TD><TD>Width of source rectangle to grab</TD>
-<TR><TD><b>height</b></TD><TD>Height of source rectangle to grab</TD>
-<TR><TD><b>decimation</b></TD><TD>Decimation to apply</TD>
-<TR><TD><b>flags</b></TD><TD>Flag settings for grabbing</TD>
-</TABLE>
-The available flags are
-<P>
-<TABLE>
-<TR><TH>Name</TH><TH>Description</TH>
-<TR><TD><b>VIDEO_CAPTURE_ODD</b><TD>Capture only odd frames</TD>
-<TR><TD><b>VIDEO_CAPTURE_EVEN</b><TD>Capture only even frames</TD>
-</TABLE>
-<P>
-<H3>Video Sources</H3>
-Each video4linux video or audio device captures from one or more 
-source <b>channels</b>. Each channel can be queries with the 
-<b>VDIOCGCHAN</b> ioctl call. Before invoking this function the caller
-must set the channel field to the channel that is being queried. On return
-the <b>struct video_channel</b> is filled in with information about the
-nature of the channel itself.
-<P>
-The <b>VIDIOCSCHAN</b> ioctl takes an integer argument and switches the
-capture to this input. It is not defined whether parameters such as colour
-settings or tuning are maintained across a channel switch. The caller should
-maintain settings as desired for each channel. (This is reasonable as 
-different video inputs may have different properties).
-<P>
-The <b>struct video_channel</b> consists of the following
-<P>
-<TABLE>
-<TR><TD><b>channel</b></TD><TD>The channel number</TD>
-<TR><TD><b>name</b></TD><TD>The input name - preferably reflecting the label
-on the card input itself</TD>
-<TR><TD><b>tuners</b></TD><TD>Number of tuners for this input</TD>
-<TR><TD><b>flags</b></TD><TD>Properties the tuner has</TD>
-<TR><TD><b>type</b></TD><TD>Input type (if known)</TD>
-<TR><TD><b>norm</b><TD>The norm for this channel</TD>
-</TABLE>
-<P>
-The flags defined are
-<P>
-<TABLE>
-<TR><TD><b>VIDEO_VC_TUNER</b><TD>Channel has tuners.</TD>
-<TR><TD><b>VIDEO_VC_AUDIO</b><TD>Channel has audio.</TD>
-<TR><TD><b>VIDEO_VC_NORM</b><TD>Channel has norm setting.</TD>
-</TABLE>
-<P>
-The types defined are
-<P>
-<TABLE>
-<TR><TD><b>VIDEO_TYPE_TV</b><TD>The input is a TV input.</TD>
-<TR><TD><b>VIDEO_TYPE_CAMERA</b><TD>The input is a camera.</TD>
-</TABLE>
-<P>
-<H3>Image Properties</H3>
-The image properties of the picture can be queried with the <b>VIDIOCGPICT</b>
-ioctl which fills in a <b>struct video_picture</b>. The <b>VIDIOCSPICT</b> 
-ioctl allows values to be changed. All values except for the palette type
-are scaled between 0-65535. 
-<P>
-The <b>struct video_picture</b> consists of the following fields
-<P>
-<TABLE>
-<TR><TD><b>brightness</b><TD>Picture brightness</TD>
-<TR><TD><b>hue</b><TD>Picture hue (colour only)</TD>
-<TR><TD><b>colour</b><TD>Picture colour (colour only)</TD>
-<TR><TD><b>contrast</b><TD>Picture contrast</TD>
-<TR><TD><b>whiteness</b><TD>The whiteness (greyscale only)</TD>
-<TR><TD><b>depth</b><TD>The capture depth (may need to match the frame buffer depth)</TD>
-<TR><TD><b>palette</b><TD>Reports the palette that should be used for this image</TD>
-</TABLE>
-<P>
-The following palettes are defined
-<P>
-<TABLE>
-<TR><TD><b>VIDEO_PALETTE_GREY</b><TD>Linear intensity grey scale (255 is brightest).</TD>
-<TR><TD><b>VIDEO_PALETTE_HI240</b><TD>The BT848 8bit colour cube.</TD>
-<TR><TD><b>VIDEO_PALETTE_RGB565</b><TD>RGB565 packed into 16 bit words.</TD>
-<TR><TD><b>VIDEO_PALETTE_RGB555</b><TD>RGV555 packed into 16 bit words, top bit undefined.</TD>
-<TR><TD><b>VIDEO_PALETTE_RGB24</b><TD>RGB888 packed into 24bit words.</TD>
-<TR><TD><b>VIDEO_PALETTE_RGB32</b><TD>RGB888 packed into the low 3 bytes of 32bit words. The top 8bits are undefined.</TD>
-<TR><TD><b>VIDEO_PALETTE_YUV422</b><TD>Video style YUV422 - 8bits packed 4bits Y 2bits U 2bits V</TD>
-<TR><TD><b>VIDEO_PALETTE_YUYV</b><TD>Describe me</TD>
-<TR><TD><b>VIDEO_PALETTE_UYVY</b><TD>Describe me</TD>
-<TR><TD><b>VIDEO_PALETTE_YUV420</b><TD>YUV420 capture</TD>
-<TR><TD><b>VIDEO_PALETTE_YUV411</b><TD>YUV411 capture</TD>
-<TR><TD><b>VIDEO_PALETTE_RAW</b><TD>RAW capture (BT848)</TD>
-<TR><TD><b>VIDEO_PALETTE_YUV422P</b><TD>YUV 4:2:2 Planar</TD>
-<TR><TD><b>VIDEO_PALETTE_YUV411P</b><TD>YUV 4:1:1 Planar</TD>
-</TABLE>
-<P>
-<H3>Tuning</H3>
-Each video input channel can have one or more tuners associated with it. Many
-devices will not have tuners. TV cards and radio cards will have one or more
-tuners attached.
-<P>
-Tuners are described by a <b>struct video_tuner</b> which can be obtained by
-the <b>VIDIOCGTUNER</b> ioctl. Fill in the tuner number in the structure
-then pass the structure to the ioctl to have the data filled in. The 
-tuner can be switched using <b>VIDIOCSTUNER</b> which takes an integer argument
-giving the tuner to use. A struct tuner has the following fields
-<P>
-<TABLE>
-<TR><TD><b>tuner</b><TD>Number of the tuner</TD>
-<TR><TD><b>name</b><TD>Canonical name for this tuner (eg FM/AM/TV)</TD>
-<TR><TD><b>rangelow</b><TD>Lowest tunable frequency</TD>
-<TR><TD><b>rangehigh</b><TD>Highest tunable frequency</TD>
-<TR><TD><b>flags</b><TD>Flags describing the tuner</TD>
-<TR><TD><b>mode</b><TD>The video signal mode if relevant</TD>
-<TR><TD><b>signal</b><TD>Signal strength if known - between 0-65535</TD>
-</TABLE>
-<P>
-The following flags exist
-<P>
-<TABLE>
-<TR><TD><b>VIDEO_TUNER_PAL</b><TD>PAL tuning is supported</TD>
-<TR><TD><b>VIDEO_TUNER_NTSC</b><TD>NTSC tuning is supported</TD>
-<TR><TD><b>VIDEO_TUNER_SECAM</b><TD>SECAM tuning is supported</TD>
-<TR><TD><b>VIDEO_TUNER_LOW</b><TD>Frequency is in a lower range</TD>
-<TR><TD><b>VIDEO_TUNER_NORM</b><TD>The norm for this tuner is settable</TD>
-<TR><TD><b>VIDEO_TUNER_STEREO_ON</b><TD>The tuner is seeing stereo audio</TD>
-<TR><TD><b>VIDEO_TUNER_RDS_ON</b><TD>The tuner is seeing a RDS datastream</TD>
-<TR><TD><b>VIDEO_TUNER_MBS_ON</b><TD>The tuner is seeing a MBS datastream</TD>
-</TABLE>
-<P>
-The following modes are defined
-<P>
-<TABLE>
-<TR><TD><b>VIDEO_MODE_PAL</b><TD>The tuner is in PAL mode</TD>
-<TR><TD><b>VIDEO_MODE_NTSC</b><TD>The tuner is in NTSC mode</TD>
-<TR><TD><b>VIDEO_MODE_SECAM</b><TD>The tuner is in SECAM mode</TD>
-<TR><TD><b>VIDEO_MODE_AUTO</b><TD>The tuner auto switches, or mode does not apply</TD>
-</TABLE>
-<P>
-Tuning frequencies are an unsigned 32bit value in 1/16th MHz or if the
-<b>VIDEO_TUNER_LOW</b> flag is set they are in 1/16th KHz. The current
-frequency is obtained as an unsigned long via the <b>VIDIOCGFREQ</b> ioctl and
-set by the <b>VIDIOCSFREQ</b> ioctl.
-<P>
-<H3>Audio</H3>
-TV and Radio devices have one or more audio inputs that may be selected. 
-The audio properties are queried by passing a <b>struct video_audio</b> to <b>VIDIOCGAUDIO</b> ioctl. The
-<b>VIDIOCSAUDIO</b> ioctl sets audio properties.
-<P>
-The structure contains the following fields
-<P>
-<TABLE>
-<TR><TD><b>audio</b><TD>The channel number</TD>
-<TR><TD><b>volume</b><TD>The volume level</TD>
-<TR><TD><b>bass</b><TD>The bass level</TD>
-<TR><TD><b>treble</b><TD>The treble level</TD>
-<TR><TD><b>flags</b><TD>Flags describing the audio channel</TD>
-<TR><TD><b>name</b><TD>Canonical name for the audio input</TD>
-<TR><TD><b>mode</b><TD>The mode the audio input is in</TD>
-<TR><TD><b>balance</b><TD>The left/right balance</TD>
-<TR><TD><b>step</b><TD>Actual step used by the hardware</TD>
-</TABLE>
-<P>
-The following flags are defined
-<P>
-<TABLE>
-<TR><TD><b>VIDEO_AUDIO_MUTE</b><TD>The audio is muted</TD>
-<TR><TD><b>VIDEO_AUDIO_MUTABLE</b><TD>Audio muting is supported</TD>
-<TR><TD><b>VIDEO_AUDIO_VOLUME</b><TD>The volume is controllable</TD>
-<TR><TD><b>VIDEO_AUDIO_BASS</b><TD>The bass is controllable</TD>
-<TR><TD><b>VIDEO_AUDIO_TREBLE</b><TD>The treble is controllable</TD>
-<TR><TD><b>VIDEO_AUDIO_BALANCE</b><TD>The balance is controllable</TD>
-</TABLE>
-<P>
-The following decoding modes are defined
-<P>
-<TABLE>
-<TR><TD><b>VIDEO_SOUND_MONO</b><TD>Mono signal</TD>
-<TR><TD><b>VIDEO_SOUND_STEREO</b><TD>Stereo signal (NICAM for TV)</TD>
-<TR><TD><b>VIDEO_SOUND_LANG1</b><TD>European TV alternate language 1</TD>
-<TR><TD><b>VIDEO_SOUND_LANG2</b><TD>European TV alternate language 2</TD>
-</TABLE>
-<P>
-<H3>Reading Images</H3>
-Each call to the <b>read</b> syscall returns the next available image
-from the device. It is up to the caller to set format and size (using
-the VIDIOCSPICT and VIDIOCSWIN ioctls) and then to pass a suitable
-size buffer and length to the function. Not all devices will support
-read operations.
-<P>
-A second way to handle image capture is via the mmap interface if supported.
-To use the mmap interface a user first sets the desired image size and depth
-properties. Next the VIDIOCGMBUF ioctl is issued. This reports the size
-of buffer to mmap and the offset within the buffer for each frame. The
-number of frames supported is device dependent and may only be one. 
-<P>
-The video_mbuf structure contains the following fields
-<P>
-<TABLE>
-<TR><TD><b>size</b><TD>The number of bytes to map</TD>
-<TR><TD><b>frames</b><TD>The number of frames</TD>
-<TR><TD><b>offsets</b><TD>The offset of each frame</TD>
-</TABLE>
-<P>
-Once the mmap has been made the VIDIOCMCAPTURE ioctl starts the
-capture to a frame using the format and image size specified in the
-video_mmap (which should match or be below the initial query size).
-When the VIDIOCMCAPTURE ioctl returns the frame is <em>not</em>
-captured yet, the driver just instructed the hardware to start the
-capture.  The application has to use the VIDIOCSYNC ioctl to wait
-until the capture of a frame is finished.  VIDIOCSYNC takes the frame
-number you want to wait for as argument.
-<p>
-It is allowed to call VIDIOCMCAPTURE multiple times (with different
-frame numbers in video_mmap->frame of course) and thus have multiple
-outstanding capture requests.  A simple way do to double-buffering
-using this feature looks like this:
-<pre>
-/* setup everything */
-VIDIOCMCAPTURE(0)
-while (whatever) {
-   VIDIOCMCAPTURE(1)
-   VIDIOCSYNC(0)
-   /* process frame 0 while the hardware captures frame 1 */
-   VIDIOCMCAPTURE(0)
-   VIDIOCSYNC(1)
-   /* process frame 1 while the hardware captures frame 0 */
-}
-</pre>
-Note that you are <em>not</em> limited to only two frames.  The API
-allows up to 32 frames, the VIDIOCGMBUF ioctl returns the number of
-frames the driver granted.  Thus it is possible to build deeper queues
-to avoid loosing frames on load peaks.
-<p>
-While capturing to memory the driver will make a "best effort" attempt
-to capture to screen as well if requested. This normally means all
-frames that "miss" memory mapped capture will go to the display.
-<P>
-A final ioctl exists to allow a device to obtain related devices if a
-driver has multiple components (for example video0 may not be associated
-with vbi0 which would cause an intercast display program to make a bad
-mistake). The VIDIOCGUNIT ioctl reports the unit numbers of the associated
-devices if any exist. The video_unit structure has the following fields.
-<P>
-<TABLE>
-<TR><TD><b>video</b><TD>Video capture device</TD>
-<TR><TD><b>vbi</b><TD>VBI capture device</TD>
-<TR><TD><b>radio</b><TD>Radio device</TD>
-<TR><TD><b>audio</b><TD>Audio mixer</TD>
-<TR><TD><b>teletext</b><TD>Teletext device</TD>
-</TABLE>
-<P>
-<H3>RDS Datastreams</H3>
-For radio devices that support it, it is possible to receive Radio Data
-System (RDS) data by means of a read() on the device.  The data is packed in
-groups of three, as follows:
-<TABLE>
-<TR><TD>First Octet</TD><TD>Least Significant Byte of RDS Block</TD></TR>
-<TR><TD>Second Octet</TD><TD>Most Significant Byte of RDS Block
-<TR><TD>Third Octet</TD><TD>Bit 7:</TD><TD>Error bit.  Indicates that
-an uncorrectable error occurred during reception of this block.</TD></TR>
-<TR><TD>&nbsp;</TD><TD>Bit 6:</TD><TD>Corrected bit.  Indicates that  
-an error was corrected for this data block.</TD></TR>
-<TR><TD>&nbsp;</TD><TD>Bits 5-3:</TD><TD>Received Offset.  Indicates the  
-offset received by the sync system.</TD></TR>
-<TR><TD>&nbsp;</TD><TD>Bits 2-0:</TD><TD>Offset Name.  Indicates the  
-offset applied to this data.</TD></TR>
-</TABLE>
-</BODY>
-</HTML>
+<TITLE>V4L API</TITLE>
+<H1>Video For Linux APIs</H1>
+<table border=0>
+<tr>
+<td>
+<A HREF=http://www.linuxtv.org/downloads/video4linux/API/V4L1_API.html>
+V4L original API</a>
+</td><td>
+Obsoleted by V4L2 API
+</td></tr><tr><td>
+<A HREF=http://www.linuxtv.org/downloads/video4linux/API/V4L2_API.html>
+V4L2 API</a>
+</td><td>
+Should be used for new projects
+</td></tr>
+</table>
index 216f705..4377aa1 100644 (file)
@@ -13,17 +13,17 @@ card=11 - Prolink PlayTV PVR
 card=12 - ASUS PVR-416
 card=13 - MSI TV-@nywhere
 card=14 - KWorld/VStream XPert DVB-T
-card=15 - DVICO FusionHDTV DVB-T1
+card=15 - DViCO FusionHDTV DVB-T1
 card=16 - KWorld LTV883RF
-card=17 - DViCO - FusionHDTV 3 Gold
+card=17 - DViCO FusionHDTV 3 Gold-Q
 card=18 - Hauppauge Nova-T DVB-T
 card=19 - Conexant DVB-T reference design
 card=20 - Provideo PV259
-card=21 - DVICO FusionHDTV DVB-T Plus
+card=21 - DViCO FusionHDTV DVB-T Plus
 card=22 - digitalnow DNTV Live! DVB-T
 card=23 - pcHDTV HD3000 HDTV
 card=24 - Hauppauge WinTV 28xxx (Roslyn) models
 card=25 - Digital-Logic MICROSPACE Entertainment Center (MEC)
 card=26 - IODATA GV/BCTV7E
 card=27 - PixelView PlayTV Ultra Pro (Stereo)
-card=28 - DViCO FusionHDTV 3 Gold-T
+card=28 - DViCO FusionHDTV 3 Gold-T
index d5ed95d..735e8ba 100644 (file)
@@ -54,3 +54,9 @@
  55 -> LifeView FlyDVB-T DUO                    [5168:0306]
  56 -> Avermedia AVerTV 307                     [1461:a70a]
  57 -> Avermedia AVerTV GO 007 FM               [1461:f31f]
+ 58 -> ADS Tech Instant TV (saa7135)            [1421:0350,1421:0370]
+ 59 -> Kworld/Tevion V-Stream Xpert TV PVR7134
+ 60 -> Typhoon DVB-T Duo Digital/Analog Cardbus
+ 61 -> Philips TOUGH DVB-T reference design
+ 62 -> Compro VideoMate TV Gold+II
+ 63 -> Kworld Xpert TV PVR7134
index aeb8df8..e78020f 100644 (file)
@@ -59,3 +59,6 @@ tuner=57 - Philips FQ1236A MK4
 tuner=58 - Ymec TVision TVF-8531MF
 tuner=59 - Ymec TVision TVF-5533MF
 tuner=60 - Thomson DDT 7611 (ATSC/NTSC)
+tuner=61 - Tena TNF9533-D/IF
+tuner=62 - Philips TEA5767HN FM Radio
+tuner=63 - Philips FMD1216ME MK3 Hybrid Tuner
index 1a446c6..1f788e4 100644 (file)
@@ -57,6 +57,15 @@ Cards can use either of these two crystals (xtal):
  - 24.576MHz -> .audio_clock=0x200000
 (xtal * .audio_clock = 51539600)
 
+Some details about 30/34/35:
+
+ - saa7130 - low-price chip, doesn't have mute, that is why all those
+ cards should have .mute field defined in their tuner structure.
+
+ - saa7134 - usual chip
+
+ - saa7133/35 - saa7135 is probably a marketing decision, since all those
+ chips identifies itself as 33 on pci.
 
 Credits
 =======
index 4db63de..19a9a1c 100644 (file)
@@ -512,11 +512,11 @@ W:        http://linuxppc64.org
 S:     Supported
 
 BTTV VIDEO4LINUX DRIVER
-P:     Gerd Knorr
-M:     kraxel@bytesex.org
+P:     Mauro Carvalho Chehab
+M:     mchehab@brturbo.com.br
 L:     video4linux-list@redhat.com
-W:     http://bytesex.org/bttv/
-S:     Orphan
+W:     http://linuxtv.org
+S:     Maintained
 
 BUSLOGIC SCSI DRIVER
 P:     Leonard N. Zubkoff
@@ -2625,10 +2625,11 @@ W:      http://rio500.sourceforge.net
 S:     Maintained
 
 VIDEO FOR LINUX
-P:     Gerd Knorr
-M:     kraxel@bytesex.org
+P:     Mauro Carvalho Chehab
+M:     mchehab@brturbo.com.br
 L:     video4linux-list@redhat.com
-S:     Orphan
+W:     http://linuxtv.org
+S:     Maintained
 
 W1 DALLAS'S 1-WIRE BUS
 P:     Evgeniy Polyakov
index c8d94dc..620f2ca 100644 (file)
@@ -361,6 +361,11 @@ config NO_IDLE_HZ
          Alternatively, if you want dynamic tick automatically enabled
          during boot, pass "dyntick=enable" via the kernel command string.
 
+         Please note that dynamic tick may affect the accuracy of
+         timekeeping on some platforms depending on the implementation.
+         Currently at least OMAP platform is known to have accurate
+         timekeeping with dynamic tick.
+
 config ARCH_DISCONTIGMEM_ENABLE
        bool
        default (ARCH_LH7A40X && !LH7A40X_CONTIGMEM)
index b668c48..cf9f46d 100644 (file)
  *   04-Nov-2004  Ben Dooks
  *               Fix standard IRQ wake for EINT0..4 and RTC
  *
- *   22-Feb-2004  Ben Dooks
+ *   22-Feb-2005  Ben Dooks
  *               Fixed edge-triggering on ADC IRQ
+ *
+ *   28-Jun-2005  Ben Dooks
+ *               Mark IRQ_LCD valid
 */
 
 #include <linux/init.h>
@@ -366,7 +369,6 @@ static struct irqchip s3c_irq_eint0t4 = {
 #define INTMSK_UART1    (1UL << (IRQ_UART1 - IRQ_EINT0))
 #define INTMSK_UART2    (1UL << (IRQ_UART2 - IRQ_EINT0))
 #define INTMSK_ADCPARENT (1UL << (IRQ_ADCPARENT - IRQ_EINT0))
-#define INTMSK_LCD      (1UL << (IRQ_LCD - IRQ_EINT0))
 
 static inline void
 s3c_irqsub_mask(unsigned int irqno, unsigned int parentbit,
@@ -716,7 +718,6 @@ void __init s3c24xx_init_irq(void)
                case IRQ_UART0:
                case IRQ_UART1:
                case IRQ_UART2:
-               case IRQ_LCD:
                case IRQ_ADCPARENT:
                        set_irq_chip(irqno, &s3c_irq_level_chip);
                        set_irq_handler(irqno, do_level_IRQ);
index ba1a6e9..8ffb523 100644 (file)
@@ -6,6 +6,6 @@ DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \
                oprofilefs.o oprofile_stats.o \
                timer_int.o )
 
-oprofile-y                             := $(DRIVER_OBJS) init.o
+oprofile-y                             := $(DRIVER_OBJS) init.o backtrace.o
 oprofile-$(CONFIG_CPU_XSCALE)          += common.o op_model_xscale.o
 
diff --git a/arch/arm/oprofile/backtrace.c b/arch/arm/oprofile/backtrace.c
new file mode 100644 (file)
index 0000000..ec58d3e
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * Arm specific backtracing code for oprofile
+ *
+ * Copyright 2005 Openedhand Ltd.
+ *
+ * Author: Richard Purdie <rpurdie@openedhand.com>
+ *
+ * Based on i386 oprofile backtrace code by John Levon, David Smith
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/oprofile.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <asm/ptrace.h>
+#include <asm/uaccess.h>
+
+
+/*
+ * The registers we're interested in are at the end of the variable
+ * length saved register structure. The fp points at the end of this
+ * structure so the address of this struct is:
+ * (struct frame_tail *)(xxx->fp)-1
+ */
+struct frame_tail {
+       struct frame_tail *fp;
+       unsigned long sp;
+       unsigned long lr;
+} __attribute__((packed));
+
+
+#ifdef CONFIG_FRAME_POINTER
+static struct frame_tail* kernel_backtrace(struct frame_tail *tail)
+{
+       oprofile_add_trace(tail->lr);
+
+       /* frame pointers should strictly progress back up the stack
+        * (towards higher addresses) */
+       if (tail >= tail->fp)
+               return NULL;
+
+       return tail->fp-1;
+}
+#endif
+
+static struct frame_tail* user_backtrace(struct frame_tail *tail)
+{
+       struct frame_tail buftail;
+
+       /* hardware pte might not be valid due to dirty/accessed bit emulation
+        * so we use copy_from_user and benefit from exception fixups */
+       if (copy_from_user(&buftail, tail, sizeof(struct frame_tail)))
+               return NULL;
+
+       oprofile_add_trace(buftail.lr);
+
+       /* frame pointers should strictly progress back up the stack
+        * (towards higher addresses) */
+       if (tail >= buftail.fp)
+               return NULL;
+
+       return buftail.fp-1;
+}
+
+/* Compare two addresses and see if they're on the same page */
+#define CMP_ADDR_EQUAL(x,y,offset) ((((unsigned long) x) >> PAGE_SHIFT) \
+       == ((((unsigned long) y) + offset) >> PAGE_SHIFT))
+
+/* check that the page(s) containing the frame tail are present */
+static int pages_present(struct frame_tail *tail)
+{
+       struct mm_struct * mm = current->mm;
+
+       if (!check_user_page_readable(mm, (unsigned long)tail))
+               return 0;
+
+       if (CMP_ADDR_EQUAL(tail, tail, 8))
+               return 1;
+
+       if (!check_user_page_readable(mm, ((unsigned long)tail) + 8))
+               return 0;
+
+       return 1;
+}
+
+/*
+ * |             | /\ Higher addresses
+ * |             |
+ * --------------- stack base (address of current_thread_info)
+ * | thread info |
+ * .             .
+ * |    stack    |
+ * --------------- saved regs->ARM_fp value if valid (frame_tail address)
+ * .             .
+ * --------------- struct pt_regs stored on stack (struct pt_regs *)
+ * |             |
+ * .             .
+ * |             |
+ * --------------- %esp
+ * |             |
+ * |             | \/ Lower addresses
+ *
+ * Thus, &pt_regs <-> stack base restricts the valid(ish) fp values
+ */
+static int valid_kernel_stack(struct frame_tail *tail, struct pt_regs *regs)
+{
+       unsigned long tailaddr = (unsigned long)tail;
+       unsigned long stack = (unsigned long)regs;
+       unsigned long stack_base = (stack & ~(THREAD_SIZE - 1)) + THREAD_SIZE;
+
+       return (tailaddr > stack) && (tailaddr < stack_base);
+}
+
+void arm_backtrace(struct pt_regs const *regs, unsigned int depth)
+{
+       struct frame_tail *tail;
+       unsigned long last_address = 0;
+
+       tail = ((struct frame_tail *) regs->ARM_fp) - 1;
+
+       if (!user_mode(regs)) {
+
+#ifdef CONFIG_FRAME_POINTER
+               while (depth-- && tail && valid_kernel_stack(tail, regs)) {
+                       tail = kernel_backtrace(tail);
+               }
+#endif
+               return;
+       }
+
+       while (depth-- && tail && !((unsigned long) tail & 3)) {
+               if ((!CMP_ADDR_EQUAL(last_address, tail, 0)
+                       || !CMP_ADDR_EQUAL(last_address, tail, 8))
+                               && !pages_present(tail))
+                       return;
+               last_address = (unsigned long) tail;
+               tail = user_backtrace(tail);
+       }
+}
+
index cce3d30..d315a3a 100644 (file)
@@ -20,6 +20,8 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
        ret = pmu_init(ops, &op_xscale_spec);
 #endif
 
+       ops->backtrace = arm_backtrace;
+
        return ret;
 }
 
index 2d4caf4..2148d07 100644 (file)
@@ -24,6 +24,8 @@ struct op_arm_model_spec {
 extern struct op_arm_model_spec op_xscale_spec;
 #endif
 
+extern void arm_backtrace(struct pt_regs * const regs, unsigned int depth);
+
 extern int __init pmu_init(struct oprofile_operations *ops, struct op_arm_model_spec *spec);
 extern void pmu_exit(void);
 #endif /* OP_ARM_MODEL_H */
index 4a17956..6835f6d 100644 (file)
@@ -70,7 +70,8 @@ void usage(void)
 
 int main(int argc, char ** argv)
 {
-       unsigned int i, c, sz, setup_sectors;
+       unsigned int i, sz, setup_sectors;
+       int c;
        u32 sys_size;
        byte major_root, minor_root;
        struct stat sb;
index 9f63ae0..b7808a8 100644 (file)
@@ -159,9 +159,15 @@ char *__acpi_map_table(unsigned long phys, unsigned long size)
 #endif
 
 #ifdef CONFIG_PCI_MMCONFIG
-static int __init acpi_parse_mcfg(unsigned long phys_addr, unsigned long size)
+/* The physical address of the MMCONFIG aperture.  Set from ACPI tables. */
+struct acpi_table_mcfg_config *pci_mmcfg_config;
+int pci_mmcfg_config_num;
+
+int __init acpi_parse_mcfg(unsigned long phys_addr, unsigned long size)
 {
        struct acpi_table_mcfg *mcfg;
+       unsigned long i;
+       int config_size;
 
        if (!phys_addr || !size)
                return -EINVAL;
@@ -172,18 +178,38 @@ static int __init acpi_parse_mcfg(unsigned long phys_addr, unsigned long size)
                return -ENODEV;
        }
 
-       if (mcfg->base_reserved) {
-               printk(KERN_ERR PREFIX "MMCONFIG not in low 4GB of memory\n");
+       /* how many config structures do we have */
+       pci_mmcfg_config_num = 0;
+       i = size - sizeof(struct acpi_table_mcfg);
+       while (i >= sizeof(struct acpi_table_mcfg_config)) {
+               ++pci_mmcfg_config_num;
+               i -= sizeof(struct acpi_table_mcfg_config);
+       };
+       if (pci_mmcfg_config_num == 0) {
+               printk(KERN_ERR PREFIX "MMCONFIG has no entries\n");
                return -ENODEV;
        }
 
-       pci_mmcfg_base_addr = mcfg->base_address;
+       config_size = pci_mmcfg_config_num * sizeof(*pci_mmcfg_config);
+       pci_mmcfg_config = kmalloc(config_size, GFP_KERNEL);
+       if (!pci_mmcfg_config) {
+               printk(KERN_WARNING PREFIX
+                      "No memory for MCFG config tables\n");
+               return -ENOMEM;
+       }
+
+       memcpy(pci_mmcfg_config, &mcfg->config, config_size);
+       for (i = 0; i < pci_mmcfg_config_num; ++i) {
+               if (mcfg->config[i].base_reserved) {
+                       printk(KERN_ERR PREFIX
+                              "MMCONFIG not in low 4GB of memory\n");
+                       return -ENODEV;
+               }
+       }
 
        return 0;
 }
-#else
-#define        acpi_parse_mcfg NULL
-#endif /* !CONFIG_PCI_MMCONFIG */
+#endif /* CONFIG_PCI_MMCONFIG */
 
 #ifdef CONFIG_X86_LOCAL_APIC
 static int __init
@@ -507,6 +533,22 @@ acpi_unmap_lsapic(int cpu)
 EXPORT_SYMBOL(acpi_unmap_lsapic);
 #endif /* CONFIG_ACPI_HOTPLUG_CPU */
 
+int
+acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base)
+{
+       /* TBD */
+       return -EINVAL;
+}
+EXPORT_SYMBOL(acpi_register_ioapic);
+
+int
+acpi_unregister_ioapic(acpi_handle handle, u32 gsi_base)
+{
+       /* TBD */
+       return -EINVAL;
+}
+EXPORT_SYMBOL(acpi_unregister_ioapic);
+
 static unsigned long __init
 acpi_scan_rsdp (
        unsigned long           start,
@@ -1123,7 +1165,6 @@ int __init acpi_boot_init(void)
        acpi_process_madt();
 
        acpi_table_parse(ACPI_HPET, acpi_parse_hpet);
-       acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg);
 
        return 0;
 }
index 720975e..8732526 100644 (file)
@@ -25,7 +25,8 @@ unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 |
 
 int pci_routeirq;
 int pcibios_last_bus = -1;
-struct pci_bus *pci_root_bus = NULL;
+unsigned long pirq_table_addr;
+struct pci_bus *pci_root_bus;
 struct pci_raw_ops *raw_pci_ops;
 
 static int pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value)
@@ -133,7 +134,7 @@ struct pci_bus * __devinit pcibios_scan_root(int busnum)
 
        printk("PCI: Probing PCI hardware (bus %02x)\n", busnum);
 
-       return pci_scan_bus(busnum, &pci_root_ops, NULL);
+       return pci_scan_bus_parented(NULL, busnum, &pci_root_ops, NULL);
 }
 
 extern u8 pci_cache_line_size;
@@ -188,6 +189,9 @@ char * __devinit  pcibios_setup(char *str)
        } else if (!strcmp(str, "biosirq")) {
                pci_probe |= PCI_BIOS_IRQ_SCAN;
                return NULL;
+       } else if (!strncmp(str, "pirqaddr=", 9)) {
+               pirq_table_addr = simple_strtoul(str+9, NULL, 0);
+               return NULL;
        }
 #endif
 #ifdef CONFIG_PCI_DIRECT
index 83458f8..78ca1ec 100644 (file)
@@ -57,6 +57,35 @@ struct irq_router_handler {
 
 int (*pcibios_enable_irq)(struct pci_dev *dev) = NULL;
 
+/*
+ *  Check passed address for the PCI IRQ Routing Table signature
+ *  and perform checksum verification.
+ */
+
+static inline struct irq_routing_table * pirq_check_routing_table(u8 *addr)
+{
+       struct irq_routing_table *rt;
+       int i;
+       u8 sum;
+
+       rt = (struct irq_routing_table *) addr;
+       if (rt->signature != PIRQ_SIGNATURE ||
+           rt->version != PIRQ_VERSION ||
+           rt->size % 16 ||
+           rt->size < sizeof(struct irq_routing_table))
+               return NULL;
+       sum = 0;
+       for (i=0; i < rt->size; i++)
+               sum += addr[i];
+       if (!sum) {
+               DBG("PCI: Interrupt Routing Table found at 0x%p\n", rt);
+               return rt;
+       }
+       return NULL;
+}
+
+
+
 /*
  *  Search 0xf0000 -- 0xfffff for the PCI IRQ Routing Table.
  */
@@ -65,23 +94,17 @@ static struct irq_routing_table * __init pirq_find_routing_table(void)
 {
        u8 *addr;
        struct irq_routing_table *rt;
-       int i;
-       u8 sum;
 
+       if (pirq_table_addr) {
+               rt = pirq_check_routing_table((u8 *) __va(pirq_table_addr));
+               if (rt)
+                       return rt;
+               printk(KERN_WARNING "PCI: PIRQ table NOT found at pirqaddr\n");
+       }
        for(addr = (u8 *) __va(0xf0000); addr < (u8 *) __va(0x100000); addr += 16) {
-               rt = (struct irq_routing_table *) addr;
-               if (rt->signature != PIRQ_SIGNATURE ||
-                   rt->version != PIRQ_VERSION ||
-                   rt->size % 16 ||
-                   rt->size < sizeof(struct irq_routing_table))
-                       continue;
-               sum = 0;
-               for(i=0; i<rt->size; i++)
-                       sum += addr[i];
-               if (!sum) {
-                       DBG("PCI: Interrupt Routing Table found at 0x%p\n", rt);
+               rt = pirq_check_routing_table(addr);
+               if (rt)
                        return rt;
-               }
        }
        return NULL;
 }
index 1492e37..149a958 100644 (file)
@@ -45,6 +45,8 @@ static int __init pci_legacy_init(void)
 
        printk("PCI: Probing PCI hardware\n");
        pci_root_bus = pcibios_scan_root(0);
+       if (pci_root_bus)
+               pci_bus_add_devices(pci_root_bus);
 
        pcibios_fixup_peer_bridges();
 
index 021a50a..60f0e7a 100644 (file)
 
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/acpi.h>
 #include "pci.h"
 
-/* The physical address of the MMCONFIG aperture.  Set from ACPI tables. */
-u32 pci_mmcfg_base_addr;
-
 #define mmcfg_virt_addr ((void __iomem *) fix_to_virt(FIX_PCIE_MCFG))
 
 /* The base address of the last MMCONFIG device accessed */
@@ -24,10 +22,31 @@ static u32 mmcfg_last_accessed_device;
 /*
  * Functions for accessing PCI configuration space with MMCONFIG accesses
  */
+static u32 get_base_addr(unsigned int seg, int bus)
+{
+       int cfg_num = -1;
+       struct acpi_table_mcfg_config *cfg;
+
+       while (1) {
+               ++cfg_num;
+               if (cfg_num >= pci_mmcfg_config_num) {
+                       /* something bad is going on, no cfg table is found. */
+                       /* so we fall back to the old way we used to do this */
+                       /* and just rely on the first entry to be correct. */
+                       return pci_mmcfg_config[0].base_address;
+               }
+               cfg = &pci_mmcfg_config[cfg_num];
+               if (cfg->pci_segment_group_number != seg)
+                       continue;
+               if ((cfg->start_bus_number <= bus) &&
+                   (cfg->end_bus_number >= bus))
+                       return cfg->base_address;
+       }
+}
 
-static inline void pci_exp_set_dev_base(int bus, int devfn)
+static inline void pci_exp_set_dev_base(unsigned int seg, int bus, int devfn)
 {
-       u32 dev_base = pci_mmcfg_base_addr | (bus << 20) | (devfn << 12);
+       u32 dev_base = get_base_addr(seg, bus) | (bus << 20) | (devfn << 12);
        if (dev_base != mmcfg_last_accessed_device) {
                mmcfg_last_accessed_device = dev_base;
                set_fixmap_nocache(FIX_PCIE_MCFG, dev_base);
@@ -44,7 +63,7 @@ static int pci_mmcfg_read(unsigned int seg, unsigned int bus,
 
        spin_lock_irqsave(&pci_config_lock, flags);
 
-       pci_exp_set_dev_base(bus, devfn);
+       pci_exp_set_dev_base(seg, bus, devfn);
 
        switch (len) {
        case 1:
@@ -73,7 +92,7 @@ static int pci_mmcfg_write(unsigned int seg, unsigned int bus,
 
        spin_lock_irqsave(&pci_config_lock, flags);
 
-       pci_exp_set_dev_base(bus, devfn);
+       pci_exp_set_dev_base(seg, bus, devfn);
 
        switch (len) {
        case 1:
@@ -101,7 +120,11 @@ static int __init pci_mmcfg_init(void)
 {
        if ((pci_probe & PCI_PROBE_MMCONF) == 0)
                goto out;
-       if (!pci_mmcfg_base_addr)
+
+       acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg);
+       if ((pci_mmcfg_config_num == 0) ||
+           (pci_mmcfg_config == NULL) ||
+           (pci_mmcfg_config[0].base_address == 0))
                goto out;
 
        /* Kludge for now. Don't use mmconfig on AMD systems because
index 9e36954..adbe17a 100644 (file)
@@ -115,6 +115,8 @@ static int __init pci_numa_init(void)
                return 0;
 
        pci_root_bus = pcibios_scan_root(0);
+       if (pci_root_bus)
+               pci_bus_add_devices(pci_root_bus);
        if (num_online_nodes() > 1)
                for_each_online_node(quad) {
                        if (quad == 0)
index a8fc80c..a80f0f5 100644 (file)
@@ -27,6 +27,7 @@
 #define PCI_ASSIGN_ALL_BUSSES  0x4000
 
 extern unsigned int pci_probe;
+extern unsigned long pirq_table_addr;
 
 /* pci-i386.c */
 
index 72dfd9e..cda06f8 100644 (file)
@@ -236,9 +236,7 @@ acpi_parse_iosapic (acpi_table_entry_header *header, const unsigned long end)
        if (BAD_MADT_ENTRY(iosapic, end))
                return -EINVAL;
 
-       iosapic_init(iosapic->address, iosapic->global_irq_base);
-
-       return 0;
+       return iosapic_init(iosapic->address, iosapic->global_irq_base);
 }
 
 
@@ -772,7 +770,7 @@ EXPORT_SYMBOL(acpi_unmap_lsapic);
  
 
 #ifdef CONFIG_ACPI_NUMA
-acpi_status __init
+acpi_status __devinit
 acpi_map_iosapic (acpi_handle handle, u32 depth, void *context, void **ret)
 {
        struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
@@ -825,4 +823,28 @@ acpi_map_iosapic (acpi_handle handle, u32 depth, void *context, void **ret)
        return AE_OK;
 }
 #endif /* CONFIG_NUMA */
+
+int
+acpi_register_ioapic (acpi_handle handle, u64 phys_addr, u32 gsi_base)
+{
+       int err;
+
+       if ((err = iosapic_init(phys_addr, gsi_base)))
+               return err;
+
+#if CONFIG_ACPI_NUMA
+       acpi_map_iosapic(handle, 0, NULL, NULL);
+#endif /* CONFIG_ACPI_NUMA */
+
+       return 0;
+}
+EXPORT_SYMBOL(acpi_register_ioapic);
+
+int
+acpi_unregister_ioapic (acpi_handle handle, u32 gsi_base)
+{
+       return iosapic_remove(gsi_base);
+}
+EXPORT_SYMBOL(acpi_unregister_ioapic);
+
 #endif /* CONFIG_ACPI_BOOT */
index 88b0143..c170be0 100644 (file)
@@ -129,14 +129,13 @@ static struct iosapic {
        char __iomem    *addr;          /* base address of IOSAPIC */
        unsigned int    gsi_base;       /* first GSI assigned to this IOSAPIC */
        unsigned short  num_rte;        /* number of RTE in this IOSAPIC */
+       int             rtes_inuse;     /* # of RTEs in use on this IOSAPIC */
 #ifdef CONFIG_NUMA
        unsigned short  node;           /* numa node association via pxm */
 #endif
 } iosapic_lists[NR_IOSAPICS];
 
-static int num_iosapic;
-
-static unsigned char pcat_compat __initdata;   /* 8259 compatibility flag */
+static unsigned char pcat_compat __devinitdata;        /* 8259 compatibility flag */
 
 static int iosapic_kmalloc_ok;
 static LIST_HEAD(free_rte_list);
@@ -149,7 +148,7 @@ find_iosapic (unsigned int gsi)
 {
        int i;
 
-       for (i = 0; i < num_iosapic; i++) {
+       for (i = 0; i < NR_IOSAPICS; i++) {
                if ((unsigned) (gsi - iosapic_lists[i].gsi_base) < iosapic_lists[i].num_rte)
                        return i;
        }
@@ -598,6 +597,7 @@ register_intr (unsigned int gsi, int vector, unsigned char delivery,
                rte->refcnt++;
                list_add_tail(&rte->rte_list, &iosapic_intr_info[vector].rtes);
                iosapic_intr_info[vector].count++;
+               iosapic_lists[index].rtes_inuse++;
        }
        else if (vector_is_shared(vector)) {
                struct iosapic_intr_info *info = &iosapic_intr_info[vector];
@@ -778,7 +778,7 @@ void
 iosapic_unregister_intr (unsigned int gsi)
 {
        unsigned long flags;
-       int irq, vector;
+       int irq, vector, index;
        irq_desc_t *idesc;
        u32 low32;
        unsigned long trigger, polarity;
@@ -819,6 +819,9 @@ iosapic_unregister_intr (unsigned int gsi)
                list_del(&rte->rte_list);
                iosapic_intr_info[vector].count--;
                iosapic_free_rte(rte);
+               index = find_iosapic(gsi);
+               iosapic_lists[index].rtes_inuse--;
+               WARN_ON(iosapic_lists[index].rtes_inuse < 0);
 
                trigger  = iosapic_intr_info[vector].trigger;
                polarity = iosapic_intr_info[vector].polarity;
@@ -952,30 +955,86 @@ iosapic_system_init (int system_pcat_compat)
        }
 }
 
-void __init
+static inline int
+iosapic_alloc (void)
+{
+       int index;
+
+       for (index = 0; index < NR_IOSAPICS; index++)
+               if (!iosapic_lists[index].addr)
+                       return index;
+
+       printk(KERN_WARNING "%s: failed to allocate iosapic\n", __FUNCTION__);
+       return -1;
+}
+
+static inline void
+iosapic_free (int index)
+{
+       memset(&iosapic_lists[index], 0, sizeof(iosapic_lists[0]));
+}
+
+static inline int
+iosapic_check_gsi_range (unsigned int gsi_base, unsigned int ver)
+{
+       int index;
+       unsigned int gsi_end, base, end;
+
+       /* check gsi range */
+       gsi_end = gsi_base + ((ver >> 16) & 0xff);
+       for (index = 0; index < NR_IOSAPICS; index++) {
+               if (!iosapic_lists[index].addr)
+                       continue;
+
+               base = iosapic_lists[index].gsi_base;
+               end  = base + iosapic_lists[index].num_rte - 1;
+
+               if (gsi_base < base && gsi_end < base)
+                       continue;/* OK */
+
+               if (gsi_base > end && gsi_end > end)
+                       continue; /* OK */
+
+               return -EBUSY;
+       }
+       return 0;
+}
+
+int __devinit
 iosapic_init (unsigned long phys_addr, unsigned int gsi_base)
 {
-       int num_rte;
+       int num_rte, err, index;
        unsigned int isa_irq, ver;
        char __iomem *addr;
+       unsigned long flags;
+
+       spin_lock_irqsave(&iosapic_lock, flags);
+       {
+               addr = ioremap(phys_addr, 0);
+               ver = iosapic_version(addr);
 
-       addr = ioremap(phys_addr, 0);
-       ver = iosapic_version(addr);
+               if ((err = iosapic_check_gsi_range(gsi_base, ver))) {
+                       iounmap(addr);
+                       spin_unlock_irqrestore(&iosapic_lock, flags);
+                       return err;
+               }
 
-       /*
-        * The MAX_REDIR register holds the highest input pin
-        * number (starting from 0).
-        * We add 1 so that we can use it for number of pins (= RTEs)
-        */
-       num_rte = ((ver >> 16) & 0xff) + 1;
+               /*
+                * The MAX_REDIR register holds the highest input pin
+                * number (starting from 0).
+                * We add 1 so that we can use it for number of pins (= RTEs)
+                */
+               num_rte = ((ver >> 16) & 0xff) + 1;
 
-       iosapic_lists[num_iosapic].addr = addr;
-       iosapic_lists[num_iosapic].gsi_base = gsi_base;
-       iosapic_lists[num_iosapic].num_rte = num_rte;
+               index = iosapic_alloc();
+               iosapic_lists[index].addr = addr;
+               iosapic_lists[index].gsi_base = gsi_base;
+               iosapic_lists[index].num_rte = num_rte;
 #ifdef CONFIG_NUMA
-       iosapic_lists[num_iosapic].node = MAX_NUMNODES;
+               iosapic_lists[index].node = MAX_NUMNODES;
 #endif
-       num_iosapic++;
+       }
+       spin_unlock_irqrestore(&iosapic_lock, flags);
 
        if ((gsi_base == 0) && pcat_compat) {
                /*
@@ -986,10 +1045,43 @@ iosapic_init (unsigned long phys_addr, unsigned int gsi_base)
                for (isa_irq = 0; isa_irq < 16; ++isa_irq)
                        iosapic_override_isa_irq(isa_irq, isa_irq, IOSAPIC_POL_HIGH, IOSAPIC_EDGE);
        }
+       return 0;
+}
+
+#ifdef CONFIG_HOTPLUG
+int
+iosapic_remove (unsigned int gsi_base)
+{
+       int index, err = 0;
+       unsigned long flags;
+
+       spin_lock_irqsave(&iosapic_lock, flags);
+       {
+               index = find_iosapic(gsi_base);
+               if (index < 0) {
+                       printk(KERN_WARNING "%s: No IOSAPIC for GSI base %u\n",
+                              __FUNCTION__, gsi_base);
+                       goto out;
+               }
+
+               if (iosapic_lists[index].rtes_inuse) {
+                       err = -EBUSY;
+                       printk(KERN_WARNING "%s: IOSAPIC for GSI base %u is busy\n",
+                              __FUNCTION__, gsi_base);
+                       goto out;
+               }
+
+               iounmap(iosapic_lists[index].addr);
+               iosapic_free(index);
+       }
+ out:
+       spin_unlock_irqrestore(&iosapic_lock, flags);
+       return err;
 }
+#endif /* CONFIG_HOTPLUG */
 
 #ifdef CONFIG_NUMA
-void __init
+void __devinit
 map_iosapic_to_node(unsigned int gsi_base, int node)
 {
        int index;
index e3fc4ed..720a861 100644 (file)
@@ -312,7 +312,7 @@ pci_acpi_scan_root(struct acpi_device *device, int domain, int bus)
        acpi_walk_resources(device->handle, METHOD_NAME__CRS, add_window,
                        &info);
 
-       pbus = pci_scan_bus(bus, &pci_root_ops, controller);
+       pbus = pci_scan_bus_parented(NULL, bus, &pci_root_ops, controller);
        if (pbus)
                pcibios_setup_root_windows(pbus, controller);
 
@@ -373,6 +373,25 @@ void pcibios_bus_to_resource(struct pci_dev *dev,
        res->end = region->end + offset;
 }
 
+static int __devinit is_valid_resource(struct pci_dev *dev, int idx)
+{
+       unsigned int i, type_mask = IORESOURCE_IO | IORESOURCE_MEM;
+       struct resource *devr = &dev->resource[idx];
+
+       if (!dev->bus)
+               return 0;
+       for (i=0; i<PCI_BUS_NUM_RESOURCES; i++) {
+               struct resource *busr = dev->bus->resource[i];
+
+               if (!busr || ((busr->flags ^ devr->flags) & type_mask))
+                       continue;
+               if ((devr->start) && (devr->start >= busr->start) &&
+                               (devr->end <= busr->end))
+                       return 1;
+       }
+       return 0;
+}
+
 static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev)
 {
        struct pci_bus_region region;
@@ -386,7 +405,8 @@ static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev)
                region.start = dev->resource[i].start;
                region.end = dev->resource[i].end;
                pcibios_bus_to_resource(dev, &dev->resource[i], &region);
-               pci_claim_resource(dev, i);
+               if ((is_valid_resource(dev, i)))
+                       pci_claim_resource(dev, i);
        }
 }
 
@@ -398,6 +418,10 @@ pcibios_fixup_bus (struct pci_bus *b)
 {
        struct pci_dev *dev;
 
+       if (b->self) {
+               pci_read_bridge_bases(b);
+               pcibios_fixup_device_resources(b->self);
+       }
        list_for_each_entry(dev, &b->devices, bus_list)
                pcibios_fixup_device_resources(dev);
 
@@ -418,18 +442,24 @@ pcibios_enable_resources (struct pci_dev *dev, int mask)
        u16 cmd, old_cmd;
        int idx;
        struct resource *r;
+       unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM;
 
        if (!dev)
                return -EINVAL;
 
        pci_read_config_word(dev, PCI_COMMAND, &cmd);
        old_cmd = cmd;
-       for (idx=0; idx<6; idx++) {
+       for (idx=0; idx<PCI_NUM_RESOURCES; idx++) {
                /* Only set up the desired resources.  */
                if (!(mask & (1 << idx)))
                        continue;
 
                r = &dev->resource[idx];
+               if (!(r->flags & type_mask))
+                       continue;
+               if ((idx == PCI_ROM_RESOURCE) &&
+                               (!(r->flags & IORESOURCE_ROM_ENABLE)))
+                       continue;
                if (!r->start && r->end) {
                        printk(KERN_ERR
                               "PCI: Device %s not available because of resource collisions\n",
@@ -441,8 +471,6 @@ pcibios_enable_resources (struct pci_dev *dev, int mask)
                if (r->flags & IORESOURCE_MEM)
                        cmd |= PCI_COMMAND_MEMORY;
        }
-       if (dev->resource[PCI_ROM_RESOURCE].start)
-               cmd |= PCI_COMMAND_MEMORY;
        if (cmd != old_cmd) {
                printk("PCI: Enabling device %s (%04x -> %04x)\n", pci_name(dev), old_cmd, cmd);
                pci_write_config_word(dev, PCI_COMMAND, cmd);
index 6d7b92d..70cfb6f 100644 (file)
@@ -1495,7 +1495,7 @@ static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
                *offset += hose->pci_mem_offset;
                res_bit = IORESOURCE_MEM;
        } else {
-               io_offset = (unsigned long)hose->io_base_virt;
+               io_offset = hose->io_base_virt - ___IO_BASE;
                *offset += io_offset;
                res_bit = IORESOURCE_IO;
        }
@@ -1522,7 +1522,7 @@ static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
 
                /* found it! construct the final physical address */
                if (mmap_state == pci_mmap_io)
-                       *offset += hose->io_base_phys - _IO_BASE;
+                       *offset += hose->io_base_phys - io_offset;
                return rp;
        }
 
@@ -1739,6 +1739,23 @@ long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn)
        return result;
 }
 
+void pci_resource_to_user(const struct pci_dev *dev, int bar,
+                         const struct resource *rsrc,
+                         u64 *start, u64 *end)
+{
+       struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
+       unsigned long offset = 0;
+
+       if (hose == NULL)
+               return;
+
+       if (rsrc->flags & IORESOURCE_IO)
+               offset = ___IO_BASE - hose->io_base_virt + hose->io_base_phys;
+
+       *start = rsrc->start + offset;
+       *end = rsrc->end + offset;
+}
+
 void __init
 pci_init_resource(struct resource *res, unsigned long start, unsigned long end,
                  int flags, char *name)
index 3defc8c..ffe3006 100644 (file)
@@ -245,7 +245,7 @@ void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq)
 
                spin_lock(&desc->lock);
                if (!noirqdebug)
-                       note_interrupt(irq, desc, action_ret);
+                       note_interrupt(irq, desc, action_ret, regs);
                if (likely(!(desc->status & IRQ_PENDING)))
                        break;
                desc->status &= ~IRQ_PENDING;
index 580676f..ae6f579 100644 (file)
@@ -351,7 +351,7 @@ static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
                *offset += hose->pci_mem_offset;
                res_bit = IORESOURCE_MEM;
        } else {
-               io_offset = (unsigned long)hose->io_base_virt;
+               io_offset = (unsigned long)hose->io_base_virt - pci_io_base;
                *offset += io_offset;
                res_bit = IORESOURCE_IO;
        }
@@ -378,7 +378,7 @@ static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
 
                /* found it! construct the final physical address */
                if (mmap_state == pci_mmap_io)
-                       *offset += hose->io_base_phys - io_offset;
+                       *offset += hose->io_base_phys - io_offset;
                return rp;
        }
 
@@ -944,4 +944,22 @@ int pci_read_irq_line(struct pci_dev *pci_dev)
 }
 EXPORT_SYMBOL(pci_read_irq_line);
 
+void pci_resource_to_user(const struct pci_dev *dev, int bar,
+                         const struct resource *rsrc,
+                         u64 *start, u64 *end)
+{
+       struct pci_controller *hose = pci_bus_to_host(dev->bus);
+       unsigned long offset = 0;
+
+       if (hose == NULL)
+               return;
+
+       if (rsrc->flags & IORESOURCE_IO)
+               offset = pci_io_base - (unsigned long)hose->io_base_virt +
+                       hose->io_base_phys;
+
+       *start = rsrc->start + offset;
+       *end = rsrc->end + offset;
+}
+
 #endif /* CONFIG_PPC_MULTIPLATFORM */
index 262e13d..7a117ef 100644 (file)
@@ -270,66 +270,10 @@ endmenu
 
 source "drivers/Kconfig"
 
-config PRINTER
-       tristate "Parallel printer support"
-       depends on PARPORT
-       ---help---
-         If you intend to attach a printer to the parallel port of your Linux
-         box (as opposed to using a serial printer; if the connector at the
-         printer has 9 or 25 holes ["female"], then it's serial), say Y.
-         Also read the Printing-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         It is possible to share one parallel port among several devices
-         (e.g. printer and ZIP drive) and it is safe to compile the
-         corresponding drivers into the kernel.  If you want to compile this
-         driver as a module however, choose M here and read
-         <file:Documentation/parport.txt>.  The module will be called lp.
-
-         If you have several parallel ports, you can specify which ports to
-         use with the "lp" kernel command line option.  (Try "man bootparam"
-         or see the documentation of your boot loader (silo) about how to pass
-         options to the kernel at boot time.)  The syntax of the "lp" command
-         line option can be found in <file:drivers/char/lp.c>.
-
-         If you have more than 8 printers, you need to increase the LP_NO
-         macro in lp.c and the PARPORT_MAX macro in parport.h.
-
-source "mm/Kconfig"
-
-endmenu
-
-source "drivers/base/Kconfig"
-
-source "drivers/video/Kconfig"
-
-source "drivers/mtd/Kconfig"
-
-source "drivers/serial/Kconfig"
-
 if !SUN4
 source "drivers/sbus/char/Kconfig"
 endif
 
-source "drivers/block/Kconfig"
-
-# Don't frighten a common SBus user
-if PCI
-
-source "drivers/ide/Kconfig"
-
-endif
-
-source "drivers/isdn/Kconfig"
-
-source "drivers/scsi/Kconfig"
-
-source "drivers/fc4/Kconfig"
-
-source "drivers/md/Kconfig"
-
-source "net/Kconfig"
-
 # This one must be before the filesystem configs. -DaveM
 
 menu "Unix98 PTY support"
index b693c23..657e88a 100644 (file)
@@ -7,25 +7,50 @@
 
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/acpi.h>
 #include "pci.h"
 
 #define MMCONFIG_APER_SIZE (256*1024*1024)
 
-/* The physical address of the MMCONFIG aperture.  Set from ACPI tables. */
-u32 pci_mmcfg_base_addr;
-
 /* Static virtual mapping of the MMCONFIG aperture */
-char *pci_mmcfg_virt;
+struct mmcfg_virt {
+       struct acpi_table_mcfg_config *cfg;
+       char *virt;
+};
+static struct mmcfg_virt *pci_mmcfg_virt;
 
-static inline char *pci_dev_base(unsigned int bus, unsigned int devfn)
+static char *get_virt(unsigned int seg, int bus)
 {
-       return pci_mmcfg_virt + ((bus << 20) | (devfn << 12));
+       int cfg_num = -1;
+       struct acpi_table_mcfg_config *cfg;
+
+       while (1) {
+               ++cfg_num;
+               if (cfg_num >= pci_mmcfg_config_num) {
+                       /* something bad is going on, no cfg table is found. */
+                       /* so we fall back to the old way we used to do this */
+                       /* and just rely on the first entry to be correct. */
+                       return pci_mmcfg_virt[0].virt;
+               }
+               cfg = pci_mmcfg_virt[cfg_num].cfg;
+               if (cfg->pci_segment_group_number != seg)
+                       continue;
+               if ((cfg->start_bus_number <= bus) &&
+                   (cfg->end_bus_number >= bus))
+                       return pci_mmcfg_virt[cfg_num].virt;
+       }
+}
+
+static inline char *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn)
+{
+
+       return get_virt(seg, bus) + ((bus << 20) | (devfn << 12));
 }
 
 static int pci_mmcfg_read(unsigned int seg, unsigned int bus,
                          unsigned int devfn, int reg, int len, u32 *value)
 {
-       char *addr = pci_dev_base(bus, devfn); 
+       char *addr = pci_dev_base(seg, bus, devfn);
 
        if (unlikely(!value || (bus > 255) || (devfn > 255) || (reg > 4095)))
                return -EINVAL;
@@ -48,7 +73,7 @@ static int pci_mmcfg_read(unsigned int seg, unsigned int bus,
 static int pci_mmcfg_write(unsigned int seg, unsigned int bus,
                           unsigned int devfn, int reg, int len, u32 value)
 {
-       char *addr = pci_dev_base(bus,devfn);
+       char *addr = pci_dev_base(seg, bus, devfn);
 
        if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095)))
                return -EINVAL;
@@ -75,9 +100,15 @@ static struct pci_raw_ops pci_mmcfg = {
 
 static int __init pci_mmcfg_init(void)
 {
+       int i;
+
        if ((pci_probe & PCI_PROBE_MMCONF) == 0)
                return 0;
-       if (!pci_mmcfg_base_addr)
+
+       acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg);
+       if ((pci_mmcfg_config_num == 0) ||
+           (pci_mmcfg_config == NULL) ||
+           (pci_mmcfg_config[0].base_address == 0))
                return 0;
 
        /* Kludge for now. Don't use mmconfig on AMD systems because
@@ -88,13 +119,22 @@ static int __init pci_mmcfg_init(void)
                return 0; 
 
        /* RED-PEN i386 doesn't do _nocache right now */
-       pci_mmcfg_virt = ioremap_nocache(pci_mmcfg_base_addr, MMCONFIG_APER_SIZE);
-       if (!pci_mmcfg_virt) { 
-               printk("PCI: Cannot map mmconfig aperture\n");
+       pci_mmcfg_virt = kmalloc(sizeof(*pci_mmcfg_virt) * pci_mmcfg_config_num, GFP_KERNEL);
+       if (pci_mmcfg_virt == NULL) {
+               printk("PCI: Can not allocate memory for mmconfig structures\n");
                return 0;
-       }       
+       }
+       for (i = 0; i < pci_mmcfg_config_num; ++i) {
+               pci_mmcfg_virt[i].cfg = &pci_mmcfg_config[i];
+               pci_mmcfg_virt[i].virt = ioremap_nocache(pci_mmcfg_config[i].base_address, MMCONFIG_APER_SIZE);
+               if (!pci_mmcfg_virt[i].virt) {
+                       printk("PCI: Cannot map mmconfig aperture for segment %d\n",
+                              pci_mmcfg_config[i].pci_segment_group_number);
+                       return 0;
+               }
+               printk(KERN_INFO "PCI: Using MMCONFIG at %x\n", pci_mmcfg_config[i].base_address);
+       }
 
-       printk(KERN_INFO "PCI: Using MMCONFIG at %x\n", pci_mmcfg_base_addr);
        raw_pci_ops = &pci_mmcfg;
        pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
 
index 5a0adbf..97013dd 100644 (file)
@@ -153,7 +153,7 @@ container_device_add(struct acpi_device **device, acpi_handle handle)
                return_VALUE(-ENODEV);
        }
 
-       result = acpi_bus_scan(*device);
+       result = acpi_bus_start(*device);
 
        return_VALUE(result);
 }
index 5d19b39..5148f3c 100644 (file)
@@ -61,15 +61,14 @@ acpi_pci_data_handler (
 
 
 /**
- * acpi_os_get_pci_id
+ * acpi_get_pci_id
  * ------------------
  * This function is used by the ACPI Interpreter (a.k.a. Core Subsystem)
  * to resolve PCI information for ACPI-PCI devices defined in the namespace.
  * This typically occurs when resolving PCI operation region information.
  */
-#ifdef ACPI_FUTURE_USAGE
 acpi_status
-acpi_os_get_pci_id (
+acpi_get_pci_id (
        acpi_handle             handle,
        struct acpi_pci_id      *id)
 {
@@ -78,7 +77,7 @@ acpi_os_get_pci_id (
        struct acpi_device      *device = NULL;
        struct acpi_pci_data    *data = NULL;
 
-       ACPI_FUNCTION_TRACE("acpi_os_get_pci_id");
+       ACPI_FUNCTION_TRACE("acpi_get_pci_id");
 
        if (!id)
                return_ACPI_STATUS(AE_BAD_PARAMETER);
@@ -92,7 +91,7 @@ acpi_os_get_pci_id (
        }
 
        status = acpi_get_data(handle, acpi_pci_data_handler, (void**) &data);
-       if (ACPI_FAILURE(status) || !data || !data->dev) {
+       if (ACPI_FAILURE(status) || !data) {
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 
                        "Invalid ACPI-PCI context for device %s\n",
                        acpi_device_bid(device)));
@@ -115,7 +114,7 @@ acpi_os_get_pci_id (
 
        return_ACPI_STATUS(AE_OK);
 }
-#endif  /*  ACPI_FUTURE_USAGE  */
+EXPORT_SYMBOL(acpi_get_pci_id);
 
        
 int
@@ -129,6 +128,8 @@ acpi_pci_bind (
        char                    *pathname = NULL;
        struct acpi_buffer      buffer = {0, NULL};
        acpi_handle             handle = NULL;
+       struct pci_dev          *dev;
+       struct pci_bus          *bus;
 
        ACPI_FUNCTION_TRACE("acpi_pci_bind");
 
@@ -193,8 +194,20 @@ acpi_pci_bind (
         * Locate matching device in PCI namespace.  If it doesn't exist
         * this typically means that the device isn't currently inserted
         * (e.g. docking station, port replicator, etc.).
+        * We cannot simply search the global pci device list, since
+        * PCI devices are added to the global pci list when the root
+        * bridge start ops are run, which may not have happened yet.
         */
-       data->dev = pci_find_slot(data->id.bus, PCI_DEVFN(data->id.device, data->id.function));
+       bus = pci_find_bus(data->id.segment, data->id.bus);
+       if (bus) {
+               list_for_each_entry(dev, &bus->devices, bus_list) {
+                       if (dev->devfn == PCI_DEVFN(data->id.device,
+                                               data->id.function)) {
+                               data->dev = dev;
+                               break;
+                       }
+               }
+       }
        if (!data->dev) {
                ACPI_DEBUG_PRINT((ACPI_DB_INFO, 
                        "Device %02x:%02x:%02x.%02x not present in PCI namespace\n",
index 7e6b8e3..5d2f77f 100644 (file)
@@ -46,6 +46,7 @@ ACPI_MODULE_NAME              ("pci_root")
 
 static int acpi_pci_root_add (struct acpi_device *device);
 static int acpi_pci_root_remove (struct acpi_device *device, int type);
+static int acpi_pci_root_start (struct acpi_device *device);
 
 static struct acpi_driver acpi_pci_root_driver = {
        .name =         ACPI_PCI_ROOT_DRIVER_NAME,
@@ -54,6 +55,7 @@ static struct acpi_driver acpi_pci_root_driver = {
        .ops =          {
                                .add =    acpi_pci_root_add,
                                .remove = acpi_pci_root_remove,
+                               .start =  acpi_pci_root_start,
                        },
 };
 
@@ -169,6 +171,7 @@ acpi_pci_root_add (
        if (!root)
                return_VALUE(-ENOMEM);
        memset(root, 0, sizeof(struct acpi_pci_root));
+       INIT_LIST_HEAD(&root->node);
 
        root->handle = device->handle;
        strcpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME);
@@ -298,12 +301,31 @@ acpi_pci_root_add (
                        root->id.bus);
 
 end:
-       if (result)
+       if (result) {
+               if (!list_empty(&root->node))
+                       list_del(&root->node);
                kfree(root);
+       }
 
        return_VALUE(result);
 }
 
+static int
+acpi_pci_root_start (
+       struct acpi_device      *device)
+{
+       struct acpi_pci_root    *root;
+
+       ACPI_FUNCTION_TRACE("acpi_pci_root_start");
+
+       list_for_each_entry(root, &acpi_pci_roots, node) {
+               if (root->handle == device->handle) {
+                       pci_bus_add_devices(root->bus);
+                       return_VALUE(0);
+               }
+       }
+       return_VALUE(-ENODEV);
+}
 
 static int
 acpi_pci_root_remove (
index f477874..76156ac 100644 (file)
@@ -723,7 +723,7 @@ int acpi_processor_device_add(
                return_VALUE(-ENODEV);
        }
 
-       acpi_bus_scan(*device);
+       acpi_bus_start(*device);
 
        pr = acpi_driver_data(*device);
        if (!pr)
index e858855..337d49b 100644 (file)
@@ -553,20 +553,29 @@ acpi_bus_driver_init (
         * upon possible configuration and currently allocated resources.
         */
 
+       ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Driver successfully bound to device\n"));
+       return_VALUE(0);
+}
+
+int
+acpi_start_single_object (
+               struct acpi_device *device)
+{
+       int result = 0;
+       struct acpi_driver *driver;
+
+       ACPI_FUNCTION_TRACE("acpi_start_single_object");
+
+       if (!(driver = device->driver))
+               return_VALUE(0);
+
        if (driver->ops.start) {
                result = driver->ops.start(device);
                if (result && driver->ops.remove)
                        driver->ops.remove(device, ACPI_BUS_REMOVAL_NORMAL);
-               return_VALUE(result);
        }
 
-       ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Driver successfully bound to device\n"));
-
-       if (driver->ops.scan) {
-               driver->ops.scan(device);
-       }
-
-       return_VALUE(0);
+       return_VALUE(result);
 }
 
 static int acpi_driver_attach(struct acpi_driver * drv)
@@ -586,6 +595,7 @@ static int acpi_driver_attach(struct acpi_driver * drv)
 
                if (!acpi_bus_match(dev, drv)) {
                        if (!acpi_bus_driver_init(dev, drv)) {
+                               acpi_start_single_object(dev);
                                atomic_inc(&drv->references);
                                count++;
                                ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found driver [%s] for device [%s]\n",
@@ -1009,8 +1019,8 @@ acpi_bus_remove (
 }
 
 
-int
-acpi_bus_add (
+static int
+acpi_add_single_object (
        struct acpi_device      **child,
        struct acpi_device      *parent,
        acpi_handle             handle,
@@ -1019,7 +1029,7 @@ acpi_bus_add (
        int                     result = 0;
        struct acpi_device      *device = NULL;
 
-       ACPI_FUNCTION_TRACE("acpi_bus_add");
+       ACPI_FUNCTION_TRACE("acpi_add_single_object");
 
        if (!child)
                return_VALUE(-EINVAL);
@@ -1140,7 +1150,7 @@ acpi_bus_add (
         *
         * TBD: Assumes LDM provides driver hot-plug capability.
         */
-       acpi_bus_find_driver(device);
+       result = acpi_bus_find_driver(device);
 
 end:
        if (!result)
@@ -1153,10 +1163,10 @@ end:
 
        return_VALUE(result);
 }
-EXPORT_SYMBOL(acpi_bus_add);
 
 
-int acpi_bus_scan (struct acpi_device  *start)
+static int acpi_bus_scan (struct acpi_device   *start,
+               struct acpi_bus_ops *ops)
 {
        acpi_status             status = AE_OK;
        struct acpi_device      *parent = NULL;
@@ -1229,9 +1239,20 @@ int acpi_bus_scan (struct acpi_device    *start)
                        continue;
                }
 
-               status = acpi_bus_add(&child, parent, chandle, type);
-               if (ACPI_FAILURE(status))
-                       continue;
+               if (ops->acpi_op_add)
+                       status = acpi_add_single_object(&child, parent,
+                                       chandle, type);
+                else
+                       status = acpi_bus_get_device(chandle, &child);
+
+                if (ACPI_FAILURE(status))
+                        continue;
+
+               if (ops->acpi_op_start) {
+                       status = acpi_start_single_object(child);
+                       if (ACPI_FAILURE(status))
+                               continue;
+               }
 
                /*
                 * If the device is present, enabled, and functioning then
@@ -1257,8 +1278,50 @@ int acpi_bus_scan (struct acpi_device    *start)
 
        return_VALUE(0);
 }
-EXPORT_SYMBOL(acpi_bus_scan);
 
+int
+acpi_bus_add (
+       struct acpi_device      **child,
+       struct acpi_device      *parent,
+       acpi_handle             handle,
+       int                     type)
+{
+       int result;
+       struct acpi_bus_ops ops;
+
+       ACPI_FUNCTION_TRACE("acpi_bus_add");
+
+       result = acpi_add_single_object(child, parent, handle, type);
+       if (!result) {
+               memset(&ops, 0, sizeof(ops));
+               ops.acpi_op_add = 1;
+               result = acpi_bus_scan(*child, &ops);
+       }
+       return_VALUE(result);
+}
+EXPORT_SYMBOL(acpi_bus_add);
+
+int
+acpi_bus_start (
+       struct acpi_device *device)
+{
+       int result;
+       struct acpi_bus_ops ops;
+
+       ACPI_FUNCTION_TRACE("acpi_bus_start");
+
+       if (!device)
+               return_VALUE(-EINVAL);
+
+       result = acpi_start_single_object(device);
+       if (!result) {
+               memset(&ops, 0, sizeof(ops));
+               ops.acpi_op_start = 1;
+               result = acpi_bus_scan(device, &ops);
+       }
+       return_VALUE(result);
+}
+EXPORT_SYMBOL(acpi_bus_start);
 
 static int
 acpi_bus_trim(struct acpi_device       *start,
@@ -1331,13 +1394,19 @@ acpi_bus_scan_fixed (
        /*
         * Enumerate all fixed-feature devices.
         */
-       if (acpi_fadt.pwr_button == 0)
-               result = acpi_bus_add(&device, acpi_root, 
+       if (acpi_fadt.pwr_button == 0) {
+               result = acpi_add_single_object(&device, acpi_root,
                        NULL, ACPI_BUS_TYPE_POWER_BUTTON);
+               if (!result)
+                       result = acpi_start_single_object(device);
+       }
 
-       if (acpi_fadt.sleep_button == 0)
-               result = acpi_bus_add(&device, acpi_root, 
+       if (acpi_fadt.sleep_button == 0) {
+               result = acpi_add_single_object(&device, acpi_root,
                        NULL, ACPI_BUS_TYPE_SLEEP_BUTTON);
+               if (!result)
+                       result = acpi_start_single_object(device);
+       }
 
        return_VALUE(result);
 }
@@ -1346,6 +1415,7 @@ acpi_bus_scan_fixed (
 static int __init acpi_scan_init(void)
 {
        int result;
+       struct acpi_bus_ops ops;
 
        ACPI_FUNCTION_TRACE("acpi_scan_init");
 
@@ -1357,17 +1427,23 @@ static int __init acpi_scan_init(void)
        /*
         * Create the root device in the bus's device tree
         */
-       result = acpi_bus_add(&acpi_root, NULL, ACPI_ROOT_OBJECT, 
+       result = acpi_add_single_object(&acpi_root, NULL, ACPI_ROOT_OBJECT,
                ACPI_BUS_TYPE_SYSTEM);
        if (result)
                goto Done;
 
+       result = acpi_start_single_object(acpi_root);
+
        /*
         * Enumerate devices in the ACPI namespace.
         */
        result = acpi_bus_scan_fixed(acpi_root);
-       if (!result) 
-               result = acpi_bus_scan(acpi_root);
+       if (!result) {
+               memset(&ops, 0, sizeof(ops));
+               ops.acpi_op_add = 1;
+               ops.acpi_op_start = 1;
+               result = acpi_bus_scan(acpi_root, &ops);
+       }
 
        if (result)
                acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL);
index 97fe13f..6522814 100644 (file)
@@ -74,6 +74,8 @@ static ssize_t
 firmware_timeout_store(struct class *class, const char *buf, size_t count)
 {
        loading_timeout = simple_strtol(buf, NULL, 10);
+       if (loading_timeout < 0)
+               loading_timeout = 0;
        return count;
 }
 
@@ -138,6 +140,10 @@ firmware_loading_store(struct class_device *class_dev,
        switch (loading) {
        case 1:
                down(&fw_lock);
+               if (!fw_priv->fw) {
+                       up(&fw_lock);
+                       break;
+               }
                vfree(fw_priv->fw->data);
                fw_priv->fw->data = NULL;
                fw_priv->fw->size = 0;
@@ -178,7 +184,7 @@ firmware_data_read(struct kobject *kobj,
 
        down(&fw_lock);
        fw = fw_priv->fw;
-       if (test_bit(FW_STATUS_DONE, &fw_priv->status)) {
+       if (!fw || test_bit(FW_STATUS_DONE, &fw_priv->status)) {
                ret_count = -ENODEV;
                goto out;
        }
@@ -238,9 +244,10 @@ firmware_data_write(struct kobject *kobj,
 
        if (!capable(CAP_SYS_RAWIO))
                return -EPERM;
+
        down(&fw_lock);
        fw = fw_priv->fw;
-       if (test_bit(FW_STATUS_DONE, &fw_priv->status)) {
+       if (!fw || test_bit(FW_STATUS_DONE, &fw_priv->status)) {
                retval = -ENODEV;
                goto out;
        }
@@ -418,7 +425,7 @@ request_firmware(const struct firmware **firmware_p, const char *name,
 
        fw_priv = class_get_devdata(class_dev);
 
-       if (loading_timeout) {
+       if (loading_timeout > 0) {
                fw_priv->timeout.expires = jiffies + loading_timeout * HZ;
                add_timer(&fw_priv->timeout);
        }
index 653512b..3e9fb6e 100644 (file)
@@ -786,7 +786,6 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
 
        case CCISS_GETLUNINFO: {
                LogvolInfo_struct luninfo;
-               int i;
                
                luninfo.LunID = drv->LunID;
                luninfo.num_opens = drv->usage_count;
index 234fdcf..1197462 100644 (file)
@@ -1867,19 +1867,20 @@ static void freed_request(request_queue_t *q, int rw)
 
 #define blkdev_free_rq(list) list_entry((list)->next, struct request, queuelist)
 /*
- * Get a free request, queue_lock must not be held
+ * Get a free request, queue_lock must be held.
+ * Returns NULL on failure, with queue_lock held.
+ * Returns !NULL on success, with queue_lock *not held*.
  */
 static struct request *get_request(request_queue_t *q, int rw, struct bio *bio,
                                   int gfp_mask)
 {
        struct request *rq = NULL;
        struct request_list *rl = &q->rq;
-       struct io_context *ioc = get_io_context(gfp_mask);
+       struct io_context *ioc = current_io_context(GFP_ATOMIC);
 
        if (unlikely(test_bit(QUEUE_FLAG_DRAIN, &q->queue_flags)))
                goto out;
 
-       spin_lock_irq(q->queue_lock);
        if (rl->count[rw]+1 >= q->nr_requests) {
                /*
                 * The queue will fill after this allocation, so set it as
@@ -1907,11 +1908,19 @@ static struct request *get_request(request_queue_t *q, int rw, struct bio *bio,
                 * The queue is full and the allocating process is not a
                 * "batcher", and not exempted by the IO scheduler
                 */
-               spin_unlock_irq(q->queue_lock);
                goto out;
        }
 
 get_rq:
+       /*
+        * Only allow batching queuers to allocate up to 50% over the defined
+        * limit of requests, otherwise we could have thousands of requests
+        * allocated with any setting of ->nr_requests
+        */
+       if (rl->count[rw] >= (3 * q->nr_requests / 2)) {
+               spin_unlock_irq(q->queue_lock);
+               goto out;
+       }
        rl->count[rw]++;
        rl->starved[rw] = 0;
        if (rl->count[rw] >= queue_congestion_on_threshold(q))
@@ -1941,7 +1950,6 @@ rq_starved:
                if (unlikely(rl->count[rw] == 0))
                        rl->starved[rw] = 1;
 
-               spin_unlock_irq(q->queue_lock);
                goto out;
        }
 
@@ -1951,21 +1959,23 @@ rq_starved:
        rq_init(q, rq);
        rq->rl = rl;
 out:
-       put_io_context(ioc);
        return rq;
 }
 
 /*
  * No available requests for this queue, unplug the device and wait for some
  * requests to become available.
+ *
+ * Called with q->queue_lock held, and returns with it unlocked.
  */
 static struct request *get_request_wait(request_queue_t *q, int rw,
                                        struct bio *bio)
 {
-       DEFINE_WAIT(wait);
        struct request *rq;
 
-       do {
+       rq = get_request(q, rw, bio, GFP_NOIO);
+       while (!rq) {
+               DEFINE_WAIT(wait);
                struct request_list *rl = &q->rq;
 
                prepare_to_wait_exclusive(&rl->wait[rw], &wait,
@@ -1976,7 +1986,8 @@ static struct request *get_request_wait(request_queue_t *q, int rw,
                if (!rq) {
                        struct io_context *ioc;
 
-                       generic_unplug_device(q);
+                       __generic_unplug_device(q);
+                       spin_unlock_irq(q->queue_lock);
                        io_schedule();
 
                        /*
@@ -1985,12 +1996,13 @@ static struct request *get_request_wait(request_queue_t *q, int rw,
                         * up to a big batch of them for a small period time.
                         * See ioc_batching, ioc_set_batching
                         */
-                       ioc = get_io_context(GFP_NOIO);
+                       ioc = current_io_context(GFP_NOIO);
                        ioc_set_batching(q, ioc);
-                       put_io_context(ioc);
+
+                       spin_lock_irq(q->queue_lock);
                }
                finish_wait(&rl->wait[rw], &wait);
-       } while (!rq);
+       }
 
        return rq;
 }
@@ -2001,14 +2013,18 @@ struct request *blk_get_request(request_queue_t *q, int rw, int gfp_mask)
 
        BUG_ON(rw != READ && rw != WRITE);
 
-       if (gfp_mask & __GFP_WAIT)
+       spin_lock_irq(q->queue_lock);
+       if (gfp_mask & __GFP_WAIT) {
                rq = get_request_wait(q, rw, NULL);
-       else
+       } else {
                rq = get_request(q, rw, NULL, gfp_mask);
+               if (!rq)
+                       spin_unlock_irq(q->queue_lock);
+       }
+       /* q->queue_lock is unlocked at this point */
 
        return rq;
 }
-
 EXPORT_SYMBOL(blk_get_request);
 
 /**
@@ -2512,7 +2528,7 @@ EXPORT_SYMBOL(blk_attempt_remerge);
 
 static int __make_request(request_queue_t *q, struct bio *bio)
 {
-       struct request *req, *freereq = NULL;
+       struct request *req;
        int el_ret, rw, nr_sectors, cur_nr_sectors, barrier, err, sync;
        unsigned short prio;
        sector_t sector;
@@ -2540,14 +2556,9 @@ static int __make_request(request_queue_t *q, struct bio *bio)
                goto end_io;
        }
 
-again:
        spin_lock_irq(q->queue_lock);
 
-       if (elv_queue_empty(q)) {
-               blk_plug_device(q);
-               goto get_rq;
-       }
-       if (barrier)
+       if (unlikely(barrier) || elv_queue_empty(q))
                goto get_rq;
 
        el_ret = elv_merge(q, &req, bio);
@@ -2592,40 +2603,24 @@ again:
                                elv_merged_request(q, req);
                        goto out;
 
-               /*
-                * elevator says don't/can't merge. get new request
-                */
-               case ELEVATOR_NO_MERGE:
-                       break;
-
+               /* ELV_NO_MERGE: elevator says don't/can't merge. */
                default:
-                       printk("elevator returned crap (%d)\n", el_ret);
-                       BUG();
+                       ;
        }
 
+get_rq:
        /*
-        * Grab a free request from the freelist - if that is empty, check
-        * if we are doing read ahead and abort instead of blocking for
-        * a free slot.
+        * Grab a free request. This is might sleep but can not fail.
+        * Returns with the queue unlocked.
+        */
+       req = get_request_wait(q, rw, bio);
+
+       /*
+        * After dropping the lock and possibly sleeping here, our request
+        * may now be mergeable after it had proven unmergeable (above).
+        * We don't worry about that case for efficiency. It won't happen
+        * often, and the elevators are able to handle it.
         */
-get_rq:
-       if (freereq) {
-               req = freereq;
-               freereq = NULL;
-       } else {
-               spin_unlock_irq(q->queue_lock);
-               if ((freereq = get_request(q, rw, bio, GFP_ATOMIC)) == NULL) {
-                       /*
-                        * READA bit set
-                        */
-                       err = -EWOULDBLOCK;
-                       if (bio_rw_ahead(bio))
-                               goto end_io;
-       
-                       freereq = get_request_wait(q, rw, bio);
-               }
-               goto again;
-       }
 
        req->flags |= REQ_CMD;
 
@@ -2654,10 +2649,11 @@ get_rq:
        req->rq_disk = bio->bi_bdev->bd_disk;
        req->start_time = jiffies;
 
+       spin_lock_irq(q->queue_lock);
+       if (elv_queue_empty(q))
+               blk_plug_device(q);
        add_request(q, req);
 out:
-       if (freereq)
-               __blk_put_request(q, freereq);
        if (sync)
                __generic_unplug_device(q);
 
@@ -3284,24 +3280,20 @@ void exit_io_context(void)
 
 /*
  * If the current task has no IO context then create one and initialise it.
- * If it does have a context, take a ref on it.
+ * Otherwise, return its existing IO context.
  *
- * This is always called in the context of the task which submitted the I/O.
- * But weird things happen, so we disable local interrupts to ensure exclusive
- * access to *current.
+ * This returned IO context doesn't have a specifically elevated refcount,
+ * but since the current task itself holds a reference, the context can be
+ * used in general code, so long as it stays within `current` context.
  */
-struct io_context *get_io_context(int gfp_flags)
+struct io_context *current_io_context(int gfp_flags)
 {
        struct task_struct *tsk = current;
-       unsigned long flags;
        struct io_context *ret;
 
-       local_irq_save(flags);
        ret = tsk->io_context;
-       if (ret)
-               goto out;
-
-       local_irq_restore(flags);
+       if (likely(ret))
+               return ret;
 
        ret = kmem_cache_alloc(iocontext_cachep, gfp_flags);
        if (ret) {
@@ -3312,25 +3304,25 @@ struct io_context *get_io_context(int gfp_flags)
                ret->nr_batch_requests = 0; /* because this is 0 */
                ret->aic = NULL;
                ret->cic = NULL;
+               tsk->io_context = ret;
+       }
 
-               local_irq_save(flags);
-
-               /*
-                * very unlikely, someone raced with us in setting up the task
-                * io context. free new context and just grab a reference.
-                */
-               if (!tsk->io_context)
-                       tsk->io_context = ret;
-               else {
-                       kmem_cache_free(iocontext_cachep, ret);
-                       ret = tsk->io_context;
-               }
+       return ret;
+}
+EXPORT_SYMBOL(current_io_context);
 
-out:
+/*
+ * If the current task has no IO context then create one and initialise it.
+ * If it does have a context, take a ref on it.
+ *
+ * This is always called in the context of the task which submitted the I/O.
+ */
+struct io_context *get_io_context(int gfp_flags)
+{
+       struct io_context *ret;
+       ret = current_io_context(gfp_flags);
+       if (likely(ret))
                atomic_inc(&ret->refcount);
-               local_irq_restore(flags);
-       }
-
        return ret;
 }
 EXPORT_SYMBOL(get_io_context);
index 1407945..59f589d 100644 (file)
@@ -686,6 +686,15 @@ static struct pci_device_id agp_amd64_pci_table[] = {
        .subvendor      = PCI_ANY_ID,
        .subdevice      = PCI_ANY_ID,
        },
+       /* SIS 760 */
+       {
+       .class          = (PCI_CLASS_BRIDGE_HOST << 8),
+       .class_mask     = ~0,
+       .vendor         = PCI_VENDOR_ID_SI,
+       .device         = PCI_DEVICE_ID_SI_760,
+       .subvendor      = PCI_ANY_ID,
+       .subdevice      = PCI_ANY_ID,
+       },
        { }
 };
 
index 1813d0d..e16c13f 100644 (file)
@@ -1088,8 +1088,8 @@ static inline int i_ipmi_request(ipmi_user_t          user,
                long                  seqid;
                int                   broadcast = 0;
 
-               if (addr->channel > IPMI_NUM_CHANNELS) {
-                       spin_lock_irqsave(&intf->counter_lock, flags);
+               if (addr->channel >= IPMI_MAX_CHANNELS) {
+                       spin_lock_irqsave(&intf->counter_lock, flags);
                        intf->sent_invalid_commands++;
                        spin_unlock_irqrestore(&intf->counter_lock, flags);
                        rv = -EINVAL;
index 7c24fbe..95f7046 100644 (file)
@@ -451,7 +451,7 @@ static int __init moxa_init(void)
                int n = (sizeof(moxa_pcibrds) / sizeof(moxa_pcibrds[0])) - 1;
                i = 0;
                while (i < n) {
-                       while ((p = pci_find_device(moxa_pcibrds[i].vendor, moxa_pcibrds[i].device, p))!=NULL)
+                       while ((p = pci_get_device(moxa_pcibrds[i].vendor, moxa_pcibrds[i].device, p))!=NULL)
                        {
                                if (pci_enable_device(p))
                                        continue;
index 7db3370..d7d4840 100644 (file)
@@ -1095,7 +1095,7 @@ static int __init rio_init(void)
 
 #ifdef CONFIG_PCI
     /* First look for the JET devices: */
-    while ((pdev = pci_find_device (PCI_VENDOR_ID_SPECIALIX, 
+    while ((pdev = pci_get_device (PCI_VENDOR_ID_SPECIALIX,
                                     PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8, 
                                     pdev))) {
        if (pci_enable_device(pdev)) continue;
@@ -1169,7 +1169,7 @@ static int __init rio_init(void)
   */
 
     /* Then look for the older RIO/PCI devices: */
-    while ((pdev = pci_find_device (PCI_VENDOR_ID_SPECIALIX, 
+    while ((pdev = pci_get_device (PCI_VENDOR_ID_SPECIALIX,
                                     PCI_DEVICE_ID_SPECIALIX_RIO, 
                                     pdev))) {
        if (pci_enable_device(pdev)) continue;
index ff4f098..d8f9e94 100644 (file)
@@ -78,6 +78,7 @@
 #include <linux/sysctl.h>
 #include <linux/wait.h>
 #include <linux/bcd.h>
+#include <linux/delay.h>
 
 #include <asm/current.h>
 #include <asm/uaccess.h>
@@ -894,7 +895,6 @@ static int __init rtc_init(void)
        struct proc_dir_entry *ent;
 #if defined(__alpha__) || defined(__mips__)
        unsigned int year, ctrl;
-       unsigned long uip_watchdog;
        char *guess = NULL;
 #endif
 #ifdef __sparc__
@@ -1000,12 +1000,8 @@ no_irq:
        /* Each operating system on an Alpha uses its own epoch.
           Let's try to guess which one we are using now. */
        
-       uip_watchdog = jiffies;
        if (rtc_is_updating() != 0)
-               while (jiffies - uip_watchdog < 2*HZ/100) { 
-                       barrier();
-                       cpu_relax();
-               }
+               msleep(20);
        
        spin_lock_irq(&rtc_lock);
        year = CMOS_READ(RTC_YEAR);
@@ -1213,7 +1209,6 @@ static int rtc_proc_open(struct inode *inode, struct file *file)
 
 void rtc_get_rtc_time(struct rtc_time *rtc_tm)
 {
-       unsigned long uip_watchdog = jiffies;
        unsigned char ctrl;
 #ifdef CONFIG_MACH_DECSTATION
        unsigned int real_year;
@@ -1221,7 +1216,7 @@ void rtc_get_rtc_time(struct rtc_time *rtc_tm)
 
        /*
         * read RTC once any update in progress is done. The update
-        * can take just over 2ms. We wait 10 to 20ms. There is no need to
+        * can take just over 2ms. We wait 20ms. There is no need to
         * to poll-wait (up to 1s - eeccch) for the falling edge of RTC_UIP.
         * If you need to know *exactly* when a second has started, enable
         * periodic update complete interrupts, (via ioctl) and then 
@@ -1230,10 +1225,7 @@ void rtc_get_rtc_time(struct rtc_time *rtc_tm)
         */
 
        if (rtc_is_updating() != 0)
-               while (jiffies - uip_watchdog < 2*HZ/100) {
-                       barrier();
-                       cpu_relax();
-               }
+               msleep(20);
 
        /*
         * Only the values that we read from the RTC are set. We leave
index 659335d..ec78d2f 100644 (file)
@@ -396,7 +396,7 @@ static struct file_operations tipar_fops = {
 static int __init
 tipar_setup(char *str)
 {
-       int ints[2];
+       int ints[3];
 
        str = get_options(str, ARRAY_SIZE(ints), ints);
 
index 5859799..f19cf9d 100644 (file)
@@ -476,11 +476,11 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file,
                        ld = tty_ldisc_ref(tty);
                        switch (arg) {
                        case TCIFLUSH:
-                               if (ld->flush_buffer)
+                               if (ld && ld->flush_buffer)
                                        ld->flush_buffer(tty);
                                break;
                        case TCIOFLUSH:
-                               if (ld->flush_buffer)
+                               if (ld && ld->flush_buffer)
                                        ld->flush_buffer(tty);
                                /* fall through */
                        case TCOFLUSH:
index 8971484..1d44f69 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/fs.h>
 #include <linux/console.h>
 #include <linux/signal.h>
+#include <linux/timex.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -386,7 +387,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                if (!perm)
                        return -EPERM;
                if (arg)
-                       arg = 1193182 / arg;
+                       arg = CLOCK_TICK_RATE / arg;
                kd_mksound(arg, 0);
                return 0;
 
@@ -403,7 +404,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                ticks = HZ * ((arg >> 16) & 0xffff) / 1000;
                count = ticks ? (arg & 0xffff) : 0;
                if (count)
-                       count = 1193182 / count;
+                       count = CLOCK_TICK_RATE / count;
                kd_mksound(count, ticks);
                return 0;
        }
index 4e98c21..4b03951 100644 (file)
@@ -162,7 +162,7 @@ ixp2000_wdt_release(struct inode *inode, struct file *file)
        if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) {
                wdt_disable();
        } else {
-               printk(KERN_CRIT "WATCHDOG: Device closed unexpectdly - "
+               printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - "
                                        "timer will not stop\n");
        }
 
index 82396e0..83df369 100644 (file)
@@ -156,7 +156,7 @@ ixp4xx_wdt_release(struct inode *inode, struct file *file)
        if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) {
                wdt_disable();
        } else {
-               printk(KERN_CRIT "WATCHDOG: Device closed unexpectdly - "
+               printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - "
                                        "timer will not stop\n");
        }
 
index 6e548a2..8949789 100644 (file)
@@ -44,7 +44,7 @@ static didd_adapter_change_notification_t\
   Array to held adapter information
    -------------------------------------------------------------------------- */
 static DESCRIPTOR  HandleTable[NEW_MAX_DESCRIPTORS];
-dword Adapters = 0; /* Number of adapters */
+static dword Adapters = 0; /* Number of adapters */
 /* --------------------------------------------------------------------------
   Shadow IDI_DIMAINT
   and 'shadow' debug stuff
index 6e7e060..7333377 100644 (file)
@@ -312,7 +312,7 @@ wait_busy(hfc4s8s_hw * a)
 /* function to read critical counter registers that   */
 /* may be udpated by the chip during read             */
 /******************************************************/
-static volatile u_char
+static u_char
 Read_hfc8_stable(hfc4s8s_hw * hw, int reg)
 {
        u_char ref8;
@@ -324,7 +324,7 @@ Read_hfc8_stable(hfc4s8s_hw * hw, int reg)
        return in8;
 }
 
-static volatile int
+static int
 Read_hfc16_stable(hfc4s8s_hw * hw, int reg)
 {
        int ref16;
@@ -1465,7 +1465,7 @@ hfc_hardware_enable(hfc4s8s_hw * hw, int enable, int nt_mode)
 /******************************************/
 /* disable memory mapped ports / io ports */
 /******************************************/
-void
+static void
 release_pci_ports(hfc4s8s_hw * hw)
 {
        pci_write_config_word(hw->pdev, PCI_COMMAND, 0);
@@ -1481,7 +1481,7 @@ release_pci_ports(hfc4s8s_hw * hw)
 /*****************************************/
 /* enable memory mapped ports / io ports */
 /*****************************************/
-void
+static void
 enable_pci_ports(hfc4s8s_hw * hw)
 {
 #ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
index 8ee25b2..1fd3d4e 100644 (file)
@@ -42,6 +42,8 @@ typedef struct _hycapi_appl {
 
 static hycapi_appl hycapi_applications[CAPI_MAXAPPL];
 
+static u16 hycapi_send_message(struct capi_ctr *ctrl, struct sk_buff *skb);
+
 static inline int _hycapi_appCheck(int app_id, int ctrl_no)
 {
        if((ctrl_no <= 0) || (ctrl_no > CAPI_MAXCONTR) || (app_id <= 0) ||
@@ -57,7 +59,7 @@ static inline int _hycapi_appCheck(int app_id, int ctrl_no)
 Kernel-Capi callback reset_ctr
 ******************************/     
 
-void 
+static void
 hycapi_reset_ctr(struct capi_ctr *ctrl)
 {
        hycapictrl_info *cinfo = ctrl->driverdata;
@@ -73,7 +75,7 @@ hycapi_reset_ctr(struct capi_ctr *ctrl)
 Kernel-Capi callback remove_ctr
 ******************************/     
 
-void 
+static void
 hycapi_remove_ctr(struct capi_ctr *ctrl)
 {
        int i;
@@ -215,7 +217,7 @@ Error-checking is done for CAPI-compliance.
 The application is recorded in the internal list.
 *************************************************************/
 
-void 
+static void
 hycapi_register_appl(struct capi_ctr *ctrl, __u16 appl, 
                     capi_register_params *rp)
 {
@@ -291,7 +293,7 @@ Release the application from the internal list an remove it's
 registration at controller-level
 ******************************************************************/
 
-void 
+static void
 hycapi_release_appl(struct capi_ctr *ctrl, __u16 appl)
 {
        int chk;
@@ -364,7 +366,7 @@ firmware-releases that do not check the MsgLen-Indication!
 
 ***************************************************************/
 
-u16 hycapi_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
+static u16 hycapi_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
 {
        __u16 appl_id;
        int _len, _len2;
@@ -437,8 +439,8 @@ Informations provided in the /proc/capi-entries.
 
 *********************************************************************/
 
-int hycapi_read_proc(char *page, char **start, off_t off,
-                    int count, int *eof, struct capi_ctr *ctrl)
+static int hycapi_read_proc(char *page, char **start, off_t off,
+                           int count, int *eof, struct capi_ctr *ctrl)
 {
        hycapictrl_info *cinfo = (hycapictrl_info *)(ctrl->driverdata);
        hysdn_card *card = cinfo->card;
@@ -485,7 +487,7 @@ on capi-interface registration.
 
 **************************************************************/
 
-int hycapi_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
+static int hycapi_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
 {
 #ifdef HYCAPI_PRINTFNAMES
        printk(KERN_NOTICE "hycapi_load_firmware\n");    
@@ -494,7 +496,7 @@ int hycapi_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
 }
 
 
-char *hycapi_procinfo(struct capi_ctr *ctrl)
+static char *hycapi_procinfo(struct capi_ctr *ctrl)
 {
        hycapictrl_info *cinfo = (hycapictrl_info *)(ctrl->driverdata);
 #ifdef HYCAPI_PRINTFNAMES
index 6c04281..7bfba19 100644 (file)
@@ -53,7 +53,7 @@ struct boot_data {
 /*  to be called at start of POF file reading,       */
 /*  before starting any decryption on any POF record. */
 /*****************************************************/
-void
+static void
 StartDecryption(struct boot_data *boot)
 {
        boot->Cryptor = CRYPT_STARTTERM;
@@ -66,7 +66,7 @@ StartDecryption(struct boot_data *boot)
 /*       to HI and LO boot loader and (all) seq tags, because  */
 /*       global Cryptor is started for whole POF.              */
 /***************************************************************/
-void
+static void
 DecryptBuf(struct boot_data *boot, int cnt)
 {
        uchar *bufp = boot->buf.BootBuf;
index 4cee26e..432f6f9 100644 (file)
@@ -227,7 +227,6 @@ typedef struct hycapictrl_info hycapictrl_info;
 /*****************/
 /* exported vars */
 /*****************/
-extern int cardmax;            /* number of found cards */
 extern hysdn_card *card_root;  /* pointer to first card */
 
 
@@ -244,7 +243,6 @@ extern void hysdn_procconf_release(void);   /* deinit proc config filesys */
 /* hysdn_proclog.c */
 extern int hysdn_proclog_init(hysdn_card *);   /* init proc log entry */
 extern void hysdn_proclog_release(hysdn_card *);       /* deinit proc log entry */
-extern void put_log_buffer(hysdn_card *, char *);      /* output log data */
 extern void hysdn_addlog(hysdn_card *, char *,...);    /* output data to log */
 extern void hysdn_card_errlog(hysdn_card *, tErrLogEntry *, int);      /* output card log */
 
@@ -278,16 +276,6 @@ extern unsigned int hycapi_enable;
 extern int hycapi_capi_create(hysdn_card *);   /* create a new capi device */
 extern int hycapi_capi_release(hysdn_card *);  /* delete the device */
 extern int hycapi_capi_stop(hysdn_card *card);   /* suspend */
-extern int hycapi_load_firmware(struct capi_ctr *, capiloaddata *);
-extern void hycapi_reset_ctr(struct capi_ctr *);
-extern void hycapi_remove_ctr(struct capi_ctr *);
-extern void hycapi_register_appl(struct capi_ctr *, __u16 appl,
-                                capi_register_params *);
-extern void hycapi_release_appl(struct capi_ctr *, __u16 appl);
-extern u16  hycapi_send_message(struct capi_ctr *, struct sk_buff *skb);
-extern char *hycapi_procinfo(struct capi_ctr *);
-extern int hycapi_read_proc(char *page, char **start, off_t off,
-                           int count, int *eof, struct capi_ctr *card);
 extern void hycapi_rx_capipkt(hysdn_card * card, uchar * buf, word len);
 extern void hycapi_tx_capiack(hysdn_card * card);
 extern struct sk_buff *hycapi_tx_capiget(hysdn_card *card);
index 5cac2bf..12c8137 100644 (file)
@@ -34,7 +34,7 @@ MODULE_AUTHOR("Werner Cornelius");
 MODULE_LICENSE("GPL");
 
 static char *hysdn_init_revision = "$Revision: 1.6.6.6 $";
-int cardmax;                   /* number of found cards */
+static int cardmax;            /* number of found cards */
 hysdn_card *card_root = NULL;  /* pointer to first card */
 
 /**********************************************/
index 8ef2b7c..4d57011 100644 (file)
@@ -22,6 +22,8 @@
 /* the proc subdir for the interface is defined in the procconf module */
 extern struct proc_dir_entry *hysdn_proc_entry;
 
+static void put_log_buffer(hysdn_card * card, char *cp);
+
 /*************************************************/
 /* structure keeping ascii log for device output */
 /*************************************************/
@@ -93,7 +95,7 @@ hysdn_addlog(hysdn_card * card, char *fmt,...)
 /* opened for read got the contents.        */
 /* Flushes buffers not longer in use.       */
 /********************************************/
-void
+static void
 put_log_buffer(hysdn_card * card, char *cp)
 {
        struct log_data *ib;
index 3802f7a..4a0c57d 100644 (file)
@@ -338,6 +338,7 @@ static int super_written(struct bio *bio, unsigned int bytes_done, int error)
 
        if (atomic_dec_and_test(&rdev->mddev->pending_writes))
                wake_up(&rdev->mddev->sb_wait);
+       bio_put(bio);
        return 0;
 }
 
index 2dc906f..810e7aa 100644 (file)
@@ -7,8 +7,7 @@ bttv-objs       :=      bttv-driver.o bttv-cards.o bttv-if.o \
 zoran-objs      :=     zr36120.o zr36120_i2c.o zr36120_mem.o
 zr36067-objs   :=      zoran_procfs.o zoran_device.o \
                        zoran_driver.o zoran_card.o
-tuner-objs     :=      tuner-core.o tuner-simple.o mt20xx.o tda8290.o
-
+tuner-objs     :=      tuner-core.o tuner-simple.o mt20xx.o tda8290.o tea5767.o
 obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-common.o v4l1-compat.o
 
 obj-$(CONFIG_VIDEO_BT848) += bttv.o msp3400.o tvaudio.o \
index 290289a..7d62b39 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    $Id: bttv-driver.c,v 1.38 2005/06/10 17:20:24 mchehab Exp $
+    $Id: bttv-driver.c,v 1.40 2005/06/16 21:38:45 nsh Exp $
 
     bttv - Bt848 frame grabber driver
 
@@ -76,6 +76,9 @@ static unsigned int whitecrush_upper = 0xCF;
 static unsigned int whitecrush_lower = 0x7F;
 static unsigned int vcr_hack    = 0;
 static unsigned int irq_iswitch = 0;
+static unsigned int uv_ratio    = 50;
+static unsigned int full_luma_range = 0;
+static unsigned int coring      = 0;
 
 /* API features (turn on/off stuff for testing) */
 static unsigned int v4l2        = 1;
@@ -106,6 +109,9 @@ module_param(adc_crush,         int, 0444);
 module_param(whitecrush_upper,  int, 0444);
 module_param(whitecrush_lower,  int, 0444);
 module_param(vcr_hack,          int, 0444);
+module_param(uv_ratio,          int, 0444);
+module_param(full_luma_range,   int, 0444);
+module_param(coring,            int, 0444);
 
 module_param_array(radio, int, NULL, 0444);
 
@@ -124,6 +130,9 @@ MODULE_PARM_DESC(whitecrush_upper,"sets the white crush upper value, default is
 MODULE_PARM_DESC(whitecrush_lower,"sets the white crush lower value, default is 127");
 MODULE_PARM_DESC(vcr_hack,"enables the VCR hack (improves synch on poor VCR tapes), default is 0 (no)");
 MODULE_PARM_DESC(irq_iswitch,"switch inputs in irq handler");
+MODULE_PARM_DESC(uv_ratio,"ratio between u and v gains, default is 50");
+MODULE_PARM_DESC(full_luma_range,"use the full luma range, default is 0 (no)");
+MODULE_PARM_DESC(coring,"set the luma coring level, default is 0 (no)");
 
 MODULE_DESCRIPTION("bttv - v4l/v4l2 driver module for bt848/878 based cards");
 MODULE_AUTHOR("Ralph Metzler & Marcus Metzler & Gerd Knorr");
@@ -484,7 +493,10 @@ static const unsigned int BTTV_FORMATS = ARRAY_SIZE(bttv_formats);
 #define V4L2_CID_PRIVATE_VCR_HACK    (V4L2_CID_PRIVATE_BASE + 5)
 #define V4L2_CID_PRIVATE_WHITECRUSH_UPPER   (V4L2_CID_PRIVATE_BASE + 6)
 #define V4L2_CID_PRIVATE_WHITECRUSH_LOWER   (V4L2_CID_PRIVATE_BASE + 7)
-#define V4L2_CID_PRIVATE_LASTP1      (V4L2_CID_PRIVATE_BASE + 8)
+#define V4L2_CID_PRIVATE_UV_RATIO    (V4L2_CID_PRIVATE_BASE + 8)
+#define V4L2_CID_PRIVATE_FULL_LUMA_RANGE    (V4L2_CID_PRIVATE_BASE + 9)
+#define V4L2_CID_PRIVATE_CORING      (V4L2_CID_PRIVATE_BASE + 10)
+#define V4L2_CID_PRIVATE_LASTP1      (V4L2_CID_PRIVATE_BASE + 11)
 
 static const struct v4l2_queryctrl no_ctl = {
        .name  = "42",
@@ -618,8 +630,32 @@ static const struct v4l2_queryctrl bttv_ctls[] = {
                .step          = 1,
                .default_value = 0x7F,
                .type          = V4L2_CTRL_TYPE_INTEGER,
+       },{
+               .id            = V4L2_CID_PRIVATE_UV_RATIO,
+               .name          = "uv ratio",
+               .minimum       = 0,
+               .maximum       = 100,
+               .step          = 1,
+               .default_value = 50,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+       },{
+               .id            = V4L2_CID_PRIVATE_FULL_LUMA_RANGE,
+               .name          = "full luma range",
+               .minimum       = 0,
+               .maximum       = 1,
+               .type          = V4L2_CTRL_TYPE_BOOLEAN,
+       },{
+               .id            = V4L2_CID_PRIVATE_CORING,
+               .name          = "coring",
+               .minimum       = 0,
+               .maximum       = 3,
+               .step          = 1,
+               .default_value = 0,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
        }
 
+
+
 };
 static const int BTTV_CTLS = ARRAY_SIZE(bttv_ctls);
 
@@ -833,8 +869,8 @@ static void bt848_sat(struct bttv *btv, int color)
        btv->saturation = color;
 
        /* 0-511 for the color */
-       val_u   = color >> 7;
-       val_v   = ((color>>7)*180L)/254;
+       val_u   = ((color * btv->opt_uv_ratio) / 50) >> 7;
+       val_v   = (((color * (100 - btv->opt_uv_ratio) / 50) >>7)*180L)/254;
         hibits  = (val_u >> 7) & 2;
        hibits |= (val_v >> 8) & 1;
         btwrite(val_u & 0xff, BT848_SAT_U_LO);
@@ -1151,6 +1187,15 @@ static int get_control(struct bttv *btv, struct v4l2_control *c)
        case V4L2_CID_PRIVATE_WHITECRUSH_LOWER:
                c->value = btv->opt_whitecrush_lower;
                break;
+       case V4L2_CID_PRIVATE_UV_RATIO:
+               c->value = btv->opt_uv_ratio;
+               break;
+       case V4L2_CID_PRIVATE_FULL_LUMA_RANGE:
+               c->value = btv->opt_full_luma_range;
+               break;
+       case V4L2_CID_PRIVATE_CORING:
+               c->value = btv->opt_coring;
+               break;
        default:
                return -EINVAL;
        }
@@ -1247,6 +1292,18 @@ static int set_control(struct bttv *btv, struct v4l2_control *c)
                btv->opt_whitecrush_lower = c->value;
                btwrite(c->value, BT848_WC_DOWN);
                break;
+       case V4L2_CID_PRIVATE_UV_RATIO:
+               btv->opt_uv_ratio = c->value;
+               bt848_sat(btv, btv->saturation);
+               break;
+       case V4L2_CID_PRIVATE_FULL_LUMA_RANGE:
+               btv->opt_full_luma_range = c->value;
+               btaor((c->value<<7), ~BT848_OFORM_RANGE, BT848_OFORM);
+               break;
+       case V4L2_CID_PRIVATE_CORING:
+               btv->opt_coring = c->value;
+               btaor((c->value<<5), ~BT848_OFORM_CORE32, BT848_OFORM);
+               break;
        default:
                return -EINVAL;
        }
@@ -3117,11 +3174,6 @@ static int radio_do_ioctl(struct inode *inode, struct file *file,
                         return -EINVAL;
                memset(v,0,sizeof(*v));
                 strcpy(v->name, "Radio");
-                /* japan:          76.0 MHz -  89.9 MHz
-                   western europe: 87.5 MHz - 108.0 MHz
-                   russia:         65.0 MHz - 108.0 MHz */
-                v->rangelow=(int)(65*16);
-                v->rangehigh=(int)(108*16);
                 bttv_call_i2c_clients(btv,cmd,v);
                 return 0;
         }
@@ -3876,6 +3928,9 @@ static int __devinit bttv_probe(struct pci_dev *dev,
        btv->opt_vcr_hack   = vcr_hack;
        btv->opt_whitecrush_upper  = whitecrush_upper;
        btv->opt_whitecrush_lower  = whitecrush_lower;
+       btv->opt_uv_ratio   = uv_ratio;
+       btv->opt_full_luma_range   = full_luma_range;
+       btv->opt_coring     = coring;
 
        /* fill struct bttv with some useful defaults */
        btv->init.btv         = btv;
index 7b6f1e8..f3293e4 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    $Id: bttvp.h,v 1.17 2005/02/16 12:14:10 kraxel Exp $
+    $Id: bttvp.h,v 1.19 2005/06/16 21:38:45 nsh Exp $
 
     bttv - Bt848 frame grabber driver
 
@@ -326,6 +326,9 @@ struct bttv {
        int opt_vcr_hack;
        int opt_whitecrush_upper;
        int opt_whitecrush_lower;
+       int opt_uv_ratio;
+       int opt_full_luma_range;
+       int opt_coring;
 
        /* radio data/state */
        int has_radio;
index 95ad17b..9c005cb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: mt20xx.c,v 1.4 2005/03/04 09:24:56 kraxel Exp $
+ * $Id: mt20xx.c,v 1.5 2005/06/16 08:29:49 nsh Exp $
  *
  * i2c tv tuner chip device driver
  * controls microtune tuners, mt2032 + mt2050 at the moment.
@@ -295,8 +295,8 @@ static void mt2032_set_radio_freq(struct i2c_client *c, unsigned int freq)
        int if2 = t->radio_if2;
 
        // per Manual for FM tuning: first if center freq. 1085 MHz
-        mt2032_set_if_freq(c, freq*62500 /* freq*1000*1000/16 */,
-                          1085*1000*1000,if2,if2,if2);
+        mt2032_set_if_freq(c, freq * 1000 / 16,
+                             1085*1000*1000,if2,if2,if2);
 }
 
 // Initalization as described in "MT203x Programming Procedures", Rev 1.2, Feb.2001
index b27cc34..f59d460 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: tda8290.c,v 1.7 2005/03/07 12:01:51 kraxel Exp $
+ * $Id: tda8290.c,v 1.11 2005/06/18 06:09:06 nsh Exp $
  *
  * i2c tv tuner chip device driver
  * controls the philips tda8290+75 tuner chip combo.
@@ -69,7 +69,7 @@ static __u8 get_freq_entry( struct freq_entry* table, __u16 freq)
 static unsigned char i2c_enable_bridge[2] =    { 0x21, 0xC0 };
 static unsigned char i2c_disable_bridge[2] =   { 0x21, 0x80 };
 static unsigned char i2c_init_tda8275[14] =    { 0x00, 0x00, 0x00, 0x00,
-                                                 0x7C, 0x04, 0xA3, 0x3F,
+                                                 0xfC, 0x04, 0xA3, 0x3F,
                                                  0x2A, 0x04, 0xFF, 0x00,
                                                  0x00, 0x40 };
 static unsigned char i2c_set_VS[2] =           { 0x30, 0x6F };
@@ -138,16 +138,24 @@ static int tda8290_tune(struct i2c_client *c)
 
 static void set_frequency(struct tuner *t, u16 ifc)
 {
-       u32 N = (((t->freq<<3)+ifc)&0x3fffc);
+       u32 freq;
+       u32 N;
 
-       N = N >> get_freq_entry(div_table, t->freq);
+       if (t->mode == V4L2_TUNER_RADIO)
+               freq = t->freq / 1000;
+       else
+               freq = t->freq;
+
+       N = (((freq<<3)+ifc)&0x3fffc);
+
+       N = N >> get_freq_entry(div_table, freq);
        t->i2c_set_freq[0] = 0;
        t->i2c_set_freq[1] = (unsigned char)(N>>8);
        t->i2c_set_freq[2] = (unsigned char) N;
        t->i2c_set_freq[3] = 0x40;
        t->i2c_set_freq[4] = 0x52;
-       t->i2c_set_freq[5] = get_freq_entry(band_table, t->freq);
-       t->i2c_set_freq[6] = get_freq_entry(agc_table,  t->freq);
+       t->i2c_set_freq[5] = get_freq_entry(band_table, freq);
+       t->i2c_set_freq[6] = get_freq_entry(agc_table,  freq);
        t->i2c_set_freq[7] = 0x8f;
 }
 
index 3977363..ee35562 100644 (file)
@@ -368,7 +368,7 @@ static int tda9887_set_tvnorm(struct tda9887 *t, char *buf)
                if (t->radio_mode == V4L2_TUNER_MODE_MONO)
                        norm = &radio_mono;
                else
-                       norm = &radio_stereo;
+                       norm = &radio_stereo;
        } else {
                for (i = 0; i < ARRAY_SIZE(tvnorms); i++) {
                        if (tvnorms[i].std & t->std) {
@@ -566,7 +566,6 @@ static int tda9887_configure(struct tda9887 *t)
        if (UNSET != t->pinnacle_id) {
                tda9887_set_pinnacle(t,buf);
        }
-
        tda9887_set_config(t,buf);
        tda9887_set_insmod(t,buf);
 
@@ -615,8 +614,8 @@ static int tda9887_attach(struct i2c_adapter *adap, int addr, int kind)
        t->pinnacle_id = UNSET;
        t->radio_mode = V4L2_TUNER_MODE_STEREO;
 
-        i2c_set_clientdata(&t->client, t);
-        i2c_attach_client(&t->client);
+       i2c_set_clientdata(&t->client, t);
+       i2c_attach_client(&t->client);
 
        return 0;
 }
diff --git a/drivers/media/video/tea5767.c b/drivers/media/video/tea5767.c
new file mode 100644 (file)
index 0000000..a29f08f
--- /dev/null
@@ -0,0 +1,334 @@
+/*
+ * For Philips TEA5767 FM Chip used on some TV Cards like Prolink Pixelview
+ * I2C address is allways 0xC0.
+ *
+ * $Id: tea5767.c,v 1.11 2005/06/21 15:40:33 mchehab Exp $
+ *
+ * Copyright (c) 2005 Mauro Carvalho Chehab (mchehab@brturbo.com.br)
+ * This code is placed under the terms of the GNU General Public License
+ *
+ * tea5767 autodetection thanks to Torsten Seeboth and Atsushi Nakagawa
+ * from their contributions on DScaler.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/videodev.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+
+#include <media/tuner.h>
+
+/* Declared at tuner-core.c */
+extern unsigned int tuner_debug;
+
+#define PREFIX "TEA5767 "
+
+/*****************************************************************************/
+
+/******************************
+ * Write mode register values *
+ ******************************/
+
+/* First register */
+#define TEA5767_MUTE           0x80 /* Mutes output */
+#define TEA5767_SEARCH         0x40 /* Activates station search */
+/* Bits 0-5 for divider MSB */
+
+/* Second register */
+/* Bits 0-7 for divider LSB */
+
+/* Third register */
+
+/* Station search from botton to up */
+#define TEA5767_SEARCH_UP      0x80
+
+/* Searches with ADC output = 10 */
+#define TEA5767_SRCH_HIGH_LVL  0x60
+
+/* Searches with ADC output = 10 */
+#define TEA5767_SRCH_MID_LVL   0x40
+
+/* Searches with ADC output = 5 */
+#define TEA5767_SRCH_LOW_LVL   0x20
+
+/* if on, div=4*(Frf+Fif)/Fref otherwise, div=4*(Frf-Fif)/Freq) */
+#define TEA5767_HIGH_LO_INJECT 0x10
+
+/* Disable stereo */
+#define TEA5767_MONO           0x08
+
+/* Disable right channel and turns to mono */
+#define TEA5767_MUTE_RIGHT     0x04
+
+/* Disable left channel and turns to mono */
+#define TEA5767_MUTE_LEFT      0x02
+
+#define TEA5767_PORT1_HIGH     0x01
+
+/* Forth register */
+#define TEA5767_PORT2_HIGH     0x80
+/* Chips stops working. Only I2C bus remains on */
+#define TEA5767_STDBY          0x40
+
+/* Japan freq (76-108 MHz. If disabled, 87.5-108 MHz */
+#define TEA5767_JAPAN_BAND     0x20
+
+/* Unselected means 32.768 KHz freq as reference. Otherwise Xtal at 13 MHz */
+#define TEA5767_XTAL_32768     0x10
+
+/* Cuts weak signals */
+#define TEA5767_SOFT_MUTE      0x08
+
+/* Activates high cut control */
+#define TEA5767_HIGH_CUT_CTRL  0x04
+
+/* Activates stereo noise control */
+#define TEA5767_ST_NOISE_CTL   0x02
+
+/* If activate PORT 1 indicates SEARCH or else it is used as PORT1 */
+#define TEA5767_SRCH_IND       0x01
+
+/* Fiveth register */
+
+/* By activating, it will use Xtal at 13 MHz as reference for divider */
+#define TEA5767_PLLREF_ENABLE  0x80
+
+/* By activating, deemphasis=50, or else, deemphasis of 50us */
+#define TEA5767_DEEMPH_75      0X40
+
+/*****************************
+ * Read mode register values *
+ *****************************/
+
+/* First register */
+#define TEA5767_READY_FLAG_MASK        0x80
+#define TEA5767_BAND_LIMIT_MASK        0X40
+/* Bits 0-5 for divider MSB after search or preset */
+
+/* Second register */
+/* Bits 0-7 for divider LSB after search or preset */
+
+/* Third register */
+#define TEA5767_STEREO_MASK    0x80
+#define TEA5767_IF_CNTR_MASK   0x7f
+
+/* Four register */
+#define TEA5767_ADC_LEVEL_MASK 0xf0
+
+/* should be 0 */
+#define TEA5767_CHIP_ID_MASK   0x0f
+
+/* Fiveth register */
+/* Reserved for future extensions */
+#define TEA5767_RESERVED_MASK  0xff
+
+/*****************************************************************************/
+
+static void set_tv_freq(struct i2c_client *c, unsigned int freq)
+{
+       struct tuner *t = i2c_get_clientdata(c);
+
+       tuner_warn("This tuner doesn't support TV freq.\n");
+}
+
+static void tea5767_status_dump(unsigned char *buffer)
+{
+       unsigned int div, frq;
+
+       if (TEA5767_READY_FLAG_MASK & buffer[0])
+               printk(PREFIX "Ready Flag ON\n");
+       else
+               printk(PREFIX "Ready Flag OFF\n");
+
+       if (TEA5767_BAND_LIMIT_MASK & buffer[0])
+               printk(PREFIX "Tuner at band limit\n");
+       else
+               printk(PREFIX "Tuner not at band limit\n");
+
+       div=((buffer[0]&0x3f)<<8) | buffer[1];
+
+       switch (TEA5767_HIGH_LO_32768) {
+       case TEA5767_HIGH_LO_13MHz:
+               frq = 1000*(div*50-700-225)/4; /* Freq in KHz */
+               break;
+       case TEA5767_LOW_LO_13MHz:
+               frq = 1000*(div*50+700+225)/4; /* Freq in KHz */
+               break;
+       case TEA5767_LOW_LO_32768:
+               frq = 1000*(div*32768/1000+700+225)/4; /* Freq in KHz */
+               break;
+       case TEA5767_HIGH_LO_32768:
+       default:
+               frq = 1000*(div*32768/1000-700-225)/4; /* Freq in KHz */
+               break;
+       }
+        buffer[0] = (div>>8) & 0x3f;
+        buffer[1] = div      & 0xff;
+
+       printk(PREFIX "Frequency %d.%03d KHz (divider = 0x%04x)\n",
+                                               frq/1000,frq%1000,div);
+
+       if (TEA5767_STEREO_MASK & buffer[2])
+               printk(PREFIX "Stereo\n");
+       else
+               printk(PREFIX "Mono\n");
+
+       printk(PREFIX "IF Counter = %d\n",buffer[2] & TEA5767_IF_CNTR_MASK);
+
+       printk(PREFIX "ADC Level = %d\n",(buffer[3] & TEA5767_ADC_LEVEL_MASK)>>4);
+
+       printk(PREFIX "Chip ID = %d\n",(buffer[3] & TEA5767_CHIP_ID_MASK));
+
+       printk(PREFIX "Reserved = 0x%02x\n",(buffer[4] & TEA5767_RESERVED_MASK));
+}
+
+/* Freq should be specifyed at 62.5 Hz */
+static void set_radio_freq(struct i2c_client *c, unsigned int frq)
+{
+       struct tuner *t = i2c_get_clientdata(c);
+        unsigned char buffer[5];
+       unsigned div;
+       int rc;
+
+       if ( tuner_debug )
+               printk(PREFIX "radio freq counter %d\n",frq);
+
+       /* Rounds freq to next decimal value - for 62.5 KHz step */
+       /* frq = 20*(frq/16)+radio_frq[frq%16]; */
+
+       buffer[2] = TEA5767_PORT1_HIGH;
+       buffer[3] = TEA5767_PORT2_HIGH | TEA5767_HIGH_CUT_CTRL | TEA5767_ST_NOISE_CTL | TEA5767_JAPAN_BAND;
+       buffer[4]=0;
+
+       if (t->audmode == V4L2_TUNER_MODE_MONO) {
+               tuner_dbg("TEA5767 set to mono\n");
+               buffer[2] |= TEA5767_MONO;
+       } else
+               tuner_dbg("TEA5767 set to stereo\n");
+
+       switch (t->type) {
+       case TEA5767_HIGH_LO_13MHz:
+               tuner_dbg("TEA5767 radio HIGH LO inject xtal @ 13 MHz\n");
+               buffer[2] |= TEA5767_HIGH_LO_INJECT;
+               buffer[4] |= TEA5767_PLLREF_ENABLE;
+               div = (frq*4/16+700+225+25)/50;
+               break;
+       case TEA5767_LOW_LO_13MHz:
+               tuner_dbg("TEA5767 radio LOW LO inject xtal @ 13 MHz\n");
+
+               buffer[4] |= TEA5767_PLLREF_ENABLE;
+               div = (frq*4/16-700-225+25)/50;
+               break;
+       case TEA5767_LOW_LO_32768:
+               tuner_dbg("TEA5767 radio LOW LO inject xtal @ 32,768 MHz\n");
+               buffer[3] |= TEA5767_XTAL_32768;
+               /* const 700=4000*175 Khz - to adjust freq to right value */
+               div = (1000*(frq*4/16-700-225)+16384)>>15;
+               break;
+       case TEA5767_HIGH_LO_32768:
+       default:
+               tuner_dbg("TEA5767 radio HIGH LO inject xtal @ 32,768 MHz\n");
+
+               buffer[2] |= TEA5767_HIGH_LO_INJECT;
+               buffer[3] |= TEA5767_XTAL_32768;
+               div = (1000*(frq*4/16+700+225)+16384)>>15;
+               break;
+       }
+        buffer[0] = (div>>8) & 0x3f;
+        buffer[1] = div      & 0xff;
+
+       if ( tuner_debug )
+               tea5767_status_dump(buffer);
+
+        if (5 != (rc = i2c_master_send(c,buffer,5)))
+               tuner_warn("i2c i/o error: rc == %d (should be 5)\n",rc);
+}
+
+static int tea5767_signal(struct i2c_client *c)
+{
+       unsigned char buffer[5];
+       int rc;
+       struct tuner *t = i2c_get_clientdata(c);
+
+       memset(buffer,0,sizeof(buffer));
+        if (5 != (rc = i2c_master_recv(c,buffer,5)))
+                tuner_warn ( "i2c i/o error: rc == %d (should be 5)\n",rc);
+
+       return ((buffer[3] & TEA5767_ADC_LEVEL_MASK) <<(13-4));
+}
+
+static int tea5767_stereo(struct i2c_client *c)
+{
+       unsigned char buffer[5];
+       int rc;
+       struct tuner *t = i2c_get_clientdata(c);
+
+       memset(buffer,0,sizeof(buffer));
+        if (5 != (rc = i2c_master_recv(c,buffer,5)))
+                tuner_warn ( "i2c i/o error: rc == %d (should be 5)\n",rc);
+
+       rc = buffer[2] & TEA5767_STEREO_MASK;
+
+       if ( tuner_debug )
+               tuner_dbg("TEA5767 radio ST GET = %02x\n", rc);
+
+       return ( (buffer[2] & TEA5767_STEREO_MASK) ? V4L2_TUNER_SUB_STEREO: 0);
+}
+
+int tea_detection(struct i2c_client *c)
+{
+       unsigned char buffer[5]= { 0xff, 0xff, 0xff, 0xff, 0xff };
+       int rc;
+       struct tuner *t = i2c_get_clientdata(c);
+
+        if (5 != (rc = i2c_master_recv(c,buffer,5))) {
+                tuner_warn ( "it is not a TEA5767. Received %i chars.\n",rc );
+               return EINVAL;
+       }
+
+       /* If all bytes are the same then it's a TV tuner and not a tea5767 chip. */
+       if (buffer[0] == buffer[1] &&  buffer[0] == buffer[2] &&
+           buffer[0] == buffer[3] &&  buffer[0] == buffer[4]) {
+                tuner_warn ( "All bytes are equal. It is not a TEA5767\n" );
+               return EINVAL;
+       }
+
+       /*  Status bytes:
+        *  Byte 4: bit 3:1 : CI (Chip Identification) == 0
+        *          bit 0   : internally set to 0
+        *  Byte 5: bit 7:0 : == 0
+        */
+
+       if (!((buffer[3] & 0x0f) == 0x00) && (buffer[4] == 0x00)) {
+                tuner_warn ( "Chip ID is not zero. It is not a TEA5767\n" );
+               return EINVAL;
+       }
+       tuner_warn ( "TEA5767 detected.\n" );
+       return 0;
+}
+
+int tea5767_tuner_init(struct i2c_client *c)
+{
+       struct tuner *t = i2c_get_clientdata(c);
+
+       if (tea_detection(c)==EINVAL) return EINVAL;
+
+        tuner_info("type set to %d (%s)\n",
+                   t->type, TEA5767_TUNER_NAME);
+        strlcpy(c->name, TEA5767_TUNER_NAME, sizeof(c->name));
+
+       t->tv_freq    = set_tv_freq;
+       t->radio_freq = set_radio_freq;
+       t->has_signal = tea5767_signal;
+       t->is_stereo  = tea5767_stereo;
+
+       return (0);
+}
index eaabfc8..6f6bf4a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: tuner-core.c,v 1.15 2005/06/12 01:36:14 mchehab Exp $
+ * $Id: tuner-core.c,v 1.29 2005/06/21 15:40:33 mchehab Exp $
  *
  * i2c tv tuner chip device driver
  * core core, i.e. kernel interfaces, registering and so on
@@ -26,7 +26,6 @@
 /*
  * comment line bellow to return to old behavor, where only one I2C device is supported
  */
-#define CONFIG_TUNER_MULTI_I2C /**/
 
 #define UNSET (-1U)
 
@@ -58,9 +57,7 @@ MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer");
 MODULE_LICENSE("GPL");
 
 static int this_adap;
-#ifdef CONFIG_TUNER_MULTI_I2C
 static unsigned short first_tuner, tv_tuner, radio_tuner;
-#endif
 
 static struct i2c_driver driver;
 static struct i2c_client client_template;
@@ -81,26 +78,9 @@ static void set_tv_freq(struct i2c_client *c, unsigned int freq)
                return;
        }
        if (freq < tv_range[0]*16 || freq > tv_range[1]*16) {
-
-               if (freq >= tv_range[0]*16364 && freq <= tv_range[1]*16384) {
-                       /* V4L2_TUNER_CAP_LOW frequency */
-
-                       tuner_dbg("V4L2_TUNER_CAP_LOW freq selected for TV. Tuners yet doesn't support converting it to valid freq.\n");
-
-                       t->tv_freq(c,freq>>10);
-
-                       return;
-                } else {
-                       /* FIXME: better do that chip-specific, but
-                          right now we don't have that in the config
-                          struct and this way is still better than no
-                          check at all */
                        tuner_info("TV freq (%d.%02d) out of range (%d-%d)\n",
                                   freq/16,freq%16*100/16,tv_range[0],tv_range[1]);
-                       return;
-               }
        }
-       tuner_dbg("62.5 Khz freq step selected for TV.\n");
        t->tv_freq(c,freq);
 }
 
@@ -116,31 +96,18 @@ static void set_radio_freq(struct i2c_client *c, unsigned int freq)
                tuner_info("no radio tuning for this one, sorry.\n");
                return;
        }
-       if (freq < radio_range[0]*16 || freq > radio_range[1]*16) {
-               if (freq >= tv_range[0]*16364 && freq <= tv_range[1]*16384) {
-                       /* V4L2_TUNER_CAP_LOW frequency */
-                       if (t->type == TUNER_TEA5767) {
-                               tuner_info("radio freq step 62.5Hz (%d.%06d)\n",(freq>>14),freq%(1<<14)*10000);
-                               t->radio_freq(c,freq>>10);
-                               return;
-                       }
-
-                       tuner_dbg("V4L2_TUNER_CAP_LOW freq selected for Radio. Tuners yet doesn't support converting it to valid freq.\n");
-
-                       tuner_info("radio freq (%d.%06d)\n",(freq>>14),freq%(1<<14)*10000);
-
-                       t->radio_freq(c,freq>>10);
-                       return;
-
-                } else {
-                       tuner_info("radio freq (%d.%02d) out of range (%d-%d)\n",
-                          freq/16,freq%16*100/16,
-                                  radio_range[0],radio_range[1]);
-                       return;
-               }
+       if (freq >= radio_range[0]*16000 && freq <= radio_range[1]*16000) {
+               if (tuner_debug)
+                       tuner_info("radio freq step 62.5Hz (%d.%06d)\n",
+                                           freq/16000,freq%16000*1000/16);
+               t->radio_freq(c,freq);
+        } else {
+               tuner_info("radio freq (%d.%02d) out of range (%d-%d)\n",
+                           freq/16,freq%16*100/16,
+                           radio_range[0],radio_range[1]);
        }
-       tuner_dbg("62.5 Khz freq step selected for Radio.\n");
-       t->radio_freq(c,freq);
+
+       return;
 }
 
 static void set_freq(struct i2c_client *c, unsigned long freq)
@@ -166,8 +133,8 @@ static void set_freq(struct i2c_client *c, unsigned long freq)
 static void set_type(struct i2c_client *c, unsigned int type)
 {
        struct tuner *t = i2c_get_clientdata(c);
+       unsigned char buffer[4];
 
-       tuner_dbg ("I2C addr 0x%02x with type %d\n",c->addr<<1,type);
        /* sanity check */
        if (type == UNSET || type == TUNER_ABSENT)
                return;
@@ -179,8 +146,8 @@ static void set_type(struct i2c_client *c, unsigned int type)
                t->type = type;
                return;
        }
-       if (t->initialized)
-               /* run only once */
+       if ((t->initialized) && (t->type == type))
+               /* run only once except type change  Hac 04/05*/
                return;
 
        t->initialized = 1;
@@ -193,25 +160,42 @@ static void set_type(struct i2c_client *c, unsigned int type)
        case TUNER_PHILIPS_TDA8290:
                tda8290_init(c);
                break;
+       case TUNER_TEA5767:
+               if (tea5767_tuner_init(c)==EINVAL) t->type=TUNER_ABSENT;
+               break;
+       case TUNER_PHILIPS_FMD1216ME_MK3:
+               buffer[0] = 0x0b;
+               buffer[1] = 0xdc;
+               buffer[2] = 0x9c;
+               buffer[3] = 0x60;
+               i2c_master_send(c,buffer,4);
+               mdelay(1);
+               buffer[2] = 0x86;
+               buffer[3] = 0x54;
+               i2c_master_send(c,buffer,4);
+               default_tuner_init(c);
+               break;
        default:
+               /* TEA5767 autodetection code */
+                       if (tea5767_tuner_init(c)!=EINVAL) {
+                               t->type = TUNER_TEA5767;
+                               if (first_tuner == 0x60)
+                                       first_tuner++;
+                               break;
+                       }
+
                default_tuner_init(c);
                break;
        }
+       tuner_dbg ("I2C addr 0x%02x with type %d\n",c->addr<<1,type);
 }
 
-#ifdef CONFIG_TUNER_MULTI_I2C
 #define CHECK_ADDR(tp,cmd,tun) if (client->addr!=tp) { \
-                         return 0; } else \
+                         return 0; } else if (tuner_debug) \
                          tuner_info ("Cmd %s accepted to "tun"\n",cmd);
 #define CHECK_MODE(cmd)        if (t->mode == V4L2_TUNER_RADIO) { \
                        CHECK_ADDR(radio_tuner,cmd,"radio") } else \
                        { CHECK_ADDR(tv_tuner,cmd,"TV"); }
-#else
-#define CHECK_ADDR(tp,cmd,tun) tuner_info ("Cmd %s accepted to "tun"\n",cmd);
-#define CHECK_MODE(cmd) tuner_info ("Cmd %s accepted\n",cmd);
-#endif
-
-#ifdef CONFIG_TUNER_MULTI_I2C
 
 static void set_addr(struct i2c_client *c, struct tuner_addr *tun_addr)
 {
@@ -242,9 +226,6 @@ static void set_addr(struct i2c_client *c, struct tuner_addr *tun_addr)
        }
        set_type(c,tun_addr->type);
 }
-#else
-#define set_addr(c,tun_addr) set_type(c,(tun_addr)->type)
-#endif
 
 static char pal[] = "-";
 module_param_string(pal, pal, sizeof(pal), 0644);
@@ -284,17 +265,12 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
 {
        struct tuner *t;
 
-#ifndef CONFIG_TUNER_MULTI_I2C
-       if (this_adap > 0)
-               return -1;
-#else
        /* by default, first I2C card is both tv and radio tuner */
        if (this_adap == 0) {
                first_tuner = addr;
                tv_tuner = addr;
                radio_tuner = addr;
        }
-#endif
        this_adap++;
 
         client_template.adapter = adap;
@@ -308,6 +284,7 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
        i2c_set_clientdata(&t->i2c, t);
        t->type       = UNSET;
        t->radio_if2  = 10700*1000; /* 10.7MHz - FM radio */
+       t->audmode    = V4L2_TUNER_MODE_STEREO;
 
         i2c_attach_client(&t->i2c);
        tuner_info("chip found @ 0x%x (%s)\n",
@@ -325,11 +302,9 @@ static int tuner_probe(struct i2c_adapter *adap)
        }
        this_adap = 0;
 
-#ifdef CONFIG_TUNER_MULTI_I2C
        first_tuner = 0;
        tv_tuner = 0;
        radio_tuner = 0;
-#endif
 
        if (adap->class & I2C_CLASS_TV_ANALOG)
                return i2c_probe(adap, &addr_data, tuner_attach);
@@ -392,8 +367,7 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
                        t->radio_if2 = 41300 * 1000;
                        break;
                }
-                break;
-
+               break;
        /* --- v4l ioctls --- */
        /* take care: bttv does userspace copying, we'll get a
           kernel pointer here... */
@@ -440,11 +414,18 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
                                vt->signal = t->has_signal(client);
                        if (t->is_stereo) {
                                if (t->is_stereo(client))
-                                       vt-> flags |= VIDEO_TUNER_STEREO_ON;
+                                       vt->flags |= VIDEO_TUNER_STEREO_ON;
                                else
-                                       vt-> flags &= 0xffff ^ VIDEO_TUNER_STEREO_ON;
+                                       vt->flags &= ~VIDEO_TUNER_STEREO_ON;
                        }
                        vt->flags |= V4L2_TUNER_CAP_LOW; /* Allow freqs at 62.5 Hz */
+
+                       vt->rangelow = radio_range[0] * 16000;
+                       vt->rangehigh = radio_range[1] * 16000;
+
+               } else {
+                       vt->rangelow = tv_range[0] * 16;
+                       vt->rangehigh = tv_range[1] * 16;
                }
 
                return 0;
@@ -510,20 +491,46 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
                                tuner -> signal = t->has_signal(client);
                        if (t->is_stereo) {
                                if (t->is_stereo(client)) {
-                                       tuner -> capability |= V4L2_TUNER_CAP_STEREO;
-                                       tuner -> rxsubchans |= V4L2_TUNER_SUB_STEREO;
+                                       tuner -> rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO;
                                } else {
-                                       tuner -> rxsubchans &= 0xffff ^ V4L2_TUNER_SUB_STEREO;
+                                       tuner -> rxsubchans = V4L2_TUNER_SUB_MONO;
                                }
                        }
+                       tuner->capability |= V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
+                       tuner->audmode = t->audmode;
+
+                       tuner->rangelow = radio_range[0] * 16000;
+                       tuner->rangehigh = radio_range[1] * 16000;
+               } else {
+                       tuner->rangelow = tv_range[0] * 16;
+                       tuner->rangehigh = tv_range[1] * 16;
                }
-               /* Wow to deal with V4L2_TUNER_CAP_LOW ? For now, it accepts from low at 62.5KHz step  to high at 62.5 Hz */
-               tuner->rangelow = tv_range[0] * 16;
-//             tuner->rangehigh = tv_range[1] * 16;
-//             tuner->rangelow = tv_range[0] * 16384;
-               tuner->rangehigh = tv_range[1] * 16384;
                break;
        }
+       case VIDIOC_S_TUNER: /* Allow changing radio range and audio mode */
+       {
+               struct v4l2_tuner *tuner = arg;
+
+               CHECK_ADDR(radio_tuner,"VIDIOC_S_TUNER","radio");
+               SWITCH_V4L2;
+
+               /* To switch the audio mode, applications initialize the
+                  index and audmode fields and the reserved array and
+                  call the VIDIOC_S_TUNER ioctl. */
+               /* rxsubchannels: V4L2_TUNER_MODE_MONO, V4L2_TUNER_MODE_STEREO,
+                  V4L2_TUNER_MODE_LANG1, V4L2_TUNER_MODE_LANG2,
+                  V4L2_TUNER_MODE_SAP */
+
+               if (tuner->audmode == V4L2_TUNER_MODE_MONO)
+                       t->audmode = V4L2_TUNER_MODE_MONO;
+               else
+                       t->audmode = V4L2_TUNER_MODE_STEREO;
+
+               set_radio_freq(client, t->freq);
+               break;
+       }
+       case TDA9887_SET_CONFIG: /* Nothing to do on tuner-core */
+               break;
        default:
                tuner_dbg ("Unimplemented IOCTL 0x%08x called to tuner.\n", cmd);
                /* nothing */
index 539f305..c39ed62 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: tuner-simple.c,v 1.21 2005/06/10 19:53:26 nsh Exp $
+ * $Id: tuner-simple.c,v 1.31 2005/06/21 16:02:25 mkrufky Exp $
  *
  * i2c tv tuner chip device driver
  * controls all those simple 4-control-bytes style tuners.
@@ -207,28 +207,27 @@ static struct tunertype tuners[] = {
        { "LG PAL (TAPE series)", LGINNOTEK, PAL,
           16*170.00, 16*450.00, 0x01,0x02,0x08,0xce,623},
 
-        { "Philips PAL/SECAM multi (FQ1216AME MK4)", Philips, PAL,
-          16*160.00,16*442.00,0x01,0x02,0x04,0xce,623 },
-        { "Philips FQ1236A MK4", Philips, NTSC,
-          16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732 },
+       { "Philips PAL/SECAM multi (FQ1216AME MK4)", Philips, PAL,
+         16*160.00,16*442.00,0x01,0x02,0x04,0xce,623 },
+       { "Philips FQ1236A MK4", Philips, NTSC,
+         16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732 },
 
        /* Should work for TVF8531MF, TVF8831MF, TVF8731MF */
        { "Ymec TVision TVF-8531MF", Philips, NTSC,
          16*160.00,16*454.00,0xa0,0x90,0x30,0x8e,732},
        { "Ymec TVision TVF-5533MF", Philips, NTSC,
          16*160.00,16*454.00,0x01,0x02,0x04,0x8e,732},
-
        { "Thomson DDT 7611 (ATSC/NTSC)", THOMSON, ATSC,
          16*157.25,16*454.00,0x39,0x3a,0x3c,0x8e,732},
-       { "Tena TNF9533-D/IF", LGINNOTEK, PAL,
-         16*160.25, 16*464.25, 0x01,0x02,0x08,0x8e,623},
+       /* Should work for TNF9533-D/IF, TNF9533-B/DF */
+       { "Tena TNF9533-D/IF", Philips, PAL,
+          16*160.25,16*464.25,0x01,0x02,0x04,0x8e,623},
 
-       /*
-        * This entry is for TEA5767 FM radio only chip used on several boards
-        * w/TV tuner
-        */
+       /* This entry is for TEA5767 FM radio only chip used on several boards w/TV tuner */
        { TEA5767_TUNER_NAME, Philips, RADIO,
-         -1, -1, 0, 0, 0, TEA5767_LOW_LO_32768,0},
+          -1, -1, 0, 0, 0, TEA5767_LOW_LO_32768,0},
+       { "Philips FMD1216ME MK3 Hybrid Tuner", Philips, PAL,
+         16*160.00,16*442.00,0x51,0x52,0x54,0x86,623 },
 };
 
 unsigned const int tuner_count = ARRAY_SIZE(tuners);
@@ -455,24 +454,24 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq)
        int rc;
 
        tun=&tuners[t->type];
-       div = freq + (int)(16*10.7);
+       div = (freq / 1000) + (int)(16*10.7);
        buffer[2] = tun->config;
 
        switch (t->type) {
        case TUNER_TENA_9533_DI:
        case TUNER_YMEC_TVF_5533MF:
-
                /*These values are empirically determinated */
-               div = (freq*122)/16 - 20;
+               div = (freq * 122) / 16000 - 20;
                buffer[2] = 0x88; /* could be also 0x80 */
                buffer[3] = 0x19; /* could be also 0x10, 0x18, 0x99 */
                break;
        case TUNER_PHILIPS_FM1216ME_MK3:
        case TUNER_PHILIPS_FM1236_MK3:
+       case TUNER_PHILIPS_FMD1216ME_MK3:
                buffer[3] = 0x19;
                break;
        case TUNER_PHILIPS_FM1256_IH3:
-               div = (20 * freq)/16 + 333 * 2;
+               div = (20 * freq) / 16000 + 333 * 2;
                buffer[2] = 0x80;
                buffer[3] = 0x19;
                break;
@@ -505,6 +504,7 @@ int default_tuner_init(struct i2c_client *c)
        t->radio_freq = default_set_radio_freq;
        t->has_signal = tuner_signal;
        t->is_stereo  = tuner_stereo;
+
        return 0;
 }
 
index d8d6539..353deb2 100644 (file)
@@ -364,9 +364,7 @@ static struct pci_driver mptfc_driver = {
        .id_table       = mptfc_pci_table,
        .probe          = mptfc_probe,
        .remove         = __devexit_p(mptscsih_remove),
-       .driver         = {
-               .shutdown = mptscsih_shutdown,
-        },
+       .shutdown       = mptscsih_shutdown,
 #ifdef CONFIG_PM
        .suspend        = mptscsih_suspend,
        .resume         = mptscsih_resume,
index a0078ae..4f973a4 100644 (file)
@@ -170,7 +170,7 @@ static void mptscsih_fillbuf(char *buffer, int size, int index, int width);
 #endif
 
 void           mptscsih_remove(struct pci_dev *);
-void           mptscsih_shutdown(struct device *);
+void           mptscsih_shutdown(struct pci_dev *);
 #ifdef CONFIG_PM
 int            mptscsih_suspend(struct pci_dev *pdev, pm_message_t state);
 int            mptscsih_resume(struct pci_dev *pdev);
@@ -988,7 +988,7 @@ mptscsih_remove(struct pci_dev *pdev)
 #endif
 #endif
 
-       mptscsih_shutdown(&pdev->dev);
+       mptscsih_shutdown(pdev);
 
        sz1=0;
 
@@ -1026,9 +1026,9 @@ mptscsih_remove(struct pci_dev *pdev)
  *
  */
 void
-mptscsih_shutdown(struct device * dev)
+mptscsih_shutdown(struct pci_dev *pdev)
 {
-       MPT_ADAPTER             *ioc = pci_get_drvdata(to_pci_dev(dev));
+       MPT_ADAPTER             *ioc = pci_get_drvdata(pdev);
        struct Scsi_Host        *host = ioc->sh;
        MPT_SCSI_HOST           *hd;
 
@@ -1054,7 +1054,7 @@ mptscsih_shutdown(struct device * dev)
 int
 mptscsih_suspend(struct pci_dev *pdev, pm_message_t state)
 {
-       mptscsih_shutdown(&pdev->dev);
+       mptscsih_shutdown(pdev);
        return mpt_suspend(pdev,state);
 }
 
index d73aec3..5ea89bf 100644 (file)
@@ -82,7 +82,7 @@
 #endif
 
 extern void mptscsih_remove(struct pci_dev *);
-extern void mptscsih_shutdown(struct device *);
+extern void mptscsih_shutdown(struct pci_dev *);
 #ifdef CONFIG_PM
 extern int mptscsih_suspend(struct pci_dev *pdev, u32 state);
 extern int mptscsih_resume(struct pci_dev *pdev);
index 5f9a61b..e0c0ee5 100644 (file)
@@ -419,9 +419,7 @@ static struct pci_driver mptspi_driver = {
        .id_table       = mptspi_pci_table,
        .probe          = mptspi_probe,
        .remove         = __devexit_p(mptscsih_remove),
-       .driver         = {
-               .shutdown = mptscsih_shutdown,
-        },
+       .shutdown       = mptscsih_shutdown,
 #ifdef CONFIG_PM
        .suspend        = mptscsih_suspend,
        .resume         = mptscsih_resume,
index 1e56c8e..d0fa244 100644 (file)
@@ -2447,9 +2447,8 @@ static int e100_resume(struct pci_dev *pdev)
 #endif
 
 
-static void e100_shutdown(struct device *dev)
+static void e100_shutdown(struct pci_dev *pdev)
 {
-       struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
        struct net_device *netdev = pci_get_drvdata(pdev);
        struct nic *nic = netdev_priv(netdev);
 
@@ -2470,11 +2469,7 @@ static struct pci_driver e100_driver = {
        .suspend =      e100_suspend,
        .resume =       e100_resume,
 #endif
-
-       .driver = {
-               .shutdown = e100_shutdown,
-       }
-
+       .shutdown =     e100_shutdown,
 };
 
 static int __init e100_init_module(void)
index a56ef0d..fc7738f 100644 (file)
@@ -507,7 +507,7 @@ static struct net_device_stats *rhine_get_stats(struct net_device *dev);
 static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static struct ethtool_ops netdev_ethtool_ops;
 static int  rhine_close(struct net_device *dev);
-static void rhine_shutdown (struct device *gdev);
+static void rhine_shutdown (struct pci_dev *pdev);
 
 #define RHINE_WAIT_FOR(condition) do {                                 \
        int i=1024;                                                     \
@@ -1895,9 +1895,8 @@ static void __devexit rhine_remove_one(struct pci_dev *pdev)
        pci_set_drvdata(pdev, NULL);
 }
 
-static void rhine_shutdown (struct device *gendev)
+static void rhine_shutdown (struct pci_dev *pdev)
 {
-       struct pci_dev *pdev = to_pci_dev(gendev);
        struct net_device *dev = pci_get_drvdata(pdev);
        struct rhine_private *rp = netdev_priv(dev);
        void __iomem *ioaddr = rp->base;
@@ -1956,7 +1955,7 @@ static int rhine_suspend(struct pci_dev *pdev, pm_message_t state)
        pci_save_state(pdev);
 
        spin_lock_irqsave(&rp->lock, flags);
-       rhine_shutdown(&pdev->dev);
+       rhine_shutdown(pdev);
        spin_unlock_irqrestore(&rp->lock, flags);
 
        free_irq(dev->irq, dev);
@@ -2010,9 +2009,7 @@ static struct pci_driver rhine_driver = {
        .suspend        = rhine_suspend,
        .resume         = rhine_resume,
 #endif /* CONFIG_PM */
-       .driver = {
-               .shutdown = rhine_shutdown,
-       }
+       .shutdown =     rhine_shutdown,
 };
 
 
index b0d2a73..2f2dbef 100644 (file)
@@ -993,6 +993,7 @@ dino_driver_callback(struct parisc_device *dev)
        bus = pci_scan_bus_parented(&dev->dev, dino_current_bus,
                                    &dino_cfg_ops, NULL);
        if(bus) {
+               pci_bus_add_devices(bus);
                /* This code *depends* on scanning being single threaded
                 * if it isn't, this global bus number count will fail
                 */
index dc83880..7fdd80b 100644 (file)
@@ -1570,6 +1570,8 @@ lba_driver_probe(struct parisc_device *dev)
        lba_bus = lba_dev->hba.hba_bus =
                pci_scan_bus_parented(&dev->dev, lba_dev->hba.bus_num.start,
                                cfg_ops, NULL);
+       if (lba_bus)
+               pci_bus_add_devices(lba_bus);
 
        /* This is in lieu of calling pci_assign_unassigned_resources() */
        if (is_pdc_pat()) {
index dbd3360..fedae89 100644 (file)
@@ -121,10 +121,13 @@ void __devinit pci_bus_add_devices(struct pci_bus *bus)
                 * If there is an unattached subordinate bus, attach
                 * it and then scan for unattached PCI devices.
                 */
-               if (dev->subordinate && list_empty(&dev->subordinate->node)) {
-                       spin_lock(&pci_bus_lock);
-                       list_add_tail(&dev->subordinate->node, &dev->bus->children);
-                       spin_unlock(&pci_bus_lock);
+               if (dev->subordinate) {
+                      if (list_empty(&dev->subordinate->node)) {
+                              spin_lock(&pci_bus_lock);
+                              list_add_tail(&dev->subordinate->node,
+                                              &dev->bus->children);
+                              spin_unlock(&pci_bus_lock);
+                      }
                        pci_bus_add_devices(dev->subordinate);
 
                        sysfs_create_link(&dev->subordinate->class_dev.kobj, &dev->dev.kobj, "bridge");
index 93c120d..3e632ff 100644 (file)
@@ -36,9 +36,7 @@ ibmphp-objs           :=      ibmphp_core.o   \
                                ibmphp_hpc.o
 
 acpiphp-objs           :=      acpiphp_core.o  \
-                               acpiphp_glue.o  \
-                               acpiphp_pci.o   \
-                               acpiphp_res.o
+                               acpiphp_glue.o
 
 rpaphp-objs            :=      rpaphp_core.o   \
                                rpaphp_pci.o    \
index d949987..293603e 100644 (file)
@@ -7,6 +7,8 @@
  * Copyright (C) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com)
  * Copyright (C) 2002,2003 Takayoshi Kochi (t-kochi@bq.jp.nec.com)
  * Copyright (C) 2002,2003 NEC Corporation
+ * Copyright (C) 2003-2005 Matthew Wilcox (matthew.wilcox@hp.com)
+ * Copyright (C) 2003-2005 Hewlett Packard
  *
  * All rights reserved.
  *
@@ -52,7 +54,6 @@
 
 struct acpiphp_bridge;
 struct acpiphp_slot;
-struct pci_resource;
 
 /*
  * struct slot - slot information for each *physical* slot
@@ -65,15 +66,6 @@ struct slot {
        struct acpiphp_slot     *acpi_slot;
 };
 
-/*
- * struct pci_resource - describes pci resource (mem, pfmem, io, bus)
- */
-struct pci_resource {
-       struct pci_resource * next;
-       u64 base;
-       u32 length;
-};
-
 /**
  * struct hpp_param - ACPI 2.0 _HPP Hot Plug Parameters
  * @cache_line_size in DWORD
@@ -101,10 +93,6 @@ struct acpiphp_bridge {
        int type;
        int nr_slots;
 
-       u8 seg;
-       u8 bus;
-       u8 sub;
-
        u32 flags;
 
        /* This bus (host bridge) or Secondary bus (PCI-to-PCI bridge) */
@@ -117,12 +105,6 @@ struct acpiphp_bridge {
        struct hpp_param hpp;
 
        spinlock_t res_lock;
-
-       /* available resources on this bus */
-       struct pci_resource *mem_head;
-       struct pci_resource *p_mem_head;
-       struct pci_resource *io_head;
-       struct pci_resource *bus_head;
 };
 
 
@@ -163,12 +145,6 @@ struct acpiphp_func {
 
        u8              function;       /* pci function# */
        u32             flags;          /* see below */
-
-       /* resources used for this function */
-       struct pci_resource *mem_head;
-       struct pci_resource *p_mem_head;
-       struct pci_resource *io_head;
-       struct pci_resource *bus_head;
 };
 
 /**
@@ -243,25 +219,6 @@ extern u8 acpiphp_get_latch_status (struct acpiphp_slot *slot);
 extern u8 acpiphp_get_adapter_status (struct acpiphp_slot *slot);
 extern u32 acpiphp_get_address (struct acpiphp_slot *slot);
 
-/* acpiphp_pci.c */
-extern struct pci_dev *acpiphp_allocate_pcidev (struct pci_bus *pbus, int dev, int fn);
-extern int acpiphp_configure_slot (struct acpiphp_slot *slot);
-extern int acpiphp_configure_function (struct acpiphp_func *func);
-extern void acpiphp_unconfigure_function (struct acpiphp_func *func);
-extern int acpiphp_detect_pci_resource (struct acpiphp_bridge *bridge);
-extern int acpiphp_init_func_resource (struct acpiphp_func *func);
-
-/* acpiphp_res.c */
-extern struct pci_resource *acpiphp_get_io_resource (struct pci_resource **head, u32 size);
-extern struct pci_resource *acpiphp_get_resource (struct pci_resource **head, u32 size);
-extern struct pci_resource *acpiphp_get_resource_with_base (struct pci_resource **head, u64 base, u32 size);
-extern int acpiphp_resource_sort_and_combine (struct pci_resource **head);
-extern struct pci_resource *acpiphp_make_resource (u64 base, u32 length);
-extern void acpiphp_move_resource (struct pci_resource **from, struct pci_resource **to);
-extern void acpiphp_free_resource (struct pci_resource **res);
-extern void acpiphp_dump_resource (struct acpiphp_bridge *bridge); /* debug */
-extern void acpiphp_dump_func_resource (struct acpiphp_func *func); /* debug */
-
 /* variables */
 extern int acpiphp_debug;
 
index 4539e61..60c4c38 100644 (file)
@@ -7,6 +7,8 @@
  * Copyright (C) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com)
  * Copyright (C) 2002,2003 Takayoshi Kochi (t-kochi@bq.jp.nec.com)
  * Copyright (C) 2002,2003 NEC Corporation
+ * Copyright (C) 2003-2005 Matthew Wilcox (matthew.wilcox@hp.com)
+ * Copyright (C) 2003-2005 Hewlett Packard
  *
  * All rights reserved.
  *
@@ -53,8 +55,8 @@ int acpiphp_debug;
 static int num_slots;
 static struct acpiphp_attention_info *attention_info;
 
-#define DRIVER_VERSION "0.4"
-#define DRIVER_AUTHOR  "Greg Kroah-Hartman <gregkh@us.ibm.com>, Takayoshi Kochi <t-kochi@bq.jp.nec.com>"
+#define DRIVER_VERSION "0.5"
+#define DRIVER_AUTHOR  "Greg Kroah-Hartman <gregkh@us.ibm.com>, Takayoshi Kochi <t-kochi@bq.jp.nec.com>, Matthew Wilcox <willy@hp.com>"
 #define DRIVER_DESC    "ACPI Hot Plug PCI Controller Driver"
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
@@ -281,8 +283,7 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
 /**
  * get_address - get pci address of a slot
  * @hotplug_slot: slot to get status
- * @busdev: pointer to struct pci_busdev (seg, bus, dev)
- *
+ * @value: pointer to struct pci_busdev (seg, bus, dev)
  */
 static int get_address(struct hotplug_slot *hotplug_slot, u32 *value)
 {
index e7f4129..424e7de 100644 (file)
@@ -4,6 +4,10 @@
  * Copyright (C) 2002,2003 Takayoshi Kochi (t-kochi@bq.jp.nec.com)
  * Copyright (C) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com)
  * Copyright (C) 2002,2003 NEC Corporation
+ * Copyright (C) 2003-2005 Matthew Wilcox (matthew.wilcox@hp.com)
+ * Copyright (C) 2003-2005 Hewlett Packard
+ * Copyright (C) 2005 Rajesh Shah (rajesh.shah@intel.com)
+ * Copyright (C) 2005 Intel Corporation
  *
  * All rights reserved.
  *
  *
  */
 
+/*
+ * Lifetime rules for pci_dev:
+ *  - The one in acpiphp_func has its refcount elevated by pci_get_slot()
+ *    when the driver is loaded or when an insertion event occurs.  It loses
+ *    a refcount when its ejected or the driver unloads.
+ *  - The one in acpiphp_bridge has its refcount elevated by pci_get_slot()
+ *    when the bridge is scanned and it loses a refcount when the bridge
+ *    is removed.
+ */
+
 #include <linux/init.h>
 #include <linux/module.h>
 
@@ -178,21 +192,18 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
 
                bridge->nr_slots++;
 
-               dbg("found ACPI PCI Hotplug slot at PCI %02x:%02x Slot:%d\n",
-                   slot->bridge->bus, slot->device, slot->sun);
+               dbg("found ACPI PCI Hotplug slot %d at PCI %04x:%02x:%02x\n",
+                               slot->sun, pci_domain_nr(bridge->pci_bus),
+                               bridge->pci_bus->number, slot->device);
        }
 
        newfunc->slot = slot;
        list_add_tail(&newfunc->sibling, &slot->funcs);
 
        /* associate corresponding pci_dev */
-       newfunc->pci_dev = pci_find_slot(bridge->bus,
+       newfunc->pci_dev = pci_get_slot(bridge->pci_bus,
                                         PCI_DEVFN(device, function));
        if (newfunc->pci_dev) {
-               if (acpiphp_init_func_resource(newfunc) < 0) {
-                       kfree(newfunc);
-                       return AE_ERROR;
-               }
                slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON);
        }
 
@@ -227,62 +238,6 @@ static int detect_ejectable_slots(acpi_handle *bridge_handle)
 }
 
 
-/* decode ACPI _CRS data and convert into our internal resource list
- * TBD: _TRA, etc.
- */
-static acpi_status
-decode_acpi_resource(struct acpi_resource *resource, void *context)
-{
-       struct acpiphp_bridge *bridge = (struct acpiphp_bridge *) context;
-       struct acpi_resource_address64 address;
-       struct pci_resource *res;
-
-       if (resource->id != ACPI_RSTYPE_ADDRESS16 &&
-           resource->id != ACPI_RSTYPE_ADDRESS32 &&
-           resource->id != ACPI_RSTYPE_ADDRESS64)
-               return AE_OK;
-
-       acpi_resource_to_address64(resource, &address);
-
-       if (address.producer_consumer == ACPI_PRODUCER && address.address_length > 0) {
-               dbg("resource type: %d: 0x%llx - 0x%llx\n", address.resource_type,
-                   (unsigned long long)address.min_address_range,
-                   (unsigned long long)address.max_address_range);
-               res = acpiphp_make_resource(address.min_address_range,
-                                   address.address_length);
-               if (!res) {
-                       err("out of memory\n");
-                       return AE_OK;
-               }
-
-               switch (address.resource_type) {
-               case ACPI_MEMORY_RANGE:
-                       if (address.attribute.memory.cache_attribute == ACPI_PREFETCHABLE_MEMORY) {
-                               res->next = bridge->p_mem_head;
-                               bridge->p_mem_head = res;
-                       } else {
-                               res->next = bridge->mem_head;
-                               bridge->mem_head = res;
-                       }
-                       break;
-               case ACPI_IO_RANGE:
-                       res->next = bridge->io_head;
-                       bridge->io_head = res;
-                       break;
-               case ACPI_BUS_NUMBER_RANGE:
-                       res->next = bridge->bus_head;
-                       bridge->bus_head = res;
-                       break;
-               default:
-                       /* invalid type */
-                       kfree(res);
-                       break;
-               }
-       }
-
-       return AE_OK;
-}
-
 /* decode ACPI 2.0 _HPP hot plug parameters */
 static void decode_hpp(struct acpiphp_bridge *bridge)
 {
@@ -346,34 +301,29 @@ static void init_bridge_misc(struct acpiphp_bridge *bridge)
        /* decode ACPI 2.0 _HPP (hot plug parameters) */
        decode_hpp(bridge);
 
-       /* subtract all resources already allocated */
-       acpiphp_detect_pci_resource(bridge);
-
        /* register all slot objects under this bridge */
        status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge->handle, (u32)1,
                                     register_slot, bridge, NULL);
 
        /* install notify handler */
-       status = acpi_install_notify_handler(bridge->handle,
+       if (bridge->type != BRIDGE_TYPE_HOST) {
+               status = acpi_install_notify_handler(bridge->handle,
                                             ACPI_SYSTEM_NOTIFY,
                                             handle_hotplug_event_bridge,
                                             bridge);
 
-       if (ACPI_FAILURE(status)) {
-               err("failed to register interrupt notify handler\n");
+               if (ACPI_FAILURE(status)) {
+                       err("failed to register interrupt notify handler\n");
+               }
        }
 
        list_add(&bridge->list, &bridge_list);
-
-       dbg("Bridge resource:\n");
-       acpiphp_dump_resource(bridge);
 }
 
 
 /* allocate and initialize host bridge data structure */
-static void add_host_bridge(acpi_handle *handle, int seg, int bus)
+static void add_host_bridge(acpi_handle *handle, struct pci_bus *pci_bus)
 {
-       acpi_status status;
        struct acpiphp_bridge *bridge;
 
        bridge = kmalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL);
@@ -384,52 +334,19 @@ static void add_host_bridge(acpi_handle *handle, int seg, int bus)
 
        bridge->type = BRIDGE_TYPE_HOST;
        bridge->handle = handle;
-       bridge->seg = seg;
-       bridge->bus = bus;
 
-       bridge->pci_bus = pci_find_bus(seg, bus);
+       bridge->pci_bus = pci_bus;
 
        spin_lock_init(&bridge->res_lock);
 
-       /* to be overridden when we decode _CRS */
-       bridge->sub = bridge->bus;
-
-       /* decode resources */
-
-       status = acpi_walk_resources(handle, METHOD_NAME__CRS,
-               decode_acpi_resource, bridge);
-
-       if (ACPI_FAILURE(status)) {
-               err("failed to decode bridge resources\n");
-               kfree(bridge);
-               return;
-       }
-
-       acpiphp_resource_sort_and_combine(&bridge->io_head);
-       acpiphp_resource_sort_and_combine(&bridge->mem_head);
-       acpiphp_resource_sort_and_combine(&bridge->p_mem_head);
-       acpiphp_resource_sort_and_combine(&bridge->bus_head);
-
-       dbg("ACPI _CRS resource:\n");
-       acpiphp_dump_resource(bridge);
-
-       if (bridge->bus_head) {
-               bridge->bus = bridge->bus_head->base;
-               bridge->sub = bridge->bus_head->base + bridge->bus_head->length - 1;
-       }
-
        init_bridge_misc(bridge);
 }
 
 
 /* allocate and initialize PCI-to-PCI bridge data structure */
-static void add_p2p_bridge(acpi_handle *handle, int seg, int bus, int dev, int fn)
+static void add_p2p_bridge(acpi_handle *handle, struct pci_dev *pci_dev)
 {
        struct acpiphp_bridge *bridge;
-       u8 tmp8;
-       u16 tmp16;
-       u64 base64, limit64;
-       u32 base, limit, base32u, limit32u;
 
        bridge = kmalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL);
        if (bridge == NULL) {
@@ -441,133 +358,22 @@ static void add_p2p_bridge(acpi_handle *handle, int seg, int bus, int dev, int f
 
        bridge->type = BRIDGE_TYPE_P2P;
        bridge->handle = handle;
-       bridge->seg = seg;
-
-       bridge->pci_dev = pci_find_slot(bus, PCI_DEVFN(dev, fn));
-       if (!bridge->pci_dev) {
-               err("Can't get pci_dev\n");
-               kfree(bridge);
-               return;
-       }
 
-       bridge->pci_bus = bridge->pci_dev->subordinate;
+       bridge->pci_dev = pci_dev_get(pci_dev);
+       bridge->pci_bus = pci_dev->subordinate;
        if (!bridge->pci_bus) {
                err("This is not a PCI-to-PCI bridge!\n");
-               kfree(bridge);
-               return;
+               goto err;
        }
 
        spin_lock_init(&bridge->res_lock);
 
-       bridge->bus = bridge->pci_bus->number;
-       bridge->sub = bridge->pci_bus->subordinate;
-
-       /*
-        * decode resources under this P2P bridge
-        */
-
-       /* I/O resources */
-       pci_read_config_byte(bridge->pci_dev, PCI_IO_BASE, &tmp8);
-       base = tmp8;
-       pci_read_config_byte(bridge->pci_dev, PCI_IO_LIMIT, &tmp8);
-       limit = tmp8;
-
-       switch (base & PCI_IO_RANGE_TYPE_MASK) {
-       case PCI_IO_RANGE_TYPE_16:
-               base = (base << 8) & 0xf000;
-               limit = ((limit << 8) & 0xf000) + 0xfff;
-               bridge->io_head = acpiphp_make_resource((u64)base, limit - base + 1);
-               if (!bridge->io_head) {
-                       err("out of memory\n");
-                       kfree(bridge);
-                       return;
-               }
-               dbg("16bit I/O range: %04x-%04x\n",
-                   (u32)bridge->io_head->base,
-                   (u32)(bridge->io_head->base + bridge->io_head->length - 1));
-               break;
-       case PCI_IO_RANGE_TYPE_32:
-               pci_read_config_word(bridge->pci_dev, PCI_IO_BASE_UPPER16, &tmp16);
-               base = ((u32)tmp16 << 16) | ((base << 8) & 0xf000);
-               pci_read_config_word(bridge->pci_dev, PCI_IO_LIMIT_UPPER16, &tmp16);
-               limit = (((u32)tmp16 << 16) | ((limit << 8) & 0xf000)) + 0xfff;
-               bridge->io_head = acpiphp_make_resource((u64)base, limit - base + 1);
-               if (!bridge->io_head) {
-                       err("out of memory\n");
-                       kfree(bridge);
-                       return;
-               }
-               dbg("32bit I/O range: %08x-%08x\n",
-                   (u32)bridge->io_head->base,
-                   (u32)(bridge->io_head->base + bridge->io_head->length - 1));
-               break;
-       case 0x0f:
-               dbg("I/O space unsupported\n");
-               break;
-       default:
-               warn("Unknown I/O range type\n");
-       }
-
-       /* Memory resources (mandatory for P2P bridge) */
-       pci_read_config_word(bridge->pci_dev, PCI_MEMORY_BASE, &tmp16);
-       base = (tmp16 & 0xfff0) << 16;
-       pci_read_config_word(bridge->pci_dev, PCI_MEMORY_LIMIT, &tmp16);
-       limit = ((tmp16 & 0xfff0) << 16) | 0xfffff;
-       bridge->mem_head = acpiphp_make_resource((u64)base, limit - base + 1);
-       if (!bridge->mem_head) {
-               err("out of memory\n");
-               kfree(bridge);
-               return;
-       }
-       dbg("32bit Memory range: %08x-%08x\n",
-           (u32)bridge->mem_head->base,
-           (u32)(bridge->mem_head->base + bridge->mem_head->length-1));
-
-       /* Prefetchable Memory resources (optional) */
-       pci_read_config_word(bridge->pci_dev, PCI_PREF_MEMORY_BASE, &tmp16);
-       base = tmp16;
-       pci_read_config_word(bridge->pci_dev, PCI_PREF_MEMORY_LIMIT, &tmp16);
-       limit = tmp16;
-
-       switch (base & PCI_MEMORY_RANGE_TYPE_MASK) {
-       case PCI_PREF_RANGE_TYPE_32:
-               base = (base & 0xfff0) << 16;
-               limit = ((limit & 0xfff0) << 16) | 0xfffff;
-               bridge->p_mem_head = acpiphp_make_resource((u64)base, limit - base + 1);
-               if (!bridge->p_mem_head) {
-                       err("out of memory\n");
-                       kfree(bridge);
-                       return;
-               }
-               dbg("32bit Prefetchable memory range: %08x-%08x\n",
-                   (u32)bridge->p_mem_head->base,
-                   (u32)(bridge->p_mem_head->base + bridge->p_mem_head->length - 1));
-               break;
-       case PCI_PREF_RANGE_TYPE_64:
-               pci_read_config_dword(bridge->pci_dev, PCI_PREF_BASE_UPPER32, &base32u);
-               pci_read_config_dword(bridge->pci_dev, PCI_PREF_LIMIT_UPPER32, &limit32u);
-               base64 = ((u64)base32u << 32) | ((base & 0xfff0) << 16);
-               limit64 = (((u64)limit32u << 32) | ((limit & 0xfff0) << 16)) + 0xfffff;
-
-               bridge->p_mem_head = acpiphp_make_resource(base64, limit64 - base64 + 1);
-               if (!bridge->p_mem_head) {
-                       err("out of memory\n");
-                       kfree(bridge);
-                       return;
-               }
-               dbg("64bit Prefetchable memory range: %08x%08x-%08x%08x\n",
-                   (u32)(bridge->p_mem_head->base >> 32),
-                   (u32)(bridge->p_mem_head->base & 0xffffffff),
-                   (u32)((bridge->p_mem_head->base + bridge->p_mem_head->length - 1) >> 32),
-                   (u32)((bridge->p_mem_head->base + bridge->p_mem_head->length - 1) & 0xffffffff));
-               break;
-       case 0x0f:
-               break;
-       default:
-               warn("Unknown prefetchale memory type\n");
-       }
-
        init_bridge_misc(bridge);
+       return;
+ err:
+       pci_dev_put(pci_dev);
+       kfree(bridge);
+       return;
 }
 
 
@@ -577,14 +383,10 @@ find_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv)
 {
        acpi_status status;
        acpi_handle dummy_handle;
-       unsigned long *segbus = context;
        unsigned long tmp;
-       int seg, bus, device, function;
+       int device, function;
        struct pci_dev *dev;
-
-       /* get PCI address */
-       seg = (*segbus >> 8) & 0xff;
-       bus = *segbus & 0xff;
+       struct pci_bus *pci_bus = context;
 
        status = acpi_get_handle(handle, "_ADR", &dummy_handle);
        if (ACPI_FAILURE(status))
@@ -599,20 +401,19 @@ find_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv)
        device = (tmp >> 16) & 0xffff;
        function = tmp & 0xffff;
 
-       dev = pci_find_slot(bus, PCI_DEVFN(device, function));
+       dev = pci_get_slot(pci_bus, PCI_DEVFN(device, function));
 
-       if (!dev)
-               return AE_OK;
-
-       if (!dev->subordinate)
-               return AE_OK;
+       if (!dev || !dev->subordinate)
+               goto out;
 
        /* check if this bridge has ejectable slots */
        if (detect_ejectable_slots(handle) > 0) {
                dbg("found PCI-to-PCI bridge at PCI %s\n", pci_name(dev));
-               add_p2p_bridge(handle, seg, bus, device, function);
+               add_p2p_bridge(handle, dev);
        }
 
+ out:
+       pci_dev_put(dev);
        return AE_OK;
 }
 
@@ -624,6 +425,7 @@ static int add_bridge(acpi_handle handle)
        unsigned long tmp;
        int seg, bus;
        acpi_handle dummy_handle;
+       struct pci_bus *pci_bus;
 
        /* if the bridge doesn't have _STA, we assume it is always there */
        status = acpi_get_handle(handle, "_STA", &dummy_handle);
@@ -653,18 +455,22 @@ static int add_bridge(acpi_handle handle)
                bus = 0;
        }
 
+       pci_bus = pci_find_bus(seg, bus);
+       if (!pci_bus) {
+               err("Can't find bus %04x:%02x\n", seg, bus);
+               return 0;
+       }
+
        /* check if this bridge has ejectable slots */
        if (detect_ejectable_slots(handle) > 0) {
                dbg("found PCI host-bus bridge with hot-pluggable slots\n");
-               add_host_bridge(handle, seg, bus);
+               add_host_bridge(handle, pci_bus);
                return 0;
        }
 
-       tmp = seg << 8 | bus;
-
        /* search P2P bridges under this host bridge */
        status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
-                                    find_p2p_bridge, &tmp, NULL);
+                                    find_p2p_bridge, pci_bus, NULL);
 
        if (ACPI_FAILURE(status))
                warn("find_p2p_bridge faied (error code = 0x%x)\n",status);
@@ -672,12 +478,205 @@ static int add_bridge(acpi_handle handle)
        return 0;
 }
 
+static struct acpiphp_bridge *acpiphp_handle_to_bridge(acpi_handle handle)
+{
+       struct list_head *head;
+       list_for_each(head, &bridge_list) {
+               struct acpiphp_bridge *bridge = list_entry(head,
+                                               struct acpiphp_bridge, list);
+               if (bridge->handle == handle)
+                       return bridge;
+       }
+
+       return NULL;
+}
+
+static void cleanup_bridge(struct acpiphp_bridge *bridge)
+{
+       struct list_head *list, *tmp;
+       struct acpiphp_slot *slot;
+       acpi_status status;
+       acpi_handle handle = bridge->handle;
+
+       status = acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
+                                           handle_hotplug_event_bridge);
+       if (ACPI_FAILURE(status))
+               err("failed to remove notify handler\n");
+
+       slot = bridge->slots;
+       while (slot) {
+               struct acpiphp_slot *next = slot->next;
+               list_for_each_safe (list, tmp, &slot->funcs) {
+                       struct acpiphp_func *func;
+                       func = list_entry(list, struct acpiphp_func, sibling);
+                       status = acpi_remove_notify_handler(func->handle,
+                                               ACPI_SYSTEM_NOTIFY,
+                                               handle_hotplug_event_func);
+                       if (ACPI_FAILURE(status))
+                               err("failed to remove notify handler\n");
+                       pci_dev_put(func->pci_dev);
+                       list_del(list);
+                       kfree(func);
+               }
+               kfree(slot);
+               slot = next;
+       }
+
+       pci_dev_put(bridge->pci_dev);
+       list_del(&bridge->list);
+       kfree(bridge);
+}
+
+static acpi_status
+cleanup_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv)
+{
+       struct acpiphp_bridge *bridge;
+
+       if (!(bridge = acpiphp_handle_to_bridge(handle)))
+               return AE_OK;
+       cleanup_bridge(bridge);
+       return AE_OK;
+}
 
 static void remove_bridge(acpi_handle handle)
 {
-       /* No-op for now .. */
+       struct acpiphp_bridge *bridge;
+
+       bridge = acpiphp_handle_to_bridge(handle);
+       if (bridge) {
+               cleanup_bridge(bridge);
+       } else {
+               /* clean-up p2p bridges under this host bridge */
+               acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
+                               (u32)1, cleanup_p2p_bridge, NULL, NULL);
+       }
+}
+
+static struct pci_dev * get_apic_pci_info(acpi_handle handle)
+{
+       struct acpi_pci_id id;
+       struct pci_bus *bus;
+       struct pci_dev *dev;
+
+       if (ACPI_FAILURE(acpi_get_pci_id(handle, &id)))
+               return NULL;
+
+       bus = pci_find_bus(id.segment, id.bus);
+       if (!bus)
+               return NULL;
+
+       dev = pci_get_slot(bus, PCI_DEVFN(id.device, id.function));
+       if (!dev)
+               return NULL;
+
+       if ((dev->class != PCI_CLASS_SYSTEM_PIC_IOAPIC) &&
+           (dev->class != PCI_CLASS_SYSTEM_PIC_IOXAPIC))
+       {
+               pci_dev_put(dev);
+               return NULL;
+       }
+
+       return dev;
+}
+
+static int get_gsi_base(acpi_handle handle, u32 *gsi_base)
+{
+       acpi_status status;
+       int result = -1;
+       unsigned long gsb;
+       struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+       union acpi_object *obj;
+       void *table;
+
+       status = acpi_evaluate_integer(handle, "_GSB", NULL, &gsb);
+       if (ACPI_SUCCESS(status)) {
+               *gsi_base = (u32)gsb;
+               return 0;
+       }
+
+       status = acpi_evaluate_object(handle, "_MAT", NULL, &buffer);
+       if (ACPI_FAILURE(status) || !buffer.length || !buffer.pointer)
+               return -1;
+
+       obj = buffer.pointer;
+       if (obj->type != ACPI_TYPE_BUFFER)
+               goto out;
+
+       table = obj->buffer.pointer;
+       switch (((acpi_table_entry_header *)table)->type) {
+       case ACPI_MADT_IOSAPIC:
+               *gsi_base = ((struct acpi_table_iosapic *)table)->global_irq_base;
+               result = 0;
+               break;
+       case ACPI_MADT_IOAPIC:
+               *gsi_base = ((struct acpi_table_ioapic *)table)->global_irq_base;
+               result = 0;
+               break;
+       default:
+               break;
+       }
+ out:
+       acpi_os_free(buffer.pointer);
+       return result;
+}
+
+static acpi_status
+ioapic_add(acpi_handle handle, u32 lvl, void *context, void **rv)
+{
+       acpi_status status;
+       unsigned long sta;
+       acpi_handle tmp;
+       struct pci_dev *pdev;
+       u32 gsi_base;
+       u64 phys_addr;
+
+       /* Evaluate _STA if present */
+       status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
+       if (ACPI_SUCCESS(status) && sta != ACPI_STA_ALL)
+               return AE_CTRL_DEPTH;
+
+       /* Scan only PCI bus scope */
+       status = acpi_get_handle(handle, "_HID", &tmp);
+       if (ACPI_SUCCESS(status))
+               return AE_CTRL_DEPTH;
+
+       if (get_gsi_base(handle, &gsi_base))
+               return AE_OK;
+
+       pdev = get_apic_pci_info(handle);
+       if (!pdev)
+               return AE_OK;
+
+       if (pci_enable_device(pdev)) {
+               pci_dev_put(pdev);
+               return AE_OK;
+       }
+
+       pci_set_master(pdev);
+
+       if (pci_request_region(pdev, 0, "I/O APIC(acpiphp)")) {
+               pci_disable_device(pdev);
+               pci_dev_put(pdev);
+               return AE_OK;
+       }
+
+       phys_addr = pci_resource_start(pdev, 0);
+       if (acpi_register_ioapic(handle, phys_addr, gsi_base)) {
+               pci_release_region(pdev, 0);
+               pci_disable_device(pdev);
+               pci_dev_put(pdev);
+               return AE_OK;
+       }
+
+       return AE_OK;
 }
 
+static int acpiphp_configure_ioapics(acpi_handle handle)
+{
+       acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
+                           ACPI_UINT32_MAX, ioapic_add, NULL, NULL);
+       return 0;
+}
 
 static int power_on_slot(struct acpiphp_slot *slot)
 {
@@ -719,8 +718,6 @@ static int power_off_slot(struct acpiphp_slot *slot)
        acpi_status status;
        struct acpiphp_func *func;
        struct list_head *l;
-       struct acpi_object_list arg_list;
-       union acpi_object arg;
 
        int retval = 0;
 
@@ -731,7 +728,7 @@ static int power_off_slot(struct acpiphp_slot *slot)
        list_for_each (l, &slot->funcs) {
                func = list_entry(l, struct acpiphp_func, sibling);
 
-               if (func->pci_dev && (func->flags & FUNC_HAS_PS3)) {
+               if (func->flags & FUNC_HAS_PS3) {
                        status = acpi_evaluate_object(func->handle, "_PS3", NULL, NULL);
                        if (ACPI_FAILURE(status)) {
                                warn("%s: _PS3 failed\n", __FUNCTION__);
@@ -742,27 +739,6 @@ static int power_off_slot(struct acpiphp_slot *slot)
                }
        }
 
-       list_for_each (l, &slot->funcs) {
-               func = list_entry(l, struct acpiphp_func, sibling);
-
-               /* We don't want to call _EJ0 on non-existing functions. */
-               if (func->pci_dev && (func->flags & FUNC_HAS_EJ0)) {
-                       /* _EJ0 method take one argument */
-                       arg_list.count = 1;
-                       arg_list.pointer = &arg;
-                       arg.type = ACPI_TYPE_INTEGER;
-                       arg.integer.value = 1;
-
-                       status = acpi_evaluate_object(func->handle, "_EJ0", &arg_list, NULL);
-                       if (ACPI_FAILURE(status)) {
-                               warn("%s: _EJ0 failed\n", __FUNCTION__);
-                               retval = -1;
-                               goto err_exit;
-                       } else
-                               break;
-               }
-       }
-
        /* TBD: evaluate _STA to check if the slot is disabled */
 
        slot->flags &= (~SLOT_POWEREDON);
@@ -782,70 +758,56 @@ static int power_off_slot(struct acpiphp_slot *slot)
  */
 static int enable_device(struct acpiphp_slot *slot)
 {
-       u8 bus;
        struct pci_dev *dev;
-       struct pci_bus *child;
+       struct pci_bus *bus = slot->bridge->pci_bus;
        struct list_head *l;
        struct acpiphp_func *func;
        int retval = 0;
-       int num;
+       int num, max, pass;
 
        if (slot->flags & SLOT_ENABLED)
                goto err_exit;
 
        /* sanity check: dev should be NULL when hot-plugged in */
-       dev = pci_find_slot(slot->bridge->bus, PCI_DEVFN(slot->device, 0));
+       dev = pci_get_slot(bus, PCI_DEVFN(slot->device, 0));
        if (dev) {
                /* This case shouldn't happen */
                err("pci_dev structure already exists.\n");
+               pci_dev_put(dev);
                retval = -1;
                goto err_exit;
        }
 
-       /* allocate resources to device */
-       retval = acpiphp_configure_slot(slot);
-       if (retval)
-               goto err_exit;
-
-       /* returned `dev' is the *first function* only! */
-       num = pci_scan_slot(slot->bridge->pci_bus, PCI_DEVFN(slot->device, 0));
-       if (num)
-               pci_bus_add_devices(slot->bridge->pci_bus);
-       dev = pci_find_slot(slot->bridge->bus, PCI_DEVFN(slot->device, 0));
-
-       if (!dev) {
+       num = pci_scan_slot(bus, PCI_DEVFN(slot->device, 0));
+       if (num == 0) {
                err("No new device found\n");
                retval = -1;
                goto err_exit;
        }
 
-       if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
-               pci_read_config_byte(dev, PCI_SECONDARY_BUS, &bus);
-               child = (struct pci_bus*) pci_add_new_bus(dev->bus, dev, bus);
-               pci_do_scan_bus(child);
+       max = bus->secondary;
+       for (pass = 0; pass < 2; pass++) {
+               list_for_each_entry(dev, &bus->devices, bus_list) {
+                       if (PCI_SLOT(dev->devfn) != slot->device)
+                               continue;
+                       if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
+                           dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
+                               max = pci_scan_bridge(bus, dev, max, pass);
+               }
        }
 
+       pci_bus_assign_resources(bus);
+       pci_bus_add_devices(bus);
+
        /* associate pci_dev to our representation */
        list_for_each (l, &slot->funcs) {
                func = list_entry(l, struct acpiphp_func, sibling);
-
-               func->pci_dev = pci_find_slot(slot->bridge->bus,
-                                             PCI_DEVFN(slot->device,
+               func->pci_dev = pci_get_slot(bus, PCI_DEVFN(slot->device,
                                                        func->function));
-               if (!func->pci_dev)
-                       continue;
-
-               /* configure device */
-               retval = acpiphp_configure_function(func);
-               if (retval)
-                       goto err_exit;
        }
 
        slot->flags |= SLOT_ENABLED;
 
-       dbg("Available resources:\n");
-       acpiphp_dump_resource(slot->bridge);
-
  err_exit:
        return retval;
 }
@@ -866,9 +828,12 @@ static int disable_device(struct acpiphp_slot *slot)
 
        list_for_each (l, &slot->funcs) {
                func = list_entry(l, struct acpiphp_func, sibling);
+               if (!func->pci_dev)
+                       continue;
 
-               if (func->pci_dev)
-                       acpiphp_unconfigure_function(func);
+               pci_remove_bus_device(func->pci_dev);
+               pci_dev_put(func->pci_dev);
+               func->pci_dev = NULL;
        }
 
        slot->flags &= (~SLOT_ENABLED);
@@ -919,6 +884,39 @@ static unsigned int get_slot_status(struct acpiphp_slot *slot)
        return (unsigned int)sta;
 }
 
+/**
+ * acpiphp_eject_slot - physically eject the slot
+ */
+static int acpiphp_eject_slot(struct acpiphp_slot *slot)
+{
+       acpi_status status;
+       struct acpiphp_func *func;
+       struct list_head *l;
+       struct acpi_object_list arg_list;
+       union acpi_object arg;
+
+       list_for_each (l, &slot->funcs) {
+               func = list_entry(l, struct acpiphp_func, sibling);
+
+               /* We don't want to call _EJ0 on non-existing functions. */
+               if ((func->flags & FUNC_HAS_EJ0)) {
+                       /* _EJ0 method take one argument */
+                       arg_list.count = 1;
+                       arg_list.pointer = &arg;
+                       arg.type = ACPI_TYPE_INTEGER;
+                       arg.integer.value = 1;
+
+                       status = acpi_evaluate_object(func->handle, "_EJ0", &arg_list, NULL);
+                       if (ACPI_FAILURE(status)) {
+                               warn("%s: _EJ0 failed\n", __FUNCTION__);
+                               return -1;
+                       } else
+                               break;
+               }
+       }
+       return 0;
+}
+
 /**
  * acpiphp_check_bridge - re-enumerate devices
  *
@@ -942,6 +940,8 @@ static int acpiphp_check_bridge(struct acpiphp_bridge *bridge)
                        if (retval) {
                                err("Error occurred in disabling\n");
                                goto err_exit;
+                       } else {
+                               acpiphp_eject_slot(slot);
                        }
                        disabled++;
                } else {
@@ -962,6 +962,144 @@ static int acpiphp_check_bridge(struct acpiphp_bridge *bridge)
        return retval;
 }
 
+static void program_hpp(struct pci_dev *dev, struct acpiphp_bridge *bridge)
+{
+       u16 pci_cmd, pci_bctl;
+       struct pci_dev *cdev;
+
+       /* Program hpp values for this device */
+       if (!(dev->hdr_type == PCI_HEADER_TYPE_NORMAL ||
+                       (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE &&
+                       (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI)))
+               return;
+       pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE,
+                       bridge->hpp.cache_line_size);
+       pci_write_config_byte(dev, PCI_LATENCY_TIMER,
+                       bridge->hpp.latency_timer);
+       pci_read_config_word(dev, PCI_COMMAND, &pci_cmd);
+       if (bridge->hpp.enable_SERR)
+               pci_cmd |= PCI_COMMAND_SERR;
+       else
+               pci_cmd &= ~PCI_COMMAND_SERR;
+       if (bridge->hpp.enable_PERR)
+               pci_cmd |= PCI_COMMAND_PARITY;
+       else
+               pci_cmd &= ~PCI_COMMAND_PARITY;
+       pci_write_config_word(dev, PCI_COMMAND, pci_cmd);
+
+       /* Program bridge control value and child devices */
+       if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
+               pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER,
+                               bridge->hpp.latency_timer);
+               pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl);
+               if (bridge->hpp.enable_SERR)
+                       pci_bctl |= PCI_BRIDGE_CTL_SERR;
+               else
+                       pci_bctl &= ~PCI_BRIDGE_CTL_SERR;
+               if (bridge->hpp.enable_PERR)
+                       pci_bctl |= PCI_BRIDGE_CTL_PARITY;
+               else
+                       pci_bctl &= ~PCI_BRIDGE_CTL_PARITY;
+               pci_write_config_word(dev, PCI_BRIDGE_CONTROL, pci_bctl);
+               if (dev->subordinate) {
+                       list_for_each_entry(cdev, &dev->subordinate->devices,
+                                       bus_list)
+                               program_hpp(cdev, bridge);
+               }
+       }
+}
+
+static void acpiphp_set_hpp_values(acpi_handle handle, struct pci_bus *bus)
+{
+       struct acpiphp_bridge bridge;
+       struct pci_dev *dev;
+
+       memset(&bridge, 0, sizeof(bridge));
+       bridge.handle = handle;
+       decode_hpp(&bridge);
+       list_for_each_entry(dev, &bus->devices, bus_list)
+               program_hpp(dev, &bridge);
+
+}
+
+/*
+ * Remove devices for which we could not assign resources, call
+ * arch specific code to fix-up the bus
+ */
+static void acpiphp_sanitize_bus(struct pci_bus *bus)
+{
+       struct pci_dev *dev;
+       int i;
+       unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM;
+
+       list_for_each_entry(dev, &bus->devices, bus_list) {
+               for (i=0; i<PCI_BRIDGE_RESOURCES; i++) {
+                       struct resource *res = &dev->resource[i];
+                       if ((res->flags & type_mask) && !res->start &&
+                                       res->end) {
+                               /* Could not assign a required resources
+                                * for this device, remove it */
+                               pci_remove_bus_device(dev);
+                               break;
+                       }
+               }
+       }
+}
+
+/* Program resources in newly inserted bridge */
+static int acpiphp_configure_bridge (acpi_handle handle)
+{
+       struct acpi_pci_id pci_id;
+       struct pci_bus *bus;
+
+       if (ACPI_FAILURE(acpi_get_pci_id(handle, &pci_id))) {
+               err("cannot get PCI domain and bus number for bridge\n");
+               return -EINVAL;
+       }
+       bus = pci_find_bus(pci_id.segment, pci_id.bus);
+       if (!bus) {
+               err("cannot find bus %d:%d\n",
+                               pci_id.segment, pci_id.bus);
+               return -EINVAL;
+       }
+
+       pci_bus_size_bridges(bus);
+       pci_bus_assign_resources(bus);
+       acpiphp_sanitize_bus(bus);
+       acpiphp_set_hpp_values(handle, bus);
+       pci_enable_bridges(bus);
+       acpiphp_configure_ioapics(handle);
+       return 0;
+}
+
+static void handle_bridge_insertion(acpi_handle handle, u32 type)
+{
+       struct acpi_device *device, *pdevice;
+       acpi_handle phandle;
+
+       if ((type != ACPI_NOTIFY_BUS_CHECK) &&
+                       (type != ACPI_NOTIFY_DEVICE_CHECK)) {
+               err("unexpected notification type %d\n", type);
+               return;
+       }
+
+       acpi_get_parent(handle, &phandle);
+       if (acpi_bus_get_device(phandle, &pdevice)) {
+               dbg("no parent device, assuming NULL\n");
+               pdevice = NULL;
+       }
+       if (acpi_bus_add(&device, pdevice, handle, ACPI_BUS_TYPE_DEVICE)) {
+               err("cannot add bridge to acpi list\n");
+               return;
+       }
+       if (!acpiphp_configure_bridge(handle) &&
+               !acpi_bus_start(device))
+               add_bridge(handle);
+       else
+               err("cannot configure and start bridge\n");
+
+}
+
 /*
  * ACPI event handlers
  */
@@ -982,8 +1120,19 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont
        char objname[64];
        struct acpi_buffer buffer = { .length = sizeof(objname),
                                      .pointer = objname };
+       struct acpi_device *device;
 
-       bridge = (struct acpiphp_bridge *)context;
+       if (acpi_bus_get_device(handle, &device)) {
+               /* This bridge must have just been physically inserted */
+               handle_bridge_insertion(handle, type);
+               return;
+       }
+
+       bridge = acpiphp_handle_to_bridge(handle);
+       if (!bridge) {
+               err("cannot get bridge info\n");
+               return;
+       }
 
        acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
 
@@ -1031,7 +1180,6 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont
        }
 }
 
-
 /**
  * handle_hotplug_event_func - handle ACPI event on functions (i.e. slots)
  *
@@ -1074,7 +1222,8 @@ static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *contex
        case ACPI_NOTIFY_EJECT_REQUEST:
                /* request device eject */
                dbg("%s: Device eject notify on %s\n", __FUNCTION__, objname);
-               acpiphp_disable_slot(func->slot);
+               if (!(acpiphp_disable_slot(func->slot)))
+                       acpiphp_eject_slot(func->slot);
                break;
 
        default:
@@ -1083,6 +1232,47 @@ static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *contex
        }
 }
 
+static int is_root_bridge(acpi_handle handle)
+{
+       acpi_status status;
+       struct acpi_device_info *info;
+       struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+       int i;
+
+       status = acpi_get_object_info(handle, &buffer);
+       if (ACPI_SUCCESS(status)) {
+               info = buffer.pointer;
+               if ((info->valid & ACPI_VALID_HID) &&
+                       !strcmp(PCI_ROOT_HID_STRING,
+                                       info->hardware_id.value)) {
+                       acpi_os_free(buffer.pointer);
+                       return 1;
+               }
+               if (info->valid & ACPI_VALID_CID) {
+                       for (i=0; i < info->compatibility_id.count; i++) {
+                               if (!strcmp(PCI_ROOT_HID_STRING,
+                                       info->compatibility_id.id[i].value)) {
+                                       acpi_os_free(buffer.pointer);
+                                       return 1;
+                               }
+                       }
+               }
+       }
+       return 0;
+}
+
+static acpi_status
+find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
+{
+       int *count = (int *)context;
+
+       if (is_root_bridge(handle)) {
+               acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
+                               handle_hotplug_event_bridge, NULL);
+                       (*count)++;
+       }
+       return AE_OK ;
+}
 
 static struct acpi_pci_driver acpi_pci_hp_driver = {
        .add =          add_bridge,
@@ -1095,15 +1285,15 @@ static struct acpi_pci_driver acpi_pci_hp_driver = {
  */
 int __init acpiphp_glue_init(void)
 {
-       int num;
-
-       if (list_empty(&pci_root_buses))
-               return -1;
+       int num = 0;
 
-       num = acpi_pci_register_driver(&acpi_pci_hp_driver);
+       acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+                       ACPI_UINT32_MAX, find_root_bridges, &num, NULL);
 
        if (num <= 0)
                return -1;
+       else
+               acpi_pci_register_driver(&acpi_pci_hp_driver);
 
        return 0;
 }
@@ -1116,46 +1306,6 @@ int __init acpiphp_glue_init(void)
  */
 void __exit acpiphp_glue_exit(void)
 {
-       struct list_head *l1, *l2, *n1, *n2;
-       struct acpiphp_bridge *bridge;
-       struct acpiphp_slot *slot, *next;
-       struct acpiphp_func *func;
-       acpi_status status;
-
-       list_for_each_safe (l1, n1, &bridge_list) {
-               bridge = (struct acpiphp_bridge *)l1;
-               slot = bridge->slots;
-               while (slot) {
-                       next = slot->next;
-                       list_for_each_safe (l2, n2, &slot->funcs) {
-                               func = list_entry(l2, struct acpiphp_func, sibling);
-                               acpiphp_free_resource(&func->io_head);
-                               acpiphp_free_resource(&func->mem_head);
-                               acpiphp_free_resource(&func->p_mem_head);
-                               acpiphp_free_resource(&func->bus_head);
-                               status = acpi_remove_notify_handler(func->handle,
-                                                                   ACPI_SYSTEM_NOTIFY,
-                                                                   handle_hotplug_event_func);
-                               if (ACPI_FAILURE(status))
-                                       err("failed to remove notify handler\n");
-                               kfree(func);
-                       }
-                       kfree(slot);
-                       slot = next;
-               }
-               status = acpi_remove_notify_handler(bridge->handle, ACPI_SYSTEM_NOTIFY,
-                                                   handle_hotplug_event_bridge);
-               if (ACPI_FAILURE(status))
-                       err("failed to remove notify handler\n");
-
-               acpiphp_free_resource(&bridge->io_head);
-               acpiphp_free_resource(&bridge->mem_head);
-               acpiphp_free_resource(&bridge->p_mem_head);
-               acpiphp_free_resource(&bridge->bus_head);
-
-               kfree(bridge);
-       }
-
        acpi_pci_unregister_driver(&acpi_pci_hp_driver);
 }
 
@@ -1173,11 +1323,14 @@ int __init acpiphp_get_num_slots(void)
 
        list_for_each (node, &bridge_list) {
                bridge = (struct acpiphp_bridge *)node;
-               dbg("Bus%d %dslot(s)\n", bridge->bus, bridge->nr_slots);
+               dbg("Bus %04x:%02x has %d slot%s\n",
+                               pci_domain_nr(bridge->pci_bus),
+                               bridge->pci_bus->number, bridge->nr_slots,
+                               bridge->nr_slots == 1 ? "" : "s");
                num_slots += bridge->nr_slots;
        }
 
-       dbg("Total %dslots\n", num_slots);
+       dbg("Total %d slots\n", num_slots);
        return num_slots;
 }
 
@@ -1254,7 +1407,6 @@ int acpiphp_enable_slot(struct acpiphp_slot *slot)
        return retval;
 }
 
-
 /**
  * acpiphp_disable_slot - power off slot
  */
@@ -1274,13 +1426,6 @@ int acpiphp_disable_slot(struct acpiphp_slot *slot)
        if (retval)
                goto err_exit;
 
-       acpiphp_resource_sort_and_combine(&slot->bridge->io_head);
-       acpiphp_resource_sort_and_combine(&slot->bridge->mem_head);
-       acpiphp_resource_sort_and_combine(&slot->bridge->p_mem_head);
-       acpiphp_resource_sort_and_combine(&slot->bridge->bus_head);
-       dbg("Available resources:\n");
-       acpiphp_dump_resource(slot->bridge);
-
  err_exit:
        up(&slot->crit_sect);
        return retval;
@@ -1293,11 +1438,7 @@ int acpiphp_disable_slot(struct acpiphp_slot *slot)
  */
 u8 acpiphp_get_power_status(struct acpiphp_slot *slot)
 {
-       unsigned int sta;
-
-       sta = get_slot_status(slot);
-
-       return (sta & ACPI_STA_ENABLED) ? 1 : 0;
+       return (slot->flags & SLOT_POWEREDON);
 }
 
 
@@ -1335,9 +1476,10 @@ u8 acpiphp_get_adapter_status(struct acpiphp_slot *slot)
 u32 acpiphp_get_address(struct acpiphp_slot *slot)
 {
        u32 address;
+       struct pci_bus *pci_bus = slot->bridge->pci_bus;
 
-       address = ((slot->bridge->seg) << 16) |
-                 ((slot->bridge->bus) << 8) |
+       address = (pci_domain_nr(pci_bus) << 16) |
+                 (pci_bus->number << 8) |
                  slot->device;
 
        return address;
diff --git a/drivers/pci/hotplug/acpiphp_pci.c b/drivers/pci/hotplug/acpiphp_pci.c
deleted file mode 100644 (file)
index 54d97c9..0000000
+++ /dev/null
@@ -1,449 +0,0 @@
-/*
- * ACPI PCI HotPlug PCI configuration space management
- *
- * Copyright (C) 1995,2001 Compaq Computer Corporation
- * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
- * Copyright (C) 2001,2002 IBM Corp.
- * Copyright (C) 2002 Takayoshi Kochi (t-kochi@bq.jp.nec.com)
- * Copyright (C) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com)
- * Copyright (C) 2002 NEC Corporation
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to <t-kochi@bq.jp.nec.com>
- *
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/acpi.h>
-#include "../pci.h"
-#include "pci_hotplug.h"
-#include "acpiphp.h"
-
-#define MY_NAME "acpiphp_pci"
-
-
-/* allocate mem/pmem/io resource to a new function */
-static int init_config_space (struct acpiphp_func *func)
-{
-       u32 bar, len;
-       u32 address[] = {
-               PCI_BASE_ADDRESS_0,
-               PCI_BASE_ADDRESS_1,
-               PCI_BASE_ADDRESS_2,
-               PCI_BASE_ADDRESS_3,
-               PCI_BASE_ADDRESS_4,
-               PCI_BASE_ADDRESS_5,
-               0
-       };
-       int count;
-       struct acpiphp_bridge *bridge;
-       struct pci_resource *res;
-       struct pci_bus *pbus;
-       int bus, device, function;
-       unsigned int devfn;
-       u16 tmp;
-
-       bridge = func->slot->bridge;
-       pbus = bridge->pci_bus;
-       bus = bridge->bus;
-       device = func->slot->device;
-       function = func->function;
-       devfn = PCI_DEVFN(device, function);
-
-       for (count = 0; address[count]; count++) {      /* for 6 BARs */
-               pci_bus_write_config_dword(pbus, devfn,
-                                          address[count], 0xFFFFFFFF);
-               pci_bus_read_config_dword(pbus, devfn, address[count], &bar);
-
-               if (!bar)       /* This BAR is not implemented */
-                       continue;
-
-               dbg("Device %02x.%02x BAR %d wants %x\n", device, function, count, bar);
-
-               if (bar & PCI_BASE_ADDRESS_SPACE_IO) {
-                       /* This is IO */
-
-                       len = bar & (PCI_BASE_ADDRESS_IO_MASK & 0xFFFF);
-                       len = len & ~(len - 1);
-
-                       dbg("len in IO %x, BAR %d\n", len, count);
-
-                       spin_lock(&bridge->res_lock);
-                       res = acpiphp_get_io_resource(&bridge->io_head, len);
-                       spin_unlock(&bridge->res_lock);
-
-                       if (!res) {
-                               err("cannot allocate requested io for %02x:%02x.%d len %x\n",
-                                   bus, device, function, len);
-                               return -1;
-                       }
-                       pci_bus_write_config_dword(pbus, devfn,
-                                                  address[count],
-                                                  (u32)res->base);
-                       res->next = func->io_head;
-                       func->io_head = res;
-
-               } else {
-                       /* This is Memory */
-                       if (bar & PCI_BASE_ADDRESS_MEM_PREFETCH) {
-                               /* pfmem */
-
-                               len = bar & 0xFFFFFFF0;
-                               len = ~len + 1;
-
-                               dbg("len in PFMEM %x, BAR %d\n", len, count);
-
-                               spin_lock(&bridge->res_lock);
-                               res = acpiphp_get_resource(&bridge->p_mem_head, len);
-                               spin_unlock(&bridge->res_lock);
-
-                               if (!res) {
-                                       err("cannot allocate requested pfmem for %02x:%02x.%d len %x\n",
-                                           bus, device, function, len);
-                                       return -1;
-                               }
-
-                               pci_bus_write_config_dword(pbus, devfn,
-                                                          address[count],
-                                                          (u32)res->base);
-
-                               if (bar & PCI_BASE_ADDRESS_MEM_TYPE_64) {       /* takes up another dword */
-                                       dbg("inside the pfmem 64 case, count %d\n", count);
-                                       count += 1;
-                                       pci_bus_write_config_dword(pbus, devfn,
-                                                                  address[count],
-                                                                  (u32)(res->base >> 32));
-                               }
-
-                               res->next = func->p_mem_head;
-                               func->p_mem_head = res;
-
-                       } else {
-                               /* regular memory */
-
-                               len = bar & 0xFFFFFFF0;
-                               len = ~len + 1;
-
-                               dbg("len in MEM %x, BAR %d\n", len, count);
-
-                               spin_lock(&bridge->res_lock);
-                               res = acpiphp_get_resource(&bridge->mem_head, len);
-                               spin_unlock(&bridge->res_lock);
-
-                               if (!res) {
-                                       err("cannot allocate requested pfmem for %02x:%02x.%d len %x\n",
-                                           bus, device, function, len);
-                                       return -1;
-                               }
-
-                               pci_bus_write_config_dword(pbus, devfn,
-                                                          address[count],
-                                                          (u32)res->base);
-
-                               if (bar & PCI_BASE_ADDRESS_MEM_TYPE_64) {
-                                       /* takes up another dword */
-                                       dbg("inside mem 64 case, reg. mem, count %d\n", count);
-                                       count += 1;
-                                       pci_bus_write_config_dword(pbus, devfn,
-                                                                  address[count],
-                                                                  (u32)(res->base >> 32));
-                               }
-
-                               res->next = func->mem_head;
-                               func->mem_head = res;
-
-                       }
-               }
-       }
-
-       /* disable expansion rom */
-       pci_bus_write_config_dword(pbus, devfn, PCI_ROM_ADDRESS, 0x00000000);
-
-       /* set PCI parameters from _HPP */
-       pci_bus_write_config_byte(pbus, devfn, PCI_CACHE_LINE_SIZE,
-                                 bridge->hpp.cache_line_size);
-       pci_bus_write_config_byte(pbus, devfn, PCI_LATENCY_TIMER,
-                                 bridge->hpp.latency_timer);
-
-       pci_bus_read_config_word(pbus, devfn, PCI_COMMAND, &tmp);
-       if (bridge->hpp.enable_SERR)
-               tmp |= PCI_COMMAND_SERR;
-       if (bridge->hpp.enable_PERR)
-               tmp |= PCI_COMMAND_PARITY;
-       pci_bus_write_config_word(pbus, devfn, PCI_COMMAND, tmp);
-
-       return 0;
-}
-
-/* detect_used_resource - subtract resource under dev from bridge */
-static int detect_used_resource (struct acpiphp_bridge *bridge, struct pci_dev *dev)
-{
-       int count;
-
-       dbg("Device %s\n", pci_name(dev));
-
-       for (count = 0; count < DEVICE_COUNT_RESOURCE; count++) {
-               struct pci_resource *res;
-               struct pci_resource **head;
-               unsigned long base = dev->resource[count].start;
-               unsigned long len = dev->resource[count].end - base + 1;
-               unsigned long flags = dev->resource[count].flags;
-
-               if (!flags)
-                       continue;
-
-               dbg("BAR[%d] 0x%lx - 0x%lx (0x%lx)\n", count, base,
-                               base + len - 1, flags);
-
-               if (flags & IORESOURCE_IO) {
-                       head = &bridge->io_head;
-               } else if (flags & IORESOURCE_PREFETCH) {
-                       head = &bridge->p_mem_head;
-               } else {
-                       head = &bridge->mem_head;
-               }
-
-               spin_lock(&bridge->res_lock);
-               res = acpiphp_get_resource_with_base(head, base, len);
-               spin_unlock(&bridge->res_lock);
-               if (res)
-                       kfree(res);
-       }
-
-       return 0;
-}
-
-
-/**
- * acpiphp_detect_pci_resource - detect resources under bridge
- * @bridge: detect all resources already used under this bridge
- *
- * collect all resources already allocated for all devices under a bridge.
- */
-int acpiphp_detect_pci_resource (struct acpiphp_bridge *bridge)
-{
-       struct list_head *l;
-       struct pci_dev *dev;
-
-       list_for_each (l, &bridge->pci_bus->devices) {
-               dev = pci_dev_b(l);
-               detect_used_resource(bridge, dev);
-       }
-
-       return 0;
-}
-
-
-/**
- * acpiphp_init_slot_resource - gather resource usage information of a slot
- * @slot: ACPI slot object to be checked, should have valid pci_dev member
- *
- * TBD: PCI-to-PCI bridge case
- *      use pci_dev->resource[]
- */
-int acpiphp_init_func_resource (struct acpiphp_func *func)
-{
-       u64 base;
-       u32 bar, len;
-       u32 address[] = {
-               PCI_BASE_ADDRESS_0,
-               PCI_BASE_ADDRESS_1,
-               PCI_BASE_ADDRESS_2,
-               PCI_BASE_ADDRESS_3,
-               PCI_BASE_ADDRESS_4,
-               PCI_BASE_ADDRESS_5,
-               0
-       };
-       int count;
-       struct pci_resource *res;
-       struct pci_dev *dev;
-
-       dev = func->pci_dev;
-       dbg("Hot-pluggable device %s\n", pci_name(dev));
-
-       for (count = 0; address[count]; count++) {      /* for 6 BARs */
-               pci_read_config_dword(dev, address[count], &bar);
-
-               if (!bar)       /* This BAR is not implemented */
-                       continue;
-
-               pci_write_config_dword(dev, address[count], 0xFFFFFFFF);
-               pci_read_config_dword(dev, address[count], &len);
-
-               if (len & PCI_BASE_ADDRESS_SPACE_IO) {
-                       /* This is IO */
-                       base = bar & 0xFFFFFFFC;
-                       len = len & (PCI_BASE_ADDRESS_IO_MASK & 0xFFFF);
-                       len = len & ~(len - 1);
-
-                       dbg("BAR[%d] %08x - %08x (IO)\n", count, (u32)base, (u32)base + len - 1);
-
-                       res = acpiphp_make_resource(base, len);
-                       if (!res)
-                               goto no_memory;
-
-                       res->next = func->io_head;
-                       func->io_head = res;
-
-               } else {
-                       /* This is Memory */
-                       base = bar & 0xFFFFFFF0;
-                       if (len & PCI_BASE_ADDRESS_MEM_PREFETCH) {
-                               /* pfmem */
-
-                               len &= 0xFFFFFFF0;
-                               len = ~len + 1;
-
-                               if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) {       /* takes up another dword */
-                                       dbg("prefetch mem 64\n");
-                                       count += 1;
-                               }
-                               dbg("BAR[%d] %08x - %08x (PMEM)\n", count, (u32)base, (u32)base + len - 1);
-                               res = acpiphp_make_resource(base, len);
-                               if (!res)
-                                       goto no_memory;
-
-                               res->next = func->p_mem_head;
-                               func->p_mem_head = res;
-
-                       } else {
-                               /* regular memory */
-
-                               len &= 0xFFFFFFF0;
-                               len = ~len + 1;
-
-                               if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) {
-                                       /* takes up another dword */
-                                       dbg("mem 64\n");
-                                       count += 1;
-                               }
-                               dbg("BAR[%d] %08x - %08x (MEM)\n", count, (u32)base, (u32)base + len - 1);
-                               res = acpiphp_make_resource(base, len);
-                               if (!res)
-                                       goto no_memory;
-
-                               res->next = func->mem_head;
-                               func->mem_head = res;
-
-                       }
-               }
-
-               pci_write_config_dword(dev, address[count], bar);
-       }
-#if 1
-       acpiphp_dump_func_resource(func);
-#endif
-
-       return 0;
-
- no_memory:
-       err("out of memory\n");
-       acpiphp_free_resource(&func->io_head);
-       acpiphp_free_resource(&func->mem_head);
-       acpiphp_free_resource(&func->p_mem_head);
-
-       return -1;
-}
-
-
-/**
- * acpiphp_configure_slot - allocate PCI resources
- * @slot: slot to be configured
- *
- * initializes a PCI functions on a device inserted
- * into the slot
- *
- */
-int acpiphp_configure_slot (struct acpiphp_slot *slot)
-{
-       struct acpiphp_func *func;
-       struct list_head *l;
-       u8 hdr;
-       u32 dvid;
-       int retval = 0;
-       int is_multi = 0;
-
-       pci_bus_read_config_byte(slot->bridge->pci_bus,
-                                PCI_DEVFN(slot->device, 0),
-                                PCI_HEADER_TYPE, &hdr);
-
-       if (hdr & 0x80)
-               is_multi = 1;
-
-       list_for_each (l, &slot->funcs) {
-               func = list_entry(l, struct acpiphp_func, sibling);
-               if (is_multi || func->function == 0) {
-                       pci_bus_read_config_dword(slot->bridge->pci_bus,
-                                                 PCI_DEVFN(slot->device,
-                                                           func->function),
-                                                 PCI_VENDOR_ID, &dvid);
-                       if (dvid != 0xffffffff) {
-                               retval = init_config_space(func);
-                               if (retval)
-                                       break;
-                       }
-               }
-       }
-
-       return retval;
-}
-
-/**
- * acpiphp_configure_function - configure PCI function
- * @func: function to be configured
- *
- * initializes a PCI functions on a device inserted
- * into the slot
- *
- */
-int acpiphp_configure_function (struct acpiphp_func *func)
-{
-       /* all handled by the pci core now */
-       return 0;
-}
-
-/**
- * acpiphp_unconfigure_function - unconfigure PCI function
- * @func: function to be unconfigured
- *
- */
-void acpiphp_unconfigure_function (struct acpiphp_func *func)
-{
-       struct acpiphp_bridge *bridge;
-
-       /* if pci_dev is NULL, ignore it */
-       if (!func->pci_dev)
-               return;
-
-       pci_remove_bus_device(func->pci_dev);
-
-       /* free all resources */
-       bridge = func->slot->bridge;
-
-       spin_lock(&bridge->res_lock);
-       acpiphp_move_resource(&func->io_head, &bridge->io_head);
-       acpiphp_move_resource(&func->mem_head, &bridge->mem_head);
-       acpiphp_move_resource(&func->p_mem_head, &bridge->p_mem_head);
-       acpiphp_move_resource(&func->bus_head, &bridge->bus_head);
-       spin_unlock(&bridge->res_lock);
-}
diff --git a/drivers/pci/hotplug/acpiphp_res.c b/drivers/pci/hotplug/acpiphp_res.c
deleted file mode 100644 (file)
index f54b1fa..0000000
+++ /dev/null
@@ -1,700 +0,0 @@
-/*
- * ACPI PCI HotPlug Utility functions
- *
- * Copyright (C) 1995,2001 Compaq Computer Corporation
- * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
- * Copyright (C) 2001 IBM Corp.
- * Copyright (C) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com)
- * Copyright (C) 2002 Takayoshi Kochi (t-kochi@bq.jp.nec.com)
- * Copyright (C) 2002 NEC Corporation
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to <gregkh@us.ibm.com>, <t-kochi@bq.jp.nec.com>
- *
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/proc_fs.h>
-#include <linux/sysctl.h>
-#include <linux/pci.h>
-#include <linux/smp.h>
-#include <linux/smp_lock.h>
-
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/timer.h>
-
-#include <linux/ioctl.h>
-#include <linux/fcntl.h>
-
-#include <linux/list.h>
-
-#include "pci_hotplug.h"
-#include "acpiphp.h"
-
-#define MY_NAME "acpiphp_res"
-
-
-/*
- * sort_by_size - sort nodes by their length, smallest first
- */
-static int sort_by_size(struct pci_resource **head)
-{
-       struct pci_resource *current_res;
-       struct pci_resource *next_res;
-       int out_of_order = 1;
-
-       if (!(*head))
-               return 1;
-
-       if (!((*head)->next))
-               return 0;
-
-       while (out_of_order) {
-               out_of_order = 0;
-
-               /* Special case for swapping list head */
-               if (((*head)->next) &&
-                   ((*head)->length > (*head)->next->length)) {
-                       out_of_order++;
-                       current_res = *head;
-                       *head = (*head)->next;
-                       current_res->next = (*head)->next;
-                       (*head)->next = current_res;
-               }
-
-               current_res = *head;
-
-               while (current_res->next && current_res->next->next) {
-                       if (current_res->next->length > current_res->next->next->length) {
-                               out_of_order++;
-                               next_res = current_res->next;
-                               current_res->next = current_res->next->next;
-                               current_res = current_res->next;
-                               next_res->next = current_res->next;
-                               current_res->next = next_res;
-                       } else
-                               current_res = current_res->next;
-               }
-       }  /* End of out_of_order loop */
-
-       return 0;
-}
-
-#if 0
-/*
- * sort_by_max_size - sort nodes by their length, largest first
- */
-static int sort_by_max_size(struct pci_resource **head)
-{
-       struct pci_resource *current_res;
-       struct pci_resource *next_res;
-       int out_of_order = 1;
-
-       if (!(*head))
-               return 1;
-
-       if (!((*head)->next))
-               return 0;
-
-       while (out_of_order) {
-               out_of_order = 0;
-
-               /* Special case for swapping list head */
-               if (((*head)->next) &&
-                   ((*head)->length < (*head)->next->length)) {
-                       out_of_order++;
-                       current_res = *head;
-                       *head = (*head)->next;
-                       current_res->next = (*head)->next;
-                       (*head)->next = current_res;
-               }
-
-               current_res = *head;
-
-               while (current_res->next && current_res->next->next) {
-                       if (current_res->next->length < current_res->next->next->length) {
-                               out_of_order++;
-                               next_res = current_res->next;
-                               current_res->next = current_res->next->next;
-                               current_res = current_res->next;
-                               next_res->next = current_res->next;
-                               current_res->next = next_res;
-                       } else
-                               current_res = current_res->next;
-               }
-       }  /* End of out_of_order loop */
-
-       return 0;
-}
-#endif
-
-/**
- * get_io_resource - get resource for I/O ports
- *
- * this function sorts the resource list by size and then
- * returns the first node of "size" length that is not in the
- * ISA aliasing window.  If it finds a node larger than "size"
- * it will split it up.
- *
- * size must be a power of two.
- *
- * difference from get_resource is handling of ISA aliasing space.
- *
- */
-struct pci_resource *acpiphp_get_io_resource (struct pci_resource **head, u32 size)
-{
-       struct pci_resource *prevnode;
-       struct pci_resource *node;
-       struct pci_resource *split_node;
-       u64 temp_qword;
-
-       if (!(*head))
-               return NULL;
-
-       if (acpiphp_resource_sort_and_combine(head))
-               return NULL;
-
-       if (sort_by_size(head))
-               return NULL;
-
-       for (node = *head; node; node = node->next) {
-               if (node->length < size)
-                       continue;
-
-               if (node->base & (size - 1)) {
-                       /* this one isn't base aligned properly
-                          so we'll make a new entry and split it up */
-                       temp_qword = (node->base | (size-1)) + 1;
-
-                       /* Short circuit if adjusted size is too small */
-                       if ((node->length - (temp_qword - node->base)) < size)
-                               continue;
-
-                       split_node = acpiphp_make_resource(node->base, temp_qword - node->base);
-
-                       if (!split_node)
-                               return NULL;
-
-                       node->base = temp_qword;
-                       node->length -= split_node->length;
-
-                       /* Put it in the list */
-                       split_node->next = node->next;
-                       node->next = split_node;
-               } /* End of non-aligned base */
-
-               /* Don't need to check if too small since we already did */
-               if (node->length > size) {
-                       /* this one is longer than we need
-                          so we'll make a new entry and split it up */
-                       split_node = acpiphp_make_resource(node->base + size, node->length - size);
-
-                       if (!split_node)
-                               return NULL;
-
-                       node->length = size;
-
-                       /* Put it in the list */
-                       split_node->next = node->next;
-                       node->next = split_node;
-               }  /* End of too big on top end */
-
-               /* For IO make sure it's not in the ISA aliasing space */
-               if ((node->base & 0x300L) && !(node->base & 0xfffff000))
-                       continue;
-
-               /* If we got here, then it is the right size
-                  Now take it out of the list */
-               if (*head == node) {
-                       *head = node->next;
-               } else {
-                       prevnode = *head;
-                       while (prevnode->next != node)
-                               prevnode = prevnode->next;
-
-                       prevnode->next = node->next;
-               }
-               node->next = NULL;
-               /* Stop looping */
-               break;
-       }
-
-       return node;
-}
-
-
-#if 0
-/**
- * get_max_resource - get the largest resource
- *
- * Gets the largest node that is at least "size" big from the
- * list pointed to by head.  It aligns the node on top and bottom
- * to "size" alignment before returning it.
- */
-static struct pci_resource *acpiphp_get_max_resource (struct pci_resource **head, u32 size)
-{
-       struct pci_resource *max;
-       struct pci_resource *temp;
-       struct pci_resource *split_node;
-       u64 temp_qword;
-
-       if (!(*head))
-               return NULL;
-
-       if (acpiphp_resource_sort_and_combine(head))
-               return NULL;
-
-       if (sort_by_max_size(head))
-               return NULL;
-
-       for (max = *head;max; max = max->next) {
-
-               /* If not big enough we could probably just bail,
-                  instead we'll continue to the next. */
-               if (max->length < size)
-                       continue;
-
-               if (max->base & (size - 1)) {
-                       /* this one isn't base aligned properly
-                          so we'll make a new entry and split it up */
-                       temp_qword = (max->base | (size-1)) + 1;
-
-                       /* Short circuit if adjusted size is too small */
-                       if ((max->length - (temp_qword - max->base)) < size)
-                               continue;
-
-                       split_node = acpiphp_make_resource(max->base, temp_qword - max->base);
-
-                       if (!split_node)
-                               return NULL;
-
-                       max->base = temp_qword;
-                       max->length -= split_node->length;
-
-                       /* Put it next in the list */
-                       split_node->next = max->next;
-                       max->next = split_node;
-               }
-
-               if ((max->base + max->length) & (size - 1)) {
-                       /* this one isn't end aligned properly at the top
-                          so we'll make a new entry and split it up */
-                       temp_qword = ((max->base + max->length) & ~(size - 1));
-
-                       split_node = acpiphp_make_resource(temp_qword,
-                                                          max->length + max->base - temp_qword);
-
-                       if (!split_node)
-                               return NULL;
-
-                       max->length -= split_node->length;
-
-                       /* Put it in the list */
-                       split_node->next = max->next;
-                       max->next = split_node;
-               }
-
-               /* Make sure it didn't shrink too much when we aligned it */
-               if (max->length < size)
-                       continue;
-
-               /* Now take it out of the list */
-               temp = (struct pci_resource*) *head;
-               if (temp == max) {
-                       *head = max->next;
-               } else {
-                       while (temp && temp->next != max) {
-                               temp = temp->next;
-                       }
-
-                       temp->next = max->next;
-               }
-
-               max->next = NULL;
-               return max;
-       }
-
-       /* If we get here, we couldn't find one */
-       return NULL;
-}
-#endif
-
-/**
- * get_resource - get resource (mem, pfmem)
- *
- * this function sorts the resource list by size and then
- * returns the first node of "size" length.  If it finds a node
- * larger than "size" it will split it up.
- *
- * size must be a power of two.
- *
- */
-struct pci_resource *acpiphp_get_resource (struct pci_resource **head, u32 size)
-{
-       struct pci_resource *prevnode;
-       struct pci_resource *node;
-       struct pci_resource *split_node;
-       u64 temp_qword;
-
-       if (!(*head))
-               return NULL;
-
-       if (acpiphp_resource_sort_and_combine(head))
-               return NULL;
-
-       if (sort_by_size(head))
-               return NULL;
-
-       for (node = *head; node; node = node->next) {
-               dbg("%s: req_size =%x node=%p, base=%x, length=%x\n",
-                   __FUNCTION__, size, node, (u32)node->base, node->length);
-               if (node->length < size)
-                       continue;
-
-               if (node->base & (size - 1)) {
-                       dbg("%s: not aligned\n", __FUNCTION__);
-                       /* this one isn't base aligned properly
-                          so we'll make a new entry and split it up */
-                       temp_qword = (node->base | (size-1)) + 1;
-
-                       /* Short circuit if adjusted size is too small */
-                       if ((node->length - (temp_qword - node->base)) < size)
-                               continue;
-
-                       split_node = acpiphp_make_resource(node->base, temp_qword - node->base);
-
-                       if (!split_node)
-                               return NULL;
-
-                       node->base = temp_qword;
-                       node->length -= split_node->length;
-
-                       /* Put it in the list */
-                       split_node->next = node->next;
-                       node->next = split_node;
-               } /* End of non-aligned base */
-
-               /* Don't need to check if too small since we already did */
-               if (node->length > size) {
-                       dbg("%s: too big\n", __FUNCTION__);
-                       /* this one is longer than we need
-                          so we'll make a new entry and split it up */
-                       split_node = acpiphp_make_resource(node->base + size, node->length - size);
-
-                       if (!split_node)
-                               return NULL;
-
-                       node->length = size;
-
-                       /* Put it in the list */
-                       split_node->next = node->next;
-                       node->next = split_node;
-               }  /* End of too big on top end */
-
-               dbg("%s: got one!!!\n", __FUNCTION__);
-               /* If we got here, then it is the right size
-                  Now take it out of the list */
-               if (*head == node) {
-                       *head = node->next;
-               } else {
-                       prevnode = *head;
-                       while (prevnode->next != node)
-                               prevnode = prevnode->next;
-
-                       prevnode->next = node->next;
-               }
-               node->next = NULL;
-               /* Stop looping */
-               break;
-       }
-       return node;
-}
-
-/**
- * get_resource_with_base - get resource with specific base address
- *
- * this function
- * returns the first node of "size" length located at specified base address.
- * If it finds a node larger than "size" it will split it up.
- *
- * size must be a power of two.
- *
- */
-struct pci_resource *acpiphp_get_resource_with_base (struct pci_resource **head, u64 base, u32 size)
-{
-       struct pci_resource *prevnode;
-       struct pci_resource *node;
-       struct pci_resource *split_node;
-       u64 temp_qword;
-
-       if (!(*head))
-               return NULL;
-
-       if (acpiphp_resource_sort_and_combine(head))
-               return NULL;
-
-       for (node = *head; node; node = node->next) {
-               dbg(": 1st req_base=%x req_size =%x node=%p, base=%x, length=%x\n",
-                   (u32)base, size, node, (u32)node->base, node->length);
-               if (node->base > base)
-                       continue;
-
-               if ((node->base + node->length) < (base + size))
-                       continue;
-
-               if (node->base < base) {
-                       dbg(": split 1\n");
-                       /* this one isn't base aligned properly
-                          so we'll make a new entry and split it up */
-                       temp_qword = base;
-
-                       /* Short circuit if adjusted size is too small */
-                       if ((node->length - (temp_qword - node->base)) < size)
-                               continue;
-
-                       split_node = acpiphp_make_resource(node->base, temp_qword - node->base);
-
-                       if (!split_node)
-                               return NULL;
-
-                       node->base = temp_qword;
-                       node->length -= split_node->length;
-
-                       /* Put it in the list */
-                       split_node->next = node->next;
-                       node->next = split_node;
-               }
-
-               dbg(": 2nd req_base=%x req_size =%x node=%p, base=%x, length=%x\n",
-                   (u32)base, size, node, (u32)node->base, node->length);
-
-               /* Don't need to check if too small since we already did */
-               if (node->length > size) {
-                       dbg(": split 2\n");
-                       /* this one is longer than we need
-                          so we'll make a new entry and split it up */
-                       split_node = acpiphp_make_resource(node->base + size, node->length - size);
-
-                       if (!split_node)
-                               return NULL;
-
-                       node->length = size;
-
-                       /* Put it in the list */
-                       split_node->next = node->next;
-                       node->next = split_node;
-               }  /* End of too big on top end */
-
-               dbg(": got one!!!\n");
-               /* If we got here, then it is the right size
-                  Now take it out of the list */
-               if (*head == node) {
-                       *head = node->next;
-               } else {
-                       prevnode = *head;
-                       while (prevnode->next != node)
-                               prevnode = prevnode->next;
-
-                       prevnode->next = node->next;
-               }
-               node->next = NULL;
-               /* Stop looping */
-               break;
-       }
-       return node;
-}
-
-
-/**
- * acpiphp_resource_sort_and_combine
- *
- * Sorts all of the nodes in the list in ascending order by
- * their base addresses.  Also does garbage collection by
- * combining adjacent nodes.
- *
- * returns 0 if success
- */
-int acpiphp_resource_sort_and_combine (struct pci_resource **head)
-{
-       struct pci_resource *node1;
-       struct pci_resource *node2;
-       int out_of_order = 1;
-
-       if (!(*head))
-               return 1;
-
-       dbg("*head->next = %p\n",(*head)->next);
-
-       if (!(*head)->next)
-               return 0;       /* only one item on the list, already sorted! */
-
-       dbg("*head->base = 0x%x\n",(u32)(*head)->base);
-       dbg("*head->next->base = 0x%x\n", (u32)(*head)->next->base);
-       while (out_of_order) {
-               out_of_order = 0;
-
-               /* Special case for swapping list head */
-               if (((*head)->next) &&
-                   ((*head)->base > (*head)->next->base)) {
-                       node1 = *head;
-                       (*head) = (*head)->next;
-                       node1->next = (*head)->next;
-                       (*head)->next = node1;
-                       out_of_order++;
-               }
-
-               node1 = (*head);
-
-               while (node1->next && node1->next->next) {
-                       if (node1->next->base > node1->next->next->base) {
-                               out_of_order++;
-                               node2 = node1->next;
-                               node1->next = node1->next->next;
-                               node1 = node1->next;
-                               node2->next = node1->next;
-                               node1->next = node2;
-                       } else
-                               node1 = node1->next;
-               }
-       }  /* End of out_of_order loop */
-
-       node1 = *head;
-
-       while (node1 && node1->next) {
-               if ((node1->base + node1->length) == node1->next->base) {
-                       /* Combine */
-                       dbg("8..\n");
-                       node1->length += node1->next->length;
-                       node2 = node1->next;
-                       node1->next = node1->next->next;
-                       kfree(node2);
-               } else
-                       node1 = node1->next;
-       }
-
-       return 0;
-}
-
-
-/**
- * acpiphp_make_resource - make resource structure
- * @base: base address of a resource
- * @length: length of a resource
- */
-struct pci_resource *acpiphp_make_resource (u64 base, u32 length)
-{
-       struct pci_resource *res;
-
-       res = kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
-       if (res) {
-               memset(res, 0, sizeof(struct pci_resource));
-               res->base = base;
-               res->length = length;
-       }
-
-       return res;
-}
-
-
-/**
- * acpiphp_move_resource - move linked resources from one to another
- * @from: head of linked resource list
- * @to: head of linked resource list
- */
-void acpiphp_move_resource (struct pci_resource **from, struct pci_resource **to)
-{
-       struct pci_resource *tmp;
-
-       while (*from) {
-               tmp = (*from)->next;
-               (*from)->next = *to;
-               *to = *from;
-               *from = tmp;
-       }
-
-       /* *from = NULL is guaranteed */
-}
-
-
-/**
- * acpiphp_free_resource - free all linked resources
- * @res: head of linked resource list
- */
-void acpiphp_free_resource (struct pci_resource **res)
-{
-       struct pci_resource *tmp;
-
-       while (*res) {
-               tmp = (*res)->next;
-               kfree(*res);
-               *res = tmp;
-       }
-
-       /* *res = NULL is guaranteed */
-}
-
-
-/* debug support functions;  will go away sometime :) */
-static void dump_resource(struct pci_resource *head)
-{
-       struct pci_resource *p;
-       int cnt;
-
-       p = head;
-       cnt = 0;
-
-       while (p) {
-               dbg("[%02d] %08x - %08x\n",
-                   cnt++, (u32)p->base, (u32)p->base + p->length - 1);
-               p = p->next;
-       }
-}
-
-void acpiphp_dump_resource(struct acpiphp_bridge *bridge)
-{
-       dbg("I/O resource:\n");
-       dump_resource(bridge->io_head);
-       dbg("MEM resource:\n");
-       dump_resource(bridge->mem_head);
-       dbg("PMEM resource:\n");
-       dump_resource(bridge->p_mem_head);
-       dbg("BUS resource:\n");
-       dump_resource(bridge->bus_head);
-}
-
-void acpiphp_dump_func_resource(struct acpiphp_func *func)
-{
-       dbg("I/O resource:\n");
-       dump_resource(func->io_head);
-       dbg("MEM resource:\n");
-       dump_resource(func->mem_head);
-       dbg("PMEM resource:\n");
-       dump_resource(func->p_mem_head);
-       dbg("BUS resource:\n");
-       dump_resource(func->bus_head);
-}
index afbccfa..8c6d398 100644 (file)
@@ -60,6 +60,7 @@ static void __iomem *smbios_start;
 static void __iomem *cpqhp_rom_start;
 static int power_mode;
 static int debug;
+static int initialized;
 
 #define DRIVER_VERSION "0.9.8"
 #define DRIVER_AUTHOR  "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>"
@@ -1271,7 +1272,6 @@ static int one_time_init(void)
 {
        int loop;
        int retval = 0;
-       static int initialized = 0;
 
        if (initialized)
                return 0;
@@ -1441,7 +1441,8 @@ static void __exit unload_cpqphpd(void)
        }
 
        // Stop the notification mechanism
-       cpqhp_event_stop_thread();
+       if (initialized)
+               cpqhp_event_stop_thread();
 
        //unmap the rom address
        if (cpqhp_rom_start)
index 30206ac..b5ab9aa 100644 (file)
@@ -28,10 +28,10 @@ static struct msi_desc* msi_desc[NR_IRQS] = { [0 ... NR_IRQS-1] = NULL };
 static kmem_cache_t* msi_cachep;
 
 static int pci_msi_enable = 1;
-static int last_alloc_vector = 0;
-static int nr_released_vectors = 0;
+static int last_alloc_vector;
+static int nr_released_vectors;
 static int nr_reserved_vectors = NR_HP_RESERVED_VECTORS;
-static int nr_msix_devices = 0;
+static int nr_msix_devices;
 
 #ifndef CONFIG_X86_IO_APIC
 int vector_irq[NR_VECTORS] = { [0 ... NR_VECTORS - 1] = -1};
@@ -170,44 +170,30 @@ static unsigned int startup_msi_irq_wo_maskbit(unsigned int vector)
        return 0;       /* never anything pending */
 }
 
-static void release_msi(unsigned int vector);
-static void shutdown_msi_irq(unsigned int vector)
-{
-       release_msi(vector);
-}
-
-#define shutdown_msi_irq_wo_maskbit    shutdown_msi_irq
-static void enable_msi_irq_wo_maskbit(unsigned int vector) {}
-static void disable_msi_irq_wo_maskbit(unsigned int vector) {}
-static void ack_msi_irq_wo_maskbit(unsigned int vector) {}
-static void end_msi_irq_wo_maskbit(unsigned int vector)
+static unsigned int startup_msi_irq_w_maskbit(unsigned int vector)
 {
-       move_msi(vector);
-       ack_APIC_irq();
+       startup_msi_irq_wo_maskbit(vector);
+       unmask_MSI_irq(vector);
+       return 0;       /* never anything pending */
 }
 
-static unsigned int startup_msi_irq_w_maskbit(unsigned int vector)
+static void shutdown_msi_irq(unsigned int vector)
 {
        struct msi_desc *entry;
        unsigned long flags;
 
        spin_lock_irqsave(&msi_lock, flags);
        entry = msi_desc[vector];
-       if (!entry || !entry->dev) {
-               spin_unlock_irqrestore(&msi_lock, flags);
-               return 0;
-       }
-       entry->msi_attrib.state = 1;    /* Mark it active */
+       if (entry && entry->dev)
+               entry->msi_attrib.state = 0;    /* Mark it not active */
        spin_unlock_irqrestore(&msi_lock, flags);
-
-       unmask_MSI_irq(vector);
-       return 0;       /* never anything pending */
 }
 
-#define shutdown_msi_irq_w_maskbit     shutdown_msi_irq
-#define enable_msi_irq_w_maskbit       unmask_MSI_irq
-#define disable_msi_irq_w_maskbit      mask_MSI_irq
-#define ack_msi_irq_w_maskbit          mask_MSI_irq
+static void end_msi_irq_wo_maskbit(unsigned int vector)
+{
+       move_msi(vector);
+       ack_APIC_irq();
+}
 
 static void end_msi_irq_w_maskbit(unsigned int vector)
 {
@@ -216,6 +202,10 @@ static void end_msi_irq_w_maskbit(unsigned int vector)
        ack_APIC_irq();
 }
 
+static void do_nothing(unsigned int vector)
+{
+}
+
 /*
  * Interrupt Type for MSI-X PCI/PCI-X/PCI-Express Devices,
  * which implement the MSI-X Capability Structure.
@@ -223,10 +213,10 @@ static void end_msi_irq_w_maskbit(unsigned int vector)
 static struct hw_interrupt_type msix_irq_type = {
        .typename       = "PCI-MSI-X",
        .startup        = startup_msi_irq_w_maskbit,
-       .shutdown       = shutdown_msi_irq_w_maskbit,
-       .enable         = enable_msi_irq_w_maskbit,
-       .disable        = disable_msi_irq_w_maskbit,
-       .ack            = ack_msi_irq_w_maskbit,
+       .shutdown       = shutdown_msi_irq,
+       .enable         = unmask_MSI_irq,
+       .disable        = mask_MSI_irq,
+       .ack            = mask_MSI_irq,
        .end            = end_msi_irq_w_maskbit,
        .set_affinity   = set_msi_irq_affinity
 };
@@ -239,10 +229,10 @@ static struct hw_interrupt_type msix_irq_type = {
 static struct hw_interrupt_type msi_irq_w_maskbit_type = {
        .typename       = "PCI-MSI",
        .startup        = startup_msi_irq_w_maskbit,
-       .shutdown       = shutdown_msi_irq_w_maskbit,
-       .enable         = enable_msi_irq_w_maskbit,
-       .disable        = disable_msi_irq_w_maskbit,
-       .ack            = ack_msi_irq_w_maskbit,
+       .shutdown       = shutdown_msi_irq,
+       .enable         = unmask_MSI_irq,
+       .disable        = mask_MSI_irq,
+       .ack            = mask_MSI_irq,
        .end            = end_msi_irq_w_maskbit,
        .set_affinity   = set_msi_irq_affinity
 };
@@ -255,10 +245,10 @@ static struct hw_interrupt_type msi_irq_w_maskbit_type = {
 static struct hw_interrupt_type msi_irq_wo_maskbit_type = {
        .typename       = "PCI-MSI",
        .startup        = startup_msi_irq_wo_maskbit,
-       .shutdown       = shutdown_msi_irq_wo_maskbit,
-       .enable         = enable_msi_irq_wo_maskbit,
-       .disable        = disable_msi_irq_wo_maskbit,
-       .ack            = ack_msi_irq_wo_maskbit,
+       .shutdown       = shutdown_msi_irq,
+       .enable         = do_nothing,
+       .disable        = do_nothing,
+       .ack            = do_nothing,
        .end            = end_msi_irq_wo_maskbit,
        .set_affinity   = set_msi_irq_affinity
 };
@@ -407,7 +397,7 @@ static struct msi_desc* alloc_msi_entry(void)
 {
        struct msi_desc *entry;
 
-       entry = (struct msi_desc*) kmem_cache_alloc(msi_cachep, SLAB_KERNEL);
+       entry = kmem_cache_alloc(msi_cachep, SLAB_KERNEL);
        if (!entry)
                return NULL;
 
@@ -796,18 +786,6 @@ void pci_disable_msi(struct pci_dev* dev)
        }
 }
 
-static void release_msi(unsigned int vector)
-{
-       struct msi_desc *entry;
-       unsigned long flags;
-
-       spin_lock_irqsave(&msi_lock, flags);
-       entry = msi_desc[vector];
-       if (entry && entry->dev)
-               entry->msi_attrib.state = 0;    /* Mark it not active */
-       spin_unlock_irqrestore(&msi_lock, flags);
-}
-
 static int msi_free_vector(struct pci_dev* dev, int vector, int reassign)
 {
        struct msi_desc *entry;
@@ -924,7 +902,7 @@ static int reroute_msix_table(int head, struct msix_entry *entries, int *nvec)
 /**
  * pci_enable_msix - configure device's MSI-X capability structure
  * @dev: pointer to the pci_dev data structure of MSI-X device function
- * @data: pointer to an array of MSI-X entries
+ * @entries: pointer to an array of MSI-X entries
  * @nvec: number of MSI-X vectors requested for allocation by device driver
  *
  * Setup the MSI-X capability structure of device function with the number
index bef21ae..390f185 100644 (file)
@@ -41,11 +41,11 @@ static inline void move_msi(int vector) {}
 #define PCI_MSIX_FLAGS_BIRMASK         (7 << 0)
 #define PCI_MSIX_FLAGS_BITMASK         (1 << 0)
 
-#define PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET       0
-#define PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET       4
-#define PCI_MSIX_ENTRY_DATA_OFFSET             8
-#define PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET      12
 #define PCI_MSIX_ENTRY_SIZE                    16
+#define  PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET      0
+#define  PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET      4
+#define  PCI_MSIX_ENTRY_DATA_OFFSET            8
+#define  PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET     12
 
 #define msi_control_reg(base)          (base + PCI_MSI_FLAGS)
 #define msi_lower_address_reg(base)    (base + PCI_MSI_ADDRESS_LO)
@@ -64,7 +64,6 @@ static inline void move_msi(int vector) {}
 #define msi_enable(control, num) multi_msi_enable(control, num); \
        control |= PCI_MSI_FLAGS_ENABLE
 
-#define msix_control_reg               msi_control_reg
 #define msix_table_offset_reg(base)    (base + 0x04)
 #define msix_pba_offset_reg(base)      (base + 0x08)
 #define msix_enable(control)           control |= PCI_MSIX_FLAGS_ENABLE
index a15f940..cc9d653 100644 (file)
@@ -60,15 +60,18 @@ resource_show(struct device * dev, struct device_attribute *attr, char * buf)
        char * str = buf;
        int i;
        int max = 7;
+       u64 start, end;
 
        if (pci_dev->subordinate)
                max = DEVICE_COUNT_RESOURCE;
 
        for (i = 0; i < max; i++) {
-               str += sprintf(str,"0x%016lx 0x%016lx 0x%016lx\n",
-                              pci_resource_start(pci_dev,i),
-                              pci_resource_end(pci_dev,i),
-                              pci_resource_flags(pci_dev,i));
+               struct resource *res =  &pci_dev->resource[i];
+               pci_resource_to_user(pci_dev, i, res, &start, &end);
+               str += sprintf(str,"0x%016llx 0x%016llx 0x%016llx\n",
+                              (unsigned long long)start,
+                              (unsigned long long)end,
+                              (unsigned long long)res->flags);
        }
        return (str - buf);
 }
@@ -313,8 +316,21 @@ pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
                                                       struct device, kobj));
        struct resource *res = (struct resource *)attr->private;
        enum pci_mmap_state mmap_type;
+       u64 start, end;
+       int i;
 
-       vma->vm_pgoff += res->start >> PAGE_SHIFT;
+       for (i = 0; i < PCI_ROM_RESOURCE; i++)
+               if (res == &pdev->resource[i])
+                       break;
+       if (i >= PCI_ROM_RESOURCE)
+               return -ENODEV;
+
+       /* pci_mmap_page_range() expects the same kind of entry as coming
+        * from /proc/bus/pci/ which is a "user visible" value. If this is
+        * different from the resource itself, arch will do necessary fixup.
+        */
+       pci_resource_to_user(pdev, i, res, &start, &end);
+       vma->vm_pgoff += start >> PAGE_SHIFT;
        mmap_type = res->flags & IORESOURCE_MEM ? pci_mmap_mem : pci_mmap_io;
 
        return pci_mmap_page_range(pdev, vma, mmap_type, 0);
index fd48b20..6a0a82f 100644 (file)
@@ -374,8 +374,11 @@ struct pci_bus * __devinit pci_add_new_bus(struct pci_bus *parent, struct pci_de
        struct pci_bus *child;
 
        child = pci_alloc_child_bus(parent, dev, busnr);
-       if (child)
+       if (child) {
+               spin_lock(&pci_bus_lock);
                list_add_tail(&child->node, &parent->children);
+               spin_unlock(&pci_bus_lock);
+       }
        return child;
 }
 
@@ -411,7 +414,7 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max
 {
        struct pci_bus *child;
        int is_cardbus = (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS);
-       u32 buses;
+       u32 buses, i;
        u16 bctl;
 
        pci_read_config_dword(dev, PCI_PRIMARY_BUS, &buses);
@@ -447,7 +450,7 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max
                        return max;
                }
 
-               child = pci_alloc_child_bus(bus, dev, busnr);
+               child = pci_add_new_bus(bus, dev, busnr);
                if (!child)
                        return max;
                child->primary = buses & 0xFF;
@@ -470,7 +473,11 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max
                /* Clear errors */
                pci_write_config_word(dev, PCI_STATUS, 0xffff);
 
-               child = pci_alloc_child_bus(bus, dev, ++max);
+               /* Prevent assigning a bus number that already exists.
+                * This can happen when a bridge is hot-plugged */
+               if (pci_find_bus(pci_domain_nr(bus), max+1))
+                       return max;
+               child = pci_add_new_bus(bus, dev, ++max);
                buses = (buses & 0xff000000)
                      | ((unsigned int)(child->primary)     <<  0)
                      | ((unsigned int)(child->secondary)   <<  8)
@@ -501,7 +508,11 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max
                         * as cards with a PCI-to-PCI bridge can be
                         * inserted later.
                         */
-                       max += CARDBUS_RESERVE_BUSNR;
+                       for (i=0; i<CARDBUS_RESERVE_BUSNR; i++)
+                               if (pci_find_bus(pci_domain_nr(bus),
+                                                       max+i+1))
+                                       break;
+                       max += i;
                }
                /*
                 * Set the subordinate bus number to its real value.
@@ -757,7 +768,9 @@ pci_scan_single_device(struct pci_bus *bus, int devfn)
         * and the bus list for fixup functions, etc.
         */
        INIT_LIST_HEAD(&dev->global_list);
+       spin_lock(&pci_bus_lock);
        list_add_tail(&dev->bus_list, &bus->devices);
+       spin_unlock(&pci_bus_lock);
 
        return dev;
 }
@@ -878,7 +891,9 @@ struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent, int bus,
                pr_debug("PCI: Bus %04x:%02x already known\n", pci_domain_nr(b), bus);
                goto err_out;
        }
+       spin_lock(&pci_bus_lock);
        list_add_tail(&b->node, &pci_root_buses);
+       spin_unlock(&pci_bus_lock);
 
        memset(dev, 0, sizeof(*dev));
        dev->parent = parent;
@@ -911,8 +926,6 @@ struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent, int bus,
 
        b->subordinate = pci_scan_child_bus(b);
 
-       pci_bus_add_devices(b);
-
        return b;
 
 sys_create_link_err:
@@ -922,7 +935,9 @@ class_dev_create_file_err:
 class_dev_reg_err:
        device_unregister(dev);
 dev_reg_err:
+       spin_lock(&pci_bus_lock);
        list_del(&b->node);
+       spin_unlock(&pci_bus_lock);
 err_out:
        kfree(dev);
        kfree(b);
index e68bbfb..7988fc8 100644 (file)
@@ -355,14 +355,20 @@ static int show_device(struct seq_file *m, void *v)
                        dev->device,
                        dev->irq);
        /* Here should be 7 and not PCI_NUM_RESOURCES as we need to preserve compatibility */
-       for(i=0; i<7; i++)
+       for (i=0; i<7; i++) {
+               u64 start, end;
+               pci_resource_to_user(dev, i, &dev->resource[i], &start, &end);
                seq_printf(m, LONG_FORMAT,
-                       dev->resource[i].start |
+                       ((unsigned long)start) |
                        (dev->resource[i].flags & PCI_REGION_FLAG_MASK));
-       for(i=0; i<7; i++)
+       }
+       for (i=0; i<7; i++) {
+               u64 start, end;
+               pci_resource_to_user(dev, i, &dev->resource[i], &start, &end);
                seq_printf(m, LONG_FORMAT,
                        dev->resource[i].start < dev->resource[i].end ?
-                       dev->resource[i].end - dev->resource[i].start + 1 : 0);
+                       (unsigned long)(end - start) + 1 : 0);
+       }
        seq_putc(m, '\t');
        if (drv)
                seq_printf(m, "%s", drv->name);
index 96f077f..27a294b 100644 (file)
@@ -18,17 +18,21 @@ static void pci_free_resources(struct pci_dev *dev)
 
 static void pci_destroy_dev(struct pci_dev *dev)
 {
-       pci_proc_detach_device(dev);
-       pci_remove_sysfs_dev_files(dev);
-       device_unregister(&dev->dev);
+       if (!list_empty(&dev->global_list)) {
+               pci_proc_detach_device(dev);
+               pci_remove_sysfs_dev_files(dev);
+               device_unregister(&dev->dev);
+               spin_lock(&pci_bus_lock);
+               list_del(&dev->global_list);
+               dev->global_list.next = dev->global_list.prev = NULL;
+               spin_unlock(&pci_bus_lock);
+       }
 
        /* Remove the device from the device lists, and prevent any further
         * list accesses from this device */
        spin_lock(&pci_bus_lock);
        list_del(&dev->bus_list);
-       list_del(&dev->global_list);
        dev->bus_list.next = dev->bus_list.prev = NULL;
-       dev->global_list.next = dev->global_list.prev = NULL;
        spin_unlock(&pci_bus_lock);
 
        pci_free_resources(dev);
index 1ba84be..6b628de 100644 (file)
@@ -72,7 +72,10 @@ pbus_assign_resources_sorted(struct pci_bus *bus)
        for (list = head.next; list;) {
                res = list->res;
                idx = res - &list->dev->resource[0];
-               pci_assign_resource(list->dev, idx);
+               if (pci_assign_resource(list->dev, idx)) {
+                       res->start = 0;
+                       res->flags = 0;
+               }
                tmp = list;
                list = list->next;
                kfree(tmp);
index 34dbc37..bc6e462 100644 (file)
@@ -1916,9 +1916,9 @@ static void __twa_shutdown(TW_Device_Extension *tw_dev)
 } /* End __twa_shutdown() */
 
 /* Wrapper for __twa_shutdown */
-static void twa_shutdown(struct device *dev)
+static void twa_shutdown(struct pci_dev *pdev)
 {
-       struct Scsi_Host *host = pci_get_drvdata(to_pci_dev(dev));
+       struct Scsi_Host *host = pci_get_drvdata(pdev);
        TW_Device_Extension *tw_dev = (TW_Device_Extension *)host->hostdata;
 
        __twa_shutdown(tw_dev);
@@ -2140,9 +2140,7 @@ static struct pci_driver twa_driver = {
        .id_table       = twa_pci_tbl,
        .probe          = twa_probe,
        .remove         = twa_remove,
-       .driver         = {
-               .shutdown = twa_shutdown
-       }
+       .shutdown       = twa_shutdown
 };
 
 /* This function is called on driver initialization */
index b6dc576..973c51f 100644 (file)
@@ -2264,9 +2264,9 @@ static void __tw_shutdown(TW_Device_Extension *tw_dev)
 } /* End __tw_shutdown() */
 
 /* Wrapper for __tw_shutdown */
-static void tw_shutdown(struct device *dev)
+static void tw_shutdown(struct pci_dev *pdev)
 {
-       struct Scsi_Host *host = pci_get_drvdata(to_pci_dev(dev));
+       struct Scsi_Host *host = pci_get_drvdata(pdev);
        TW_Device_Extension *tw_dev = (TW_Device_Extension *)host->hostdata;
 
        __tw_shutdown(tw_dev);
@@ -2451,9 +2451,7 @@ static struct pci_driver tw_driver = {
        .id_table       = tw_pci_tbl,
        .probe          = tw_probe,
        .remove         = tw_remove,
-       .driver         = {
-               .shutdown = tw_shutdown
-       }
+       .shutdown       = tw_shutdown,
 };
 
 /* This function is called on driver initialization */
index 80d0226..babd483 100644 (file)
@@ -6012,7 +6012,7 @@ static int __devinit ipr_probe(struct pci_dev *pdev,
 
 /**
  * ipr_shutdown - Shutdown handler.
- * @dev:       device struct
+ * @pdev:      pci device struct
  *
  * This function is invoked upon system shutdown/reboot. It will issue
  * an adapter shutdown to the adapter to flush the write cache.
@@ -6020,9 +6020,9 @@ static int __devinit ipr_probe(struct pci_dev *pdev,
  * Return value:
  *     none
  **/
-static void ipr_shutdown(struct device *dev)
+static void ipr_shutdown(struct pci_dev *pdev)
 {
-       struct ipr_ioa_cfg *ioa_cfg = pci_get_drvdata(to_pci_dev(dev));
+       struct ipr_ioa_cfg *ioa_cfg = pci_get_drvdata(pdev);
        unsigned long lock_flags = 0;
 
        spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
@@ -6068,9 +6068,7 @@ static struct pci_driver ipr_driver = {
        .id_table = ipr_pci_table,
        .probe = ipr_probe,
        .remove = ipr_remove,
-       .driver = {
-               .shutdown = ipr_shutdown,
-       },
+       .shutdown = ipr_shutdown,
 };
 
 /**
index ec81532..a70cdf3 100644 (file)
@@ -5036,9 +5036,9 @@ megaraid_remove_one(struct pci_dev *pdev)
 }
 
 static void
-megaraid_shutdown(struct device *dev)
+megaraid_shutdown(struct pci_dev *pdev)
 {
-       struct Scsi_Host *host = pci_get_drvdata(to_pci_dev(dev));
+       struct Scsi_Host *host = pci_get_drvdata(pdev);
        adapter_t *adapter = (adapter_t *)host->hostdata;
 
        __megaraid_shutdown(adapter);
@@ -5070,9 +5070,7 @@ static struct pci_driver megaraid_pci_driver = {
        .id_table       = megaraid_pci_tbl,
        .probe          = megaraid_probe_one,
        .remove         = __devexit_p(megaraid_remove_one),
-       .driver         = {
-               .shutdown = megaraid_shutdown,
-       },
+       .shutdown       = megaraid_shutdown,
 };
 
 static int __init megaraid_init(void)
index 621dee8..10506f9 100644 (file)
@@ -632,7 +632,7 @@ static void scsi_free_sgtable(struct scatterlist *sgl, int index)
 {
        struct scsi_host_sg_pool *sgp;
 
-       BUG_ON(index > SG_MEMPOOL_NR);
+       BUG_ON(index >= SG_MEMPOOL_NR);
 
        sgp = scsi_sg_pools + index;
        mempool_free(sgl, sgp->pool);
index 7afa222..06d7d43 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -58,6 +58,7 @@ static DEFINE_SPINLOCK(fput_lock);
 static LIST_HEAD(fput_head);
 
 static void aio_kick_handler(void *);
+static void aio_queue_work(struct kioctx *);
 
 /* aio_setup
  *     Creates the slab caches used by the aio routines, panic on
@@ -747,6 +748,14 @@ out:
                 * has already been kicked */
                if (kiocbIsKicked(iocb)) {
                        __queue_kicked_iocb(iocb);
+
+                       /*
+                        * __queue_kicked_iocb will always return 1 here, because
+                        * iocb->ki_run_list is empty at this point so it should
+                        * be safe to unconditionally queue the context into the
+                        * work queue.
+                        */
+                       aio_queue_work(ctx);
                }
        }
        return ret;
index 13e5938..561e63a 100644 (file)
@@ -278,7 +278,7 @@ EXPORT_SYMBOL(thaw_bdev);
  */
 static void do_sync(unsigned long wait)
 {
-       wakeup_bdflush(0);
+       wakeup_pdflush(0);
        sync_inodes(0);         /* All mappings, inodes and their blockdevs */
        DQUOT_SYNC(NULL);
        sync_supers();          /* Write the superblocks */
@@ -497,7 +497,7 @@ static void free_more_memory(void)
        struct zone **zones;
        pg_data_t *pgdat;
 
-       wakeup_bdflush(1024);
+       wakeup_pdflush(1024);
        yield();
 
        for_each_pgdat(pgdat) {
index e82aac9..a69a5d8 100644 (file)
@@ -150,7 +150,7 @@ __unregister_chrdev_region(unsigned major, unsigned baseminor, int minorct)
        struct char_device_struct *cd = NULL, **cp;
        int i = major_to_index(major);
 
-       up(&chrdevs_lock);
+       down(&chrdevs_lock);
        for (cp = &chrdevs[i]; *cp; cp = &(*cp)->next)
                if ((*cp)->major == major &&
                    (*cp)->baseminor == baseminor &&
index ccd632f..e463dca 100644 (file)
@@ -749,24 +749,24 @@ fail_access:
  *     to find a free region that is of my size and has not
  *     been reserved.
  *
- *     on succeed, it returns the reservation window to be appended to.
- *     failed, return NULL.
  */
-static struct ext3_reserve_window_node *find_next_reservable_window(
+static int find_next_reservable_window(
                                struct ext3_reserve_window_node *search_head,
-                               unsigned long size, int *start_block,
+                               struct ext3_reserve_window_node *my_rsv,
+                               struct super_block * sb, int start_block,
                                int last_block)
 {
        struct rb_node *next;
        struct ext3_reserve_window_node *rsv, *prev;
        int cur;
+       int size = my_rsv->rsv_goal_size;
 
        /* TODO: make the start of the reservation window byte-aligned */
        /* cur = *start_block & ~7;*/
-       cur = *start_block;
+       cur = start_block;
        rsv = search_head;
        if (!rsv)
-               return NULL;
+               return -1;
 
        while (1) {
                if (cur <= rsv->rsv_end)
@@ -782,11 +782,11 @@ static struct ext3_reserve_window_node *find_next_reservable_window(
                 * space with expected-size (or more)...
                 */
                if (cur > last_block)
-                       return NULL;            /* fail */
+                       return -1;              /* fail */
 
                prev = rsv;
                next = rb_next(&rsv->rsv_node);
-               rsv = list_entry(next, struct ext3_reserve_window_node, rsv_node);
+               rsv = list_entry(next,struct ext3_reserve_window_node,rsv_node);
 
                /*
                 * Reached the last reservation, we can just append to the
@@ -813,8 +813,25 @@ static struct ext3_reserve_window_node *find_next_reservable_window(
         * return the reservation window that we could append to.
         * succeed.
         */
-       *start_block = cur;
-       return prev;
+
+       if ((prev != my_rsv) && (!rsv_is_empty(&my_rsv->rsv_window)))
+               rsv_window_remove(sb, my_rsv);
+
+       /*
+        * Let's book the whole avaliable window for now.  We will check the
+        * disk bitmap later and then, if there are free blocks then we adjust
+        * the window size if it's larger than requested.
+        * Otherwise, we will remove this node from the tree next time
+        * call find_next_reservable_window.
+        */
+       my_rsv->rsv_start = cur;
+       my_rsv->rsv_end = cur + size - 1;
+       my_rsv->rsv_alloc_hit = 0;
+
+       if (prev != my_rsv)
+               ext3_rsv_window_add(sb, my_rsv);
+
+       return 0;
 }
 
 /**
@@ -852,6 +869,7 @@ static struct ext3_reserve_window_node *find_next_reservable_window(
  *     @sb: the super block
  *     @group: the group we are trying to allocate in
  *     @bitmap_bh: the block group block bitmap
+ *
  */
 static int alloc_new_reservation(struct ext3_reserve_window_node *my_rsv,
                int goal, struct super_block *sb,
@@ -860,10 +878,10 @@ static int alloc_new_reservation(struct ext3_reserve_window_node *my_rsv,
        struct ext3_reserve_window_node *search_head;
        int group_first_block, group_end_block, start_block;
        int first_free_block;
-       int reservable_space_start;
-       struct ext3_reserve_window_node *prev_rsv;
        struct rb_root *fs_rsv_root = &EXT3_SB(sb)->s_rsv_window_root;
        unsigned long size;
+       int ret;
+       spinlock_t *rsv_lock = &EXT3_SB(sb)->s_rsv_window_lock;
 
        group_first_block = le32_to_cpu(EXT3_SB(sb)->s_es->s_first_data_block) +
                                group * EXT3_BLOCKS_PER_GROUP(sb);
@@ -875,6 +893,7 @@ static int alloc_new_reservation(struct ext3_reserve_window_node *my_rsv,
                start_block = goal + group_first_block;
 
        size = my_rsv->rsv_goal_size;
+
        if (!rsv_is_empty(&my_rsv->rsv_window)) {
                /*
                 * if the old reservation is cross group boundary
@@ -908,6 +927,8 @@ static int alloc_new_reservation(struct ext3_reserve_window_node *my_rsv,
                        my_rsv->rsv_goal_size= size;
                }
        }
+
+       spin_lock(rsv_lock);
        /*
         * shift the search start to the window near the goal block
         */
@@ -921,11 +942,16 @@ static int alloc_new_reservation(struct ext3_reserve_window_node *my_rsv,
         * need to check the bitmap after we found a reservable window.
         */
 retry:
-       prev_rsv = find_next_reservable_window(search_head, size,
-                                               &start_block, group_end_block);
-       if (prev_rsv == NULL)
-               goto failed;
-       reservable_space_start = start_block;
+       ret = find_next_reservable_window(search_head, my_rsv, sb,
+                                               start_block, group_end_block);
+
+       if (ret == -1) {
+               if (!rsv_is_empty(&my_rsv->rsv_window))
+                       rsv_window_remove(sb, my_rsv);
+               spin_unlock(rsv_lock);
+               return -1;
+       }
+
        /*
         * On success, find_next_reservable_window() returns the
         * reservation window where there is a reservable space after it.
@@ -937,8 +963,9 @@ retry:
         * block. Search start from the start block of the reservable space
         * we just found.
         */
+       spin_unlock(rsv_lock);
        first_free_block = bitmap_search_next_usable_block(
-                       reservable_space_start - group_first_block,
+                       my_rsv->rsv_start - group_first_block,
                        bitmap_bh, group_end_block - group_first_block + 1);
 
        if (first_free_block < 0) {
@@ -946,54 +973,29 @@ retry:
                 * no free block left on the bitmap, no point
                 * to reserve the space. return failed.
                 */
-               goto failed;
+               spin_lock(rsv_lock);
+               if (!rsv_is_empty(&my_rsv->rsv_window))
+                       rsv_window_remove(sb, my_rsv);
+               spin_unlock(rsv_lock);
+               return -1;              /* failed */
        }
+
        start_block = first_free_block + group_first_block;
        /*
         * check if the first free block is within the
-        * free space we just found
+        * free space we just reserved
         */
-       if ((start_block >= reservable_space_start) &&
-         (start_block < reservable_space_start + size))
-               goto found_rsv_window;
+       if (start_block >= my_rsv->rsv_start && start_block < my_rsv->rsv_end)
+               return 0;               /* success */
        /*
         * if the first free bit we found is out of the reservable space
-        * this means there is no free block on the reservable space
-        * we should continue search for next reservable space,
+        * continue search for next reservable space,
         * start from where the free block is,
         * we also shift the list head to where we stopped last time
         */
-       search_head = prev_rsv;
+       search_head = my_rsv;
+       spin_lock(rsv_lock);
        goto retry;
-
-found_rsv_window:
-       /*
-        * great! the reservable space contains some free blocks.
-        * if the search returns that we should add the new
-        * window just next to where the old window, we don't
-        * need to remove the old window first then add it to the
-        * same place, just update the new start and new end.
-        */
-       if (my_rsv != prev_rsv)  {
-               if (!rsv_is_empty(&my_rsv->rsv_window))
-                       rsv_window_remove(sb, my_rsv);
-       }
-       my_rsv->rsv_start = reservable_space_start;
-       my_rsv->rsv_end = my_rsv->rsv_start + size - 1;
-       my_rsv->rsv_alloc_hit = 0;
-       if (my_rsv != prev_rsv)  {
-               ext3_rsv_window_add(sb, my_rsv);
-       }
-       return 0;               /* succeed */
-failed:
-       /*
-        * failed to find a new reservation window in the current
-        * group, remove the current(stale) reservation window
-        * if there is any
-        */
-       if (!rsv_is_empty(&my_rsv->rsv_window))
-               rsv_window_remove(sb, my_rsv);
-       return -1;              /* failed */
 }
 
 /*
@@ -1023,7 +1025,6 @@ ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle,
                        int goal, struct ext3_reserve_window_node * my_rsv,
                        int *errp)
 {
-       spinlock_t *rsv_lock;
        unsigned long group_first_block;
        int ret = 0;
        int fatal;
@@ -1052,7 +1053,6 @@ ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle,
                ret = ext3_try_to_allocate(sb, handle, group, bitmap_bh, goal, NULL);
                goto out;
        }
-       rsv_lock = &EXT3_SB(sb)->s_rsv_window_lock;
        /*
         * goal is a group relative block number (if there is a goal)
         * 0 < goal < EXT3_BLOCKS_PER_GROUP(sb)
@@ -1078,30 +1078,21 @@ ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle,
         * then we could go to allocate from the reservation window directly.
         */
        while (1) {
-               struct ext3_reserve_window rsv_copy;
-
-               rsv_copy._rsv_start = my_rsv->rsv_start;
-               rsv_copy._rsv_end = my_rsv->rsv_end;
-
-               if (rsv_is_empty(&rsv_copy) || (ret < 0) ||
-                       !goal_in_my_reservation(&rsv_copy, goal, group, sb)) {
-                       spin_lock(rsv_lock);
+               if (rsv_is_empty(&my_rsv->rsv_window) || (ret < 0) ||
+                       !goal_in_my_reservation(&my_rsv->rsv_window, goal, group, sb)) {
                        ret = alloc_new_reservation(my_rsv, goal, sb,
                                                        group, bitmap_bh);
-                       rsv_copy._rsv_start = my_rsv->rsv_start;
-                       rsv_copy._rsv_end = my_rsv->rsv_end;
-                       spin_unlock(rsv_lock);
                        if (ret < 0)
                                break;                  /* failed */
 
-                       if (!goal_in_my_reservation(&rsv_copy, goal, group, sb))
+                       if (!goal_in_my_reservation(&my_rsv->rsv_window, goal, group, sb))
                                goal = -1;
                }
-               if ((rsv_copy._rsv_start >= group_first_block + EXT3_BLOCKS_PER_GROUP(sb))
-                   || (rsv_copy._rsv_end < group_first_block))
+               if ((my_rsv->rsv_start >= group_first_block + EXT3_BLOCKS_PER_GROUP(sb))
+                   || (my_rsv->rsv_end < group_first_block))
                        BUG();
                ret = ext3_try_to_allocate(sb, handle, group, bitmap_bh, goal,
-                                          &rsv_copy);
+                                          &my_rsv->rsv_window);
                if (ret >= 0) {
                        my_rsv->rsv_alloc_hit++;
                        break;                          /* succeed */
index 5ad8cf0..98e7834 100644 (file)
@@ -36,7 +36,11 @@ static int ext3_release_file (struct inode * inode, struct file * filp)
        /* if we are the last writer on the inode, drop the block reservation */
        if ((filp->f_mode & FMODE_WRITE) &&
                        (atomic_read(&inode->i_writecount) == 1))
+       {
+               down(&EXT3_I(inode)->truncate_sem);
                ext3_discard_reservation(inode);
+               up(&EXT3_I(inode)->truncate_sem);
+       }
        if (is_dx(inode) && filp->private_data)
                ext3_htree_free_dir_info(filp->private_data);
 
index b4b3e8a..a6d1779 100644 (file)
@@ -944,7 +944,8 @@ clear_qf_name:
                                        "for remount\n");
                                return 0;
                        }
-                       match_int(&args[0], &option);
+                       if (match_int(&args[0], &option) != 0)
+                               return 0;
                        *n_blocks_count = option;
                        break;
                case Opt_nobh:
index ee3536f..1b7a3ef 100644 (file)
@@ -2,7 +2,7 @@
 #include <linux/nfs.h>
 #include <linux/nfs3.h>
 #include <linux/nfs_fs.h>
-#include <linux/xattr_acl.h>
+#include <linux/posix_acl_xattr.h>
 #include <linux/nfsacl.h>
 
 #define NFSDBG_FACILITY        NFSDBG_PROC
@@ -53,9 +53,9 @@ ssize_t nfs3_getxattr(struct dentry *dentry, const char *name,
        struct posix_acl *acl;
        int type, error = 0;
 
-       if (strcmp(name, XATTR_NAME_ACL_ACCESS) == 0)
+       if (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0)
                type = ACL_TYPE_ACCESS;
-       else if (strcmp(name, XATTR_NAME_ACL_DEFAULT) == 0)
+       else if (strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0)
                type = ACL_TYPE_DEFAULT;
        else
                return -EOPNOTSUPP;
@@ -82,9 +82,9 @@ int nfs3_setxattr(struct dentry *dentry, const char *name,
        struct posix_acl *acl;
        int type, error;
 
-       if (strcmp(name, XATTR_NAME_ACL_ACCESS) == 0)
+       if (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0)
                type = ACL_TYPE_ACCESS;
-       else if (strcmp(name, XATTR_NAME_ACL_DEFAULT) == 0)
+       else if (strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0)
                type = ACL_TYPE_DEFAULT;
        else
                return -EOPNOTSUPP;
@@ -103,9 +103,9 @@ int nfs3_removexattr(struct dentry *dentry, const char *name)
        struct inode *inode = dentry->d_inode;
        int type;
 
-       if (strcmp(name, XATTR_NAME_ACL_ACCESS) == 0)
+       if (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0)
                type = ACL_TYPE_ACCESS;
-       else if (strcmp(name, XATTR_NAME_ACL_DEFAULT) == 0)
+       else if (strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0)
                type = ACL_TYPE_DEFAULT;
        else
                return -EOPNOTSUPP;
index de340ff..be24ead 100644 (file)
 #include <linux/nfsd/nfsfh.h>
 #include <linux/quotaops.h>
 #include <linux/dnotify.h>
-#include <linux/xattr_acl.h>
 #include <linux/posix_acl.h>
-#ifdef CONFIG_NFSD_V4
 #include <linux/posix_acl_xattr.h>
+#ifdef CONFIG_NFSD_V4
 #include <linux/xattr.h>
 #include <linux/nfs4.h>
 #include <linux/nfs4_acl.h>
@@ -1872,10 +1871,10 @@ nfsd_get_posix_acl(struct svc_fh *fhp, int type)
                return ERR_PTR(-EOPNOTSUPP);
        switch(type) {
                case ACL_TYPE_ACCESS:
-                       name = XATTR_NAME_ACL_ACCESS;
+                       name = POSIX_ACL_XATTR_ACCESS;
                        break;
                case ACL_TYPE_DEFAULT:
-                       name = XATTR_NAME_ACL_DEFAULT;
+                       name = POSIX_ACL_XATTR_DEFAULT;
                        break;
                default:
                        return ERR_PTR(-EOPNOTSUPP);
@@ -1919,17 +1918,17 @@ nfsd_set_posix_acl(struct svc_fh *fhp, int type, struct posix_acl *acl)
                return -EOPNOTSUPP;
        switch(type) {
                case ACL_TYPE_ACCESS:
-                       name = XATTR_NAME_ACL_ACCESS;
+                       name = POSIX_ACL_XATTR_ACCESS;
                        break;
                case ACL_TYPE_DEFAULT:
-                       name = XATTR_NAME_ACL_DEFAULT;
+                       name = POSIX_ACL_XATTR_DEFAULT;
                        break;
                default:
                        return -EOPNOTSUPP;
        }
 
        if (acl && acl->a_count) {
-               size = xattr_acl_size(acl->a_count);
+               size = posix_acl_xattr_size(acl->a_count);
                value = kmalloc(size, GFP_KERNEL);
                if (!value)
                        return -ENOMEM;
index 3f6dc71..4673157 100644 (file)
@@ -159,7 +159,7 @@ udf_find_entry(struct inode *dir, struct dentry *dentry,
        char *nameptr;
        uint8_t lfi;
        uint16_t liu;
-       loff_t size = (udf_ext0_offset(dir) + dir->i_size) >> 2;
+       loff_t size;
        kernel_lb_addr bloc, eloc;
        uint32_t extoffset, elen, offset;
        struct buffer_head *bh = NULL;
@@ -167,6 +167,8 @@ udf_find_entry(struct inode *dir, struct dentry *dentry,
        if (!dir)
                return NULL;
 
+       size = (udf_ext0_offset(dir) + dir->i_size) >> 2;
+
        f_pos = (udf_ext0_offset(dir) >> 2);
 
        fibh->soffset = fibh->eoffset = (f_pos & ((dir->i_sb->s_blocksize - 1) >> 2)) << 2;
index c627bc4..9ad1424 100644 (file)
@@ -108,6 +108,21 @@ typedef int (*acpi_op_unbind)      (struct acpi_device *device);
 typedef int (*acpi_op_match)   (struct acpi_device *device,
                                 struct acpi_driver *driver);
 
+struct acpi_bus_ops {
+       u32                     acpi_op_add:1;
+       u32                     acpi_op_remove:1;
+       u32                     acpi_op_lock:1;
+       u32                     acpi_op_start:1;
+       u32                     acpi_op_stop:1;
+       u32                     acpi_op_suspend:1;
+       u32                     acpi_op_resume:1;
+       u32                     acpi_op_scan:1;
+       u32                     acpi_op_bind:1;
+       u32                     acpi_op_unbind:1;
+       u32                     acpi_op_match:1;
+       u32                     reserved:21;
+};
+
 struct acpi_device_ops {
        acpi_op_add             add;
        acpi_op_remove          remove;
@@ -327,9 +342,9 @@ int acpi_bus_generate_event (struct acpi_device *device, u8 type, int data);
 int acpi_bus_receive_event (struct acpi_bus_event *event);
 int acpi_bus_register_driver (struct acpi_driver *driver);
 int acpi_bus_unregister_driver (struct acpi_driver *driver);
-int acpi_bus_scan (struct acpi_device *start);
 int acpi_bus_add (struct acpi_device **child, struct acpi_device *parent,
                acpi_handle handle, int type);
+int acpi_bus_start (struct acpi_device *device);
 
 
 int acpi_match_ids (struct acpi_device *device, char   *ids);
index c62e92e..4ec722d 100644 (file)
@@ -68,6 +68,7 @@ void acpi_pci_irq_del_prt (int segment, int bus);
 
 struct pci_bus;
 
+acpi_status acpi_get_pci_id (acpi_handle handle, struct acpi_pci_id *id);
 int acpi_pci_bind (struct acpi_device *device);
 int acpi_pci_unbind (struct acpi_device *device);
 int acpi_pci_bind_root (struct acpi_device *device, struct acpi_pci_id *id, struct pci_bus *bus);
index 0c7b57b..b7806aa 100644 (file)
@@ -223,6 +223,25 @@ pci_dac_dma_sync_single_for_device(struct pci_dev *pdev, dma64_addr_t dma_addr,
        /* Nothing to do. */
 }
 
+#ifdef CONFIG_PCI
+static inline void pci_dma_burst_advice(struct pci_dev *pdev,
+                                       enum pci_dma_burst_strategy *strat,
+                                       unsigned long *strategy_parameter)
+{
+       unsigned long cacheline_size;
+       u8 byte;
+
+       pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &byte);
+       if (byte == 0)
+               cacheline_size = 1024;
+       else
+               cacheline_size = (int) byte * 4;
+
+       *strat = PCI_DMA_BURST_BOUNDARY;
+       *strategy_parameter = cacheline_size;
+}
+#endif
+
 /* TODO: integrate with include/asm-generic/pci.h ? */
 static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
 {
diff --git a/include/asm-arm/arch-s3c2410/audio.h b/include/asm-arm/arch-s3c2410/audio.h
new file mode 100644 (file)
index 0000000..0d276e6
--- /dev/null
@@ -0,0 +1,49 @@
+/* linux/include/asm-arm/arch-s3c2410/audio.h
+ *
+ * (c) 2004-2005 Simtec Electronics
+ *     http://www.simtec.co.uk/products/SWLINUX/
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C24XX - Audio platfrom_device info
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Changelog:
+ *     20-Nov-2004 BJD  Created file
+ *     07-Mar-2005 BJD  Added suspend/resume calls
+*/
+
+#ifndef __ASM_ARCH_AUDIO_H
+#define __ASM_ARCH_AUDIO_H __FILE__
+
+/* struct s3c24xx_iis_ops
+ *
+ * called from the s3c24xx audio core to deal with the architecture
+ * or the codec's setup and control.
+ *
+ * the pointer to itself is passed through in case the caller wants to
+ * embed this in an larger structure for easy reference to it's context.
+*/
+
+struct s3c24xx_iis_ops {
+       struct module *owner;
+
+       int     (*startup)(struct s3c24xx_iis_ops *me);
+       void    (*shutdown)(struct s3c24xx_iis_ops *me);
+       int     (*suspend)(struct s3c24xx_iis_ops *me);
+       int     (*resume)(struct s3c24xx_iis_ops *me);
+
+       int     (*open)(struct s3c24xx_iis_ops *me, snd_pcm_substream_t *strm);
+       int     (*close)(struct s3c24xx_iis_ops *me, snd_pcm_substream_t *strm);
+       int     (*prepare)(struct s3c24xx_iis_ops *me, snd_pcm_substream_t *strm, snd_pcm_runtime_t *rt);
+};
+
+struct s3c24xx_platdata_iis {
+       const char              *codec_clk;
+       struct s3c24xx_iis_ops  *ops;
+       int                     (*match_dev)(struct device *dev);
+};
+
+#endif /* __ASM_ARCH_AUDIO_H */
index 40ffaef..e300646 100644 (file)
@@ -42,6 +42,16 @@ static inline void pcibios_penalize_isa_irq(int irq)
 #define pci_unmap_len(PTR, LEN_NAME)           ((PTR)->LEN_NAME)
 #define pci_unmap_len_set(PTR, LEN_NAME, VAL)  (((PTR)->LEN_NAME) = (VAL))
 
+#ifdef CONFIG_PCI
+static inline void pci_dma_burst_advice(struct pci_dev *pdev,
+                                       enum pci_dma_burst_strategy *strat,
+                                       unsigned long *strategy_parameter)
+{
+       *strat = PCI_DMA_BURST_INFINITY;
+       *strategy_parameter = ~0UL;
+}
+#endif
+
 #define HAVE_PCI_MMAP
 extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
                                enum pci_mmap_state mmap_state, int write_combine);
index a6a4692..b4efe5e 100644 (file)
@@ -57,6 +57,16 @@ extern void pci_free_consistent(struct pci_dev *hwdev, size_t size,
  */
 #define PCI_DMA_BUS_IS_PHYS    (1)
 
+#ifdef CONFIG_PCI
+static inline void pci_dma_burst_advice(struct pci_dev *pdev,
+                                       enum pci_dma_burst_strategy *strat,
+                                       unsigned long *strategy_parameter)
+{
+       *strat = PCI_DMA_BURST_INFINITY;
+       *strategy_parameter = ~0UL;
+}
+#endif
+
 /*
  *     These are pretty much arbitary with the CoMEM implementation.
  *     We have the whole address space to ourselves.
index fb749b8..3561899 100644 (file)
@@ -99,6 +99,16 @@ static inline void pcibios_add_platform_entries(struct pci_dev *dev)
 {
 }
 
+#ifdef CONFIG_PCI
+static inline void pci_dma_burst_advice(struct pci_dev *pdev,
+                                       enum pci_dma_burst_strategy *strat,
+                                       unsigned long *strategy_parameter)
+{
+       *strat = PCI_DMA_BURST_INFINITY;
+       *strategy_parameter = ~0UL;
+}
+#endif
+
 #endif /* __KERNEL__ */
 
 /* implement the pci_ DMA API in terms of the generic device dma_ one */
index 38a7a72..1093f35 100644 (file)
@@ -71,8 +71,11 @@ static inline void iosapic_eoi(char __iomem *iosapic, u32 vector)
 }
 
 extern void __init iosapic_system_init (int pcat_compat);
-extern void __init iosapic_init (unsigned long address,
+extern int __devinit iosapic_init (unsigned long address,
                                    unsigned int gsi_base);
+#ifdef CONFIG_HOTPLUG
+extern int iosapic_remove (unsigned int gsi_base);
+#endif /* CONFIG_HOTPLUG */
 extern int gsi_to_vector (unsigned int gsi);
 extern int gsi_to_irq (unsigned int gsi);
 extern void iosapic_enable_intr (unsigned int vector);
@@ -94,11 +97,14 @@ extern unsigned int iosapic_version (char __iomem *addr);
 
 extern void iosapic_pci_fixup (int);
 #ifdef CONFIG_NUMA
-extern void __init map_iosapic_to_node (unsigned int, int);
+extern void __devinit map_iosapic_to_node (unsigned int, int);
 #endif
 #else
 #define iosapic_system_init(pcat_compat)                       do { } while (0)
-#define iosapic_init(address,gsi_base)                         do { } while (0)
+#define iosapic_init(address,gsi_base)                         (-EINVAL)
+#ifdef CONFIG_HOTPLUG
+#define iosapic_remove(gsi_base)                               (-ENODEV)
+#endif /* CONFIG_HOTPLUG */
 #define iosapic_register_intr(gsi,polarity,trigger)            (gsi)
 #define iosapic_unregister_intr(irq)                           do { } while (0)
 #define iosapic_override_isa_irq(isa_irq,gsi,polarity,trigger) do { } while (0)
index a8314ee..0c4c5d8 100644 (file)
@@ -82,6 +82,25 @@ extern int pcibios_prep_mwi (struct pci_dev *);
 #define sg_dma_len(sg)         ((sg)->dma_length)
 #define sg_dma_address(sg)     ((sg)->dma_address)
 
+#ifdef CONFIG_PCI
+static inline void pci_dma_burst_advice(struct pci_dev *pdev,
+                                       enum pci_dma_burst_strategy *strat,
+                                       unsigned long *strategy_parameter)
+{
+       unsigned long cacheline_size;
+       u8 byte;
+
+       pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &byte);
+       if (byte == 0)
+               cacheline_size = 1024;
+       else
+               cacheline_size = (int) byte * 4;
+
+       *strat = PCI_DMA_BURST_MULTIPLE;
+       *strategy_parameter = cacheline_size;
+}
+#endif
+
 #define HAVE_PCI_MMAP
 extern int pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma,
                                enum pci_mmap_state mmap_state, int write_combine);
index c9c576b..2d323b6 100644 (file)
@@ -130,6 +130,16 @@ extern void pci_dac_dma_sync_single_for_cpu(struct pci_dev *pdev,
 extern void pci_dac_dma_sync_single_for_device(struct pci_dev *pdev,
        dma64_addr_t dma_addr, size_t len, int direction);
 
+#ifdef CONFIG_PCI
+static inline void pci_dma_burst_advice(struct pci_dev *pdev,
+                                       enum pci_dma_burst_strategy *strat,
+                                       unsigned long *strategy_parameter)
+{
+       *strat = PCI_DMA_BURST_INFINITY;
+       *strategy_parameter = ~0UL;
+}
+#endif
+
 extern void pcibios_resource_to_bus(struct pci_dev *dev,
        struct pci_bus_region *region, struct resource *res);
 
index 0763c29..ee741c1 100644 (file)
@@ -230,6 +230,25 @@ extern inline void pcibios_register_hba(struct pci_hba_data *x)
 /* export the pci_ DMA API in terms of the dma_ one */
 #include <asm-generic/pci-dma-compat.h>
 
+#ifdef CONFIG_PCI
+static inline void pci_dma_burst_advice(struct pci_dev *pdev,
+                                       enum pci_dma_burst_strategy *strat,
+                                       unsigned long *strategy_parameter)
+{
+       unsigned long cacheline_size;
+       u8 byte;
+
+       pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &byte);
+       if (byte == 0)
+               cacheline_size = 1024;
+       else
+               cacheline_size = (int) byte * 4;
+
+       *strat = PCI_DMA_BURST_MULTIPLE;
+       *strategy_parameter = cacheline_size;
+}
+#endif
+
 extern void
 pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
                         struct resource *res);
index ce5ae6d..db0a2a0 100644 (file)
@@ -69,6 +69,16 @@ extern unsigned long pci_bus_to_phys(unsigned int ba, int busnr);
 #define pci_unmap_len(PTR, LEN_NAME)           (0)
 #define pci_unmap_len_set(PTR, LEN_NAME, VAL)  do { } while (0)
 
+#ifdef CONFIG_PCI
+static inline void pci_dma_burst_advice(struct pci_dev *pdev,
+                                       enum pci_dma_burst_strategy *strat,
+                                       unsigned long *strategy_parameter)
+{
+       *strat = PCI_DMA_BURST_INFINITY;
+       *strategy_parameter = ~0UL;
+}
+#endif
+
 /*
  * At present there are very few 32-bit PPC machines that can have
  * memory above the 4GB point, and we don't support that.
@@ -103,6 +113,12 @@ extern pgprot_t    pci_phys_mem_access_prot(struct file *file,
                                         unsigned long size,
                                         pgprot_t prot);
 
+#define HAVE_ARCH_PCI_RESOURCE_TO_USER
+extern void pci_resource_to_user(const struct pci_dev *dev, int bar,
+                                const struct resource *rsrc,
+                                u64 *start, u64 *end);
+
+
 #endif /* __KERNEL__ */
 
 #endif /* __PPC_PCI_H */
index 8032753..8b57da6 100644 (file)
@@ -40,7 +40,6 @@ static __inline__ void st_le32(volatile __u32 *addr, const __u32 val)
        __asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr));
 }
 
-#if 0
 static __inline__ __attribute_const__ __u16 ___arch__swab16(__u16 value)
 {
        __u16 result;
@@ -63,17 +62,8 @@ static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 value)
        return result;
 }
 
-static __inline__ __attribute_const__ __u64 ___arch__swab64(__u64 value)
-{
-       __u64 result;
-#error implement me
-}
-
 #define __arch__swab16(x) ___arch__swab16(x)
 #define __arch__swab32(x) ___arch__swab32(x)
-#define __arch__swab64(x) ___arch__swab64(x)
-
-#endif
 
 /* The same, but returns converted value from the location pointer by addr. */
 #define __arch__swab16p(addr) ld_le16(addr)
index 6cd593f..d12dfce 100644 (file)
@@ -78,6 +78,25 @@ static inline int pci_dac_dma_supported(struct pci_dev *hwdev,u64 mask)
        return 0;
 }
 
+#ifdef CONFIG_PCI
+static inline void pci_dma_burst_advice(struct pci_dev *pdev,
+                                       enum pci_dma_burst_strategy *strat,
+                                       unsigned long *strategy_parameter)
+{
+       unsigned long cacheline_size;
+       u8 byte;
+
+       pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &byte);
+       if (byte == 0)
+               cacheline_size = 1024;
+       else
+               cacheline_size = (int) byte * 4;
+
+       *strat = PCI_DMA_BURST_MULTIPLE;
+       *strategy_parameter = cacheline_size;
+}
+#endif
+
 extern int pci_domain_nr(struct pci_bus *bus);
 
 /* Decide whether to display the domain number in /proc */
@@ -136,6 +155,13 @@ extern pgprot_t    pci_phys_mem_access_prot(struct file *file,
                                         unsigned long size,
                                         pgprot_t prot);
 
+#ifdef CONFIG_PPC_MULTIPLATFORM
+#define HAVE_ARCH_PCI_RESOURCE_TO_USER
+extern void pci_resource_to_user(const struct pci_dev *dev, int bar,
+                                const struct resource *rsrc,
+                                u64 *start, u64 *end);
+#endif /* CONFIG_PPC_MULTIPLATFORM */
+
 
 #endif /* __KERNEL__ */
 
index 9c3b63d..2604488 100644 (file)
@@ -96,6 +96,16 @@ static inline void pcibios_penalize_isa_irq(int irq)
 #define sg_dma_address(sg)     (virt_to_bus((sg)->dma_address))
 #define sg_dma_len(sg)         ((sg)->length)
 
+#ifdef CONFIG_PCI
+static inline void pci_dma_burst_advice(struct pci_dev *pdev,
+                                       enum pci_dma_burst_strategy *strat,
+                                       unsigned long *strategy_parameter)
+{
+       *strat = PCI_DMA_BURST_INFINITY;
+       *strategy_parameter = ~0UL;
+}
+#endif
+
 /* Board-specific fixup routines. */
 extern void pcibios_fixup(void);
 extern void pcibios_fixup_irqs(void);
index 8cc14e1..c68870e 100644 (file)
@@ -86,6 +86,16 @@ static inline void pcibios_penalize_isa_irq(int irq)
 #define sg_dma_address(sg)     ((sg)->dma_address)
 #define sg_dma_len(sg)         ((sg)->length)
 
+#ifdef CONFIG_PCI
+static inline void pci_dma_burst_advice(struct pci_dev *pdev,
+                                       enum pci_dma_burst_strategy *strat,
+                                       unsigned long *strategy_parameter)
+{
+       *strat = PCI_DMA_BURST_INFINITY;
+       *strategy_parameter = ~0UL;
+}
+#endif
+
 /* Board-specific fixup routines. */
 extern void pcibios_fixup(void);
 extern void pcibios_fixup_irqs(void);
index d200a25..44bb387 100644 (file)
@@ -144,6 +144,16 @@ extern inline int pci_dma_supported(struct pci_dev *hwdev, u64 mask)
 
 #define pci_dac_dma_supported(dev, mask)       (0)
 
+#ifdef CONFIG_PCI
+static inline void pci_dma_burst_advice(struct pci_dev *pdev,
+                                       enum pci_dma_burst_strategy *strat,
+                                       unsigned long *strategy_parameter)
+{
+       *strat = PCI_DMA_BURST_INFINITY;
+       *strategy_parameter = ~0UL;
+}
+#endif
+
 static inline void pcibios_add_platform_entries(struct pci_dev *dev)
 {
 }
index 2a0c85c..84e41c1 100644 (file)
@@ -220,6 +220,25 @@ static inline int pci_dma_mapping_error(dma_addr_t dma_addr)
        return (dma_addr == PCI_DMA_ERROR_CODE);
 }
 
+#ifdef CONFIG_PCI
+static inline void pci_dma_burst_advice(struct pci_dev *pdev,
+                                       enum pci_dma_burst_strategy *strat,
+                                       unsigned long *strategy_parameter)
+{
+       unsigned long cacheline_size;
+       u8 byte;
+
+       pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &byte);
+       if (byte == 0)
+               cacheline_size = 1024;
+       else
+               cacheline_size = (int) byte * 4;
+
+       *strat = PCI_DMA_BURST_BOUNDARY;
+       *strategy_parameter = cacheline_size;
+}
+#endif
+
 /* Return the index of the PCI controller for device PDEV. */
 
 extern int pci_domain_nr(struct pci_bus *bus);
index e419414..8e79be0 100644 (file)
@@ -81,6 +81,16 @@ extern void
 pci_free_consistent (struct pci_dev *pdev, size_t size, void *cpu_addr,
                     dma_addr_t dma_addr);
 
+#ifdef CONFIG_PCI
+static inline void pci_dma_burst_advice(struct pci_dev *pdev,
+                                       enum pci_dma_burst_strategy *strat,
+                                       unsigned long *strategy_parameter)
+{
+       *strat = PCI_DMA_BURST_INFINITY;
+       *strategy_parameter = ~0UL;
+}
+#endif
+
 static inline void pcibios_add_platform_entries(struct pci_dev *dev)
 {
 }
index 8712520..c1961db 100644 (file)
@@ -123,6 +123,16 @@ pci_dac_dma_sync_single_for_device(struct pci_dev *pdev, dma64_addr_t dma_addr,
        flush_write_buffers();
 }
 
+#ifdef CONFIG_PCI
+static inline void pci_dma_burst_advice(struct pci_dev *pdev,
+                                       enum pci_dma_burst_strategy *strat,
+                                       unsigned long *strategy_parameter)
+{
+       *strat = PCI_DMA_BURST_INFINITY;
+       *strategy_parameter = ~0UL;
+}
+#endif
+
 #define HAVE_PCI_MMAP
 extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
                               enum pci_mmap_state mmap_state, int write_combine);
index b123cc0..ef84836 100644 (file)
@@ -342,11 +342,19 @@ struct acpi_table_ecdt {
 
 /* PCI MMCONFIG */
 
+/* Defined in PCI Firmware Specification 3.0 */
+struct acpi_table_mcfg_config {
+       u32                             base_address;
+       u32                             base_reserved;
+       u16                             pci_segment_group_number;
+       u8                              start_bus_number;
+       u8                              end_bus_number;
+       u8                              reserved[4];
+} __attribute__ ((packed));
 struct acpi_table_mcfg {
        struct acpi_table_header        header;
        u8                              reserved[8];
-       u32                             base_address;
-       u32                             base_reserved;
+       struct acpi_table_mcfg_config   config[0];
 } __attribute__ ((packed));
 
 /* Table Handlers */
@@ -391,6 +399,7 @@ int acpi_table_parse (enum acpi_table_id id, acpi_table_handler handler);
 int acpi_get_table_header_early (enum acpi_table_id id, struct acpi_table_header **header);
 int acpi_table_parse_madt (enum acpi_madt_entry_id id, acpi_madt_entry_handler handler, unsigned int max_entries);
 int acpi_table_parse_srat (enum acpi_srat_entry_id id, acpi_madt_entry_handler handler, unsigned int max_entries);
+int acpi_parse_mcfg (unsigned long phys_addr, unsigned long size);
 void acpi_table_print (struct acpi_table_header *header, unsigned long phys_addr);
 void acpi_table_print_madt_entry (acpi_table_entry_header *madt);
 void acpi_table_print_srat_entry (acpi_table_entry_header *srat);
@@ -407,9 +416,13 @@ int acpi_map_lsapic(acpi_handle handle, int *pcpu);
 int acpi_unmap_lsapic(int cpu);
 #endif /* CONFIG_ACPI_HOTPLUG_CPU */
 
+int acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base);
+int acpi_unregister_ioapic(acpi_handle handle, u32 gsi_base);
+
 extern int acpi_mp_config;
 
-extern u32 pci_mmcfg_base_addr;
+extern struct acpi_table_mcfg_config *pci_mmcfg_config;
+extern int pci_mmcfg_config_num;
 
 extern int sbf_port ;
 
index 21a8674..0881b5c 100644 (file)
@@ -96,6 +96,7 @@ struct io_context {
 
 void put_io_context(struct io_context *ioc);
 void exit_io_context(void);
+struct io_context *current_io_context(int gfp_flags);
 struct io_context *get_io_context(int gfp_flags);
 void copy_io_context(struct io_context **pdst, struct io_context **psrc);
 void swap_io_context(struct io_context **ioc1, struct io_context **ioc2);
index d28d9a8..d5f2a32 100644 (file)
 #endif /* OPTIMIZE */
 
 
-static __inline__ __const__ __u32 __fswahw32(__u32 x)
+static inline __u32 __fswahw32(__u32 x)
 {
        return __arch__swahw32(x);
 }
-static __inline__ __u32 __swahw32p(__u32 *x)
+
+static inline __u32 __swahw32p(__u32 *x)
 {
        return __arch__swahw32p(x);
 }
-static __inline__ void __swahw32s(__u32 *addr)
+
+static inline void __swahw32s(__u32 *addr)
 {
        __arch__swahw32s(addr);
 }
 
-
-static __inline__ __const__ __u32 __fswahb32(__u32 x)
+static inline __u32 __fswahb32(__u32 x)
 {
        return __arch__swahb32(x);
 }
-static __inline__ __u32 __swahb32p(__u32 *x)
+
+static inline __u32 __swahb32p(__u32 *x)
 {
        return __arch__swahb32p(x);
 }
-static __inline__ void __swahb32s(__u32 *addr)
+
+static inline void __swahb32s(__u32 *addr)
 {
        __arch__swahb32s(addr);
 }
index d228230..5416956 100644 (file)
@@ -25,6 +25,7 @@
 #define _LINUX_I2C_DEV_H
 
 #include <linux/types.h>
+#include <linux/compiler.h>
 
 /* Some IOCTL commands are defined in <linux/i2c.h> */
 /* Note: 10-bit addresses are NOT supported! */
index 1227779..069d3b8 100644 (file)
@@ -85,9 +85,10 @@ extern int no_irq_affinity;
 extern int noirqdebug_setup(char *str);
 
 extern fastcall int handle_IRQ_event(unsigned int irq, struct pt_regs *regs,
-                                      struct irqaction *action);
+                                       struct irqaction *action);
 extern fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs);
-extern void note_interrupt(unsigned int irq, irq_desc_t *desc, int action_ret);
+extern void note_interrupt(unsigned int irq, irq_desc_t *desc,
+                                       int action_ret, struct pt_regs *regs);
 extern int can_request_irq(unsigned int irq, unsigned long irqflags);
 
 extern void init_irq_proc(void);
index b5238bd..66798b4 100644 (file)
@@ -734,16 +734,20 @@ void pcibios_update_irq(struct pci_dev *, int irq);
 /* Generic PCI functions used internally */
 
 extern struct pci_bus *pci_find_bus(int domain, int busnr);
+void pci_bus_add_devices(struct pci_bus *bus);
 struct pci_bus *pci_scan_bus_parented(struct device *parent, int bus, struct pci_ops *ops, void *sysdata);
 static inline struct pci_bus *pci_scan_bus(int bus, struct pci_ops *ops, void *sysdata)
 {
-       return pci_scan_bus_parented(NULL, bus, ops, sysdata);
+       struct pci_bus *root_bus;
+       root_bus = pci_scan_bus_parented(NULL, bus, ops, sysdata);
+       if (root_bus)
+               pci_bus_add_devices(root_bus);
+       return root_bus;
 }
 int pci_scan_slot(struct pci_bus *bus, int devfn);
 struct pci_dev * pci_scan_single_device(struct pci_bus *bus, int devfn);
 unsigned int pci_scan_child_bus(struct pci_bus *bus);
 void pci_bus_add_device(struct pci_dev *dev);
-void pci_bus_add_devices(struct pci_bus *bus);
 void pci_name_device(struct pci_dev *dev);
 char *pci_class_name(u32 class);
 void pci_read_bridge_bases(struct pci_bus *child);
@@ -870,6 +874,15 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max, int pass
 #define        pci_pool_alloc(pool, flags, handle) dma_pool_alloc(pool, flags, handle)
 #define        pci_pool_free(pool, vaddr, addr) dma_pool_free(pool, vaddr, addr)
 
+enum pci_dma_burst_strategy {
+       PCI_DMA_BURST_INFINITY, /* make bursts as large as possible,
+                                  strategy_parameter is N/A */
+       PCI_DMA_BURST_BOUNDARY, /* disconnect at every strategy_parameter
+                                  byte boundaries */
+       PCI_DMA_BURST_MULTIPLE, /* disconnect at some multiple of
+                                  strategy_parameter byte boundaries */
+};
+
 #if defined(CONFIG_ISA) || defined(CONFIG_EISA)
 extern struct pci_dev *isa_bridge;
 #endif
@@ -972,6 +985,8 @@ static inline int pci_proc_domain(struct pci_bus *bus)
 }
 #endif
 
+#define pci_dma_burst_advice(pdev, strat, strategy_parameter) do { } while (0)
+
 #endif /* !CONFIG_PCI */
 
 /* these helpers provide future and backwards compatibility
@@ -1016,6 +1031,20 @@ static inline char *pci_name(struct pci_dev *pdev)
 #define pci_pretty_name(dev) ""
 #endif
 
+
+/* Some archs don't want to expose struct resource to userland as-is
+ * in sysfs and /proc
+ */
+#ifndef HAVE_ARCH_PCI_RESOURCE_TO_USER
+static inline void pci_resource_to_user(const struct pci_dev *dev, int bar,
+                const struct resource *rsrc, u64 *start, u64 *end)
+{
+       *start = rsrc->start;
+       *end = rsrc->end;
+}
+#endif /* HAVE_ARCH_PCI_RESOURCE_TO_USER */
+
+
 /*
  *  The world is not perfect and supplies us with broken PCI devices.
  *  For at least a part of these bugs we need a work-around, so both
index 1e0bc6a..c3ee1ae 100644 (file)
@@ -62,6 +62,8 @@
 
 #define PCI_BASE_CLASS_SYSTEM          0x08
 #define PCI_CLASS_SYSTEM_PIC           0x0800
+#define PCI_CLASS_SYSTEM_PIC_IOAPIC    0x080010
+#define PCI_CLASS_SYSTEM_PIC_IOXAPIC   0x080020
 #define PCI_CLASS_SYSTEM_DMA           0x0801
 #define PCI_CLASS_SYSTEM_TIMER         0x0802
 #define PCI_CLASS_SYSTEM_RTC           0x0803
index 39e7ff4..ee21e6b 100644 (file)
@@ -19,7 +19,7 @@
 #ifndef __LINUX_USB_CH9_H
 #define __LINUX_USB_CH9_H
 
-#include <asm/types.h>         /* __u8 etc */
+#include <linux/types.h>       /* __u8 etc */
 
 /*-------------------------------------------------------------------------*/
 
@@ -294,8 +294,8 @@ struct usb_endpoint_descriptor {
        __le16 wMaxPacketSize;
        __u8  bInterval;
 
-       // NOTE:  these two are _only_ in audio endpoints.
-       // use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof.
+       /* NOTE:  these two are _only_ in audio endpoints. */
+       /* use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof. */
        __u8  bRefresh;
        __u8  bSynchAddress;
 } __attribute__ ((packed));
index 4e0edce..acbfc52 100644 (file)
@@ -221,6 +221,8 @@ struct v4l2_pix_format
 /*  Vendor-specific formats   */
 #define V4L2_PIX_FMT_WNVA     v4l2_fourcc('W','N','V','A') /* Winnov hw compress */
 #define V4L2_PIX_FMT_SN9C10X  v4l2_fourcc('S','9','1','0') /* SN9C10x compression */
+#define V4L2_PIX_FMT_PWC1     v4l2_fourcc('P','W','C','1') /* pwc older webcam */
+#define V4L2_PIX_FMT_PWC2     v4l2_fourcc('P','W','C','2') /* pwc newer webcam */
 
 /*
  *     F O R M A T   E N U M E R A T I O N
index d5c3fe1..542dbae 100644 (file)
@@ -85,7 +85,7 @@ static inline void wait_on_inode(struct inode *inode)
 /*
  * mm/page-writeback.c
  */
-int wakeup_bdflush(long nr_pages);
+int wakeup_pdflush(long nr_pages);
 void laptop_io_completion(void);
 void laptop_sync_completion(void);
 void throttle_vm_writeout(void);
diff --git a/include/linux/xattr_acl.h b/include/linux/xattr_acl.h
deleted file mode 100644 (file)
index 7a1f9b9..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
-  File: linux/xattr_acl.h
-
-  (extended attribute representation of access control lists)
-
-  (C) 2000 Andreas Gruenbacher, <a.gruenbacher@computer.org>
-*/
-
-#ifndef _LINUX_XATTR_ACL_H
-#define _LINUX_XATTR_ACL_H
-
-#include <linux/posix_acl.h>
-
-#define XATTR_NAME_ACL_ACCESS  "system.posix_acl_access"
-#define XATTR_NAME_ACL_DEFAULT "system.posix_acl_default"
-
-#define XATTR_ACL_VERSION      0x0002
-
-typedef struct {
-       __u16           e_tag;
-       __u16           e_perm;
-       __u32           e_id;
-} xattr_acl_entry;
-
-typedef struct {
-       __u32           a_version;
-       xattr_acl_entry a_entries[0];
-} xattr_acl_header;
-
-static inline size_t xattr_acl_size(int count)
-{
-       return sizeof(xattr_acl_header) + count * sizeof(xattr_acl_entry);
-}
-
-static inline int xattr_acl_count(size_t size)
-{
-       if (size < sizeof(xattr_acl_header))
-               return -1;
-       size -= sizeof(xattr_acl_header);
-       if (size % sizeof(xattr_acl_entry))
-               return -1;
-       return size / sizeof(xattr_acl_entry);
-}
-
-struct posix_acl * posix_acl_from_xattr(const void *value, size_t size);
-int posix_acl_to_xattr(const struct posix_acl *acl, void *buffer, size_t size);
-
-
-
-#endif /* _LINUX_XATTR_ACL_H */
index 2dd8310..4794c56 100644 (file)
@@ -1,5 +1,6 @@
 
-/*
+/* $Id: tuner.h,v 1.33 2005/06/21 14:58:08 mkrufky Exp $
+ *
     tuner.h - definition for different tuners
 
     Copyright (C) 1997 Markus Schroeder (schroedm@uni-duesseldorf.de)
@@ -23,6 +24,8 @@
 #ifndef _TUNER_H
 #define _TUNER_H
 
+#include <linux/videodev2.h>
+
 #include "id.h"
 
 #define ADDR_UNSET (255)
@@ -88,7 +91,7 @@
 #define TUNER_LG_NTSC_TAPE       47
 
 #define TUNER_TNF_8831BGFF       48
-#define TUNER_MICROTUNE_4042FI5  49    /* FusionHDTV 3 Gold - 4042 FI5 (3X 8147) */
+#define TUNER_MICROTUNE_4042FI5  49    /* DViCO FusionHDTV 3 Gold-Q - 4042 FI5 (3X 8147) */
 #define TUNER_TCL_2002N          50
 #define TUNER_PHILIPS_FM1256_IH3   51
 
 #define TUNER_LG_PAL_TAPE        55    /* Hauppauge PVR-150 PAL */
 
 #define TUNER_PHILIPS_FQ1216AME_MK4 56 /* Hauppauge PVR-150 PAL */
-#define TUNER_PHILIPS_FQ1236A_MK4 57   /* Hauppauge PVR-500MCE NTSC */
+#define TUNER_PHILIPS_FQ1236A_MK4   57   /* Hauppauge PVR-500MCE NTSC */
 
 #define TUNER_YMEC_TVF_8531MF 58
 #define TUNER_YMEC_TVF_5533MF 59       /* Pixelview Pro Ultra NTSC */
-#define TUNER_THOMSON_DTT7611 60
+#define TUNER_THOMSON_DTT7611 60       /* DViCO FusionHDTV 3 Gold-T */
 #define TUNER_TENA_9533_DI    61
+
 #define TUNER_TEA5767         62       /* Only FM Radio Tuner */
+#define TUNER_PHILIPS_FMD1216ME_MK3 63
 
 #define TEA5767_TUNER_NAME "Philips TEA5767HN FM Radio"
 
-#define TUNER_THOMSON_DTT7611    60
-
 #define NOTUNER 0
 #define PAL     1      /* PAL_BG */
 #define PAL_I   2
@@ -194,11 +197,15 @@ struct tuner {
        unsigned char i2c_easy_mode[2];
        unsigned char i2c_set_freq[8];
 
+       /* used to keep track of audmode */
+       unsigned int audmode;
+
        /* function ptrs */
        void (*tv_freq)(struct i2c_client *c, unsigned int freq);
        void (*radio_freq)(struct i2c_client *c, unsigned int freq);
        int  (*has_signal)(struct i2c_client *c);
        int  (*is_stereo)(struct i2c_client *c);
+       int  (*set_tuner)(struct i2c_client *c, struct v4l2_tuner *v);
 };
 
 extern unsigned int tuner_debug;
@@ -206,6 +213,7 @@ extern unsigned const int tuner_count;
 
 extern int microtune_init(struct i2c_client *c);
 extern int tda8290_init(struct i2c_client *c);
+extern int tea5767_tuner_init(struct i2c_client *c);
 extern int default_tuner_init(struct i2c_client *c);
 
 #define tuner_warn(fmt, arg...) \
index d324801..b5e421e 100644 (file)
@@ -383,6 +383,13 @@ static void noinline rest_init(void)
        numa_default_policy();
        unlock_kernel();
        preempt_enable_no_resched();
+
+       /*
+        * The boot idle thread must execute schedule()
+        * at least one to get things moving:
+        */
+       schedule();
+
        cpu_idle();
 } 
 
index 98d62d8..3467097 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/irq.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
+#include <linux/delay.h>
 
 /*
  * Autodetection depends on the fact that any interrupt that
@@ -26,7 +27,7 @@ static DECLARE_MUTEX(probe_sem);
  */
 unsigned long probe_irq_on(void)
 {
-       unsigned long val, delay;
+       unsigned long val;
        irq_desc_t *desc;
        unsigned int i;
 
@@ -45,8 +46,7 @@ unsigned long probe_irq_on(void)
        }
 
        /* Wait for longstanding interrupts to trigger. */
-       for (delay = jiffies + HZ/50; time_after(delay, jiffies); )
-               /* about 20ms delay */ barrier();
+       msleep(20);
 
        /*
         * enable any unassigned irqs
@@ -68,8 +68,7 @@ unsigned long probe_irq_on(void)
        /*
         * Wait for spurious interrupts to trigger
         */
-       for (delay = jiffies + HZ/10; time_after(delay, jiffies); )
-               /* about 100ms delay */ barrier();
+       msleep(100);
 
        /*
         * Now filter out any obviously spurious interrupts
index 436c7d9..c29f83c 100644 (file)
@@ -172,7 +172,7 @@ fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs)
 
                spin_lock(&desc->lock);
                if (!noirqdebug)
-                       note_interrupt(irq, desc, action_ret);
+                       note_interrupt(irq, desc, action_ret, regs);
                if (likely(!(desc->status & IRQ_PENDING)))
                        break;
                desc->status &= ~IRQ_PENDING;
index ba039e8..7df9abd 100644 (file)
 #include <linux/kallsyms.h>
 #include <linux/interrupt.h>
 
+static int irqfixup;
+
+/*
+ * Recovery handler for misrouted interrupts.
+ */
+
+static int misrouted_irq(int irq, struct pt_regs *regs)
+{
+       int i;
+       irq_desc_t *desc;
+       int ok = 0;
+       int work = 0;   /* Did we do work for a real IRQ */
+
+       for(i = 1; i < NR_IRQS; i++) {
+               struct irqaction *action;
+
+               if (i == irq)   /* Already tried */
+                       continue;
+               desc = &irq_desc[i];
+               spin_lock(&desc->lock);
+               action = desc->action;
+               /* Already running on another processor */
+               if (desc->status & IRQ_INPROGRESS) {
+                       /*
+                        * Already running: If it is shared get the other
+                        * CPU to go looking for our mystery interrupt too
+                        */
+                       if (desc->action && (desc->action->flags & SA_SHIRQ))
+                               desc->status |= IRQ_PENDING;
+                       spin_unlock(&desc->lock);
+                       continue;
+               }
+               /* Honour the normal IRQ locking */
+               desc->status |= IRQ_INPROGRESS;
+               spin_unlock(&desc->lock);
+               while (action) {
+                       /* Only shared IRQ handlers are safe to call */
+                       if (action->flags & SA_SHIRQ) {
+                               if (action->handler(i, action->dev_id, regs) ==
+                                               IRQ_HANDLED)
+                                       ok = 1;
+                       }
+                       action = action->next;
+               }
+               local_irq_disable();
+               /* Now clean up the flags */
+               spin_lock(&desc->lock);
+               action = desc->action;
+
+               /*
+                * While we were looking for a fixup someone queued a real
+                * IRQ clashing with our walk
+                */
+
+               while ((desc->status & IRQ_PENDING) && action) {
+                       /*
+                        * Perform real IRQ processing for the IRQ we deferred
+                        */
+                       work = 1;
+                       spin_unlock(&desc->lock);
+                       handle_IRQ_event(i, regs, action);
+                       spin_lock(&desc->lock);
+                       desc->status &= ~IRQ_PENDING;
+               }
+               desc->status &= ~IRQ_INPROGRESS;
+               /*
+                * If we did actual work for the real IRQ line we must let the
+                * IRQ controller clean up too
+                */
+               if(work)
+                       desc->handler->end(i);
+               spin_unlock(&desc->lock);
+       }
+       /* So the caller can adjust the irq error counts */
+       return ok;
+}
+
 /*
  * If 99,900 of the previous 100,000 interrupts have not been handled
  * then assume that the IRQ is stuck in some manner. Drop a diagnostic
@@ -31,7 +108,8 @@ __report_bad_irq(unsigned int irq, irq_desc_t *desc, irqreturn_t action_ret)
                printk(KERN_ERR "irq event %d: bogus return value %x\n",
                                irq, action_ret);
        } else {
-               printk(KERN_ERR "irq %d: nobody cared!\n", irq);
+               printk(KERN_ERR "irq %d: nobody cared (try booting with "
+                               "the \"irqpoll\" option)\n", irq);
        }
        dump_stack();
        printk(KERN_ERR "handlers:\n");
@@ -55,7 +133,8 @@ static void report_bad_irq(unsigned int irq, irq_desc_t *desc, irqreturn_t actio
        }
 }
 
-void note_interrupt(unsigned int irq, irq_desc_t *desc, irqreturn_t action_ret)
+void note_interrupt(unsigned int irq, irq_desc_t *desc, irqreturn_t action_ret,
+                       struct pt_regs *regs)
 {
        if (action_ret != IRQ_HANDLED) {
                desc->irqs_unhandled++;
@@ -63,6 +142,15 @@ void note_interrupt(unsigned int irq, irq_desc_t *desc, irqreturn_t action_ret)
                        report_bad_irq(irq, desc, action_ret);
        }
 
+       if (unlikely(irqfixup)) {
+               /* Don't punish working computers */
+               if ((irqfixup == 2 && irq == 0) || action_ret == IRQ_NONE) {
+                       int ok = misrouted_irq(irq, regs);
+                       if (action_ret == IRQ_NONE)
+                               desc->irqs_unhandled -= ok;
+               }
+       }
+
        desc->irq_count++;
        if (desc->irq_count < 100000)
                return;
@@ -94,3 +182,24 @@ int __init noirqdebug_setup(char *str)
 
 __setup("noirqdebug", noirqdebug_setup);
 
+static int __init irqfixup_setup(char *str)
+{
+       irqfixup = 1;
+       printk(KERN_WARNING "Misrouted IRQ fixup support enabled.\n");
+       printk(KERN_WARNING "This may impact system performance.\n");
+       return 1;
+}
+
+__setup("irqfixup", irqfixup_setup);
+
+static int __init irqpoll_setup(char *str)
+{
+       irqfixup = 2;
+       printk(KERN_WARNING "Misrouted IRQ fixup and polling support "
+                               "enabled\n");
+       printk(KERN_WARNING "This may significantly impact system "
+                               "performance\n");
+       return 1;
+}
+
+__setup("irqpoll", irqpoll_setup);
index 1dc988e..a72cb0e 100644 (file)
@@ -153,11 +153,15 @@ int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
 
        switch (which) {
        case ITIMER_REAL:
+again:
                spin_lock_irq(&tsk->sighand->siglock);
                interval = tsk->signal->it_real_incr;
                val = it_real_value(tsk->signal);
-               if (val)
-                       del_timer_sync(&tsk->signal->real_timer);
+               /* We are sharing ->siglock with it_real_fn() */
+               if (try_to_del_timer_sync(&tsk->signal->real_timer) < 0) {
+                       spin_unlock_irq(&tsk->sighand->siglock);
+                       goto again;
+               }
                tsk->signal->it_real_incr =
                        timeval_to_jiffies(&value->it_interval);
                it_real_arm(tsk, timeval_to_jiffies(&value->it_value));
index 7843548..cdd4dcd 100644 (file)
@@ -241,7 +241,7 @@ static int kimage_normal_alloc(struct kimage **rimage, unsigned long entry,
 
 static int kimage_crash_alloc(struct kimage **rimage, unsigned long entry,
                                unsigned long nr_segments,
-                               struct kexec_segment *segments)
+                               struct kexec_segment __user *segments)
 {
        int result;
        struct kimage *image;
@@ -650,7 +650,7 @@ static kimage_entry_t *kimage_dst_used(struct kimage *image,
                }
        }
 
-       return 0;
+       return NULL;
 }
 
 static struct page *kimage_alloc_page(struct kimage *image,
@@ -696,7 +696,7 @@ static struct page *kimage_alloc_page(struct kimage *image,
                /* Allocate a page, if we run out of memory give up */
                page = kimage_alloc_pages(gfp_mask, 0);
                if (!page)
-                       return 0;
+                       return NULL;
                /* If the page cannot be used file it away */
                if (page_to_pfn(page) >
                                (KEXEC_SOURCE_MEMORY_LIMIT >> PAGE_SHIFT)) {
@@ -754,7 +754,7 @@ static int kimage_load_normal_segment(struct kimage *image,
        unsigned long maddr;
        unsigned long ubytes, mbytes;
        int result;
-       unsigned char *buf;
+       unsigned char __user *buf;
 
        result = 0;
        buf = segment->buf;
@@ -818,7 +818,7 @@ static int kimage_load_crash_segment(struct kimage *image,
        unsigned long maddr;
        unsigned long ubytes, mbytes;
        int result;
-       unsigned char *buf;
+       unsigned char __user *buf;
 
        result = 0;
        buf = segment->buf;
index e2b0d3e..5f2182d 100644 (file)
@@ -4166,6 +4166,14 @@ void show_state(void)
        read_unlock(&tasklist_lock);
 }
 
+/**
+ * init_idle - set up an idle thread for a given CPU
+ * @idle: task in question
+ * @cpu: cpu the idle task belongs to
+ *
+ * NOTE: this function does not set the idle thread's NEED_RESCHED
+ * flag, to make booting more robust.
+ */
 void __devinit init_idle(task_t *idle, int cpu)
 {
        runqueue_t *rq = cpu_rq(cpu);
@@ -4183,7 +4191,6 @@ void __devinit init_idle(task_t *idle, int cpu)
 #if defined(CONFIG_SMP) && defined(__ARCH_WANT_UNLOCKED_CTXSW)
        idle->oncpu = 1;
 #endif
-       set_tsk_need_resched(idle);
        spin_unlock_irqrestore(&rq->lock, flags);
 
        /* Set the preempt count _outside_ the spinlocks! */
index 613b99a..a6329fa 100644 (file)
@@ -354,7 +354,7 @@ static void background_writeout(unsigned long _min_pages)
  * the whole world.  Returns 0 if a pdflush thread was dispatched.  Returns
  * -1 if all pdflush threads were busy.
  */
-int wakeup_bdflush(long nr_pages)
+int wakeup_pdflush(long nr_pages)
 {
        if (nr_pages == 0) {
                struct writeback_state wbs;
index 1fa312a..cfffe50 100644 (file)
@@ -972,7 +972,7 @@ int try_to_free_pages(struct zone **zones, unsigned int gfp_mask)
                 * writeout.  So in laptop mode, write out the whole world.
                 */
                if (total_scanned > sc.swap_cluster_max + sc.swap_cluster_max/2) {
-                       wakeup_bdflush(laptop_mode ? 0 : total_scanned);
+                       wakeup_pdflush(laptop_mode ? 0 : total_scanned);
                        sc.may_writepage = 1;
                }