Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 7 Jul 2011 20:16:21 +0000 (13:16 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 7 Jul 2011 20:16:21 +0000 (13:16 -0700)
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: (31 commits)
  sctp: fix missing send up SCTP_SENDER_DRY_EVENT when subscribe it
  net: refine {udp|tcp|sctp}_mem limits
  vmxnet3: round down # of queues to power of two
  net: sh_eth: fix the parameter for the ETHER of SH7757
  net: sh_eth: fix cannot work half-duplex mode
  net: vlan: enable soft features regardless of underlying device
  vmxnet3: fix starving rx ring whenoc_skb kb fails
  bridge: Always flood broadcast packets
  greth: greth_set_mac_add would corrupt the MAC address.
  net: bind() fix error return on wrong address family
  natsemi: silence dma-debug warnings
  net: 8139too: Initial necessary vlan_features to support vlan
  Fix call trace when interrupts are disabled while sleeping function kzalloc is called
  qlge:Version change to v1.00.00.29
  qlge: Fix printk priority so chip fatal errors are always reported.
  qlge:Fix crash caused by mailbox execution on wedged chip.
  xfrm4: Don't call icmp_send on local error
  ipv4: Don't use ufo handling on later transformed packets
  xfrm: Remove family arg from xfrm_bundle_ok
  ipv6: Don't put artificial limit on routing table size.
  ...

164 files changed:
CREDITS
Documentation/CodingStyle
Documentation/cgroups/blkio-controller.txt
Documentation/hwmon/f71882fg
Documentation/hwmon/k10temp
Documentation/power/runtime_pm.txt
MAINTAINERS
Makefile
README
arch/arm/mach-at91/at91cap9.c
arch/arm/mach-at91/at91cap9_devices.c
arch/arm/mach-at91/at91rm9200.c
arch/arm/mach-at91/at91rm9200_devices.c
arch/arm/mach-at91/at91sam9260_devices.c
arch/arm/mach-at91/at91sam9261_devices.c
arch/arm/mach-at91/at91sam9263_devices.c
arch/arm/mach-at91/at91sam9g45.c
arch/arm/mach-at91/at91sam9g45_devices.c
arch/arm/mach-at91/at91sam9rl.c
arch/arm/mach-at91/at91sam9rl_devices.c
arch/arm/mach-at91/board-cap9adk.c
arch/arm/mach-at91/board-sam9260ek.c
arch/arm/mach-at91/board-sam9261ek.c
arch/arm/mach-at91/board-sam9263ek.c
arch/arm/mach-at91/board-sam9g20ek.c
arch/arm/mach-at91/board-sam9m10g45ek.c
arch/arm/mach-at91/include/mach/system_rev.h
arch/x86/pci/xen.c
arch/x86/xen/mmu.c
drivers/gpio/tps65910-gpio.c
drivers/gpu/drm/i915/i915_debugfs.c
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/i915_suspend.c
drivers/gpu/drm/i915/intel_overlay.c
drivers/gpu/drm/nouveau/nouveau_state.c
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/nid.h
drivers/gpu/drm/radeon/rv770.c
drivers/hwmon/Kconfig
drivers/hwmon/adm1275.c
drivers/hwmon/emc6w201.c
drivers/hwmon/f71882fg.c
drivers/hwmon/hwmon-vid.c
drivers/hwmon/pmbus.c
drivers/hwmon/pmbus_core.c
drivers/hwmon/sch5627.c
drivers/infiniband/core/cm.c
drivers/infiniband/core/uverbs_main.c
drivers/input/keyboard/pmic8xxx-keypad.c
drivers/input/misc/pmic8xxx-pwrkey.c
drivers/media/rc/fintek-cir.c
drivers/media/rc/imon.c
drivers/media/rc/ir-raw.c
drivers/media/rc/ite-cir.c
drivers/media/rc/ite-cir.h
drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c
drivers/media/rc/lirc_dev.c
drivers/media/rc/mceusb.c
drivers/media/rc/nuvoton-cir.c
drivers/media/rc/nuvoton-cir.h
drivers/media/rc/rc-main.c
drivers/media/video/m5mols/m5mols.h
drivers/media/video/m5mols/m5mols_capture.c
drivers/media/video/m5mols/m5mols_controls.c
drivers/media/video/m5mols/m5mols_core.c
drivers/media/video/m5mols/m5mols_reg.h
drivers/media/video/mx1_camera.c
drivers/media/video/omap/omap_vout.c
drivers/media/video/omap/omap_voutlib.c
drivers/media/video/omap3isp/isp.c
drivers/media/video/pwc/pwc-ctrl.c
drivers/media/video/pwc/pwc-if.c
drivers/media/video/pwc/pwc.h
drivers/media/video/s5p-fimc/fimc-capture.c
drivers/media/video/s5p-fimc/fimc-core.c
drivers/media/video/s5p-fimc/fimc-core.h
drivers/media/video/saa7134/saa7134-input.c
drivers/media/video/uvc/uvc_entity.c
drivers/media/video/uvc/uvc_queue.c
drivers/media/video/uvc/uvc_video.c
drivers/media/video/v4l2-dev.c
drivers/media/video/videobuf2-core.c
drivers/media/video/videobuf2-dma-sg.c
drivers/mfd/Kconfig
drivers/mfd/Makefile
drivers/mfd/omap-usb-host.c
drivers/mfd/tps65911-comparator.c
drivers/scsi/Kconfig
drivers/scsi/Makefile
drivers/scsi/hpsa.c
drivers/scsi/ibmvscsi/ibmvfc.c
drivers/scsi/isci/Makefile [new file with mode: 0644]
drivers/scsi/isci/firmware/Makefile [new file with mode: 0644]
drivers/scsi/isci/firmware/README [new file with mode: 0644]
drivers/scsi/isci/firmware/create_fw.c [new file with mode: 0644]
drivers/scsi/isci/firmware/create_fw.h [new file with mode: 0644]
drivers/scsi/isci/host.c [new file with mode: 0644]
drivers/scsi/isci/host.h [new file with mode: 0644]
drivers/scsi/isci/init.c [new file with mode: 0644]
drivers/scsi/isci/isci.h [new file with mode: 0644]
drivers/scsi/isci/phy.c [new file with mode: 0644]
drivers/scsi/isci/phy.h [new file with mode: 0644]
drivers/scsi/isci/port.c [new file with mode: 0644]
drivers/scsi/isci/port.h [new file with mode: 0644]
drivers/scsi/isci/port_config.c [new file with mode: 0644]
drivers/scsi/isci/probe_roms.c [new file with mode: 0644]
drivers/scsi/isci/probe_roms.h [new file with mode: 0644]
drivers/scsi/isci/registers.h [new file with mode: 0644]
drivers/scsi/isci/remote_device.c [new file with mode: 0644]
drivers/scsi/isci/remote_device.h [new file with mode: 0644]
drivers/scsi/isci/remote_node_context.c [new file with mode: 0644]
drivers/scsi/isci/remote_node_context.h [new file with mode: 0644]
drivers/scsi/isci/remote_node_table.c [new file with mode: 0644]
drivers/scsi/isci/remote_node_table.h [new file with mode: 0644]
drivers/scsi/isci/request.c [new file with mode: 0644]
drivers/scsi/isci/request.h [new file with mode: 0644]
drivers/scsi/isci/sas.h [new file with mode: 0644]
drivers/scsi/isci/scu_completion_codes.h [new file with mode: 0644]
drivers/scsi/isci/scu_event_codes.h [new file with mode: 0644]
drivers/scsi/isci/scu_remote_node_context.h [new file with mode: 0644]
drivers/scsi/isci/scu_task_context.h [new file with mode: 0644]
drivers/scsi/isci/task.c [new file with mode: 0644]
drivers/scsi/isci/task.h [new file with mode: 0644]
drivers/scsi/isci/unsolicited_frame_control.c [new file with mode: 0644]
drivers/scsi/isci/unsolicited_frame_control.h [new file with mode: 0644]
drivers/staging/lirc/lirc_imon.c
drivers/staging/lirc/lirc_serial.c
drivers/staging/lirc/lirc_sir.c
drivers/staging/lirc/lirc_zilog.c
drivers/tty/serial/atmel_serial.c
drivers/usb/core/message.c
drivers/usb/gadget/fsl_udc_core.c
drivers/video/amba-clcd.c
drivers/video/fsl-diu-fb.c
drivers/video/geode/gx1fb_core.c
drivers/video/hecubafb.c
drivers/video/sh_mobile_meram.c
drivers/video/sm501fb.c
drivers/video/udlfb.c
drivers/video/vesafb.c
firmware/Makefile
firmware/isci/isci_firmware.bin.ihex [new file with mode: 0644]
fs/binfmt_elf_fdpic.c
fs/ceph/file.c
fs/cifs/connect.c
fs/hfsplus/super.c
fs/hfsplus/wrapper.c
fs/locks.c
include/linux/fsl-diu-fb.h
include/media/lirc_dev.h
include/media/m5mols.h
include/sound/sb16_csp.h
kernel/resource.c
net/ceph/osd_client.c
sound/atmel/abdac.c
sound/atmel/ac97c.c
sound/pci/cs5535audio/cs5535audio_pcm.c
sound/pci/hda/hda_eld.c
sound/pci/hda/patch_conexant.c
sound/pci/rme9652/hdspm.c
sound/spi/at73c213.c

diff --git a/CREDITS b/CREDITS
index d78359f..1deb331 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -518,7 +518,7 @@ N: Zach Brown
 E: zab@zabbo.net
 D: maestro pci sound
 
-M: David Brownell
+N: David Brownell
 D: Kernel engineer, mentor, and friend.  Maintained USB EHCI and
 D: gadget layers, SPI subsystem, GPIO subsystem, and more than a few
 D: device drivers.  His encouragement also helped many engineers get
index 58b0bf9..fa6e25b 100644 (file)
@@ -680,8 +680,8 @@ ones already enabled by DEBUG.
                Chapter 14: Allocating memory
 
 The kernel provides the following general purpose memory allocators:
-kmalloc(), kzalloc(), kcalloc(), and vmalloc().  Please refer to the API
-documentation for further information about them.
+kmalloc(), kzalloc(), kcalloc(), vmalloc(), and vzalloc().  Please refer to
+the API documentation for further information about them.
 
 The preferred form for passing a size of a struct is the following:
 
index cd45c8e..84f0a15 100644 (file)
@@ -77,7 +77,7 @@ Throttling/Upper Limit policy
 - Specify a bandwidth rate on particular device for root group. The format
   for policy is "<major>:<minor>  <byes_per_second>".
 
-        echo "8:16  1048576" > /sys/fs/cgroup/blkio/blkio.read_bps_device
+        echo "8:16  1048576" > /sys/fs/cgroup/blkio/blkio.throttle.read_bps_device
 
   Above will put a limit of 1MB/second on reads happening for root group
   on device having major/minor number 8:16.
@@ -90,7 +90,7 @@ Throttling/Upper Limit policy
         1024+0 records out
         4194304 bytes (4.2 MB) copied, 4.0001 s, 1.0 MB/s
 
- Limits for writes can be put using blkio.write_bps_device file.
+ Limits for writes can be put using blkio.throttle.write_bps_device file.
 
 Hierarchical Cgroups
 ====================
@@ -286,28 +286,28 @@ Throttling/Upper limit policy files
          specified in bytes per second. Rules are per deivce. Following is
          the format.
 
-  echo "<major>:<minor>  <rate_bytes_per_second>" > /cgrp/blkio.read_bps_device
+  echo "<major>:<minor>  <rate_bytes_per_second>" > /cgrp/blkio.throttle.read_bps_device
 
 - blkio.throttle.write_bps_device
        - Specifies upper limit on WRITE rate to the device. IO rate is
          specified in bytes per second. Rules are per deivce. Following is
          the format.
 
-  echo "<major>:<minor>  <rate_bytes_per_second>" > /cgrp/blkio.write_bps_device
+  echo "<major>:<minor>  <rate_bytes_per_second>" > /cgrp/blkio.throttle.write_bps_device
 
 - blkio.throttle.read_iops_device
        - Specifies upper limit on READ rate from the device. IO rate is
          specified in IO per second. Rules are per deivce. Following is
          the format.
 
-  echo "<major>:<minor>  <rate_io_per_second>" > /cgrp/blkio.read_iops_device
+  echo "<major>:<minor>  <rate_io_per_second>" > /cgrp/blkio.throttle.read_iops_device
 
 - blkio.throttle.write_iops_device
        - Specifies upper limit on WRITE rate to the device. IO rate is
          specified in io per second. Rules are per deivce. Following is
          the format.
 
-  echo "<major>:<minor>  <rate_io_per_second>" > /cgrp/blkio.write_iops_device
+  echo "<major>:<minor>  <rate_io_per_second>" > /cgrp/blkio.throttle.write_iops_device
 
 Note: If both BW and IOPS rules are specified for a device, then IO is
       subjectd to both the constraints.
index 84d2623..de91c0d 100644 (file)
@@ -22,6 +22,10 @@ Supported chips:
     Prefix: 'f71869'
     Addresses scanned: none, address read from Super I/O config space
     Datasheet: Available from the Fintek website
+  * Fintek F71869A
+    Prefix: 'f71869a'
+    Addresses scanned: none, address read from Super I/O config space
+    Datasheet: Not public
   * Fintek F71882FG and F71883FG
     Prefix: 'f71882fg'
     Addresses scanned: none, address read from Super I/O config space
index 0393c89..a10f736 100644 (file)
@@ -9,8 +9,8 @@ Supported chips:
   Socket S1G3: Athlon II, Sempron, Turion II
 * AMD Family 11h processors:
   Socket S1G2: Athlon (X2), Sempron (X2), Turion X2 (Ultra)
-* AMD Family 12h processors: "Llano"
-* AMD Family 14h processors: "Brazos" (C/E/G-Series)
+* AMD Family 12h processors: "Llano" (E2/A4/A6/A8-Series)
+* AMD Family 14h processors: "Brazos" (C/E/G/Z-Series)
 * AMD Family 15h processors: "Bulldozer"
 
   Prefix: 'k10temp'
@@ -20,12 +20,16 @@ Supported chips:
     http://support.amd.com/us/Processor_TechDocs/31116.pdf
   BIOS and Kernel Developer's Guide (BKDG) for AMD Family 11h Processors:
     http://support.amd.com/us/Processor_TechDocs/41256.pdf
+  BIOS and Kernel Developer's Guide (BKDG) for AMD Family 12h Processors:
+    http://support.amd.com/us/Processor_TechDocs/41131.pdf
   BIOS and Kernel Developer's Guide (BKDG) for AMD Family 14h Models 00h-0Fh Processors:
     http://support.amd.com/us/Processor_TechDocs/43170.pdf
   Revision Guide for AMD Family 10h Processors:
     http://support.amd.com/us/Processor_TechDocs/41322.pdf
   Revision Guide for AMD Family 11h Processors:
     http://support.amd.com/us/Processor_TechDocs/41788.pdf
+  Revision Guide for AMD Family 12h Processors:
+    http://support.amd.com/us/Processor_TechDocs/44739.pdf
   Revision Guide for AMD Family 14h Models 00h-0Fh Processors:
     http://support.amd.com/us/Processor_TechDocs/47534.pdf
   AMD Family 11h Processor Power and Thermal Data Sheet for Notebooks:
index 22accb3..b24875b 100644 (file)
@@ -501,13 +501,29 @@ helper functions described in Section 4.  In that case, pm_runtime_resume()
 should be used.  Of course, for this purpose the device's run-time PM has to be
 enabled earlier by calling pm_runtime_enable().
 
-If the device bus type's or driver's ->probe() or ->remove() callback runs
+If the device bus type's or driver's ->probe() callback runs
 pm_runtime_suspend() or pm_runtime_idle() or their asynchronous counterparts,
 they will fail returning -EAGAIN, because the device's usage counter is
-incremented by the core before executing ->probe() and ->remove().  Still, it
-may be desirable to suspend the device as soon as ->probe() or ->remove() has
-finished, so the PM core uses pm_runtime_idle_sync() to invoke the
-subsystem-level idle callback for the device at that time.
+incremented by the driver core before executing ->probe().  Still, it may be
+desirable to suspend the device as soon as ->probe() has finished, so the driver
+core uses pm_runtime_put_sync() to invoke the subsystem-level idle callback for
+the device at that time.
+
+Moreover, the driver core prevents runtime PM callbacks from racing with the bus
+notifier callback in __device_release_driver(), which is necessary, because the
+notifier is used by some subsystems to carry out operations affecting the
+runtime PM functionality.  It does so by calling pm_runtime_get_sync() before
+driver_sysfs_remove() and the BUS_NOTIFY_UNBIND_DRIVER notifications.  This
+resumes the device if it's in the suspended state and prevents it from
+being suspended again while those routines are being executed.
+
+To allow bus types and drivers to put devices into the suspended state by
+calling pm_runtime_suspend() from their ->remove() routines, the driver core
+executes pm_runtime_put_sync() after running the BUS_NOTIFY_UNBIND_DRIVER
+notifications in __device_release_driver().  This requires bus types and
+drivers to make their ->remove() callbacks avoid races with runtime PM directly,
+but also it allows of more flexibility in the handling of devices during the
+removal of their drivers.
 
 The user space can effectively disallow the driver of the device to power manage
 it at run time by changing the value of its /sys/devices/.../power/control
index ae563fa..9820e89 100644 (file)
@@ -2197,7 +2197,7 @@ F:        drivers/acpi/dock.c
 DOCUMENTATION
 M:     Randy Dunlap <rdunlap@xenotime.net>
 L:     linux-doc@vger.kernel.org
-T:     quilt oss.oracle.com/~rdunlap/kernel-doc-patches/current/
+T:     quilt http://userweb.kernel.org/~rdunlap/kernel-doc-patches/current/
 S:     Maintained
 F:     Documentation/
 
@@ -6733,6 +6733,7 @@ F:        fs/fat/
 VIDEOBUF2 FRAMEWORK
 M:     Pawel Osciak <pawel@osciak.com>
 M:     Marek Szyprowski <m.szyprowski@samsung.com>
+M:     Kyungmin Park <kyungmin.park@samsung.com>
 L:     linux-media@vger.kernel.org
 S:     Maintained
 F:     drivers/media/video/videobuf2-*
index dc67046..86f47a0 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 3
 PATCHLEVEL = 0
 SUBLEVEL = 0
-EXTRAVERSION = -rc5
+EXTRAVERSION = -rc6
 NAME = Sneaky Weasel
 
 # *DOCUMENTATION*
diff --git a/README b/README
index 8510017..0d5a7dd 100644 (file)
--- a/README
+++ b/README
@@ -1,6 +1,6 @@
-       Linux kernel release 2.6.xx <http://kernel.org/>
+       Linux kernel release 3.x <http://kernel.org/>
 
-These are the release notes for Linux version 2.6.  Read them carefully,
+These are the release notes for Linux version 3.  Read them carefully,
 as they tell you what this is all about, explain how to install the
 kernel, and what to do if something goes wrong. 
 
@@ -62,10 +62,10 @@ INSTALLING the kernel source:
    directory where you have permissions (eg. your home directory) and
    unpack it:
 
-               gzip -cd linux-2.6.XX.tar.gz | tar xvf -
+               gzip -cd linux-3.X.tar.gz | tar xvf -
 
    or
-               bzip2 -dc linux-2.6.XX.tar.bz2 | tar xvf -
+               bzip2 -dc linux-3.X.tar.bz2 | tar xvf -
 
 
    Replace "XX" with the version number of the latest kernel.
@@ -75,15 +75,15 @@ INSTALLING the kernel source:
    files.  They should match the library, and not get messed up by
    whatever the kernel-du-jour happens to be.
 
- - You can also upgrade between 2.6.xx releases by patching.  Patches are
+ - You can also upgrade between 3.x releases by patching.  Patches are
    distributed in the traditional gzip and the newer bzip2 format.  To
    install by patching, get all the newer patch files, enter the
-   top level directory of the kernel source (linux-2.6.xx) and execute:
+   top level directory of the kernel source (linux-3.x) and execute:
 
-               gzip -cd ../patch-2.6.xx.gz | patch -p1
+               gzip -cd ../patch-3.x.gz | patch -p1
 
    or
-               bzip2 -dc ../patch-2.6.xx.bz2 | patch -p1
+               bzip2 -dc ../patch-3.x.bz2 | patch -p1
 
    (repeat xx for all versions bigger than the version of your current
    source tree, _in_order_) and you should be ok.  You may want to remove
@@ -91,9 +91,9 @@ INSTALLING the kernel source:
    failed patches (xxx# or xxx.rej). If there are, either you or me has
    made a mistake.
 
-   Unlike patches for the 2.6.x kernels, patches for the 2.6.x.y kernels
+   Unlike patches for the 3.x kernels, patches for the 3.x.y kernels
    (also known as the -stable kernels) are not incremental but instead apply
-   directly to the base 2.6.x kernel.  Please read
+   directly to the base 3.x kernel.  Please read
    Documentation/applying-patches.txt for more information.
 
    Alternatively, the script patch-kernel can be used to automate this
@@ -107,14 +107,14 @@ INSTALLING the kernel source:
    an alternative directory can be specified as the second argument.
 
  - If you are upgrading between releases using the stable series patches
-   (for example, patch-2.6.xx.y), note that these "dot-releases" are
-   not incremental and must be applied to the 2.6.xx base tree. For
-   example, if your base kernel is 2.6.12 and you want to apply the
-   2.6.12.3 patch, you do not and indeed must not first apply the
-   2.6.12.1 and 2.6.12.2 patches. Similarly, if you are running kernel
-   version 2.6.12.2 and want to jump to 2.6.12.3, you must first
-   reverse the 2.6.12.2 patch (that is, patch -R) _before_ applying
-   the 2.6.12.3 patch.
+   (for example, patch-3.x.y), note that these "dot-releases" are
+   not incremental and must be applied to the 3.x base tree. For
+   example, if your base kernel is 3.0 and you want to apply the
+   3.0.3 patch, you do not and indeed must not first apply the
+   3.0.1 and 3.0.2 patches. Similarly, if you are running kernel
+   version 3.0.2 and want to jump to 3.0.3, you must first
+   reverse the 3.0.2 patch (that is, patch -R) _before_ applying
+   the 3.0.3 patch.
    You can read more on this in Documentation/applying-patches.txt
 
  - Make sure you have no stale .o files and dependencies lying around:
@@ -126,7 +126,7 @@ INSTALLING the kernel source:
 
 SOFTWARE REQUIREMENTS
 
-   Compiling and running the 2.6.xx kernels requires up-to-date
+   Compiling and running the 3.x kernels requires up-to-date
    versions of various software packages.  Consult
    Documentation/Changes for the minimum version numbers required
    and how to get updates for these packages.  Beware that using
@@ -142,11 +142,11 @@ BUILD directory for the kernel:
    Using the option "make O=output/dir" allow you to specify an alternate
    place for the output files (including .config).
    Example:
-     kernel source code:       /usr/src/linux-2.6.N
+     kernel source code:       /usr/src/linux-3.N
      build directory:          /home/name/build/kernel
 
    To configure and build the kernel use:
-   cd /usr/src/linux-2.6.N
+   cd /usr/src/linux-3.N
    make O=/home/name/build/kernel menuconfig
    make O=/home/name/build/kernel
    sudo make O=/home/name/build/kernel modules_install install
index 17fae4a..f1013d0 100644 (file)
@@ -223,15 +223,15 @@ static struct clk *periph_clocks[] __initdata = {
 };
 
 static struct clk_lookup periph_clocks_lookups[] = {
-       CLKDEV_CON_DEV_ID("hclk", "atmel_usba_udc.0", &utmi_clk),
-       CLKDEV_CON_DEV_ID("pclk", "atmel_usba_udc.0", &udphs_clk),
+       CLKDEV_CON_DEV_ID("hclk", "atmel_usba_udc", &utmi_clk),
+       CLKDEV_CON_DEV_ID("pclk", "atmel_usba_udc", &udphs_clk),
        CLKDEV_CON_DEV_ID("mci_clk", "at91_mci.0", &mmc0_clk),
        CLKDEV_CON_DEV_ID("mci_clk", "at91_mci.1", &mmc1_clk),
        CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.0", &spi0_clk),
        CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.1", &spi1_clk),
        CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tcb_clk),
-       CLKDEV_CON_DEV_ID("ssc", "ssc.0", &ssc0_clk),
-       CLKDEV_CON_DEV_ID("ssc", "ssc.1", &ssc1_clk),
+       CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
+       CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
 };
 
 static struct clk_lookup usart_clocks_lookups[] = {
index cd850ed..dba0d8d 100644 (file)
@@ -1220,7 +1220,7 @@ void __init at91_set_serial_console(unsigned portnr)
 {
        if (portnr < ATMEL_MAX_UART) {
                atmel_default_console_device = at91_uarts[portnr];
-               at91cap9_set_console_clock(portnr);
+               at91cap9_set_console_clock(at91_uarts[portnr]->id);
        }
 }
 
index b228ce9..83a1a3f 100644 (file)
@@ -199,9 +199,9 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.1", &tc3_clk),
        CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.1", &tc4_clk),
        CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.1", &tc5_clk),
-       CLKDEV_CON_DEV_ID("ssc", "ssc.0", &ssc0_clk),
-       CLKDEV_CON_DEV_ID("ssc", "ssc.1", &ssc1_clk),
-       CLKDEV_CON_DEV_ID("ssc", "ssc.2", &ssc2_clk),
+       CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
+       CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
+       CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk),
 };
 
 static struct clk_lookup usart_clocks_lookups[] = {
index a0ba475..7227755 100644 (file)
@@ -1135,7 +1135,7 @@ void __init at91_set_serial_console(unsigned portnr)
 {
        if (portnr < ATMEL_MAX_UART) {
                atmel_default_console_device = at91_uarts[portnr];
-               at91rm9200_set_console_clock(portnr);
+               at91rm9200_set_console_clock(at91_uarts[portnr]->id);
        }
 }
 
index 1fdeb90..39f81f4 100644 (file)
@@ -1173,7 +1173,7 @@ void __init at91_set_serial_console(unsigned portnr)
 {
        if (portnr < ATMEL_MAX_UART) {
                atmel_default_console_device = at91_uarts[portnr];
-               at91sam9260_set_console_clock(portnr);
+               at91sam9260_set_console_clock(at91_uarts[portnr]->id);
        }
 }
 
index 3eb4538..5004bf0 100644 (file)
@@ -1013,7 +1013,7 @@ void __init at91_set_serial_console(unsigned portnr)
 {
        if (portnr < ATMEL_MAX_UART) {
                atmel_default_console_device = at91_uarts[portnr];
-               at91sam9261_set_console_clock(portnr);
+               at91sam9261_set_console_clock(at91_uarts[portnr]->id);
        }
 }
 
index ffe081b..a050f41 100644 (file)
@@ -1395,7 +1395,7 @@ void __init at91_set_serial_console(unsigned portnr)
 {
        if (portnr < ATMEL_MAX_UART) {
                atmel_default_console_device = at91_uarts[portnr];
-               at91sam9263_set_console_clock(portnr);
+               at91sam9263_set_console_clock(at91_uarts[portnr]->id);
        }
 }
 
index 2bb6ff9..11e2141 100644 (file)
@@ -217,11 +217,11 @@ static struct clk *periph_clocks[] __initdata = {
 static struct clk_lookup periph_clocks_lookups[] = {
        /* One additional fake clock for ohci */
        CLKDEV_CON_ID("ohci_clk", &uhphs_clk),
-       CLKDEV_CON_DEV_ID("ehci_clk", "atmel-ehci.0", &uhphs_clk),
-       CLKDEV_CON_DEV_ID("hclk", "atmel_usba_udc.0", &utmi_clk),
-       CLKDEV_CON_DEV_ID("pclk", "atmel_usba_udc.0", &udphs_clk),
-       CLKDEV_CON_DEV_ID("mci_clk", "at91_mci.0", &mmc0_clk),
-       CLKDEV_CON_DEV_ID("mci_clk", "at91_mci.1", &mmc1_clk),
+       CLKDEV_CON_DEV_ID("ehci_clk", "atmel-ehci", &uhphs_clk),
+       CLKDEV_CON_DEV_ID("hclk", "atmel_usba_udc", &utmi_clk),
+       CLKDEV_CON_DEV_ID("pclk", "atmel_usba_udc", &udphs_clk),
+       CLKDEV_CON_DEV_ID("mci_clk", "atmel_mci.0", &mmc0_clk),
+       CLKDEV_CON_DEV_ID("mci_clk", "atmel_mci.1", &mmc1_clk),
        CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.0", &spi0_clk),
        CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.1", &spi1_clk),
        CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tcb0_clk),
index 0567486..600bffb 100644 (file)
@@ -1550,7 +1550,7 @@ void __init at91_set_serial_console(unsigned portnr)
 {
        if (portnr < ATMEL_MAX_UART) {
                atmel_default_console_device = at91_uarts[portnr];
-               at91sam9g45_set_console_clock(portnr);
+               at91sam9g45_set_console_clock(at91_uarts[portnr]->id);
        }
 }
 
index 1a40f16..29dff18 100644 (file)
@@ -191,8 +191,8 @@ static struct clk *periph_clocks[] __initdata = {
 };
 
 static struct clk_lookup periph_clocks_lookups[] = {
-       CLKDEV_CON_DEV_ID("hclk", "atmel_usba_udc.0", &utmi_clk),
-       CLKDEV_CON_DEV_ID("pclk", "atmel_usba_udc.0", &udphs_clk),
+       CLKDEV_CON_DEV_ID("hclk", "atmel_usba_udc", &utmi_clk),
+       CLKDEV_CON_DEV_ID("pclk", "atmel_usba_udc", &udphs_clk),
        CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tc0_clk),
        CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.0", &tc1_clk),
        CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.0", &tc2_clk),
index c296045..aacb19d 100644 (file)
@@ -1168,7 +1168,7 @@ void __init at91_set_serial_console(unsigned portnr)
 {
        if (portnr < ATMEL_MAX_UART) {
                atmel_default_console_device = at91_uarts[portnr];
-               at91sam9rl_set_console_clock(portnr);
+               at91sam9rl_set_console_clock(at91_uarts[portnr]->id);
        }
 }
 
index 1904fdf..cdb65d4 100644 (file)
@@ -215,7 +215,7 @@ static void __init cap9adk_add_device_nand(void)
        csa = at91_sys_read(AT91_MATRIX_EBICSA);
        at91_sys_write(AT91_MATRIX_EBICSA, csa | AT91_MATRIX_EBI_VDDIOMSEL_3_3V);
 
-       cap9adk_nand_data.bus_width_16 = !board_have_nand_8bit();
+       cap9adk_nand_data.bus_width_16 = board_have_nand_16bit();
        /* setup bus-width (8 or 16) */
        if (cap9adk_nand_data.bus_width_16)
                cap9adk_nand_smc_config.mode |= AT91_SMC_DBW_16;
index d600dc1..5c24074 100644 (file)
@@ -214,7 +214,7 @@ static struct sam9_smc_config __initdata ek_nand_smc_config = {
 
 static void __init ek_add_device_nand(void)
 {
-       ek_nand_data.bus_width_16 = !board_have_nand_8bit();
+       ek_nand_data.bus_width_16 = board_have_nand_16bit();
        /* setup bus-width (8 or 16) */
        if (ek_nand_data.bus_width_16)
                ek_nand_smc_config.mode |= AT91_SMC_DBW_16;
index f897f84..b60c22b 100644 (file)
@@ -220,7 +220,7 @@ static struct sam9_smc_config __initdata ek_nand_smc_config = {
 
 static void __init ek_add_device_nand(void)
 {
-       ek_nand_data.bus_width_16 = !board_have_nand_8bit();
+       ek_nand_data.bus_width_16 = board_have_nand_16bit();
        /* setup bus-width (8 or 16) */
        if (ek_nand_data.bus_width_16)
                ek_nand_smc_config.mode |= AT91_SMC_DBW_16;
index 605b26f..9bbdc92 100644 (file)
@@ -221,7 +221,7 @@ static struct sam9_smc_config __initdata ek_nand_smc_config = {
 
 static void __init ek_add_device_nand(void)
 {
-       ek_nand_data.bus_width_16 = !board_have_nand_8bit();
+       ek_nand_data.bus_width_16 = board_have_nand_16bit();
        /* setup bus-width (8 or 16) */
        if (ek_nand_data.bus_width_16)
                ek_nand_smc_config.mode |= AT91_SMC_DBW_16;
index 7624cf0..1325a50 100644 (file)
@@ -198,7 +198,7 @@ static struct sam9_smc_config __initdata ek_nand_smc_config = {
 
 static void __init ek_add_device_nand(void)
 {
-       ek_nand_data.bus_width_16 = !board_have_nand_8bit();
+       ek_nand_data.bus_width_16 = board_have_nand_16bit();
        /* setup bus-width (8 or 16) */
        if (ek_nand_data.bus_width_16)
                ek_nand_smc_config.mode |= AT91_SMC_DBW_16;
index 063c95d..33eaa13 100644 (file)
@@ -178,7 +178,7 @@ static struct sam9_smc_config __initdata ek_nand_smc_config = {
 
 static void __init ek_add_device_nand(void)
 {
-       ek_nand_data.bus_width_16 = !board_have_nand_8bit();
+       ek_nand_data.bus_width_16 = board_have_nand_16bit();
        /* setup bus-width (8 or 16) */
        if (ek_nand_data.bus_width_16)
                ek_nand_smc_config.mode |= AT91_SMC_DBW_16;
index b855ee7..8f48660 100644 (file)
  * the 16-31 bit are reserved for at91 generic information
  *
  * bit 31:
- *     0 => nand 16 bit
- *     1 => nand 8 bit
+ *     0 => nand 8 bit
+ *     1 => nand 16 bit
  */
-#define BOARD_HAVE_NAND_8BIT   (1 << 31)
-static int inline board_have_nand_8bit(void)
+#define BOARD_HAVE_NAND_16BIT  (1 << 31)
+static inline int board_have_nand_16bit(void)
 {
-       return system_rev & BOARD_HAVE_NAND_8BIT;
+       return system_rev & BOARD_HAVE_NAND_16BIT;
 }
 
 #endif /* __ARCH_SYSTEM_REV_H__ */
index 8214724..fe00830 100644 (file)
@@ -333,6 +333,7 @@ static int xen_register_pirq(u32 gsi, int triggering)
        struct physdev_map_pirq map_irq;
        int shareable = 0;
        char *name;
+       bool gsi_override = false;
 
        if (!xen_pv_domain())
                return -1;
@@ -349,11 +350,32 @@ static int xen_register_pirq(u32 gsi, int triggering)
        if (pirq < 0)
                goto out;
 
-       irq = xen_bind_pirq_gsi_to_irq(gsi, pirq, shareable, name);
+       /* Before we bind the GSI to a Linux IRQ, check whether
+        * we need to override it with bus_irq (IRQ) value. Usually for
+        * IRQs below IRQ_LEGACY_IRQ this holds IRQ == GSI, as so:
+        *  ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 9 low level)
+        * but there are oddballs where the IRQ != GSI:
+        *  ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 20 low level)
+        * which ends up being: gsi_to_irq[9] == 20
+        * (which is what acpi_gsi_to_irq ends up calling when starting the
+        * the ACPI interpreter and keels over since IRQ 9 has not been
+        * setup as we had setup IRQ 20 for it).
+        */
+       if (gsi == acpi_sci_override_gsi) {
+               /* Check whether the GSI != IRQ */
+               acpi_gsi_to_irq(gsi, &irq);
+               if (irq != gsi)
+                       /* Bugger, we MUST have that IRQ. */
+                       gsi_override = true;
+       }
+       if (gsi_override)
+               irq = xen_bind_pirq_gsi_to_irq(irq, pirq, shareable, name);
+       else
+               irq = xen_bind_pirq_gsi_to_irq(gsi, pirq, shareable, name);
        if (irq < 0)
                goto out;
 
-       printk(KERN_DEBUG "xen: --> pirq=%d -> irq=%d\n", pirq, irq);
+       printk(KERN_DEBUG "xen: --> pirq=%d -> irq=%d (gsi=%d)\n", pirq, irq, gsi);
 
        map_irq.domid = DOMID_SELF;
        map_irq.type = MAP_PIRQ_TYPE_GSI;
index 673e968..0ccccb6 100644 (file)
@@ -1232,7 +1232,11 @@ static void xen_flush_tlb_others(const struct cpumask *cpus,
 {
        struct {
                struct mmuext_op op;
+#ifdef CONFIG_SMP
                DECLARE_BITMAP(mask, num_processors);
+#else
+               DECLARE_BITMAP(mask, NR_CPUS);
+#endif
        } *args;
        struct multicall_space mcs;
 
index 8d1ddfd..15097ca 100644 (file)
@@ -81,8 +81,10 @@ void tps65910_gpio_init(struct tps65910 *tps65910, int gpio_base)
        switch(tps65910_chip_id(tps65910)) {
        case TPS65910:
                tps65910->gpio.ngpio    = 6;
+               break;
        case TPS65911:
                tps65910->gpio.ngpio    = 9;
+               break;
        default:
                return;
        }
index 4d46441..0a893f7 100644 (file)
@@ -1207,13 +1207,17 @@ static int i915_context_status(struct seq_file *m, void *unused)
        if (ret)
                return ret;
 
-       seq_printf(m, "power context ");
-       describe_obj(m, dev_priv->pwrctx);
-       seq_printf(m, "\n");
+       if (dev_priv->pwrctx) {
+               seq_printf(m, "power context ");
+               describe_obj(m, dev_priv->pwrctx);
+               seq_printf(m, "\n");
+       }
 
-       seq_printf(m, "render context ");
-       describe_obj(m, dev_priv->renderctx);
-       seq_printf(m, "\n");
+       if (dev_priv->renderctx) {
+               seq_printf(m, "render context ");
+               describe_obj(m, dev_priv->renderctx);
+               seq_printf(m, "\n");
+       }
 
        mutex_unlock(&dev->mode_config.mutex);
 
index 2b79588..e178702 100644 (file)
@@ -1266,30 +1266,6 @@ static int i915_load_modeset_init(struct drm_device *dev)
 
        intel_modeset_gem_init(dev);
 
-       if (IS_IVYBRIDGE(dev)) {
-               /* Share pre & uninstall handlers with ILK/SNB */
-               dev->driver->irq_handler = ivybridge_irq_handler;
-               dev->driver->irq_preinstall = ironlake_irq_preinstall;
-               dev->driver->irq_postinstall = ivybridge_irq_postinstall;
-               dev->driver->irq_uninstall = ironlake_irq_uninstall;
-               dev->driver->enable_vblank = ivybridge_enable_vblank;
-               dev->driver->disable_vblank = ivybridge_disable_vblank;
-       } else if (HAS_PCH_SPLIT(dev)) {
-               dev->driver->irq_handler = ironlake_irq_handler;
-               dev->driver->irq_preinstall = ironlake_irq_preinstall;
-               dev->driver->irq_postinstall = ironlake_irq_postinstall;
-               dev->driver->irq_uninstall = ironlake_irq_uninstall;
-               dev->driver->enable_vblank = ironlake_enable_vblank;
-               dev->driver->disable_vblank = ironlake_disable_vblank;
-       } else {
-               dev->driver->irq_preinstall = i915_driver_irq_preinstall;
-               dev->driver->irq_postinstall = i915_driver_irq_postinstall;
-               dev->driver->irq_uninstall = i915_driver_irq_uninstall;
-               dev->driver->irq_handler = i915_driver_irq_handler;
-               dev->driver->enable_vblank = i915_enable_vblank;
-               dev->driver->disable_vblank = i915_disable_vblank;
-       }
-
        ret = drm_irq_install(dev);
        if (ret)
                goto cleanup_gem;
@@ -2017,12 +1993,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
        /* enable GEM by default */
        dev_priv->has_gem = 1;
 
-       dev->driver->get_vblank_counter = i915_get_vblank_counter;
-       dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
-       if (IS_G4X(dev) || IS_GEN5(dev) || IS_GEN6(dev) || IS_IVYBRIDGE(dev)) {
-               dev->max_vblank_count = 0xffffffff; /* full 32 bit counter */
-               dev->driver->get_vblank_counter = gm45_get_vblank_counter;
-       }
+       intel_irq_init(dev);
 
        /* Try to make sure MCHBAR is enabled before poking at it */
        intel_setup_mchbar(dev);
index 609358f..013d304 100644 (file)
@@ -765,14 +765,6 @@ static struct drm_driver driver = {
        .resume = i915_resume,
 
        .device_is_agp = i915_driver_device_is_agp,
-       .enable_vblank = i915_enable_vblank,
-       .disable_vblank = i915_disable_vblank,
-       .get_vblank_timestamp = i915_get_vblank_timestamp,
-       .get_scanout_position = i915_get_crtc_scanoutpos,
-       .irq_preinstall = i915_driver_irq_preinstall,
-       .irq_postinstall = i915_driver_irq_postinstall,
-       .irq_uninstall = i915_driver_irq_uninstall,
-       .irq_handler = i915_driver_irq_handler,
        .reclaim_buffers = drm_core_reclaim_buffers,
        .master_create = i915_master_create,
        .master_destroy = i915_master_destroy,
index eddabf6..f245c58 100644 (file)
@@ -997,8 +997,6 @@ extern unsigned int i915_enable_fbc;
 
 extern int i915_suspend(struct drm_device *dev, pm_message_t state);
 extern int i915_resume(struct drm_device *dev);
-extern void i915_save_display(struct drm_device *dev);
-extern void i915_restore_display(struct drm_device *dev);
 extern int i915_master_create(struct drm_device *dev, struct drm_master *master);
 extern void i915_master_destroy(struct drm_device *dev, struct drm_master *master);
 
@@ -1033,33 +1031,12 @@ extern int i915_irq_emit(struct drm_device *dev, void *data,
 extern int i915_irq_wait(struct drm_device *dev, void *data,
                         struct drm_file *file_priv);
 
-extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS);
-extern void i915_driver_irq_preinstall(struct drm_device * dev);
-extern int i915_driver_irq_postinstall(struct drm_device *dev);
-extern void i915_driver_irq_uninstall(struct drm_device * dev);
-
-extern irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS);
-extern void ironlake_irq_preinstall(struct drm_device *dev);
-extern int ironlake_irq_postinstall(struct drm_device *dev);
-extern void ironlake_irq_uninstall(struct drm_device *dev);
-
-extern irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS);
-extern void ivybridge_irq_preinstall(struct drm_device *dev);
-extern int ivybridge_irq_postinstall(struct drm_device *dev);
-extern void ivybridge_irq_uninstall(struct drm_device *dev);
+extern void intel_irq_init(struct drm_device *dev);
 
 extern int i915_vblank_pipe_set(struct drm_device *dev, void *data,
                                struct drm_file *file_priv);
 extern int i915_vblank_pipe_get(struct drm_device *dev, void *data,
                                struct drm_file *file_priv);
-extern int i915_enable_vblank(struct drm_device *dev, int crtc);
-extern void i915_disable_vblank(struct drm_device *dev, int crtc);
-extern int ironlake_enable_vblank(struct drm_device *dev, int crtc);
-extern void ironlake_disable_vblank(struct drm_device *dev, int crtc);
-extern int ivybridge_enable_vblank(struct drm_device *dev, int crtc);
-extern void ivybridge_disable_vblank(struct drm_device *dev, int crtc);
-extern u32 i915_get_vblank_counter(struct drm_device *dev, int crtc);
-extern u32 gm45_get_vblank_counter(struct drm_device *dev, int crtc);
 extern int i915_vblank_swap(struct drm_device *dev, void *data,
                            struct drm_file *file_priv);
 
@@ -1070,13 +1047,6 @@ void
 i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask);
 
 void intel_enable_asle (struct drm_device *dev);
-int i915_get_vblank_timestamp(struct drm_device *dev, int crtc,
-                             int *max_error,
-                             struct timeval *vblank_time,
-                             unsigned flags);
-
-int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe,
-                            int *vpos, int *hpos);
 
 #ifdef CONFIG_DEBUG_FS
 extern void i915_destroy_error_state(struct drm_device *dev);
index ae2b499..3b03f85 100644 (file)
@@ -152,7 +152,7 @@ i915_pipe_enabled(struct drm_device *dev, int pipe)
 /* Called from drm generic code, passed a 'crtc', which
  * we use as a pipe index
  */
-u32 i915_get_vblank_counter(struct drm_device *dev, int pipe)
+static u32 i915_get_vblank_counter(struct drm_device *dev, int pipe)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
        unsigned long high_frame;
@@ -184,7 +184,7 @@ u32 i915_get_vblank_counter(struct drm_device *dev, int pipe)
        return (high1 << 8) | low;
 }
 
-u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe)
+static u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
        int reg = PIPE_FRMCOUNT_GM45(pipe);
@@ -198,7 +198,7 @@ u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe)
        return I915_READ(reg);
 }
 
-int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe,
+static int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe,
                             int *vpos, int *hpos)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -264,7 +264,7 @@ int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe,
        return ret;
 }
 
-int i915_get_vblank_timestamp(struct drm_device *dev, int pipe,
+static int i915_get_vblank_timestamp(struct drm_device *dev, int pipe,
                              int *max_error,
                              struct timeval *vblank_time,
                              unsigned flags)
@@ -462,7 +462,7 @@ static void pch_irq_handler(struct drm_device *dev)
                DRM_DEBUG_DRIVER("PCH transcoder A underrun interrupt\n");
 }
 
-irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS)
+static irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS)
 {
        struct drm_device *dev = (struct drm_device *) arg;
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -550,7 +550,7 @@ done:
        return ret;
 }
 
-irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS)
+static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS)
 {
        struct drm_device *dev = (struct drm_device *) arg;
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -1209,7 +1209,7 @@ static void i915_pageflip_stall_check(struct drm_device *dev, int pipe)
        }
 }
 
-irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
+static irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
 {
        struct drm_device *dev = (struct drm_device *) arg;
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -1454,7 +1454,7 @@ int i915_irq_wait(struct drm_device *dev, void *data,
 /* Called from drm generic code, passed 'crtc' which
  * we use as a pipe index
  */
-int i915_enable_vblank(struct drm_device *dev, int pipe)
+static int i915_enable_vblank(struct drm_device *dev, int pipe)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
        unsigned long irqflags;
@@ -1478,7 +1478,7 @@ int i915_enable_vblank(struct drm_device *dev, int pipe)
        return 0;
 }
 
-int ironlake_enable_vblank(struct drm_device *dev, int pipe)
+static int ironlake_enable_vblank(struct drm_device *dev, int pipe)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
        unsigned long irqflags;
@@ -1494,7 +1494,7 @@ int ironlake_enable_vblank(struct drm_device *dev, int pipe)
        return 0;
 }
 
-int ivybridge_enable_vblank(struct drm_device *dev, int pipe)
+static int ivybridge_enable_vblank(struct drm_device *dev, int pipe)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
        unsigned long irqflags;
@@ -1513,7 +1513,7 @@ int ivybridge_enable_vblank(struct drm_device *dev, int pipe)
 /* Called from drm generic code, passed 'crtc' which
  * we use as a pipe index
  */
-void i915_disable_vblank(struct drm_device *dev, int pipe)
+static void i915_disable_vblank(struct drm_device *dev, int pipe)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
        unsigned long irqflags;
@@ -1529,7 +1529,7 @@ void i915_disable_vblank(struct drm_device *dev, int pipe)
        spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 }
 
-void ironlake_disable_vblank(struct drm_device *dev, int pipe)
+static void ironlake_disable_vblank(struct drm_device *dev, int pipe)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
        unsigned long irqflags;
@@ -1540,7 +1540,7 @@ void ironlake_disable_vblank(struct drm_device *dev, int pipe)
        spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 }
 
-void ivybridge_disable_vblank(struct drm_device *dev, int pipe)
+static void ivybridge_disable_vblank(struct drm_device *dev, int pipe)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
        unsigned long irqflags;
@@ -1728,7 +1728,7 @@ repeat:
 
 /* drm_dma.h hooks
 */
-void ironlake_irq_preinstall(struct drm_device *dev)
+static void ironlake_irq_preinstall(struct drm_device *dev)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 
@@ -1740,7 +1740,7 @@ void ironlake_irq_preinstall(struct drm_device *dev)
                INIT_WORK(&dev_priv->rps_work, gen6_pm_rps_work);
 
        I915_WRITE(HWSTAM, 0xeffe);
-       if (IS_GEN6(dev)) {
+       if (IS_GEN6(dev) || IS_GEN7(dev)) {
                /* Workaround stalls observed on Sandy Bridge GPUs by
                 * making the blitter command streamer generate a
                 * write to the Hardware Status Page for
@@ -1769,7 +1769,7 @@ void ironlake_irq_preinstall(struct drm_device *dev)
        POSTING_READ(SDEIER);
 }
 
-int ironlake_irq_postinstall(struct drm_device *dev)
+static int ironlake_irq_postinstall(struct drm_device *dev)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
        /* enable kind of interrupts always enabled */
@@ -1841,7 +1841,7 @@ int ironlake_irq_postinstall(struct drm_device *dev)
        return 0;
 }
 
-int ivybridge_irq_postinstall(struct drm_device *dev)
+static int ivybridge_irq_postinstall(struct drm_device *dev)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
        /* enable kind of interrupts always enabled */
@@ -1891,7 +1891,7 @@ int ivybridge_irq_postinstall(struct drm_device *dev)
        return 0;
 }
 
-void i915_driver_irq_preinstall(struct drm_device * dev)
+static void i915_driver_irq_preinstall(struct drm_device * dev)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
        int pipe;
@@ -1918,7 +1918,7 @@ void i915_driver_irq_preinstall(struct drm_device * dev)
  * Must be called after intel_modeset_init or hotplug interrupts won't be
  * enabled correctly.
  */
-int i915_driver_irq_postinstall(struct drm_device *dev)
+static int i915_driver_irq_postinstall(struct drm_device *dev)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
        u32 enable_mask = I915_INTERRUPT_ENABLE_FIX | I915_INTERRUPT_ENABLE_VAR;
@@ -1994,7 +1994,7 @@ int i915_driver_irq_postinstall(struct drm_device *dev)
        return 0;
 }
 
-void ironlake_irq_uninstall(struct drm_device *dev)
+static void ironlake_irq_uninstall(struct drm_device *dev)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 
@@ -2014,7 +2014,7 @@ void ironlake_irq_uninstall(struct drm_device *dev)
        I915_WRITE(GTIIR, I915_READ(GTIIR));
 }
 
-void i915_driver_irq_uninstall(struct drm_device * dev)
+static void i915_driver_irq_uninstall(struct drm_device * dev)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
        int pipe;
@@ -2040,3 +2040,41 @@ void i915_driver_irq_uninstall(struct drm_device * dev)
                           I915_READ(PIPESTAT(pipe)) & 0x8000ffff);
        I915_WRITE(IIR, I915_READ(IIR));
 }
+
+void intel_irq_init(struct drm_device *dev)
+{
+       dev->driver->get_vblank_counter = i915_get_vblank_counter;
+       dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
+       if (IS_G4X(dev) || IS_GEN5(dev) || IS_GEN6(dev) || IS_IVYBRIDGE(dev)) {
+               dev->max_vblank_count = 0xffffffff; /* full 32 bit counter */
+               dev->driver->get_vblank_counter = gm45_get_vblank_counter;
+       }
+
+
+       dev->driver->get_vblank_timestamp = i915_get_vblank_timestamp;
+       dev->driver->get_scanout_position = i915_get_crtc_scanoutpos;
+
+       if (IS_IVYBRIDGE(dev)) {
+               /* Share pre & uninstall handlers with ILK/SNB */
+               dev->driver->irq_handler = ivybridge_irq_handler;
+               dev->driver->irq_preinstall = ironlake_irq_preinstall;
+               dev->driver->irq_postinstall = ivybridge_irq_postinstall;
+               dev->driver->irq_uninstall = ironlake_irq_uninstall;
+               dev->driver->enable_vblank = ivybridge_enable_vblank;
+               dev->driver->disable_vblank = ivybridge_disable_vblank;
+       } else if (HAS_PCH_SPLIT(dev)) {
+               dev->driver->irq_handler = ironlake_irq_handler;
+               dev->driver->irq_preinstall = ironlake_irq_preinstall;
+               dev->driver->irq_postinstall = ironlake_irq_postinstall;
+               dev->driver->irq_uninstall = ironlake_irq_uninstall;
+               dev->driver->enable_vblank = ironlake_enable_vblank;
+               dev->driver->disable_vblank = ironlake_disable_vblank;
+       } else {
+               dev->driver->irq_preinstall = i915_driver_irq_preinstall;
+               dev->driver->irq_postinstall = i915_driver_irq_postinstall;
+               dev->driver->irq_uninstall = i915_driver_irq_uninstall;
+               dev->driver->irq_handler = i915_driver_irq_handler;
+               dev->driver->enable_vblank = i915_enable_vblank;
+               dev->driver->disable_vblank = i915_disable_vblank;
+       }
+}
index e8152d2..5257cfc 100644 (file)
@@ -597,7 +597,7 @@ static void i915_restore_modeset_reg(struct drm_device *dev)
        return;
 }
 
-void i915_save_display(struct drm_device *dev)
+static void i915_save_display(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
 
@@ -678,7 +678,6 @@ void i915_save_display(struct drm_device *dev)
        }
 
        /* VGA state */
-       mutex_lock(&dev->struct_mutex);
        dev_priv->saveVGA0 = I915_READ(VGA0);
        dev_priv->saveVGA1 = I915_READ(VGA1);
        dev_priv->saveVGA_PD = I915_READ(VGA_PD);
@@ -688,10 +687,9 @@ void i915_save_display(struct drm_device *dev)
                dev_priv->saveVGACNTRL = I915_READ(VGACNTRL);
 
        i915_save_vga(dev);
-       mutex_unlock(&dev->struct_mutex);
 }
 
-void i915_restore_display(struct drm_device *dev)
+static void i915_restore_display(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
 
@@ -783,7 +781,6 @@ void i915_restore_display(struct drm_device *dev)
        else
                I915_WRITE(VGACNTRL, dev_priv->saveVGACNTRL);
 
-       mutex_lock(&dev->struct_mutex);
        I915_WRITE(VGA0, dev_priv->saveVGA0);
        I915_WRITE(VGA1, dev_priv->saveVGA1);
        I915_WRITE(VGA_PD, dev_priv->saveVGA_PD);
@@ -791,7 +788,6 @@ void i915_restore_display(struct drm_device *dev)
        udelay(150);
 
        i915_restore_vga(dev);
-       mutex_unlock(&dev->struct_mutex);
 }
 
 int i915_save_state(struct drm_device *dev)
@@ -801,6 +797,8 @@ int i915_save_state(struct drm_device *dev)
 
        pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB);
 
+       mutex_lock(&dev->struct_mutex);
+
        /* Hardware status page */
        dev_priv->saveHWS = I915_READ(HWS_PGA);
 
@@ -840,6 +838,8 @@ int i915_save_state(struct drm_device *dev)
        for (i = 0; i < 3; i++)
                dev_priv->saveSWF2[i] = I915_READ(SWF30 + (i << 2));
 
+       mutex_unlock(&dev->struct_mutex);
+
        return 0;
 }
 
@@ -850,6 +850,8 @@ int i915_restore_state(struct drm_device *dev)
 
        pci_write_config_byte(dev->pdev, LBB, dev_priv->saveLBB);
 
+       mutex_lock(&dev->struct_mutex);
+
        /* Hardware status page */
        I915_WRITE(HWS_PGA, dev_priv->saveHWS);
 
@@ -867,6 +869,7 @@ int i915_restore_state(struct drm_device *dev)
                I915_WRITE(IER, dev_priv->saveIER);
                I915_WRITE(IMR, dev_priv->saveIMR);
        }
+       mutex_unlock(&dev->struct_mutex);
 
        intel_init_clock_gating(dev);
 
@@ -878,6 +881,8 @@ int i915_restore_state(struct drm_device *dev)
        if (IS_GEN6(dev))
                gen6_enable_rps(dev_priv);
 
+       mutex_lock(&dev->struct_mutex);
+
        /* Cache mode state */
        I915_WRITE (CACHE_MODE_0, dev_priv->saveCACHE_MODE_0 | 0xffff0000);
 
