Merge branch 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 3 Jun 2010 22:46:37 +0000 (15:46 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 3 Jun 2010 22:46:37 +0000 (15:46 -0700)
* 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc:
  powerpc/macio: Fix probing of macio devices by using the right of match table
  agp/uninorth: Fix oops caused by flushing too much
  powerpc/pasemi: Update MAINTAINERS file
  powerpc/cell: Fix integer constant warning
  powerpc/kprobes: Remove resume_execution() in kprobes
  powerpc/macio: Don't dereference pointer before null check

181 files changed:
Documentation/DocBook/drm.tmpl
Documentation/i2c/busses/i2c-ali1535
Documentation/i2c/busses/i2c-ali1563
Documentation/i2c/busses/i2c-ali15x3
Documentation/i2c/busses/i2c-pca-isa
Documentation/i2c/busses/i2c-sis5595
Documentation/i2c/busses/i2c-sis630
Documentation/i2c/ten-bit-addresses
arch/powerpc/sysdev/fsl_msi.c
arch/powerpc/sysdev/fsl_rio.c
arch/x86/kernel/cpu/perf_event.c
arch/x86/xen/suspend.c
drivers/block/virtio_blk.c
drivers/char/virtio_console.c
drivers/crypto/amcc/crypto4xx_core.c
drivers/crypto/n2_core.c
drivers/dma/mpc512x_dma.c
drivers/dma/ppc4xx/adma.c
drivers/edac/mpc85xx_edac.c
drivers/edac/ppc4xx_edac.c
drivers/gpu/drm/drm_crtc_helper.c
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/nouveau/nouveau_acpi.c
drivers/gpu/drm/nouveau/nouveau_bios.c
drivers/gpu/drm/nouveau/nouveau_connector.c
drivers/gpu/drm/nouveau/nouveau_crtc.h
drivers/gpu/drm/nouveau/nouveau_drv.c
drivers/gpu/drm/nouveau/nouveau_drv.h
drivers/gpu/drm/nouveau/nouveau_mem.c
drivers/gpu/drm/nouveau/nouveau_state.c
drivers/gpu/drm/nouveau/nv04_cursor.c
drivers/gpu/drm/nouveau/nv50_cursor.c
drivers/gpu/drm/nouveau/nv50_sor.c
drivers/gpu/drm/radeon/Makefile
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/evergreen_cs.c [new file with mode: 0644]
drivers/gpu/drm/radeon/evergreen_reg.h
drivers/gpu/drm/radeon/evergreend.h
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_asic.c
drivers/gpu/drm/radeon/radeon_asic.h
drivers/gpu/drm/radeon/radeon_atombios.c
drivers/gpu/drm/radeon/radeon_combios.c
drivers/gpu/drm/radeon/radeon_device.c
drivers/gpu/drm/radeon/radeon_pm.c
drivers/gpu/drm/radeon/reg_srcs/evergreen [new file with mode: 0644]
drivers/gpu/drm/radeon/rs600.c
drivers/gpu/drm/radeon/rv770.c
drivers/gpu/drm/ttm/ttm_page_alloc.c
drivers/gpu/drm/vmwgfx/Makefile
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
drivers/gpu/drm/vmwgfx/vmwgfx_fence.c [new file with mode: 0644]
drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
drivers/gpu/drm/vmwgfx/vmwgfx_irq.c
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c
drivers/gpu/vga/vgaarb.c
drivers/hwmon/adt7411.c
drivers/hwmon/asc7621.c
drivers/hwmon/f75375s.c
drivers/hwmon/g760a.c
drivers/hwmon/lm73.c
drivers/hwmon/lm75.c
drivers/hwmon/lm95241.c
drivers/hwmon/tmp102.c
drivers/hwmon/tmp421.c
drivers/hwmon/w83781d.c
drivers/i2c/busses/Kconfig
drivers/i2c/busses/Makefile
drivers/i2c/i2c-core.c
drivers/i2c/i2c-smbus.c
drivers/input/keyboard/adp5588-keys.c
drivers/input/keyboard/lm8323.c
drivers/input/keyboard/max7359_keypad.c
drivers/input/keyboard/qt2160.c
drivers/input/keyboard/tca6416-keypad.c
drivers/input/misc/ad714x-i2c.c
drivers/input/misc/pcf8574_keypad.c
drivers/input/mouse/synaptics_i2c.c
drivers/input/touchscreen/ad7879.c
drivers/input/touchscreen/eeti_ts.c
drivers/input/touchscreen/mcs5000_ts.c
drivers/input/touchscreen/tsc2007.c
drivers/leds/leds-bd2802.c
drivers/leds/leds-lp3944.c
drivers/leds/leds-pca9532.c
drivers/leds/leds-pca955x.c
drivers/macintosh/therm_adt746x.c
drivers/macintosh/windfarm_lm75_sensor.c
drivers/macintosh/windfarm_max6690_sensor.c
drivers/macintosh/windfarm_smu_sat.c
drivers/media/radio/si470x/radio-si470x-i2c.c
drivers/media/video/mt9m001.c
drivers/media/video/mt9m111.c
drivers/media/video/mt9t031.c
drivers/media/video/mt9t112.c
drivers/media/video/mt9v022.c
drivers/media/video/ov772x.c
drivers/media/video/ov9640.c
drivers/media/video/rj54n1cb0c.c
drivers/media/video/tcm825x.c
drivers/media/video/tw9910.c
drivers/mfd/88pm860x-i2c.c
drivers/mfd/ab3100-core.c
drivers/mfd/ab3550-core.c
drivers/mfd/adp5520.c
drivers/mfd/da903x.c
drivers/mfd/max8925-i2c.c
drivers/mfd/menelaus.c
drivers/mfd/pcf50633-core.c
drivers/mfd/tc35892.c
drivers/mfd/tps65010.c
drivers/mfd/wm8350-i2c.c
drivers/mfd/wm8400-core.c
drivers/misc/eeprom/at24.c
drivers/mtd/maps/pismo.c
drivers/mtd/nand/fsl_upm.c
drivers/mtd/nand/mpc5121_nfc.c
drivers/mtd/nand/socrates_nand.c
drivers/net/fs_enet/mii-bitbang.c
drivers/pcmcia/m8xx_pcmcia.c
drivers/power/max17040_battery.c
drivers/regulator/lp3971.c
drivers/regulator/max1586.c
drivers/regulator/max8649.c
drivers/regulator/max8660.c
drivers/regulator/tps65023-regulator.c
drivers/rtc/rtc-ds1374.c
drivers/rtc/rtc-mpc5121.c
drivers/rtc/rtc-rx8025.c
drivers/rtc/rtc-s35390a.c
drivers/spi/mpc512x_psc_spi.c
drivers/spi/spi_ppc4xx.c
drivers/staging/dream/synaptics_i2c_rmi.c
drivers/staging/go7007/wis-saa7113.c
drivers/staging/go7007/wis-saa7115.c
drivers/staging/go7007/wis-sony-tuner.c
drivers/staging/go7007/wis-tw2804.c
drivers/staging/go7007/wis-tw9903.c
drivers/staging/iio/adc/max1363_core.c
drivers/staging/iio/light/tsl2563.c
drivers/usb/gadget/fsl_qe_udc.c
drivers/usb/host/ehci-xilinx-of.c
drivers/video/aty/mach64_accel.c
drivers/video/backlight/adp8860_bl.c
drivers/video/backlight/tosa_bl.c
drivers/video/bw2.c
drivers/video/cg14.c
drivers/video/cg3.c
drivers/video/leo.c
drivers/video/mb862xx/mb862xxfb.c
drivers/video/p9100.c
drivers/video/tcx.c
drivers/watchdog/gef_wdt.c
drivers/watchdog/mpc8xxx_wdt.c
drivers/xen/xenbus/xenbus_xs.c
fs/cifs/file.c
include/drm/drm_crtc_helper.h
include/drm/nouveau_drm.h
include/drm/vmwgfx_drm.h
include/linux/perf_event.h
include/linux/vgaarb.h
include/trace/ftrace.h
kernel/perf_event.c
kernel/trace/blktrace.c
kernel/trace/trace_event_perf.c
kernel/trace/trace_kprobe.c
kernel/trace/trace_syscalls.c
tools/perf/builtin-buildid-list.c
tools/perf/builtin-record.c
tools/perf/builtin-sched.c
tools/perf/scripts/python/check-perf-trace.py
tools/perf/util/event.c
tools/perf/util/hist.c
tools/perf/util/scripting-engines/trace-event-python.c

index 7583dc7cf64d5b321cd9e50aba766087e07a9fc5..910c923a9b86fe5bbd4e38abd6ad2eb593a25e2b 100644 (file)
       </para>
       <para>
        If your driver supports memory management (it should!), you'll
-       need to set that up at load time as well.  How you intialize
+       need to set that up at load time as well.  How you initialize
        it depends on which memory manager you're using, TTM or GEM.
       </para>
       <sect3>
          aperture space for graphics devices. TTM supports both UMA devices
          and devices with dedicated video RAM (VRAM), i.e. most discrete
          graphics devices.  If your device has dedicated RAM, supporting
-         TTM is desireable.  TTM also integrates tightly with your
+         TTM is desirable.  TTM also integrates tightly with your
          driver specific buffer execution function.  See the radeon
          driver for examples.
        </para>
          likely eventually calling ttm_bo_global_init and
          ttm_bo_global_release, respectively.  Also like the previous
          object, ttm_global_item_ref is used to create an initial reference
-         count for the TTM, which will call your initalization function.
+         count for the TTM, which will call your initialization function.
        </para>
       </sect3>
       <sect3>
@@ -557,7 +557,7 @@ void intel_crt_init(struct drm_device *dev)
          CRT connector and encoder combination is created.  A device
          specific i2c bus is also created, for fetching EDID data and
          performing monitor detection.  Once the process is complete,
-         the new connector is regsitered with sysfs, to make its
+         the new connector is registered with sysfs, to make its
          properties available to applications.
        </para>
        <sect4>
@@ -581,12 +581,12 @@ void intel_crt_init(struct drm_device *dev)
        <para>
          For each encoder, CRTC and connector, several functions must
          be provided, depending on the object type.  Encoder objects
-         need should provide a DPMS (basically on/off) function, mode fixup
+         need to provide a DPMS (basically on/off) function, mode fixup
          (for converting requested modes into native hardware timings),
          and prepare, set and commit functions for use by the core DRM
          helper functions.  Connector helpers need to provide mode fetch and
          validity functions as well as an encoder matching function for
-         returing an ideal encoder for a given connector.  The core
+         returning an ideal encoder for a given connector.  The core
          connector functions include a DPMS callback, (deprecated)
          save/restore routines, detection, mode probing, property handling,
          and cleanup functions.
index 0db3b4c74ad11109ac59e1486388b5675d49bc56..acbc65a08097777c41d5e400602bde9ed04ae160 100644 (file)
@@ -6,12 +6,12 @@ Supported adapters:
        http://www.ali.com.tw/eng/support/datasheet_request.php
 
 Authors:
-       Frodo Looijaard <frodol@dds.nl>, 
+       Frodo Looijaard <frodol@dds.nl>,
        Philip Edelbrock <phil@netroedge.com>,
        Mark D. Studebaker <mdsxyz123@yahoo.com>,
        Dan Eaton <dan.eaton@rocketlogix.com>,
        Stephen Rousset<stephen.rousset@rocketlogix.com>
-                                                                                               
+
 Description
 -----------
 
index 99ad4b9bcc32ec945235298ee1b9ffd8fbaa3e69..54691698d2ddd465f2a5e9ecd7a1e99ae1da57e5 100644 (file)
@@ -18,7 +18,7 @@ For an overview of these chips see http://www.acerlabs.com
 The M1563 southbridge is deceptively similar to the M1533, with a few
 notable exceptions. One of those happens to be the fact they upgraded the
 i2c core to be SMBus 2.0 compliant, and happens to be almost identical to
-the i2c controller found in the Intel 801 south bridges. 
+the i2c controller found in the Intel 801 south bridges.
 
 Features
 --------
index ff28d381bebe8daa880e344c767e4dad7ff4be14..600da90b8f12138fbf0bd5eb78c2bf0922317443 100644 (file)
@@ -6,8 +6,8 @@ Supported adapters:
        http://www.ali.com.tw/eng/support/datasheet_request.php
 
 Authors:
-       Frodo Looijaard <frodol@dds.nl>, 
-       Philip Edelbrock <phil@netroedge.com>, 
+       Frodo Looijaard <frodol@dds.nl>,
+       Philip Edelbrock <phil@netroedge.com>,
        Mark D. Studebaker <mdsxyz123@yahoo.com>
 
 Module Parameters
@@ -40,10 +40,10 @@ M1541 and M1543C South Bridges.
 The M1543C is a South bridge for desktop systems.
 The M1541 is a South bridge for portable systems.
 They are part of the following ALI chipsets:
-   
- * "Aladdin Pro 2" includes the M1621 Slot 1 North bridge with AGP and 
+
+ * "Aladdin Pro 2" includes the M1621 Slot 1 North bridge with AGP and
                100MHz CPU Front Side bus
- * "Aladdin V" includes the M1541 Socket 7 North bridge with AGP and 100MHz 
+ * "Aladdin V" includes the M1541 Socket 7 North bridge with AGP and 100MHz
                CPU Front Side bus
    Some Aladdin V motherboards:
        Asus P5A
@@ -77,7 +77,7 @@ output of lspci will show something similar to the following:
 ** then run lspci.
 ** If you see the 1533 and 5229 devices but NOT the 7101 device,
 ** then you must enable ACPI, the PMU, SMB, or something similar
-** in the BIOS. 
+** in the BIOS.
 ** The driver won't work if it can't find the M7101 device.
 
 The SMB controller is part of the M7101 device, which is an ACPI-compliant
@@ -87,8 +87,8 @@ The whole M7101 device has to be enabled for the SMB to work. You can't
 just enable the SMB alone. The SMB and the ACPI have separate I/O spaces.
 We make sure that the SMB is enabled. We leave the ACPI alone.
 
-Features 
--------- 
+Features
+--------
 
 This driver controls the SMB Host only. The SMB Slave
 controller on the M15X3 is not enabled. This driver does not use
index 6fc8f4c27c3ce58a12470e11efed3435dede8d85..b044e52654886c05dd37d16212a4cd2cf80419a3 100644 (file)
@@ -1,10 +1,10 @@
 Kernel driver i2c-pca-isa
 
 Supported adapters:
-This driver supports ISA boards using the Philips PCA 9564 
-Parallel bus to I2C bus controller 
+This driver supports ISA boards using the Philips PCA 9564
+Parallel bus to I2C bus controller
 
-Author: Ian Campbell <icampbell@arcom.com>, Arcom Control Systems 
+Author: Ian Campbell <icampbell@arcom.com>, Arcom Control Systems
 
 Module Parameters
 -----------------
@@ -12,12 +12,12 @@ Module Parameters
 * base int
  I/O base address
 * irq int
- IRQ interrupt 
-* clock int 
+ IRQ interrupt
+* clock int
  Clock rate as described in table 1 of PCA9564 datasheet
 
 Description
 -----------
 
-This driver supports ISA boards using the Philips PCA 9564 
-Parallel bus to I2C bus controller 
+This driver supports ISA boards using the Philips PCA 9564
+Parallel bus to I2C bus controller
index cc47db7d00a989da91f6cf99b1578a76ff7cc577..ecd21fb49a8f0c7cd780def05f3ca5408983c3c5 100644 (file)
@@ -1,41 +1,41 @@
 Kernel driver i2c-sis5595
 
-Authors: 
+Authors:
        Frodo Looijaard <frodol@dds.nl>,
         Mark D. Studebaker <mdsxyz123@yahoo.com>,
-       Philip Edelbrock <phil@netroedge.com> 
+       Philip Edelbrock <phil@netroedge.com>
 
 Supported adapters:
   * Silicon Integrated Systems Corp. SiS5595 Southbridge
     Datasheet: Publicly available at the Silicon Integrated Systems Corp. site.
 
-Note: all have mfr. ID 0x1039. 
-
-   SUPPORTED            PCI ID           
-        5595            0008 
-   Note: these chips contain a 0008 device which is incompatible with the 
-         5595. We recognize these by the presence of the listed 
-         "blacklist" PCI ID and refuse to load. 
-   NOT SUPPORTED        PCI ID          BLACKLIST PCI ID         
-         540            0008            0540 
-         550            0008            0550 
-        5513            0008            5511 
-        5581            0008            5597 
-        5582            0008            5597 
-        5597            0008            5597 
-        5598            0008            5597/5598 
-         630            0008            0630 
-         645            0008            0645 
-         646            0008            0646 
-         648            0008            0648 
-         650            0008            0650 
-         651            0008            0651 
-         730            0008            0730 
-         735            0008            0735 
-         745            0008            0745 
-         746            0008            0746 
+Note: all have mfr. ID 0x1039.
+
+   SUPPORTED            PCI ID
+        5595            0008
+
+   Note: these chips contain a 0008 device which is incompatible with the
+         5595. We recognize these by the presence of the listed
+         "blacklist" PCI ID and refuse to load.
+
+   NOT SUPPORTED        PCI ID          BLACKLIST PCI ID
+         540            0008            0540
+         550            0008            0550
+        5513            0008            5511
+        5581            0008            5597
+        5582            0008            5597
+        5597            0008            5597
+        5598            0008            5597/5598
+         630            0008            0630
+         645            0008            0645
+         646            0008            0646
+         648            0008            0648
+         650            0008            0650
+         651            0008            0651
+         730            0008            0730
+         735            0008            0735
+         745            0008            0745
+         746            0008            0746
 
 Module Parameters
 -----------------
index 9aca6889f748e2479052c5c42e9144f852ea42b7..629ea2c356fdb1d00594f57865cbe148c283ee82 100644 (file)
@@ -14,9 +14,9 @@ Module Parameters
 * force = [1|0] Forcibly enable the SIS630. DANGEROUS!
                This can be interesting for chipsets not named
                above to check if it works for you chipset, but DANGEROUS!
-               
-* high_clock = [1|0] Forcibly set Host Master Clock to 56KHz (default, 
-                       what your BIOS use). DANGEROUS! This should be a bit 
+
+* high_clock = [1|0] Forcibly set Host Master Clock to 56KHz (default,
+                       what your BIOS use). DANGEROUS! This should be a bit
                        faster, but freeze some systems (i.e. my Laptop).
 
 
@@ -44,6 +44,6 @@ Philip Edelbrock <phil@netroedge.com>
 - testing SiS730 support
 Mark M. Hoffman <mhoffman@lightlink.com>
 - bug fixes
+
 To anyone else which I forgot here ;), thanks!
 
index 200074f8136073bf988463272e0ea269020ac980..e9890709c508b25ed9878ab979797d1fc58a7a4b 100644 (file)
@@ -1,17 +1,17 @@
-The I2C protocol knows about two kinds of device addresses: normal 7 bit 
+The I2C protocol knows about two kinds of device addresses: normal 7 bit
 addresses, and an extended set of 10 bit addresses. The sets of addresses
 do not intersect: the 7 bit address 0x10 is not the same as the 10 bit
 address 0x10 (though a single device could respond to both of them). You
 select a 10 bit address by adding an extra byte after the address
 byte:
-  S Addr7 Rd/Wr ....  
+  S Addr7 Rd/Wr ....
 becomes
   S 11110 Addr10 Rd/Wr
 S is the start bit, Rd/Wr the read/write bit, and if you count the number
 of bits, you will see the there are 8 after the S bit for 7 bit addresses,
 and 16 after the S bit for 10 bit addresses.
 
-WARNING! The current 10 bit address support is EXPERIMENTAL. There are 
+WARNING! The current 10 bit address support is EXPERIMENTAL. There are
 several places in the code that will cause SEVERE PROBLEMS with 10 bit
 addresses, even though there is some basic handling and hooks. Also,
 almost no supported adapter handles the 10 bit addresses correctly.
index 0f5bee90ee4e2b572ff28a68431af2b51b60d825..962c2d8dd8d927e0d2e03336dff954e42935ef86 100644 (file)
@@ -347,7 +347,7 @@ static int __devinit fsl_of_msi_probe(struct of_device *dev,
                goto error_out;
        }
        offset = 0;
-       p = of_get_property(dev->node, "msi-available-ranges", &len);
+       p = of_get_property(dev->dev.of_node, "msi-available-ranges", &len);
        if (p)
                offset = *p / IRQS_PER_MSI_REG;
 
index cd37e49e70349d05cc82c48e83b0bd6a42faa9ce..30e1626b2e850c9f2d5f9d2137f3025cf05f4ea8 100644 (file)
@@ -1426,7 +1426,7 @@ int fsl_rio_setup(struct of_device *dev)
        port->iores.flags = IORESOURCE_MEM;
        port->iores.name = "rio_io_win";
 
-       priv->pwirq   = irq_of_parse_and_map(dev->node, 0);
+       priv->pwirq   = irq_of_parse_and_map(dev->dev.of_node, 0);
        priv->bellirq = irq_of_parse_and_map(dev->dev.of_node, 2);
        priv->txirq = irq_of_parse_and_map(dev->dev.of_node, 3);
        priv->rxirq = irq_of_parse_and_map(dev->dev.of_node, 4);
index c77586061bcbc7642d2f7662f487f4432d2e3ff0..5db5b7d65a180f6a7f0c2cb970d63e04129add2a 100644 (file)
@@ -106,6 +106,7 @@ struct cpu_hw_events {
 
        int                     n_events;
        int                     n_added;
+       int                     n_txn;
        int                     assign[X86_PMC_IDX_MAX]; /* event to counter assignment */
        u64                     tags[X86_PMC_IDX_MAX];
        struct perf_event       *event_list[X86_PMC_IDX_MAX]; /* in enabled order */
@@ -983,6 +984,7 @@ static int x86_pmu_enable(struct perf_event *event)
 out:
        cpuc->n_events = n;
        cpuc->n_added += n - n0;
+       cpuc->n_txn += n - n0;
 
        return 0;
 }
@@ -1089,6 +1091,14 @@ static void x86_pmu_disable(struct perf_event *event)
        struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
        int i;
 
+       /*
+        * If we're called during a txn, we don't need to do anything.
+        * The events never got scheduled and ->cancel_txn will truncate
+        * the event_list.
+        */
+       if (cpuc->group_flag & PERF_EVENT_TXN_STARTED)
+               return;
+
        x86_pmu_stop(event);
 
        for (i = 0; i < cpuc->n_events; i++) {
@@ -1379,6 +1389,7 @@ static void x86_pmu_start_txn(const struct pmu *pmu)
        struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 
        cpuc->group_flag |= PERF_EVENT_TXN_STARTED;
+       cpuc->n_txn = 0;
 }
 
 /*
@@ -1391,6 +1402,11 @@ static void x86_pmu_cancel_txn(const struct pmu *pmu)
        struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 
        cpuc->group_flag &= ~PERF_EVENT_TXN_STARTED;
+       /*
+        * Truncate the collected events.
+        */
+       cpuc->n_added -= cpuc->n_txn;
+       cpuc->n_events -= cpuc->n_txn;
 }
 
 /*
@@ -1419,6 +1435,12 @@ static int x86_pmu_commit_txn(const struct pmu *pmu)
         */
        memcpy(cpuc->assign, assign, n*sizeof(int));
 
+       /*
+        * Clear out the txn count so that ->cancel_txn() which gets
+        * run after ->commit_txn() doesn't undo things.
+        */
+       cpuc->n_txn = 0;
+
        return 0;
 }
 
index 987267f79bf5154648cb729cedf29e712fa58ab3..a9c6611080347bd4368beff2ab582d07347fa256 100644 (file)
@@ -60,6 +60,6 @@ static void xen_vcpu_notify_restore(void *data)
 
 void xen_arch_resume(void)
 {
-       smp_call_function(xen_vcpu_notify_restore,
-                              (void *)CLOCK_EVT_NOTIFY_RESUME, 1);
+       on_each_cpu(xen_vcpu_notify_restore,
+                   (void *)CLOCK_EVT_NOTIFY_RESUME, 1);
 }
index 83fa09a836ca8574a3696c888d7574a833b35447..258bc2ae2885625a1650cebcabb4b9eb975092bb 100644 (file)
@@ -298,7 +298,9 @@ static int __devinit virtblk_probe(struct virtio_device *vdev)
        err = virtio_config_val(vdev, VIRTIO_BLK_F_SEG_MAX,
                                offsetof(struct virtio_blk_config, seg_max),
                                &sg_elems);
-       if (err)
+
+       /* We need at least one SG element, whatever they say. */
+       if (err || !sg_elems)
                sg_elems = 1;
 
        /* We need an extra sg elements at head and tail. */
index 8c99bf1b5e9fde218dab95f2091b807a7fbb4623..942a9826bd23ed64b83095fcdeb65ed059c9ce02 100644 (file)
@@ -529,6 +529,10 @@ static bool will_write_block(struct port *port)
 {
        bool ret;
 
+       if (!port->guest_connected) {
+               /* Port got hot-unplugged. Let's exit. */
+               return false;
+       }
        if (!port->host_connected)
                return true;
 
@@ -1099,6 +1103,13 @@ static int remove_port(struct port *port)
 {
        struct port_buffer *buf;
 
+       if (port->guest_connected) {
+               port->guest_connected = false;
+               port->host_connected = false;
+               wake_up_interruptible(&port->waitqueue);
+               send_control_msg(port, VIRTIO_CONSOLE_PORT_OPEN, 0);
+       }
+
        spin_lock_irq(&port->portdev->ports_lock);
        list_del(&port->list);
        spin_unlock_irq(&port->portdev->ports_lock);
@@ -1120,9 +1131,6 @@ static int remove_port(struct port *port)
                hvc_remove(port->cons.hvc);
 #endif
        }
-       if (port->guest_connected)
-               send_control_msg(port, VIRTIO_CONSOLE_PORT_OPEN, 0);
-
        sysfs_remove_group(&port->dev->kobj, &port_attribute_group);
        device_destroy(pdrvdata.class, port->dev->devt);
        cdev_del(&port->cdev);
index 9d65b371de64cced72bcb0f1e483913962277552..983530ba04a7e932c3a70ec692e719fe44cccb21 100644 (file)
@@ -1158,7 +1158,7 @@ static int __init crypto4xx_probe(struct of_device *ofdev,
        struct device *dev = &ofdev->dev;
        struct crypto4xx_core_device *core_dev;
 
-       rc = of_address_to_resource(ofdev->node, 0, &res);
+       rc = of_address_to_resource(ofdev->dev.of_node, 0, &res);
        if (rc)
                return -ENODEV;
 
@@ -1215,13 +1215,13 @@ static int __init crypto4xx_probe(struct of_device *ofdev,
                     (unsigned long) dev);
 
        /* Register for Crypto isr, Crypto Engine IRQ */
-       core_dev->irq = irq_of_parse_and_map(ofdev->node, 0);
+       core_dev->irq = irq_of_parse_and_map(ofdev->dev.of_node, 0);
        rc = request_irq(core_dev->irq, crypto4xx_ce_interrupt_handler, 0,
                         core_dev->dev->name, dev);
        if (rc)
                goto err_request_irq;
 
-       core_dev->dev->ce_base = of_iomap(ofdev->node, 0);
+       core_dev->dev->ce_base = of_iomap(ofdev->dev.of_node, 0);
        if (!core_dev->dev->ce_base) {
                dev_err(dev, "failed to of_iomap\n");
                goto err_iomap;
index 8566be832f5172b7fab29ccf134442d109681170..23163fda5035357a50c892c1a65a35e7ae3a89ea 100644 (file)
@@ -251,16 +251,10 @@ static void n2_base_ctx_init(struct n2_base_ctx *ctx)
 struct n2_hash_ctx {
        struct n2_base_ctx              base;
 
-       struct crypto_ahash             *fallback;
+       struct crypto_ahash             *fallback_tfm;
+};
 
-       /* These next three members must match the layout created by
-        * crypto_init_shash_ops_async.  This allows us to properly
-        * plumb requests we can't do in hardware down to the fallback
-        * operation, providing all of the data structures and layouts
-        * expected by those paths.
-        */
-       struct ahash_request            fallback_req;
-       struct shash_desc               fallback_desc;
+struct n2_hash_req_ctx {
        union {
                struct md5_state        md5;
                struct sha1_state       sha1;
@@ -269,56 +263,62 @@ struct n2_hash_ctx {
 
        unsigned char                   hash_key[64];
        unsigned char                   keyed_zero_hash[32];
+
+       struct ahash_request            fallback_req;
 };
 
 static int n2_hash_async_init(struct ahash_request *req)
 {
+       struct n2_hash_req_ctx *rctx = ahash_request_ctx(req);
        struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
        struct n2_hash_ctx *ctx = crypto_ahash_ctx(tfm);
 
-       ctx->fallback_req.base.tfm = crypto_ahash_tfm(ctx->fallback);
-       ctx->fallback_req.base.flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP;
+       ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm);
+       rctx->fallback_req.base.flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP;
 
-       return crypto_ahash_init(&ctx->fallback_req);
+       return crypto_ahash_init(&rctx->fallback_req);
 }
 
 static int n2_hash_async_update(struct ahash_request *req)
 {
+       struct n2_hash_req_ctx *rctx = ahash_request_ctx(req);
        struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
        struct n2_hash_ctx *ctx = crypto_ahash_ctx(tfm);
 
-       ctx->fallback_req.base.tfm = crypto_ahash_tfm(ctx->fallback);
-       ctx->fallback_req.base.flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP;
-       ctx->fallback_req.nbytes = req->nbytes;
-       ctx->fallback_req.src = req->src;
+       ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm);
+       rctx->fallback_req.base.flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP;
+       rctx->fallback_req.nbytes = req->nbytes;
+       rctx->fallback_req.src = req->src;
 
-       return crypto_ahash_update(&ctx->fallback_req);
+       return crypto_ahash_update(&rctx->fallback_req);
 }
 
 static int n2_hash_async_final(struct ahash_request *req)
 {
+       struct n2_hash_req_ctx *rctx = ahash_request_ctx(req);
        struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
        struct n2_hash_ctx *ctx = crypto_ahash_ctx(tfm);
 
-       ctx->fallback_req.base.tfm = crypto_ahash_tfm(ctx->fallback);
-       ctx->fallback_req.base.flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP;
-       ctx->fallback_req.result = req->result;
+       ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm);
+       rctx->fallback_req.base.flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP;
+       rctx->fallback_req.result = req->result;
 
-       return crypto_ahash_final(&ctx->fallback_req);
+       return crypto_ahash_final(&rctx->fallback_req);
 }
 
 static int n2_hash_async_finup(struct ahash_request *req)
 {
+       struct n2_hash_req_ctx *rctx = ahash_request_ctx(req);
        struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
        struct n2_hash_ctx *ctx = crypto_ahash_ctx(tfm);
 
-       ctx->fallback_req.base.tfm = crypto_ahash_tfm(ctx->fallback);
-       ctx->fallback_req.base.flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP;
-       ctx->fallback_req.nbytes = req->nbytes;
-       ctx->fallback_req.src = req->src;
-       ctx->fallback_req.result = req->result;
+       ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm);
+       rctx->fallback_req.base.flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP;
+       rctx->fallback_req.nbytes = req->nbytes;
+       rctx->fallback_req.src = req->src;
+       rctx->fallback_req.result = req->result;
 
-       return crypto_ahash_finup(&ctx->fallback_req);
+       return crypto_ahash_finup(&rctx->fallback_req);
 }
 
 static int n2_hash_cra_init(struct crypto_tfm *tfm)
@@ -338,7 +338,10 @@ static int n2_hash_cra_init(struct crypto_tfm *tfm)
                goto out;
        }
 
-       ctx->fallback = fallback_tfm;
+       crypto_ahash_set_reqsize(ahash, (sizeof(struct n2_hash_req_ctx) +
+                                        crypto_ahash_reqsize(fallback_tfm)));
+
+       ctx->fallback_tfm = fallback_tfm;
        return 0;
 
 out:
@@ -350,7 +353,7 @@ static void n2_hash_cra_exit(struct crypto_tfm *tfm)
        struct crypto_ahash *ahash = __crypto_ahash_cast(tfm);
        struct n2_hash_ctx *ctx = crypto_ahash_ctx(ahash);
 
-       crypto_free_ahash(ctx->fallback);
+       crypto_free_ahash(ctx->fallback_tfm);
 }
 
 static unsigned long wait_for_tail(struct spu_queue *qp)
@@ -399,14 +402,16 @@ static int n2_hash_async_digest(struct ahash_request *req,
         * exceed 2^16.
         */
        if (unlikely(req->nbytes > (1 << 16))) {
-               ctx->fallback_req.base.tfm = crypto_ahash_tfm(ctx->fallback);
-               ctx->fallback_req.base.flags =
+               struct n2_hash_req_ctx *rctx = ahash_request_ctx(req);
+
+               ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm);
+               rctx->fallback_req.base.flags =
                        req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP;
-               ctx->fallback_req.nbytes = req->nbytes;
-               ctx->fallback_req.src = req->src;
-               ctx->fallback_req.result = req->result;
+               rctx->fallback_req.nbytes = req->nbytes;
+               rctx->fallback_req.src = req->src;
+               rctx->fallback_req.result = req->result;
 
-               return crypto_ahash_digest(&ctx->fallback_req);
+               return crypto_ahash_digest(&rctx->fallback_req);
        }
 
        n2_base_ctx_init(&ctx->base);
@@ -472,9 +477,8 @@ out:
 
 static int n2_md5_async_digest(struct ahash_request *req)
 {
-       struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
-       struct n2_hash_ctx *ctx = crypto_ahash_ctx(tfm);
-       struct md5_state *m = &ctx->u.md5;
+       struct n2_hash_req_ctx *rctx = ahash_request_ctx(req);
+       struct md5_state *m = &rctx->u.md5;
 
        if (unlikely(req->nbytes == 0)) {
                static const char md5_zero[MD5_DIGEST_SIZE] = {
@@ -497,9 +501,8 @@ static int n2_md5_async_digest(struct ahash_request *req)
 
 static int n2_sha1_async_digest(struct ahash_request *req)
 {
-       struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
-       struct n2_hash_ctx *ctx = crypto_ahash_ctx(tfm);
-       struct sha1_state *s = &ctx->u.sha1;
+       struct n2_hash_req_ctx *rctx = ahash_request_ctx(req);
+       struct sha1_state *s = &rctx->u.sha1;
 
        if (unlikely(req->nbytes == 0)) {
                static const char sha1_zero[SHA1_DIGEST_SIZE] = {
@@ -524,9 +527,8 @@ static int n2_sha1_async_digest(struct ahash_request *req)
 
 static int n2_sha256_async_digest(struct ahash_request *req)
 {
-       struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
-       struct n2_hash_ctx *ctx = crypto_ahash_ctx(tfm);
-       struct sha256_state *s = &ctx->u.sha256;
+       struct n2_hash_req_ctx *rctx = ahash_request_ctx(req);
+       struct sha256_state *s = &rctx->u.sha256;
 
        if (req->nbytes == 0) {
                static const char sha256_zero[SHA256_DIGEST_SIZE] = {
@@ -555,9 +557,8 @@ static int n2_sha256_async_digest(struct ahash_request *req)
 
 static int n2_sha224_async_digest(struct ahash_request *req)
 {
-       struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
-       struct n2_hash_ctx *ctx = crypto_ahash_ctx(tfm);
-       struct sha256_state *s = &ctx->u.sha256;
+       struct n2_hash_req_ctx *rctx = ahash_request_ctx(req);
+       struct sha256_state *s = &rctx->u.sha256;
 
        if (req->nbytes == 0) {
                static const char sha224_zero[SHA224_DIGEST_SIZE] = {
@@ -1398,7 +1399,7 @@ static int find_devino_index(struct of_device *dev, struct spu_mdesc_info *ip,
 
        intr = ip->ino_table[i].intr;
 
-       dev_intrs = of_get_property(dev->node, "interrupts", NULL);
+       dev_intrs = of_get_property(dev->dev.of_node, "interrupts", NULL);
        if (!dev_intrs)
                return -ENODEV;
 
@@ -1449,7 +1450,7 @@ static int queue_cache_init(void)
 {
        if (!queue_cache[HV_NCS_QTYPE_MAU - 1])
                queue_cache[HV_NCS_QTYPE_MAU - 1] =
-                       kmem_cache_create("cwq_queue",
+                       kmem_cache_create("mau_queue",
                                          (MAU_NUM_ENTRIES *
                                           MAU_ENTRY_SIZE),
                                          MAU_ENTRY_SIZE, 0, NULL);
@@ -1574,7 +1575,7 @@ static int spu_mdesc_walk_arcs(struct mdesc_handle *mdesc,
                id = mdesc_get_property(mdesc, tgt, "id", NULL);
                if (table[*id] != NULL) {
                        dev_err(&dev->dev, "%s: SPU cpu slot already set.\n",
-                               dev->node->full_name);
+                               dev->dev.of_node->full_name);
                        return -EINVAL;
                }
                cpu_set(*id, p->sharing);
@@ -1595,7 +1596,7 @@ static int handle_exec_unit(struct spu_mdesc_info *ip, struct list_head *list,
        p = kzalloc(sizeof(struct spu_queue), GFP_KERNEL);
        if (!p) {
                dev_err(&dev->dev, "%s: Could not allocate SPU queue.\n",
-                       dev->node->full_name);
+                       dev->dev.of_node->full_name);
                return -ENOMEM;
        }
 
@@ -1684,7 +1685,7 @@ static int __devinit grab_mdesc_irq_props(struct mdesc_handle *mdesc,
        const unsigned int *reg;
        u64 node;
 
-       reg = of_get_property(dev->node, "reg", NULL);
+       reg = of_get_property(dev->dev.of_node, "reg", NULL);
        if (!reg)
                return -ENODEV;
 
@@ -1836,7 +1837,7 @@ static int __devinit n2_crypto_probe(struct of_device *dev,
 
        n2_spu_driver_version();
 
-       full_name = dev->node->full_name;
+       full_name = dev->dev.of_node->full_name;
        pr_info("Found N2CP at %s\n", full_name);
 
        np = alloc_n2cp();
@@ -1948,7 +1949,7 @@ static int __devinit n2_mau_probe(struct of_device *dev,
 
        n2_spu_driver_version();
 
-       full_name = dev->node->full_name;
+       full_name = dev->dev.of_node->full_name;
        pr_info("Found NCP at %s\n", full_name);
 
        mp = alloc_ncp();
@@ -2034,8 +2035,11 @@ static struct of_device_id n2_crypto_match[] = {
 MODULE_DEVICE_TABLE(of, n2_crypto_match);
 
 static struct of_platform_driver n2_crypto_driver = {
-       .name           =       "n2cp",
-       .match_table    =       n2_crypto_match,
+       .driver = {
+               .name           =       "n2cp",
+               .owner          =       THIS_MODULE,
+               .of_match_table =       n2_crypto_match,
+       },
        .probe          =       n2_crypto_probe,
        .remove         =       __devexit_p(n2_crypto_remove),
 };
@@ -2055,8 +2059,11 @@ static struct of_device_id n2_mau_match[] = {
 MODULE_DEVICE_TABLE(of, n2_mau_match);
 
 static struct of_platform_driver n2_mau_driver = {
-       .name           =       "ncp",
-       .match_table    =       n2_mau_match,
+       .driver = {
+               .name           =       "ncp",
+               .owner          =       THIS_MODULE,
+               .of_match_table =       n2_mau_match,
+       },
        .probe          =       n2_mau_probe,
        .remove         =       __devexit_p(n2_mau_remove),
 };
index 201e6e19c344d1cfe1ca2ff7402027bf6ca3ba54..14a8c0f1698e4fd1c5e33e33b6f28244741273be 100644 (file)
@@ -630,7 +630,7 @@ mpc_dma_prep_memcpy(struct dma_chan *chan, dma_addr_t dst, dma_addr_t src,
 static int __devinit mpc_dma_probe(struct of_device *op,
                                        const struct of_device_id *match)
 {
-       struct device_node *dn = op->node;
+       struct device_node *dn = op->dev.of_node;
        struct device *dev = &op->dev;
        struct dma_device *dma;
        struct mpc_dma *mdma;
@@ -771,12 +771,12 @@ static struct of_device_id mpc_dma_match[] = {
 };
 
 static struct of_platform_driver mpc_dma_driver = {
-       .match_table    = mpc_dma_match,
        .probe          = mpc_dma_probe,
        .remove         = __devexit_p(mpc_dma_remove),
-       .driver         = {
-               .name   = DRV_NAME,
-               .owner  = THIS_MODULE,
+       .driver = {
+               .name = DRV_NAME,
+               .owner = THIS_MODULE,
+               .of_match_table = mpc_dma_match,
        },
 };
 
index fa98abe4686fb06598c6f8b318e4866dff1f41be..5a22ca6927e5da6bd10b1abe04736218e0b31459 100644 (file)
@@ -4394,7 +4394,7 @@ static void ppc440spe_adma_release_irqs(struct ppc440spe_adma_device *adev,
 static int __devinit ppc440spe_adma_probe(struct of_device *ofdev,
                                          const struct of_device_id *match)
 {
-       struct device_node *np = ofdev->node;
+       struct device_node *np = ofdev->dev.of_node;
        struct resource res;
        struct ppc440spe_adma_device *adev;
        struct ppc440spe_adma_chan *chan;
@@ -4626,7 +4626,7 @@ out:
 static int __devexit ppc440spe_adma_remove(struct of_device *ofdev)
 {
        struct ppc440spe_adma_device *adev = dev_get_drvdata(&ofdev->dev);
-       struct device_node *np = ofdev->node;
+       struct device_node *np = ofdev->dev.of_node;
        struct resource res;
        struct dma_chan *chan, *_chan;
        struct ppc_dma_chan_ref *ref, *_ref;
index 6c1886b497ff673add09b99809f065c9a294090b..52ca09bf4726ae9cb5984d38c79d86705c5b51f8 100644 (file)
@@ -229,7 +229,7 @@ static int __devinit mpc85xx_pci_err_probe(struct of_device *op,
 
        pdata->edac_idx = edac_pci_idx++;
 
-       res = of_address_to_resource(op->node, 0, &r);
+       res = of_address_to_resource(op->dev.of_node, 0, &r);
        if (res) {
                printk(KERN_ERR "%s: Unable to get resource for "
                       "PCI err regs\n", __func__);
@@ -274,7 +274,7 @@ static int __devinit mpc85xx_pci_err_probe(struct of_device *op,
        }
 
        if (edac_op_state == EDAC_OPSTATE_INT) {
-               pdata->irq = irq_of_parse_and_map(op->node, 0);
+               pdata->irq = irq_of_parse_and_map(op->dev.of_node, 0);
                res = devm_request_irq(&op->dev, pdata->irq,
                                       mpc85xx_pci_isr, IRQF_DISABLED,
                                       "[EDAC] PCI err", pci);
@@ -529,7 +529,7 @@ static int __devinit mpc85xx_l2_err_probe(struct of_device *op,
        edac_dev->ctl_name = pdata->name;
        edac_dev->dev_name = pdata->name;
 
-       res = of_address_to_resource(op->node, 0, &r);
+       res = of_address_to_resource(op->dev.of_node, 0, &r);
        if (res) {
                printk(KERN_ERR "%s: Unable to get resource for "
                       "L2 err regs\n", __func__);
@@ -576,7 +576,7 @@ static int __devinit mpc85xx_l2_err_probe(struct of_device *op,
        }
 
        if (edac_op_state == EDAC_OPSTATE_INT) {
-               pdata->irq = irq_of_parse_and_map(op->node, 0);
+               pdata->irq = irq_of_parse_and_map(op->dev.of_node, 0);
                res = devm_request_irq(&op->dev, pdata->irq,
                                       mpc85xx_l2_isr, IRQF_DISABLED,
                                       "[EDAC] L2 err", edac_dev);
@@ -978,7 +978,7 @@ static int __devinit mpc85xx_mc_err_probe(struct of_device *op,
        mci->ctl_name = pdata->name;
        mci->dev_name = pdata->name;
 
-       res = of_address_to_resource(op->node, 0, &r);
+       res = of_address_to_resource(op->dev.of_node, 0, &r);
        if (res) {
                printk(KERN_ERR "%s: Unable to get resource for MC err regs\n",
                       __func__);
@@ -1052,7 +1052,7 @@ static int __devinit mpc85xx_mc_err_probe(struct of_device *op,
                out_be32(pdata->mc_vbase + MPC85XX_MC_ERR_SBE, 0x10000);
 
                /* register interrupts */
-               pdata->irq = irq_of_parse_and_map(op->node, 0);
+               pdata->irq = irq_of_parse_and_map(op->dev.of_node, 0);
                res = devm_request_irq(&op->dev, pdata->irq,
                                       mpc85xx_mc_isr,
                                        IRQF_DISABLED | IRQF_SHARED,
index 9d6f6783328c80357cb794614ff79dca1e0b84d0..e78839e89a067400726b26a302eb05f317200b02 100644 (file)
@@ -1022,7 +1022,7 @@ ppc4xx_edac_mc_init(struct mem_ctl_info *mci,
        int status = 0;
        const u32 memcheck = (mcopt1 & SDRAM_MCOPT1_MCHK_MASK);
        struct ppc4xx_edac_pdata *pdata = NULL;
-       const struct device_node *np = op->node;
+       const struct device_node *np = op->dev.of_node;
 
        if (match == NULL)
                return -EINVAL;
@@ -1113,7 +1113,7 @@ ppc4xx_edac_register_irq(struct of_device *op, struct mem_ctl_info *mci)
        int status = 0;
        int ded_irq, sec_irq;
        struct ppc4xx_edac_pdata *pdata = mci->pvt_info;
-       struct device_node *np = op->node;
+       struct device_node *np = op->dev.of_node;
 
        ded_irq = irq_of_parse_and_map(np, INTMAP_ECCDED_INDEX);
        sec_irq = irq_of_parse_and_map(np, INTMAP_ECCSEC_INDEX);
@@ -1243,7 +1243,7 @@ ppc4xx_edac_probe(struct of_device *op, const struct of_device_id *match)
        int status = 0;
        u32 mcopt1, memcheck;
        dcr_host_t dcr_host;
-       const struct device_node *np = op->node;
+       const struct device_node *np = op->dev.of_node;
        struct mem_ctl_info *mci = NULL;
        static int ppc4xx_edac_instance;
 
index 764401951041910692901ea9c1489962de3277b8..9b2a54117c91c0a306c41c7eb437b641bbd58b31 100644 (file)
@@ -860,19 +860,24 @@ static void output_poll_execute(struct slow_work *work)
        }
 }
 
-void drm_kms_helper_poll_init(struct drm_device *dev)
+void drm_kms_helper_poll_disable(struct drm_device *dev)
+{
+       if (!dev->mode_config.poll_enabled)
+               return;
+       delayed_slow_work_cancel(&dev->mode_config.output_poll_slow_work);
+}
+EXPORT_SYMBOL(drm_kms_helper_poll_disable);
+
+void drm_kms_helper_poll_enable(struct drm_device *dev)
 {
-       struct drm_connector *connector;
        bool poll = false;
+       struct drm_connector *connector;
        int ret;
 
        list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
                if (connector->polled)
                        poll = true;
        }
-       slow_work_register_user(THIS_MODULE);
-       delayed_slow_work_init(&dev->mode_config.output_poll_slow_work,
-                              &output_poll_ops);
 
        if (poll) {
                ret = delayed_slow_work_enqueue(&dev->mode_config.output_poll_slow_work, DRM_OUTPUT_POLL_PERIOD);
@@ -880,11 +885,22 @@ void drm_kms_helper_poll_init(struct drm_device *dev)
                        DRM_ERROR("delayed enqueue failed %d\n", ret);
        }
 }
+EXPORT_SYMBOL(drm_kms_helper_poll_enable);
+
+void drm_kms_helper_poll_init(struct drm_device *dev)
+{
+       slow_work_register_user(THIS_MODULE);
+       delayed_slow_work_init(&dev->mode_config.output_poll_slow_work,
+                              &output_poll_ops);
+       dev->mode_config.poll_enabled = true;
+
+       drm_kms_helper_poll_enable(dev);
+}
 EXPORT_SYMBOL(drm_kms_helper_poll_init);
 
 void drm_kms_helper_poll_fini(struct drm_device *dev)
 {
-       delayed_slow_work_cancel(&dev->mode_config.output_poll_slow_work);
+       drm_kms_helper_poll_disable(dev);
        slow_work_unregister_user(THIS_MODULE);
 }
 EXPORT_SYMBOL(drm_kms_helper_poll_fini);
index 84ce95602f00b478f5fe1ab90bdc6f7fa01276bc..b2ebf02e4f8a738a00bf9089c212db8d3fc468ee 100644 (file)
@@ -1320,12 +1320,14 @@ static void i915_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_
        struct drm_device *dev = pci_get_drvdata(pdev);
        pm_message_t pmm = { .event = PM_EVENT_SUSPEND };
        if (state == VGA_SWITCHEROO_ON) {
-               printk(KERN_INFO "i915: switched off\n");
+               printk(KERN_INFO "i915: switched on\n");
                /* i915 resume handler doesn't set to D0 */
                pci_set_power_state(dev->pdev, PCI_D0);
                i915_resume(dev);
+               drm_kms_helper_poll_enable(dev);
        } else {
                printk(KERN_ERR "i915: switched off\n");
+               drm_kms_helper_poll_disable(dev);
                i915_suspend(dev, pmm);
        }
 }
index e13f6af0037ac4dc805a821d785bf5ef541d9c07..d4bcca8a5133b2a4565b8f7d794b4d558da5557e 100644 (file)
@@ -34,7 +34,7 @@
 static struct nouveau_dsm_priv {
        bool dsm_detected;
        acpi_handle dhandle;
-       acpi_handle dsm_handle;
+       acpi_handle rom_handle;
 } nouveau_dsm_priv;
 
 static const char nouveau_dsm_muid[] = {
@@ -107,9 +107,9 @@ static int nouveau_dsm_set_discrete_state(acpi_handle handle, enum vga_switchero
 static int nouveau_dsm_switchto(enum vga_switcheroo_client_id id)
 {
        if (id == VGA_SWITCHEROO_IGD)
-               return nouveau_dsm_switch_mux(nouveau_dsm_priv.dsm_handle, NOUVEAU_DSM_LED_STAMINA);
+               return nouveau_dsm_switch_mux(nouveau_dsm_priv.dhandle, NOUVEAU_DSM_LED_STAMINA);
        else
-               return nouveau_dsm_switch_mux(nouveau_dsm_priv.dsm_handle, NOUVEAU_DSM_LED_SPEED);
+               return nouveau_dsm_switch_mux(nouveau_dsm_priv.dhandle, NOUVEAU_DSM_LED_SPEED);
 }
 
 static int nouveau_dsm_power_state(enum vga_switcheroo_client_id id,
@@ -118,7 +118,7 @@ static int nouveau_dsm_power_state(enum vga_switcheroo_client_id id,
        if (id == VGA_SWITCHEROO_IGD)
                return 0;
 
-       return nouveau_dsm_set_discrete_state(nouveau_dsm_priv.dsm_handle, state);
+       return nouveau_dsm_set_discrete_state(nouveau_dsm_priv.dhandle, state);
 }
 
 static int nouveau_dsm_init(void)
@@ -151,18 +151,18 @@ static bool nouveau_dsm_pci_probe(struct pci_dev *pdev)
        dhandle = DEVICE_ACPI_HANDLE(&pdev->dev);
        if (!dhandle)
                return false;
+
        status = acpi_get_handle(dhandle, "_DSM", &nvidia_handle);
        if (ACPI_FAILURE(status)) {
                return false;
        }
 
-       ret= nouveau_dsm(nvidia_handle, NOUVEAU_DSM_SUPPORTED,
-                        NOUVEAU_DSM_SUPPORTED_FUNCTIONS, &result);
+       ret = nouveau_dsm(dhandle, NOUVEAU_DSM_SUPPORTED,
+                         NOUVEAU_DSM_SUPPORTED_FUNCTIONS, &result);
        if (ret < 0)
                return false;
 
        nouveau_dsm_priv.dhandle = dhandle;
-       nouveau_dsm_priv.dsm_handle = nvidia_handle;
        return true;
 }
 
@@ -173,6 +173,7 @@ static bool nouveau_dsm_detect(void)
        struct pci_dev *pdev = NULL;
        int has_dsm = 0;
        int vga_count = 0;
+
        while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) {
                vga_count++;
 
@@ -180,7 +181,7 @@ static bool nouveau_dsm_detect(void)
        }
 
        if (vga_count == 2 && has_dsm) {
-               acpi_get_name(nouveau_dsm_priv.dsm_handle, ACPI_FULL_PATHNAME, &buffer);
+               acpi_get_name(nouveau_dsm_priv.dhandle, ACPI_FULL_PATHNAME, &buffer);
                printk(KERN_INFO "VGA switcheroo: detected DSM switching method %s handle\n",
                       acpi_method_name);
                nouveau_dsm_priv.dsm_detected = true;
@@ -204,3 +205,57 @@ void nouveau_unregister_dsm_handler(void)
 {
        vga_switcheroo_unregister_handler();
 }
+
+/* retrieve the ROM in 4k blocks */
+static int nouveau_rom_call(acpi_handle rom_handle, uint8_t *bios,
+                           int offset, int len)
+{
+       acpi_status status;
+       union acpi_object rom_arg_elements[2], *obj;
+       struct acpi_object_list rom_arg;
+       struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL};
+
+       rom_arg.count = 2;
+       rom_arg.pointer = &rom_arg_elements[0];
+
+       rom_arg_elements[0].type = ACPI_TYPE_INTEGER;
+       rom_arg_elements[0].integer.value = offset;
+
+       rom_arg_elements[1].type = ACPI_TYPE_INTEGER;
+       rom_arg_elements[1].integer.value = len;
+
+       status = acpi_evaluate_object(rom_handle, NULL, &rom_arg, &buffer);
+       if (ACPI_FAILURE(status)) {
+               printk(KERN_INFO "failed to evaluate ROM got %s\n", acpi_format_exception(status));
+               return -ENODEV;
+       }
+       obj = (union acpi_object *)buffer.pointer;
+       memcpy(bios+offset, obj->buffer.pointer, len);
+       kfree(buffer.pointer);
+       return len;
+}
+
+bool nouveau_acpi_rom_supported(struct pci_dev *pdev)
+{
+       acpi_status status;
+       acpi_handle dhandle, rom_handle;
+
+       if (!nouveau_dsm_priv.dsm_detected)
+               return false;
+
+       dhandle = DEVICE_ACPI_HANDLE(&pdev->dev);
+       if (!dhandle)
+               return false;
+
+       status = acpi_get_handle(dhandle, "_ROM", &rom_handle);
+       if (ACPI_FAILURE(status))
+               return false;
+
+       nouveau_dsm_priv.rom_handle = rom_handle;
+       return true;
+}
+
+int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len)
+{
+       return nouveau_rom_call(nouveau_dsm_priv.rom_handle, bios, offset, len);
+}
index e7e69ccce5c9985ba77b7e7790582f984c8efdb9..9ba2deaadcc7d38b833ff63fc99f4b76cc144ac1 100644 (file)
@@ -178,6 +178,25 @@ out:
        pci_disable_rom(dev->pdev);
 }
 
+static void load_vbios_acpi(struct drm_device *dev, uint8_t *data)
+{
+       int i;
+       int ret;
+       int size = 64 * 1024;
+
+       if (!nouveau_acpi_rom_supported(dev->pdev))
+               return;
+
+       for (i = 0; i < (size / ROM_BIOS_PAGE); i++) {
+               ret = nouveau_acpi_get_bios_chunk(data,
+                                                 (i * ROM_BIOS_PAGE),
+                                                 ROM_BIOS_PAGE);
+               if (ret <= 0)
+                       break;
+       }
+       return;
+}
+
 struct methods {
        const char desc[8];
        void (*loadbios)(struct drm_device *, uint8_t *);
@@ -191,6 +210,7 @@ static struct methods nv04_methods[] = {
 };
 
 static struct methods nv50_methods[] = {
+       { "ACPI", load_vbios_acpi, true },
        { "PRAMIN", load_vbios_pramin, true },
        { "PROM", load_vbios_prom, false },
        { "PCIROM", load_vbios_pci, true },
@@ -2807,7 +2827,10 @@ init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 
                BIOSLOG(bios, "0x%04X: Entry: 0x%08X\n", offset, gpio->entry);
 
-               nv50_gpio_set(bios->dev, gpio->tag, gpio->state_default);
+               BIOSLOG(bios, "0x%04X: set gpio 0x%02x, state %d\n",
+                       offset, gpio->tag, gpio->state_default);
+               if (bios->execute)
+                       nv50_gpio_set(bios->dev, gpio->tag, gpio->state_default);
 
                /* The NVIDIA binary driver doesn't appear to actually do
                 * any of this, my VBIOS does however.
@@ -5533,12 +5556,6 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb,
        entry->bus = (conn >> 16) & 0xf;
        entry->location = (conn >> 20) & 0x3;
        entry->or = (conn >> 24) & 0xf;
-       /*
-        * Normal entries consist of a single bit, but dual link has the
-        * next most significant bit set too
-        */
-       entry->duallink_possible =
-                       ((1 << (ffs(entry->or) - 1)) * 3 == entry->or);
 
        switch (entry->type) {
        case OUTPUT_ANALOG:
@@ -5622,6 +5639,16 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb,
                break;
        }
 
+       if (dcb->version < 0x40) {
+               /* Normal entries consist of a single bit, but dual link has
+                * the next most significant bit set too
+                */
+               entry->duallink_possible =
+                       ((1 << (ffs(entry->or) - 1)) * 3 == entry->or);
+       } else {
+               entry->duallink_possible = (entry->sorconf.link == 3);
+       }
+
        /* unsure what DCB version introduces this, 3.0? */
        if (conf & 0x100000)
                entry->i2c_upper_default = true;
@@ -6205,6 +6232,30 @@ nouveau_bios_i2c_devices_takedown(struct drm_device *dev)
                nouveau_i2c_fini(dev, entry);
 }
 
+static bool
+nouveau_bios_posted(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       bool was_locked;
+       unsigned htotal;
+
+       if (dev_priv->chipset >= NV_50) {
+               if (NVReadVgaCrtc(dev, 0, 0x00) == 0 &&
+                   NVReadVgaCrtc(dev, 0, 0x1a) == 0)
+                       return false;
+               return true;
+       }
+
+       was_locked = NVLockVgaCrtcs(dev, false);
+       htotal  = NVReadVgaCrtc(dev, 0, 0x06);
+       htotal |= (NVReadVgaCrtc(dev, 0, 0x07) & 0x01) << 8;
+       htotal |= (NVReadVgaCrtc(dev, 0, 0x07) & 0x20) << 4;
+       htotal |= (NVReadVgaCrtc(dev, 0, 0x25) & 0x01) << 10;
+       htotal |= (NVReadVgaCrtc(dev, 0, 0x41) & 0x01) << 11;
+       NVLockVgaCrtcs(dev, was_locked);
+       return (htotal != 0);
+}
+
 int
 nouveau_bios_init(struct drm_device *dev)
 {
@@ -6239,11 +6290,9 @@ nouveau_bios_init(struct drm_device *dev)
        bios->execute = false;
 
        /* ... unless card isn't POSTed already */
-       if (dev_priv->card_type >= NV_10 &&
-           NVReadVgaCrtc(dev, 0, 0x00) == 0 &&
-           NVReadVgaCrtc(dev, 0, 0x1a) == 0) {
+       if (!nouveau_bios_posted(dev)) {
                NV_INFO(dev, "Adaptor not initialised\n");
-               if (dev_priv->card_type < NV_50) {
+               if (dev_priv->card_type < NV_40) {
                        NV_ERROR(dev, "Unable to POST this chipset\n");
                        return -ENODEV;
                }
index 266b0ff441af37b75ee555360bdcd68ce1cd881f..149ed224c3cb48c86c56e2f4b9bb18a599190d10 100644 (file)
@@ -432,24 +432,27 @@ nouveau_connector_set_property(struct drm_connector *connector,
 }
 
 static struct drm_display_mode *
-nouveau_connector_native_mode(struct nouveau_connector *connector)
+nouveau_connector_native_mode(struct drm_connector *connector)
 {
-       struct drm_device *dev = connector->base.dev;
+       struct drm_connector_helper_funcs *helper = connector->helper_private;
+       struct nouveau_connector *nv_connector = nouveau_connector(connector);
+       struct drm_device *dev = connector->dev;
        struct drm_display_mode *mode, *largest = NULL;
        int high_w = 0, high_h = 0, high_v = 0;
 
-       /* Use preferred mode if there is one.. */
-       list_for_each_entry(mode, &connector->base.probed_modes, head) {
+       list_for_each_entry(mode, &nv_connector->base.probed_modes, head) {
+               if (helper->mode_valid(connector, mode) != MODE_OK)
+                       continue;
+
+               /* Use preferred mode if there is one.. */
                if (mode->type & DRM_MODE_TYPE_PREFERRED) {
                        NV_DEBUG_KMS(dev, "native mode from preferred\n");
                        return drm_mode_duplicate(dev, mode);
                }
-       }
 
-       /* Otherwise, take the resolution with the largest width, then height,
-        * then vertical refresh
-        */
-       list_for_each_entry(mode, &connector->base.probed_modes, head) {
+               /* Otherwise, take the resolution with the largest width, then
+                * height, then vertical refresh
+                */
                if (mode->hdisplay < high_w)
                        continue;
 
@@ -553,7 +556,7 @@ nouveau_connector_get_modes(struct drm_connector *connector)
         */
        if (!nv_connector->native_mode)
                nv_connector->native_mode =
-                       nouveau_connector_native_mode(nv_connector);
+                       nouveau_connector_native_mode(connector);
        if (ret == 0 && nv_connector->native_mode) {
                struct drm_display_mode *mode;
 
@@ -584,9 +587,9 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
 
        switch (nv_encoder->dcb->type) {
        case OUTPUT_LVDS:
-               BUG_ON(!nv_connector->native_mode);
-               if (mode->hdisplay > nv_connector->native_mode->hdisplay ||
-                   mode->vdisplay > nv_connector->native_mode->vdisplay)
+               if (nv_connector->native_mode &&
+                   (mode->hdisplay > nv_connector->native_mode->hdisplay ||
+                    mode->vdisplay > nv_connector->native_mode->vdisplay))
                        return MODE_PANEL;
 
                min_clock = 0;
@@ -594,8 +597,7 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
                break;
        case OUTPUT_TMDS:
                if ((dev_priv->card_type >= NV_50 && !nouveau_duallink) ||
-                   (dev_priv->card_type < NV_50 &&
-                    !nv_encoder->dcb->duallink_possible))
+                   !nv_encoder->dcb->duallink_possible)
                        max_clock = 165000;
                else
                        max_clock = 330000;
@@ -729,7 +731,7 @@ nouveau_connector_create_lvds(struct drm_device *dev,
        if (ret == 0)
                goto out;
        nv_connector->detected_encoder = nv_encoder;
-       nv_connector->native_mode = nouveau_connector_native_mode(nv_connector);
+       nv_connector->native_mode = nouveau_connector_native_mode(connector);
        list_for_each_entry_safe(mode, temp, &connector->probed_modes, head)
                drm_mode_remove(connector, mode);
 
index 49fa7b2d257e8e739391720ffaf66e8eea86ee45..cb1ce2a0916257ecbbe8ea72949baa8a80b32c56 100644 (file)
@@ -40,6 +40,8 @@ struct nouveau_crtc {
        int sharpness;
        int last_dpms;
 
+       int cursor_saved_x, cursor_saved_y;
+
        struct {
                int cpp;
                bool blanked;
index c6079e36669d9f43893db8ad88623dbb70b6147c..273770432298b72ae5687505e156fe5b03e0e4e4 100644 (file)
@@ -175,6 +175,13 @@ nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state)
                nouveau_bo_unpin(nouveau_fb->nvbo);
        }
 
+       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+               struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+
+               nouveau_bo_unmap(nv_crtc->cursor.nvbo);
+               nouveau_bo_unpin(nv_crtc->cursor.nvbo);
+       }
+
        NV_INFO(dev, "Evicting buffers...\n");
        ttm_bo_evict_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM);
 
@@ -314,12 +321,34 @@ nouveau_pci_resume(struct pci_dev *pdev)
                nouveau_bo_pin(nouveau_fb->nvbo, TTM_PL_FLAG_VRAM);
        }
 
+       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+               struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+               int ret;
+
+               ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM);
+               if (!ret)
+                       ret = nouveau_bo_map(nv_crtc->cursor.nvbo);
+               if (ret)
+                       NV_ERROR(dev, "Could not pin/map cursor.\n");
+       }
+
        if (dev_priv->card_type < NV_50) {
                nv04_display_restore(dev);
                NVLockVgaCrtcs(dev, false);
        } else
                nv50_display_init(dev);
 
+       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+               struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+
+               nv_crtc->cursor.set_offset(nv_crtc,
+                                       nv_crtc->cursor.nvbo->bo.offset -
+                                       dev_priv->vm_vram_base);
+
+               nv_crtc->cursor.set_pos(nv_crtc, nv_crtc->cursor_saved_x,
+                       nv_crtc->cursor_saved_y);
+       }
+
        /* Force CLUT to get re-loaded during modeset */
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
                struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
index 5b134438effebcda05e2fbb8c4a74581f6148bcc..c697191064894345efbbf76bf3bfd1fc83188270 100644 (file)
@@ -851,12 +851,17 @@ extern int  nouveau_dma_init(struct nouveau_channel *);
 extern int  nouveau_dma_wait(struct nouveau_channel *, int slots, int size);
 
 /* nouveau_acpi.c */
+#define ROM_BIOS_PAGE 4096
 #if defined(CONFIG_ACPI)
 void nouveau_register_dsm_handler(void);
 void nouveau_unregister_dsm_handler(void);
+int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len);
+bool nouveau_acpi_rom_supported(struct pci_dev *pdev);
 #else
 static inline void nouveau_register_dsm_handler(void) {}
 static inline void nouveau_unregister_dsm_handler(void) {}
+static inline bool nouveau_acpi_rom_supported(struct pci_dev *pdev) { return false; }
+static inline int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len) { return -EINVAL; }
 #endif
 
 /* nouveau_backlight.c */
index 775a7017af6437da7c149dfda2a04d172704fdb2..c1fd42b0dad19cb18e34463548c8ff4b60093747 100644 (file)
@@ -540,7 +540,8 @@ nouveau_mem_detect(struct drm_device *dev)
                dev_priv->vram_size  = nv_rd32(dev, NV04_FIFO_DATA);
                dev_priv->vram_size &= NV10_FIFO_DATA_RAM_AMOUNT_MB_MASK;
                if (dev_priv->chipset == 0xaa || dev_priv->chipset == 0xac)
-                       dev_priv->vram_sys_base = nv_rd32(dev, 0x100e10) << 12;
+                       dev_priv->vram_sys_base = nv_rd32(dev, 0x100e10);
+                       dev_priv->vram_sys_base <<= 12;
        }
 
        NV_INFO(dev, "Detected %dMiB VRAM\n", (int)(dev_priv->vram_size >> 20));
index e632339c323e5bd03efe592f554875117322b7b1..147e59c4015148e4b645648346b2e959370d3dcf 100644 (file)
@@ -376,12 +376,15 @@ out_err:
 static void nouveau_switcheroo_set_state(struct pci_dev *pdev,
                                         enum vga_switcheroo_state state)
 {
+       struct drm_device *dev = pci_get_drvdata(pdev);
        pm_message_t pmm = { .event = PM_EVENT_SUSPEND };
        if (state == VGA_SWITCHEROO_ON) {
                printk(KERN_ERR "VGA switcheroo: switched nouveau on\n");
                nouveau_pci_resume(pdev);
+               drm_kms_helper_poll_enable(dev);
        } else {
                printk(KERN_ERR "VGA switcheroo: switched nouveau off\n");
+               drm_kms_helper_poll_disable(dev);
                nouveau_pci_suspend(pdev, pmm);
        }
 }
@@ -913,6 +916,9 @@ int nouveau_ioctl_getparam(struct drm_device *dev, void *data,
        case NOUVEAU_GETPARAM_VM_VRAM_BASE:
                getparam->value = dev_priv->vm_vram_base;
                break;
+       case NOUVEAU_GETPARAM_PTIMER_TIME:
+               getparam->value = dev_priv->engine.timer.read(dev);
+               break;
        case NOUVEAU_GETPARAM_GRAPH_UNITS:
                /* NV40 and NV50 versions are quite different, but register
                 * address is the same. User is supposed to know the card
index 89a91b9d8b258d54e24c2b3725727824c7a18df0..aaf3de3bc816c5e0d9e1d34fcd4847fa2fa3e5db 100644 (file)
@@ -20,6 +20,7 @@ nv04_cursor_hide(struct nouveau_crtc *nv_crtc, bool update)
 static void
 nv04_cursor_set_pos(struct nouveau_crtc *nv_crtc, int x, int y)
 {
+       nv_crtc->cursor_saved_x = x; nv_crtc->cursor_saved_y = y;
        NVWriteRAMDAC(nv_crtc->base.dev, nv_crtc->index,
                      NV_PRAMDAC_CU_START_POS,
                      XLATE(y, 0, NV_PRAMDAC_CU_START_POS_Y) |
index 753e723adb3afb9e0dc733d4ef416a4468b3aacc..03ad7ab14f0960e1729674cd637a15ff325ae169 100644 (file)
@@ -107,6 +107,7 @@ nv50_cursor_set_pos(struct nouveau_crtc *nv_crtc, int x, int y)
 {
        struct drm_device *dev = nv_crtc->base.dev;
 
+       nv_crtc->cursor_saved_x = x; nv_crtc->cursor_saved_y = y;
        nv_wr32(dev, NV50_PDISPLAY_CURSOR_USER_POS(nv_crtc->index),
                ((y & 0xFFFF) << 16) | (x & 0xFFFF));
        /* Needed to make the cursor move. */
index b11eaf9c5c7cd0575eec63e20d7217b7c8fd49c1..812778db76ac185b5943a8257ae401ff82f27202 100644 (file)
@@ -274,7 +274,6 @@ static const struct drm_encoder_funcs nv50_sor_encoder_funcs = {
 int
 nv50_sor_create(struct drm_device *dev, struct dcb_entry *entry)
 {
-       struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nouveau_encoder *nv_encoder = NULL;
        struct drm_encoder *encoder;
        bool dum;
@@ -324,11 +323,7 @@ nv50_sor_create(struct drm_device *dev, struct dcb_entry *entry)
                int or = nv_encoder->or, link = !(entry->dpconf.sor.link & 1);
                uint32_t tmp;
 
-               if (dev_priv->chipset < 0x90 ||
-                   dev_priv->chipset == 0x92 || dev_priv->chipset == 0xa0)
-                       tmp = nv_rd32(dev, NV50_PDISPLAY_SOR_MODE_CTRL_C(or));
-               else
-                       tmp = nv_rd32(dev, NV90_PDISPLAY_SOR_MODE_CTRL_C(or));
+               tmp = nv_rd32(dev, 0x61c700 + (or * 0x800));
 
                switch ((tmp & 0x00000f00) >> 8) {
                case 8:
index 3c91312dea9a00d8aa93b097d2d5d476487fb2d8..84b1f2729d430deaddcf6e4241a1886339c0123b 100644 (file)
@@ -33,6 +33,9 @@ $(obj)/rs600_reg_safe.h: $(src)/reg_srcs/rs600 $(obj)/mkregtable
 $(obj)/r600_reg_safe.h: $(src)/reg_srcs/r600 $(obj)/mkregtable
        $(call if_changed,mkregtable)
 
+$(obj)/evergreen_reg_safe.h: $(src)/reg_srcs/evergreen $(obj)/mkregtable
+       $(call if_changed,mkregtable)
+
 $(obj)/r100.o: $(obj)/r100_reg_safe.h $(obj)/rn50_reg_safe.h
 
 $(obj)/r200.o: $(obj)/r200_reg_safe.h
@@ -47,6 +50,8 @@ $(obj)/rs600.o: $(obj)/rs600_reg_safe.h
 
 $(obj)/r600_cs.o: $(obj)/r600_reg_safe.h
 
+$(obj)/evergreen_cs.o: $(obj)/evergreen_reg_safe.h
+
 radeon-y := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o \
        radeon_irq.o r300_cmdbuf.o r600_cp.o
 # add KMS driver
@@ -60,7 +65,7 @@ radeon-y += radeon_device.o radeon_asic.o radeon_kms.o \
        rs400.o rs600.o rs690.o rv515.o r520.o r600.o rv770.o radeon_test.o \
        r200.o radeon_legacy_tv.o r600_cs.o r600_blit.o r600_blit_shaders.o \
        r600_blit_kms.o radeon_pm.o atombios_dp.o r600_audio.o r600_hdmi.o \
-       evergreen.o
+       evergreen.o evergreen_cs.o
 
 radeon-$(CONFIG_COMPAT) += radeon_ioc32.o
 radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o
index 8c8e4d3cbaa377773d9fc39b5035a928f93ddf55..0440c0939bdd00e4efc71f09b0b02de16b3788da 100644 (file)
@@ -41,7 +41,12 @@ void evergreen_fini(struct radeon_device *rdev);
 
 void evergreen_pm_misc(struct radeon_device *rdev)
 {
+       int requested_index = rdev->pm.requested_power_state_index;
+       struct radeon_power_state *ps = &rdev->pm.power_state[requested_index];
+       struct radeon_voltage *voltage = &ps->clock_info[0].voltage;
 
+       if ((voltage->type == VOLTAGE_SW) && voltage->voltage)
+               radeon_atom_set_voltage(rdev, voltage->voltage);
 }
 
 void evergreen_pm_prepare(struct radeon_device *rdev)
diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c
new file mode 100644 (file)
index 0000000..64516b9
--- /dev/null
@@ -0,0 +1,1356 @@
+/*
+ * Copyright 2010 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Jerome Glisse.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ *          Jerome Glisse
+ */
+#include "drmP.h"
+#include "radeon.h"
+#include "evergreend.h"
+#include "evergreen_reg_safe.h"
+
+static int evergreen_cs_packet_next_reloc(struct radeon_cs_parser *p,
+                                         struct radeon_cs_reloc **cs_reloc);
+
+struct evergreen_cs_track {
+       u32                     group_size;
+       u32                     nbanks;
+       u32                     npipes;
+       /* value we track */
+       u32                     nsamples;
+       u32                     cb_color_base_last[12];
+       struct radeon_bo        *cb_color_bo[12];
+       u32                     cb_color_bo_offset[12];
+       struct radeon_bo        *cb_color_fmask_bo[8];
+       struct radeon_bo        *cb_color_cmask_bo[8];
+       u32                     cb_color_info[12];
+       u32                     cb_color_view[12];
+       u32                     cb_color_pitch_idx[12];
+       u32                     cb_color_slice_idx[12];
+       u32                     cb_color_dim_idx[12];
+       u32                     cb_color_dim[12];
+       u32                     cb_color_pitch[12];
+       u32                     cb_color_slice[12];
+       u32                     cb_color_cmask_slice[8];
+       u32                     cb_color_fmask_slice[8];
+       u32                     cb_target_mask;
+       u32                     cb_shader_mask;
+       u32                     vgt_strmout_config;
+       u32                     vgt_strmout_buffer_config;
+       u32                     db_depth_control;
+       u32                     db_depth_view;
+       u32                     db_depth_size;
+       u32                     db_depth_size_idx;
+       u32                     db_z_info;
+       u32                     db_z_idx;
+       u32                     db_z_read_offset;
+       u32                     db_z_write_offset;
+       struct radeon_bo        *db_z_read_bo;
+       struct radeon_bo        *db_z_write_bo;
+       u32                     db_s_info;
+       u32                     db_s_idx;
+       u32                     db_s_read_offset;
+       u32                     db_s_write_offset;
+       struct radeon_bo        *db_s_read_bo;
+       struct radeon_bo        *db_s_write_bo;
+};
+
+static void evergreen_cs_track_init(struct evergreen_cs_track *track)
+{
+       int i;
+
+       for (i = 0; i < 8; i++) {
+               track->cb_color_fmask_bo[i] = NULL;
+               track->cb_color_cmask_bo[i] = NULL;
+               track->cb_color_cmask_slice[i] = 0;
+               track->cb_color_fmask_slice[i] = 0;
+       }
+
+       for (i = 0; i < 12; i++) {
+               track->cb_color_base_last[i] = 0;
+               track->cb_color_bo[i] = NULL;
+               track->cb_color_bo_offset[i] = 0xFFFFFFFF;
+               track->cb_color_info[i] = 0;
+               track->cb_color_view[i] = 0;
+               track->cb_color_pitch_idx[i] = 0;
+               track->cb_color_slice_idx[i] = 0;
+               track->cb_color_dim[i] = 0;
+               track->cb_color_pitch[i] = 0;
+               track->cb_color_slice[i] = 0;
+               track->cb_color_dim[i] = 0;
+       }
+       track->cb_target_mask = 0xFFFFFFFF;
+       track->cb_shader_mask = 0xFFFFFFFF;
+
+       track->db_depth_view = 0xFFFFC000;
+       track->db_depth_size = 0xFFFFFFFF;
+       track->db_depth_size_idx = 0;
+       track->db_depth_control = 0xFFFFFFFF;
+       track->db_z_info = 0xFFFFFFFF;
+       track->db_z_idx = 0xFFFFFFFF;
+       track->db_z_read_offset = 0xFFFFFFFF;
+       track->db_z_write_offset = 0xFFFFFFFF;
+       track->db_z_read_bo = NULL;
+       track->db_z_write_bo = NULL;
+       track->db_s_info = 0xFFFFFFFF;
+       track->db_s_idx = 0xFFFFFFFF;
+       track->db_s_read_offset = 0xFFFFFFFF;
+       track->db_s_write_offset = 0xFFFFFFFF;
+       track->db_s_read_bo = NULL;
+       track->db_s_write_bo = NULL;
+}
+
+static inline int evergreen_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
+{
+       /* XXX fill in */
+       return 0;
+}
+
+static int evergreen_cs_track_check(struct radeon_cs_parser *p)
+{
+       struct evergreen_cs_track *track = p->track;
+
+       /* we don't support stream out buffer yet */
+       if (track->vgt_strmout_config || track->vgt_strmout_buffer_config) {
+               dev_warn(p->dev, "this kernel doesn't support SMX output buffer\n");
+               return -EINVAL;
+       }
+
+       /* XXX fill in */
+       return 0;
+}
+
+/**
+ * evergreen_cs_packet_parse() - parse cp packet and point ib index to next packet
+ * @parser:    parser structure holding parsing context.
+ * @pkt:       where to store packet informations
+ *
+ * Assume that chunk_ib_index is properly set. Will return -EINVAL
+ * if packet is bigger than remaining ib size. or if packets is unknown.
+ **/
+int evergreen_cs_packet_parse(struct radeon_cs_parser *p,
+                             struct radeon_cs_packet *pkt,
+                             unsigned idx)
+{
+       struct radeon_cs_chunk *ib_chunk = &p->chunks[p->chunk_ib_idx];
+       uint32_t header;
+
+       if (idx >= ib_chunk->length_dw) {
+               DRM_ERROR("Can not parse packet at %d after CS end %d !\n",
+                         idx, ib_chunk->length_dw);
+               return -EINVAL;
+       }
+       header = radeon_get_ib_value(p, idx);
+       pkt->idx = idx;
+       pkt->type = CP_PACKET_GET_TYPE(header);
+       pkt->count = CP_PACKET_GET_COUNT(header);
+       pkt->one_reg_wr = 0;
+       switch (pkt->type) {
+       case PACKET_TYPE0:
+               pkt->reg = CP_PACKET0_GET_REG(header);
+               break;
+       case PACKET_TYPE3:
+               pkt->opcode = CP_PACKET3_GET_OPCODE(header);
+               break;
+       case PACKET_TYPE2:
+               pkt->count = -1;
+               break;
+       default:
+               DRM_ERROR("Unknown packet type %d at %d !\n", pkt->type, idx);
+               return -EINVAL;
+       }
+       if ((pkt->count + 1 + pkt->idx) >= ib_chunk->length_dw) {
+               DRM_ERROR("Packet (%d:%d:%d) end after CS buffer (%d) !\n",
+                         pkt->idx, pkt->type, pkt->count, ib_chunk->length_dw);
+               return -EINVAL;
+       }
+       return 0;
+}
+
+/**
+ * evergreen_cs_packet_next_reloc() - parse next packet which should be reloc packet3
+ * @parser:            parser structure holding parsing context.
+ * @data:              pointer to relocation data
+ * @offset_start:      starting offset
+ * @offset_mask:       offset mask (to align start offset on)
+ * @reloc:             reloc informations
+ *
+ * Check next packet is relocation packet3, do bo validation and compute
+ * GPU offset using the provided start.
+ **/
+static int evergreen_cs_packet_next_reloc(struct radeon_cs_parser *p,
+                                         struct radeon_cs_reloc **cs_reloc)
+{
+       struct radeon_cs_chunk *relocs_chunk;
+       struct radeon_cs_packet p3reloc;
+       unsigned idx;
+       int r;
+
+       if (p->chunk_relocs_idx == -1) {
+               DRM_ERROR("No relocation chunk !\n");
+               return -EINVAL;
+       }
+       *cs_reloc = NULL;
+       relocs_chunk = &p->chunks[p->chunk_relocs_idx];
+       r = evergreen_cs_packet_parse(p, &p3reloc, p->idx);
+       if (r) {
+               return r;
+       }
+       p->idx += p3reloc.count + 2;
+       if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) {
+               DRM_ERROR("No packet3 for relocation for packet at %d.\n",
+                         p3reloc.idx);
+               return -EINVAL;
+       }
+       idx = radeon_get_ib_value(p, p3reloc.idx + 1);
+       if (idx >= relocs_chunk->length_dw) {
+               DRM_ERROR("Relocs at %d after relocations chunk end %d !\n",
+                         idx, relocs_chunk->length_dw);
+               return -EINVAL;
+       }
+       /* FIXME: we assume reloc size is 4 dwords */
+       *cs_reloc = p->relocs_ptr[(idx / 4)];
+       return 0;
+}
+
+/**
+ * evergreen_cs_packet_next_is_pkt3_nop() - test if next packet is packet3 nop for reloc
+ * @parser:            parser structure holding parsing context.
+ *
+ * Check next packet is relocation packet3, do bo validation and compute
+ * GPU offset using the provided start.
+ **/
+static inline int evergreen_cs_packet_next_is_pkt3_nop(struct radeon_cs_parser *p)
+{
+       struct radeon_cs_packet p3reloc;
+       int r;
+
+       r = evergreen_cs_packet_parse(p, &p3reloc, p->idx);
+       if (r) {
+               return 0;
+       }
+       if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) {
+               return 0;
+       }
+       return 1;
+}
+
+/**
+ * evergreen_cs_packet_next_vline() - parse userspace VLINE packet
+ * @parser:            parser structure holding parsing context.
+ *
+ * Userspace sends a special sequence for VLINE waits.
+ * PACKET0 - VLINE_START_END + value
+ * PACKET3 - WAIT_REG_MEM poll vline status reg
+ * RELOC (P3) - crtc_id in reloc.
+ *
+ * This function parses this and relocates the VLINE START END
+ * and WAIT_REG_MEM packets to the correct crtc.
+ * It also detects a switched off crtc and nulls out the
+ * wait in that case.
+ */
+static int evergreen_cs_packet_parse_vline(struct radeon_cs_parser *p)
+{
+       struct drm_mode_object *obj;
+       struct drm_crtc *crtc;
+       struct radeon_crtc *radeon_crtc;
+       struct radeon_cs_packet p3reloc, wait_reg_mem;
+       int crtc_id;
+       int r;
+       uint32_t header, h_idx, reg, wait_reg_mem_info;
+       volatile uint32_t *ib;
+
+       ib = p->ib->ptr;
+
+       /* parse the WAIT_REG_MEM */
+       r = evergreen_cs_packet_parse(p, &wait_reg_mem, p->idx);
+       if (r)
+               return r;
+
+       /* check its a WAIT_REG_MEM */
+       if (wait_reg_mem.type != PACKET_TYPE3 ||
+           wait_reg_mem.opcode != PACKET3_WAIT_REG_MEM) {
+               DRM_ERROR("vline wait missing WAIT_REG_MEM segment\n");
+               r = -EINVAL;
+               return r;
+       }
+
+       wait_reg_mem_info = radeon_get_ib_value(p, wait_reg_mem.idx + 1);
+       /* bit 4 is reg (0) or mem (1) */
+       if (wait_reg_mem_info & 0x10) {
+               DRM_ERROR("vline WAIT_REG_MEM waiting on MEM rather than REG\n");
+               r = -EINVAL;
+               return r;
+       }
+       /* waiting for value to be equal */
+       if ((wait_reg_mem_info & 0x7) != 0x3) {
+               DRM_ERROR("vline WAIT_REG_MEM function not equal\n");
+               r = -EINVAL;
+               return r;
+       }
+       if ((radeon_get_ib_value(p, wait_reg_mem.idx + 2) << 2) != EVERGREEN_VLINE_STATUS) {
+               DRM_ERROR("vline WAIT_REG_MEM bad reg\n");
+               r = -EINVAL;
+               return r;
+       }
+
+       if (radeon_get_ib_value(p, wait_reg_mem.idx + 5) != EVERGREEN_VLINE_STAT) {
+               DRM_ERROR("vline WAIT_REG_MEM bad bit mask\n");
+               r = -EINVAL;
+               return r;
+       }
+
+       /* jump over the NOP */
+       r = evergreen_cs_packet_parse(p, &p3reloc, p->idx + wait_reg_mem.count + 2);
+       if (r)
+               return r;
+
+       h_idx = p->idx - 2;
+       p->idx += wait_reg_mem.count + 2;
+       p->idx += p3reloc.count + 2;
+
+       header = radeon_get_ib_value(p, h_idx);
+       crtc_id = radeon_get_ib_value(p, h_idx + 2 + 7 + 1);
+       reg = CP_PACKET0_GET_REG(header);
+       mutex_lock(&p->rdev->ddev->mode_config.mutex);
+       obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC);
+       if (!obj) {
+               DRM_ERROR("cannot find crtc %d\n", crtc_id);
+               r = -EINVAL;
+               goto out;
+       }
+       crtc = obj_to_crtc(obj);
+       radeon_crtc = to_radeon_crtc(crtc);
+       crtc_id = radeon_crtc->crtc_id;
+
+       if (!crtc->enabled) {
+               /* if the CRTC isn't enabled - we need to nop out the WAIT_REG_MEM */
+               ib[h_idx + 2] = PACKET2(0);
+               ib[h_idx + 3] = PACKET2(0);
+               ib[h_idx + 4] = PACKET2(0);
+               ib[h_idx + 5] = PACKET2(0);
+               ib[h_idx + 6] = PACKET2(0);
+               ib[h_idx + 7] = PACKET2(0);
+               ib[h_idx + 8] = PACKET2(0);
+       } else {
+               switch (reg) {
+               case EVERGREEN_VLINE_START_END:
+                       header &= ~R600_CP_PACKET0_REG_MASK;
+                       header |= (EVERGREEN_VLINE_START_END + radeon_crtc->crtc_offset) >> 2;
+                       ib[h_idx] = header;
+                       ib[h_idx + 4] = (EVERGREEN_VLINE_STATUS + radeon_crtc->crtc_offset) >> 2;
+                       break;
+               default:
+                       DRM_ERROR("unknown crtc reloc\n");
+                       r = -EINVAL;
+                       goto out;
+               }
+       }
+out:
+       mutex_unlock(&p->rdev->ddev->mode_config.mutex);
+       return r;
+}
+
+static int evergreen_packet0_check(struct radeon_cs_parser *p,
+                                  struct radeon_cs_packet *pkt,
+                                  unsigned idx, unsigned reg)
+{
+       int r;
+
+       switch (reg) {
+       case EVERGREEN_VLINE_START_END:
+               r = evergreen_cs_packet_parse_vline(p);
+               if (r) {
+                       DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
+                                       idx, reg);
+                       return r;
+               }
+               break;
+       default:
+               printk(KERN_ERR "Forbidden register 0x%04X in cs at %d\n",
+                      reg, idx);
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int evergreen_cs_parse_packet0(struct radeon_cs_parser *p,
+                                     struct radeon_cs_packet *pkt)
+{
+       unsigned reg, i;
+       unsigned idx;
+       int r;
+
+       idx = pkt->idx + 1;
+       reg = pkt->reg;
+       for (i = 0; i <= pkt->count; i++, idx++, reg += 4) {
+               r = evergreen_packet0_check(p, pkt, idx, reg);
+               if (r) {
+                       return r;
+               }
+       }
+       return 0;
+}
+
+/**
+ * evergreen_cs_check_reg() - check if register is authorized or not
+ * @parser: parser structure holding parsing context
+ * @reg: register we are testing
+ * @idx: index into the cs buffer
+ *
+ * This function will test against evergreen_reg_safe_bm and return 0
+ * if register is safe. If register is not flag as safe this function
+ * will test it against a list of register needind special handling.
+ */
+static inline int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
+{
+       struct evergreen_cs_track *track = (struct evergreen_cs_track *)p->track;
+       struct radeon_cs_reloc *reloc;
+       u32 last_reg = ARRAY_SIZE(evergreen_reg_safe_bm);
+       u32 m, i, tmp, *ib;
+       int r;
+
+       i = (reg >> 7);
+       if (i > last_reg) {
+               dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
+               return -EINVAL;
+       }
+       m = 1 << ((reg >> 2) & 31);
+       if (!(evergreen_reg_safe_bm[i] & m))
+               return 0;
+       ib = p->ib->ptr;
+       switch (reg) {
+       /* force following reg to 0 in an attemp to disable out buffer
+        * which will need us to better understand how it works to perform
+        * security check on it (Jerome)
+        */
+       case SQ_ESGS_RING_SIZE:
+       case SQ_GSVS_RING_SIZE:
+       case SQ_ESTMP_RING_SIZE:
+       case SQ_GSTMP_RING_SIZE:
+       case SQ_HSTMP_RING_SIZE:
+       case SQ_LSTMP_RING_SIZE:
+       case SQ_PSTMP_RING_SIZE:
+       case SQ_VSTMP_RING_SIZE:
+       case SQ_ESGS_RING_ITEMSIZE:
+       case SQ_ESTMP_RING_ITEMSIZE:
+       case SQ_GSTMP_RING_ITEMSIZE:
+       case SQ_GSVS_RING_ITEMSIZE:
+       case SQ_GS_VERT_ITEMSIZE:
+       case SQ_GS_VERT_ITEMSIZE_1:
+       case SQ_GS_VERT_ITEMSIZE_2:
+       case SQ_GS_VERT_ITEMSIZE_3:
+       case SQ_GSVS_RING_OFFSET_1:
+       case SQ_GSVS_RING_OFFSET_2:
+       case SQ_GSVS_RING_OFFSET_3:
+       case SQ_HSTMP_RING_ITEMSIZE:
+       case SQ_LSTMP_RING_ITEMSIZE:
+       case SQ_PSTMP_RING_ITEMSIZE:
+       case SQ_VSTMP_RING_ITEMSIZE:
+       case VGT_TF_RING_SIZE:
+               /* get value to populate the IB don't remove */
+               tmp =radeon_get_ib_value(p, idx);
+               ib[idx] = 0;
+               break;
+       case DB_DEPTH_CONTROL:
+               track->db_depth_control = radeon_get_ib_value(p, idx);
+               break;
+       case DB_Z_INFO:
+               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               if (r) {
+                       dev_warn(p->dev, "bad SET_CONTEXT_REG "
+                                       "0x%04X\n", reg);
+                       return -EINVAL;
+               }
+               track->db_z_info = radeon_get_ib_value(p, idx);
+               ib[idx] &= ~Z_ARRAY_MODE(0xf);
+               track->db_z_info &= ~Z_ARRAY_MODE(0xf);
+               if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
+                       ib[idx] |= Z_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
+                       track->db_z_info |= Z_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
+               } else {
+                       ib[idx] |= Z_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
+                       track->db_z_info |= Z_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
+               }
+               break;
+       case DB_STENCIL_INFO:
+               track->db_s_info = radeon_get_ib_value(p, idx);
+               break;
+       case DB_DEPTH_VIEW:
+               track->db_depth_view = radeon_get_ib_value(p, idx);
+               break;
+       case DB_DEPTH_SIZE:
+               track->db_depth_size = radeon_get_ib_value(p, idx);
+               track->db_depth_size_idx = idx;
+               break;
+       case DB_Z_READ_BASE:
+               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               if (r) {
+                       dev_warn(p->dev, "bad SET_CONTEXT_REG "
+                                       "0x%04X\n", reg);
+                       return -EINVAL;
+               }
+               track->db_z_read_offset = radeon_get_ib_value(p, idx);
+               ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+               track->db_z_read_bo = reloc->robj;
+               break;
+       case DB_Z_WRITE_BASE:
+               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               if (r) {
+                       dev_warn(p->dev, "bad SET_CONTEXT_REG "
+                                       "0x%04X\n", reg);
+                       return -EINVAL;
+               }
+               track->db_z_write_offset = radeon_get_ib_value(p, idx);
+               ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+               track->db_z_write_bo = reloc->robj;
+               break;
+       case DB_STENCIL_READ_BASE:
+               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               if (r) {
+                       dev_warn(p->dev, "bad SET_CONTEXT_REG "
+                                       "0x%04X\n", reg);
+                       return -EINVAL;
+               }
+               track->db_s_read_offset = radeon_get_ib_value(p, idx);
+               ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+               track->db_s_read_bo = reloc->robj;
+               break;
+       case DB_STENCIL_WRITE_BASE:
+               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               if (r) {
+                       dev_warn(p->dev, "bad SET_CONTEXT_REG "
+                                       "0x%04X\n", reg);
+                       return -EINVAL;
+               }
+               track->db_s_write_offset = radeon_get_ib_value(p, idx);
+               ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+               track->db_s_write_bo = reloc->robj;
+               break;
+       case VGT_STRMOUT_CONFIG:
+               track->vgt_strmout_config = radeon_get_ib_value(p, idx);
+               break;
+       case VGT_STRMOUT_BUFFER_CONFIG:
+               track->vgt_strmout_buffer_config = radeon_get_ib_value(p, idx);
+               break;
+       case CB_TARGET_MASK:
+               track->cb_target_mask = radeon_get_ib_value(p, idx);
+               break;
+       case CB_SHADER_MASK:
+               track->cb_shader_mask = radeon_get_ib_value(p, idx);
+               break;
+       case PA_SC_AA_CONFIG:
+               tmp = radeon_get_ib_value(p, idx) & MSAA_NUM_SAMPLES_MASK;
+               track->nsamples = 1 << tmp;
+               break;
+       case CB_COLOR0_VIEW:
+       case CB_COLOR1_VIEW:
+       case CB_COLOR2_VIEW:
+       case CB_COLOR3_VIEW:
+       case CB_COLOR4_VIEW:
+       case CB_COLOR5_VIEW:
+       case CB_COLOR6_VIEW:
+       case CB_COLOR7_VIEW:
+               tmp = (reg - CB_COLOR0_VIEW) / 0x3c;
+               track->cb_color_view[tmp] = radeon_get_ib_value(p, idx);
+               break;
+       case CB_COLOR8_VIEW:
+       case CB_COLOR9_VIEW:
+       case CB_COLOR10_VIEW:
+       case CB_COLOR11_VIEW:
+               tmp = ((reg - CB_COLOR8_VIEW) / 0x1c) + 8;
+               track->cb_color_view[tmp] = radeon_get_ib_value(p, idx);
+               break;
+       case CB_COLOR0_INFO:
+       case CB_COLOR1_INFO:
+       case CB_COLOR2_INFO:
+       case CB_COLOR3_INFO:
+       case CB_COLOR4_INFO:
+       case CB_COLOR5_INFO:
+       case CB_COLOR6_INFO:
+       case CB_COLOR7_INFO:
+               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               if (r) {
+                       dev_warn(p->dev, "bad SET_CONTEXT_REG "
+                                       "0x%04X\n", reg);
+                       return -EINVAL;
+               }
+               tmp = (reg - CB_COLOR0_INFO) / 0x3c;
+               track->cb_color_info[tmp] = radeon_get_ib_value(p, idx);
+               if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
+                       ib[idx] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
+                       track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
+               } else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) {
+                       ib[idx] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
+                       track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
+               }
+               break;
+       case CB_COLOR8_INFO:
+       case CB_COLOR9_INFO:
+       case CB_COLOR10_INFO:
+       case CB_COLOR11_INFO:
+               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               if (r) {
+                       dev_warn(p->dev, "bad SET_CONTEXT_REG "
+                                       "0x%04X\n", reg);
+                       return -EINVAL;
+               }
+               tmp = ((reg - CB_COLOR8_INFO) / 0x1c) + 8;
+               track->cb_color_info[tmp] = radeon_get_ib_value(p, idx);
+               if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
+                       ib[idx] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
+                       track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
+               } else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) {
+                       ib[idx] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
+                       track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
+               }
+               break;
+       case CB_COLOR0_PITCH:
+       case CB_COLOR1_PITCH:
+       case CB_COLOR2_PITCH:
+       case CB_COLOR3_PITCH:
+       case CB_COLOR4_PITCH:
+       case CB_COLOR5_PITCH:
+       case CB_COLOR6_PITCH:
+       case CB_COLOR7_PITCH:
+               tmp = (reg - CB_COLOR0_PITCH) / 0x3c;
+               track->cb_color_pitch[tmp] = radeon_get_ib_value(p, idx);
+               track->cb_color_pitch_idx[tmp] = idx;
+               break;
+       case CB_COLOR8_PITCH:
+       case CB_COLOR9_PITCH:
+       case CB_COLOR10_PITCH:
+       case CB_COLOR11_PITCH:
+               tmp = ((reg - CB_COLOR8_PITCH) / 0x1c) + 8;
+               track->cb_color_pitch[tmp] = radeon_get_ib_value(p, idx);
+               track->cb_color_pitch_idx[tmp] = idx;
+               break;
+       case CB_COLOR0_SLICE:
+       case CB_COLOR1_SLICE:
+       case CB_COLOR2_SLICE:
+       case CB_COLOR3_SLICE:
+       case CB_COLOR4_SLICE:
+       case CB_COLOR5_SLICE:
+       case CB_COLOR6_SLICE:
+       case CB_COLOR7_SLICE:
+               tmp = (reg - CB_COLOR0_SLICE) / 0x3c;
+               track->cb_color_slice[tmp] = radeon_get_ib_value(p, idx);
+               track->cb_color_slice_idx[tmp] = idx;
+               break;
+       case CB_COLOR8_SLICE:
+       case CB_COLOR9_SLICE:
+       case CB_COLOR10_SLICE:
+       case CB_COLOR11_SLICE:
+               tmp = ((reg - CB_COLOR8_SLICE) / 0x1c) + 8;
+               track->cb_color_slice[tmp] = radeon_get_ib_value(p, idx);
+               track->cb_color_slice_idx[tmp] = idx;
+               break;
+       case CB_COLOR0_ATTRIB:
+       case CB_COLOR1_ATTRIB:
+       case CB_COLOR2_ATTRIB:
+       case CB_COLOR3_ATTRIB:
+       case CB_COLOR4_ATTRIB:
+       case CB_COLOR5_ATTRIB:
+       case CB_COLOR6_ATTRIB:
+       case CB_COLOR7_ATTRIB:
+       case CB_COLOR8_ATTRIB:
+       case CB_COLOR9_ATTRIB:
+       case CB_COLOR10_ATTRIB:
+       case CB_COLOR11_ATTRIB:
+               break;
+       case CB_COLOR0_DIM:
+       case CB_COLOR1_DIM:
+       case CB_COLOR2_DIM:
+       case CB_COLOR3_DIM:
+       case CB_COLOR4_DIM:
+       case CB_COLOR5_DIM:
+       case CB_COLOR6_DIM:
+       case CB_COLOR7_DIM:
+               tmp = (reg - CB_COLOR0_DIM) / 0x3c;
+               track->cb_color_dim[tmp] = radeon_get_ib_value(p, idx);
+               track->cb_color_dim_idx[tmp] = idx;
+               break;
+       case CB_COLOR8_DIM:
+       case CB_COLOR9_DIM:
+       case CB_COLOR10_DIM:
+       case CB_COLOR11_DIM:
+               tmp = ((reg - CB_COLOR8_DIM) / 0x1c) + 8;
+               track->cb_color_dim[tmp] = radeon_get_ib_value(p, idx);
+               track->cb_color_dim_idx[tmp] = idx;
+               break;
+       case CB_COLOR0_FMASK:
+       case CB_COLOR1_FMASK:
+       case CB_COLOR2_FMASK:
+       case CB_COLOR3_FMASK:
+       case CB_COLOR4_FMASK:
+       case CB_COLOR5_FMASK:
+       case CB_COLOR6_FMASK:
+       case CB_COLOR7_FMASK:
+               tmp = (reg - CB_COLOR0_FMASK) / 0x3c;
+               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               if (r) {
+                       dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
+                       return -EINVAL;
+               }
+               ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+               track->cb_color_fmask_bo[tmp] = reloc->robj;
+               break;
+       case CB_COLOR0_CMASK:
+       case CB_COLOR1_CMASK:
+       case CB_COLOR2_CMASK:
+       case CB_COLOR3_CMASK:
+       case CB_COLOR4_CMASK:
+       case CB_COLOR5_CMASK:
+       case CB_COLOR6_CMASK:
+       case CB_COLOR7_CMASK:
+               tmp = (reg - CB_COLOR0_CMASK) / 0x3c;
+               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               if (r) {
+                       dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
+                       return -EINVAL;
+               }
+               ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+               track->cb_color_cmask_bo[tmp] = reloc->robj;
+               break;
+       case CB_COLOR0_FMASK_SLICE:
+       case CB_COLOR1_FMASK_SLICE:
+       case CB_COLOR2_FMASK_SLICE:
+       case CB_COLOR3_FMASK_SLICE:
+       case CB_COLOR4_FMASK_SLICE:
+       case CB_COLOR5_FMASK_SLICE:
+       case CB_COLOR6_FMASK_SLICE:
+       case CB_COLOR7_FMASK_SLICE:
+               tmp = (reg - CB_COLOR0_FMASK_SLICE) / 0x3c;
+               track->cb_color_fmask_slice[tmp] = radeon_get_ib_value(p, idx);
+               break;
+       case CB_COLOR0_CMASK_SLICE:
+       case CB_COLOR1_CMASK_SLICE:
+       case CB_COLOR2_CMASK_SLICE:
+       case CB_COLOR3_CMASK_SLICE:
+       case CB_COLOR4_CMASK_SLICE:
+       case CB_COLOR5_CMASK_SLICE:
+       case CB_COLOR6_CMASK_SLICE:
+       case CB_COLOR7_CMASK_SLICE:
+               tmp = (reg - CB_COLOR0_CMASK_SLICE) / 0x3c;
+               track->cb_color_cmask_slice[tmp] = radeon_get_ib_value(p, idx);
+               break;
+       case CB_COLOR0_BASE:
+       case CB_COLOR1_BASE:
+       case CB_COLOR2_BASE:
+       case CB_COLOR3_BASE:
+       case CB_COLOR4_BASE:
+       case CB_COLOR5_BASE:
+       case CB_COLOR6_BASE:
+       case CB_COLOR7_BASE:
+               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               if (r) {
+                       dev_warn(p->dev, "bad SET_CONTEXT_REG "
+                                       "0x%04X\n", reg);
+                       return -EINVAL;
+               }
+               tmp = (reg - CB_COLOR0_BASE) / 0x3c;
+               track->cb_color_bo_offset[tmp] = radeon_get_ib_value(p, idx);
+               ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+               track->cb_color_base_last[tmp] = ib[idx];
+               track->cb_color_bo[tmp] = reloc->robj;
+               break;
+       case CB_COLOR8_BASE:
+       case CB_COLOR9_BASE:
+       case CB_COLOR10_BASE:
+       case CB_COLOR11_BASE:
+               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               if (r) {
+                       dev_warn(p->dev, "bad SET_CONTEXT_REG "
+                                       "0x%04X\n", reg);
+                       return -EINVAL;
+               }
+               tmp = ((reg - CB_COLOR8_BASE) / 0x1c) + 8;
+               track->cb_color_bo_offset[tmp] = radeon_get_ib_value(p, idx);
+               ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+               track->cb_color_base_last[tmp] = ib[idx];
+               track->cb_color_bo[tmp] = reloc->robj;
+               break;
+       case CB_IMMED0_BASE:
+       case CB_IMMED1_BASE:
+       case CB_IMMED2_BASE:
+       case CB_IMMED3_BASE:
+       case CB_IMMED4_BASE:
+       case CB_IMMED5_BASE:
+       case CB_IMMED6_BASE:
+       case CB_IMMED7_BASE:
+       case CB_IMMED8_BASE:
+       case CB_IMMED9_BASE:
+       case CB_IMMED10_BASE:
+       case CB_IMMED11_BASE:
+       case DB_HTILE_DATA_BASE:
+       case SQ_PGM_START_FS:
+       case SQ_PGM_START_ES:
+       case SQ_PGM_START_VS:
+       case SQ_PGM_START_GS:
+       case SQ_PGM_START_PS:
+       case SQ_PGM_START_HS:
+       case SQ_PGM_START_LS:
+       case GDS_ADDR_BASE:
+       case SQ_CONST_MEM_BASE:
+       case SQ_ALU_CONST_CACHE_GS_0:
+       case SQ_ALU_CONST_CACHE_GS_1:
+       case SQ_ALU_CONST_CACHE_GS_2:
+       case SQ_ALU_CONST_CACHE_GS_3:
+       case SQ_ALU_CONST_CACHE_GS_4:
+       case SQ_ALU_CONST_CACHE_GS_5:
+       case SQ_ALU_CONST_CACHE_GS_6:
+       case SQ_ALU_CONST_CACHE_GS_7:
+       case SQ_ALU_CONST_CACHE_GS_8:
+       case SQ_ALU_CONST_CACHE_GS_9:
+       case SQ_ALU_CONST_CACHE_GS_10:
+       case SQ_ALU_CONST_CACHE_GS_11:
+       case SQ_ALU_CONST_CACHE_GS_12:
+       case SQ_ALU_CONST_CACHE_GS_13:
+       case SQ_ALU_CONST_CACHE_GS_14:
+       case SQ_ALU_CONST_CACHE_GS_15:
+       case SQ_ALU_CONST_CACHE_PS_0:
+       case SQ_ALU_CONST_CACHE_PS_1:
+       case SQ_ALU_CONST_CACHE_PS_2:
+       case SQ_ALU_CONST_CACHE_PS_3:
+       case SQ_ALU_CONST_CACHE_PS_4:
+       case SQ_ALU_CONST_CACHE_PS_5:
+       case SQ_ALU_CONST_CACHE_PS_6:
+       case SQ_ALU_CONST_CACHE_PS_7:
+       case SQ_ALU_CONST_CACHE_PS_8:
+       case SQ_ALU_CONST_CACHE_PS_9:
+       case SQ_ALU_CONST_CACHE_PS_10:
+       case SQ_ALU_CONST_CACHE_PS_11:
+       case SQ_ALU_CONST_CACHE_PS_12:
+       case SQ_ALU_CONST_CACHE_PS_13:
+       case SQ_ALU_CONST_CACHE_PS_14:
+       case SQ_ALU_CONST_CACHE_PS_15:
+       case SQ_ALU_CONST_CACHE_VS_0:
+       case SQ_ALU_CONST_CACHE_VS_1:
+       case SQ_ALU_CONST_CACHE_VS_2:
+       case SQ_ALU_CONST_CACHE_VS_3:
+       case SQ_ALU_CONST_CACHE_VS_4:
+       case SQ_ALU_CONST_CACHE_VS_5:
+       case SQ_ALU_CONST_CACHE_VS_6:
+       case SQ_ALU_CONST_CACHE_VS_7:
+       case SQ_ALU_CONST_CACHE_VS_8:
+       case SQ_ALU_CONST_CACHE_VS_9:
+       case SQ_ALU_CONST_CACHE_VS_10:
+       case SQ_ALU_CONST_CACHE_VS_11:
+       case SQ_ALU_CONST_CACHE_VS_12:
+       case SQ_ALU_CONST_CACHE_VS_13:
+       case SQ_ALU_CONST_CACHE_VS_14:
+       case SQ_ALU_CONST_CACHE_VS_15:
+       case SQ_ALU_CONST_CACHE_HS_0:
+       case SQ_ALU_CONST_CACHE_HS_1:
+       case SQ_ALU_CONST_CACHE_HS_2:
+       case SQ_ALU_CONST_CACHE_HS_3:
+       case SQ_ALU_CONST_CACHE_HS_4:
+       case SQ_ALU_CONST_CACHE_HS_5:
+       case SQ_ALU_CONST_CACHE_HS_6:
+       case SQ_ALU_CONST_CACHE_HS_7:
+       case SQ_ALU_CONST_CACHE_HS_8:
+       case SQ_ALU_CONST_CACHE_HS_9:
+       case SQ_ALU_CONST_CACHE_HS_10:
+       case SQ_ALU_CONST_CACHE_HS_11:
+       case SQ_ALU_CONST_CACHE_HS_12:
+       case SQ_ALU_CONST_CACHE_HS_13:
+       case SQ_ALU_CONST_CACHE_HS_14:
+       case SQ_ALU_CONST_CACHE_HS_15:
+       case SQ_ALU_CONST_CACHE_LS_0:
+       case SQ_ALU_CONST_CACHE_LS_1:
+       case SQ_ALU_CONST_CACHE_LS_2:
+       case SQ_ALU_CONST_CACHE_LS_3:
+       case SQ_ALU_CONST_CACHE_LS_4:
+       case SQ_ALU_CONST_CACHE_LS_5:
+       case SQ_ALU_CONST_CACHE_LS_6:
+       case SQ_ALU_CONST_CACHE_LS_7:
+       case SQ_ALU_CONST_CACHE_LS_8:
+       case SQ_ALU_CONST_CACHE_LS_9:
+       case SQ_ALU_CONST_CACHE_LS_10:
+       case SQ_ALU_CONST_CACHE_LS_11:
+       case SQ_ALU_CONST_CACHE_LS_12:
+       case SQ_ALU_CONST_CACHE_LS_13:
+       case SQ_ALU_CONST_CACHE_LS_14:
+       case SQ_ALU_CONST_CACHE_LS_15:
+               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               if (r) {
+                       dev_warn(p->dev, "bad SET_CONTEXT_REG "
+                                       "0x%04X\n", reg);
+                       return -EINVAL;
+               }
+               ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+               break;
+       default:
+               dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
+               return -EINVAL;
+       }
+       return 0;
+}
+
+/**
+ * evergreen_check_texture_resource() - check if register is authorized or not
+ * @p: parser structure holding parsing context
+ * @idx: index into the cs buffer
+ * @texture: texture's bo structure
+ * @mipmap: mipmap's bo structure
+ *
+ * This function will check that the resource has valid field and that
+ * the texture and mipmap bo object are big enough to cover this resource.
+ */
+static inline int evergreen_check_texture_resource(struct radeon_cs_parser *p,  u32 idx,
+                                                  struct radeon_bo *texture,
+                                                  struct radeon_bo *mipmap)
+{
+       /* XXX fill in */
+       return 0;
+}
+
+static int evergreen_packet3_check(struct radeon_cs_parser *p,
+                                  struct radeon_cs_packet *pkt)
+{
+       struct radeon_cs_reloc *reloc;
+       struct evergreen_cs_track *track;
+       volatile u32 *ib;
+       unsigned idx;
+       unsigned i;
+       unsigned start_reg, end_reg, reg;
+       int r;
+       u32 idx_value;
+
+       track = (struct evergreen_cs_track *)p->track;
+       ib = p->ib->ptr;
+       idx = pkt->idx + 1;
+       idx_value = radeon_get_ib_value(p, idx);
+
+       switch (pkt->opcode) {
+       case PACKET3_CONTEXT_CONTROL:
+               if (pkt->count != 1) {
+                       DRM_ERROR("bad CONTEXT_CONTROL\n");
+                       return -EINVAL;
+               }
+               break;
+       case PACKET3_INDEX_TYPE:
+       case PACKET3_NUM_INSTANCES:
+       case PACKET3_CLEAR_STATE:
+               if (pkt->count) {
+                       DRM_ERROR("bad INDEX_TYPE/NUM_INSTANCES/CLEAR_STATE\n");
+                       return -EINVAL;
+               }
+               break;
+       case PACKET3_INDEX_BASE:
+               if (pkt->count != 1) {
+                       DRM_ERROR("bad INDEX_BASE\n");
+                       return -EINVAL;
+               }
+               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               if (r) {
+                       DRM_ERROR("bad INDEX_BASE\n");
+                       return -EINVAL;
+               }
+               ib[idx+0] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff);
+               ib[idx+1] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
+               r = evergreen_cs_track_check(p);
+               if (r) {
+                       dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
+                       return r;
+               }
+               break;
+       case PACKET3_DRAW_INDEX:
+               if (pkt->count != 3) {
+                       DRM_ERROR("bad DRAW_INDEX\n");
+                       return -EINVAL;
+               }
+               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               if (r) {
+                       DRM_ERROR("bad DRAW_INDEX\n");
+                       return -EINVAL;
+               }
+               ib[idx+0] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff);
+               ib[idx+1] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
+               r = evergreen_cs_track_check(p);
+               if (r) {
+                       dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
+                       return r;
+               }
+               break;
+       case PACKET3_DRAW_INDEX_2:
+               if (pkt->count != 4) {
+                       DRM_ERROR("bad DRAW_INDEX_2\n");
+                       return -EINVAL;
+               }
+               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               if (r) {
+                       DRM_ERROR("bad DRAW_INDEX_2\n");
+                       return -EINVAL;
+               }
+               ib[idx+1] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff);
+               ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
+               r = evergreen_cs_track_check(p);
+               if (r) {
+                       dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
+                       return r;
+               }
+               break;
+       case PACKET3_DRAW_INDEX_AUTO:
+               if (pkt->count != 1) {
+                       DRM_ERROR("bad DRAW_INDEX_AUTO\n");
+                       return -EINVAL;
+               }
+               r = evergreen_cs_track_check(p);
+               if (r) {
+                       dev_warn(p->dev, "%s:%d invalid cmd stream %d\n", __func__, __LINE__, idx);
+                       return r;
+               }
+               break;
+       case PACKET3_DRAW_INDEX_MULTI_AUTO:
+               if (pkt->count != 2) {
+                       DRM_ERROR("bad DRAW_INDEX_MULTI_AUTO\n");
+                       return -EINVAL;
+               }
+               r = evergreen_cs_track_check(p);
+               if (r) {
+                       dev_warn(p->dev, "%s:%d invalid cmd stream %d\n", __func__, __LINE__, idx);
+                       return r;
+               }
+               break;
+       case PACKET3_DRAW_INDEX_IMMD:
+               if (pkt->count < 2) {
+                       DRM_ERROR("bad DRAW_INDEX_IMMD\n");
+                       return -EINVAL;
+               }
+               r = evergreen_cs_track_check(p);
+               if (r) {
+                       dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
+                       return r;
+               }
+               break;
+       case PACKET3_DRAW_INDEX_OFFSET:
+               if (pkt->count != 2) {
+                       DRM_ERROR("bad DRAW_INDEX_OFFSET\n");
+                       return -EINVAL;
+               }
+               r = evergreen_cs_track_check(p);
+               if (r) {
+                       dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
+                       return r;
+               }
+               break;
+       case PACKET3_DRAW_INDEX_OFFSET_2:
+               if (pkt->count != 3) {
+                       DRM_ERROR("bad DRAW_INDEX_OFFSET_2\n");
+                       return -EINVAL;
+               }
+               r = evergreen_cs_track_check(p);
+               if (r) {
+                       dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
+                       return r;
+               }
+               break;
+       case PACKET3_WAIT_REG_MEM:
+               if (pkt->count != 5) {
+                       DRM_ERROR("bad WAIT_REG_MEM\n");
+                       return -EINVAL;
+               }
+               /* bit 4 is reg (0) or mem (1) */
+               if (idx_value & 0x10) {
+                       r = evergreen_cs_packet_next_reloc(p, &reloc);
+                       if (r) {
+                               DRM_ERROR("bad WAIT_REG_MEM\n");
+                               return -EINVAL;
+                       }
+                       ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
+                       ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
+               }
+               break;
+       case PACKET3_SURFACE_SYNC:
+               if (pkt->count != 3) {
+                       DRM_ERROR("bad SURFACE_SYNC\n");
+                       return -EINVAL;
+               }
+               /* 0xffffffff/0x0 is flush all cache flag */
+               if (radeon_get_ib_value(p, idx + 1) != 0xffffffff ||
+                   radeon_get_ib_value(p, idx + 2) != 0) {
+                       r = evergreen_cs_packet_next_reloc(p, &reloc);
+                       if (r) {
+                               DRM_ERROR("bad SURFACE_SYNC\n");
+                               return -EINVAL;
+                       }
+                       ib[idx+2] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+               }
+               break;
+       case PACKET3_EVENT_WRITE:
+               if (pkt->count != 2 && pkt->count != 0) {
+                       DRM_ERROR("bad EVENT_WRITE\n");
+                       return -EINVAL;
+               }
+               if (pkt->count) {
+                       r = evergreen_cs_packet_next_reloc(p, &reloc);
+                       if (r) {
+                               DRM_ERROR("bad EVENT_WRITE\n");
+                               return -EINVAL;
+                       }
+                       ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
+                       ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
+               }
+               break;
+       case PACKET3_EVENT_WRITE_EOP:
+               if (pkt->count != 4) {
+                       DRM_ERROR("bad EVENT_WRITE_EOP\n");
+                       return -EINVAL;
+               }
+               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               if (r) {
+                       DRM_ERROR("bad EVENT_WRITE_EOP\n");
+                       return -EINVAL;
+               }
+               ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
+               ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
+               break;
+       case PACKET3_EVENT_WRITE_EOS:
+               if (pkt->count != 3) {
+                       DRM_ERROR("bad EVENT_WRITE_EOS\n");
+                       return -EINVAL;
+               }
+               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               if (r) {
+                       DRM_ERROR("bad EVENT_WRITE_EOS\n");
+                       return -EINVAL;
+               }
+               ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
+               ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
+               break;
+       case PACKET3_SET_CONFIG_REG:
+               start_reg = (idx_value << 2) + PACKET3_SET_CONFIG_REG_START;
+               end_reg = 4 * pkt->count + start_reg - 4;
+               if ((start_reg < PACKET3_SET_CONFIG_REG_START) ||
+                   (start_reg >= PACKET3_SET_CONFIG_REG_END) ||
+                   (end_reg >= PACKET3_SET_CONFIG_REG_END)) {
+                       DRM_ERROR("bad PACKET3_SET_CONFIG_REG\n");
+                       return -EINVAL;
+               }
+               for (i = 0; i < pkt->count; i++) {
+                       reg = start_reg + (4 * i);
+                       r = evergreen_cs_check_reg(p, reg, idx+1+i);
+                       if (r)
+                               return r;
+               }
+               break;
+       case PACKET3_SET_CONTEXT_REG:
+               start_reg = (idx_value << 2) + PACKET3_SET_CONTEXT_REG_START;
+               end_reg = 4 * pkt->count + start_reg - 4;
+               if ((start_reg < PACKET3_SET_CONTEXT_REG_START) ||
+                   (start_reg >= PACKET3_SET_CONTEXT_REG_END) ||
+                   (end_reg >= PACKET3_SET_CONTEXT_REG_END)) {
+                       DRM_ERROR("bad PACKET3_SET_CONTEXT_REG\n");
+                       return -EINVAL;
+               }
+               for (i = 0; i < pkt->count; i++) {
+                       reg = start_reg + (4 * i);
+                       r = evergreen_cs_check_reg(p, reg, idx+1+i);
+                       if (r)
+                               return r;
+               }
+               break;
+       case PACKET3_SET_RESOURCE:
+               if (pkt->count % 8) {
+                       DRM_ERROR("bad SET_RESOURCE\n");
+                       return -EINVAL;
+               }
+               start_reg = (idx_value << 2) + PACKET3_SET_RESOURCE_START;
+               end_reg = 4 * pkt->count + start_reg - 4;
+               if ((start_reg < PACKET3_SET_RESOURCE_START) ||
+                   (start_reg >= PACKET3_SET_RESOURCE_END) ||
+                   (end_reg >= PACKET3_SET_RESOURCE_END)) {
+                       DRM_ERROR("bad SET_RESOURCE\n");
+                       return -EINVAL;
+               }
+               for (i = 0; i < (pkt->count / 8); i++) {
+                       struct radeon_bo *texture, *mipmap;
+                       u32 size, offset;
+
+                       switch (G__SQ_CONSTANT_TYPE(radeon_get_ib_value(p, idx+1+(i*8)+7))) {
+                       case SQ_TEX_VTX_VALID_TEXTURE:
+                               /* tex base */
+                               r = evergreen_cs_packet_next_reloc(p, &reloc);
+                               if (r) {
+                                       DRM_ERROR("bad SET_RESOURCE (tex)\n");
+                                       return -EINVAL;
+                               }
+                               ib[idx+1+(i*8)+3] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+                               if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
+                                       ib[idx+1+(i*8)+1] |= TEX_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
+                               else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
+                                       ib[idx+1+(i*8)+1] |= TEX_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
+                               texture = reloc->robj;
+                               /* tex mip base */
+                               r = evergreen_cs_packet_next_reloc(p, &reloc);
+                               if (r) {
+                                       DRM_ERROR("bad SET_RESOURCE (tex)\n");
+                                       return -EINVAL;
+                               }
+                               ib[idx+1+(i*8)+4] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+                               mipmap = reloc->robj;
+                               r = evergreen_check_texture_resource(p,  idx+1+(i*8),
+                                               texture, mipmap);
+                               if (r)
+                                       return r;
+                               break;
+                       case SQ_TEX_VTX_VALID_BUFFER:
+                               /* vtx base */
+                               r = evergreen_cs_packet_next_reloc(p, &reloc);
+                               if (r) {
+                                       DRM_ERROR("bad SET_RESOURCE (vtx)\n");
+                                       return -EINVAL;
+                               }
+                               offset = radeon_get_ib_value(p, idx+1+(i*8)+0);
+                               size = radeon_get_ib_value(p, idx+1+(i*8)+1);
+                               if (p->rdev && (size + offset) > radeon_bo_size(reloc->robj)) {
+                                       /* force size to size of the buffer */
+                                       dev_warn(p->dev, "vbo resource seems too big for the bo\n");
+                                       ib[idx+1+(i*8)+1] = radeon_bo_size(reloc->robj);
+                               }
+                               ib[idx+1+(i*8)+0] += (u32)((reloc->lobj.gpu_offset) & 0xffffffff);
+                               ib[idx+1+(i*8)+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
+                               break;
+                       case SQ_TEX_VTX_INVALID_TEXTURE:
+                       case SQ_TEX_VTX_INVALID_BUFFER:
+                       default:
+                               DRM_ERROR("bad SET_RESOURCE\n");
+                               return -EINVAL;
+                       }
+               }
+               break;
+       case PACKET3_SET_ALU_CONST:
+               /* XXX fix me ALU const buffers only */
+               break;
+       case PACKET3_SET_BOOL_CONST:
+               start_reg = (idx_value << 2) + PACKET3_SET_BOOL_CONST_START;
+               end_reg = 4 * pkt->count + start_reg - 4;
+               if ((start_reg < PACKET3_SET_BOOL_CONST_START) ||
+                   (start_reg >= PACKET3_SET_BOOL_CONST_END) ||
+                   (end_reg >= PACKET3_SET_BOOL_CONST_END)) {
+                       DRM_ERROR("bad SET_BOOL_CONST\n");
+                       return -EINVAL;
+               }
+               break;
+       case PACKET3_SET_LOOP_CONST:
+               start_reg = (idx_value << 2) + PACKET3_SET_LOOP_CONST_START;
+               end_reg = 4 * pkt->count + start_reg - 4;
+               if ((start_reg < PACKET3_SET_LOOP_CONST_START) ||
+                   (start_reg >= PACKET3_SET_LOOP_CONST_END) ||
+                   (end_reg >= PACKET3_SET_LOOP_CONST_END)) {
+                       DRM_ERROR("bad SET_LOOP_CONST\n");
+                       return -EINVAL;
+               }
+               break;
+       case PACKET3_SET_CTL_CONST:
+               start_reg = (idx_value << 2) + PACKET3_SET_CTL_CONST_START;
+               end_reg = 4 * pkt->count + start_reg - 4;
+               if ((start_reg < PACKET3_SET_CTL_CONST_START) ||
+                   (start_reg >= PACKET3_SET_CTL_CONST_END) ||
+                   (end_reg >= PACKET3_SET_CTL_CONST_END)) {
+                       DRM_ERROR("bad SET_CTL_CONST\n");
+                       return -EINVAL;
+               }
+               break;
+       case PACKET3_SET_SAMPLER:
+               if (pkt->count % 3) {
+                       DRM_ERROR("bad SET_SAMPLER\n");
+                       return -EINVAL;
+               }
+               start_reg = (idx_value << 2) + PACKET3_SET_SAMPLER_START;
+               end_reg = 4 * pkt->count + start_reg - 4;
+               if ((start_reg < PACKET3_SET_SAMPLER_START) ||
+                   (start_reg >= PACKET3_SET_SAMPLER_END) ||
+                   (end_reg >= PACKET3_SET_SAMPLER_END)) {
+                       DRM_ERROR("bad SET_SAMPLER\n");
+                       return -EINVAL;
+               }
+               break;
+       case PACKET3_NOP:
+               break;
+       default:
+               DRM_ERROR("Packet3 opcode %x not supported\n", pkt->opcode);
+               return -EINVAL;
+       }
+       return 0;
+}
+
+int evergreen_cs_parse(struct radeon_cs_parser *p)
+{
+       struct radeon_cs_packet pkt;
+       struct evergreen_cs_track *track;
+       int r;
+
+       if (p->track == NULL) {
+               /* initialize tracker, we are in kms */
+               track = kzalloc(sizeof(*track), GFP_KERNEL);
+               if (track == NULL)
+                       return -ENOMEM;
+               evergreen_cs_track_init(track);
+               track->npipes = p->rdev->config.evergreen.tiling_npipes;
+               track->nbanks = p->rdev->config.evergreen.tiling_nbanks;
+               track->group_size = p->rdev->config.evergreen.tiling_group_size;
+               p->track = track;
+       }
+       do {
+               r = evergreen_cs_packet_parse(p, &pkt, p->idx);
+               if (r) {
+                       kfree(p->track);
+                       p->track = NULL;
+                       return r;
+               }
+               p->idx += pkt.count + 2;
+               switch (pkt.type) {
+               case PACKET_TYPE0:
+                       r = evergreen_cs_parse_packet0(p, &pkt);
+                       break;
+               case PACKET_TYPE2:
+                       break;
+               case PACKET_TYPE3:
+                       r = evergreen_packet3_check(p, &pkt);
+                       break;
+               default:
+                       DRM_ERROR("Unknown packet type %d !\n", pkt.type);
+                       kfree(p->track);
+                       p->track = NULL;
+                       return -EINVAL;
+               }
+               if (r) {
+                       kfree(p->track);
+                       p->track = NULL;
+                       return r;
+               }
+       } while (p->idx < p->chunks[p->chunk_ib_idx].length_dw);
+#if 0
+       for (r = 0; r < p->ib->length_dw; r++) {
+               printk(KERN_INFO "%05d  0x%08X\n", r, p->ib->ptr[r]);
+               mdelay(1);
+       }
+#endif
+       kfree(p->track);
+       p->track = NULL;
+       return 0;
+}
+
index af86af836f13dcb446d78418c65f3c6c69a2660f..e028c1cd9d9b7732d8eeaf1c8773df35e13c93fa 100644 (file)
 #define EVERGREEN_DATA_FORMAT                           0x6b00
 #       define EVERGREEN_INTERLEAVE_EN                  (1 << 0)
 #define EVERGREEN_DESKTOP_HEIGHT                        0x6b04
+#define EVERGREEN_VLINE_START_END                       0x6b08
+#define EVERGREEN_VLINE_STATUS                          0x6bb8
+#       define EVERGREEN_VLINE_STAT                     (1 << 12)
 
 #define EVERGREEN_VIEWPORT_START                        0x6d70
 #define EVERGREEN_VIEWPORT_SIZE                         0x6d74
index 93e9e17ad54ad4a1717738489cad54caaf47bb17..79683f6b4452907854d2a6fa9639bf04132a785c 100644 (file)
 #define                CLIP_VTX_REORDER_ENA                            (1 << 0)
 #define                NUM_CLIP_SEQ(x)                                 ((x) << 1)
 #define PA_SC_AA_CONFIG                                        0x28C04
+#define         MSAA_NUM_SAMPLES_SHIFT                  0
+#define         MSAA_NUM_SAMPLES_MASK                   0x3
 #define PA_SC_CLIPRECT_RULE                            0x2820C
 #define        PA_SC_EDGERULE                                  0x28230
 #define        PA_SC_FIFO_SIZE                                 0x8BCC
 #       define DC_HPDx_RX_INT_TIMER(x)                    ((x) << 16)
 #       define DC_HPDx_EN                                 (1 << 28)
 
+/*
+ * PM4
+ */
+#define        PACKET_TYPE0    0
+#define        PACKET_TYPE1    1
+#define        PACKET_TYPE2    2
+#define        PACKET_TYPE3    3
+
+#define CP_PACKET_GET_TYPE(h) (((h) >> 30) & 3)
+#define CP_PACKET_GET_COUNT(h) (((h) >> 16) & 0x3FFF)
+#define CP_PACKET0_GET_REG(h) (((h) & 0xFFFF) << 2)
+#define CP_PACKET3_GET_OPCODE(h) (((h) >> 8) & 0xFF)
+#define PACKET0(reg, n)        ((PACKET_TYPE0 << 30) |                         \
+                        (((reg) >> 2) & 0xFFFF) |                      \
+                        ((n) & 0x3FFF) << 16)
+#define CP_PACKET2                     0x80000000
+#define                PACKET2_PAD_SHIFT               0
+#define                PACKET2_PAD_MASK                (0x3fffffff << 0)
+
+#define PACKET2(v)     (CP_PACKET2 | REG_SET(PACKET2_PAD, (v)))
+
+#define PACKET3(op, n) ((PACKET_TYPE3 << 30) |                         \
+                        (((op) & 0xFF) << 8) |                         \
+                        ((n) & 0x3FFF) << 16)
+
+/* Packet 3 types */
+#define        PACKET3_NOP                                     0x10
+#define        PACKET3_SET_BASE                                0x11
+#define        PACKET3_CLEAR_STATE                             0x12
+#define        PACKET3_INDIRECT_BUFFER_SIZE                    0x13
+#define        PACKET3_DISPATCH_DIRECT                         0x15
+#define        PACKET3_DISPATCH_INDIRECT                       0x16
+#define        PACKET3_INDIRECT_BUFFER_END                     0x17
+#define        PACKET3_SET_PREDICATION                         0x20
+#define        PACKET3_REG_RMW                                 0x21
+#define        PACKET3_COND_EXEC                               0x22
+#define        PACKET3_PRED_EXEC                               0x23
+#define        PACKET3_DRAW_INDIRECT                           0x24
+#define        PACKET3_DRAW_INDEX_INDIRECT                     0x25
+#define        PACKET3_INDEX_BASE                              0x26
+#define        PACKET3_DRAW_INDEX_2                            0x27
+#define        PACKET3_CONTEXT_CONTROL                         0x28
+#define        PACKET3_DRAW_INDEX_OFFSET                       0x29
+#define        PACKET3_INDEX_TYPE                              0x2A
+#define        PACKET3_DRAW_INDEX                              0x2B
+#define        PACKET3_DRAW_INDEX_AUTO                         0x2D
+#define        PACKET3_DRAW_INDEX_IMMD                         0x2E
+#define        PACKET3_NUM_INSTANCES                           0x2F
+#define        PACKET3_DRAW_INDEX_MULTI_AUTO                   0x30
+#define        PACKET3_STRMOUT_BUFFER_UPDATE                   0x34
+#define        PACKET3_DRAW_INDEX_OFFSET_2                     0x35
+#define        PACKET3_DRAW_INDEX_MULTI_ELEMENT                0x36
+#define        PACKET3_MEM_SEMAPHORE                           0x39
+#define        PACKET3_MPEG_INDEX                              0x3A
+#define        PACKET3_WAIT_REG_MEM                            0x3C
+#define        PACKET3_MEM_WRITE                               0x3D
+#define        PACKET3_INDIRECT_BUFFER                         0x32
+#define        PACKET3_SURFACE_SYNC                            0x43
+#              define PACKET3_CB0_DEST_BASE_ENA    (1 << 6)
+#              define PACKET3_CB1_DEST_BASE_ENA    (1 << 7)
+#              define PACKET3_CB2_DEST_BASE_ENA    (1 << 8)
+#              define PACKET3_CB3_DEST_BASE_ENA    (1 << 9)
+#              define PACKET3_CB4_DEST_BASE_ENA    (1 << 10)
+#              define PACKET3_CB5_DEST_BASE_ENA    (1 << 11)
+#              define PACKET3_CB6_DEST_BASE_ENA    (1 << 12)
+#              define PACKET3_CB7_DEST_BASE_ENA    (1 << 13)
+#              define PACKET3_DB_DEST_BASE_ENA     (1 << 14)
+#              define PACKET3_CB8_DEST_BASE_ENA    (1 << 15)
+#              define PACKET3_CB9_DEST_BASE_ENA    (1 << 16)
+#              define PACKET3_CB10_DEST_BASE_ENA   (1 << 17)
+#              define PACKET3_CB11_DEST_BASE_ENA   (1 << 17)
+#              define PACKET3_FULL_CACHE_ENA       (1 << 20)
+#              define PACKET3_TC_ACTION_ENA        (1 << 23)
+#              define PACKET3_VC_ACTION_ENA        (1 << 24)
+#              define PACKET3_CB_ACTION_ENA        (1 << 25)
+#              define PACKET3_DB_ACTION_ENA        (1 << 26)
+#              define PACKET3_SH_ACTION_ENA        (1 << 27)
+#              define PACKET3_SMX_ACTION_ENA       (1 << 28)
+#define        PACKET3_ME_INITIALIZE                           0x44
+#define                PACKET3_ME_INITIALIZE_DEVICE_ID(x) ((x) << 16)
+#define        PACKET3_COND_WRITE                              0x45
+#define        PACKET3_EVENT_WRITE                             0x46
+#define        PACKET3_EVENT_WRITE_EOP                         0x47
+#define        PACKET3_EVENT_WRITE_EOS                         0x48
+#define        PACKET3_PREAMBLE_CNTL                           0x4A
+#define        PACKET3_RB_OFFSET                               0x4B
+#define        PACKET3_ALU_PS_CONST_BUFFER_COPY                0x4C
+#define        PACKET3_ALU_VS_CONST_BUFFER_COPY                0x4D
+#define        PACKET3_ALU_PS_CONST_UPDATE                     0x4E
+#define        PACKET3_ALU_VS_CONST_UPDATE                     0x4F
+#define        PACKET3_ONE_REG_WRITE                           0x57
+#define        PACKET3_SET_CONFIG_REG                          0x68
+#define                PACKET3_SET_CONFIG_REG_START                    0x00008000
+#define                PACKET3_SET_CONFIG_REG_END                      0x0000ac00
+#define        PACKET3_SET_CONTEXT_REG                         0x69
+#define                PACKET3_SET_CONTEXT_REG_START                   0x00028000
+#define                PACKET3_SET_CONTEXT_REG_END                     0x00029000
+#define        PACKET3_SET_ALU_CONST                           0x6A
+/* alu const buffers only; no reg file */
+#define        PACKET3_SET_BOOL_CONST                          0x6B
+#define                PACKET3_SET_BOOL_CONST_START                    0x0003a500
+#define                PACKET3_SET_BOOL_CONST_END                      0x0003a518
+#define        PACKET3_SET_LOOP_CONST                          0x6C
+#define                PACKET3_SET_LOOP_CONST_START                    0x0003a200
+#define                PACKET3_SET_LOOP_CONST_END                      0x0003a500
+#define        PACKET3_SET_RESOURCE                            0x6D
+#define                PACKET3_SET_RESOURCE_START                      0x00030000
+#define                PACKET3_SET_RESOURCE_END                        0x00038000
+#define        PACKET3_SET_SAMPLER                             0x6E
+#define                PACKET3_SET_SAMPLER_START                       0x0003c000
+#define                PACKET3_SET_SAMPLER_END                         0x0003c600
+#define        PACKET3_SET_CTL_CONST                           0x6F
+#define                PACKET3_SET_CTL_CONST_START                     0x0003cff0
+#define                PACKET3_SET_CTL_CONST_END                       0x0003ff0c
+#define        PACKET3_SET_RESOURCE_OFFSET                     0x70
+#define        PACKET3_SET_ALU_CONST_VS                        0x71
+#define        PACKET3_SET_ALU_CONST_DI                        0x72
+#define        PACKET3_SET_CONTEXT_REG_INDIRECT                0x73
+#define        PACKET3_SET_RESOURCE_INDIRECT                   0x74
+#define        PACKET3_SET_APPEND_CNT                          0x75
+
+#define        SQ_RESOURCE_CONSTANT_WORD7_0                            0x3001c
+#define                S__SQ_CONSTANT_TYPE(x)                  (((x) & 3) << 30)
+#define                G__SQ_CONSTANT_TYPE(x)                  (((x) >> 30) & 3)
+#define                        SQ_TEX_VTX_INVALID_TEXTURE                      0x0
+#define                        SQ_TEX_VTX_INVALID_BUFFER                       0x1
+#define                        SQ_TEX_VTX_VALID_TEXTURE                        0x2
+#define                        SQ_TEX_VTX_VALID_BUFFER                         0x3
+
+#define SQ_CONST_MEM_BASE                              0x8df8
+
+#define SQ_ESGS_RING_SIZE                              0x8c44
+#define SQ_GSVS_RING_SIZE                              0x8c4c
+#define SQ_ESTMP_RING_SIZE                             0x8c54
+#define SQ_GSTMP_RING_SIZE                             0x8c5c
+#define SQ_VSTMP_RING_SIZE                             0x8c64
+#define SQ_PSTMP_RING_SIZE                             0x8c6c
+#define SQ_LSTMP_RING_SIZE                             0x8e14
+#define SQ_HSTMP_RING_SIZE                             0x8e1c
+#define VGT_TF_RING_SIZE                               0x8988
+
+#define SQ_ESGS_RING_ITEMSIZE                          0x28900
+#define SQ_GSVS_RING_ITEMSIZE                          0x28904
+#define SQ_ESTMP_RING_ITEMSIZE                         0x28908
+#define SQ_GSTMP_RING_ITEMSIZE                         0x2890c
+#define SQ_VSTMP_RING_ITEMSIZE                         0x28910
+#define SQ_PSTMP_RING_ITEMSIZE                         0x28914
+#define SQ_LSTMP_RING_ITEMSIZE                         0x28830
+#define SQ_HSTMP_RING_ITEMSIZE                         0x28834
+
+#define SQ_GS_VERT_ITEMSIZE                            0x2891c
+#define SQ_GS_VERT_ITEMSIZE_1                          0x28920
+#define SQ_GS_VERT_ITEMSIZE_2                          0x28924
+#define SQ_GS_VERT_ITEMSIZE_3                          0x28928
+#define SQ_GSVS_RING_OFFSET_1                          0x2892c
+#define SQ_GSVS_RING_OFFSET_2                          0x28930
+#define SQ_GSVS_RING_OFFSET_3                          0x28934
+
+#define SQ_ALU_CONST_CACHE_PS_0                                0x28940
+#define SQ_ALU_CONST_CACHE_PS_1                                0x28944
+#define SQ_ALU_CONST_CACHE_PS_2                                0x28948
+#define SQ_ALU_CONST_CACHE_PS_3                                0x2894c
+#define SQ_ALU_CONST_CACHE_PS_4                                0x28950
+#define SQ_ALU_CONST_CACHE_PS_5                                0x28954
+#define SQ_ALU_CONST_CACHE_PS_6                                0x28958
+#define SQ_ALU_CONST_CACHE_PS_7                                0x2895c
+#define SQ_ALU_CONST_CACHE_PS_8                                0x28960
+#define SQ_ALU_CONST_CACHE_PS_9                                0x28964
+#define SQ_ALU_CONST_CACHE_PS_10                       0x28968
+#define SQ_ALU_CONST_CACHE_PS_11                       0x2896c
+#define SQ_ALU_CONST_CACHE_PS_12                       0x28970
+#define SQ_ALU_CONST_CACHE_PS_13                       0x28974
+#define SQ_ALU_CONST_CACHE_PS_14                       0x28978
+#define SQ_ALU_CONST_CACHE_PS_15                       0x2897c
+#define SQ_ALU_CONST_CACHE_VS_0                                0x28980
+#define SQ_ALU_CONST_CACHE_VS_1                                0x28984
+#define SQ_ALU_CONST_CACHE_VS_2                                0x28988
+#define SQ_ALU_CONST_CACHE_VS_3                                0x2898c
+#define SQ_ALU_CONST_CACHE_VS_4                                0x28990
+#define SQ_ALU_CONST_CACHE_VS_5                                0x28994
+#define SQ_ALU_CONST_CACHE_VS_6                                0x28998
+#define SQ_ALU_CONST_CACHE_VS_7                                0x2899c
+#define SQ_ALU_CONST_CACHE_VS_8                                0x289a0
+#define SQ_ALU_CONST_CACHE_VS_9                                0x289a4
+#define SQ_ALU_CONST_CACHE_VS_10                       0x289a8
+#define SQ_ALU_CONST_CACHE_VS_11                       0x289ac
+#define SQ_ALU_CONST_CACHE_VS_12                       0x289b0
+#define SQ_ALU_CONST_CACHE_VS_13                       0x289b4
+#define SQ_ALU_CONST_CACHE_VS_14                       0x289b8
+#define SQ_ALU_CONST_CACHE_VS_15                       0x289bc
+#define SQ_ALU_CONST_CACHE_GS_0                                0x289c0
+#define SQ_ALU_CONST_CACHE_GS_1                                0x289c4
+#define SQ_ALU_CONST_CACHE_GS_2                                0x289c8
+#define SQ_ALU_CONST_CACHE_GS_3                                0x289cc
+#define SQ_ALU_CONST_CACHE_GS_4                                0x289d0
+#define SQ_ALU_CONST_CACHE_GS_5                                0x289d4
+#define SQ_ALU_CONST_CACHE_GS_6                                0x289d8
+#define SQ_ALU_CONST_CACHE_GS_7                                0x289dc
+#define SQ_ALU_CONST_CACHE_GS_8                                0x289e0
+#define SQ_ALU_CONST_CACHE_GS_9                                0x289e4
+#define SQ_ALU_CONST_CACHE_GS_10                       0x289e8
+#define SQ_ALU_CONST_CACHE_GS_11                       0x289ec
+#define SQ_ALU_CONST_CACHE_GS_12                       0x289f0
+#define SQ_ALU_CONST_CACHE_GS_13                       0x289f4
+#define SQ_ALU_CONST_CACHE_GS_14                       0x289f8
+#define SQ_ALU_CONST_CACHE_GS_15                       0x289fc
+#define SQ_ALU_CONST_CACHE_HS_0                                0x28f00
+#define SQ_ALU_CONST_CACHE_HS_1                                0x28f04
+#define SQ_ALU_CONST_CACHE_HS_2                                0x28f08
+#define SQ_ALU_CONST_CACHE_HS_3                                0x28f0c
+#define SQ_ALU_CONST_CACHE_HS_4                                0x28f10
+#define SQ_ALU_CONST_CACHE_HS_5                                0x28f14
+#define SQ_ALU_CONST_CACHE_HS_6                                0x28f18
+#define SQ_ALU_CONST_CACHE_HS_7                                0x28f1c
+#define SQ_ALU_CONST_CACHE_HS_8                                0x28f20
+#define SQ_ALU_CONST_CACHE_HS_9                                0x28f24
+#define SQ_ALU_CONST_CACHE_HS_10                       0x28f28
+#define SQ_ALU_CONST_CACHE_HS_11                       0x28f2c
+#define SQ_ALU_CONST_CACHE_HS_12                       0x28f30
+#define SQ_ALU_CONST_CACHE_HS_13                       0x28f34
+#define SQ_ALU_CONST_CACHE_HS_14                       0x28f38
+#define SQ_ALU_CONST_CACHE_HS_15                       0x28f3c
+#define SQ_ALU_CONST_CACHE_LS_0                                0x28f40
+#define SQ_ALU_CONST_CACHE_LS_1                                0x28f44
+#define SQ_ALU_CONST_CACHE_LS_2                                0x28f48
+#define SQ_ALU_CONST_CACHE_LS_3                                0x28f4c
+#define SQ_ALU_CONST_CACHE_LS_4                                0x28f50
+#define SQ_ALU_CONST_CACHE_LS_5                                0x28f54
+#define SQ_ALU_CONST_CACHE_LS_6                                0x28f58
+#define SQ_ALU_CONST_CACHE_LS_7                                0x28f5c
+#define SQ_ALU_CONST_CACHE_LS_8                                0x28f60
+#define SQ_ALU_CONST_CACHE_LS_9                                0x28f64
+#define SQ_ALU_CONST_CACHE_LS_10                       0x28f68
+#define SQ_ALU_CONST_CACHE_LS_11                       0x28f6c
+#define SQ_ALU_CONST_CACHE_LS_12                       0x28f70
+#define SQ_ALU_CONST_CACHE_LS_13                       0x28f74
+#define SQ_ALU_CONST_CACHE_LS_14                       0x28f78
+#define SQ_ALU_CONST_CACHE_LS_15                       0x28f7c
+
+#define DB_DEPTH_CONTROL                               0x28800
+#define DB_DEPTH_VIEW                                  0x28008
+#define DB_HTILE_DATA_BASE                             0x28014
+#define DB_Z_INFO                                      0x28040
+#       define Z_ARRAY_MODE(x)                          ((x) << 4)
+#define DB_STENCIL_INFO                                        0x28044
+#define DB_Z_READ_BASE                                 0x28048
+#define DB_STENCIL_READ_BASE                           0x2804c
+#define DB_Z_WRITE_BASE                                        0x28050
+#define DB_STENCIL_WRITE_BASE                          0x28054
+#define DB_DEPTH_SIZE                                  0x28058
+
+#define SQ_PGM_START_PS                                        0x28840
+#define SQ_PGM_START_VS                                        0x2885c
+#define SQ_PGM_START_GS                                        0x28874
+#define SQ_PGM_START_ES                                        0x2888c
+#define SQ_PGM_START_FS                                        0x288a4
+#define SQ_PGM_START_HS                                        0x288b8
+#define SQ_PGM_START_LS                                        0x288d0
+
+#define VGT_STRMOUT_CONFIG                             0x28b94
+#define VGT_STRMOUT_BUFFER_CONFIG                      0x28b98
+
+#define CB_TARGET_MASK                                 0x28238
+#define CB_SHADER_MASK                                 0x2823c
+
+#define GDS_ADDR_BASE                                  0x28720
+
+#define        CB_IMMED0_BASE                                  0x28b9c
+#define        CB_IMMED1_BASE                                  0x28ba0
+#define        CB_IMMED2_BASE                                  0x28ba4
+#define        CB_IMMED3_BASE                                  0x28ba8
+#define        CB_IMMED4_BASE                                  0x28bac
+#define        CB_IMMED5_BASE                                  0x28bb0
+#define        CB_IMMED6_BASE                                  0x28bb4
+#define        CB_IMMED7_BASE                                  0x28bb8
+#define        CB_IMMED8_BASE                                  0x28bbc
+#define        CB_IMMED9_BASE                                  0x28bc0
+#define        CB_IMMED10_BASE                                 0x28bc4
+#define        CB_IMMED11_BASE                                 0x28bc8
+
+/* all 12 CB blocks have these regs */
+#define        CB_COLOR0_BASE                                  0x28c60
+#define        CB_COLOR0_PITCH                                 0x28c64
+#define        CB_COLOR0_SLICE                                 0x28c68
+#define        CB_COLOR0_VIEW                                  0x28c6c
+#define        CB_COLOR0_INFO                                  0x28c70
+#       define CB_ARRAY_MODE(x)                         ((x) << 8)
+#       define ARRAY_LINEAR_GENERAL                     0
+#       define ARRAY_LINEAR_ALIGNED                     1
+#       define ARRAY_1D_TILED_THIN1                     2
+#       define ARRAY_2D_TILED_THIN1                     4
+#define        CB_COLOR0_ATTRIB                                0x28c74
+#define        CB_COLOR0_DIM                                   0x28c78
+/* only CB0-7 blocks have these regs */
+#define        CB_COLOR0_CMASK                                 0x28c7c
+#define        CB_COLOR0_CMASK_SLICE                           0x28c80
+#define        CB_COLOR0_FMASK                                 0x28c84
+#define        CB_COLOR0_FMASK_SLICE                           0x28c88
+#define        CB_COLOR0_CLEAR_WORD0                           0x28c8c
+#define        CB_COLOR0_CLEAR_WORD1                           0x28c90
+#define        CB_COLOR0_CLEAR_WORD2                           0x28c94
+#define        CB_COLOR0_CLEAR_WORD3                           0x28c98
+
+#define        CB_COLOR1_BASE                                  0x28c9c
+#define        CB_COLOR2_BASE                                  0x28cd8
+#define        CB_COLOR3_BASE                                  0x28d14
+#define        CB_COLOR4_BASE                                  0x28d50
+#define        CB_COLOR5_BASE                                  0x28d8c
+#define        CB_COLOR6_BASE                                  0x28dc8
+#define        CB_COLOR7_BASE                                  0x28e04
+#define        CB_COLOR8_BASE                                  0x28e40
+#define        CB_COLOR9_BASE                                  0x28e5c
+#define        CB_COLOR10_BASE                                 0x28e78
+#define        CB_COLOR11_BASE                                 0x28e94
+
+#define        CB_COLOR1_PITCH                                 0x28ca0
+#define        CB_COLOR2_PITCH                                 0x28cdc
+#define        CB_COLOR3_PITCH                                 0x28d18
+#define        CB_COLOR4_PITCH                                 0x28d54
+#define        CB_COLOR5_PITCH                                 0x28d90
+#define        CB_COLOR6_PITCH                                 0x28dcc
+#define        CB_COLOR7_PITCH                                 0x28e08
+#define        CB_COLOR8_PITCH                                 0x28e44
+#define        CB_COLOR9_PITCH                                 0x28e60
+#define        CB_COLOR10_PITCH                                0x28e7c
+#define        CB_COLOR11_PITCH                                0x28e98
+
+#define        CB_COLOR1_SLICE                                 0x28ca4
+#define        CB_COLOR2_SLICE                                 0x28ce0
+#define        CB_COLOR3_SLICE                                 0x28d1c
+#define        CB_COLOR4_SLICE                                 0x28d58
+#define        CB_COLOR5_SLICE                                 0x28d94
+#define        CB_COLOR6_SLICE                                 0x28dd0
+#define        CB_COLOR7_SLICE                                 0x28e0c
+#define        CB_COLOR8_SLICE                                 0x28e48
+#define        CB_COLOR9_SLICE                                 0x28e64
+#define        CB_COLOR10_SLICE                                0x28e80
+#define        CB_COLOR11_SLICE                                0x28e9c
+
+#define        CB_COLOR1_VIEW                                  0x28ca8
+#define        CB_COLOR2_VIEW                                  0x28ce4
+#define        CB_COLOR3_VIEW                                  0x28d20
+#define        CB_COLOR4_VIEW                                  0x28d5c
+#define        CB_COLOR5_VIEW                                  0x28d98
+#define        CB_COLOR6_VIEW                                  0x28dd4
+#define        CB_COLOR7_VIEW                                  0x28e10
+#define        CB_COLOR8_VIEW                                  0x28e4c
+#define        CB_COLOR9_VIEW                                  0x28e68
+#define        CB_COLOR10_VIEW                                 0x28e84
+#define        CB_COLOR11_VIEW                                 0x28ea0
+
+#define        CB_COLOR1_INFO                                  0x28cac
+#define        CB_COLOR2_INFO                                  0x28ce8
+#define        CB_COLOR3_INFO                                  0x28d24
+#define        CB_COLOR4_INFO                                  0x28d60
+#define        CB_COLOR5_INFO                                  0x28d9c
+#define        CB_COLOR6_INFO                                  0x28dd8
+#define        CB_COLOR7_INFO                                  0x28e14
+#define        CB_COLOR8_INFO                                  0x28e50
+#define        CB_COLOR9_INFO                                  0x28e6c
+#define        CB_COLOR10_INFO                                 0x28e88
+#define        CB_COLOR11_INFO                                 0x28ea4
+
+#define        CB_COLOR1_ATTRIB                                0x28cb0
+#define        CB_COLOR2_ATTRIB                                0x28cec
+#define        CB_COLOR3_ATTRIB                                0x28d28
+#define        CB_COLOR4_ATTRIB                                0x28d64
+#define        CB_COLOR5_ATTRIB                                0x28da0
+#define        CB_COLOR6_ATTRIB                                0x28ddc
+#define        CB_COLOR7_ATTRIB                                0x28e18
+#define        CB_COLOR8_ATTRIB                                0x28e54
+#define        CB_COLOR9_ATTRIB                                0x28e70
+#define        CB_COLOR10_ATTRIB                               0x28e8c
+#define        CB_COLOR11_ATTRIB                               0x28ea8
+
+#define        CB_COLOR1_DIM                                   0x28cb4
+#define        CB_COLOR2_DIM                                   0x28cf0
+#define        CB_COLOR3_DIM                                   0x28d2c
+#define        CB_COLOR4_DIM                                   0x28d68
+#define        CB_COLOR5_DIM                                   0x28da4
+#define        CB_COLOR6_DIM                                   0x28de0
+#define        CB_COLOR7_DIM                                   0x28e1c
+#define        CB_COLOR8_DIM                                   0x28e58
+#define        CB_COLOR9_DIM                                   0x28e74
+#define        CB_COLOR10_DIM                                  0x28e90
+#define        CB_COLOR11_DIM                                  0x28eac
+
+#define        CB_COLOR1_CMASK                                 0x28cb8
+#define        CB_COLOR2_CMASK                                 0x28cf4
+#define        CB_COLOR3_CMASK                                 0x28d30
+#define        CB_COLOR4_CMASK                                 0x28d6c
+#define        CB_COLOR5_CMASK                                 0x28da8
+#define        CB_COLOR6_CMASK                                 0x28de4
+#define        CB_COLOR7_CMASK                                 0x28e20
+
+#define        CB_COLOR1_CMASK_SLICE                           0x28cbc
+#define        CB_COLOR2_CMASK_SLICE                           0x28cf8
+#define        CB_COLOR3_CMASK_SLICE                           0x28d34
+#define        CB_COLOR4_CMASK_SLICE                           0x28d70
+#define        CB_COLOR5_CMASK_SLICE                           0x28dac
+#define        CB_COLOR6_CMASK_SLICE                           0x28de8
+#define        CB_COLOR7_CMASK_SLICE                           0x28e24
+
+#define        CB_COLOR1_FMASK                                 0x28cc0
+#define        CB_COLOR2_FMASK                                 0x28cfc
+#define        CB_COLOR3_FMASK                                 0x28d38
+#define        CB_COLOR4_FMASK                                 0x28d74
+#define        CB_COLOR5_FMASK                                 0x28db0
+#define        CB_COLOR6_FMASK                                 0x28dec
+#define        CB_COLOR7_FMASK                                 0x28e28
+
+#define        CB_COLOR1_FMASK_SLICE                           0x28cc4
+#define        CB_COLOR2_FMASK_SLICE                           0x28d00
+#define        CB_COLOR3_FMASK_SLICE                           0x28d3c
+#define        CB_COLOR4_FMASK_SLICE                           0x28d78
+#define        CB_COLOR5_FMASK_SLICE                           0x28db4
+#define        CB_COLOR6_FMASK_SLICE                           0x28df0
+#define        CB_COLOR7_FMASK_SLICE                           0x28e2c
+
+#define        CB_COLOR1_CLEAR_WORD0                           0x28cc8
+#define        CB_COLOR2_CLEAR_WORD0                           0x28d04
+#define        CB_COLOR3_CLEAR_WORD0                           0x28d40
+#define        CB_COLOR4_CLEAR_WORD0                           0x28d7c
+#define        CB_COLOR5_CLEAR_WORD0                           0x28db8
+#define        CB_COLOR6_CLEAR_WORD0                           0x28df4
+#define        CB_COLOR7_CLEAR_WORD0                           0x28e30
+
+#define        CB_COLOR1_CLEAR_WORD1                           0x28ccc
+#define        CB_COLOR2_CLEAR_WORD1                           0x28d08
+#define        CB_COLOR3_CLEAR_WORD1                           0x28d44
+#define        CB_COLOR4_CLEAR_WORD1                           0x28d80
+#define        CB_COLOR5_CLEAR_WORD1                           0x28dbc
+#define        CB_COLOR6_CLEAR_WORD1                           0x28df8
+#define        CB_COLOR7_CLEAR_WORD1                           0x28e34
+
+#define        CB_COLOR1_CLEAR_WORD2                           0x28cd0
+#define        CB_COLOR2_CLEAR_WORD2                           0x28d0c
+#define        CB_COLOR3_CLEAR_WORD2                           0x28d48
+#define        CB_COLOR4_CLEAR_WORD2                           0x28d84
+#define        CB_COLOR5_CLEAR_WORD2                           0x28dc0
+#define        CB_COLOR6_CLEAR_WORD2                           0x28dfc
+#define        CB_COLOR7_CLEAR_WORD2                           0x28e38
+
+#define        CB_COLOR1_CLEAR_WORD3                           0x28cd4
+#define        CB_COLOR2_CLEAR_WORD3                           0x28d10
+#define        CB_COLOR3_CLEAR_WORD3                           0x28d4c
+#define        CB_COLOR4_CLEAR_WORD3                           0x28d88
+#define        CB_COLOR5_CLEAR_WORD3                           0x28dc4
+#define        CB_COLOR6_CLEAR_WORD3                           0x28e00
+#define        CB_COLOR7_CLEAR_WORD3                           0x28e3c
+
+#define SQ_TEX_RESOURCE_WORD0_0                         0x30000
+#define SQ_TEX_RESOURCE_WORD1_0                         0x30004
+#       define TEX_ARRAY_MODE(x)                        ((x) << 28)
+#define SQ_TEX_RESOURCE_WORD2_0                         0x30008
+#define SQ_TEX_RESOURCE_WORD3_0                         0x3000C
+#define SQ_TEX_RESOURCE_WORD4_0                         0x30010
+#define SQ_TEX_RESOURCE_WORD5_0                         0x30014
+#define SQ_TEX_RESOURCE_WORD6_0                         0x30018
+#define SQ_TEX_RESOURCE_WORD7_0                         0x3001c
+
+
 #endif
index 44e96a2ae25aa2be1640d491a68570aa1257bae9..e14f59748e65212f628ed7b1a5ed427fa89f7aec 100644 (file)
@@ -475,6 +475,12 @@ void r600_pm_init_profile(struct radeon_device *rdev)
 
 void r600_pm_misc(struct radeon_device *rdev)
 {
+       int requested_index = rdev->pm.requested_power_state_index;
+       struct radeon_power_state *ps = &rdev->pm.power_state[requested_index];
+       struct radeon_voltage *voltage = &ps->clock_info[0].voltage;
+
+       if ((voltage->type == VOLTAGE_SW) && voltage->voltage)
+               radeon_atom_set_voltage(rdev, voltage->voltage);
 
 }
 
index 669feb689bfcdc6df0f8536493c4defc5bd0e42a..5f96fe871b3fdeb13c89c2e8438958c06651ab60 100644 (file)
@@ -176,6 +176,7 @@ void radeon_pm_suspend(struct radeon_device *rdev);
 void radeon_pm_resume(struct radeon_device *rdev);
 void radeon_combios_get_power_modes(struct radeon_device *rdev);
 void radeon_atombios_get_power_modes(struct radeon_device *rdev);
+void radeon_atom_set_voltage(struct radeon_device *rdev, u16 level);
 
 /*
  * Fences.
index e57df08d4aeb9a36eb2f721ddde0f282e7365998..87f7e2cc52d4ef81be592d50891769740d9bf4e8 100644 (file)
@@ -724,8 +724,8 @@ static struct radeon_asic evergreen_asic = {
        .irq_set = &evergreen_irq_set,
        .irq_process = &evergreen_irq_process,
        .get_vblank_counter = &evergreen_get_vblank_counter,
-       .fence_ring_emit = NULL,
-       .cs_parse = NULL,
+       .fence_ring_emit = &r600_fence_ring_emit,
+       .cs_parse = &evergreen_cs_parse,
        .copy_blit = NULL,
        .copy_dma = NULL,
        .copy = NULL,
index 5c40a3dfaca2e936679c7610468521b5c7c93b90..c0bbaa64157a466efb81990431903dc8fbe2dc33 100644 (file)
@@ -314,6 +314,7 @@ void evergreen_hpd_set_polarity(struct radeon_device *rdev,
 u32 evergreen_get_vblank_counter(struct radeon_device *rdev, int crtc);
 int evergreen_irq_set(struct radeon_device *rdev);
 int evergreen_irq_process(struct radeon_device *rdev);
+extern int evergreen_cs_parse(struct radeon_cs_parser *p);
 extern void evergreen_pm_misc(struct radeon_device *rdev);
 extern void evergreen_pm_prepare(struct radeon_device *rdev);
 extern void evergreen_pm_finish(struct radeon_device *rdev);
index 24ea683f7cf53ec5bd2a2958a0a86d95a5185624..4305cd55d0acf6976c54f17e93e860031e74abfe 100644 (file)
@@ -1538,7 +1538,8 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
                                        rdev->pm.power_state[state_index].pcie_lanes =
                                                power_info->info.asPowerPlayInfo[i].ucNumPciELanes;
                                        misc = le32_to_cpu(power_info->info.asPowerPlayInfo[i].ulMiscInfo);
-                                       if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) {
+                                       if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) ||
+                                           (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) {
                                                rdev->pm.power_state[state_index].clock_info[0].voltage.type =
                                                        VOLTAGE_GPIO;
                                                rdev->pm.power_state[state_index].clock_info[0].voltage.gpio =
@@ -1605,7 +1606,8 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
                                                power_info->info_2.asPowerPlayInfo[i].ucNumPciELanes;
                                        misc = le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMiscInfo);
                                        misc2 = le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMiscInfo2);
-                                       if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) {
+                                       if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) ||
+                                           (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) {
                                                rdev->pm.power_state[state_index].clock_info[0].voltage.type =
                                                        VOLTAGE_GPIO;
                                                rdev->pm.power_state[state_index].clock_info[0].voltage.gpio =
@@ -1679,7 +1681,8 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
                                                power_info->info_3.asPowerPlayInfo[i].ucNumPciELanes;
                                        misc = le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMiscInfo);
                                        misc2 = le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMiscInfo2);
-                                       if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) {
+                                       if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) ||
+                                           (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) {
                                                rdev->pm.power_state[state_index].clock_info[0].voltage.type =
                                                        VOLTAGE_GPIO;
                                                rdev->pm.power_state[state_index].clock_info[0].voltage.gpio =
@@ -1755,9 +1758,22 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
                                rdev->pm.power_state[state_index].misc2 = 0;
                        }
                } else {
+                       int fw_index = GetIndexIntoMasterTable(DATA, FirmwareInfo);
+                       uint8_t fw_frev, fw_crev;
+                       uint16_t fw_data_offset, vddc = 0;
+                       union firmware_info *firmware_info;
+                       ATOM_PPLIB_THERMALCONTROLLER *controller = &power_info->info_4.sThermalController;
+
+                       if (atom_parse_data_header(mode_info->atom_context, fw_index, NULL,
+                                                  &fw_frev, &fw_crev, &fw_data_offset)) {
+                               firmware_info =
+                                       (union firmware_info *)(mode_info->atom_context->bios +
+                                                               fw_data_offset);
+                               vddc = firmware_info->info_14.usBootUpVDDCVoltage;
+                       }
+
                        /* add the i2c bus for thermal/fan chip */
                        /* no support for internal controller yet */
-                       ATOM_PPLIB_THERMALCONTROLLER *controller = &power_info->info_4.sThermalController;
                        if (controller->ucType > 0) {
                                if ((controller->ucType == ATOM_PP_THERMALCONTROLLER_RV6xx) ||
                                    (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV770) ||
@@ -1904,6 +1920,16 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
                                                rdev->pm.default_power_state_index = state_index;
                                                rdev->pm.power_state[state_index].default_clock_mode =
                                                        &rdev->pm.power_state[state_index].clock_info[mode_index - 1];
+                                               /* patch the table values with the default slck/mclk from firmware info */
+                                               for (j = 0; j < mode_index; j++) {
+                                                       rdev->pm.power_state[state_index].clock_info[j].mclk =
+                                                               rdev->clock.default_mclk;
+                                                       rdev->pm.power_state[state_index].clock_info[j].sclk =
+                                                               rdev->clock.default_sclk;
+                                                       if (vddc)
+                                                               rdev->pm.power_state[state_index].clock_info[j].voltage.voltage =
+                                                                       vddc;
+                                               }
                                        }
                                        state_index++;
                                }
@@ -1998,6 +2024,42 @@ void radeon_atom_set_memory_clock(struct radeon_device *rdev,
        atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
 }
 
+union set_voltage {
+       struct _SET_VOLTAGE_PS_ALLOCATION alloc;
+       struct _SET_VOLTAGE_PARAMETERS v1;
+       struct _SET_VOLTAGE_PARAMETERS_V2 v2;
+};
+
+void radeon_atom_set_voltage(struct radeon_device *rdev, u16 level)
+{
+       union set_voltage args;
+       int index = GetIndexIntoMasterTable(COMMAND, SetVoltage);
+       u8 frev, crev, volt_index = level;
+
+       if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
+               return;
+
+       switch (crev) {
+       case 1:
+               args.v1.ucVoltageType = SET_VOLTAGE_TYPE_ASIC_VDDC;
+               args.v1.ucVoltageMode = SET_ASIC_VOLTAGE_MODE_ALL_SOURCE;
+               args.v1.ucVoltageIndex = volt_index;
+               break;
+       case 2:
+               args.v2.ucVoltageType = SET_VOLTAGE_TYPE_ASIC_VDDC;
+               args.v2.ucVoltageMode = SET_ASIC_VOLTAGE_MODE_SET_VOLTAGE;
+               args.v2.usVoltageLevel = cpu_to_le16(level);
+               break;
+       default:
+               DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
+               return;
+       }
+
+       atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+}
+
+
+
 void radeon_atom_initialize_bios_scratch_regs(struct drm_device *dev)
 {
        struct radeon_device *rdev = dev->dev_private;
index 7b5e10d3e9c9223556f3319aba979d5cecc19c15..102c744eaf5a14a7ee093c96db24bc2d40c6072d 100644 (file)
@@ -2454,7 +2454,12 @@ default_mode:
        rdev->pm.power_state[state_index].clock_info[0].mclk = rdev->clock.default_mclk;
        rdev->pm.power_state[state_index].clock_info[0].sclk = rdev->clock.default_sclk;
        rdev->pm.power_state[state_index].default_clock_mode = &rdev->pm.power_state[state_index].clock_info[0];
-       rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
+       if ((state_index > 0) &&
+           (rdev->pm.power_state[0].clock_info[0].voltage.type = VOLTAGE_GPIO))
+               rdev->pm.power_state[state_index].clock_info[0].voltage =
+                       rdev->pm.power_state[0].clock_info[0].voltage;
+       else
+               rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
        rdev->pm.power_state[state_index].pcie_lanes = 16;
        rdev->pm.power_state[state_index].flags = 0;
        rdev->pm.default_power_state_index = state_index;
index fdc3fdf78acb3b45dc025ae6598942d032b99bf8..f10faed21567f85feef0d1f097b219002d68b978 100644 (file)
@@ -546,8 +546,10 @@ static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switchero
                /* don't suspend or resume card normally */
                rdev->powered_down = false;
                radeon_resume_kms(dev);
+               drm_kms_helper_poll_enable(dev);
        } else {
                printk(KERN_INFO "radeon: switched off\n");
+               drm_kms_helper_poll_disable(dev);
                radeon_suspend_kms(dev, pmm);
                /* don't suspend or resume card normally */
                rdev->powered_down = true;
@@ -711,6 +713,7 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state)
 {
        struct radeon_device *rdev;
        struct drm_crtc *crtc;
+       struct drm_connector *connector;
        int r;
 
        if (dev == NULL || dev->dev_private == NULL) {
@@ -723,6 +726,12 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state)
 
        if (rdev->powered_down)
                return 0;
+
+       /* turn off display hw */
+       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+               drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
+       }
+
        /* unpin the front buffers */
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
                struct radeon_framebuffer *rfb = to_radeon_framebuffer(crtc->fb);
index a8d162c6f82966e83b482e41187af4a37e2b4957..02281269a88153d4d04b9054233bf7c8320b8e51 100644 (file)
@@ -151,6 +151,7 @@ static void radeon_sync_with_vblank(struct radeon_device *rdev)
 static void radeon_set_power_state(struct radeon_device *rdev)
 {
        u32 sclk, mclk;
+       bool misc_after = false;
 
        if ((rdev->pm.requested_clock_mode_index == rdev->pm.current_clock_mode_index) &&
            (rdev->pm.requested_power_state_index == rdev->pm.current_power_state_index))
@@ -167,55 +168,47 @@ static void radeon_set_power_state(struct radeon_device *rdev)
                if (mclk > rdev->clock.default_mclk)
                        mclk = rdev->clock.default_mclk;
 
-               /* voltage, pcie lanes, etc.*/
-               radeon_pm_misc(rdev);
+               /* upvolt before raising clocks, downvolt after lowering clocks */
+               if (sclk < rdev->pm.current_sclk)
+                       misc_after = true;
 
-               if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
-                       radeon_sync_with_vblank(rdev);
+               radeon_sync_with_vblank(rdev);
 
+               if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
                        if (!radeon_pm_in_vbl(rdev))
                                return;
+               }
 
-                       radeon_pm_prepare(rdev);
-                       /* set engine clock */
-                       if (sclk != rdev->pm.current_sclk) {
-                               radeon_pm_debug_check_in_vbl(rdev, false);
-                               radeon_set_engine_clock(rdev, sclk);
-                               radeon_pm_debug_check_in_vbl(rdev, true);
-                               rdev->pm.current_sclk = sclk;
-                               DRM_DEBUG("Setting: e: %d\n", sclk);
-                       }
+               radeon_pm_prepare(rdev);
 
-                       /* set memory clock */
-                       if (rdev->asic->set_memory_clock && (mclk != rdev->pm.current_mclk)) {
-                               radeon_pm_debug_check_in_vbl(rdev, false);
-                               radeon_set_memory_clock(rdev, mclk);
-                               radeon_pm_debug_check_in_vbl(rdev, true);
-                               rdev->pm.current_mclk = mclk;
-                               DRM_DEBUG("Setting: m: %d\n", mclk);
-                       }
-                       radeon_pm_finish(rdev);
-               } else {
-                       /* set engine clock */
-                       if (sclk != rdev->pm.current_sclk) {
-                               radeon_sync_with_vblank(rdev);
-                               radeon_pm_prepare(rdev);
-                               radeon_set_engine_clock(rdev, sclk);
-                               radeon_pm_finish(rdev);
-                               rdev->pm.current_sclk = sclk;
-                               DRM_DEBUG("Setting: e: %d\n", sclk);
-                       }
-                       /* set memory clock */
-                       if (rdev->asic->set_memory_clock && (mclk != rdev->pm.current_mclk)) {
-                               radeon_sync_with_vblank(rdev);
-                               radeon_pm_prepare(rdev);
-                               radeon_set_memory_clock(rdev, mclk);
-                               radeon_pm_finish(rdev);
-                               rdev->pm.current_mclk = mclk;
-                               DRM_DEBUG("Setting: m: %d\n", mclk);
-                       }
+               if (!misc_after)
+                       /* voltage, pcie lanes, etc.*/
+                       radeon_pm_misc(rdev);
+
+               /* set engine clock */
+               if (sclk != rdev->pm.current_sclk) {
+                       radeon_pm_debug_check_in_vbl(rdev, false);
+                       radeon_set_engine_clock(rdev, sclk);
+                       radeon_pm_debug_check_in_vbl(rdev, true);
+                       rdev->pm.current_sclk = sclk;
+                       DRM_DEBUG("Setting: e: %d\n", sclk);
+               }
+
+               /* set memory clock */
+               if (rdev->asic->set_memory_clock && (mclk != rdev->pm.current_mclk)) {
+                       radeon_pm_debug_check_in_vbl(rdev, false);
+                       radeon_set_memory_clock(rdev, mclk);
+                       radeon_pm_debug_check_in_vbl(rdev, true);
+                       rdev->pm.current_mclk = mclk;
+                       DRM_DEBUG("Setting: m: %d\n", mclk);
                }
 
+               if (misc_after)
+                       /* voltage, pcie lanes, etc.*/
+                       radeon_pm_misc(rdev);
+
+               radeon_pm_finish(rdev);
+
                rdev->pm.current_power_state_index = rdev->pm.requested_power_state_index;
                rdev->pm.current_clock_mode_index = rdev->pm.requested_clock_mode_index;
        } else
diff --git a/drivers/gpu/drm/radeon/reg_srcs/evergreen b/drivers/gpu/drm/radeon/reg_srcs/evergreen
new file mode 100644 (file)
index 0000000..b5c757f
--- /dev/null
@@ -0,0 +1,611 @@
+evergreen 0x9400
+0x00008040 WAIT_UNTIL
+0x00008044 WAIT_UNTIL_POLL_CNTL
+0x00008048 WAIT_UNTIL_POLL_MASK
+0x0000804c WAIT_UNTIL_POLL_REFDATA
+0x000088B0 VGT_VTX_VECT_EJECT_REG
+0x000088C4 VGT_CACHE_INVALIDATION
+0x000088D4 VGT_GS_VERTEX_REUSE
+0x00008958 VGT_PRIMITIVE_TYPE
+0x0000895C VGT_INDEX_TYPE
+0x00008970 VGT_NUM_INDICES
+0x00008974 VGT_NUM_INSTANCES
+0x00008990 VGT_COMPUTE_DIM_X
+0x00008994 VGT_COMPUTE_DIM_Y
+0x00008998 VGT_COMPUTE_DIM_Z
+0x0000899C VGT_COMPUTE_START_X
+0x000089A0 VGT_COMPUTE_START_Y
+0x000089A4 VGT_COMPUTE_START_Z
+0x000089AC VGT_COMPUTE_THREAD_GOURP_SIZE
+0x00008A14 PA_CL_ENHANCE
+0x00008A60 PA_SC_LINE_STIPPLE_VALUE
+0x00008B10 PA_SC_LINE_STIPPLE_STATE
+0x00008BF0 PA_SC_ENHANCE
+0x00008D8C SQ_DYN_GPR_CNTL_PS_FLUSH_REQ
+0x00008C00 SQ_CONFIG
+0x00008C04 SQ_GPR_RESOURCE_MGMT_1
+0x00008C08 SQ_GPR_RESOURCE_MGMT_2
+0x00008C0C SQ_GPR_RESOURCE_MGMT_3
+0x00008C10 SQ_GLOBAL_GPR_RESOURCE_MGMT_1
+0x00008C14 SQ_GLOBAL_GPR_RESOURCE_MGMT_2
+0x00008C18 SQ_THREAD_RESOURCE_MGMT
+0x00008C1C SQ_THREAD_RESOURCE_MGMT_2
+0x00008C20 SQ_STACK_RESOURCE_MGMT_1
+0x00008C24 SQ_STACK_RESOURCE_MGMT_2
+0x00008C28 SQ_STACK_RESOURCE_MGMT_3
+0x00008DF8 SQ_CONST_MEM_BASE
+0x00008E48 SQ_EX_ALLOC_TABLE_SLOTS
+0x00009100 SPI_CONFIG_CNTL
+0x0000913C SPI_CONFIG_CNTL_1
+0x00009700 VC_CNTL
+0x00009714 VC_ENHANCE
+0x00009830 DB_DEBUG
+0x00009834 DB_DEBUG2
+0x00009838 DB_DEBUG3
+0x0000983C DB_DEBUG4
+0x00009854 DB_WATERMARKS
+0x0000A400 TD_PS_BORDER_COLOR_INDEX
+0x0000A404 TD_PS_BORDER_COLOR_RED
+0x0000A408 TD_PS_BORDER_COLOR_GREEN
+0x0000A40C TD_PS_BORDER_COLOR_BLUE
+0x0000A410 TD_PS_BORDER_COLOR_ALPHA
+0x0000A414 TD_VS_BORDER_COLOR_INDEX
+0x0000A418 TD_VS_BORDER_COLOR_RED
+0x0000A41C TD_VS_BORDER_COLOR_GREEN
+0x0000A420 TD_VS_BORDER_COLOR_BLUE
+0x0000A424 TD_VS_BORDER_COLOR_ALPHA
+0x0000A428 TD_GS_BORDER_COLOR_INDEX
+0x0000A42C TD_GS_BORDER_COLOR_RED
+0x0000A430 TD_GS_BORDER_COLOR_GREEN
+0x0000A434 TD_GS_BORDER_COLOR_BLUE
+0x0000A438 TD_GS_BORDER_COLOR_ALPHA
+0x0000A43C TD_HS_BORDER_COLOR_INDEX
+0x0000A440 TD_HS_BORDER_COLOR_RED
+0x0000A444 TD_HS_BORDER_COLOR_GREEN
+0x0000A448 TD_HS_BORDER_COLOR_BLUE
+0x0000A44C TD_HS_BORDER_COLOR_ALPHA
+0x0000A450 TD_LS_BORDER_COLOR_INDEX
+0x0000A454 TD_LS_BORDER_COLOR_RED
+0x0000A458 TD_LS_BORDER_COLOR_GREEN
+0x0000A45C TD_LS_BORDER_COLOR_BLUE
+0x0000A460 TD_LS_BORDER_COLOR_ALPHA
+0x0000A464 TD_CS_BORDER_COLOR_INDEX
+0x0000A468 TD_CS_BORDER_COLOR_RED
+0x0000A46C TD_CS_BORDER_COLOR_GREEN
+0x0000A470 TD_CS_BORDER_COLOR_BLUE
+0x0000A474 TD_CS_BORDER_COLOR_ALPHA
+0x00028000 DB_RENDER_CONTROL
+0x00028004 DB_COUNT_CONTROL
+0x0002800C DB_RENDER_OVERRIDE
+0x00028010 DB_RENDER_OVERRIDE2
+0x00028028 DB_STENCIL_CLEAR
+0x0002802C DB_DEPTH_CLEAR
+0x00028034 PA_SC_SCREEN_SCISSOR_BR
+0x00028030 PA_SC_SCREEN_SCISSOR_TL
+0x0002805C DB_DEPTH_SLICE
+0x00028140 SQ_ALU_CONST_BUFFER_SIZE_PS_0
+0x00028144 SQ_ALU_CONST_BUFFER_SIZE_PS_1
+0x00028148 SQ_ALU_CONST_BUFFER_SIZE_PS_2
+0x0002814C SQ_ALU_CONST_BUFFER_SIZE_PS_3
+0x00028150 SQ_ALU_CONST_BUFFER_SIZE_PS_4
+0x00028154 SQ_ALU_CONST_BUFFER_SIZE_PS_5
+0x00028158 SQ_ALU_CONST_BUFFER_SIZE_PS_6
+0x0002815C SQ_ALU_CONST_BUFFER_SIZE_PS_7
+0x00028160 SQ_ALU_CONST_BUFFER_SIZE_PS_8
+0x00028164 SQ_ALU_CONST_BUFFER_SIZE_PS_9
+0x00028168 SQ_ALU_CONST_BUFFER_SIZE_PS_10
+0x0002816C SQ_ALU_CONST_BUFFER_SIZE_PS_11
+0x00028170 SQ_ALU_CONST_BUFFER_SIZE_PS_12
+0x00028174 SQ_ALU_CONST_BUFFER_SIZE_PS_13
+0x00028178 SQ_ALU_CONST_BUFFER_SIZE_PS_14
+0x0002817C SQ_ALU_CONST_BUFFER_SIZE_PS_15
+0x00028180 SQ_ALU_CONST_BUFFER_SIZE_VS_0
+0x00028184 SQ_ALU_CONST_BUFFER_SIZE_VS_1
+0x00028188 SQ_ALU_CONST_BUFFER_SIZE_VS_2
+0x0002818C SQ_ALU_CONST_BUFFER_SIZE_VS_3
+0x00028190 SQ_ALU_CONST_BUFFER_SIZE_VS_4
+0x00028194 SQ_ALU_CONST_BUFFER_SIZE_VS_5
+0x00028198 SQ_ALU_CONST_BUFFER_SIZE_VS_6
+0x0002819C SQ_ALU_CONST_BUFFER_SIZE_VS_7
+0x000281A0 SQ_ALU_CONST_BUFFER_SIZE_VS_8
+0x000281A4 SQ_ALU_CONST_BUFFER_SIZE_VS_9
+0x000281A8 SQ_ALU_CONST_BUFFER_SIZE_VS_10
+0x000281AC SQ_ALU_CONST_BUFFER_SIZE_VS_11
+0x000281B0 SQ_ALU_CONST_BUFFER_SIZE_VS_12
+0x000281B4 SQ_ALU_CONST_BUFFER_SIZE_VS_13
+0x000281B8 SQ_ALU_CONST_BUFFER_SIZE_VS_14
+0x000281BC SQ_ALU_CONST_BUFFER_SIZE_VS_15
+0x000281C0 SQ_ALU_CONST_BUFFER_SIZE_GS_0
+0x000281C4 SQ_ALU_CONST_BUFFER_SIZE_GS_1
+0x000281C8 SQ_ALU_CONST_BUFFER_SIZE_GS_2
+0x000281CC SQ_ALU_CONST_BUFFER_SIZE_GS_3
+0x000281D0 SQ_ALU_CONST_BUFFER_SIZE_GS_4
+0x000281D4 SQ_ALU_CONST_BUFFER_SIZE_GS_5
+0x000281D8 SQ_ALU_CONST_BUFFER_SIZE_GS_6
+0x000281DC SQ_ALU_CONST_BUFFER_SIZE_GS_7
+0x000281E0 SQ_ALU_CONST_BUFFER_SIZE_GS_8
+0x000281E4 SQ_ALU_CONST_BUFFER_SIZE_GS_9
+0x000281E8 SQ_ALU_CONST_BUFFER_SIZE_GS_10
+0x000281EC SQ_ALU_CONST_BUFFER_SIZE_GS_11
+0x000281F0 SQ_ALU_CONST_BUFFER_SIZE_GS_12
+0x000281F4 SQ_ALU_CONST_BUFFER_SIZE_GS_13
+0x000281F8 SQ_ALU_CONST_BUFFER_SIZE_GS_14
+0x000281FC SQ_ALU_CONST_BUFFER_SIZE_GS_15
+0x00028200 PA_SC_WINDOW_OFFSET
+0x00028204 PA_SC_WINDOW_SCISSOR_TL
+0x00028208 PA_SC_WINDOW_SCISSOR_BR
+0x0002820C PA_SC_CLIPRECT_RULE
+0x00028210 PA_SC_CLIPRECT_0_TL
+0x00028214 PA_SC_CLIPRECT_0_BR
+0x00028218 PA_SC_CLIPRECT_1_TL
+0x0002821C PA_SC_CLIPRECT_1_BR
+0x00028220 PA_SC_CLIPRECT_2_TL
+0x00028224 PA_SC_CLIPRECT_2_BR
+0x00028228 PA_SC_CLIPRECT_3_TL
+0x0002822C PA_SC_CLIPRECT_3_BR
+0x00028230 PA_SC_EDGERULE
+0x00028234 PA_SU_HARDWARE_SCREEN_OFFSET
+0x00028240 PA_SC_GENERIC_SCISSOR_TL
+0x00028244 PA_SC_GENERIC_SCISSOR_BR
+0x00028250 PA_SC_VPORT_SCISSOR_0_TL
+0x00028254 PA_SC_VPORT_SCISSOR_0_BR
+0x00028258 PA_SC_VPORT_SCISSOR_1_TL
+0x0002825C PA_SC_VPORT_SCISSOR_1_BR
+0x00028260 PA_SC_VPORT_SCISSOR_2_TL
+0x00028264 PA_SC_VPORT_SCISSOR_2_BR
+0x00028268 PA_SC_VPORT_SCISSOR_3_TL
+0x0002826C PA_SC_VPORT_SCISSOR_3_BR
+0x00028270 PA_SC_VPORT_SCISSOR_4_TL
+0x00028274 PA_SC_VPORT_SCISSOR_4_BR
+0x00028278 PA_SC_VPORT_SCISSOR_5_TL
+0x0002827C PA_SC_VPORT_SCISSOR_5_BR
+0x00028280 PA_SC_VPORT_SCISSOR_6_TL
+0x00028284 PA_SC_VPORT_SCISSOR_6_BR
+0x00028288 PA_SC_VPORT_SCISSOR_7_TL
+0x0002828C PA_SC_VPORT_SCISSOR_7_BR
+0x00028290 PA_SC_VPORT_SCISSOR_8_TL
+0x00028294 PA_SC_VPORT_SCISSOR_8_BR
+0x00028298 PA_SC_VPORT_SCISSOR_9_TL
+0x0002829C PA_SC_VPORT_SCISSOR_9_BR
+0x000282A0 PA_SC_VPORT_SCISSOR_10_TL
+0x000282A4 PA_SC_VPORT_SCISSOR_10_BR
+0x000282A8 PA_SC_VPORT_SCISSOR_11_TL
+0x000282AC PA_SC_VPORT_SCISSOR_11_BR
+0x000282B0 PA_SC_VPORT_SCISSOR_12_TL
+0x000282B4 PA_SC_VPORT_SCISSOR_12_BR
+0x000282B8 PA_SC_VPORT_SCISSOR_13_TL
+0x000282BC PA_SC_VPORT_SCISSOR_13_BR
+0x000282C0 PA_SC_VPORT_SCISSOR_14_TL
+0x000282C4 PA_SC_VPORT_SCISSOR_14_BR
+0x000282C8 PA_SC_VPORT_SCISSOR_15_TL
+0x000282CC PA_SC_VPORT_SCISSOR_15_BR
+0x000282D0 PA_SC_VPORT_ZMIN_0
+0x000282D4 PA_SC_VPORT_ZMAX_0
+0x000282D8 PA_SC_VPORT_ZMIN_1
+0x000282DC PA_SC_VPORT_ZMAX_1
+0x000282E0 PA_SC_VPORT_ZMIN_2
+0x000282E4 PA_SC_VPORT_ZMAX_2
+0x000282E8 PA_SC_VPORT_ZMIN_3
+0x000282EC PA_SC_VPORT_ZMAX_3
+0x000282F0 PA_SC_VPORT_ZMIN_4
+0x000282F4 PA_SC_VPORT_ZMAX_4
+0x000282F8 PA_SC_VPORT_ZMIN_5
+0x000282FC PA_SC_VPORT_ZMAX_5
+0x00028300 PA_SC_VPORT_ZMIN_6
+0x00028304 PA_SC_VPORT_ZMAX_6
+0x00028308 PA_SC_VPORT_ZMIN_7
+0x0002830C PA_SC_VPORT_ZMAX_7
+0x00028310 PA_SC_VPORT_ZMIN_8
+0x00028314 PA_SC_VPORT_ZMAX_8
+0x00028318 PA_SC_VPORT_ZMIN_9
+0x0002831C PA_SC_VPORT_ZMAX_9
+0x00028320 PA_SC_VPORT_ZMIN_10
+0x00028324 PA_SC_VPORT_ZMAX_10
+0x00028328 PA_SC_VPORT_ZMIN_11
+0x0002832C PA_SC_VPORT_ZMAX_11
+0x00028330 PA_SC_VPORT_ZMIN_12
+0x00028334 PA_SC_VPORT_ZMAX_12
+0x00028338 PA_SC_VPORT_ZMIN_13
+0x0002833C PA_SC_VPORT_ZMAX_13
+0x00028340 PA_SC_VPORT_ZMIN_14
+0x00028344 PA_SC_VPORT_ZMAX_14
+0x00028348 PA_SC_VPORT_ZMIN_15
+0x0002834C PA_SC_VPORT_ZMAX_15
+0x00028350 SX_MISC
+0x00028380 SQ_VTX_SEMANTIC_0
+0x00028384 SQ_VTX_SEMANTIC_1
+0x00028388 SQ_VTX_SEMANTIC_2
+0x0002838C SQ_VTX_SEMANTIC_3
+0x00028390 SQ_VTX_SEMANTIC_4
+0x00028394 SQ_VTX_SEMANTIC_5
+0x00028398 SQ_VTX_SEMANTIC_6
+0x0002839C SQ_VTX_SEMANTIC_7
+0x000283A0 SQ_VTX_SEMANTIC_8
+0x000283A4 SQ_VTX_SEMANTIC_9
+0x000283A8 SQ_VTX_SEMANTIC_10
+0x000283AC SQ_VTX_SEMANTIC_11
+0x000283B0 SQ_VTX_SEMANTIC_12
+0x000283B4 SQ_VTX_SEMANTIC_13
+0x000283B8 SQ_VTX_SEMANTIC_14
+0x000283BC SQ_VTX_SEMANTIC_15
+0x000283C0 SQ_VTX_SEMANTIC_16
+0x000283C4 SQ_VTX_SEMANTIC_17
+0x000283C8 SQ_VTX_SEMANTIC_18
+0x000283CC SQ_VTX_SEMANTIC_19
+0x000283D0 SQ_VTX_SEMANTIC_20
+0x000283D4 SQ_VTX_SEMANTIC_21
+0x000283D8 SQ_VTX_SEMANTIC_22
+0x000283DC SQ_VTX_SEMANTIC_23
+0x000283E0 SQ_VTX_SEMANTIC_24
+0x000283E4 SQ_VTX_SEMANTIC_25
+0x000283E8 SQ_VTX_SEMANTIC_26
+0x000283EC SQ_VTX_SEMANTIC_27
+0x000283F0 SQ_VTX_SEMANTIC_28
+0x000283F4 SQ_VTX_SEMANTIC_29
+0x000283F8 SQ_VTX_SEMANTIC_30
+0x000283FC SQ_VTX_SEMANTIC_31
+0x00028400 VGT_MAX_VTX_INDX
+0x00028404 VGT_MIN_VTX_INDX
+0x00028408 VGT_INDX_OFFSET
+0x0002840C VGT_MULTI_PRIM_IB_RESET_INDX
+0x00028410 SX_ALPHA_TEST_CONTROL
+0x00028414 CB_BLEND_RED
+0x00028418 CB_BLEND_GREEN
+0x0002841C CB_BLEND_BLUE
+0x00028420 CB_BLEND_ALPHA
+0x00028430 DB_STENCILREFMASK
+0x00028434 DB_STENCILREFMASK_BF
+0x00028438 SX_ALPHA_REF
+0x0002843C PA_CL_VPORT_XSCALE_0
+0x00028440 PA_CL_VPORT_XOFFSET_0
+0x00028444 PA_CL_VPORT_YSCALE_0
+0x00028448 PA_CL_VPORT_YOFFSET_0
+0x0002844C PA_CL_VPORT_ZSCALE_0
+0x00028450 PA_CL_VPORT_ZOFFSET_0
+0x00028454 PA_CL_VPORT_XSCALE_1
+0x00028458 PA_CL_VPORT_XOFFSET_1
+0x0002845C PA_CL_VPORT_YSCALE_1
+0x00028460 PA_CL_VPORT_YOFFSET_1
+0x00028464 PA_CL_VPORT_ZSCALE_1
+0x00028468 PA_CL_VPORT_ZOFFSET_1
+0x0002846C PA_CL_VPORT_XSCALE_2
+0x00028470 PA_CL_VPORT_XOFFSET_2
+0x00028474 PA_CL_VPORT_YSCALE_2
+0x00028478 PA_CL_VPORT_YOFFSET_2
+0x0002847C PA_CL_VPORT_ZSCALE_2
+0x00028480 PA_CL_VPORT_ZOFFSET_2
+0x00028484 PA_CL_VPORT_XSCALE_3
+0x00028488 PA_CL_VPORT_XOFFSET_3
+0x0002848C PA_CL_VPORT_YSCALE_3
+0x00028490 PA_CL_VPORT_YOFFSET_3
+0x00028494 PA_CL_VPORT_ZSCALE_3
+0x00028498 PA_CL_VPORT_ZOFFSET_3
+0x0002849C PA_CL_VPORT_XSCALE_4
+0x000284A0 PA_CL_VPORT_XOFFSET_4
+0x000284A4 PA_CL_VPORT_YSCALE_4
+0x000284A8 PA_CL_VPORT_YOFFSET_4
+0x000284AC PA_CL_VPORT_ZSCALE_4
+0x000284B0 PA_CL_VPORT_ZOFFSET_4
+0x000284B4 PA_CL_VPORT_XSCALE_5
+0x000284B8 PA_CL_VPORT_XOFFSET_5
+0x000284BC PA_CL_VPORT_YSCALE_5
+0x000284C0 PA_CL_VPORT_YOFFSET_5
+0x000284C4 PA_CL_VPORT_ZSCALE_5
+0x000284C8 PA_CL_VPORT_ZOFFSET_5
+0x000284CC PA_CL_VPORT_XSCALE_6
+0x000284D0 PA_CL_VPORT_XOFFSET_6
+0x000284D4 PA_CL_VPORT_YSCALE_6
+0x000284D8 PA_CL_VPORT_YOFFSET_6
+0x000284DC PA_CL_VPORT_ZSCALE_6
+0x000284E0 PA_CL_VPORT_ZOFFSET_6
+0x000284E4 PA_CL_VPORT_XSCALE_7
+0x000284E8 PA_CL_VPORT_XOFFSET_7
+0x000284EC PA_CL_VPORT_YSCALE_7
+0x000284F0 PA_CL_VPORT_YOFFSET_7
+0x000284F4 PA_CL_VPORT_ZSCALE_7
+0x000284F8 PA_CL_VPORT_ZOFFSET_7
+0x000284FC PA_CL_VPORT_XSCALE_8
+0x00028500 PA_CL_VPORT_XOFFSET_8
+0x00028504 PA_CL_VPORT_YSCALE_8
+0x00028508 PA_CL_VPORT_YOFFSET_8
+0x0002850C PA_CL_VPORT_ZSCALE_8
+0x00028510 PA_CL_VPORT_ZOFFSET_8
+0x00028514 PA_CL_VPORT_XSCALE_9
+0x00028518 PA_CL_VPORT_XOFFSET_9
+0x0002851C PA_CL_VPORT_YSCALE_9
+0x00028520 PA_CL_VPORT_YOFFSET_9
+0x00028524 PA_CL_VPORT_ZSCALE_9
+0x00028528 PA_CL_VPORT_ZOFFSET_9
+0x0002852C PA_CL_VPORT_XSCALE_10
+0x00028530 PA_CL_VPORT_XOFFSET_10
+0x00028534 PA_CL_VPORT_YSCALE_10
+0x00028538 PA_CL_VPORT_YOFFSET_10
+0x0002853C PA_CL_VPORT_ZSCALE_10
+0x00028540 PA_CL_VPORT_ZOFFSET_10
+0x00028544 PA_CL_VPORT_XSCALE_11
+0x00028548 PA_CL_VPORT_XOFFSET_11
+0x0002854C PA_CL_VPORT_YSCALE_11
+0x00028550 PA_CL_VPORT_YOFFSET_11
+0x00028554 PA_CL_VPORT_ZSCALE_11
+0x00028558 PA_CL_VPORT_ZOFFSET_11
+0x0002855C PA_CL_VPORT_XSCALE_12
+0x00028560 PA_CL_VPORT_XOFFSET_12
+0x00028564 PA_CL_VPORT_YSCALE_12
+0x00028568 PA_CL_VPORT_YOFFSET_12
+0x0002856C PA_CL_VPORT_ZSCALE_12
+0x00028570 PA_CL_VPORT_ZOFFSET_12
+0x00028574 PA_CL_VPORT_XSCALE_13
+0x00028578 PA_CL_VPORT_XOFFSET_13
+0x0002857C PA_CL_VPORT_YSCALE_13
+0x00028580 PA_CL_VPORT_YOFFSET_13
+0x00028584 PA_CL_VPORT_ZSCALE_13
+0x00028588 PA_CL_VPORT_ZOFFSET_13
+0x0002858C PA_CL_VPORT_XSCALE_14
+0x00028590 PA_CL_VPORT_XOFFSET_14
+0x00028594 PA_CL_VPORT_YSCALE_14
+0x00028598 PA_CL_VPORT_YOFFSET_14
+0x0002859C PA_CL_VPORT_ZSCALE_14
+0x000285A0 PA_CL_VPORT_ZOFFSET_14
+0x000285A4 PA_CL_VPORT_XSCALE_15
+0x000285A8 PA_CL_VPORT_XOFFSET_15
+0x000285AC PA_CL_VPORT_YSCALE_15
+0x000285B0 PA_CL_VPORT_YOFFSET_15
+0x000285B4 PA_CL_VPORT_ZSCALE_15
+0x000285B8 PA_CL_VPORT_ZOFFSET_15
+0x000285BC PA_CL_UCP_0_X
+0x000285C0 PA_CL_UCP_0_Y
+0x000285C4 PA_CL_UCP_0_Z
+0x000285C8 PA_CL_UCP_0_W
+0x000285CC PA_CL_UCP_1_X
+0x000285D0 PA_CL_UCP_1_Y
+0x000285D4 PA_CL_UCP_1_Z
+0x000285D8 PA_CL_UCP_1_W
+0x000285DC PA_CL_UCP_2_X
+0x000285E0 PA_CL_UCP_2_Y
+0x000285E4 PA_CL_UCP_2_Z
+0x000285E8 PA_CL_UCP_2_W
+0x000285EC PA_CL_UCP_3_X
+0x000285F0 PA_CL_UCP_3_Y
+0x000285F4 PA_CL_UCP_3_Z
+0x000285F8 PA_CL_UCP_3_W
+0x000285FC PA_CL_UCP_4_X
+0x00028600 PA_CL_UCP_4_Y
+0x00028604 PA_CL_UCP_4_Z
+0x00028608 PA_CL_UCP_4_W
+0x0002860C PA_CL_UCP_5_X
+0x00028610 PA_CL_UCP_5_Y
+0x00028614 PA_CL_UCP_5_Z
+0x00028618 PA_CL_UCP_5_W
+0x0002861C SPI_VS_OUT_ID_0
+0x00028620 SPI_VS_OUT_ID_1
+0x00028624 SPI_VS_OUT_ID_2
+0x00028628 SPI_VS_OUT_ID_3
+0x0002862C SPI_VS_OUT_ID_4
+0x00028630 SPI_VS_OUT_ID_5
+0x00028634 SPI_VS_OUT_ID_6
+0x00028638 SPI_VS_OUT_ID_7
+0x0002863C SPI_VS_OUT_ID_8
+0x00028640 SPI_VS_OUT_ID_9
+0x00028644 SPI_PS_INPUT_CNTL_0
+0x00028648 SPI_PS_INPUT_CNTL_1
+0x0002864C SPI_PS_INPUT_CNTL_2
+0x00028650 SPI_PS_INPUT_CNTL_3
+0x00028654 SPI_PS_INPUT_CNTL_4
+0x00028658 SPI_PS_INPUT_CNTL_5
+0x0002865C SPI_PS_INPUT_CNTL_6
+0x00028660 SPI_PS_INPUT_CNTL_7
+0x00028664 SPI_PS_INPUT_CNTL_8
+0x00028668 SPI_PS_INPUT_CNTL_9
+0x0002866C SPI_PS_INPUT_CNTL_10
+0x00028670 SPI_PS_INPUT_CNTL_11
+0x00028674 SPI_PS_INPUT_CNTL_12
+0x00028678 SPI_PS_INPUT_CNTL_13
+0x0002867C SPI_PS_INPUT_CNTL_14
+0x00028680 SPI_PS_INPUT_CNTL_15
+0x00028684 SPI_PS_INPUT_CNTL_16
+0x00028688 SPI_PS_INPUT_CNTL_17
+0x0002868C SPI_PS_INPUT_CNTL_18
+0x00028690 SPI_PS_INPUT_CNTL_19
+0x00028694 SPI_PS_INPUT_CNTL_20
+0x00028698 SPI_PS_INPUT_CNTL_21
+0x0002869C SPI_PS_INPUT_CNTL_22
+0x000286A0 SPI_PS_INPUT_CNTL_23
+0x000286A4 SPI_PS_INPUT_CNTL_24
+0x000286A8 SPI_PS_INPUT_CNTL_25
+0x000286AC SPI_PS_INPUT_CNTL_26
+0x000286B0 SPI_PS_INPUT_CNTL_27
+0x000286B4 SPI_PS_INPUT_CNTL_28
+0x000286B8 SPI_PS_INPUT_CNTL_29
+0x000286BC SPI_PS_INPUT_CNTL_30
+0x000286C0 SPI_PS_INPUT_CNTL_31
+0x000286C4 SPI_VS_OUT_CONFIG
+0x000286C8 SPI_THREAD_GROUPING
+0x000286CC SPI_PS_IN_CONTROL_0
+0x000286D0 SPI_PS_IN_CONTROL_1
+0x000286D4 SPI_INTERP_CONTROL_0
+0x000286D8 SPI_INPUT_Z
+0x000286DC SPI_FOG_CNTL
+0x000286E0 SPI_BARYC_CNTL
+0x000286E4 SPI_PS_IN_CONTROL_2
+0x000286E8 SPI_COMPUTE_INPUT_CNTL
+0x000286EC SPI_COMPUTE_NUM_THREAD_X
+0x000286F0 SPI_COMPUTE_NUM_THREAD_Y
+0x000286F4 SPI_COMPUTE_NUM_THREAD_Z
+0x000286F8 GDS_ADDR_SIZE
+0x00028780 CB_BLEND0_CONTROL
+0x00028784 CB_BLEND1_CONTROL
+0x00028788 CB_BLEND2_CONTROL
+0x0002878C CB_BLEND3_CONTROL
+0x00028790 CB_BLEND4_CONTROL
+0x00028794 CB_BLEND5_CONTROL
+0x00028798 CB_BLEND6_CONTROL
+0x0002879C CB_BLEND7_CONTROL
+0x000287CC CS_COPY_STATE
+0x000287D0 GFX_COPY_STATE
+0x000287D4 PA_CL_POINT_X_RAD
+0x000287D8 PA_CL_POINT_Y_RAD
+0x000287DC PA_CL_POINT_SIZE
+0x000287E0 PA_CL_POINT_CULL_RAD
+0x00028808 CB_COLOR_CONTROL
+0x0002880C DB_SHADER_CONTROL
+0x00028810 PA_CL_CLIP_CNTL
+0x00028814 PA_SU_SC_MODE_CNTL
+0x00028818 PA_CL_VTE_CNTL
+0x0002881C PA_CL_VS_OUT_CNTL
+0x00028820 PA_CL_NANINF_CNTL
+0x00028824 PA_SU_LINE_STIPPLE_CNTL
+0x00028828 PA_SU_LINE_STIPPLE_SCALE
+0x0002882C PA_SU_PRIM_FILTER_CNTL
+0x00028838 SQ_DYN_GPR_RESOURCE_LIMIT_1
+0x00028844 SQ_PGM_RESOURCES_PS
+0x00028848 SQ_PGM_RESOURCES_2_PS
+0x0002884C SQ_PGM_EXPORTS_PS
+0x0002885C SQ_PGM_RESOURCES_VS
+0x00028860 SQ_PGM_RESOURCES_2_VS
+0x00028878 SQ_PGM_RESOURCES_GS
+0x0002887C SQ_PGM_RESOURCES_2_GS
+0x00028890 SQ_PGM_RESOURCES_ES
+0x00028894 SQ_PGM_RESOURCES_2_ES
+0x000288A8 SQ_PGM_RESOURCES_FS
+0x000288BC SQ_PGM_RESOURCES_HS
+0x000288C0 SQ_PGM_RESOURCES_2_HS
+0x000288D0 SQ_PGM_RESOURCES_LS
+0x000288D4 SQ_PGM_RESOURCES_2_LS
+0x000288E8 SQ_LDS_ALLOC
+0x000288EC SQ_LDS_ALLOC_PS
+0x000288F0 SQ_VTX_SEMANTIC_CLEAR
+0x00028A00 PA_SU_POINT_SIZE
+0x00028A04 PA_SU_POINT_MINMAX
+0x00028A08 PA_SU_LINE_CNTL
+0x00028A0C PA_SC_LINE_STIPPLE
+0x00028A10 VGT_OUTPUT_PATH_CNTL
+0x00028A14 VGT_HOS_CNTL
+0x00028A18 VGT_HOS_MAX_TESS_LEVEL
+0x00028A1C VGT_HOS_MIN_TESS_LEVEL
+0x00028A20 VGT_HOS_REUSE_DEPTH
+0x00028A24 VGT_GROUP_PRIM_TYPE
+0x00028A28 VGT_GROUP_FIRST_DECR
+0x00028A2C VGT_GROUP_DECR
+0x00028A30 VGT_GROUP_VECT_0_CNTL
+0x00028A34 VGT_GROUP_VECT_1_CNTL
+0x00028A38 VGT_GROUP_VECT_0_FMT_CNTL
+0x00028A3C VGT_GROUP_VECT_1_FMT_CNTL
+0x00028A40 VGT_GS_MODE
+0x00028A48 PA_SC_MODE_CNTL_0
+0x00028A4C PA_SC_MODE_CNTL_1
+0x00028A50 VGT_ENHANCE
+0x00028A54 VGT_GS_PER_ES
+0x00028A58 VGT_ES_PER_GS
+0x00028A5C VGT_GS_PER_VS
+0x00028A6C VGT_GS_OUT_PRIM_TYPE
+0x00028A84 VGT_PRIMITIVEID_EN
+0x00028A94 VGT_MULTI_PRIM_IB_RESET_EN
+0x00028AA0 VGT_INSTANCE_STEP_RATE_0
+0x00028AA4 VGT_INSTANCE_STEP_RATE_1
+0x00028AB4 VGT_REUSE_OFF
+0x00028AB8 VGT_VTX_CNT_EN
+0x00028ABC DB_HTILE_SURFACE
+0x00028AC0 DB_SRESULTS_COMPARE_STATE0
+0x00028AC4 DB_SRESULTS_COMPARE_STATE1
+0x00028AC8 DB_PRELOAD_CONTROL
+0x00028B38 VGT_GS_MAX_VERT_OUT
+0x00028B54 VGT_SHADER_STAGES_EN
+0x00028B58 VGT_LS_HS_CONFIG
+0x00028B5C VGT_LS_SIZE
+0x00028B60 VGT_HS_SIZE
+0x00028B64 VGT_LS_HS_ALLOC
+0x00028B68 VGT_HS_PATCH_CONST
+0x00028B6C VGT_TF_PARAM
+0x00028B70 DB_ALPHA_TO_MASK
+0x00028B74 VGT_DISPATCH_INITIATOR
+0x00028B78 PA_SU_POLY_OFFSET_DB_FMT_CNTL
+0x00028B7C PA_SU_POLY_OFFSET_CLAMP
+0x00028B80 PA_SU_POLY_OFFSET_FRONT_SCALE
+0x00028B84 PA_SU_POLY_OFFSET_FRONT_OFFSET
+0x00028B88 PA_SU_POLY_OFFSET_BACK_SCALE
+0x00028B8C PA_SU_POLY_OFFSET_BACK_OFFSET
+0x00028B74 VGT_GS_INSTANCE_CNT
+0x00028C00 PA_SC_LINE_CNTL
+0x00028C08 PA_SU_VTX_CNTL
+0x00028C0C PA_CL_GB_VERT_CLIP_ADJ
+0x00028C10 PA_CL_GB_VERT_DISC_ADJ
+0x00028C14 PA_CL_GB_HORZ_CLIP_ADJ
+0x00028C18 PA_CL_GB_HORZ_DISC_ADJ
+0x00028C1C PA_SC_AA_SAMPLE_LOCS_0
+0x00028C20 PA_SC_AA_SAMPLE_LOCS_1
+0x00028C24 PA_SC_AA_SAMPLE_LOCS_2
+0x00028C28 PA_SC_AA_SAMPLE_LOCS_3
+0x00028C2C PA_SC_AA_SAMPLE_LOCS_4
+0x00028C30 PA_SC_AA_SAMPLE_LOCS_5
+0x00028C34 PA_SC_AA_SAMPLE_LOCS_6
+0x00028C38 PA_SC_AA_SAMPLE_LOCS_7
+0x00028C3C PA_SC_AA_MASK
+0x00028C8C CB_COLOR0_CLEAR_WORD0
+0x00028C90 CB_COLOR0_CLEAR_WORD1
+0x00028C94 CB_COLOR0_CLEAR_WORD2
+0x00028C98 CB_COLOR0_CLEAR_WORD3
+0x00028CC8 CB_COLOR1_CLEAR_WORD0
+0x00028CCC CB_COLOR1_CLEAR_WORD1
+0x00028CD0 CB_COLOR1_CLEAR_WORD2
+0x00028CD4 CB_COLOR1_CLEAR_WORD3
+0x00028D04 CB_COLOR2_CLEAR_WORD0
+0x00028D08 CB_COLOR2_CLEAR_WORD1
+0x00028D0C CB_COLOR2_CLEAR_WORD2
+0x00028D10 CB_COLOR2_CLEAR_WORD3
+0x00028D40 CB_COLOR3_CLEAR_WORD0
+0x00028D44 CB_COLOR3_CLEAR_WORD1
+0x00028D48 CB_COLOR3_CLEAR_WORD2
+0x00028D4C CB_COLOR3_CLEAR_WORD3
+0x00028D7C CB_COLOR4_CLEAR_WORD0
+0x00028D80 CB_COLOR4_CLEAR_WORD1
+0x00028D84 CB_COLOR4_CLEAR_WORD2
+0x00028D88 CB_COLOR4_CLEAR_WORD3
+0x00028DB8 CB_COLOR5_CLEAR_WORD0
+0x00028DBC CB_COLOR5_CLEAR_WORD1
+0x00028DC0 CB_COLOR5_CLEAR_WORD2
+0x00028DC4 CB_COLOR5_CLEAR_WORD3
+0x00028DF4 CB_COLOR6_CLEAR_WORD0
+0x00028DF8 CB_COLOR6_CLEAR_WORD1
+0x00028DFC CB_COLOR6_CLEAR_WORD2
+0x00028E00 CB_COLOR6_CLEAR_WORD3
+0x00028E30 CB_COLOR7_CLEAR_WORD0
+0x00028E34 CB_COLOR7_CLEAR_WORD1
+0x00028E38 CB_COLOR7_CLEAR_WORD2
+0x00028E3C CB_COLOR7_CLEAR_WORD3
+0x00028F80 SQ_ALU_CONST_BUFFER_SIZE_HS_0
+0x00028F84 SQ_ALU_CONST_BUFFER_SIZE_HS_1
+0x00028F88 SQ_ALU_CONST_BUFFER_SIZE_HS_2
+0x00028F8C SQ_ALU_CONST_BUFFER_SIZE_HS_3
+0x00028F90 SQ_ALU_CONST_BUFFER_SIZE_HS_4
+0x00028F94 SQ_ALU_CONST_BUFFER_SIZE_HS_5
+0x00028F98 SQ_ALU_CONST_BUFFER_SIZE_HS_6
+0x00028F9C SQ_ALU_CONST_BUFFER_SIZE_HS_7
+0x00028FA0 SQ_ALU_CONST_BUFFER_SIZE_HS_8
+0x00028FA4 SQ_ALU_CONST_BUFFER_SIZE_HS_9
+0x00028FA8 SQ_ALU_CONST_BUFFER_SIZE_HS_10
+0x00028FAC SQ_ALU_CONST_BUFFER_SIZE_HS_11
+0x00028FB0 SQ_ALU_CONST_BUFFER_SIZE_HS_12
+0x00028FB4 SQ_ALU_CONST_BUFFER_SIZE_HS_13
+0x00028FB8 SQ_ALU_CONST_BUFFER_SIZE_HS_14
+0x00028FBC SQ_ALU_CONST_BUFFER_SIZE_HS_15
+0x00028FC0 SQ_ALU_CONST_BUFFER_SIZE_LS_0
+0x00028FC4 SQ_ALU_CONST_BUFFER_SIZE_LS_1
+0x00028FC8 SQ_ALU_CONST_BUFFER_SIZE_LS_2
+0x00028FCC SQ_ALU_CONST_BUFFER_SIZE_LS_3
+0x00028FD0 SQ_ALU_CONST_BUFFER_SIZE_LS_4
+0x00028FD4 SQ_ALU_CONST_BUFFER_SIZE_LS_5
+0x00028FD8 SQ_ALU_CONST_BUFFER_SIZE_LS_6
+0x00028FDC SQ_ALU_CONST_BUFFER_SIZE_LS_7
+0x00028FE0 SQ_ALU_CONST_BUFFER_SIZE_LS_8
+0x00028FE4 SQ_ALU_CONST_BUFFER_SIZE_LS_9
+0x00028FE8 SQ_ALU_CONST_BUFFER_SIZE_LS_10
+0x00028FEC SQ_ALU_CONST_BUFFER_SIZE_LS_11
+0x00028FF0 SQ_ALU_CONST_BUFFER_SIZE_LS_12
+0x00028FF4 SQ_ALU_CONST_BUFFER_SIZE_LS_13
+0x00028FF8 SQ_ALU_CONST_BUFFER_SIZE_LS_14
+0x00028FFC SQ_ALU_CONST_BUFFER_SIZE_LS_15
+0x0003CFF0 SQ_VTX_BASE_VTX_LOC
+0x0003CFF4 SQ_VTX_START_INST_LOC
+0x0003FF00 SQ_TEX_SAMPLER_CLEAR
+0x0003FF04 SQ_TEX_RESOURCE_CLEAR
+0x0003FF08 SQ_LOOP_BOOL_CLEAR
index 79887cac5b54ce19da66e1d5ba3e55df8df07527..7bb4c3e52f3b055ceafc27471e516477e4a3fa5b 100644 (file)
@@ -74,7 +74,8 @@ void rs600_pm_misc(struct radeon_device *rdev)
                        if (voltage->delay)
                                udelay(voltage->delay);
                }
-       }
+       } else if (voltage->type == VOLTAGE_VDDC)
+               radeon_atom_set_voltage(rdev, voltage->vddc_id);
 
        dyn_pwrmgt_sclk_length = RREG32_PLL(DYN_PWRMGT_SCLK_LENGTH);
        dyn_pwrmgt_sclk_length &= ~REDUCED_POWER_SCLK_HILEN(0xf);
index 253f24aec031e48e1cf2bd99d8595a50275b1f0d..33952da65340503ad3e07bbb428bf4487b027737 100644 (file)
@@ -44,7 +44,12 @@ void rv770_fini(struct radeon_device *rdev);
 
 void rv770_pm_misc(struct radeon_device *rdev)
 {
+       int requested_index = rdev->pm.requested_power_state_index;
+       struct radeon_power_state *ps = &rdev->pm.power_state[requested_index];
+       struct radeon_voltage *voltage = &ps->clock_info[0].voltage;
 
+       if ((voltage->type == VOLTAGE_SW) && voltage->voltage)
+               radeon_atom_set_voltage(rdev, voltage->voltage);
 }
 
 /*
index 0d9a42c2394f79983344cd8bd21d99204a288109..ef910694bd634807631dd0958831bfa8c44421df 100644 (file)
@@ -77,7 +77,7 @@ struct ttm_page_pool {
 /**
  * Limits for the pool. They are handled without locks because only place where
  * they may change is in sysfs store. They won't have immediate effect anyway
- * so forcing serialiazation to access them is pointless.
+ * so forcing serialization to access them is pointless.
  */
 
 struct ttm_pool_opts {
@@ -165,16 +165,18 @@ static ssize_t ttm_pool_store(struct kobject *kobj,
                m->options.small = val;
        else if (attr == &ttm_page_pool_alloc_size) {
                if (val > NUM_PAGES_TO_ALLOC*8) {
-                       printk(KERN_ERR "[ttm] Setting allocation size to %lu "
-                                       "is not allowed. Recomended size is "
-                                       "%lu\n",
-                                       NUM_PAGES_TO_ALLOC*(PAGE_SIZE >> 7),
-                                       NUM_PAGES_TO_ALLOC*(PAGE_SIZE >> 10));
+                       printk(KERN_ERR TTM_PFX
+                              "Setting allocation size to %lu "
+                              "is not allowed. Recommended size is "
+                              "%lu\n",
+                              NUM_PAGES_TO_ALLOC*(PAGE_SIZE >> 7),
+                              NUM_PAGES_TO_ALLOC*(PAGE_SIZE >> 10));
                        return size;
                } else if (val > NUM_PAGES_TO_ALLOC) {
-                       printk(KERN_WARNING "[ttm] Setting allocation size to "
-                                       "larger than %lu is not recomended.\n",
-                                       NUM_PAGES_TO_ALLOC*(PAGE_SIZE >> 10));
+                       printk(KERN_WARNING TTM_PFX
+                              "Setting allocation size to "
+                              "larger than %lu is not recommended.\n",
+                              NUM_PAGES_TO_ALLOC*(PAGE_SIZE >> 10));
                }
                m->options.alloc_size = val;
        }
@@ -277,7 +279,7 @@ static void ttm_pages_put(struct page *pages[], unsigned npages)
 {
        unsigned i;
        if (set_pages_array_wb(pages, npages))
-               printk(KERN_ERR "[ttm] Failed to set %d pages to wb!\n",
+               printk(KERN_ERR TTM_PFX "Failed to set %d pages to wb!\n",
                                npages);
        for (i = 0; i < npages; ++i)
                __free_page(pages[i]);
@@ -313,7 +315,8 @@ static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free)
        pages_to_free = kmalloc(npages_to_free * sizeof(struct page *),
                        GFP_KERNEL);
        if (!pages_to_free) {
-               printk(KERN_ERR "Failed to allocate memory for pool free operation.\n");
+               printk(KERN_ERR TTM_PFX
+                      "Failed to allocate memory for pool free operation.\n");
                return 0;
        }
 
@@ -390,7 +393,7 @@ static int ttm_pool_get_num_unused_pages(void)
 }
 
 /**
- * Calback for mm to request pool to reduce number of page held.
+ * Callback for mm to request pool to reduce number of page held.
  */
 static int ttm_pool_mm_shrink(int shrink_pages, gfp_t gfp_mask)
 {
@@ -433,14 +436,16 @@ static int ttm_set_pages_caching(struct page **pages,
        case tt_uncached:
                r = set_pages_array_uc(pages, cpages);
                if (r)
-                       printk(KERN_ERR "[ttm] Failed to set %d pages to uc!\n",
-                                       cpages);
+                       printk(KERN_ERR TTM_PFX
+                              "Failed to set %d pages to uc!\n",
+                              cpages);
                break;
        case tt_wc:
                r = set_pages_array_wc(pages, cpages);
                if (r)
-                       printk(KERN_ERR "[ttm] Failed to set %d pages to wc!\n",
-                                       cpages);
+                       printk(KERN_ERR TTM_PFX
+                              "Failed to set %d pages to wc!\n",
+                              cpages);
                break;
        default:
                break;
@@ -458,7 +463,7 @@ static void ttm_handle_caching_state_failure(struct list_head *pages,
                struct page **failed_pages, unsigned cpages)
 {
        unsigned i;
-       /* Failed pages has to be reed */
+       /* Failed pages have to be freed */
        for (i = 0; i < cpages; ++i) {
                list_del(&failed_pages[i]->lru);
                __free_page(failed_pages[i]);
@@ -485,7 +490,8 @@ static int ttm_alloc_new_pages(struct list_head *pages, int gfp_flags,
        caching_array = kmalloc(max_cpages*sizeof(struct page *), GFP_KERNEL);
 
        if (!caching_array) {
-               printk(KERN_ERR "[ttm] unable to allocate table for new pages.");
+               printk(KERN_ERR TTM_PFX
+                      "Unable to allocate table for new pages.");
                return -ENOMEM;
        }
 
@@ -493,12 +499,13 @@ static int ttm_alloc_new_pages(struct list_head *pages, int gfp_flags,
                p = alloc_page(gfp_flags);
 
                if (!p) {
-                       printk(KERN_ERR "[ttm] unable to get page %u\n", i);
+                       printk(KERN_ERR TTM_PFX "Unable to get page %u.\n", i);
 
                        /* store already allocated pages in the pool after
                         * setting the caching state */
                        if (cpages) {
-                               r = ttm_set_pages_caching(caching_array, cstate, cpages);
+                               r = ttm_set_pages_caching(caching_array,
+                                                         cstate, cpages);
                                if (r)
                                        ttm_handle_caching_state_failure(pages,
                                                ttm_flags, cstate,
@@ -590,7 +597,8 @@ static void ttm_page_pool_fill_locked(struct ttm_page_pool *pool,
                        ++pool->nrefills;
                        pool->npages += alloc_size;
                } else {
-                       printk(KERN_ERR "[ttm] Failed to fill pool (%p).", pool);
+                       printk(KERN_ERR TTM_PFX
+                              "Failed to fill pool (%p).", pool);
                        /* If we have any pages left put them to the pool. */
                        list_for_each_entry(p, &pool->list, lru) {
                                ++cpages;
@@ -671,13 +679,14 @@ int ttm_get_pages(struct list_head *pages, int flags,
                if (flags & TTM_PAGE_FLAG_DMA32)
                        gfp_flags |= GFP_DMA32;
                else
-                       gfp_flags |= __GFP_HIGHMEM;
+                       gfp_flags |= GFP_HIGHUSER;
 
                for (r = 0; r < count; ++r) {
                        p = alloc_page(gfp_flags);
                        if (!p) {
 
-                               printk(KERN_ERR "[ttm] unable to allocate page.");
+                               printk(KERN_ERR TTM_PFX
+                                      "Unable to allocate page.");
                                return -ENOMEM;
                        }
 
@@ -709,8 +718,9 @@ int ttm_get_pages(struct list_head *pages, int flags,
                if (r) {
                        /* If there is any pages in the list put them back to
                         * the pool. */
-                       printk(KERN_ERR "[ttm] Failed to allocate extra pages "
-                                       "for large request.");
+                       printk(KERN_ERR TTM_PFX
+                              "Failed to allocate extra pages "
+                              "for large request.");
                        ttm_put_pages(pages, 0, flags, cstate);
                        return r;
                }
@@ -778,7 +788,7 @@ int ttm_page_alloc_init(struct ttm_mem_global *glob, unsigned max_pages)
        if (atomic_add_return(1, &_manager.page_alloc_inited) > 1)
                return 0;
 
-       printk(KERN_INFO "[ttm] Initializing pool allocator.\n");
+       printk(KERN_INFO TTM_PFX "Initializing pool allocator.\n");
 
        ttm_page_pool_init_locked(&_manager.wc_pool, GFP_HIGHUSER, "wc");
 
@@ -813,7 +823,7 @@ void ttm_page_alloc_fini()
        if (atomic_sub_return(1, &_manager.page_alloc_inited) > 0)
                return;
 
-       printk(KERN_INFO "[ttm] Finilizing pool allocator.\n");
+       printk(KERN_INFO TTM_PFX "Finalizing pool allocator.\n");
        ttm_pool_mm_shrink_fini(&_manager);
 
        for (i = 0; i < NUM_POOLS; ++i)
index 1a3cb6816d1cc1a72a58b75a1c4c952e6607c7d3..4505e17df3f557e21beb14581e72f3356985e345 100644 (file)
@@ -4,6 +4,6 @@ ccflags-y := -Iinclude/drm
 vmwgfx-y := vmwgfx_execbuf.o vmwgfx_gmr.o vmwgfx_kms.o vmwgfx_drv.o \
            vmwgfx_fb.o vmwgfx_ioctl.o vmwgfx_resource.o vmwgfx_buffer.o \
            vmwgfx_fifo.o vmwgfx_irq.o vmwgfx_ldu.o vmwgfx_ttm_glue.o \
-           vmwgfx_overlay.o
+           vmwgfx_overlay.o vmwgfx_fence.o
 
 obj-$(CONFIG_DRM_VMWGFX) := vmwgfx.o
index 0c9c0811f42dd03b9c92d0ea154e249b8ed3b397..b793c8c9acb3162049fabe03b7cf43cfab1939fb 100644 (file)
@@ -88,6 +88,9 @@
 #define DRM_IOCTL_VMW_FENCE_WAIT                               \
        DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_FENCE_WAIT,         \
                 struct drm_vmw_fence_wait_arg)
+#define DRM_IOCTL_VMW_UPDATE_LAYOUT                            \
+       DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_UPDATE_LAYOUT,      \
+                struct drm_vmw_update_layout_arg)
 
 
 /**
@@ -135,7 +138,9 @@ static struct drm_ioctl_desc vmw_ioctls[] = {
        VMW_IOCTL_DEF(DRM_IOCTL_VMW_FIFO_DEBUG, vmw_fifo_debug_ioctl,
                      DRM_AUTH | DRM_ROOT_ONLY | DRM_MASTER | DRM_UNLOCKED),
        VMW_IOCTL_DEF(DRM_IOCTL_VMW_FENCE_WAIT, vmw_fence_wait_ioctl,
-                     DRM_AUTH | DRM_UNLOCKED)
+                     DRM_AUTH | DRM_UNLOCKED),
+       VMW_IOCTL_DEF(DRM_IOCTL_VMW_UPDATE_LAYOUT, vmw_kms_update_layout_ioctl,
+                     DRM_MASTER | DRM_CONTROL_ALLOW | DRM_UNLOCKED)
 };
 
 static struct pci_device_id vmw_pci_id_list[] = {
@@ -318,6 +323,15 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
                goto out_err3;
        }
 
+       /* Need mmio memory to check for fifo pitchlock cap. */
+       if (!(dev_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY) &&
+           !(dev_priv->capabilities & SVGA_CAP_PITCHLOCK) &&
+           !vmw_fifo_have_pitchlock(dev_priv)) {
+               ret = -ENOSYS;
+               DRM_ERROR("Hardware has no pitchlock\n");
+               goto out_err4;
+       }
+
        dev_priv->tdev = ttm_object_device_init
            (dev_priv->mem_global_ref.object, 12);
 
@@ -399,8 +413,6 @@ static int vmw_driver_unload(struct drm_device *dev)
 {
        struct vmw_private *dev_priv = vmw_priv(dev);
 
-       DRM_INFO(VMWGFX_DRIVER_NAME " unload.\n");
-
        unregister_pm_notifier(&dev_priv->pm_nb);
 
        vmw_fb_close(dev_priv);
@@ -546,7 +558,6 @@ static int vmw_master_create(struct drm_device *dev,
 {
        struct vmw_master *vmaster;
 
-       DRM_INFO("Master create.\n");
        vmaster = kzalloc(sizeof(*vmaster), GFP_KERNEL);
        if (unlikely(vmaster == NULL))
                return -ENOMEM;
@@ -563,7 +574,6 @@ static void vmw_master_destroy(struct drm_device *dev,
 {
        struct vmw_master *vmaster = vmw_master(master);
 
-       DRM_INFO("Master destroy.\n");
        master->driver_priv = NULL;
        kfree(vmaster);
 }
@@ -579,8 +589,6 @@ static int vmw_master_set(struct drm_device *dev,
        struct vmw_master *vmaster = vmw_master(file_priv->master);
        int ret = 0;
 
-       DRM_INFO("Master set.\n");
-
        if (active) {
                BUG_ON(active != &dev_priv->fbdev_master);
                ret = ttm_vt_lock(&active->lock, false, vmw_fp->tfile);
@@ -622,8 +630,6 @@ static void vmw_master_drop(struct drm_device *dev,
        struct vmw_master *vmaster = vmw_master(file_priv->master);
        int ret;
 
-       DRM_INFO("Master drop.\n");
-
        /**
         * Make sure the master doesn't disappear while we have
         * it locked.
index 356dc935ec133f974c2c95e2be5d1146cd07c9a9..eaad520953393f5f5da3601627e0ec141c4c4a1f 100644 (file)
 
 #define VMWGFX_DRIVER_DATE "20100209"
 #define VMWGFX_DRIVER_MAJOR 1
-#define VMWGFX_DRIVER_MINOR 0
+#define VMWGFX_DRIVER_MINOR 2
 #define VMWGFX_DRIVER_PATCHLEVEL 0
 #define VMWGFX_FILE_PAGE_OFFSET 0x00100000
 #define VMWGFX_FIFO_STATIC_SIZE (1024*1024)
 #define VMWGFX_MAX_RELOCATIONS 2048
 #define VMWGFX_MAX_GMRS 2048
+#define VMWGFX_MAX_DISPLAYS 16
 
 struct vmw_fpriv {
        struct drm_master *locked_master;
@@ -102,6 +103,13 @@ struct vmw_surface {
        struct vmw_cursor_snooper snooper;
 };
 
+struct vmw_fence_queue {
+       struct list_head head;
+       struct timespec lag;
+       struct timespec lag_time;
+       spinlock_t lock;
+};
+
 struct vmw_fifo_state {
        unsigned long reserved_size;
        __le32 *dynamic_buffer;
@@ -115,6 +123,7 @@ struct vmw_fifo_state {
        uint32_t capabilities;
        struct mutex fifo_mutex;
        struct rw_semaphore rwsem;
+       struct vmw_fence_queue fence_queue;
 };
 
 struct vmw_relocation {
@@ -144,6 +153,14 @@ struct vmw_master {
        struct ttm_lock lock;
 };
 
+struct vmw_vga_topology_state {
+       uint32_t width;
+       uint32_t height;
+       uint32_t primary;
+       uint32_t pos_x;
+       uint32_t pos_y;
+};
+
 struct vmw_private {
        struct ttm_bo_device bdev;
        struct ttm_bo_global_ref bo_global_ref;
@@ -171,14 +188,19 @@ struct vmw_private {
         * VGA registers.
         */
 
+       struct vmw_vga_topology_state vga_save[VMWGFX_MAX_DISPLAYS];
        uint32_t vga_width;
        uint32_t vga_height;
        uint32_t vga_depth;
        uint32_t vga_bpp;
        uint32_t vga_pseudo;
        uint32_t vga_red_mask;
-       uint32_t vga_blue_mask;
        uint32_t vga_green_mask;
+       uint32_t vga_blue_mask;
+       uint32_t vga_bpl;
+       uint32_t vga_pitchlock;
+
+       uint32_t num_displays;
 
        /*
         * Framebuffer info.
@@ -393,6 +415,7 @@ extern int vmw_fifo_send_fence(struct vmw_private *dev_priv,
 extern void vmw_fifo_ping_host(struct vmw_private *dev_priv, uint32_t reason);
 extern int vmw_fifo_mmap(struct file *filp, struct vm_area_struct *vma);
 extern bool vmw_fifo_have_3d(struct vmw_private *dev_priv);
+extern bool vmw_fifo_have_pitchlock(struct vmw_private *dev_priv);
 
 /**
  * TTM glue - vmwgfx_ttm_glue.c
@@ -441,6 +464,23 @@ extern int vmw_fallback_wait(struct vmw_private *dev_priv,
                             uint32_t sequence,
                             bool interruptible,
                             unsigned long timeout);
+extern void vmw_update_sequence(struct vmw_private *dev_priv,
+                               struct vmw_fifo_state *fifo_state);
+
+
+/**
+ * Rudimentary fence objects currently used only for throttling -
+ * vmwgfx_fence.c
+ */
+
+extern void vmw_fence_queue_init(struct vmw_fence_queue *queue);
+extern void vmw_fence_queue_takedown(struct vmw_fence_queue *queue);
+extern int vmw_fence_push(struct vmw_fence_queue *queue,
+                         uint32_t sequence);
+extern int vmw_fence_pull(struct vmw_fence_queue *queue,
+                         uint32_t signaled_sequence);
+extern int vmw_wait_lag(struct vmw_private *dev_priv,
+                       struct vmw_fence_queue *queue, uint32_t us);
 
 /**
  * Kernel framebuffer - vmwgfx_fb.c
@@ -466,6 +506,11 @@ void vmw_kms_cursor_snoop(struct vmw_surface *srf,
                          struct ttm_object_file *tfile,
                          struct ttm_buffer_object *bo,
                          SVGA3dCmdHeader *header);
+void vmw_kms_write_svga(struct vmw_private *vmw_priv,
+                       unsigned width, unsigned height, unsigned pitch,
+                       unsigned bbp, unsigned depth);
+int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
+                               struct drm_file *file_priv);
 
 /**
  * Overlay control - vmwgfx_overlay.c
index dbd36b8910cf5cc65f22879c61017f8a0de83dc3..bdd67cf83315f590165fbf6b40437454d4e29186 100644 (file)
@@ -669,6 +669,15 @@ int vmw_execbuf_ioctl(struct drm_device *dev, void *data,
                goto out_err;
 
        vmw_apply_relocations(sw_context);
+
+       if (arg->throttle_us) {
+               ret = vmw_wait_lag(dev_priv, &dev_priv->fifo.fence_queue,
+                                  arg->throttle_us);
+
+               if (unlikely(ret != 0))
+                       goto out_err;
+       }
+
        vmw_fifo_commit(dev_priv, arg->command_size);
 
        ret = vmw_fifo_send_fence(dev_priv, &sequence);
index 7421aaad8d094e17da75b3b5308d3f491a63e9fa..b0866f04ec7613133a6e4ebc7ab3546906af8258 100644 (file)
@@ -132,16 +132,14 @@ static int vmw_fb_check_var(struct fb_var_screeninfo *var,
                return -EINVAL;
        }
 
-       /* without multimon its hard to resize */
-       if (!(vmw_priv->capabilities & SVGA_CAP_MULTIMON) &&
-           (var->xres != par->max_width ||
-            var->yres != par->max_height)) {
-               DRM_ERROR("Tried to resize, but we don't have multimon\n");
+       if (!(vmw_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY) &&
+           (var->xoffset != 0 || var->yoffset != 0)) {
+               DRM_ERROR("Can not handle panning without display topology\n");
                return -EINVAL;
        }
 
-       if (var->xres > par->max_width ||
-           var->yres > par->max_height) {
+       if ((var->xoffset + var->xres) > par->max_width ||
+           (var->yoffset + var->yres) > par->max_height) {
                DRM_ERROR("Requested geom can not fit in framebuffer\n");
                return -EINVAL;
        }
@@ -154,27 +152,11 @@ static int vmw_fb_set_par(struct fb_info *info)
        struct vmw_fb_par *par = info->par;
        struct vmw_private *vmw_priv = par->vmw_priv;
 
-       if (vmw_priv->capabilities & SVGA_CAP_MULTIMON) {
-               vmw_write(vmw_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 1);
-               vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, 0);
-               vmw_write(vmw_priv, SVGA_REG_DISPLAY_IS_PRIMARY, true);
-               vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_X, 0);
-               vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_Y, 0);
-               vmw_write(vmw_priv, SVGA_REG_DISPLAY_WIDTH, 0);
-               vmw_write(vmw_priv, SVGA_REG_DISPLAY_HEIGHT, 0);
-               vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
-
-               vmw_write(vmw_priv, SVGA_REG_ENABLE, 1);
-               vmw_write(vmw_priv, SVGA_REG_WIDTH, par->max_width);
-               vmw_write(vmw_priv, SVGA_REG_HEIGHT, par->max_height);
-               vmw_write(vmw_priv, SVGA_REG_BITS_PER_PIXEL, par->bpp);
-               vmw_write(vmw_priv, SVGA_REG_DEPTH, par->depth);
-               vmw_write(vmw_priv, SVGA_REG_RED_MASK, 0x00ff0000);
-               vmw_write(vmw_priv, SVGA_REG_GREEN_MASK, 0x0000ff00);
-               vmw_write(vmw_priv, SVGA_REG_BLUE_MASK, 0x000000ff);
-
+       vmw_kms_write_svga(vmw_priv, info->var.xres, info->var.yres,
+                          info->fix.line_length,
+                          par->bpp, par->depth);
+       if (vmw_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY) {
                /* TODO check if pitch and offset changes */
-
                vmw_write(vmw_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 1);
                vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, 0);
                vmw_write(vmw_priv, SVGA_REG_DISPLAY_IS_PRIMARY, true);
@@ -183,13 +165,13 @@ static int vmw_fb_set_par(struct fb_info *info)
                vmw_write(vmw_priv, SVGA_REG_DISPLAY_WIDTH, info->var.xres);
                vmw_write(vmw_priv, SVGA_REG_DISPLAY_HEIGHT, info->var.yres);
                vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
-       } else {
-               vmw_write(vmw_priv, SVGA_REG_WIDTH, info->var.xres);
-               vmw_write(vmw_priv, SVGA_REG_HEIGHT, info->var.yres);
-
-               /* TODO check if pitch and offset changes */
        }
 
+       /* This is really helpful since if this fails the user
+        * can probably not see anything on the screen.
+        */
+       WARN_ON(vmw_read(vmw_priv, SVGA_REG_FB_OFFSET) != 0);
+
        return 0;
 }
 
@@ -416,48 +398,23 @@ int vmw_fb_init(struct vmw_private *vmw_priv)
        unsigned fb_bbp, fb_depth, fb_offset, fb_pitch, fb_size;
        int ret;
 
+       /* XXX These shouldn't be hardcoded. */
        initial_width = 800;
        initial_height = 600;
 
        fb_bbp = 32;
        fb_depth = 24;
 
-       if (vmw_priv->capabilities & SVGA_CAP_MULTIMON) {
-               fb_width = min(vmw_priv->fb_max_width, (unsigned)2048);
-               fb_height = min(vmw_priv->fb_max_height, (unsigned)2048);
-       } else {
-               fb_width = min(vmw_priv->fb_max_width, initial_width);
-               fb_height = min(vmw_priv->fb_max_height, initial_height);
-       }
+       /* XXX As shouldn't these be as well. */
+       fb_width = min(vmw_priv->fb_max_width, (unsigned)2048);
+       fb_height = min(vmw_priv->fb_max_height, (unsigned)2048);
 
        initial_width = min(fb_width, initial_width);
        initial_height = min(fb_height, initial_height);
 
-       vmw_write(vmw_priv, SVGA_REG_WIDTH, fb_width);
-       vmw_write(vmw_priv, SVGA_REG_HEIGHT, fb_height);
-       vmw_write(vmw_priv, SVGA_REG_BITS_PER_PIXEL, fb_bbp);
-       vmw_write(vmw_priv, SVGA_REG_DEPTH, fb_depth);
-       vmw_write(vmw_priv, SVGA_REG_RED_MASK, 0x00ff0000);
-       vmw_write(vmw_priv, SVGA_REG_GREEN_MASK, 0x0000ff00);
-       vmw_write(vmw_priv, SVGA_REG_BLUE_MASK, 0x000000ff);
-
-       fb_size = vmw_read(vmw_priv, SVGA_REG_FB_SIZE);
+       fb_pitch = fb_width * fb_bbp / 8;
+       fb_size = fb_pitch * fb_height;
        fb_offset = vmw_read(vmw_priv, SVGA_REG_FB_OFFSET);
-       fb_pitch = vmw_read(vmw_priv, SVGA_REG_BYTES_PER_LINE);
-
-       DRM_DEBUG("width  %u\n", vmw_read(vmw_priv, SVGA_REG_MAX_WIDTH));
-       DRM_DEBUG("height %u\n", vmw_read(vmw_priv, SVGA_REG_MAX_HEIGHT));
-       DRM_DEBUG("width  %u\n", vmw_read(vmw_priv, SVGA_REG_WIDTH));
-       DRM_DEBUG("height %u\n", vmw_read(vmw_priv, SVGA_REG_HEIGHT));
-       DRM_DEBUG("bpp    %u\n", vmw_read(vmw_priv, SVGA_REG_BITS_PER_PIXEL));
-       DRM_DEBUG("depth  %u\n", vmw_read(vmw_priv, SVGA_REG_DEPTH));
-       DRM_DEBUG("bpl    %u\n", vmw_read(vmw_priv, SVGA_REG_BYTES_PER_LINE));
-       DRM_DEBUG("r mask %08x\n", vmw_read(vmw_priv, SVGA_REG_RED_MASK));
-       DRM_DEBUG("g mask %08x\n", vmw_read(vmw_priv, SVGA_REG_GREEN_MASK));
-       DRM_DEBUG("b mask %08x\n", vmw_read(vmw_priv, SVGA_REG_BLUE_MASK));
-       DRM_DEBUG("fb_offset 0x%08x\n", fb_offset);
-       DRM_DEBUG("fb_pitch  %u\n", fb_pitch);
-       DRM_DEBUG("fb_size   %u kiB\n", fb_size / 1024);
 
        info = framebuffer_alloc(sizeof(*par), device);
        if (!info)
@@ -659,6 +616,10 @@ int vmw_dmabuf_to_start_of_vram(struct vmw_private *vmw_priv,
                goto err_unlock;
 
        ret = ttm_bo_validate(bo, &ne_placement, false, false, false);
+
+       /* Could probably bug on */
+       WARN_ON(bo->offset != 0);
+
        ttm_bo_unreserve(bo);
 err_unlock:
        ttm_write_unlock(&vmw_priv->active_master->lock);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
new file mode 100644 (file)
index 0000000..61eacc1
--- /dev/null
@@ -0,0 +1,173 @@
+/**************************************************************************
+ *
+ * Copyright (C) 2010 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "vmwgfx_drv.h"
+
+struct vmw_fence {
+       struct list_head head;
+       uint32_t sequence;
+       struct timespec submitted;
+};
+
+void vmw_fence_queue_init(struct vmw_fence_queue *queue)
+{
+       INIT_LIST_HEAD(&queue->head);
+       queue->lag = ns_to_timespec(0);
+       getrawmonotonic(&queue->lag_time);
+       spin_lock_init(&queue->lock);
+}
+
+void vmw_fence_queue_takedown(struct vmw_fence_queue *queue)
+{
+       struct vmw_fence *fence, *next;
+
+       spin_lock(&queue->lock);
+       list_for_each_entry_safe(fence, next, &queue->head, head) {
+               kfree(fence);
+       }
+       spin_unlock(&queue->lock);
+}
+
+int vmw_fence_push(struct vmw_fence_queue *queue,
+                  uint32_t sequence)
+{
+       struct vmw_fence *fence = kmalloc(sizeof(*fence), GFP_KERNEL);
+
+       if (unlikely(!fence))
+               return -ENOMEM;
+
+       fence->sequence = sequence;
+       getrawmonotonic(&fence->submitted);
+       spin_lock(&queue->lock);
+       list_add_tail(&fence->head, &queue->head);
+       spin_unlock(&queue->lock);
+
+       return 0;
+}
+
+int vmw_fence_pull(struct vmw_fence_queue *queue,
+                  uint32_t signaled_sequence)
+{
+       struct vmw_fence *fence, *next;
+       struct timespec now;
+       bool updated = false;
+
+       spin_lock(&queue->lock);
+       getrawmonotonic(&now);
+
+       if (list_empty(&queue->head)) {
+               queue->lag = ns_to_timespec(0);
+               queue->lag_time = now;
+               updated = true;
+               goto out_unlock;
+       }
+
+       list_for_each_entry_safe(fence, next, &queue->head, head) {
+               if (signaled_sequence - fence->sequence > (1 << 30))
+                       continue;
+
+               queue->lag = timespec_sub(now, fence->submitted);
+               queue->lag_time = now;
+               updated = true;
+               list_del(&fence->head);
+               kfree(fence);
+       }
+
+out_unlock:
+       spin_unlock(&queue->lock);
+
+       return (updated) ? 0 : -EBUSY;
+}
+
+static struct timespec vmw_timespec_add(struct timespec t1,
+                                       struct timespec t2)
+{
+       t1.tv_sec += t2.tv_sec;
+       t1.tv_nsec += t2.tv_nsec;
+       if (t1.tv_nsec >= 1000000000L) {
+               t1.tv_sec += 1;
+               t1.tv_nsec -= 1000000000L;
+       }
+
+       return t1;
+}
+
+static struct timespec vmw_fifo_lag(struct vmw_fence_queue *queue)
+{
+       struct timespec now;
+
+       spin_lock(&queue->lock);
+       getrawmonotonic(&now);
+       queue->lag = vmw_timespec_add(queue->lag,
+                                     timespec_sub(now, queue->lag_time));
+       queue->lag_time = now;
+       spin_unlock(&queue->lock);
+       return queue->lag;
+}
+
+
+static bool vmw_lag_lt(struct vmw_fence_queue *queue,
+                      uint32_t us)
+{
+       struct timespec lag, cond;
+
+       cond = ns_to_timespec((s64) us * 1000);
+       lag = vmw_fifo_lag(queue);
+       return (timespec_compare(&lag, &cond) < 1);
+}
+
+int vmw_wait_lag(struct vmw_private *dev_priv,
+                struct vmw_fence_queue *queue, uint32_t us)
+{
+       struct vmw_fence *fence;
+       uint32_t sequence;
+       int ret;
+
+       while (!vmw_lag_lt(queue, us)) {
+               spin_lock(&queue->lock);
+               if (list_empty(&queue->head))
+                       sequence = atomic_read(&dev_priv->fence_seq);
+               else {
+                       fence = list_first_entry(&queue->head,
+                                                struct vmw_fence, head);
+                       sequence = fence->sequence;
+               }
+               spin_unlock(&queue->lock);
+
+               ret = vmw_wait_fence(dev_priv, false, sequence, true,
+                                    3*HZ);
+
+               if (unlikely(ret != 0))
+                       return ret;
+
+               (void) vmw_fence_pull(queue, sequence);
+       }
+       return 0;
+}
+
+
index 39d43a01d846fd9e7bcd6a1206b06143f90a740d..e6a1eb7ea95498f00e65d123adeae79160af8fa8 100644 (file)
@@ -34,6 +34,9 @@ bool vmw_fifo_have_3d(struct vmw_private *dev_priv)
        __le32 __iomem *fifo_mem = dev_priv->mmio_virt;
        uint32_t fifo_min, hwversion;
 
+       if (!(dev_priv->capabilities & SVGA_CAP_EXTENDED_FIFO))
+               return false;
+
        fifo_min = ioread32(fifo_mem  + SVGA_FIFO_MIN);
        if (fifo_min <= SVGA_FIFO_3D_HWVERSION * sizeof(unsigned int))
                return false;
@@ -48,6 +51,21 @@ bool vmw_fifo_have_3d(struct vmw_private *dev_priv)
        return true;
 }
 
+bool vmw_fifo_have_pitchlock(struct vmw_private *dev_priv)
+{
+       __le32 __iomem *fifo_mem = dev_priv->mmio_virt;
+       uint32_t caps;
+
+       if (!(dev_priv->capabilities & SVGA_CAP_EXTENDED_FIFO))
+               return false;
+
+       caps = ioread32(fifo_mem + SVGA_FIFO_CAPABILITIES);
+       if (caps & SVGA_FIFO_CAP_PITCHLOCK)
+               return true;
+
+       return false;
+}
+
 int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
 {
        __le32 __iomem *fifo_mem = dev_priv->mmio_virt;
@@ -120,7 +138,7 @@ int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
 
        atomic_set(&dev_priv->fence_seq, dev_priv->last_read_sequence);
        iowrite32(dev_priv->last_read_sequence, fifo_mem + SVGA_FIFO_FENCE);
-
+       vmw_fence_queue_init(&fifo->fence_queue);
        return vmw_fifo_send_fence(dev_priv, &dummy);
 out_err:
        vfree(fifo->static_buffer);
@@ -159,6 +177,7 @@ void vmw_fifo_release(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
                  dev_priv->enable_state);
 
        mutex_unlock(&dev_priv->hw_mutex);
+       vmw_fence_queue_takedown(&fifo->fence_queue);
 
        if (likely(fifo->last_buffer != NULL)) {
                vfree(fifo->last_buffer);
@@ -484,6 +503,8 @@ int vmw_fifo_send_fence(struct vmw_private *dev_priv, uint32_t *sequence)
        fifo_state->last_buffer_add = true;
        vmw_fifo_commit(dev_priv, bytes);
        fifo_state->last_buffer_add = false;
+       (void) vmw_fence_push(&fifo_state->fence_queue, *sequence);
+       vmw_update_sequence(dev_priv, fifo_state);
 
 out_err:
        return ret;
index 4d7cb539386000b50798960f8615d2fc2b25d2ba..e92298a6a383c1fe60c290002a33a3e39caa456f 100644 (file)
@@ -64,22 +64,33 @@ static bool vmw_fifo_idle(struct vmw_private *dev_priv, uint32_t sequence)
        return (busy == 0);
 }
 
+void vmw_update_sequence(struct vmw_private *dev_priv,
+                        struct vmw_fifo_state *fifo_state)
+{
+       __le32 __iomem *fifo_mem = dev_priv->mmio_virt;
+
+       uint32_t sequence = ioread32(fifo_mem + SVGA_FIFO_FENCE);
+
+       if (dev_priv->last_read_sequence != sequence) {
+               dev_priv->last_read_sequence = sequence;
+               vmw_fence_pull(&fifo_state->fence_queue, sequence);
+       }
+}
 
 bool vmw_fence_signaled(struct vmw_private *dev_priv,
                        uint32_t sequence)
 {
-       __le32 __iomem *fifo_mem = dev_priv->mmio_virt;
        struct vmw_fifo_state *fifo_state;
        bool ret;
 
        if (likely(dev_priv->last_read_sequence - sequence < VMW_FENCE_WRAP))
                return true;
 
-       dev_priv->last_read_sequence = ioread32(fifo_mem + SVGA_FIFO_FENCE);
+       fifo_state = &dev_priv->fifo;
+       vmw_update_sequence(dev_priv, fifo_state);
        if (likely(dev_priv->last_read_sequence - sequence < VMW_FENCE_WRAP))
                return true;
 
-       fifo_state = &dev_priv->fifo;
        if (!(fifo_state->capabilities & SVGA_FIFO_CAP_FENCE) &&
            vmw_fifo_idle(dev_priv, sequence))
                return true;
index bbc7c4c30bc7fc26d6c2244ba53ab70324af1593..f1d62611241586f73115a0a8cd60f853837308f6 100644 (file)
@@ -30,6 +30,8 @@
 /* Might need a hrtimer here? */
 #define VMWGFX_PRESENT_RATE ((HZ / 60 > 0) ? HZ / 60 : 1)
 
+static int vmw_surface_dmabuf_pin(struct vmw_framebuffer *vfb);
+static int vmw_surface_dmabuf_unpin(struct vmw_framebuffer *vfb);
 
 void vmw_display_unit_cleanup(struct vmw_display_unit *du)
 {
@@ -326,6 +328,7 @@ int vmw_framebuffer_create_handle(struct drm_framebuffer *fb,
 struct vmw_framebuffer_surface {
        struct vmw_framebuffer base;
        struct vmw_surface *surface;
+       struct vmw_dma_buffer *buffer;
        struct delayed_work d_work;
        struct mutex work_lock;
        bool present_fs;
@@ -500,8 +503,8 @@ int vmw_kms_new_framebuffer_surface(struct vmw_private *dev_priv,
        vfbs->base.base.depth = 24;
        vfbs->base.base.width = width;
        vfbs->base.base.height = height;
-       vfbs->base.pin = NULL;
-       vfbs->base.unpin = NULL;
+       vfbs->base.pin = &vmw_surface_dmabuf_pin;
+       vfbs->base.unpin = &vmw_surface_dmabuf_unpin;
        vfbs->surface = surface;
        mutex_init(&vfbs->work_lock);
        INIT_DELAYED_WORK(&vfbs->d_work, &vmw_framebuffer_present_fs_callback);
@@ -589,6 +592,40 @@ static struct drm_framebuffer_funcs vmw_framebuffer_dmabuf_funcs = {
        .create_handle = vmw_framebuffer_create_handle,
 };
 
+static int vmw_surface_dmabuf_pin(struct vmw_framebuffer *vfb)
+{
+       struct vmw_private *dev_priv = vmw_priv(vfb->base.dev);
+       struct vmw_framebuffer_surface *vfbs =
+               vmw_framebuffer_to_vfbs(&vfb->base);
+       unsigned long size = vfbs->base.base.pitch * vfbs->base.base.height;
+       int ret;
+
+       vfbs->buffer = kzalloc(sizeof(*vfbs->buffer), GFP_KERNEL);
+       if (unlikely(vfbs->buffer == NULL))
+               return -ENOMEM;
+
+       vmw_overlay_pause_all(dev_priv);
+       ret = vmw_dmabuf_init(dev_priv, vfbs->buffer, size,
+                              &vmw_vram_ne_placement,
+                              false, &vmw_dmabuf_bo_free);
+       vmw_overlay_resume_all(dev_priv);
+
+       return ret;
+}
+
+static int vmw_surface_dmabuf_unpin(struct vmw_framebuffer *vfb)
+{
+       struct ttm_buffer_object *bo;
+       struct vmw_framebuffer_surface *vfbs =
+               vmw_framebuffer_to_vfbs(&vfb->base);
+
+       bo = &vfbs->buffer->base;
+       ttm_bo_unref(&bo);
+       vfbs->buffer = NULL;
+
+       return 0;
+}
+
 static int vmw_framebuffer_dmabuf_pin(struct vmw_framebuffer *vfb)
 {
        struct vmw_private *dev_priv = vmw_priv(vfb->base.dev);
@@ -596,33 +633,15 @@ static int vmw_framebuffer_dmabuf_pin(struct vmw_framebuffer *vfb)
                vmw_framebuffer_to_vfbd(&vfb->base);
        int ret;
 
+
        vmw_overlay_pause_all(dev_priv);
 
        ret = vmw_dmabuf_to_start_of_vram(dev_priv, vfbd->buffer);
 
-       if (dev_priv->capabilities & SVGA_CAP_MULTIMON) {
-               vmw_write(dev_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 1);
-               vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, 0);
-               vmw_write(dev_priv, SVGA_REG_DISPLAY_IS_PRIMARY, true);
-               vmw_write(dev_priv, SVGA_REG_DISPLAY_POSITION_X, 0);
-               vmw_write(dev_priv, SVGA_REG_DISPLAY_POSITION_Y, 0);
-               vmw_write(dev_priv, SVGA_REG_DISPLAY_WIDTH, 0);
-               vmw_write(dev_priv, SVGA_REG_DISPLAY_HEIGHT, 0);
-               vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
-
-               vmw_write(dev_priv, SVGA_REG_ENABLE, 1);
-               vmw_write(dev_priv, SVGA_REG_WIDTH, vfb->base.width);
-               vmw_write(dev_priv, SVGA_REG_HEIGHT, vfb->base.height);
-               vmw_write(dev_priv, SVGA_REG_BITS_PER_PIXEL, vfb->base.bits_per_pixel);
-               vmw_write(dev_priv, SVGA_REG_DEPTH, vfb->base.depth);
-               vmw_write(dev_priv, SVGA_REG_RED_MASK, 0x00ff0000);
-               vmw_write(dev_priv, SVGA_REG_GREEN_MASK, 0x0000ff00);
-               vmw_write(dev_priv, SVGA_REG_BLUE_MASK, 0x000000ff);
-       } else
-               WARN_ON(true);
-
        vmw_overlay_resume_all(dev_priv);
 
+       WARN_ON(ret != 0);
+
        return 0;
 }
 
@@ -668,7 +687,7 @@ int vmw_kms_new_framebuffer_dmabuf(struct vmw_private *dev_priv,
 
        /* XXX get the first 3 from the surface info */
        vfbd->base.base.bits_per_pixel = 32;
-       vfbd->base.base.pitch = width * 32 / 4;
+       vfbd->base.base.pitch = width * vfbd->base.base.bits_per_pixel / 8;
        vfbd->base.base.depth = 24;
        vfbd->base.base.width = width;
        vfbd->base.base.height = height;
@@ -765,8 +784,9 @@ int vmw_kms_init(struct vmw_private *dev_priv)
        dev->mode_config.funcs = &vmw_kms_funcs;
        dev->mode_config.min_width = 1;
        dev->mode_config.min_height = 1;
-       dev->mode_config.max_width = dev_priv->fb_max_width;
-       dev->mode_config.max_height = dev_priv->fb_max_height;
+       /* assumed largest fb size */
+       dev->mode_config.max_width = 8192;
+       dev->mode_config.max_height = 8192;
 
        ret = vmw_kms_init_legacy_display_system(dev_priv);
 
@@ -826,49 +846,140 @@ out:
        return ret;
 }
 
+void vmw_kms_write_svga(struct vmw_private *vmw_priv,
+                       unsigned width, unsigned height, unsigned pitch,
+                       unsigned bbp, unsigned depth)
+{
+       if (vmw_priv->capabilities & SVGA_CAP_PITCHLOCK)
+               vmw_write(vmw_priv, SVGA_REG_PITCHLOCK, pitch);
+       else if (vmw_fifo_have_pitchlock(vmw_priv))
+               iowrite32(pitch, vmw_priv->mmio_virt + SVGA_FIFO_PITCHLOCK);
+       vmw_write(vmw_priv, SVGA_REG_WIDTH, width);
+       vmw_write(vmw_priv, SVGA_REG_HEIGHT, height);
+       vmw_write(vmw_priv, SVGA_REG_BITS_PER_PIXEL, bbp);
+       vmw_write(vmw_priv, SVGA_REG_DEPTH, depth);
+       vmw_write(vmw_priv, SVGA_REG_RED_MASK, 0x00ff0000);
+       vmw_write(vmw_priv, SVGA_REG_GREEN_MASK, 0x0000ff00);
+       vmw_write(vmw_priv, SVGA_REG_BLUE_MASK, 0x000000ff);
+}
+
 int vmw_kms_save_vga(struct vmw_private *vmw_priv)
 {
-       /*
-        * setup a single multimon monitor with the size
-        * of 0x0, this stops the UI from resizing when we
-        * change the framebuffer size
-        */
-       if (vmw_priv->capabilities & SVGA_CAP_MULTIMON) {
-               vmw_write(vmw_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 1);
-               vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, 0);
-               vmw_write(vmw_priv, SVGA_REG_DISPLAY_IS_PRIMARY, true);
-               vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_X, 0);
-               vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_Y, 0);
-               vmw_write(vmw_priv, SVGA_REG_DISPLAY_WIDTH, 0);
-               vmw_write(vmw_priv, SVGA_REG_DISPLAY_HEIGHT, 0);
-               vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
-       }
+       struct vmw_vga_topology_state *save;
+       uint32_t i;
 
        vmw_priv->vga_width = vmw_read(vmw_priv, SVGA_REG_WIDTH);
        vmw_priv->vga_height = vmw_read(vmw_priv, SVGA_REG_HEIGHT);
-       vmw_priv->vga_bpp = vmw_read(vmw_priv, SVGA_REG_BITS_PER_PIXEL);
        vmw_priv->vga_depth = vmw_read(vmw_priv, SVGA_REG_DEPTH);
+       vmw_priv->vga_bpp = vmw_read(vmw_priv, SVGA_REG_BITS_PER_PIXEL);
        vmw_priv->vga_pseudo = vmw_read(vmw_priv, SVGA_REG_PSEUDOCOLOR);
        vmw_priv->vga_red_mask = vmw_read(vmw_priv, SVGA_REG_RED_MASK);
-       vmw_priv->vga_green_mask = vmw_read(vmw_priv, SVGA_REG_GREEN_MASK);
        vmw_priv->vga_blue_mask = vmw_read(vmw_priv, SVGA_REG_BLUE_MASK);
+       vmw_priv->vga_green_mask = vmw_read(vmw_priv, SVGA_REG_GREEN_MASK);
+       if (vmw_priv->capabilities & SVGA_CAP_PITCHLOCK)
+               vmw_priv->vga_pitchlock =
+                 vmw_read(vmw_priv, SVGA_REG_PITCHLOCK);
+       else if (vmw_fifo_have_pitchlock(vmw_priv))
+               vmw_priv->vga_pitchlock = ioread32(vmw_priv->mmio_virt +
+                                                      SVGA_FIFO_PITCHLOCK);
+
+       if (!(vmw_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY))
+               return 0;
 
+       vmw_priv->num_displays = vmw_read(vmw_priv,
+                                         SVGA_REG_NUM_GUEST_DISPLAYS);
+
+       for (i = 0; i < vmw_priv->num_displays; ++i) {
+               save = &vmw_priv->vga_save[i];
+               vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, i);
+               save->primary = vmw_read(vmw_priv, SVGA_REG_DISPLAY_IS_PRIMARY);
+               save->pos_x = vmw_read(vmw_priv, SVGA_REG_DISPLAY_POSITION_X);
+               save->pos_y = vmw_read(vmw_priv, SVGA_REG_DISPLAY_POSITION_Y);
+               save->width = vmw_read(vmw_priv, SVGA_REG_DISPLAY_WIDTH);
+               save->height = vmw_read(vmw_priv, SVGA_REG_DISPLAY_HEIGHT);
+               vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
+       }
        return 0;
 }
 
 int vmw_kms_restore_vga(struct vmw_private *vmw_priv)
 {
+       struct vmw_vga_topology_state *save;
+       uint32_t i;
+
        vmw_write(vmw_priv, SVGA_REG_WIDTH, vmw_priv->vga_width);
        vmw_write(vmw_priv, SVGA_REG_HEIGHT, vmw_priv->vga_height);
-       vmw_write(vmw_priv, SVGA_REG_BITS_PER_PIXEL, vmw_priv->vga_bpp);
        vmw_write(vmw_priv, SVGA_REG_DEPTH, vmw_priv->vga_depth);
+       vmw_write(vmw_priv, SVGA_REG_BITS_PER_PIXEL, vmw_priv->vga_bpp);
        vmw_write(vmw_priv, SVGA_REG_PSEUDOCOLOR, vmw_priv->vga_pseudo);
        vmw_write(vmw_priv, SVGA_REG_RED_MASK, vmw_priv->vga_red_mask);
        vmw_write(vmw_priv, SVGA_REG_GREEN_MASK, vmw_priv->vga_green_mask);
        vmw_write(vmw_priv, SVGA_REG_BLUE_MASK, vmw_priv->vga_blue_mask);
+       if (vmw_priv->capabilities & SVGA_CAP_PITCHLOCK)
+               vmw_write(vmw_priv, SVGA_REG_PITCHLOCK,
+                         vmw_priv->vga_pitchlock);
+       else if (vmw_fifo_have_pitchlock(vmw_priv))
+               iowrite32(vmw_priv->vga_pitchlock,
+                         vmw_priv->mmio_virt + SVGA_FIFO_PITCHLOCK);
+
+       if (!(vmw_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY))
+               return 0;
 
-       /* TODO check for multimon */
-       vmw_write(vmw_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 0);
+       for (i = 0; i < vmw_priv->num_displays; ++i) {
+               save = &vmw_priv->vga_save[i];
+               vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, i);
+               vmw_write(vmw_priv, SVGA_REG_DISPLAY_IS_PRIMARY, save->primary);
+               vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_X, save->pos_x);
+               vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_Y, save->pos_y);
+               vmw_write(vmw_priv, SVGA_REG_DISPLAY_WIDTH, save->width);
+               vmw_write(vmw_priv, SVGA_REG_DISPLAY_HEIGHT, save->height);
+               vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
+       }
 
        return 0;
 }
+
+int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
+                               struct drm_file *file_priv)
+{
+       struct vmw_private *dev_priv = vmw_priv(dev);
+       struct drm_vmw_update_layout_arg *arg =
+               (struct drm_vmw_update_layout_arg *)data;
+       struct vmw_master *vmaster = vmw_master(file_priv->master);
+       void __user *user_rects;
+       struct drm_vmw_rect *rects;
+       unsigned rects_size;
+       int ret;
+
+       ret = ttm_read_lock(&vmaster->lock, true);
+       if (unlikely(ret != 0))
+               return ret;
+
+       if (!arg->num_outputs) {
+               struct drm_vmw_rect def_rect = {0, 0, 800, 600};
+               vmw_kms_ldu_update_layout(dev_priv, 1, &def_rect);
+               goto out_unlock;
+       }
+
+       rects_size = arg->num_outputs * sizeof(struct drm_vmw_rect);
+       rects = kzalloc(rects_size, GFP_KERNEL);
+       if (unlikely(!rects)) {
+               ret = -ENOMEM;
+               goto out_unlock;
+       }
+
+       user_rects = (void __user *)(unsigned long)arg->rects;
+       ret = copy_from_user(rects, user_rects, rects_size);
+       if (unlikely(ret != 0)) {
+               DRM_ERROR("Failed to get rects.\n");
+               goto out_free;
+       }
+
+       vmw_kms_ldu_update_layout(dev_priv, arg->num_outputs, rects);
+
+out_free:
+       kfree(rects);
+out_unlock:
+       ttm_read_unlock(&vmaster->lock);
+       return ret;
+}
index 8b95249f0531ab0767f9248daee39063874d024f..8a398a0339b6c82a2c86178eb8d7657f80212964 100644 (file)
@@ -94,9 +94,11 @@ int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
 int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y);
 
 /*
- * Legacy display unit functions - vmwgfx_ldu.h
+ * Legacy display unit functions - vmwgfx_ldu.c
  */
 int vmw_kms_init_legacy_display_system(struct vmw_private *dev_priv);
 int vmw_kms_close_legacy_display_system(struct vmw_private *dev_priv);
+int vmw_kms_ldu_update_layout(struct vmw_private *dev_priv, unsigned num,
+                             struct drm_vmw_rect *rects);
 
 #endif
index 90891593bf6c2ea01cc23ab52d03452cb5d99c08..cfaf690a5b2f423d6f150800cfb2d655d272a0bc 100644 (file)
@@ -38,6 +38,7 @@ struct vmw_legacy_display {
        struct list_head active;
 
        unsigned num_active;
+       unsigned last_num_active;
 
        struct vmw_framebuffer *fb;
 };
@@ -48,9 +49,12 @@ struct vmw_legacy_display {
 struct vmw_legacy_display_unit {
        struct vmw_display_unit base;
 
-       struct list_head active;
+       unsigned pref_width;
+       unsigned pref_height;
+       bool pref_active;
+       struct drm_display_mode *pref_mode;
 
-       unsigned unit;
+       struct list_head active;
 };
 
 static void vmw_ldu_destroy(struct vmw_legacy_display_unit *ldu)
@@ -88,23 +92,44 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv)
 {
        struct vmw_legacy_display *lds = dev_priv->ldu_priv;
        struct vmw_legacy_display_unit *entry;
-       struct drm_crtc *crtc;
+       struct drm_framebuffer *fb = NULL;
+       struct drm_crtc *crtc = NULL;
        int i = 0;
 
-       /* to stop the screen from changing size on resize */
-       vmw_write(dev_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 0);
-       for (i = 0; i < lds->num_active; i++) {
-               vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, i);
-               vmw_write(dev_priv, SVGA_REG_DISPLAY_IS_PRIMARY, !i);
-               vmw_write(dev_priv, SVGA_REG_DISPLAY_POSITION_X, 0);
-               vmw_write(dev_priv, SVGA_REG_DISPLAY_POSITION_Y, 0);
-               vmw_write(dev_priv, SVGA_REG_DISPLAY_WIDTH, 0);
-               vmw_write(dev_priv, SVGA_REG_DISPLAY_HEIGHT, 0);
-               vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
+       /* If there is no display topology the host just assumes
+        * that the guest will set the same layout as the host.
+        */
+       if (!(dev_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY)) {
+               int w = 0, h = 0;
+               list_for_each_entry(entry, &lds->active, active) {
+                       crtc = &entry->base.crtc;
+                       w = max(w, crtc->x + crtc->mode.hdisplay);
+                       h = max(h, crtc->y + crtc->mode.vdisplay);
+                       i++;
+               }
+
+               if (crtc == NULL)
+                       return 0;
+               fb = entry->base.crtc.fb;
+
+               vmw_kms_write_svga(dev_priv, w, h, fb->pitch,
+                                  fb->bits_per_pixel, fb->depth);
+
+               return 0;
        }
 
-       /* Now set the mode */
-       vmw_write(dev_priv, SVGA_REG_NUM_GUEST_DISPLAYS, lds->num_active);
+       if (!list_empty(&lds->active)) {
+               entry = list_entry(lds->active.next, typeof(*entry), active);
+               fb = entry->base.crtc.fb;
+
+               vmw_kms_write_svga(dev_priv, fb->width, fb->height, fb->pitch,
+                                  fb->bits_per_pixel, fb->depth);
+       }
+
+       /* Make sure we always show something. */
+       vmw_write(dev_priv, SVGA_REG_NUM_GUEST_DISPLAYS,
+                 lds->num_active ? lds->num_active : 1);
+
        i = 0;
        list_for_each_entry(entry, &lds->active, active) {
                crtc = &entry->base.crtc;
@@ -120,6 +145,10 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv)
                i++;
        }
 
+       BUG_ON(i != lds->num_active);
+
+       lds->last_num_active = lds->num_active;
+
        return 0;
 }
 
@@ -130,6 +159,7 @@ static int vmw_ldu_del_active(struct vmw_private *vmw_priv,
        if (list_empty(&ldu->active))
                return 0;
 
+       /* Must init otherwise list_empty(&ldu->active) will not work. */
        list_del_init(&ldu->active);
        if (--(ld->num_active) == 0) {
                BUG_ON(!ld->fb);
@@ -149,24 +179,29 @@ static int vmw_ldu_add_active(struct vmw_private *vmw_priv,
        struct vmw_legacy_display_unit *entry;
        struct list_head *at;
 
+       BUG_ON(!ld->num_active && ld->fb);
+       if (vfb != ld->fb) {
+               if (ld->fb && ld->fb->unpin)
+                       ld->fb->unpin(ld->fb);
+               if (vfb->pin)
+                       vfb->pin(vfb);
+               ld->fb = vfb;
+       }
+
        if (!list_empty(&ldu->active))
                return 0;
 
        at = &ld->active;
        list_for_each_entry(entry, &ld->active, active) {
-               if (entry->unit > ldu->unit)
+               if (entry->base.unit > ldu->base.unit)
                        break;
 
                at = &entry->active;
        }
 
        list_add(&ldu->active, at);
-       if (ld->num_active++ == 0) {
-               BUG_ON(ld->fb);
-               if (vfb->pin)
-                       vfb->pin(vfb);
-               ld->fb = vfb;
-       }
+
+       ld->num_active++;
 
        return 0;
 }
@@ -208,6 +243,8 @@ static int vmw_ldu_crtc_set_config(struct drm_mode_set *set)
 
        /* ldu only supports one fb active at the time */
        if (dev_priv->ldu_priv->fb && vfb &&
+           !(dev_priv->ldu_priv->num_active == 1 &&
+             !list_empty(&ldu->active)) &&
            dev_priv->ldu_priv->fb != vfb) {
                DRM_ERROR("Multiple framebuffers not supported\n");
                return -EINVAL;
@@ -300,8 +337,7 @@ static void vmw_ldu_connector_restore(struct drm_connector *connector)
 static enum drm_connector_status
        vmw_ldu_connector_detect(struct drm_connector *connector)
 {
-       /* XXX vmwctrl should control connection status */
-       if (vmw_connector_to_ldu(connector)->base.unit == 0)
+       if (vmw_connector_to_ldu(connector)->pref_active)
                return connector_status_connected;
        return connector_status_disconnected;
 }
@@ -312,10 +348,9 @@ static struct drm_display_mode vmw_ldu_connector_builtin[] = {
                   752, 800, 0, 480, 489, 492, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
        /* 800x600@60Hz */
-       { DRM_MODE("800x600",
-                  DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
-                  40000, 800, 840, 968, 1056, 0, 600, 601, 605, 628,
-                  0, DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
+       { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 40000, 800, 840,
+                  968, 1056, 0, 600, 601, 605, 628, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
        /* 1024x768@60Hz */
        { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048,
                   1184, 1344, 0, 768, 771, 777, 806, 0,
@@ -387,10 +422,34 @@ static struct drm_display_mode vmw_ldu_connector_builtin[] = {
 static int vmw_ldu_connector_fill_modes(struct drm_connector *connector,
                                        uint32_t max_width, uint32_t max_height)
 {
+       struct vmw_legacy_display_unit *ldu = vmw_connector_to_ldu(connector);
        struct drm_device *dev = connector->dev;
        struct drm_display_mode *mode = NULL;
+       struct drm_display_mode prefmode = { DRM_MODE("preferred",
+               DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+               DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC)
+       };
        int i;
 
+       /* Add preferred mode */
+       {
+               mode = drm_mode_duplicate(dev, &prefmode);
+               if (!mode)
+                       return 0;
+               mode->hdisplay = ldu->pref_width;
+               mode->vdisplay = ldu->pref_height;
+               mode->vrefresh = drm_mode_vrefresh(mode);
+               drm_mode_probed_add(connector, mode);
+
+               if (ldu->pref_mode) {
+                       list_del_init(&ldu->pref_mode->head);
+                       drm_mode_destroy(dev, ldu->pref_mode);
+               }
+
+               ldu->pref_mode = mode;
+       }
+
        for (i = 0; vmw_ldu_connector_builtin[i].type != 0; i++) {
                if (vmw_ldu_connector_builtin[i].hdisplay > max_width ||
                    vmw_ldu_connector_builtin[i].vdisplay > max_height)
@@ -443,18 +502,21 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
        if (!ldu)
                return -ENOMEM;
 
-       ldu->unit = unit;
+       ldu->base.unit = unit;
        crtc = &ldu->base.crtc;
        encoder = &ldu->base.encoder;
        connector = &ldu->base.connector;
 
+       INIT_LIST_HEAD(&ldu->active);
+
+       ldu->pref_active = (unit == 0);
+       ldu->pref_width = 800;
+       ldu->pref_height = 600;
+       ldu->pref_mode = NULL;
+
        drm_connector_init(dev, connector, &vmw_legacy_connector_funcs,
                           DRM_MODE_CONNECTOR_LVDS);
-       /* Initial status */
-       if (unit == 0)
-               connector->status = connector_status_connected;
-       else
-               connector->status = connector_status_disconnected;
+       connector->status = vmw_ldu_connector_detect(connector);
 
        drm_encoder_init(dev, encoder, &vmw_legacy_encoder_funcs,
                         DRM_MODE_ENCODER_LVDS);
@@ -462,8 +524,6 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
        encoder->possible_crtcs = (1 << unit);
        encoder->possible_clones = 0;
 
-       INIT_LIST_HEAD(&ldu->active);
-
        drm_crtc_init(dev, crtc, &vmw_legacy_crtc_funcs);
 
        drm_connector_attach_property(connector,
@@ -487,18 +547,22 @@ int vmw_kms_init_legacy_display_system(struct vmw_private *dev_priv)
 
        INIT_LIST_HEAD(&dev_priv->ldu_priv->active);
        dev_priv->ldu_priv->num_active = 0;
+       dev_priv->ldu_priv->last_num_active = 0;
        dev_priv->ldu_priv->fb = NULL;
 
        drm_mode_create_dirty_info_property(dev_priv->dev);
 
        vmw_ldu_init(dev_priv, 0);
-       vmw_ldu_init(dev_priv, 1);
-       vmw_ldu_init(dev_priv, 2);
-       vmw_ldu_init(dev_priv, 3);
-       vmw_ldu_init(dev_priv, 4);
-       vmw_ldu_init(dev_priv, 5);
-       vmw_ldu_init(dev_priv, 6);
-       vmw_ldu_init(dev_priv, 7);
+       /* for old hardware without multimon only enable one display */
+       if (dev_priv->capabilities & SVGA_CAP_MULTIMON) {
+               vmw_ldu_init(dev_priv, 1);
+               vmw_ldu_init(dev_priv, 2);
+               vmw_ldu_init(dev_priv, 3);
+               vmw_ldu_init(dev_priv, 4);
+               vmw_ldu_init(dev_priv, 5);
+               vmw_ldu_init(dev_priv, 6);
+               vmw_ldu_init(dev_priv, 7);
+       }
 
        return 0;
 }
@@ -514,3 +578,42 @@ int vmw_kms_close_legacy_display_system(struct vmw_private *dev_priv)
 
        return 0;
 }
+
+int vmw_kms_ldu_update_layout(struct vmw_private *dev_priv, unsigned num,
+                             struct drm_vmw_rect *rects)
+{
+       struct drm_device *dev = dev_priv->dev;
+       struct vmw_legacy_display_unit *ldu;
+       struct drm_connector *con;
+       int i;
+
+       mutex_lock(&dev->mode_config.mutex);
+
+#if 0
+       DRM_INFO("%s: new layout ", __func__);
+       for (i = 0; i < (int)num; i++)
+               DRM_INFO("(%i, %i %ux%u) ", rects[i].x, rects[i].y,
+                        rects[i].w, rects[i].h);
+       DRM_INFO("\n");
+#else
+       (void)i;
+#endif
+
+       list_for_each_entry(con, &dev->mode_config.connector_list, head) {
+               ldu = vmw_connector_to_ldu(con);
+               if (num > ldu->base.unit) {
+                       ldu->pref_width = rects[ldu->base.unit].w;
+                       ldu->pref_height = rects[ldu->base.unit].h;
+                       ldu->pref_active = true;
+               } else {
+                       ldu->pref_width = 800;
+                       ldu->pref_height = 600;
+                       ldu->pref_active = false;
+               }
+               con->status = vmw_ldu_connector_detect(con);
+       }
+
+       mutex_unlock(&dev->mode_config.mutex);
+
+       return 0;
+}
index ad566c85b075da13305ecef856b254ff4dc30a6b..df2036ed18d5f2c920ba61f99b716998a6f25329 100644 (file)
@@ -358,6 +358,8 @@ static int vmw_overlay_update_stream(struct vmw_private *dev_priv,
        if (stream->buf != buf)
                stream->buf = vmw_dmabuf_reference(buf);
        stream->saved = *arg;
+       /* stream is no longer stopped/paused */
+       stream->paused = false;
 
        return 0;
 }
index 441e38c95a8535b863d924aea1c468872ba6d27a..b87569e96b163c04fb35790ef8c457999480e3f3 100644 (file)
@@ -1,12 +1,32 @@
 /*
- * vgaarb.c
+ * vgaarb.c: Implements the VGA arbitration. For details refer to
+ * Documentation/vgaarbiter.txt
+ *
  *
  * (C) Copyright 2005 Benjamin Herrenschmidt <benh@kernel.crashing.org>
  * (C) Copyright 2007 Paulo R. Zanoni <przanoni@gmail.com>
  * (C) Copyright 2007, 2009 Tiago Vignatti <vignatti@freedesktop.org>
  *
- * Implements the VGA arbitration. For details refer to
- * Documentation/vgaarbiter.txt
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS
+ * IN THE SOFTWARE.
+ *
  */
 
 #include <linux/module.h>
@@ -155,8 +175,8 @@ static struct vga_device *__vga_tryget(struct vga_device *vgadev,
            (vgadev->decodes & VGA_RSRC_LEGACY_MEM))
                rsrc |= VGA_RSRC_LEGACY_MEM;
 
-       pr_devel("%s: %d\n", __func__, rsrc);
-       pr_devel("%s: owns: %d\n", __func__, vgadev->owns);
+       pr_debug("%s: %d\n", __func__, rsrc);
+       pr_debug("%s: owns: %d\n", __func__, vgadev->owns);
 
        /* Check what resources we need to acquire */
        wants = rsrc & ~vgadev->owns;
@@ -268,7 +288,7 @@ static void __vga_put(struct vga_device *vgadev, unsigned int rsrc)
 {
        unsigned int old_locks = vgadev->locks;
 
-       pr_devel("%s\n", __func__);
+       pr_debug("%s\n", __func__);
 
        /* Update our counters, and account for equivalent legacy resources
         * if we decode them
@@ -575,6 +595,7 @@ static inline void vga_update_device_decodes(struct vga_device *vgadev,
                else
                        vga_decode_count--;
        }
+       pr_debug("vgaarb: decoding count now is: %d\n", vga_decode_count);
 }
 
 void __vga_set_legacy_decoding(struct pci_dev *pdev, unsigned int decodes, bool userspace)
@@ -831,7 +852,7 @@ static ssize_t vga_arb_write(struct file *file, const char __user * buf,
                curr_pos += 5;
                remaining -= 5;
 
-               pr_devel("client 0x%p called 'lock'\n", priv);
+               pr_debug("client 0x%p called 'lock'\n", priv);
 
                if (!vga_str_to_iostate(curr_pos, remaining, &io_state)) {
                        ret_val = -EPROTO;
@@ -867,7 +888,7 @@ static ssize_t vga_arb_write(struct file *file, const char __user * buf,
                curr_pos += 7;
                remaining -= 7;
 
-               pr_devel("client 0x%p called 'unlock'\n", priv);
+               pr_debug("client 0x%p called 'unlock'\n", priv);
 
                if (strncmp(curr_pos, "all", 3) == 0)
                        io_state = VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM;
@@ -917,7 +938,7 @@ static ssize_t vga_arb_write(struct file *file, const char __user * buf,
                curr_pos += 8;
                remaining -= 8;
 
-               pr_devel("client 0x%p called 'trylock'\n", priv);
+               pr_debug("client 0x%p called 'trylock'\n", priv);
 
                if (!vga_str_to_iostate(curr_pos, remaining, &io_state)) {
                        ret_val = -EPROTO;
@@ -961,7 +982,7 @@ static ssize_t vga_arb_write(struct file *file, const char __user * buf,
 
                curr_pos += 7;
                remaining -= 7;
-               pr_devel("client 0x%p called 'target'\n", priv);
+               pr_debug("client 0x%p called 'target'\n", priv);
                /* if target is default */
                if (!strncmp(curr_pos, "default", 7))
                        pdev = pci_dev_get(vga_default_device());
@@ -971,11 +992,11 @@ static ssize_t vga_arb_write(struct file *file, const char __user * buf,
                                ret_val = -EPROTO;
                                goto done;
                        }
-                       pr_devel("vgaarb: %s ==> %x:%x:%x.%x\n", curr_pos,
+                       pr_debug("vgaarb: %s ==> %x:%x:%x.%x\n", curr_pos,
                                domain, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
 
                        pbus = pci_find_bus(domain, bus);
-                       pr_devel("vgaarb: pbus %p\n", pbus);
+                       pr_debug("vgaarb: pbus %p\n", pbus);
                        if (pbus == NULL) {
                                pr_err("vgaarb: invalid PCI domain and/or bus address %x:%x\n",
                                        domain, bus);
@@ -983,7 +1004,7 @@ static ssize_t vga_arb_write(struct file *file, const char __user * buf,
                                goto done;
                        }
                        pdev = pci_get_slot(pbus, devfn);
-                       pr_devel("vgaarb: pdev %p\n", pdev);
+                       pr_debug("vgaarb: pdev %p\n", pdev);
                        if (!pdev) {
                                pr_err("vgaarb: invalid PCI address %x:%x\n",
                                        bus, devfn);
@@ -993,7 +1014,7 @@ static ssize_t vga_arb_write(struct file *file, const char __user * buf,
                }
 
                vgadev = vgadev_find(pdev);
-               pr_devel("vgaarb: vgadev %p\n", vgadev);
+               pr_debug("vgaarb: vgadev %p\n", vgadev);
                if (vgadev == NULL) {
                        pr_err("vgaarb: this pci device is not a vga device\n");
                        pci_dev_put(pdev);
@@ -1029,7 +1050,7 @@ static ssize_t vga_arb_write(struct file *file, const char __user * buf,
        } else if (strncmp(curr_pos, "decodes ", 8) == 0) {
                curr_pos += 8;
                remaining -= 8;
-               pr_devel("vgaarb: client 0x%p called 'decodes'\n", priv);
+               pr_debug("vgaarb: client 0x%p called 'decodes'\n", priv);
 
                if (!vga_str_to_iostate(curr_pos, remaining, &io_state)) {
                        ret_val = -EPROTO;
@@ -1058,7 +1079,7 @@ static unsigned int vga_arb_fpoll(struct file *file, poll_table * wait)
 {
        struct vga_arb_private *priv = file->private_data;
 
-       pr_devel("%s\n", __func__);
+       pr_debug("%s\n", __func__);
 
        if (priv == NULL)
                return -ENODEV;
@@ -1071,7 +1092,7 @@ static int vga_arb_open(struct inode *inode, struct file *file)
        struct vga_arb_private *priv;
        unsigned long flags;
 
-       pr_devel("%s\n", __func__);
+       pr_debug("%s\n", __func__);
 
        priv = kmalloc(sizeof(struct vga_arb_private), GFP_KERNEL);
        if (priv == NULL)
@@ -1101,7 +1122,7 @@ static int vga_arb_release(struct inode *inode, struct file *file)
        unsigned long flags;
        int i;
 
-       pr_devel("%s\n", __func__);
+       pr_debug("%s\n", __func__);
 
        if (priv == NULL)
                return -ENODEV;
@@ -1112,7 +1133,7 @@ static int vga_arb_release(struct inode *inode, struct file *file)
                uc = &priv->cards[i];
                if (uc->pdev == NULL)
                        continue;
-               pr_devel("uc->io_cnt == %d, uc->mem_cnt == %d\n",
+               pr_debug("uc->io_cnt == %d, uc->mem_cnt == %d\n",
                         uc->io_cnt, uc->mem_cnt);
                while (uc->io_cnt--)
                        vga_put(uc->pdev, VGA_RSRC_LEGACY_IO);
@@ -1165,7 +1186,7 @@ static int pci_notify(struct notifier_block *nb, unsigned long action,
        struct pci_dev *pdev = to_pci_dev(dev);
        bool notify = false;
 
-       pr_devel("%s\n", __func__);
+       pr_debug("%s\n", __func__);
 
        /* For now we're only intereted in devices added and removed. I didn't
         * test this thing here, so someone needs to double check for the
index 4086c7257f912f23608c261f1b29f68b3c04a602..f13c843a2964bbb07728c06363cda065937293bb 100644 (file)
@@ -316,7 +316,6 @@ static int __devinit adt7411_probe(struct i2c_client *client,
  exit_remove:
        sysfs_remove_group(&client->dev.kobj, &adt7411_attr_grp);
  exit_free:
-       i2c_set_clientdata(client, NULL);
        kfree(data);
        return ret;
 }
@@ -327,7 +326,6 @@ static int __devexit adt7411_remove(struct i2c_client *client)
 
        hwmon_device_unregister(data->hwmon_dev);
        sysfs_remove_group(&client->dev.kobj, &adt7411_attr_grp);
-       i2c_set_clientdata(client, NULL);
        kfree(data);
        return 0;
 }
index 0f388adc61876cc3f0481de786289d724b1977a6..3b973f30b1f6495a89029b4002816ee8ff299353 100644 (file)
@@ -1141,7 +1141,6 @@ exit_remove:
                                   &(asc7621_params[i].sda.dev_attr));
        }
 
-       i2c_set_clientdata(client, NULL);
        kfree(data);
        return err;
 }
@@ -1196,7 +1195,6 @@ static int asc7621_remove(struct i2c_client *client)
                                   &(asc7621_params[i].sda.dev_attr));
        }
 
-       i2c_set_clientdata(client, NULL);
        kfree(data);
        return 0;
 }
index bad2cf3ef4a448aa76a72033b527647c6434f9d3..0f58ecc5334d941cb4114a3681e2e5a44893280e 100644 (file)
@@ -662,7 +662,6 @@ exit_remove:
        sysfs_remove_group(&client->dev.kobj, &f75375_group);
 exit_free:
        kfree(data);
-       i2c_set_clientdata(client, NULL);
        return err;
 }
 
@@ -672,7 +671,6 @@ static int f75375_remove(struct i2c_client *client)
        hwmon_device_unregister(data->hwmon_dev);
        sysfs_remove_group(&client->dev.kobj, &f75375_group);
        kfree(data);
-       i2c_set_clientdata(client, NULL);
        return 0;
 }
 
index 09ea12e0a55185b3e5d0699cf7922898752b70af..1f63d1a3af5ebc4aae1d31f18d505881273b8a65 100644 (file)
@@ -236,7 +236,6 @@ error_hwmon_device_register:
        sysfs_remove_group(&client->dev.kobj, &g760a_group);
 error_sysfs_create_group:
        kfree(data);
-       i2c_set_clientdata(client, NULL);
 
        return err;
 }
@@ -247,7 +246,6 @@ static int g760a_remove(struct i2c_client *client)
        hwmon_device_unregister(data->hwmon_dev);
        sysfs_remove_group(&client->dev.kobj, &g760a_group);
        kfree(data);
-       i2c_set_clientdata(client, NULL);
 
        return 0;
 }
index 4d1b76bc81486b64dc6963d8ee415c2608c0fb82..29b9030d42c3111ecfdc49cc2a9cbf8aa4257cd6 100644 (file)
@@ -136,7 +136,6 @@ static int lm73_remove(struct i2c_client *client)
 
        hwmon_device_unregister(hwmon_dev);
        sysfs_remove_group(&client->dev.kobj, &lm73_group);
-       i2c_set_clientdata(client, NULL);
        return 0;
 }
 
index 56463428a419ce8f4222f5504b96f57cd44503fd..393f354f92a4c012c46ee96a8062f7b604697cdf 100644 (file)
@@ -192,7 +192,6 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
 exit_remove:
        sysfs_remove_group(&client->dev.kobj, &lm75_group);
 exit_free:
-       i2c_set_clientdata(client, NULL);
        kfree(data);
        return status;
 }
@@ -204,7 +203,6 @@ static int lm75_remove(struct i2c_client *client)
        hwmon_device_unregister(data->hwmon_dev);
        sysfs_remove_group(&client->dev.kobj, &lm75_group);
        lm75_write_value(client, LM75_REG_CONF, data->orig_conf);
-       i2c_set_clientdata(client, NULL);
        kfree(data);
        return 0;
 }
index 8fc8eb8cba47400fd23614a392b135949aab8c76..94741d42112da02ca902b2e87beacbe96aab3cd3 100644 (file)
@@ -399,7 +399,6 @@ static int lm95241_remove(struct i2c_client *client)
        hwmon_device_unregister(data->hwmon_dev);
        sysfs_remove_group(&client->dev.kobj, &lm95241_group);
 
-       i2c_set_clientdata(client, NULL);
        kfree(data);
        return 0;
 }
index 8013895a1fafc19918faca9b838be7b4dc58d581..93187c3cb5e7949a72b5599bb127fce61701ec49 100644 (file)
@@ -224,7 +224,6 @@ fail_remove_sysfs:
 fail_restore_config:
        tmp102_write_reg(client, TMP102_CONF_REG, tmp102->config_orig);
 fail_free:
-       i2c_set_clientdata(client, NULL);
        kfree(tmp102);
 
        return status;
@@ -247,7 +246,6 @@ static int __devexit tmp102_remove(struct i2c_client *client)
                                         config | TMP102_CONF_SD);
        }
 
-       i2c_set_clientdata(client, NULL);
        kfree(tmp102);
 
        return 0;
index 738c472ece273bf972b1206e9b164b88d046b0bc..6b4165c12092b388c365824c49c8c7d6a65c9a8c 100644 (file)
@@ -295,7 +295,6 @@ exit_remove:
        sysfs_remove_group(&client->dev.kobj, &tmp421_group);
 
 exit_free:
-       i2c_set_clientdata(client, NULL);
        kfree(data);
 
        return err;
@@ -308,7 +307,6 @@ static int tmp421_remove(struct i2c_client *client)
        hwmon_device_unregister(data->hwmon_dev);
        sysfs_remove_group(&client->dev.kobj, &tmp421_group);
 
-       i2c_set_clientdata(client, NULL);
        kfree(data);
 
        return 0;
index 32d4adee73db650fc5ba2b2cc42586b12b642cd3..c84b9b4e69609e70e55419a6faae4f8f1905a63c 100644 (file)
@@ -1197,7 +1197,6 @@ ERROR4:
        if (data->lm75[1])
                i2c_unregister_device(data->lm75[1]);
 ERROR3:
-       i2c_set_clientdata(client, NULL);
        kfree(data);
 ERROR1:
        return err;
@@ -1219,7 +1218,6 @@ w83781d_remove(struct i2c_client *client)
        if (data->lm75[1])
                i2c_unregister_device(data->lm75[1]);
 
-       i2c_set_clientdata(client, NULL);
        kfree(data);
 
        return 0;
index 87ab0568bb0ed1e18b979b675a5d8db0303ef545..bceafbfa72683698769890bfb664dbe57ea3a010 100644 (file)
@@ -475,6 +475,26 @@ config I2C_PASEMI
        help
          Supports the PA Semi PWRficient on-chip SMBus interfaces.
 
+config I2C_PCA_PLATFORM
+       tristate "PCA9564/PCA9665 as platform device"
+       select I2C_ALGOPCA
+       default n
+       help
+         This driver supports a memory mapped Philips PCA9564/PCA9665
+         parallel bus to I2C bus controller.
+
+         This driver can also be built as a module.  If so, the module
+         will be called i2c-pca-platform.
+
+config I2C_PMCMSP
+       tristate "PMC MSP I2C TWI Controller"
+       depends on PMC_MSP
+       help
+         This driver supports the PMC TWI controller on MSP devices.
+
+         This driver can also be built as module. If so, the module
+         will be called i2c-pmcmsp.
+
 config I2C_PNX
        tristate "I2C bus support for Philips PNX targets"
        depends on ARCH_PNX4008
@@ -711,26 +731,6 @@ config I2C_PCA_ISA
          delays when I2C/SMBus chip drivers are loaded (e.g. at boot
          time).  If unsure, say N.
 
-config I2C_PCA_PLATFORM
-       tristate "PCA9564/PCA9665 as platform device"
-       select I2C_ALGOPCA
-       default n
-       help
-         This driver supports a memory mapped Philips PCA9564/PCA9665
-         parallel bus to I2C bus controller.
-
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-pca-platform.
-
-config I2C_PMCMSP
-       tristate "PMC MSP I2C TWI Controller"
-       depends on PMC_MSP
-       help
-         This driver supports the PMC TWI controller on MSP devices.
-
-         This driver can also be built as module. If so, the module
-         will be called i2c-pmcmsp.
-
 config I2C_SIBYTE
        tristate "SiByte SMBus interface"
        depends on SIBYTE_SB1xxx_SOC
index 097236f631e8d68e57a2ca87562912c995f280ca..936880bd1dc58404d4ed666919939729c7c99585 100644 (file)
@@ -27,7 +27,7 @@ obj-$(CONFIG_I2C_VIAPRO)      += i2c-viapro.o
 obj-$(CONFIG_I2C_HYDRA)                += i2c-hydra.o
 obj-$(CONFIG_I2C_POWERMAC)     += i2c-powermac.o
 
-# Embebbed system I2C/SMBus host controller drivers
+# Embedded system I2C/SMBus host controller drivers
 obj-$(CONFIG_I2C_AT91)         += i2c-at91.o
 obj-$(CONFIG_I2C_AU1550)       += i2c-au1550.o
 obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o
@@ -46,6 +46,8 @@ obj-$(CONFIG_I2C_NOMADIK)     += i2c-nomadik.o
 obj-$(CONFIG_I2C_OCORES)       += i2c-ocores.o
 obj-$(CONFIG_I2C_OMAP)         += i2c-omap.o
 obj-$(CONFIG_I2C_PASEMI)       += i2c-pasemi.o
+obj-$(CONFIG_I2C_PCA_PLATFORM) += i2c-pca-platform.o
+obj-$(CONFIG_I2C_PMCMSP)       += i2c-pmcmsp.o
 obj-$(CONFIG_I2C_PNX)          += i2c-pnx.o
 obj-$(CONFIG_I2C_PXA)          += i2c-pxa.o
 obj-$(CONFIG_I2C_S3C2410)      += i2c-s3c2410.o
@@ -68,8 +70,6 @@ obj-$(CONFIG_I2C_TINY_USB)    += i2c-tiny-usb.o
 obj-$(CONFIG_I2C_ACORN)                += i2c-acorn.o
 obj-$(CONFIG_I2C_ELEKTOR)      += i2c-elektor.o
 obj-$(CONFIG_I2C_PCA_ISA)      += i2c-pca-isa.o
-obj-$(CONFIG_I2C_PCA_PLATFORM) += i2c-pca-platform.o
-obj-$(CONFIG_I2C_PMCMSP)       += i2c-pmcmsp.o
 obj-$(CONFIG_I2C_SIBYTE)       += i2c-sibyte.o
 obj-$(CONFIG_I2C_STUB)         += i2c-stub.o
 obj-$(CONFIG_SCx200_ACB)       += scx200_acb.o
index e0f833cca3f1193c24480c4efc446a7568a9a3af..1cca2631e5b3bc8331062617a68968006a9fd06e 100644 (file)
@@ -47,7 +47,6 @@ static DEFINE_MUTEX(core_lock);
 static DEFINE_IDR(i2c_adapter_idr);
 
 static struct device_type i2c_client_type;
-static int i2c_check_addr(struct i2c_adapter *adapter, int addr);
 static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver);
 
 /* ------------------------------------------------------------------------- */
@@ -371,6 +370,59 @@ struct i2c_client *i2c_verify_client(struct device *dev)
 EXPORT_SYMBOL(i2c_verify_client);
 
 
+/* This is a permissive address validity check, I2C address map constraints
+ * are purposedly not enforced, except for the general call address. */
+static int i2c_check_client_addr_validity(const struct i2c_client *client)
+{
+       if (client->flags & I2C_CLIENT_TEN) {
+               /* 10-bit address, all values are valid */
+               if (client->addr > 0x3ff)
+                       return -EINVAL;
+       } else {
+               /* 7-bit address, reject the general call address */
+               if (client->addr == 0x00 || client->addr > 0x7f)
+                       return -EINVAL;
+       }
+       return 0;
+}
+
+/* And this is a strict address validity check, used when probing. If a
+ * device uses a reserved address, then it shouldn't be probed. 7-bit
+ * addressing is assumed, 10-bit address devices are rare and should be
+ * explicitly enumerated. */
+static int i2c_check_addr_validity(unsigned short addr)
+{
+       /*
+        * Reserved addresses per I2C specification:
+        *  0x00       General call address / START byte
+        *  0x01       CBUS address
+        *  0x02       Reserved for different bus format
+        *  0x03       Reserved for future purposes
+        *  0x04-0x07  Hs-mode master code
+        *  0x78-0x7b  10-bit slave addressing
+        *  0x7c-0x7f  Reserved for future purposes
+        */
+       if (addr < 0x08 || addr > 0x77)
+               return -EINVAL;
+       return 0;
+}
+
+static int __i2c_check_addr_busy(struct device *dev, void *addrp)
+{
+       struct i2c_client       *client = i2c_verify_client(dev);
+       int                     addr = *(int *)addrp;
+
+       if (client && client->addr == addr)
+               return -EBUSY;
+       return 0;
+}
+
+static int i2c_check_addr_busy(struct i2c_adapter *adapter, int addr)
+{
+       return device_for_each_child(&adapter->dev, &addr,
+                                    __i2c_check_addr_busy);
+}
+
 /**
  * i2c_new_device - instantiate an i2c device
  * @adap: the adapter managing the device
@@ -410,8 +462,16 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
 
        strlcpy(client->name, info->type, sizeof(client->name));
 
+       /* Check for address validity */
+       status = i2c_check_client_addr_validity(client);
+       if (status) {
+               dev_err(&adap->dev, "Invalid %d-bit I2C address 0x%02hx\n",
+                       client->flags & I2C_CLIENT_TEN ? 10 : 7, client->addr);
+               goto out_err_silent;
+       }
+
        /* Check for address business */
-       status = i2c_check_addr(adap, client->addr);
+       status = i2c_check_addr_busy(adap, client->addr);
        if (status)
                goto out_err;
 
@@ -436,6 +496,7 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
 out_err:
        dev_err(&adap->dev, "Failed to register i2c client %s at 0x%02x "
                "(%d)\n", client->name, client->addr, status);
+out_err_silent:
        kfree(client);
        return NULL;
 }
@@ -561,15 +622,9 @@ i2c_sysfs_new_device(struct device *dev, struct device_attribute *attr,
                return -EINVAL;
        }
 
-       if (info.addr < 0x03 || info.addr > 0x77) {
-               dev_err(dev, "%s: Invalid I2C address 0x%hx\n", "new_device",
-                       info.addr);
-               return -EINVAL;
-       }
-
        client = i2c_new_device(adap, &info);
        if (!client)
-               return -EEXIST;
+               return -EINVAL;
 
        /* Keep track of the added device */
        i2c_lock_adapter(adap);
@@ -1024,21 +1079,6 @@ EXPORT_SYMBOL(i2c_del_driver);
 
 /* ------------------------------------------------------------------------- */
 
-static int __i2c_check_addr(struct device *dev, void *addrp)
-{
-       struct i2c_client       *client = i2c_verify_client(dev);
-       int                     addr = *(int *)addrp;
-
-       if (client && client->addr == addr)
-               return -EBUSY;
-       return 0;
-}
-
-static int i2c_check_addr(struct i2c_adapter *adapter, int addr)
-{
-       return device_for_each_child(&adapter->dev, &addr, __i2c_check_addr);
-}
-
 /**
  * i2c_use_client - increments the reference count of the i2c client structure
  * @client: the client being referenced
@@ -1277,6 +1317,41 @@ EXPORT_SYMBOL(i2c_master_recv);
  * ----------------------------------------------------
  */
 
+/*
+ * Legacy default probe function, mostly relevant for SMBus. The default
+ * probe method is a quick write, but it is known to corrupt the 24RF08
+ * EEPROMs due to a state machine bug, and could also irreversibly
+ * write-protect some EEPROMs, so for address ranges 0x30-0x37 and 0x50-0x5f,
+ * we use a short byte read instead. Also, some bus drivers don't implement
+ * quick write, so we fallback to a byte read in that case too.
+ * On x86, there is another special case for FSC hardware monitoring chips,
+ * which want regular byte reads (address 0x73.) Fortunately, these are the
+ * only known chips using this I2C address on PC hardware.
+ * Returns 1 if probe succeeded, 0 if not.
+ */
+static int i2c_default_probe(struct i2c_adapter *adap, unsigned short addr)
+{
+       int err;
+       union i2c_smbus_data dummy;
+
+#ifdef CONFIG_X86
+       if (addr == 0x73 && (adap->class & I2C_CLASS_HWMON)
+        && i2c_check_functionality(adap, I2C_FUNC_SMBUS_READ_BYTE_DATA))
+               err = i2c_smbus_xfer(adap, addr, 0, I2C_SMBUS_READ, 0,
+                                    I2C_SMBUS_BYTE_DATA, &dummy);
+       else
+#endif
+       if ((addr & ~0x07) == 0x30 || (addr & ~0x0f) == 0x50
+        || !i2c_check_functionality(adap, I2C_FUNC_SMBUS_QUICK))
+               err = i2c_smbus_xfer(adap, addr, 0, I2C_SMBUS_READ, 0,
+                                    I2C_SMBUS_BYTE, &dummy);
+       else
+               err = i2c_smbus_xfer(adap, addr, 0, I2C_SMBUS_WRITE, 0,
+                                    I2C_SMBUS_QUICK, NULL);
+
+       return err >= 0;
+}
+
 static int i2c_detect_address(struct i2c_client *temp_client,
                              struct i2c_driver *driver)
 {
@@ -1286,34 +1361,20 @@ static int i2c_detect_address(struct i2c_client *temp_client,
        int err;
 
        /* Make sure the address is valid */
-       if (addr < 0x03 || addr > 0x77) {
+       err = i2c_check_addr_validity(addr);
+       if (err) {
                dev_warn(&adapter->dev, "Invalid probe address 0x%02x\n",
                         addr);
-               return -EINVAL;
+               return err;
        }
 
        /* Skip if already in use */
-       if (i2c_check_addr(adapter, addr))
+       if (i2c_check_addr_busy(adapter, addr))
                return 0;
 
        /* Make sure there is something at this address */
-       if (addr == 0x73 && (adapter->class & I2C_CLASS_HWMON)) {
-               /* Special probe for FSC hwmon chips */
-               union i2c_smbus_data dummy;
-
-               if (i2c_smbus_xfer(adapter, addr, 0, I2C_SMBUS_READ, 0,
-                                  I2C_SMBUS_BYTE_DATA, &dummy) < 0)
-                       return 0;
-       } else {
-               if (i2c_smbus_xfer(adapter, addr, 0, I2C_SMBUS_WRITE, 0,
-                                  I2C_SMBUS_QUICK, NULL) < 0)
-                       return 0;
-
-               /* Prevent 24RF08 corruption */
-               if ((addr & ~0x0f) == 0x50)
-                       i2c_smbus_xfer(adapter, addr, 0, I2C_SMBUS_WRITE, 0,
-                                      I2C_SMBUS_QUICK, NULL);
-       }
+       if (!i2c_default_probe(adapter, addr))
+               return 0;
 
        /* Finally call the custom detection function */
        memset(&info, 0, sizeof(struct i2c_board_info));
@@ -1407,42 +1468,22 @@ i2c_new_probed_device(struct i2c_adapter *adap,
 
        for (i = 0; addr_list[i] != I2C_CLIENT_END; i++) {
                /* Check address validity */
-               if (addr_list[i] < 0x03 || addr_list[i] > 0x77) {
+               if (i2c_check_addr_validity(addr_list[i]) < 0) {
                        dev_warn(&adap->dev, "Invalid 7-bit address "
                                 "0x%02x\n", addr_list[i]);
                        continue;
                }
 
                /* Check address availability */
-               if (i2c_check_addr(adap, addr_list[i])) {
+               if (i2c_check_addr_busy(adap, addr_list[i])) {
                        dev_dbg(&adap->dev, "Address 0x%02x already in "
                                "use, not probing\n", addr_list[i]);
                        continue;
                }
 
-               /* Test address responsiveness
-                  The default probe method is a quick write, but it is known
-                  to corrupt the 24RF08 EEPROMs due to a state machine bug,
-                  and could also irreversibly write-protect some EEPROMs, so
-                  for address ranges 0x30-0x37 and 0x50-0x5f, we use a byte
-                  read instead. Also, some bus drivers don't implement
-                  quick write, so we fallback to a byte read it that case
-                  too. */
-               if ((addr_list[i] & ~0x07) == 0x30
-                || (addr_list[i] & ~0x0f) == 0x50
-                || !i2c_check_functionality(adap, I2C_FUNC_SMBUS_QUICK)) {
-                       union i2c_smbus_data data;
-
-                       if (i2c_smbus_xfer(adap, addr_list[i], 0,
-                                          I2C_SMBUS_READ, 0,
-                                          I2C_SMBUS_BYTE, &data) >= 0)
-                               break;
-               } else {
-                       if (i2c_smbus_xfer(adap, addr_list[i], 0,
-                                          I2C_SMBUS_WRITE, 0,
-                                          I2C_SMBUS_QUICK, NULL) >= 0)
-                               break;
-               }
+               /* Test address responsiveness */
+               if (i2c_default_probe(adap, addr_list[i]))
+                       break;
        }
 
        if (addr_list[i] == I2C_CLIENT_END) {
index a24e0bfe9201a87a7012b1f42791d925aaf5b76f..f61ccc1e5ea3ea7a350af1cc3ec7858bf0f5dbe8 100644 (file)
@@ -173,7 +173,6 @@ static int smbalert_remove(struct i2c_client *ara)
 
        cancel_work_sync(&alert->alert);
 
-       i2c_set_clientdata(ara, NULL);
        kfree(alert);
        return 0;
 }
index 4771ab172b59b22dda93eaa5437aba8019d7a208..744600eff222935b8af076ac8122c07f22a896e9 100644 (file)
@@ -287,7 +287,6 @@ static int __devexit adp5588_remove(struct i2c_client *client)
        free_irq(client->irq, kpad);
        cancel_delayed_work_sync(&kpad->work);
        input_unregister_device(kpad->input);
-       i2c_set_clientdata(client, NULL);
        kfree(kpad);
 
        return 0;
index bc696931fed7b127a87afb262f63aa26fc63ac9a..40b032f0e32cd47a12e33f300810da9a131941c0 100644 (file)
@@ -778,8 +778,6 @@ static int __devexit lm8323_remove(struct i2c_client *client)
        struct lm8323_chip *lm = i2c_get_clientdata(client);
        int i;
 
-       i2c_set_clientdata(client, NULL);
-
        disable_irq_wake(client->irq);
        free_irq(client->irq, lm);
        cancel_work_sync(&lm->work);
index 7fc8185e5c1bd8ab914cedb0f0d78e15e974ed89..9091ff5ea808b8829d7d9475f15f704532d10c5e 100644 (file)
@@ -265,7 +265,6 @@ static int __devexit max7359_remove(struct i2c_client *client)
 
        free_irq(client->irq, keypad);
        input_unregister_device(keypad->input_dev);
-       i2c_set_clientdata(client, NULL);
        kfree(keypad);
 
        return 0;
index 31f30087b591866c9e81af4401d0a3feeaae359e..fac695157e8afce221fb8dae22fa2d750d745963 100644 (file)
@@ -358,7 +358,6 @@ static int __devexit qt2160_remove(struct i2c_client *client)
        input_unregister_device(qt2160->input);
        kfree(qt2160);
 
-       i2c_set_clientdata(client, NULL);
        return 0;
 }
 
index 493c93f25e2abb96c0555d46d6ac9f20801d9098..00137bebcf974a8133ff3f4f4234bcace30cd084 100644 (file)
@@ -316,8 +316,6 @@ static int __devexit tca6416_keypad_remove(struct i2c_client *client)
        input_unregister_device(chip->input);
        kfree(chip);
 
-       i2c_set_clientdata(client, NULL);
-
        return 0;
 }
 
index e9adbe49f6a49fe0a01e74648747985cb517061d..2bef8fa56c948e0ba4305ea0f4f22450244f79d4 100644 (file)
@@ -97,7 +97,6 @@ static int __devexit ad714x_i2c_remove(struct i2c_client *client)
        struct ad714x_chip *chip = i2c_get_clientdata(client);
 
        ad714x_remove(chip);
-       i2c_set_clientdata(client, NULL);
 
        return 0;
 }
index 5c3ac4e0b055837976624cbd3ef1873cc81d82c6..0ac47d2898ec6d2baca97153f737f75878ffa950 100644 (file)
@@ -168,8 +168,6 @@ static int __devexit pcf8574_kp_remove(struct i2c_client *client)
        input_unregister_device(lp->idev);
        kfree(lp);
 
-       i2c_set_clientdata(client, NULL);
-
        return 0;
 }
 
index 8291e7399ffab3606d2563a8e7257e513b5179f6..0ae62f0bcb3216ca32c494e3a807a75a8f6753bd 100644 (file)
@@ -613,7 +613,6 @@ static int __devexit synaptics_i2c_remove(struct i2c_client *client)
                free_irq(client->irq, touch);
 
        input_unregister_device(touch->input);
-       i2c_set_clientdata(client, NULL);
        kfree(touch);
 
        return 0;
index 794d070c6900607752f2af1b7641f0cc98ef267f..4b32fb4704cd37b24f67c84db53de4ed431320c8 100644 (file)
@@ -812,10 +812,8 @@ static int __devinit ad7879_probe(struct i2c_client *client,
        ts->bus = client;
 
        error = ad7879_construct(client, ts);
-       if (error) {
-               i2c_set_clientdata(client, NULL);
+       if (error)
                kfree(ts);
-       }
 
        return error;
 }
@@ -825,7 +823,6 @@ static int __devexit ad7879_remove(struct i2c_client *client)
        struct ad7879 *ts = dev_get_drvdata(&client->dev);
 
        ad7879_destroy(client, ts);
-       i2c_set_clientdata(client, NULL);
        kfree(ts);
 
        return 0;
index 75f8b73010fa5aa30dd3758a7421697b16c03e46..7a3a916f84a857137332ba89a53373d9dfe136d7 100644 (file)
@@ -238,7 +238,6 @@ err2:
        input = NULL; /* so we dont try to free it below */
 err1:
        input_free_device(input);
-       i2c_set_clientdata(client, NULL);
        kfree(priv);
 err0:
        return err;
@@ -256,7 +255,6 @@ static int __devexit eeti_ts_remove(struct i2c_client *client)
        enable_irq(priv->irq);
 
        input_unregister_device(priv->input);
-       i2c_set_clientdata(client, NULL);
        kfree(priv);
 
        return 0;
index ce8ab0269f6fc755f6496e90a5a4cd4c8157b816..1fb0c2f06a4470657b1b05e5295b77b3c67d6236 100644 (file)
@@ -256,7 +256,6 @@ static int __devexit mcs5000_ts_remove(struct i2c_client *client)
        free_irq(client->irq, data);
        input_unregister_device(data->input_dev);
        kfree(data);
-       i2c_set_clientdata(client, NULL);
 
        return 0;
 }
index 769b479fcaa625fb4406096dd84746b89cc877e4..be23780e8a3e3b81be9df7b7cd0f8aab86d87e61 100644 (file)
@@ -347,8 +347,6 @@ static int __devexit tsc2007_remove(struct i2c_client *client)
        struct tsc2007  *ts = i2c_get_clientdata(client);
        struct tsc2007_platform_data *pdata = client->dev.platform_data;
 
-       i2c_set_clientdata(client, NULL);
-
        tsc2007_free_irq(ts);
 
        if (pdata->exit_platform_hw)
index 286b501a3573d3b7d0d4cec872fa7b40008c83d5..5dcdf9d69b3abae8d0370ccbe1a0d913c716e7d1 100644 (file)
@@ -742,7 +742,6 @@ failed_unregister_dev_file:
        for (i--; i >= 0; i--)
                device_remove_file(&led->client->dev, bd2802_attributes[i]);
 failed_free:
-       i2c_set_clientdata(client, NULL);
        kfree(led);
 
        return ret;
@@ -759,7 +758,6 @@ static int __exit bd2802_remove(struct i2c_client *client)
                bd2802_disable_adv_conf(led);
        for (i = 0; i < ARRAY_SIZE(bd2802_attributes); i++)
                device_remove_file(&led->client->dev, bd2802_attributes[i]);
-       i2c_set_clientdata(client, NULL);
        kfree(led);
 
        return 0;
index 932a58da76c4e97cba12a3c7b657b72dafa70e86..9010c054615e414fa5c236a8fe2cc4a700a00757 100644 (file)
@@ -432,7 +432,6 @@ static int __devexit lp3944_remove(struct i2c_client *client)
                }
 
        kfree(data);
-       i2c_set_clientdata(client, NULL);
 
        return 0;
 }
index 6682175fa9f7c4e3c5a91d99120c83b2003f6b9a..43d08756d823556b26f5c531d6837ff89818964b 100644 (file)
@@ -320,10 +320,8 @@ static int pca9532_probe(struct i2c_client *client,
        mutex_init(&data->update_lock);
 
        err = pca9532_configure(client, data, pca9532_pdata);
-       if (err) {
+       if (err)
                kfree(data);
-               i2c_set_clientdata(client, NULL);
-       }
 
        return err;
 }
@@ -351,7 +349,6 @@ static int pca9532_remove(struct i2c_client *client)
                }
 
        kfree(data);
-       i2c_set_clientdata(client, NULL);
        return 0;
 }
 
index 8ff50f234190a38129342d743a14c8c7c201ad6c..66aa3e8e786f545c4db0e6bd4318a173a792fc1e 100644 (file)
@@ -342,7 +342,6 @@ exit:
        }
 
        kfree(pca955x);
-       i2c_set_clientdata(client, NULL);
 
        return err;
 }
@@ -358,7 +357,6 @@ static int __devexit pca955x_remove(struct i2c_client *client)
        }
 
        kfree(pca955x);
-       i2c_set_clientdata(client, NULL);
 
        return 0;
 }
index 16d82f17ae82b3a2e0f5a5e37a0a73e18e51e7b5..c42eeb43042daa92d9f04e22b2205ce6d1d2a33d 100644 (file)
@@ -182,7 +182,6 @@ remove_thermostat(struct i2c_client *client)
 
        thermostat = NULL;
 
-       i2c_set_clientdata(client, NULL);
        kfree(th);
 
        return 0;
@@ -400,7 +399,6 @@ static int probe_thermostat(struct i2c_client *client,
        rc = read_reg(th, CONFIG_REG);
        if (rc < 0) {
                dev_err(&client->dev, "Thermostat failed to read config!\n");
-               i2c_set_clientdata(client, NULL);
                kfree(th);
                return -ENODEV;
        }
index d8257d35afde91c225b49bad6f0cc9885cf3fc69..647c6add2193e63d9bcec2be088ac2f28096a962 100644 (file)
@@ -107,10 +107,8 @@ static int wf_lm75_probe(struct i2c_client *client,
        i2c_set_clientdata(client, lm);
 
        rc = wf_register_sensor(&lm->sens);
-       if (rc) {
-               i2c_set_clientdata(client, NULL);
+       if (rc)
                kfree(lm);
-       }
 
        return rc;
 }
@@ -216,7 +214,6 @@ static int wf_lm75_remove(struct i2c_client *client)
        /* release sensor */
        wf_unregister_sensor(&lm->sens);
 
-       i2c_set_clientdata(client, NULL);
        return 0;
 }
 
index b486eb929fde725fb9e0271d4af46cdc241c2113..8204113268f471db6021ffa7915be03272a0c40c 100644 (file)
@@ -81,7 +81,6 @@ static int wf_max6690_probe(struct i2c_client *client,
 
        rc = wf_register_sensor(&max->sens);
        if (rc) {
-               i2c_set_clientdata(client, NULL);
                kfree(max);
        }
 
index e20330a28959bc539d0691337bf49438e2022efe..65a8ff3e1f8e8d4e1e73a7a7eda4bb9500fb9c82 100644 (file)
@@ -376,7 +376,6 @@ static int wf_sat_remove(struct i2c_client *client)
        /* XXX TODO */
 
        sat->i2c = NULL;
-       i2c_set_clientdata(client, NULL);
        return 0;
 }
 
index a5844d08d8b7917c19702d9f7879a1bc0244aba4..67a4ec8768a6145ecfd6fb1d44095bfb51f29fdc 100644 (file)
@@ -482,7 +482,6 @@ static __devexit int si470x_i2c_remove(struct i2c_client *client)
        cancel_work_sync(&radio->radio_work);
        video_unregister_device(radio->videodev);
        kfree(radio);
-       i2c_set_clientdata(client, NULL);
 
        return 0;
 }
index b62c0bd3f8ea013de803ceac7f3f25f1c7a9bb57..e3b9a8ab37f4e5c53f11c14d82a8855883f50036 100644 (file)
@@ -785,7 +785,6 @@ static int mt9m001_probe(struct i2c_client *client,
        ret = mt9m001_video_probe(icd, client);
        if (ret) {
                icd->ops = NULL;
-               i2c_set_clientdata(client, NULL);
                kfree(mt9m001);
        }
 
@@ -799,7 +798,6 @@ static int mt9m001_remove(struct i2c_client *client)
 
        icd->ops = NULL;
        mt9m001_video_remove(icd);
-       i2c_set_clientdata(client, NULL);
        client->driver = NULL;
        kfree(mt9m001);
 
index d35f536f9fc37fd6729211d9610adbfa2334c77e..e42162c50f0a3436ae74ee2249221b6ff75a1120 100644 (file)
@@ -1068,7 +1068,6 @@ static int mt9m111_probe(struct i2c_client *client,
        ret = mt9m111_video_probe(icd, client);
        if (ret) {
                icd->ops = NULL;
-               i2c_set_clientdata(client, NULL);
                kfree(mt9m111);
        }
 
@@ -1081,7 +1080,6 @@ static int mt9m111_remove(struct i2c_client *client)
        struct soc_camera_device *icd = client->dev.platform_data;
 
        icd->ops = NULL;
-       i2c_set_clientdata(client, NULL);
        client->driver = NULL;
        kfree(mt9m111);
 
index 78b4e091d2d5f527dd76db13a072bb339289fa84..9f5ff2547f1993bde3f594aa95bf4bb11d23c50d 100644 (file)
@@ -883,7 +883,6 @@ static int mt9t031_probe(struct i2c_client *client,
        if (ret) {
                if (icd)
                        icd->ops = NULL;
-               i2c_set_clientdata(client, NULL);
                kfree(mt9t031);
        }
 
@@ -897,7 +896,6 @@ static int mt9t031_remove(struct i2c_client *client)
 
        if (icd)
                icd->ops = NULL;
-       i2c_set_clientdata(client, NULL);
        client->driver = NULL;
        kfree(mt9t031);
 
index 7438f8d775ba7fa09fb32f9ad2f0a8934606afb5..aa4fce95098f06a5e8dcb832cd56d7d15de972ba 100644 (file)
@@ -1119,7 +1119,6 @@ static int mt9t112_probe(struct i2c_client *client,
        ret = mt9t112_camera_probe(icd, client);
        if (ret) {
                icd->ops = NULL;
-               i2c_set_clientdata(client, NULL);
                kfree(priv);
        }
 
@@ -1132,7 +1131,6 @@ static int mt9t112_remove(struct i2c_client *client)
        struct soc_camera_device *icd = client->dev.platform_data;
 
        icd->ops = NULL;
-       i2c_set_clientdata(client, NULL);
        kfree(priv);
        return 0;
 }
index e5bae4c9393b8b9e3d4a0c8acbcf770d627fe3bc..fb44ff006628834fb45b5d728589edfad34b99a8 100644 (file)
@@ -920,7 +920,6 @@ static int mt9v022_probe(struct i2c_client *client,
        ret = mt9v022_video_probe(icd, client);
        if (ret) {
                icd->ops = NULL;
-               i2c_set_clientdata(client, NULL);
                kfree(mt9v022);
        }
 
@@ -934,7 +933,6 @@ static int mt9v022_remove(struct i2c_client *client)
 
        icd->ops = NULL;
        mt9v022_video_remove(icd);
-       i2c_set_clientdata(client, NULL);
        client->driver = NULL;
        kfree(mt9v022);
 
index 7f8ece30c77ba790cb38c314783544a0de0e162d..c33acc94b7472c5c6fdaec46b26d1690fed541d7 100644 (file)
@@ -1159,7 +1159,6 @@ static int ov772x_probe(struct i2c_client *client,
        ret = ov772x_video_probe(icd, client);
        if (ret) {
                icd->ops = NULL;
-               i2c_set_clientdata(client, NULL);
                kfree(priv);
        }
 
@@ -1172,7 +1171,6 @@ static int ov772x_remove(struct i2c_client *client)
        struct soc_camera_device *icd = client->dev.platform_data;
 
        icd->ops = NULL;
-       i2c_set_clientdata(client, NULL);
        kfree(priv);
        return 0;
 }
index 36599a65f54851759f47a5a412bd5fdc629b8e1f..035e9ecb0c7569ce0e65bde6607d1b6b529c10ff 100644 (file)
@@ -783,7 +783,6 @@ static int ov9640_probe(struct i2c_client *client,
 
        if (ret) {
                icd->ops = NULL;
-               i2c_set_clientdata(client, NULL);
                kfree(priv);
        }
 
@@ -794,7 +793,6 @@ static int ov9640_remove(struct i2c_client *client)
 {
        struct ov9640_priv *priv = i2c_get_clientdata(client);
 
-       i2c_set_clientdata(client, NULL);
        kfree(priv);
        return 0;
 }
index bbd9c11e2c5a721436230f6656f83806058ade54..2c3b58c99e1884fb8db7bc7546eb758b5aaea094 100644 (file)
@@ -1444,7 +1444,6 @@ static int rj54n1_probe(struct i2c_client *client,
        ret = rj54n1_video_probe(icd, client, rj54n1_priv);
        if (ret < 0) {
                icd->ops = NULL;
-               i2c_set_clientdata(client, NULL);
                kfree(rj54n1);
                return ret;
        }
@@ -1461,7 +1460,6 @@ static int rj54n1_remove(struct i2c_client *client)
        icd->ops = NULL;
        if (icl->free_bus)
                icl->free_bus(icl);
-       i2c_set_clientdata(client, NULL);
        client->driver = NULL;
        kfree(rj54n1);
 
index b90e9da3167dde4e38df0037832375e9aaa48e3f..54681a5358222df6a722451e92d9fd9e627d22f8 100644 (file)
@@ -850,7 +850,6 @@ static int tcm825x_probe(struct i2c_client *client,
                         const struct i2c_device_id *did)
 {
        struct tcm825x_sensor *sensor = &tcm825x;
-       int rval;
 
        if (i2c_get_clientdata(client))
                return -EBUSY;
@@ -871,11 +870,7 @@ static int tcm825x_probe(struct i2c_client *client,
        sensor->pix.height = tcm825x_sizes[QVGA].height;
        sensor->pix.pixelformat = V4L2_PIX_FMT_RGB565;
 
-       rval = v4l2_int_device_register(sensor->v4l2_int_device);
-       if (rval)
-               i2c_set_clientdata(client, NULL);
-
-       return rval;
+       return v4l2_int_device_register(sensor->v4l2_int_device);
 }
 
 static int tcm825x_remove(struct i2c_client *client)
@@ -886,7 +881,6 @@ static int tcm825x_remove(struct i2c_client *client)
                return -ENODEV; /* our client isn't attached */
 
        v4l2_int_device_unregister(sensor->v4l2_int_device);
-       i2c_set_clientdata(client, NULL);
 
        return 0;
 }
index 76be733eabfd4d3f7b4bc474219a6f0a9c8fb5ea..6eb3395def077754f30e7be7cdb5c1a60ea57b4c 100644 (file)
@@ -977,7 +977,6 @@ static int tw9910_probe(struct i2c_client *client,
        ret = tw9910_video_probe(icd, client);
        if (ret) {
                icd->ops = NULL;
-               i2c_set_clientdata(client, NULL);
                kfree(priv);
        }
 
@@ -990,7 +989,6 @@ static int tw9910_remove(struct i2c_client *client)
        struct soc_camera_device *icd = client->dev.platform_data;
 
        icd->ops = NULL;
-       i2c_set_clientdata(client, NULL);
        kfree(priv);
        return 0;
 }
index c933b64d1283645071301eb4571b45e7ede1909a..bc02e6b21608be1ee4a0fcf4e52e3e6e7f383982 100644 (file)
@@ -200,8 +200,6 @@ static int __devexit pm860x_remove(struct i2c_client *client)
 
        pm860x_device_exit(chip);
        i2c_unregister_device(chip->companion);
-       i2c_set_clientdata(chip->client, NULL);
-       i2c_set_clientdata(client, NULL);
        kfree(chip);
        return 0;
 }
index 53ebfee548fa3bfbc5311d34c98bfc5b166290b7..66379b413906a3ed5147370040ed7ccffd0b5068 100644 (file)
@@ -957,7 +957,6 @@ static int __init ab3100_probe(struct i2c_client *client,
        i2c_unregister_device(ab3100->testreg_client);
  exit_no_testreg_client:
  exit_no_detect:
-       i2c_set_clientdata(client, NULL);
        kfree(ab3100);
        return err;
 }
@@ -979,7 +978,6 @@ static int __exit ab3100_remove(struct i2c_client *client)
         * their notifiers so deactivate IRQ
         */
        free_irq(client->irq, ab3100);
-       i2c_set_clientdata(client, NULL);
        kfree(ab3100);
        return 0;
 }
index 1060f8e1c40a1cd0c280b2dbfcb3759fd932241e..f54ab62e7bc6b50a11558b470637889d8a5c6533 100644 (file)
@@ -1362,7 +1362,6 @@ static int __exit ab3550_remove(struct i2c_client *client)
         * their notifiers so deactivate IRQ
         */
        free_irq(client->irq, ab);
-       i2c_set_clientdata(client, NULL);
        kfree(ab);
        return 0;
 }
index 005532865654b0bbfa036bc873a37858220ffac1..3122139b430022d819b532ba90d4d7dbccf69c96 100644 (file)
@@ -302,7 +302,6 @@ out_free_irq:
                free_irq(chip->irq, chip);
 
 out_free_chip:
-       i2c_set_clientdata(client, NULL);
        kfree(chip);
 
        return ret;
@@ -317,7 +316,6 @@ static int __devexit adp5520_remove(struct i2c_client *client)
 
        adp5520_remove_subdevs(chip);
        adp5520_write(chip->dev, ADP5520_MODE_STATUS, 0);
-       i2c_set_clientdata(client, NULL);
        kfree(chip);
        return 0;
 }
index 3ad915d0589c0626234ffdbc357afbbe2ff37af3..c07aece900fbb93b9ec08b2aa99ee85e144093fe 100644 (file)
@@ -534,7 +534,6 @@ static int __devinit da903x_probe(struct i2c_client *client,
 out_free_irq:
        free_irq(client->irq, chip);
 out_free_chip:
-       i2c_set_clientdata(client, NULL);
        kfree(chip);
        return ret;
 }
@@ -544,7 +543,6 @@ static int __devexit da903x_remove(struct i2c_client *client)
        struct da903x_chip *chip = i2c_get_clientdata(client);
 
        da903x_remove_subdevs(chip);
-       i2c_set_clientdata(client, NULL);
        kfree(chip);
        return 0;
 }
index e73f3f5252a89cf138dac35254263ed58630f72c..0219115e00c73f84c925045afceb96d65ea83ea3 100644 (file)
@@ -173,7 +173,6 @@ static int __devexit max8925_remove(struct i2c_client *client)
        max8925_device_exit(chip);
        i2c_unregister_device(chip->adc);
        i2c_unregister_device(chip->rtc);
-       i2c_set_clientdata(chip->i2c, NULL);
        kfree(chip);
        return 0;
 }
index 721948be12c77a7ad622e3559abc2f3953c1365a..a3fb4bcb98897718400da09d23dfd95116b99f58 100644 (file)
@@ -1228,7 +1228,6 @@ fail2:
        free_irq(client->irq, menelaus);
        flush_scheduled_work();
 fail1:
-       i2c_set_clientdata(client, NULL);
        kfree(menelaus);
        return err;
 }
@@ -1238,7 +1237,6 @@ static int __exit menelaus_remove(struct i2c_client *client)
        struct menelaus_chip    *menelaus = i2c_get_clientdata(client);
 
        free_irq(client->irq, menelaus);
-       i2c_set_clientdata(client, NULL);
        kfree(menelaus);
        the_menelaus = NULL;
        return 0;
index 704736e6e9b9b2efea2c66f4cf3a6ee36183eaa4..23e58552728596d7be431583e27602792b7e65d3 100644 (file)
@@ -336,7 +336,6 @@ static int __devinit pcf50633_probe(struct i2c_client *client,
        return 0;
 
 err_free:
-       i2c_set_clientdata(client, NULL);
        kfree(pcf);
 
        return ret;
@@ -357,7 +356,6 @@ static int __devexit pcf50633_remove(struct i2c_client *client)
        for (i = 0; i < PCF50633_NUM_REGULATORS; i++)
                platform_device_unregister(pcf->regulator_pdev[i]);
 
-       i2c_set_clientdata(client, NULL);
        kfree(pcf);
 
        return 0;
index 715f095dd7a6119b580e6eed2a6b425347ed88d4..e619e2a55997ebd0ed1ab6f27969da4497a78de9 100644 (file)
@@ -296,7 +296,6 @@ out_freeirq:
 out_removeirq:
        tc35892_irq_remove(tc35892);
 out_free:
-       i2c_set_clientdata(i2c, NULL);
        kfree(tc35892);
        return ret;
 }
@@ -310,7 +309,6 @@ static int __devexit tc35892_remove(struct i2c_client *client)
        free_irq(tc35892->i2c->irq, tc35892);
        tc35892_irq_remove(tc35892);
 
-       i2c_set_clientdata(client, NULL);
        kfree(tc35892);
 
        return 0;
index 9b22a77f70f5dac90aec0395d176d9ad06d4a71f..d0016b67d125ce40b8d9a810f1abb7ade2678756 100644 (file)
@@ -530,7 +530,6 @@ static int __exit tps65010_remove(struct i2c_client *client)
        cancel_delayed_work(&tps->work);
        flush_scheduled_work();
        debugfs_remove(tps->file);
-       i2c_set_clientdata(client, NULL);
        kfree(tps);
        the_tps = NULL;
        return 0;
index 7795af4b1fe15f7ee4690bd1a16eb17188ac492f..5fe5de166adb39bdafb2e7714ce046f58b6ccb3b 100644 (file)
@@ -80,7 +80,6 @@ static int wm8350_i2c_probe(struct i2c_client *i2c,
        return ret;
 
 err:
-       i2c_set_clientdata(i2c, NULL);
        kfree(wm8350);
        return ret;
 }
@@ -90,7 +89,6 @@ static int wm8350_i2c_remove(struct i2c_client *i2c)
        struct wm8350 *wm8350 = i2c_get_clientdata(i2c);
 
        wm8350_device_exit(wm8350);
-       i2c_set_clientdata(i2c, NULL);
        kfree(wm8350);
 
        return 0;
index e08aafa663dc4a1460bd901fd369fe9ec11a12b9..1bfef4846b07b0d98138c87509872937b2c29e6f 100644 (file)
@@ -415,7 +415,6 @@ static int wm8400_i2c_probe(struct i2c_client *i2c,
        return 0;
 
 struct_err:
-       i2c_set_clientdata(i2c, NULL);
        kfree(wm8400);
 err:
        return ret;
@@ -426,7 +425,6 @@ static int wm8400_i2c_remove(struct i2c_client *i2c)
        struct wm8400 *wm8400 = i2c_get_clientdata(i2c);
 
        wm8400_release(wm8400);
-       i2c_set_clientdata(i2c, NULL);
        kfree(wm8400);
 
        return 0;
index f7ca3a42b49089fcf48c6927260057d908641762..559b0b3c16c379584be01a08db209e2437549a04 100644 (file)
@@ -643,7 +643,6 @@ static int __devexit at24_remove(struct i2c_client *client)
 
        kfree(at24->writebuf);
        kfree(at24);
-       i2c_set_clientdata(client, NULL);
        return 0;
 }
 
index eb476b7f8d113cdadd87f558994a1fe95061cf49..f4ce273e93fd5e5888adbc73c9e684bd5568849c 100644 (file)
@@ -234,7 +234,6 @@ static int __devexit pismo_remove(struct i2c_client *client)
        /* FIXME: set_vpp needs saner arguments */
        pismo_setvpp_remove_fix(pismo);
 
-       i2c_set_clientdata(client, NULL);
        kfree(pismo);
 
        return 0;
@@ -286,7 +285,6 @@ static int __devinit pismo_probe(struct i2c_client *client,
        return 0;
 
  exit_free:
-       i2c_set_clientdata(client, NULL);
        kfree(pismo);
        return ret;
 }
index 00aea6f7d1f1bc6bbf8bfae8080bce0b01c633e7..1312eda57ba6621c335fe592f7a7d963a5d05a5d 100644 (file)
@@ -232,7 +232,7 @@ static int __devinit fun_probe(struct of_device *ofdev,
        if (!fun)
                return -ENOMEM;
 
-       ret = of_address_to_resource(ofdev->node, 0, &io_res);
+       ret = of_address_to_resource(ofdev->dev.of_node, 0, &io_res);
        if (ret) {
                dev_err(&ofdev->dev, "can't get IO base\n");
                goto err1;
@@ -244,7 +244,8 @@ static int __devinit fun_probe(struct of_device *ofdev,
                goto err1;
        }
 
-       prop = of_get_property(ofdev->node, "fsl,upm-addr-offset", &size);
+       prop = of_get_property(ofdev->dev.of_node, "fsl,upm-addr-offset",
+                              &size);
        if (!prop || size != sizeof(uint32_t)) {
                dev_err(&ofdev->dev, "can't get UPM address offset\n");
                ret = -EINVAL;
@@ -252,7 +253,7 @@ static int __devinit fun_probe(struct of_device *ofdev,
        }
        fun->upm_addr_offset = *prop;
 
-       prop = of_get_property(ofdev->node, "fsl,upm-cmd-offset", &size);
+       prop = of_get_property(ofdev->dev.of_node, "fsl,upm-cmd-offset", &size);
        if (!prop || size != sizeof(uint32_t)) {
                dev_err(&ofdev->dev, "can't get UPM command offset\n");
                ret = -EINVAL;
@@ -260,7 +261,7 @@ static int __devinit fun_probe(struct of_device *ofdev,
        }
        fun->upm_cmd_offset = *prop;
 
-       prop = of_get_property(ofdev->node,
+       prop = of_get_property(ofdev->dev.of_node,
                               "fsl,upm-addr-line-cs-offsets", &size);
        if (prop && (size / sizeof(uint32_t)) > 0) {
                fun->mchip_count = size / sizeof(uint32_t);
@@ -276,7 +277,7 @@ static int __devinit fun_probe(struct of_device *ofdev,
 
        for (i = 0; i < fun->mchip_count; i++) {
                fun->rnb_gpio[i] = -1;
-               rnb_gpio = of_get_gpio(ofdev->node, i);
+               rnb_gpio = of_get_gpio(ofdev->dev.of_node, i);
                if (rnb_gpio >= 0) {
                        ret = gpio_request(rnb_gpio, dev_name(&ofdev->dev));
                        if (ret) {
@@ -292,13 +293,13 @@ static int __devinit fun_probe(struct of_device *ofdev,
                }
        }
 
-       prop = of_get_property(ofdev->node, "chip-delay", NULL);
+       prop = of_get_property(ofdev->dev.of_node, "chip-delay", NULL);
        if (prop)
                fun->chip_delay = *prop;
        else
                fun->chip_delay = 50;
 
-       prop = of_get_property(ofdev->node, "fsl,upm-wait-flags", &size);
+       prop = of_get_property(ofdev->dev.of_node, "fsl,upm-wait-flags", &size);
        if (prop && size == sizeof(uint32_t))
                fun->wait_flags = *prop;
        else
@@ -315,7 +316,7 @@ static int __devinit fun_probe(struct of_device *ofdev,
        fun->dev = &ofdev->dev;
        fun->last_ctrl = NAND_CLE;
 
-       ret = fun_chip_init(fun, ofdev->node, &io_res);
+       ret = fun_chip_init(fun, ofdev->dev.of_node, &io_res);
        if (ret)
                goto err2;
 
index 3d0867d829cb01a02976328aa2fd1fe858b3fcf1..0a130dcaa1292974b264199824ec602fe002b677 100644 (file)
@@ -650,7 +650,7 @@ static void mpc5121_nfc_free(struct device *dev, struct mtd_info *mtd)
 static int __devinit mpc5121_nfc_probe(struct of_device *op,
                                        const struct of_device_id *match)
 {
-       struct device_node *rootnode, *dn = op->node;
+       struct device_node *rootnode, *dn = op->dev.of_node;
        struct device *dev = &op->dev;
        struct mpc5121_nfc_prv *prv;
        struct resource res;
@@ -889,12 +889,12 @@ static struct of_device_id mpc5121_nfc_match[] __devinitdata = {
 };
 
 static struct of_platform_driver mpc5121_nfc_driver = {
-       .match_table    = mpc5121_nfc_match,
        .probe          = mpc5121_nfc_probe,
        .remove         = __devexit_p(mpc5121_nfc_remove),
        .driver         = {
-               .name   = DRV_NAME,
-               .owner  = THIS_MODULE,
+               .name = DRV_NAME,
+               .owner = THIS_MODULE,
+               .of_match_table = mpc5121_nfc_match,
        },
 };
 
index 884852dc7eb44b29d1788fb43db7c3f6846c6936..cc728b12de82d4446315f91c165a032aa15f1c4b 100644 (file)
@@ -183,7 +183,7 @@ static int __devinit socrates_nand_probe(struct of_device *ofdev,
                return -ENOMEM;
        }
 
-       host->io_base = of_iomap(ofdev->node, 0);
+       host->io_base = of_iomap(ofdev->dev.of_node, 0);
        if (host->io_base == NULL) {
                printk(KERN_ERR "socrates_nand: ioremap failed\n");
                kfree(host);
@@ -244,7 +244,7 @@ static int __devinit socrates_nand_probe(struct of_device *ofdev,
 #ifdef CONFIG_MTD_OF_PARTS
        if (num_partitions == 0) {
                num_partitions = of_mtd_parse_partitions(&ofdev->dev,
-                                                        ofdev->node,
+                                                        ofdev->dev.of_node,
                                                         &partitions);
                if (num_partitions < 0) {
                        res = num_partitions;
index 0f90685d3d19472e3bc0dc9b05ed5872a5fa9f63..3607340f3da7ce93a671a964366758780f7bc038 100644 (file)
@@ -169,7 +169,7 @@ static int __devinit fs_enet_mdio_probe(struct of_device *ofdev,
 
        new_bus->name = "CPM2 Bitbanged MII",
 
-       ret = fs_mii_bitbang_init(new_bus, ofdev->node);
+       ret = fs_mii_bitbang_init(new_bus, ofdev->dev.of_node);
        if (ret)
                goto out_free_bus;
 
@@ -181,7 +181,7 @@ static int __devinit fs_enet_mdio_probe(struct of_device *ofdev,
        new_bus->parent = &ofdev->dev;
        dev_set_drvdata(&ofdev->dev, new_bus);
 
-       ret = of_mdiobus_register(new_bus, ofdev->node);
+       ret = of_mdiobus_register(new_bus, ofdev->dev.of_node);
        if (ret)
                goto out_free_irqs;
 
index 1a648b90b634890512ffb95560c1944d5d7a214a..25e5e30a18afdd6bafaae72e1c06314f42c9efb0 100644 (file)
@@ -1157,7 +1157,7 @@ static int __init m8xx_probe(struct of_device *ofdev,
        unsigned int i, m, hwirq;
        pcmconf8xx_t *pcmcia;
        int status;
-       struct device_node *np = ofdev->node;
+       struct device_node *np = ofdev->dev.of_node;
 
        pcmcia_info("%s\n", version);
 
@@ -1301,7 +1301,7 @@ static struct of_platform_driver m8xx_pcmcia_driver = {
        .driver = {
                .name = driver_name,
                .owner = THIS_MODULE,
-               .match_table = m8xx_pcmcia_match,
+               .of_match_table = m8xx_pcmcia_match,
        },
        .probe = m8xx_probe,
        .remove = m8xx_remove,
index f3e22c9fe20a538581a70fc0d0134bf78a5a1b33..2f2f9a6f54fad6d75dc692fbee4d128b7ba642a4 100644 (file)
@@ -225,7 +225,6 @@ static int __devinit max17040_probe(struct i2c_client *client,
        ret = power_supply_register(&client->dev, &chip->battery);
        if (ret) {
                dev_err(&client->dev, "failed: power supply register\n");
-               i2c_set_clientdata(client, NULL);
                kfree(chip);
                return ret;
        }
@@ -245,7 +244,6 @@ static int __devexit max17040_remove(struct i2c_client *client)
 
        power_supply_unregister(&chip->battery);
        cancel_delayed_work(&chip->work);
-       i2c_set_clientdata(client, NULL);
        kfree(chip);
        return 0;
 }
index 671a7d1f1f0e33e5f9f0fd4e016b742a870da3a4..8ae3732eb24bcd28e414049b583d3644fa8ffd17 100644 (file)
@@ -519,8 +519,6 @@ static int __devexit lp3971_i2c_remove(struct i2c_client *i2c)
        struct lp3971 *lp3971 = i2c_get_clientdata(i2c);
        int i;
 
-       i2c_set_clientdata(i2c, NULL);
-
        for (i = 0; i < lp3971->num_regulators; i++)
                regulator_unregister(lp3971->rdev[i]);
 
index b3c1afc16889434f47c9fd74e387da39bb255737..2b54d9d75f11e2893ead65a3624199fa13fb9b24 100644 (file)
@@ -244,7 +244,6 @@ static int __devexit max1586_pmic_remove(struct i2c_client *client)
        for (i = 0; i <= MAX1586_V6; i++)
                if (rdev[i])
                        regulator_unregister(rdev[i]);
-       i2c_set_clientdata(client, NULL);
        kfree(rdev);
 
        return 0;
index bfc4c5ffdc966f3ab03081259faf52adce239906..4520ace3f7e707f82ccbf0fb068df921dfc6c2df 100644 (file)
@@ -357,7 +357,6 @@ static int __devinit max8649_regulator_probe(struct i2c_client *client,
        dev_info(info->dev, "Max8649 regulator device is detected.\n");
        return 0;
 out:
-       i2c_set_clientdata(client, NULL);
        kfree(info);
        return ret;
 }
@@ -369,7 +368,6 @@ static int __devexit max8649_regulator_remove(struct i2c_client *client)
        if (info) {
                if (info->regulator)
                        regulator_unregister(info->regulator);
-               i2c_set_clientdata(client, NULL);
                kfree(info);
        }
 
index 3790b21879ff2f8d2c5b8000fe216f1f0770a436..d97220efae5ab4f1fde54cd909c724a3f5bf3523 100644 (file)
@@ -471,7 +471,6 @@ static int __devexit max8660_remove(struct i2c_client *client)
        for (i = 0; i < MAX8660_V_END; i++)
                if (rdev[i])
                        regulator_unregister(rdev[i]);
-       i2c_set_clientdata(client, NULL);
        kfree(rdev);
 
        return 0;
index 8e2f2098b00562fd2e9608494569f28f9b85a83f..f50afc9f287a80f04513bcf670839fcf84ebc23b 100644 (file)
@@ -538,9 +538,6 @@ static int __devexit tps_65023_remove(struct i2c_client *client)
        struct tps_pmic *tps = i2c_get_clientdata(client);
        int i;
 
-       /* clear the client data in i2c */
-       i2c_set_clientdata(client, NULL);
-
        for (i = 0; i < TPS65023_NUM_REGULATOR; i++)
                regulator_unregister(tps->rdev[i]);
 
index 61945734ad003c379fde6424c708942b1afbbf8a..1f0007fd44314c5b65ffc39fde6df81cc568d492 100644 (file)
@@ -403,7 +403,6 @@ out_irq:
                free_irq(client->irq, client);
 
 out_free:
-       i2c_set_clientdata(client, NULL);
        kfree(ds1374);
        return ret;
 }
@@ -422,7 +421,6 @@ static int __devexit ds1374_remove(struct i2c_client *client)
        }
 
        rtc_device_unregister(ds1374->rtc);
-       i2c_set_clientdata(client, NULL);
        kfree(ds1374);
        return 0;
 }
index f0dbf9cb8f9c42f30e51b6db7dba823d887c6f61..db5d8c416d26a18e6fdb141c3bfa1d7c106e18d9 100644 (file)
@@ -279,7 +279,7 @@ static int __devinit mpc5121_rtc_probe(struct of_device *op,
        if (!rtc)
                return -ENOMEM;
 
-       rtc->regs = of_iomap(op->node, 0);
+       rtc->regs = of_iomap(op->dev.of_node, 0);
        if (!rtc->regs) {
                dev_err(&op->dev, "%s: couldn't map io space\n", __func__);
                err = -ENOSYS;
@@ -290,7 +290,7 @@ static int __devinit mpc5121_rtc_probe(struct of_device *op,
 
        dev_set_drvdata(&op->dev, rtc);
 
-       rtc->irq = irq_of_parse_and_map(op->node, 1);
+       rtc->irq = irq_of_parse_and_map(op->dev.of_node, 1);
        err = request_irq(rtc->irq, mpc5121_rtc_handler, IRQF_DISABLED,
                                                "mpc5121-rtc", &op->dev);
        if (err) {
@@ -299,7 +299,7 @@ static int __devinit mpc5121_rtc_probe(struct of_device *op,
                goto out_dispose;
        }
 
-       rtc->irq_periodic = irq_of_parse_and_map(op->node, 0);
+       rtc->irq_periodic = irq_of_parse_and_map(op->dev.of_node, 0);
        err = request_irq(rtc->irq_periodic, mpc5121_rtc_handler_upd,
                                IRQF_DISABLED, "mpc5121-rtc_upd", &op->dev);
        if (err) {
@@ -365,9 +365,11 @@ static struct of_device_id mpc5121_rtc_match[] __devinitdata = {
 };
 
 static struct of_platform_driver mpc5121_rtc_driver = {
-       .owner = THIS_MODULE,
-       .name = "mpc5121-rtc",
-       .match_table = mpc5121_rtc_match,
+       .driver = {
+               .name = "mpc5121-rtc",
+               .owner = THIS_MODULE,
+               .of_match_table = mpc5121_rtc_match,
+       },
        .probe = mpc5121_rtc_probe,
        .remove = __devexit_p(mpc5121_rtc_remove),
 };
index b65c82f792d9cd6f86614304db1f4c9d99077c6b..789f62f9b47d4b288ba8dffe30adeaf123c1fc84 100644 (file)
@@ -632,7 +632,6 @@ errout_reg:
        rtc_device_unregister(rx8025->rtc);
 
 errout_free:
-       i2c_set_clientdata(client, NULL);
        kfree(rx8025);
 
 errout:
@@ -656,7 +655,6 @@ static int __devexit rx8025_remove(struct i2c_client *client)
 
        rx8025_sysfs_unregister(&client->dev);
        rtc_device_unregister(rx8025->rtc);
-       i2c_set_clientdata(client, NULL);
        kfree(rx8025);
        return 0;
 }
index def4d396d0b096cef968a5572f2b5122d92eeb33..f789e002c9b013664a2588ea342b25a52acf8a1c 100644 (file)
@@ -275,7 +275,6 @@ exit_dummy:
                if (s35390a->client[i])
                        i2c_unregister_device(s35390a->client[i]);
        kfree(s35390a);
-       i2c_set_clientdata(client, NULL);
 
 exit:
        return err;
@@ -292,7 +291,6 @@ static int s35390a_remove(struct i2c_client *client)
 
        rtc_device_unregister(s35390a->rtc);
        kfree(s35390a);
-       i2c_set_clientdata(client, NULL);
 
        return 0;
 }
index 28a126d2742bcf1fd89e1f753080341dfe4958a3..2534b1ec3eddc5b39485c8fa71fff21dcbef07d3 100644 (file)
@@ -512,29 +512,29 @@ static int __init mpc512x_psc_spi_of_probe(struct of_device *op,
        u64 regaddr64, size64;
        s16 id = -1;
 
-       regaddr_p = of_get_address(op->node, 0, &size64, NULL);
+       regaddr_p = of_get_address(op->dev.of_node, 0, &size64, NULL);
        if (!regaddr_p) {
                dev_err(&op->dev, "Invalid PSC address\n");
                return -EINVAL;
        }
-       regaddr64 = of_translate_address(op->node, regaddr_p);
+       regaddr64 = of_translate_address(op->dev.of_node, regaddr_p);
 
        /* get PSC id (0..11, used by port_config) */
        if (op->dev.platform_data == NULL) {
                const u32 *psc_nump;
 
-               psc_nump = of_get_property(op->node, "cell-index", NULL);
+               psc_nump = of_get_property(op->dev.of_node, "cell-index", NULL);
                if (!psc_nump || *psc_nump > 11) {
                        dev_err(&op->dev, "mpc512x_psc_spi: Device node %s "
                                "has invalid cell-index property\n",
-                               op->node->full_name);
+                               op->dev.of_node->full_name);
                        return -EINVAL;
                }
                id = *psc_nump;
        }
 
        return mpc512x_psc_spi_do_probe(&op->dev, (u32) regaddr64, (u32) size64,
-                                       irq_of_parse_and_map(op->node, 0), id);
+                               irq_of_parse_and_map(op->dev.of_node, 0), id);
 }
 
 static int __exit mpc512x_psc_spi_of_remove(struct of_device *op)
@@ -550,12 +550,12 @@ static struct of_device_id mpc512x_psc_spi_of_match[] = {
 MODULE_DEVICE_TABLE(of, mpc512x_psc_spi_of_match);
 
 static struct of_platform_driver mpc512x_psc_spi_of_driver = {
-       .match_table = mpc512x_psc_spi_of_match,
        .probe = mpc512x_psc_spi_of_probe,
        .remove = __exit_p(mpc512x_psc_spi_of_remove),
        .driver = {
                .name = "mpc512x-psc-spi",
                .owner = THIS_MODULE,
+               .of_match_table = mpc512x_psc_spi_of_match,
        },
 };
 
index 19c0b3b34fce0160d7cb4d0b0c16f14d8143671d..d53466a249d9700bb9108478a5b08ffcf1955b6a 100644 (file)
@@ -397,7 +397,7 @@ static int __init spi_ppc4xx_of_probe(struct of_device *op,
        struct spi_master *master;
        struct spi_bitbang *bbp;
        struct resource resource;
-       struct device_node *np = op->node;
+       struct device_node *np = op->dev.of_node;
        struct device *dev = &op->dev;
        struct device_node *opbnp;
        int ret;
index 1f020dad6234b475ea4edc76dd48d7e02278b341..3320359408a966b15d11809ddf9760b00e2a782a 100644 (file)
@@ -519,7 +519,6 @@ err_input_register_device_failed:
 err_input_dev_alloc_failed:
 err_detect_failed:
 err_power_failed:
-       i2c_set_clientdata(client, NULL);
        kfree(ts);
 err_alloc_data_failed:
 err_check_functionality_failed:
@@ -537,7 +536,6 @@ static int synaptics_ts_remove(struct i2c_client *client)
        else
                hrtimer_cancel(&ts->timer);
        input_unregister_device(ts->input_dev);
-       i2c_set_clientdata(client, NULL);
        kfree(ts);
        return 0;
 }
index bd925457f8b710ec8b44a86b7a32dddc22d0abfd..72f5c1f56d195f9c777ba09106b829f1814b9de0 100644 (file)
@@ -289,7 +289,6 @@ static int wis_saa7113_probe(struct i2c_client *client,
        if (write_regs(client, initial_registers) < 0) {
                printk(KERN_ERR
                        "wis-saa7113: error initializing SAA7113\n");
-               i2c_set_clientdata(client, NULL);
                kfree(dec);
                return -ENODEV;
        }
@@ -301,7 +300,6 @@ static int wis_saa7113_remove(struct i2c_client *client)
 {
        struct wis_saa7113 *dec = i2c_get_clientdata(client);
 
-       i2c_set_clientdata(client, NULL);
        kfree(dec);
        return 0;
 }
index b2eb804c1954ceedd9fe7986e319c9425551babf..cd950b61cf70ee1c4d1d883f2949c5677c085368 100644 (file)
@@ -422,7 +422,6 @@ static int wis_saa7115_probe(struct i2c_client *client,
        if (write_regs(client, initial_registers) < 0) {
                printk(KERN_ERR
                        "wis-saa7115: error initializing SAA7115\n");
-               i2c_set_clientdata(client, NULL);
                kfree(dec);
                return -ENODEV;
        }
@@ -434,7 +433,6 @@ static int wis_saa7115_remove(struct i2c_client *client)
 {
        struct wis_saa7115 *dec = i2c_get_clientdata(client);
 
-       i2c_set_clientdata(client, NULL);
        kfree(dec);
        return 0;
 }
index b1013291190f162f6668af96c8593c81b57cb7e9..981c9b311b8b9643befcd08440b1e598354cc5eb 100644 (file)
@@ -684,7 +684,6 @@ static int wis_sony_tuner_remove(struct i2c_client *client)
 {
        struct wis_sony_tuner *t = i2c_get_clientdata(client);
 
-       i2c_set_clientdata(client, NULL);
        kfree(t);
        return 0;
 }
index 315268d130dd61311873a36bd3ae373ed75f3539..ee28a99dc3883620135726feba6034f54632c9ea 100644 (file)
@@ -323,7 +323,6 @@ static int wis_tw2804_remove(struct i2c_client *client)
 {
        struct wis_tw2804 *dec = i2c_get_clientdata(client);
 
-       i2c_set_clientdata(client, NULL);
        kfree(dec);
        return 0;
 }
index 2afea09091b97e020fff05d4438b1b93156e64a7..80d47269b1c01f4054faeb8f2f4514f242e0dc29 100644 (file)
@@ -294,7 +294,6 @@ static int wis_tw9903_probe(struct i2c_client *client,
 
        if (write_regs(client, initial_registers) < 0) {
                printk(KERN_ERR "wis-tw9903: error initializing TW9903\n");
-               i2c_set_clientdata(client, NULL);
                kfree(dec);
                return -ENODEV;
        }
@@ -306,7 +305,6 @@ static int wis_tw9903_remove(struct i2c_client *client)
 {
        struct wis_tw9903 *dec = i2c_get_clientdata(client);
 
-       i2c_set_clientdata(client, NULL);
        kfree(dec);
        return 0;
 }
index 20e267448d1fdffe25eedf5ef35c1b10c2746413..905f8560d31f94d0a4651d54ab8b8191ca69d1f4 100644 (file)
@@ -1011,7 +1011,6 @@ error_put_reg:
        if (!IS_ERR(st->reg))
                regulator_put(st->reg);
 error_free_st:
-       i2c_set_clientdata(client, NULL);
        kfree(st);
 
 error_ret:
@@ -1030,7 +1029,6 @@ static int max1363_remove(struct i2c_client *client)
                regulator_disable(st->reg);
                regulator_put(st->reg);
        }
-       i2c_set_clientdata(client, NULL);
        kfree(st);
 
        return 0;
index 43aaacff4e744bc6a1d18f182f5ac640ac2eabef..e4b0a5ef1c1f4913d39870c9ef363917ca552e83 100644 (file)
@@ -694,7 +694,6 @@ static int __devinit tsl2563_probe(struct i2c_client *client,
 fail2:
        iio_device_unregister(chip->indio_dev);
 fail1:
-       i2c_set_clientdata(client, NULL);
        kfree(chip);
        return err;
 }
@@ -705,7 +704,6 @@ static int tsl2563_remove(struct i2c_client *client)
 
        iio_device_unregister(chip->indio_dev);
 
-       i2c_set_clientdata(client, NULL);
        kfree(chip);
        return 0;
 }
index 2928523268b53ac61470959ac6d6cd41519633d1..82506ca297d5f1632312f8d52b7f80b7aab49637 100644 (file)
@@ -2400,7 +2400,7 @@ EXPORT_SYMBOL(usb_gadget_unregister_driver);
 static struct qe_udc __devinit *qe_udc_config(struct of_device *ofdev)
 {
        struct qe_udc *udc;
-       struct device_node *np = ofdev->node;
+       struct device_node *np = ofdev->dev.of_node;
        unsigned int tmp_addr = 0;
        struct usb_device_para __iomem *usbpram;
        unsigned int i;
@@ -2525,7 +2525,7 @@ static void qe_udc_release(struct device *dev)
 static int __devinit qe_udc_probe(struct of_device *ofdev,
                        const struct of_device_id *match)
 {
-       struct device_node *np = ofdev->node;
+       struct device_node *np = ofdev->dev.of_node;
        struct qe_ep *ep;
        unsigned int ret = 0;
        unsigned int i;
index 013972bbde57d21bd16c737c1a1e455a1f90876a..4899f451add98f5727cd72710ea8f4751070d868 100644 (file)
@@ -151,7 +151,7 @@ static const struct hc_driver ehci_xilinx_of_hc_driver = {
 static int __devinit
 ehci_hcd_xilinx_of_probe(struct of_device *op, const struct of_device_id *match)
 {
-       struct device_node *dn = op->node;
+       struct device_node *dn = op->dev.of_node;
        struct usb_hcd *hcd;
        struct ehci_hcd *ehci;
        struct resource res;
index 51fcc0a2c94a9097aea33eff174b1b38969b263d..e45833ce975bd6cb60fb2d8b09db767d28987c14 100644 (file)
@@ -242,7 +242,7 @@ void atyfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
 void atyfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
 {
        struct atyfb_par *par = (struct atyfb_par *) info->par;
-       u32 color = rect->color, dx = rect->dx, width = rect->width, rotation = 0;
+       u32 color, dx = rect->dx, width = rect->width, rotation = 0;
 
        if (par->asleep)
                return;
@@ -253,8 +253,11 @@ void atyfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
                return;
        }
 
-       color |= (rect->color << 8);
-       color |= (rect->color << 16);
+       if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
+           info->fix.visual == FB_VISUAL_DIRECTCOLOR)
+               color = ((u32 *)(info->pseudo_palette))[rect->color];
+       else
+               color = rect->color;
 
        if (info->var.bits_per_pixel == 24) {
                /* In 24 bpp, the engine is in 8 bpp - this requires that all */
index 921ca37398f39b63943f3484192140dc355087d6..3ec24609151e8ec322c48afcebae8dc9ce578b5d 100644 (file)
@@ -756,7 +756,6 @@ out:
 out1:
        backlight_device_unregister(bl);
 out2:
-       i2c_set_clientdata(client, NULL);
        kfree(data);
 
        return ret;
@@ -776,7 +775,6 @@ static int __devexit adp8860_remove(struct i2c_client *client)
                        &adp8860_bl_attr_group);
 
        backlight_device_unregister(data->bl);
-       i2c_set_clientdata(client, NULL);
        kfree(data);
 
        return 0;
index e03e60bbfd855f01301ab14d71b1fc9d94453bcc..2a04b382ec4834a03270db15701136f5f01694cf 100644 (file)
@@ -119,7 +119,6 @@ static int __devinit tosa_bl_probe(struct i2c_client *client,
 
 err_reg:
        data->bl = NULL;
-       i2c_set_clientdata(client, NULL);
 err_gpio_dir:
        gpio_free(TOSA_GPIO_BL_C20MA);
 err_gpio_bl:
@@ -133,7 +132,6 @@ static int __devexit tosa_bl_remove(struct i2c_client *client)
 
        backlight_device_unregister(data->bl);
        data->bl = NULL;
-       i2c_set_clientdata(client, NULL);
 
        gpio_free(TOSA_GPIO_BL_C20MA);
 
index 2c371c07f0daaff562b844184bfb742284b9cc53..09f1b9b462f4a8a4ce86a600aa55a4cbf1685622 100644 (file)
@@ -275,7 +275,7 @@ static int __devinit bw2_do_default_mode(struct bw2_par *par,
 
 static int __devinit bw2_probe(struct of_device *op, const struct of_device_id *match)
 {
-       struct device_node *dp = op->node;
+       struct device_node *dp = op->dev.of_node;
        struct fb_info *info;
        struct bw2_par *par;
        int linebytes, err;
index d12e05b6e63f96ce0cd36ba1ddb810167953d280..e5dc2241194fed66606c1e694aa4c77ed3357c81 100644 (file)
@@ -465,7 +465,7 @@ static void cg14_unmap_regs(struct of_device *op, struct fb_info *info,
 
 static int __devinit cg14_probe(struct of_device *op, const struct of_device_id *match)
 {
-       struct device_node *dp = op->node;
+       struct device_node *dp = op->dev.of_node;
        struct fb_info *info;
        struct cg14_par *par;
        int is_8mb, linebytes, i, err;
index b98f93f7f6638f0a02a39250aaeaca54b595bbb3..558d73a948a0d836c73ea20c26440229738ba581 100644 (file)
@@ -349,7 +349,7 @@ static int __devinit cg3_do_default_mode(struct cg3_par *par)
 static int __devinit cg3_probe(struct of_device *op,
                               const struct of_device_id *match)
 {
-       struct device_node *dp = op->node;
+       struct device_node *dp = op->dev.of_node;
        struct fb_info *info;
        struct cg3_par *par;
        int linebytes, err;
index 3d7895316eaf37e79bb56f2413d748fcbdfca131..9e8bf7d5e249df2a3d0f3243181bab0b76b633a9 100644 (file)
@@ -550,7 +550,7 @@ static void leo_unmap_regs(struct of_device *op, struct fb_info *info,
 static int __devinit leo_probe(struct of_device *op,
                               const struct of_device_id *match)
 {
-       struct device_node *dp = op->node;
+       struct device_node *dp = op->dev.of_node;
        struct fb_info *info;
        struct leo_par *par;
        int linebytes, err;
index 0540de4f5cb48f062bedb6d9874964ab1423d62b..4e2b8cc3d46093299a2ae05178ead6db2e783640 100644 (file)
@@ -553,7 +553,7 @@ static int mb862xx_gdc_init(struct mb862xxfb_par *par)
 static int __devinit of_platform_mb862xx_probe(struct of_device *ofdev,
                                               const struct of_device_id *id)
 {
-       struct device_node *np = ofdev->node;
+       struct device_node *np = ofdev->dev.of_node;
        struct device *dev = &ofdev->dev;
        struct mb862xxfb_par *par;
        struct fb_info *info;
index c85dd408a9b87369fffdce371fad0754f1100810..6552751e81aaa058a18af29ff8892d9abe1a54af 100644 (file)
@@ -251,7 +251,7 @@ static void p9100_init_fix(struct fb_info *info, int linebytes, struct device_no
 
 static int __devinit p9100_probe(struct of_device *op, const struct of_device_id *match)
 {
-       struct device_node *dp = op->node;
+       struct device_node *dp = op->dev.of_node;
        struct fb_info *info;
        struct p9100_par *par;
        int linebytes, err;
index ef7a7bd8b503492fec8aa1f56ab678adfe2f06f0..cc039b33d2d8bd762a493bd650fceb1b0895a52f 100644 (file)
@@ -365,7 +365,7 @@ static void tcx_unmap_regs(struct of_device *op, struct fb_info *info,
 static int __devinit tcx_probe(struct of_device *op,
                               const struct of_device_id *match)
 {
-       struct device_node *dp = op->node;
+       struct device_node *dp = op->dev.of_node;
        struct fb_info *info;
        struct tcx_par *par;
        int linebytes, i, err;
index ca0f4c6cf5ab98217f1b444a94611b0098781041..1df284f9c2a1b3fcd9e667b49915e4dbc21f5de3 100644 (file)
@@ -273,7 +273,7 @@ static int __devinit gef_wdt_probe(struct of_device *dev,
                bus_clk = freq;
 
        /* Map devices registers into memory */
-       gef_wdt_regs = of_iomap(dev->node, 0);
+       gef_wdt_regs = of_iomap(dev->dev.of_node, 0);
        if (gef_wdt_regs == NULL)
                return -ENOMEM;
 
index 6622335773bbc53fd2f0c3aa90b986d6b2dca0ea..4cda64dd309c0367208358ef6eb41b73180969cc 100644 (file)
@@ -189,7 +189,7 @@ static int __devinit mpc8xxx_wdt_probe(struct of_device *ofdev,
                                       const struct of_device_id *match)
 {
        int ret;
-       struct device_node *np = ofdev->node;
+       struct device_node *np = ofdev->dev.of_node;
        struct mpc8xxx_wdt_type *wdt_type = match->data;
        u32 freq = fsl_get_sys_freq();
        bool enabled;
index eab33f1dbdf7013f451af491b882973ea017f718..7b547f53f65ee9267f19dd493a6ab7321310ed4c 100644 (file)
@@ -499,7 +499,7 @@ int xenbus_printf(struct xenbus_transaction t,
 #define PRINTF_BUFFER_SIZE 4096
        char *printf_buffer;
 
-       printf_buffer = kmalloc(PRINTF_BUFFER_SIZE, GFP_KERNEL);
+       printf_buffer = kmalloc(PRINTF_BUFFER_SIZE, GFP_NOIO | __GFP_HIGH);
        if (printf_buffer == NULL)
                return -ENOMEM;
 
index f1ff785b22924d8ccb736fd7794f8c424c2b32c0..75541af4b3db1395ecfab6fd318144b88b959fd8 100644 (file)
@@ -1952,6 +1952,7 @@ static void cifs_copy_cache_pages(struct address_space *mapping,
                        bytes_read -= PAGE_CACHE_SIZE;
                        continue;
                }
+               page_cache_release(page);
 
                target = kmap_atomic(page, KM_USER0);
 
index dc5873c21e4566ceaf6628882abae905098763f9..1121f7799c6ff527838ec50052d51bc10b10e2e7 100644 (file)
@@ -130,4 +130,7 @@ extern int drm_helper_resume_force_mode(struct drm_device *dev);
 extern void drm_kms_helper_poll_init(struct drm_device *dev);
 extern void drm_kms_helper_poll_fini(struct drm_device *dev);
 extern void drm_helper_hpd_irq_event(struct drm_device *dev);
+
+extern void drm_kms_helper_poll_disable(struct drm_device *dev);
+extern void drm_kms_helper_poll_enable(struct drm_device *dev);
 #endif
index a6a9f4af5ebd8257d92dcd592551b6fb05f91931..fe917dee723a7357f44c285626189ae7acd5e863 100644 (file)
@@ -79,6 +79,7 @@ struct drm_nouveau_gpuobj_free {
 #define NOUVEAU_GETPARAM_CHIPSET_ID      11
 #define NOUVEAU_GETPARAM_VM_VRAM_BASE    12
 #define NOUVEAU_GETPARAM_GRAPH_UNITS     13
+#define NOUVEAU_GETPARAM_PTIMER_TIME     14
 struct drm_nouveau_getparam {
        uint64_t param;
        uint64_t value;
index c7645f480d1219cb84c765e5962d86cdd470ec54..4d0842391edc666f8985329fed245b989e3a0c2d 100644 (file)
@@ -50,6 +50,8 @@
 #define DRM_VMW_EXECBUF              12
 #define DRM_VMW_FIFO_DEBUG           13
 #define DRM_VMW_FENCE_WAIT           14
+/* guarded by minor version >= 2 */
+#define DRM_VMW_UPDATE_LAYOUT        15
 
 
 /*************************************************************************/
@@ -585,4 +587,28 @@ struct drm_vmw_stream_arg {
  * sure that the stream has been stopped.
  */
 
+/*************************************************************************/
+/**
+ * DRM_VMW_UPDATE_LAYOUT - Update layout
+ *
+ * Updates the prefered modes and connection status for connectors. The
+ * command conisits of one drm_vmw_update_layout_arg pointing out a array
+ * of num_outputs drm_vmw_rect's.
+ */
+
+/**
+ * struct drm_vmw_update_layout_arg
+ *
+ * @num_outputs: number of active
+ * @rects: pointer to array of drm_vmw_rect
+ *
+ * Input argument to the DRM_VMW_UPDATE_LAYOUT Ioctl.
+ */
+
+struct drm_vmw_update_layout_arg {
+       uint32_t num_outputs;
+       uint32_t pad64;
+       uint64_t rects;
+};
+
 #endif
index fb6c91eac7e3eb7cef23b2be992a0ed6eece85a0..5d0266d94985c65acbd8b13a41961964cdde4a72 100644 (file)
@@ -585,6 +585,7 @@ enum perf_event_active_state {
 struct file;
 
 struct perf_mmap_data {
+       atomic_t                        refcount;
        struct rcu_head                 rcu_head;
 #ifdef CONFIG_PERF_USE_VMALLOC
        struct work_struct              work;
@@ -592,7 +593,6 @@ struct perf_mmap_data {
 #endif
        int                             nr_pages;       /* nr of data pages  */
        int                             writable;       /* are we writable   */
-       int                             nr_locked;      /* nr pages mlocked  */
 
        atomic_t                        poll;           /* POLL_ for wakeups */
 
@@ -631,6 +631,9 @@ struct swevent_hlist {
        struct rcu_head         rcu_head;
 };
 
+#define PERF_ATTACH_CONTEXT    0x01
+#define PERF_ATTACH_GROUP      0x02
+
 /**
  * struct perf_event - performance event kernel representation:
  */
@@ -643,10 +646,10 @@ struct perf_event {
        int                             nr_siblings;
        int                             group_flags;
        struct perf_event               *group_leader;
-       struct perf_event               *output;
        const struct pmu                *pmu;
 
        enum perf_event_active_state    state;
+       unsigned int                    attach_state;
        atomic64_t                      count;
 
        /*
@@ -704,6 +707,8 @@ struct perf_event {
        /* mmap bits */
        struct mutex                    mmap_mutex;
        atomic_t                        mmap_count;
+       int                             mmap_locked;
+       struct user_struct              *mmap_user;
        struct perf_mmap_data           *data;
 
        /* poll related */
index 2dfaa293ae8c971303092235da547b5afb438319..c9a97597699522db33b2f309bd58368970eb9651 100644 (file)
@@ -5,6 +5,27 @@
  * (C) Copyright 2005 Benjamin Herrenschmidt <benh@kernel.crashing.org>
  * (C) Copyright 2007 Paulo R. Zanoni <przanoni@gmail.com>
  * (C) Copyright 2007, 2009 Tiago Vignatti <vignatti@freedesktop.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS
+ * IN THE SOFTWARE.
+ *
  */
 
 #ifndef LINUX_VGA_H
index 3d685d1f2a03f0099f159ac96eb648eed107a0a7..5a64905d7278a47fb683a0aceb63cef029dd467b 100644 (file)
@@ -725,7 +725,7 @@ perf_trace_##call(void *__data, proto)                                      \
                                                                        \
        { assign; }                                                     \
                                                                        \
-       head = per_cpu_ptr(event_call->perf_events, smp_processor_id());\
+       head = this_cpu_ptr(event_call->perf_events);                   \
        perf_trace_buf_submit(entry, __entry_size, rctx, __addr,        \
                __count, &__regs, head);                                \
 }
index bd7ce8ca5bb9d7aff449674f1a8a24cdf1604be0..31d6afe9259412025f02e20bddcc37fa3bf4d62b 100644 (file)
@@ -283,14 +283,15 @@ ctx_group_list(struct perf_event *event, struct perf_event_context *ctx)
 static void
 list_add_event(struct perf_event *event, struct perf_event_context *ctx)
 {
-       struct perf_event *group_leader = event->group_leader;
+       WARN_ON_ONCE(event->attach_state & PERF_ATTACH_CONTEXT);
+       event->attach_state |= PERF_ATTACH_CONTEXT;
 
        /*
-        * Depending on whether it is a standalone or sibling event,
-        * add it straight to the context's event list, or to the group
-        * leader's sibling list:
+        * If we're a stand alone event or group leader, we go to the context
+        * list, group events are kept attached to the group so that
+        * perf_group_detach can, at all times, locate all siblings.
         */
-       if (group_leader == event) {
+       if (event->group_leader == event) {
                struct list_head *list;
 
                if (is_software_event(event))
@@ -298,13 +299,6 @@ list_add_event(struct perf_event *event, struct perf_event_context *ctx)
 
                list = ctx_group_list(event, ctx);
                list_add_tail(&event->group_entry, list);
-       } else {
-               if (group_leader->group_flags & PERF_GROUP_SOFTWARE &&
-                   !is_software_event(event))
-                       group_leader->group_flags &= ~PERF_GROUP_SOFTWARE;
-
-               list_add_tail(&event->group_entry, &group_leader->sibling_list);
-               group_leader->nr_siblings++;
        }
 
        list_add_rcu(&event->event_entry, &ctx->event_list);
@@ -313,6 +307,24 @@ list_add_event(struct perf_event *event, struct perf_event_context *ctx)
                ctx->nr_stat++;
 }
 
+static void perf_group_attach(struct perf_event *event)
+{
+       struct perf_event *group_leader = event->group_leader;
+
+       WARN_ON_ONCE(event->attach_state & PERF_ATTACH_GROUP);
+       event->attach_state |= PERF_ATTACH_GROUP;
+
+       if (group_leader == event)
+               return;
+
+       if (group_leader->group_flags & PERF_GROUP_SOFTWARE &&
+                       !is_software_event(event))
+               group_leader->group_flags &= ~PERF_GROUP_SOFTWARE;
+
+       list_add_tail(&event->group_entry, &group_leader->sibling_list);
+       group_leader->nr_siblings++;
+}
+
 /*
  * Remove a event from the lists for its context.
  * Must be called with ctx->mutex and ctx->lock held.
@@ -320,17 +332,22 @@ list_add_event(struct perf_event *event, struct perf_event_context *ctx)
 static void
 list_del_event(struct perf_event *event, struct perf_event_context *ctx)
 {
-       if (list_empty(&event->group_entry))
+       /*
+        * We can have double detach due to exit/hot-unplug + close.
+        */
+       if (!(event->attach_state & PERF_ATTACH_CONTEXT))
                return;
+
+       event->attach_state &= ~PERF_ATTACH_CONTEXT;
+
        ctx->nr_events--;
        if (event->attr.inherit_stat)
                ctx->nr_stat--;
 
-       list_del_init(&event->group_entry);
        list_del_rcu(&event->event_entry);
 
-       if (event->group_leader != event)
-               event->group_leader->nr_siblings--;
+       if (event->group_leader == event)
+               list_del_init(&event->group_entry);
 
        update_group_times(event);
 
@@ -345,21 +362,39 @@ list_del_event(struct perf_event *event, struct perf_event_context *ctx)
                event->state = PERF_EVENT_STATE_OFF;
 }
 
-static void
-perf_destroy_group(struct perf_event *event, struct perf_event_context *ctx)
+static void perf_group_detach(struct perf_event *event)
 {
        struct perf_event *sibling, *tmp;
+       struct list_head *list = NULL;
+
+       /*
+        * We can have double detach due to exit/hot-unplug + close.
+        */
+       if (!(event->attach_state & PERF_ATTACH_GROUP))
+               return;
+
+       event->attach_state &= ~PERF_ATTACH_GROUP;
+
+       /*
+        * If this is a sibling, remove it from its group.
+        */
+       if (event->group_leader != event) {
+               list_del_init(&event->group_entry);
+               event->group_leader->nr_siblings--;
+               return;
+       }
+
+       if (!list_empty(&event->group_entry))
+               list = &event->group_entry;
 
        /*
         * If this was a group event with sibling events then
         * upgrade the siblings to singleton events by adding them
-        * to the context list directly:
+        * to whatever list we are on.
         */
        list_for_each_entry_safe(sibling, tmp, &event->sibling_list, group_entry) {
-               struct list_head *list;
-
-               list = ctx_group_list(event, ctx);
-               list_move_tail(&sibling->group_entry, list);
+               if (list)
+                       list_move_tail(&sibling->group_entry, list);
                sibling->group_leader = sibling;
 
                /* Inherit group flags from the previous leader */
@@ -652,8 +687,11 @@ group_sched_in(struct perf_event *group_event,
        if (txn)
                pmu->start_txn(pmu);
 
-       if (event_sched_in(group_event, cpuctx, ctx))
+       if (event_sched_in(group_event, cpuctx, ctx)) {
+               if (txn)
+                       pmu->cancel_txn(pmu);
                return -EAGAIN;
+       }
 
        /*
         * Schedule in siblings as one group (if any):
@@ -675,9 +713,6 @@ group_sched_in(struct perf_event *group_event,
        }
 
 group_error:
-       if (txn)
-               pmu->cancel_txn(pmu);
-
        /*
         * Groups can be scheduled in as one unit only, so undo any
         * partial group before returning:
@@ -689,6 +724,9 @@ group_error:
        }
        event_sched_out(group_event, cpuctx, ctx);
 
+       if (txn)
+               pmu->cancel_txn(pmu);
+
        return -EAGAIN;
 }
 
@@ -727,6 +765,7 @@ static void add_event_to_ctx(struct perf_event *event,
                               struct perf_event_context *ctx)
 {
        list_add_event(event, ctx);
+       perf_group_attach(event);
        event->tstamp_enabled = ctx->time;
        event->tstamp_running = ctx->time;
        event->tstamp_stopped = ctx->time;
@@ -1841,6 +1880,7 @@ static void free_event_rcu(struct rcu_head *head)
 }
 
 static void perf_pending_sync(struct perf_event *event);
+static void perf_mmap_data_put(struct perf_mmap_data *data);
 
 static void free_event(struct perf_event *event)
 {
@@ -1856,9 +1896,9 @@ static void free_event(struct perf_event *event)
                        atomic_dec(&nr_task_events);
        }
 
-       if (event->output) {
-               fput(event->output->filp);
-               event->output = NULL;
+       if (event->data) {
+               perf_mmap_data_put(event->data);
+               event->data = NULL;
        }
 
        if (event->destroy)
@@ -1893,8 +1933,8 @@ int perf_event_release_kernel(struct perf_event *event)
         */
        mutex_lock_nested(&ctx->mutex, SINGLE_DEPTH_NESTING);
        raw_spin_lock_irq(&ctx->lock);
+       perf_group_detach(event);
        list_del_event(event, ctx);
-       perf_destroy_group(event, ctx);
        raw_spin_unlock_irq(&ctx->lock);
        mutex_unlock(&ctx->mutex);
 
@@ -2175,7 +2215,27 @@ unlock:
        return ret;
 }
 
-static int perf_event_set_output(struct perf_event *event, int output_fd);
+static const struct file_operations perf_fops;
+
+static struct perf_event *perf_fget_light(int fd, int *fput_needed)
+{
+       struct file *file;
+
+       file = fget_light(fd, fput_needed);
+       if (!file)
+               return ERR_PTR(-EBADF);
+
+       if (file->f_op != &perf_fops) {
+               fput_light(file, *fput_needed);
+               *fput_needed = 0;
+               return ERR_PTR(-EBADF);
+       }
+
+       return file->private_data;
+}
+
+static int perf_event_set_output(struct perf_event *event,
+                                struct perf_event *output_event);
 static int perf_event_set_filter(struct perf_event *event, void __user *arg);
 
 static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
@@ -2202,7 +2262,23 @@ static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                return perf_event_period(event, (u64 __user *)arg);
 
        case PERF_EVENT_IOC_SET_OUTPUT:
-               return perf_event_set_output(event, arg);
+       {
+               struct perf_event *output_event = NULL;
+               int fput_needed = 0;
+               int ret;
+
+               if (arg != -1) {
+                       output_event = perf_fget_light(arg, &fput_needed);
+                       if (IS_ERR(output_event))
+                               return PTR_ERR(output_event);
+               }
+
+               ret = perf_event_set_output(event, output_event);
+               if (output_event)
+                       fput_light(output_event->filp, fput_needed);
+
+               return ret;
+       }
 
        case PERF_EVENT_IOC_SET_FILTER:
                return perf_event_set_filter(event, (void __user *)arg);
@@ -2335,8 +2411,6 @@ perf_mmap_data_alloc(struct perf_event *event, int nr_pages)
        unsigned long size;
        int i;
 
-       WARN_ON(atomic_read(&event->mmap_count));
-
        size = sizeof(struct perf_mmap_data);
        size += nr_pages * sizeof(void *);
 
@@ -2452,8 +2526,6 @@ perf_mmap_data_alloc(struct perf_event *event, int nr_pages)
        unsigned long size;
        void *all_buf;
 
-       WARN_ON(atomic_read(&event->mmap_count));
-
        size = sizeof(struct perf_mmap_data);
        size += sizeof(void *);
 
@@ -2536,7 +2608,7 @@ perf_mmap_data_init(struct perf_event *event, struct perf_mmap_data *data)
        if (!data->watermark)
                data->watermark = max_size / 2;
 
-
+       atomic_set(&data->refcount, 1);
        rcu_assign_pointer(event->data, data);
 }
 
@@ -2548,13 +2620,26 @@ static void perf_mmap_data_free_rcu(struct rcu_head *rcu_head)
        perf_mmap_data_free(data);
 }
 
-static void perf_mmap_data_release(struct perf_event *event)
+static struct perf_mmap_data *perf_mmap_data_get(struct perf_event *event)
 {
-       struct perf_mmap_data *data = event->data;
+       struct perf_mmap_data *data;
 
-       WARN_ON(atomic_read(&event->mmap_count));
+       rcu_read_lock();
+       data = rcu_dereference(event->data);
+       if (data) {
+               if (!atomic_inc_not_zero(&data->refcount))
+                       data = NULL;
+       }
+       rcu_read_unlock();
+
+       return data;
+}
+
+static void perf_mmap_data_put(struct perf_mmap_data *data)
+{
+       if (!atomic_dec_and_test(&data->refcount))
+               return;
 
-       rcu_assign_pointer(event->data, NULL);
        call_rcu(&data->rcu_head, perf_mmap_data_free_rcu);
 }
 
@@ -2569,15 +2654,18 @@ static void perf_mmap_close(struct vm_area_struct *vma)
 {
        struct perf_event *event = vma->vm_file->private_data;
 
-       WARN_ON_ONCE(event->ctx->parent_ctx);
        if (atomic_dec_and_mutex_lock(&event->mmap_count, &event->mmap_mutex)) {
                unsigned long size = perf_data_size(event->data);
-               struct user_struct *user = current_user();
+               struct user_struct *user = event->mmap_user;
+               struct perf_mmap_data *data = event->data;
 
                atomic_long_sub((size >> PAGE_SHIFT) + 1, &user->locked_vm);
-               vma->vm_mm->locked_vm -= event->data->nr_locked;
-               perf_mmap_data_release(event);
+               vma->vm_mm->locked_vm -= event->mmap_locked;
+               rcu_assign_pointer(event->data, NULL);
                mutex_unlock(&event->mmap_mutex);
+
+               perf_mmap_data_put(data);
+               free_uid(user);
        }
 }
 
@@ -2629,13 +2717,10 @@ static int perf_mmap(struct file *file, struct vm_area_struct *vma)
 
        WARN_ON_ONCE(event->ctx->parent_ctx);
        mutex_lock(&event->mmap_mutex);
-       if (event->output) {
-               ret = -EINVAL;
-               goto unlock;
-       }
-
-       if (atomic_inc_not_zero(&event->mmap_count)) {
-               if (nr_pages != event->data->nr_pages)
+       if (event->data) {
+               if (event->data->nr_pages == nr_pages)
+                       atomic_inc(&event->data->refcount);
+               else
                        ret = -EINVAL;
                goto unlock;
        }
@@ -2667,21 +2752,23 @@ static int perf_mmap(struct file *file, struct vm_area_struct *vma)
        WARN_ON(event->data);
 
        data = perf_mmap_data_alloc(event, nr_pages);
-       ret = -ENOMEM;
-       if (!data)
+       if (!data) {
+               ret = -ENOMEM;
                goto unlock;
+       }
 
-       ret = 0;
        perf_mmap_data_init(event, data);
-
-       atomic_set(&event->mmap_count, 1);
-       atomic_long_add(user_extra, &user->locked_vm);
-       vma->vm_mm->locked_vm += extra;
-       event->data->nr_locked = extra;
        if (vma->vm_flags & VM_WRITE)
                event->data->writable = 1;
 
+       atomic_long_add(user_extra, &user->locked_vm);
+       event->mmap_locked = extra;
+       event->mmap_user = get_current_user();
+       vma->vm_mm->locked_vm += event->mmap_locked;
+
 unlock:
+       if (!ret)
+               atomic_inc(&event->mmap_count);
        mutex_unlock(&event->mmap_mutex);
 
        vma->vm_flags |= VM_RESERVED;
@@ -2977,6 +3064,7 @@ __always_inline void perf_output_copy(struct perf_output_handle *handle,
 
                len -= size;
                handle->addr += size;
+               buf += size;
                handle->size -= size;
                if (!handle->size) {
                        struct perf_mmap_data *data = handle->data;
@@ -2993,7 +3081,6 @@ int perf_output_begin(struct perf_output_handle *handle,
                      struct perf_event *event, unsigned int size,
                      int nmi, int sample)
 {
-       struct perf_event *output_event;
        struct perf_mmap_data *data;
        unsigned long tail, offset, head;
        int have_lost;
@@ -3010,10 +3097,6 @@ int perf_output_begin(struct perf_output_handle *handle,
        if (event->parent)
                event = event->parent;
 
-       output_event = rcu_dereference(event->output);
-       if (output_event)
-               event = output_event;
-
        data = rcu_dereference(event->data);
        if (!data)
                goto out;
@@ -3972,13 +4055,6 @@ static void perf_swevent_overflow(struct perf_event *event, u64 overflow,
        }
 }
 
-static void perf_swevent_unthrottle(struct perf_event *event)
-{
-       /*
-        * Nothing to do, we already reset hwc->interrupts.
-        */
-}
-
 static void perf_swevent_add(struct perf_event *event, u64 nr,
                               int nmi, struct perf_sample_data *data,
                               struct pt_regs *regs)
@@ -4193,11 +4269,22 @@ static void perf_swevent_disable(struct perf_event *event)
        hlist_del_rcu(&event->hlist_entry);
 }
 
+static void perf_swevent_void(struct perf_event *event)
+{
+}
+
+static int perf_swevent_int(struct perf_event *event)
+{
+       return 0;
+}
+
 static const struct pmu perf_ops_generic = {
        .enable         = perf_swevent_enable,
        .disable        = perf_swevent_disable,
+       .start          = perf_swevent_int,
+       .stop           = perf_swevent_void,
        .read           = perf_swevent_read,
-       .unthrottle     = perf_swevent_unthrottle,
+       .unthrottle     = perf_swevent_void, /* hwc->interrupts already reset */
 };
 
 /*
@@ -4478,8 +4565,10 @@ static int swevent_hlist_get(struct perf_event *event)
 static const struct pmu perf_ops_tracepoint = {
        .enable         = perf_trace_enable,
        .disable        = perf_trace_disable,
+       .start          = perf_swevent_int,
+       .stop           = perf_swevent_void,
        .read           = perf_swevent_read,
-       .unthrottle     = perf_swevent_unthrottle,
+       .unthrottle     = perf_swevent_void,
 };
 
 static int perf_tp_filter_match(struct perf_event *event,
@@ -4912,39 +5001,17 @@ err_size:
        goto out;
 }
 
-static int perf_event_set_output(struct perf_event *event, int output_fd)
+static int
+perf_event_set_output(struct perf_event *event, struct perf_event *output_event)
 {
-       struct perf_event *output_event = NULL;
-       struct file *output_file = NULL;
-       struct perf_event *old_output;
-       int fput_needed = 0;
+       struct perf_mmap_data *data = NULL, *old_data = NULL;
        int ret = -EINVAL;
 
-       /*
-        * Don't allow output of inherited per-task events. This would
-        * create performance issues due to cross cpu access.
-        */
-       if (event->cpu == -1 && event->attr.inherit)
-               return -EINVAL;
-
-       if (!output_fd)
+       if (!output_event)
                goto set;
 
-       output_file = fget_light(output_fd, &fput_needed);
-       if (!output_file)
-               return -EBADF;
-
-       if (output_file->f_op != &perf_fops)
-               goto out;
-
-       output_event = output_file->private_data;
-
-       /* Don't chain output fds */
-       if (output_event->output)
-               goto out;
-
-       /* Don't set an output fd when we already have an output channel */
-       if (event->data)
+       /* don't allow circular references */
+       if (event == output_event)
                goto out;
 
        /*
@@ -4959,26 +5026,28 @@ static int perf_event_set_output(struct perf_event *event, int output_fd)
        if (output_event->cpu == -1 && output_event->ctx != event->ctx)
                goto out;
 
-       atomic_long_inc(&output_file->f_count);
-
 set:
        mutex_lock(&event->mmap_mutex);
-       old_output = event->output;
-       rcu_assign_pointer(event->output, output_event);
-       mutex_unlock(&event->mmap_mutex);
+       /* Can't redirect output if we've got an active mmap() */
+       if (atomic_read(&event->mmap_count))
+               goto unlock;
 
-       if (old_output) {
-               /*
-                * we need to make sure no existing perf_output_*()
-                * is still referencing this event.
-                */
-               synchronize_rcu();
-               fput(old_output->filp);
+       if (output_event) {
+               /* get the buffer we want to redirect to */
+               data = perf_mmap_data_get(output_event);
+               if (!data)
+                       goto unlock;
        }
 
+       old_data = event->data;
+       rcu_assign_pointer(event->data, data);
        ret = 0;
+unlock:
+       mutex_unlock(&event->mmap_mutex);
+
+       if (old_data)
+               perf_mmap_data_put(old_data);
 out:
-       fput_light(output_file, fput_needed);
        return ret;
 }
 
@@ -4994,7 +5063,7 @@ SYSCALL_DEFINE5(perf_event_open,
                struct perf_event_attr __user *, attr_uptr,
                pid_t, pid, int, cpu, int, group_fd, unsigned long, flags)
 {
-       struct perf_event *event, *group_leader;
+       struct perf_event *event, *group_leader = NULL, *output_event = NULL;
        struct perf_event_attr attr;
        struct perf_event_context *ctx;
        struct file *event_file = NULL;
@@ -5034,19 +5103,25 @@ SYSCALL_DEFINE5(perf_event_open,
                goto err_fd;
        }
 
+       if (group_fd != -1) {
+               group_leader = perf_fget_light(group_fd, &fput_needed);
+               if (IS_ERR(group_leader)) {
+                       err = PTR_ERR(group_leader);
+                       goto err_put_context;
+               }
+               group_file = group_leader->filp;
+               if (flags & PERF_FLAG_FD_OUTPUT)
+                       output_event = group_leader;
+               if (flags & PERF_FLAG_FD_NO_GROUP)
+                       group_leader = NULL;
+       }
+
        /*
         * Look up the group leader (we will attach this event to it):
         */
-       group_leader = NULL;
-       if (group_fd != -1 && !(flags & PERF_FLAG_FD_NO_GROUP)) {
+       if (group_leader) {
                err = -EINVAL;
-               group_file = fget_light(group_fd, &fput_needed);
-               if (!group_file)
-                       goto err_put_context;
-               if (group_file->f_op != &perf_fops)
-                       goto err_put_context;
 
-               group_leader = group_file->private_data;
                /*
                 * Do not allow a recursive hierarchy (this new sibling
                 * becoming part of another group-sibling):
@@ -5068,9 +5143,16 @@ SYSCALL_DEFINE5(perf_event_open,
 
        event = perf_event_alloc(&attr, cpu, ctx, group_leader,
                                     NULL, NULL, GFP_KERNEL);
-       err = PTR_ERR(event);
-       if (IS_ERR(event))
+       if (IS_ERR(event)) {
+               err = PTR_ERR(event);
                goto err_put_context;
+       }
+
+       if (output_event) {
+               err = perf_event_set_output(event, output_event);
+               if (err)
+                       goto err_free_put_context;
+       }
 
        event_file = anon_inode_getfile("[perf_event]", &perf_fops, event, O_RDWR);
        if (IS_ERR(event_file)) {
@@ -5078,12 +5160,6 @@ SYSCALL_DEFINE5(perf_event_open,
                goto err_free_put_context;
        }
 
-       if (flags & PERF_FLAG_FD_OUTPUT) {
-               err = perf_event_set_output(event, group_fd);
-               if (err)
-                       goto err_fput_free_put_context;
-       }
-
        event->filp = event_file;
        WARN_ON_ONCE(ctx->parent_ctx);
        mutex_lock(&ctx->mutex);
@@ -5097,12 +5173,16 @@ SYSCALL_DEFINE5(perf_event_open,
        list_add_tail(&event->owner_entry, &current->perf_event_list);
        mutex_unlock(&current->perf_event_mutex);
 
+       /*
+        * Drop the reference on the group_event after placing the
+        * new event on the sibling_list. This ensures destruction
+        * of the group leader will find the pointer to itself in
+        * perf_group_detach().
+        */
        fput_light(group_file, fput_needed);
        fd_install(event_fd, event_file);
        return event_fd;
 
-err_fput_free_put_context:
-       fput(event_file);
 err_free_put_context:
        free_event(event);
 err_put_context:
@@ -5420,6 +5500,7 @@ static void perf_free_event(struct perf_event *event,
 
        fput(parent->filp);
 
+       perf_group_detach(event);
        list_del_event(event, ctx);
        free_event(event);
 }
index 36ea2b65dcdc65a281bef8e7fa1acf0a44434003..638711c175048b00b8adb1175ed192a0b8181102 100644 (file)
@@ -842,6 +842,7 @@ static void blk_add_trace_split(void *ignore,
 
 /**
  * blk_add_trace_remap - Add a trace for a remap operation
+ * @ignore:    trace callback data parameter (not used)
  * @q:         queue the io is for
  * @bio:       the source bio
  * @dev:       target device
@@ -873,6 +874,7 @@ static void blk_add_trace_remap(void *ignore,
 
 /**
  * blk_add_trace_rq_remap - Add a trace for a request-remap operation
+ * @ignore:    trace callback data parameter (not used)
  * @q:         queue the io is for
  * @rq:                the source request
  * @dev:       target device
index cb6f365016e48f0c7f7848cbaebb39d45fb80c45..e6f65887842c9a91649550daee07c593c818f9b5 100644 (file)
@@ -116,7 +116,7 @@ int perf_trace_enable(struct perf_event *p_event)
        if (WARN_ON_ONCE(!list))
                return -EINVAL;
 
-       list = per_cpu_ptr(list, smp_processor_id());
+       list = this_cpu_ptr(list);
        hlist_add_head_rcu(&p_event->hlist_entry, list);
 
        return 0;
@@ -132,8 +132,9 @@ void perf_trace_destroy(struct perf_event *p_event)
        struct ftrace_event_call *tp_event = p_event->tp_event;
        int i;
 
+       mutex_lock(&event_mutex);
        if (--tp_event->perf_refcount > 0)
-               return;
+               goto out;
 
        if (tp_event->class->reg)
                tp_event->class->reg(tp_event, TRACE_REG_PERF_UNREGISTER);
@@ -142,6 +143,12 @@ void perf_trace_destroy(struct perf_event *p_event)
                                            tp_event->class->perf_probe,
                                            tp_event);
 
+       /*
+        * Ensure our callback won't be called anymore. See
+        * tracepoint_probe_unregister() and __DO_TRACE().
+        */
+       synchronize_sched();
+
        free_percpu(tp_event->perf_events);
        tp_event->perf_events = NULL;
 
@@ -151,6 +158,8 @@ void perf_trace_destroy(struct perf_event *p_event)
                        perf_trace_buf[i] = NULL;
                }
        }
+out:
+       mutex_unlock(&event_mutex);
 }
 
 __kprobes void *perf_trace_buf_prepare(int size, unsigned short type,
@@ -169,7 +178,7 @@ __kprobes void *perf_trace_buf_prepare(int size, unsigned short type,
        if (*rctxp < 0)
                return NULL;
 
-       raw_data = per_cpu_ptr(perf_trace_buf[*rctxp], smp_processor_id());
+       raw_data = this_cpu_ptr(perf_trace_buf[*rctxp]);
 
        /* zero the dead bytes from align to not leak stack to user */
        memset(&raw_data[size - sizeof(u64)], 0, sizeof(u64));
index faf7cefd15daf985afaadacb1d7a4b466993aa30..f52b5f50299dae5cc74dfe807054cd7d0e3f875e 100644 (file)
@@ -1359,7 +1359,7 @@ static __kprobes void kprobe_perf_func(struct kprobe *kp,
        for (i = 0; i < tp->nr_args; i++)
                call_fetch(&tp->args[i].fetch, regs, data + tp->args[i].offset);
 
-       head = per_cpu_ptr(call->perf_events, smp_processor_id());
+       head = this_cpu_ptr(call->perf_events);
        perf_trace_buf_submit(entry, size, rctx, entry->ip, 1, regs, head);
 }
 
@@ -1392,7 +1392,7 @@ static __kprobes void kretprobe_perf_func(struct kretprobe_instance *ri,
        for (i = 0; i < tp->nr_args; i++)
                call_fetch(&tp->args[i].fetch, regs, data + tp->args[i].offset);
 
-       head = per_cpu_ptr(call->perf_events, smp_processor_id());
+       head = this_cpu_ptr(call->perf_events);
        perf_trace_buf_submit(entry, size, rctx, entry->ret_ip, 1, regs, head);
 }
 
index d2c859cec9ea85b6f2e32c4c016937bee450aacb..34e35804304b03a7549b2f3a00064e8ec4675d7f 100644 (file)
@@ -519,7 +519,7 @@ static void perf_syscall_enter(void *ignore, struct pt_regs *regs, long id)
        syscall_get_arguments(current, regs, 0, sys_data->nb_args,
                               (unsigned long *)&rec->args);
 
-       head = per_cpu_ptr(sys_data->enter_event->perf_events, smp_processor_id());
+       head = this_cpu_ptr(sys_data->enter_event->perf_events);
        perf_trace_buf_submit(rec, size, rctx, 0, 1, regs, head);
 }
 
@@ -595,7 +595,7 @@ static void perf_syscall_exit(void *ignore, struct pt_regs *regs, long ret)
        rec->nr = syscall_nr;
        rec->ret = syscall_get_return_value(current, regs);
 
-       head = per_cpu_ptr(sys_data->exit_event->perf_events, smp_processor_id());
+       head = this_cpu_ptr(sys_data->exit_event->perf_events);
        perf_trace_buf_submit(rec, size, rctx, 0, 1, regs, head);
 }
 
index 44a47e13bd673eb362f956b80bd02adbec367d45..99890728409eba3bc390d2060a58d140f543c488 100644 (file)
@@ -43,8 +43,10 @@ static int __cmd_buildid_list(void)
        if (session == NULL)
                return -1;
 
-       if (with_hits)
+       if (with_hits) {
+               symbol_conf.full_paths = true;
                perf_session__process_events(session, &build_id__mark_dso_hit_ops);
+       }
 
        perf_session__fprintf_dsos_buildid(session, stdout, with_hits);
 
index 9bc89050e6f8642cf65cbfbd354c7a8f209cd816..dc3435e18bdeb18cfdcb8e2a08a21a98cc695a2d 100644 (file)
@@ -503,7 +503,6 @@ static int __cmd_record(int argc, const char **argv)
 {
        int i, counter;
        struct stat st;
-       pid_t pid = 0;
        int flags;
        int err;
        unsigned long waking = 0;
@@ -572,7 +571,7 @@ static int __cmd_record(int argc, const char **argv)
 
        if (forks) {
                child_pid = fork();
-               if (pid < 0) {
+               if (child_pid < 0) {
                        perror("failed to fork");
                        exit(-1);
                }
index f67bce2a83b4e090d86a0ecc2dd5a1240521db0a..55f3b5dcc731417198a2e5fd29ac8eefd96e1a5e 100644 (file)
@@ -1645,6 +1645,7 @@ static struct perf_event_ops event_ops = {
        .sample                 = process_sample_event,
        .comm                   = event__process_comm,
        .lost                   = event__process_lost,
+       .fork                   = event__process_task,
        .ordered_samples        = true,
 };
 
index 964d934395ff67d57b65a17660400bff8a1483e2..d9f7893e315c0d5aa064df04a8cc3ac870aebdad 100644 (file)
@@ -51,8 +51,7 @@ def kmem__kmalloc(event_name, context, common_cpu,
 
                flag_str("kmem__kmalloc", "gfp_flags", gfp_flags)),
 
-def trace_unhandled(event_name, context, common_cpu, common_secs, common_nsecs,
-               common_pid, common_comm):
+def trace_unhandled(event_name, context, event_fields_dict):
     try:
         unhandled[event_name] += 1
     except TypeError:
index 50771b5813ee6e15a6843a232b108415f77a4a29..1f08f008d289f841f7ae0089462129f97e313afc 100644 (file)
@@ -370,9 +370,9 @@ static int thread__set_comm_adjust(struct thread *self, const char *comm)
 
 int event__process_comm(event_t *self, struct perf_session *session)
 {
-       struct thread *thread = perf_session__findnew(session, self->comm.pid);
+       struct thread *thread = perf_session__findnew(session, self->comm.tid);
 
-       dump_printf(": %s:%d\n", self->comm.comm, self->comm.pid);
+       dump_printf(": %s:%d\n", self->comm.comm, self->comm.tid);
 
        if (thread == NULL || thread__set_comm_adjust(thread, self->comm.comm)) {
                dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n");
@@ -532,16 +532,11 @@ out_problem:
 
 int event__process_task(event_t *self, struct perf_session *session)
 {
-       struct thread *thread = perf_session__findnew(session, self->fork.pid);
-       struct thread *parent = perf_session__findnew(session, self->fork.ppid);
+       struct thread *thread = perf_session__findnew(session, self->fork.tid);
+       struct thread *parent = perf_session__findnew(session, self->fork.ptid);
 
        dump_printf("(%d:%d):(%d:%d)\n", self->fork.pid, self->fork.tid,
                    self->fork.ppid, self->fork.ptid);
-       /*
-        * A thread clone will have the same PID for both parent and child.
-        */
-       if (thread == parent)
-               return 0;
 
        if (self->header.type == PERF_RECORD_EXIT)
                return 0;
index cbf7eae2ce0909326afa68cb534315df11badeae..07f89b66b318e43748f666f495f87b75f6a34462 100644 (file)
@@ -965,7 +965,7 @@ static int hist_entry__parse_objdump_line(struct hist_entry *self, FILE *file,
                 * Parse hexa addresses followed by ':'
                 */
                line_ip = strtoull(tmp, &tmp2, 16);
-               if (*tmp2 != ':')
+               if (*tmp2 != ':' || tmp == tmp2)
                        line_ip = -1;
        }
 
index 81f39cab3aaa5981b60d38e7402e21d5a359e3b2..33a632523743deff80cb9e3636bd9144b84b2f76 100644 (file)
@@ -208,7 +208,7 @@ static void python_process_event(int cpu, void *data,
                                 int size __unused,
                                 unsigned long long nsecs, char *comm)
 {
-       PyObject *handler, *retval, *context, *t, *obj;
+       PyObject *handler, *retval, *context, *t, *obj, *dict = NULL;
        static char handler_name[256];
        struct format_field *field;
        unsigned long long val;
@@ -232,6 +232,14 @@ static void python_process_event(int cpu, void *data,
 
        sprintf(handler_name, "%s__%s", event->system, event->name);
 
+       handler = PyDict_GetItemString(main_dict, handler_name);
+       if (handler && !PyCallable_Check(handler))
+               handler = NULL;
+       if (!handler) {
+               dict = PyDict_New();
+               if (!dict)
+                       Py_FatalError("couldn't create Python dict");
+       }
        s = nsecs / NSECS_PER_SEC;
        ns = nsecs - s * NSECS_PER_SEC;
 
@@ -242,12 +250,20 @@ static void python_process_event(int cpu, void *data,
        PyTuple_SetItem(t, n++, PyString_FromString(handler_name));
        PyTuple_SetItem(t, n++,
                        PyCObject_FromVoidPtr(scripting_context, NULL));
-       PyTuple_SetItem(t, n++, PyInt_FromLong(cpu));
-       PyTuple_SetItem(t, n++, PyInt_FromLong(s));
-       PyTuple_SetItem(t, n++, PyInt_FromLong(ns));
-       PyTuple_SetItem(t, n++, PyInt_FromLong(pid));
-       PyTuple_SetItem(t, n++, PyString_FromString(comm));
 
+       if (handler) {
+               PyTuple_SetItem(t, n++, PyInt_FromLong(cpu));
+               PyTuple_SetItem(t, n++, PyInt_FromLong(s));
+               PyTuple_SetItem(t, n++, PyInt_FromLong(ns));
+               PyTuple_SetItem(t, n++, PyInt_FromLong(pid));
+               PyTuple_SetItem(t, n++, PyString_FromString(comm));
+       } else {
+               PyDict_SetItemString(dict, "common_cpu", PyInt_FromLong(cpu));
+               PyDict_SetItemString(dict, "common_s", PyInt_FromLong(s));
+               PyDict_SetItemString(dict, "common_ns", PyInt_FromLong(ns));
+               PyDict_SetItemString(dict, "common_pid", PyInt_FromLong(pid));
+               PyDict_SetItemString(dict, "common_comm", PyString_FromString(comm));
+       }
        for (field = event->format.fields; field; field = field->next) {
                if (field->flags & FIELD_IS_STRING) {
                        int offset;
@@ -272,27 +288,31 @@ static void python_process_event(int cpu, void *data,
                                        obj = PyLong_FromUnsignedLongLong(val);
                        }
                }
-               PyTuple_SetItem(t, n++, obj);
+               if (handler)
+                       PyTuple_SetItem(t, n++, obj);
+               else
+                       PyDict_SetItemString(dict, field->name, obj);
+
        }
+       if (!handler)
+               PyTuple_SetItem(t, n++, dict);
 
        if (_PyTuple_Resize(&t, n) == -1)
                Py_FatalError("error resizing Python tuple");
 
-       handler = PyDict_GetItemString(main_dict, handler_name);
-       if (handler && PyCallable_Check(handler)) {
+       if (handler) {
                retval = PyObject_CallObject(handler, t);
                if (retval == NULL)
                        handler_call_die(handler_name);
        } else {
                handler = PyDict_GetItemString(main_dict, "trace_unhandled");
                if (handler && PyCallable_Check(handler)) {
-                       if (_PyTuple_Resize(&t, N_COMMON_FIELDS) == -1)
-                               Py_FatalError("error resizing Python tuple");
 
                        retval = PyObject_CallObject(handler, t);
                        if (retval == NULL)
                                handler_call_die("trace_unhandled");
                }
+               Py_DECREF(dict);
        }
 
        Py_DECREF(t);
@@ -548,12 +568,10 @@ static int python_generate_script(const char *outfile)
        }
 
        fprintf(ofp, "def trace_unhandled(event_name, context, "
-               "common_cpu, common_secs, common_nsecs,\n\t\t"
-               "common_pid, common_comm):\n");
+               "event_fields_dict):\n");
 
-       fprintf(ofp, "\t\tprint_header(event_name, common_cpu, "
-               "common_secs, common_nsecs,\n\t\tcommon_pid, "
-               "common_comm)\n\n");
+       fprintf(ofp, "\t\tprint ' '.join(['%%s=%%s'%%(k,str(v))"
+               "for k,v in sorted(event_fields_dict.items())])\n\n");
 
        fprintf(ofp, "def print_header("
                "event_name, cpu, secs, nsecs, pid, comm):\n"