Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 26 Jan 2010 03:03:45 +0000 (19:03 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 26 Jan 2010 03:03:45 +0000 (19:03 -0800)
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6:
  ASoC: fix a memory-leak in wm8903
  ALSA: hda - add possibility to choose speakers configuration for 4930g
  ALSA: hda - Fix HP T5735 automute
  ALSA: hda - Turn on EAPD only if available for Realtek codecs
  ALSA: hda - Fix parsing pin node 0x21 on ALC259

183 files changed:
MAINTAINERS
arch/arm/mach-omap1/clock.c
arch/arm/mach-omap2/clock34xx_data.c
arch/arm/mach-omap2/clock44xx_data.c
arch/arm/mach-omap2/cpuidle34xx.c
arch/arm/mach-omap2/gpmc.c
arch/arm/mach-omap2/id.c
arch/arm/mach-omap2/irq.c
arch/arm/mach-omap2/mux.c
arch/arm/mach-omap2/mux.h
arch/arm/mach-omap2/omap_hwmod.c
arch/arm/mach-omap2/pm-debug.c
arch/arm/mach-omap2/pm.h
arch/arm/mach-omap2/pm34xx.c
arch/arm/mach-omap2/prcm.c
arch/arm/mach-omap2/prm.h
arch/arm/mach-omap2/prm44xx.h
arch/arm/mach-omap2/sleep34xx.S
arch/arm/mach-s3c6410/mach-hmt.c
arch/arm/plat-omap/common.c
arch/arm/plat-omap/dma.c
arch/arm/plat-omap/dmtimer.c
arch/arm/plat-omap/include/plat/cpu.h
arch/arm/plat-omap/include/plat/irqs.h
arch/arm/plat-omap/include/plat/omap_hwmod.h
arch/powerpc/kvm/Kconfig
arch/s390/kvm/intercept.c
arch/sparc/Kconfig
arch/sparc/configs/sparc32_defconfig
arch/sparc/configs/sparc64_defconfig
arch/sparc/include/asm/io_32.h
arch/sparc/include/asm/page_32.h
arch/sparc/include/asm/param.h
arch/sparc/include/asm/timex_32.h
arch/sparc/include/asm/topology_64.h
arch/sparc/include/asm/uaccess_32.h
arch/sparc/include/asm/uaccess_64.h
arch/sparc/kernel/central.c
arch/sparc/kernel/irq_64.c
arch/sparc/kernel/pcic.c
arch/sparc/kernel/perf_event.c
arch/sparc/kernel/sys_sparc_64.c
arch/sparc/kernel/time_32.c
arch/sparc/mm/fault_32.c
arch/sparc/mm/fault_64.c
arch/x86/kvm/lapic.c
arch/x86/kvm/mmu.c
arch/x86/kvm/paging_tmpl.h
arch/x86/kvm/x86.c
drivers/gpu/drm/drm_edid.c
drivers/gpu/drm/drm_fb_helper.c
drivers/gpu/drm/nouveau/nouveau_bios.c
drivers/gpu/drm/nouveau/nouveau_bo.c
drivers/gpu/drm/nouveau/nouveau_connector.c
drivers/gpu/drm/nouveau/nouveau_dma.c
drivers/gpu/drm/nouveau/nouveau_dp.c
drivers/gpu/drm/nouveau/nouveau_drv.c
drivers/gpu/drm/nouveau/nouveau_drv.h
drivers/gpu/drm/nouveau/nouveau_gem.c
drivers/gpu/drm/nouveau/nouveau_irq.c
drivers/gpu/drm/nouveau/nouveau_mem.c
drivers/gpu/drm/nouveau/nouveau_state.c
drivers/gpu/drm/nouveau/nv04_instmem.c
drivers/gpu/drm/nouveau/nv50_crtc.c
drivers/gpu/drm/nouveau/nv50_fifo.c
drivers/gpu/drm/nouveau/nv50_graph.c
drivers/gpu/drm/nouveau/nv50_sor.c
drivers/gpu/drm/radeon/atom.c
drivers/gpu/drm/radeon/atom.h
drivers/gpu/drm/radeon/atombios_crtc.c
drivers/gpu/drm/radeon/r100.c
drivers/gpu/drm/radeon/r200.c
drivers/gpu/drm/radeon/r420.c
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/r600_blit_kms.c
drivers/gpu/drm/radeon/r600_cs.c
drivers/gpu/drm/radeon/r600d.h
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_agp.c
drivers/gpu/drm/radeon/radeon_clocks.c
drivers/gpu/drm/radeon/radeon_cs.c
drivers/gpu/drm/radeon/radeon_device.c
drivers/gpu/drm/radeon/radeon_display.c
drivers/gpu/drm/radeon/radeon_legacy_crtc.c
drivers/gpu/drm/radeon/radeon_mode.h
drivers/gpu/drm/radeon/radeon_object.c
drivers/gpu/drm/radeon/reg_srcs/r200
drivers/gpu/drm/radeon/rv770.c
drivers/gpu/drm/ttm/ttm_bo.c
drivers/gpu/drm/ttm/ttm_lock.c
drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c
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_fifo.c
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c
drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
drivers/hwmon/amc6821.c
drivers/hwmon/asus_atk0110.c
drivers/hwmon/fschmd.c
drivers/hwmon/smsc47m1.c
drivers/i2c/busses/i2c-imx.c
drivers/mtd/maps/Kconfig
drivers/mtd/maps/pismo.c [new file with mode: 0644]
drivers/mtd/mtdoops.c
drivers/mtd/tests/mtd_readtest.c
drivers/mtd/tests/mtd_speedtest.c
drivers/mtd/tests/mtd_stresstest.c
drivers/mtd/ubi/kapi.c
drivers/mtd/ubi/upd.c
drivers/mtd/ubi/vtbl.c
drivers/net/benet/be_cmds.c
drivers/net/benet/be_main.c
drivers/net/bfin_mac.c
drivers/net/e1000/e1000.h
drivers/net/e1000/e1000_main.c
drivers/net/e1000e/e1000.h
drivers/net/e1000e/netdev.c
drivers/net/igb/igb_main.c
drivers/net/igbvf/netdev.c
drivers/net/ixgb/ixgb_main.c
drivers/net/ixgbe/ixgbe_main.c
drivers/net/pcmcia/fmvj18x_cs.c
drivers/net/phy/phy.c
drivers/net/phy/phy_device.c
drivers/net/qlge/qlge_main.c
drivers/net/s2io.c
drivers/net/sfc/mcdi.c
drivers/net/sfc/mcdi.h
drivers/net/sfc/mcdi_pcol.h
drivers/net/sfc/mtd.c
drivers/net/sfc/qt202x_phy.c
drivers/net/sky2.c
drivers/net/tulip/tulip_core.c
drivers/net/ucc_geth.c
drivers/net/virtio_net.c
drivers/net/wimax/i2400m/i2400m-usb.h
drivers/net/wimax/i2400m/usb.c
drivers/net/wireless/iwlwifi/iwl-5000.c
drivers/net/wireless/iwlwifi/iwl-devtrace.c
drivers/net/wireless/iwlwifi/iwl-devtrace.h
drivers/net/wireless/iwmc3200wifi/commands.c
drivers/net/wireless/iwmc3200wifi/commands.h
drivers/net/wireless/p54/p54pci.c
drivers/net/wireless/zd1211rw/zd_usb.c
drivers/serial/serial_cs.c
fs/eventfd.c
include/drm/ttm/ttm_bo_driver.h
include/linux/eventfd.h
include/linux/kmsg_dump.h
include/linux/mtd/pismo.h [new file with mode: 0644]
include/linux/phy.h
include/net/netns/xfrm.h
include/net/netrom.h
include/net/xfrm.h
kernel/kexec.c
kernel/panic.c
kernel/printk.c
kernel/time/clockevents.c
net/8021q/vlan_dev.c
net/appletalk/aarp.c
net/ax25/ax25_out.c
net/dccp/ccid.c
net/dccp/ccid.h
net/dccp/probe.c
net/ipv4/inet_diag.c
net/ipv4/route.c
net/ipv4/tcp_probe.c
net/ipv4/xfrm4_policy.c
net/ipv6/xfrm6_policy.c
net/mac80211/cfg.c
net/mac80211/rc80211_pid_algo.c
net/netrom/nr_route.c
net/rose/rose_link.c
net/rose/rose_route.c
net/wireless/sme.c
net/xfrm/xfrm_policy.c
net/xfrm/xfrm_state.c
net/xfrm/xfrm_user.c
virt/kvm/eventfd.c
virt/kvm/irq_comm.c

index 1858646..03f38c1 100644 (file)
@@ -987,7 +987,6 @@ F:  drivers/platform/x86/asus-laptop.c
 
 ASYNCHRONOUS TRANSFERS/TRANSFORMS (IOAT) API
 M:     Dan Williams <dan.j.williams@intel.com>
-M:     Maciej Sosnowski <maciej.sosnowski@intel.com>
 W:     http://sourceforge.net/projects/xscaleiop
 S:     Supported
 F:     Documentation/crypto/async-tx-api.txt
@@ -1823,7 +1822,6 @@ S:        Supported
 F:     fs/dlm/
 
 DMA GENERIC OFFLOAD ENGINE SUBSYSTEM
-M:     Maciej Sosnowski <maciej.sosnowski@intel.com>
 M:     Dan Williams <dan.j.williams@intel.com>
 S:     Supported
 F:     drivers/dma/
@@ -2786,7 +2784,7 @@ F:        arch/x86/kernel/microcode_core.c
 F:     arch/x86/kernel/microcode_intel.c
 
 INTEL I/OAT DMA DRIVER
-M:     Maciej Sosnowski <maciej.sosnowski@intel.com>
+M:     Dan Williams <dan.j.williams@intel.com>
 S:     Supported
 F:     drivers/dma/ioat*
 
@@ -2824,10 +2822,11 @@ L:      netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/ixp2000/
 
-INTEL ETHERNET DRIVERS (e100/e1000/e1000e/igb/ixgb/ixgbe)
+INTEL ETHERNET DRIVERS (e100/e1000/e1000e/igb/igbvf/ixgb/ixgbe)
 M:     Jeff Kirsher <jeffrey.t.kirsher@intel.com>
 M:     Jesse Brandeburg <jesse.brandeburg@intel.com>
 M:     Bruce Allan <bruce.w.allan@intel.com>
+M:     Alex Duyck <alexander.h.duyck@intel.com>
 M:     PJ Waskiewicz <peter.p.waskiewicz.jr@intel.com>
 M:     John Ronciak <john.ronciak@intel.com>
 L:     e1000-devel@lists.sourceforge.net
@@ -2837,6 +2836,7 @@ F:        drivers/net/e100.c
 F:     drivers/net/e1000/
 F:     drivers/net/e1000e/
 F:     drivers/net/igb/
+F:     drivers/net/igbvf/
 F:     drivers/net/ixgb/
 F:     drivers/net/ixgbe/
 
index 2ba9ab9..04f1d29 100644 (file)
@@ -214,8 +214,8 @@ int omap1_select_table_rate(struct clk *clk, unsigned long rate)
        struct mpu_rate * ptr;
        unsigned long dpll1_rate, ref_rate;
 
-       dpll1_rate = clk_get_rate(ck_dpll1_p);
-       ref_rate = clk_get_rate(ck_ref_p);
+       dpll1_rate = ck_dpll1_p->rate;
+       ref_rate = ck_ref_p->rate;
 
        for (ptr = omap1_rate_table; ptr->rate; ptr++) {
                if (ptr->xtal != ref_rate)
@@ -306,7 +306,7 @@ long omap1_round_to_table_rate(struct clk *clk, unsigned long rate)
        long highest_rate;
        unsigned long ref_rate;
 
-       ref_rate = clk_get_rate(ck_ref_p);
+       ref_rate = ck_ref_p->rate;
 
        highest_rate = -EINVAL;
 
index c6031d7..74930e3 100644 (file)
@@ -671,7 +671,6 @@ static struct clk dpll4_m3x2_ck = {
        .name           = "dpll4_m3x2_ck",
        .ops            = &clkops_omap2_dflt_wait,
        .parent         = &dpll4_m3_ck,
-       .init           = &omap2_init_clksel_parent,
        .enable_reg     = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
        .enable_bit     = OMAP3430_PWRDN_TV_SHIFT,
        .flags          = INVERT_ENABLE,
@@ -811,7 +810,6 @@ static struct clk dpll4_m6x2_ck = {
        .name           = "dpll4_m6x2_ck",
        .ops            = &clkops_omap2_dflt_wait,
        .parent         = &dpll4_m6_ck,
-       .init           = &omap2_init_clksel_parent,
        .enable_reg     = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
        .enable_bit     = OMAP3430_PWRDN_EMU_PERIPH_SHIFT,
        .flags          = INVERT_ENABLE,
@@ -1047,7 +1045,6 @@ static struct clk iva2_ck = {
        .name           = "iva2_ck",
        .ops            = &clkops_omap2_dflt_wait,
        .parent         = &dpll2_m2_ck,
-       .init           = &omap2_init_clksel_parent,
        .enable_reg     = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, CM_FCLKEN),
        .enable_bit     = OMAP3430_CM_FCLKEN_IVA2_EN_IVA2_SHIFT,
        .clkdm_name     = "iva2_clkdm",
@@ -1121,7 +1118,6 @@ static struct clk gfx_l3_ck = {
        .name           = "gfx_l3_ck",
        .ops            = &clkops_omap2_dflt_wait,
        .parent         = &l3_ick,
-       .init           = &omap2_init_clksel_parent,
        .enable_reg     = OMAP_CM_REGADDR(GFX_MOD, CM_ICLKEN),
        .enable_bit     = OMAP_EN_GFX_SHIFT,
        .recalc         = &followparent_recalc,
index 2210e22..9d882bc 100644 (file)
@@ -346,37 +346,37 @@ static struct clk aess_fclk = {
 };
 
 static const struct clksel_rate div31_1to31_rates[] = {
-       { .div = 1, .val = 0, .flags = RATE_IN_4430 },
-       { .div = 2, .val = 1, .flags = RATE_IN_4430 },
-       { .div = 3, .val = 2, .flags = RATE_IN_4430 },
-       { .div = 4, .val = 3, .flags = RATE_IN_4430 },
-       { .div = 5, .val = 4, .flags = RATE_IN_4430 },
-       { .div = 6, .val = 5, .flags = RATE_IN_4430 },
-       { .div = 7, .val = 6, .flags = RATE_IN_4430 },
-       { .div = 8, .val = 7, .flags = RATE_IN_4430 },
-       { .div = 9, .val = 8, .flags = RATE_IN_4430 },
-       { .div = 10, .val = 9, .flags = RATE_IN_4430 },
-       { .div = 11, .val = 10, .flags = RATE_IN_4430 },
-       { .div = 12, .val = 11, .flags = RATE_IN_4430 },
-       { .div = 13, .val = 12, .flags = RATE_IN_4430 },
-       { .div = 14, .val = 13, .flags = RATE_IN_4430 },
-       { .div = 15, .val = 14, .flags = RATE_IN_4430 },
-       { .div = 16, .val = 15, .flags = RATE_IN_4430 },
-       { .div = 17, .val = 16, .flags = RATE_IN_4430 },
-       { .div = 18, .val = 17, .flags = RATE_IN_4430 },
-       { .div = 19, .val = 18, .flags = RATE_IN_4430 },
-       { .div = 20, .val = 19, .flags = RATE_IN_4430 },
-       { .div = 21, .val = 20, .flags = RATE_IN_4430 },
-       { .div = 22, .val = 21, .flags = RATE_IN_4430 },
-       { .div = 23, .val = 22, .flags = RATE_IN_4430 },
-       { .div = 24, .val = 23, .flags = RATE_IN_4430 },
-       { .div = 25, .val = 24, .flags = RATE_IN_4430 },
-       { .div = 26, .val = 25, .flags = RATE_IN_4430 },
-       { .div = 27, .val = 26, .flags = RATE_IN_4430 },
-       { .div = 28, .val = 27, .flags = RATE_IN_4430 },
-       { .div = 29, .val = 28, .flags = RATE_IN_4430 },
-       { .div = 30, .val = 29, .flags = RATE_IN_4430 },
-       { .div = 31, .val = 30, .flags = RATE_IN_4430 },
+       { .div = 1, .val = 1, .flags = RATE_IN_4430 },
+       { .div = 2, .val = 2, .flags = RATE_IN_4430 },
+       { .div = 3, .val = 3, .flags = RATE_IN_4430 },
+       { .div = 4, .val = 4, .flags = RATE_IN_4430 },
+       { .div = 5, .val = 5, .flags = RATE_IN_4430 },
+       { .div = 6, .val = 6, .flags = RATE_IN_4430 },
+       { .div = 7, .val = 7, .flags = RATE_IN_4430 },
+       { .div = 8, .val = 8, .flags = RATE_IN_4430 },
+       { .div = 9, .val = 9, .flags = RATE_IN_4430 },
+       { .div = 10, .val = 10, .flags = RATE_IN_4430 },
+       { .div = 11, .val = 11, .flags = RATE_IN_4430 },
+       { .div = 12, .val = 12, .flags = RATE_IN_4430 },
+       { .div = 13, .val = 13, .flags = RATE_IN_4430 },
+       { .div = 14, .val = 14, .flags = RATE_IN_4430 },
+       { .div = 15, .val = 15, .flags = RATE_IN_4430 },
+       { .div = 16, .val = 16, .flags = RATE_IN_4430 },
+       { .div = 17, .val = 17, .flags = RATE_IN_4430 },
+       { .div = 18, .val = 18, .flags = RATE_IN_4430 },
+       { .div = 19, .val = 19, .flags = RATE_IN_4430 },
+       { .div = 20, .val = 20, .flags = RATE_IN_4430 },
+       { .div = 21, .val = 21, .flags = RATE_IN_4430 },
+       { .div = 22, .val = 22, .flags = RATE_IN_4430 },
+       { .div = 23, .val = 23, .flags = RATE_IN_4430 },
+       { .div = 24, .val = 24, .flags = RATE_IN_4430 },
+       { .div = 25, .val = 25, .flags = RATE_IN_4430 },
+       { .div = 26, .val = 26, .flags = RATE_IN_4430 },
+       { .div = 27, .val = 27, .flags = RATE_IN_4430 },
+       { .div = 28, .val = 28, .flags = RATE_IN_4430 },
+       { .div = 29, .val = 29, .flags = RATE_IN_4430 },
+       { .div = 30, .val = 30, .flags = RATE_IN_4430 },
+       { .div = 31, .val = 31, .flags = RATE_IN_4430 },
        { .div = 0 },
 };
 
index a26d6a0..12f0cbf 100644 (file)
@@ -137,7 +137,7 @@ return_sleep_time:
        local_irq_enable();
        local_fiq_enable();
 
-       return (u32)timespec_to_ns(&ts_idle)/1000;
+       return ts_idle.tv_nsec / NSEC_PER_USEC + ts_idle.tv_sec * USEC_PER_SEC;
 }
 
 /**
index bd8cb59..3f1334f 100644 (file)
@@ -534,6 +534,8 @@ void __init gpmc_init(void)
                BUG();
        }
 
+       clk_enable(gpmc_l3_clk);
+
        l = gpmc_read_reg(GPMC_REVISION);
        printk(KERN_INFO "GPMC revision %d.%d\n", (l >> 4) & 0x0f, l & 0x0f);
        /* Set smart idle mode and automatic L3 clock gating */
index a091b53..3d65c50 100644 (file)
@@ -188,6 +188,8 @@ void __init omap3_check_revision(void)
        u16 hawkeye;
        u8 rev;
 
+       omap_chip.oc = CHIP_IS_OMAP3430;
+
        /*
         * We cannot access revision registers on ES1.0.
         * If the processor type is Cortex-A8 and the revision is 0x0
@@ -196,6 +198,7 @@ void __init omap3_check_revision(void)
        cpuid = read_cpuid(CPUID_ID);
        if ((((cpuid >> 4) & 0xfff) == 0xc08) && ((cpuid & 0xf) == 0x0)) {
                omap_revision = OMAP3430_REV_ES1_0;
+               omap_chip.oc |= CHIP_IS_OMAP3430ES1;
                return;
        }
 
@@ -216,18 +219,28 @@ void __init omap3_check_revision(void)
                case 0: /* Take care of early samples */
                case 1:
                        omap_revision = OMAP3430_REV_ES2_0;
+                       omap_chip.oc |= CHIP_IS_OMAP3430ES2;
                        break;
                case 2:
                        omap_revision = OMAP3430_REV_ES2_1;
+                       omap_chip.oc |= CHIP_IS_OMAP3430ES2;
                        break;
                case 3:
                        omap_revision = OMAP3430_REV_ES3_0;
+                       omap_chip.oc |= CHIP_IS_OMAP3430ES3_0;
                        break;
                case 4:
+                       omap_revision = OMAP3430_REV_ES3_1;
+                       omap_chip.oc |= CHIP_IS_OMAP3430ES3_1;
+                       break;
+               case 7:
                /* FALLTHROUGH */
                default:
                        /* Use the latest known revision as default */
-                       omap_revision = OMAP3430_REV_ES3_1;
+                       omap_revision = OMAP3430_REV_ES3_1_2;
+
+                       /* REVISIT: Add CHIP_IS_OMAP3430ES3_1_2? */
+                       omap_chip.oc |= CHIP_IS_OMAP3430ES3_1;
                }
                break;
        case 0xb868:
@@ -235,14 +248,18 @@ void __init omap3_check_revision(void)
                 *
                 * Set the device to be OMAP3505 here. Actual device
                 * is identified later based on the features.
+                *
+                * REVISIT: AM3505/AM3517 should have their own CHIP_IS
                 */
                omap_revision = OMAP3505_REV(rev);
+               omap_chip.oc |= CHIP_IS_OMAP3430ES3_1;
                break;
        case 0xb891:
        /* FALLTHROUGH */
        default:
                /* Unknown default to latest silicon rev as default*/
                omap_revision = OMAP3630_REV_ES1_0;
+               omap_chip.oc |= CHIP_IS_OMAP3630ES1;
        }
 }
 
@@ -360,6 +377,7 @@ void __init omap2_check_revision(void)
                omap3_check_revision();
                omap3_check_features();
                omap3_cpuinfo();
+               return;
        } else if (cpu_is_omap44xx()) {
                omap4_check_revision();
                return;
@@ -374,27 +392,14 @@ void __init omap2_check_revision(void)
        if (cpu_is_omap243x()) {
                /* Currently only supports 2430ES2.1 and 2430-all */
                omap_chip.oc |= CHIP_IS_OMAP2430;
+               return;
        } else if (cpu_is_omap242x()) {
                /* Currently only supports 2420ES2.1.1 and 2420-all */
                omap_chip.oc |= CHIP_IS_OMAP2420;
-       } else if (cpu_is_omap3505() || cpu_is_omap3517()) {
-               omap_chip.oc = CHIP_IS_OMAP3430 | CHIP_IS_OMAP3430ES3_1;
-       } else if (cpu_is_omap343x()) {
-               omap_chip.oc = CHIP_IS_OMAP3430;
-               if (omap_rev() == OMAP3430_REV_ES1_0)
-                       omap_chip.oc |= CHIP_IS_OMAP3430ES1;
-               else if (omap_rev() >= OMAP3430_REV_ES2_0 &&
-                        omap_rev() <= OMAP3430_REV_ES2_1)
-                       omap_chip.oc |= CHIP_IS_OMAP3430ES2;
-               else if (omap_rev() == OMAP3430_REV_ES3_0)
-                       omap_chip.oc |= CHIP_IS_OMAP3430ES3_0;
-               else if (omap_rev() == OMAP3430_REV_ES3_1)
-                       omap_chip.oc |= CHIP_IS_OMAP3430ES3_1;
-               else if (omap_rev() == OMAP3630_REV_ES1_0)
-                       omap_chip.oc |= CHIP_IS_OMAP3630ES1;
-       } else {
-               pr_err("Uninitialized omap_chip, please fix!\n");
+               return;
        }
+
+       pr_err("Uninitialized omap_chip, please fix!\n");
 }
 
 /*
index e9bc782..2705402 100644 (file)
@@ -274,4 +274,22 @@ void omap_intc_restore_context(void)
        }
        /* MIRs are saved and restore with other PRCM registers */
 }
+
+void omap3_intc_suspend(void)
+{
+       /* A pending interrupt would prevent OMAP from entering suspend */
+       omap_ack_irq(0);
+}
+
+void omap3_intc_prepare_idle(void)
+{
+       /* Disable autoidle as it can stall interrupt controller */
+       intc_bank_write_reg(0, &irq_banks[0], INTC_SYSCONFIG);
+}
+
+void omap3_intc_resume_idle(void)
+{
+       /* Re-enable autoidle */
+       intc_bank_write_reg(1, &irq_banks[0], INTC_SYSCONFIG);
+}
 #endif /* CONFIG_ARCH_OMAP3 */
index 459ef23..3f59bd1 100644 (file)
@@ -51,7 +51,7 @@ struct omap_mux_entry {
 static unsigned long mux_phys;
 static void __iomem *mux_base;
 
-static inline u16 omap_mux_read(u16 reg)
+u16 omap_mux_read(u16 reg)
 {
        if (cpu_is_omap24xx())
                return __raw_readb(mux_base + reg);
@@ -59,7 +59,7 @@ static inline u16 omap_mux_read(u16 reg)
                return __raw_readw(mux_base + reg);
 }
 
-static inline void omap_mux_write(u16 val, u16 reg)
+void omap_mux_write(u16 val, u16 reg)
 {
        if (cpu_is_omap24xx())
                __raw_writeb(val, mux_base + reg);
@@ -67,6 +67,14 @@ static inline void omap_mux_write(u16 val, u16 reg)
                __raw_writew(val, mux_base + reg);
 }
 
+void omap_mux_write_array(struct omap_board_mux *board_mux)
+{
+       while (board_mux->reg_offset !=  OMAP_MUX_TERMINATOR) {
+               omap_mux_write(board_mux->value, board_mux->reg_offset);
+               board_mux++;
+       }
+}
+
 #if defined(CONFIG_ARCH_OMAP24XX) && defined(CONFIG_OMAP_MUX)
 
 static struct omap_mux_cfg arch_mux_cfg;
@@ -833,14 +841,6 @@ static void __init omap_mux_set_cmdline_signals(void)
        kfree(options);
 }
 
-static void __init omap_mux_set_board_signals(struct omap_board_mux *board_mux)
-{
-       while (board_mux->reg_offset !=  OMAP_MUX_TERMINATOR) {
-               omap_mux_write(board_mux->value, board_mux->reg_offset);
-               board_mux++;
-       }
-}
-
 static int __init omap_mux_copy_names(struct omap_mux *src,
                                        struct omap_mux *dst)
 {
@@ -998,12 +998,15 @@ int __init omap_mux_init(u32 mux_pbase, u32 mux_size,
                omap_mux_package_fixup(package_subset, superset);
        if (package_balls)
                omap_mux_package_init_balls(package_balls, superset);
-       omap_mux_set_cmdline_signals();
-       omap_mux_set_board_signals(board_mux);
 #endif
 
        omap_mux_init_list(superset);
 
+#ifdef CONFIG_OMAP_MUX
+       omap_mux_set_cmdline_signals();
+       omap_mux_write_array(board_mux);
+#endif
+
        return 0;
 }
 
index d8b4d5a..f8c2e7a 100644 (file)
@@ -146,6 +146,30 @@ u16 omap_mux_get_gpio(int gpio);
  */
 void omap_mux_set_gpio(u16 val, int gpio);
 
+/**
+ * omap_mux_read() - read mux register
+ * @mux_offset:                Offset of the mux register
+ *
+ */
+u16 omap_mux_read(u16 mux_offset);
+
+/**
+ * omap_mux_write() - write mux register
+ * @val:               New mux register value
+ * @mux_offset:                Offset of the mux register
+ *
+ * This should be only needed for dynamic remuxing of non-gpio signals.
+ */
+void omap_mux_write(u16 val, u16 mux_offset);
+
+/**
+ * omap_mux_write_array() - write an array of mux registers
+ * @board_mux:         Array of mux registers terminated by MAP_MUX_TERMINATOR
+ *
+ * This should be only needed for dynamic remuxing of non-gpio signals.
+ */
+void omap_mux_write_array(struct omap_board_mux *board_mux);
+
 /**
  * omap3_mux_init() - initialize mux system with board specific set
  * @board_mux:         Board specific mux table
index d8c8545..478ae58 100644 (file)
@@ -94,7 +94,8 @@ static int _update_sysc_cache(struct omap_hwmod *oh)
 
        oh->_sysc_cache = omap_hwmod_readl(oh, oh->sysconfig->sysc_offs);
 
-       oh->_int_flags |= _HWMOD_SYSCONFIG_LOADED;
+       if (!(oh->sysconfig->sysc_flags & SYSC_NO_CACHE))
+               oh->_int_flags |= _HWMOD_SYSCONFIG_LOADED;
 
        return 0;
 }
index 860b755..a086626 100644 (file)
@@ -54,8 +54,6 @@ int omap2_pm_debug;
        regs[reg_count++].val = \
                         __raw_readl(OMAP2_L4_IO_ADDRESS(0x480fe000 + (off)))
 
-static int __init pm_dbg_init(void);
-
 void omap2_pm_dump(int mode, int resume, unsigned int us)
 {
        struct reg {
@@ -167,6 +165,8 @@ struct dentry *pm_dbg_dir;
 
 static int pm_dbg_init_done;
 
+static int __init pm_dbg_init(void);
+
 enum {
        DEBUG_FILE_COUNTERS = 0,
        DEBUG_FILE_TIMERS,
@@ -488,9 +488,11 @@ int pm_dbg_regset_init(int reg_set)
 
 static int pwrdm_suspend_get(void *data, u64 *val)
 {
-       *val = omap3_pm_get_suspend_state((struct powerdomain *)data);
+       int ret;
+       ret = omap3_pm_get_suspend_state((struct powerdomain *)data);
+       *val = ret;
 
-       if (*val >= 0)
+       if (ret >= 0)
                return 0;
        return *val;
 }
@@ -604,6 +606,4 @@ static int __init pm_dbg_init(void)
 }
 arch_initcall(pm_dbg_init);
 
-#else
-void pm_dbg_update_time(struct powerdomain *pwrdm, int prev) {}
 #endif
index 0bf345d..7a9c2d0 100644 (file)
@@ -32,12 +32,16 @@ extern struct omap_dm_timer *gptimer_wakeup;
 #ifdef CONFIG_PM_DEBUG
 extern void omap2_pm_dump(int mode, int resume, unsigned int us);
 extern int omap2_pm_debug;
+#else
+#define omap2_pm_dump(mode, resume, us)                do {} while (0);
+#define omap2_pm_debug                         0
+#endif
+
+#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS)
 extern void pm_dbg_update_time(struct powerdomain *pwrdm, int prev);
 extern int pm_dbg_regset_save(int reg_set);
 extern int pm_dbg_regset_init(int reg_set);
 #else
-#define omap2_pm_dump(mode, resume, us)                do {} while (0);
-#define omap2_pm_debug                         0
 #define pm_dbg_update_time(pwrdm, prev) do {} while (0);
 #define pm_dbg_regset_save(reg_set) do {} while (0);
 #define pm_dbg_regset_init(reg_set) do {} while (0);
index c6cc809..910a7ac 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/err.h>
 #include <linux/gpio.h>
 #include <linux/clk.h>
+#include <linux/delay.h>
 
 #include <plat/sram.h>
 #include <plat/clockdomain.h>
@@ -126,7 +127,15 @@ static void omap3_core_save_context(void)
        /* wait for the save to complete */
        while (!(omap_ctrl_readl(OMAP343X_CONTROL_GENERAL_PURPOSE_STATUS)
                        & PADCONF_SAVE_DONE))
-               ;
+               udelay(1);
+
+       /*
+        * Force write last pad into memory, as this can fail in some
+        * cases according to erratas 1.157, 1.185
+        */
+       omap_ctrl_writel(omap_ctrl_readl(OMAP343X_PADCONF_ETK_D14),
+               OMAP343X_CONTROL_MEM_WKUP + 0x2a0);
+
        /* Save the Interrupt controller context */
        omap_intc_save_context();
        /* Save the GPMC context */
@@ -392,6 +401,7 @@ void omap_sram_idle(void)
                prm_set_mod_reg_bits(OMAP3430_EN_IO, WKUP_MOD, PM_WKEN);
                omap3_enable_io_chain();
        }
+       omap3_intc_prepare_idle();
 
        /*
        * On EMU/HS devices ROM code restores a SRDC value
@@ -438,6 +448,7 @@ void omap_sram_idle(void)
                                               OMAP3430_GR_MOD,
                                               OMAP3_PRM_VOLTCTRL_OFFSET);
        }
+       omap3_intc_resume_idle();
 
        /* PER */
        if (per_next_state < PWRDM_POWER_ON) {
@@ -578,6 +589,8 @@ static int omap3_pm_suspend(void)
        }
 
        omap_uart_prepare_suspend();
+       omap3_intc_suspend();
+
        omap_sram_idle();
 
 restore:
@@ -835,6 +848,8 @@ static void __init prcm_setup_regs(void)
                        CM_AUTOIDLE);
        }
 
+       omap_ctrl_writel(OMAP3430_AUTOIDLE, OMAP2_CONTROL_SYSCONFIG);
+
        /*
         * Set all plls to autoidle. This is needed until autoidle is
         * enabled by clockfw
@@ -875,15 +890,23 @@ static void __init prcm_setup_regs(void)
        prm_write_mod_reg(OMAP3430_IO_EN | OMAP3430_WKUP_EN,
                          OCP_MOD, OMAP3_PRM_IRQENABLE_MPU_OFFSET);
 
+       /* Enable PM_WKEN to support DSS LPR */
+       prm_write_mod_reg(OMAP3430_PM_WKEN_DSS_EN_DSS,
+                               OMAP3430_DSS_MOD, PM_WKEN);
+
        /* Enable wakeups in PER */
        prm_write_mod_reg(OMAP3430_EN_GPIO2 | OMAP3430_EN_GPIO3 |
                          OMAP3430_EN_GPIO4 | OMAP3430_EN_GPIO5 |
-                         OMAP3430_EN_GPIO6 | OMAP3430_EN_UART3,
+                         OMAP3430_EN_GPIO6 | OMAP3430_EN_UART3 |
+                         OMAP3430_EN_MCBSP2 | OMAP3430_EN_MCBSP3 |
+                         OMAP3430_EN_MCBSP4,
                          OMAP3430_PER_MOD, PM_WKEN);
        /* and allow them to wake up MPU */
        prm_write_mod_reg(OMAP3430_GRPSEL_GPIO2 | OMAP3430_EN_GPIO3 |
                          OMAP3430_GRPSEL_GPIO4 | OMAP3430_EN_GPIO5 |
-                         OMAP3430_GRPSEL_GPIO6 | OMAP3430_EN_UART3,
+                         OMAP3430_GRPSEL_GPIO6 | OMAP3430_EN_UART3 |
+                         OMAP3430_EN_MCBSP2 | OMAP3430_EN_MCBSP3 |
+                         OMAP3430_EN_MCBSP4,
                          OMAP3430_PER_MOD, OMAP3430_PM_MPUGRPSEL);
 
        /* Don't attach IVA interrupts */
@@ -904,24 +927,6 @@ static void __init prcm_setup_regs(void)
        /* Clear any pending PRCM interrupts */
        prm_write_mod_reg(0, OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
 
-       /* Don't attach IVA interrupts */
-       prm_write_mod_reg(0, WKUP_MOD, OMAP3430_PM_IVAGRPSEL);
-       prm_write_mod_reg(0, CORE_MOD, OMAP3430_PM_IVAGRPSEL1);
-       prm_write_mod_reg(0, CORE_MOD, OMAP3430ES2_PM_IVAGRPSEL3);
-       prm_write_mod_reg(0, OMAP3430_PER_MOD, OMAP3430_PM_IVAGRPSEL);
-
-       /* Clear any pending 'reset' flags */
-       prm_write_mod_reg(0xffffffff, MPU_MOD, RM_RSTST);
-       prm_write_mod_reg(0xffffffff, CORE_MOD, RM_RSTST);
-       prm_write_mod_reg(0xffffffff, OMAP3430_PER_MOD, RM_RSTST);
-       prm_write_mod_reg(0xffffffff, OMAP3430_EMU_MOD, RM_RSTST);
-       prm_write_mod_reg(0xffffffff, OMAP3430_NEON_MOD, RM_RSTST);
-       prm_write_mod_reg(0xffffffff, OMAP3430_DSS_MOD, RM_RSTST);
-       prm_write_mod_reg(0xffffffff, OMAP3430ES2_USBHOST_MOD, RM_RSTST);
-
-       /* Clear any pending PRCM interrupts */
-       prm_write_mod_reg(0, OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
-
        omap3_iva_idle();
        omap3_d2d_idle();
 }
index 3ea8177..cf466ea 100644 (file)
@@ -44,7 +44,6 @@ struct omap3_prcm_regs {
        u32 iva2_cm_clksel2;
        u32 cm_sysconfig;
        u32 sgx_cm_clksel;
-       u32 wkup_cm_clksel;
        u32 dss_cm_clksel;
        u32 cam_cm_clksel;
        u32 per_cm_clksel;
@@ -53,7 +52,6 @@ struct omap3_prcm_regs {
        u32 pll_cm_autoidle2;
        u32 pll_cm_clksel4;
        u32 pll_cm_clksel5;
-       u32 pll_cm_clken;
        u32 pll_cm_clken2;
        u32 cm_polctrl;
        u32 iva2_cm_fclken;
@@ -77,7 +75,6 @@ struct omap3_prcm_regs {
        u32 usbhost_cm_iclken;
        u32 iva2_cm_autiidle2;
        u32 mpu_cm_autoidle2;
-       u32 pll_cm_autoidle;
        u32 iva2_cm_clkstctrl;
        u32 mpu_cm_clkstctrl;
        u32 core_cm_clkstctrl;
@@ -274,7 +271,6 @@ void omap3_prcm_save_context(void)
        prcm_context.cm_sysconfig = __raw_readl(OMAP3430_CM_SYSCONFIG);
        prcm_context.sgx_cm_clksel =
                         cm_read_mod_reg(OMAP3430ES2_SGX_MOD, CM_CLKSEL);
-       prcm_context.wkup_cm_clksel = cm_read_mod_reg(WKUP_MOD, CM_CLKSEL);
        prcm_context.dss_cm_clksel =
                         cm_read_mod_reg(OMAP3430_DSS_MOD, CM_CLKSEL);
        prcm_context.cam_cm_clksel =
@@ -291,8 +287,6 @@ void omap3_prcm_save_context(void)
                        cm_read_mod_reg(PLL_MOD, OMAP3430ES2_CM_CLKSEL4);
        prcm_context.pll_cm_clksel5 =
                         cm_read_mod_reg(PLL_MOD, OMAP3430ES2_CM_CLKSEL5);
-       prcm_context.pll_cm_clken =
-                       cm_read_mod_reg(PLL_MOD, CM_CLKEN);
        prcm_context.pll_cm_clken2 =
                        cm_read_mod_reg(PLL_MOD, OMAP3430ES2_CM_CLKEN2);
        prcm_context.cm_polctrl = __raw_readl(OMAP3430_CM_POLCTRL);
@@ -338,8 +332,6 @@ void omap3_prcm_save_context(void)
                         cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_AUTOIDLE2);
        prcm_context.mpu_cm_autoidle2 =
                         cm_read_mod_reg(MPU_MOD, CM_AUTOIDLE2);
-       prcm_context.pll_cm_autoidle =
-                        cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE);
        prcm_context.iva2_cm_clkstctrl =
                         cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_CLKSTCTRL);
        prcm_context.mpu_cm_clkstctrl =
@@ -431,7 +423,6 @@ void omap3_prcm_restore_context(void)
        __raw_writel(prcm_context.cm_sysconfig, OMAP3430_CM_SYSCONFIG);
        cm_write_mod_reg(prcm_context.sgx_cm_clksel, OMAP3430ES2_SGX_MOD,
                                         CM_CLKSEL);
-       cm_write_mod_reg(prcm_context.wkup_cm_clksel, WKUP_MOD, CM_CLKSEL);
        cm_write_mod_reg(prcm_context.dss_cm_clksel, OMAP3430_DSS_MOD,
                                         CM_CLKSEL);
        cm_write_mod_reg(prcm_context.cam_cm_clksel, OMAP3430_CAM_MOD,
@@ -448,7 +439,6 @@ void omap3_prcm_restore_context(void)
                                        OMAP3430ES2_CM_CLKSEL4);
        cm_write_mod_reg(prcm_context.pll_cm_clksel5, PLL_MOD,
                                         OMAP3430ES2_CM_CLKSEL5);
-       cm_write_mod_reg(prcm_context.pll_cm_clken, PLL_MOD, CM_CLKEN);
        cm_write_mod_reg(prcm_context.pll_cm_clken2, PLL_MOD,
                                        OMAP3430ES2_CM_CLKEN2);
        __raw_writel(prcm_context.cm_polctrl, OMAP3430_CM_POLCTRL);
@@ -487,7 +477,6 @@ void omap3_prcm_restore_context(void)
        cm_write_mod_reg(prcm_context.iva2_cm_autiidle2, OMAP3430_IVA2_MOD,
                                        CM_AUTOIDLE2);
        cm_write_mod_reg(prcm_context.mpu_cm_autoidle2, MPU_MOD, CM_AUTOIDLE2);
-       cm_write_mod_reg(prcm_context.pll_cm_autoidle, PLL_MOD, CM_AUTOIDLE);
        cm_write_mod_reg(prcm_context.iva2_cm_clkstctrl, OMAP3430_IVA2_MOD,
                                        CM_CLKSTCTRL);
        cm_write_mod_reg(prcm_context.mpu_cm_clkstctrl, MPU_MOD, CM_CLKSTCTRL);
index ea050ce..40f0062 100644 (file)
@@ -24,6 +24,8 @@
                OMAP2_L4_IO_ADDRESS(OMAP3430_PRM_BASE + (module) + (reg))
 #define OMAP44XX_PRM_REGADDR(module, reg)                              \
                OMAP2_L4_IO_ADDRESS(OMAP4430_PRM_BASE + (module) + (reg))
+#define OMAP44XX_CHIRONSS_REGADDR(module, reg)                         \
+               OMAP2_L4_IO_ADDRESS(OMAP4430_CHIRONSS_BASE + (module) + (reg))
 
 #include "prm44xx.h"
 
index 89be97f..adb2558 100644 (file)
 
 
 /* CHIRON_PRCM.CHIRONSS_OCP_SOCKET_PRCM register offsets */
-#define OMAP4430_REVISION_PRCM                         OMAP44XX_PRM_REGADDR(OMAP4430_CHIRONSS_CHIRONSS_OCP_SOCKET_PRCM_MOD, 0x0000)
+#define OMAP4430_REVISION_PRCM                         OMAP44XX_CHIRONSS_REGADDR(OMAP4430_CHIRONSS_CHIRONSS_OCP_SOCKET_PRCM_MOD, 0x0000)
 
 /* CHIRON_PRCM.CHIRONSS_DEVICE_PRM register offsets */
-#define OMAP4430_CHIRON_PRCM_PRM_RSTST                 OMAP44XX_PRM_REGADDR(OMAP4430_CHIRONSS_CHIRONSS_DEVICE_PRM_MOD, 0x0000)
+#define OMAP4430_CHIRON_PRCM_PRM_RSTST                 OMAP44XX_CHIRONSS_REGADDR(OMAP4430_CHIRONSS_CHIRONSS_DEVICE_PRM_MOD, 0x0000)
 
 /* CHIRON_PRCM.CHIRONSS_CPU0 register offsets */
-#define OMAP4430_PM_PDA_CPU0_PWRSTCTRL                 OMAP44XX_PRM_REGADDR(OMAP4430_CHIRONSS_CHIRONSS_CPU0_MOD, 0x0000)
-#define OMAP4430_PM_PDA_CPU0_PWRSTST                   OMAP44XX_PRM_REGADDR(OMAP4430_CHIRONSS_CHIRONSS_CPU0_MOD, 0x0004)
-#define OMAP4430_RM_PDA_CPU0_CPU0_CONTEXT              OMAP44XX_PRM_REGADDR(OMAP4430_CHIRONSS_CHIRONSS_CPU0_MOD, 0x0008)
-#define OMAP4430_RM_PDA_CPU0_CPU0_RSTCTRL              OMAP44XX_PRM_REGADDR(OMAP4430_CHIRONSS_CHIRONSS_CPU0_MOD, 0x000c)
-#define OMAP4430_RM_PDA_CPU0_CPU0_RSTST                        OMAP44XX_PRM_REGADDR(OMAP4430_CHIRONSS_CHIRONSS_CPU0_MOD, 0x0010)
-#define OMAP4430_CM_PDA_CPU0_CPU0_CLKCTRL              OMAP44XX_PRM_REGADDR(OMAP4430_CHIRONSS_CHIRONSS_CPU0_MOD, 0x0014)
-#define OMAP4430_CM_PDA_CPU0_CLKSTCTRL                 OMAP44XX_PRM_REGADDR(OMAP4430_CHIRONSS_CHIRONSS_CPU0_MOD, 0x0018)
+#define OMAP4430_PM_PDA_CPU0_PWRSTCTRL                 OMAP44XX_CHIRONSS_REGADDR(OMAP4430_CHIRONSS_CHIRONSS_CPU0_MOD, 0x0000)
+#define OMAP4430_PM_PDA_CPU0_PWRSTST                   OMAP44XX_CHIRONSS_REGADDR(OMAP4430_CHIRONSS_CHIRONSS_CPU0_MOD, 0x0004)
+#define OMAP4430_RM_PDA_CPU0_CPU0_CONTEXT              OMAP44XX_CHIRONSS_REGADDR(OMAP4430_CHIRONSS_CHIRONSS_CPU0_MOD, 0x0008)
+#define OMAP4430_RM_PDA_CPU0_CPU0_RSTCTRL              OMAP44XX_CHIRONSS_REGADDR(OMAP4430_CHIRONSS_CHIRONSS_CPU0_MOD, 0x000c)
+#define OMAP4430_RM_PDA_CPU0_CPU0_RSTST                        OMAP44XX_CHIRONSS_REGADDR(OMAP4430_CHIRONSS_CHIRONSS_CPU0_MOD, 0x0010)
+#define OMAP4430_CM_PDA_CPU0_CPU0_CLKCTRL              OMAP44XX_CHIRONSS_REGADDR(OMAP4430_CHIRONSS_CHIRONSS_CPU0_MOD, 0x0014)
+#define OMAP4430_CM_PDA_CPU0_CLKSTCTRL                 OMAP44XX_CHIRONSS_REGADDR(OMAP4430_CHIRONSS_CHIRONSS_CPU0_MOD, 0x0018)
 
 /* CHIRON_PRCM.CHIRONSS_CPU1 register offsets */
-#define OMAP4430_PM_PDA_CPU1_PWRSTCTRL                 OMAP44XX_PRM_REGADDR(OMAP4430_CHIRONSS_CHIRONSS_CPU1_MOD, 0x0000)
-#define OMAP4430_PM_PDA_CPU1_PWRSTST                   OMAP44XX_PRM_REGADDR(OMAP4430_CHIRONSS_CHIRONSS_CPU1_MOD, 0x0004)
-#define OMAP4430_RM_PDA_CPU1_CPU1_CONTEXT              OMAP44XX_PRM_REGADDR(OMAP4430_CHIRONSS_CHIRONSS_CPU1_MOD, 0x0008)
-#define OMAP4430_RM_PDA_CPU1_CPU1_RSTCTRL              OMAP44XX_PRM_REGADDR(OMAP4430_CHIRONSS_CHIRONSS_CPU1_MOD, 0x000c)
-#define OMAP4430_RM_PDA_CPU1_CPU1_RSTST                        OMAP44XX_PRM_REGADDR(OMAP4430_CHIRONSS_CHIRONSS_CPU1_MOD, 0x0010)
-#define OMAP4430_CM_PDA_CPU1_CPU1_CLKCTRL              OMAP44XX_PRM_REGADDR(OMAP4430_CHIRONSS_CHIRONSS_CPU1_MOD, 0x0014)
-#define OMAP4430_CM_PDA_CPU1_CLKSTCTRL                 OMAP44XX_PRM_REGADDR(OMAP4430_CHIRONSS_CHIRONSS_CPU1_MOD, 0x0018)
+#define OMAP4430_PM_PDA_CPU1_PWRSTCTRL                 OMAP44XX_CHIRONSS_REGADDR(OMAP4430_CHIRONSS_CHIRONSS_CPU1_MOD, 0x0000)
+#define OMAP4430_PM_PDA_CPU1_PWRSTST                   OMAP44XX_CHIRONSS_REGADDR(OMAP4430_CHIRONSS_CHIRONSS_CPU1_MOD, 0x0004)
+#define OMAP4430_RM_PDA_CPU1_CPU1_CONTEXT              OMAP44XX_CHIRONSS_REGADDR(OMAP4430_CHIRONSS_CHIRONSS_CPU1_MOD, 0x0008)
+#define OMAP4430_RM_PDA_CPU1_CPU1_RSTCTRL              OMAP44XX_CHIRONSS_REGADDR(OMAP4430_CHIRONSS_CHIRONSS_CPU1_MOD, 0x000c)
+#define OMAP4430_RM_PDA_CPU1_CPU1_RSTST                        OMAP44XX_CHIRONSS_REGADDR(OMAP4430_CHIRONSS_CHIRONSS_CPU1_MOD, 0x0010)
+#define OMAP4430_CM_PDA_CPU1_CPU1_CLKCTRL              OMAP44XX_CHIRONSS_REGADDR(OMAP4430_CHIRONSS_CHIRONSS_CPU1_MOD, 0x0014)
+#define OMAP4430_CM_PDA_CPU1_CLKSTCTRL                 OMAP44XX_CHIRONSS_REGADDR(OMAP4430_CHIRONSS_CHIRONSS_CPU1_MOD, 0x0018)
 #endif
index 15268f8..c3626ea 100644 (file)
@@ -245,7 +245,8 @@ restore:
        mov     r1, #0          @ set task id for ROM code in r1
        mov     r2, #4          @ set some flags in r2, r6
        mov     r6, #0xff
-       adr     r3, write_aux_control_params    @ r3 points to parameters
+       ldr     r4, scratchpad_base
+       ldr     r3, [r4, #0xBC] @ r3 points to parameters
        mcr     p15, 0, r0, c7, c10, 4  @ data write barrier
        mcr     p15, 0, r0, c7, c10, 5  @ data memory barrier
        .word   0xE1600071              @ call SMI monitor (smi #1)
@@ -253,14 +254,14 @@ restore:
        b       logic_l1_restore
 l2_inv_api_params:
        .word   0x1, 0x00
-write_aux_control_params:
-       .word   0x1, 0x72
 l2_inv_gp:
        /* Execute smi to invalidate L2 cache */
        mov r12, #0x1                         @ set up to invalide L2
 smi:    .word 0xE1600070               @ Call SMI monitor (smieq)
        /* Write to Aux control register to set some bits */
-       mov     r0, #0x72
+       ldr     r4, scratchpad_base
+       ldr     r3, [r4,#0xBC]
+       ldr     r0, [r3,#4]
        mov     r12, #0x3
        .word 0xE1600070        @ Call SMI monitor (smieq)
 logic_l1_restore:
@@ -271,6 +272,7 @@ logic_l1_restore:
 
        ldr     r4, scratchpad_base
        ldr     r3, [r4,#0xBC]
+       adds    r3, r3, #8
        ldmia   r3!, {r4-r6}
        mov     sp, r4
        msr     spsr_cxsf, r5
@@ -387,6 +389,9 @@ usettbr0:
 save_context_wfi:
        /*b     save_context_wfi*/      @ enable to debug save code
        mov     r8, r0 /* Store SDRAM address in r8 */
+       mrc     p15, 0, r5, c1, c0, 1   @ Read Auxiliary Control Register
+       mov     r4, #0x1                @ Number of parameters for restore call
+       stmia   r8!, {r4-r5}
         /* Check what that target sleep state is:stored in r1*/
         /* 1 - Only L1 and logic lost */
         /* 2 - Only L2 lost */
index cdd4b53..7619456 100644 (file)
@@ -82,7 +82,7 @@ static int hmt_bl_init(struct device *dev)
        return ret;
 }
 
-static int hmt_bl_notify(int brightness)
+static int hmt_bl_notify(struct device *dev, int brightness)
 {
        /*
         * translate from CIELUV/CIELAB L*->brightness, E.G. from
index bf1eaf3..dddc027 100644 (file)
@@ -172,6 +172,32 @@ unsigned long long sched_clock(void)
                                  clocksource_32k.mult, clocksource_32k.shift);
 }
 
+/**
+ * read_persistent_clock -  Return time from a persistent clock.
+ *
+ * Reads the time from a source which isn't disabled during PM, the
+ * 32k sync timer.  Convert the cycles elapsed since last read into
+ * nsecs and adds to a monotonically increasing timespec.
+ */
+static struct timespec persistent_ts;
+static cycles_t cycles, last_cycles;
+void read_persistent_clock(struct timespec *ts)
+{
+       unsigned long long nsecs;
+       cycles_t delta;
+       struct timespec *tsp = &persistent_ts;
+
+       last_cycles = cycles;
+       cycles = clocksource_32k.read(&clocksource_32k);
+       delta = cycles - last_cycles;
+
+       nsecs = clocksource_cyc2ns(delta,
+                                  clocksource_32k.mult, clocksource_32k.shift);
+
+       timespec_add_ns(tsp, nsecs);
+       *ts = *tsp;
+}
+
 static int __init omap_init_clocksource_32k(void)
 {
        static char err[] __initdata = KERN_ERR
index 09d82b3..728c642 100644 (file)
@@ -1183,7 +1183,7 @@ void omap_dma_unlink_lch(int lch_head, int lch_queue)
        }
 
        if ((dma_chan[lch_head].flags & OMAP_DMA_ACTIVE) ||
-           (dma_chan[lch_head].flags & OMAP_DMA_ACTIVE)) {
+           (dma_chan[lch_queue].flags & OMAP_DMA_ACTIVE)) {
                printk(KERN_ERR "omap_dma: You need to stop the DMA channels "
                       "before unlinking\n");
                dump_stack();
index 64f407e..08ccf89 100644 (file)
@@ -551,6 +551,19 @@ void omap_dm_timer_stop(struct omap_dm_timer *timer)
        if (l & OMAP_TIMER_CTRL_ST) {
                l &= ~0x1;
                omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
+#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) || \
+                       defined(CONFIG_ARCH_OMAP4)
+               /* Readback to make sure write has completed */
+               omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
+                /*
+                 * Wait for functional clock period x 3.5 to make sure that
+                 * timer is stopped
+                 */
+               udelay(3500000 / clk_get_rate(timer->fclk) + 1);
+               /* Ack possibly pending interrupt */
+               omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG,
+                               OMAP_TIMER_INT_OVERFLOW);
+#endif
        }
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_stop);
index 9a028bd..a162f58 100644 (file)
@@ -434,6 +434,7 @@ IS_OMAP_TYPE(3517, 0x3517)
 #define OMAP3430_REV_ES2_1     0x34302034
 #define OMAP3430_REV_ES3_0     0x34303034
 #define OMAP3430_REV_ES3_1     0x34304034
+#define OMAP3430_REV_ES3_1_2   0x34305034
 
 #define OMAP3630_REV_ES1_0     0x36300034
 
index 97d6c50..c0ab7c8 100644 (file)
@@ -499,6 +499,9 @@ extern void omap_init_irq(void);
 extern int omap_irq_pending(void);
 void omap_intc_save_context(void);
 void omap_intc_restore_context(void);
+void omap3_intc_suspend(void);
+void omap3_intc_prepare_idle(void);
+void omap3_intc_resume_idle(void);
 #endif
 
 #include <mach/hardware.h>
index 007935a..3393325 100644 (file)
@@ -227,6 +227,7 @@ struct omap_hwmod_ocp_if {
 #define SYSC_HAS_SIDLEMODE     (1 << 5)
 #define SYSC_HAS_MIDLEMODE     (1 << 6)
 #define SYSS_MISSING           (1 << 7)
+#define SYSC_NO_CACHE          (1 << 8)  /* XXX SW flag, belongs elsewhere */
 
 /* omap_hwmod_sysconfig.clockact flags */
 #define CLOCKACT_TEST_BOTH     0x0
index 07703f7..6fb6e8a 100644 (file)
@@ -53,7 +53,7 @@ config KVM_440
 
 config KVM_EXIT_TIMING
        bool "Detailed exit timing"
-       depends on KVM
+       depends on KVM_440 || KVM_E500
        ---help---
          Calculate elapsed time for every exit/enter cycle. A per-vcpu
          report is available in debugfs kvm/vm#_vcpu#_timing.
index ba9d8a7..b400964 100644 (file)
@@ -213,7 +213,7 @@ static int handle_instruction_and_prog(struct kvm_vcpu *vcpu)
        return rc2;
 }
 
-static const intercept_handler_t intercept_funcs[0x48 >> 2] = {
+static const intercept_handler_t intercept_funcs[] = {
        [0x00 >> 2] = handle_noop,
        [0x04 >> 2] = handle_instruction,
        [0x08 >> 2] = handle_prog,
@@ -230,7 +230,7 @@ int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu)
        intercept_handler_t func;
        u8 code = vcpu->arch.sie_block->icptcode;
 
-       if (code & 3 || code > 0x48)
+       if (code & 3 || (code >> 2) >= ARRAY_SIZE(intercept_funcs))
                return -ENOTSUPP;
        func = intercept_funcs[code >> 2];
        if (func)
index 108197a..4097f6a 100644 (file)
@@ -64,8 +64,11 @@ config BITS
        default 64 if SPARC64
 
 config GENERIC_TIME
+       def_bool y
+
+config ARCH_USES_GETTIMEOFFSET
        bool
-       default y if SPARC64
+       default y if SPARC32
 
 config GENERIC_CMOS_UPDATE
        bool
index 983d598..99a1f19 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.31
-# Wed Sep 16 00:03:43 2009
+# Linux kernel version: 2.6.33-rc2
+# Mon Jan 11 23:20:31 2010
 #
 # CONFIG_64BIT is not set
 CONFIG_SPARC=y
@@ -41,6 +41,7 @@ CONFIG_POSIX_MQUEUE_SYSCTL=y
 #
 CONFIG_TREE_RCU=y
 # CONFIG_TREE_PREEMPT_RCU is not set
+# CONFIG_TINY_RCU is not set
 # CONFIG_RCU_TRACE is not set
 CONFIG_RCU_FANOUT=32
 # CONFIG_RCU_FANOUT_EXACT is not set
@@ -88,21 +89,21 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
-CONFIG_HAVE_PERF_COUNTERS=y
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
 
 #
-# Performance Counters
+# Kernel Performance Events And Counters
 #
+# CONFIG_PERF_EVENTS is not set
 # CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
 # CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_DMA_ATTRS=y
@@ -131,14 +132,41 @@ CONFIG_LBDAF=y
 # IO Schedulers
 #
 CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
 CONFIG_IOSCHED_DEADLINE=y
 CONFIG_IOSCHED_CFQ=y
-# CONFIG_DEFAULT_AS is not set
 # CONFIG_DEFAULT_DEADLINE is not set
 CONFIG_DEFAULT_CFQ=y
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="cfq"
+# CONFIG_INLINE_SPIN_TRYLOCK is not set
+# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK is not set
+# CONFIG_INLINE_SPIN_LOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
+CONFIG_INLINE_SPIN_UNLOCK=y
+# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
+CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_READ_TRYLOCK is not set
+# CONFIG_INLINE_READ_LOCK is not set
+# CONFIG_INLINE_READ_LOCK_BH is not set
+# CONFIG_INLINE_READ_LOCK_IRQ is not set
+# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set
+CONFIG_INLINE_READ_UNLOCK=y
+# CONFIG_INLINE_READ_UNLOCK_BH is not set
+CONFIG_INLINE_READ_UNLOCK_IRQ=y
+# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_WRITE_TRYLOCK is not set
+# CONFIG_INLINE_WRITE_LOCK is not set
+# CONFIG_INLINE_WRITE_LOCK_BH is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set
+CONFIG_INLINE_WRITE_UNLOCK=y
+# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
+CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
+# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
+# CONFIG_MUTEX_SPIN_ON_OWNER is not set
 # CONFIG_FREEZER is not set
 
 #
@@ -168,8 +196,7 @@ CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
-CONFIG_HAVE_MLOCK=y
-CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+# CONFIG_KSM is not set
 CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_SUN_PM=y
 # CONFIG_SPARC_LED is not set
@@ -257,6 +284,7 @@ CONFIG_INET6_XFRM_MODE_TUNNEL=m
 CONFIG_INET6_XFRM_MODE_BEET=m
 # CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
 CONFIG_IPV6_SIT=m
+# CONFIG_IPV6_SIT_6RD is not set
 CONFIG_IPV6_NDISC_NODETYPE=y
 CONFIG_IPV6_TUNNEL=m
 # CONFIG_IPV6_MULTIPLE_TABLES is not set
@@ -295,9 +323,6 @@ CONFIG_NET_PKTGEN=m
 # CONFIG_AF_RXRPC is not set
 CONFIG_WIRELESS=y
 # CONFIG_CFG80211 is not set
-CONFIG_CFG80211_DEFAULT_PS_VALUE=0
-CONFIG_WIRELESS_OLD_REGULATORY=y
-# CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
 
 #
@@ -335,6 +360,10 @@ CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=m
 CONFIG_BLK_DEV_CRYPTOLOOP=m
+
+#
+# DRBD disabled because PROC_FS, INET or CONNECTOR not selected
+#
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_SX8 is not set
 CONFIG_BLK_DEV_RAM=y
@@ -398,8 +427,11 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_CXGB3_ISCSI is not set
 # CONFIG_SCSI_BNX2_ISCSI is not set
+# CONFIG_BE2ISCSI is not set
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_HPSA is not set
 # CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_3W_SAS is not set
 # CONFIG_SCSI_ACARD is not set
 # CONFIG_SCSI_AACRAID is not set
 # CONFIG_SCSI_AIC7XXX is not set
@@ -434,7 +466,9 @@ CONFIG_SCSI_QLOGICPTI=m
 # CONFIG_SCSI_DEBUG is not set
 CONFIG_SCSI_SUNESP=y
 # CONFIG_SCSI_PMCRAID is not set
+# CONFIG_SCSI_PM8001 is not set
 # CONFIG_SCSI_SRP is not set
+# CONFIG_SCSI_BFA_FC is not set
 # CONFIG_SCSI_DH is not set
 # CONFIG_SCSI_OSD_INITIATOR is not set
 # CONFIG_ATA is not set
@@ -450,7 +484,7 @@ CONFIG_SCSI_SUNESP=y
 #
 
 #
-# See the help texts for more information.
+# The newer stack is recommended.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
@@ -487,6 +521,7 @@ CONFIG_SUNQE=m
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
 # CONFIG_KS8842 is not set
+# CONFIG_KS8851_MLL is not set
 # CONFIG_ATL2 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
@@ -546,6 +581,7 @@ CONFIG_CHELSIO_T3_DEPENDS=y
 # CONFIG_NETCONSOLE is not set
 # CONFIG_NETPOLL is not set
 # CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_VMXNET3 is not set
 # CONFIG_ISDN is not set
 # CONFIG_PHONE is not set
 
@@ -555,6 +591,7 @@ CONFIG_CHELSIO_T3_DEPENDS=y
 CONFIG_INPUT=y
 # CONFIG_INPUT_FF_MEMLESS is not set
 # CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
 
 #
 # Userland interfaces
@@ -574,6 +611,7 @@ CONFIG_INPUT_KEYBOARD=y
 CONFIG_KEYBOARD_ATKBD=m
 # CONFIG_KEYBOARD_LKKBD is not set
 # CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_OPENCORES is not set
 # CONFIG_KEYBOARD_STOWAWAY is not set
 CONFIG_KEYBOARD_SUNKBD=m
 # CONFIG_KEYBOARD_XTKBD is not set
@@ -604,6 +642,7 @@ CONFIG_SERIO_SERPORT=m
 # CONFIG_SERIO_PCIPS2 is not set
 CONFIG_SERIO_LIBPS2=m
 # CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO_ALTERA_PS2 is not set
 # CONFIG_GAMEPORT is not set
 
 #
@@ -636,6 +675,7 @@ CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_CONSOLE_POLL=y
 # CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_GRLIB_GAISLER_APBUART is not set
 CONFIG_UNIX98_PTYS=y
 # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
 CONFIG_LEGACY_PTYS=y
@@ -661,6 +701,11 @@ CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_POWER_SUPPLY is not set
 CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Native drivers
+#
 # CONFIG_SENSORS_I5K_AMB is not set
 # CONFIG_SENSORS_F71805F is not set
 # CONFIG_SENSORS_F71882FG is not set
@@ -675,9 +720,7 @@ CONFIG_HWMON=y
 # CONFIG_SENSORS_VT8231 is not set
 # CONFIG_SENSORS_W83627HF is not set
 # CONFIG_SENSORS_W83627EHF is not set
-# CONFIG_HWMON_DEBUG_CHIP is not set
 # CONFIG_THERMAL is not set
-# CONFIG_THERMAL_HWMON is not set
 # CONFIG_WATCHDOG is not set
 CONFIG_SSB_POSSIBLE=y
 
@@ -699,6 +742,7 @@ CONFIG_SSB_POSSIBLE=y
 #
 # Graphics support
 #
+CONFIG_VGA_ARB=y
 # CONFIG_VGASTATE is not set
 # CONFIG_VIDEO_OUTPUT_CONTROL is not set
 # CONFIG_FB is not set
@@ -776,7 +820,9 @@ CONFIG_RTC_INTF_DEV=y
 # CONFIG_RTC_DRV_M48T86 is not set
 # CONFIG_RTC_DRV_M48T35 is not set
 CONFIG_RTC_DRV_M48T59=y
+# CONFIG_RTC_DRV_MSM6242 is not set
 # CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_RP5C01 is not set
 # CONFIG_RTC_DRV_V3020 is not set
 
 #
@@ -955,6 +1001,7 @@ CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_FRAME_WARN=1024
 CONFIG_MAGIC_SYSRQ=y
+# CONFIG_STRIP_ASM_SYMS is not set
 # CONFIG_UNUSED_SYMBOLS is not set
 # CONFIG_DEBUG_FS is not set
 # CONFIG_HEADERS_CHECK is not set
@@ -1003,9 +1050,9 @@ CONFIG_KGDB=y
 CONFIG_KGDB_SERIAL_CONSOLE=y
 CONFIG_KGDB_TESTS=y
 # CONFIG_KGDB_TESTS_ON_BOOT is not set
-# CONFIG_KMEMCHECK is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
 # CONFIG_STACK_DEBUG is not set
+# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set
 
 #
 # Security options
@@ -1013,7 +1060,11 @@ CONFIG_KGDB_TESTS=y
 # CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
 # CONFIG_SECURITYFS is not set
-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+# CONFIG_DEFAULT_SECURITY_SELINUX is not set
+# CONFIG_DEFAULT_SECURITY_SMACK is not set
+# CONFIG_DEFAULT_SECURITY_TOMOYO is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
 CONFIG_CRYPTO=y
 
 #
index f80b881..41c5a56 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.31
-# Tue Sep 15 17:06:03 2009
+# Linux kernel version: 2.6.33-rc2
+# Wed Jan 20 16:31:47 2010
 #
 CONFIG_64BIT=y
 CONFIG_SPARC=y
@@ -20,6 +20,7 @@ CONFIG_HAVE_LATENCYTOP_SUPPORT=y
 CONFIG_AUDIT_ARCH=y
 CONFIG_HAVE_SETUP_PER_CPU_AREA=y
 CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y
+CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y
 CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_MMU=y
 CONFIG_ARCH_NO_VIRT_TO_BUS=y
@@ -50,6 +51,7 @@ CONFIG_POSIX_MQUEUE_SYSCTL=y
 #
 CONFIG_TREE_RCU=y
 # CONFIG_TREE_PREEMPT_RCU is not set
+# CONFIG_TINY_RCU is not set
 # CONFIG_RCU_TRACE is not set
 CONFIG_RCU_FANOUT=64
 # CONFIG_RCU_FANOUT_EXACT is not set
@@ -62,8 +64,7 @@ CONFIG_RT_GROUP_SCHED=y
 CONFIG_USER_SCHED=y
 # CONFIG_CGROUP_SCHED is not set
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 CONFIG_RELAY=y
 CONFIG_NAMESPACES=y
 # CONFIG_UTS_NS is not set
@@ -97,24 +98,25 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
-CONFIG_HAVE_PERF_COUNTERS=y
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
 
 #
-# Performance Counters
+# Kernel Performance Events And Counters
 #
-CONFIG_PERF_COUNTERS=y
+CONFIG_PERF_EVENTS=y
 CONFIG_EVENT_PROFILE=y
+CONFIG_PERF_COUNTERS=y
+# CONFIG_DEBUG_PERF_USE_VMALLOC is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
-# CONFIG_STRIP_ASM_SYMS is not set
 # CONFIG_COMPAT_BRK is not set
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
 # CONFIG_SLOB is not set
 CONFIG_PROFILING=y
 CONFIG_TRACEPOINTS=y
-CONFIG_MARKERS=y
 CONFIG_OPROFILE=m
 CONFIG_HAVE_OPROFILE=y
 CONFIG_KPROBES=y
@@ -152,14 +154,41 @@ CONFIG_BLOCK_COMPAT=y
 # IO Schedulers
 #
 CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
 CONFIG_IOSCHED_DEADLINE=y
 CONFIG_IOSCHED_CFQ=y
-CONFIG_DEFAULT_AS=y
 # CONFIG_DEFAULT_DEADLINE is not set
-# CONFIG_DEFAULT_CFQ is not set
+CONFIG_DEFAULT_CFQ=y
 # CONFIG_DEFAULT_NOOP is not set
-CONFIG_DEFAULT_IOSCHED="anticipatory"
+CONFIG_DEFAULT_IOSCHED="cfq"
+# CONFIG_INLINE_SPIN_TRYLOCK is not set
+# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK is not set
+# CONFIG_INLINE_SPIN_LOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
+CONFIG_INLINE_SPIN_UNLOCK=y
+# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
+CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_READ_TRYLOCK is not set
+# CONFIG_INLINE_READ_LOCK is not set
+# CONFIG_INLINE_READ_LOCK_BH is not set
+# CONFIG_INLINE_READ_LOCK_IRQ is not set
+# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set
+CONFIG_INLINE_READ_UNLOCK=y
+# CONFIG_INLINE_READ_UNLOCK_BH is not set
+CONFIG_INLINE_READ_UNLOCK_IRQ=y
+# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_WRITE_TRYLOCK is not set
+# CONFIG_INLINE_WRITE_LOCK is not set
+# CONFIG_INLINE_WRITE_LOCK_BH is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set
+CONFIG_INLINE_WRITE_UNLOCK=y
+# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
+CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
+# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
+CONFIG_MUTEX_SPIN_ON_OWNER=y
 # CONFIG_FREEZER is not set
 
 #
@@ -179,6 +208,7 @@ CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_ARCH_MAY_HAVE_PC_FDC=y
 CONFIG_SPARC64_SMP=y
+CONFIG_EARLYFB=y
 CONFIG_SPARC64_PAGE_SIZE_8KB=y
 # CONFIG_SPARC64_PAGE_SIZE_64KB is not set
 CONFIG_SECCOMP=y
@@ -216,8 +246,7 @@ CONFIG_MIGRATION=y
 CONFIG_PHYS_ADDR_T_64BIT=y
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_NR_QUICK=1
-CONFIG_HAVE_MLOCK=y
-CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+# CONFIG_KSM is not set
 CONFIG_DEFAULT_MMAP_MIN_ADDR=8192
 CONFIG_SCHED_SMT=y
 CONFIG_SCHED_MC=y
@@ -315,6 +344,7 @@ CONFIG_INET6_XFRM_MODE_TUNNEL=m
 CONFIG_INET6_XFRM_MODE_BEET=m
 # CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
 CONFIG_IPV6_SIT=m
+# CONFIG_IPV6_SIT_6RD is not set
 CONFIG_IPV6_NDISC_NODETYPE=y
 CONFIG_IPV6_TUNNEL=m
 # CONFIG_IPV6_MULTIPLE_TABLES is not set
@@ -356,9 +386,6 @@ CONFIG_NET_TCPPROBE=m
 # CONFIG_AF_RXRPC is not set
 CONFIG_WIRELESS=y
 # CONFIG_CFG80211 is not set
-CONFIG_CFG80211_DEFAULT_PS_VALUE=0
-CONFIG_WIRELESS_OLD_REGULATORY=y
-# CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
 
 #
@@ -376,6 +403,7 @@ CONFIG_WIRELESS_OLD_REGULATORY=y
 # Generic Driver Options
 #
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_DEVTMPFS is not set
 CONFIG_STANDALONE=y
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 CONFIG_FW_LOADER=y
@@ -397,6 +425,11 @@ CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=m
 CONFIG_BLK_DEV_CRYPTOLOOP=m
+
+#
+# DRBD disabled because PROC_FS, INET or CONNECTOR not selected
+#
+# CONFIG_BLK_DEV_DRBD is not set
 CONFIG_BLK_DEV_NBD=m
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_UB is not set
@@ -408,6 +441,7 @@ CONFIG_ATA_OVER_ETH=m
 CONFIG_SUNVDC=m
 # CONFIG_BLK_DEV_HD is not set
 CONFIG_MISC_DEVICES=y
+# CONFIG_AD525X_DPOT is not set
 # CONFIG_PHANTOM is not set
 # CONFIG_SGI_IOC4 is not set
 # CONFIG_TIFM_CORE is not set
@@ -415,6 +449,7 @@ CONFIG_MISC_DEVICES=y
 # CONFIG_ENCLOSURE_SERVICES is not set
 # CONFIG_HP_ILO is not set
 # CONFIG_ISL29003 is not set
+# CONFIG_DS1682 is not set
 # CONFIG_C2PORT is not set
 
 #
@@ -522,8 +557,11 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_CXGB3_ISCSI is not set
 # CONFIG_SCSI_BNX2_ISCSI is not set
+# CONFIG_BE2ISCSI is not set
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_HPSA is not set
 # CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_3W_SAS is not set
 # CONFIG_SCSI_ACARD is not set
 # CONFIG_SCSI_AACRAID is not set
 # CONFIG_SCSI_AIC7XXX is not set
@@ -557,7 +595,9 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_DEBUG is not set
 # CONFIG_SCSI_SUNESP is not set
 # CONFIG_SCSI_PMCRAID is not set
+# CONFIG_SCSI_PM8001 is not set
 # CONFIG_SCSI_SRP is not set
+# CONFIG_SCSI_BFA_FC is not set
 # CONFIG_SCSI_DH is not set
 # CONFIG_SCSI_OSD_INITIATOR is not set
 # CONFIG_ATA is not set
@@ -568,7 +608,9 @@ CONFIG_MD_RAID0=m
 CONFIG_MD_RAID1=m
 CONFIG_MD_RAID10=m
 CONFIG_MD_RAID456=m
+# CONFIG_MULTICORE_RAID456 is not set
 CONFIG_MD_RAID6_PQ=m
+# CONFIG_ASYNC_RAID6_TEST is not set
 CONFIG_MD_MULTIPATH=m
 # CONFIG_MD_FAULTY is not set
 CONFIG_BLK_DEV_DM=m
@@ -592,7 +634,7 @@ CONFIG_DM_ZERO=m
 #
 
 #
-# See the help texts for more information.
+# The newer stack is recommended.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
@@ -664,6 +706,7 @@ CONFIG_NET_PCI=y
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
 # CONFIG_KS8842 is not set
+# CONFIG_KS8851_MLL is not set
 # CONFIG_VIA_RHINE is not set
 # CONFIG_SC92031 is not set
 # CONFIG_ATL2 is not set
@@ -745,6 +788,7 @@ CONFIG_SLHC=m
 # CONFIG_NETCONSOLE is not set
 # CONFIG_NETPOLL is not set
 # CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_VMXNET3 is not set
 # CONFIG_ISDN is not set
 # CONFIG_PHONE is not set
 
@@ -754,6 +798,7 @@ CONFIG_SLHC=m
 CONFIG_INPUT=y
 # CONFIG_INPUT_FF_MEMLESS is not set
 # CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
 
 #
 # Userland interfaces
@@ -770,9 +815,13 @@ CONFIG_INPUT_EVDEV=y
 # Input Device Drivers
 #
 CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ADP5588 is not set
 CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_QT2160 is not set
 CONFIG_KEYBOARD_LKKBD=m
+# CONFIG_KEYBOARD_MAX7359 is not set
 # CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_OPENCORES is not set
 # CONFIG_KEYBOARD_STOWAWAY is not set
 CONFIG_KEYBOARD_SUNKBD=y
 # CONFIG_KEYBOARD_XTKBD is not set
@@ -812,6 +861,7 @@ CONFIG_SERIO_I8042=y
 CONFIG_SERIO_PCIPS2=m
 CONFIG_SERIO_LIBPS2=y
 CONFIG_SERIO_RAW=m
+# CONFIG_SERIO_ALTERA_PS2 is not set
 # CONFIG_GAMEPORT is not set
 
 #
@@ -844,6 +894,7 @@ CONFIG_SERIAL_SUNHV=y
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_GRLIB_GAISLER_APBUART is not set
 CONFIG_UNIX98_PTYS=y
 # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
 # CONFIG_LEGACY_PTYS is not set
@@ -858,6 +909,7 @@ CONFIG_HW_RANDOM_N2RNG=m
 CONFIG_DEVPORT=y
 CONFIG_I2C=y
 CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
 # CONFIG_I2C_CHARDEV is not set
 CONFIG_I2C_HELPER_AUTO=y
 CONFIG_I2C_ALGOBIT=y
@@ -897,11 +949,6 @@ CONFIG_I2C_ALGOBIT=y
 # CONFIG_I2C_TAOS_EVM is not set
 # CONFIG_I2C_TINY_USB is not set
 
-#
-# Graphics adapter I2C/DDC channel drivers
-#
-# CONFIG_I2C_VOODOO3 is not set
-
 #
 # Other I2C/SMBus bus drivers
 #
@@ -911,10 +958,6 @@ CONFIG_I2C_ALGOBIT=y
 #
 # Miscellaneous I2C Chip support
 #
-# CONFIG_DS1682 is not set
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_PCF8575 is not set
-# CONFIG_SENSORS_PCA9539 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
@@ -932,6 +975,11 @@ CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_POWER_SUPPLY is not set
 CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Native drivers
+#
 # CONFIG_SENSORS_AD7414 is not set
 # CONFIG_SENSORS_AD7418 is not set
 # CONFIG_SENSORS_ADM1021 is not set
@@ -955,6 +1003,7 @@ CONFIG_HWMON=y
 # CONFIG_SENSORS_GL520SM is not set
 # CONFIG_SENSORS_IT87 is not set
 # CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM73 is not set
 # CONFIG_SENSORS_LM75 is not set
 # CONFIG_SENSORS_LM77 is not set
 # CONFIG_SENSORS_LM78 is not set
@@ -981,6 +1030,7 @@ CONFIG_HWMON=y
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
 # CONFIG_SENSORS_TMP401 is not set
+# CONFIG_SENSORS_TMP421 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -993,9 +1043,8 @@ CONFIG_HWMON=y
 # CONFIG_SENSORS_W83627HF is not set
 # CONFIG_SENSORS_W83627EHF is not set
 # CONFIG_SENSORS_ULTRA45 is not set
-# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_SENSORS_LIS3_I2C is not set
 # CONFIG_THERMAL is not set
-# CONFIG_THERMAL_HWMON is not set
 # CONFIG_WATCHDOG is not set
 CONFIG_SSB_POSSIBLE=y
 
@@ -1013,16 +1062,20 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_TWL4030_CORE is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_PMIC_DA903X is not set
+# CONFIG_PMIC_ADP5520 is not set
 # CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
 # CONFIG_AB3100_CORE is not set
+# CONFIG_MFD_88PM8607 is not set
 # CONFIG_REGULATOR is not set
 # CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
 #
+CONFIG_VGA_ARB=y
 # CONFIG_DRM is not set
 # CONFIG_VGASTATE is not set
 # CONFIG_VIDEO_OUTPUT_CONTROL is not set
@@ -1176,6 +1229,7 @@ CONFIG_SND_ALI5451=m
 # CONFIG_SND_OXYGEN is not set
 # CONFIG_SND_CS4281 is not set
 # CONFIG_SND_CS46XX is not set
+# CONFIG_SND_CS5535AUDIO is not set
 # CONFIG_SND_CTXFI is not set
 # CONFIG_SND_DARLA20 is not set
 # CONFIG_SND_GINA20 is not set
@@ -1311,6 +1365,7 @@ CONFIG_USB_EHCI_HCD=m
 # CONFIG_USB_OXU210HP_HCD is not set
 # CONFIG_USB_ISP116X_HCD is not set
 # CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
 CONFIG_USB_OHCI_HCD=y
 # CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
 # CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
@@ -1426,6 +1481,7 @@ CONFIG_RTC_INTF_DEV=y
 # CONFIG_RTC_DRV_PCF8563 is not set
 # CONFIG_RTC_DRV_PCF8583 is not set
 # CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_BQ32K is not set
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
@@ -1447,7 +1503,9 @@ CONFIG_RTC_DRV_CMOS=y
 # CONFIG_RTC_DRV_M48T86 is not set
 # CONFIG_RTC_DRV_M48T35 is not set
 CONFIG_RTC_DRV_M48T59=y
+# CONFIG_RTC_DRV_MSM6242 is not set
 CONFIG_RTC_DRV_BQ4802=y
+# CONFIG_RTC_DRV_RP5C01 is not set
 # CONFIG_RTC_DRV_V3020 is not set
 
 #
@@ -1625,6 +1683,7 @@ CONFIG_PRINTK_TIME=y
 CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_FRAME_WARN=2048
 CONFIG_MAGIC_SYSRQ=y
+# CONFIG_STRIP_ASM_SYMS is not set
 # CONFIG_UNUSED_SYMBOLS is not set
 CONFIG_DEBUG_FS=y
 # CONFIG_HEADERS_CHECK is not set
@@ -1678,9 +1737,11 @@ CONFIG_NOP_TRACER=y
 CONFIG_HAVE_FUNCTION_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
 CONFIG_RING_BUFFER=y
 CONFIG_EVENT_TRACING=y
 CONFIG_CONTEXT_SWITCH_TRACER=y
+CONFIG_RING_BUFFER_ALLOW_SWAP=y
 CONFIG_TRACING=y
 CONFIG_GENERIC_TRACER=y
 CONFIG_TRACING_SUPPORT=y
@@ -1688,6 +1749,7 @@ CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
 # CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
+# CONFIG_FTRACE_SYSCALLS is not set
 # CONFIG_BOOT_TRACER is not set
 CONFIG_BRANCH_PROFILE_NONE=y
 # CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
@@ -1706,6 +1768,7 @@ CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_DEBUG_STACK_USAGE is not set
 # CONFIG_DEBUG_DCFLUSH is not set
 # CONFIG_STACK_DEBUG is not set
+# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set
 
 #
 # Security options
@@ -1714,11 +1777,17 @@ CONFIG_KEYS=y
 # CONFIG_KEYS_DEBUG_PROC_KEYS is not set
 # CONFIG_SECURITY is not set
 # CONFIG_SECURITYFS is not set
-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+# CONFIG_DEFAULT_SECURITY_SELINUX is not set
+# CONFIG_DEFAULT_SECURITY_SMACK is not set
+# CONFIG_DEFAULT_SECURITY_TOMOYO is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
 CONFIG_XOR_BLOCKS=m
 CONFIG_ASYNC_CORE=m
 CONFIG_ASYNC_MEMCPY=m
 CONFIG_ASYNC_XOR=m
+CONFIG_ASYNC_PQ=m
+CONFIG_ASYNC_RAID6_RECOV=m
 CONFIG_CRYPTO=y
 
 #
index 93fe21e..679c750 100644 (file)
@@ -8,7 +8,7 @@
 #include <asm/page.h>      /* IO address mapping routines need this */
 #include <asm/system.h>
 
-#define page_to_phys(page)     (((page) - mem_map) << PAGE_SHIFT)
+#define page_to_phys(page)     (page_to_pfn(page) << PAGE_SHIFT)
 
 static inline u32 flip_dword (u32 l)
 {
index f72080b..156707b 100644 (file)
@@ -143,7 +143,7 @@ extern unsigned long pfn_base;
 #define phys_to_virt           __va
 
 #define ARCH_PFN_OFFSET                (pfn_base)
-#define virt_to_page(kaddr)    (mem_map + ((((unsigned long)(kaddr)-PAGE_OFFSET)>>PAGE_SHIFT)))
+#define virt_to_page(kaddr)    pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
 
 #define pfn_valid(pfn)         (((pfn) >= (pfn_base)) && (((pfn)-(pfn_base)) < max_mapnr))
 #define virt_addr_valid(kaddr) ((((unsigned long)(kaddr)-PAGE_OFFSET)>>PAGE_SHIFT) < max_mapnr)
index 9836d9a..0bc356b 100644 (file)
@@ -1,22 +1,7 @@
 #ifndef _ASMSPARC_PARAM_H
 #define _ASMSPARC_PARAM_H
 
-#ifdef __KERNEL__
-# define HZ            CONFIG_HZ       /* Internal kernel timer frequency */
-# define USER_HZ       100     /* .. some user interfaces are in "ticks" */
-# define CLOCKS_PER_SEC (USER_HZ)
-#endif
-
-#ifndef HZ
-#define HZ 100
-#endif
-
 #define EXEC_PAGESIZE  8192    /* Thanks for sun4's we carry baggage... */
+#include <asm-generic/param.h>
 
-#ifndef NOGROUP
-#define NOGROUP                (-1)
-#endif
-
-#define MAXHOSTNAMELEN 64      /* max length of hostname */
-
-#endif
+#endif /* _ASMSPARC_PARAM_H */
index b6ccdb0..a254750 100644 (file)
@@ -12,4 +12,5 @@
 typedef unsigned long cycles_t;
 #define get_cycles()   (0)
 
+extern u32 (*do_arch_gettimeoffset)(void);
 #endif
index 600a790..1c79f32 100644 (file)
@@ -12,7 +12,9 @@ static inline int cpu_to_node(int cpu)
 
 #define parent_node(node)      (node)
 
-#define cpumask_of_node(node) (&numa_cpumask_lookup_table[node])
+#define cpumask_of_node(node) ((node) == -1 ?                          \
+                              cpu_all_mask :                           \
+                              &numa_cpumask_lookup_table[node])
 
 struct pci_bus;
 #ifdef CONFIG_PCI
index 489d2ba..25f1d10 100644 (file)
@@ -274,7 +274,7 @@ static inline unsigned long copy_from_user(void *to, const void __user *from, un
 
        if (unlikely(sz != -1 && sz < n)) {
                copy_from_user_overflow();
-               return -EFAULT;
+               return n;
        }
 
        if (n && __access_ok((unsigned long) from, n))
index dbc1416..2406788 100644 (file)
@@ -221,8 +221,8 @@ extern unsigned long copy_from_user_fixup(void *to, const void __user *from,
 static inline unsigned long __must_check
 copy_from_user(void *to, const void __user *from, unsigned long size)
 {
-       unsigned long ret = (unsigned long) -EFAULT;
        int sz = __compiletime_object_size(to);
+       unsigned long ret = size;
 
        if (likely(sz == -1 || sz >= size)) {
                ret = ___copy_from_user(to, from, size);
index f3b5466..4589ca3 100644 (file)
@@ -99,7 +99,7 @@ static int __devinit clock_board_probe(struct of_device *op,
 
        p->leds_resource.start = (unsigned long)
                (p->clock_regs + CLOCK_CTRL);
-       p->leds_resource.end = p->leds_resource.end;
+       p->leds_resource.end = p->leds_resource.start;
        p->leds_resource.name = "leds";
 
        p->leds_pdev.name = "sunfire-clockboard-leds";
@@ -194,7 +194,7 @@ static int __devinit fhc_probe(struct of_device *op,
        if (!p->central) {
                p->leds_resource.start = (unsigned long)
                        (p->pregs + FHC_PREGS_CTRL);
-               p->leds_resource.end = p->leds_resource.end;
+               p->leds_resource.end = p->leds_resource.start;
                p->leds_resource.name = "leds";
 
                p->leds_pdev.name = "sunfire-fhc-leds";
index 8d6882b..f2179cc 100644 (file)
@@ -250,12 +250,12 @@ struct irq_handler_data {
 };
 
 #ifdef CONFIG_SMP
-static int irq_choose_cpu(unsigned int virt_irq)
+static int irq_choose_cpu(unsigned int virt_irq, const struct cpumask *affinity)
 {
        cpumask_t mask;
        int cpuid;
 
-       cpumask_copy(&mask, irq_desc[virt_irq].affinity);
+       cpumask_copy(&mask, affinity);
        if (cpus_equal(mask, cpu_online_map)) {
                cpuid = map_to_cpu(virt_irq);
        } else {
@@ -268,7 +268,7 @@ static int irq_choose_cpu(unsigned int virt_irq)
        return cpuid;
 }
 #else
-static int irq_choose_cpu(unsigned int virt_irq)
+static int irq_choose_cpu(unsigned int virt_irq, const struct cpumask *affinity)
 {
        return real_hard_smp_processor_id();
 }
@@ -282,7 +282,8 @@ static void sun4u_irq_enable(unsigned int virt_irq)
                unsigned long cpuid, imap, val;
                unsigned int tid;
 
-               cpuid = irq_choose_cpu(virt_irq);
+               cpuid = irq_choose_cpu(virt_irq,
+                                      irq_desc[virt_irq].affinity);
                imap = data->imap;
 
                tid = sun4u_compute_tid(imap, cpuid);
@@ -299,7 +300,24 @@ static void sun4u_irq_enable(unsigned int virt_irq)
 static int sun4u_set_affinity(unsigned int virt_irq,
                               const struct cpumask *mask)
 {
-       sun4u_irq_enable(virt_irq);
+       struct irq_handler_data *data = get_irq_chip_data(virt_irq);
+
+       if (likely(data)) {
+               unsigned long cpuid, imap, val;
+               unsigned int tid;
+
+               cpuid = irq_choose_cpu(virt_irq, mask);
+               imap = data->imap;
+
+               tid = sun4u_compute_tid(imap, cpuid);
+
+               val = upa_readq(imap);
+               val &= ~(IMAP_TID_UPA | IMAP_TID_JBUS |
+                        IMAP_AID_SAFARI | IMAP_NID_SAFARI);
+               val |= tid | IMAP_VALID;
+               upa_writeq(val, imap);
+               upa_writeq(ICLR_IDLE, data->iclr);
+       }
 
        return 0;
 }
@@ -340,7 +358,8 @@ static void sun4u_irq_eoi(unsigned int virt_irq)
 static void sun4v_irq_enable(unsigned int virt_irq)
 {
        unsigned int ino = virt_irq_table[virt_irq].dev_ino;
-       unsigned long cpuid = irq_choose_cpu(virt_irq);
+       unsigned long cpuid = irq_choose_cpu(virt_irq,
+                                            irq_desc[virt_irq].affinity);
        int err;
 
        err = sun4v_intr_settarget(ino, cpuid);
@@ -361,7 +380,7 @@ static int sun4v_set_affinity(unsigned int virt_irq,
                               const struct cpumask *mask)
 {
        unsigned int ino = virt_irq_table[virt_irq].dev_ino;
-       unsigned long cpuid = irq_choose_cpu(virt_irq);
+       unsigned long cpuid = irq_choose_cpu(virt_irq, mask);
        int err;
 
        err = sun4v_intr_settarget(ino, cpuid);
@@ -403,7 +422,7 @@ static void sun4v_virq_enable(unsigned int virt_irq)
        unsigned long cpuid, dev_handle, dev_ino;
        int err;
 
-       cpuid = irq_choose_cpu(virt_irq);
+       cpuid = irq_choose_cpu(virt_irq, irq_desc[virt_irq].affinity);
 
        dev_handle = virt_irq_table[virt_irq].dev_handle;
        dev_ino = virt_irq_table[virt_irq].dev_ino;
@@ -433,7 +452,7 @@ static int sun4v_virt_set_affinity(unsigned int virt_irq,
        unsigned long cpuid, dev_handle, dev_ino;
        int err;
 
-       cpuid = irq_choose_cpu(virt_irq);
+       cpuid = irq_choose_cpu(virt_irq, mask);
 
        dev_handle = virt_irq_table[virt_irq].dev_handle;
        dev_ino = virt_irq_table[virt_irq].dev_ino;
index 85e7037..4e2724e 100644 (file)
@@ -30,6 +30,7 @@
 #include <asm/oplib.h>
 #include <asm/prom.h>
 #include <asm/pcic.h>
+#include <asm/timex.h>
 #include <asm/timer.h>
 #include <asm/uaccess.h>
 #include <asm/irq_regs.h>
@@ -163,8 +164,6 @@ void __iomem *pcic_regs;
 volatile int pcic_speculative;
 volatile int pcic_trapped;
 
-static void pci_do_gettimeofday(struct timeval *tv);
-static int pci_do_settimeofday(struct timespec *tv);
 
 #define CONFIG_CMD(bus, device_fn, where) (0x80000000 | (((unsigned int)bus) << 16) | (((unsigned int)device_fn) << 8) | (where & ~3))
 
@@ -716,19 +715,27 @@ static irqreturn_t pcic_timer_handler (int irq, void *h)
 #define USECS_PER_JIFFY  10000  /* We have 100HZ "standard" timer for sparc */
 #define TICK_TIMER_LIMIT ((100*1000000/4)/100)
 
+u32 pci_gettimeoffset(void)
+{
+       /*
+        * We divide all by 100
+        * to have microsecond resolution and to avoid overflow
+        */
+       unsigned long count =
+           readl(pcic0.pcic_regs+PCI_SYS_COUNTER) & ~PCI_SYS_COUNTER_OVERFLOW;
+       count = ((count/100)*USECS_PER_JIFFY) / (TICK_TIMER_LIMIT/100);
+       return count * 1000;
+}
+
+
 void __init pci_time_init(void)
 {
        struct linux_pcic *pcic = &pcic0;
        unsigned long v;
        int timer_irq, irq;
 
-       /* A hack until do_gettimeofday prototype is moved to arch specific headers
-          and btfixupped. Patch do_gettimeofday with ba pci_do_gettimeofday; nop */
-       ((unsigned int *)do_gettimeofday)[0] = 
-           0x10800000 | ((((unsigned long)pci_do_gettimeofday -
-            (unsigned long)do_gettimeofday) >> 2) & 0x003fffff);
-       ((unsigned int *)do_gettimeofday)[1] = 0x01000000;
-       BTFIXUPSET_CALL(bus_do_settimeofday, pci_do_settimeofday, BTFIXUPCALL_NORM);
+       do_arch_gettimeoffset = pci_gettimeoffset;
+
        btfixup();
 
        writel (TICK_TIMER_LIMIT, pcic->pcic_regs+PCI_SYS_LIMIT);
@@ -746,84 +753,6 @@ void __init pci_time_init(void)
        local_irq_enable();
 }
 
-static inline unsigned long do_gettimeoffset(void)
-{
-       /*
-        * We divide all by 100
-        * to have microsecond resolution and to avoid overflow
-        */
-       unsigned long count =
-           readl(pcic0.pcic_regs+PCI_SYS_COUNTER) & ~PCI_SYS_COUNTER_OVERFLOW;
-       count = ((count/100)*USECS_PER_JIFFY) / (TICK_TIMER_LIMIT/100);
-       return count;
-}
-
-static void pci_do_gettimeofday(struct timeval *tv)
-{
-       unsigned long flags;
-       unsigned long seq;
-       unsigned long usec, sec;
-       unsigned long max_ntp_tick = tick_usec - tickadj;
-
-       do {
-               seq = read_seqbegin_irqsave(&xtime_lock, flags);
-               usec = do_gettimeoffset();
-
-               /*
-                * If time_adjust is negative then NTP is slowing the clock
-                * so make sure not to go into next possible interval.
-                * Better to lose some accuracy than have time go backwards..
-                */
-               if (unlikely(time_adjust < 0))
-                       usec = min(usec, max_ntp_tick);
-
-               sec = xtime.tv_sec;
-               usec += (xtime.tv_nsec / 1000);
-       } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
-
-       while (usec >= 1000000) {
-               usec -= 1000000;
-               sec++;
-       }
-
-       tv->tv_sec = sec;
-       tv->tv_usec = usec;
-}
-
-static int pci_do_settimeofday(struct timespec *tv)
-{
-       if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
-               return -EINVAL;
-
-       /*
-        * This is revolting. We need to set "xtime" correctly. However, the
-        * value in this location is the value at the most recent update of
-        * wall time.  Discover what correction gettimeofday() would have
-        * made, and then undo it!
-        */
-       tv->tv_nsec -= 1000 * do_gettimeoffset();
-       while (tv->tv_nsec < 0) {
-               tv->tv_nsec += NSEC_PER_SEC;
-               tv->tv_sec--;
-       }
-
-       wall_to_monotonic.tv_sec += xtime.tv_sec - tv->tv_sec;
-       wall_to_monotonic.tv_nsec += xtime.tv_nsec - tv->tv_nsec;
-
-       if (wall_to_monotonic.tv_nsec > NSEC_PER_SEC) {
-               wall_to_monotonic.tv_nsec -= NSEC_PER_SEC;
-               wall_to_monotonic.tv_sec++;
-       }
-       if (wall_to_monotonic.tv_nsec < 0) {
-               wall_to_monotonic.tv_nsec += NSEC_PER_SEC;
-               wall_to_monotonic.tv_sec--;
-       }
-
-       xtime.tv_sec = tv->tv_sec;
-       xtime.tv_nsec = tv->tv_nsec;
-       ntp_clear();
-       return 0;
-}
 
 #if 0
 static void watchdog_reset() {
index 198fb4e..e856456 100644 (file)
@@ -1,6 +1,6 @@
 /* Performance event support for sparc64.
  *
- * Copyright (C) 2009 David S. Miller <davem@davemloft.net>
+ * Copyright (C) 2009, 2010 David S. Miller <davem@davemloft.net>
  *
  * This code is based almost entirely upon the x86 perf event
  * code, which is:
 #include <linux/kdebug.h>
 #include <linux/mutex.h>
 
+#include <asm/stacktrace.h>
 #include <asm/cpudata.h>
+#include <asm/uaccess.h>
 #include <asm/atomic.h>
 #include <asm/nmi.h>
 #include <asm/pcr.h>
 
+#include "kstack.h"
+
 /* Sparc64 chips have two performance counters, 32-bits each, with
  * overflow interrupts generated on transition from 0xffffffff to 0.
  * The counters are accessed in one go using a 64-bit register.
 
 #define PIC_UPPER_INDEX                        0
 #define PIC_LOWER_INDEX                        1
+#define PIC_NO_INDEX                   -1
 
 struct cpu_hw_events {
-       struct perf_event       *events[MAX_HWEVENTS];
-       unsigned long           used_mask[BITS_TO_LONGS(MAX_HWEVENTS)];
-       unsigned long           active_mask[BITS_TO_LONGS(MAX_HWEVENTS)];
+       /* Number of events currently scheduled onto this cpu.
+        * This tells how many entries in the arrays below
+        * are valid.
+        */
+       int                     n_events;
+
+       /* Number of new events added since the last hw_perf_disable().
+        * This works because the perf event layer always adds new
+        * events inside of a perf_{disable,enable}() sequence.
+        */
+       int                     n_added;
+
+       /* Array of events current scheduled on this cpu.  */
+       struct perf_event       *event[MAX_HWEVENTS];
+
+       /* Array of encoded longs, specifying the %pcr register
+        * encoding and the mask of PIC counters this even can
+        * be scheduled on.  See perf_event_encode() et al.
+        */
+       unsigned long           events[MAX_HWEVENTS];
+
+       /* The current counter index assigned to an event.  When the
+        * event hasn't been programmed into the cpu yet, this will
+        * hold PIC_NO_INDEX.  The event->hw.idx value tells us where
+        * we ought to schedule the event.
+        */
+       int                     current_idx[MAX_HWEVENTS];
+
+       /* Software copy of %pcr register on this cpu.  */
        u64                     pcr;
+
+       /* Enabled/disable state.  */
        int                     enabled;
 };
 DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events) = { .enabled = 1, };
 
+/* An event map describes the characteristics of a performance
+ * counter event.  In particular it gives the encoding as well as
+ * a mask telling which counters the event can be measured on.
+ */
 struct perf_event_map {
        u16     encoding;
        u8      pic_mask;
@@ -69,15 +106,20 @@ struct perf_event_map {
 #define PIC_LOWER      0x02
 };
 
+/* Encode a perf_event_map entry into a long.  */
 static unsigned long perf_event_encode(const struct perf_event_map *pmap)
 {
        return ((unsigned long) pmap->encoding << 16) | pmap->pic_mask;
 }
 
-static void perf_event_decode(unsigned long val, u16 *enc, u8 *msk)
+static u8 perf_event_get_msk(unsigned long val)
 {
-       *msk = val & 0xff;
-       *enc = val >> 16;
+       return val & 0xff;
+}
+
+static u64 perf_event_get_enc(unsigned long val)
+{
+       return val >> 16;
 }
 
 #define C(x) PERF_COUNT_HW_CACHE_##x
@@ -491,53 +533,6 @@ static inline void sparc_pmu_disable_event(struct cpu_hw_events *cpuc, struct hw
        pcr_ops->write(cpuc->pcr);
 }
 
-void hw_perf_enable(void)
-{
-       struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
-       u64 val;
-       int i;
-
-       if (cpuc->enabled)
-               return;
-
-       cpuc->enabled = 1;
-       barrier();
-
-       val = cpuc->pcr;
-
-       for (i = 0; i < MAX_HWEVENTS; i++) {
-               struct perf_event *cp = cpuc->events[i];
-               struct hw_perf_event *hwc;
-
-               if (!cp)
-                       continue;
-               hwc = &cp->hw;
-               val |= hwc->config_base;
-       }
-
-       cpuc->pcr = val;
-
-       pcr_ops->write(cpuc->pcr);
-}
-
-void hw_perf_disable(void)
-{
-       struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
-       u64 val;
-
-       if (!cpuc->enabled)
-               return;
-
-       cpuc->enabled = 0;
-
-       val = cpuc->pcr;
-       val &= ~(PCR_UTRACE | PCR_STRACE |
-                sparc_pmu->hv_bit | sparc_pmu->irq_bit);
-       cpuc->pcr = val;
-
-       pcr_ops->write(cpuc->pcr);
-}
-
 static u32 read_pmc(int idx)
 {
        u64 val;
@@ -566,6 +561,30 @@ static void write_pmc(int idx, u64 val)
        write_pic(pic);
 }
 
+static u64 sparc_perf_event_update(struct perf_event *event,
+                                  struct hw_perf_event *hwc, int idx)
+{
+       int shift = 64 - 32;
+       u64 prev_raw_count, new_raw_count;
+       s64 delta;
+
+again:
+       prev_raw_count = atomic64_read(&hwc->prev_count);
+       new_raw_count = read_pmc(idx);
+
+       if (atomic64_cmpxchg(&hwc->prev_count, prev_raw_count,
+                            new_raw_count) != prev_raw_count)
+               goto again;
+
+       delta = (new_raw_count << shift) - (prev_raw_count << shift);
+       delta >>= shift;
+
+       atomic64_add(delta, &event->count);
+       atomic64_sub(delta, &hwc->period_left);
+
+       return new_raw_count;
+}
+
 static int sparc_perf_event_set_period(struct perf_event *event,
                                       struct hw_perf_event *hwc, int idx)
 {
@@ -598,81 +617,166 @@ static int sparc_perf_event_set_period(struct perf_event *event,
        return ret;
 }
 
-static int sparc_pmu_enable(struct perf_event *event)
+/* If performance event entries have been added, move existing
+ * events around (if necessary) and then assign new entries to
+ * counters.
+ */
+static u64 maybe_change_configuration(struct cpu_hw_events *cpuc, u64 pcr)
 {
-       struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
-       struct hw_perf_event *hwc = &event->hw;
-       int idx = hwc->idx;
+       int i;
 
-       if (test_and_set_bit(idx, cpuc->used_mask))
-               return -EAGAIN;
+       if (!cpuc->n_added)
+               goto out;
 
-       sparc_pmu_disable_event(cpuc, hwc, idx);
+       /* Read in the counters which are moving.  */
+       for (i = 0; i < cpuc->n_events; i++) {
+               struct perf_event *cp = cpuc->event[i];
 
-       cpuc->events[idx] = event;
-       set_bit(idx, cpuc->active_mask);
+               if (cpuc->current_idx[i] != PIC_NO_INDEX &&
+                   cpuc->current_idx[i] != cp->hw.idx) {
+                       sparc_perf_event_update(cp, &cp->hw,
+                                               cpuc->current_idx[i]);
+                       cpuc->current_idx[i] = PIC_NO_INDEX;
+               }
+       }
 
-       sparc_perf_event_set_period(event, hwc, idx);
-       sparc_pmu_enable_event(cpuc, hwc, idx);
-       perf_event_update_userpage(event);
-       return 0;
+       /* Assign to counters all unassigned events.  */
+       for (i = 0; i < cpuc->n_events; i++) {
+               struct perf_event *cp = cpuc->event[i];
+               struct hw_perf_event *hwc = &cp->hw;
+               int idx = hwc->idx;
+               u64 enc;
+
+               if (cpuc->current_idx[i] != PIC_NO_INDEX)
+                       continue;
+
+               sparc_perf_event_set_period(cp, hwc, idx);
+               cpuc->current_idx[i] = idx;
+
+               enc = perf_event_get_enc(cpuc->events[i]);
+               pcr |= event_encoding(enc, idx);
+       }
+out:
+       return pcr;
 }
 
-static u64 sparc_perf_event_update(struct perf_event *event,
-                                  struct hw_perf_event *hwc, int idx)
+void hw_perf_enable(void)
 {
-       int shift = 64 - 32;
-       u64 prev_raw_count, new_raw_count;
-       s64 delta;
+       struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+       u64 pcr;
 
-again:
-       prev_raw_count = atomic64_read(&hwc->prev_count);
-       new_raw_count = read_pmc(idx);
+       if (cpuc->enabled)
+               return;
 
-       if (atomic64_cmpxchg(&hwc->prev_count, prev_raw_count,
-                            new_raw_count) != prev_raw_count)
-               goto again;
+       cpuc->enabled = 1;
+       barrier();
 
-       delta = (new_raw_count << shift) - (prev_raw_count << shift);
-       delta >>= shift;
+       pcr = cpuc->pcr;
+       if (!cpuc->n_events) {
+               pcr = 0;
+       } else {
+               pcr = maybe_change_configuration(cpuc, pcr);
 
-       atomic64_add(delta, &event->count);
-       atomic64_sub(delta, &hwc->period_left);
+               /* We require that all of the events have the same
+                * configuration, so just fetch the settings from the
+                * first entry.
+                */
+               cpuc->pcr = pcr | cpuc->event[0]->hw.config_base;
+       }
 
-       return new_raw_count;
+       pcr_ops->write(cpuc->pcr);
+}
+
+void hw_perf_disable(void)
+{
+       struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+       u64 val;
+
+       if (!cpuc->enabled)
+               return;
+
+       cpuc->enabled = 0;
+       cpuc->n_added = 0;
+
+       val = cpuc->pcr;
+       val &= ~(PCR_UTRACE | PCR_STRACE |
+                sparc_pmu->hv_bit | sparc_pmu->irq_bit);
+       cpuc->pcr = val;
+
+       pcr_ops->write(cpuc->pcr);
 }
 
 static void sparc_pmu_disable(struct perf_event *event)
 {
        struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
        struct hw_perf_event *hwc = &event->hw;
-       int idx = hwc->idx;
+       unsigned long flags;
+       int i;
 
-       clear_bit(idx, cpuc->active_mask);
-       sparc_pmu_disable_event(cpuc, hwc, idx);
+       local_irq_save(flags);
+       perf_disable();
+
+       for (i = 0; i < cpuc->n_events; i++) {
+               if (event == cpuc->event[i]) {
+                       int idx = cpuc->current_idx[i];
+
+                       /* Shift remaining entries down into
+                        * the existing slot.
+                        */
+                       while (++i < cpuc->n_events) {
+                               cpuc->event[i - 1] = cpuc->event[i];
+                               cpuc->events[i - 1] = cpuc->events[i];
+                               cpuc->current_idx[i - 1] =
+                                       cpuc->current_idx[i];
+                       }
+
+                       /* Absorb the final count and turn off the
+                        * event.
+                        */
+                       sparc_pmu_disable_event(cpuc, hwc, idx);
+                       barrier();
+                       sparc_perf_event_update(event, hwc, idx);
 
-       barrier();
+                       perf_event_update_userpage(event);
 
-       sparc_perf_event_update(event, hwc, idx);
-       cpuc->events[idx] = NULL;
-       clear_bit(idx, cpuc->used_mask);
+                       cpuc->n_events--;
+                       break;
+               }
+       }
 
-       perf_event_update_userpage(event);
+       perf_enable();
+       local_irq_restore(flags);
+}
+
+static int active_event_index(struct cpu_hw_events *cpuc,
+                             struct perf_event *event)
+{
+       int i;
+
+       for (i = 0; i < cpuc->n_events; i++) {
+               if (cpuc->event[i] == event)
+                       break;
+       }
+       BUG_ON(i == cpuc->n_events);
+       return cpuc->current_idx[i];
 }
 
 static void sparc_pmu_read(struct perf_event *event)
 {
+       struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+       int idx = active_event_index(cpuc, event);
        struct hw_perf_event *hwc = &event->hw;
 
-       sparc_perf_event_update(event, hwc, hwc->idx);
+       sparc_perf_event_update(event, hwc, idx);
 }
 
 static void sparc_pmu_unthrottle(struct perf_event *event)
 {
        struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+       int idx = active_event_index(cpuc, event);
        struct hw_perf_event *hwc = &event->hw;
 
-       sparc_pmu_enable_event(cpuc, hwc, hwc->idx);
+       sparc_pmu_enable_event(cpuc, hwc, idx);
 }
 
 static atomic_t active_events = ATOMIC_INIT(0);
@@ -750,43 +854,75 @@ static void hw_perf_event_destroy(struct perf_event *event)
 /* Make sure all events can be scheduled into the hardware at
  * the same time.  This is simplified by the fact that we only
  * need to support 2 simultaneous HW events.
+ *
+ * As a side effect, the evts[]->hw.idx values will be assigned
+ * on success.  These are pending indexes.  When the events are
+ * actually programmed into the chip, these values will propagate
+ * to the per-cpu cpuc->current_idx[] slots, see the code in
+ * maybe_change_configuration() for details.
  */
-static int sparc_check_constraints(unsigned long *events, int n_ev)
+static int sparc_check_constraints(struct perf_event **evts,
+                                  unsigned long *events, int n_ev)
 {
-       if (n_ev <= perf_max_events) {
-               u8 msk1, msk2;
-               u16 dummy;
-
-               if (n_ev == 1)
-                       return 0;
-               BUG_ON(n_ev != 2);
-               perf_event_decode(events[0], &dummy, &msk1);
-               perf_event_decode(events[1], &dummy, &msk2);
-
-               /* If both events can go on any counter, OK.  */
-               if (msk1 == (PIC_UPPER | PIC_LOWER) &&
-                   msk2 == (PIC_UPPER | PIC_LOWER))
-                       return 0;
-
-               /* If one event is limited to a specific counter,
-                * and the other can go on both, OK.
-                */
-               if ((msk1 == PIC_UPPER || msk1 == PIC_LOWER) &&
-                   msk2 == (PIC_UPPER | PIC_LOWER))
-                       return 0;
-               if ((msk2 == PIC_UPPER || msk2 == PIC_LOWER) &&
-                   msk1 == (PIC_UPPER | PIC_LOWER))
-                       return 0;
-
-               /* If the events are fixed to different counters, OK.  */
-               if ((msk1 == PIC_UPPER && msk2 == PIC_LOWER) ||
-                   (msk1 == PIC_LOWER && msk2 == PIC_UPPER))
-                       return 0;
-
-               /* Otherwise, there is a conflict.  */
+       u8 msk0 = 0, msk1 = 0;
+       int idx0 = 0;
+
+       /* This case is possible when we are invoked from
+        * hw_perf_group_sched_in().
+        */
+       if (!n_ev)
+               return 0;
+
+       if (n_ev > perf_max_events)
+               return -1;
+
+       msk0 = perf_event_get_msk(events[0]);
+       if (n_ev == 1) {
+               if (msk0 & PIC_LOWER)
+                       idx0 = 1;
+               goto success;
        }
+       BUG_ON(n_ev != 2);
+       msk1 = perf_event_get_msk(events[1]);
+
+       /* If both events can go on any counter, OK.  */
+       if (msk0 == (PIC_UPPER | PIC_LOWER) &&
+           msk1 == (PIC_UPPER | PIC_LOWER))
+               goto success;
 
+       /* If one event is limited to a specific counter,
+        * and the other can go on both, OK.
+        */
+       if ((msk0 == PIC_UPPER || msk0 == PIC_LOWER) &&
+           msk1 == (PIC_UPPER | PIC_LOWER)) {
+               if (msk0 & PIC_LOWER)
+                       idx0 = 1;
+               goto success;
+       }
+
+       if ((msk1 == PIC_UPPER || msk1 == PIC_LOWER) &&
+           msk0 == (PIC_UPPER | PIC_LOWER)) {
+               if (msk1 & PIC_UPPER)
+                       idx0 = 1;
+               goto success;
+       }
+
+       /* If the events are fixed to different counters, OK.  */
+       if ((msk0 == PIC_UPPER && msk1 == PIC_LOWER) ||
+           (msk0 == PIC_LOWER && msk1 == PIC_UPPER)) {
+               if (msk0 & PIC_LOWER)
+                       idx0 = 1;
+               goto success;
+       }
+
+       /* Otherwise, there is a conflict.  */
        return -1;
+
+success:
+       evts[0]->hw.idx = idx0;
+       if (n_ev == 2)
+               evts[1]->hw.idx = idx0 ^ 1;
+       return 0;
 }
 
 static int check_excludes(struct perf_event **evts, int n_prev, int n_new)
@@ -818,7 +954,8 @@ static int check_excludes(struct perf_event **evts, int n_prev, int n_new)
 }
 
 static int collect_events(struct perf_event *group, int max_count,
-                         struct perf_event *evts[], unsigned long *events)
+                         struct perf_event *evts[], unsigned long *events,
+                         int *current_idx)
 {
        struct perf_event *event;
        int n = 0;
@@ -827,7 +964,8 @@ static int collect_events(struct perf_event *group, int max_count,
                if (n >= max_count)
                        return -1;
                evts[n] = group;
-               events[n++] = group->hw.event_base;
+               events[n] = group->hw.event_base;
+               current_idx[n++] = PIC_NO_INDEX;
        }
        list_for_each_entry(event, &group->sibling_list, group_entry) {
                if (!is_software_event(event) &&
@@ -835,20 +973,100 @@ static int collect_events(struct perf_event *group, int max_count,
                        if (n >= max_count)
                                return -1;
                        evts[n] = event;
-                       events[n++] = event->hw.event_base;
+                       events[n] = event->hw.event_base;
+                       current_idx[n++] = PIC_NO_INDEX;
                }
        }
        return n;
 }
 
+static void event_sched_in(struct perf_event *event, int cpu)
+{
+       event->state = PERF_EVENT_STATE_ACTIVE;
+       event->oncpu = cpu;
+       event->tstamp_running += event->ctx->time - event->tstamp_stopped;
+       if (is_software_event(event))
+               event->pmu->enable(event);
+}
+
+int hw_perf_group_sched_in(struct perf_event *group_leader,
+                          struct perf_cpu_context *cpuctx,
+                          struct perf_event_context *ctx, int cpu)
+{
+       struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+       struct perf_event *sub;
+       int n0, n;
+
+       if (!sparc_pmu)
+               return 0;
+
+       n0 = cpuc->n_events;
+       n = collect_events(group_leader, perf_max_events - n0,
+                          &cpuc->event[n0], &cpuc->events[n0],
+                          &cpuc->current_idx[n0]);
+       if (n < 0)
+               return -EAGAIN;
+       if (check_excludes(cpuc->event, n0, n))
+               return -EINVAL;
+       if (sparc_check_constraints(cpuc->event, cpuc->events, n + n0))
+               return -EAGAIN;
+       cpuc->n_events = n0 + n;
+       cpuc->n_added += n;
+
+       cpuctx->active_oncpu += n;
+       n = 1;
+       event_sched_in(group_leader, cpu);
+       list_for_each_entry(sub, &group_leader->sibling_list, group_entry) {
+               if (sub->state != PERF_EVENT_STATE_OFF) {
+                       event_sched_in(sub, cpu);
+                       n++;
+               }
+       }
+       ctx->nr_active += n;
+
+       return 1;
+}
+
+static int sparc_pmu_enable(struct perf_event *event)
+{
+       struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+       int n0, ret = -EAGAIN;
+       unsigned long flags;
+
+       local_irq_save(flags);
+       perf_disable();
+
+       n0 = cpuc->n_events;
+       if (n0 >= perf_max_events)
+               goto out;
+
+       cpuc->event[n0] = event;
+       cpuc->events[n0] = event->hw.event_base;
+       cpuc->current_idx[n0] = PIC_NO_INDEX;
+
+       if (check_excludes(cpuc->event, n0, 1))
+               goto out;
+       if (sparc_check_constraints(cpuc->event, cpuc->events, n0 + 1))
+               goto out;
+
+       cpuc->n_events++;
+       cpuc->n_added++;
+
+       ret = 0;
+out:
+       perf_enable();
+       local_irq_restore(flags);
+       return ret;
+}
+
 static int __hw_perf_event_init(struct perf_event *event)
 {
        struct perf_event_attr *attr = &event->attr;
        struct perf_event *evts[MAX_HWEVENTS];
        struct hw_perf_event *hwc = &event->hw;
        unsigned long events[MAX_HWEVENTS];
+       int current_idx_dmy[MAX_HWEVENTS];
        const struct perf_event_map *pmap;
-       u64 enc;
        int n;
 
        if (atomic_read(&nmi_active) < 0)
@@ -865,10 +1083,7 @@ static int __hw_perf_event_init(struct perf_event *event)
        } else
                return -EOPNOTSUPP;
 
-       /* We save the enable bits in the config_base.  So to
-        * turn off sampling just write 'config', and to enable
-        * things write 'config | config_base'.
-        */
+       /* We save the enable bits in the config_base.  */
        hwc->config_base = sparc_pmu->irq_bit;
        if (!attr->exclude_user)
                hwc->config_base |= PCR_UTRACE;
@@ -879,13 +1094,11 @@ static int __hw_perf_event_init(struct perf_event *event)
 
        hwc->event_base = perf_event_encode(pmap);
 
-       enc = pmap->encoding;
-
        n = 0;
        if (event->group_leader != event) {
                n = collect_events(event->group_leader,
                                   perf_max_events - 1,
-                                  evts, events);
+                                  evts, events, current_idx_dmy);
                if (n < 0)
                        return -EINVAL;
        }
@@ -895,9 +1108,11 @@ static int __hw_perf_event_init(struct perf_event *event)
        if (check_excludes(evts, n, 1))
                return -EINVAL;
 
-       if (sparc_check_constraints(events, n + 1))
+       if (sparc_check_constraints(evts, events, n + 1))
                return -EINVAL;
 
+       hwc->idx = PIC_NO_INDEX;
+
        /* Try to do all error checking before this point, as unwinding
         * state after grabbing the PMC is difficult.
         */
@@ -910,15 +1125,6 @@ static int __hw_perf_event_init(struct perf_event *event)
                atomic64_set(&hwc->period_left, hwc->sample_period);
        }
 
-       if (pmap->pic_mask & PIC_UPPER) {
-               hwc->idx = PIC_UPPER_INDEX;
-               enc <<= sparc_pmu->upper_shift;
-       } else {
-               hwc->idx = PIC_LOWER_INDEX;
-               enc <<= sparc_pmu->lower_shift;
-       }
-
-       hwc->config |= enc;
        return 0;
 }
 
@@ -968,7 +1174,7 @@ static int __kprobes perf_event_nmi_handler(struct notifier_block *self,
        struct perf_sample_data data;
        struct cpu_hw_events *cpuc;
        struct pt_regs *regs;
-       int idx;
+       int i;
 
        if (!atomic_read(&active_events))
                return NOTIFY_DONE;
@@ -997,13 +1203,12 @@ static int __kprobes perf_event_nmi_handler(struct notifier_block *self,
        if (sparc_pmu->irq_bit)
                pcr_ops->write(cpuc->pcr);
 
-       for (idx = 0; idx < MAX_HWEVENTS; idx++) {
-               struct perf_event *event = cpuc->events[idx];
+       for (i = 0; i < cpuc->n_events; i++) {
+               struct perf_event *event = cpuc->event[i];
+               int idx = cpuc->current_idx[i];
                struct hw_perf_event *hwc;
                u64 val;
 
-               if (!test_bit(idx, cpuc->active_mask))
-                       continue;
                hwc = &event->hw;
                val = sparc_perf_event_update(event, hwc, idx);
                if (val & (1ULL << 31))
@@ -1055,10 +1260,122 @@ void __init init_hw_perf_events(void)
 
        pr_cont("Supported PMU type is '%s'\n", sparc_pmu_type);
 
-       /* All sparc64 PMUs currently have 2 events.  But this simple
-        * driver only supports one active event at a time.
-        */
-       perf_max_events = 1;
+       /* All sparc64 PMUs currently have 2 events.  */
+       perf_max_events = 2;
 
        register_die_notifier(&perf_event_nmi_notifier);
 }
+
+static inline void callchain_store(struct perf_callchain_entry *entry, u64 ip)
+{
+       if (entry->nr < PERF_MAX_STACK_DEPTH)
+               entry->ip[entry->nr++] = ip;
+}
+
+static void perf_callchain_kernel(struct pt_regs *regs,
+                                 struct perf_callchain_entry *entry)
+{
+       unsigned long ksp, fp;
+
+       callchain_store(entry, PERF_CONTEXT_KERNEL);
+       callchain_store(entry, regs->tpc);
+
+       ksp = regs->u_regs[UREG_I6];
+       fp = ksp + STACK_BIAS;
+       do {
+               struct sparc_stackf *sf;
+               struct pt_regs *regs;
+               unsigned long pc;
+
+               if (!kstack_valid(current_thread_info(), fp))
+                       break;
+
+               sf = (struct sparc_stackf *) fp;
+               regs = (struct pt_regs *) (sf + 1);
+
+               if (kstack_is_trap_frame(current_thread_info(), regs)) {
+                       if (user_mode(regs))
+                               break;
+                       pc = regs->tpc;
+                       fp = regs->u_regs[UREG_I6] + STACK_BIAS;
+               } else {
+                       pc = sf->callers_pc;
+                       fp = (unsigned long)sf->fp + STACK_BIAS;
+               }
+               callchain_store(entry, pc);
+       } while (entry->nr < PERF_MAX_STACK_DEPTH);
+}
+
+static void perf_callchain_user_64(struct pt_regs *regs,
+                                  struct perf_callchain_entry *entry)
+{
+       unsigned long ufp;
+
+       callchain_store(entry, PERF_CONTEXT_USER);
+       callchain_store(entry, regs->tpc);
+
+       ufp = regs->u_regs[UREG_I6] + STACK_BIAS;
+       do {
+               struct sparc_stackf *usf, sf;
+               unsigned long pc;
+
+               usf = (struct sparc_stackf *) ufp;
+               if (__copy_from_user_inatomic(&sf, usf, sizeof(sf)))
+                       break;
+
+               pc = sf.callers_pc;
+               ufp = (unsigned long)sf.fp + STACK_BIAS;
+               callchain_store(entry, pc);
+       } while (entry->nr < PERF_MAX_STACK_DEPTH);
+}
+
+static void perf_callchain_user_32(struct pt_regs *regs,
+                                  struct perf_callchain_entry *entry)
+{
+       unsigned long ufp;
+
+       callchain_store(entry, PERF_CONTEXT_USER);
+       callchain_store(entry, regs->tpc);
+
+       ufp = regs->u_regs[UREG_I6];
+       do {
+               struct sparc_stackf32 *usf, sf;
+               unsigned long pc;
+
+               usf = (struct sparc_stackf32 *) ufp;
+               if (__copy_from_user_inatomic(&sf, usf, sizeof(sf)))
+                       break;
+
+               pc = sf.callers_pc;
+               ufp = (unsigned long)sf.fp;
+               callchain_store(entry, pc);
+       } while (entry->nr < PERF_MAX_STACK_DEPTH);
+}
+
+/* Like powerpc we can't get PMU interrupts within the PMU handler,
+ * so no need for seperate NMI and IRQ chains as on x86.
+ */
+static DEFINE_PER_CPU(struct perf_callchain_entry, callchain);
+
+struct perf_callchain_entry *perf_callchain(struct pt_regs *regs)
+{
+       struct perf_callchain_entry *entry = &__get_cpu_var(callchain);
+
+       entry->nr = 0;
+       if (!user_mode(regs)) {
+               stack_trace_flush();
+               perf_callchain_kernel(regs, entry);
+               if (current->mm)
+                       regs = task_pt_regs(current);
+               else
+                       regs = NULL;
+       }
+       if (regs) {
+               flushw_user();
+               if (test_thread_flag(TIF_32BIT))
+                       perf_callchain_user_32(regs, entry);
+               else
+                       perf_callchain_user_64(regs, entry);
+       }
+       return entry;
+}
index cfa0e19..d77f543 100644 (file)
@@ -365,6 +365,7 @@ EXPORT_SYMBOL(get_fb_unmapped_area);
 void arch_pick_mmap_layout(struct mm_struct *mm)
 {
        unsigned long random_factor = 0UL;
+       unsigned long gap;
 
        if (current->flags & PF_RANDOMIZE) {
                random_factor = get_random_int();
@@ -379,9 +380,10 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
         * Fall back to the standard layout if the personality
         * bit is set, or if the expected stack growth is unlimited:
         */
+       gap = rlimit(RLIMIT_STACK);
        if (!test_thread_flag(TIF_32BIT) ||
            (current->personality & ADDR_COMPAT_LAYOUT) ||
-           current->signal->rlim[RLIMIT_STACK].rlim_cur == RLIM_INFINITY ||
+           gap == RLIM_INFINITY ||
            sysctl_legacy_va_layout) {
                mm->mmap_base = TASK_UNMAPPED_BASE + random_factor;
                mm->get_unmapped_area = arch_get_unmapped_area;
@@ -389,9 +391,7 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
        } else {
                /* We know it's 32-bit */
                unsigned long task_size = STACK_TOP32;
-               unsigned long gap;
 
-               gap = current->signal->rlim[RLIMIT_STACK].rlim_cur;
                if (gap < 128 * 1024 * 1024)
                        gap = 128 * 1024 * 1024;
                if (gap > (task_size / 6 * 5))
index 5b2f595..0d4c09b 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/platform_device.h>
 
 #include <asm/oplib.h>
+#include <asm/timex.h>
 #include <asm/timer.h>
 #include <asm/system.h>
 #include <asm/irq.h>
@@ -51,7 +52,6 @@ DEFINE_SPINLOCK(rtc_lock);
 EXPORT_SYMBOL(rtc_lock);
 
 static int set_rtc_mmss(unsigned long);
-static int sbus_do_settimeofday(struct timespec *tv);
 
 unsigned long profile_pc(struct pt_regs *regs)
 {
@@ -76,6 +76,8 @@ EXPORT_SYMBOL(profile_pc);
 
 __volatile__ unsigned int *master_l10_counter;
 
+u32 (*do_arch_gettimeoffset)(void);
+
 /*
  * timer_interrupt() needs to keep up the real-time clock,
  * as well as call the "do_timer()" routine every clocktick
@@ -196,35 +198,14 @@ static int __init clock_init(void)
 {
        return of_register_driver(&clock_driver, &of_platform_bus_type);
 }
-
 /* Must be after subsys_initcall() so that busses are probed.  Must
  * be before device_initcall() because things like the RTC driver
  * need to see the clock registers.
  */
 fs_initcall(clock_init);
 
-static void __init sbus_time_init(void)
-{
-
-       BTFIXUPSET_CALL(bus_do_settimeofday, sbus_do_settimeofday, BTFIXUPCALL_NORM);
-       btfixup();
-
-       sparc_init_timers(timer_interrupt);
-}
-
-void __init time_init(void)
-{
-#ifdef CONFIG_PCI
-       extern void pci_time_init(void);
-       if (pcic_present()) {
-               pci_time_init();
-               return;
-       }
-#endif
-       sbus_time_init();
-}
 
-static inline unsigned long do_gettimeoffset(void)
+u32 sbus_do_gettimeoffset(void)
 {
        unsigned long val = *master_l10_counter;
        unsigned long usec = (val >> 10) & 0x1fffff;
@@ -233,86 +214,39 @@ static inline unsigned long do_gettimeoffset(void)
        if (val & 0x80000000)
                usec += 1000000 / HZ;
 
-       return usec;
+       return usec * 1000;
 }
 
-/* Ok, my cute asm atomicity trick doesn't work anymore.
- * There are just too many variables that need to be protected
- * now (both members of xtime, et al.)
- */
-void do_gettimeofday(struct timeval *tv)
-{
-       unsigned long flags;
-       unsigned long seq;
-       unsigned long usec, sec;
-       unsigned long max_ntp_tick = tick_usec - tickadj;
-
-       do {
-               seq = read_seqbegin_irqsave(&xtime_lock, flags);
-               usec = do_gettimeoffset();
-
-               /*
-                * If time_adjust is negative then NTP is slowing the clock
-                * so make sure not to go into next possible interval.
-                * Better to lose some accuracy than have time go backwards..
-                */
-               if (unlikely(time_adjust < 0))
-                       usec = min(usec, max_ntp_tick);
-
-               sec = xtime.tv_sec;
-               usec += (xtime.tv_nsec / 1000);
-       } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
-
-       while (usec >= 1000000) {
-               usec -= 1000000;
-               sec++;
-       }
 
-       tv->tv_sec = sec;
-       tv->tv_usec = usec;
-}
-
-EXPORT_SYMBOL(do_gettimeofday);
-
-int do_settimeofday(struct timespec *tv)
+u32 arch_gettimeoffset(void)
 {
-       int ret;
-
-       write_seqlock_irq(&xtime_lock);
-       ret = bus_do_settimeofday(tv);
-       write_sequnlock_irq(&xtime_lock);
-       clock_was_set();
-       return ret;
+       if (unlikely(!do_arch_gettimeoffset))
+               return 0;
+       return do_arch_gettimeoffset();
 }
 
-EXPORT_SYMBOL(do_settimeofday);
-
-static int sbus_do_settimeofday(struct timespec *tv)
+static void __init sbus_time_init(void)
 {
-       time_t wtm_sec, sec = tv->tv_sec;
-       long wtm_nsec, nsec = tv->tv_nsec;
+       do_arch_gettimeoffset = sbus_do_gettimeoffset;
 
-       if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
-               return -EINVAL;
-
-       /*
-        * This is revolting. We need to set "xtime" correctly. However, the
-        * value in this location is the value at the most recent update of
-        * wall time.  Discover what correction gettimeofday() would have
-        * made, and then undo it!
-        */
-       nsec -= 1000 * do_gettimeoffset();
-
-       wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
-       wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
+       btfixup();
 
-       set_normalized_timespec(&xtime, sec, nsec);
-       set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
+       sparc_init_timers(timer_interrupt);
+}
 
-       ntp_clear();
-       return 0;
+void __init time_init(void)
+{
+#ifdef CONFIG_PCI
+       extern void pci_time_init(void);
+       if (pcic_present()) {
+               pci_time_init();
+               return;
+       }
+#endif
+       sbus_time_init();
 }
 
+
 static int set_rtc_mmss(unsigned long secs)
 {
        struct rtc_device *rtc = rtc_class_open("rtc0");
index b99f81c..a3413ac 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/signal.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
+#include <linux/perf_event.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/kdebug.h>
@@ -203,6 +204,8 @@ asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write,
         if (in_atomic() || !mm)
                 goto no_context;
 
+       perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, address);
+
        down_read(&mm->mmap_sem);
 
        /*
@@ -249,10 +252,15 @@ good_area:
                        goto do_sigbus;
                BUG();
        }
-       if (fault & VM_FAULT_MAJOR)
+       if (fault & VM_FAULT_MAJOR) {
                current->maj_flt++;
-       else
+               perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 0,
+                             regs, address);
+       } else {
                current->min_flt++;
+               perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 0,
+                             regs, address);
+       }
        up_read(&mm->mmap_sem);
        return;
 
index 6081936..b9d4ff0 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/perf_event.h>
 #include <linux/interrupt.h>
 #include <linux/kprobes.h>
 #include <linux/kdebug.h>
@@ -296,6 +297,8 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs)
        if (in_atomic() || !mm)
                goto intr_or_no_mm;
 
+       perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, address);
+
        if (!down_read_trylock(&mm->mmap_sem)) {
                if ((regs->tstate & TSTATE_PRIV) &&
                    !search_exception_tables(regs->tpc)) {
@@ -400,11 +403,15 @@ good_area:
                        goto do_sigbus;
                BUG();
        }
-       if (fault & VM_FAULT_MAJOR)
+       if (fault & VM_FAULT_MAJOR) {
                current->maj_flt++;
-       else
+               perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 0,
+                             regs, address);
+       } else {
                current->min_flt++;
-
+               perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 0,
+                             regs, address);
+       }
        up_read(&mm->mmap_sem);
 
        mm_rss = get_mm_rss(mm);
index 3063a0c..ba8c045 100644 (file)
@@ -373,6 +373,12 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
                if (unlikely(!apic_enabled(apic)))
                        break;
 
+               if (trig_mode) {
+                       apic_debug("level trig mode for vector %d", vector);
+                       apic_set_vector(vector, apic->regs + APIC_TMR);
+               } else
+                       apic_clear_vector(vector, apic->regs + APIC_TMR);
+
                result = !apic_test_and_set_irr(vector, apic);
                trace_kvm_apic_accept_irq(vcpu->vcpu_id, delivery_mode,
                                          trig_mode, vector, !result);
@@ -383,11 +389,6 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
                        break;
                }
 
-               if (trig_mode) {
-                       apic_debug("level trig mode for vector %d", vector);
-                       apic_set_vector(vector, apic->regs + APIC_TMR);
-               } else
-                       apic_clear_vector(vector, apic->regs + APIC_TMR);
                kvm_vcpu_kick(vcpu);
                break;
 
index 4c3e5b2..89a49fb 100644 (file)
@@ -477,7 +477,7 @@ static int host_mapping_level(struct kvm *kvm, gfn_t gfn)
 
        addr = gfn_to_hva(kvm, gfn);
        if (kvm_is_error_hva(addr))
-               return page_size;
+               return PT_PAGE_TABLE_LEVEL;
 
        down_read(&current->mm->mmap_sem);
        vma = find_vma(current->mm, addr);
@@ -515,11 +515,9 @@ static int mapping_level(struct kvm_vcpu *vcpu, gfn_t large_gfn)
        if (host_level == PT_PAGE_TABLE_LEVEL)
                return host_level;
 
-       for (level = PT_DIRECTORY_LEVEL; level <= host_level; ++level) {
-
+       for (level = PT_DIRECTORY_LEVEL; level <= host_level; ++level)
                if (has_wrprotected_page(vcpu->kvm, large_gfn, level))
                        break;
-       }
 
        return level - 1;
 }
index 58a0f1e..ede2131 100644 (file)
@@ -150,7 +150,9 @@ walk:
                walker->table_gfn[walker->level - 1] = table_gfn;
                walker->pte_gpa[walker->level - 1] = pte_gpa;
 
-               kvm_read_guest(vcpu->kvm, pte_gpa, &pte, sizeof(pte));
+               if (kvm_read_guest(vcpu->kvm, pte_gpa, &pte, sizeof(pte)))
+                       goto not_present;
+
                trace_kvm_mmu_paging_element(pte, walker->level);
 
                if (!is_present_gpte(pte))
index 6651dbf..1ddcad4 100644 (file)
@@ -5072,12 +5072,13 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
                                       GFP_KERNEL);
        if (!vcpu->arch.mce_banks) {
                r = -ENOMEM;
-               goto fail_mmu_destroy;
+               goto fail_free_lapic;
        }
        vcpu->arch.mcg_cap = KVM_MAX_MCE_BANKS;
 
        return 0;
-
+fail_free_lapic:
+       kvm_free_lapic(vcpu);
 fail_mmu_destroy:
        kvm_mmu_destroy(vcpu);
 fail_free_pio_data:
@@ -5088,6 +5089,7 @@ fail:
 
 void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu)
 {
+       kfree(vcpu->arch.mce_banks);
        kvm_free_lapic(vcpu);
        down_read(&vcpu->kvm->slots_lock);
        kvm_mmu_destroy(vcpu);
index defcaf1..f665b05 100644 (file)
@@ -633,8 +633,7 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev,
                return NULL;
        }
        if (!(pt->misc & DRM_EDID_PT_SEPARATE_SYNC)) {
-               printk(KERN_WARNING "integrated sync not supported\n");
-               return NULL;
+               printk(KERN_WARNING "composite sync not supported\n");
        }
 
        /* it is incorrect if hsync/vsync width is zero */
index 1c2b7d4..0f9e905 100644 (file)
@@ -389,7 +389,7 @@ int drm_fb_helper_blank(int blank, struct fb_info *info)
                break;
        /* Display: Off; HSync: On, VSync: On */
        case FB_BLANK_NORMAL:
-               drm_fb_helper_off(info, DRM_MODE_DPMS_ON);
+               drm_fb_helper_off(info, DRM_MODE_DPMS_STANDBY);
                break;
        /* Display: Off; HSync: Off, VSync: On */
        case FB_BLANK_HSYNC_SUSPEND:
index ba14397..d7f8d8b 100644 (file)
@@ -310,63 +310,22 @@ valid_reg(struct nvbios *bios, uint32_t reg)
        struct drm_device *dev = bios->dev;
 
        /* C51 has misaligned regs on purpose. Marvellous */
-       if (reg & 0x2 || (reg & 0x1 && dev_priv->VBIOS.pub.chip_version != 0x51)) {
-               NV_ERROR(dev, "========== misaligned reg 0x%08X ==========\n",
-                        reg);
-               return 0;
-       }
-       /*
-        * Warn on C51 regs that have not been verified accessible in
-        * mmiotracing
-        */
+       if (reg & 0x2 ||
+           (reg & 0x1 && dev_priv->VBIOS.pub.chip_version != 0x51))
+               NV_ERROR(dev, "======= misaligned reg 0x%08X =======\n", reg);
+
+       /* warn on C51 regs that haven't been verified accessible in tracing */
        if (reg & 0x1 && dev_priv->VBIOS.pub.chip_version == 0x51 &&
            reg != 0x130d && reg != 0x1311 && reg != 0x60081d)
                NV_WARN(dev, "=== C51 misaligned reg 0x%08X not verified ===\n",
                        reg);
 
-       /* Trust the init scripts on G80 */
-       if (dev_priv->card_type >= NV_50)
-               return 1;
-
-       #define WITHIN(x, y, z) ((x >= y) && (x < y + z))
-       if (WITHIN(reg, NV_PMC_OFFSET, NV_PMC_SIZE))
-               return 1;
-       if (WITHIN(reg, NV_PBUS_OFFSET, NV_PBUS_SIZE))
-               return 1;
-       if (WITHIN(reg, NV_PFIFO_OFFSET, NV_PFIFO_SIZE))
-               return 1;
-       if (dev_priv->VBIOS.pub.chip_version >= 0x30 &&
-           (WITHIN(reg, 0x4000, 0x600) || reg == 0x00004600))
-               return 1;
-       if (dev_priv->VBIOS.pub.chip_version >= 0x40 &&
-                                               WITHIN(reg, 0xc000, 0x48))
-               return 1;
-       if (dev_priv->VBIOS.pub.chip_version >= 0x17 && reg == 0x0000d204)
-               return 1;
-       if (dev_priv->VBIOS.pub.chip_version >= 0x40) {
-               if (reg == 0x00011014 || reg == 0x00020328)
-                       return 1;
-               if (WITHIN(reg, 0x88000, NV_PBUS_SIZE)) /* new PBUS */
-                       return 1;
+       if (reg >= (8*1024*1024)) {
+               NV_ERROR(dev, "=== reg 0x%08x out of mapped bounds ===\n", reg);
+               return 0;
        }
-       if (WITHIN(reg, NV_PFB_OFFSET, NV_PFB_SIZE))
-               return 1;
-       if (WITHIN(reg, NV_PEXTDEV_OFFSET, NV_PEXTDEV_SIZE))
-               return 1;
-       if (WITHIN(reg, NV_PCRTC0_OFFSET, NV_PCRTC0_SIZE * 2))
-               return 1;
-       if (WITHIN(reg, NV_PRAMDAC0_OFFSET, NV_PRAMDAC0_SIZE * 2))
-               return 1;
-       if (dev_priv->VBIOS.pub.chip_version >= 0x17 && reg == 0x0070fff0)
-               return 1;
-       if (dev_priv->VBIOS.pub.chip_version == 0x51 &&
-                               WITHIN(reg, NV_PRAMIN_OFFSET, NV_PRAMIN_SIZE))
-               return 1;
-       #undef WITHIN
 
-       NV_ERROR(dev, "========== unknown reg 0x%08X ==========\n", reg);
-
-       return 0;
+       return 1;
 }
 
 static bool
@@ -3196,16 +3155,25 @@ static int call_lvds_manufacturer_script(struct drm_device *dev, struct dcb_entr
        }
 #ifdef __powerpc__
        /* Powerbook specific quirks */
-       if (script == LVDS_RESET && ((dev->pci_device & 0xffff) == 0x0179 || (dev->pci_device & 0xffff) == 0x0329))
-               nv_write_tmds(dev, dcbent->or, 0, 0x02, 0x72);
-       if ((dev->pci_device & 0xffff) == 0x0179 || (dev->pci_device & 0xffff) == 0x0189 || (dev->pci_device & 0xffff) == 0x0329) {
-               if (script == LVDS_PANEL_ON) {
-                       bios_wr32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL, bios_rd32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL) | (1 << 31));
-                       bios_wr32(bios, NV_PCRTC_GPIO_EXT, bios_rd32(bios, NV_PCRTC_GPIO_EXT) | 1);
-               }
-               if (script == LVDS_PANEL_OFF) {
-                       bios_wr32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL, bios_rd32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL) & ~(1 << 31));
-                       bios_wr32(bios, NV_PCRTC_GPIO_EXT, bios_rd32(bios, NV_PCRTC_GPIO_EXT) & ~3);
+       if ((dev->pci_device & 0xffff) == 0x0179 ||
+           (dev->pci_device & 0xffff) == 0x0189 ||
+           (dev->pci_device & 0xffff) == 0x0329) {
+               if (script == LVDS_RESET) {
+                       nv_write_tmds(dev, dcbent->or, 0, 0x02, 0x72);
+
+               } else if (script == LVDS_PANEL_ON) {
+                       bios_wr32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL,
+                                 bios_rd32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL)
+                                 | (1 << 31));
+                       bios_wr32(bios, NV_PCRTC_GPIO_EXT,
+                                 bios_rd32(bios, NV_PCRTC_GPIO_EXT) | 1);
+
+               } else if (script == LVDS_PANEL_OFF) {
+                       bios_wr32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL,
+                                 bios_rd32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL)
+                                 & ~(1 << 31));
+                       bios_wr32(bios, NV_PCRTC_GPIO_EXT,
+                                 bios_rd32(bios, NV_PCRTC_GPIO_EXT) & ~3);
                }
        }
 #endif
@@ -5434,52 +5402,49 @@ static bool
 parse_dcb15_entry(struct drm_device *dev, struct parsed_dcb *dcb,
                  uint32_t conn, uint32_t conf, struct dcb_entry *entry)
 {
-       if (conn != 0xf0003f00 && conn != 0xf2247f10 && conn != 0xf2204001 &&
-           conn != 0xf2204301 && conn != 0xf2204311 && conn != 0xf2208001 &&
-           conn != 0xf2244001 && conn != 0xf2244301 && conn != 0xf2244311 &&
-           conn != 0xf4204011 && conn != 0xf4208011 && conn != 0xf4248011 &&
-           conn != 0xf2045ff2 && conn != 0xf2045f14 && conn != 0xf207df14 &&
-           conn != 0xf2205004 && conn != 0xf2209004) {
-               NV_ERROR(dev, "Unknown DCB 1.5 entry, please report\n");
-
-               /* cause output setting to fail for !TV, so message is seen */
-               if ((conn & 0xf) != 0x1)
-                       dcb->entries = 0;
-
-               return false;
-       }
-       /* most of the below is a "best guess" atm */
-       entry->type = conn & 0xf;
-       if (entry->type == 2)
-               /* another way of specifying straps based lvds... */
+       switch (conn & 0x0000000f) {
+       case 0:
+               entry->type = OUTPUT_ANALOG;
+               break;
+       case 1:
+               entry->type = OUTPUT_TV;
+               break;
+       case 2:
+       case 3:
                entry->type = OUTPUT_LVDS;
-       if (entry->type == 4) { /* digital */
-               if (conn & 0x10)
-                       entry->type = OUTPUT_LVDS;
-               else
+               break;
+       case 4:
+               switch ((conn & 0x000000f0) >> 4) {
+               case 0:
                        entry->type = OUTPUT_TMDS;
+                       break;
+               case 1:
+                       entry->type = OUTPUT_LVDS;
+                       break;
+               default:
+                       NV_ERROR(dev, "Unknown DCB subtype 4/%d\n",
+                                (conn & 0x000000f0) >> 4);
+                       return false;
+               }
+               break;
+       default:
+               NV_ERROR(dev, "Unknown DCB type %d\n", conn & 0x0000000f);
+               return false;
        }
-       /* what's in bits 5-13? could be some encoder maker thing, in tv case */
-       entry->i2c_index = (conn >> 14) & 0xf;
-       /* raw heads field is in range 0-1, so move to 1-2 */
-       entry->heads = ((conn >> 18) & 0x7) + 1;
-       entry->location = (conn >> 21) & 0xf;
-       /* unused: entry->bus = (conn >> 25) & 0x7; */
-       /* set or to be same as heads -- hopefully safe enough */
-       entry->or = entry->heads;
+
+       entry->i2c_index = (conn & 0x0003c000) >> 14;
+       entry->heads = ((conn & 0x001c0000) >> 18) + 1;
+       entry->or = entry->heads; /* same as heads, hopefully safe enough */
+       entry->location = (conn & 0x01e00000) >> 21;
+       entry->bus = (conn & 0x0e000000) >> 25;
        entry->duallink_possible = false;
 
        switch (entry->type) {
        case OUTPUT_ANALOG:
                entry->crtconf.maxfreq = (conf & 0xffff) * 10;
                break;
-       case OUTPUT_LVDS:
-               /*
-                * This is probably buried in conn's unknown bits.
-                * This will upset EDID-ful models, if they exist
-                */
-               entry->lvdsconf.use_straps_for_mode = true;
-               entry->lvdsconf.use_power_scripts = true;
+       case OUTPUT_TV:
+               entry->tvconf.has_component_output = false;
                break;
        case OUTPUT_TMDS:
                /*
@@ -5488,8 +5453,12 @@ parse_dcb15_entry(struct drm_device *dev, struct parsed_dcb *dcb,
                 */
                fabricate_vga_output(dcb, entry->i2c_index, entry->heads);
                break;
-       case OUTPUT_TV:
-               entry->tvconf.has_component_output = false;
+       case OUTPUT_LVDS:
+               if ((conn & 0x00003f00) != 0x10)
+                       entry->lvdsconf.use_straps_for_mode = true;
+               entry->lvdsconf.use_power_scripts = true;
+               break;
+       default:
                break;
        }
 
@@ -5564,11 +5533,13 @@ void merge_like_dcb_entries(struct drm_device *dev, struct parsed_dcb *dcb)
        dcb->entries = newentries;
 }
 
-static int parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads)
+static int
+parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads)
 {
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct bios_parsed_dcb *bdcb = &bios->bdcb;
        struct parsed_dcb *dcb;
-       uint16_t dcbptr, i2ctabptr = 0;
+       uint16_t dcbptr = 0, i2ctabptr = 0;
        uint8_t *dcbtable;
        uint8_t headerlen = 0x4, entries = DCB_MAX_NUM_ENTRIES;
        bool configblock = true;
@@ -5579,16 +5550,18 @@ static int parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool two
        dcb->entries = 0;
 
        /* get the offset from 0x36 */
-       dcbptr = ROM16(bios->data[0x36]);
+       if (dev_priv->card_type > NV_04) {
+               dcbptr = ROM16(bios->data[0x36]);
+               if (dcbptr == 0x0000)
+                       NV_WARN(dev, "No output data (DCB) found in BIOS\n");
+       }
 
+       /* this situation likely means a really old card, pre DCB */
        if (dcbptr == 0x0) {
-               NV_WARN(dev, "No output data (DCB) found in BIOS, "
-                              "assuming a CRT output exists\n");
-               /* this situation likely means a really old card, pre DCB */
+               NV_INFO(dev, "Assuming a CRT output exists\n");
                fabricate_vga_output(dcb, LEGACY_I2C_CRT, 1);
 
-               if (nv04_tv_identify(dev,
-                                    bios->legacy.i2c_indices.tv) >= 0)
+               if (nv04_tv_identify(dev, bios->legacy.i2c_indices.tv) >= 0)
                        fabricate_tv_output(dcb, twoHeads);
 
                return 0;
index e342a41..db0ed4c 100644 (file)
@@ -469,6 +469,8 @@ nouveau_bo_move_accel_cleanup(struct nouveau_channel *chan,
 
        ret = ttm_bo_move_accel_cleanup(&nvbo->bo, fence, NULL,
                                        evict, no_wait, new_mem);
+       if (nvbo->channel && nvbo->channel != chan)
+               ret = nouveau_fence_wait(fence, NULL, false, false);
        nouveau_fence_unref((void *)&fence);
        return ret;
 }
index 5a10deb..7e6d673 100644 (file)
  *
  */
 
+#include <acpi/button.h>
+
 #include "drmP.h"
 #include "drm_edid.h"
 #include "drm_crtc_helper.h"
+
 #include "nouveau_reg.h"
 #include "nouveau_drv.h"
 #include "nouveau_encoder.h"
@@ -83,14 +86,16 @@ nouveau_encoder_connector_get(struct nouveau_encoder *encoder)
 static void
 nouveau_connector_destroy(struct drm_connector *drm_connector)
 {
-       struct nouveau_connector *connector = nouveau_connector(drm_connector);
-       struct drm_device *dev = connector->base.dev;
+       struct nouveau_connector *nv_connector =
+               nouveau_connector(drm_connector);
+       struct drm_device *dev = nv_connector->base.dev;
 
        NV_DEBUG_KMS(dev, "\n");
 
-       if (!connector)
+       if (!nv_connector)
                return;
 
+       kfree(nv_connector->edid);
        drm_sysfs_connector_remove(drm_connector);
        drm_connector_cleanup(drm_connector);
        kfree(drm_connector);
@@ -233,10 +238,21 @@ nouveau_connector_detect(struct drm_connector *connector)
        if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)
                nv_encoder = find_encoder_by_type(connector, OUTPUT_LVDS);
        if (nv_encoder && nv_connector->native_mode) {
+#ifdef CONFIG_ACPI
+               if (!nouveau_ignorelid && !acpi_lid_open())
+                       return connector_status_disconnected;
+#endif
                nouveau_connector_set_encoder(connector, nv_encoder);
                return connector_status_connected;
        }
 
+       /* Cleanup the previous EDID block. */
+       if (nv_connector->edid) {
+               drm_mode_connector_update_edid_property(connector, NULL);
+               kfree(nv_connector->edid);
+               nv_connector->edid = NULL;
+       }
+
        i2c = nouveau_connector_ddc_detect(connector, &nv_encoder);
        if (i2c) {
                nouveau_connector_ddc_prepare(connector, &flags);
@@ -247,7 +263,7 @@ nouveau_connector_detect(struct drm_connector *connector)
                if (!nv_connector->edid) {
                        NV_ERROR(dev, "DDC responded, but no EDID for %s\n",
                                 drm_get_connector_name(connector));
-                       return connector_status_disconnected;
+                       goto detect_analog;
                }
 
                if (nv_encoder->dcb->type == OUTPUT_DP &&
@@ -281,6 +297,7 @@ nouveau_connector_detect(struct drm_connector *connector)
                return connector_status_connected;
        }
 
+detect_analog:
        nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG);
        if (!nv_encoder)
                nv_encoder = find_encoder_by_type(connector, OUTPUT_TV);
@@ -687,8 +704,12 @@ nouveau_connector_create_lvds(struct drm_device *dev,
         */
        if (!nv_connector->edid && !nv_connector->native_mode &&
            !dev_priv->VBIOS.pub.fp_no_ddc) {
-               nv_connector->edid =
+               struct edid *edid =
                        (struct edid *)nouveau_bios_embedded_edid(dev);
+               if (edid) {
+                       nv_connector->edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
+                       *(nv_connector->edid) = *edid;
+               }
        }
 
        if (!nv_connector->edid)
index 7afbe8b..50d9e67 100644 (file)
@@ -126,47 +126,52 @@ OUT_RINGp(struct nouveau_channel *chan, const void *data, unsigned nr_dwords)
        chan->dma.cur += nr_dwords;
 }
 
-static inline bool
-READ_GET(struct nouveau_channel *chan, uint32_t *get)
+/* Fetch and adjust GPU GET pointer
+ *
+ * Returns:
+ *  value >= 0, the adjusted GET pointer
+ *  -EINVAL if GET pointer currently outside main push buffer
+ *  -EBUSY if timeout exceeded
+ */
+static inline int
+READ_GET(struct nouveau_channel *chan, uint32_t *prev_get, uint32_t *timeout)
 {
        uint32_t val;
 
        val = nvchan_rd32(chan, chan->user_get);
-       if (val < chan->pushbuf_base ||
-           val > chan->pushbuf_base + (chan->dma.max << 2)) {
-               /* meaningless to dma_wait() except to know whether the
-                * GPU has stalled or not
-                */
-               *get = val;
-               return false;
+
+       /* reset counter as long as GET is still advancing, this is
+        * to avoid misdetecting a GPU lockup if the GPU happens to
+        * just be processing an operation that takes a long time
+        */
+       if (val != *prev_get) {
+               *prev_get = val;
+               *timeout = 0;
+       }
+
+       if ((++*timeout & 0xff) == 0) {
+               DRM_UDELAY(1);
+               if (*timeout > 100000)
+                       return -EBUSY;
        }
 
-       *get = (val - chan->pushbuf_base) >> 2;
-       return true;
+       if (val < chan->pushbuf_base ||
+           val > chan->pushbuf_base + (chan->dma.max << 2))
+               return -EINVAL;
+
+       return (val - chan->pushbuf_base) >> 2;
 }
 
 int
 nouveau_dma_wait(struct nouveau_channel *chan, int size)
 {
-       uint32_t get, prev_get = 0, cnt = 0;
-       bool get_valid;
+       uint32_t prev_get = 0, cnt = 0;
+       int get;
 
        while (chan->dma.free < size) {
-               /* reset counter as long as GET is still advancing, this is
-                * to avoid misdetecting a GPU lockup if the GPU happens to
-                * just be processing an operation that takes a long time
-                */
-               get_valid = READ_GET(chan, &get);
-               if (get != prev_get) {
-                       prev_get = get;
-                       cnt = 0;
-               }
-
-               if ((++cnt & 0xff) == 0) {
-                       DRM_UDELAY(1);
-                       if (cnt > 100000)
-                               return -EBUSY;
-               }
+               get = READ_GET(chan, &prev_get, &cnt);
+               if (unlikely(get == -EBUSY))
+                       return -EBUSY;
 
                /* loop until we have a usable GET pointer.  the value
                 * we read from the GPU may be outside the main ring if
@@ -177,7 +182,7 @@ nouveau_dma_wait(struct nouveau_channel *chan, int size)
                 * from the SKIPS area, so the code below doesn't have to deal
                 * with some fun corner cases.
                 */
-               if (!get_valid || get < NOUVEAU_DMA_SKIPS)
+               if (unlikely(get == -EINVAL) || get < NOUVEAU_DMA_SKIPS)
                        continue;
 
                if (get <= chan->dma.cur) {
@@ -203,6 +208,19 @@ nouveau_dma_wait(struct nouveau_channel *chan, int size)
                         * after processing the currently pending commands.
                         */
                        OUT_RING(chan, chan->pushbuf_base | 0x20000000);
+
+                       /* wait for GET to depart from the skips area.
+                        * prevents writing GET==PUT and causing a race
+                        * condition that causes us to think the GPU is
+                        * idle when it's not.
+                        */
+                       do {
+                               get = READ_GET(chan, &prev_get, &cnt);
+                               if (unlikely(get == -EBUSY))
+                                       return -EBUSY;
+                               if (unlikely(get == -EINVAL))
+                                       continue;
+                       } while (get <= NOUVEAU_DMA_SKIPS);
                        WRITE_PUT(NOUVEAU_DMA_SKIPS);
 
                        /* we're now submitting commands at the start of
index 9e2926c..dd49372 100644 (file)
@@ -490,7 +490,8 @@ nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr,
                if (!nv_wait(NV50_AUXCH_CTRL(index), 0x00010000, 0x00000000)) {
                        NV_ERROR(dev, "expected bit 16 == 0, got 0x%08x\n",
                                 nv_rd32(dev, NV50_AUXCH_CTRL(index)));
-                       return -EBUSY;
+                       ret = -EBUSY;
+                       goto out;
                }
 
                udelay(400);
@@ -501,6 +502,11 @@ nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr,
                        break;
        }
 
+       if ((stat & NV50_AUXCH_STAT_COUNT) != data_nr) {
+               ret = -EREMOTEIO;
+               goto out;
+       }
+
        if (cmd & 1) {
                for (i = 0; i < 4; i++) {
                        data32[i] = nv_rd32(dev, NV50_AUXCH_DATA_IN(index, i));
index 06eb993..343ab7f 100644 (file)
@@ -71,6 +71,10 @@ MODULE_PARM_DESC(uscript_tmds, "TMDS output script table ID (>=GeForce 8)");
 int nouveau_uscript_tmds = -1;
 module_param_named(uscript_tmds, nouveau_uscript_tmds, int, 0400);
 
+MODULE_PARM_DESC(ignorelid, "Ignore ACPI lid status");
+int nouveau_ignorelid = 0;
+module_param_named(ignorelid, nouveau_ignorelid, int, 0400);
+
 MODULE_PARM_DESC(tv_norm, "Default TV norm.\n"
                 "\t\tSupported: PAL, PAL-M, PAL-N, PAL-Nc, NTSC-M, NTSC-J,\n"
                 "\t\t\thd480i, hd480p, hd576i, hd576p, hd720p, hd1080i.\n"
index 026419f..6b96904 100644 (file)
@@ -509,6 +509,8 @@ struct drm_nouveau_private {
        void __iomem *ramin;
        uint32_t ramin_size;
 
+       struct nouveau_bo *vga_ram;
+
        struct workqueue_struct *wq;
        struct work_struct irq_work;
 
@@ -675,6 +677,7 @@ extern char *nouveau_tv_norm;
 extern int nouveau_reg_debug;
 extern char *nouveau_vbios;
 extern int nouveau_ctxfw;
+extern int nouveau_ignorelid;
 
 /* nouveau_state.c */
 extern void nouveau_preclose(struct drm_device *dev, struct drm_file *);
index 2009db2..6ac804b 100644 (file)
@@ -321,6 +321,7 @@ retry:
                else {
                        NV_ERROR(dev, "invalid valid domains: 0x%08x\n",
                                 b->valid_domains);
+                       list_add_tail(&nvbo->entry, &op->both_list);
                        validate_fini(op, NULL);
                        return -EINVAL;
                }
@@ -466,13 +467,14 @@ u_memcpya(uint64_t user, unsigned nmemb, unsigned size)
 static int
 nouveau_gem_pushbuf_reloc_apply(struct nouveau_channel *chan, int nr_bo,
                                struct drm_nouveau_gem_pushbuf_bo *bo,
-                               int nr_relocs, uint64_t ptr_relocs,
-                               int nr_dwords, int first_dword,
+                               unsigned nr_relocs, uint64_t ptr_relocs,
+                               unsigned nr_dwords, unsigned first_dword,
                                uint32_t *pushbuf, bool is_iomem)
 {
        struct drm_nouveau_gem_pushbuf_reloc *reloc = NULL;
        struct drm_device *dev = chan->dev;
-       int ret = 0, i;
+       int ret = 0;
+       unsigned i;
 
        reloc = u_memcpya(ptr_relocs, nr_relocs, sizeof(*reloc));
        if (IS_ERR(reloc))
@@ -667,6 +669,18 @@ nouveau_gem_ioctl_pushbuf_call(struct drm_device *dev, void *data,
        }
        pbbo = nouveau_gem_object(gem);
 
+       if ((req->offset & 3) || req->nr_dwords < 2 ||
+           (unsigned long)req->offset > (unsigned long)pbbo->bo.mem.size ||
+           (unsigned long)req->nr_dwords >
+            ((unsigned long)(pbbo->bo.mem.size - req->offset ) >> 2)) {
+               NV_ERROR(dev, "pb call misaligned or out of bounds: "
+                             "%d + %d * 4 > %ld\n",
+                        req->offset, req->nr_dwords, pbbo->bo.mem.size);
+               ret = -EINVAL;
+               drm_gem_object_unreference(gem);
+               goto out;
+       }
+
        ret = ttm_bo_reserve(&pbbo->bo, false, false, true,
                             chan->fence.sequence);
        if (ret) {
index 919a619..3b9bad6 100644 (file)
@@ -483,6 +483,13 @@ nouveau_pgraph_intr_error(struct drm_device *dev, uint32_t nsource)
        if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) {
                if (nouveau_pgraph_intr_swmthd(dev, &trap))
                        unhandled = 1;
+       } else if (nsource & NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION) {
+               uint32_t v = nv_rd32(dev, 0x402000);
+               nv_wr32(dev, 0x402000, v);
+
+               /* dump the error anyway for now: it's useful for
+                  Gallium development */
+               unhandled = 1;
        } else {
                unhandled = 1;
        }
index fb9bdd6..8f3a12f 100644 (file)
@@ -383,9 +383,8 @@ void nouveau_mem_close(struct drm_device *dev)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
 
-       if (dev_priv->ttm.bdev.man[TTM_PL_PRIV0].has_type)
-               ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_PRIV0);
-       ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM);
+       nouveau_bo_unpin(dev_priv->vga_ram);
+       nouveau_bo_ref(NULL, &dev_priv->vga_ram);
 
        ttm_bo_device_release(&dev_priv->ttm.bdev);
 
@@ -622,6 +621,15 @@ nouveau_mem_init(struct drm_device *dev)
                return ret;
        }
 
+       ret = nouveau_bo_new(dev, NULL, 256*1024, 0, TTM_PL_FLAG_VRAM,
+                            0, 0, true, true, &dev_priv->vga_ram);
+       if (ret == 0)
+               ret = nouveau_bo_pin(dev_priv->vga_ram, TTM_PL_FLAG_VRAM);
+       if (ret) {
+               NV_WARN(dev, "failed to reserve VGA memory\n");
+               nouveau_bo_ref(NULL, &dev_priv->vga_ram);
+       }
+
        /* GART */
 #if !defined(__powerpc__) && !defined(__ia64__)
        if (drm_device_is_agp(dev) && dev->agp) {
@@ -653,6 +661,7 @@ nouveau_mem_init(struct drm_device *dev)
        dev_priv->fb_mtrr = drm_mtrr_add(drm_get_resource_start(dev, 1),
                                         drm_get_resource_len(dev, 1),
                                         DRM_MTRR_WC);
+
        return 0;
 }
 
index 09b9a46..f2d0187 100644 (file)
@@ -525,6 +525,7 @@ static void nouveau_card_takedown(struct drm_device *dev)
                engine->mc.takedown(dev);
 
                mutex_lock(&dev->struct_mutex);
+               ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM);
                ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_TT);
                mutex_unlock(&dev->struct_mutex);
                nouveau_sgdma_takedown(dev);
index a20c206..a3b9563 100644 (file)
@@ -30,7 +30,7 @@ nv04_instmem_determine_amount(struct drm_device *dev)
                 * of vram.  For now, only reserve a small piece until we know
                 * more about what each chipset requires.
                 */
-               switch (dev_priv->chipset & 0xf0) {
+               switch (dev_priv->chipset) {
                case 0x40:
                case 0x47:
                case 0x49:
index 118d328..40b7360 100644 (file)
@@ -432,6 +432,7 @@ nv50_crtc_prepare(struct drm_crtc *crtc)
        struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
        struct drm_device *dev = crtc->dev;
        struct drm_encoder *encoder;
+       uint32_t dac = 0, sor = 0;
 
        NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index);
 
@@ -439,9 +440,28 @@ nv50_crtc_prepare(struct drm_crtc *crtc)
        list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
                struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
 
-               if (drm_helper_encoder_in_use(encoder))
+               if (!drm_helper_encoder_in_use(encoder))
                        continue;
 
+               if (nv_encoder->dcb->type == OUTPUT_ANALOG ||
+                   nv_encoder->dcb->type == OUTPUT_TV)
+                       dac |= (1 << nv_encoder->or);
+               else
+                       sor |= (1 << nv_encoder->or);
+       }
+
+       list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+               struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+
+               if (nv_encoder->dcb->type == OUTPUT_ANALOG ||
+                   nv_encoder->dcb->type == OUTPUT_TV) {
+                       if (dac & (1 << nv_encoder->or))
+                               continue;
+               } else {
+                       if (sor & (1 << nv_encoder->or))
+                               continue;
+               }
+
                nv_encoder->disconnect(nv_encoder);
        }
 
index 39caf16..32b244b 100644 (file)
@@ -272,7 +272,7 @@ nv50_fifo_create_context(struct nouveau_channel *chan)
                        return ret;
                ramfc = chan->ramfc->gpuobj;
 
-               ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, 4096, 256,
+               ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, 4096, 1024,
                                             0, &chan->cache);
                if (ret)
                        return ret;
index ca79f32..20319e5 100644 (file)
@@ -84,7 +84,7 @@ nv50_graph_init_regs__nv(struct drm_device *dev)
        nv_wr32(dev, 0x400804, 0xc0000000);
        nv_wr32(dev, 0x406800, 0xc0000000);
        nv_wr32(dev, 0x400c04, 0xc0000000);
-       nv_wr32(dev, 0x401804, 0xc0000000);
+       nv_wr32(dev, 0x401800, 0xc0000000);
        nv_wr32(dev, 0x405018, 0xc0000000);
        nv_wr32(dev, 0x402000, 0xc0000000);
 
@@ -282,6 +282,7 @@ nv50_graph_unload_context(struct drm_device *dev)
                return 0;
        inst &= NV50_PGRAPH_CTXCTL_CUR_INSTANCE;
 
+       nouveau_wait_for_idle(dev);
        nv_wr32(dev, 0x400500, fifo & ~1);
        nv_wr32(dev, 0x400784, inst);
        nv_wr32(dev, 0x400824, nv_rd32(dev, 0x400824) | 0x20);
index e395c16..ecf1936 100644 (file)
@@ -90,11 +90,24 @@ nv50_sor_dpms(struct drm_encoder *encoder, int mode)
 {
        struct drm_device *dev = encoder->dev;
        struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+       struct drm_encoder *enc;
        uint32_t val;
        int or = nv_encoder->or;
 
        NV_DEBUG_KMS(dev, "or %d mode %d\n", or, mode);
 
+       nv_encoder->last_dpms = mode;
+       list_for_each_entry(enc, &dev->mode_config.encoder_list, head) {
+               struct nouveau_encoder *nvenc = nouveau_encoder(enc);
+
+               if (nvenc == nv_encoder ||
+                   nvenc->dcb->or != nv_encoder->dcb->or)
+                       continue;
+
+               if (nvenc->last_dpms == DRM_MODE_DPMS_ON)
+                       return;
+       }
+
        /* wait for it to be done */
        if (!nv_wait(NV50_PDISPLAY_SOR_DPMS_CTRL(or),
                     NV50_PDISPLAY_SOR_DPMS_CTRL_PENDING, 0)) {
index 388140a..e3b4456 100644 (file)
@@ -246,6 +246,9 @@ static uint32_t atom_get_src_int(atom_exec_context *ctx, uint8_t attr,
                case ATOM_WS_ATTRIBUTES:
                        val = gctx->io_attr;
                        break;
+               case ATOM_WS_REGPTR:
+                       val = gctx->reg_block;
+                       break;
                default:
                        val = ctx->ws[idx];
                }
@@ -385,6 +388,32 @@ static uint32_t atom_get_src(atom_exec_context *ctx, uint8_t attr, int *ptr)
        return atom_get_src_int(ctx, attr, ptr, NULL, 1);
 }
 
+static uint32_t atom_get_src_direct(atom_exec_context *ctx, uint8_t align, int *ptr)
+{
+       uint32_t val = 0xCDCDCDCD;
+
+       switch (align) {
+       case ATOM_SRC_DWORD:
+               val = U32(*ptr);
+               (*ptr) += 4;
+               break;
+       case ATOM_SRC_WORD0:
+       case ATOM_SRC_WORD8:
+       case ATOM_SRC_WORD16:
+               val = U16(*ptr);
+               (*ptr) += 2;
+               break;
+       case ATOM_SRC_BYTE0:
+       case ATOM_SRC_BYTE8:
+       case ATOM_SRC_BYTE16:
+       case ATOM_SRC_BYTE24:
+               val = U8(*ptr);
+               (*ptr)++;
+               break;
+       }
+       return val;
+}
+
 static uint32_t atom_get_dst(atom_exec_context *ctx, int arg, uint8_t attr,
                             int *ptr, uint32_t *saved, int print)
 {
@@ -482,6 +511,9 @@ static void atom_put_dst(atom_exec_context *ctx, int arg, uint8_t attr,
                case ATOM_WS_ATTRIBUTES:
                        gctx->io_attr = val;
                        break;
+               case ATOM_WS_REGPTR:
+                       gctx->reg_block = val;
+                       break;
                default:
                        ctx->ws[idx] = val;
                }
@@ -677,7 +709,7 @@ static void atom_op_mask(atom_exec_context *ctx, int *ptr, int arg)
        SDEBUG("   dst: ");
        dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
        SDEBUG("   src1: ");
-       src1 = atom_get_src(ctx, attr, ptr);
+       src1 = atom_get_src_direct(ctx, ((attr >> 3) & 7), ptr);
        SDEBUG("   src2: ");
        src2 = atom_get_src(ctx, attr, ptr);
        dst &= src1;
@@ -809,6 +841,38 @@ static void atom_op_setregblock(atom_exec_context *ctx, int *ptr, int arg)
        SDEBUG("   base: 0x%04X\n", ctx->ctx->reg_block);
 }
 
+static void atom_op_shift_left(atom_exec_context *ctx, int *ptr, int arg)
+{
+       uint8_t attr = U8((*ptr)++), shift;
+       uint32_t saved, dst;
+       int dptr = *ptr;
+       attr &= 0x38;
+       attr |= atom_def_dst[attr >> 3] << 6;
+       SDEBUG("   dst: ");
+       dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
+       shift = atom_get_src_direct(ctx, ATOM_SRC_BYTE0, ptr);
+       SDEBUG("   shift: %d\n", shift);
+       dst <<= shift;
+       SDEBUG("   dst: ");
+       atom_put_dst(ctx, arg, attr, &dptr, dst, saved);
+}
+
+static void atom_op_shift_right(atom_exec_context *ctx, int *ptr, int arg)
+{
+       uint8_t attr = U8((*ptr)++), shift;
+       uint32_t saved, dst;
+       int dptr = *ptr;
+       attr &= 0x38;
+       attr |= atom_def_dst[attr >> 3] << 6;
+       SDEBUG("   dst: ");
+       dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
+       shift = atom_get_src_direct(ctx, ATOM_SRC_BYTE0, ptr);
+       SDEBUG("   shift: %d\n", shift);
+       dst >>= shift;
+       SDEBUG("   dst: ");
+       atom_put_dst(ctx, arg, attr, &dptr, dst, saved);
+}
+
 static void atom_op_shl(atom_exec_context *ctx, int *ptr, int arg)
 {
        uint8_t attr = U8((*ptr)++), shift;
@@ -818,7 +882,7 @@ static void atom_op_shl(atom_exec_context *ctx, int *ptr, int arg)
        attr |= atom_def_dst[attr >> 3] << 6;
        SDEBUG("   dst: ");
        dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
-       shift = U8((*ptr)++);
+       shift = atom_get_src(ctx, attr, ptr);
        SDEBUG("   shift: %d\n", shift);
        dst <<= shift;
        SDEBUG("   dst: ");
@@ -834,7 +898,7 @@ static void atom_op_shr(atom_exec_context *ctx, int *ptr, int arg)
        attr |= atom_def_dst[attr >> 3] << 6;
        SDEBUG("   dst: ");
        dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
-       shift = U8((*ptr)++);
+       shift = atom_get_src(ctx, attr, ptr);
        SDEBUG("   shift: %d\n", shift);
        dst >>= shift;
        SDEBUG("   dst: ");
@@ -937,18 +1001,18 @@ static struct {
        atom_op_or, ATOM_ARG_FB}, {
        atom_op_or, ATOM_ARG_PLL}, {
        atom_op_or, ATOM_ARG_MC}, {
-       atom_op_shl, ATOM_ARG_REG}, {
-       atom_op_shl, ATOM_ARG_PS}, {
-       atom_op_shl, ATOM_ARG_WS}, {
-       atom_op_shl, ATOM_ARG_FB}, {
-       atom_op_shl, ATOM_ARG_PLL}, {
-       atom_op_shl, ATOM_ARG_MC}, {
-       atom_op_shr, ATOM_ARG_REG}, {
-       atom_op_shr, ATOM_ARG_PS}, {
-       atom_op_shr, ATOM_ARG_WS}, {
-       atom_op_shr, ATOM_ARG_FB}, {
-       atom_op_shr, ATOM_ARG_PLL}, {
-       atom_op_shr, ATOM_ARG_MC}, {
+       atom_op_shift_left, ATOM_ARG_REG}, {
+       atom_op_shift_left, ATOM_ARG_PS}, {
+       atom_op_shift_left, ATOM_ARG_WS}, {
+       atom_op_shift_left, ATOM_ARG_FB}, {
+       atom_op_shift_left, ATOM_ARG_PLL}, {
+       atom_op_shift_left, ATOM_ARG_MC}, {
+       atom_op_shift_right, ATOM_ARG_REG}, {
+       atom_op_shift_right, ATOM_ARG_PS}, {
+       atom_op_shift_right, ATOM_ARG_WS}, {
+       atom_op_shift_right, ATOM_ARG_FB}, {
+       atom_op_shift_right, ATOM_ARG_PLL}, {
+       atom_op_shift_right, ATOM_ARG_MC}, {
        atom_op_mul, ATOM_ARG_REG}, {
        atom_op_mul, ATOM_ARG_PS}, {
        atom_op_mul, ATOM_ARG_WS}, {
@@ -1058,8 +1122,6 @@ static void atom_execute_table_locked(struct atom_context *ctx, int index, uint3
 
        SDEBUG(">> execute %04X (len %d, WS %d, PS %d)\n", base, len, ws, ps);
 
-       /* reset reg block */
-       ctx->reg_block = 0;
        ectx.ctx = ctx;
        ectx.ps_shift = ps / 4;
        ectx.start = base;
@@ -1096,6 +1158,12 @@ static void atom_execute_table_locked(struct atom_context *ctx, int index, uint3
 void atom_execute_table(struct atom_context *ctx, int index, uint32_t * params)
 {
        mutex_lock(&ctx->mutex);
+       /* reset reg block */
+       ctx->reg_block = 0;
+       /* reset fb window */
+       ctx->fb_base = 0;
+       /* reset io mode */
+       ctx->io_mode = ATOM_IO_MM;
        atom_execute_table_locked(ctx, index, params);
        mutex_unlock(&ctx->mutex);
 }
index 47fd943..bc73781 100644 (file)
@@ -91,6 +91,7 @@
 #define ATOM_WS_AND_MASK       0x45
 #define ATOM_WS_FB_WINDOW      0x46
 #define ATOM_WS_ATTRIBUTES     0x47
+#define ATOM_WS_REGPTR         0x48
 
 #define ATOM_IIO_NOP           0
 #define ATOM_IIO_START         1
index 260fcf5..af464e3 100644 (file)
@@ -307,7 +307,6 @@ atombios_set_crtc_dtd_timing(struct drm_crtc *crtc,
        args.susModeMiscInfo.usAccess = cpu_to_le16(misc);
        args.ucCRTC = radeon_crtc->crtc_id;
 
-       printk("executing set crtc dtd timing\n");
        atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
 }
 
@@ -347,7 +346,6 @@ static void atombios_crtc_set_timing(struct drm_crtc *crtc,
        args.susModeMiscInfo.usAccess = cpu_to_le16(misc);
        args.ucCRTC = radeon_crtc->crtc_id;
 
-       printk("executing set crtc timing\n");
        atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
 }
 
@@ -409,59 +407,57 @@ static void atombios_set_ss(struct drm_crtc *crtc, int enable)
        }
 }
 
-void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
+union adjust_pixel_clock {
+       ADJUST_DISPLAY_PLL_PS_ALLOCATION v1;
+};
+
+static u32 atombios_adjust_pll(struct drm_crtc *crtc,
+                              struct drm_display_mode *mode,
+                              struct radeon_pll *pll)
 {
-       struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
        struct drm_device *dev = crtc->dev;
        struct radeon_device *rdev = dev->dev_private;
        struct drm_encoder *encoder = NULL;
        struct radeon_encoder *radeon_encoder = NULL;
-       uint8_t frev, crev;
-       int index;
-       SET_PIXEL_CLOCK_PS_ALLOCATION args;
-       PIXEL_CLOCK_PARAMETERS *spc1_ptr;
-       PIXEL_CLOCK_PARAMETERS_V2 *spc2_ptr;
-       PIXEL_CLOCK_PARAMETERS_V3 *spc3_ptr;
-       uint32_t pll_clock = mode->clock;
-       uint32_t adjusted_clock;
-       uint32_t ref_div = 0, fb_div = 0, frac_fb_div = 0, post_div = 0;
-       struct radeon_pll *pll;
-       int pll_flags = 0;
+       u32 adjusted_clock = mode->clock;
 
-       memset(&args, 0, sizeof(args));
+       /* reset the pll flags */
+       pll->flags = 0;
 
        if (ASIC_IS_AVIVO(rdev)) {
                if ((rdev->family == CHIP_RS600) ||
                    (rdev->family == CHIP_RS690) ||
                    (rdev->family == CHIP_RS740))
-                       pll_flags |= (RADEON_PLL_USE_FRAC_FB_DIV |
-                                     RADEON_PLL_PREFER_CLOSEST_LOWER);
+                       pll->flags |= (RADEON_PLL_USE_FRAC_FB_DIV |
+                                      RADEON_PLL_PREFER_CLOSEST_LOWER);
 
                if (ASIC_IS_DCE32(rdev) && mode->clock > 200000)        /* range limits??? */
-                       pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
+                       pll->flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
                else
-                       pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
+                       pll->flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
        } else {
-               pll_flags |= RADEON_PLL_LEGACY;
+               pll->flags |= RADEON_PLL_LEGACY;
 
                if (mode->clock > 200000)       /* range limits??? */
-                       pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
+                       pll->flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
                else
-                       pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
+                       pll->flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
 
        }
 
        list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
                if (encoder->crtc == crtc) {
-                       if (!ASIC_IS_AVIVO(rdev)) {
-                               if (encoder->encoder_type !=
-                                   DRM_MODE_ENCODER_DAC)
-                                       pll_flags |= RADEON_PLL_NO_ODD_POST_DIV;
-                               if (encoder->encoder_type ==
-                                       DRM_MODE_ENCODER_LVDS)
-                                       pll_flags |= RADEON_PLL_USE_REF_DIV;
-                       }
                        radeon_encoder = to_radeon_encoder(encoder);
+                       if (ASIC_IS_AVIVO(rdev)) {
+                               /* DVO wants 2x pixel clock if the DVO chip is in 12 bit mode */
+                               if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1)
+                                       adjusted_clock = mode->clock * 2;
+                       } else {
+                               if (encoder->encoder_type != DRM_MODE_ENCODER_DAC)
+                                       pll->flags |= RADEON_PLL_NO_ODD_POST_DIV;
+                               if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS)
+                                       pll->flags |= RADEON_PLL_USE_REF_DIV;
+                       }
                        break;
                }
        }
@@ -471,46 +467,101 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
         * special hw requirements.
         */
        if (ASIC_IS_DCE3(rdev)) {
-               ADJUST_DISPLAY_PLL_PS_ALLOCATION adjust_pll_args;
+               union adjust_pixel_clock args;
+               struct radeon_encoder_atom_dig *dig;
+               u8 frev, crev;
+               int index;
 
-               if (!encoder)
-                       return;
-
-               memset(&adjust_pll_args, 0, sizeof(adjust_pll_args));
-               adjust_pll_args.usPixelClock = cpu_to_le16(mode->clock / 10);
-               adjust_pll_args.ucTransmitterID = radeon_encoder->encoder_id;
-               adjust_pll_args.ucEncodeMode = atombios_get_encoder_mode(encoder);
+               if (!radeon_encoder->enc_priv)
+                       return adjusted_clock;
+               dig = radeon_encoder->enc_priv;
 
                index = GetIndexIntoMasterTable(COMMAND, AdjustDisplayPll);
-               atom_execute_table(rdev->mode_info.atom_context,
-                                  index, (uint32_t *)&adjust_pll_args);
-               adjusted_clock = le16_to_cpu(adjust_pll_args.usPixelClock) * 10;
-       } else {
-               /* DVO wants 2x pixel clock if the DVO chip is in 12 bit mode */
-               if (ASIC_IS_AVIVO(rdev) &&
-                   (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1))
-                       adjusted_clock = mode->clock * 2;
-               else
-                       adjusted_clock = mode->clock;
+               atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev,
+                                     &crev);
+
+               memset(&args, 0, sizeof(args));
+
+               switch (frev) {
+               case 1:
+                       switch (crev) {
+                       case 1:
+                       case 2:
+                               args.v1.usPixelClock = cpu_to_le16(mode->clock / 10);
+                               args.v1.ucTransmitterID = radeon_encoder->encoder_id;
+                               args.v1.ucEncodeMode = atombios_get_encoder_mode(encoder);
+
+                               atom_execute_table(rdev->mode_info.atom_context,
+                                                  index, (uint32_t *)&args);
+                               adjusted_clock = le16_to_cpu(args.v1.usPixelClock) * 10;
+                               break;
+                       default:
+                               DRM_ERROR("Unknown table version %d %d\n", frev, crev);
+                               return adjusted_clock;
+                       }
+                       break;
+               default:
+                       DRM_ERROR("Unknown table version %d %d\n", frev, crev);
+                       return adjusted_clock;
+               }
        }
+       return adjusted_clock;
+}
+
+union set_pixel_clock {
+       SET_PIXEL_CLOCK_PS_ALLOCATION base;
+       PIXEL_CLOCK_PARAMETERS v1;
+       PIXEL_CLOCK_PARAMETERS_V2 v2;
+       PIXEL_CLOCK_PARAMETERS_V3 v3;
+};
+
+void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
+{
+       struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+       struct drm_device *dev = crtc->dev;
+       struct radeon_device *rdev = dev->dev_private;
+       struct drm_encoder *encoder = NULL;
+       struct radeon_encoder *radeon_encoder = NULL;
+       u8 frev, crev;
+       int index;
+       union set_pixel_clock args;
+       u32 pll_clock = mode->clock;
+       u32 ref_div = 0, fb_div = 0, frac_fb_div = 0, post_div = 0;
+       struct radeon_pll *pll;
+       u32 adjusted_clock;
+
+       memset(&args, 0, sizeof(args));
+
+       list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+               if (encoder->crtc == crtc) {
+                       radeon_encoder = to_radeon_encoder(encoder);
+                       break;
+               }
+       }
+
+       if (!radeon_encoder)
+               return;
 
        if (radeon_crtc->crtc_id == 0)
                pll = &rdev->clock.p1pll;
        else
                pll = &rdev->clock.p2pll;
 
+       /* adjust pixel clock as needed */
+       adjusted_clock = atombios_adjust_pll(crtc, mode, pll);
+
        if (ASIC_IS_AVIVO(rdev)) {
                if (radeon_new_pll)
                        radeon_compute_pll_avivo(pll, adjusted_clock, &pll_clock,
                                                 &fb_div, &frac_fb_div,
-                                                &ref_div, &post_div, pll_flags);
+                                                &ref_div, &post_div);
                else
                        radeon_compute_pll(pll, adjusted_clock, &pll_clock,
                                           &fb_div, &frac_fb_div,
-                                          &ref_div, &post_div, pll_flags);
+                                          &ref_div, &post_div);
        } else
                radeon_compute_pll(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div,
-                                  &ref_div, &post_div, pll_flags);
+                                  &ref_div, &post_div);
 
        index = GetIndexIntoMasterTable(COMMAND, SetPixelClock);
        atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev,
@@ -520,45 +571,38 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
        case 1:
                switch (crev) {
                case 1:
-                       spc1_ptr = (PIXEL_CLOCK_PARAMETERS *) & args.sPCLKInput;
-                       spc1_ptr->usPixelClock = cpu_to_le16(mode->clock / 10);
-                       spc1_ptr->usRefDiv = cpu_to_le16(ref_div);
-                       spc1_ptr->usFbDiv = cpu_to_le16(fb_div);
-                       spc1_ptr->ucFracFbDiv = frac_fb_div;
-                       spc1_ptr->ucPostDiv = post_div;
-                       spc1_ptr->ucPpll =
+                       args.v1.usPixelClock = cpu_to_le16(mode->clock / 10);
+                       args.v1.usRefDiv = cpu_to_le16(ref_div);
+                       args.v1.usFbDiv = cpu_to_le16(fb_div);
+                       args.v1.ucFracFbDiv = frac_fb_div;
+                       args.v1.ucPostDiv = post_div;
+                       args.v1.ucPpll =
                            radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1;
-                       spc1_ptr->ucCRTC = radeon_crtc->crtc_id;
-                       spc1_ptr->ucRefDivSrc = 1;
+                       args.v1.ucCRTC = radeon_crtc->crtc_id;
+                       args.v1.ucRefDivSrc = 1;
                        break;
                case 2:
-                       spc2_ptr =
-                           (PIXEL_CLOCK_PARAMETERS_V2 *) & args.sPCLKInput;
-                       spc2_ptr->usPixelClock = cpu_to_le16(mode->clock / 10);
-                       spc2_ptr->usRefDiv = cpu_to_le16(ref_div);
-                       spc2_ptr->usFbDiv = cpu_to_le16(fb_div);
-                       spc2_ptr->ucFracFbDiv = frac_fb_div;
-                       spc2_ptr->ucPostDiv = post_div;
-                       spc2_ptr->ucPpll =
+                       args.v2.usPixelClock = cpu_to_le16(mode->clock / 10);
+                       args.v2.usRefDiv = cpu_to_le16(ref_div);
+                       args.v2.usFbDiv = cpu_to_le16(fb_div);
+                       args.v2.ucFracFbDiv = frac_fb_div;
+                       args.v2.ucPostDiv = post_div;
+                       args.v2.ucPpll =
                            radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1;
-                       spc2_ptr->ucCRTC = radeon_crtc->crtc_id;
-                       spc2_ptr->ucRefDivSrc = 1;
+                       args.v2.ucCRTC = radeon_crtc->crtc_id;
+                       args.v2.ucRefDivSrc = 1;
                        break;
                case 3:
-                       if (!encoder)
-                               return;
-                       spc3_ptr =
-                           (PIXEL_CLOCK_PARAMETERS_V3 *) & args.sPCLKInput;
-                       spc3_ptr->usPixelClock = cpu_to_le16(mode->clock / 10);
-                       spc3_ptr->usRefDiv = cpu_to_le16(ref_div);
-                       spc3_ptr->usFbDiv = cpu_to_le16(fb_div);
-                       spc3_ptr->ucFracFbDiv = frac_fb_div;
-                       spc3_ptr->ucPostDiv = post_div;
-                       spc3_ptr->ucPpll =
+                       args.v3.usPixelClock = cpu_to_le16(mode->clock / 10);
+                       args.v3.usRefDiv = cpu_to_le16(ref_div);
+                       args.v3.usFbDiv = cpu_to_le16(fb_div);
+                       args.v3.ucFracFbDiv = frac_fb_div;
+                       args.v3.ucPostDiv = post_div;
+                       args.v3.ucPpll =
                            radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1;
-                       spc3_ptr->ucMiscInfo = (radeon_crtc->crtc_id << 2);
-                       spc3_ptr->ucTransmitterId = radeon_encoder->encoder_id;
-                       spc3_ptr->ucEncoderMode =
+                       args.v3.ucMiscInfo = (radeon_crtc->crtc_id << 2);
+                       args.v3.ucTransmitterId = radeon_encoder->encoder_id;
+                       args.v3.ucEncoderMode =
                            atombios_get_encoder_mode(encoder);
                        break;
                default:
@@ -571,12 +615,11 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
                return;
        }
 
-       printk("executing set pll\n");
        atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
 }
 
-int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y,
-                          struct drm_framebuffer *old_fb)
+static int avivo_crtc_set_base(struct drm_crtc *crtc, int x, int y,
+                              struct drm_framebuffer *old_fb)
 {
        struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
        struct drm_device *dev = crtc->dev;
@@ -706,6 +749,42 @@ int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y,
        return 0;
 }
 
+int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y,
+                          struct drm_framebuffer *old_fb)
+{
+       struct drm_device *dev = crtc->dev;
+       struct radeon_device *rdev = dev->dev_private;
+
+       if (ASIC_IS_AVIVO(rdev))
+               return avivo_crtc_set_base(crtc, x, y, old_fb);
+       else
+               return radeon_crtc_set_base(crtc, x, y, old_fb);
+}
+
+/* properly set additional regs when using atombios */
+static void radeon_legacy_atom_fixup(struct drm_crtc *crtc)
+{
+       struct drm_device *dev = crtc->dev;
+       struct radeon_device *rdev = dev->dev_private;
+       struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+       u32 disp_merge_cntl;
+
+       switch (radeon_crtc->crtc_id) {
+       case 0:
+               disp_merge_cntl = RREG32(RADEON_DISP_MERGE_CNTL);
+               disp_merge_cntl &= ~RADEON_DISP_RGB_OFFSET_EN;
+               WREG32(RADEON_DISP_MERGE_CNTL, disp_merge_cntl);
+               break;
+       case 1:
+               disp_merge_cntl = RREG32(RADEON_DISP2_MERGE_CNTL);
+               disp_merge_cntl &= ~RADEON_DISP2_RGB_OFFSET_EN;
+               WREG32(RADEON_DISP2_MERGE_CNTL, disp_merge_cntl);
+               WREG32(RADEON_FP_H2_SYNC_STRT_WID,   RREG32(RADEON_CRTC2_H_SYNC_STRT_WID));
+               WREG32(RADEON_FP_V2_SYNC_STRT_WID,   RREG32(RADEON_CRTC2_V_SYNC_STRT_WID));
+               break;
+       }
+}
+
 int atombios_crtc_mode_set(struct drm_crtc *crtc,
                           struct drm_display_mode *mode,
                           struct drm_display_mode *adjusted_mode,
@@ -727,8 +806,8 @@ int atombios_crtc_mode_set(struct drm_crtc *crtc,
        else {
                if (radeon_crtc->crtc_id == 0)
                        atombios_set_crtc_dtd_timing(crtc, adjusted_mode);
-               radeon_crtc_set_base(crtc, x, y, old_fb);
-               radeon_legacy_atom_set_surface(crtc);
+               atombios_crtc_set_base(crtc, x, y, old_fb);
+               radeon_legacy_atom_fixup(crtc);
        }
        atombios_overscan_setup(crtc, mode, adjusted_mode);
        atombios_scaler_setup(crtc);
@@ -746,8 +825,8 @@ static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc,
 
 static void atombios_crtc_prepare(struct drm_crtc *crtc)
 {
-       atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
        atombios_lock_crtc(crtc, 1);
+       atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
 }
 
 static void atombios_crtc_commit(struct drm_crtc *crtc)
index 8760d66..11c9a3f 100644 (file)
@@ -1504,6 +1504,7 @@ static int r100_packet3_check(struct radeon_cs_parser *p,
                        DRM_ERROR("PRIM_WALK must be 3 for IMMD draw\n");
                        return -EINVAL;
                }
+               track->vtx_size = r100_get_vtx_size(radeon_get_ib_value(p, idx + 0));
                track->vap_vf_cntl = radeon_get_ib_value(p, idx + 1);
                track->immd_dwords = pkt->count - 1;
                r = r100_cs_track_check(p->rdev, track);
@@ -3399,9 +3400,7 @@ int r100_mc_init(struct radeon_device *rdev)
        if (rdev->flags & RADEON_IS_AGP) {
                r = radeon_agp_init(rdev);
                if (r) {
-                       printk(KERN_WARNING "[drm] Disabling AGP\n");
-                       rdev->flags &= ~RADEON_IS_AGP;
-                       rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
+                       radeon_agp_disable(rdev);
                } else {
                        rdev->mc.gtt_location = rdev->mc.agp_base;
                }
index 2094212..ff1e0cd 100644 (file)
@@ -371,13 +371,16 @@ int r200_packet0_check(struct radeon_cs_parser *p,
                case 5:
                case 6:
                case 7:
+                       /* 1D/2D */
                        track->textures[i].tex_coord_type = 0;
                        break;
                case 1:
-                       track->textures[i].tex_coord_type = 1;
+                       /* CUBE */
+                       track->textures[i].tex_coord_type = 2;
                        break;
                case 2:
-                       track->textures[i].tex_coord_type = 2;
+                       /* 3D */
+                       track->textures[i].tex_coord_type = 1;
                        break;
                }
                break;
index 053404e..4526faa 100644 (file)
@@ -50,9 +50,7 @@ int r420_mc_init(struct radeon_device *rdev)
        if (rdev->flags & RADEON_IS_AGP) {
                r = radeon_agp_init(rdev);
                if (r) {
-                       printk(KERN_WARNING "[drm] Disabling AGP\n");
-                       rdev->flags &= ~RADEON_IS_AGP;
-                       rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
+                       radeon_agp_disable(rdev);
                } else {
                        rdev->mc.gtt_location = rdev->mc.agp_base;
                }
index f5ff349..da9aa3c 100644 (file)
@@ -624,7 +624,6 @@ int r600_mc_init(struct radeon_device *rdev)
        fixed20_12 a;
        u32 tmp;
        int chansize, numchan;
-       int r;
 
        /* Get VRAM informations */
        rdev->mc.vram_is_ddr = true;
@@ -667,9 +666,6 @@ int r600_mc_init(struct radeon_device *rdev)
                rdev->mc.real_vram_size = rdev->mc.aper_size;
 
        if (rdev->flags & RADEON_IS_AGP) {
-               r = radeon_agp_init(rdev);
-               if (r)
-                       return r;
                /* gtt_size is setup by radeon_agp_init */
                rdev->mc.gtt_location = rdev->mc.agp_base;
                tmp = 0xFFFFFFFFUL - rdev->mc.agp_base - rdev->mc.gtt_size;
@@ -1958,14 +1954,17 @@ int r600_suspend(struct radeon_device *rdev)
        /* FIXME: we should wait for ring to be empty */
        r600_cp_stop(rdev);
        rdev->cp.ready = false;
+       r600_irq_suspend(rdev);
        r600_wb_disable(rdev);
        r600_pcie_gart_disable(rdev);
        /* unpin shaders bo */
-       r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
-       if (unlikely(r != 0))
-               return r;
-       radeon_bo_unpin(rdev->r600_blit.shader_obj);
-       radeon_bo_unreserve(rdev->r600_blit.shader_obj);
+       if (rdev->r600_blit.shader_obj) {
+               r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
+               if (!r) {
+                       radeon_bo_unpin(rdev->r600_blit.shader_obj);
+                       radeon_bo_unreserve(rdev->r600_blit.shader_obj);
+               }
+       }
        return 0;
 }
 
@@ -2026,6 +2025,11 @@ int r600_init(struct radeon_device *rdev)
        r = radeon_fence_driver_init(rdev);
        if (r)
                return r;
+       if (rdev->flags & RADEON_IS_AGP) {
+               r = radeon_agp_init(rdev);
+               if (r)
+                       radeon_agp_disable(rdev);
+       }
        r = r600_mc_init(rdev);
        if (r)
                return r;
@@ -2060,13 +2064,14 @@ int r600_init(struct radeon_device *rdev)
        if (rdev->accel_working) {
                r = radeon_ib_pool_init(rdev);
                if (r) {
-                       DRM_ERROR("radeon: failed initializing IB pool (%d).\n", r);
-                       rdev->accel_working = false;
-               }
-               r = r600_ib_test(rdev);
-               if (r) {
-                       DRM_ERROR("radeon: failed testing IB (%d).\n", r);
+                       dev_err(rdev->dev, "IB initialization failed (%d).\n", r);
                        rdev->accel_working = false;
+               } else {
+                       r = r600_ib_test(rdev);
+                       if (r) {
+                               dev_err(rdev->dev, "IB test failed (%d).\n", r);
+                               rdev->accel_working = false;
+                       }
                }
        }
 
@@ -2197,14 +2202,14 @@ void r600_ih_ring_init(struct radeon_device *rdev, unsigned ring_size)
        rb_bufsz = drm_order(ring_size / 4);
        ring_size = (1 << rb_bufsz) * 4;
        rdev->ih.ring_size = ring_size;
-       rdev->ih.align_mask = 4 - 1;
+       rdev->ih.ptr_mask = rdev->ih.ring_size - 1;
+       rdev->ih.rptr = 0;
 }
 
-static int r600_ih_ring_alloc(struct radeon_device *rdev, unsigned ring_size)
+static int r600_ih_ring_alloc(struct radeon_device *rdev)
 {
        int r;
 
-       rdev->ih.ring_size = ring_size;
        /* Allocate ring buffer */
        if (rdev->ih.ring_obj == NULL) {
                r = radeon_bo_create(rdev, NULL, rdev->ih.ring_size,
@@ -2234,9 +2239,6 @@ static int r600_ih_ring_alloc(struct radeon_device *rdev, unsigned ring_size)
                        return r;
                }
        }
-       rdev->ih.ptr_mask = (rdev->cp.ring_size / 4) - 1;
-       rdev->ih.rptr = 0;
-
        return 0;
 }
 
@@ -2386,7 +2388,7 @@ int r600_irq_init(struct radeon_device *rdev)
        u32 interrupt_cntl, ih_cntl, ih_rb_cntl;
 
        /* allocate ring */
-       ret = r600_ih_ring_alloc(rdev, rdev->ih.ring_size);
+       ret = r600_ih_ring_alloc(rdev);
        if (ret)
                return ret;
 
@@ -2449,10 +2451,15 @@ int r600_irq_init(struct radeon_device *rdev)
        return ret;
 }
 
-void r600_irq_fini(struct radeon_device *rdev)
+void r600_irq_suspend(struct radeon_device *rdev)
 {
        r600_disable_interrupts(rdev);
        r600_rlc_stop(rdev);
+}
+
+void r600_irq_fini(struct radeon_device *rdev)
+{
+       r600_irq_suspend(rdev);
        r600_ih_ring_fini(rdev);
 }
 
@@ -2467,8 +2474,12 @@ int r600_irq_set(struct radeon_device *rdev)
                return -EINVAL;
        }
        /* don't enable anything if the ih is disabled */
-       if (!rdev->ih.enabled)
+       if (!rdev->ih.enabled) {
+               r600_disable_interrupts(rdev);
+               /* force the active interrupt state to all disabled */
+               r600_disable_interrupt_state(rdev);
                return 0;
+       }
 
        if (ASIC_IS_DCE3(rdev)) {
                hpd1 = RREG32(DC_HPD1_INT_CONTROL) & ~DC_HPDx_INT_EN;
@@ -2638,16 +2649,18 @@ static inline u32 r600_get_ih_wptr(struct radeon_device *rdev)
        wptr = RREG32(IH_RB_WPTR);
 
        if (wptr & RB_OVERFLOW) {
-               WARN_ON(1);
-               /* XXX deal with overflow */
-               DRM_ERROR("IH RB overflow\n");
+               /* When a ring buffer overflow happen start parsing interrupt
+                * from the last not overwritten vector (wptr + 16). Hopefully
+                * this should allow us to catchup.
+                */
+               dev_warn(rdev->dev, "IH ring buffer overflow (0x%08X, %d, %d)\n",
+                       wptr, rdev->ih.rptr, (wptr + 16) + rdev->ih.ptr_mask);
+               rdev->ih.rptr = (wptr + 16) & rdev->ih.ptr_mask;
                tmp = RREG32(IH_RB_CNTL);
                tmp |= IH_WPTR_OVERFLOW_CLEAR;
                WREG32(IH_RB_CNTL, tmp);
        }
-       wptr = wptr & WPTR_OFFSET_MASK;
-
-       return wptr;
+       return (wptr & rdev->ih.ptr_mask);
 }
 
 /*        r600 IV Ring
@@ -2683,12 +2696,13 @@ int r600_irq_process(struct radeon_device *rdev)
        u32 wptr = r600_get_ih_wptr(rdev);
        u32 rptr = rdev->ih.rptr;
        u32 src_id, src_data;
-       u32 last_entry = rdev->ih.ring_size - 16;
        u32 ring_index, disp_int, disp_int_cont, disp_int_cont2;
        unsigned long flags;
        bool queue_hotplug = false;
 
        DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr);
+       if (!rdev->ih.enabled)
+               return IRQ_NONE;
 
        spin_lock_irqsave(&rdev->ih.lock, flags);
 
@@ -2817,10 +2831,8 @@ restart_ih:
                }
 
                /* wptr/rptr are in bytes! */
-               if (rptr == last_entry)
-                       rptr = 0;
-               else
-                       rptr += 16;
+               rptr += 16;
+               rptr &= rdev->ih.ptr_mask;
        }
        /* make sure wptr hasn't changed while processing */
        wptr = r600_get_ih_wptr(rdev);
index 8787ea8..2bedce4 100644 (file)
@@ -512,14 +512,16 @@ void r600_blit_fini(struct radeon_device *rdev)
 {
        int r;
 
+       if (rdev->r600_blit.shader_obj == NULL)
+               return;
+       /* If we can't reserve the bo, unref should be enough to destroy
+        * it when it becomes idle.
+        */
        r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
-       if (unlikely(r != 0)) {
-               dev_err(rdev->dev, "(%d) can't finish r600 blit\n", r);
-               goto out_unref;
+       if (!r) {
+               radeon_bo_unpin(rdev->r600_blit.shader_obj);
+               radeon_bo_unreserve(rdev->r600_blit.shader_obj);
        }
-       radeon_bo_unpin(rdev->r600_blit.shader_obj);
-       radeon_bo_unreserve(rdev->r600_blit.shader_obj);
-out_unref:
        radeon_bo_unref(&rdev->r600_blit.shader_obj);
 }
 
index 44060b9..e4c45ec 100644 (file)
@@ -36,6 +36,10 @@ static int r600_cs_packet_next_reloc_nomm(struct radeon_cs_parser *p,
 typedef int (*next_reloc_t)(struct radeon_cs_parser*, struct radeon_cs_reloc**);
 static next_reloc_t r600_cs_packet_next_reloc = &r600_cs_packet_next_reloc_mm;
 
+struct r600_cs_track {
+       u32     cb_color0_base_last;
+};
+
 /**
  * r600_cs_packet_parse() - parse cp packet and point ib index to next packet
  * @parser:    parser structure holding parsing context.
@@ -176,6 +180,28 @@ static int r600_cs_packet_next_reloc_nomm(struct radeon_cs_parser *p,
        return 0;
 }
 
+/**
+ * r600_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 r600_cs_packet_next_is_pkt3_nop(struct radeon_cs_parser *p)
+{
+       struct radeon_cs_packet p3reloc;
+       int r;
+
+       r = r600_cs_packet_parse(p, &p3reloc, p->idx);
+       if (r) {
+               return 0;
+       }
+       if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) {
+               return 0;
+       }
+       return 1;
+}
+
 /**
  * r600_cs_packet_next_vline() - parse userspace VLINE packet
  * @parser:            parser structure holding parsing context.
@@ -337,6 +363,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
                                struct radeon_cs_packet *pkt)
 {
        struct radeon_cs_reloc *reloc;
+       struct r600_cs_track *track;
        volatile u32 *ib;
        unsigned idx;
        unsigned i;
@@ -344,6 +371,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
        int r;
        u32 idx_value;
 
+       track = (struct r600_cs_track *)p->track;
        ib = p->ib->ptr;
        idx = pkt->idx + 1;
        idx_value = radeon_get_ib_value(p, idx);
@@ -503,9 +531,60 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
                for (i = 0; i < pkt->count; i++) {
                        reg = start_reg + (4 * i);
                        switch (reg) {
+                       /* This register were added late, there is userspace
+                        * which does provide relocation for those but set
+                        * 0 offset. In order to avoid breaking old userspace
+                        * we detect this and set address to point to last
+                        * CB_COLOR0_BASE, note that if userspace doesn't set
+                        * CB_COLOR0_BASE before this register we will report
+                        * error. Old userspace always set CB_COLOR0_BASE
+                        * before any of this.
+                        */
+                       case R_0280E0_CB_COLOR0_FRAG:
+                       case R_0280E4_CB_COLOR1_FRAG:
+                       case R_0280E8_CB_COLOR2_FRAG:
+                       case R_0280EC_CB_COLOR3_FRAG:
+                       case R_0280F0_CB_COLOR4_FRAG:
+                       case R_0280F4_CB_COLOR5_FRAG:
+                       case R_0280F8_CB_COLOR6_FRAG:
+                       case R_0280FC_CB_COLOR7_FRAG:
+                       case R_0280C0_CB_COLOR0_TILE:
+                       case R_0280C4_CB_COLOR1_TILE:
+                       case R_0280C8_CB_COLOR2_TILE:
+                       case R_0280CC_CB_COLOR3_TILE:
+                       case R_0280D0_CB_COLOR4_TILE:
+                       case R_0280D4_CB_COLOR5_TILE:
+                       case R_0280D8_CB_COLOR6_TILE:
+                       case R_0280DC_CB_COLOR7_TILE:
+                               if (!r600_cs_packet_next_is_pkt3_nop(p)) {
+                                       if (!track->cb_color0_base_last) {
+                                               dev_err(p->dev, "Broken old userspace ? no cb_color0_base supplied before trying to write 0x%08X\n", reg);
+                                               return -EINVAL;
+                                       }
+                                       ib[idx+1+i] = track->cb_color0_base_last;
+                                       printk_once(KERN_WARNING "radeon: You have old & broken userspace "
+                                               "please consider updating mesa & xf86-video-ati\n");
+                               } else {
+                                       r = r600_cs_packet_next_reloc(p, &reloc);
+                                       if (r) {
+                                               dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
+                                               return -EINVAL;
+                                       }
+                                       ib[idx+1+i] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+                               }
+                               break;
                        case DB_DEPTH_BASE:
                        case DB_HTILE_DATA_BASE:
                        case CB_COLOR0_BASE:
+                               r = r600_cs_packet_next_reloc(p, &reloc);
+                               if (r) {
+                                       DRM_ERROR("bad SET_CONTEXT_REG "
+                                                       "0x%04X\n", reg);
+                                       return -EINVAL;
+                               }
+                               ib[idx+1+i] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+                               track->cb_color0_base_last = ib[idx+1+i];
+                               break;
                        case CB_COLOR1_BASE:
                        case CB_COLOR2_BASE:
                        case CB_COLOR3_BASE:
@@ -678,8 +757,11 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
 int r600_cs_parse(struct radeon_cs_parser *p)
 {
        struct radeon_cs_packet pkt;
+       struct r600_cs_track *track;
        int r;
 
+       track = kzalloc(sizeof(*track), GFP_KERNEL);
+       p->track = track;
        do {
                r = r600_cs_packet_parse(p, &pkt, p->idx);
                if (r) {
@@ -757,6 +839,7 @@ int r600_cs_legacy(struct drm_device *dev, void *data, struct drm_file *filp,
        /* initialize parser */
        memset(&parser, 0, sizeof(struct radeon_cs_parser));
        parser.filp = filp;
+       parser.dev = &dev->pdev->dev;
        parser.rdev = NULL;
        parser.family = family;
        parser.ib = &fake_ib;
index 05894ed..3048088 100644 (file)
 #define                S_000E60_SOFT_RESET_VMC(x)              (((x) & 1) << 17)
 
 #define R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL          0x5480
+
+#define R_0280E0_CB_COLOR0_FRAG                      0x0280E0
+#define   S_0280E0_BASE_256B(x)                        (((x) & 0xFFFFFFFF) << 0)
+#define   G_0280E0_BASE_256B(x)                        (((x) >> 0) & 0xFFFFFFFF)
+#define   C_0280E0_BASE_256B                           0x00000000
+#define R_0280E4_CB_COLOR1_FRAG                      0x0280E4
+#define R_0280E8_CB_COLOR2_FRAG                      0x0280E8
+#define R_0280EC_CB_COLOR3_FRAG                      0x0280EC
+#define R_0280F0_CB_COLOR4_FRAG                      0x0280F0
+#define R_0280F4_CB_COLOR5_FRAG                      0x0280F4
+#define R_0280F8_CB_COLOR6_FRAG                      0x0280F8
+#define R_0280FC_CB_COLOR7_FRAG                      0x0280FC
+#define R_0280C0_CB_COLOR0_TILE                      0x0280C0
+#define   S_0280C0_BASE_256B(x)                        (((x) & 0xFFFFFFFF) << 0)
+#define   G_0280C0_BASE_256B(x)                        (((x) >> 0) & 0xFFFFFFFF)
+#define   C_0280C0_BASE_256B                           0x00000000
+#define R_0280C4_CB_COLOR1_TILE                      0x0280C4
+#define R_0280C8_CB_COLOR2_TILE                      0x0280C8
+#define R_0280CC_CB_COLOR3_TILE                      0x0280CC
+#define R_0280D0_CB_COLOR4_TILE                      0x0280D0
+#define R_0280D4_CB_COLOR5_TILE                      0x0280D4
+#define R_0280D8_CB_COLOR6_TILE                      0x0280D8
+#define R_0280DC_CB_COLOR7_TILE                      0x0280DC
+
+
 #endif
index eb5f99b..f7df1a7 100644 (file)
@@ -410,7 +410,6 @@ struct r600_ih {
        unsigned                wptr_old;
        unsigned                ring_size;
        uint64_t                gpu_addr;
-       uint32_t                align_mask;
        uint32_t                ptr_mask;
        spinlock_t              lock;
        bool                    enabled;
@@ -465,6 +464,7 @@ struct radeon_cs_chunk {
 };
 
 struct radeon_cs_parser {
+       struct device           *dev;
        struct radeon_device    *rdev;
        struct drm_file         *filp;
        /* chunks */
@@ -847,7 +847,7 @@ void r600_kms_blit_copy(struct radeon_device *rdev,
 
 static inline uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg)
 {
-       if (reg < 0x10000)
+       if (reg < rdev->rmmio_size)
                return readl(((void __iomem *)rdev->rmmio) + reg);
        else {
                writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
@@ -857,7 +857,7 @@ static inline uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg)
 
 static inline void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
 {
-       if (reg < 0x10000)
+       if (reg < rdev->rmmio_size)
                writel(v, ((void __iomem *)rdev->rmmio) + reg);
        else {
                writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
@@ -1017,6 +1017,8 @@ static inline void radeon_ring_write(struct radeon_device *rdev, uint32_t v)
 #define radeon_hpd_set_polarity(rdev, hpd) (rdev)->asic->hpd_set_polarity((rdev), (hpd))
 
 /* Common functions */
+/* AGP */
+extern void radeon_agp_disable(struct radeon_device *rdev);
 extern int radeon_gart_table_vram_pin(struct radeon_device *rdev);
 extern int radeon_modeset_init(struct radeon_device *rdev);
 extern void radeon_modeset_fini(struct radeon_device *rdev);
@@ -1160,7 +1162,8 @@ extern int r600_irq_init(struct radeon_device *rdev);
 extern void r600_irq_fini(struct radeon_device *rdev);
 extern void r600_ih_ring_init(struct radeon_device *rdev, unsigned ring_size);
 extern int r600_irq_set(struct radeon_device *rdev);
-
+extern void r600_irq_suspend(struct radeon_device *rdev);
+/* r600 audio */
 extern int r600_audio_init(struct radeon_device *rdev);
 extern int r600_audio_tmds_index(struct drm_encoder *encoder);
 extern void r600_audio_set_clock(struct drm_encoder *encoder, int clock);
index 220f454..c9ad7f5 100644 (file)
@@ -133,6 +133,13 @@ int radeon_agp_init(struct radeon_device *rdev)
        bool is_v3;
        int ret;
 
+       if (rdev->ddev->agp->agp_info.aper_size < 32) {
+               dev_warn(rdev->dev, "AGP aperture to small (%dM) "
+                       "need at least 32M, disabling AGP\n",
+                       rdev->ddev->agp->agp_info.aper_size);
+               return -EINVAL;
+       }
+
        /* Acquire AGP. */
        if (!rdev->ddev->agp->acquired) {
                ret = drm_agp_acquire(rdev->ddev);
index 812f24d..73c4405 100644 (file)
@@ -56,7 +56,7 @@ uint32_t radeon_legacy_get_engine_clock(struct radeon_device *rdev)
        else if (post_div == 3)
                sclk >>= 2;
        else if (post_div == 4)
-               sclk >>= 4;
+               sclk >>= 3;
 
        return sclk;
 }
@@ -86,7 +86,7 @@ uint32_t radeon_legacy_get_memory_clock(struct radeon_device *rdev)
        else if (post_div == 3)
                mclk >>= 2;
        else if (post_div == 4)
-               mclk >>= 4;
+               mclk >>= 3;
 
        return mclk;
 }
index 65590a0..1496cb8 100644 (file)
@@ -231,6 +231,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
        memset(&parser, 0, sizeof(struct radeon_cs_parser));
        parser.filp = filp;
        parser.rdev = rdev;
+       parser.dev = rdev->dev;
        r = radeon_cs_parser_init(&parser, data);
        if (r) {
                DRM_ERROR("Failed to initialize parser !\n");
index 0c51f8e..768b150 100644 (file)
@@ -544,6 +544,7 @@ void radeon_agp_disable(struct radeon_device *rdev)
                rdev->asic->gart_tlb_flush = &r100_pci_gart_tlb_flush;
                rdev->asic->gart_set_page = &r100_pci_gart_set_page;
        }
+       rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
 }
 
 void radeon_check_arguments(struct radeon_device *rdev)
index 0ec491e..6a92f99 100644 (file)
@@ -357,7 +357,8 @@ int radeon_ddc_get_modes(struct radeon_connector *radeon_connector)
        if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) ||
            (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP)) {
                struct radeon_connector_atom_dig *dig = radeon_connector->con_priv;
-               if (dig->dp_i2c_bus)
+               if ((dig->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT ||
+                    dig->dp_sink_type == CONNECTOR_OBJECT_ID_eDP) && dig->dp_i2c_bus)
                        radeon_connector->edid = drm_get_edid(&radeon_connector->base, &dig->dp_i2c_bus->adapter);
        }
        if (!radeon_connector->ddc_bus)
@@ -410,11 +411,12 @@ void radeon_compute_pll(struct radeon_pll *pll,
                        uint32_t *fb_div_p,
                        uint32_t *frac_fb_div_p,
                        uint32_t *ref_div_p,
-                       uint32_t *post_div_p,
-                       int flags)
+                       uint32_t *post_div_p)
 {
        uint32_t min_ref_div = pll->min_ref_div;
        uint32_t max_ref_div = pll->max_ref_div;
+       uint32_t min_post_div = pll->min_post_div;
+       uint32_t max_post_div = pll->max_post_div;
        uint32_t min_fractional_feed_div = 0;
        uint32_t max_fractional_feed_div = 0;
        uint32_t best_vco = pll->best_vco;
@@ -430,7 +432,7 @@ void radeon_compute_pll(struct radeon_pll *pll,
        DRM_DEBUG("PLL freq %llu %u %u\n", freq, pll->min_ref_div, pll->max_ref_div);
        freq = freq * 1000;
 
-       if (flags & RADEON_PLL_USE_REF_DIV)
+       if (pll->flags & RADEON_PLL_USE_REF_DIV)
                min_ref_div = max_ref_div = pll->reference_div;
        else {
                while (min_ref_div < max_ref_div-1) {
@@ -445,19 +447,22 @@ void radeon_compute_pll(struct radeon_pll *pll,
                }
        }
 
-       if (flags & RADEON_PLL_USE_FRAC_FB_DIV) {
+       if (pll->flags & RADEON_PLL_USE_POST_DIV)
+               min_post_div = max_post_div = pll->post_div;
+
+       if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV) {
                min_fractional_feed_div = pll->min_frac_feedback_div;
                max_fractional_feed_div = pll->max_frac_feedback_div;
        }
 
-       for (post_div = pll->min_post_div; post_div <= pll->max_post_div; ++post_div) {
+       for (post_div = min_post_div; post_div <= max_post_div; ++post_div) {
                uint32_t ref_div;
 
-               if ((flags & RADEON_PLL_NO_ODD_POST_DIV) && (post_div & 1))
+               if ((pll->flags & RADEON_PLL_NO_ODD_POST_DIV) && (post_div & 1))
                        continue;
 
                /* legacy radeons only have a few post_divs */
-               if (flags & RADEON_PLL_LEGACY) {
+               if (pll->flags & RADEON_PLL_LEGACY) {
                        if ((post_div == 5) ||
                            (post_div == 7) ||
                            (post_div == 9) ||
@@ -504,7 +509,7 @@ void radeon_compute_pll(struct radeon_pll *pll,
                                        tmp += (uint64_t)pll->reference_freq * 1000 * frac_feedback_div;
                                        current_freq = radeon_div(tmp, ref_div * post_div);
 
-                                       if (flags & RADEON_PLL_PREFER_CLOSEST_LOWER) {
+                                       if (pll->flags & RADEON_PLL_PREFER_CLOSEST_LOWER) {
                                                error = freq - current_freq;
                                                error = error < 0 ? 0xffffffff : error;
                                        } else
@@ -531,12 +536,12 @@ void radeon_compute_pll(struct radeon_pll *pll,
                                                        best_freq = current_freq;
                                                        best_error = error;
                                                        best_vco_diff = vco_diff;
-                                               } else if (((flags & RADEON_PLL_PREFER_LOW_REF_DIV) && (ref_div < best_ref_div)) ||
-                                                          ((flags & RADEON_PLL_PREFER_HIGH_REF_DIV) && (ref_div > best_ref_div)) ||
-                                                          ((flags & RADEON_PLL_PREFER_LOW_FB_DIV) && (feedback_div < best_feedback_div)) ||
-                                                          ((flags & RADEON_PLL_PREFER_HIGH_FB_DIV) && (feedback_div > best_feedback_div)) ||
-                                                          ((flags & RADEON_PLL_PREFER_LOW_POST_DIV) && (post_div < best_post_div)) ||
-                                                          ((flags & RADEON_PLL_PREFER_HIGH_POST_DIV) && (post_div > best_post_div))) {
+                                               } else if (((pll->flags & RADEON_PLL_PREFER_LOW_REF_DIV) && (ref_div < best_ref_div)) ||
+                                                          ((pll->flags & RADEON_PLL_PREFER_HIGH_REF_DIV) && (ref_div > best_ref_div)) ||
+                                                          ((pll->flags & RADEON_PLL_PREFER_LOW_FB_DIV) && (feedback_div < best_feedback_div)) ||
+                                                          ((pll->flags & RADEON_PLL_PREFER_HIGH_FB_DIV) && (feedback_div > best_feedback_div)) ||
+                                                          ((pll->flags & RADEON_PLL_PREFER_LOW_POST_DIV) && (post_div < best_post_div)) ||
+                                                          ((pll->flags & RADEON_PLL_PREFER_HIGH_POST_DIV) && (post_div > best_post_div))) {
                                                        best_post_div = post_div;
                                                        best_ref_div = ref_div;
                                                        best_feedback_div = feedback_div;
@@ -572,8 +577,7 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll,
                              uint32_t *fb_div_p,
                              uint32_t *frac_fb_div_p,
                              uint32_t *ref_div_p,
-                             uint32_t *post_div_p,
-                             int flags)
+                             uint32_t *post_div_p)
 {
        fixed20_12 m, n, frac_n, p, f_vco, f_pclk, best_freq;
        fixed20_12 pll_out_max, pll_out_min;
@@ -667,7 +671,6 @@ static void radeon_user_framebuffer_destroy(struct drm_framebuffer *fb)
                radeonfb_remove(dev, fb);
 
        if (radeon_fb->obj) {
-               radeon_gem_object_unpin(radeon_fb->obj);
                mutex_lock(&dev->struct_mutex);
                drm_gem_object_unreference(radeon_fb->obj);
                mutex_unlock(&dev->struct_mutex);
@@ -715,7 +718,11 @@ radeon_user_framebuffer_create(struct drm_device *dev,
        struct drm_gem_object *obj;
 
        obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handle);
-
+       if (obj ==  NULL) {
+               dev_err(&dev->pdev->dev, "No GEM object associated to handle 0x%08X, "
+                       "can't create framebuffer\n", mode_cmd->handle);
+               return NULL;
+       }
        return radeon_framebuffer_create(dev, mode_cmd, obj);
 }
 
index cc27485..b6d8081 100644 (file)
@@ -339,69 +339,6 @@ void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
        }
 }
 
-/* properly set crtc bpp when using atombios */
-void radeon_legacy_atom_set_surface(struct drm_crtc *crtc)
-{
-       struct drm_device *dev = crtc->dev;
-       struct radeon_device *rdev = dev->dev_private;
-       struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
-       int format;
-       uint32_t crtc_gen_cntl;
-       uint32_t disp_merge_cntl;
-       uint32_t crtc_pitch;
-
-       switch (crtc->fb->bits_per_pixel) {
-       case 8:
-               format = 2;
-               break;
-       case 15:      /*  555 */
-               format = 3;
-               break;
-       case 16:      /*  565 */
-               format = 4;
-               break;
-       case 24:      /*  RGB */
-               format = 5;
-               break;
-       case 32:      /* xRGB */
-               format = 6;
-               break;
-       default:
-               return;
-       }
-
-       crtc_pitch  = ((((crtc->fb->pitch / (crtc->fb->bits_per_pixel / 8)) * crtc->fb->bits_per_pixel) +
-                       ((crtc->fb->bits_per_pixel * 8) - 1)) /
-                      (crtc->fb->bits_per_pixel * 8));
-       crtc_pitch |= crtc_pitch << 16;
-
-       WREG32(RADEON_CRTC_PITCH + radeon_crtc->crtc_offset, crtc_pitch);
-
-       switch (radeon_crtc->crtc_id) {
-       case 0:
-               disp_merge_cntl = RREG32(RADEON_DISP_MERGE_CNTL);
-               disp_merge_cntl &= ~RADEON_DISP_RGB_OFFSET_EN;
-               WREG32(RADEON_DISP_MERGE_CNTL, disp_merge_cntl);
-
-               crtc_gen_cntl = RREG32(RADEON_CRTC_GEN_CNTL) & 0xfffff0ff;
-               crtc_gen_cntl |= (format << 8);
-               crtc_gen_cntl |= RADEON_CRTC_EXT_DISP_EN;
-               WREG32(RADEON_CRTC_GEN_CNTL, crtc_gen_cntl);
-               break;
-       case 1:
-               disp_merge_cntl = RREG32(RADEON_DISP2_MERGE_CNTL);
-               disp_merge_cntl &= ~RADEON_DISP2_RGB_OFFSET_EN;
-               WREG32(RADEON_DISP2_MERGE_CNTL, disp_merge_cntl);
-
-               crtc_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL) & 0xfffff0ff;
-               crtc_gen_cntl |= (format << 8);
-               WREG32(RADEON_CRTC2_GEN_CNTL, crtc_gen_cntl);
-               WREG32(RADEON_FP_H2_SYNC_STRT_WID,   RREG32(RADEON_CRTC2_H_SYNC_STRT_WID));
-               WREG32(RADEON_FP_V2_SYNC_STRT_WID,   RREG32(RADEON_CRTC2_V_SYNC_STRT_WID));
-               break;
-       }
-}
-
 int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y,
                         struct drm_framebuffer *old_fb)
 {
@@ -755,7 +692,6 @@ static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
        uint32_t post_divider = 0;
        uint32_t freq = 0;
        uint8_t pll_gain;
-       int pll_flags = RADEON_PLL_LEGACY;
        bool use_bios_divs = false;
        /* PLL registers */
        uint32_t pll_ref_div = 0;
@@ -789,10 +725,12 @@ static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
        else
                pll = &rdev->clock.p1pll;
 
+       pll->flags = RADEON_PLL_LEGACY;
+
        if (mode->clock > 200000) /* range limits??? */
-               pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
+               pll->flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
        else
-               pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
+               pll->flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
 
        list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
                if (encoder->crtc == crtc) {
@@ -804,7 +742,7 @@ static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
                        }
 
                        if (encoder->encoder_type != DRM_MODE_ENCODER_DAC)
-                               pll_flags |= RADEON_PLL_NO_ODD_POST_DIV;
+                               pll->flags |= RADEON_PLL_NO_ODD_POST_DIV;
                        if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS) {
                                if (!rdev->is_atom_bios) {
                                        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
@@ -819,7 +757,7 @@ static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
                                                }
                                        }
                                }
-                               pll_flags |= RADEON_PLL_USE_REF_DIV;
+                               pll->flags |= RADEON_PLL_USE_REF_DIV;
                        }
                }
        }
@@ -829,8 +767,7 @@ static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
        if (!use_bios_divs) {
                radeon_compute_pll(pll, mode->clock,
                                   &freq, &feedback_div, &frac_fb_div,
-                                  &reference_div, &post_divider,
-                                  pll_flags);
+                                  &reference_div, &post_divider);
 
                for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
                        if (post_div->divider == post_divider)
index 91cb041..96b851f 100644 (file)
@@ -125,16 +125,24 @@ struct radeon_tmds_pll {
 #define RADEON_PLL_PREFER_HIGH_POST_DIV (1 << 9)
 #define RADEON_PLL_USE_FRAC_FB_DIV      (1 << 10)
 #define RADEON_PLL_PREFER_CLOSEST_LOWER (1 << 11)
+#define RADEON_PLL_USE_POST_DIV         (1 << 12)
 
 struct radeon_pll {
-       uint16_t reference_freq;
-       uint16_t reference_div;
+       /* reference frequency */
+       uint32_t reference_freq;
+
+       /* fixed dividers */
+       uint32_t reference_div;
+       uint32_t post_div;
+
+       /* pll in/out limits */
        uint32_t pll_in_min;
        uint32_t pll_in_max;
        uint32_t pll_out_min;
        uint32_t pll_out_max;
-       uint16_t xclk;
+       uint32_t best_vco;
 
+       /* divider limits */
        uint32_t min_ref_div;
        uint32_t max_ref_div;
        uint32_t min_post_div;
@@ -143,7 +151,12 @@ struct radeon_pll {
        uint32_t max_feedback_div;
        uint32_t min_frac_feedback_div;
        uint32_t max_frac_feedback_div;
-       uint32_t best_vco;
+
+       /* flags for the current clock */
+       uint32_t flags;
+
+       /* pll id */
+       uint32_t id;
 };
 
 struct radeon_i2c_chan {
@@ -417,8 +430,7 @@ extern void radeon_compute_pll(struct radeon_pll *pll,
                               uint32_t *fb_div_p,
                               uint32_t *frac_fb_div_p,
                               uint32_t *ref_div_p,
-                              uint32_t *post_div_p,
-                              int flags);
+                              uint32_t *post_div_p);
 
 extern void radeon_compute_pll_avivo(struct radeon_pll *pll,
                                     uint64_t freq,
@@ -426,8 +438,7 @@ extern void radeon_compute_pll_avivo(struct radeon_pll *pll,
                                     uint32_t *fb_div_p,
                                     uint32_t *frac_fb_div_p,
                                     uint32_t *ref_div_p,
-                                    uint32_t *post_div_p,
-                                    int flags);
+                                    uint32_t *post_div_p);
 
 extern void radeon_setup_encoder_clones(struct drm_device *dev);
 
@@ -453,7 +464,6 @@ extern void atombios_crtc_dpms(struct drm_crtc *crtc, int mode);
 
 extern int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y,
                                 struct drm_framebuffer *old_fb);
-extern void radeon_legacy_atom_set_surface(struct drm_crtc *crtc);
 
 extern int radeon_crtc_cursor_set(struct drm_crtc *crtc,
                                  struct drm_file *file_priv,
index 4e636de..d72a71b 100644 (file)
@@ -220,7 +220,8 @@ int radeon_bo_unpin(struct radeon_bo *bo)
 
 int radeon_bo_evict_vram(struct radeon_device *rdev)
 {
-       if (rdev->flags & RADEON_IS_IGP) {
+       /* late 2.6.33 fix IGP hibernate - we need pm ops to do this correct */
+       if (0 && (rdev->flags & RADEON_IS_IGP)) {
                if (rdev->mc.igp_sideport_enabled == false)
                        /* Useless to evict on IGP chips */
                        return 0;
index 6021c88..c29ac43 100644 (file)
@@ -91,6 +91,8 @@ r200 0x3294
 0x22b8 SE_TCL_TEX_CYL_WRAP_CTL
 0x22c0 SE_TCL_UCP_VERT_BLEND_CNTL
 0x22c4 SE_TCL_POINT_SPRITE_CNTL
+0x22d0 SE_PVS_CNTL
+0x22d4 SE_PVS_CONST_CNTL
 0x2648 RE_POINTSIZE
 0x26c0 RE_TOP_LEFT
 0x26c4 RE_MISC
index 59c7124..55f6ffc 100644 (file)
@@ -779,7 +779,6 @@ int rv770_mc_init(struct radeon_device *rdev)
        fixed20_12 a;
        u32 tmp;
        int chansize, numchan;
-       int r;
 
        /* Get VRAM informations */
        rdev->mc.vram_is_ddr = true;
@@ -822,9 +821,6 @@ int rv770_mc_init(struct radeon_device *rdev)
                rdev->mc.real_vram_size = rdev->mc.aper_size;
 
        if (rdev->flags & RADEON_IS_AGP) {
-               r = radeon_agp_init(rdev);
-               if (r)
-                       return r;
                /* gtt_size is setup by radeon_agp_init */
                rdev->mc.gtt_location = rdev->mc.agp_base;
                tmp = 0xFFFFFFFFUL - rdev->mc.agp_base - rdev->mc.gtt_size;
@@ -972,13 +968,16 @@ int rv770_suspend(struct radeon_device *rdev)
        /* FIXME: we should wait for ring to be empty */
        r700_cp_stop(rdev);
        rdev->cp.ready = false;
+       r600_irq_suspend(rdev);
        r600_wb_disable(rdev);
        rv770_pcie_gart_disable(rdev);
        /* unpin shaders bo */
-       r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
-       if (likely(r == 0)) {
-               radeon_bo_unpin(rdev->r600_blit.shader_obj);
-               radeon_bo_unreserve(rdev->r600_blit.shader_obj);
+       if (rdev->r600_blit.shader_obj) {
+               r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
+               if (likely(r == 0)) {
+                       radeon_bo_unpin(rdev->r600_blit.shader_obj);
+                       radeon_bo_unreserve(rdev->r600_blit.shader_obj);
+               }
        }
        return 0;
 }
@@ -1037,6 +1036,11 @@ int rv770_init(struct radeon_device *rdev)
        r = radeon_fence_driver_init(rdev);
        if (r)
                return r;
+       if (rdev->flags & RADEON_IS_AGP) {
+               r = radeon_agp_init(rdev);
+               if (r)
+                       radeon_agp_disable(rdev);
+       }
        r = rv770_mc_init(rdev);
        if (r)
                return r;
@@ -1071,13 +1075,14 @@ int rv770_init(struct radeon_device *rdev)
        if (rdev->accel_working) {
                r = radeon_ib_pool_init(rdev);
                if (r) {
-                       DRM_ERROR("radeon: failed initializing IB pool (%d).\n", r);
-                       rdev->accel_working = false;
-               }
-               r = r600_ib_test(rdev);
-               if (r) {
-                       DRM_ERROR("radeon: failed testing IB (%d).\n", r);
+                       dev_err(rdev->dev, "IB initialization failed (%d).\n", r);
                        rdev->accel_working = false;
+               } else {
+                       r = r600_ib_test(rdev);
+                       if (r) {
+                               dev_err(rdev->dev, "IB test failed (%d).\n", r);
+                               rdev->accel_working = false;
+                       }
                }
        }
        return 0;
index 2920f9a..1a3e909 100644 (file)
@@ -426,7 +426,8 @@ moved:
                    bdev->man[bo->mem.mem_type].gpu_offset;
                bo->cur_placement = bo->mem.placement;
                spin_unlock(&bo->lock);
-       }
+       } else
+               bo->offset = 0;
 
        return 0;
 
@@ -523,52 +524,44 @@ static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo, bool remove_all)
 static int ttm_bo_delayed_delete(struct ttm_bo_device *bdev, bool remove_all)
 {
        struct ttm_bo_global *glob = bdev->glob;
-       struct ttm_buffer_object *entry, *nentry;
-       struct list_head *list, *next;
-       int ret;
+       struct ttm_buffer_object *entry = NULL;
+       int ret = 0;
 
        spin_lock(&glob->lru_lock);
-       list_for_each_safe(list, next, &bdev->ddestroy) {
-               entry = list_entry(list, struct ttm_buffer_object, ddestroy);
-               nentry = NULL;
+       if (list_empty(&bdev->ddestroy))
+               goto out_unlock;
 
-               /*
-                * Protect the next list entry from destruction while we
-                * unlock the lru_lock.
-                */
+       entry = list_first_entry(&bdev->ddestroy,
+               struct ttm_buffer_object, ddestroy);
+       kref_get(&entry->list_kref);
 
-               if (next != &bdev->ddestroy) {
-                       nentry = list_entry(next, struct ttm_buffer_object,
-                                           ddestroy);
+       for (;;) {
+               struct ttm_buffer_object *nentry = NULL;
+
+               if (entry->ddestroy.next != &bdev->ddestroy) {
+                       nentry = list_first_entry(&entry->ddestroy,
+                               struct ttm_buffer_object, ddestroy);
                        kref_get(&nentry->list_kref);
                }
-               kref_get(&entry->list_kref);
 
                spin_unlock(&glob->lru_lock);
                ret = ttm_bo_cleanup_refs(entry, remove_all);
                kref_put(&entry->list_kref, ttm_bo_release_list);
+               entry = nentry;
+
+               if (ret || !entry)
+                       goto out;
 
                spin_lock(&glob->lru_lock);
-               if (nentry) {
-                       bool next_onlist = !list_empty(next);
-                       spin_unlock(&glob->lru_lock);
-                       kref_put(&nentry->list_kref, ttm_bo_release_list);
-                       spin_lock(&glob->lru_lock);
-                       /*
-                        * Someone might have raced us and removed the
-                        * next entry from the list. We don't bother restarting
-                        * list traversal.
-                        */
-
-                       if (!next_onlist)
-                               break;
-               }
-               if (ret)
+               if (list_empty(&entry->ddestroy))
                        break;
        }
-       ret = !list_empty(&bdev->ddestroy);
-       spin_unlock(&glob->lru_lock);
 
+out_unlock:
+       spin_unlock(&glob->lru_lock);
+out:
+       if (entry)
+               kref_put(&entry->list_kref, ttm_bo_release_list);
        return ret;
 }
 
@@ -950,6 +943,14 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo,
                ttm_flag_masked(&cur_flags, placement->busy_placement[i],
                                ~TTM_PL_MASK_MEMTYPE);
 
+
+               if (mem_type == TTM_PL_SYSTEM) {
+                       mem->mem_type = mem_type;
+                       mem->placement = cur_flags;
+                       mem->mm_node = NULL;
+                       return 0;
+               }
+
                ret = ttm_bo_mem_force_space(bo, mem_type, placement, mem,
                                                interruptible, no_wait);
                if (ret == 0 && mem->mm_node) {
@@ -1844,6 +1845,9 @@ static int ttm_bo_swapout(struct ttm_mem_shrink *shrink)
         * anyone tries to access a ttm page.
         */
 
+       if (bo->bdev->driver->swap_notify)
+               bo->bdev->driver->swap_notify(bo);
+
        ret = ttm_tt_swapout(bo->ttm, bo->persistant_swap_storage);
 out:
 
@@ -1864,3 +1868,4 @@ void ttm_bo_swapout_all(struct ttm_bo_device *bdev)
        while (ttm_bo_swapout(&bdev->glob->shrink) == 0)
                ;
 }
+EXPORT_SYMBOL(ttm_bo_swapout_all);
index f619ebc..3d172ef 100644 (file)
@@ -288,6 +288,7 @@ void ttm_suspend_unlock(struct ttm_lock *lock)
        wake_up_all(&lock->queue);
        spin_unlock(&lock->lock);
 }
+EXPORT_SYMBOL(ttm_suspend_unlock);
 
 static bool __ttm_suspend_lock(struct ttm_lock *lock)
 {
@@ -309,3 +310,4 @@ void ttm_suspend_lock(struct ttm_lock *lock)
 {
        wait_event(lock->queue, __ttm_suspend_lock(lock));
 }
+EXPORT_SYMBOL(ttm_suspend_lock);
index d6f2d2b..825ebe3 100644 (file)
@@ -48,6 +48,15 @@ struct ttm_placement vmw_vram_placement = {
        .busy_placement = &vram_placement_flags
 };
 
+struct ttm_placement vmw_vram_sys_placement = {
+       .fpfn = 0,
+       .lpfn = 0,
+       .num_placement = 1,
+       .placement = &vram_placement_flags,
+       .num_busy_placement = 1,
+       .busy_placement = &sys_placement_flags
+};
+
 struct ttm_placement vmw_vram_ne_placement = {
        .fpfn = 0,
        .lpfn = 0,
@@ -172,6 +181,18 @@ static int vmw_verify_access(struct ttm_buffer_object *bo, struct file *filp)
        return 0;
 }
 
+static void vmw_move_notify(struct ttm_buffer_object *bo,
+                    struct ttm_mem_reg *new_mem)
+{
+       if (new_mem->mem_type != TTM_PL_SYSTEM)
+               vmw_dmabuf_gmr_unbind(bo);
+}
+
+static void vmw_swap_notify(struct ttm_buffer_object *bo)
+{
+       vmw_dmabuf_gmr_unbind(bo);
+}
+
 /**
  * FIXME: We're using the old vmware polling method to sync.
  * Do this with fences instead.
@@ -225,5 +246,7 @@ struct ttm_bo_driver vmw_bo_driver = {
        .sync_obj_wait = vmw_sync_obj_wait,
        .sync_obj_flush = vmw_sync_obj_flush,
        .sync_obj_unref = vmw_sync_obj_unref,
-       .sync_obj_ref = vmw_sync_obj_ref
+       .sync_obj_ref = vmw_sync_obj_ref,
+       .move_notify = vmw_move_notify,
+       .swap_notify = vmw_swap_notify
 };
index 1db1ef3..dedd121 100644 (file)
@@ -147,6 +147,8 @@ static char *vmw_devname = "vmwgfx";
 
 static int vmw_probe(struct pci_dev *, const struct pci_device_id *);
 static void vmw_master_init(struct vmw_master *);
+static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val,
+                             void *ptr);
 
 static void vmw_print_capabilities(uint32_t capabilities)
 {
@@ -217,6 +219,7 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
 
        dev_priv->dev = dev;
        dev_priv->vmw_chipset = chipset;
+       dev_priv->last_read_sequence = (uint32_t) -100;
        mutex_init(&dev_priv->hw_mutex);
        mutex_init(&dev_priv->cmdbuf_mutex);
        rwlock_init(&dev_priv->resource_lock);
@@ -351,6 +354,9 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
                vmw_fb_init(dev_priv);
        }
 
+       dev_priv->pm_nb.notifier_call = vmwgfx_pm_notifier;
+       register_pm_notifier(&dev_priv->pm_nb);
+
        return 0;
 
 out_no_device:
@@ -385,6 +391,8 @@ static int vmw_driver_unload(struct drm_device *dev)
 
        DRM_INFO(VMWGFX_DRIVER_NAME " unload.\n");
 
+       unregister_pm_notifier(&dev_priv->pm_nb);
+
        if (!dev_priv->stealth) {
                vmw_fb_close(dev_priv);
                vmw_kms_close(dev_priv);
@@ -650,6 +658,57 @@ static void vmw_remove(struct pci_dev *pdev)
        drm_put_dev(dev);
 }
 
+static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val,
+                             void *ptr)
+{
+       struct vmw_private *dev_priv =
+               container_of(nb, struct vmw_private, pm_nb);
+       struct vmw_master *vmaster = dev_priv->active_master;
+
+       switch (val) {
+       case PM_HIBERNATION_PREPARE:
+       case PM_SUSPEND_PREPARE:
+               ttm_suspend_lock(&vmaster->lock);
+
+               /**
+                * This empties VRAM and unbinds all GMR bindings.
+                * Buffer contents is moved to swappable memory.
+                */
+               ttm_bo_swapout_all(&dev_priv->bdev);
+               break;
+       case PM_POST_HIBERNATION:
+       case PM_POST_SUSPEND:
+               ttm_suspend_unlock(&vmaster->lock);
+               break;
+       case PM_RESTORE_PREPARE:
+               break;
+       case PM_POST_RESTORE:
+               break;
+       default:
+               break;
+       }
+       return 0;
+}
+
+/**
+ * These might not be needed with the virtual SVGA device.
+ */
+
+int vmw_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+       pci_save_state(pdev);
+       pci_disable_device(pdev);
+       pci_set_power_state(pdev, PCI_D3hot);
+       return 0;
+}
+
+int vmw_pci_resume(struct pci_dev *pdev)
+{
+       pci_set_power_state(pdev, PCI_D0);
+       pci_restore_state(pdev);
+       return pci_enable_device(pdev);
+}
+
 static struct drm_driver driver = {
        .driver_features = DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED |
        DRIVER_MODESET,
@@ -689,7 +748,9 @@ static struct drm_driver driver = {
                       .name = VMWGFX_DRIVER_NAME,
                       .id_table = vmw_pci_id_list,
                       .probe = vmw_probe,
-                      .remove = vmw_remove
+                      .remove = vmw_remove,
+                      .suspend = vmw_pci_suspend,
+                      .resume = vmw_pci_resume
                       },
        .name = VMWGFX_DRIVER_NAME,
        .desc = VMWGFX_DRIVER_DESC,
index e61bd85..50529a7 100644 (file)
@@ -32,6 +32,7 @@
 #include "drmP.h"
 #include "vmwgfx_drm.h"
 #include "drm_hashtab.h"
+#include "linux/suspend.h"
 #include "ttm/ttm_bo_driver.h"
 #include "ttm/ttm_object.h"
 #include "ttm/ttm_lock.h"
@@ -258,6 +259,7 @@ struct vmw_private {
 
        struct vmw_master *active_master;
        struct vmw_master fbdev_master;
+       struct notifier_block pm_nb;
 };
 
 static inline struct vmw_private *vmw_priv(struct drm_device *dev)
@@ -353,6 +355,7 @@ extern int vmw_dmabuf_to_start_of_vram(struct vmw_private *vmw_priv,
                                       struct vmw_dma_buffer *bo);
 extern int vmw_dmabuf_from_vram(struct vmw_private *vmw_priv,
                                struct vmw_dma_buffer *bo);
+extern void vmw_dmabuf_gmr_unbind(struct ttm_buffer_object *bo);
 extern int vmw_stream_claim_ioctl(struct drm_device *dev, void *data,
                                  struct drm_file *file_priv);
 extern int vmw_stream_unref_ioctl(struct drm_device *dev, void *data,
@@ -401,6 +404,7 @@ extern int vmw_mmap(struct file *filp, struct vm_area_struct *vma);
 
 extern struct ttm_placement vmw_vram_placement;
 extern struct ttm_placement vmw_vram_ne_placement;
+extern struct ttm_placement vmw_vram_sys_placement;
 extern struct ttm_placement vmw_sys_placement;
 extern struct ttm_bo_driver vmw_bo_driver;
 extern int vmw_dma_quiescent(struct drm_device *dev);
index 2e92da5..d69caf9 100644 (file)
@@ -487,6 +487,21 @@ static int vmw_validate_single_buffer(struct vmw_private *dev_priv,
 {
        int ret;
 
+       if (vmw_dmabuf_gmr(bo) != SVGA_GMR_NULL)
+               return 0;
+
+       /**
+        * Put BO in VRAM, only if there is space.
+        */
+
+       ret = ttm_bo_validate(bo, &vmw_vram_sys_placement, true, false);
+       if (unlikely(ret == -ERESTARTSYS))
+               return ret;
+
+       /**
+        * Otherwise, set it up as GMR.
+        */
+
        if (vmw_dmabuf_gmr(bo) != SVGA_GMR_NULL)
                return 0;
 
@@ -494,6 +509,10 @@ static int vmw_validate_single_buffer(struct vmw_private *dev_priv,
        if (likely(ret == 0 || ret == -ERESTARTSYS))
                return ret;
 
+       /**
+        * If that failed, try VRAM again, this time evicting
+        * previous contents.
+        */
 
        ret = ttm_bo_validate(bo, &vmw_vram_placement, true, false);
        return ret;
index 641dde7..4f4f643 100644 (file)
@@ -649,14 +649,6 @@ int vmw_dmabuf_to_start_of_vram(struct vmw_private *vmw_priv,
        if (unlikely(ret != 0))
                goto err_unlock;
 
-       if (vmw_bo->gmr_bound) {
-               vmw_gmr_unbind(vmw_priv, vmw_bo->gmr_id);
-               spin_lock(&bo->glob->lru_lock);
-               ida_remove(&vmw_priv->gmr_ida, vmw_bo->gmr_id);
-               spin_unlock(&bo->glob->lru_lock);
-               vmw_bo->gmr_bound = NULL;
-       }
-
        ret = ttm_bo_validate(bo, &ne_placement, false, false);
        ttm_bo_unreserve(bo);
 err_unlock:
index 01feb48..f7d5f70 100644 (file)
@@ -98,8 +98,7 @@ int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
                 (unsigned int) min,
                 (unsigned int) fifo->capabilities);
 
-       dev_priv->fence_seq = (uint32_t) -100;
-       dev_priv->last_read_sequence = (uint32_t) -100;
+       dev_priv->fence_seq = dev_priv->last_read_sequence;
        iowrite32(dev_priv->last_read_sequence, fifo_mem + SVGA_FIFO_FENCE);
 
        return vmw_fifo_send_fence(dev_priv, &dummy);
index b1af76e..686692d 100644 (file)
@@ -553,9 +553,7 @@ int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer,
        } *cmd;
        int i, increment = 1;
 
-       if (!num_clips ||
-           !(dev_priv->fifo.capabilities &
-             SVGA_FIFO_CAP_SCREEN_OBJECT)) {
+       if (!num_clips) {
                num_clips = 1;
                clips = &norect;
                norect.x1 = norect.y1 = 0;
@@ -574,10 +572,10 @@ int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer,
 
        for (i = 0; i < num_clips; i++, clips += increment) {
                cmd[i].header = cpu_to_le32(SVGA_CMD_UPDATE);
-               cmd[i].body.x = cpu_to_le32(clips[i].x1);
-               cmd[i].body.y = cpu_to_le32(clips[i].y1);
-               cmd[i].body.width = cpu_to_le32(clips[i].x2 - clips[i].x1);
-               cmd[i].body.height = cpu_to_le32(clips[i].y2 - clips[i].y1);
+               cmd[i].body.x = cpu_to_le32(clips->x1);
+               cmd[i].body.y = cpu_to_le32(clips->y1);
+               cmd[i].body.width = cpu_to_le32(clips->x2 - clips->x1);
+               cmd[i].body.height = cpu_to_le32(clips->y2 - clips->y1);
        }
 
        vmw_fifo_commit(dev_priv, sizeof(*cmd) * num_clips);
index bb6e6a0..5b6eabe 100644 (file)
@@ -104,7 +104,6 @@ static int vmw_dmabuf_pin_in_vram(struct vmw_private *dev_priv,
                                  bool pin, bool interruptible)
 {
        struct ttm_buffer_object *bo = &buf->base;
-       struct ttm_bo_global *glob = bo->glob;
        struct ttm_placement *overlay_placement = &vmw_vram_placement;
        int ret;
 
@@ -116,14 +115,6 @@ static int vmw_dmabuf_pin_in_vram(struct vmw_private *dev_priv,
        if (unlikely(ret != 0))
                goto err;
 
-       if (buf->gmr_bound) {
-               vmw_gmr_unbind(dev_priv, buf->gmr_id);
-               spin_lock(&glob->lru_lock);
-               ida_remove(&dev_priv->gmr_ida, buf->gmr_id);
-               spin_unlock(&glob->lru_lock);
-               buf->gmr_bound = NULL;
-       }
-
        if (pin)
                overlay_placement = &vmw_vram_ne_placement;
 
index c012d59..e01db12 100644 (file)
@@ -599,6 +599,27 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
        if (unlikely(ret != 0))
                goto out_err1;
 
+
+       if (srf->flags & (1 << 9) &&
+           srf->num_sizes == 1 &&
+           srf->sizes[0].width == 64 &&
+           srf->sizes[0].height == 64 &&
+           srf->format == SVGA3D_A8R8G8B8) {
+
+               srf->snooper.image = kmalloc(64 * 64 * 4, GFP_KERNEL);
+               /* clear the image */
+               if (srf->snooper.image) {
+                       memset(srf->snooper.image, 0x00, 64 * 64 * 4);
+               } else {
+                       DRM_ERROR("Failed to allocate cursor_image\n");
+                       ret = -ENOMEM;
+                       goto out_err1;
+               }
+       } else {
+               srf->snooper.image = NULL;
+       }
+       srf->snooper.crtc = NULL;
+
        user_srf->base.shareable = false;
        user_srf->base.tfile = NULL;
 
@@ -622,24 +643,6 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
                return ret;
        }
 
-       if (srf->flags & (1 << 9) &&
-           srf->num_sizes == 1 &&
-           srf->sizes[0].width == 64 &&
-           srf->sizes[0].height == 64 &&
-           srf->format == SVGA3D_A8R8G8B8) {
-
-               srf->snooper.image = kmalloc(64 * 64 * 4, GFP_KERNEL);
-               /* clear the image */
-               if (srf->snooper.image)
-                       memset(srf->snooper.image, 0x00, 64 * 64 * 4);
-               else
-                       DRM_ERROR("Failed to allocate cursor_image\n");
-
-       } else {
-               srf->snooper.image = NULL;
-       }
-       srf->snooper.crtc = NULL;
-
        rep->sid = user_srf->base.hash.key;
        if (rep->sid == SVGA3D_INVALID_ID)
                DRM_ERROR("Created bad Surface ID.\n");
@@ -754,20 +757,29 @@ static size_t vmw_dmabuf_acc_size(struct ttm_bo_global *glob,
        return bo_user_size + page_array_size;
 }
 
-void vmw_dmabuf_bo_free(struct ttm_buffer_object *bo)
+void vmw_dmabuf_gmr_unbind(struct ttm_buffer_object *bo)
 {
        struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo);
        struct ttm_bo_global *glob = bo->glob;
        struct vmw_private *dev_priv =
                container_of(bo->bdev, struct vmw_private, bdev);
 
-       ttm_mem_global_free(glob->mem_glob, bo->acc_size);
        if (vmw_bo->gmr_bound) {
                vmw_gmr_unbind(dev_priv, vmw_bo->gmr_id);
                spin_lock(&glob->lru_lock);
                ida_remove(&dev_priv->gmr_ida, vmw_bo->gmr_id);
                spin_unlock(&glob->lru_lock);
+               vmw_bo->gmr_bound = false;
        }
+}
+
+void vmw_dmabuf_bo_free(struct ttm_buffer_object *bo)
+{
+       struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo);
+       struct ttm_bo_global *glob = bo->glob;
+
+       vmw_dmabuf_gmr_unbind(bo);
+       ttm_mem_global_free(glob->mem_glob, bo->acc_size);
        kfree(vmw_bo);
 }
 
@@ -813,18 +825,10 @@ int vmw_dmabuf_init(struct vmw_private *dev_priv,
 static void vmw_user_dmabuf_destroy(struct ttm_buffer_object *bo)
 {
        struct vmw_user_dma_buffer *vmw_user_bo = vmw_user_dma_buffer(bo);
-       struct vmw_dma_buffer *vmw_bo = &vmw_user_bo->dma;
        struct ttm_bo_global *glob = bo->glob;
-       struct vmw_private *dev_priv =
-               container_of(bo->bdev, struct vmw_private, bdev);
 
+       vmw_dmabuf_gmr_unbind(bo);
        ttm_mem_global_free(glob->mem_glob, bo->acc_size);
-       if (vmw_bo->gmr_bound) {
-               vmw_gmr_unbind(dev_priv, vmw_bo->gmr_id);
-               spin_lock(&glob->lru_lock);
-               ida_remove(&dev_priv->gmr_ida, vmw_bo->gmr_id);
-               spin_unlock(&glob->lru_lock);
-       }
        kfree(vmw_user_bo);
 }
 
@@ -868,7 +872,7 @@ int vmw_dmabuf_alloc_ioctl(struct drm_device *dev, void *data,
        }
 
        ret = vmw_dmabuf_init(dev_priv, &vmw_user_bo->dma, req->size,
-                             &vmw_vram_placement, true,
+                             &vmw_vram_sys_placement, true,
                              &vmw_user_dmabuf_destroy);
        if (unlikely(ret != 0))
                return ret;
index 1c89d92..fa9708c 100644 (file)
@@ -686,7 +686,6 @@ static ssize_t set_fan1_div(
                data->fan1_div = 4;
                break;
        default:
-               mutex_unlock(&data->update_lock);
                count = -EINVAL;
                goto EXIT;
        }
index 6811346..028284f 100644 (file)
@@ -1329,17 +1329,16 @@ static int atk_add(struct acpi_device *device)
                        &buf, ACPI_TYPE_PACKAGE);
        if (ret != AE_OK) {
                dev_dbg(&device->dev, "atk: method MBIF not found\n");
-               err = -ENODEV;
-               goto out;
-       }
-
-       obj = buf.pointer;
-       if (obj->package.count >= 2 &&
-                       obj->package.elements[1].type == ACPI_TYPE_STRING) {
-               dev_dbg(&device->dev, "board ID = %s\n",
-                               obj->package.elements[1].string.pointer);
+       } else {
+               obj = buf.pointer;
+               if (obj->package.count >= 2) {
+                       union acpi_object *id = &obj->package.elements[1];
+                       if (id->type == ACPI_TYPE_STRING)
+                               dev_dbg(&device->dev, "board ID = %s\n",
+                                       id->string.pointer);
+               }
+               ACPI_FREE(buf.pointer);
        }
-       ACPI_FREE(buf.pointer);
 
        err = atk_probe_if(data);
        if (err) {
index bd0fc67..fa07282 100644 (file)
@@ -768,6 +768,7 @@ leave:
 static int watchdog_open(struct inode *inode, struct file *filp)
 {
        struct fschmd_data *pos, *data = NULL;
+       int watchdog_is_open;
 
        /* We get called from drivers/char/misc.c with misc_mtx hold, and we
           call misc_register() from fschmd_probe() with watchdog_data_mutex
@@ -782,10 +783,12 @@ static int watchdog_open(struct inode *inode, struct file *filp)
                }
        }
        /* Note we can never not have found data, so we don't check for this */
-       kref_get(&data->kref);
+       watchdog_is_open = test_and_set_bit(0, &data->watchdog_is_open);
+       if (!watchdog_is_open)
+               kref_get(&data->kref);
        mutex_unlock(&watchdog_data_mutex);
 
-       if (test_and_set_bit(0, &data->watchdog_is_open))
+       if (watchdog_is_open)
                return -EBUSY;
 
        /* Start the watchdog */
index 9ca9781..8fa462f 100644 (file)
@@ -488,7 +488,7 @@ static int __init smsc47m1_find(unsigned short *addr,
 }
 
 /* Restore device to its initial state */
-static void __init smsc47m1_restore(const struct smsc47m1_sio_data *sio_data)
+static void smsc47m1_restore(const struct smsc47m1_sio_data *sio_data)
 {
        if ((sio_data->activate & 0x01) == 0) {
                superio_enter();
index e3654d6..75bf820 100644 (file)
@@ -226,7 +226,6 @@ static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx)
                temp = readb(i2c_imx->base + IMX_I2C_I2CR);
                temp &= ~(I2CR_MSTA | I2CR_MTX);
                writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
-               i2c_imx->stopped = 1;
        }
        if (cpu_is_mx1()) {
                /*
@@ -236,8 +235,10 @@ static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx)
                udelay(i2c_imx->disable_delay);
        }
 
-       if (!i2c_imx->stopped)
+       if (!i2c_imx->stopped) {
                i2c_imx_bus_busy(i2c_imx, 0);
+               i2c_imx->stopped = 1;
+       }
 
        /* Disable I2C controller */
        writeb(0, i2c_imx->base + IMX_I2C_I2CR);
@@ -496,22 +497,23 @@ static int __init i2c_imx_probe(struct platform_device *pdev)
        }
 
        res_size = resource_size(res);
+
+       if (!request_mem_region(res->start, res_size, DRIVER_NAME)) {
+               ret = -EBUSY;
+               goto fail0;
+       }
+
        base = ioremap(res->start, res_size);
        if (!base) {
                dev_err(&pdev->dev, "ioremap failed\n");
                ret = -EIO;
-               goto fail0;
+               goto fail1;
        }
 
        i2c_imx = kzalloc(sizeof(struct imx_i2c_struct), GFP_KERNEL);
        if (!i2c_imx) {
                dev_err(&pdev->dev, "can't allocate interface\n");
                ret = -ENOMEM;
-               goto fail1;
-       }
-
-       if (!request_mem_region(res->start, res_size, DRIVER_NAME)) {
-               ret = -EBUSY;
                goto fail2;
        }
 
@@ -582,11 +584,11 @@ fail5:
 fail4:
        clk_put(i2c_imx->clk);
 fail3:
-       release_mem_region(i2c_imx->res->start, resource_size(res));
-fail2:
        kfree(i2c_imx);
-fail1:
+fail2:
        iounmap(base);
+fail1:
+       release_mem_region(res->start, resource_size(res));
 fail0:
        if (pdata && pdata->exit)
                pdata->exit(&pdev->dev);
@@ -618,8 +620,8 @@ static int __exit i2c_imx_remove(struct platform_device *pdev)
 
        clk_put(i2c_imx->clk);
 
-       release_mem_region(i2c_imx->res->start, resource_size(i2c_imx->res));
        iounmap(i2c_imx->base);
+       release_mem_region(i2c_imx->res->start, resource_size(i2c_imx->res));
        kfree(i2c_imx);
        return 0;
 }
index 4c364d4..2de0cc8 100644 (file)
@@ -549,4 +549,21 @@ config MTD_VMU
          To build this as a module select M here, the module will be called
          vmu-flash.
 
+config MTD_PISMO
+       tristate "MTD discovery driver for PISMO modules"
+       depends on I2C
+       depends on ARCH_VERSATILE
+       help
+         This driver allows for discovery of PISMO modules - see
+         <http://www.pismoworld.org/>.  These are small modules containing
+         up to five memory devices (eg, SRAM, flash, DOC) described by an
+         I2C EEPROM.
+
+         This driver does not create any MTD maps itself; instead it
+         creates MTD physmap and MTD SRAM platform devices.  If you
+         enable this option, you should consider enabling MTD_PHYSMAP
+         and/or MTD_PLATRAM according to the devices on your module.
+
+         When built as a module, it will be called pismo.ko
+
 endmenu
diff --git a/drivers/mtd/maps/pismo.c b/drivers/mtd/maps/pismo.c
new file mode 100644 (file)
index 0000000..c48cad2
--- /dev/null
@@ -0,0 +1,320 @@
+/*
+ * PISMO memory driver - http://www.pismoworld.org/
+ *
+ * For ARM Realview and Versatile platforms
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License.
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/mutex.h>
+#include <linux/mtd/physmap.h>
+#include <linux/mtd/plat-ram.h>
+#include <linux/mtd/pismo.h>
+
+#define PISMO_NUM_CS   5
+
+struct pismo_cs_block {
+       u8      type;
+       u8      width;
+       __le16  access;
+       __le32  size;
+       u32     reserved[2];
+       char    device[32];
+} __packed;
+
+struct pismo_eeprom {
+       struct pismo_cs_block cs[PISMO_NUM_CS];
+       char    board[15];
+       u8      sum;
+} __packed;
+
+struct pismo_mem {
+       phys_addr_t base;
+       u32     size;
+       u16     access;
+       u8      width;
+       u8      type;
+};
+
+struct pismo_data {
+       struct i2c_client       *client;
+       void                    (*vpp)(void *, int);
+       void                    *vpp_data;
+       struct platform_device  *dev[PISMO_NUM_CS];
+};
+
+/* FIXME: set_vpp could do with a better calling convention */
+static struct pismo_data *vpp_pismo;
+static DEFINE_MUTEX(pismo_mutex);
+
+static int pismo_setvpp_probe_fix(struct pismo_data *pismo)
+{
+       mutex_lock(&pismo_mutex);
+       if (vpp_pismo) {
+               mutex_unlock(&pismo_mutex);
+               kfree(pismo);
+               return -EBUSY;
+       }
+       vpp_pismo = pismo;
+       mutex_unlock(&pismo_mutex);
+       return 0;
+}
+
+static void pismo_setvpp_remove_fix(struct pismo_data *pismo)
+{
+       mutex_lock(&pismo_mutex);
+       if (vpp_pismo == pismo)
+               vpp_pismo = NULL;
+       mutex_unlock(&pismo_mutex);
+}
+
+static void pismo_set_vpp(struct map_info *map, int on)
+{
+       struct pismo_data *pismo = vpp_pismo;
+
+       pismo->vpp(pismo->vpp_data, on);
+}
+/* end of hack */
+
+
+static unsigned int __devinit pismo_width_to_bytes(unsigned int width)
+{
+       width &= 15;
+       if (width > 2)
+               return 0;
+       return 1 << width;
+}
+
+static int __devinit pismo_eeprom_read(struct i2c_client *client, void *buf,
+       u8 addr, size_t size)
+{
+       int ret;
+       struct i2c_msg msg[] = {
+               {
+                       .addr = client->addr,
+                       .len = sizeof(addr),
+                       .buf = &addr,
+               }, {
+                       .addr = client->addr,
+                       .flags = I2C_M_RD,
+                       .len = size,
+                       .buf = buf,
+               },
+       };
+
+       ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
+
+       return ret == ARRAY_SIZE(msg) ? size : -EIO;
+}
+
+static int __devinit pismo_add_device(struct pismo_data *pismo, int i,
+       struct pismo_mem *region, const char *name, void *pdata, size_t psize)
+{
+       struct platform_device *dev;
+       struct resource res = { };
+       phys_addr_t base = region.base;
+       int ret;
+
+       if (base == ~0)
+               return -ENXIO;
+
+       res.start = base;
+       res.end = base + region->size - 1;
+       res.flags = IORESOURCE_MEM;
+
+       dev = platform_device_alloc(name, i);
+       if (!dev)
+               return -ENOMEM;
+       dev->dev.parent = &pismo->client->dev;
+
+       do {
+               ret = platform_device_add_resources(dev, &res, 1);
+               if (ret)
+                       break;
+
+               ret = platform_device_add_data(dev, pdata, psize);
+               if (ret)
+                       break;
+
+               ret = platform_device_add(dev);
+               if (ret)
+                       break;
+
+               pismo->dev[i] = dev;
+               return 0;
+       } while (0);
+
+       platform_device_put(dev);
+       return ret;
+}
+
+static int __devinit pismo_add_nor(struct pismo_data *pismo, int i,
+       struct pismo_mem *region)
+{
+       struct physmap_flash_data data = {
+               .width = region->width,
+       };
+
+       if (pismo->vpp)
+               data.set_vpp = pismo_set_vpp;
+
+       return pismo_add_device(pismo, i, region, "physmap-flash",
+               &data, sizeof(data));
+}
+
+static int __devinit pismo_add_sram(struct pismo_data *pismo, int i,
+       struct pismo_mem *region)
+{
+       struct platdata_mtd_ram data = {
+               .bankwidth = region->width,
+       };
+
+       return pismo_add_device(pismo, i, region, "mtd-ram",
+               &data, sizeof(data));
+}
+
+static void __devinit pismo_add_one(struct pismo_data *pismo, int i,
+       const struct pismo_cs_block *cs, phys_addr_t base)
+{
+       struct device *dev = &pismo->client->dev;
+       struct pismo_mem region;
+
+       region.base = base;
+       region.type = cs->type;
+       region.width = pismo_width_to_bytes(cs->width);
+       region.access = le16_to_cpu(cs->access);
+       region.size = le32_to_cpu(cs->size);
+
+       if (region.width == 0) {
+               dev_err(dev, "cs%u: bad width: %02x, ignoring\n", i, cs->width);
+               return;
+       }
+
+       /*
+        * FIXME: may need to the platforms memory controller here, but at
+        * the moment we assume that it has already been correctly setup.
+        * The memory controller can also tell us the base address as well.
+        */
+
+       dev_info(dev, "cs%u: %.32s: type %02x access %u00ps size %uK\n",
+               i, cs->device, region.type, region.access, region.size / 1024);
+
+       switch (region.type) {
+       case 0:
+               break;
+       case 1:
+               /* static DOC */
+               break;
+       case 2:
+               /* static NOR */
+               pismo_add_nor(pismo, i, &region);
+               break;
+       case 3:
+               /* static RAM */
+               pismo_add_sram(pismo, i, &region);
+               break;
+       }
+}
+
+static int __devexit pismo_remove(struct i2c_client *client)
+{
+       struct pismo_data *pismo = i2c_get_clientdata(client);
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(pismo->dev); i++)
+               platform_device_unregister(pismo->dev[i]);
+
+       /* FIXME: set_vpp needs saner arguments */
+       pismo_setvpp_remove_fix(pismo);
+
+       kfree(pismo);
+
+       return 0;
+}
+
+static int __devinit pismo_probe(struct i2c_client *client,
+                                const struct i2c_device_id *id)
+{
+       struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+       struct pismo_pdata *pdata = client->dev.platform_data;
+       struct pismo_eeprom eeprom;
+       struct pismo_data *pismo;
+       int ret, i;
+
+       if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
+               dev_err(&client->dev, "functionality mismatch\n");
+               return -EIO;
+       }
+
+       pismo = kzalloc(sizeof(*pismo), GFP_KERNEL);
+       if (!pismo)
+               return -ENOMEM;
+
+       /* FIXME: set_vpp needs saner arguments */
+       ret = pismo_setvpp_probe_fix(pismo);
+       if (ret)
+               return ret;
+
+       pismo->client = client;
+       if (pdata) {
+               pismo->vpp = pdata->set_vpp;
+               pismo->vpp_data = pdata->vpp_data;
+       }
+       i2c_set_clientdata(client, pismo);
+
+       ret = pismo_eeprom_read(client, &eeprom, 0, sizeof(eeprom));
+       if (ret < 0) {
+               dev_err(&client->dev, "error reading EEPROM: %d\n", ret);
+               return ret;
+       }
+
+       dev_info(&client->dev, "%.15s board found\n", eeprom.board);
+
+       for (i = 0; i < ARRAY_SIZE(eeprom.cs); i++)
+               if (eeprom.cs[i].type != 0xff)
+                       pismo_add_one(pismo, i, &eeprom.cs[i],
+                                     pdata->cs_addrs[i]);
+
+       return 0;
+}
+
+static const struct i2c_device_id pismo_id[] = {
+       { "pismo" },
+       { },
+};
+MODULE_DEVICE_TABLE(i2c, pismo_id);
+
+static struct i2c_driver pismo_driver = {
+       .driver = {
+               .name   = "pismo",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = pismo_probe,
+       .remove         = __devexit_p(pismo_remove),
+       .id_table       = pismo_id,
+};
+
+static int __init pismo_init(void)
+{
+       BUILD_BUG_ON(sizeof(struct pismo_cs_block) != 48);
+       BUILD_BUG_ON(sizeof(struct pismo_eeprom) != 256);
+
+       return i2c_add_driver(&pismo_driver);
+}
+module_init(pismo_init);
+
+static void __exit pismo_exit(void)
+{
+       i2c_del_driver(&pismo_driver);
+}
+module_exit(pismo_exit);
+
+MODULE_AUTHOR("Russell King <linux@arm.linux.org.uk>");
+MODULE_DESCRIPTION("PISMO memory driver");
+MODULE_LICENSE("GPL");
index a714ec4..92e12df 100644 (file)
@@ -322,7 +322,7 @@ static void mtdoops_do_dump(struct kmsg_dumper *dumper,
        memcpy(dst + l1_cpy, s2 + s2_start, l2_cpy);
 
        /* Panics must be written immediately */
-       if (reason == KMSG_DUMP_PANIC) {
+       if (reason != KMSG_DUMP_OOPS) {
                if (!cxt->mtd->panic_write)
                        printk(KERN_ERR "mtdoops: Cannot write from panic without panic_write\n");
                else
index 79fc453..25c5dd0 100644 (file)
@@ -147,6 +147,10 @@ static int scan_for_bad_eraseblocks(void)
        }
        memset(bbt, 0 , ebcnt);
 
+       /* NOR flash does not implement block_isbad */
+       if (mtd->block_isbad == NULL)
+               return 0;
+
        printk(PRINT_PREF "scanning for bad eraseblocks\n");
        for (i = 0; i < ebcnt; ++i) {
                bbt[i] = is_block_bad(i) ? 1 : 0;
@@ -184,7 +188,7 @@ static int __init mtd_readtest_init(void)
        tmp = mtd->size;
        do_div(tmp, mtd->erasesize);
        ebcnt = tmp;
-       pgcnt = mtd->erasesize / mtd->writesize;
+       pgcnt = mtd->erasesize / pgsize;
 
        printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, "
               "page size %u, count of eraseblocks %u, pages per "
index 141363a..7fbb51d 100644 (file)
@@ -301,6 +301,10 @@ static int scan_for_bad_eraseblocks(void)
        }
        memset(bbt, 0 , ebcnt);
 
+       /* NOR flash does not implement block_isbad */
+       if (mtd->block_isbad == NULL)
+               goto out;
+
        printk(PRINT_PREF "scanning for bad eraseblocks\n");
        for (i = 0; i < ebcnt; ++i) {
                bbt[i] = is_block_bad(i) ? 1 : 0;
@@ -309,6 +313,7 @@ static int scan_for_bad_eraseblocks(void)
                cond_resched();
        }
        printk(PRINT_PREF "scanned %d eraseblocks, %d are bad\n", i, bad);
+out:
        goodebcnt = ebcnt - bad;
        return 0;
 }
@@ -340,7 +345,7 @@ static int __init mtd_speedtest_init(void)
        tmp = mtd->size;
        do_div(tmp, mtd->erasesize);
        ebcnt = tmp;
-       pgcnt = mtd->erasesize / mtd->writesize;
+       pgcnt = mtd->erasesize / pgsize;
 
        printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, "
               "page size %u, count of eraseblocks %u, pages per "
index 6392047..a99d3cd 100644 (file)
@@ -227,6 +227,10 @@ static int scan_for_bad_eraseblocks(void)
        }
        memset(bbt, 0 , ebcnt);
 
+       /* NOR flash does not implement block_isbad */
+       if (mtd->block_isbad == NULL)
+               return 0;
+
        printk(PRINT_PREF "scanning for bad eraseblocks\n");
        for (i = 0; i < ebcnt; ++i) {
                bbt[i] = is_block_bad(i) ? 1 : 0;
@@ -265,7 +269,7 @@ static int __init mtd_stresstest_init(void)
        tmp = mtd->size;
        do_div(tmp, mtd->erasesize);
        ebcnt = tmp;
-       pgcnt = mtd->erasesize / mtd->writesize;
+       pgcnt = mtd->erasesize / pgsize;
 
        printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, "
               "page size %u, count of eraseblocks %u, pages per "
index 277786e..1361574 100644 (file)
@@ -291,8 +291,7 @@ EXPORT_SYMBOL_GPL(ubi_open_volume_nm);
  */
 struct ubi_volume_desc *ubi_open_volume_path(const char *pathname, int mode)
 {
-       int error, ubi_num, vol_id;
-       struct ubi_volume_desc *ret;
+       int error, ubi_num, vol_id, mod;
        struct inode *inode;
        struct path path;
 
@@ -306,16 +305,16 @@ struct ubi_volume_desc *ubi_open_volume_path(const char *pathname, int mode)
                return ERR_PTR(error);
 
        inode = path.dentry->d_inode;
+       mod = inode->i_mode;
        ubi_num = ubi_major2num(imajor(inode));
        vol_id = iminor(inode) - 1;
+       path_put(&path);
 
+       if (!S_ISCHR(mod))
+               return ERR_PTR(-EINVAL);
        if (vol_id >= 0 && ubi_num >= 0)
-               ret = ubi_open_volume(ubi_num, vol_id, mode);
-       else
-               ret = ERR_PTR(-ENODEV);
-
-       path_put(&path);
-       return ret;
+               return ubi_open_volume(ubi_num, vol_id, mode);
+       return ERR_PTR(-ENODEV);
 }
 EXPORT_SYMBOL_GPL(ubi_open_volume_path);
 
index c1d7b88..425bf5a 100644 (file)
@@ -155,6 +155,7 @@ int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol,
                if (err)
                        return err;
                vol->updating = 0;
+               return 0;
        }
 
        vol->upd_buf = vmalloc(ubi->leb_size);
index 1afc61e..4004402 100644 (file)
@@ -566,6 +566,7 @@ static int init_volumes(struct ubi_device *ubi, const struct ubi_scan_info *si,
                vol->reserved_pebs = be32_to_cpu(vtbl[i].reserved_pebs);
                vol->alignment = be32_to_cpu(vtbl[i].alignment);
                vol->data_pad = be32_to_cpu(vtbl[i].data_pad);
+               vol->upd_marker = vtbl[i].upd_marker;
                vol->vol_type = vtbl[i].vol_type == UBI_VID_DYNAMIC ?
                                        UBI_DYNAMIC_VOLUME : UBI_STATIC_VOLUME;
                vol->name_len = be16_to_cpu(vtbl[i].name_len);
index 102ade1..fee6eee 100644 (file)
@@ -286,7 +286,7 @@ static void be_wrb_hdr_prepare(struct be_mcc_wrb *wrb, int payload_len,
                                MCC_WRB_SGE_CNT_SHIFT;
        wrb->payload_length = payload_len;
        wrb->tag0 = opcode;
-       be_dws_cpu_to_le(wrb, 20);
+       be_dws_cpu_to_le(wrb, 8);
 }
 
 /* Don't touch the hdr after it's prepared */
index 3a1f790..33ab8c7 100644 (file)
@@ -910,7 +910,7 @@ static inline struct page *be_alloc_pages(u32 size)
 static void be_post_rx_frags(struct be_adapter *adapter)
 {
        struct be_rx_page_info *page_info_tbl = adapter->rx_obj.page_info_tbl;
-       struct be_rx_page_info *page_info = NULL;
+       struct be_rx_page_info *page_info = NULL, *prev_page_info = NULL;
        struct be_queue_info *rxq = &adapter->rx_obj.q;
        struct page *pagep = NULL;
        struct be_eth_rx_d *rxd;
@@ -941,7 +941,6 @@ static void be_post_rx_frags(struct be_adapter *adapter)
                rxd = queue_head_node(rxq);
                rxd->fragpa_lo = cpu_to_le32(frag_dmaaddr & 0xFFFFFFFF);
                rxd->fragpa_hi = cpu_to_le32(upper_32_bits(frag_dmaaddr));
-               queue_head_inc(rxq);
 
                /* Any space left in the current big page for another frag? */
                if ((page_offset + rx_frag_size + rx_frag_size) >
@@ -949,10 +948,13 @@ static void be_post_rx_frags(struct be_adapter *adapter)
                        pagep = NULL;
                        page_info->last_page_user = true;
                }
+
+               prev_page_info = page_info;
+               queue_head_inc(rxq);
                page_info = &page_info_tbl[rxq->head];
        }
        if (pagep)
-               page_info->last_page_user = true;
+               prev_page_info->last_page_user = true;
 
        if (posted) {
                atomic_add(posted, &rxq->used);
index 8ffea39..0b23bc4 100644 (file)
@@ -33,6 +33,7 @@
 #include <asm/dma.h>
 #include <linux/dma-mapping.h>
 
+#include <asm/dpmc.h>
 #include <asm/blackfin.h>
 #include <asm/cacheflush.h>
 #include <asm/portmux.h>
@@ -386,8 +387,8 @@ static int mii_probe(struct net_device *dev)
        u32 sclk, mdc_div;
 
        /* Enable PHY output early */
-       if (!(bfin_read_VR_CTL() & PHYCLKOE))
-               bfin_write_VR_CTL(bfin_read_VR_CTL() | PHYCLKOE);
+       if (!(bfin_read_VR_CTL() & CLKBUFOE))
+               bfin_write_VR_CTL(bfin_read_VR_CTL() | CLKBUFOE);
 
        sclk = get_sclk();
        mdc_div = ((sclk / MDC_CLK) / 2) - 1;
index 2a567df..e8932db 100644 (file)
@@ -326,6 +326,8 @@ struct e1000_adapter {
        /* for ioport free */
        int bars;
        int need_ioport;
+
+       bool discarding;
 };
 
 enum e1000_state_t {
index 7e855f9..d29bb53 100644 (file)
@@ -1698,18 +1698,6 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter)
        rctl &= ~E1000_RCTL_SZ_4096;
        rctl |= E1000_RCTL_BSEX;
        switch (adapter->rx_buffer_len) {
-               case E1000_RXBUFFER_256:
-                       rctl |= E1000_RCTL_SZ_256;
-                       rctl &= ~E1000_RCTL_BSEX;
-                       break;
-               case E1000_RXBUFFER_512:
-                       rctl |= E1000_RCTL_SZ_512;
-                       rctl &= ~E1000_RCTL_BSEX;
-                       break;
-               case E1000_RXBUFFER_1024:
-                       rctl |= E1000_RCTL_SZ_1024;
-                       rctl &= ~E1000_RCTL_BSEX;
-                       break;
                case E1000_RXBUFFER_2048:
                default:
                        rctl |= E1000_RCTL_SZ_2048;
@@ -2802,13 +2790,13 @@ static int e1000_tx_map(struct e1000_adapter *adapter,
 dma_error:
        dev_err(&pdev->dev, "TX DMA map failed\n");
        buffer_info->dma = 0;
-       count--;
-
-       while (count >= 0) {
+       if (count)
                count--;
-               i--;
-               if (i < 0)
+
+       while (count--) {
+               if (i==0)
                        i += tx_ring->count;
+               i--;
                buffer_info = &tx_ring->buffer_info[i];
                e1000_unmap_and_free_tx_resource(adapter, buffer_info);
        }
@@ -3176,13 +3164,7 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu)
         *  however with the new *_jumbo_rx* routines, jumbo receives will use
         *  fragmented skbs */
 
-       if (max_frame <= E1000_RXBUFFER_256)
-               adapter->rx_buffer_len = E1000_RXBUFFER_256;
-       else if (max_frame <= E1000_RXBUFFER_512)
-               adapter->rx_buffer_len = E1000_RXBUFFER_512;
-       else if (max_frame <= E1000_RXBUFFER_1024)
-               adapter->rx_buffer_len = E1000_RXBUFFER_1024;
-       else if (max_frame <= E1000_RXBUFFER_2048)
+       if (max_frame <= E1000_RXBUFFER_2048)
                adapter->rx_buffer_len = E1000_RXBUFFER_2048;
        else
 #if (PAGE_SIZE >= E1000_RXBUFFER_16384)
@@ -3850,13 +3832,22 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
 
                length = le16_to_cpu(rx_desc->length);
                /* !EOP means multiple descriptors were used to store a single
-                * packet, also make sure the frame isn't just CRC only */
-               if (unlikely(!(status & E1000_RXD_STAT_EOP) || (length <= 4))) {
+                * packet, if thats the case we need to toss it.  In fact, we
+                * to toss every packet with the EOP bit clear and the next
+                * frame that _does_ have the EOP bit set, as it is by
+                * definition only a frame fragment
+                */
+               if (unlikely(!(status & E1000_RXD_STAT_EOP)))
+                       adapter->discarding = true;
+
+               if (adapter->discarding) {
                        /* All receives must fit into a single buffer */
                        E1000_DBG("%s: Receive packet consumed multiple"
                                  " buffers\n", netdev->name);
                        /* recycle */
                        buffer_info->skb = skb;
+                       if (status & E1000_RXD_STAT_EOP)
+                               adapter->discarding = false;
                        goto next_desc;
                }
 
index d6ee28f..d236efa 100644 (file)
@@ -421,6 +421,7 @@ struct e1000_info {
 /* CRC Stripping defines */
 #define FLAG2_CRC_STRIPPING               (1 << 0)
 #define FLAG2_HAS_PHY_WAKEUP              (1 << 1)
+#define FLAG2_IS_DISCARDING               (1 << 2)
 
 #define E1000_RX_DESC_PS(R, i)     \
        (&(((union e1000_rx_desc_packet_split *)((R).desc))[i]))
index c45965a..57f149b 100644 (file)
@@ -450,13 +450,23 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
 
                length = le16_to_cpu(rx_desc->length);
 
-               /* !EOP means multiple descriptors were used to store a single
-                * packet, also make sure the frame isn't just CRC only */
-               if (!(status & E1000_RXD_STAT_EOP) || (length <= 4)) {
+               /*
+                * !EOP means multiple descriptors were used to store a single
+                * packet, if that's the case we need to toss it.  In fact, we
+                * need to toss every packet with the EOP bit clear and the
+                * next frame that _does_ have the EOP bit set, as it is by
+                * definition only a frame fragment
+                */
+               if (unlikely(!(status & E1000_RXD_STAT_EOP)))
+                       adapter->flags2 |= FLAG2_IS_DISCARDING;
+
+               if (adapter->flags2 & FLAG2_IS_DISCARDING) {
                        /* All receives must fit into a single buffer */
                        e_dbg("Receive packet consumed multiple buffers\n");
                        /* recycle */
                        buffer_info->skb = skb;
+                       if (status & E1000_RXD_STAT_EOP)
+                               adapter->flags2 &= ~FLAG2_IS_DISCARDING;
                        goto next_desc;
                }
 
@@ -745,10 +755,16 @@ static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
                                 PCI_DMA_FROMDEVICE);
                buffer_info->dma = 0;
 
-               if (!(staterr & E1000_RXD_STAT_EOP)) {
+               /* see !EOP comment in other rx routine */
+               if (!(staterr & E1000_RXD_STAT_EOP))
+                       adapter->flags2 |= FLAG2_IS_DISCARDING;
+
+               if (adapter->flags2 & FLAG2_IS_DISCARDING) {
                        e_dbg("Packet Split buffers didn't pick up the full "
                              "packet\n");
                        dev_kfree_skb_irq(skb);
+                       if (staterr & E1000_RXD_STAT_EOP)
+                               adapter->flags2 &= ~FLAG2_IS_DISCARDING;
                        goto next_desc;
                }
 
@@ -1118,6 +1134,7 @@ static void e1000_clean_rx_ring(struct e1000_adapter *adapter)
 
        rx_ring->next_to_clean = 0;
        rx_ring->next_to_use = 0;
+       adapter->flags2 &= ~FLAG2_IS_DISCARDING;
 
        writel(0, adapter->hw.hw_addr + rx_ring->head);
        writel(0, adapter->hw.hw_addr + rx_ring->tail);
@@ -2333,18 +2350,6 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter)
        rctl &= ~E1000_RCTL_SZ_4096;
        rctl |= E1000_RCTL_BSEX;
        switch (adapter->rx_buffer_len) {
-       case 256:
-               rctl |= E1000_RCTL_SZ_256;
-               rctl &= ~E1000_RCTL_BSEX;
-               break;
-       case 512:
-               rctl |= E1000_RCTL_SZ_512;
-               rctl &= ~E1000_RCTL_BSEX;
-               break;
-       case 1024:
-               rctl |= E1000_RCTL_SZ_1024;
-               rctl &= ~E1000_RCTL_BSEX;
-               break;
        case 2048:
        default:
                rctl |= E1000_RCTL_SZ_2048;
@@ -3781,7 +3786,7 @@ static int e1000_tso(struct e1000_adapter *adapter,
                                                         0, IPPROTO_TCP, 0);
                cmd_length = E1000_TXD_CMD_IP;
                ipcse = skb_transport_offset(skb) - 1;
-       } else if (skb_shinfo(skb)->gso_type == SKB_GSO_TCPV6) {
+       } else if (skb_is_gso_v6(skb)) {
                ipv6_hdr(skb)->payload_len = 0;
                tcp_hdr(skb)->check = ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
                                                       &ipv6_hdr(skb)->daddr,
@@ -3962,13 +3967,13 @@ static int e1000_tx_map(struct e1000_adapter *adapter,
 dma_error:
        dev_err(&pdev->dev, "TX DMA map failed\n");
        buffer_info->dma = 0;
-       count--;
-
-       while (count >= 0) {
+       if (count)
                count--;
-               i--;
-               if (i < 0)
+
+       while (count--) {
+               if (i==0)
                        i += tx_ring->count;
+               i--;
                buffer_info = &tx_ring->buffer_info[i];
                e1000_put_txbuf(adapter, buffer_info);;
        }
@@ -4317,13 +4322,7 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu)
         * fragmented skbs
         */
 
-       if (max_frame <= 256)
-               adapter->rx_buffer_len = 256;
-       else if (max_frame <= 512)
-               adapter->rx_buffer_len = 512;
-       else if (max_frame <= 1024)
-               adapter->rx_buffer_len = 1024;
-       else if (max_frame <= 2048)
+       if (max_frame <= 2048)
                adapter->rx_buffer_len = 2048;
        else
                adapter->rx_buffer_len = 4096;
index 933c64f..997124d 100644 (file)
@@ -3422,7 +3422,7 @@ static inline int igb_tso_adv(struct igb_ring *tx_ring,
                                                         iph->daddr, 0,
                                                         IPPROTO_TCP,
                                                         0);
-       } else if (skb_shinfo(skb)->gso_type == SKB_GSO_TCPV6) {
+       } else if (skb_is_gso_v6(skb)) {
                ipv6_hdr(skb)->payload_len = 0;
                tcp_hdr(skb)->check = ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
                                                       &ipv6_hdr(skb)->daddr,
@@ -3584,6 +3584,7 @@ static inline int igb_tx_map_adv(struct igb_ring *tx_ring, struct sk_buff *skb,
        for (f = 0; f < skb_shinfo(skb)->nr_frags; f++) {
                struct skb_frag_struct *frag;
 
+               count++;
                i++;
                if (i == tx_ring->count)
                        i = 0;
@@ -3605,7 +3606,6 @@ static inline int igb_tx_map_adv(struct igb_ring *tx_ring, struct sk_buff *skb,
                if (pci_dma_mapping_error(pdev, buffer_info->dma))
                        goto dma_error;
 
-               count++;
        }
 
        tx_ring->buffer_info[i].skb = skb;
index 0dbd032..297a5dd 100644 (file)
@@ -1963,7 +1963,7 @@ static int igbvf_tso(struct igbvf_adapter *adapter,
                                                         iph->daddr, 0,
                                                         IPPROTO_TCP,
                                                         0);
-       } else if (skb_shinfo(skb)->gso_type == SKB_GSO_TCPV6) {
+       } else if (skb_is_gso_v6(skb)) {
                ipv6_hdr(skb)->payload_len = 0;
                tcp_hdr(skb)->check = ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
                                                       &ipv6_hdr(skb)->daddr,
@@ -2126,6 +2126,7 @@ static inline int igbvf_tx_map_adv(struct igbvf_adapter *adapter,
        for (f = 0; f < skb_shinfo(skb)->nr_frags; f++) {
                struct skb_frag_struct *frag;
 
+               count++;
                i++;
                if (i == tx_ring->count)
                        i = 0;
@@ -2146,7 +2147,6 @@ static inline int igbvf_tx_map_adv(struct igbvf_adapter *adapter,
                                                PCI_DMA_TODEVICE);
                if (pci_dma_mapping_error(pdev, buffer_info->dma))
                        goto dma_error;
-               count++;
        }
 
        tx_ring->buffer_info[i].skb = skb;
@@ -2163,14 +2163,14 @@ dma_error:
        buffer_info->length = 0;
        buffer_info->next_to_watch = 0;
        buffer_info->mapped_as_page = false;
-       count--;
+       if (count)
+               count--;
 
        /* clear timestamp and dma mappings for remaining portion of packet */
-       while (count >= 0) {
-               count--;
-               i--;
-               if (i < 0)
+       while (count--) {
+               if (i==0)
                        i += tx_ring->count;
+               i--;
                buffer_info = &tx_ring->buffer_info[i];
                igbvf_put_txbuf(adapter, buffer_info);
        }
index bcd0f01..593d1a4 100644 (file)
@@ -1363,13 +1363,13 @@ ixgb_tx_map(struct ixgb_adapter *adapter, struct sk_buff *skb,
 dma_error:
        dev_err(&pdev->dev, "TX DMA map failed\n");
        buffer_info->dma = 0;
-       count--;
-
-       while (count >= 0) {
+       if (count)
                count--;
-               i--;
-               if (i < 0)
+
+       while (count--) {
+               if (i==0)
                        i += tx_ring->count;
+               i--;
                buffer_info = &tx_ring->buffer_info[i];
                ixgb_unmap_and_free_tx_resource(adapter, buffer_info);
        }
index 9c9202f..b5f64ad 100644 (file)
@@ -4928,7 +4928,7 @@ static int ixgbe_tso(struct ixgbe_adapter *adapter,
                                                                 iph->daddr, 0,
                                                                 IPPROTO_TCP,
                                                                 0);
-               } else if (skb_shinfo(skb)->gso_type == SKB_GSO_TCPV6) {
+               } else if (skb_is_gso_v6(skb)) {
                        ipv6_hdr(skb)->payload_len = 0;
                        tcp_hdr(skb)->check =
                            ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
@@ -5167,14 +5167,14 @@ dma_error:
        tx_buffer_info->dma = 0;
        tx_buffer_info->time_stamp = 0;
        tx_buffer_info->next_to_watch = 0;
-       count--;
+       if (count)
+               count--;
 
        /* clear timestamp and dma mappings for remaining portion of packet */
-       while (count >= 0) {
-               count--;
-               i--;
-               if (i < 0)
+       while (count--) {
+               if (i==0)
                        i += tx_ring->count;
+               i--;
                tx_buffer_info = &tx_ring->tx_buffer_info[i];
                ixgbe_unmap_and_free_tx_resource(adapter, tx_buffer_info);
        }
index 813aca3..7b17404 100644 (file)
@@ -717,6 +717,7 @@ static struct pcmcia_device_id fmvj18x_ids[] = {
        PCMCIA_PFC_DEVICE_PROD_ID12(0, "NEC", "PK-UG-J001" ,0x18df0ba0 ,0x831b1064),
        PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0x0d0a),
        PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0x0e0a),
+       PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0032, 0x0e01),
        PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0032, 0x0a05),
        PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0032, 0x1101),
        PCMCIA_DEVICE_NULL,
index b0e9f9c..0295097 100644 (file)
@@ -410,7 +410,6 @@ EXPORT_SYMBOL(phy_start_aneg);
 
 
 static void phy_change(struct work_struct *work);
-static void phy_state_machine(struct work_struct *work);
 
 /**
  * phy_start_machine - start PHY state machine tracking
@@ -430,7 +429,6 @@ void phy_start_machine(struct phy_device *phydev,
 {
        phydev->adjust_state = handler;
 
-       INIT_DELAYED_WORK(&phydev->state_queue, phy_state_machine);
        schedule_delayed_work(&phydev->state_queue, HZ);
 }
 
@@ -761,7 +759,7 @@ EXPORT_SYMBOL(phy_start);
  * phy_state_machine - Handle the state machine
  * @work: work_struct that describes the work to be done
  */
-static void phy_state_machine(struct work_struct *work)
+void phy_state_machine(struct work_struct *work)
 {
        struct delayed_work *dwork = to_delayed_work(work);
        struct phy_device *phydev =
index 8212b2b..adbc0fd 100644 (file)
@@ -177,6 +177,7 @@ struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id)
        dev->state = PHY_DOWN;
 
        mutex_init(&dev->lock);
+       INIT_DELAYED_WORK(&dev->state_queue, phy_state_machine);
 
        return dev;
 }
index 707b391..894a7c8 100644 (file)
@@ -4119,7 +4119,7 @@ static int __devinit ql_init_device(struct pci_dev *pdev,
        err = pcie_set_readrq(pdev, 4096);
        if (err) {
                dev_err(&pdev->dev, "Set readrq failed.\n");
-               goto err_out;
+               goto err_out1;
        }
 
        err = pci_request_regions(pdev, DRV_NAME);
@@ -4140,7 +4140,7 @@ static int __devinit ql_init_device(struct pci_dev *pdev,
 
        if (err) {
                dev_err(&pdev->dev, "No usable DMA configuration.\n");
-               goto err_out;
+               goto err_out2;
        }
 
        /* Set PCIe reset type for EEH to fundamental. */
@@ -4152,7 +4152,7 @@ static int __devinit ql_init_device(struct pci_dev *pdev,
        if (!qdev->reg_base) {
                dev_err(&pdev->dev, "Register mapping failed.\n");
                err = -ENOMEM;
-               goto err_out;
+               goto err_out2;
        }
 
        qdev->doorbell_area_size = pci_resource_len(pdev, 3);
@@ -4162,14 +4162,14 @@ static int __devinit ql_init_device(struct pci_dev *pdev,
        if (!qdev->doorbell_area) {
                dev_err(&pdev->dev, "Doorbell register mapping failed.\n");
                err = -ENOMEM;
-               goto err_out;
+               goto err_out2;
        }
 
        err = ql_get_board_info(qdev);
        if (err) {
                dev_err(&pdev->dev, "Register access failed.\n");
                err = -EIO;
-               goto err_out;
+               goto err_out2;
        }
        qdev->msg_enable = netif_msg_init(debug, default_msg);
        spin_lock_init(&qdev->hw_lock);
@@ -4179,7 +4179,7 @@ static int __devinit ql_init_device(struct pci_dev *pdev,
        err = qdev->nic_ops->get_flash(qdev);
        if (err) {
                dev_err(&pdev->dev, "Invalid FLASH.\n");
-               goto err_out;
+               goto err_out2;
        }
 
        memcpy(ndev->perm_addr, ndev->dev_addr, ndev->addr_len);
@@ -4212,8 +4212,9 @@ static int __devinit ql_init_device(struct pci_dev *pdev,
                         DRV_NAME, DRV_VERSION);
        }
        return 0;
-err_out:
+err_out2:
        ql_release_all(pdev);
+err_out1:
        pci_disable_device(pdev);
        return err;
 }
index cc42186..3c4836d 100644 (file)
@@ -3421,7 +3421,7 @@ static int wait_for_cmd_complete(void __iomem *addr, u64 busy_bit,
                                break;
                        }
                } else {
-                       if (!(val64 & busy_bit)) {
+                       if (val64 & busy_bit) {
                                ret = SUCCESS;
                                break;
                        }
index 0d4eba7..9f035b9 100644 (file)
@@ -804,7 +804,7 @@ int efx_mcdi_nvram_read(struct efx_nic *efx, unsigned int type,
                        loff_t offset, u8 *buffer, size_t length)
 {
        u8 inbuf[MC_CMD_NVRAM_READ_IN_LEN];
-       u8 outbuf[MC_CMD_NVRAM_READ_OUT_LEN(length)];
+       u8 outbuf[MC_CMD_NVRAM_READ_OUT_LEN(EFX_MCDI_NVRAM_LEN_MAX)];
        size_t outlen;
        int rc;
 
@@ -828,7 +828,7 @@ fail:
 int efx_mcdi_nvram_write(struct efx_nic *efx, unsigned int type,
                           loff_t offset, const u8 *buffer, size_t length)
 {
-       u8 inbuf[MC_CMD_NVRAM_WRITE_IN_LEN(length)];
+       u8 inbuf[MC_CMD_NVRAM_WRITE_IN_LEN(EFX_MCDI_NVRAM_LEN_MAX)];
        int rc;
 
        MCDI_SET_DWORD(inbuf, NVRAM_WRITE_IN_TYPE, type);
@@ -838,7 +838,8 @@ int efx_mcdi_nvram_write(struct efx_nic *efx, unsigned int type,
 
        BUILD_BUG_ON(MC_CMD_NVRAM_WRITE_OUT_LEN != 0);
 
-       rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_WRITE, inbuf, sizeof(inbuf),
+       rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_WRITE, inbuf,
+                         ALIGN(MC_CMD_NVRAM_WRITE_IN_LEN(length), 4),
                          NULL, 0, NULL);
        if (rc)
                goto fail;
index de91672..10ce98f 100644 (file)
@@ -111,6 +111,7 @@ extern int efx_mcdi_nvram_read(struct efx_nic *efx, unsigned int type,
 extern int efx_mcdi_nvram_write(struct efx_nic *efx, unsigned int type,
                                loff_t offset, const u8 *buffer,
                                size_t length);
+#define EFX_MCDI_NVRAM_LEN_MAX 128
 extern int efx_mcdi_nvram_erase(struct efx_nic *efx, unsigned int type,
                                loff_t offset, size_t length);
 extern int efx_mcdi_nvram_update_finish(struct efx_nic *efx,
index 2a85360..73e71f4 100644 (file)
 #define MC_CMD_MAC_RX_LANES01_DISP_ERR 57
 #define MC_CMD_MAC_RX_LANES23_DISP_ERR 58
 #define MC_CMD_MAC_RX_MATCH_FAULT 59
+#define MC_CMD_GMAC_DMABUF_START 64
+#define MC_CMD_GMAC_DMABUF_END   95
 /* Insert new members here. */
-#define MC_CMD_MAC_GENERATION_END 60
+#define MC_CMD_MAC_GENERATION_END 96
 #define MC_CMD_MAC_NSTATS (MC_CMD_MAC_GENERATION_END+1)
 
 /* MC_CMD_MAC_STATS:
index 3a46452..407bbad 100644 (file)
@@ -23,7 +23,6 @@
 #include "mcdi_pcol.h"
 
 #define EFX_SPI_VERIFY_BUF_LEN 16
-#define EFX_MCDI_CHUNK_LEN 128
 
 struct efx_mtd_partition {
        struct mtd_info mtd;
@@ -428,7 +427,7 @@ static int siena_mtd_read(struct mtd_info *mtd, loff_t start,
        int rc = 0;
 
        while (offset < end) {
-               chunk = min_t(size_t, end - offset, EFX_MCDI_CHUNK_LEN);
+               chunk = min_t(size_t, end - offset, EFX_MCDI_NVRAM_LEN_MAX);
                rc = efx_mcdi_nvram_read(efx, part->mcdi.nvram_type, offset,
                                         buffer, chunk);
                if (rc)
@@ -491,7 +490,7 @@ static int siena_mtd_write(struct mtd_info *mtd, loff_t start,
        }
 
        while (offset < end) {
-               chunk = min_t(size_t, end - offset, EFX_MCDI_CHUNK_LEN);
+               chunk = min_t(size_t, end - offset, EFX_MCDI_NVRAM_LEN_MAX);
                rc = efx_mcdi_nvram_write(efx, part->mcdi.nvram_type, offset,
                                          buffer, chunk);
                if (rc)
index ff8f0a4..e0d13a4 100644 (file)
@@ -318,12 +318,6 @@ static int qt202x_reset_phy(struct efx_nic *efx)
        /* Wait 250ms for the PHY to complete bootup */
        msleep(250);
 
-       /* Check that all the MMDs we expect are present and responding. We
-        * expect faults on some if the link is down, but not on the PHY XS */
-       rc = efx_mdio_check_mmds(efx, QT202X_REQUIRED_DEVS, MDIO_DEVS_PHYXS);
-       if (rc < 0)
-               goto fail;
-
        falcon_board(efx)->type->init_phy(efx);
 
        return rc;
index 37f486b..d760650 100644 (file)
@@ -644,6 +644,7 @@ static void sky2_phy_power_up(struct sky2_hw *hw, unsigned port)
 {
        u32 reg1;
 
+       sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
        reg1 = sky2_pci_read32(hw, PCI_DEV_REG1);
        reg1 &= ~phy_power[port];
 
@@ -651,6 +652,7 @@ static void sky2_phy_power_up(struct sky2_hw *hw, unsigned port)
                reg1 |= coma_mode[port];
 
        sky2_pci_write32(hw, PCI_DEV_REG1, reg1);
+       sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
        sky2_pci_read32(hw, PCI_DEV_REG1);
 
        if (hw->chip_id == CHIP_ID_YUKON_FE)
@@ -707,9 +709,11 @@ static void sky2_phy_power_down(struct sky2_hw *hw, unsigned port)
                gm_phy_write(hw, port, PHY_MARV_CTRL, PHY_CT_PDOWN);
        }
 
+       sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
        reg1 = sky2_pci_read32(hw, PCI_DEV_REG1);
        reg1 |= phy_power[port];                /* set PHY to PowerDown/COMA Mode */
        sky2_pci_write32(hw, PCI_DEV_REG1, reg1);
+       sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
 }
 
 /* Force a renegotiation */
@@ -2149,7 +2153,9 @@ static void sky2_qlink_intr(struct sky2_hw *hw)
 
        /* reset PHY Link Detect */
        phy = sky2_pci_read16(hw, PSM_CONFIG_REG4);
+       sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
        sky2_pci_write16(hw, PSM_CONFIG_REG4, phy | 1);
+       sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
 
        sky2_link_up(sky2);
 }
@@ -2640,6 +2646,7 @@ static void sky2_hw_intr(struct sky2_hw *hw)
        if (status & (Y2_IS_MST_ERR | Y2_IS_IRQ_STAT)) {
                u16 pci_err;
 
+               sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
                pci_err = sky2_pci_read16(hw, PCI_STATUS);
                if (net_ratelimit())
                        dev_err(&pdev->dev, "PCI hardware error (0x%x)\n",
@@ -2647,12 +2654,14 @@ static void sky2_hw_intr(struct sky2_hw *hw)
 
                sky2_pci_write16(hw, PCI_STATUS,
                                      pci_err | PCI_STATUS_ERROR_BITS);
+               sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
        }
 
        if (status & Y2_IS_PCI_EXP) {
                /* PCI-Express uncorrectable Error occurred */
                u32 err;
 
+               sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
                err = sky2_read32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS);
                sky2_write32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS,
                             0xfffffffful);
@@ -2660,6 +2669,7 @@ static void sky2_hw_intr(struct sky2_hw *hw)
                        dev_err(&pdev->dev, "PCI Express error (0x%x)\n", err);
 
                sky2_read32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS);
+               sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
        }
 
        if (status & Y2_HWE_L1_MASK)
@@ -3038,6 +3048,7 @@ static void sky2_reset(struct sky2_hw *hw)
        }
 
        sky2_power_on(hw);
+       sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
 
        for (i = 0; i < hw->ports; i++) {
                sky2_write8(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_SET);
@@ -3074,6 +3085,7 @@ static void sky2_reset(struct sky2_hw *hw)
                reg <<= PSM_CONFIG_REG4_TIMER_PHY_LINK_DETECT_BASE;
 
                /* reset PHY Link Detect */
+               sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
                sky2_pci_write16(hw, PSM_CONFIG_REG4,
                                 reg | PSM_CONFIG_REG4_RST_PHY_LINK_DETECT);
                sky2_pci_write16(hw, PSM_CONFIG_REG4, reg);
@@ -3091,6 +3103,7 @@ static void sky2_reset(struct sky2_hw *hw)
                        /* restore the PCIe Link Control register */
                        sky2_pci_write16(hw, cap + PCI_EXP_LNKCTL, reg);
                }
+               sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
 
                /* re-enable PEX PM in PEX PHY debug reg. 8 (clear bit 12) */
                sky2_write32(hw, Y2_PEX_PHY_DATA, PEX_DB_ACCESS | (0x08UL << 16));
@@ -3228,6 +3241,27 @@ static inline u8 sky2_wol_supported(const struct sky2_hw *hw)
        return sky2_is_copper(hw) ? (WAKE_PHY | WAKE_MAGIC) : 0;
 }
 
+static void sky2_hw_set_wol(struct sky2_hw *hw)
+{
+       int wol = 0;
+       int i;
+
+       for (i = 0; i < hw->ports; i++) {
+               struct net_device *dev = hw->dev[i];
+               struct sky2_port *sky2 = netdev_priv(dev);
+
+               if (sky2->wol)
+                       wol = 1;
+       }
+
+       if (hw->chip_id == CHIP_ID_YUKON_EC_U ||
+           hw->chip_id == CHIP_ID_YUKON_EX ||
+           hw->chip_id == CHIP_ID_YUKON_FE_P)
+               sky2_write32(hw, B0_CTST, wol ? Y2_HW_WOL_ON : Y2_HW_WOL_OFF);
+
+       device_set_wakeup_enable(&hw->pdev->dev, wol);
+}
+
 static void sky2_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 {
        const struct sky2_port *sky2 = netdev_priv(dev);
@@ -3247,13 +3281,7 @@ static int sky2_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 
        sky2->wol = wol->wolopts;
 
-       if (hw->chip_id == CHIP_ID_YUKON_EC_U ||
-           hw->chip_id == CHIP_ID_YUKON_EX ||
-           hw->chip_id == CHIP_ID_YUKON_FE_P)
-               sky2_write32(hw, B0_CTST, sky2->wol
-                            ? Y2_HW_WOL_ON : Y2_HW_WOL_OFF);
-
-       device_set_wakeup_enable(&hw->pdev->dev, sky2->wol);
+       sky2_hw_set_wol(hw);
 
        if (!netif_running(dev))
                sky2_wol_init(sky2);
index 595777d..20696b5 100644 (file)
@@ -249,6 +249,7 @@ static struct pci_device_id tulip_pci_tbl[] = {
        { 0x17B3, 0xAB08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
        { 0x10b7, 0x9300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, /* 3Com 3CSOHO100B-TX */
        { 0x14ea, 0xab08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, /* Planex FNW-3602-TX */
+       { 0x1414, 0x0001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, /* Microsoft MN-120 */
        { 0x1414, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
        { } /* terminate list */
 };
index 96bdc0b..eb8fe7e 100644 (file)
@@ -3279,13 +3279,12 @@ static int ucc_geth_tx(struct net_device *dev, u8 txQ)
                /* Handle the transmitted buffer and release */
                /* the BD to be used with the current frame  */
 
-               if (bd == ugeth->txBd[txQ]) /* queue empty? */
+               skb = ugeth->tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]];
+               if (!skb)
                        break;
 
                dev->stats.tx_packets++;
 
-               skb = ugeth->tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]];
-
                if (skb_queue_len(&ugeth->rx_recycle) < RX_BD_RING_LEN &&
                             skb_recycle_check(skb,
                                    ugeth->ug_info->uf_info.max_rx_buf_length +
index c708ecc..9ead30b 100644 (file)
@@ -395,8 +395,7 @@ static void refill_work(struct work_struct *work)
 
        vi = container_of(work, struct virtnet_info, refill.work);
        napi_disable(&vi->napi);
-       try_fill_recv(vi, GFP_KERNEL);
-       still_empty = (vi->num == 0);
+       still_empty = !try_fill_recv(vi, GFP_KERNEL);
        napi_enable(&vi->napi);
 
        /* In theory, this can happen: if we don't get any buffers in
index 5cc0f27..2d7c96d 100644 (file)
@@ -151,6 +151,7 @@ enum {
 
        /* Device IDs */
        USB_DEVICE_ID_I6050 = 0x0186,
+       USB_DEVICE_ID_I6050_2 = 0x0188,
 };
 
 
@@ -234,6 +235,7 @@ struct i2400mu {
        u8 rx_size_auto_shrink;
 
        struct dentry *debugfs_dentry;
+       unsigned i6050:1;       /* 1 if this is a 6050 based SKU */
 };
 
 
index 3b48681..98f4f8c 100644 (file)
@@ -478,7 +478,16 @@ int i2400mu_probe(struct usb_interface *iface,
        i2400m->bus_bm_wait_for_ack = i2400mu_bus_bm_wait_for_ack;
        i2400m->bus_bm_mac_addr_impaired = 0;
 
-       if (id->idProduct == USB_DEVICE_ID_I6050) {
+       switch (id->idProduct) {
+       case USB_DEVICE_ID_I6050:
+       case USB_DEVICE_ID_I6050_2:
+               i2400mu->i6050 = 1;
+               break;
+       default:
+               break;
+       }
+
+       if (i2400mu->i6050) {
                i2400m->bus_fw_names = i2400mu_bus_fw_names_6050;
                i2400mu->endpoint_cfg.bulk_out = 0;
                i2400mu->endpoint_cfg.notification = 3;
@@ -719,6 +728,7 @@ int i2400mu_post_reset(struct usb_interface *iface)
 static
 struct usb_device_id i2400mu_id_table[] = {
        { USB_DEVICE(0x8086, USB_DEVICE_ID_I6050) },
+       { USB_DEVICE(0x8086, USB_DEVICE_ID_I6050_2) },
        { USB_DEVICE(0x8086, 0x0181) },
        { USB_DEVICE(0x8086, 0x1403) },
        { USB_DEVICE(0x8086, 0x1405) },
index 33a5866..de45f30 100644 (file)
@@ -1598,6 +1598,7 @@ struct iwl_cfg iwl5300_agn_cfg = {
        .use_bsm = false,
        .ht_greenfield_support = true,
        .led_compensation = 51,
+       .use_rts_for_ht = true, /* use rts/cts protection */
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
        .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED,
 };
@@ -1622,6 +1623,7 @@ struct iwl_cfg iwl5100_bgn_cfg = {
        .use_bsm = false,
        .ht_greenfield_support = true,
        .led_compensation = 51,
+       .use_rts_for_ht = true, /* use rts/cts protection */
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
 };
 
@@ -1667,6 +1669,7 @@ struct iwl_cfg iwl5100_agn_cfg = {
        .use_bsm = false,
        .ht_greenfield_support = true,
        .led_compensation = 51,
+       .use_rts_for_ht = true, /* use rts/cts protection */
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
        .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED,
 };
@@ -1691,6 +1694,7 @@ struct iwl_cfg iwl5350_agn_cfg = {
        .use_bsm = false,
        .ht_greenfield_support = true,
        .led_compensation = 51,
+       .use_rts_for_ht = true, /* use rts/cts protection */
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
        .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED,
 };
@@ -1715,6 +1719,7 @@ struct iwl_cfg iwl5150_agn_cfg = {
        .use_bsm = false,
        .ht_greenfield_support = true,
        .led_compensation = 51,
+       .use_rts_for_ht = true, /* use rts/cts protection */
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
        .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED,
 };
index e7d88d1..83cc4e5 100644 (file)
@@ -1,3 +1,29 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009 - 2010 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
 #include <linux/module.h>
 
 /* sparse doesn't like tracepoint macros */
index 2136196..d9c7363 100644 (file)
@@ -1,3 +1,29 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009 - 2010 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
 #if !defined(__IWLWIFI_DEVICE_TRACE) || defined(TRACE_HEADER_MULTI_READ)
 #define __IWLWIFI_DEVICE_TRACE
 
index 777584d..1e41ad0 100644 (file)
@@ -973,6 +973,10 @@ int iwm_send_pmkid_update(struct iwm_priv *iwm,
 
        memset(&update, 0, sizeof(struct iwm_umac_pmkid_update));
 
+       update.hdr.oid = UMAC_WIFI_IF_CMD_PMKID_UPDATE;
+       update.hdr.buf_size = cpu_to_le16(sizeof(struct iwm_umac_pmkid_update) -
+                                         sizeof(struct iwm_umac_wifi_if));
+
        update.command = cpu_to_le32(command);
        if (pmksa->bssid)
                memcpy(&update.bssid, pmksa->bssid, ETH_ALEN);
index 06af055..3dfd9f0 100644 (file)
@@ -463,6 +463,7 @@ struct iwm_umac_cmd_stop_resume_tx {
 #define IWM_CMD_PMKID_FLUSH 3
 
 struct iwm_umac_pmkid_update {
+       struct iwm_umac_wifi_if hdr;
        __le32 command;
        u8 bssid[ETH_ALEN];
        __le16 reserved;
index a15962a..a72f7c2 100644 (file)
@@ -197,6 +197,14 @@ static void p54p_check_rx_ring(struct ieee80211_hw *dev, u32 *index,
                        i %= ring_limit;
                        continue;
                }
+
+               if (unlikely(len > priv->common.rx_mtu)) {
+                       if (net_ratelimit())
+                               dev_err(&priv->pdev->dev, "rx'd frame size "
+                                       "exceeds length threshold.\n");
+
+                       len = priv->common.rx_mtu;
+               }
                skb_put(skb, len);
 
                if (p54_rx(dev, skb)) {
index ac19ecd..72d3e43 100644 (file)
@@ -62,6 +62,7 @@ static struct usb_device_id usb_ids[] = {
        { USB_DEVICE(0x6891, 0xa727), .driver_info = DEVICE_ZD1211 },
        /* ZD1211B */
        { USB_DEVICE(0x0053, 0x5301), .driver_info = DEVICE_ZD1211B },
+       { USB_DEVICE(0x0409, 0x0248), .driver_info = DEVICE_ZD1211B },
        { USB_DEVICE(0x0411, 0x00da), .driver_info = DEVICE_ZD1211B },
        { USB_DEVICE(0x0471, 0x1236), .driver_info = DEVICE_ZD1211B },
        { USB_DEVICE(0x0471, 0x1237), .driver_info = DEVICE_ZD1211B },
index df85440..95421fa 100644 (file)
@@ -758,6 +758,7 @@ static struct pcmcia_device_id serial_ids[] = {
        PCMCIA_PFC_DEVICE_PROD_ID12(1, "PCMCIAs", "LanModem", 0xdcfe12d3, 0xc67c648f),
        PCMCIA_PFC_DEVICE_PROD_ID12(1, "TDK", "GlobalNetworker 3410/3412", 0x1eae9475, 0xd9a93bed),
        PCMCIA_PFC_DEVICE_PROD_ID12(1, "Xircom", "CreditCard Ethernet+Modem II", 0x2e3ee845, 0xeca401bf),
+       PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0032, 0x0e01),
        PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0032, 0x0a05),
        PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0032, 0x1101),
        PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0104, 0x0070),
index d26402f..7758cc3 100644 (file)
@@ -135,26 +135,71 @@ static unsigned int eventfd_poll(struct file *file, poll_table *wait)
        return events;
 }
 
-static ssize_t eventfd_read(struct file *file, char __user *buf, size_t count,
-                           loff_t *ppos)
+static void eventfd_ctx_do_read(struct eventfd_ctx *ctx, __u64 *cnt)
+{
+       *cnt = (ctx->flags & EFD_SEMAPHORE) ? 1 : ctx->count;
+       ctx->count -= *cnt;
+}
+
+/**
+ * eventfd_ctx_remove_wait_queue - Read the current counter and removes wait queue.
+ * @ctx: [in] Pointer to eventfd context.
+ * @wait: [in] Wait queue to be removed.
+ * @cnt: [out] Pointer to the 64bit conter value.
+ *
+ * Returns zero if successful, or the following error codes:
+ *
+ * -EAGAIN      : The operation would have blocked.
+ *
+ * This is used to atomically remove a wait queue entry from the eventfd wait
+ * queue head, and read/reset the counter value.
+ */
+int eventfd_ctx_remove_wait_queue(struct eventfd_ctx *ctx, wait_queue_t *wait,
+                                 __u64 *cnt)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&ctx->wqh.lock, flags);
+       eventfd_ctx_do_read(ctx, cnt);
+       __remove_wait_queue(&ctx->wqh, wait);
+       if (*cnt != 0 && waitqueue_active(&ctx->wqh))
+               wake_up_locked_poll(&ctx->wqh, POLLOUT);
+       spin_unlock_irqrestore(&ctx->wqh.lock, flags);
+
+       return *cnt != 0 ? 0 : -EAGAIN;
+}
+EXPORT_SYMBOL_GPL(eventfd_ctx_remove_wait_queue);
+
+/**
+ * eventfd_ctx_read - Reads the eventfd counter or wait if it is zero.
+ * @ctx: [in] Pointer to eventfd context.
+ * @no_wait: [in] Different from zero if the operation should not block.
+ * @cnt: [out] Pointer to the 64bit conter value.
+ *
+ * Returns zero if successful, or the following error codes:
+ *
+ * -EAGAIN      : The operation would have blocked but @no_wait was nonzero.
+ * -ERESTARTSYS : A signal interrupted the wait operation.
+ *
+ * If @no_wait is zero, the function might sleep until the eventfd internal
+ * counter becomes greater than zero.
+ */
+ssize_t eventfd_ctx_read(struct eventfd_ctx *ctx, int no_wait, __u64 *cnt)
 {
-       struct eventfd_ctx *ctx = file->private_data;
        ssize_t res;
-       __u64 ucnt = 0;
        DECLARE_WAITQUEUE(wait, current);
 
-       if (count < sizeof(ucnt))
-               return -EINVAL;
        spin_lock_irq(&ctx->wqh.lock);
+       *cnt = 0;
        res = -EAGAIN;
        if (ctx->count > 0)
-               res = sizeof(ucnt);
-       else if (!(file->f_flags & O_NONBLOCK)) {
+               res = 0;
+       else if (!no_wait) {
                __add_wait_queue(&ctx->wqh, &wait);
-               for (res = 0;;) {
+               for (;;) {
                        set_current_state(TASK_INTERRUPTIBLE);
                        if (ctx->count > 0) {
-                               res = sizeof(ucnt);
+                               res = 0;
                                break;
                        }
                        if (signal_pending(current)) {
@@ -168,18 +213,32 @@ static ssize_t eventfd_read(struct file *file, char __user *buf, size_t count,
                __remove_wait_queue(&ctx->wqh, &wait);
                __set_current_state(TASK_RUNNING);
        }
-       if (likely(res > 0)) {
-               ucnt = (ctx->flags & EFD_SEMAPHORE) ? 1 : ctx->count;
-               ctx->count -= ucnt;
+       if (likely(res == 0)) {
+               eventfd_ctx_do_read(ctx, cnt);
                if (waitqueue_active(&ctx->wqh))
                        wake_up_locked_poll(&ctx->wqh, POLLOUT);
        }
        spin_unlock_irq(&ctx->wqh.lock);
-       if (res > 0 && put_user(ucnt, (__u64 __user *) buf))
-               return -EFAULT;
 
        return res;
 }
+EXPORT_SYMBOL_GPL(eventfd_ctx_read);
+
+static ssize_t eventfd_read(struct file *file, char __user *buf, size_t count,
+                           loff_t *ppos)
+{
+       struct eventfd_ctx *ctx = file->private_data;
+       ssize_t res;
+       __u64 cnt;
+
+       if (count < sizeof(cnt))
+               return -EINVAL;
+       res = eventfd_ctx_read(ctx, file->f_flags & O_NONBLOCK, &cnt);
+       if (res < 0)
+               return res;
+
+       return put_user(cnt, (__u64 __user *) buf) ? -EFAULT : sizeof(cnt);
+}
 
 static ssize_t eventfd_write(struct file *file, const char __user *buf, size_t count,
                             loff_t *ppos)
index ff7664e..4c4e0f8 100644 (file)
@@ -353,6 +353,11 @@ struct ttm_bo_driver {
        /* notify the driver we are taking a fault on this BO
         * and have reserved it */
        void (*fault_reserve_notify)(struct ttm_buffer_object *bo);
+
+       /**
+        * notify the driver that we're about to swap out this bo
+        */
+       void (*swap_notify) (struct ttm_buffer_object *bo);
 };
 
 /**
index 94dd103..91bb4f2 100644 (file)
@@ -10,6 +10,7 @@
 
 #include <linux/fcntl.h>
 #include <linux/file.h>
+#include <linux/wait.h>
 
 /*
  * CAREFUL: Check include/asm-generic/fcntl.h when defining
@@ -34,6 +35,9 @@ struct file *eventfd_fget(int fd);
 struct eventfd_ctx *eventfd_ctx_fdget(int fd);
 struct eventfd_ctx *eventfd_ctx_fileget(struct file *file);
 int eventfd_signal(struct eventfd_ctx *ctx, int n);
+ssize_t eventfd_ctx_read(struct eventfd_ctx *ctx, int no_wait, __u64 *cnt);
+int eventfd_ctx_remove_wait_queue(struct eventfd_ctx *ctx, wait_queue_t *wait,
+                                 __u64 *cnt);
 
 #else /* CONFIG_EVENTFD */
 
@@ -61,6 +65,18 @@ static inline void eventfd_ctx_put(struct eventfd_ctx *ctx)
 
 }
 
+static inline ssize_t eventfd_ctx_read(struct eventfd_ctx *ctx, int no_wait,
+                                      __u64 *cnt)
+{
+       return -ENOSYS;
+}
+
+static inline int eventfd_ctx_remove_wait_queue(struct eventfd_ctx *ctx,
+                                               wait_queue_t *wait, __u64 *cnt)
+{
+       return -ENOSYS;
+}
+
 #endif
 
 #endif /* _LINUX_EVENTFD_H */
index e32aa26..24b4414 100644 (file)
@@ -17,6 +17,7 @@
 enum kmsg_dump_reason {
        KMSG_DUMP_OOPS,
        KMSG_DUMP_PANIC,
+       KMSG_DUMP_KEXEC,
 };
 
 /**
diff --git a/include/linux/mtd/pismo.h b/include/linux/mtd/pismo.h
new file mode 100644 (file)
index 0000000..8dfb7e1
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * PISMO memory driver - http://www.pismoworld.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License.
+ */
+#ifndef __LINUX_MTD_PISMO_H
+#define __LINUX_MTD_PISMO_H
+
+struct pismo_pdata {
+       void                    (*set_vpp)(void *, int);
+       void                    *vpp_data;
+       phys_addr_t             cs_addrs[5];
+};
+
+#endif
index 7968def..6a7eb40 100644 (file)
@@ -485,6 +485,7 @@ void phy_driver_unregister(struct phy_driver *drv);
 int phy_driver_register(struct phy_driver *new_driver);
 void phy_prepare_link(struct phy_device *phydev,
                void (*adjust_link)(struct net_device *));
+void phy_state_machine(struct work_struct *work);
 void phy_start_machine(struct phy_device *phydev,
                void (*handler)(struct net_device *));
 void phy_stop_machine(struct phy_device *phydev);
index 56f8e55..74f119a 100644 (file)
@@ -5,6 +5,7 @@
 #include <linux/wait.h>
 #include <linux/workqueue.h>
 #include <linux/xfrm.h>
+#include <net/dst_ops.h>
 
 struct ctl_table_header;
 
@@ -42,6 +43,11 @@ struct netns_xfrm {
        unsigned int            policy_count[XFRM_POLICY_MAX * 2];
        struct work_struct      policy_hash_work;
 
+       struct dst_ops          xfrm4_dst_ops;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+       struct dst_ops          xfrm6_dst_ops;
+#endif
+
        struct sock             *nlsk;
        struct sock             *nlsk_stash;
 
index 15696b1..ab170a6 100644 (file)
@@ -132,6 +132,8 @@ static __inline__ void nr_node_put(struct nr_node *nr_node)
 static __inline__ void nr_neigh_put(struct nr_neigh *nr_neigh)
 {
        if (atomic_dec_and_test(&nr_neigh->refcount)) {
+               if (nr_neigh->ax25)
+                       ax25_cb_put(nr_neigh->ax25);
                kfree(nr_neigh->digipeat);
                kfree(nr_neigh);
        }
index 6d85861..60c2770 100644 (file)
@@ -1367,8 +1367,8 @@ struct xfrmk_spdinfo {
 extern struct xfrm_state *xfrm_find_acq_byseq(struct net *net, u32 seq);
 extern int xfrm_state_delete(struct xfrm_state *x);
 extern int xfrm_state_flush(struct net *net, u8 proto, struct xfrm_audit *audit_info);
-extern void xfrm_sad_getinfo(struct xfrmk_sadinfo *si);
-extern void xfrm_spd_getinfo(struct xfrmk_spdinfo *si);
+extern void xfrm_sad_getinfo(struct net *net, struct xfrmk_sadinfo *si);
+extern void xfrm_spd_getinfo(struct net *net, struct xfrmk_spdinfo *si);
 extern int xfrm_replay_check(struct xfrm_state *x,
                             struct sk_buff *skb, __be32 seq);
 extern void xfrm_replay_advance(struct xfrm_state *x, __be32 seq);
index a9a93d9..ef077fb 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/console.h>
 #include <linux/vmalloc.h>
 #include <linux/swap.h>
+#include <linux/kmsg_dump.h>
 
 #include <asm/page.h>
 #include <asm/uaccess.h>
@@ -1074,6 +1075,9 @@ void crash_kexec(struct pt_regs *regs)
        if (mutex_trylock(&kexec_mutex)) {
                if (kexec_crash_image) {
                        struct pt_regs fixed_regs;
+
+                       kmsg_dump(KMSG_DUMP_KEXEC);
+
                        crash_setup_regs(&fixed_regs, regs);
                        crash_save_vmcoreinfo();
                        machine_crash_shutdown(&fixed_regs);
index 5827f7b..c787333 100644 (file)
@@ -75,7 +75,6 @@ NORET_TYPE void panic(const char * fmt, ...)
        dump_stack();
 #endif
 
-       kmsg_dump(KMSG_DUMP_PANIC);
        /*
         * If we have crashed and we have a crash kernel loaded let it handle
         * everything else.
@@ -83,6 +82,8 @@ NORET_TYPE void panic(const char * fmt, ...)
         */
        crash_kexec(NULL);
 
+       kmsg_dump(KMSG_DUMP_PANIC);
+
        /*
         * Note smp_send_stop is the usual smp shutdown function, which
         * unfortunately means it may not be hardened to work in a panic
index 17463ca..1751c45 100644 (file)
@@ -1467,6 +1467,7 @@ EXPORT_SYMBOL_GPL(kmsg_dump_unregister);
 static const char const *kmsg_reasons[] = {
        [KMSG_DUMP_OOPS]        = "oops",
        [KMSG_DUMP_PANIC]       = "panic",
+       [KMSG_DUMP_KEXEC]       = "kexec",
 };
 
 static const char *kmsg_to_str(enum kmsg_dump_reason reason)
index 6f740d9..d7395fd 100644 (file)
@@ -259,7 +259,8 @@ void clockevents_notify(unsigned long reason, void *arg)
                cpu = *((int *)arg);
                list_for_each_entry_safe(dev, tmp, &clockevent_devices, list) {
                        if (cpumask_test_cpu(cpu, dev->cpumask) &&
-                           cpumask_weight(dev->cpumask) == 1) {
+                           cpumask_weight(dev->cpumask) == 1 &&
+                           !tick_is_broadcast_device(dev)) {
                                BUG_ON(dev->mode != CLOCK_EVT_MODE_UNUSED);
                                list_del(&dev->list);
                        }
index b788978..c1b92ca 100644 (file)
@@ -163,7 +163,7 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
                goto err_unlock;
        }
 
-       rx_stats = per_cpu_ptr(vlan_dev_info(dev)->vlan_rx_stats,
+       rx_stats = per_cpu_ptr(vlan_dev_info(skb->dev)->vlan_rx_stats,
                               smp_processor_id());
        rx_stats->rx_packets++;
        rx_stats->rx_bytes += skb->len;
index 9d4adfd..f2b3b56 100644 (file)
@@ -819,7 +819,7 @@ static int aarp_rcv(struct sk_buff *skb, struct net_device *dev,
                                ma = &ifa->address;
                        else { /* We need to make a copy of the entry. */
                                da.s_node = sa.s_node;
-                               da.s_net = da.s_net;
+                               da.s_net = sa.s_net;
                                ma = &da;
                        }
 
index bf706f8..1491260 100644 (file)
@@ -92,6 +92,12 @@ ax25_cb *ax25_send_frame(struct sk_buff *skb, int paclen, ax25_address *src, ax2
 #endif
        }
 
+       /*
+        * There is one ref for the state machine; a caller needs
+        * one more to put it back, just like with the existing one.
+        */
+       ax25_cb_hold(ax25);
+
        ax25_cb_add(ax25);
 
        ax25->state = AX25_STATE_1;
index f3e9ba1..57dfb9c 100644 (file)
@@ -77,34 +77,24 @@ int ccid_getsockopt_builtin_ccids(struct sock *sk, int len,
        return err;
 }
 
-static struct kmem_cache *ccid_kmem_cache_create(int obj_size, const char *fmt,...)
+static struct kmem_cache *ccid_kmem_cache_create(int obj_size, char *slab_name_fmt, const char *fmt,...)
 {
        struct kmem_cache *slab;
-       char slab_name_fmt[32], *slab_name;
        va_list args;
 
        va_start(args, fmt);
        vsnprintf(slab_name_fmt, sizeof(slab_name_fmt), fmt, args);
        va_end(args);
 
-       slab_name = kstrdup(slab_name_fmt, GFP_KERNEL);
-       if (slab_name == NULL)
-               return NULL;
-       slab = kmem_cache_create(slab_name, sizeof(struct ccid) + obj_size, 0,
+       slab = kmem_cache_create(slab_name_fmt, sizeof(struct ccid) + obj_size, 0,
                                 SLAB_HWCACHE_ALIGN, NULL);
-       if (slab == NULL)
-               kfree(slab_name);
        return slab;
 }
 
 static void ccid_kmem_cache_destroy(struct kmem_cache *slab)
 {
-       if (slab != NULL) {
-               const char *name = kmem_cache_name(slab);
-
+       if (slab != NULL)
                kmem_cache_destroy(slab);
-               kfree(name);
-       }
 }
 
 static int ccid_activate(struct ccid_operations *ccid_ops)
@@ -113,6 +103,7 @@ static int ccid_activate(struct ccid_operations *ccid_ops)
 
        ccid_ops->ccid_hc_rx_slab =
                        ccid_kmem_cache_create(ccid_ops->ccid_hc_rx_obj_size,
+                                              ccid_ops->ccid_hc_rx_slab_name,
                                               "ccid%u_hc_rx_sock",
                                               ccid_ops->ccid_id);
        if (ccid_ops->ccid_hc_rx_slab == NULL)
@@ -120,6 +111,7 @@ static int ccid_activate(struct ccid_operations *ccid_ops)
 
        ccid_ops->ccid_hc_tx_slab =
                        ccid_kmem_cache_create(ccid_ops->ccid_hc_tx_obj_size,
+                                              ccid_ops->ccid_hc_tx_slab_name,
                                               "ccid%u_hc_tx_sock",
                                               ccid_ops->ccid_id);
        if (ccid_ops->ccid_hc_tx_slab == NULL)
index facedd2..269958b 100644 (file)
@@ -49,6 +49,8 @@ struct ccid_operations {
        const char              *ccid_name;
        struct kmem_cache       *ccid_hc_rx_slab,
                                *ccid_hc_tx_slab;
+       char                    ccid_hc_rx_slab_name[32];
+       char                    ccid_hc_tx_slab_name[32];
        __u32                   ccid_hc_rx_obj_size,
                                ccid_hc_tx_obj_size;
        /* Interface Routines */
index a1362dc..bace1d8 100644 (file)
@@ -161,7 +161,8 @@ static __init int dccpprobe_init(void)
        if (!proc_net_fops_create(&init_net, procname, S_IRUSR, &dccpprobe_fops))
                goto err0;
 
-       ret = register_jprobe(&dccp_send_probe);
+       ret = try_then_request_module((register_jprobe(&dccp_send_probe) == 0),
+                                       "dccp");
        if (ret)
                goto err1;
 
index bdb78dd..1aaa811 100644 (file)
@@ -368,7 +368,7 @@ static int inet_diag_bc_run(const void *bc, int len,
                        yes = entry->sport >= op[1].no;
                        break;
                case INET_DIAG_BC_S_LE:
-                       yes = entry->dport <= op[1].no;
+                       yes = entry->sport <= op[1].no;
                        break;
                case INET_DIAG_BC_D_GE:
                        yes = entry->dport >= op[1].no;
index e446496..d62b05d 100644 (file)
@@ -586,7 +586,9 @@ static void __net_exit ip_rt_do_proc_exit(struct net *net)
 {
        remove_proc_entry("rt_cache", net->proc_net_stat);
        remove_proc_entry("rt_cache", net->proc_net);
+#ifdef CONFIG_NET_CLS_ROUTE
        remove_proc_entry("rt_acct", net->proc_net);
+#endif
 }
 
 static struct pernet_operations ip_rt_proc_ops __net_initdata =  {
index bb110c5..9bc805d 100644 (file)
@@ -39,9 +39,9 @@ static int port __read_mostly = 0;
 MODULE_PARM_DESC(port, "Port to match (0=all)");
 module_param(port, int, 0);
 
-static int bufsize __read_mostly = 4096;
+static unsigned int bufsize __read_mostly = 4096;
 MODULE_PARM_DESC(bufsize, "Log buffer size in packets (4096)");
-module_param(bufsize, int, 0);
+module_param(bufsize, uint, 0);
 
 static int full __read_mostly;
 MODULE_PARM_DESC(full, "Full log (1=every ack packet received,  0=only cwnd changes)");
@@ -75,12 +75,12 @@ static struct {
 
 static inline int tcp_probe_used(void)
 {
-       return (tcp_probe.head - tcp_probe.tail) % bufsize;
+       return (tcp_probe.head - tcp_probe.tail) & (bufsize - 1);
 }
 
 static inline int tcp_probe_avail(void)
 {
-       return bufsize - tcp_probe_used();
+       return bufsize - tcp_probe_used() - 1;
 }
 
 /*
@@ -116,7 +116,7 @@ static int jtcp_rcv_established(struct sock *sk, struct sk_buff *skb,
                        p->ssthresh = tcp_current_ssthresh(sk);
                        p->srtt = tp->srtt >> 3;
 
-                       tcp_probe.head = (tcp_probe.head + 1) % bufsize;
+                       tcp_probe.head = (tcp_probe.head + 1) & (bufsize - 1);
                }
                tcp_probe.lastcwnd = tp->snd_cwnd;
                spin_unlock(&tcp_probe.lock);
@@ -149,7 +149,7 @@ static int tcpprobe_open(struct inode * inode, struct file * file)
 static int tcpprobe_sprint(char *tbuf, int n)
 {
        const struct tcp_log *p
-               = tcp_probe.log + tcp_probe.tail % bufsize;
+               = tcp_probe.log + tcp_probe.tail;
        struct timespec tv
                = ktime_to_timespec(ktime_sub(p->tstamp, tcp_probe.start));
 
@@ -192,7 +192,7 @@ static ssize_t tcpprobe_read(struct file *file, char __user *buf,
                width = tcpprobe_sprint(tbuf, sizeof(tbuf));
 
                if (cnt + width < len)
-                       tcp_probe.tail = (tcp_probe.tail + 1) % bufsize;
+                       tcp_probe.tail = (tcp_probe.tail + 1) & (bufsize - 1);
 
                spin_unlock_bh(&tcp_probe.lock);
 
@@ -222,9 +222,10 @@ static __init int tcpprobe_init(void)
        init_waitqueue_head(&tcp_probe.wait);
        spin_lock_init(&tcp_probe.lock);
 
-       if (bufsize < 0)
+       if (bufsize == 0)
                return -EINVAL;
 
+       bufsize = roundup_pow_of_two(bufsize);
        tcp_probe.log = kcalloc(bufsize, sizeof(struct tcp_log), GFP_KERNEL);
        if (!tcp_probe.log)
                goto err0;
@@ -236,7 +237,7 @@ static __init int tcpprobe_init(void)
        if (ret)
                goto err1;
 
-       pr_info("TCP probe registered (port=%d)\n", port);
+       pr_info("TCP probe registered (port=%d) bufsize=%u\n", port, bufsize);
        return 0;
  err1:
        proc_net_remove(&init_net, procname);
index 8c08a28..67107d6 100644 (file)
@@ -15,7 +15,6 @@
 #include <net/xfrm.h>
 #include <net/ip.h>
 
-static struct dst_ops xfrm4_dst_ops;
 static struct xfrm_policy_afinfo xfrm4_policy_afinfo;
 
 static struct dst_entry *xfrm4_dst_lookup(struct net *net, int tos,
@@ -190,8 +189,10 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse)
 
 static inline int xfrm4_garbage_collect(struct dst_ops *ops)
 {
-       xfrm4_policy_afinfo.garbage_collect(&init_net);
-       return (atomic_read(&xfrm4_dst_ops.entries) > xfrm4_dst_ops.gc_thresh*2);
+       struct net *net = container_of(ops, struct net, xfrm.xfrm4_dst_ops);
+
+       xfrm4_policy_afinfo.garbage_collect(net);
+       return (atomic_read(&ops->entries) > ops->gc_thresh * 2);
 }
 
 static void xfrm4_update_pmtu(struct dst_entry *dst, u32 mtu)
@@ -268,7 +269,7 @@ static struct xfrm_policy_afinfo xfrm4_policy_afinfo = {
 static struct ctl_table xfrm4_policy_table[] = {
        {
                .procname       = "xfrm4_gc_thresh",
-               .data           = &xfrm4_dst_ops.gc_thresh,
+               .data           = &init_net.xfrm.xfrm4_dst_ops.gc_thresh,
                .maxlen         = sizeof(int),
                .mode           = 0644,
                .proc_handler   = proc_dointvec,
@@ -295,8 +296,6 @@ static void __exit xfrm4_policy_fini(void)
 
 void __init xfrm4_init(int rt_max_size)
 {
-       xfrm4_state_init();
-       xfrm4_policy_init();
        /*
         * Select a default value for the gc_thresh based on the main route
         * table hash size.  It seems to me the worst case scenario is when
@@ -308,6 +307,9 @@ void __init xfrm4_init(int rt_max_size)
         * and start cleaning when were 1/2 full
         */
        xfrm4_dst_ops.gc_thresh = rt_max_size/2;
+
+       xfrm4_state_init();
+       xfrm4_policy_init();
 #ifdef CONFIG_SYSCTL
        sysctl_hdr = register_net_sysctl_table(&init_net, net_ipv4_ctl_path,
                                                xfrm4_policy_table);
index 7254e3f..dbdc696 100644 (file)
@@ -24,7 +24,6 @@
 #include <net/mip6.h>
 #endif
 
-static struct dst_ops xfrm6_dst_ops;
 static struct xfrm_policy_afinfo xfrm6_policy_afinfo;
 
 static struct dst_entry *xfrm6_dst_lookup(struct net *net, int tos,
@@ -224,8 +223,10 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse)
 
 static inline int xfrm6_garbage_collect(struct dst_ops *ops)
 {
-       xfrm6_policy_afinfo.garbage_collect(&init_net);
-       return (atomic_read(&xfrm6_dst_ops.entries) > xfrm6_dst_ops.gc_thresh*2);
+       struct net *net = container_of(ops, struct net, xfrm.xfrm6_dst_ops);
+
+       xfrm6_policy_afinfo.garbage_collect(net);
+       return (atomic_read(&ops->entries) > ops->gc_thresh * 2);
 }
 
 static void xfrm6_update_pmtu(struct dst_entry *dst, u32 mtu)
@@ -310,7 +311,7 @@ static void xfrm6_policy_fini(void)
 static struct ctl_table xfrm6_policy_table[] = {
        {
                .procname       = "xfrm6_gc_thresh",
-               .data           = &xfrm6_dst_ops.gc_thresh,
+               .data           = &init_net.xfrm.xfrm6_dst_ops.gc_thresh,
                .maxlen         = sizeof(int),
                .mode           = 0644,
                .proc_handler   = proc_dointvec,
@@ -326,13 +327,6 @@ int __init xfrm6_init(void)
        int ret;
        unsigned int gc_thresh;
 
-       ret = xfrm6_policy_init();
-       if (ret)
-               goto out;
-
-       ret = xfrm6_state_init();
-       if (ret)
-               goto out_policy;
        /*
         * We need a good default value for the xfrm6 gc threshold.
         * In ipv4 we set it to the route hash table size * 8, which
@@ -346,6 +340,15 @@ int __init xfrm6_init(void)
         */
        gc_thresh = FIB6_TABLE_HASHSZ * 8;
        xfrm6_dst_ops.gc_thresh = (gc_thresh < 1024) ? 1024 : gc_thresh;
+
+       ret = xfrm6_policy_init();
+       if (ret)
+               goto out;
+
+       ret = xfrm6_state_init();
+       if (ret)
+               goto out_policy;
+
 #ifdef CONFIG_SYSCTL
        sysctl_hdr = register_net_sysctl_table(&init_net, net_ipv6_ctl_path,
                                                xfrm6_policy_table);
index 6dc3579..9ae1a47 100644 (file)
@@ -1331,6 +1331,9 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
        struct ieee80211_conf *conf = &local->hw.conf;
 
+       if (sdata->vif.type != NL80211_IFTYPE_STATION)
+               return -EOPNOTSUPP;
+
        if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS))
                return -EOPNOTSUPP;
 
index 699d3ed..29bc4c5 100644 (file)
@@ -190,7 +190,7 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo,
        rate_control_pid_normalize(pinfo, sband->n_bitrates);
 
        /* Compute the proportional, integral and derivative errors. */
-       err_prop = (pinfo->target << RC_PID_ARITH_SHIFT) - pf;
+       err_prop = (pinfo->target - pf) << RC_PID_ARITH_SHIFT;
 
        err_avg = spinfo->err_avg_sc >> pinfo->smoothing_shift;
        spinfo->err_avg_sc = spinfo->err_avg_sc - err_avg + err_prop;
index aacba76..e2e2d33 100644 (file)
@@ -843,12 +843,13 @@ int nr_route_frame(struct sk_buff *skb, ax25_cb *ax25)
        dptr  = skb_push(skb, 1);
        *dptr = AX25_P_NETROM;
 
-       ax25s = ax25_send_frame(skb, 256, (ax25_address *)dev->dev_addr, &nr_neigh->callsign, nr_neigh->digipeat, nr_neigh->dev);
-       if (nr_neigh->ax25 && ax25s) {
-               /* We were already holding this ax25_cb */
+       ax25s = nr_neigh->ax25;
+       nr_neigh->ax25 = ax25_send_frame(skb, 256,
+                                        (ax25_address *)dev->dev_addr,
+                                        &nr_neigh->callsign,
+                                        nr_neigh->digipeat, nr_neigh->dev);
+       if (ax25s)
                ax25_cb_put(ax25s);
-       }
-       nr_neigh->ax25 = ax25s;
 
        dev_put(dev);
        ret = (nr_neigh->ax25 != NULL);
index bd86a63..5ef5f69 100644 (file)
@@ -101,13 +101,17 @@ static void rose_t0timer_expiry(unsigned long param)
 static int rose_send_frame(struct sk_buff *skb, struct rose_neigh *neigh)
 {
        ax25_address *rose_call;
+       ax25_cb *ax25s;
 
        if (ax25cmp(&rose_callsign, &null_ax25_address) == 0)
                rose_call = (ax25_address *)neigh->dev->dev_addr;
        else
                rose_call = &rose_callsign;
 
+       ax25s = neigh->ax25;
        neigh->ax25 = ax25_send_frame(skb, 260, rose_call, &neigh->callsign, neigh->digipeat, neigh->dev);
+       if (ax25s)
+               ax25_cb_put(ax25s);
 
        return (neigh->ax25 != NULL);
 }
@@ -120,13 +124,17 @@ static int rose_send_frame(struct sk_buff *skb, struct rose_neigh *neigh)
 static int rose_link_up(struct rose_neigh *neigh)
 {
        ax25_address *rose_call;
+       ax25_cb *ax25s;
 
        if (ax25cmp(&rose_callsign, &null_ax25_address) == 0)
                rose_call = (ax25_address *)neigh->dev->dev_addr;
        else
                rose_call = &rose_callsign;
 
+       ax25s = neigh->ax25;
        neigh->ax25 = ax25_find_cb(rose_call, &neigh->callsign, neigh->digipeat, neigh->dev);
+       if (ax25s)
+               ax25_cb_put(ax25s);
 
        return (neigh->ax25 != NULL);
 }
index 795c4b0..70a0b3b 100644 (file)
@@ -235,6 +235,8 @@ static void rose_remove_neigh(struct rose_neigh *rose_neigh)
 
        if ((s = rose_neigh_list) == rose_neigh) {
                rose_neigh_list = rose_neigh->next;
+               if (rose_neigh->ax25)
+                       ax25_cb_put(rose_neigh->ax25);
                kfree(rose_neigh->digipeat);
                kfree(rose_neigh);
                return;
@@ -243,6 +245,8 @@ static void rose_remove_neigh(struct rose_neigh *rose_neigh)
        while (s != NULL && s->next != NULL) {
                if (s->next == rose_neigh) {
                        s->next = rose_neigh->next;
+                       if (rose_neigh->ax25)
+                               ax25_cb_put(rose_neigh->ax25);
                        kfree(rose_neigh->digipeat);
                        kfree(rose_neigh);
                        return;
@@ -812,6 +816,7 @@ void rose_link_failed(ax25_cb *ax25, int reason)
 
        if (rose_neigh != NULL) {
                rose_neigh->ax25 = NULL;
+               ax25_cb_put(ax25);
 
                rose_del_route_by_neigh(rose_neigh);
                rose_kill_by_neigh(rose_neigh);
index 2333d78..dc0fc49 100644 (file)
@@ -655,6 +655,7 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
        memset(&wrqu, 0, sizeof(wrqu));
        wrqu.ap_addr.sa_family = ARPHRD_ETHER;
        wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
+       wdev->wext.connect.ssid_len = 0;
 #endif
 }
 
index 4725a54..0ecb16a 100644 (file)
@@ -469,16 +469,16 @@ static inline int xfrm_byidx_should_resize(struct net *net, int total)
        return 0;
 }
 
-void xfrm_spd_getinfo(struct xfrmk_spdinfo *si)
+void xfrm_spd_getinfo(struct net *net, struct xfrmk_spdinfo *si)
 {
        read_lock_bh(&xfrm_policy_lock);
-       si->incnt = init_net.xfrm.policy_count[XFRM_POLICY_IN];
-       si->outcnt = init_net.xfrm.policy_count[XFRM_POLICY_OUT];
-       si->fwdcnt = init_net.xfrm.policy_count[XFRM_POLICY_FWD];
-       si->inscnt = init_net.xfrm.policy_count[XFRM_POLICY_IN+XFRM_POLICY_MAX];
-       si->outscnt = init_net.xfrm.policy_count[XFRM_POLICY_OUT+XFRM_POLICY_MAX];
-       si->fwdscnt = init_net.xfrm.policy_count[XFRM_POLICY_FWD+XFRM_POLICY_MAX];
-       si->spdhcnt = init_net.xfrm.policy_idx_hmask;
+       si->incnt = net->xfrm.policy_count[XFRM_POLICY_IN];
+       si->outcnt = net->xfrm.policy_count[XFRM_POLICY_OUT];
+       si->fwdcnt = net->xfrm.policy_count[XFRM_POLICY_FWD];
+       si->inscnt = net->xfrm.policy_count[XFRM_POLICY_IN+XFRM_POLICY_MAX];
+       si->outscnt = net->xfrm.policy_count[XFRM_POLICY_OUT+XFRM_POLICY_MAX];
+       si->fwdscnt = net->xfrm.policy_count[XFRM_POLICY_FWD+XFRM_POLICY_MAX];
+       si->spdhcnt = net->xfrm.policy_idx_hmask;
        si->spdhmcnt = xfrm_policy_hashmax;
        read_unlock_bh(&xfrm_policy_lock);
 }
@@ -1309,15 +1309,28 @@ static inline int xfrm_get_tos(struct flowi *fl, int family)
        return tos;
 }
 
-static inline struct xfrm_dst *xfrm_alloc_dst(int family)
+static inline struct xfrm_dst *xfrm_alloc_dst(struct net *net, int family)
 {
        struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family);
+       struct dst_ops *dst_ops;
        struct xfrm_dst *xdst;
 
        if (!afinfo)
                return ERR_PTR(-EINVAL);
 
-       xdst = dst_alloc(afinfo->dst_ops) ?: ERR_PTR(-ENOBUFS);
+       switch (family) {
+       case AF_INET:
+               dst_ops = &net->xfrm.xfrm4_dst_ops;
+               break;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+       case AF_INET6:
+               dst_ops = &net->xfrm.xfrm6_dst_ops;
+               break;
+#endif
+       default:
+               BUG();
+       }
+       xdst = dst_alloc(dst_ops) ?: ERR_PTR(-ENOBUFS);
 
        xfrm_policy_put_afinfo(afinfo);
 
@@ -1366,6 +1379,7 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
                                            struct flowi *fl,
                                            struct dst_entry *dst)
 {
+       struct net *net = xp_net(policy);
        unsigned long now = jiffies;
        struct net_device *dev;
        struct dst_entry *dst_prev = NULL;
@@ -1389,7 +1403,7 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
        dst_hold(dst);
 
        for (; i < nx; i++) {
-               struct xfrm_dst *xdst = xfrm_alloc_dst(family);
+               struct xfrm_dst *xdst = xfrm_alloc_dst(net, family);
                struct dst_entry *dst1 = &xdst->u.dst;
 
                err = PTR_ERR(xdst);
@@ -2279,6 +2293,7 @@ EXPORT_SYMBOL(xfrm_bundle_ok);
 
 int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo)
 {
+       struct net *net;
        int err = 0;
        if (unlikely(afinfo == NULL))
                return -EINVAL;
@@ -2302,6 +2317,27 @@ int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo)
                xfrm_policy_afinfo[afinfo->family] = afinfo;
        }
        write_unlock_bh(&xfrm_policy_afinfo_lock);
+
+       rtnl_lock();
+       for_each_net(net) {
+               struct dst_ops *xfrm_dst_ops;
+
+               switch (afinfo->family) {
+               case AF_INET:
+                       xfrm_dst_ops = &net->xfrm.xfrm4_dst_ops;
+                       break;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+               case AF_INET6:
+                       xfrm_dst_ops = &net->xfrm.xfrm6_dst_ops;
+                       break;
+#endif
+               default:
+                       BUG();
+               }
+               *xfrm_dst_ops = *afinfo->dst_ops;
+       }
+       rtnl_unlock();
+
        return err;
 }
 EXPORT_SYMBOL(xfrm_policy_register_afinfo);
@@ -2332,6 +2368,22 @@ int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo)
 }
 EXPORT_SYMBOL(xfrm_policy_unregister_afinfo);
 
+static void __net_init xfrm_dst_ops_init(struct net *net)
+{
+       struct xfrm_policy_afinfo *afinfo;
+
+       read_lock_bh(&xfrm_policy_afinfo_lock);
+       afinfo = xfrm_policy_afinfo[AF_INET];
+       if (afinfo)
+               net->xfrm.xfrm4_dst_ops = *afinfo->dst_ops;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+       afinfo = xfrm_policy_afinfo[AF_INET6];
+       if (afinfo)
+               net->xfrm.xfrm6_dst_ops = *afinfo->dst_ops;
+#endif
+       read_unlock_bh(&xfrm_policy_afinfo_lock);
+}
+
 static struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family)
 {
        struct xfrm_policy_afinfo *afinfo;
@@ -2494,6 +2546,7 @@ static int __net_init xfrm_net_init(struct net *net)
        rv = xfrm_policy_init(net);
        if (rv < 0)
                goto out_policy;
+       xfrm_dst_ops_init(net);
        rv = xfrm_sysctl_init(net);
        if (rv < 0)
                goto out_sysctl;
index d847f1a..b36cc34 100644 (file)
@@ -641,11 +641,11 @@ out:
 }
 EXPORT_SYMBOL(xfrm_state_flush);
 
-void xfrm_sad_getinfo(struct xfrmk_sadinfo *si)
+void xfrm_sad_getinfo(struct net *net, struct xfrmk_sadinfo *si)
 {
        spin_lock_bh(&xfrm_state_lock);
-       si->sadcnt = init_net.xfrm.state_num;
-       si->sadhcnt = init_net.xfrm.state_hmask;
+       si->sadcnt = net->xfrm.state_num;
+       si->sadhcnt = net->xfrm.state_hmask;
        si->sadhmcnt = xfrm_state_hashmax;
        spin_unlock_bh(&xfrm_state_lock);
 }
index 1ada618..d5a7129 100644 (file)
@@ -781,7 +781,8 @@ static inline size_t xfrm_spdinfo_msgsize(void)
               + nla_total_size(sizeof(struct xfrmu_spdhinfo));
 }
 
-static int build_spdinfo(struct sk_buff *skb, u32 pid, u32 seq, u32 flags)
+static int build_spdinfo(struct sk_buff *skb, struct net *net,
+                        u32 pid, u32 seq, u32 flags)
 {
        struct xfrmk_spdinfo si;
        struct xfrmu_spdinfo spc;
@@ -795,7 +796,7 @@ static int build_spdinfo(struct sk_buff *skb, u32 pid, u32 seq, u32 flags)
 
        f = nlmsg_data(nlh);
        *f = flags;
-       xfrm_spd_getinfo(&si);
+       xfrm_spd_getinfo(net, &si);
        spc.incnt = si.incnt;
        spc.outcnt = si.outcnt;
        spc.fwdcnt = si.fwdcnt;
@@ -828,7 +829,7 @@ static int xfrm_get_spdinfo(struct sk_buff *skb, struct nlmsghdr *nlh,
        if (r_skb == NULL)
                return -ENOMEM;
 
-       if (build_spdinfo(r_skb, spid, seq, *flags) < 0)
+       if (build_spdinfo(r_skb, net, spid, seq, *flags) < 0)
                BUG();
 
        return nlmsg_unicast(net->xfrm.nlsk, r_skb, spid);
@@ -841,7 +842,8 @@ static inline size_t xfrm_sadinfo_msgsize(void)
               + nla_total_size(4); /* XFRMA_SAD_CNT */
 }
 
-static int build_sadinfo(struct sk_buff *skb, u32 pid, u32 seq, u32 flags)
+static int build_sadinfo(struct sk_buff *skb, struct net *net,
+                        u32 pid, u32 seq, u32 flags)
 {
        struct xfrmk_sadinfo si;
        struct xfrmu_sadhinfo sh;
@@ -854,7 +856,7 @@ static int build_sadinfo(struct sk_buff *skb, u32 pid, u32 seq, u32 flags)
 
        f = nlmsg_data(nlh);
        *f = flags;
-       xfrm_sad_getinfo(&si);
+       xfrm_sad_getinfo(net, &si);
 
        sh.sadhmcnt = si.sadhmcnt;
        sh.sadhcnt = si.sadhcnt;
@@ -882,7 +884,7 @@ static int xfrm_get_sadinfo(struct sk_buff *skb, struct nlmsghdr *nlh,
        if (r_skb == NULL)
                return -ENOMEM;
 
-       if (build_sadinfo(r_skb, spid, seq, *flags) < 0)
+       if (build_sadinfo(r_skb, net, spid, seq, *flags) < 0)
                BUG();
 
        return nlmsg_unicast(net->xfrm.nlsk, r_skb, spid);
index 30f70fd..a9d3fc6 100644 (file)
@@ -72,12 +72,13 @@ static void
 irqfd_shutdown(struct work_struct *work)
 {
        struct _irqfd *irqfd = container_of(work, struct _irqfd, shutdown);
+       u64 cnt;
 
        /*
         * Synchronize with the wait-queue and unhook ourselves to prevent
         * further events.
         */
-       remove_wait_queue(irqfd->wqh, &irqfd->wait);
+       eventfd_ctx_remove_wait_queue(irqfd->eventfd, &irqfd->wait, &cnt);
 
        /*
         * We know no new events will be scheduled at this point, so block
@@ -166,7 +167,7 @@ irqfd_ptable_queue_proc(struct file *file, wait_queue_head_t *wqh,
 static int
 kvm_irqfd_assign(struct kvm *kvm, int fd, int gsi)
 {
-       struct _irqfd *irqfd;
+       struct _irqfd *irqfd, *tmp;
        struct file *file = NULL;
        struct eventfd_ctx *eventfd = NULL;
        int ret;
@@ -203,9 +204,20 @@ kvm_irqfd_assign(struct kvm *kvm, int fd, int gsi)
        init_waitqueue_func_entry(&irqfd->wait, irqfd_wakeup);
        init_poll_funcptr(&irqfd->pt, irqfd_ptable_queue_proc);
 
+       spin_lock_irq(&kvm->irqfds.lock);
+
+       ret = 0;
+       list_for_each_entry(tmp, &kvm->irqfds.items, list) {
+               if (irqfd->eventfd != tmp->eventfd)
+                       continue;
+               /* This fd is used for another irq already. */
+               ret = -EBUSY;
+               spin_unlock_irq(&kvm->irqfds.lock);
+               goto fail;
+       }
+
        events = file->f_op->poll(file, &irqfd->pt);
 
-       spin_lock_irq(&kvm->irqfds.lock);
        list_add_tail(&irqfd->list, &kvm->irqfds.items);
        spin_unlock_irq(&kvm->irqfds.lock);
 
index 9b07734..9fd5b3e 100644 (file)
@@ -302,6 +302,7 @@ static int setup_routing_entry(struct kvm_irq_routing_table *rt,
 {
        int r = -EINVAL;
        int delta;
+       unsigned max_pin;
        struct kvm_kernel_irq_routing_entry *ei;
        struct hlist_node *n;
 
@@ -322,12 +323,15 @@ static int setup_routing_entry(struct kvm_irq_routing_table *rt,
                switch (ue->u.irqchip.irqchip) {
                case KVM_IRQCHIP_PIC_MASTER:
                        e->set = kvm_set_pic_irq;
+                       max_pin = 16;
                        break;
                case KVM_IRQCHIP_PIC_SLAVE:
                        e->set = kvm_set_pic_irq;
+                       max_pin = 16;
                        delta = 8;
                        break;
                case KVM_IRQCHIP_IOAPIC:
+                       max_pin = KVM_IOAPIC_NUM_PINS;
                        e->set = kvm_set_ioapic_irq;
                        break;
                default:
@@ -335,7 +339,7 @@ static int setup_routing_entry(struct kvm_irq_routing_table *rt,
                }
                e->irqchip.irqchip = ue->u.irqchip.irqchip;
                e->irqchip.pin = ue->u.irqchip.pin + delta;
-               if (e->irqchip.pin >= KVM_IOAPIC_NUM_PINS)
+               if (e->irqchip.pin >= max_pin)
                        goto out;
                rt->chip[ue->u.irqchip.irqchip][e->irqchip.pin] = ue->gsi;
                break;