@@ -891,6 +896,8 @@ int i915_restore_state(struct drm_device *dev)
        for (i = 0; i < 3; i++)
                I915_WRITE(SWF30 + (i << 2), dev_priv->saveSWF2[i]);
 
+       mutex_unlock(&dev->struct_mutex);
+
        intel_i2c_reset(dev);
 
        return 0;
index 56a8e2a..9e2959b 100644 (file)
@@ -1409,6 +1409,11 @@ void intel_setup_overlay(struct drm_device *dev)
        overlay = kzalloc(sizeof(struct intel_overlay), GFP_KERNEL);
        if (!overlay)
                return;
+
+       mutex_lock(&dev->struct_mutex);
+       if (WARN_ON(dev_priv->overlay))
+               goto out_free;
+
        overlay->dev = dev;
 
        reg_bo = i915_gem_alloc_object(dev, PAGE_SIZE);
@@ -1416,8 +1421,6 @@ void intel_setup_overlay(struct drm_device *dev)
                goto out_free;
        overlay->reg_bo = reg_bo;
 
-       mutex_lock(&dev->struct_mutex);
-
        if (OVERLAY_NEEDS_PHYSICAL(dev)) {
                ret = i915_gem_attach_phys_object(dev, reg_bo,
                                                  I915_GEM_PHYS_OVERLAY_REGS,
@@ -1442,8 +1445,6 @@ void intel_setup_overlay(struct drm_device *dev)
                 }
        }
 
-       mutex_unlock(&dev->struct_mutex);
-
        /* init all values */
        overlay->color_key = 0x0101fe;
        overlay->brightness = -19;
@@ -1452,7 +1453,7 @@ void intel_setup_overlay(struct drm_device *dev)
 
        regs = intel_overlay_map_regs(overlay);
        if (!regs)
-               goto out_free_bo;
+               goto out_unpin_bo;
 
        memset(regs, 0, sizeof(struct overlay_registers));
        update_polyphase_filter(regs);
@@ -1461,15 +1462,17 @@ void intel_setup_overlay(struct drm_device *dev)
        intel_overlay_unmap_regs(overlay, regs);
 
        dev_priv->overlay = overlay;
+       mutex_unlock(&dev->struct_mutex);
        DRM_INFO("initialized overlay support\n");
        return;
 
 out_unpin_bo:
-       i915_gem_object_unpin(reg_bo);
+       if (!OVERLAY_NEEDS_PHYSICAL(dev))
+               i915_gem_object_unpin(reg_bo);
 out_free_bo:
        drm_gem_object_unreference(&reg_bo->base);
-       mutex_unlock(&dev->struct_mutex);
 out_free:
+       mutex_unlock(&dev->struct_mutex);
        kfree(overlay);
        return;
 }
index 144f79a..731acea 100644 (file)
@@ -371,7 +371,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
                engine->vram.flags_valid        = nv50_vram_flags_valid;
                break;
        case 0xC0:
-       case 0xD0:
                engine->instmem.init            = nvc0_instmem_init;
                engine->instmem.takedown        = nvc0_instmem_takedown;
                engine->instmem.suspend         = nvc0_instmem_suspend;
@@ -923,7 +922,6 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)
                dev_priv->card_type = NV_50;
                break;
        case 0xc0:
-       case 0xd0:
                dev_priv->card_type = NV_C0;
                break;
        default:
index 12d2fdc..e8a5ffb 100644 (file)
@@ -2248,7 +2248,10 @@ int evergreen_mc_init(struct radeon_device *rdev)
 
        /* Get VRAM informations */
        rdev->mc.vram_is_ddr = true;
-       tmp = RREG32(MC_ARB_RAMCFG);
+       if (rdev->flags & RADEON_IS_IGP)
+               tmp = RREG32(FUS_MC_ARB_RAMCFG);
+       else
+               tmp = RREG32(MC_ARB_RAMCFG);
        if (tmp & CHANSIZE_OVERRIDE) {
                chansize = 16;
        } else if (tmp & CHANSIZE_MASK) {
index 9736746..4672869 100644 (file)
 #define        CGTS_USER_TCC_DISABLE                           0x914C
 #define                TCC_DISABLE_MASK                                0xFFFF0000
 #define                TCC_DISABLE_SHIFT                               16
-#define        CGTS_SM_CTRL_REG                                0x915C
+#define        CGTS_SM_CTRL_REG                                0x9150
 #define                OVERRIDE                                (1 << 21)
 
 #define        TA_CNTL_AUX                                     0x9508
index 6f508ff..8bb347d 100644 (file)
@@ -575,6 +575,12 @@ static void rv770_program_channel_remap(struct radeon_device *rdev)
        else
                tcp_chan_steer = 0x00fac688;
 
+       /* RV770 CE has special chremap setup */
+       if (rdev->pdev->device == 0x944e) {
+               tcp_chan_steer = 0x00b08b08;
+               mc_shared_chremap = 0x00b08b08;
+       }
+
        WREG32(TCP_CHAN_STEER, tcp_chan_steer);
        WREG32(MC_SHARED_CHREMAP, mc_shared_chremap);
 }
index 16db83c..5f888f7 100644 (file)
@@ -333,7 +333,7 @@ config SENSORS_F71882FG
            F71858FG
            F71862FG
            F71863FG
-           F71869F/E
+           F71869F/E/A
            F71882FG
            F71883FG
            F71889FG/ED/A
index c2ee204..b9b7caf 100644 (file)
@@ -32,6 +32,7 @@ static int adm1275_probe(struct i2c_client *client,
                         const struct i2c_device_id *id)
 {
        int config;
+       int ret;
        struct pmbus_driver_info *info;
 
        if (!i2c_check_functionality(client->adapter,
@@ -43,8 +44,10 @@ static int adm1275_probe(struct i2c_client *client,
                return -ENOMEM;
 
        config = i2c_smbus_read_byte_data(client, ADM1275_PMON_CONFIG);
-       if (config < 0)
-               return config;
+       if (config < 0) {
+               ret = config;
+               goto err_mem;
+       }
 
        info->pages = 1;
        info->direct[PSC_VOLTAGE_IN] = true;
@@ -76,7 +79,14 @@ static int adm1275_probe(struct i2c_client *client,
        else
                info->func[0] |= PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT;
 
-       return pmbus_do_probe(client, id, info);
+       ret = pmbus_do_probe(client, id, info);
+       if (ret)
+               goto err_mem;
+       return 0;
+
+err_mem:
+       kfree(info);
+       return ret;
 }
 
 static int adm1275_remove(struct i2c_client *client)
index e0ef323..0064432 100644 (file)
@@ -78,8 +78,9 @@ static u16 emc6w201_read16(struct i2c_client *client, u8 reg)
 
        lsb = i2c_smbus_read_byte_data(client, reg);
        msb = i2c_smbus_read_byte_data(client, reg + 1);
-       if (lsb < 0 || msb < 0) {
-               dev_err(&client->dev, "16-bit read failed at 0x%02x\n", reg);
+       if (unlikely(lsb < 0 || msb < 0)) {
+               dev_err(&client->dev, "%d-bit %s failed at 0x%02x\n",
+                       16, "read", reg);
                return 0xFFFF;  /* Arbitrary value */
        }
 
@@ -95,10 +96,39 @@ static int emc6w201_write16(struct i2c_client *client, u8 reg, u16 val)
        int err;
 
        err = i2c_smbus_write_byte_data(client, reg, val & 0xff);
-       if (!err)
+       if (likely(!err))
                err = i2c_smbus_write_byte_data(client, reg + 1, val >> 8);
-       if (err < 0)
-               dev_err(&client->dev, "16-bit write failed at 0x%02x\n", reg);
+       if (unlikely(err < 0))
+               dev_err(&client->dev, "%d-bit %s failed at 0x%02x\n",
+                       16, "write", reg);
+
+       return err;
+}
+
+/* Read 8-bit value from register */
+static u8 emc6w201_read8(struct i2c_client *client, u8 reg)
+{
+       int val;
+
+       val = i2c_smbus_read_byte_data(client, reg);
+       if (unlikely(val < 0)) {
+               dev_err(&client->dev, "%d-bit %s failed at 0x%02x\n",
+                       8, "read", reg);
+               return 0x00;    /* Arbitrary value */
+       }
+
+       return val;
+}
+
+/* Write 8-bit value to register */
+static int emc6w201_write8(struct i2c_client *client, u8 reg, u8 val)
+{
+       int err;
+
+       err = i2c_smbus_write_byte_data(client, reg, val);
+       if (unlikely(err < 0))
+               dev_err(&client->dev, "%d-bit %s failed at 0x%02x\n",
+                       8, "write", reg);
 
        return err;
 }
@@ -114,25 +144,25 @@ static struct emc6w201_data *emc6w201_update_device(struct device *dev)
        if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
                for (nr = 0; nr < 6; nr++) {
                        data->in[input][nr] =
-                               i2c_smbus_read_byte_data(client,
+                               emc6w201_read8(client,
                                                EMC6W201_REG_IN(nr));
                        data->in[min][nr] =
-                               i2c_smbus_read_byte_data(client,
+                               emc6w201_read8(client,
                                                EMC6W201_REG_IN_LOW(nr));
                        data->in[max][nr] =
-                               i2c_smbus_read_byte_data(client,
+                               emc6w201_read8(client,
                                                EMC6W201_REG_IN_HIGH(nr));
                }
 
                for (nr = 0; nr < 6; nr++) {
                        data->temp[input][nr] =
-                               i2c_smbus_read_byte_data(client,
+                               emc6w201_read8(client,
                                                EMC6W201_REG_TEMP(nr));
                        data->temp[min][nr] =
-                               i2c_smbus_read_byte_data(client,
+                               emc6w201_read8(client,
                                                EMC6W201_REG_TEMP_LOW(nr));
                        data->temp[max][nr] =
-                               i2c_smbus_read_byte_data(client,
+                               emc6w201_read8(client,
                                                EMC6W201_REG_TEMP_HIGH(nr));
                }
 
@@ -192,7 +222,7 @@ static ssize_t set_in(struct device *dev, struct device_attribute *devattr,
 
        mutex_lock(&data->update_lock);
        data->in[sf][nr] = SENSORS_LIMIT(val, 0, 255);
-       err = i2c_smbus_write_byte_data(client, reg, data->in[sf][nr]);
+       err = emc6w201_write8(client, reg, data->in[sf][nr]);
        mutex_unlock(&data->update_lock);
 
        return err < 0 ? err : count;
@@ -229,7 +259,7 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *devattr,
 
        mutex_lock(&data->update_lock);
        data->temp[sf][nr] = SENSORS_LIMIT(val, -127, 128);
-       err = i2c_smbus_write_byte_data(client, reg, data->temp[sf][nr]);
+       err = emc6w201_write8(client, reg, data->temp[sf][nr]);
        mutex_unlock(&data->update_lock);
 
        return err < 0 ? err : count;
@@ -444,7 +474,7 @@ static int emc6w201_detect(struct i2c_client *client,
 
        /* Check configuration */
        config = i2c_smbus_read_byte_data(client, EMC6W201_REG_CONFIG);
-       if ((config & 0xF4) != 0x04)
+       if (config < 0 || (config & 0xF4) != 0x04)
                return -ENODEV;
        if (!(config & 0x01)) {
                dev_err(&client->dev, "Monitoring not enabled\n");
index a4a94a0..2d96ed2 100644 (file)
@@ -52,6 +52,7 @@
 #define SIO_F71858_ID          0x0507  /* Chipset ID */
 #define SIO_F71862_ID          0x0601  /* Chipset ID */
 #define SIO_F71869_ID          0x0814  /* Chipset ID */
+#define SIO_F71869A_ID         0x1007  /* Chipset ID */
 #define SIO_F71882_ID          0x0541  /* Chipset ID */
 #define SIO_F71889_ID          0x0723  /* Chipset ID */
 #define SIO_F71889E_ID         0x0909  /* Chipset ID */
@@ -108,8 +109,8 @@ static unsigned short force_id;
 module_param(force_id, ushort, 0);
 MODULE_PARM_DESC(force_id, "Override the detected device ID");
 
-enum chips { f71808e, f71808a, f71858fg, f71862fg, f71869, f71882fg, f71889fg,
-            f71889ed, f71889a, f8000, f81865f };
+enum chips { f71808e, f71808a, f71858fg, f71862fg, f71869, f71869a, f71882fg,
+            f71889fg, f71889ed, f71889a, f8000, f81865f };
 
 static const char *f71882fg_names[] = {
        "f71808e",
@@ -117,6 +118,7 @@ static const char *f71882fg_names[] = {
        "f71858fg",
        "f71862fg",
        "f71869", /* Both f71869f and f71869e, reg. compatible and same id */
+       "f71869a",
        "f71882fg",
        "f71889fg", /* f81801u too, same id */
        "f71889ed",
@@ -131,6 +133,7 @@ static const char f71882fg_has_in[][F71882FG_MAX_INS] = {
        [f71858fg]      = { 1, 1, 1, 0, 0, 0, 0, 0, 0 },
        [f71862fg]      = { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
        [f71869]        = { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+       [f71869a]       = { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
        [f71882fg]      = { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
        [f71889fg]      = { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
        [f71889ed]      = { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
@@ -145,6 +148,7 @@ static const char f71882fg_has_in1_alarm[] = {
        [f71858fg]      = 0,
        [f71862fg]      = 0,
        [f71869]        = 0,
+       [f71869a]       = 0,
        [f71882fg]      = 1,
        [f71889fg]      = 1,
        [f71889ed]      = 1,
@@ -159,6 +163,7 @@ static const char f71882fg_fan_has_beep[] = {
        [f71858fg]      = 0,
        [f71862fg]      = 1,
        [f71869]        = 1,
+       [f71869a]       = 1,
        [f71882fg]      = 1,
        [f71889fg]      = 1,
        [f71889ed]      = 1,
@@ -173,6 +178,7 @@ static const char f71882fg_nr_fans[] = {
        [f71858fg]      = 3,
        [f71862fg]      = 3,
        [f71869]        = 3,
+       [f71869a]       = 3,
        [f71882fg]      = 4,
        [f71889fg]      = 3,
        [f71889ed]      = 3,
@@ -187,6 +193,7 @@ static const char f71882fg_temp_has_beep[] = {
        [f71858fg]      = 0,
        [f71862fg]      = 1,
        [f71869]        = 1,
+       [f71869a]       = 1,
        [f71882fg]      = 1,
        [f71889fg]      = 1,
        [f71889ed]      = 1,
@@ -201,6 +208,7 @@ static const char f71882fg_nr_temps[] = {
        [f71858fg]      = 3,
        [f71862fg]      = 3,
        [f71869]        = 3,
+       [f71869a]       = 3,
        [f71882fg]      = 3,
        [f71889fg]      = 3,
        [f71889ed]      = 3,
@@ -2243,6 +2251,7 @@ static int __devinit f71882fg_probe(struct platform_device *pdev)
                case f71808e:
                case f71808a:
                case f71869:
+               case f71869a:
                        /* These always have signed auto point temps */
                        data->auto_point_temp_signed = 1;
                        /* Fall through to select correct fan/pwm reg bank! */
@@ -2305,6 +2314,7 @@ static int __devinit f71882fg_probe(struct platform_device *pdev)
                case f71808e:
                case f71808a:
                case f71869:
+               case f71869a:
                case f71889fg:
                case f71889ed:
                case f71889a:
@@ -2528,6 +2538,9 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address,
        case SIO_F71869_ID:
                sio_data->type = f71869;
                break;
+       case SIO_F71869A_ID:
+               sio_data->type = f71869a;
+               break;
        case SIO_F71882_ID:
                sio_data->type = f71882fg;
                break;
@@ -2662,7 +2675,7 @@ static void __exit f71882fg_exit(void)
 }
 
 MODULE_DESCRIPTION("F71882FG Hardware Monitoring Driver");
-MODULE_AUTHOR("Hans Edgington, Hans de Goede (hdegoede@redhat.com)");
+MODULE_AUTHOR("Hans Edgington, Hans de Goede <hdegoede@redhat.com>");
 MODULE_LICENSE("GPL");
 
 module_init(f71882fg_init);
index 2582bfe..c8195a0 100644 (file)
@@ -202,7 +202,7 @@ static struct vrm_model vrm_models[] = {
 
        {X86_VENDOR_CENTAUR, 0x6, 0x7, ANY, 85},        /* Eden ESP/Ezra */
        {X86_VENDOR_CENTAUR, 0x6, 0x8, 0x7, 85},        /* Ezra T */
-       {X86_VENDOR_CENTAUR, 0x6, 0x9, 0x7, 85},        /* Nemiah */
+       {X86_VENDOR_CENTAUR, 0x6, 0x9, 0x7, 85},        /* Nehemiah */
        {X86_VENDOR_CENTAUR, 0x6, 0x9, ANY, 17},        /* C3-M, Eden-N */
        {X86_VENDOR_CENTAUR, 0x6, 0xA, 0x7, 0},         /* No information */
        {X86_VENDOR_CENTAUR, 0x6, 0xA, ANY, 13},        /* C7, Esther */
index 98e2e28..931d940 100644 (file)
@@ -47,12 +47,14 @@ static void pmbus_find_sensor_groups(struct i2c_client *client,
        if (info->func[0]
            && pmbus_check_byte_register(client, 0, PMBUS_STATUS_INPUT))
                info->func[0] |= PMBUS_HAVE_STATUS_INPUT;
-       if (pmbus_check_word_register(client, 0, PMBUS_READ_FAN_SPEED_1)) {
+       if (pmbus_check_byte_register(client, 0, PMBUS_FAN_CONFIG_12) &&
+           pmbus_check_word_register(client, 0, PMBUS_READ_FAN_SPEED_1)) {
                info->func[0] |= PMBUS_HAVE_FAN12;
                if (pmbus_check_byte_register(client, 0, PMBUS_STATUS_FAN_12))
                        info->func[0] |= PMBUS_HAVE_STATUS_FAN12;
        }
-       if (pmbus_check_word_register(client, 0, PMBUS_READ_FAN_SPEED_3)) {
+       if (pmbus_check_byte_register(client, 0, PMBUS_FAN_CONFIG_34) &&
+           pmbus_check_word_register(client, 0, PMBUS_READ_FAN_SPEED_3)) {
                info->func[0] |= PMBUS_HAVE_FAN34;
                if (pmbus_check_byte_register(client, 0, PMBUS_STATUS_FAN_34))
                        info->func[0] |= PMBUS_HAVE_STATUS_FAN34;
@@ -63,6 +65,10 @@ static void pmbus_find_sensor_groups(struct i2c_client *client,
                                              PMBUS_STATUS_TEMPERATURE))
                        info->func[0] |= PMBUS_HAVE_STATUS_TEMP;
        }
+       if (pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_2))
+               info->func[0] |= PMBUS_HAVE_TEMP2;
+       if (pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_3))
+               info->func[0] |= PMBUS_HAVE_TEMP3;
 
        /* Sensors detected on all pages */
        for (page = 0; page < info->pages; page++) {
index 354770e..744672c 100644 (file)
@@ -1430,14 +1430,9 @@ int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
        i2c_set_clientdata(client, data);
        mutex_init(&data->update_lock);
 
-       /*
-        * Bail out if status register or PMBus revision register
-        * does not exist.
-        */
-       if (i2c_smbus_read_byte_data(client, PMBUS_STATUS_BYTE) < 0
-           || i2c_smbus_read_byte_data(client, PMBUS_REVISION) < 0) {
-               dev_err(&client->dev,
-                       "Status or revision register not found\n");
+       /* Bail out if PMBus status register does not exist. */
+       if (i2c_smbus_read_byte_data(client, PMBUS_STATUS_BYTE) < 0) {
+               dev_err(&client->dev, "PMBus status register not found\n");
                ret = -ENODEV;
                goto out_data;
        }
index 020c872..3494a4c 100644 (file)
@@ -887,7 +887,7 @@ static void __exit sch5627_exit(void)
 }
 
 MODULE_DESCRIPTION("SMSC SCH5627 Hardware Monitoring Driver");
-MODULE_AUTHOR("Hans de Goede (hdegoede@redhat.com)");
+MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
 MODULE_LICENSE("GPL");
 
 module_init(sch5627_init);
index f62f52f..fc0f2bd 100644 (file)
@@ -3641,7 +3641,8 @@ static struct kobj_type cm_port_obj_type = {
 
 static char *cm_devnode(struct device *dev, mode_t *mode)
 {
-       *mode = 0666;
+       if (mode)
+               *mode = 0666;
        return kasprintf(GFP_KERNEL, "infiniband/%s", dev_name(dev));
 }
 
index e49a85f..56898b6 100644 (file)
@@ -826,7 +826,8 @@ static void ib_uverbs_remove_one(struct ib_device *device)
 
 static char *uverbs_devnode(struct device *dev, mode_t *mode)
 {
-       *mode = 0666;
+       if (mode)
+               *mode = 0666;
        return kasprintf(GFP_KERNEL, "infiniband/%s", dev_name(dev));
 }
 
index 40b02ae..6229c3e 100644 (file)
@@ -520,7 +520,8 @@ static void pmic8xxx_kp_close(struct input_dev *dev)
  */
 static int __devinit pmic8xxx_kp_probe(struct platform_device *pdev)
 {
-       const struct pm8xxx_keypad_platform_data *pdata = mfd_get_data(pdev);
+       const struct pm8xxx_keypad_platform_data *pdata =
+                                       dev_get_platdata(&pdev->dev);
        const struct matrix_keymap_data *keymap_data;
        struct pmic8xxx_kp *kp;
        int rc;
index 97e07e7..b3cfb9c 100644 (file)
@@ -90,7 +90,8 @@ static int __devinit pmic8xxx_pwrkey_probe(struct platform_device *pdev)
        unsigned int delay;
        u8 pon_cntl;
        struct pmic8xxx_pwrkey *pwrkey;
-       const struct pm8xxx_pwrkey_platform_data *pdata = mfd_get_data(pdev);
+       const struct pm8xxx_pwrkey_platform_data *pdata =
+                                       dev_get_platdata(&pdev->dev);
 
        if (!pdata) {
                dev_err(&pdev->dev, "power key platform data not supplied\n");
index 8fa539d..7f7079b 100644 (file)
@@ -597,12 +597,17 @@ static void __devexit fintek_remove(struct pnp_dev *pdev)
 static int fintek_suspend(struct pnp_dev *pdev, pm_message_t state)
 {
        struct fintek_dev *fintek = pnp_get_drvdata(pdev);
+       unsigned long flags;
 
        fit_dbg("%s called", __func__);
 
+       spin_lock_irqsave(&fintek->fintek_lock, flags);
+
        /* disable all CIR interrupts */
        fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_MASK, CIR_STATUS);
 
+       spin_unlock_irqrestore(&fintek->fintek_lock, flags);
+
        fintek_config_mode_enable(fintek);
 
        /* disable cir logical dev */
index 3f3c707..6bc35ee 100644 (file)
@@ -307,6 +307,14 @@ static const struct {
        /* 0xffdc iMON MCE VFD */
        { 0x00010000ffffffeell, KEY_VOLUMEUP },
        { 0x01000000ffffffeell, KEY_VOLUMEDOWN },
+       { 0x00000001ffffffeell, KEY_MUTE },
+       { 0x0000000fffffffeell, KEY_MEDIA },
+       { 0x00000012ffffffeell, KEY_UP },
+       { 0x00000013ffffffeell, KEY_DOWN },
+       { 0x00000014ffffffeell, KEY_LEFT },
+       { 0x00000015ffffffeell, KEY_RIGHT },
+       { 0x00000016ffffffeell, KEY_ENTER },
+       { 0x00000017ffffffeell, KEY_ESC },
        /* iMON Knob values */
        { 0x000100ffffffffeell, KEY_VOLUMEUP },
        { 0x010000ffffffffeell, KEY_VOLUMEDOWN },
@@ -1582,16 +1590,16 @@ static void imon_incoming_packet(struct imon_context *ictx,
        /* Only panel type events left to process now */
        spin_lock_irqsave(&ictx->kc_lock, flags);
 
+       do_gettimeofday(&t);
        /* KEY_MUTE repeats from knob need to be suppressed */
        if (ictx->kc == KEY_MUTE && ictx->kc == ictx->last_keycode) {
-               do_gettimeofday(&t);
                msec = tv2int(&t, &prev_time);
-               prev_time = t;
                if (msec < ictx->idev->rep[REP_DELAY]) {
                        spin_unlock_irqrestore(&ictx->kc_lock, flags);
                        return;
                }
        }
+       prev_time = t;
        kc = ictx->kc;
 
        spin_unlock_irqrestore(&ictx->kc_lock, flags);
@@ -1603,7 +1611,9 @@ static void imon_incoming_packet(struct imon_context *ictx,
        input_report_key(ictx->idev, kc, 0);
        input_sync(ictx->idev);
 
+       spin_lock_irqsave(&ictx->kc_lock, flags);
        ictx->last_keycode = kc;
+       spin_unlock_irqrestore(&ictx->kc_lock, flags);
 
        return;
 
@@ -1740,6 +1750,8 @@ static void imon_get_ffdc_type(struct imon_context *ictx)
                detected_display_type = IMON_DISPLAY_TYPE_VFD;
                break;
        /* iMON VFD, MCE IR */
+       case 0x46:
+       case 0x7e:
        case 0x9e:
                dev_info(ictx->dev, "0xffdc iMON VFD, MCE IR");
                detected_display_type = IMON_DISPLAY_TYPE_VFD;
@@ -1755,6 +1767,9 @@ static void imon_get_ffdc_type(struct imon_context *ictx)
                dev_info(ictx->dev, "Unknown 0xffdc device, "
                         "defaulting to VFD and iMON IR");
                detected_display_type = IMON_DISPLAY_TYPE_VFD;
+               /* We don't know which one it is, allow user to set the
+                * RC6 one from userspace if OTHER wasn't correct. */
+               allowed_protos |= RC_TYPE_RC6;
                break;
        }
 
index 11c19d8..423ed45 100644 (file)
@@ -114,18 +114,20 @@ int ir_raw_event_store_edge(struct rc_dev *dev, enum raw_event_type type)
        s64                     delta; /* ns */
        DEFINE_IR_RAW_EVENT(ev);
        int                     rc = 0;
+       int                     delay;
 
        if (!dev->raw)
                return -EINVAL;
 
        now = ktime_get();
        delta = ktime_to_ns(ktime_sub(now, dev->raw->last_event));
+       delay = MS_TO_NS(dev->input_dev->rep[REP_DELAY]);
 
        /* Check for a long duration since last event or if we're
         * being called for the first time, note that delta can't
         * possibly be negative.
         */
-       if (delta > IR_MAX_DURATION || !dev->raw->last_type)
+       if (delta > delay || !dev->raw->last_type)
                type |= IR_START_EVENT;
        else
                ev.duration = delta;
index e716b93..ecd3d02 100644 (file)
@@ -1347,6 +1347,7 @@ static const struct ite_dev_params ite_dev_descs[] = {
        {       /* 0: ITE8704 */
               .model = "ITE8704 CIR transceiver",
               .io_region_size = IT87_IOREG_LENGTH,
+              .io_rsrc_no = 0,
               .hw_tx_capable = true,
               .sample_period = (u32) (1000000000ULL / 115200),
               .tx_carrier_freq = 38000,
@@ -1371,6 +1372,7 @@ static const struct ite_dev_params ite_dev_descs[] = {
        {       /* 1: ITE8713 */
               .model = "ITE8713 CIR transceiver",
               .io_region_size = IT87_IOREG_LENGTH,
+              .io_rsrc_no = 0,
               .hw_tx_capable = true,
               .sample_period = (u32) (1000000000ULL / 115200),
               .tx_carrier_freq = 38000,
@@ -1395,6 +1397,7 @@ static const struct ite_dev_params ite_dev_descs[] = {
        {       /* 2: ITE8708 */
               .model = "ITE8708 CIR transceiver",
               .io_region_size = IT8708_IOREG_LENGTH,
+              .io_rsrc_no = 0,
               .hw_tx_capable = true,
               .sample_period = (u32) (1000000000ULL / 115200),
               .tx_carrier_freq = 38000,
@@ -1420,6 +1423,7 @@ static const struct ite_dev_params ite_dev_descs[] = {
        {       /* 3: ITE8709 */
               .model = "ITE8709 CIR transceiver",
               .io_region_size = IT8709_IOREG_LENGTH,
+              .io_rsrc_no = 2,
               .hw_tx_capable = true,
               .sample_period = (u32) (1000000000ULL / 115200),
               .tx_carrier_freq = 38000,
@@ -1461,6 +1465,7 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id
        struct rc_dev *rdev = NULL;
        int ret = -ENOMEM;
        int model_no;
+       int io_rsrc_no;
 
        ite_dbg("%s called", __func__);
 
@@ -1490,10 +1495,11 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id
 
        /* get the description for the device */
        dev_desc = &ite_dev_descs[model_no];
+       io_rsrc_no = dev_desc->io_rsrc_no;
 
        /* validate pnp resources */
-       if (!pnp_port_valid(pdev, 0) ||
-           pnp_port_len(pdev, 0) != dev_desc->io_region_size) {
+       if (!pnp_port_valid(pdev, io_rsrc_no) ||
+           pnp_port_len(pdev, io_rsrc_no) != dev_desc->io_region_size) {
                dev_err(&pdev->dev, "IR PNP Port not valid!\n");
                goto failure;
        }
@@ -1504,7 +1510,7 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id
        }
 
        /* store resource values */
-       itdev->cir_addr = pnp_port_start(pdev, 0);
+       itdev->cir_addr = pnp_port_start(pdev, io_rsrc_no);
        itdev->cir_irq = pnp_irq(pdev, 0);
 
        /* initialize spinlocks */
index 16a19f5..aa899a0 100644 (file)
@@ -57,6 +57,9 @@ struct ite_dev_params {
        /* size of the I/O region */
        int io_region_size;
 
+       /* IR pnp I/O resource number */
+       int io_rsrc_no;
+
        /* true if the hardware supports transmission */
        bool hw_tx_capable;
 
index bb10ffe..8d558ae 100644 (file)
 /* Pinnacle PCTV HD 800i mini remote */
 
 static struct rc_map_table pinnacle_pctv_hd[] = {
-
-       { 0x0f, KEY_1 },
-       { 0x15, KEY_2 },
-       { 0x10, KEY_3 },
-       { 0x18, KEY_4 },
-       { 0x1b, KEY_5 },
-       { 0x1e, KEY_6 },
-       { 0x11, KEY_7 },
-       { 0x21, KEY_8 },
-       { 0x12, KEY_9 },
-       { 0x27, KEY_0 },
-
-       { 0x24, KEY_ZOOM },
-       { 0x2a, KEY_SUBTITLE },
-
-       { 0x00, KEY_MUTE },
-       { 0x01, KEY_ENTER },    /* Pinnacle Logo */
-       { 0x39, KEY_POWER },
-
-       { 0x03, KEY_VOLUMEUP },
-       { 0x09, KEY_VOLUMEDOWN },
-       { 0x06, KEY_CHANNELUP },
-       { 0x0c, KEY_CHANNELDOWN },
-
-       { 0x2d, KEY_REWIND },
-       { 0x30, KEY_PLAYPAUSE },
-       { 0x33, KEY_FASTFORWARD },
-       { 0x3c, KEY_STOP },
-       { 0x36, KEY_RECORD },
-       { 0x3f, KEY_EPG },      /* Labeled "?" */
+       /* Key codes for the tiny Pinnacle remote*/
+       { 0x0700, KEY_MUTE },
+       { 0x0701, KEY_MENU }, /* Pinnacle logo */
+       { 0x0739, KEY_POWER },
+       { 0x0703, KEY_VOLUMEUP },
+       { 0x0709, KEY_VOLUMEDOWN },
+       { 0x0706, KEY_CHANNELUP },
+       { 0x070c, KEY_CHANNELDOWN },
+       { 0x070f, KEY_1 },
+       { 0x0715, KEY_2 },
+       { 0x0710, KEY_3 },
+       { 0x0718, KEY_4 },
+       { 0x071b, KEY_5 },
+       { 0x071e, KEY_6 },
+       { 0x0711, KEY_7 },
+       { 0x0721, KEY_8 },
+       { 0x0712, KEY_9 },
+       { 0x0727, KEY_0 },
+       { 0x0724, KEY_ZOOM }, /* 'Square' key */
+       { 0x072a, KEY_SUBTITLE },   /* 'T' key */
+       { 0x072d, KEY_REWIND },
+       { 0x0730, KEY_PLAYPAUSE },
+       { 0x0733, KEY_FASTFORWARD },
+       { 0x0736, KEY_RECORD },
+       { 0x073c, KEY_STOP },
+       { 0x073f, KEY_HELP }, /* '?' key */
 };
 
 static struct rc_map_list pinnacle_pctv_hd_map = {
        .map = {
                .scan    = pinnacle_pctv_hd,
                .size    = ARRAY_SIZE(pinnacle_pctv_hd),
-               .rc_type = RC_TYPE_UNKNOWN,     /* Legacy IR type */
+               .rc_type = RC_TYPE_RC5,
                .name    = RC_MAP_PINNACLE_PCTV_HD,
        }
 };
index fd237ab..27997a9 100644 (file)
@@ -55,6 +55,8 @@ struct irctl {
        struct lirc_buffer *buf;
        unsigned int chunk_size;
 
+       struct cdev *cdev;
+
        struct task_struct *task;
        long jiffies_to_wait;
 };
@@ -62,7 +64,6 @@ struct irctl {
 static DEFINE_MUTEX(lirc_dev_lock);
 
 static struct irctl *irctls[MAX_IRCTL_DEVICES];
-static struct cdev cdevs[MAX_IRCTL_DEVICES];
 
 /* Only used for sysfs but defined to void otherwise */
 static struct class *lirc_class;
@@ -167,9 +168,13 @@ static struct file_operations lirc_dev_fops = {
 
 static int lirc_cdev_add(struct irctl *ir)
 {
-       int retval;
+       int retval = -ENOMEM;
        struct lirc_driver *d = &ir->d;
-       struct cdev *cdev = &cdevs[d->minor];
+       struct cdev *cdev;
+
+       cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
+       if (!cdev)
+               goto err_out;
 
        if (d->fops) {
                cdev_init(cdev, d->fops);
@@ -180,12 +185,20 @@ static int lirc_cdev_add(struct irctl *ir)
        }
        retval = kobject_set_name(&cdev->kobj, "lirc%d", d->minor);
        if (retval)
-               return retval;
+               goto err_out;
 
        retval = cdev_add(cdev, MKDEV(MAJOR(lirc_base_dev), d->minor), 1);
-       if (retval)
+       if (retval) {
                kobject_put(&cdev->kobj);
+               goto err_out;
+       }
+
+       ir->cdev = cdev;
+
+       return 0;
 
+err_out:
+       kfree(cdev);
        return retval;
 }
 
@@ -214,7 +227,7 @@ int lirc_register_driver(struct lirc_driver *d)
        if (MAX_IRCTL_DEVICES <= d->minor) {
                dev_err(d->dev, "lirc_dev: lirc_register_driver: "
                        "\"minor\" must be between 0 and %d (%d)!\n",
-                       MAX_IRCTL_DEVICES-1, d->minor);
+                       MAX_IRCTL_DEVICES - 1, d->minor);
                err = -EBADRQC;
                goto out;
        }
@@ -369,7 +382,7 @@ int lirc_unregister_driver(int minor)
 
        if (minor < 0 || minor >= MAX_IRCTL_DEVICES) {
                printk(KERN_ERR "lirc_dev: %s: minor (%d) must be between "
-                      "0 and %d!\n", __func__, minor, MAX_IRCTL_DEVICES-1);
+                      "0 and %d!\n", __func__, minor, MAX_IRCTL_DEVICES - 1);
                return -EBADRQC;
        }
 
@@ -380,7 +393,7 @@ int lirc_unregister_driver(int minor)
                return -ENOENT;
        }
 
-       cdev = &cdevs[minor];
+       cdev = ir->cdev;
 
        mutex_lock(&lirc_dev_lock);
 
@@ -410,6 +423,7 @@ int lirc_unregister_driver(int minor)
        } else {
                lirc_irctl_cleanup(ir);
                cdev_del(cdev);
+               kfree(cdev);
                kfree(ir);
                irctls[minor] = NULL;
        }
@@ -453,7 +467,7 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file)
                goto error;
        }
 
-       cdev = &cdevs[iminor(inode)];
+       cdev = ir->cdev;
        if (try_module_get(cdev->owner)) {
                ir->open++;
                retval = ir->d.set_use_inc(ir->d.data);
@@ -484,13 +498,15 @@ EXPORT_SYMBOL(lirc_dev_fop_open);
 int lirc_dev_fop_close(struct inode *inode, struct file *file)
 {
        struct irctl *ir = irctls[iminor(inode)];
-       struct cdev *cdev = &cdevs[iminor(inode)];
+       struct cdev *cdev;
 
        if (!ir) {
                printk(KERN_ERR "%s: called with invalid irctl\n", __func__);
                return -EINVAL;
        }
 
+       cdev = ir->cdev;
+
        dev_dbg(ir->d.dev, LOGHEAD "close called\n", ir->d.name, ir->d.minor);
 
        WARN_ON(mutex_lock_killable(&lirc_dev_lock));
@@ -503,6 +519,7 @@ int lirc_dev_fop_close(struct inode *inode, struct file *file)
                lirc_irctl_cleanup(ir);
                cdev_del(cdev);
                irctls[ir->d.minor] = NULL;
+               kfree(cdev);
                kfree(ir);
        }
 
index ad927fc..06dfe09 100644 (file)
@@ -108,6 +108,12 @@ static int debug = 1;
 static int debug;
 #endif
 
+#define mce_dbg(dev, fmt, ...)                                 \
+       do {                                                    \
+               if (debug)                                      \
+                       dev_info(dev, fmt, ## __VA_ARGS__);     \
+       } while (0)
+
 /* general constants */
 #define SEND_FLAG_IN_PROGRESS  1
 #define SEND_FLAG_COMPLETE     2
@@ -246,6 +252,9 @@ static struct usb_device_id mceusb_dev_table[] = {
          .driver_info = MCE_GEN2_TX_INV },
        /* SMK eHome Infrared Transceiver */
        { USB_DEVICE(VENDOR_SMK, 0x0338) },
+       /* SMK/I-O Data GV-MC7/RCKIT Receiver */
+       { USB_DEVICE(VENDOR_SMK, 0x0353),
+         .driver_info = MCE_GEN2_NO_TX },
        /* Tatung eHome Infrared Transceiver */
        { USB_DEVICE(VENDOR_TATUNG, 0x9150) },
        /* Shuttle eHome Infrared Transceiver */
@@ -606,12 +615,15 @@ static void mce_async_callback(struct urb *urb, struct pt_regs *regs)
        if (ir) {
                len = urb->actual_length;
 
-               dev_dbg(ir->dev, "callback called (status=%d len=%d)\n",
+               mce_dbg(ir->dev, "callback called (status=%d len=%d)\n",
                        urb->status, len);
 
                mceusb_dev_printdata(ir, urb->transfer_buffer, 0, len, true);
        }
 
+       /* the transfer buffer and urb were allocated in mce_request_packet */
+       kfree(urb->transfer_buffer);
+       usb_free_urb(urb);
 }
 
 /* request incoming or send outgoing usb packet - used to initialize remote */
@@ -655,17 +667,17 @@ static void mce_request_packet(struct mceusb_dev *ir, unsigned char *data,
                return;
        }
 
-       dev_dbg(dev, "receive request called (size=%#x)\n", size);
+       mce_dbg(dev, "receive request called (size=%#x)\n", size);
 
        async_urb->transfer_buffer_length = size;
        async_urb->dev = ir->usbdev;
 
        res = usb_submit_urb(async_urb, GFP_ATOMIC);
        if (res) {
-               dev_dbg(dev, "receive request FAILED! (res=%d)\n", res);
+               mce_dbg(dev, "receive request FAILED! (res=%d)\n", res);
                return;
        }
-       dev_dbg(dev, "receive request complete (res=%d)\n", res);
+       mce_dbg(dev, "receive request complete (res=%d)\n", res);
 }
 
 static void mce_async_out(struct mceusb_dev *ir, unsigned char *data, int size)
@@ -673,9 +685,9 @@ static void mce_async_out(struct mceusb_dev *ir, unsigned char *data, int size)
        mce_request_packet(ir, data, size, MCEUSB_TX);
 }
 
-static void mce_sync_in(struct mceusb_dev *ir, unsigned char *data, int size)
+static void mce_flush_rx_buffer(struct mceusb_dev *ir, int size)
 {
-       mce_request_packet(ir, data, size, MCEUSB_RX);
+       mce_request_packet(ir, NULL, size, MCEUSB_RX);
 }
 
 /* Send data out the IR blaster port(s) */
@@ -794,7 +806,7 @@ static int mceusb_set_tx_carrier(struct rc_dev *dev, u32 carrier)
                        ir->carrier = carrier;
                        cmdbuf[2] = MCE_CMD_SIG_END;
                        cmdbuf[3] = MCE_IRDATA_TRAILER;
-                       dev_dbg(ir->dev, "%s: disabling carrier "
+                       mce_dbg(ir->dev, "%s: disabling carrier "
                                "modulation\n", __func__);
                        mce_async_out(ir, cmdbuf, sizeof(cmdbuf));
                        return carrier;
@@ -806,7 +818,7 @@ static int mceusb_set_tx_carrier(struct rc_dev *dev, u32 carrier)
                                ir->carrier = carrier;
                                cmdbuf[2] = prescaler;
                                cmdbuf[3] = divisor;
-                               dev_dbg(ir->dev, "%s: requesting %u HZ "
+                               mce_dbg(ir->dev, "%s: requesting %u HZ "
                                        "carrier\n", __func__, carrier);
 
                                /* Transmit new carrier to mce device */
@@ -879,7 +891,7 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)
                        rawir.duration = (ir->buf_in[i] & MCE_PULSE_MASK)
                                         * US_TO_NS(MCE_TIME_UNIT);
 
-                       dev_dbg(ir->dev, "Storing %s with duration %d\n",
+                       mce_dbg(ir->dev, "Storing %s with duration %d\n",
                                rawir.pulse ? "pulse" : "space",
                                rawir.duration);
 
@@ -911,7 +923,7 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)
                if (ir->parser_state != CMD_HEADER && !ir->rem)
                        ir->parser_state = CMD_HEADER;
        }
-       dev_dbg(ir->dev, "processed IR data, calling ir_raw_event_handle\n");
+       mce_dbg(ir->dev, "processed IR data, calling ir_raw_event_handle\n");
        ir_raw_event_handle(ir->rc);
 }
 
@@ -933,7 +945,7 @@ static void mceusb_dev_recv(struct urb *urb, struct pt_regs *regs)
 
        if (ir->send_flags == RECV_FLAG_IN_PROGRESS) {
                ir->send_flags = SEND_FLAG_COMPLETE;
-               dev_dbg(ir->dev, "setup answer received %d bytes\n",
+               mce_dbg(ir->dev, "setup answer received %d bytes\n",
                        buf_len);
        }
 
@@ -951,7 +963,7 @@ static void mceusb_dev_recv(struct urb *urb, struct pt_regs *regs)
 
        case -EPIPE:
        default:
-               dev_dbg(ir->dev, "Error: urb status = %d\n", urb->status);
+               mce_dbg(ir->dev, "Error: urb status = %d\n", urb->status);
                break;
        }
 
@@ -961,7 +973,6 @@ static void mceusb_dev_recv(struct urb *urb, struct pt_regs *regs)
 static void mceusb_gen1_init(struct mceusb_dev *ir)
 {
        int ret;
-       int maxp = ir->len_in;
        struct device *dev = ir->dev;
        char *data;
 
@@ -978,8 +989,8 @@ static void mceusb_gen1_init(struct mceusb_dev *ir)
        ret = usb_control_msg(ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0),
                              USB_REQ_SET_ADDRESS, USB_TYPE_VENDOR, 0, 0,
                              data, USB_CTRL_MSG_SZ, HZ * 3);
-       dev_dbg(dev, "%s - ret = %d\n", __func__, ret);
-       dev_dbg(dev, "%s - data[0] = %d, data[1] = %d\n",
+       mce_dbg(dev, "%s - ret = %d\n", __func__, ret);
+       mce_dbg(dev, "%s - data[0] = %d, data[1] = %d\n",
                __func__, data[0], data[1]);
 
        /* set feature: bit rate 38400 bps */
@@ -987,71 +998,56 @@ static void mceusb_gen1_init(struct mceusb_dev *ir)
                              USB_REQ_SET_FEATURE, USB_TYPE_VENDOR,
                              0xc04e, 0x0000, NULL, 0, HZ * 3);
 
-       dev_dbg(dev, "%s - ret = %d\n", __func__, ret);
+       mce_dbg(dev, "%s - ret = %d\n", __func__, ret);
 
        /* bRequest 4: set char length to 8 bits */
        ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0),
                              4, USB_TYPE_VENDOR,
                              0x0808, 0x0000, NULL, 0, HZ * 3);
-       dev_dbg(dev, "%s - retB = %d\n", __func__, ret);
+       mce_dbg(dev, "%s - retB = %d\n", __func__, ret);
 
        /* bRequest 2: set handshaking to use DTR/DSR */
        ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0),
                              2, USB_TYPE_VENDOR,
                              0x0000, 0x0100, NULL, 0, HZ * 3);
-       dev_dbg(dev, "%s - retC = %d\n", __func__, ret);
+       mce_dbg(dev, "%s - retC = %d\n", __func__, ret);
 
        /* device reset */
        mce_async_out(ir, DEVICE_RESET, sizeof(DEVICE_RESET));
-       mce_sync_in(ir, NULL, maxp);
 
        /* get hw/sw revision? */
        mce_async_out(ir, GET_REVISION, sizeof(GET_REVISION));
-       mce_sync_in(ir, NULL, maxp);
 
        kfree(data);
 };
 
 static void mceusb_gen2_init(struct mceusb_dev *ir)
 {
-       int maxp = ir->len_in;
-
        /* device reset */
        mce_async_out(ir, DEVICE_RESET, sizeof(DEVICE_RESET));
-       mce_sync_in(ir, NULL, maxp);
 
        /* get hw/sw revision? */
        mce_async_out(ir, GET_REVISION, sizeof(GET_REVISION));
-       mce_sync_in(ir, NULL, maxp);
 
        /* unknown what the next two actually return... */
        mce_async_out(ir, GET_UNKNOWN, sizeof(GET_UNKNOWN));
-       mce_sync_in(ir, NULL, maxp);
        mce_async_out(ir, GET_UNKNOWN2, sizeof(GET_UNKNOWN2));
-       mce_sync_in(ir, NULL, maxp);
 }
 
 static void mceusb_get_parameters(struct mceusb_dev *ir)
 {
-       int maxp = ir->len_in;
-
        /* get the carrier and frequency */
        mce_async_out(ir, GET_CARRIER_FREQ, sizeof(GET_CARRIER_FREQ));
-       mce_sync_in(ir, NULL, maxp);
 
-       if (!ir->flags.no_tx) {
+       if (!ir->flags.no_tx)
                /* get the transmitter bitmask */
                mce_async_out(ir, GET_TX_BITMASK, sizeof(GET_TX_BITMASK));
-               mce_sync_in(ir, NULL, maxp);
-       }
 
        /* get receiver timeout value */
        mce_async_out(ir, GET_RX_TIMEOUT, sizeof(GET_RX_TIMEOUT));
-       mce_sync_in(ir, NULL, maxp);
 
        /* get receiver sensor setting */
        mce_async_out(ir, GET_RX_SENSOR, sizeof(GET_RX_SENSOR));
-       mce_sync_in(ir, NULL, maxp);
 }
 
 static struct rc_dev *mceusb_init_rc_dev(struct mceusb_dev *ir)
@@ -1122,7 +1118,7 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf,
        bool tx_mask_normal;
        int ir_intfnum;
 
-       dev_dbg(&intf->dev, "%s called\n", __func__);
+       mce_dbg(&intf->dev, "%s called\n", __func__);
 
        idesc  = intf->cur_altsetting;
 
@@ -1150,7 +1146,7 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf,
                        ep_in = ep;
                        ep_in->bmAttributes = USB_ENDPOINT_XFER_INT;
                        ep_in->bInterval = 1;
-                       dev_dbg(&intf->dev, "acceptable inbound endpoint "
+                       mce_dbg(&intf->dev, "acceptable inbound endpoint "
                                "found\n");
                }
 
@@ -1165,12 +1161,12 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf,
                        ep_out = ep;
                        ep_out->bmAttributes = USB_ENDPOINT_XFER_INT;
                        ep_out->bInterval = 1;
-                       dev_dbg(&intf->dev, "acceptable outbound endpoint "
+                       mce_dbg(&intf->dev, "acceptable outbound endpoint "
                                "found\n");
                }
        }
        if (ep_in == NULL) {
-               dev_dbg(&intf->dev, "inbound and/or endpoint not found\n");
+               mce_dbg(&intf->dev, "inbound and/or endpoint not found\n");
                return -ENODEV;
        }
 
@@ -1215,16 +1211,16 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf,
        if (!ir->rc)
                goto rc_dev_fail;
 
-       /* flush buffers on the device */
-       mce_sync_in(ir, NULL, maxp);
-       mce_sync_in(ir, NULL, maxp);
-
        /* wire up inbound data handler */
        usb_fill_int_urb(ir->urb_in, dev, pipe, ir->buf_in,
                maxp, (usb_complete_t) mceusb_dev_recv, ir, ep_in->bInterval);
        ir->urb_in->transfer_dma = ir->dma_in;
        ir->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
+       /* flush buffers on the device */
+       mce_dbg(&intf->dev, "Flushing receive buffers\n");
+       mce_flush_rx_buffer(ir, maxp);
+
        /* initialize device */
        if (ir->flags.microsoft_gen1)
                mceusb_gen1_init(ir);
index bf3060e..565f24c 100644 (file)
@@ -991,7 +991,6 @@ static int nvt_open(struct rc_dev *dev)
        unsigned long flags;
 
        spin_lock_irqsave(&nvt->nvt_lock, flags);
-       nvt->in_use = true;
        nvt_enable_cir(nvt);
        spin_unlock_irqrestore(&nvt->nvt_lock, flags);
 
@@ -1004,7 +1003,6 @@ static void nvt_close(struct rc_dev *dev)
        unsigned long flags;
 
        spin_lock_irqsave(&nvt->nvt_lock, flags);
-       nvt->in_use = false;
        nvt_disable_cir(nvt);
        spin_unlock_irqrestore(&nvt->nvt_lock, flags);
 }
index 379795d..1241fc8 100644 (file)
@@ -70,7 +70,6 @@ struct nvt_dev {
        struct ir_raw_event rawir;
 
        spinlock_t nvt_lock;
-       bool in_use;
 
        /* for rx */
        u8 buf[RX_BUF_LEN];
index f57cd56..3186ac7 100644 (file)
@@ -522,18 +522,20 @@ EXPORT_SYMBOL_GPL(rc_g_keycode_from_table);
 /**
  * ir_do_keyup() - internal function to signal the release of a keypress
  * @dev:       the struct rc_dev descriptor of the device
+ * @sync:      whether or not to call input_sync
  *
  * This function is used internally to release a keypress, it must be
  * called with keylock held.
  */
-static void ir_do_keyup(struct rc_dev *dev)
+static void ir_do_keyup(struct rc_dev *dev, bool sync)
 {
        if (!dev->keypressed)
                return;
 
        IR_dprintk(1, "keyup key 0x%04x\n", dev->last_keycode);
        input_report_key(dev->input_dev, dev->last_keycode, 0);
-       input_sync(dev->input_dev);
+       if (sync)
+               input_sync(dev->input_dev);
        dev->keypressed = false;
 }
 
@@ -549,7 +551,7 @@ void rc_keyup(struct rc_dev *dev)
        unsigned long flags;
 
        spin_lock_irqsave(&dev->keylock, flags);
-       ir_do_keyup(dev);
+       ir_do_keyup(dev, true);
        spin_unlock_irqrestore(&dev->keylock, flags);
 }
 EXPORT_SYMBOL_GPL(rc_keyup);
@@ -578,7 +580,7 @@ static void ir_timer_keyup(unsigned long cookie)
         */
        spin_lock_irqsave(&dev->keylock, flags);
        if (time_is_before_eq_jiffies(dev->keyup_jiffies))
-               ir_do_keyup(dev);
+               ir_do_keyup(dev, true);
        spin_unlock_irqrestore(&dev->keylock, flags);
 }
 
@@ -597,6 +599,7 @@ void rc_repeat(struct rc_dev *dev)
        spin_lock_irqsave(&dev->keylock, flags);
 
        input_event(dev->input_dev, EV_MSC, MSC_SCAN, dev->last_scancode);
+       input_sync(dev->input_dev);
 
        if (!dev->keypressed)
                goto out;
@@ -622,29 +625,28 @@ EXPORT_SYMBOL_GPL(rc_repeat);
 static void ir_do_keydown(struct rc_dev *dev, int scancode,
                          u32 keycode, u8 toggle)
 {
-       input_event(dev->input_dev, EV_MSC, MSC_SCAN, scancode);
-
-       /* Repeat event? */
-       if (dev->keypressed &&
-           dev->last_scancode == scancode &&
-           dev->last_toggle == toggle)
-               return;
+       bool new_event = !dev->keypressed ||
+                        dev->last_scancode != scancode ||
+                        dev->last_toggle != toggle;
 
-       /* Release old keypress */
-       ir_do_keyup(dev);
+       if (new_event && dev->keypressed)
+               ir_do_keyup(dev, false);
 
-       dev->last_scancode = scancode;
-       dev->last_toggle = toggle;
-       dev->last_keycode = keycode;
+       input_event(dev->input_dev, EV_MSC, MSC_SCAN, scancode);
 
-       if (keycode == KEY_RESERVED)
-               return;
+       if (new_event && keycode != KEY_RESERVED) {
+               /* Register a keypress */
+               dev->keypressed = true;
+               dev->last_scancode = scancode;
+               dev->last_toggle = toggle;
+               dev->last_keycode = keycode;
+
+               IR_dprintk(1, "%s: key down event, "
+                          "key 0x%04x, scancode 0x%04x\n",
+                          dev->input_name, keycode, scancode);
+               input_report_key(dev->input_dev, keycode, 1);
+       }
 
-       /* Register a keypress */
-       dev->keypressed = true;
-       IR_dprintk(1, "%s: key down event, key 0x%04x, scancode 0x%04x\n",
-                  dev->input_name, keycode, scancode);
-       input_report_key(dev->input_dev, dev->last_keycode, 1);
        input_sync(dev->input_dev);
 }
 
index 10b55c8..89d09a8 100644 (file)
@@ -2,10 +2,10 @@
  * Header for M-5MOLS 8M Pixel camera sensor with ISP
  *
  * Copyright (C) 2011 Samsung Electronics Co., Ltd.
- * Author: HeungJun Kim, riverful.kim@samsung.com
+ * Author: HeungJun Kim <riverful.kim@samsung.com>
  *
  * Copyright (C) 2009 Samsung Electronics Co., Ltd.
- * Author: Dongsoo Nathaniel Kim, dongsoo45.kim@samsung.com
+ * Author: Dongsoo Nathaniel Kim <dongsoo45.kim@samsung.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -106,23 +106,23 @@ struct m5mols_capture {
  * The each value according to each scenemode is recommended in the documents.
  */
 struct m5mols_scenemode {
-       u32 metering;
-       u32 ev_bias;
-       u32 wb_mode;
-       u32 wb_preset;
-       u32 chroma_en;
-       u32 chroma_lvl;
-       u32 edge_en;
-       u32 edge_lvl;
-       u32 af_range;
-       u32 fd_mode;
-       u32 mcc;
-       u32 light;
-       u32 flash;
-       u32 tone;
-       u32 iso;
-       u32 capt_mode;
-       u32 wdr;
+       u8 metering;
+       u8 ev_bias;
+       u8 wb_mode;
+       u8 wb_preset;
+       u8 chroma_en;
+       u8 chroma_lvl;
+       u8 edge_en;
+       u8 edge_lvl;
+       u8 af_range;
+       u8 fd_mode;
+       u8 mcc;
+       u8 light;
+       u8 flash;
+       u8 tone;
+       u8 iso;
+       u8 capt_mode;
+       u8 wdr;
 };
 
 /**
@@ -154,7 +154,6 @@ struct m5mols_version {
        u8      str[VERSION_STRING_SIZE];
        u8      af;
 };
-#define VERSION_SIZE sizeof(struct m5mols_version)
 
 /**
  * struct m5mols_info - M-5MOLS driver data structure
@@ -216,9 +215,9 @@ struct m5mols_info {
        bool lock_ae;
        bool lock_awb;
        u8 resolution;
-       u32 interrupt;
-       u32 mode;
-       u32 mode_save;
+       u8 interrupt;
+       u8 mode;
+       u8 mode_save;
        int (*set_power)(struct device *dev, int on);
 };
 
@@ -256,9 +255,11 @@ struct m5mols_info {
  *   +-------+---+----------+-----+------+------+------+------+
  *   - d[0..3]: according to size1
  */
-int m5mols_read(struct v4l2_subdev *sd, u32 reg_comb, u32 *val);
+int m5mols_read_u8(struct v4l2_subdev *sd, u32 reg_comb, u8 *val);
+int m5mols_read_u16(struct v4l2_subdev *sd, u32 reg_comb, u16 *val);
+int m5mols_read_u32(struct v4l2_subdev *sd, u32 reg_comb, u32 *val);
 int m5mols_write(struct v4l2_subdev *sd, u32 reg_comb, u32 val);
-int m5mols_busy(struct v4l2_subdev *sd, u8 category, u8 cmd, u32 value);
+int m5mols_busy(struct v4l2_subdev *sd, u8 category, u8 cmd, u8 value);
 
 /*
  * Mode operation of the M-5MOLS
@@ -280,12 +281,12 @@ int m5mols_busy(struct v4l2_subdev *sd, u8 category, u8 cmd, u32 value);
  * The available executing order between each modes are as follows:
  *   PARAMETER <---> MONITOR <---> CAPTURE
  */
-int m5mols_mode(struct m5mols_info *info, u32 mode);
+int m5mols_mode(struct m5mols_info *info, u8 mode);
 
-int m5mols_enable_interrupt(struct v4l2_subdev *sd, u32 reg);
+int m5mols_enable_interrupt(struct v4l2_subdev *sd, u8 reg);
 int m5mols_sync_controls(struct m5mols_info *info);
 int m5mols_start_capture(struct m5mols_info *info);
-int m5mols_do_scenemode(struct m5mols_info *info, u32 mode);
+int m5mols_do_scenemode(struct m5mols_info *info, u8 mode);
 int m5mols_lock_3a(struct m5mols_info *info, bool lock);
 int m5mols_set_ctrl(struct v4l2_ctrl *ctrl);
 
index d71a390..d947192 100644 (file)
@@ -2,10 +2,10 @@
  * The Capture code for Fujitsu M-5MOLS ISP
  *
  * Copyright (C) 2011 Samsung Electronics Co., Ltd.
- * Author: HeungJun Kim, riverful.kim@samsung.com
+ * Author: HeungJun Kim <riverful.kim@samsung.com>
  *
  * Copyright (C) 2009 Samsung Electronics Co., Ltd.
- * Author: Dongsoo Nathaniel Kim, dongsoo45.kim@samsung.com
+ * Author: Dongsoo Nathaniel Kim <dongsoo45.kim@samsung.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -58,9 +58,9 @@ static int m5mols_read_rational(struct v4l2_subdev *sd, u32 addr_num,
 {
        u32 num, den;
 
-       int ret = m5mols_read(sd, addr_num, &num);
+       int ret = m5mols_read_u32(sd, addr_num, &num);
        if (!ret)
-               ret = m5mols_read(sd, addr_den, &den);
+               ret = m5mols_read_u32(sd, addr_den, &den);
        if (ret)
                return ret;
        *val = den == 0 ? 0 : num / den;
@@ -99,20 +99,20 @@ static int m5mols_capture_info(struct m5mols_info *info)
        if (ret)
                return ret;
 
-       ret = m5mols_read(sd, EXIF_INFO_ISO, (u32 *)&exif->iso_speed);
+       ret = m5mols_read_u16(sd, EXIF_INFO_ISO, &exif->iso_speed);
        if (!ret)
-               ret = m5mols_read(sd, EXIF_INFO_FLASH, (u32 *)&exif->flash);
+               ret = m5mols_read_u16(sd, EXIF_INFO_FLASH, &exif->flash);
        if (!ret)
-               ret = m5mols_read(sd, EXIF_INFO_SDR, (u32 *)&exif->sdr);
+               ret = m5mols_read_u16(sd, EXIF_INFO_SDR, &exif->sdr);
        if (!ret)
-               ret = m5mols_read(sd, EXIF_INFO_QVAL, (u32 *)&exif->qval);
+               ret = m5mols_read_u16(sd, EXIF_INFO_QVAL, &exif->qval);
        if (ret)
                return ret;
 
        if (!ret)
-               ret = m5mols_read(sd, CAPC_IMAGE_SIZE, &info->cap.main);
+               ret = m5mols_read_u32(sd, CAPC_IMAGE_SIZE, &info->cap.main);
        if (!ret)
-               ret = m5mols_read(sd, CAPC_THUMB_SIZE, &info->cap.thumb);
+               ret = m5mols_read_u32(sd, CAPC_THUMB_SIZE, &info->cap.thumb);
        if (!ret)
                info->cap.total = info->cap.main + info->cap.thumb;
 
@@ -122,7 +122,7 @@ static int m5mols_capture_info(struct m5mols_info *info)
 int m5mols_start_capture(struct m5mols_info *info)
 {
        struct v4l2_subdev *sd = &info->sd;
-       u32 resolution = info->resolution;
+       u8 resolution = info->resolution;
        int timeout;
        int ret;
 
index 817c16f..d135d20 100644 (file)
@@ -2,10 +2,10 @@
  * Controls for M-5MOLS 8M Pixel camera sensor with ISP
  *
  * Copyright (C) 2011 Samsung Electronics Co., Ltd.
- * Author: HeungJun Kim, riverful.kim@samsung.com
+ * Author: HeungJun Kim <riverful.kim@samsung.com>
  *
  * Copyright (C) 2009 Samsung Electronics Co., Ltd.
- * Author: Dongsoo Nathaniel Kim, dongsoo45.kim@samsung.com
+ * Author: Dongsoo Nathaniel Kim <dongsoo45.kim@samsung.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -130,7 +130,7 @@ static struct m5mols_scenemode m5mols_default_scenemode[] = {
  *
  * WARNING: The execution order is important. Do not change the order.
  */
-int m5mols_do_scenemode(struct m5mols_info *info, u32 mode)
+int m5mols_do_scenemode(struct m5mols_info *info, u8 mode)
 {
        struct v4l2_subdev *sd = &info->sd;
        struct m5mols_scenemode scenemode = m5mols_default_scenemode[mode];
index 76eac26..43c68f5 100644 (file)
@@ -2,10 +2,10 @@
  * Driver for M-5MOLS 8M Pixel camera sensor with ISP
  *
  * Copyright (C) 2011 Samsung Electronics Co., Ltd.
- * Author: HeungJun Kim, riverful.kim@samsung.com
+ * Author: HeungJun Kim <riverful.kim@samsung.com>
  *
  * Copyright (C) 2009 Samsung Electronics Co., Ltd.
- * Author: Dongsoo Nathaniel Kim, dongsoo45.kim@samsung.com
+ * Author: Dongsoo Nathaniel Kim <dongsoo45.kim@samsung.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -133,13 +133,13 @@ static u32 m5mols_swap_byte(u8 *data, u8 length)
 /**
  * m5mols_read -  I2C read function
  * @reg: combination of size, category and command for the I2C packet
+ * @size: desired size of I2C packet
  * @val: read value
  */
-int m5mols_read(struct v4l2_subdev *sd, u32 reg, u32 *val)
+static int m5mols_read(struct v4l2_subdev *sd, u32 size, u32 reg, u32 *val)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
        u8 rbuf[M5MOLS_I2C_MAX_SIZE + 1];
-       u8 size = I2C_SIZE(reg);
        u8 category = I2C_CATEGORY(reg);
        u8 cmd = I2C_COMMAND(reg);
        struct i2c_msg msg[2];
@@ -149,11 +149,6 @@ int m5mols_read(struct v4l2_subdev *sd, u32 reg, u32 *val)
        if (!client->adapter)
                return -ENODEV;
 
-       if (size != 1 && size != 2 && size != 4) {
-               v4l2_err(sd, "Wrong data size\n");
-               return -EINVAL;
-       }
-
        msg[0].addr = client->addr;
        msg[0].flags = 0;
        msg[0].len = 5;
@@ -184,6 +179,52 @@ int m5mols_read(struct v4l2_subdev *sd, u32 reg, u32 *val)
        return 0;
 }
 
+int m5mols_read_u8(struct v4l2_subdev *sd, u32 reg, u8 *val)
+{
+       u32 val_32;
+       int ret;
+
+       if (I2C_SIZE(reg) != 1) {
+               v4l2_err(sd, "Wrong data size\n");
+               return -EINVAL;
+       }
+
+       ret = m5mols_read(sd, I2C_SIZE(reg), reg, &val_32);
+       if (ret)
+               return ret;
+
+       *val = (u8)val_32;
+       return ret;
+}
+
+int m5mols_read_u16(struct v4l2_subdev *sd, u32 reg, u16 *val)
+{
+       u32 val_32;
+       int ret;
+
+       if (I2C_SIZE(reg) != 2) {
+               v4l2_err(sd, "Wrong data size\n");
+               return -EINVAL;
+       }
+
+       ret = m5mols_read(sd, I2C_SIZE(reg), reg, &val_32);
+       if (ret)
+               return ret;
+
+       *val = (u16)val_32;
+       return ret;
+}
+
+int m5mols_read_u32(struct v4l2_subdev *sd, u32 reg, u32 *val)
+{
+       if (I2C_SIZE(reg) != 4) {
+               v4l2_err(sd, "Wrong data size\n");
+               return -EINVAL;
+       }
+
+       return m5mols_read(sd, I2C_SIZE(reg), reg, val);
+}
+
 /**
  * m5mols_write - I2C command write function
  * @reg: combination of size, category and command for the I2C packet
@@ -231,13 +272,14 @@ int m5mols_write(struct v4l2_subdev *sd, u32 reg, u32 val)
        return 0;
 }
 
-int m5mols_busy(struct v4l2_subdev *sd, u8 category, u8 cmd, u32 mask)
+int m5mols_busy(struct v4l2_subdev *sd, u8 category, u8 cmd, u8 mask)
 {
-       u32 busy, i;
+       u8 busy;
+       int i;
        int ret;
 
        for (i = 0; i < M5MOLS_I2C_CHECK_RETRY; i++) {
-               ret = m5mols_read(sd, I2C_REG(category, cmd, 1), &busy);
+               ret = m5mols_read_u8(sd, I2C_REG(category, cmd, 1), &busy);
                if (ret < 0)
                        return ret;
                if ((busy & mask) == mask)
@@ -252,14 +294,14 @@ int m5mols_busy(struct v4l2_subdev *sd, u8 category, u8 cmd, u32 mask)
  * Before writing desired interrupt value the INT_FACTOR register should
  * be read to clear pending interrupts.
  */
-int m5mols_enable_interrupt(struct v4l2_subdev *sd, u32 reg)
+int m5mols_enable_interrupt(struct v4l2_subdev *sd, u8 reg)
 {
        struct m5mols_info *info = to_m5mols(sd);
-       u32 mask = is_available_af(info) ? REG_INT_AF : 0;
-       u32 dummy;
+       u8 mask = is_available_af(info) ? REG_INT_AF : 0;
+       u8 dummy;
        int ret;
 
-       ret = m5mols_read(sd, SYSTEM_INT_FACTOR, &dummy);
+       ret = m5mols_read_u8(sd, SYSTEM_INT_FACTOR, &dummy);
        if (!ret)
                ret = m5mols_write(sd, SYSTEM_INT_ENABLE, reg & ~mask);
        return ret;
@@ -271,7 +313,7 @@ int m5mols_enable_interrupt(struct v4l2_subdev *sd, u32 reg)
  * It always accompanies a little delay changing the M-5MOLS mode, so it is
  * needed checking current busy status to guarantee right mode.
  */
-static int m5mols_reg_mode(struct v4l2_subdev *sd, u32 mode)
+static int m5mols_reg_mode(struct v4l2_subdev *sd, u8 mode)
 {
        int ret = m5mols_write(sd, SYSTEM_SYSMODE, mode);
 
@@ -286,16 +328,16 @@ static int m5mols_reg_mode(struct v4l2_subdev *sd, u32 mode)
  * can be guaranteed only when the sensor is operating in mode which which
  * a command belongs to.
  */
-int m5mols_mode(struct m5mols_info *info, u32 mode)
+int m5mols_mode(struct m5mols_info *info, u8 mode)
 {
        struct v4l2_subdev *sd = &info->sd;
        int ret = -EINVAL;
-       u32 reg;
+       u8 reg;
 
        if (mode < REG_PARAMETER && mode > REG_CAPTURE)
                return ret;
 
-       ret = m5mols_read(sd, SYSTEM_SYSMODE, &reg);
+       ret = m5mols_read_u8(sd, SYSTEM_SYSMODE, &reg);
        if ((!ret && reg == mode) || ret)
                return ret;
 
@@ -344,41 +386,37 @@ int m5mols_mode(struct m5mols_info *info, u32 mode)
 static int m5mols_get_version(struct v4l2_subdev *sd)
 {
        struct m5mols_info *info = to_m5mols(sd);
-       union {
-               struct m5mols_version ver;
-               u8 bytes[VERSION_SIZE];
-       } version;
-       u32 *value;
-       u8 cmd = CAT0_VER_CUSTOMER;
+       struct m5mols_version *ver = &info->ver;
+       u8 *str = ver->str;
+       int i;
        int ret;
 
-       do {
-               value = (u32 *)&version.bytes[cmd];
-               ret = m5mols_read(sd, SYSTEM_CMD(cmd), value);
-               if (ret)
-                       return ret;
-       } while (cmd++ != CAT0_VER_AWB);
+       ret = m5mols_read_u8(sd, SYSTEM_VER_CUSTOMER, &ver->customer);
+       if (!ret)
+               ret = m5mols_read_u8(sd, SYSTEM_VER_PROJECT, &ver->project);
+       if (!ret)
+               ret = m5mols_read_u16(sd, SYSTEM_VER_FIRMWARE, &ver->fw);
+       if (!ret)
+               ret = m5mols_read_u16(sd, SYSTEM_VER_HARDWARE, &ver->hw);
+       if (!ret)
+               ret = m5mols_read_u16(sd, SYSTEM_VER_PARAMETER, &ver->param);
+       if (!ret)
+               ret = m5mols_read_u16(sd, SYSTEM_VER_AWB, &ver->awb);
+       if (!ret)
+               ret = m5mols_read_u8(sd, AF_VERSION, &ver->af);
+       if (ret)
+               return ret;
 
-       do {
-               value = (u32 *)&version.bytes[cmd];
-               ret = m5mols_read(sd, SYSTEM_VER_STRING, value);
+       for (i = 0; i < VERSION_STRING_SIZE; i++) {
+               ret = m5mols_read_u8(sd, SYSTEM_VER_STRING, &str[i]);
                if (ret)
                        return ret;
-               if (cmd >= VERSION_SIZE - 1)
-                       return -EINVAL;
-       } while (version.bytes[cmd++]);
-
-       value = (u32 *)&version.bytes[cmd];
-       ret = m5mols_read(sd, AF_VERSION, value);
-       if (ret)
-               return ret;
+       }
 
-       /* store version information swapped for being readable */
-       info->ver       = version.ver;
-       info->ver.fw    = be16_to_cpu(info->ver.fw);
-       info->ver.hw    = be16_to_cpu(info->ver.hw);
-       info->ver.param = be16_to_cpu(info->ver.param);
-       info->ver.awb   = be16_to_cpu(info->ver.awb);
+       ver->fw = be16_to_cpu(ver->fw);
+       ver->hw = be16_to_cpu(ver->hw);
+       ver->param = be16_to_cpu(ver->param);
+       ver->awb = be16_to_cpu(ver->awb);
 
        v4l2_info(sd, "Manufacturer\t[%s]\n",
                        is_manufacturer(info, REG_SAMSUNG_ELECTRO) ?
@@ -722,7 +760,7 @@ static int m5mols_init_controls(struct m5mols_info *info)
        int ret;
 
        /* Determine value's range & step of controls for various FW version */
-       ret = m5mols_read(sd, AE_MAX_GAIN_MON, (u32 *)&max_exposure);
+       ret = m5mols_read_u16(sd, AE_MAX_GAIN_MON, &max_exposure);
        if (!ret)
                step_zoom = is_manufacturer(info, REG_SAMSUNG_OPTICS) ? 31 : 1;
        if (ret)
@@ -842,18 +880,18 @@ static void m5mols_irq_work(struct work_struct *work)
        struct m5mols_info *info =
                container_of(work, struct m5mols_info, work_irq);
        struct v4l2_subdev *sd = &info->sd;
-       u32 reg;
+       u8 reg;
        int ret;
 
        if (!is_powered(info) ||
-                       m5mols_read(sd, SYSTEM_INT_FACTOR, &info->interrupt))
+                       m5mols_read_u8(sd, SYSTEM_INT_FACTOR, &info->interrupt))
                return;
 
        switch (info->interrupt & REG_INT_MASK) {
        case REG_INT_AF:
                if (!is_available_af(info))
                        break;
-               ret = m5mols_read(sd, AF_STATUS, &reg);
+               ret = m5mols_read_u8(sd, AF_STATUS, &reg);
                v4l2_dbg(2, m5mols_debug, sd, "AF %s\n",
                         reg == REG_AF_FAIL ? "Failed" :
                         reg == REG_AF_SUCCESS ? "Success" :
index b83e36f..c755bd6 100644 (file)
@@ -2,10 +2,10 @@
  * Register map for M-5MOLS 8M Pixel camera sensor with ISP
  *
  * Copyright (C) 2011 Samsung Electronics Co., Ltd.
- * Author: HeungJun Kim, riverful.kim@samsung.com
+ * Author: HeungJun Kim <riverful.kim@samsung.com>
  *
  * Copyright (C) 2009 Samsung Electronics Co., Ltd.
- * Author: Dongsoo Nathaniel Kim, dongsoo45.kim@samsung.com
+ * Author: Dongsoo Nathaniel Kim <dongsoo45.kim@samsung.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * more specific contents, see definition if file m5mols.h.
  */
 #define CAT0_VER_CUSTOMER      0x00    /* customer version */
-#define CAT0_VER_AWB           0x09    /* Auto WB version */
+#define CAT0_VER_PROJECT       0x01    /* project version */
+#define CAT0_VER_FIRMWARE      0x02    /* Firmware version */
+#define CAT0_VER_HARDWARE      0x04    /* Hardware version */
+#define CAT0_VER_PARAMETER     0x06    /* Parameter version */
+#define CAT0_VER_AWB           0x08    /* Auto WB version */
 #define CAT0_VER_STRING                0x0a    /* string including M-5MOLS */
 #define CAT0_SYSMODE           0x0b    /* SYSTEM mode register */
 #define CAT0_STATUS            0x0c    /* SYSTEM mode status register */
 #define CAT0_INT_FACTOR                0x10    /* interrupt pending register */
 #define CAT0_INT_ENABLE                0x11    /* interrupt enable register */
 
+#define SYSTEM_VER_CUSTOMER    I2C_REG(CAT_SYSTEM, CAT0_VER_CUSTOMER, 1)
+#define SYSTEM_VER_PROJECT     I2C_REG(CAT_SYSTEM, CAT0_VER_PROJECT, 1)
+#define SYSTEM_VER_FIRMWARE    I2C_REG(CAT_SYSTEM, CAT0_VER_FIRMWARE, 2)
+#define SYSTEM_VER_HARDWARE    I2C_REG(CAT_SYSTEM, CAT0_VER_HARDWARE, 2)
+#define SYSTEM_VER_PARAMETER   I2C_REG(CAT_SYSTEM, CAT0_VER_PARAMETER, 2)
+#define SYSTEM_VER_AWB         I2C_REG(CAT_SYSTEM, CAT0_VER_AWB, 2)
+
 #define SYSTEM_SYSMODE         I2C_REG(CAT_SYSTEM, CAT0_SYSMODE, 1)
 #define REG_SYSINIT            0x00    /* SYSTEM mode */
 #define REG_PARAMETER          0x01    /* PARAMETER mode */
 #define REG_CAP_START_MAIN     0x01
 #define REG_CAP_START_THUMB    0x03
 
-#define CAPC_IMAGE_SIZE                I2C_REG(CAT_CAPT_CTRL, CATC_CAP_IMAGE_SIZE, 1)
-#define CAPC_THUMB_SIZE                I2C_REG(CAT_CAPT_CTRL, CATC_CAP_THUMB_SIZE, 1)
+#define CAPC_IMAGE_SIZE                I2C_REG(CAT_CAPT_CTRL, CATC_CAP_IMAGE_SIZE, 4)
+#define CAPC_THUMB_SIZE                I2C_REG(CAT_CAPT_CTRL, CATC_CAP_THUMB_SIZE, 4)
 
 /*
  * Category F - Flash
index bc0c23a..63f8a0c 100644 (file)
@@ -444,12 +444,9 @@ static int mx1_camera_add_device(struct soc_camera_device *icd)
 {
        struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
        struct mx1_camera_dev *pcdev = ici->priv;
-       int ret;
 
-       if (pcdev->icd) {
-               ret = -EBUSY;
-               goto ebusy;
-       }
+       if (pcdev->icd)
+               return -EBUSY;
 
        dev_info(icd->dev.parent, "MX1 Camera driver attached to camera %d\n",
                 icd->devnum);
@@ -458,8 +455,7 @@ static int mx1_camera_add_device(struct soc_camera_device *icd)
 
        pcdev->icd = icd;
 
-ebusy:
-       return ret;
+       return 0;
 }
 
 static void mx1_camera_remove_device(struct soc_camera_device *icd)
index 4ada9be..4d07c58 100644 (file)
@@ -982,6 +982,14 @@ static int omap_vout_buffer_setup(struct videobuf_queue *q, unsigned int *count,
        startindex = (vout->vid == OMAP_VIDEO1) ?
                video1_numbuffers : video2_numbuffers;
 
+       /* Check the size of the buffer */
+       if (*size > vout->buffer_size) {
+               v4l2_err(&vout->vid_dev->v4l2_dev,
+                               "buffer allocation mismatch [%u] [%u]\n",
+                               *size, vout->buffer_size);
+               return -ENOMEM;
+       }
+
        for (i = startindex; i < *count; i++) {
                vout->buffer_size = *size;
 
@@ -1228,6 +1236,14 @@ static int omap_vout_mmap(struct file *file, struct vm_area_struct *vma)
                                (vma->vm_pgoff << PAGE_SHIFT));
                return -EINVAL;
        }
+       /* Check the size of the buffer */
+       if (size > vout->buffer_size) {
+               v4l2_err(&vout->vid_dev->v4l2_dev,
+                               "insufficient memory [%lu] [%u]\n",
+                               size, vout->buffer_size);
+               return -ENOMEM;
+       }
+
        q->bufs[i]->baddr = vma->vm_start;
 
        vma->vm_flags |= VM_RESERVED;
@@ -2391,7 +2407,7 @@ static int __init omap_vout_create_video_devices(struct platform_device *pdev)
                /* Register the Video device with V4L2
                 */
                vfd = vout->vfd;
-               if (video_register_device(vfd, VFL_TYPE_GRABBER, k + 1) < 0) {
+               if (video_register_device(vfd, VFL_TYPE_GRABBER, -1) < 0) {
                        dev_err(&pdev->dev, ": Could not register "
                                        "Video for Linux device\n");
                        vfd->minor = -1;
index 2aa6a76..8ae7481 100644 (file)
@@ -193,7 +193,7 @@ int omap_vout_new_crop(struct v4l2_pix_format *pix,
                return -EINVAL;
 
        if (cpu_is_omap24xx()) {
-               if (crop->height != win->w.height) {
+               if (try_crop.height != win->w.height) {
                        /* If we're resizing vertically, we can't support a
                         * crop width wider than 768 pixels.
                         */
@@ -202,7 +202,7 @@ int omap_vout_new_crop(struct v4l2_pix_format *pix,
                }
        }
        /* vertical resizing */
-       vresize = (1024 * crop->height) / win->w.height;
+       vresize = (1024 * try_crop.height) / win->w.height;
        if (cpu_is_omap24xx() && (vresize > 2048))
                vresize = 2048;
        else if (cpu_is_omap34xx() && (vresize > 4096))
@@ -221,7 +221,7 @@ int omap_vout_new_crop(struct v4l2_pix_format *pix,
                        try_crop.height = 2;
        }
        /* horizontal resizing */
-       hresize = (1024 * crop->width) / win->w.width;
+       hresize = (1024 * try_crop.width) / win->w.width;
        if (cpu_is_omap24xx() && (hresize > 2048))
                hresize = 2048;
        else if (cpu_is_omap34xx() && (hresize > 4096))
index c9fd04e..94b6ed8 100644 (file)
@@ -1748,7 +1748,7 @@ static int isp_register_entities(struct isp_device *isp)
                goto done;
 
        /* Register external entities */
-       for (subdevs = pdata->subdevs; subdevs->subdevs; ++subdevs) {
+       for (subdevs = pdata->subdevs; subdevs && subdevs->subdevs; ++subdevs) {
                struct v4l2_subdev *sensor;
                struct media_entity *input;
                unsigned int flags;
index 1593f8d..760b4de 100644 (file)
@@ -1414,7 +1414,7 @@ long pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
        {
                ARG_DEF(struct pwc_probe, probe)
 
-               strcpy(ARGR(probe).name, pdev->vdev->name);
+               strcpy(ARGR(probe).name, pdev->vdev.name);
                ARGR(probe).type = pdev->type;
                ARG_OUT(probe)
                break;
index 356cd42..b0bde5a 100644 (file)
@@ -40,7 +40,7 @@
    Oh yes, convention: to disctinguish between all the various pointers to
    device-structures, I use these names for the pointer variables:
    udev: struct usb_device *
-   vdev: struct video_device *
+   vdev: struct video_device (member of pwc_dev)
    pdev: struct pwc_devive *
 */
 
@@ -152,6 +152,7 @@ static ssize_t pwc_video_read(struct file *file, char __user *buf,
                          size_t count, loff_t *ppos);
 static unsigned int pwc_video_poll(struct file *file, poll_table *wait);
 static int  pwc_video_mmap(struct file *file, struct vm_area_struct *vma);
+static void pwc_video_release(struct video_device *vfd);
 
 static const struct v4l2_file_operations pwc_fops = {
        .owner =        THIS_MODULE,
@@ -164,41 +165,11 @@ static const struct v4l2_file_operations pwc_fops = {
 };
 static struct video_device pwc_template = {
        .name =         "Philips Webcam",       /* Filled in later */
-       .release =      video_device_release,
+       .release =      pwc_video_release,
        .fops =         &pwc_fops,
+       .ioctl_ops =    &pwc_ioctl_ops,
 };
 
-/***************************************************************************/
-
-/* Okay, this is some magic that I worked out and the reasoning behind it...
-
-   The biggest problem with any USB device is of course: "what to do
-   when the user unplugs the device while it is in use by an application?"
-   We have several options:
-   1) Curse them with the 7 plagues when they do (requires divine intervention)
-   2) Tell them not to (won't work: they'll do it anyway)
-   3) Oops the kernel (this will have a negative effect on a user's uptime)
-   4) Do something sensible.
-
-   Of course, we go for option 4.
-
-   It happens that this device will be linked to two times, once from
-   usb_device and once from the video_device in their respective 'private'
-   pointers. This is done when the device is probed() and all initialization
-   succeeded. The pwc_device struct links back to both structures.
-
-   When a device is unplugged while in use it will be removed from the
-   list of known USB devices; I also de-register it as a V4L device, but
-   unfortunately I can't free the memory since the struct is still in use
-   by the file descriptor. This free-ing is then deferend until the first
-   opportunity. Crude, but it works.
-
-   A small 'advantage' is that if a user unplugs the cam and plugs it back
-   in, it should get assigned the same video device minor, but unfortunately
-   it's non-trivial to re-link the cam back to the video device... (that
-   would surely be magic! :))
-*/
-
 /***************************************************************************/
 /* Private functions */
 
@@ -1016,16 +987,15 @@ static ssize_t show_snapshot_button_status(struct device *class_dev,
 static DEVICE_ATTR(button, S_IRUGO | S_IWUSR, show_snapshot_button_status,
                   NULL);
 
-static int pwc_create_sysfs_files(struct video_device *vdev)
+static int pwc_create_sysfs_files(struct pwc_device *pdev)
 {
-       struct pwc_device *pdev = video_get_drvdata(vdev);
        int rc;
 
-       rc = device_create_file(&vdev->dev, &dev_attr_button);
+       rc = device_create_file(&pdev->vdev.dev, &dev_attr_button);
        if (rc)
                goto err;
        if (pdev->features & FEATURE_MOTOR_PANTILT) {
-               rc = device_create_file(&vdev->dev, &dev_attr_pan_tilt);
+               rc = device_create_file(&pdev->vdev.dev, &dev_attr_pan_tilt);
                if (rc)
                        goto err_button;
        }
@@ -1033,19 +1003,17 @@ static int pwc_create_sysfs_files(struct video_device *vdev)
        return 0;
 
 err_button:
-       device_remove_file(&vdev->dev, &dev_attr_button);
+       device_remove_file(&pdev->vdev.dev, &dev_attr_button);
 err:
        PWC_ERROR("Could not create sysfs files.\n");
        return rc;
 }
 
-static void pwc_remove_sysfs_files(struct video_device *vdev)
+static void pwc_remove_sysfs_files(struct pwc_device *pdev)
 {
-       struct pwc_device *pdev = video_get_drvdata(vdev);
-
        if (pdev->features & FEATURE_MOTOR_PANTILT)
-               device_remove_file(&vdev->dev, &dev_attr_pan_tilt);
-       device_remove_file(&vdev->dev, &dev_attr_button);
+               device_remove_file(&pdev->vdev.dev, &dev_attr_pan_tilt);
+       device_remove_file(&pdev->vdev.dev, &dev_attr_button);
 }
 
 #ifdef CONFIG_USB_PWC_DEBUG
@@ -1106,7 +1074,7 @@ static int pwc_video_open(struct file *file)
                if (ret >= 0)
                {
                        PWC_DEBUG_OPEN("This %s camera is equipped with a %s (%d).\n",
-                                       pdev->vdev->name,
+                                       pdev->vdev.name,
                                        pwc_sensor_type_to_string(i), i);
                }
        }
@@ -1180,16 +1148,15 @@ static int pwc_video_open(struct file *file)
        return 0;
 }
 
-
-static void pwc_cleanup(struct pwc_device *pdev)
+static void pwc_video_release(struct video_device *vfd)
 {
-       pwc_remove_sysfs_files(pdev->vdev);
-       video_unregister_device(pdev->vdev);
+       struct pwc_device *pdev = container_of(vfd, struct pwc_device, vdev);
+       int hint;
 
-#ifdef CONFIG_USB_PWC_INPUT_EVDEV
-       if (pdev->button_dev)
-               input_unregister_device(pdev->button_dev);
-#endif
+       /* search device_hint[] table if we occupy a slot, by any chance */
+       for (hint = 0; hint < MAX_DEV_HINTS; hint++)
+               if (device_hint[hint].pdev == pdev)
+                       device_hint[hint].pdev = NULL;
 
        kfree(pdev);
 }
@@ -1199,7 +1166,7 @@ static int pwc_video_close(struct file *file)
 {
        struct video_device *vdev = file->private_data;
        struct pwc_device *pdev;
-       int i, hint;
+       int i;
 
        PWC_DEBUG_OPEN(">> video_close called(vdev = 0x%p).\n", vdev);
 
@@ -1234,12 +1201,6 @@ static int pwc_video_close(struct file *file)
                }
                pdev->vopen--;
                PWC_DEBUG_OPEN("<< video_close() vopen=%d\n", pdev->vopen);
-       } else {
-               pwc_cleanup(pdev);
-               /* search device_hint[] table if we occupy a slot, by any chance */
-               for (hint = 0; hint < MAX_DEV_HINTS; hint++)
-                       if (device_hint[hint].pdev == pdev)
-                               device_hint[hint].pdev = NULL;
        }
 
        return 0;
@@ -1715,19 +1676,12 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
        init_waitqueue_head(&pdev->frameq);
        pdev->vcompression = pwc_preferred_compression;
 
-       /* Allocate video_device structure */
-       pdev->vdev = video_device_alloc();
-       if (!pdev->vdev) {
-               PWC_ERROR("Err, cannot allocate video_device struture. Failing probe.");
-               rc = -ENOMEM;
-               goto err_free_mem;
-       }
-       memcpy(pdev->vdev, &pwc_template, sizeof(pwc_template));
-       pdev->vdev->parent = &intf->dev;
-       pdev->vdev->lock = &pdev->modlock;
-       pdev->vdev->ioctl_ops = &pwc_ioctl_ops;
-       strcpy(pdev->vdev->name, name);
-       video_set_drvdata(pdev->vdev, pdev);
+       /* Init video_device structure */
+       memcpy(&pdev->vdev, &pwc_template, sizeof(pwc_template));
+       pdev->vdev.parent = &intf->dev;
+       pdev->vdev.lock = &pdev->modlock;
+       strcpy(pdev->vdev.name, name);
+       video_set_drvdata(&pdev->vdev, pdev);
 
        pdev->release = le16_to_cpu(udev->descriptor.bcdDevice);
        PWC_DEBUG_PROBE("Release: %04x\n", pdev->release);
@@ -1746,8 +1700,6 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
                }
        }
 
-       pdev->vdev->release = video_device_release;
-
        /* occupy slot */
        if (hint < MAX_DEV_HINTS)
                device_hint[hint].pdev = pdev;
@@ -1759,16 +1711,16 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
        pwc_set_leds(pdev, 0, 0);
        pwc_camera_power(pdev, 0);
 
-       rc = video_register_device(pdev->vdev, VFL_TYPE_GRABBER, video_nr);
+       rc = video_register_device(&pdev->vdev, VFL_TYPE_GRABBER, video_nr);
        if (rc < 0) {
                PWC_ERROR("Failed to register as video device (%d).\n", rc);
-               goto err_video_release;
+               goto err_free_mem;
        }
-       rc = pwc_create_sysfs_files(pdev->vdev);
+       rc = pwc_create_sysfs_files(pdev);
        if (rc)
                goto err_video_unreg;
 
-       PWC_INFO("Registered as %s.\n", video_device_node_name(pdev->vdev));
+       PWC_INFO("Registered as %s.\n", video_device_node_name(&pdev->vdev));
 
 #ifdef CONFIG_USB_PWC_INPUT_EVDEV
        /* register webcam snapshot button input device */
@@ -1776,7 +1728,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
        if (!pdev->button_dev) {
                PWC_ERROR("Err, insufficient memory for webcam snapshot button device.");
                rc = -ENOMEM;
-               pwc_remove_sysfs_files(pdev->vdev);
+               pwc_remove_sysfs_files(pdev);
                goto err_video_unreg;
        }
 
@@ -1794,7 +1746,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
        if (rc) {
                input_free_device(pdev->button_dev);
                pdev->button_dev = NULL;
-               pwc_remove_sysfs_files(pdev->vdev);
+               pwc_remove_sysfs_files(pdev);
                goto err_video_unreg;
        }
 #endif
@@ -1804,10 +1756,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
 err_video_unreg:
        if (hint < MAX_DEV_HINTS)
                device_hint[hint].pdev = NULL;
-       video_unregister_device(pdev->vdev);
-       pdev->vdev = NULL;      /* So we don't try to release it below */
-err_video_release:
-       video_device_release(pdev->vdev);
+       video_unregister_device(&pdev->vdev);
 err_free_mem:
        kfree(pdev);
        return rc;
@@ -1816,10 +1765,8 @@ err_free_mem:
 /* The user yanked out the cable... */
 static void usb_pwc_disconnect(struct usb_interface *intf)
 {
-       struct pwc_device *pdev;
-       int hint;
+       struct pwc_device *pdev  = usb_get_intfdata(intf);
 
-       pdev = usb_get_intfdata (intf);
        mutex_lock(&pdev->modlock);
        usb_set_intfdata (intf, NULL);
        if (pdev == NULL) {
@@ -1836,30 +1783,25 @@ static void usb_pwc_disconnect(struct usb_interface *intf)
        }
 
        /* We got unplugged; this is signalled by an EPIPE error code */
-       if (pdev->vopen) {
-               PWC_INFO("Disconnected while webcam is in use!\n");
-               pdev->error_status = EPIPE;
-       }
+       pdev->error_status = EPIPE;
+       pdev->unplugged = 1;
 
        /* Alert waiting processes */
        wake_up_interruptible(&pdev->frameq);
-       /* Wait until device is closed */
-       if (pdev->vopen) {
-               pdev->unplugged = 1;
-               pwc_iso_stop(pdev);
-       } else {
-               /* Device is closed, so we can safely unregister it */
-               PWC_DEBUG_PROBE("Unregistering video device in disconnect().\n");
 
-disconnect_out:
-               /* search device_hint[] table if we occupy a slot, by any chance */
-               for (hint = 0; hint < MAX_DEV_HINTS; hint++)
-                       if (device_hint[hint].pdev == pdev)
-                               device_hint[hint].pdev = NULL;
-       }
+       /* No need to keep the urbs around after disconnection */
+       pwc_isoc_cleanup(pdev);
 
+disconnect_out:
        mutex_unlock(&pdev->modlock);
-       pwc_cleanup(pdev);
+
+       pwc_remove_sysfs_files(pdev);
+       video_unregister_device(&pdev->vdev);
+
+#ifdef CONFIG_USB_PWC_INPUT_EVDEV
+       if (pdev->button_dev)
+               input_unregister_device(pdev->button_dev);
+#endif
 }
 
 
index e947766..083f8b1 100644 (file)
@@ -162,9 +162,9 @@ struct pwc_imgbuf
 
 struct pwc_device
 {
-   struct video_device *vdev;
+       struct video_device vdev;
 
-   /* Pointer to our usb_device */
+   /* Pointer to our usb_device, may be NULL after unplug */
    struct usb_device *udev;
 
    int type;                    /* type of cam (645, 646, 675, 680, 690, 720, 730, 740, 750) */
index d142b40..81b4a82 100644 (file)
@@ -1,7 +1,7 @@
 /*
- * Samsung S5P SoC series camera interface (camera capture) driver
+ * Samsung S5P/EXYNOS4 SoC series camera interface (camera capture) driver
  *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd
+ * Copyright (C) 2010 - 2011 Samsung Electronics Co., Ltd.
  * Author: Sylwester Nawrocki, <s.nawrocki@samsung.com>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -262,12 +262,7 @@ static unsigned int get_plane_size(struct fimc_frame *fr, unsigned int plane)
 {
        if (!fr || plane >= fr->fmt->memplanes)
                return 0;
-
-       dbg("%s: w: %d. h: %d. depth[%d]: %d",
-           __func__, fr->width, fr->height, plane, fr->fmt->depth[plane]);
-
        return fr->f_width * fr->f_height * fr->fmt->depth[plane] / 8;
-
 }
 
 static int queue_setup(struct vb2_queue *vq, unsigned int *num_buffers,
@@ -283,24 +278,14 @@ static int queue_setup(struct vb2_queue *vq, unsigned int *num_buffers,
 
        *num_planes = fmt->memplanes;
 
-       dbg("%s, buffer count=%d, plane count=%d",
-           __func__, *num_buffers, *num_planes);
-
        for (i = 0; i < fmt->memplanes; i++) {
                sizes[i] = get_plane_size(&ctx->d_frame, i);
-               dbg("plane: %u, plane_size: %lu", i, sizes[i]);
                allocators[i] = ctx->fimc_dev->alloc_ctx;
        }
 
        return 0;
 }
 
-static int buffer_init(struct vb2_buffer *vb)
-{
-       /* TODO: */
-       return 0;
-}
-
 static int buffer_prepare(struct vb2_buffer *vb)
 {
        struct vb2_queue *vq = vb->vb2_queue;
@@ -380,7 +365,6 @@ static struct vb2_ops fimc_capture_qops = {
        .queue_setup            = queue_setup,
        .buf_prepare            = buffer_prepare,
        .buf_queue              = buffer_queue,
-       .buf_init               = buffer_init,
        .wait_prepare           = fimc_unlock,
        .wait_finish            = fimc_lock,
        .start_streaming        = start_streaming,
@@ -903,6 +887,7 @@ err_vd_reg:
 err_v4l2_reg:
        v4l2_device_unregister(v4l2_dev);
 err_info:
+       kfree(ctx);
        dev_err(&fimc->pdev->dev, "failed to install\n");
        return ret;
 }
index dc91a85..bdf19ad 100644 (file)
@@ -1,9 +1,8 @@
 /*
- * S5P camera interface (video postprocessor) driver
+ * Samsung S5P/EXYNOS4 SoC series camera interface (video postprocessor) driver
  *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd
- *
- * Sylwester Nawrocki, <s.nawrocki@samsung.com>
+ * Copyright (C) 2010-2011 Samsung Electronics Co., Ltd.
+ * Contact: Sylwester Nawrocki, <s.nawrocki@samsung.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published
@@ -42,7 +41,6 @@ static struct fimc_fmt fimc_formats[] = {
                .color          = S5P_FIMC_RGB565,
                .memplanes      = 1,
                .colplanes      = 1,
-               .mbus_code      = V4L2_MBUS_FMT_RGB565_2X8_BE,
                .flags          = FMT_FLAGS_M2M,
        }, {
                .name           = "BGR666",
@@ -232,11 +230,7 @@ static int fimc_get_scaler_factor(u32 src, u32 tar, u32 *ratio, u32 *shift)
                        return 0;
                }
        }
-
        *shift = 0, *ratio = 1;
-
-       dbg("s: %d, t: %d, shift: %d, ratio: %d",
-           src, tar, *shift, *ratio);
        return 0;
 }
 
@@ -268,10 +262,8 @@ int fimc_set_scaler_info(struct fimc_ctx *ctx)
                err("invalid source size: %d x %d", sx, sy);
                return -EINVAL;
        }
-
        sc->real_width = sx;
        sc->real_height = sy;
-       dbg("sx= %d, sy= %d, tx= %d, ty= %d", sx, sy, tx, ty);
 
        ret = fimc_get_scaler_factor(sx, tx, &sc->pre_hratio, &sc->hfactor);
        if (ret)
@@ -711,22 +703,18 @@ static int fimc_queue_setup(struct vb2_queue *vq, unsigned int *num_buffers,
        f = ctx_get_frame(ctx, vq->type);
        if (IS_ERR(f))
                return PTR_ERR(f);
-
        /*
         * Return number of non-contigous planes (plane buffers)
         * depending on the configured color format.
         */
-       if (f->fmt)
-               *num_planes = f->fmt->memplanes;
+       if (!f->fmt)
+               return -EINVAL;
 
+       *num_planes = f->fmt->memplanes;
        for (i = 0; i < f->fmt->memplanes; i++) {
-               sizes[i] = (f->width * f->height * f->fmt->depth[i]) >> 3;
+               sizes[i] = (f->f_width * f->f_height * f->fmt->depth[i]) / 8;
                allocators[i] = ctx->fimc_dev->alloc_ctx;
        }
-
-       if (*num_buffers == 0)
-               *num_buffers = 1;
-
        return 0;
 }
 
@@ -852,7 +840,7 @@ struct fimc_fmt *find_format(struct v4l2_format *f, unsigned int mask)
 
        for (i = 0; i < ARRAY_SIZE(fimc_formats); ++i) {
                fmt = &fimc_formats[i];
-               if (fmt->fourcc == f->fmt.pix.pixelformat &&
+               if (fmt->fourcc == f->fmt.pix_mp.pixelformat &&
                   (fmt->flags & mask))
                        break;
        }
index 3beb1e5..1f70772 100644 (file)
@@ -1,7 +1,5 @@
 /*
- * Copyright (c) 2010 Samsung Electronics
- *
- * Sylwester Nawrocki, <s.nawrocki@samsung.com>
+ * Copyright (C) 2010 - 2011 Samsung Electronics Co., Ltd.
  *
  * 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
@@ -135,9 +133,10 @@ enum fimc_color_fmt {
  * @name: format description
  * @fourcc: the fourcc code for this format, 0 if not applicable
  * @color: the corresponding fimc_color_fmt
- * @depth: per plane driver's private 'number of bits per pixel'
  * @memplanes: number of physically non-contiguous data planes
  * @colplanes: number of physically contiguous data planes
+ * @depth: per plane driver's private 'number of bits per pixel'
+ * @flags: flags indicating which operation mode format applies to
  */
 struct fimc_fmt {
        enum v4l2_mbus_pixelcode mbus_code;
@@ -171,7 +170,7 @@ struct fimc_dma_offset {
 };
 
 /**
- * struct fimc_effect - the configuration data for the "Arbitrary" image effect
+ * struct fimc_effect - color effect information
  * @type:      effect type
  * @pat_cb:    cr value when type is "arbitrary"
  * @pat_cr:    cr value when type is "arbitrary"
@@ -184,7 +183,6 @@ struct fimc_effect {
 
 /**
  * struct fimc_scaler - the configuration data for FIMC inetrnal scaler
- *
  * @scaleup_h:         flag indicating scaling up horizontally
  * @scaleup_v:         flag indicating scaling up vertically
  * @copy_mode:         flag indicating transparent DMA transfer (no scaling
@@ -220,7 +218,6 @@ struct fimc_scaler {
 
 /**
  * struct fimc_addr - the FIMC physical address set for DMA
- *
  * @y:  luminance plane physical address
  * @cb:         Cb plane physical address
  * @cr:         Cr plane physical address
@@ -234,6 +231,7 @@ struct fimc_addr {
 /**
  * struct fimc_vid_buffer - the driver's video buffer
  * @vb:    v4l videobuf buffer
+ * @list:  linked list structure for buffer queue
  * @paddr: precalculated physical address set
  * @index: buffer index for the output DMA engine
  */
@@ -254,11 +252,10 @@ struct fimc_vid_buffer {
  * @offs_v:    image vertical pixel offset
  * @width:     image pixel width
  * @height:    image pixel weight
- * @paddr:     image frame buffer physical addresses
- * @buf_cnt:   number of buffers depending on a color format
  * @payload:   image size in bytes (w x h x bpp)
- * @color:     color format
+ * @paddr:     image frame buffer physical addresses
  * @dma_offset:        DMA offset in bytes
+ * @fmt:       fimc color format pointer
  */
 struct fimc_frame {
        u32     f_width;
@@ -390,21 +387,22 @@ struct fimc_ctx;
 
 /**
  * struct fimc_dev - abstraction for FIMC entity
- *
  * @slock:     the spinlock protecting this data structure
  * @lock:      the mutex protecting this data structure
  * @pdev:      pointer to the FIMC platform device
  * @pdata:     pointer to the device platform data
+ * @variant:   the IP variant information
  * @id:                FIMC device index (0..FIMC_MAX_DEVS)
  * @num_clocks: the number of clocks managed by this device instance
- * @clock[]:   the clocks required for FIMC operation
+ * @clock:     clocks required for FIMC operation
  * @regs:      the mapped hardware registers
  * @regs_res:  the resource claimed for IO registers
- * @irq:       interrupt number of the FIMC subdevice
- * @irq_queue:
+ * @irq:       FIMC interrupt number
+ * @irq_queue: interrupt handler waitqueue
  * @m2m:       memory-to-memory V4L2 device information
  * @vid_cap:   camera capture device information
  * @state:     flags used to synchronize m2m and capture mode operation
+ * @alloc_ctx: videobuf2 memory allocator context
  */
 struct fimc_dev {
        spinlock_t                      slock;
@@ -427,8 +425,7 @@ struct fimc_dev {
 
 /**
  * fimc_ctx - the device context data
- *
- * @lock:              mutex protecting this data structure
+ * @slock:             spinlock protecting this data structure
  * @s_frame:           source frame properties
  * @d_frame:           destination frame properties
  * @out_order_1p:      output 1-plane YCBCR order
index ff6c0e9..d4ee24b 100644 (file)
@@ -963,7 +963,7 @@ static int saa7134_raw_decode_irq(struct saa7134_dev *dev)
         * to work with other protocols.
         */
        if (!ir->active) {
-               timeout = jiffies + jiffies_to_msecs(15);
+               timeout = jiffies + msecs_to_jiffies(15);
                mod_timer(&ir->timer, timeout);
                ir->active = true;
        }
index c3ab0c8..48fea37 100644 (file)
@@ -27,14 +27,20 @@ static int uvc_mc_register_entity(struct uvc_video_chain *chain,
        struct uvc_entity *entity)
 {
        const u32 flags = MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE;
-       struct uvc_entity *remote;
+       struct media_entity *sink;
        unsigned int i;
-       u8 remote_pad;
-       int ret = 0;
+       int ret;
+
+       sink = (UVC_ENTITY_TYPE(entity) == UVC_TT_STREAMING)
+            ? (entity->vdev ? &entity->vdev->entity : NULL)
+            : &entity->subdev.entity;
+       if (sink == NULL)
+               return 0;
 
        for (i = 0; i < entity->num_pads; ++i) {
                struct media_entity *source;
-               struct media_entity *sink;
+               struct uvc_entity *remote;
+               u8 remote_pad;
 
                if (!(entity->pads[i].flags & MEDIA_PAD_FL_SINK))
                        continue;
@@ -43,10 +49,11 @@ static int uvc_mc_register_entity(struct uvc_video_chain *chain,
                if (remote == NULL)
                        return -EINVAL;
 
-               source = (UVC_ENTITY_TYPE(remote) == UVC_TT_STREAMING)
-                      ? &remote->vdev->entity : &remote->subdev.entity;
-               sink = (UVC_ENTITY_TYPE(entity) == UVC_TT_STREAMING)
-                    ? &entity->vdev->entity : &entity->subdev.entity;
+               source = (UVC_ENTITY_TYPE(remote) != UVC_TT_STREAMING)
+                      ? (remote->vdev ? &remote->vdev->entity : NULL)
+                      : &remote->subdev.entity;
+               if (source == NULL)
+                       continue;
 
                remote_pad = remote->num_pads - 1;
                ret = media_entity_create_link(source, remote_pad,
@@ -55,11 +62,10 @@ static int uvc_mc_register_entity(struct uvc_video_chain *chain,
                        return ret;
        }
 
-       if (UVC_ENTITY_TYPE(entity) != UVC_TT_STREAMING)
-               ret = v4l2_device_register_subdev(&chain->dev->vdev,
-                                                 &entity->subdev);
+       if (UVC_ENTITY_TYPE(entity) == UVC_TT_STREAMING)
+               return 0;
 
-       return ret;
+       return v4l2_device_register_subdev(&chain->dev->vdev, &entity->subdev);
 }
 
 static struct v4l2_subdev_ops uvc_subdev_ops = {
@@ -84,9 +90,11 @@ static int uvc_mc_init_entity(struct uvc_entity *entity)
 
                ret = media_entity_init(&entity->subdev.entity,
                                        entity->num_pads, entity->pads, 0);
-       } else
+       } else if (entity->vdev != NULL) {
                ret = media_entity_init(&entity->vdev->entity,
                                        entity->num_pads, entity->pads, 0);
+       } else
+               ret = 0;
 
        return ret;
 }
index 109a063..f90ce9f 100644 (file)
@@ -104,6 +104,8 @@ static int __uvc_free_buffers(struct uvc_video_queue *queue)
        }
 
        if (queue->count) {
+               uvc_queue_cancel(queue, 0);
+               INIT_LIST_HEAD(&queue->mainqueue);
                vfree(queue->mem);
                queue->count = 0;
        }
index fc766b9..4999479 100644 (file)
@@ -1255,8 +1255,10 @@ int uvc_video_enable(struct uvc_streaming *stream, int enable)
 
        /* Commit the streaming parameters. */
        ret = uvc_commit_video(stream, &stream->ctrl);
-       if (ret < 0)
+       if (ret < 0) {
+               uvc_queue_enable(&stream->queue, 0);
                return ret;
+       }
 
        return uvc_init_video(stream, GFP_KERNEL);
 }
index 19d5ae2..06f1400 100644 (file)
@@ -167,6 +167,12 @@ static void v4l2_device_release(struct device *cd)
 
        mutex_unlock(&videodev_lock);
 
+#if defined(CONFIG_MEDIA_CONTROLLER)
+       if (vdev->v4l2_dev && vdev->v4l2_dev->mdev &&
+           vdev->vfl_type != VFL_TYPE_SUBDEV)
+               media_device_unregister_entity(&vdev->entity);
+#endif
+
        /* Release video_device and perform other
           cleanups as needed. */
        vdev->release(vdev);
@@ -389,9 +395,6 @@ static int v4l2_mmap(struct file *filp, struct vm_area_struct *vm)
 static int v4l2_open(struct inode *inode, struct file *filp)
 {
        struct video_device *vdev;
-#if defined(CONFIG_MEDIA_CONTROLLER)
-       struct media_entity *entity = NULL;
-#endif
        int ret = 0;
 
        /* Check if the video device is available */
@@ -405,17 +408,6 @@ static int v4l2_open(struct inode *inode, struct file *filp)
        /* and increase the device refcount */
        video_get(vdev);
        mutex_unlock(&videodev_lock);
-#if defined(CONFIG_MEDIA_CONTROLLER)
-       if (vdev->v4l2_dev && vdev->v4l2_dev->mdev &&
-           vdev->vfl_type != VFL_TYPE_SUBDEV) {
-               entity = media_entity_get(&vdev->entity);
-               if (!entity) {
-                       ret = -EBUSY;
-                       video_put(vdev);
-                       return ret;
-               }
-       }
-#endif
        if (vdev->fops->open) {
                if (vdev->lock && mutex_lock_interruptible(vdev->lock)) {
                        ret = -ERESTARTSYS;
@@ -431,14 +423,8 @@ static int v4l2_open(struct inode *inode, struct file *filp)
 
 err:
        /* decrease the refcount in case of an error */
-       if (ret) {
-#if defined(CONFIG_MEDIA_CONTROLLER)
-               if (vdev->v4l2_dev && vdev->v4l2_dev->mdev &&
-                   vdev->vfl_type != VFL_TYPE_SUBDEV)
-                       media_entity_put(entity);
-#endif
+       if (ret)
                video_put(vdev);
-       }
        return ret;
 }
 
@@ -455,11 +441,6 @@ static int v4l2_release(struct inode *inode, struct file *filp)
                if (vdev->lock)
                        mutex_unlock(vdev->lock);
        }
-#if defined(CONFIG_MEDIA_CONTROLLER)
-       if (vdev->v4l2_dev && vdev->v4l2_dev->mdev &&
-           vdev->vfl_type != VFL_TYPE_SUBDEV)
-               media_entity_put(&vdev->entity);
-#endif
        /* decrease the refcount unconditionally since the release()
           return value is ignored. */
        video_put(vdev);
@@ -754,12 +735,6 @@ void video_unregister_device(struct video_device *vdev)
        if (!vdev || !video_is_registered(vdev))
                return;
 
-#if defined(CONFIG_MEDIA_CONTROLLER)
-       if (vdev->v4l2_dev && vdev->v4l2_dev->mdev &&
-           vdev->vfl_type != VFL_TYPE_SUBDEV)
-               media_device_unregister_entity(&vdev->entity);
-#endif
-
        mutex_lock(&videodev_lock);
        /* This must be in a critical section to prevent a race with v4l2_open.
         * Once this bit has been cleared video_get may never be called again.
index 6ba1461..3015e60 100644 (file)
@@ -492,13 +492,6 @@ int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
                return -EINVAL;
        }
 
-       /*
-        * If the same number of buffers and memory access method is requested
-        * then return immediately.
-        */
-       if (q->memory == req->memory && req->count == q->num_buffers)
-               return 0;
-
        if (req->count == 0 || q->num_buffers != 0 || q->memory != req->memory) {
                /*
                 * We already have buffers allocated, so first check if they
@@ -539,9 +532,9 @@ int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
        /* Finally, allocate buffers and video memory */
        ret = __vb2_queue_alloc(q, req->memory, num_buffers, num_planes,
                                plane_sizes);
-       if (ret < 0) {
-               dprintk(1, "Memory allocation failed with error: %d\n", ret);
-               return ret;
+       if (ret == 0) {
+               dprintk(1, "Memory allocation failed\n");
+               return -ENOMEM;
        }
 
        /*
@@ -1196,6 +1189,7 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
         * has not already dequeued before initiating cancel.
         */
        INIT_LIST_HEAD(&q->done_list);
+       atomic_set(&q->queued_count, 0);
        wake_up_all(&q->done_wq);
 
        /*
index b2d9485..10a20d9 100644 (file)
@@ -62,7 +62,7 @@ static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size)
                goto fail_pages_array_alloc;
 
        for (i = 0; i < buf->sg_desc.num_pages; ++i) {
-               buf->pages[i] = alloc_page(GFP_KERNEL | __GFP_ZERO);
+               buf->pages[i] = alloc_page(GFP_KERNEL | __GFP_ZERO | __GFP_NOWARN);
                if (NULL == buf->pages[i])
                        goto fail_pages_alloc;
                sg_set_page(&buf->sg_desc.sglist[i],
index 0f09c05..6ca938a 100644 (file)
@@ -728,6 +728,9 @@ config MFD_TPS65910
          if you say yes here you get support for the TPS65910 series of
          Power Management chips.
 
+config TPS65911_COMPARATOR
+       tristate
+
 endif # MFD_SUPPORT
 
 menu "Multimedia Capabilities Port drivers"
index efe3cc3..d7d47d2 100644 (file)
@@ -94,3 +94,4 @@ obj-$(CONFIG_MFD_OMAP_USB_HOST)       += omap-usb-host.o
 obj-$(CONFIG_MFD_PM8921_CORE)  += pm8921-core.o
 obj-$(CONFIG_MFD_PM8XXX_IRQ)   += pm8xxx-irq.o
 obj-$(CONFIG_MFD_TPS65910)     += tps65910.o tps65910-irq.o
+obj-$(CONFIG_TPS65911_COMPARATOR)      += tps65911-comparator.o
index 8552195..1717144 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/spinlock.h>
 #include <linux/gpio.h>
 #include <plat/usb.h>
-#include <linux/pm_runtime.h>
 
 #define USBHS_DRIVER_NAME      "usbhs-omap"
 #define OMAP_EHCI_DEVICE       "ehci-omap"
 
 
 struct usbhs_hcd_omap {
+       struct clk                      *usbhost_ick;
+       struct clk                      *usbhost_hs_fck;
+       struct clk                      *usbhost_fs_fck;
        struct clk                      *xclk60mhsp1_ck;
        struct clk                      *xclk60mhsp2_ck;
        struct clk                      *utmi_p1_fck;
@@ -156,6 +158,8 @@ struct usbhs_hcd_omap {
        struct clk                      *usbhost_p2_fck;
        struct clk                      *usbtll_p2_fck;
        struct clk                      *init_60m_fclk;
+       struct clk                      *usbtll_fck;
+       struct clk                      *usbtll_ick;
 
        void __iomem                    *uhh_base;
        void __iomem                    *tll_base;
@@ -349,13 +353,46 @@ static int __devinit usbhs_omap_probe(struct platform_device *pdev)
        omap->platdata.ehci_data = pdata->ehci_data;
        omap->platdata.ohci_data = pdata->ohci_data;
 
-       pm_runtime_enable(&pdev->dev);
+       omap->usbhost_ick = clk_get(dev, "usbhost_ick");
+       if (IS_ERR(omap->usbhost_ick)) {
+               ret =  PTR_ERR(omap->usbhost_ick);
+               dev_err(dev, "usbhost_ick failed error:%d\n", ret);
+               goto err_end;
+       }
+
+       omap->usbhost_hs_fck = clk_get(dev, "hs_fck");
+       if (IS_ERR(omap->usbhost_hs_fck)) {
+               ret = PTR_ERR(omap->usbhost_hs_fck);
+               dev_err(dev, "usbhost_hs_fck failed error:%d\n", ret);
+               goto err_usbhost_ick;
+       }
+
+       omap->usbhost_fs_fck = clk_get(dev, "fs_fck");
+       if (IS_ERR(omap->usbhost_fs_fck)) {
+               ret = PTR_ERR(omap->usbhost_fs_fck);
+               dev_err(dev, "usbhost_fs_fck failed error:%d\n", ret);
+               goto err_usbhost_hs_fck;
+       }
+
+       omap->usbtll_fck = clk_get(dev, "usbtll_fck");
+       if (IS_ERR(omap->usbtll_fck)) {
+               ret = PTR_ERR(omap->usbtll_fck);
+               dev_err(dev, "usbtll_fck failed error:%d\n", ret);
+               goto err_usbhost_fs_fck;
+       }
+
+       omap->usbtll_ick = clk_get(dev, "usbtll_ick");
+       if (IS_ERR(omap->usbtll_ick)) {
+               ret = PTR_ERR(omap->usbtll_ick);
+               dev_err(dev, "usbtll_ick failed error:%d\n", ret);
+               goto err_usbtll_fck;
+       }
 
        omap->utmi_p1_fck = clk_get(dev, "utmi_p1_gfclk");
        if (IS_ERR(omap->utmi_p1_fck)) {
                ret = PTR_ERR(omap->utmi_p1_fck);
                dev_err(dev, "utmi_p1_gfclk failed error:%d\n", ret);
-               goto err_end;
+               goto err_usbtll_ick;
        }
 
        omap->xclk60mhsp1_ck = clk_get(dev, "xclk60mhsp1_ck");
@@ -485,8 +522,22 @@ err_xclk60mhsp1_ck:
 err_utmi_p1_fck:
        clk_put(omap->utmi_p1_fck);
 
+err_usbtll_ick:
+       clk_put(omap->usbtll_ick);
+
+err_usbtll_fck:
+       clk_put(omap->usbtll_fck);
+
+err_usbhost_fs_fck:
+       clk_put(omap->usbhost_fs_fck);
+
+err_usbhost_hs_fck:
+       clk_put(omap->usbhost_hs_fck);
+
+err_usbhost_ick:
+       clk_put(omap->usbhost_ick);
+
 err_end:
-       pm_runtime_disable(&pdev->dev);
        kfree(omap);
 
 end_probe:
@@ -520,7 +571,11 @@ static int __devexit usbhs_omap_remove(struct platform_device *pdev)
        clk_put(omap->utmi_p2_fck);
        clk_put(omap->xclk60mhsp1_ck);
        clk_put(omap->utmi_p1_fck);
-       pm_runtime_disable(&pdev->dev);
+       clk_put(omap->usbtll_ick);
+       clk_put(omap->usbtll_fck);
+       clk_put(omap->usbhost_fs_fck);
+       clk_put(omap->usbhost_hs_fck);
+       clk_put(omap->usbhost_ick);
        kfree(omap);
 
        return 0;
@@ -640,6 +695,7 @@ static int usbhs_enable(struct device *dev)
        struct usbhs_omap_platform_data *pdata = &omap->platdata;
        unsigned long                   flags = 0;
        int                             ret = 0;
+       unsigned long                   timeout;
        unsigned                        reg;
 
        dev_dbg(dev, "starting TI HSUSB Controller\n");
@@ -652,7 +708,11 @@ static int usbhs_enable(struct device *dev)
        if (omap->count > 0)
                goto end_count;
 
-       pm_runtime_get_sync(dev);
+       clk_enable(omap->usbhost_ick);
+       clk_enable(omap->usbhost_hs_fck);
+       clk_enable(omap->usbhost_fs_fck);
+       clk_enable(omap->usbtll_fck);
+       clk_enable(omap->usbtll_ick);
 
        if (pdata->ehci_data->phy_reset) {
                if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0])) {
@@ -676,6 +736,50 @@ static int usbhs_enable(struct device *dev)
        omap->usbhs_rev = usbhs_read(omap->uhh_base, OMAP_UHH_REVISION);
        dev_dbg(dev, "OMAP UHH_REVISION 0x%x\n", omap->usbhs_rev);
 
+       /* perform TLL soft reset, and wait until reset is complete */
+       usbhs_write(omap->tll_base, OMAP_USBTLL_SYSCONFIG,
+                       OMAP_USBTLL_SYSCONFIG_SOFTRESET);
+
+       /* Wait for TLL reset to complete */
+       timeout = jiffies + msecs_to_jiffies(1000);
+       while (!(usbhs_read(omap->tll_base, OMAP_USBTLL_SYSSTATUS)
+                       & OMAP_USBTLL_SYSSTATUS_RESETDONE)) {
+               cpu_relax();
+
+               if (time_after(jiffies, timeout)) {
+                       dev_dbg(dev, "operation timed out\n");
+                       ret = -EINVAL;
+                       goto err_tll;
+               }
+       }
+
+       dev_dbg(dev, "TLL RESET DONE\n");
+
+       /* (1<<3) = no idle mode only for initial debugging */
+       usbhs_write(omap->tll_base, OMAP_USBTLL_SYSCONFIG,
+                       OMAP_USBTLL_SYSCONFIG_ENAWAKEUP |
+                       OMAP_USBTLL_SYSCONFIG_SIDLEMODE |
+                       OMAP_USBTLL_SYSCONFIG_AUTOIDLE);
+
+       /* Put UHH in NoIdle/NoStandby mode */
+       reg = usbhs_read(omap->uhh_base, OMAP_UHH_SYSCONFIG);
+       if (is_omap_usbhs_rev1(omap)) {
+               reg |= (OMAP_UHH_SYSCONFIG_ENAWAKEUP
+                               | OMAP_UHH_SYSCONFIG_SIDLEMODE
+                               | OMAP_UHH_SYSCONFIG_CACTIVITY
+                               | OMAP_UHH_SYSCONFIG_MIDLEMODE);
+               reg &= ~OMAP_UHH_SYSCONFIG_AUTOIDLE;
+
+
+       } else if (is_omap_usbhs_rev2(omap)) {
+               reg &= ~OMAP4_UHH_SYSCONFIG_IDLEMODE_CLEAR;
+               reg |= OMAP4_UHH_SYSCONFIG_NOIDLE;
+               reg &= ~OMAP4_UHH_SYSCONFIG_STDBYMODE_CLEAR;
+               reg |= OMAP4_UHH_SYSCONFIG_NOSTDBY;
+       }
+
+       usbhs_write(omap->uhh_base, OMAP_UHH_SYSCONFIG, reg);
+
        reg = usbhs_read(omap->uhh_base, OMAP_UHH_HOSTCONFIG);
        /* setup ULPI bypass and burst configurations */
        reg |= (OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN
@@ -815,8 +919,6 @@ end_count:
        return 0;
 
 err_tll:
-       pm_runtime_put_sync(dev);
-       spin_unlock_irqrestore(&omap->lock, flags);
        if (pdata->ehci_data->phy_reset) {
                if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
                        gpio_free(pdata->ehci_data->reset_gpio_port[0]);
@@ -824,6 +926,13 @@ err_tll:
                if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
                        gpio_free(pdata->ehci_data->reset_gpio_port[1]);
        }
+
+       clk_disable(omap->usbtll_ick);
+       clk_disable(omap->usbtll_fck);
+       clk_disable(omap->usbhost_fs_fck);
+       clk_disable(omap->usbhost_hs_fck);
+       clk_disable(omap->usbhost_ick);
+       spin_unlock_irqrestore(&omap->lock, flags);
        return ret;
 }
 
@@ -896,7 +1005,11 @@ static void usbhs_disable(struct device *dev)
                clk_disable(omap->utmi_p1_fck);
        }
 
-       pm_runtime_put_sync(dev);
+       clk_disable(omap->usbtll_ick);
+       clk_disable(omap->usbtll_fck);
+       clk_disable(omap->usbhost_fs_fck);
+       clk_disable(omap->usbhost_hs_fck);
+       clk_disable(omap->usbhost_ick);
 
        /* The gpio_free migh sleep; so unlock the spinlock */
        spin_unlock_irqrestore(&omap->lock, flags);
index 3d2dc56..283ac67 100644 (file)
@@ -125,7 +125,7 @@ static DEVICE_ATTR(comp2_threshold, S_IRUGO, comp_threshold_show, NULL);
 static __devinit int tps65911_comparator_probe(struct platform_device *pdev)
 {
        struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent);
-       struct tps65910_platform_data *pdata = dev_get_platdata(tps65910->dev);
+       struct tps65910_board *pdata = dev_get_platdata(tps65910->dev);
        int ret;
 
        ret = comp_threshold_set(tps65910, COMP1,  pdata->vmbch_threshold);
index 4a1f029..8d9dae8 100644 (file)
@@ -830,6 +830,19 @@ config SCSI_GDTH
          To compile this driver as a module, choose M here: the
          module will be called gdth.
 
+config SCSI_ISCI
+       tristate "Intel(R) C600 Series Chipset SAS Controller"
+       depends on PCI && SCSI
+       depends on X86
+       # (temporary): known alpha quality driver
+       depends on EXPERIMENTAL
+       select SCSI_SAS_LIBSAS
+       ---help---
+         This driver supports the 6Gb/s SAS capabilities of the storage
+         control unit found in the Intel(R) C600 series chipset.
+
+         The experimental tag will be removed after the driver exits alpha
+
 config SCSI_GENERIC_NCR5380
        tristate "Generic NCR5380/53c400 SCSI PIO support"
        depends on ISA && SCSI
index 7ad0b8a..3c08f53 100644 (file)
@@ -73,6 +73,7 @@ obj-$(CONFIG_SCSI_AACRAID)    += aacraid/
 obj-$(CONFIG_SCSI_AIC7XXX_OLD) += aic7xxx_old.o
 obj-$(CONFIG_SCSI_AIC94XX)     += aic94xx/
 obj-$(CONFIG_SCSI_PM8001)      += pm8001/
+obj-$(CONFIG_SCSI_ISCI)                += isci/
 obj-$(CONFIG_SCSI_IPS)         += ips.o
 obj-$(CONFIG_SCSI_FD_MCS)      += fd_mcs.o
 obj-$(CONFIG_SCSI_FUTURE_DOMAIN)+= fdomain.o
index c6c0434..6bba23a 100644 (file)
@@ -1037,6 +1037,7 @@ static void complete_scsi_command(struct CommandList *cp)
        unsigned char sense_key;
        unsigned char asc;      /* additional sense code */
        unsigned char ascq;     /* additional sense code qualifier */
+       unsigned long sense_data_size;
 
        ei = cp->err_info;
        cmd = (struct scsi_cmnd *) cp->scsi_cmd;
@@ -1051,10 +1052,14 @@ static void complete_scsi_command(struct CommandList *cp)
        cmd->result |= ei->ScsiStatus;
 
        /* copy the sense data whether we need to or not. */
-       memcpy(cmd->sense_buffer, ei->SenseInfo,
-               ei->SenseLen > SCSI_SENSE_BUFFERSIZE ?
-                       SCSI_SENSE_BUFFERSIZE :
-                       ei->SenseLen);
+       if (SCSI_SENSE_BUFFERSIZE < sizeof(ei->SenseInfo))
+               sense_data_size = SCSI_SENSE_BUFFERSIZE;
+       else
+               sense_data_size = sizeof(ei->SenseInfo);
+       if (ei->SenseLen < sense_data_size)
+               sense_data_size = ei->SenseLen;
+
+       memcpy(cmd->sense_buffer, ei->SenseInfo, sense_data_size);
        scsi_set_resid(cmd, ei->ResidualCnt);
 
        if (ei->CommandStatus == 0) {
@@ -2580,7 +2585,8 @@ static int hpsa_passthru_ioctl(struct ctlr_info *h, void __user *argp)
                c->SG[0].Ext = 0; /* we are not chaining*/
        }
        hpsa_scsi_do_simple_cmd_core(h, c);
-       hpsa_pci_unmap(h->pdev, c, 1, PCI_DMA_BIDIRECTIONAL);
+       if (iocommand.buf_size > 0)
+               hpsa_pci_unmap(h->pdev, c, 1, PCI_DMA_BIDIRECTIONAL);
        check_ioctl_unit_attention(h, c);
 
        /* Copy the error information out */
index b765061..bdfa223 100644 (file)
@@ -4306,8 +4306,8 @@ static void ibmvfc_do_work(struct ibmvfc_host *vhost)
                spin_lock_irqsave(vhost->host->host_lock, flags);
                if (rc == H_CLOSED)
                        vio_enable_interrupts(to_vio_dev(vhost->dev));
-               else if (rc || (rc = ibmvfc_send_crq_init(vhost)) ||
-                        (rc = vio_enable_interrupts(to_vio_dev(vhost->dev)))) {
+               if (rc || (rc = ibmvfc_send_crq_init(vhost)) ||
+                   (rc = vio_enable_interrupts(to_vio_dev(vhost->dev)))) {
                        ibmvfc_link_down(vhost, IBMVFC_LINK_DEAD);
                        dev_err(vhost->dev, "Error after reset (rc=%d)\n", rc);
                }
diff --git a/drivers/scsi/isci/Makefile b/drivers/scsi/isci/Makefile
new file mode 100644 (file)
index 0000000..3359e10
--- /dev/null
@@ -0,0 +1,8 @@
+obj-$(CONFIG_SCSI_ISCI) += isci.o
+isci-objs := init.o phy.o request.o \
+            remote_device.o port.o \
+            host.o task.o probe_roms.o \
+            remote_node_context.o \
+            remote_node_table.o \
+            unsolicited_frame_control.o \
+            port_config.o \
diff --git a/drivers/scsi/isci/firmware/Makefile b/drivers/scsi/isci/firmware/Makefile
new file mode 100644 (file)
index 0000000..5f54461
--- /dev/null
@@ -0,0 +1,19 @@
+# Makefile for create_fw
+#
+CC=gcc
+CFLAGS=-c -Wall -O2 -g
+LDFLAGS=
+SOURCES=create_fw.c
+OBJECTS=$(SOURCES:.cpp=.o)
+EXECUTABLE=create_fw
+
+all: $(SOURCES) $(EXECUTABLE)
+
+$(EXECUTABLE): $(OBJECTS)
+       $(CC) $(LDFLAGS) $(OBJECTS) -o $@
+
+.c.o:
+       $(CC) $(CFLAGS) $< -O $@
+
+clean:
+       rm -f *.o $(EXECUTABLE)
diff --git a/drivers/scsi/isci/firmware/README b/drivers/scsi/isci/firmware/README
new file mode 100644 (file)
index 0000000..8056d2b
--- /dev/null
@@ -0,0 +1,36 @@
+This defines the temporary binary blow we are to pass to the SCU
+driver to emulate the binary firmware that we will eventually be
+able to access via NVRAM on the SCU controller.
+
+The current size of the binary blob is expected to be 149 bytes or larger
+
+Header Types:
+0x1: Phy Masks
+0x2: Phy Gens
+0x3: SAS Addrs
+0xff: End of Data
+
+ID string - u8[12]: "#SCU MAGIC#\0"
+Version - u8: 1
+SubVersion - u8: 0
+
+Header Type - u8: 0x1
+Size - u8: 8
+Phy Mask - u32[8]
+
+Header Type - u8: 0x2
+Size - u8: 8
+Phy Gen - u32[8]
+
+Header Type - u8: 0x3
+Size - u8: 8
+Sas Addr - u64[8]
+
+Header Type - u8: 0xf
+
+
+==============================================================================
+
+Place isci_firmware.bin in /lib/firmware
+Be sure to recreate the initramfs image to include the firmware.
+
diff --git a/drivers/scsi/isci/firmware/create_fw.c b/drivers/scsi/isci/firmware/create_fw.c
new file mode 100644 (file)
index 0000000..c7a2887
--- /dev/null
@@ -0,0 +1,99 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <asm/types.h>
+#include <strings.h>
+#include <stdint.h>
+
+#include "create_fw.h"
+#include "../probe_roms.h"
+
+int write_blob(struct isci_orom *isci_orom)
+{
+       FILE *fd;
+       int err;
+       size_t count;
+
+       fd = fopen(blob_name, "w+");
+       if (!fd) {
+               perror("Open file for write failed");
+               fclose(fd);
+               return -EIO;
+       }
+
+       count = fwrite(isci_orom, sizeof(struct isci_orom), 1, fd);
+       if (count != 1) {
+               perror("Write data failed");
+               fclose(fd);
+               return -EIO;
+       }
+
+       fclose(fd);
+
+       return 0;
+}
+
+void set_binary_values(struct isci_orom *isci_orom)
+{
+       int ctrl_idx, phy_idx, port_idx;
+
+       /* setting OROM signature */
+       strncpy(isci_orom->hdr.signature, sig, strlen(sig));
+       isci_orom->hdr.version = version;
+       isci_orom->hdr.total_block_length = sizeof(struct isci_orom);
+       isci_orom->hdr.hdr_length = sizeof(struct sci_bios_oem_param_block_hdr);
+       isci_orom->hdr.num_elements = num_elements;
+
+       for (ctrl_idx = 0; ctrl_idx < 2; ctrl_idx++) {
+               isci_orom->ctrl[ctrl_idx].controller.mode_type = mode_type;
+               isci_orom->ctrl[ctrl_idx].controller.max_concurrent_dev_spin_up =
+                       max_num_concurrent_dev_spin_up;
+               isci_orom->ctrl[ctrl_idx].controller.do_enable_ssc =
+                       enable_ssc;
+
+               for (port_idx = 0; port_idx < 4; port_idx++)
+                       isci_orom->ctrl[ctrl_idx].ports[port_idx].phy_mask =
+                               phy_mask[ctrl_idx][port_idx];
+
+               for (phy_idx = 0; phy_idx < 4; phy_idx++) {
+                       isci_orom->ctrl[ctrl_idx].phys[phy_idx].sas_address.high =
+                               (__u32)(sas_addr[ctrl_idx][phy_idx] >> 32);
+                       isci_orom->ctrl[ctrl_idx].phys[phy_idx].sas_address.low =
+                               (__u32)(sas_addr[ctrl_idx][phy_idx]);
+
+                       isci_orom->ctrl[ctrl_idx].phys[phy_idx].afe_tx_amp_control0 =
+                               afe_tx_amp_control0;
+                       isci_orom->ctrl[ctrl_idx].phys[phy_idx].afe_tx_amp_control1 =
+                               afe_tx_amp_control1;
+                       isci_orom->ctrl[ctrl_idx].phys[phy_idx].afe_tx_amp_control2 =
+                               afe_tx_amp_control2;
+                       isci_orom->ctrl[ctrl_idx].phys[phy_idx].afe_tx_amp_control3 =
+                               afe_tx_amp_control3;
+               }
+       }
+}
+
+int main(void)
+{
+       int err;
+       struct isci_orom *isci_orom;
+
+       isci_orom = malloc(sizeof(struct isci_orom));
+       memset(isci_orom, 0, sizeof(struct isci_orom));
+
+       set_binary_values(isci_orom);
+
+       err = write_blob(isci_orom);
+       if (err < 0) {
+               free(isci_orom);
+               return err;
+       }
+
+       free(isci_orom);
+       return 0;
+}
diff --git a/drivers/scsi/isci/firmware/create_fw.h b/drivers/scsi/isci/firmware/create_fw.h
new file mode 100644 (file)
index 0000000..5f29882
--- /dev/null
@@ -0,0 +1,77 @@
+#ifndef _CREATE_FW_H_
+#define _CREATE_FW_H_
+#include "../probe_roms.h"
+
+
+/* we are configuring for 2 SCUs */
+static const int num_elements = 2;
+
+/*
+ * For all defined arrays:
+ * elements 0-3 are for SCU0, ports 0-3
+ * elements 4-7 are for SCU1, ports 0-3
+ *
+ * valid configurations for one SCU are:
+ *  P0  P1  P2  P3
+ * ----------------
+ * 0xF,0x0,0x0,0x0 # 1 x4 port
+ * 0x3,0x0,0x4,0x8 # Phys 0 and 1 are a x2 port, phy 2 and phy 3 are each x1
+ *                 # ports
+ * 0x1,0x2,0xC,0x0 # Phys 0 and 1 are each x1 ports, phy 2 and phy 3 are a x2
+ *                 # port
+ * 0x3,0x0,0xC,0x0 # Phys 0 and 1 are a x2 port, phy 2 and phy 3 are a x2 port
+ * 0x1,0x2,0x4,0x8 # Each phy is a x1 port (this is the default configuration)
+ *
+ * if there is a port/phy on which you do not wish to override the default
+ * values, use the value assigned to UNINIT_PARAM (255).
+ */
+
+/* discovery mode type (port auto config mode by default ) */
+
+/*
+ * if there is a port/phy on which you do not wish to override the default
+ * values, use the value "0000000000000000". SAS address of zero's is
+ * considered invalid and will not be used.
+ */
+#ifdef MPC
+static const int mode_type = SCIC_PORT_MANUAL_CONFIGURATION_MODE;
+static const __u8 phy_mask[2][4] = { {1, 2, 4, 8},
+                                    {1, 2, 4, 8} };
+static const unsigned long long sas_addr[2][4] = { { 0x5FCFFFFFF0000001ULL,
+                                                    0x5FCFFFFFF0000002ULL,
+                                                    0x5FCFFFFFF0000003ULL,
+                                                    0x5FCFFFFFF0000004ULL },
+                                                  { 0x5FCFFFFFF0000005ULL,
+                                                    0x5FCFFFFFF0000006ULL,
+                                                    0x5FCFFFFFF0000007ULL,
+                                                    0x5FCFFFFFF0000008ULL } };
+#else  /* APC (default) */
+static const int mode_type = SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE;
+static const __u8 phy_mask[2][4];
+static const unsigned long long sas_addr[2][4] = { { 0x5FCFFFFF00000001ULL,
+                                                    0x5FCFFFFF00000001ULL,
+                                                    0x5FCFFFFF00000001ULL,
+                                                    0x5FCFFFFF00000001ULL },
+                                                  { 0x5FCFFFFF00000002ULL,
+                                                    0x5FCFFFFF00000002ULL,
+                                                    0x5FCFFFFF00000002ULL,
+                                                    0x5FCFFFFF00000002ULL } };
+#endif
+
+/* Maximum number of concurrent device spin up */
+static const int max_num_concurrent_dev_spin_up = 1;
+
+/* enable of ssc operation */
+static const int enable_ssc;
+
+/* AFE_TX_AMP_CONTROL */
+static const unsigned int afe_tx_amp_control0 = 0x000bdd08;
+static const unsigned int afe_tx_amp_control1 = 0x000ffc00;
+static const unsigned int afe_tx_amp_control2 = 0x000b7c09;
+static const unsigned int afe_tx_amp_control3 = 0x000afc6e;
+
+static const char blob_name[] = "isci_firmware.bin";
+static const char sig[] = "ISCUOEMB";
+static const unsigned char version = 0x10;
+
+#endif
diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c
new file mode 100644 (file)
index 0000000..26072f1
--- /dev/null
@@ -0,0 +1,2751 @@
+/*
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <linux/circ_buf.h>
+#include <linux/device.h>
+#include <scsi/sas.h>
+#include "host.h"
+#include "isci.h"
+#include "port.h"
+#include "host.h"
+#include "probe_roms.h"
+#include "remote_device.h"
+#include "request.h"
+#include "scu_completion_codes.h"
+#include "scu_event_codes.h"
+#include "registers.h"
+#include "scu_remote_node_context.h"
+#include "scu_task_context.h"
+
+#define SCU_CONTEXT_RAM_INIT_STALL_TIME      200
+
+#define smu_max_ports(dcc_value) \
+       (\
+               (((dcc_value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_MASK) \
+                >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_SHIFT) + 1 \
+       )
+
+#define smu_max_task_contexts(dcc_value)       \
+       (\
+               (((dcc_value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_TC_MASK) \
+                >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_TC_SHIFT) + 1 \
+       )
+
+#define smu_max_rncs(dcc_value) \
+       (\
+               (((dcc_value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_RNC_MASK) \
+                >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_RNC_SHIFT) + 1 \
+       )
+
+#define SCIC_SDS_CONTROLLER_PHY_START_TIMEOUT      100
+
+/**
+ *
+ *
+ * The number of milliseconds to wait while a given phy is consuming power
+ * before allowing another set of phys to consume power. Ultimately, this will
+ * be specified by OEM parameter.
+ */
+#define SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL 500
+
+/**
+ * NORMALIZE_PUT_POINTER() -
+ *
+ * This macro will normalize the completion queue put pointer so its value can
+ * be used as an array inde
+ */
+#define NORMALIZE_PUT_POINTER(x) \
+       ((x) & SMU_COMPLETION_QUEUE_PUT_POINTER_MASK)
+
+
+/**
+ * NORMALIZE_EVENT_POINTER() -
+ *
+ * This macro will normalize the completion queue event entry so its value can
+ * be used as an index.
+ */
+#define NORMALIZE_EVENT_POINTER(x) \
+       (\
+               ((x) & SMU_COMPLETION_QUEUE_GET_EVENT_POINTER_MASK) \
+               >> SMU_COMPLETION_QUEUE_GET_EVENT_POINTER_SHIFT \
+       )
+
+/**
+ * NORMALIZE_GET_POINTER() -
+ *
+ * This macro will normalize the completion queue get pointer so its value can
+ * be used as an index into an array
+ */
+#define NORMALIZE_GET_POINTER(x) \
+       ((x) & SMU_COMPLETION_QUEUE_GET_POINTER_MASK)
+
+/**
+ * NORMALIZE_GET_POINTER_CYCLE_BIT() -
+ *
+ * This macro will normalize the completion queue cycle pointer so it matches
+ * the completion queue cycle bit
+ */
+#define NORMALIZE_GET_POINTER_CYCLE_BIT(x) \
+       ((SMU_CQGR_CYCLE_BIT & (x)) << (31 - SMU_COMPLETION_QUEUE_GET_CYCLE_BIT_SHIFT))
+
+/**
+ * COMPLETION_QUEUE_CYCLE_BIT() -
+ *
+ * This macro will return the cycle bit of the completion queue entry
+ */
+#define COMPLETION_QUEUE_CYCLE_BIT(x) ((x) & 0x80000000)
+
+/* Init the state machine and call the state entry function (if any) */
+void sci_init_sm(struct sci_base_state_machine *sm,
+                const struct sci_base_state *state_table, u32 initial_state)
+{
+       sci_state_transition_t handler;
+
+       sm->initial_state_id    = initial_state;
+       sm->previous_state_id   = initial_state;
+       sm->current_state_id    = initial_state;
+       sm->state_table         = state_table;
+
+       handler = sm->state_table[initial_state].enter_state;
+       if (handler)
+               handler(sm);
+}
+
+/* Call the state exit fn, update the current state, call the state entry fn */
+void sci_change_state(struct sci_base_state_machine *sm, u32 next_state)
+{
+       sci_state_transition_t handler;
+
+       handler = sm->state_table[sm->current_state_id].exit_state;
+       if (handler)
+               handler(sm);
+
+       sm->previous_state_id = sm->current_state_id;
+       sm->current_state_id = next_state;
+
+       handler = sm->state_table[sm->current_state_id].enter_state;
+       if (handler)
+               handler(sm);
+}
+
+static bool sci_controller_completion_queue_has_entries(struct isci_host *ihost)
+{
+       u32 get_value = ihost->completion_queue_get;
+       u32 get_index = get_value & SMU_COMPLETION_QUEUE_GET_POINTER_MASK;
+
+       if (NORMALIZE_GET_POINTER_CYCLE_BIT(get_value) ==
+           COMPLETION_QUEUE_CYCLE_BIT(ihost->completion_queue[get_index]))
+               return true;
+
+       return false;
+}
+
+static bool sci_controller_isr(struct isci_host *ihost)
+{
+       if (sci_controller_completion_queue_has_entries(ihost)) {
+               return true;
+       } else {
+               /*
+                * we have a spurious interrupt it could be that we have already
+                * emptied the completion queue from a previous interrupt */
+               writel(SMU_ISR_COMPLETION, &ihost->smu_registers->interrupt_status);
+
+               /*
+                * There is a race in the hardware that could cause us not to be notified
+                * of an interrupt completion if we do not take this step.  We will mask
+                * then unmask the interrupts so if there is another interrupt pending
+                * the clearing of the interrupt source we get the next interrupt message. */
+               writel(0xFF000000, &ihost->smu_registers->interrupt_mask);
+               writel(0, &ihost->smu_registers->interrupt_mask);
+       }
+
+       return false;
+}
+
+irqreturn_t isci_msix_isr(int vec, void *data)
+{
+       struct isci_host *ihost = data;
+
+       if (sci_controller_isr(ihost))
+               tasklet_schedule(&ihost->completion_tasklet);
+
+       return IRQ_HANDLED;
+}
+
+static bool sci_controller_error_isr(struct isci_host *ihost)
+{
+       u32 interrupt_status;
+
+       interrupt_status =
+               readl(&ihost->smu_registers->interrupt_status);
+       interrupt_status &= (SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND);
+
+       if (interrupt_status != 0) {
+               /*
+                * There is an error interrupt pending so let it through and handle
+                * in the callback */
+               return true;
+       }
+
+       /*
+        * There is a race in the hardware that could cause us not to be notified
+        * of an interrupt completion if we do not take this step.  We will mask
+        * then unmask the error interrupts so if there was another interrupt
+        * pending we will be notified.
+        * Could we write the value of (SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND)? */
+       writel(0xff, &ihost->smu_registers->interrupt_mask);
+       writel(0, &ihost->smu_registers->interrupt_mask);
+
+       return false;
+}
+
+static void sci_controller_task_completion(struct isci_host *ihost, u32 ent)
+{
+       u32 index = SCU_GET_COMPLETION_INDEX(ent);
+       struct isci_request *ireq = ihost->reqs[index];
+
+       /* Make sure that we really want to process this IO request */
+       if (test_bit(IREQ_ACTIVE, &ireq->flags) &&
+           ireq->io_tag != SCI_CONTROLLER_INVALID_IO_TAG &&
+           ISCI_TAG_SEQ(ireq->io_tag) == ihost->io_request_sequence[index])
+               /* Yep this is a valid io request pass it along to the
+                * io request handler
+                */
+               sci_io_request_tc_completion(ireq, ent);
+}
+
+static void sci_controller_sdma_completion(struct isci_host *ihost, u32 ent)
+{
+       u32 index;
+       struct isci_request *ireq;
+       struct isci_remote_device *idev;
+
+       index = SCU_GET_COMPLETION_INDEX(ent);
+
+       switch (scu_get_command_request_type(ent)) {
+       case SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC:
+       case SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_TC:
+               ireq = ihost->reqs[index];
+               dev_warn(&ihost->pdev->dev, "%s: %x for io request %p\n",
+                        __func__, ent, ireq);
+               /* @todo For a post TC operation we need to fail the IO
+                * request
+                */
+               break;
+       case SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_RNC:
+       case SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC:
+       case SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_RNC:
+               idev = ihost->device_table[index];
+               dev_warn(&ihost->pdev->dev, "%s: %x for device %p\n",
+                        __func__, ent, idev);
+               /* @todo For a port RNC operation we need to fail the
+                * device
+                */
+               break;
+       default:
+               dev_warn(&ihost->pdev->dev, "%s: unknown completion type %x\n",
+                        __func__, ent);
+               break;
+       }
+}
+
+static void sci_controller_unsolicited_frame(struct isci_host *ihost, u32 ent)
+{
+       u32 index;
+       u32 frame_index;
+
+       struct scu_unsolicited_frame_header *frame_header;
+       struct isci_phy *iphy;
+       struct isci_remote_device *idev;
+
+       enum sci_status result = SCI_FAILURE;
+
+       frame_index = SCU_GET_FRAME_INDEX(ent);
+
+       frame_header = ihost->uf_control.buffers.array[frame_index].header;
+       ihost->uf_control.buffers.array[frame_index].state = UNSOLICITED_FRAME_IN_USE;
+
+       if (SCU_GET_FRAME_ERROR(ent)) {
+               /*
+                * / @todo If the IAF frame or SIGNATURE FIS frame has an error will
+                * /       this cause a problem? We expect the phy initialization will
+                * /       fail if there is an error in the frame. */
+               sci_controller_release_frame(ihost, frame_index);
+               return;
+       }
+
+       if (frame_header->is_address_frame) {
+               index = SCU_GET_PROTOCOL_ENGINE_INDEX(ent);
+               iphy = &ihost->phys[index];
+               result = sci_phy_frame_handler(iphy, frame_index);
+       } else {
+
+               index = SCU_GET_COMPLETION_INDEX(ent);
+
+               if (index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) {
+                       /*
+                        * This is a signature fis or a frame from a direct attached SATA
+                        * device that has not yet been created.  In either case forwared
+                        * the frame to the PE and let it take care of the frame data. */
+                       index = SCU_GET_PROTOCOL_ENGINE_INDEX(ent);
+                       iphy = &ihost->phys[index];
+                       result = sci_phy_frame_handler(iphy, frame_index);
+               } else {
+                       if (index < ihost->remote_node_entries)
+                               idev = ihost->device_table[index];
+                       else
+                               idev = NULL;
+
+                       if (idev != NULL)
+                               result = sci_remote_device_frame_handler(idev, frame_index);
+                       else
+                               sci_controller_release_frame(ihost, frame_index);
+               }
+       }
+
+       if (result != SCI_SUCCESS) {
+               /*
+                * / @todo Is there any reason to report some additional error message
+                * /       when we get this failure notifiction? */
+       }
+}
+
+static void sci_controller_event_completion(struct isci_host *ihost, u32 ent)
+{
+       struct isci_remote_device *idev;
+       struct isci_request *ireq;
+       struct isci_phy *iphy;
+       u32 index;
+
+       index = SCU_GET_COMPLETION_INDEX(ent);
+
+       switch (scu_get_event_type(ent)) {
+       case SCU_EVENT_TYPE_SMU_COMMAND_ERROR:
+               /* / @todo The driver did something wrong and we need to fix the condtion. */
+               dev_err(&ihost->pdev->dev,
+                       "%s: SCIC Controller 0x%p received SMU command error "
+                       "0x%x\n",
+                       __func__,
+                       ihost,
+                       ent);
+               break;
+
+       case SCU_EVENT_TYPE_SMU_PCQ_ERROR:
+       case SCU_EVENT_TYPE_SMU_ERROR:
+       case SCU_EVENT_TYPE_FATAL_MEMORY_ERROR:
+               /*
+                * / @todo This is a hardware failure and its likely that we want to
+                * /       reset the controller. */
+               dev_err(&ihost->pdev->dev,
+                       "%s: SCIC Controller 0x%p received fatal controller "
+                       "event  0x%x\n",
+                       __func__,
+                       ihost,
+                       ent);
+               break;
+
+       case SCU_EVENT_TYPE_TRANSPORT_ERROR:
+               ireq = ihost->reqs[index];
+               sci_io_request_event_handler(ireq, ent);
+               break;
+
+       case SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT:
+               switch (scu_get_event_specifier(ent)) {
+               case SCU_EVENT_SPECIFIC_SMP_RESPONSE_NO_PE:
+               case SCU_EVENT_SPECIFIC_TASK_TIMEOUT:
+                       ireq = ihost->reqs[index];
+                       if (ireq != NULL)
+                               sci_io_request_event_handler(ireq, ent);
+                       else
+                               dev_warn(&ihost->pdev->dev,
+                                        "%s: SCIC Controller 0x%p received "
+                                        "event 0x%x for io request object "
+                                        "that doesnt exist.\n",
+                                        __func__,
+                                        ihost,
+                                        ent);
+
+                       break;
+
+               case SCU_EVENT_SPECIFIC_IT_NEXUS_TIMEOUT:
+                       idev = ihost->device_table[index];
+                       if (idev != NULL)
+                               sci_remote_device_event_handler(idev, ent);
+                       else
+                               dev_warn(&ihost->pdev->dev,
+                                        "%s: SCIC Controller 0x%p received "
+                                        "event 0x%x for remote device object "
+                                        "that doesnt exist.\n",
+                                        __func__,
+                                        ihost,
+                                        ent);
+
+                       break;
+               }
+               break;
+
+       case SCU_EVENT_TYPE_BROADCAST_CHANGE:
+       /*
+        * direct the broadcast change event to the phy first and then let
+        * the phy redirect the broadcast change to the port object */
+       case SCU_EVENT_TYPE_ERR_CNT_EVENT:
+       /*
+        * direct error counter event to the phy object since that is where
+        * we get the event notification.  This is a type 4 event. */
+       case SCU_EVENT_TYPE_OSSP_EVENT:
+               index = SCU_GET_PROTOCOL_ENGINE_INDEX(ent);
+               iphy = &ihost->phys[index];
+               sci_phy_event_handler(iphy, ent);
+               break;
+
+       case SCU_EVENT_TYPE_RNC_SUSPEND_TX:
+       case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX:
+       case SCU_EVENT_TYPE_RNC_OPS_MISC:
+               if (index < ihost->remote_node_entries) {
+                       idev = ihost->device_table[index];
+
+                       if (idev != NULL)
+                               sci_remote_device_event_handler(idev, ent);
+               } else
+                       dev_err(&ihost->pdev->dev,
+                               "%s: SCIC Controller 0x%p received event 0x%x "
+                               "for remote device object 0x%0x that doesnt "
+                               "exist.\n",
+                               __func__,
+                               ihost,
+                               ent,
+                               index);
+
+               break;
+
+       default:
+               dev_warn(&ihost->pdev->dev,
+                        "%s: SCIC Controller received unknown event code %x\n",
+                        __func__,
+                        ent);
+               break;
+       }
+}
+
+static void sci_controller_process_completions(struct isci_host *ihost)
+{
+       u32 completion_count = 0;
+       u32 ent;
+       u32 get_index;
+       u32 get_cycle;
+       u32 event_get;
+       u32 event_cycle;
+
+       dev_dbg(&ihost->pdev->dev,
+               "%s: completion queue begining get:0x%08x\n",
+               __func__,
+               ihost->completion_queue_get);
+
+       /* Get the component parts of the completion queue */
+       get_index = NORMALIZE_GET_POINTER(ihost->completion_queue_get);
+       get_cycle = SMU_CQGR_CYCLE_BIT & ihost->completion_queue_get;
+
+       event_get = NORMALIZE_EVENT_POINTER(ihost->completion_queue_get);
+       event_cycle = SMU_CQGR_EVENT_CYCLE_BIT & ihost->completion_queue_get;
+
+       while (
+               NORMALIZE_GET_POINTER_CYCLE_BIT(get_cycle)
+               == COMPLETION_QUEUE_CYCLE_BIT(ihost->completion_queue[get_index])
+               ) {
+               completion_count++;
+
+               ent = ihost->completion_queue[get_index];
+
+               /* increment the get pointer and check for rollover to toggle the cycle bit */
+               get_cycle ^= ((get_index+1) & SCU_MAX_COMPLETION_QUEUE_ENTRIES) <<
+                            (SMU_COMPLETION_QUEUE_GET_CYCLE_BIT_SHIFT - SCU_MAX_COMPLETION_QUEUE_SHIFT);
+               get_index = (get_index+1) & (SCU_MAX_COMPLETION_QUEUE_ENTRIES-1);
+
+               dev_dbg(&ihost->pdev->dev,
+                       "%s: completion queue entry:0x%08x\n",
+                       __func__,
+                       ent);
+
+               switch (SCU_GET_COMPLETION_TYPE(ent)) {
+               case SCU_COMPLETION_TYPE_TASK:
+                       sci_controller_task_completion(ihost, ent);
+                       break;
+
+               case SCU_COMPLETION_TYPE_SDMA:
+                       sci_controller_sdma_completion(ihost, ent);
+                       break;
+
+               case SCU_COMPLETION_TYPE_UFI:
+                       sci_controller_unsolicited_frame(ihost, ent);
+                       break;
+
+               case SCU_COMPLETION_TYPE_EVENT:
+               case SCU_COMPLETION_TYPE_NOTIFY: {
+                       event_cycle ^= ((event_get+1) & SCU_MAX_EVENTS) <<
+                                      (SMU_COMPLETION_QUEUE_GET_EVENT_CYCLE_BIT_SHIFT - SCU_MAX_EVENTS_SHIFT);
+                       event_get = (event_get+1) & (SCU_MAX_EVENTS-1);
+
+                       sci_controller_event_completion(ihost, ent);
+                       break;
+               }
+               default:
+                       dev_warn(&ihost->pdev->dev,
+                                "%s: SCIC Controller received unknown "
+                                "completion type %x\n",
+                                __func__,
+                                ent);
+                       break;
+               }
+       }
+
+       /* Update the get register if we completed one or more entries */
+       if (completion_count > 0) {
+               ihost->completion_queue_get =
+                       SMU_CQGR_GEN_BIT(ENABLE) |
+                       SMU_CQGR_GEN_BIT(EVENT_ENABLE) |
+                       event_cycle |
+                       SMU_CQGR_GEN_VAL(EVENT_POINTER, event_get) |
+                       get_cycle |
+                       SMU_CQGR_GEN_VAL(POINTER, get_index);
+
+               writel(ihost->completion_queue_get,
+                      &ihost->smu_registers->completion_queue_get);
+
+       }
+
+       dev_dbg(&ihost->pdev->dev,
+               "%s: completion queue ending get:0x%08x\n",
+               __func__,
+               ihost->completion_queue_get);
+
+}
+
+static void sci_controller_error_handler(struct isci_host *ihost)
+{
+       u32 interrupt_status;
+
+       interrupt_status =
+               readl(&ihost->smu_registers->interrupt_status);
+
+       if ((interrupt_status & SMU_ISR_QUEUE_SUSPEND) &&
+           sci_controller_completion_queue_has_entries(ihost)) {
+
+               sci_controller_process_completions(ihost);
+               writel(SMU_ISR_QUEUE_SUSPEND, &ihost->smu_registers->interrupt_status);
+       } else {
+               dev_err(&ihost->pdev->dev, "%s: status: %#x\n", __func__,
+                       interrupt_status);
+
+               sci_change_state(&ihost->sm, SCIC_FAILED);
+
+               return;
+       }
+
+       /* If we dont process any completions I am not sure that we want to do this.
+        * We are in the middle of a hardware fault and should probably be reset.
+        */
+       writel(0, &ihost->smu_registers->interrupt_mask);
+}
+
+irqreturn_t isci_intx_isr(int vec, void *data)
+{
+       irqreturn_t ret = IRQ_NONE;
+       struct isci_host *ihost = data;
+
+       if (sci_controller_isr(ihost)) {
+               writel(SMU_ISR_COMPLETION, &ihost->smu_registers->interrupt_status);
+               tasklet_schedule(&ihost->completion_tasklet);
+               ret = IRQ_HANDLED;
+       } else if (sci_controller_error_isr(ihost)) {
+               spin_lock(&ihost->scic_lock);
+               sci_controller_error_handler(ihost);
+               spin_unlock(&ihost->scic_lock);
+               ret = IRQ_HANDLED;
+       }
+
+       return ret;
+}
+
+irqreturn_t isci_error_isr(int vec, void *data)
+{
+       struct isci_host *ihost = data;
+
+       if (sci_controller_error_isr(ihost))
+               sci_controller_error_handler(ihost);
+
+       return IRQ_HANDLED;
+}
+
+/**
+ * isci_host_start_complete() - This function is called by the core library,
+ *    through the ISCI Module, to indicate controller start status.
+ * @isci_host: This parameter specifies the ISCI host object
+ * @completion_status: This parameter specifies the completion status from the
+ *    core library.
+ *
+ */
+static void isci_host_start_complete(struct isci_host *ihost, enum sci_status completion_status)
+{
+       if (completion_status != SCI_SUCCESS)
+               dev_info(&ihost->pdev->dev,
+                       "controller start timed out, continuing...\n");
+       isci_host_change_state(ihost, isci_ready);
+       clear_bit(IHOST_START_PENDING, &ihost->flags);
+       wake_up(&ihost->eventq);
+}
+
+int isci_host_scan_finished(struct Scsi_Host *shost, unsigned long time)
+{
+       struct isci_host *ihost = SHOST_TO_SAS_HA(shost)->lldd_ha;
+
+       if (test_bit(IHOST_START_PENDING, &ihost->flags))
+               return 0;
+
+       /* todo: use sas_flush_discovery once it is upstream */
+       scsi_flush_work(shost);
+
+       scsi_flush_work(shost);
+
+       dev_dbg(&ihost->pdev->dev,
+               "%s: ihost->status = %d, time = %ld\n",
+                __func__, isci_host_get_state(ihost), time);
+
+       return 1;
+
+}
+
+/**
+ * sci_controller_get_suggested_start_timeout() - This method returns the
+ *    suggested sci_controller_start() timeout amount.  The user is free to
+ *    use any timeout value, but this method provides the suggested minimum
+ *    start timeout value.  The returned value is based upon empirical
+ *    information determined as a result of interoperability testing.
+ * @controller: the handle to the controller object for which to return the
+ *    suggested start timeout.
+ *
+ * This method returns the number of milliseconds for the suggested start
+ * operation timeout.
+ */
+static u32 sci_controller_get_suggested_start_timeout(struct isci_host *ihost)
+{
+       /* Validate the user supplied parameters. */
+       if (!ihost)
+               return 0;
+
+       /*
+        * The suggested minimum timeout value for a controller start operation:
+        *
+        *     Signature FIS Timeout
+        *   + Phy Start Timeout
+        *   + Number of Phy Spin Up Intervals
+        *   ---------------------------------
+        *   Number of milliseconds for the controller start operation.
+        *
+        * NOTE: The number of phy spin up intervals will be equivalent
+        *       to the number of phys divided by the number phys allowed
+        *       per interval - 1 (once OEM parameters are supported).
+        *       Currently we assume only 1 phy per interval. */
+
+       return SCIC_SDS_SIGNATURE_FIS_TIMEOUT
+               + SCIC_SDS_CONTROLLER_PHY_START_TIMEOUT
+               + ((SCI_MAX_PHYS - 1) * SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL);
+}
+
+static void sci_controller_enable_interrupts(struct isci_host *ihost)
+{
+       BUG_ON(ihost->smu_registers == NULL);
+       writel(0, &ihost->smu_registers->interrupt_mask);
+}
+
+void sci_controller_disable_interrupts(struct isci_host *ihost)
+{
+       BUG_ON(ihost->smu_registers == NULL);
+       writel(0xffffffff, &ihost->smu_registers->interrupt_mask);
+}
+
+static void sci_controller_enable_port_task_scheduler(struct isci_host *ihost)
+{
+       u32 port_task_scheduler_value;
+
+       port_task_scheduler_value =
+               readl(&ihost->scu_registers->peg0.ptsg.control);
+       port_task_scheduler_value |=
+               (SCU_PTSGCR_GEN_BIT(ETM_ENABLE) |
+                SCU_PTSGCR_GEN_BIT(PTSG_ENABLE));
+       writel(port_task_scheduler_value,
+              &ihost->scu_registers->peg0.ptsg.control);
+}
+
+static void sci_controller_assign_task_entries(struct isci_host *ihost)
+{
+       u32 task_assignment;
+
+       /*
+        * Assign all the TCs to function 0
+        * TODO: Do we actually need to read this register to write it back?
+        */
+
+       task_assignment =
+               readl(&ihost->smu_registers->task_context_assignment[0]);
+
+       task_assignment |= (SMU_TCA_GEN_VAL(STARTING, 0)) |
+               (SMU_TCA_GEN_VAL(ENDING,  ihost->task_context_entries - 1)) |
+               (SMU_TCA_GEN_BIT(RANGE_CHECK_ENABLE));
+
+       writel(task_assignment,
+               &ihost->smu_registers->task_context_assignment[0]);
+
+}
+
+static void sci_controller_initialize_completion_queue(struct isci_host *ihost)
+{
+       u32 index;
+       u32 completion_queue_control_value;
+       u32 completion_queue_get_value;
+       u32 completion_queue_put_value;
+
+       ihost->completion_queue_get = 0;
+
+       completion_queue_control_value =
+               (SMU_CQC_QUEUE_LIMIT_SET(SCU_MAX_COMPLETION_QUEUE_ENTRIES - 1) |
+                SMU_CQC_EVENT_LIMIT_SET(SCU_MAX_EVENTS - 1));
+
+       writel(completion_queue_control_value,
+              &ihost->smu_registers->completion_queue_control);
+
+
+       /* Set the completion queue get pointer and enable the queue */
+       completion_queue_get_value = (
+               (SMU_CQGR_GEN_VAL(POINTER, 0))
+               | (SMU_CQGR_GEN_VAL(EVENT_POINTER, 0))
+               | (SMU_CQGR_GEN_BIT(ENABLE))
+               | (SMU_CQGR_GEN_BIT(EVENT_ENABLE))
+               );
+
+       writel(completion_queue_get_value,
+              &ihost->smu_registers->completion_queue_get);
+
+       /* Set the completion queue put pointer */
+       completion_queue_put_value = (
+               (SMU_CQPR_GEN_VAL(POINTER, 0))
+               | (SMU_CQPR_GEN_VAL(EVENT_POINTER, 0))
+               );
+
+       writel(completion_queue_put_value,
+              &ihost->smu_registers->completion_queue_put);
+
+       /* Initialize the cycle bit of the completion queue entries */
+       for (index = 0; index < SCU_MAX_COMPLETION_QUEUE_ENTRIES; index++) {
+               /*
+                * If get.cycle_bit != completion_queue.cycle_bit
+                * its not a valid completion queue entry
+                * so at system start all entries are invalid */
+               ihost->completion_queue[index] = 0x80000000;
+       }
+}
+
+static void sci_controller_initialize_unsolicited_frame_queue(struct isci_host *ihost)
+{
+       u32 frame_queue_control_value;
+       u32 frame_queue_get_value;
+       u32 frame_queue_put_value;
+
+       /* Write the queue size */
+       frame_queue_control_value =
+               SCU_UFQC_GEN_VAL(QUEUE_SIZE, SCU_MAX_UNSOLICITED_FRAMES);
+
+       writel(frame_queue_control_value,
+              &ihost->scu_registers->sdma.unsolicited_frame_queue_control);
+
+       /* Setup the get pointer for the unsolicited frame queue */
+       frame_queue_get_value = (
+               SCU_UFQGP_GEN_VAL(POINTER, 0)
+               |  SCU_UFQGP_GEN_BIT(ENABLE_BIT)
+               );
+
+       writel(frame_queue_get_value,
+              &ihost->scu_registers->sdma.unsolicited_frame_get_pointer);
+       /* Setup the put pointer for the unsolicited frame queue */
+       frame_queue_put_value = SCU_UFQPP_GEN_VAL(POINTER, 0);
+       writel(frame_queue_put_value,
+              &ihost->scu_registers->sdma.unsolicited_frame_put_pointer);
+}
+
+static void sci_controller_transition_to_ready(struct isci_host *ihost, enum sci_status status)
+{
+       if (ihost->sm.current_state_id == SCIC_STARTING) {
+               /*
+                * We move into the ready state, because some of the phys/ports
+                * may be up and operational.
+                */
+               sci_change_state(&ihost->sm, SCIC_READY);
+
+               isci_host_start_complete(ihost, status);
+       }
+}
+
+static bool is_phy_starting(struct isci_phy *iphy)
+{
+       enum sci_phy_states state;
+
+       state = iphy->sm.current_state_id;
+       switch (state) {
+       case SCI_PHY_STARTING:
+       case SCI_PHY_SUB_INITIAL:
+       case SCI_PHY_SUB_AWAIT_SAS_SPEED_EN:
+       case SCI_PHY_SUB_AWAIT_IAF_UF:
+       case SCI_PHY_SUB_AWAIT_SAS_POWER:
+       case SCI_PHY_SUB_AWAIT_SATA_POWER:
+       case SCI_PHY_SUB_AWAIT_SATA_PHY_EN:
+       case SCI_PHY_SUB_AWAIT_SATA_SPEED_EN:
+       case SCI_PHY_SUB_AWAIT_SIG_FIS_UF:
+       case SCI_PHY_SUB_FINAL:
+               return true;
+       default:
+               return false;
+       }
+}
+
+/**
+ * sci_controller_start_next_phy - start phy
+ * @scic: controller
+ *
+ * If all the phys have been started, then attempt to transition the
+ * controller to the READY state and inform the user
+ * (sci_cb_controller_start_complete()).
+ */
+static enum sci_status sci_controller_start_next_phy(struct isci_host *ihost)
+{
+       struct sci_oem_params *oem = &ihost->oem_parameters;
+       struct isci_phy *iphy;
+       enum sci_status status;
+
+       status = SCI_SUCCESS;
+
+       if (ihost->phy_startup_timer_pending)