Merge remote-tracking branch 'spi/topic/mpc512x' into spi-next
authorMark Brown <broonie@linaro.org>
Sun, 1 Sep 2013 12:48:57 +0000 (13:48 +0100)
committerMark Brown <broonie@linaro.org>
Sun, 1 Sep 2013 12:48:57 +0000 (13:48 +0100)
174 files changed:
Documentation/devicetree/bindings/spi/efm32-spi.txt [new file with mode: 0644]
Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt [new file with mode: 0644]
Documentation/kernel-parameters.txt
Documentation/spi/spi-summary
MAINTAINERS
Makefile
arch/arc/lib/strchr-700.S
arch/arm/boot/dts/at91sam9n12ek.dts
arch/arm/boot/dts/at91sam9x5ek.dtsi
arch/arm/boot/dts/tegra20-seaboard.dts
arch/arm/boot/dts/tegra20-trimslice.dts
arch/arm/boot/dts/tegra20-whistler.dts
arch/arm/kernel/fiq.c
arch/arm/kernel/machine_kexec.c
arch/arm/kvm/coproc.c
arch/arm/kvm/coproc.h
arch/arm/kvm/coproc_a15.c
arch/arm/kvm/mmio.c
arch/arm/kvm/mmu.c
arch/arm/mach-at91/at91sam9x5.c
arch/arm/mach-davinci/board-dm355-leopard.c
arch/arm/mach-davinci/board-dm644x-evm.c
arch/arm/mach-davinci/board-dm646x-evm.c
arch/arm/mach-davinci/board-neuros-osd2.c
arch/arm/mach-omap2/board-n8x0.c
arch/arm/mach-omap2/board-rx51.c
arch/arm/mach-omap2/usb-musb.c
arch/arm/mm/Kconfig
arch/arm/plat-samsung/init.c
arch/arm/xen/enlighten.c
arch/arm64/include/asm/kvm_asm.h
arch/arm64/include/asm/kvm_host.h
arch/arm64/kernel/perf_event.c
arch/arm64/kvm/hyp.S
arch/arm64/kvm/sys_regs.c
arch/mips/math-emu/cp1emu.c
arch/x86/include/asm/bootparam_utils.h
arch/x86/include/asm/microcode_amd.h
arch/x86/kernel/cpu/amd.c
arch/x86/kernel/microcode_amd.c
arch/x86/kernel/microcode_amd_early.c
arch/x86/kernel/sys_x86_64.c
arch/x86/mm/mmap.c
arch/x86/xen/setup.c
arch/x86/xen/smp.c
drivers/acpi/video.c
drivers/ata/libata-pmp.c
drivers/ata/sata_fsl.c
drivers/ata/sata_highbank.c
drivers/gpu/drm/gma500/psb_intel_sdvo.c
drivers/gpu/drm/i915/i915_gem_dmabuf.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_ringbuffer.c
drivers/gpu/drm/nouveau/core/core/mm.c
drivers/gpu/drm/nouveau/core/include/subdev/mc.h
drivers/gpu/drm/nouveau/core/subdev/fb/ramnv49.c
drivers/gpu/drm/nouveau/core/subdev/fb/ramnv4e.c
drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c
drivers/gpu/drm/nouveau/core/subdev/mc/base.c
drivers/gpu/drm/nouveau/core/subdev/mc/nv04.c
drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c
drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c
drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c
drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c
drivers/gpu/drm/nouveau/dispnv04/crtc.c
drivers/gpu/drm/nouveau/dispnv04/disp.h
drivers/gpu/drm/nouveau/nouveau_display.c
drivers/gpu/drm/nouveau/nv40_pm.c
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_uvd.c
drivers/gpu/drm/radeon/rv770.c
drivers/iio/light/adjd_s311.c
drivers/md/dm-cache-policy-mq.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
drivers/net/ethernet/emulex/benet/be_main.c
drivers/net/ethernet/realtek/r8169.c
drivers/net/ethernet/sfc/filter.c
drivers/net/irda/via-ircc.c
drivers/net/macvtap.c
drivers/net/phy/realtek.c
drivers/net/usb/hso.c
drivers/net/wireless/hostap/hostap_ioctl.c
drivers/net/wireless/iwlwifi/dvm/mac80211.c
drivers/net/wireless/iwlwifi/iwl-prph.h
drivers/net/wireless/iwlwifi/mvm/time-event.c
drivers/net/wireless/iwlwifi/pcie/rx.c
drivers/net/wireless/iwlwifi/pcie/trans.c
drivers/net/wireless/zd1201.c
drivers/of/fdt.c
drivers/pinctrl/pinctrl-sunxi.c
drivers/pinctrl/pinctrl-sunxi.h
drivers/platform/olpc/olpc-ec.c
drivers/platform/x86/hp-wmi.c
drivers/platform/x86/sony-laptop.c
drivers/s390/scsi/zfcp_erp.c
drivers/s390/scsi/zfcp_qdio.c
drivers/s390/scsi/zfcp_sysfs.c
drivers/scsi/Kconfig
drivers/spi/Kconfig
drivers/spi/Makefile
drivers/spi/spi-altera.c
drivers/spi/spi-atmel.c
drivers/spi/spi-bcm2835.c
drivers/spi/spi-bcm63xx.c
drivers/spi/spi-bfin-v3.c [new file with mode: 0644]
drivers/spi/spi-bitbang.c
drivers/spi/spi-clps711x.c
drivers/spi/spi-efm32.c [new file with mode: 0644]
drivers/spi/spi-ep93xx.c
drivers/spi/spi-fsl-dspi.c [new file with mode: 0644]
drivers/spi/spi-imx.c
drivers/spi/spi-nuc900.c
drivers/spi/spi-oc-tiny.c
drivers/spi/spi-orion.c
drivers/spi/spi-xilinx.c
drivers/spi/spi.c
drivers/staging/comedi/drivers.c
drivers/usb/host/ohci-pci.c
drivers/usb/phy/phy-fsl-usb.h
drivers/usb/phy/phy-fsm-usb.c
drivers/xen/events.c
fs/bfs/inode.c
fs/bio.c
fs/dcache.c
fs/efs/inode.c
fs/gfs2/glock.c
fs/gfs2/glops.c
fs/gfs2/inode.c
fs/gfs2/main.c
fs/hugetlbfs/inode.c
fs/namespace.c
fs/nilfs2/segbuf.c
fs/proc/fd.c
fs/proc/generic.c
fs/proc/root.c
include/linux/dcache.h
include/linux/inetdevice.h
include/linux/ipv6.h
include/linux/mm_types.h
include/linux/platform_data/efm32-spi.h [new file with mode: 0644]
include/linux/sched.h
include/linux/spi/spi.h
include/linux/spi/spi_bitbang.h
include/linux/wait.h
include/net/ip6_route.h
include/uapi/linux/ip.h
init/Kconfig
kernel/cpuset.c
kernel/time/sched_clock.c
kernel/time/tick-sched.c
kernel/wait.c
lib/lz4/lz4_compress.c
lib/lz4/lz4_decompress.c
lib/lz4/lz4hc_compress.c
mm/memcontrol.c
mm/shmem.c
net/batman-adv/unicast.c
net/bridge/br_fdb.c
net/bridge/br_netlink.c
net/bridge/br_vlan.c
net/ipv4/tcp.c
net/ipv6/addrconf.c
net/ipv6/ndisc.c
net/ipv6/reassembly.c
net/ipv6/route.c
net/netlink/genetlink.c
net/packet/af_packet.c
net/wireless/nl80211.c
net/wireless/sme.c

diff --git a/Documentation/devicetree/bindings/spi/efm32-spi.txt b/Documentation/devicetree/bindings/spi/efm32-spi.txt
new file mode 100644 (file)
index 0000000..a590ca5
--- /dev/null
@@ -0,0 +1,34 @@
+* Energy Micro EFM32 SPI
+
+Required properties:
+- #address-cells: see spi-bus.txt
+- #size-cells: see spi-bus.txt
+- compatible: should be "efm32,spi"
+- reg: Offset and length of the register set for the controller
+- interrupts: pair specifying rx and tx irq
+- clocks: phandle to the spi clock
+- cs-gpios: see spi-bus.txt
+- location: Value to write to the ROUTE register's LOCATION bitfield to configure the pinmux for the device, see datasheet for values.
+
+Example:
+
+spi1: spi@0x4000c400 { /* USART1 */
+       #address-cells = <1>;
+       #size-cells = <0>;
+       compatible = "efm32,spi";
+       reg = <0x4000c400 0x400>;
+       interrupts = <15 16>;
+       clocks = <&cmu 20>;
+       cs-gpios = <&gpio 51 1>; // D3
+       location = <1>;
+       status = "ok";
+
+       ks8851@0 {
+               compatible = "ks8851";
+               spi-max-frequency = <6000000>;
+               reg = <0>;
+               interrupt-parent = <&boardfpga>;
+               interrupts = <4>;
+               status = "ok";
+       };
+};
diff --git a/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt b/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt
new file mode 100644 (file)
index 0000000..a1fb303
--- /dev/null
@@ -0,0 +1,42 @@
+ARM Freescale DSPI controller
+
+Required properties:
+- compatible : "fsl,vf610-dspi"
+- reg : Offset and length of the register set for the device
+- interrupts : Should contain SPI controller interrupt
+- clocks: from common clock binding: handle to dspi clock.
+- clock-names: from common clock binding: Shall be "dspi".
+- pinctrl-0: pin control group to be used for this controller.
+- pinctrl-names: must contain a "default" entry.
+- spi-num-chipselects : the number of the chipselect signals.
+- bus-num : the slave chip chipselect signal number.
+Example:
+
+dspi0@4002c000 {
+       #address-cells = <1>;
+       #size-cells = <0>;
+       compatible = "fsl,vf610-dspi";
+       reg = <0x4002c000 0x1000>;
+       interrupts = <0 67 0x04>;
+       clocks = <&clks VF610_CLK_DSPI0>;
+       clock-names = "dspi";
+       spi-num-chipselects = <5>;
+       bus-num = <0>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_dspi0_1>;
+       status = "okay";
+
+       sflash: at26df081a@0 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "atmel,at26df081a";
+               spi-max-frequency = <16000000>;
+               spi-cpol;
+               spi-cpha;
+               reg = <0>;
+               linux,modalias = "m25p80";
+               modal = "at26df081a";
+       };
+};
+
+
index 15356ac..7f9d4f5 100644 (file)
@@ -2953,7 +2953,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        improve throughput, but will also increase the
                        amount of memory reserved for use by the client.
 
-       swapaccount[=0|1]
+       swapaccount=[0|1]
                        [KNL] Enable accounting of swap in memory resource
                        controller if no parameter or 1 is given or disable
                        it if 0 is given (See Documentation/cgroups/memory.txt)
index 2331eb2..f21edb9 100644 (file)
@@ -215,7 +215,7 @@ So for example arch/.../mach-*/board-*.c files might have code like:
        /* if your mach-* infrastructure doesn't support kernels that can
         * run on multiple boards, pdata wouldn't benefit from "__init".
         */
-       static struct mysoc_spi_data __initdata pdata = { ... };
+       static struct mysoc_spi_data pdata __initdata = { ... };
 
        static __init board_init(void)
        {
index 229c66b..8197fbd 100644 (file)
@@ -5884,7 +5884,7 @@ F:        drivers/i2c/busses/i2c-omap.c
 F:     include/linux/i2c-omap.h
 
 OMAP DEVICE TREE SUPPORT
-M:     Benoît Cousson <b-cousson@ti.com>
+M:     Benoît Cousson <bcousson@baylibre.com>
 M:     Tony Lindgren <tony@atomide.com>
 L:     linux-omap@vger.kernel.org
 L:     devicetree@vger.kernel.org
@@ -5964,14 +5964,14 @@ S:      Maintained
 F:     drivers/char/hw_random/omap-rng.c
 
 OMAP HWMOD SUPPORT
-M:     Benoît Cousson <b-cousson@ti.com>
+M:     Benoît Cousson <bcousson@baylibre.com>
 M:     Paul Walmsley <paul@pwsan.com>
 L:     linux-omap@vger.kernel.org
 S:     Maintained
 F:     arch/arm/mach-omap2/omap_hwmod.*
 
 OMAP HWMOD DATA FOR OMAP4-BASED DEVICES
-M:     Benoît Cousson <b-cousson@ti.com>
+M:     Benoît Cousson <bcousson@baylibre.com>
 L:     linux-omap@vger.kernel.org
 S:     Maintained
 F:     arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index a5a55f4..369882e 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 3
 PATCHLEVEL = 11
 SUBLEVEL = 0
-EXTRAVERSION = -rc6
+EXTRAVERSION = -rc7
 NAME = Linux for Workgroups
 
 # *DOCUMENTATION*
index 99c1047..9c548c7 100644 (file)
@@ -39,9 +39,18 @@ ARC_ENTRY strchr
        ld.a    r2,[r0,4]
        sub     r12,r6,r7
        bic     r12,r12,r6
+#ifdef __LITTLE_ENDIAN__
        and     r7,r12,r4
        breq    r7,0,.Loop ; For speed, we want this branch to be unaligned.
        b       .Lfound_char ; Likewise this one.
+#else
+       and     r12,r12,r4
+       breq    r12,0,.Loop ; For speed, we want this branch to be unaligned.
+       lsr_s   r12,r12,7
+       bic     r2,r7,r6
+       b.d     .Lfound_char_b
+       and_s   r2,r2,r12
+#endif
 ; /* We require this code address to be unaligned for speed...  */
 .Laligned:
        ld_s    r2,[r0]
@@ -95,6 +104,7 @@ ARC_ENTRY strchr
        lsr     r7,r7,7
 
        bic     r2,r7,r6
+.Lfound_char_b:
        norm    r2,r2
        sub_s   r0,r0,4
        asr_s   r2,r2,3
index d59b70c..3d77dbe 100644 (file)
        compatible = "atmel,at91sam9n12ek", "atmel,at91sam9n12", "atmel,at91sam9";
 
        chosen {
-               bootargs = "mem=128M console=ttyS0,115200 root=/dev/mtdblock1 rw rootfstype=jffs2";
+               bootargs = "console=ttyS0,115200 root=/dev/mtdblock1 rw rootfstype=jffs2";
        };
 
        memory {
-               reg = <0x20000000 0x10000000>;
+               reg = <0x20000000 0x8000000>;
        };
 
        clocks {
index b753855..49e3c45 100644 (file)
@@ -94,8 +94,9 @@
 
                usb0: ohci@00600000 {
                        status = "okay";
-                       num-ports = <2>;
-                       atmel,vbus-gpio = <&pioD 19 GPIO_ACTIVE_LOW
+                       num-ports = <3>;
+                       atmel,vbus-gpio = <0 /* &pioD 18 GPIO_ACTIVE_LOW *//* Activate to have access to port A */
+                                          &pioD 19 GPIO_ACTIVE_LOW
                                           &pioD 20 GPIO_ACTIVE_LOW
                                          >;
                };
index 365760b..40e6fb2 100644 (file)
                        regulator-max-microvolt = <5000000>;
                        enable-active-high;
                        gpio = <&gpio 24 0>; /* PD0 */
+                       regulator-always-on;
+                       regulator-boot-on;
                };
        };
 
index ed4b901..37c93d3 100644 (file)
                        regulator-max-microvolt = <5000000>;
                        enable-active-high;
                        gpio = <&gpio 170 0>; /* PV2 */
+                       regulator-always-on;
+                       regulator-boot-on;
                };
        };
 
index ab67c94..a3d0eba 100644 (file)
                        regulator-max-microvolt = <5000000>;
                        enable-active-high;
                        gpio = <&tca6416 0 0>; /* GPIO_PMU0 */
+                       regulator-always-on;
+                       regulator-boot-on;
                };
 
                vbus3_reg: regulator@3 {
                        regulator-max-microvolt = <5000000>;
                        enable-active-high;
                        gpio = <&tca6416 1 0>; /* GPIO_PMU1 */
+                       regulator-always-on;
+                       regulator-boot-on;
                };
        };
 
index fc79202..918875d 100644 (file)
@@ -89,7 +89,8 @@ void set_fiq_handler(void *start, unsigned int length)
 
        memcpy(base + offset, start, length);
        if (!cache_is_vipt_nonaliasing())
-               flush_icache_range(base + offset, offset + length);
+               flush_icache_range((unsigned long)base + offset, offset +
+                                  length);
        flush_icache_range(0xffff0000 + offset, 0xffff0000 + offset + length);
 }
 
index d7c82df..57221e3 100644 (file)
@@ -82,6 +82,7 @@ void machine_crash_nonpanic_core(void *unused)
        crash_save_cpu(&regs, smp_processor_id());
        flush_cache_all();
 
+       set_cpu_online(smp_processor_id(), false);
        atomic_dec(&waiting_for_crash_ipi);
        while (1)
                cpu_relax();
index 4a51990..db9cf69 100644 (file)
@@ -146,7 +146,11 @@ static bool pm_fake(struct kvm_vcpu *vcpu,
 #define access_pmintenclr pm_fake
 
 /* Architected CP15 registers.
- * Important: Must be sorted ascending by CRn, CRM, Op1, Op2
+ * CRn denotes the primary register number, but is copied to the CRm in the
+ * user space API for 64-bit register access in line with the terminology used
+ * in the ARM ARM.
+ * Important: Must be sorted ascending by CRn, CRM, Op1, Op2 and with 64-bit
+ *            registers preceding 32-bit ones.
  */
 static const struct coproc_reg cp15_regs[] = {
        /* CSSELR: swapped by interrupt.S. */
@@ -154,8 +158,8 @@ static const struct coproc_reg cp15_regs[] = {
                        NULL, reset_unknown, c0_CSSELR },
 
        /* TTBR0/TTBR1: swapped by interrupt.S. */
-       { CRm( 2), Op1( 0), is64, NULL, reset_unknown64, c2_TTBR0 },
-       { CRm( 2), Op1( 1), is64, NULL, reset_unknown64, c2_TTBR1 },
+       { CRm64( 2), Op1( 0), is64, NULL, reset_unknown64, c2_TTBR0 },
+       { CRm64( 2), Op1( 1), is64, NULL, reset_unknown64, c2_TTBR1 },
 
        /* TTBCR: swapped by interrupt.S. */
        { CRn( 2), CRm( 0), Op1( 0), Op2( 2), is32,
@@ -182,7 +186,7 @@ static const struct coproc_reg cp15_regs[] = {
                        NULL, reset_unknown, c6_IFAR },
 
        /* PAR swapped by interrupt.S */
-       { CRn( 7), Op1( 0), is64, NULL, reset_unknown64, c7_PAR },
+       { CRm64( 7), Op1( 0), is64, NULL, reset_unknown64, c7_PAR },
 
        /*
         * DC{C,I,CI}SW operations:
@@ -399,12 +403,13 @@ static bool index_to_params(u64 id, struct coproc_params *params)
                              | KVM_REG_ARM_OPC1_MASK))
                        return false;
                params->is_64bit = true;
-               params->CRm = ((id & KVM_REG_ARM_CRM_MASK)
+               /* CRm to CRn: see cp15_to_index for details */
+               params->CRn = ((id & KVM_REG_ARM_CRM_MASK)
                               >> KVM_REG_ARM_CRM_SHIFT);
                params->Op1 = ((id & KVM_REG_ARM_OPC1_MASK)
                               >> KVM_REG_ARM_OPC1_SHIFT);
                params->Op2 = 0;
-               params->CRn = 0;
+               params->CRm = 0;
                return true;
        default:
                return false;
@@ -898,7 +903,14 @@ static u64 cp15_to_index(const struct coproc_reg *reg)
        if (reg->is_64) {
                val |= KVM_REG_SIZE_U64;
                val |= (reg->Op1 << KVM_REG_ARM_OPC1_SHIFT);
-               val |= (reg->CRm << KVM_REG_ARM_CRM_SHIFT);
+               /*
+                * CRn always denotes the primary coproc. reg. nr. for the
+                * in-kernel representation, but the user space API uses the
+                * CRm for the encoding, because it is modelled after the
+                * MRRC/MCRR instructions: see the ARM ARM rev. c page
+                * B3-1445
+                */
+               val |= (reg->CRn << KVM_REG_ARM_CRM_SHIFT);
        } else {
                val |= KVM_REG_SIZE_U32;
                val |= (reg->Op1 << KVM_REG_ARM_OPC1_SHIFT);
index b7301d3..0461d5c 100644 (file)
@@ -135,6 +135,8 @@ static inline int cmp_reg(const struct coproc_reg *i1,
                return -1;
        if (i1->CRn != i2->CRn)
                return i1->CRn - i2->CRn;
+       if (i1->is_64 != i2->is_64)
+               return i2->is_64 - i1->is_64;
        if (i1->CRm != i2->CRm)
                return i1->CRm - i2->CRm;
        if (i1->Op1 != i2->Op1)
@@ -145,6 +147,7 @@ static inline int cmp_reg(const struct coproc_reg *i1,
 
 #define CRn(_x)                .CRn = _x
 #define CRm(_x)        .CRm = _x
+#define CRm64(_x)       .CRn = _x, .CRm = 0
 #define Op1(_x)        .Op1 = _x
 #define Op2(_x)        .Op2 = _x
 #define is64           .is_64 = true
index 685063a..cf93472 100644 (file)
@@ -114,7 +114,11 @@ static bool access_l2ectlr(struct kvm_vcpu *vcpu,
 
 /*
  * A15-specific CP15 registers.
- * Important: Must be sorted ascending by CRn, CRM, Op1, Op2
+ * CRn denotes the primary register number, but is copied to the CRm in the
+ * user space API for 64-bit register access in line with the terminology used
+ * in the ARM ARM.
+ * Important: Must be sorted ascending by CRn, CRM, Op1, Op2 and with 64-bit
+ *            registers preceding 32-bit ones.
  */
 static const struct coproc_reg a15_regs[] = {
        /* MPIDR: we use VMPIDR for guest access. */
index b8e06b7..0c25d94 100644 (file)
@@ -63,7 +63,8 @@ int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run)
 static int decode_hsr(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
                      struct kvm_exit_mmio *mmio)
 {
-       unsigned long rt, len;
+       unsigned long rt;
+       int len;
        bool is_write, sign_extend;
 
        if (kvm_vcpu_dabt_isextabt(vcpu)) {
index ca6bea4..0988d9e 100644 (file)
@@ -85,6 +85,12 @@ static void *mmu_memory_cache_alloc(struct kvm_mmu_memory_cache *mc)
        return p;
 }
 
+static bool page_empty(void *ptr)
+{
+       struct page *ptr_page = virt_to_page(ptr);
+       return page_count(ptr_page) == 1;
+}
+
 static void clear_pud_entry(struct kvm *kvm, pud_t *pud, phys_addr_t addr)
 {
        pmd_t *pmd_table = pmd_offset(pud, 0);
@@ -103,12 +109,6 @@ static void clear_pmd_entry(struct kvm *kvm, pmd_t *pmd, phys_addr_t addr)
        put_page(virt_to_page(pmd));
 }
 
-static bool pmd_empty(pmd_t *pmd)
-{
-       struct page *pmd_page = virt_to_page(pmd);
-       return page_count(pmd_page) == 1;
-}
-
 static void clear_pte_entry(struct kvm *kvm, pte_t *pte, phys_addr_t addr)
 {
        if (pte_present(*pte)) {
@@ -118,12 +118,6 @@ static void clear_pte_entry(struct kvm *kvm, pte_t *pte, phys_addr_t addr)
        }
 }
 
-static bool pte_empty(pte_t *pte)
-{
-       struct page *pte_page = virt_to_page(pte);
-       return page_count(pte_page) == 1;
-}
-
 static void unmap_range(struct kvm *kvm, pgd_t *pgdp,
                        unsigned long long start, u64 size)
 {
@@ -132,37 +126,37 @@ static void unmap_range(struct kvm *kvm, pgd_t *pgdp,
        pmd_t *pmd;
        pte_t *pte;
        unsigned long long addr = start, end = start + size;
-       u64 range;
+       u64 next;
 
        while (addr < end) {
                pgd = pgdp + pgd_index(addr);
                pud = pud_offset(pgd, addr);
                if (pud_none(*pud)) {
-                       addr += PUD_SIZE;
+                       addr = pud_addr_end(addr, end);
                        continue;
                }
 
                pmd = pmd_offset(pud, addr);
                if (pmd_none(*pmd)) {
-                       addr += PMD_SIZE;
+                       addr = pmd_addr_end(addr, end);
                        continue;
                }
 
                pte = pte_offset_kernel(pmd, addr);
                clear_pte_entry(kvm, pte, addr);
-               range = PAGE_SIZE;
+               next = addr + PAGE_SIZE;
 
                /* If we emptied the pte, walk back up the ladder */
-               if (pte_empty(pte)) {
+               if (page_empty(pte)) {
                        clear_pmd_entry(kvm, pmd, addr);
-                       range = PMD_SIZE;
-                       if (pmd_empty(pmd)) {
+                       next = pmd_addr_end(addr, end);
+                       if (page_empty(pmd) && !page_empty(pud)) {
                                clear_pud_entry(kvm, pud, addr);
-                               range = PUD_SIZE;
+                               next = pud_addr_end(addr, end);
                        }
                }
 
-               addr += range;
+               addr = next;
        }
 }
 
index 2abee66..916e5a1 100644 (file)
@@ -227,6 +227,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_DEV_ID("usart", "f8020000.serial", &usart1_clk),
        CLKDEV_CON_DEV_ID("usart", "f8024000.serial", &usart2_clk),
        CLKDEV_CON_DEV_ID("usart", "f8028000.serial", &usart3_clk),
+       CLKDEV_CON_DEV_ID("usart", "f8040000.serial", &uart0_clk),
+       CLKDEV_CON_DEV_ID("usart", "f8044000.serial", &uart1_clk),
        CLKDEV_CON_DEV_ID("t0_clk", "f8008000.timer", &tcb0_clk),
        CLKDEV_CON_DEV_ID("t0_clk", "f800c000.timer", &tcb0_clk),
        CLKDEV_CON_DEV_ID("mci_clk", "f0008000.mmc", &mmc0_clk),
index dff4ddc..139e42d 100644 (file)
@@ -75,6 +75,7 @@ static struct davinci_nand_pdata davinci_nand_data = {
        .parts                  = davinci_nand_partitions,
        .nr_parts               = ARRAY_SIZE(davinci_nand_partitions),
        .ecc_mode               = NAND_ECC_HW_SYNDROME,
+       .ecc_bits               = 4,
        .bbt_options            = NAND_BBT_USE_FLASH,
 };
 
index a33686a..fa4bfaf 100644 (file)
@@ -153,6 +153,7 @@ static struct davinci_nand_pdata davinci_evm_nandflash_data = {
        .parts          = davinci_evm_nandflash_partition,
        .nr_parts       = ARRAY_SIZE(davinci_evm_nandflash_partition),
        .ecc_mode       = NAND_ECC_HW,
+       .ecc_bits       = 1,
        .bbt_options    = NAND_BBT_USE_FLASH,
        .timing         = &davinci_evm_nandflash_timing,
 };
index fbb8e5a..0c005e8 100644 (file)
@@ -90,6 +90,7 @@ static struct davinci_nand_pdata davinci_nand_data = {
        .parts                  = davinci_nand_partitions,
        .nr_parts               = ARRAY_SIZE(davinci_nand_partitions),
        .ecc_mode               = NAND_ECC_HW,
+       .ecc_bits               = 1,
        .options                = 0,
 };
 
index 2bc112a..808233b 100644 (file)
@@ -88,6 +88,7 @@ static struct davinci_nand_pdata davinci_ntosd2_nandflash_data = {
        .parts          = davinci_ntosd2_nandflash_partition,
        .nr_parts       = ARRAY_SIZE(davinci_ntosd2_nandflash_partition),
        .ecc_mode       = NAND_ECC_HW,
+       .ecc_bits       = 1,
        .bbt_options    = NAND_BBT_USE_FLASH,
 };
 
index f6eeb87..827d150 100644 (file)
@@ -122,11 +122,7 @@ static struct musb_hdrc_config musb_config = {
 };
 
 static struct musb_hdrc_platform_data tusb_data = {
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
        .mode           = MUSB_OTG,
-#else
-       .mode           = MUSB_HOST,
-#endif
        .set_power      = tusb_set_power,
        .min_power      = 25,   /* x2 = 50 mA drawn from VBUS as peripheral */
        .power          = 100,  /* Max 100 mA VBUS for host mode */
index d2ea68e..7735105 100644 (file)
@@ -85,7 +85,7 @@ static struct omap_board_mux board_mux[] __initdata = {
 
 static struct omap_musb_board_data musb_board_data = {
        .interface_type         = MUSB_INTERFACE_ULPI,
-       .mode                   = MUSB_PERIPHERAL,
+       .mode                   = MUSB_OTG,
        .power                  = 0,
 };
 
index 8c4de27..bc89723 100644 (file)
@@ -38,11 +38,8 @@ static struct musb_hdrc_config musb_config = {
 };
 
 static struct musb_hdrc_platform_data musb_plat = {
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
        .mode           = MUSB_OTG,
-#else
-       .mode           = MUSB_HOST,
-#endif
+
        /* .clock is set dynamically */
        .config         = &musb_config,
 
index db5c2ca..cd2c88e 100644 (file)
@@ -809,15 +809,18 @@ config KUSER_HELPERS
          the CPU type fitted to the system.  This permits binaries to be
          run on ARMv4 through to ARMv7 without modification.
 
+         See Documentation/arm/kernel_user_helpers.txt for details.
+
          However, the fixed address nature of these helpers can be used
          by ROP (return orientated programming) authors when creating
          exploits.
 
          If all of the binaries and libraries which run on your platform
          are built specifically for your platform, and make no use of
-         these helpers, then you can turn this option off.  However,
-         when such an binary or library is run, it will receive a SIGILL
-         signal, which will terminate the program.
+         these helpers, then you can turn this option off to hinder
+         such exploits. However, in that case, if a binary or library
+         relying on those helpers is run, it will receive a SIGILL signal,
+         which will terminate the program.
 
          Say N here only if you are absolutely certain that you do not
          need these helpers; otherwise, the safe option is to say Y.
index 3e5c461..50a3ea0 100644 (file)
@@ -55,12 +55,13 @@ void __init s3c_init_cpu(unsigned long idcode,
 
        printk("CPU %s (id 0x%08lx)\n", cpu->name, idcode);
 
-       if (cpu->map_io == NULL || cpu->init == NULL) {
+       if (cpu->init == NULL) {
                printk(KERN_ERR "CPU %s support not enabled\n", cpu->name);
                panic("Unsupported Samsung CPU");
        }
 
-       cpu->map_io();
+       if (cpu->map_io)
+               cpu->map_io();
 }
 
 /* s3c24xx_init_clocks
index c9770ba..8a6295c 100644 (file)
@@ -170,6 +170,7 @@ static void __init xen_percpu_init(void *unused)
        per_cpu(xen_vcpu, cpu) = vcpup;
 
        enable_percpu_irq(xen_events_irq, 0);
+       put_cpu();
 }
 
 static void xen_restart(enum reboot_mode reboot_mode, const char *cmd)
index c92de41..b25763b 100644 (file)
 #define        TPIDR_EL1       18      /* Thread ID, Privileged */
 #define        AMAIR_EL1       19      /* Aux Memory Attribute Indirection Register */
 #define        CNTKCTL_EL1     20      /* Timer Control Register (EL1) */
+#define        PAR_EL1         21      /* Physical Address Register */
 /* 32bit specific registers. Keep them at the end of the range */
-#define        DACR32_EL2      21      /* Domain Access Control Register */
-#define        IFSR32_EL2      22      /* Instruction Fault Status Register */
-#define        FPEXC32_EL2     23      /* Floating-Point Exception Control Register */
-#define        DBGVCR32_EL2    24      /* Debug Vector Catch Register */
-#define        TEECR32_EL1     25      /* ThumbEE Configuration Register */
-#define        TEEHBR32_EL1    26      /* ThumbEE Handler Base Register */
-#define        NR_SYS_REGS     27
+#define        DACR32_EL2      22      /* Domain Access Control Register */
+#define        IFSR32_EL2      23      /* Instruction Fault Status Register */
+#define        FPEXC32_EL2     24      /* Floating-Point Exception Control Register */
+#define        DBGVCR32_EL2    25      /* Debug Vector Catch Register */
+#define        TEECR32_EL1     26      /* ThumbEE Configuration Register */
+#define        TEEHBR32_EL1    27      /* ThumbEE Handler Base Register */
+#define        NR_SYS_REGS     28
 
 /* 32bit mapping */
 #define c0_MPIDR       (MPIDR_EL1 * 2) /* MultiProcessor ID Register */
@@ -69,6 +70,8 @@
 #define c5_AIFSR       (AFSR1_EL1 * 2) /* Auxiliary Instr Fault Status R */
 #define c6_DFAR                (FAR_EL1 * 2)   /* Data Fault Address Register */
 #define c6_IFAR                (c6_DFAR + 1)   /* Instruction Fault Address Register */
+#define c7_PAR         (PAR_EL1 * 2)   /* Physical Address Register */
+#define c7_PAR_high    (c7_PAR + 1)    /* PAR top 32 bits */
 #define c10_PRRR       (MAIR_EL1 * 2)  /* Primary Region Remap Register */
 #define c10_NMRR       (c10_PRRR + 1)  /* Normal Memory Remap Register */
 #define c12_VBAR       (VBAR_EL1 * 2)  /* Vector Base Address Register */
index 644d739..0859a4d 100644 (file)
@@ -129,7 +129,7 @@ struct kvm_vcpu_arch {
        struct kvm_mmu_memory_cache mmu_page_cache;
 
        /* Target CPU and feature flags */
-       u32 target;
+       int target;
        DECLARE_BITMAP(features, KVM_VCPU_MAX_FEATURES);
 
        /* Detect first run of a vcpu */
index 9ba33c4..12e6ccb 100644 (file)
@@ -107,7 +107,12 @@ armpmu_map_cache_event(const unsigned (*cache_map)
 static int
 armpmu_map_event(const unsigned (*event_map)[PERF_COUNT_HW_MAX], u64 config)
 {
-       int mapping = (*event_map)[config];
+       int mapping;
+
+       if (config >= PERF_COUNT_HW_MAX)
+               return -EINVAL;
+
+       mapping = (*event_map)[config];
        return mapping == HW_OP_UNSUPPORTED ? -ENOENT : mapping;
 }
 
@@ -317,6 +322,9 @@ validate_event(struct pmu_hw_events *hw_events,
        struct hw_perf_event fake_event = event->hw;
        struct pmu *leader_pmu = event->group_leader->pmu;
 
+       if (is_software_event(event))
+               return 1;
+
        if (event->pmu != leader_pmu || event->state <= PERF_EVENT_STATE_OFF)
                return 1;
 
index ff985e3..1ac0bbb 100644 (file)
@@ -214,6 +214,7 @@ __kvm_hyp_code_start:
        mrs     x21,    tpidr_el1
        mrs     x22,    amair_el1
        mrs     x23,    cntkctl_el1
+       mrs     x24,    par_el1
 
        stp     x4, x5, [x3]
        stp     x6, x7, [x3, #16]
@@ -225,6 +226,7 @@ __kvm_hyp_code_start:
        stp     x18, x19, [x3, #112]
        stp     x20, x21, [x3, #128]
        stp     x22, x23, [x3, #144]
+       str     x24, [x3, #160]
 .endm
 
 .macro restore_sysregs
@@ -243,6 +245,7 @@ __kvm_hyp_code_start:
        ldp     x18, x19, [x3, #112]
        ldp     x20, x21, [x3, #128]
        ldp     x22, x23, [x3, #144]
+       ldr     x24, [x3, #160]
 
        msr     vmpidr_el2,     x4
        msr     csselr_el1,     x5
@@ -264,6 +267,7 @@ __kvm_hyp_code_start:
        msr     tpidr_el1,      x21
        msr     amair_el1,      x22
        msr     cntkctl_el1,    x23
+       msr     par_el1,        x24
 .endm
 
 .macro skip_32bit_state tmp, target
@@ -600,6 +604,8 @@ END(__kvm_vcpu_run)
 
 // void __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa);
 ENTRY(__kvm_tlb_flush_vmid_ipa)
+       dsb     ishst
+
        kern_hyp_va     x0
        ldr     x2, [x0, #KVM_VTTBR]
        msr     vttbr_el2, x2
@@ -621,6 +627,7 @@ ENTRY(__kvm_tlb_flush_vmid_ipa)
 ENDPROC(__kvm_tlb_flush_vmid_ipa)
 
 ENTRY(__kvm_flush_vm_context)
+       dsb     ishst
        tlbi    alle1is
        ic      ialluis
        dsb     sy
@@ -753,6 +760,10 @@ el1_trap:
         */
        tbnz    x1, #7, 1f      // S1PTW is set
 
+       /* Preserve PAR_EL1 */
+       mrs     x3, par_el1
+       push    x3, xzr
+
        /*
         * Permission fault, HPFAR_EL2 is invalid.
         * Resolve the IPA the hard way using the guest VA.
@@ -766,6 +777,8 @@ el1_trap:
 
        /* Read result */
        mrs     x3, par_el1
+       pop     x0, xzr                 // Restore PAR_EL1 from the stack
+       msr     par_el1, x0
        tbnz    x3, #0, 3f              // Bail out if we failed the translation
        ubfx    x3, x3, #12, #36        // Extract IPA
        lsl     x3, x3, #4              // and present it like HPFAR
index 9492360..02e9d09 100644 (file)
@@ -211,6 +211,9 @@ static const struct sys_reg_desc sys_reg_descs[] = {
        /* FAR_EL1 */
        { Op0(0b11), Op1(0b000), CRn(0b0110), CRm(0b0000), Op2(0b000),
          NULL, reset_unknown, FAR_EL1 },
+       /* PAR_EL1 */
+       { Op0(0b11), Op1(0b000), CRn(0b0111), CRm(0b0100), Op2(0b000),
+         NULL, reset_unknown, PAR_EL1 },
 
        /* PMINTENSET_EL1 */
        { Op0(0b11), Op1(0b000), CRn(0b1001), CRm(0b1110), Op2(0b001),
index e773659..46048d2 100644 (file)
@@ -803,6 +803,32 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
                                dec_insn.next_pc_inc;
                return 1;
                break;
+#ifdef CONFIG_CPU_CAVIUM_OCTEON
+       case lwc2_op: /* This is bbit0 on Octeon */
+               if ((regs->regs[insn.i_format.rs] & (1ull<<insn.i_format.rt)) == 0)
+                       *contpc = regs->cp0_epc + 4 + (insn.i_format.simmediate << 2);
+               else
+                       *contpc = regs->cp0_epc + 8;
+               return 1;
+       case ldc2_op: /* This is bbit032 on Octeon */
+               if ((regs->regs[insn.i_format.rs] & (1ull<<(insn.i_format.rt + 32))) == 0)
+                       *contpc = regs->cp0_epc + 4 + (insn.i_format.simmediate << 2);
+               else
+                       *contpc = regs->cp0_epc + 8;
+               return 1;
+       case swc2_op: /* This is bbit1 on Octeon */
+               if (regs->regs[insn.i_format.rs] & (1ull<<insn.i_format.rt))
+                       *contpc = regs->cp0_epc + 4 + (insn.i_format.simmediate << 2);
+               else
+                       *contpc = regs->cp0_epc + 8;
+               return 1;
+       case sdc2_op: /* This is bbit132 on Octeon */
+               if (regs->regs[insn.i_format.rs] & (1ull<<(insn.i_format.rt + 32)))
+                       *contpc = regs->cp0_epc + 4 + (insn.i_format.simmediate << 2);
+               else
+                       *contpc = regs->cp0_epc + 8;
+               return 1;
+#endif
        case cop0_op:
        case cop1_op:
        case cop2_op:
index 653668d..4a8cb8d 100644 (file)
@@ -35,9 +35,9 @@ static void sanitize_boot_params(struct boot_params *boot_params)
         */
        if (boot_params->sentinel) {
                /* fields in boot_params are left uninitialized, clear them */
-               memset(&boot_params->olpc_ofw_header, 0,
+               memset(&boot_params->ext_ramdisk_image, 0,
                       (char *)&boot_params->efi_info -
-                       (char *)&boot_params->olpc_ofw_header);
+                       (char *)&boot_params->ext_ramdisk_image);
                memset(&boot_params->kbd_status, 0,
                       (char *)&boot_params->hdr -
                       (char *)&boot_params->kbd_status);
index 50e5c58..4c01917 100644 (file)
@@ -59,7 +59,7 @@ static inline u16 find_equiv_id(struct equiv_cpu_entry *equiv_cpu_table,
 
 extern int __apply_microcode_amd(struct microcode_amd *mc_amd);
 extern int apply_microcode_amd(int cpu);
-extern enum ucode_state load_microcode_amd(int cpu, const u8 *data, size_t size);
+extern enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t size);
 
 #ifdef CONFIG_MICROCODE_AMD_EARLY
 #ifdef CONFIG_X86_32
index f654ece..08a0890 100644 (file)
@@ -512,7 +512,7 @@ static void early_init_amd(struct cpuinfo_x86 *c)
 
 static const int amd_erratum_383[];
 static const int amd_erratum_400[];
-static bool cpu_has_amd_erratum(const int *erratum);
+static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum);
 
 static void init_amd(struct cpuinfo_x86 *c)
 {
@@ -729,11 +729,11 @@ static void init_amd(struct cpuinfo_x86 *c)
                value &= ~(1ULL << 24);
                wrmsrl_safe(MSR_AMD64_BU_CFG2, value);
 
-               if (cpu_has_amd_erratum(amd_erratum_383))
+               if (cpu_has_amd_erratum(c, amd_erratum_383))
                        set_cpu_bug(c, X86_BUG_AMD_TLB_MMATCH);
        }
 
-       if (cpu_has_amd_erratum(amd_erratum_400))
+       if (cpu_has_amd_erratum(c, amd_erratum_400))
                set_cpu_bug(c, X86_BUG_AMD_APIC_C1E);
 
        rdmsr_safe(MSR_AMD64_PATCH_LEVEL, &c->microcode, &dummy);
@@ -878,23 +878,13 @@ static const int amd_erratum_400[] =
 static const int amd_erratum_383[] =
        AMD_OSVW_ERRATUM(3, AMD_MODEL_RANGE(0x10, 0, 0, 0xff, 0xf));
 
-static bool cpu_has_amd_erratum(const int *erratum)
+
+static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum)
 {
-       struct cpuinfo_x86 *cpu = __this_cpu_ptr(&cpu_info);
        int osvw_id = *erratum++;
        u32 range;
        u32 ms;
 
-       /*
-        * If called early enough that current_cpu_data hasn't been initialized
-        * yet, fall back to boot_cpu_data.
-        */
-       if (cpu->x86 == 0)
-               cpu = &boot_cpu_data;
-
-       if (cpu->x86_vendor != X86_VENDOR_AMD)
-               return false;
-
        if (osvw_id >= 0 && osvw_id < 65536 &&
            cpu_has(cpu, X86_FEATURE_OSVW)) {
                u64 osvw_len;
index 7a0adb7..7123b5d 100644 (file)
@@ -145,10 +145,9 @@ static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig)
        return 0;
 }
 
-static unsigned int verify_patch_size(int cpu, u32 patch_size,
+static unsigned int verify_patch_size(u8 family, u32 patch_size,
                                      unsigned int size)
 {
-       struct cpuinfo_x86 *c = &cpu_data(cpu);
        u32 max_size;
 
 #define F1XH_MPB_MAX_SIZE 2048
@@ -156,7 +155,7 @@ static unsigned int verify_patch_size(int cpu, u32 patch_size,
 #define F15H_MPB_MAX_SIZE 4096
 #define F16H_MPB_MAX_SIZE 3458
 
-       switch (c->x86) {
+       switch (family) {
        case 0x14:
                max_size = F14H_MPB_MAX_SIZE;
                break;
@@ -277,9 +276,8 @@ static void cleanup(void)
  * driver cannot continue functioning normally. In such cases, we tear
  * down everything we've used up so far and exit.
  */
-static int verify_and_add_patch(unsigned int cpu, u8 *fw, unsigned int leftover)
+static int verify_and_add_patch(u8 family, u8 *fw, unsigned int leftover)
 {
-       struct cpuinfo_x86 *c = &cpu_data(cpu);
        struct microcode_header_amd *mc_hdr;
        struct ucode_patch *patch;
        unsigned int patch_size, crnt_size, ret;
@@ -299,7 +297,7 @@ static int verify_and_add_patch(unsigned int cpu, u8 *fw, unsigned int leftover)
 
        /* check if patch is for the current family */
        proc_fam = ((proc_fam >> 8) & 0xf) + ((proc_fam >> 20) & 0xff);
-       if (proc_fam != c->x86)
+       if (proc_fam != family)
                return crnt_size;
 
        if (mc_hdr->nb_dev_id || mc_hdr->sb_dev_id) {
@@ -308,7 +306,7 @@ static int verify_and_add_patch(unsigned int cpu, u8 *fw, unsigned int leftover)
                return crnt_size;
        }
 
-       ret = verify_patch_size(cpu, patch_size, leftover);
+       ret = verify_patch_size(family, patch_size, leftover);
        if (!ret) {
                pr_err("Patch-ID 0x%08x: size mismatch.\n", mc_hdr->patch_id);
                return crnt_size;
@@ -339,7 +337,8 @@ static int verify_and_add_patch(unsigned int cpu, u8 *fw, unsigned int leftover)
        return crnt_size;
 }
 
-static enum ucode_state __load_microcode_amd(int cpu, const u8 *data, size_t size)
+static enum ucode_state __load_microcode_amd(u8 family, const u8 *data,
+                                            size_t size)
 {
        enum ucode_state ret = UCODE_ERROR;
        unsigned int leftover;
@@ -362,7 +361,7 @@ static enum ucode_state __load_microcode_amd(int cpu, const u8 *data, size_t siz
        }
 
        while (leftover) {
-               crnt_size = verify_and_add_patch(cpu, fw, leftover);
+               crnt_size = verify_and_add_patch(family, fw, leftover);
                if (crnt_size < 0)
                        return ret;
 
@@ -373,22 +372,22 @@ static enum ucode_state __load_microcode_amd(int cpu, const u8 *data, size_t siz
        return UCODE_OK;
 }
 
-enum ucode_state load_microcode_amd(int cpu, const u8 *data, size_t size)
+enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t size)
 {
        enum ucode_state ret;
 
        /* free old equiv table */
        free_equiv_cpu_table();
 
-       ret = __load_microcode_amd(cpu, data, size);
+       ret = __load_microcode_amd(family, data, size);
 
        if (ret != UCODE_OK)
                cleanup();
 
 #if defined(CONFIG_MICROCODE_AMD_EARLY) && defined(CONFIG_X86_32)
        /* save BSP's matching patch for early load */
-       if (cpu_data(cpu).cpu_index == boot_cpu_data.cpu_index) {
-               struct ucode_patch *p = find_patch(cpu);
+       if (cpu_data(smp_processor_id()).cpu_index == boot_cpu_data.cpu_index) {
+               struct ucode_patch *p = find_patch(smp_processor_id());
                if (p) {
                        memset(amd_bsp_mpb, 0, MPB_MAX_SIZE);
                        memcpy(amd_bsp_mpb, p->data, min_t(u32, ksize(p->data),
@@ -441,7 +440,7 @@ static enum ucode_state request_microcode_amd(int cpu, struct device *device,
                goto fw_release;
        }
 
-       ret = load_microcode_amd(cpu, fw->data, fw->size);
+       ret = load_microcode_amd(c->x86, fw->data, fw->size);
 
  fw_release:
        release_firmware(fw);
index 1d14ffe..6073104 100644 (file)
@@ -238,25 +238,17 @@ static void __init collect_cpu_sig_on_bsp(void *arg)
        uci->cpu_sig.sig = cpuid_eax(0x00000001);
 }
 #else
-static void collect_cpu_info_amd_early(struct cpuinfo_x86 *c,
-                                                struct ucode_cpu_info *uci)
+void load_ucode_amd_ap(void)
 {
+       unsigned int cpu = smp_processor_id();
+       struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
        u32 rev, eax;
 
        rdmsr(MSR_AMD64_PATCH_LEVEL, rev, eax);
        eax = cpuid_eax(0x00000001);
 
-       uci->cpu_sig.sig = eax;
        uci->cpu_sig.rev = rev;
-       c->microcode = rev;
-       c->x86 = ((eax >> 8) & 0xf) + ((eax >> 20) & 0xff);
-}
-
-void load_ucode_amd_ap(void)
-{
-       unsigned int cpu = smp_processor_id();
-
-       collect_cpu_info_amd_early(&cpu_data(cpu), ucode_cpu_info + cpu);
+       uci->cpu_sig.sig = eax;
 
        if (cpu && !ucode_loaded) {
                void *ucode;
@@ -265,8 +257,10 @@ void load_ucode_amd_ap(void)
                        return;
 
                ucode = (void *)(initrd_start + ucode_offset);
-               if (load_microcode_amd(0, ucode, ucode_size) != UCODE_OK)
+               eax   = ((eax >> 8) & 0xf) + ((eax >> 20) & 0xff);
+               if (load_microcode_amd(eax, ucode, ucode_size) != UCODE_OK)
                        return;
+
                ucode_loaded = true;
        }
 
@@ -278,6 +272,8 @@ int __init save_microcode_in_initrd_amd(void)
 {
        enum ucode_state ret;
        void *ucode;
+       u32 eax;
+
 #ifdef CONFIG_X86_32
        unsigned int bsp = boot_cpu_data.cpu_index;
        struct ucode_cpu_info *uci = ucode_cpu_info + bsp;
@@ -293,7 +289,10 @@ int __init save_microcode_in_initrd_amd(void)
                return 0;
 
        ucode = (void *)(initrd_start + ucode_offset);
-       ret = load_microcode_amd(0, ucode, ucode_size);
+       eax   = cpuid_eax(0x00000001);
+       eax   = ((eax >> 8) & 0xf) + ((eax >> 20) & 0xff);
+
+       ret = load_microcode_amd(eax, ucode, ucode_size);
        if (ret != UCODE_OK)
                return -EINVAL;
 
index 48f8375..30277e2 100644 (file)
@@ -101,7 +101,7 @@ static void find_start_end(unsigned long flags, unsigned long *begin,
                                *begin = new_begin;
                }
        } else {
-               *begin = mmap_legacy_base();
+               *begin = current->mm->mmap_legacy_base;
                *end = TASK_SIZE;
        }
 }
index f63778c..25e7e13 100644 (file)
@@ -98,7 +98,7 @@ static unsigned long mmap_base(void)
  * Bottom-up (legacy) layout on X86_32 did not support randomization, X86_64
  * does, but not when emulating X86_32
  */
-unsigned long mmap_legacy_base(void)
+static unsigned long mmap_legacy_base(void)
 {
        if (mmap_is_ia32())
                return TASK_UNMAPPED_BASE;
@@ -112,11 +112,13 @@ unsigned long mmap_legacy_base(void)
  */
 void arch_pick_mmap_layout(struct mm_struct *mm)
 {
+       mm->mmap_legacy_base = mmap_legacy_base();
+       mm->mmap_base = mmap_base();
+
        if (mmap_is_legacy()) {
-               mm->mmap_base = mmap_legacy_base();
+               mm->mmap_base = mm->mmap_legacy_base;
                mm->get_unmapped_area = arch_get_unmapped_area;
        } else {
-               mm->mmap_base = mmap_base();
                mm->get_unmapped_area = arch_get_unmapped_area_topdown;
        }
 }
index 056d11f..8f3eea6 100644 (file)
@@ -313,6 +313,17 @@ static void xen_align_and_add_e820_region(u64 start, u64 size, int type)
        e820_add_region(start, end - start, type);
 }
 
+void xen_ignore_unusable(struct e820entry *list, size_t map_size)
+{
+       struct e820entry *entry;
+       unsigned int i;
+
+       for (i = 0, entry = list; i < map_size; i++, entry++) {
+               if (entry->type == E820_UNUSABLE)
+                       entry->type = E820_RAM;
+       }
+}
+
 /**
  * machine_specific_memory_setup - Hook for machine specific memory setup.
  **/
@@ -353,6 +364,17 @@ char * __init xen_memory_setup(void)
        }
        BUG_ON(rc);
 
+       /*
+        * Xen won't allow a 1:1 mapping to be created to UNUSABLE
+        * regions, so if we're using the machine memory map leave the
+        * region as RAM as it is in the pseudo-physical map.
+        *
+        * UNUSABLE regions in domUs are not handled and will need
+        * a patch in the future.
+        */
+       if (xen_initial_domain())
+               xen_ignore_unusable(map, memmap.nr_entries);
+
        /* Make sure the Xen-supplied memory map is well-ordered. */
        sanitize_e820_map(map, memmap.nr_entries, &memmap.nr_entries);
 
index ca92754..b81c88e 100644 (file)
@@ -694,8 +694,15 @@ static void __init xen_hvm_smp_prepare_cpus(unsigned int max_cpus)
 static int xen_hvm_cpu_up(unsigned int cpu, struct task_struct *tidle)
 {
        int rc;
-       rc = native_cpu_up(cpu, tidle);
-       WARN_ON (xen_smp_intr_init(cpu));
+       /*
+        * xen_smp_intr_init() needs to run before native_cpu_up()
+        * so that IPI vectors are set up on the booting CPU before
+        * it is marked online in native_cpu_up().
+       */
+       rc = xen_smp_intr_init(cpu);
+       WARN_ON(rc);
+       if (!rc)
+               rc =  native_cpu_up(cpu, tidle);
        return rc;
 }
 
index e1284b8..3270d3c 100644 (file)
@@ -908,9 +908,6 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
                device->cap._DDC = 1;
        }
 
-       if (acpi_video_init_brightness(device))
-               return;
-
        if (acpi_video_backlight_support()) {
                struct backlight_properties props;
                struct pci_dev *pdev;
@@ -920,6 +917,9 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
                static int count = 0;
                char *name;
 
+               result = acpi_video_init_brightness(device);
+               if (result)
+                       return;
                name = kasprintf(GFP_KERNEL, "acpi_video%d", count);
                if (!name)
                        return;
@@ -979,11 +979,6 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
                if (result)
                        printk(KERN_ERR PREFIX "Create sysfs link\n");
 
-       } else {
-               /* Remove the brightness object. */
-               kfree(device->brightness->levels);
-               kfree(device->brightness);
-               device->brightness = NULL;
        }
 }
 
index 1c41722..20fd337 100644 (file)
@@ -289,24 +289,24 @@ static int sata_pmp_configure(struct ata_device *dev, int print_info)
 
        /* Disable sending Early R_OK.
         * With "cached read" HDD testing and multiple ports busy on a SATA
-        * host controller, 3726 PMP will very rarely drop a deferred
+        * host controller, 3x26 PMP will very rarely drop a deferred
         * R_OK that was intended for the host. Symptom will be all
         * 5 drives under test will timeout, get reset, and recover.
         */
-       if (vendor == 0x1095 && devid == 0x3726) {
+       if (vendor == 0x1095 && (devid == 0x3726 || devid == 0x3826)) {
                u32 reg;
 
                err_mask = sata_pmp_read(&ap->link, PMP_GSCR_SII_POL, &reg);
                if (err_mask) {
                        rc = -EIO;
-                       reason = "failed to read Sil3726 Private Register";
+                       reason = "failed to read Sil3x26 Private Register";
                        goto fail;
                }
                reg &= ~0x1;
                err_mask = sata_pmp_write(&ap->link, PMP_GSCR_SII_POL, reg);
                if (err_mask) {
                        rc = -EIO;
-                       reason = "failed to write Sil3726 Private Register";
+                       reason = "failed to write Sil3x26 Private Register";
                        goto fail;
                }
        }
@@ -383,8 +383,8 @@ static void sata_pmp_quirks(struct ata_port *ap)
        u16 devid = sata_pmp_gscr_devid(gscr);
        struct ata_link *link;
 
-       if (vendor == 0x1095 && devid == 0x3726) {
-               /* sil3726 quirks */
+       if (vendor == 0x1095 && (devid == 0x3726 || devid == 0x3826)) {
+               /* sil3x26 quirks */
                ata_for_each_link(link, ap, EDGE) {
                        /* link reports offline after LPM */
                        link->flags |= ATA_LFLAG_NO_LPM;
index 19720a0..851bd3f 100644 (file)
@@ -293,6 +293,7 @@ static void fsl_sata_set_irq_coalescing(struct ata_host *host,
 {
        struct sata_fsl_host_priv *host_priv = host->private_data;
        void __iomem *hcr_base = host_priv->hcr_base;
+       unsigned long flags;
 
        if (count > ICC_MAX_INT_COUNT_THRESHOLD)
                count = ICC_MAX_INT_COUNT_THRESHOLD;
@@ -305,12 +306,12 @@ static void fsl_sata_set_irq_coalescing(struct ata_host *host,
                        (count > ICC_MIN_INT_COUNT_THRESHOLD))
                ticks = ICC_SAFE_INT_TICKS;
 
-       spin_lock(&host->lock);
+       spin_lock_irqsave(&host->lock, flags);
        iowrite32((count << 24 | ticks), hcr_base + ICC);
 
        intr_coalescing_count = count;
        intr_coalescing_ticks = ticks;
-       spin_unlock(&host->lock);
+       spin_unlock_irqrestore(&host->lock, flags);
 
        DPRINTK("interrupt coalescing, count = 0x%x, ticks = %x\n",
                        intr_coalescing_count, intr_coalescing_ticks);
index d047d92..e9a4f46 100644 (file)
@@ -86,11 +86,11 @@ struct ecx_plat_data {
 
 #define SGPIO_SIGNALS                  3
 #define ECX_ACTIVITY_BITS              0x300000
-#define ECX_ACTIVITY_SHIFT             2
+#define ECX_ACTIVITY_SHIFT             0
 #define ECX_LOCATE_BITS                        0x80000
 #define ECX_LOCATE_SHIFT               1
 #define ECX_FAULT_BITS                 0x400000
-#define ECX_FAULT_SHIFT                        0
+#define ECX_FAULT_SHIFT                        2
 static inline int sgpio_bit_shift(struct ecx_plat_data *pdata, u32 port,
                                u32 shift)
 {
index 19e3660..3bc8414 100644 (file)
@@ -500,7 +500,8 @@ static bool psb_intel_sdvo_read_response(struct psb_intel_sdvo *psb_intel_sdvo,
                                  &status))
                goto log_fail;
 
-       while (status == SDVO_CMD_STATUS_PENDING && retry--) {
+       while ((status == SDVO_CMD_STATUS_PENDING ||
+               status == SDVO_CMD_STATUS_TARGET_NOT_SPECIFIED) && retry--) {
                udelay(15);
                if (!psb_intel_sdvo_read_byte(psb_intel_sdvo,
                                          SDVO_I2C_CMD_STATUS,
index dc53a52..9e65783 100644 (file)
@@ -85,9 +85,17 @@ static void i915_gem_unmap_dma_buf(struct dma_buf_attachment *attachment,
                                   struct sg_table *sg,
                                   enum dma_data_direction dir)
 {
+       struct drm_i915_gem_object *obj = attachment->dmabuf->priv;
+
+       mutex_lock(&obj->base.dev->struct_mutex);
+
        dma_unmap_sg(attachment->dev, sg->sgl, sg->nents, dir);
        sg_free_table(sg);
        kfree(sg);
+
+       i915_gem_object_unpin_pages(obj);
+
+       mutex_unlock(&obj->base.dev->struct_mutex);
 }
 
 static void i915_gem_dmabuf_release(struct dma_buf *dma_buf)
index 6f51429..53cddd9 100644 (file)
                                        will not assert AGPBUSY# and will only
                                        be delivered when out of C3. */
 #define   INSTPM_FORCE_ORDERING                                (1<<7) /* GEN6+ */
+#define   INSTPM_TLB_INVALIDATE        (1<<9)
+#define   INSTPM_SYNC_FLUSH    (1<<5)
 #define ACTHD          0x020c8
 #define FW_BLC         0x020d8
 #define FW_BLC2                0x020dc
index e38b457..be79f47 100644 (file)
@@ -10042,6 +10042,8 @@ struct intel_display_error_state {
 
        u32 power_well_driver;
 
+       int num_transcoders;
+
        struct intel_cursor_error_state {
                u32 control;
                u32 position;
@@ -10050,16 +10052,7 @@ struct intel_display_error_state {
        } cursor[I915_MAX_PIPES];
 
        struct intel_pipe_error_state {
-               enum transcoder cpu_transcoder;
-               u32 conf;
                u32 source;
-
-               u32 htotal;
-               u32 hblank;
-               u32 hsync;
-               u32 vtotal;
-               u32 vblank;
-               u32 vsync;
        } pipe[I915_MAX_PIPES];
 
        struct intel_plane_error_state {
@@ -10071,6 +10064,19 @@ struct intel_display_error_state {
                u32 surface;
                u32 tile_offset;
        } plane[I915_MAX_PIPES];
+
+       struct intel_transcoder_error_state {
+               enum transcoder cpu_transcoder;
+
+               u32 conf;
+
+               u32 htotal;
+               u32 hblank;
+               u32 hsync;
+               u32 vtotal;
+               u32 vblank;
+               u32 vsync;
+       } transcoder[4];
 };
 
 struct intel_display_error_state *
@@ -10078,9 +10084,17 @@ intel_display_capture_error_state(struct drm_device *dev)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
        struct intel_display_error_state *error;
-       enum transcoder cpu_transcoder;
+       int transcoders[] = {
+               TRANSCODER_A,
+               TRANSCODER_B,
+               TRANSCODER_C,
+               TRANSCODER_EDP,
+       };
        int i;
 
+       if (INTEL_INFO(dev)->num_pipes == 0)
+               return NULL;
+
        error = kmalloc(sizeof(*error), GFP_ATOMIC);
        if (error == NULL)
                return NULL;
@@ -10089,9 +10103,6 @@ intel_display_capture_error_state(struct drm_device *dev)
                error->power_well_driver = I915_READ(HSW_PWR_WELL_DRIVER);
 
        for_each_pipe(i) {
-               cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv, i);
-               error->pipe[i].cpu_transcoder = cpu_transcoder;
-
                if (INTEL_INFO(dev)->gen <= 6 || IS_VALLEYVIEW(dev)) {
                        error->cursor[i].control = I915_READ(CURCNTR(i));
                        error->cursor[i].position = I915_READ(CURPOS(i));
@@ -10115,14 +10126,25 @@ intel_display_capture_error_state(struct drm_device *dev)
                        error->plane[i].tile_offset = I915_READ(DSPTILEOFF(i));
                }
 
-               error->pipe[i].conf = I915_READ(PIPECONF(cpu_transcoder));
                error->pipe[i].source = I915_READ(PIPESRC(i));
-               error->pipe[i].htotal = I915_READ(HTOTAL(cpu_transcoder));
-               error->pipe[i].hblank = I915_READ(HBLANK(cpu_transcoder));
-               error->pipe[i].hsync = I915_READ(HSYNC(cpu_transcoder));
-               error->pipe[i].vtotal = I915_READ(VTOTAL(cpu_transcoder));
-               error->pipe[i].vblank = I915_READ(VBLANK(cpu_transcoder));
-               error->pipe[i].vsync = I915_READ(VSYNC(cpu_transcoder));
+       }
+
+       error->num_transcoders = INTEL_INFO(dev)->num_pipes;
+       if (HAS_DDI(dev_priv->dev))
+               error->num_transcoders++; /* Account for eDP. */
+
+       for (i = 0; i < error->num_transcoders; i++) {
+               enum transcoder cpu_transcoder = transcoders[i];
+
+               error->transcoder[i].cpu_transcoder = cpu_transcoder;
+
+               error->transcoder[i].conf = I915_READ(PIPECONF(cpu_transcoder));
+               error->transcoder[i].htotal = I915_READ(HTOTAL(cpu_transcoder));
+               error->transcoder[i].hblank = I915_READ(HBLANK(cpu_transcoder));
+               error->transcoder[i].hsync = I915_READ(HSYNC(cpu_transcoder));
+               error->transcoder[i].vtotal = I915_READ(VTOTAL(cpu_transcoder));
+               error->transcoder[i].vblank = I915_READ(VBLANK(cpu_transcoder));
+               error->transcoder[i].vsync = I915_READ(VSYNC(cpu_transcoder));
        }
 
        /* In the code above we read the registers without checking if the power
@@ -10144,22 +10166,16 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m,
 {
        int i;
 
+       if (!error)
+               return;
+
        err_printf(m, "Num Pipes: %d\n", INTEL_INFO(dev)->num_pipes);
        if (HAS_POWER_WELL(dev))
                err_printf(m, "PWR_WELL_CTL2: %08x\n",
                           error->power_well_driver);
        for_each_pipe(i) {
                err_printf(m, "Pipe [%d]:\n", i);
-               err_printf(m, "  CPU transcoder: %c\n",
-                          transcoder_name(error->pipe[i].cpu_transcoder));
-               err_printf(m, "  CONF: %08x\n", error->pipe[i].conf);
                err_printf(m, "  SRC: %08x\n", error->pipe[i].source);
-               err_printf(m, "  HTOTAL: %08x\n", error->pipe[i].htotal);
-               err_printf(m, "  HBLANK: %08x\n", error->pipe[i].hblank);
-               err_printf(m, "  HSYNC: %08x\n", error->pipe[i].hsync);
-               err_printf(m, "  VTOTAL: %08x\n", error->pipe[i].vtotal);
-               err_printf(m, "  VBLANK: %08x\n", error->pipe[i].vblank);
-               err_printf(m, "  VSYNC: %08x\n", error->pipe[i].vsync);
 
                err_printf(m, "Plane [%d]:\n", i);
                err_printf(m, "  CNTR: %08x\n", error->plane[i].control);
@@ -10180,5 +10196,17 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m,
                err_printf(m, "  POS: %08x\n", error->cursor[i].position);
                err_printf(m, "  BASE: %08x\n", error->cursor[i].base);
        }
+
+       for (i = 0; i < error->num_transcoders; i++) {
+               err_printf(m, "  CPU transcoder: %c\n",
+                          transcoder_name(error->transcoder[i].cpu_transcoder));
+               err_printf(m, "  CONF: %08x\n", error->transcoder[i].conf);
+               err_printf(m, "  HTOTAL: %08x\n", error->transcoder[i].htotal);
+               err_printf(m, "  HBLANK: %08x\n", error->transcoder[i].hblank);
+               err_printf(m, "  HSYNC: %08x\n", error->transcoder[i].hsync);
+               err_printf(m, "  VTOTAL: %08x\n", error->transcoder[i].vtotal);
+               err_printf(m, "  VBLANK: %08x\n", error->transcoder[i].vblank);
+               err_printf(m, "  VSYNC: %08x\n", error->transcoder[i].vsync);
+       }
 }
 #endif
index 664118d..079ef01 100644 (file)
@@ -968,6 +968,18 @@ void intel_ring_setup_status_page(struct intel_ring_buffer *ring)
 
        I915_WRITE(mmio, (u32)ring->status_page.gfx_addr);
        POSTING_READ(mmio);
+
+       /* Flush the TLB for this page */
+       if (INTEL_INFO(dev)->gen >= 6) {
+               u32 reg = RING_INSTPM(ring->mmio_base);
+               I915_WRITE(reg,
+                          _MASKED_BIT_ENABLE(INSTPM_TLB_INVALIDATE |
+                                             INSTPM_SYNC_FLUSH));
+               if (wait_for((I915_READ(reg) & INSTPM_SYNC_FLUSH) == 0,
+                            1000))
+                       DRM_ERROR("%s: wait for SyncFlush to complete for TLB invalidation timed out\n",
+                                 ring->name);
+       }
 }
 
 static int
index d829172..7a4e089 100644 (file)
@@ -98,6 +98,8 @@ nouveau_mm_head(struct nouveau_mm *mm, u8 type, u32 size_max, u32 size_min,
        u32 splitoff;
        u32 s, e;
 
+       BUG_ON(!type);
+
        list_for_each_entry(this, &mm->free, fl_entry) {
                e = this->offset + this->length;
                s = this->offset;
@@ -162,6 +164,8 @@ nouveau_mm_tail(struct nouveau_mm *mm, u8 type, u32 size_max, u32 size_min,
        struct nouveau_mm_node *prev, *this, *next;
        u32 mask = align - 1;
 
+       BUG_ON(!type);
+
        list_for_each_entry_reverse(this, &mm->free, fl_entry) {
                u32 e = this->offset + this->length;
                u32 s = this->offset;
index d550226..9d2cd20 100644 (file)
@@ -20,8 +20,8 @@ nouveau_mc(void *obj)
        return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_MC];
 }
 
-#define nouveau_mc_create(p,e,o,d)                                             \
-       nouveau_mc_create_((p), (e), (o), sizeof(**d), (void **)d)
+#define nouveau_mc_create(p,e,o,m,d)                                           \
+       nouveau_mc_create_((p), (e), (o), (m), sizeof(**d), (void **)d)
 #define nouveau_mc_destroy(p) ({                                               \
        struct nouveau_mc *pmc = (p); _nouveau_mc_dtor(nv_object(pmc));        \
 })
@@ -33,7 +33,8 @@ nouveau_mc(void *obj)
 })
 
 int  nouveau_mc_create_(struct nouveau_object *, struct nouveau_object *,
-                       struct nouveau_oclass *, int, void **);
+                       struct nouveau_oclass *, const struct nouveau_mc_intr *,
+                       int, void **);
 void _nouveau_mc_dtor(struct nouveau_object *);
 int  _nouveau_mc_init(struct nouveau_object *);
 int  _nouveau_mc_fini(struct nouveau_object *, bool);
index 19e3a9a..ab7ef0a 100644 (file)
@@ -40,15 +40,15 @@ nv49_ram_create(struct nouveau_object *parent, struct nouveau_object *engine,
                return ret;
 
        switch (pfb914 & 0x00000003) {
-       case 0x00000000: pfb->ram->type = NV_MEM_TYPE_DDR1; break;
-       case 0x00000001: pfb->ram->type = NV_MEM_TYPE_DDR2; break;
-       case 0x00000002: pfb->ram->type = NV_MEM_TYPE_GDDR3; break;
+       case 0x00000000: ram->type = NV_MEM_TYPE_DDR1; break;
+       case 0x00000001: ram->type = NV_MEM_TYPE_DDR2; break;
+       case 0x00000002: ram->type = NV_MEM_TYPE_GDDR3; break;
        case 0x00000003: break;
        }
 
-       pfb->ram->size  =  nv_rd32(pfb, 0x10020c) & 0xff000000;
-       pfb->ram->parts = (nv_rd32(pfb, 0x100200) & 0x00000003) + 1;
-       pfb->ram->tags  =  nv_rd32(pfb, 0x100320);
+       ram->size  =  nv_rd32(pfb, 0x10020c) & 0xff000000;
+       ram->parts = (nv_rd32(pfb, 0x100200) & 0x00000003) + 1;
+       ram->tags  =  nv_rd32(pfb, 0x100320);
        return 0;
 }
 
index 7192aa6..63a6aab 100644 (file)
@@ -38,8 +38,8 @@ nv4e_ram_create(struct nouveau_object *parent, struct nouveau_object *engine,
        if (ret)
                return ret;
 
-       pfb->ram->size = nv_rd32(pfb, 0x10020c) & 0xff000000;
-       pfb->ram->type = NV_MEM_TYPE_STOLEN;
+       ram->size = nv_rd32(pfb, 0x10020c) & 0xff000000;
+       ram->type = NV_MEM_TYPE_STOLEN;
        return 0;
 }
 
index bcca883..cce65cc 100644 (file)
@@ -30,8 +30,9 @@ struct nvc0_ltcg_priv {
        struct nouveau_ltcg base;
        u32 part_nr;
        u32 subp_nr;
-       struct nouveau_mm tags;
        u32 num_tags;
+       u32 tag_base;
+       struct nouveau_mm tags;
        struct nouveau_mm_node *tag_ram;
 };
 
@@ -117,10 +118,6 @@ nvc0_ltcg_init_tag_ram(struct nouveau_fb *pfb, struct nvc0_ltcg_priv *priv)
        u32 tag_size, tag_margin, tag_align;
        int ret;
 
-       nv_wr32(priv, 0x17e8d8, priv->part_nr);
-       if (nv_device(pfb)->card_type >= NV_E0)
-               nv_wr32(priv, 0x17e000, priv->part_nr);
-
        /* tags for 1/4 of VRAM should be enough (8192/4 per GiB of VRAM) */
        priv->num_tags = (pfb->ram->size >> 17) / 4;
        if (priv->num_tags > (1 << 17))
@@ -142,7 +139,7 @@ nvc0_ltcg_init_tag_ram(struct nouveau_fb *pfb, struct nvc0_ltcg_priv *priv)
        tag_size += tag_align;
        tag_size  = (tag_size + 0xfff) >> 12; /* round up */
 
-       ret = nouveau_mm_tail(&pfb->vram, 0, tag_size, tag_size, 1,
+       ret = nouveau_mm_tail(&pfb->vram, 1, tag_size, tag_size, 1,
                              &priv->tag_ram);
        if (ret) {
                priv->num_tags = 0;
@@ -152,7 +149,7 @@ nvc0_ltcg_init_tag_ram(struct nouveau_fb *pfb, struct nvc0_ltcg_priv *priv)
                tag_base += tag_align - 1;
                ret = do_div(tag_base, tag_align);
 
-               nv_wr32(priv, 0x17e8d4, tag_base);
+               priv->tag_base = tag_base;
        }
        ret = nouveau_mm_init(&priv->tags, 0, priv->num_tags, 1);
 
@@ -182,8 +179,6 @@ nvc0_ltcg_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        }
        priv->subp_nr = nv_rd32(priv, 0x17e8dc) >> 28;
 
-       nv_mask(priv, 0x17e820, 0x00100000, 0x00000000); /* INTR_EN &= ~0x10 */
-
        ret = nvc0_ltcg_init_tag_ram(pfb, priv);
        if (ret)
                return ret;
@@ -209,13 +204,32 @@ nvc0_ltcg_dtor(struct nouveau_object *object)
        nouveau_ltcg_destroy(ltcg);
 }
 
+static int
+nvc0_ltcg_init(struct nouveau_object *object)
+{
+       struct nouveau_ltcg *ltcg = (struct nouveau_ltcg *)object;
+       struct nvc0_ltcg_priv *priv = (struct nvc0_ltcg_priv *)ltcg;
+       int ret;
+
+       ret = nouveau_ltcg_init(ltcg);
+       if (ret)
+               return ret;
+
+       nv_mask(priv, 0x17e820, 0x00100000, 0x00000000); /* INTR_EN &= ~0x10 */
+       nv_wr32(priv, 0x17e8d8, priv->part_nr);
+       if (nv_device(ltcg)->card_type >= NV_E0)
+               nv_wr32(priv, 0x17e000, priv->part_nr);
+       nv_wr32(priv, 0x17e8d4, priv->tag_base);
+       return 0;
+}
+
 struct nouveau_oclass
 nvc0_ltcg_oclass = {
        .handle = NV_SUBDEV(LTCG, 0xc0),
        .ofuncs = &(struct nouveau_ofuncs) {
                .ctor = nvc0_ltcg_ctor,
                .dtor = nvc0_ltcg_dtor,
-               .init = _nouveau_ltcg_init,
+               .init = nvc0_ltcg_init,
                .fini = _nouveau_ltcg_fini,
        },
 };
index 1c0330b..ec9cd6f 100644 (file)
@@ -80,7 +80,9 @@ _nouveau_mc_dtor(struct nouveau_object *object)
 
 int
 nouveau_mc_create_(struct nouveau_object *parent, struct nouveau_object *engine,
-                  struct nouveau_oclass *oclass, int length, void **pobject)
+                  struct nouveau_oclass *oclass,
+                  const struct nouveau_mc_intr *intr_map,
+                  int length, void **pobject)
 {
        struct nouveau_device *device = nv_device(parent);
        struct nouveau_mc *pmc;
@@ -92,6 +94,8 @@ nouveau_mc_create_(struct nouveau_object *parent, struct nouveau_object *engine,
        if (ret)
                return ret;
 
+       pmc->intr_map = intr_map;
+
        ret = request_irq(device->pdev->irq, nouveau_mc_intr,
                          IRQF_SHARED, "nouveau", pmc);
        if (ret < 0)
index 8c76971..64aa4ed 100644 (file)
@@ -50,12 +50,11 @@ nv04_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nv04_mc_priv *priv;
        int ret;
 
-       ret = nouveau_mc_create(parent, engine, oclass, &priv);
+       ret = nouveau_mc_create(parent, engine, oclass, nv04_mc_intr, &priv);
        *pobject = nv_object(priv);
        if (ret)
                return ret;
 
-       priv->base.intr_map = nv04_mc_intr;
        return 0;
 }
 
index 5191937..d989178 100644 (file)
@@ -36,12 +36,11 @@ nv44_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nv44_mc_priv *priv;
        int ret;
 
-       ret = nouveau_mc_create(parent, engine, oclass, &priv);
+       ret = nouveau_mc_create(parent, engine, oclass, nv04_mc_intr, &priv);
        *pobject = nv_object(priv);
        if (ret)
                return ret;
 
-       priv->base.intr_map = nv04_mc_intr;
        return 0;
 }
 
index f25fc5f..2b1afe2 100644 (file)
@@ -53,12 +53,11 @@ nv50_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nv50_mc_priv *priv;
        int ret;
 
-       ret = nouveau_mc_create(parent, engine, oclass, &priv);
+       ret = nouveau_mc_create(parent, engine, oclass, nv50_mc_intr, &priv);
        *pobject = nv_object(priv);
        if (ret)
                return ret;
 
-       priv->base.intr_map = nv50_mc_intr;
        return 0;
 }
 
index e82fd21..0d57b4d 100644 (file)
@@ -54,12 +54,11 @@ nv98_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nv98_mc_priv *priv;
        int ret;
 
-       ret = nouveau_mc_create(parent, engine, oclass, &priv);
+       ret = nouveau_mc_create(parent, engine, oclass, nv98_mc_intr, &priv);
        *pobject = nv_object(priv);
        if (ret)
                return ret;
 
-       priv->base.intr_map = nv98_mc_intr;
        return 0;
 }
 
index c5da3ba..104175c 100644 (file)
@@ -57,12 +57,11 @@ nvc0_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nvc0_mc_priv *priv;
        int ret;
 
-       ret = nouveau_mc_create(parent, engine, oclass, &priv);
+       ret = nouveau_mc_create(parent, engine, oclass, nvc0_mc_intr, &priv);
        *pobject = nv_object(priv);
        if (ret)
                return ret;
 
-       priv->base.intr_map = nvc0_mc_intr;
        return 0;
 }
 
index 0782bd2..6a13ffb 100644 (file)
@@ -606,6 +606,24 @@ nv_crtc_mode_set_regs(struct drm_crtc *crtc, struct drm_display_mode * mode)
        regp->ramdac_a34 = 0x1;
 }
 
+static int
+nv_crtc_swap_fbs(struct drm_crtc *crtc, struct drm_framebuffer *old_fb)
+{
+       struct nv04_display *disp = nv04_display(crtc->dev);
+       struct nouveau_framebuffer *nvfb = nouveau_framebuffer(crtc->fb);
+       struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+       int ret;
+
+       ret = nouveau_bo_pin(nvfb->nvbo, TTM_PL_FLAG_VRAM);
+       if (ret == 0) {
+               if (disp->image[nv_crtc->index])
+                       nouveau_bo_unpin(disp->image[nv_crtc->index]);
+               nouveau_bo_ref(nvfb->nvbo, &disp->image[nv_crtc->index]);
+       }
+
+       return ret;
+}
+
 /**
  * Sets up registers for the given mode/adjusted_mode pair.
  *
@@ -622,10 +640,15 @@ nv_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
        struct drm_device *dev = crtc->dev;
        struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
        struct nouveau_drm *drm = nouveau_drm(dev);
+       int ret;
 
        NV_DEBUG(drm, "CTRC mode on CRTC %d:\n", nv_crtc->index);
        drm_mode_debug_printmodeline(adjusted_mode);
 
+       ret = nv_crtc_swap_fbs(crtc, old_fb);
+       if (ret)
+               return ret;
+
        /* unlock must come after turning off FP_TG_CONTROL in output_prepare */
        nv_lock_vga_crtc_shadow(dev, nv_crtc->index, -1);
 
@@ -722,6 +745,7 @@ static void nv_crtc_commit(struct drm_crtc *crtc)
 
 static void nv_crtc_destroy(struct drm_crtc *crtc)
 {
+       struct nv04_display *disp = nv04_display(crtc->dev);
        struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
 
        if (!nv_crtc)
@@ -729,6 +753,10 @@ static void nv_crtc_destroy(struct drm_crtc *crtc)
 
        drm_crtc_cleanup(crtc);
 
+       if (disp->image[nv_crtc->index])
+               nouveau_bo_unpin(disp->image[nv_crtc->index]);
+       nouveau_bo_ref(NULL, &disp->image[nv_crtc->index]);
+
        nouveau_bo_unmap(nv_crtc->cursor.nvbo);
        nouveau_bo_unpin(nv_crtc->cursor.nvbo);
        nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo);
@@ -754,6 +782,16 @@ nv_crtc_gamma_load(struct drm_crtc *crtc)
 }
 
 static void
+nv_crtc_disable(struct drm_crtc *crtc)
+{
+       struct nv04_display *disp = nv04_display(crtc->dev);
+       struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+       if (disp->image[nv_crtc->index])
+               nouveau_bo_unpin(disp->image[nv_crtc->index]);
+       nouveau_bo_ref(NULL, &disp->image[nv_crtc->index]);
+}
+
+static void
 nv_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, uint32_t start,
                  uint32_t size)
 {
@@ -791,7 +829,6 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,
        struct drm_framebuffer *drm_fb;
        struct nouveau_framebuffer *fb;
        int arb_burst, arb_lwm;
-       int ret;
 
        NV_DEBUG(drm, "index %d\n", nv_crtc->index);
 
@@ -801,10 +838,8 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,
                return 0;
        }
 
-
        /* If atomic, we want to switch to the fb we were passed, so
-        * now we update pointers to do that.  (We don't pin; just
-        * assume we're already pinned and update the base address.)
+        * now we update pointers to do that.
         */
        if (atomic) {
                drm_fb = passed_fb;
@@ -812,17 +847,6 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,
        } else {
                drm_fb = crtc->fb;
                fb = nouveau_framebuffer(crtc->fb);
-               /* If not atomic, we can go ahead and pin, and unpin the
-                * old fb we were passed.
-                */
-               ret = nouveau_bo_pin(fb->nvbo, TTM_PL_FLAG_VRAM);
-               if (ret)
-                       return ret;
-
-               if (passed_fb) {
-                       struct nouveau_framebuffer *ofb = nouveau_framebuffer(passed_fb);
-                       nouveau_bo_unpin(ofb->nvbo);
-               }
        }
 
        nv_crtc->fb.offset = fb->nvbo->bo.offset;
@@ -877,6 +901,9 @@ static int
 nv04_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
                        struct drm_framebuffer *old_fb)
 {
+       int ret = nv_crtc_swap_fbs(crtc, old_fb);
+       if (ret)
+               return ret;
        return nv04_crtc_do_mode_set_base(crtc, old_fb, x, y, false);
 }
 
@@ -1027,6 +1054,7 @@ static const struct drm_crtc_helper_funcs nv04_crtc_helper_funcs = {
        .mode_set_base = nv04_crtc_mode_set_base,
        .mode_set_base_atomic = nv04_crtc_mode_set_base_atomic,
        .load_lut = nv_crtc_gamma_load,
+       .disable = nv_crtc_disable,
 };
 
 int
index a0a031d..9928187 100644 (file)
@@ -81,6 +81,7 @@ struct nv04_display {
        uint32_t saved_vga_font[4][16384];
        uint32_t dac_users[4];
        struct nouveau_object *core;
+       struct nouveau_bo *image[2];
 };
 
 static inline struct nv04_display *
index 907d20e..a03e75d 100644 (file)
@@ -577,6 +577,9 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
                ret = nv50_display_flip_next(crtc, fb, chan, 0);
                if (ret)
                        goto fail_unreserve;
+       } else {
+               struct nv04_display *dispnv04 = nv04_display(dev);
+               nouveau_bo_ref(new_bo, &dispnv04->image[nouveau_crtc(crtc)->index]);
        }
 
        ret = nouveau_page_flip_emit(chan, old_bo, new_bo, s, &fence);
index 3af5bcd..625f80d 100644 (file)
@@ -131,7 +131,7 @@ nv40_calc_pll(struct drm_device *dev, u32 reg, struct nvbios_pll *pll,
        if (clk < pll->vco1.max_freq)
                pll->vco2.max_freq = 0;
 
-       pclk->pll_calc(pclk, pll, clk, &coef);
+       ret = pclk->pll_calc(pclk, pll, clk, &coef);
        if (ret == 0)
                return -ERANGE;
 
index 274b8e1..9f19259 100644 (file)
@@ -2163,7 +2163,7 @@ void cik_mm_wdoorbell(struct radeon_device *rdev, u32 offset, u32 v);
                WREG32(reg, tmp_);                              \
        } while (0)
 #define WREG32_AND(reg, and) WREG32_P(reg, 0, and)
-#define WREG32_OR(reg, or) WREG32_P(reg, or, ~or)
+#define WREG32_OR(reg, or) WREG32_P(reg, or, ~(or))
 #define WREG32_PLL_P(reg, val, mask)                           \
        do {                                                    \
                uint32_t tmp_ = RREG32_PLL(reg);                \
index f1c1575..b79f4f5 100644 (file)
@@ -356,6 +356,14 @@ static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo,
                return -EINVAL;
        }
 
+       if (bo->tbo.sync_obj) {
+               r = radeon_fence_wait(bo->tbo.sync_obj, false);
+               if (r) {
+                       DRM_ERROR("Failed waiting for UVD message (%d)!\n", r);
+                       return r;
+               }
+       }
+
        r = radeon_bo_kmap(bo, &ptr);
        if (r) {
                DRM_ERROR("Failed mapping the UVD message (%d)!\n", r);
index bcc68ec..f5e92cf 100644 (file)
@@ -744,10 +744,10 @@ static void rv770_init_golden_registers(struct radeon_device *rdev)
                                                 (const u32)ARRAY_SIZE(r7xx_golden_dyn_gpr_registers));
                radeon_program_register_sequence(rdev,
                                                 rv730_golden_registers,
-                                                (const u32)ARRAY_SIZE(rv770_golden_registers));
+                                                (const u32)ARRAY_SIZE(rv730_golden_registers));
                radeon_program_register_sequence(rdev,
                                                 rv730_mgcg_init,
-                                                (const u32)ARRAY_SIZE(rv770_mgcg_init));
+                                                (const u32)ARRAY_SIZE(rv730_mgcg_init));
                break;
        case CHIP_RV710:
                radeon_program_register_sequence(rdev,
@@ -758,18 +758,18 @@ static void rv770_init_golden_registers(struct radeon_device *rdev)
                                                 (const u32)ARRAY_SIZE(r7xx_golden_dyn_gpr_registers));
                radeon_program_register_sequence(rdev,
                                                 rv710_golden_registers,
-                                                (const u32)ARRAY_SIZE(rv770_golden_registers));
+                                                (const u32)ARRAY_SIZE(rv710_golden_registers));
                radeon_program_register_sequence(rdev,
                                                 rv710_mgcg_init,
-                                                (const u32)ARRAY_SIZE(rv770_mgcg_init));
+                                                (const u32)ARRAY_SIZE(rv710_mgcg_init));
                break;
        case CHIP_RV740:
                radeon_program_register_sequence(rdev,
                                                 rv740_golden_registers,
-                                                (const u32)ARRAY_SIZE(rv770_golden_registers));
+                                                (const u32)ARRAY_SIZE(rv740_golden_registers));
                radeon_program_register_sequence(rdev,
                                                 rv740_mgcg_init,
-                                                (const u32)ARRAY_SIZE(rv770_mgcg_init));
+                                                (const u32)ARRAY_SIZE(rv740_mgcg_init));
                break;
        default:
                break;
index 5f4749e..c1cd569 100644 (file)
@@ -232,7 +232,8 @@ static int adjd_s311_read_raw(struct iio_dev *indio_dev,
 
        switch (mask) {
        case IIO_CHAN_INFO_RAW:
-               ret = adjd_s311_read_data(indio_dev, chan->address, val);
+               ret = adjd_s311_read_data(indio_dev,
+                       ADJD_S311_DATA_REG(chan->address), val);
                if (ret < 0)
                        return ret;
                return IIO_VAL_INT;
index dc112a7..4296155 100644 (file)
@@ -959,23 +959,21 @@ out:
        return r;
 }
 
-static void remove_mapping(struct mq_policy *mq, dm_oblock_t oblock)
+static void mq_remove_mapping(struct dm_cache_policy *p, dm_oblock_t oblock)
 {
-       struct entry *e = hash_lookup(mq, oblock);
+       struct mq_policy *mq = to_mq_policy(p);
+       struct entry *e;
+
+       mutex_lock(&mq->lock);
+
+       e = hash_lookup(mq, oblock);
 
        BUG_ON(!e || !e->in_cache);
 
        del(mq, e);
        e->in_cache = false;
        push(mq, e);
-}
 
-static void mq_remove_mapping(struct dm_cache_policy *p, dm_oblock_t oblock)
-{
-       struct mq_policy *mq = to_mq_policy(p);
-
-       mutex_lock(&mq->lock);
-       remove_mapping(mq, oblock);
        mutex_unlock(&mq->lock);
 }
 
index ce9b387..00b88cb 100644 (file)
@@ -1333,6 +1333,8 @@ enum {
        BNX2X_SP_RTNL_VFPF_CHANNEL_DOWN,
        BNX2X_SP_RTNL_VFPF_STORM_RX_MODE,
        BNX2X_SP_RTNL_HYPERVISOR_VLAN,
+       BNX2X_SP_RTNL_TX_STOP,
+       BNX2X_SP_RTNL_TX_RESUME,
 };
 
 struct bnx2x_prev_path_list {
index f9122f2..fcf2761 100644 (file)
 #include "bnx2x_dcb.h"
 
 /* forward declarations of dcbx related functions */
-static int bnx2x_dcbx_stop_hw_tx(struct bnx2x *bp);
 static void bnx2x_pfc_set_pfc(struct bnx2x *bp);
 static void bnx2x_dcbx_update_ets_params(struct bnx2x *bp);
-static int bnx2x_dcbx_resume_hw_tx(struct bnx2x *bp);
 static void bnx2x_dcbx_get_ets_pri_pg_tbl(struct bnx2x *bp,
                                          u32 *set_configuration_ets_pg,
                                          u32 *pri_pg_tbl);
@@ -425,30 +423,52 @@ static void bnx2x_pfc_set_pfc(struct bnx2x *bp)
                bnx2x_pfc_clear(bp);
 }
 
-static int bnx2x_dcbx_stop_hw_tx(struct bnx2x *bp)
+int bnx2x_dcbx_stop_hw_tx(struct bnx2x *bp)
 {
        struct bnx2x_func_state_params func_params = {NULL};
+       int rc;
 
        func_params.f_obj = &bp->func_obj;
        func_params.cmd = BNX2X_F_CMD_TX_STOP;
 
+       __set_bit(RAMROD_COMP_WAIT, &func_params.ramrod_flags);
+       __set_bit(RAMROD_RETRY, &func_params.ramrod_flags);
+
        DP(BNX2X_MSG_DCB, "STOP TRAFFIC\n");
-       return bnx2x_func_state_change(bp, &func_params);
+
+       rc = bnx2x_func_state_change(bp, &func_params);
+       if (rc) {
+               BNX2X_ERR("Unable to hold traffic for HW configuration\n");
+               bnx2x_panic();
+       }
+
+       return rc;
 }
 
-static int bnx2x_dcbx_resume_hw_tx(struct bnx2x *bp)
+int bnx2x_dcbx_resume_hw_tx(struct bnx2x *bp)
 {
        struct bnx2x_func_state_params func_params = {NULL};
        struct bnx2x_func_tx_start_params *tx_params =
                &func_params.params.tx_start;
+       int rc;
 
        func_params.f_obj = &bp->func_obj;
        func_params.cmd = BNX2X_F_CMD_TX_START;
 
+       __set_bit(RAMROD_COMP_WAIT, &func_params.ramrod_flags);
+       __set_bit(RAMROD_RETRY, &func_params.ramrod_flags);
+
        bnx2x_dcbx_fw_struct(bp, tx_params);
 
        DP(BNX2X_MSG_DCB, "START TRAFFIC\n");
-       return bnx2x_func_state_change(bp, &func_params);
+
+       rc = bnx2x_func_state_change(bp, &func_params);
+       if (rc) {
+               BNX2X_ERR("Unable to resume traffic after HW configuration\n");
+               bnx2x_panic();
+       }
+
+       return rc;
 }
 
 static void bnx2x_dcbx_2cos_limit_update_ets_config(struct bnx2x *bp)
@@ -744,7 +764,9 @@ void bnx2x_dcbx_set_params(struct bnx2x *bp, u32 state)
                        if (IS_MF(bp))
                                bnx2x_link_sync_notify(bp);
 
-                       bnx2x_dcbx_stop_hw_tx(bp);
+                       set_bit(BNX2X_SP_RTNL_TX_STOP, &bp->sp_rtnl_state);
+
+                       schedule_delayed_work(&bp->sp_rtnl_task, 0);
 
                        return;
                }
@@ -757,7 +779,9 @@ void bnx2x_dcbx_set_params(struct bnx2x *bp, u32 state)
                /* ets may affect cmng configuration: reinit it in hw */
                bnx2x_set_local_cmng(bp);
 
-               bnx2x_dcbx_resume_hw_tx(bp);
+               set_bit(BNX2X_SP_RTNL_TX_RESUME, &bp->sp_rtnl_state);
+
+               schedule_delayed_work(&bp->sp_rtnl_task, 0);
 
                return;
        case BNX2X_DCBX_STATE_TX_RELEASED:
@@ -2367,21 +2391,24 @@ static u8 bnx2x_dcbnl_get_featcfg(struct net_device *netdev, int featid,
                case DCB_FEATCFG_ATTR_PG:
                        if (bp->dcbx_local_feat.ets.enabled)
                                *flags |= DCB_FEATCFG_ENABLE;
-                       if (bp->dcbx_error & DCBX_LOCAL_ETS_ERROR)
+                       if (bp->dcbx_error & (DCBX_LOCAL_ETS_ERROR |
+                                             DCBX_REMOTE_MIB_ERROR))
                                *flags |= DCB_FEATCFG_ERROR;
                        break;
                case DCB_FEATCFG_ATTR_PFC:
                        if (bp->dcbx_local_feat.pfc.enabled)
                                *flags |= DCB_FEATCFG_ENABLE;
                        if (bp->dcbx_error & (DCBX_LOCAL_PFC_ERROR |
-                           DCBX_LOCAL_PFC_MISMATCH))
+                                             DCBX_LOCAL_PFC_MISMATCH |
+                                             DCBX_REMOTE_MIB_ERROR))
                                *flags |= DCB_FEATCFG_ERROR;
                        break;
                case DCB_FEATCFG_ATTR_APP:
                        if (bp->dcbx_local_feat.app.enabled)
                                *flags |= DCB_FEATCFG_ENABLE;
                        if (bp->dcbx_error & (DCBX_LOCAL_APP_ERROR |
-                           DCBX_LOCAL_APP_MISMATCH))
+                                             DCBX_LOCAL_APP_MISMATCH |
+                                             DCBX_REMOTE_MIB_ERROR))
                                *flags |= DCB_FEATCFG_ERROR;
                        break;
                default:
index 125bd1b..804b8f6 100644 (file)
@@ -199,4 +199,7 @@ extern const struct dcbnl_rtnl_ops bnx2x_dcbnl_ops;
 int bnx2x_dcbnl_update_applist(struct bnx2x *bp, bool delall);
 #endif /* BCM_DCBNL */
 
+int bnx2x_dcbx_stop_hw_tx(struct bnx2x *bp);
+int bnx2x_dcbx_resume_hw_tx(struct bnx2x *bp);
+
 #endif /* BNX2X_DCB_H */
index 955d6cf..8bdc8b9 100644 (file)
@@ -2261,6 +2261,23 @@ static void bnx2x_set_requested_fc(struct bnx2x *bp)
                bp->link_params.req_fc_auto_adv = BNX2X_FLOW_CTRL_BOTH;
 }
 
+static void bnx2x_init_dropless_fc(struct bnx2x *bp)
+{
+       u32 pause_enabled = 0;
+
+       if (!CHIP_IS_E1(bp) && bp->dropless_fc && bp->link_vars.link_up) {
+               if (bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_TX)
+                       pause_enabled = 1;
+
+               REG_WR(bp, BAR_USTRORM_INTMEM +
+                          USTORM_ETH_PAUSE_ENABLED_OFFSET(BP_PORT(bp)),
+                      pause_enabled);
+       }
+
+       DP(NETIF_MSG_IFUP | NETIF_MSG_LINK, "dropless_fc is %s\n",
+          pause_enabled ? "enabled" : "disabled");
+}
+
 int bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode)
 {
        int rc, cfx_idx = bnx2x_get_link_cfg_idx(bp);
@@ -2294,6 +2311,8 @@ int bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode)
 
                bnx2x_release_phy_lock(bp);
 
+               bnx2x_init_dropless_fc(bp);
+
                bnx2x_calc_fc_adv(bp);
 
                if (bp->link_vars.link_up) {
@@ -2315,6 +2334,8 @@ void bnx2x_link_set(struct bnx2x *bp)
                bnx2x_phy_init(&bp->link_params, &bp->link_vars);
                bnx2x_release_phy_lock(bp);
 
+               bnx2x_init_dropless_fc(bp);
+
                bnx2x_calc_fc_adv(bp);
        } else
                BNX2X_ERR("Bootcode is missing - can not set link\n");
@@ -2556,20 +2577,9 @@ static void bnx2x_link_attn(struct bnx2x *bp)
 
        bnx2x_link_update(&bp->link_params, &bp->link_vars);
 
-       if (bp->link_vars.link_up) {
+       bnx2x_init_dropless_fc(bp);
 
-               /* dropless flow control */
-               if (!CHIP_IS_E1(bp) && bp->dropless_fc) {
-                       int port = BP_PORT(bp);
-                       u32 pause_enabled = 0;
-
-                       if (bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_TX)
-                               pause_enabled = 1;
-
-                       REG_WR(bp, BAR_USTRORM_INTMEM +
-                              USTORM_ETH_PAUSE_ENABLED_OFFSET(port),
-                              pause_enabled);
-               }
+       if (bp->link_vars.link_up) {
 
                if (bp->link_vars.mac_type != MAC_TYPE_EMAC) {
                        struct host_port_stats *pstats;
@@ -9645,6 +9655,12 @@ sp_rtnl_not_reset:
                               &bp->sp_rtnl_state))
                bnx2x_pf_set_vfs_vlan(bp);
 
+       if (test_and_clear_bit(BNX2X_SP_RTNL_TX_STOP, &bp->sp_rtnl_state))
+               bnx2x_dcbx_stop_hw_tx(bp);
+
+       if (test_and_clear_bit(BNX2X_SP_RTNL_TX_RESUME, &bp->sp_rtnl_state))
+               bnx2x_dcbx_resume_hw_tx(bp);
+
        /* work which needs rtnl lock not-taken (as it takes the lock itself and
         * can be called from other contexts as well)
         */
@@ -11147,6 +11163,9 @@ static bool bnx2x_get_dropless_info(struct bnx2x *bp)
        int tmp;
        u32 cfg;
 
+       if (IS_VF(bp))
+               return 0;
+
        if (IS_MF(bp) && !CHIP_IS_E1x(bp)) {
                /* Take function: tmp = func */
                tmp = BP_ABS_FUNC(bp);
index 44104fb..ad83f4b 100644 (file)
@@ -1747,11 +1747,8 @@ void bnx2x_iov_init_dq(struct bnx2x *bp)
 
 void bnx2x_iov_init_dmae(struct bnx2x *bp)
 {
-       DP(BNX2X_MSG_IOV, "SRIOV is %s\n", IS_SRIOV(bp) ? "ON" : "OFF");
-       if (!IS_SRIOV(bp))
-               return;
-
-       REG_WR(bp, DMAE_REG_BACKWARD_COMP_EN, 0);
+       if (pci_find_ext_capability(bp->pdev, PCI_EXT_CAP_ID_SRIOV))
+               REG_WR(bp, DMAE_REG_BACKWARD_COMP_EN, 0);
 }
 
 static int bnx2x_vf_bus(struct bnx2x *bp, int vfid)
@@ -3084,8 +3081,9 @@ void bnx2x_disable_sriov(struct bnx2x *bp)
        pci_disable_sriov(bp->pdev);
 }
 
-static int bnx2x_vf_ndo_sanity(struct bnx2x *bp, int vfidx,
-                              struct bnx2x_virtf *vf)
+static int bnx2x_vf_ndo_prep(struct bnx2x *bp, int vfidx,
+                            struct bnx2x_virtf **vf,
+                            struct pf_vf_bulletin_content **bulletin)
 {
        if (bp->state != BNX2X_STATE_OPEN) {
                BNX2X_ERR("vf ndo called though PF is down\n");
@@ -3103,12 +3101,22 @@ static int bnx2x_vf_ndo_sanity(struct bnx2x *bp, int vfidx,
                return -EINVAL;
        }
 
-       if (!vf) {
+       /* init members */
+       *vf = BP_VF(bp, vfidx);
+       *bulletin = BP_VF_BULLETIN(bp, vfidx);
+
+       if (!*vf) {
                BNX2X_ERR("vf ndo called but vf was null. vfidx was %d\n",
                          vfidx);
                return -EINVAL;
        }
 
+       if (!*bulletin) {
+               BNX2X_ERR("vf ndo called but Bulletin Board struct is null. vfidx was %d\n",
+                         vfidx);
+               return -EINVAL;
+       }
+
        return 0;
 }
 
@@ -3116,17 +3124,19 @@ int bnx2x_get_vf_config(struct net_device *dev, int vfidx,
                        struct ifla_vf_info *ivi)
 {
        struct bnx2x *bp = netdev_priv(dev);
-       struct bnx2x_virtf *vf = BP_VF(bp, vfidx);
-       struct bnx2x_vlan_mac_obj *mac_obj = &bnx2x_vfq(vf, 0, mac_obj);
-       struct bnx2x_vlan_mac_obj *vlan_obj = &bnx2x_vfq(vf, 0, vlan_obj);
-       struct pf_vf_bulletin_content *bulletin = BP_VF_BULLETIN(bp, vfidx);
+       struct bnx2x_virtf *vf = NULL;
+       struct pf_vf_bulletin_content *bulletin = NULL;
+       struct bnx2x_vlan_mac_obj *mac_obj;
+       struct bnx2x_vlan_mac_obj *vlan_obj;
        int rc;
 
-       /* sanity */
-       rc = bnx2x_vf_ndo_sanity(bp, vfidx, vf);
+       /* sanity and init */
+       rc = bnx2x_vf_ndo_prep(bp, vfidx, &vf, &bulletin);
        if (rc)
                return rc;
-       if (!mac_obj || !vlan_obj || !bulletin) {
+       mac_obj = &bnx2x_vfq(vf, 0, mac_obj);
+       vlan_obj = &bnx2x_vfq(vf, 0, vlan_obj);
+       if (!mac_obj || !vlan_obj) {
                BNX2X_ERR("VF partially initialized\n");
                return -EINVAL;
        }
@@ -3183,11 +3193,11 @@ int bnx2x_set_vf_mac(struct net_device *dev, int vfidx, u8 *mac)
 {
        struct bnx2x *bp = netdev_priv(dev);
        int rc, q_logical_state;
-       struct bnx2x_virtf *vf = BP_VF(bp, vfidx);
-       struct pf_vf_bulletin_content *bulletin = BP_VF_BULLETIN(bp, vfidx);
+       struct bnx2x_virtf *vf = NULL;
+       struct pf_vf_bulletin_content *bulletin = NULL;
 
-       /* sanity */
-       rc = bnx2x_vf_ndo_sanity(bp, vfidx, vf);
+       /* sanity and init */
+       rc = bnx2x_vf_ndo_prep(bp, vfidx, &vf, &bulletin);
        if (rc)
                return rc;
        if (!is_valid_ether_addr(mac)) {
@@ -3249,11 +3259,11 @@ int bnx2x_set_vf_vlan(struct net_device *dev, int vfidx, u16 vlan, u8 qos)
 {
        struct bnx2x *bp = netdev_priv(dev);
        int rc, q_logical_state;
-       struct bnx2x_virtf *vf = BP_VF(bp, vfidx);
-       struct pf_vf_bulletin_content *bulletin = BP_VF_BULLETIN(bp, vfidx);
+       struct bnx2x_virtf *vf = NULL;
+       struct pf_vf_bulletin_content *bulletin = NULL;
 
-       /* sanity */
-       rc = bnx2x_vf_ndo_sanity(bp, vfidx, vf);
+       /* sanity and init */
+       rc = bnx2x_vf_ndo_prep(bp, vfidx, &vf, &bulletin);
        if (rc)
                return rc;
 
index 181edb5..4559c35 100644 (file)
@@ -2563,8 +2563,8 @@ static int be_close(struct net_device *netdev)
        /* Wait for all pending tx completions to arrive so that
         * all tx skbs are freed.
         */
-       be_tx_compl_clean(adapter);
        netif_tx_disable(netdev);
+       be_tx_compl_clean(adapter);
 
        be_rx_qs_destroy(adapter);
 
index b5eb419..85e5c97 100644 (file)
@@ -7088,7 +7088,7 @@ rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        RTL_W8(Cfg9346, Cfg9346_Unlock);
        RTL_W8(Config1, RTL_R8(Config1) | PMEnable);
-       RTL_W8(Config5, RTL_R8(Config5) & PMEStatus);
+       RTL_W8(Config5, RTL_R8(Config5) & (BWF | MWF | UWF | LanWake | PMEStatus));
        if ((RTL_R8(Config3) & (LinkUp | MagicPacket)) != 0)
                tp->features |= RTL_FEATURE_WOL;
        if ((RTL_R8(Config5) & (UWF | BWF | MWF)) != 0)
index 2a469b2..30d7442 100644 (file)
@@ -675,7 +675,7 @@ s32 efx_filter_insert_filter(struct efx_nic *efx, struct efx_filter_spec *spec,
                BUILD_BUG_ON(EFX_FILTER_INDEX_UC_DEF != 0);
                BUILD_BUG_ON(EFX_FILTER_INDEX_MC_DEF !=
                             EFX_FILTER_MC_DEF - EFX_FILTER_UC_DEF);
-               rep_index = spec->type - EFX_FILTER_INDEX_UC_DEF;
+               rep_index = spec->type - EFX_FILTER_UC_DEF;
                ins_index = rep_index;
 
                spin_lock_bh(&state->lock);
index 51f2bc3..2dcc60f 100644 (file)
@@ -210,8 +210,7 @@ static int via_init_one(struct pci_dev *pcidev, const struct pci_device_id *id)
                        pci_write_config_byte(pcidev,0x42,(bTmp | 0xf0));
                        pci_write_config_byte(pcidev,0x5a,0xc0);
                        WriteLPCReg(0x28, 0x70 );
-                       if (via_ircc_open(pcidev, &info, 0x3076) == 0)
-                               rc=0;
+                       rc = via_ircc_open(pcidev, &info, 0x3076);
                } else
                        rc = -ENODEV; //IR not turn on   
        } else { //Not VT1211
@@ -249,8 +248,7 @@ static int via_init_one(struct pci_dev *pcidev, const struct pci_device_id *id)
                        info.irq=FirIRQ;
                        info.dma=FirDRQ1;
                        info.dma2=FirDRQ0;
-                       if (via_ircc_open(pcidev, &info, 0x3096) == 0)
-                               rc=0;
+                       rc = via_ircc_open(pcidev, &info, 0x3096);
                } else
                        rc = -ENODEV; //IR not turn on !!!!!
        }//Not VT1211
index b51db2a..ea53abb 100644 (file)
@@ -68,6 +68,8 @@ static const struct proto_ops macvtap_socket_ops;
 #define TUN_OFFLOADS (NETIF_F_HW_CSUM | NETIF_F_TSO_ECN | NETIF_F_TSO | \
                      NETIF_F_TSO6 | NETIF_F_UFO)
 #define RX_OFFLOADS (NETIF_F_GRO | NETIF_F_LRO)
+#define TAP_FEATURES (NETIF_F_GSO | NETIF_F_SG)
+
 /*
  * RCU usage:
  * The macvtap_queue and the macvlan_dev are loosely coupled, the
@@ -278,7 +280,8 @@ static int macvtap_forward(struct net_device *dev, struct sk_buff *skb)
 {
        struct macvlan_dev *vlan = netdev_priv(dev);
        struct macvtap_queue *q = macvtap_get_queue(dev, skb);
-       netdev_features_t features;
+       netdev_features_t features = TAP_FEATURES;
+
        if (!q)
                goto drop;
 
@@ -287,9 +290,11 @@ static int macvtap_forward(struct net_device *dev, struct sk_buff *skb)
 
        skb->dev = dev;
        /* Apply the forward feature mask so that we perform segmentation
-        * according to users wishes.
+        * according to users wishes.  This only works if VNET_HDR is
+        * enabled.
         */
-       features = netif_skb_features(skb) & vlan->tap_features;
+       if (q->flags & IFF_VNET_HDR)
+               features |= vlan->tap_features;
        if (netif_needs_gso(skb, features)) {
                struct sk_buff *segs = __skb_gso_segment(skb, features, false);
 
@@ -1064,8 +1069,7 @@ static int set_offload(struct macvtap_queue *q, unsigned long arg)
        /* tap_features are the same as features on tun/tap and
         * reflect user expectations.
         */
-       vlan->tap_features = vlan->dev->features &
-                           (feature_mask | ~TUN_OFFLOADS);
+       vlan->tap_features = feature_mask;
        vlan->set_features = features;
        netdev_update_features(vlan->dev);
 
@@ -1161,10 +1165,6 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd,
                            TUN_F_TSO_ECN | TUN_F_UFO))
                        return -EINVAL;
 
-               /* TODO: only accept frames with the features that
-                        got enabled for forwarded frames */
-               if (!(q->flags & IFF_VNET_HDR))
-                       return  -EINVAL;
                rtnl_lock();
                ret = set_offload(q, arg);
                rtnl_unlock();
index 8e7af83..138de83 100644 (file)
@@ -23,7 +23,7 @@
 #define RTL821x_INER_INIT      0x6400
 #define RTL821x_INSR           0x13
 
-#define        RTL8211E_INER_LINK_STAT 0x10
+#define        RTL8211E_INER_LINK_STATUS       0x400
 
 MODULE_DESCRIPTION("Realtek PHY driver");
 MODULE_AUTHOR("Johnson Leung");
@@ -57,7 +57,7 @@ static int rtl8211e_config_intr(struct phy_device *phydev)
 
        if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
                err = phy_write(phydev, RTL821x_INER,
-                               RTL8211E_INER_LINK_STAT);
+                               RTL8211E_INER_LINK_STATUS);
        else
                err = phy_write(phydev, RTL821x_INER, 0);
 
index cba1d46..86292e6 100644 (file)
@@ -2816,13 +2816,16 @@ exit:
 static int hso_get_config_data(struct usb_interface *interface)
 {
        struct usb_device *usbdev = interface_to_usbdev(interface);
-       u8 config_data[17];
+       u8 *config_data = kmalloc(17, GFP_KERNEL);
        u32 if_num = interface->altsetting->desc.bInterfaceNumber;
        s32 result;
 
+       if (!config_data)
+               return -ENOMEM;
        if (usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0),
                            0x86, 0xC0, 0, 0, config_data, 17,
                            USB_CTRL_SET_TIMEOUT) != 0x11) {
+               kfree(config_data);
                return -EIO;
        }
 
@@ -2873,6 +2876,7 @@ static int hso_get_config_data(struct usb_interface *interface)
        if (config_data[16] & 0x1)
                result |= HSO_INFO_CRC_BUG;
 
+       kfree(config_data);
        return result;
 }
 
@@ -2886,6 +2890,11 @@ static int hso_probe(struct usb_interface *interface,
        struct hso_shared_int *shared_int;
        struct hso_device *tmp_dev = NULL;
 
+       if (interface->cur_altsetting->desc.bInterfaceClass != 0xFF) {
+               dev_err(&interface->dev, "Not our interface\n");
+               return -ENODEV;
+       }
+
        if_num = interface->altsetting->desc.bInterfaceNumber;
 
        /* Get the interface/port specification from either driver_info or from
@@ -2895,10 +2904,6 @@ static int hso_probe(struct usb_interface *interface,
        else
                port_spec = hso_get_config_data(interface);
 
-       if (interface->cur_altsetting->desc.bInterfaceClass != 0xFF) {
-               dev_err(&interface->dev, "Not our interface\n");
-               return -ENODEV;
-       }
        /* Check if we need to switch to alt interfaces prior to port
         * configuration */
        if (interface->num_altsetting > 1)
index ac07473..e509030 100644 (file)
@@ -523,9 +523,9 @@ static int prism2_ioctl_giwaplist(struct net_device *dev,
 
        data->length = prism2_ap_get_sta_qual(local, addr, qual, IW_MAX_AP, 1);
 
-       memcpy(extra, &addr, sizeof(struct sockaddr) * data->length);
+       memcpy(extra, addr, sizeof(struct sockaddr) * data->length);
        data->flags = 1; /* has quality information */
-       memcpy(extra + sizeof(struct sockaddr) * data->length, &qual,
+       memcpy(extra + sizeof(struct sockaddr) * data->length, qual,
               sizeof(struct iw_quality) * data->length);
 
        kfree(addr);
index 822f1a0..3193872 100644 (file)
@@ -1068,7 +1068,10 @@ void iwl_chswitch_done(struct iwl_priv *priv, bool is_success)
        if (test_bit(STATUS_EXIT_PENDING, &priv->status))
                return;
 
-       if (test_and_clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status))
+       if (!test_and_clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status))
+               return;
+
+       if (ctx->vif)
                ieee80211_chswitch_done(ctx->vif, is_success);
 }
 
index a70c7b9..ff8cc75 100644 (file)
@@ -97,8 +97,6 @@
 
 #define APMG_PCIDEV_STT_VAL_L1_ACT_DIS         (0x00000800)
 
-#define APMG_RTC_INT_STT_RFKILL                (0x10000000)
-
 /* Device system time */
 #define DEVICE_SYSTEM_TIME_REG 0xA0206C
 
index ad9bbca..7fd6fbf 100644 (file)
@@ -138,6 +138,20 @@ static void iwl_mvm_roc_finished(struct iwl_mvm *mvm)
        schedule_work(&mvm->roc_done_wk);
 }
 
+static bool iwl_mvm_te_check_disconnect(struct iwl_mvm *mvm,
+                                       struct ieee80211_vif *vif,
+                                       const char *errmsg)
+{
+       if (vif->type != NL80211_IFTYPE_STATION)
+               return false;
+       if (vif->bss_conf.assoc && vif->bss_conf.dtim_period)
+               return false;
+       if (errmsg)
+               IWL_ERR(mvm, "%s\n", errmsg);
+       ieee80211_connection_loss(vif);
+       return true;
+}
+
 /*
  * Handles a FW notification for an event that is known to the driver.
  *
@@ -163,8 +177,13 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm,
         * P2P Device discoveribility, while there are other higher priority
         * events in the system).
         */
-       WARN_ONCE(!le32_to_cpu(notif->status),
-                 "Failed to schedule time event\n");
+       if (WARN_ONCE(!le32_to_cpu(notif->status),
+                     "Failed to schedule time event\n")) {
+               if (iwl_mvm_te_check_disconnect(mvm, te_data->vif, NULL)) {
+                       iwl_mvm_te_clear_data(mvm, te_data);
+                       return;
+               }
+       }
 
        if (le32_to_cpu(notif->action) & TE_NOTIF_HOST_EVENT_END) {
                IWL_DEBUG_TE(mvm,
@@ -180,14 +199,8 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm,
                 * By now, we should have finished association
                 * and know the dtim period.
                 */
-               if (te_data->vif->type == NL80211_IFTYPE_STATION &&
-                   (!te_data->vif->bss_conf.assoc ||
-                    !te_data->vif->bss_conf.dtim_period)) {
-                       IWL_ERR(mvm,
-                               "No assocation and the time event is over already...\n");
-                       ieee80211_connection_loss(te_data->vif);
-               }
-
+               iwl_mvm_te_check_disconnect(mvm, te_data->vif,
+                       "No assocation and the time event is over already...");
                iwl_mvm_te_clear_data(mvm, te_data);
        } else if (le32_to_cpu(notif->action) & TE_NOTIF_HOST_EVENT_START) {
                te_data->running = true;
index f600e68..fd848cd 100644 (file)
@@ -888,14 +888,6 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
 
                iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill);
                if (hw_rfkill) {
-                       /*
-                        * Clear the interrupt in APMG if the NIC is going down.
-                        * Note that when the NIC exits RFkill (else branch), we
-                        * can't access prph and the NIC will be reset in
-                        * start_hw anyway.
-                        */
-                       iwl_write_prph(trans, APMG_RTC_INT_STT_REG,
-                                      APMG_RTC_INT_STT_RFKILL);
                        set_bit(STATUS_RFKILL, &trans_pcie->status);
                        if (test_and_clear_bit(STATUS_HCMD_ACTIVE,
                                               &trans_pcie->status))
index 96cfcdd..390e2f0 100644 (file)
@@ -1502,16 +1502,16 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
        spin_lock_init(&trans_pcie->reg_lock);
        init_waitqueue_head(&trans_pcie->ucode_write_waitq);
 
-       /* W/A - seems to solve weird behavior. We need to remove this if we
-        * don't want to stay in L1 all the time. This wastes a lot of power */
-       pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
-                              PCIE_LINK_STATE_CLKPM);
-
        if (pci_enable_device(pdev)) {
                err = -ENODEV;
                goto out_no_pci;
        }
 
+       /* W/A - seems to solve weird behavior. We need to remove this if we
+        * don't want to stay in L1 all the time. This wastes a lot of power */
+       pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
+                              PCIE_LINK_STATE_CLKPM);
+
        pci_set_master(pdev);
 
        err = pci_set_dma_mask(pdev, DMA_BIT_MASK(36));
index 4941f20..b8ba1f9 100644 (file)
@@ -98,10 +98,12 @@ static int zd1201_fw_upload(struct usb_device *dev, int apfw)
                goto exit;
 
        err = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), 0x4,
-           USB_DIR_IN | 0x40, 0,0, &ret, sizeof(ret), ZD1201_FW_TIMEOUT);
+           USB_DIR_IN | 0x40, 0, 0, buf, sizeof(ret), ZD1201_FW_TIMEOUT);
        if (err < 0)
                goto exit;
 
+       memcpy(&ret, buf, sizeof(ret));
+
        if (ret & 0x80) {
                err = -EIO;
                goto exit;
index 6bb7cf2..b10ba00 100644 (file)
@@ -392,6 +392,8 @@ static void __unflatten_device_tree(struct boot_param_header *blob,
        mem = (unsigned long)
                dt_alloc(size + 4, __alignof__(struct device_node));
 
+       memset((void *)mem, 0, size);
+
        ((__be32 *)mem)[size / 4] = cpu_to_be32(0xdeadbeef);
 
        pr_debug("  unflattening %lx...\n", mem);
index c47fd1e..94716c7 100644 (file)
@@ -278,6 +278,7 @@ static int sunxi_pconf_group_set(struct pinctrl_dev *pctldev,
 {
        struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
        struct sunxi_pinctrl_group *g = &pctl->groups[group];
+       unsigned long flags;
        u32 val, mask;
        u16 strength;
        u8 dlevel;
@@ -295,22 +296,35 @@ static int sunxi_pconf_group_set(struct pinctrl_dev *pctldev,
                 *   3: 40mA
                 */
                dlevel = strength / 10 - 1;
+
+               spin_lock_irqsave(&pctl->lock, flags);
+
                val = readl(pctl->membase + sunxi_dlevel_reg(g->pin));
                mask = DLEVEL_PINS_MASK << sunxi_dlevel_offset(g->pin);
                writel((val & ~mask) | dlevel << sunxi_dlevel_offset(g->pin),
                        pctl->membase + sunxi_dlevel_reg(g->pin));
+
+               spin_unlock_irqrestore(&pctl->lock, flags);
                break;
        case PIN_CONFIG_BIAS_PULL_UP:
+               spin_lock_irqsave(&pctl->lock, flags);
+
                val = readl(pctl->membase + sunxi_pull_reg(g->pin));
                mask = PULL_PINS_MASK << sunxi_pull_offset(g->pin);
                writel((val & ~mask) | 1 << sunxi_pull_offset(g->pin),
                        pctl->membase + sunxi_pull_reg(g->pin));
+
+               spin_unlock_irqrestore(&pctl->lock, flags);
                break;
        case PIN_CONFIG_BIAS_PULL_DOWN:
+               spin_lock_irqsave(&pctl->lock, flags);
+
                val = readl(pctl->membase + sunxi_pull_reg(g->pin));
                mask = PULL_PINS_MASK << sunxi_pull_offset(g->pin);
                writel((val & ~mask) | 2 << sunxi_pull_offset(g->pin),
                        pctl->membase + sunxi_pull_reg(g->pin));
+
+               spin_unlock_irqrestore(&pctl->lock, flags);
                break;
        default:
                break;
@@ -360,11 +374,17 @@ static void sunxi_pmx_set(struct pinctrl_dev *pctldev,
                                 u8 config)
 {
        struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+       unsigned long flags;
+       u32 val, mask;
+
+       spin_lock_irqsave(&pctl->lock, flags);
 
-       u32 val = readl(pctl->membase + sunxi_mux_reg(pin));
-       u32 mask = MUX_PINS_MASK << sunxi_mux_offset(pin);
+       val = readl(pctl->membase + sunxi_mux_reg(pin));
+       mask = MUX_PINS_MASK << sunxi_mux_offset(pin);
        writel((val & ~mask) | config << sunxi_mux_offset(pin),
                pctl->membase + sunxi_mux_reg(pin));
+
+       spin_unlock_irqrestore(&pctl->lock, flags);
 }
 
 static int sunxi_pmx_enable(struct pinctrl_dev *pctldev,
@@ -464,8 +484,21 @@ static void sunxi_pinctrl_gpio_set(struct gpio_chip *chip,
        struct sunxi_pinctrl *pctl = dev_get_drvdata(chip->dev);
        u32 reg = sunxi_data_reg(offset);
        u8 index = sunxi_data_offset(offset);
+       unsigned long flags;
+       u32 regval;
+
+       spin_lock_irqsave(&pctl->lock, flags);
+
+       regval = readl(pctl->membase + reg);
 
-       writel((value & DATA_PINS_MASK) << index, pctl->membase + reg);
+       if (value)
+               regval |= BIT(index);
+       else
+               regval &= ~(BIT(index));
+
+       writel(regval, pctl->membase + reg);
+
+       spin_unlock_irqrestore(&pctl->lock, flags);
 }
 
 static int sunxi_pinctrl_gpio_of_xlate(struct gpio_chip *gc,
@@ -526,6 +559,8 @@ static int sunxi_pinctrl_irq_set_type(struct irq_data *d,
        struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
        u32 reg = sunxi_irq_cfg_reg(d->hwirq);
        u8 index = sunxi_irq_cfg_offset(d->hwirq);
+       unsigned long flags;
+       u32 regval;
        u8 mode;
 
        switch (type) {
@@ -548,7 +583,13 @@ static int sunxi_pinctrl_irq_set_type(struct irq_data *d,
                return -EINVAL;
        }
 
-       writel((mode & IRQ_CFG_IRQ_MASK) << index, pctl->membase + reg);
+       spin_lock_irqsave(&pctl->lock, flags);
+
+       regval = readl(pctl->membase + reg);
+       regval &= ~IRQ_CFG_IRQ_MASK;
+       writel(regval | (mode << index), pctl->membase + reg);
+
+       spin_unlock_irqrestore(&pctl->lock, flags);
 
        return 0;
 }
@@ -560,14 +601,19 @@ static void sunxi_pinctrl_irq_mask_ack(struct irq_data *d)
        u8 ctrl_idx = sunxi_irq_ctrl_offset(d->hwirq);
        u32 status_reg = sunxi_irq_status_reg(d->hwirq);
        u8 status_idx = sunxi_irq_status_offset(d->hwirq);
+       unsigned long flags;
        u32 val;
 
+       spin_lock_irqsave(&pctl->lock, flags);
+
        /* Mask the IRQ */
        val = readl(pctl->membase + ctrl_reg);
        writel(val & ~(1 << ctrl_idx), pctl->membase + ctrl_reg);
 
        /* Clear the IRQ */
        writel(1 << status_idx, pctl->membase + status_reg);
+
+       spin_unlock_irqrestore(&pctl->lock, flags);
 }
 
 static void sunxi_pinctrl_irq_mask(struct irq_data *d)
@@ -575,11 +621,16 @@ static void sunxi_pinctrl_irq_mask(struct irq_data *d)
        struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
        u32 reg = sunxi_irq_ctrl_reg(d->hwirq);
        u8 idx = sunxi_irq_ctrl_offset(d->hwirq);
+       unsigned long flags;
        u32 val;
 
+       spin_lock_irqsave(&pctl->lock, flags);
+
        /* Mask the IRQ */
        val = readl(pctl->membase + reg);
        writel(val & ~(1 << idx), pctl->membase + reg);
+
+       spin_unlock_irqrestore(&pctl->lock, flags);
 }
 
 static void sunxi_pinctrl_irq_unmask(struct irq_data *d)
@@ -588,6 +639,7 @@ static void sunxi_pinctrl_irq_unmask(struct irq_data *d)
        struct sunxi_desc_function *func;
        u32 reg = sunxi_irq_ctrl_reg(d->hwirq);
        u8 idx = sunxi_irq_ctrl_offset(d->hwirq);
+       unsigned long flags;
        u32 val;
 
        func = sunxi_pinctrl_desc_find_function_by_pin(pctl,
@@ -597,9 +649,13 @@ static void sunxi_pinctrl_irq_unmask(struct irq_data *d)
        /* Change muxing to INT mode */
        sunxi_pmx_set(pctl->pctl_dev, pctl->irq_array[d->hwirq], func->muxval);
 
+       spin_lock_irqsave(&pctl->lock, flags);
+
        /* Unmask the IRQ */
        val = readl(pctl->membase + reg);
        writel(val | (1 << idx), pctl->membase + reg);
+
+       spin_unlock_irqrestore(&pctl->lock, flags);
 }
 
 static struct irq_chip sunxi_pinctrl_irq_chip = {
@@ -752,6 +808,8 @@ static int sunxi_pinctrl_probe(struct platform_device *pdev)
                return -ENOMEM;
        platform_set_drvdata(pdev, pctl);
 
+       spin_lock_init(&pctl->lock);
+
        pctl->membase = of_iomap(node, 0);
        if (!pctl->membase)
                return -ENOMEM;
index d68047d..01c494f 100644 (file)
@@ -14,6 +14,7 @@
 #define __PINCTRL_SUNXI_H
 
 #include <linux/kernel.h>
+#include <linux/spinlock.h>
 
 #define PA_BASE        0
 #define PB_BASE        32
@@ -407,6 +408,7 @@ struct sunxi_pinctrl {
        unsigned                        ngroups;
        int                             irq;
        int                             irq_array[SUNXI_IRQ_NUMBER];
+       spinlock_t                      lock;
        struct pinctrl_dev              *pctl_dev;
 };
 
index 0f9f859..f911952 100644 (file)
@@ -330,7 +330,7 @@ static int __init olpc_ec_init_module(void)
        return platform_driver_register(&olpc_ec_plat_driver);
 }
 
-module_init(olpc_ec_init_module);
+arch_initcall(olpc_ec_init_module);
 
 MODULE_AUTHOR("Andres Salomon <dilinger@queued.net>");
 MODULE_LICENSE("GPL");
index 97bb05e..d6970f4 100644 (file)
@@ -53,7 +53,6 @@ MODULE_ALIAS("wmi:5FB7F034-2C63-45e9-BE91-3D44E2C707E4");
 #define HPWMI_ALS_QUERY 0x3
 #define HPWMI_HARDWARE_QUERY 0x4
 #define HPWMI_WIRELESS_QUERY 0x5
-#define HPWMI_BIOS_QUERY 0x9
 #define HPWMI_HOTKEY_QUERY 0xc
 #define HPWMI_WIRELESS2_QUERY 0x1b
 #define HPWMI_POSTCODEERROR_QUERY 0x2a
@@ -293,19 +292,6 @@ static int hp_wmi_tablet_state(void)
        return (state & 0x4) ? 1 : 0;
 }
 
-static int hp_wmi_enable_hotkeys(void)
-{
-       int ret;
-       int query = 0x6e;
-
-       ret = hp_wmi_perform_query(HPWMI_BIOS_QUERY, 1, &query, sizeof(query),
-                                  0);
-
-       if (ret)
-               return -EINVAL;
-       return 0;
-}
-
 static int hp_wmi_set_block(void *data, bool blocked)
 {
        enum hp_wmi_radio r = (enum hp_wmi_radio) data;
@@ -1009,8 +995,6 @@ static int __init hp_wmi_init(void)
                err = hp_wmi_input_setup();
                if (err)
                        return err;
-
-               hp_wmi_enable_hotkeys();
        }
 
        if (bios_capable) {
index 2ac045f..3a1b6bf 100644 (file)
@@ -2440,7 +2440,10 @@ static ssize_t sony_nc_gfx_switch_status_show(struct device *dev,
        if (pos < 0)
                return pos;
 
-       return snprintf(buffer, PAGE_SIZE, "%s\n", pos ? "speed" : "stamina");
+       return snprintf(buffer, PAGE_SIZE, "%s\n",
+                                       pos == SPEED ? "speed" :
+                                       pos == STAMINA ? "stamina" :
+                                       pos == AUTO ? "auto" : "unknown");
 }
 
 static int sony_nc_gfx_switch_setup(struct platform_device *pd,
@@ -4320,7 +4323,8 @@ static int sony_pic_add(struct acpi_device *device)
                goto err_free_resources;
        }
 
-       if (sonypi_compat_init())
+       result = sonypi_compat_init();
+       if (result)
                goto err_remove_input;
 
        /* request io port */
index 1d4c8fe..c82fe65 100644 (file)
@@ -102,10 +102,13 @@ static void zfcp_erp_action_dismiss_port(struct zfcp_port *port)
 
        if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_INUSE)
                zfcp_erp_action_dismiss(&port->erp_action);
-       else
-               shost_for_each_device(sdev, port->adapter->scsi_host)
+       else {
+               spin_lock(port->adapter->scsi_host->host_lock);
+               __shost_for_each_device(sdev, port->adapter->scsi_host)
                        if (sdev_to_zfcp(sdev)->port == port)
                                zfcp_erp_action_dismiss_lun(sdev);
+               spin_unlock(port->adapter->scsi_host->host_lock);
+       }
 }
 
 static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter)
@@ -592,9 +595,11 @@ static void _zfcp_erp_lun_reopen_all(struct zfcp_port *port, int clear,
 {
        struct scsi_device *sdev;
 
-       shost_for_each_device(sdev, port->adapter->scsi_host)
+       spin_lock(port->adapter->scsi_host->host_lock);
+       __shost_for_each_device(sdev, port->adapter->scsi_host)
                if (sdev_to_zfcp(sdev)->port == port)
                        _zfcp_erp_lun_reopen(sdev, clear, id, 0);
+       spin_unlock(port->adapter->scsi_host->host_lock);
 }
 
 static void zfcp_erp_strategy_followup_failed(struct zfcp_erp_action *act)
@@ -1434,8 +1439,10 @@ void zfcp_erp_set_adapter_status(struct zfcp_adapter *adapter, u32 mask)
                atomic_set_mask(common_mask, &port->status);
        read_unlock_irqrestore(&adapter->port_list_lock, flags);
 
-       shost_for_each_device(sdev, adapter->scsi_host)
+       spin_lock_irqsave(adapter->scsi_host->host_lock, flags);
+       __shost_for_each_device(sdev, adapter->scsi_host)
                atomic_set_mask(common_mask, &sdev_to_zfcp(sdev)->status);
+       spin_unlock_irqrestore(adapter->scsi_host->host_lock, flags);
 }
 
 /**
@@ -1469,11 +1476,13 @@ void zfcp_erp_clear_adapter_status(struct zfcp_adapter *adapter, u32 mask)
        }
        read_unlock_irqrestore(&adapter->port_list_lock, flags);
 
-       shost_for_each_device(sdev, adapter->scsi_host) {
+       spin_lock_irqsave(adapter->scsi_host->host_lock, flags);
+       __shost_for_each_device(sdev, adapter->scsi_host) {
                atomic_clear_mask(common_mask, &sdev_to_zfcp(sdev)->status);
                if (clear_counter)
                        atomic_set(&sdev_to_zfcp(sdev)->erp_counter, 0);
        }
+       spin_unlock_irqrestore(adapter->scsi_host->host_lock, flags);
 }
 
 /**
@@ -1487,16 +1496,19 @@ void zfcp_erp_set_port_status(struct zfcp_port *port, u32 mask)
 {
        struct scsi_device *sdev;
        u32 common_mask = mask & ZFCP_COMMON_FLAGS;
+       unsigned long flags;
 
        atomic_set_mask(mask, &port->status);
 
        if (!common_mask)
                return;
 
-       shost_for_each_device(sdev, port->adapter->scsi_host)
+       spin_lock_irqsave(port->adapter->scsi_host->host_lock, flags);
+       __shost_for_each_device(sdev, port->adapter->scsi_host)
                if (sdev_to_zfcp(sdev)->port == port)
                        atomic_set_mask(common_mask,
                                        &sdev_to_zfcp(sdev)->status);
+       spin_unlock_irqrestore(port->adapter->scsi_host->host_lock, flags);
 }
 
 /**
@@ -1511,6 +1523,7 @@ void zfcp_erp_clear_port_status(struct zfcp_port *port, u32 mask)
        struct scsi_device *sdev;
        u32 common_mask = mask & ZFCP_COMMON_FLAGS;
        u32 clear_counter = mask & ZFCP_STATUS_COMMON_ERP_FAILED;
+       unsigned long flags;
 
        atomic_clear_mask(mask, &port->status);
 
@@ -1520,13 +1533,15 @@ void zfcp_erp_clear_port_status(struct zfcp_port *port, u32 mask)
        if (clear_counter)
                atomic_set(&port->erp_counter, 0);
 
-       shost_for_each_device(sdev, port->adapter->scsi_host)
+       spin_lock_irqsave(port->adapter->scsi_host->host_lock, flags);
+       __shost_for_each_device(sdev, port->adapter->scsi_host)
                if (sdev_to_zfcp(sdev)->port == port) {
                        atomic_clear_mask(common_mask,
                                          &sdev_to_zfcp(sdev)->status);
                        if (clear_counter)
                                atomic_set(&sdev_to_zfcp(sdev)->erp_counter, 0);
                }
+       spin_unlock_irqrestore(port->adapter->scsi_host->host_lock, flags);
 }
 
 /**
index 665e3cf..de0598e 100644 (file)
@@ -224,11 +224,9 @@ int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req,
 
 static int zfcp_qdio_sbal_check(struct zfcp_qdio *qdio)
 {
-       spin_lock_irq(&qdio->req_q_lock);
        if (atomic_read(&qdio->req_q_free) ||
            !(atomic_read(&qdio->adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP))
                return 1;
-       spin_unlock_irq(&qdio->req_q_lock);
        return 0;
 }
 
@@ -246,9 +244,8 @@ int zfcp_qdio_sbal_get(struct zfcp_qdio *qdio)
 {
        long ret;
 
-       spin_unlock_irq(&qdio->req_q_lock);
-       ret = wait_event_interruptible_timeout(qdio->req_q_wq,
-                              zfcp_qdio_sbal_check(qdio), 5 * HZ);
+       ret = wait_event_interruptible_lock_irq_timeout(qdio->req_q_wq,
+                      zfcp_qdio_sbal_check(qdio), qdio->req_q_lock, 5 * HZ);
 
        if (!(atomic_read(&qdio->adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP))
                return -EIO;
@@ -262,7 +259,6 @@ int zfcp_qdio_sbal_get(struct zfcp_qdio *qdio)
                zfcp_erp_adapter_reopen(qdio->adapter, 0, "qdsbg_1");
        }
 
-       spin_lock_irq(&qdio->req_q_lock);
        return -EIO;
 }
 
index 3f01bbf..8906392 100644 (file)
@@ -27,6 +27,16 @@ static ssize_t zfcp_sysfs_##_feat##_##_name##_show(struct device *dev,              \
 static ZFCP_DEV_ATTR(_feat, _name, S_IRUGO,                                   \
                     zfcp_sysfs_##_feat##_##_name##_show, NULL);
 
+#define ZFCP_DEFINE_ATTR_CONST(_feat, _name, _format, _value)                 \
+static ssize_t zfcp_sysfs_##_feat##_##_name##_show(struct device *dev,        \
+                                                  struct device_attribute *at,\
+                                                  char *buf)                  \
+{                                                                             \
+       return sprintf(buf, _format, _value);                                  \
+}                                                                             \
+static ZFCP_DEV_ATTR(_feat, _name, S_IRUGO,                                   \
+                    zfcp_sysfs_##_feat##_##_name##_show, NULL);
+
 #define ZFCP_DEFINE_A_ATTR(_name, _format, _value)                          \
 static ssize_t zfcp_sysfs_adapter_##_name##_show(struct device *dev,        \
                                                 struct device_attribute *at,\
@@ -75,6 +85,8 @@ ZFCP_DEFINE_ATTR(zfcp_unit, unit, in_recovery, "%d\n",
 ZFCP_DEFINE_ATTR(zfcp_unit, unit, access_denied, "%d\n",
                 (zfcp_unit_sdev_status(unit) &
                  ZFCP_STATUS_COMMON_ACCESS_DENIED) != 0);
+ZFCP_DEFINE_ATTR_CONST(unit, access_shared, "%d\n", 0);
+ZFCP_DEFINE_ATTR_CONST(unit, access_readonly, "%d\n", 0);
 
 static ssize_t zfcp_sysfs_port_failed_show(struct device *dev,
                                           struct device_attribute *attr,
@@ -347,6 +359,8 @@ static struct attribute *zfcp_unit_attrs[] = {
        &dev_attr_unit_in_recovery.attr,
        &dev_attr_unit_status.attr,
        &dev_attr_unit_access_denied.attr,
+       &dev_attr_unit_access_shared.attr,
+       &dev_attr_unit_access_readonly.attr,
        NULL
 };
 static struct attribute_group zfcp_unit_attr_group = {
index 48b2918..92ff027 100644 (file)
@@ -1353,7 +1353,6 @@ config SCSI_LPFC
        tristate "Emulex LightPulse Fibre Channel Support"
        depends on PCI && SCSI
        select SCSI_FC_ATTRS
-       select GENERIC_CSUM
        select CRC_T10DIF
        help
           This lpfc driver supports the Emulex LightPulse
index 89cbbab..8aad2c1 100644 (file)
@@ -70,14 +70,14 @@ config SPI_ATH79
 
 config SPI_ATMEL
        tristate "Atmel SPI Controller"
-       depends on (ARCH_AT91 || AVR32)
+       depends on (ARCH_AT91 || AVR32 || COMPILE_TEST)
        help
          This selects a driver for the Atmel SPI Controller, present on
          many AT32 (AVR32) and AT91 (ARM) chips.
 
 config SPI_BCM2835
        tristate "BCM2835 SPI controller"
-       depends on ARCH_BCM2835
+       depends on ARCH_BCM2835 || COMPILE_TEST
        help
          This selects a driver for the Broadcom BCM2835 SPI master.
 
@@ -88,10 +88,17 @@ config SPI_BCM2835
 
 config SPI_BFIN5XX
        tristate "SPI controller driver for ADI Blackfin5xx"
-       depends on BLACKFIN
+       depends on BLACKFIN && !BF60x
        help
          This is the SPI controller master driver for Blackfin 5xx processor.
 
+config SPI_BFIN_V3
+       tristate "SPI controller v3 for Blackfin"
+       depends on BF60x
+       help
+         This is the SPI controller v3 master driver
+         found on Blackfin 60x processor.
+
 config SPI_BFIN_SPORT
        tristate "SPI bus via Blackfin SPORT"
        depends on BLACKFIN
@@ -151,15 +158,22 @@ config SPI_COLDFIRE_QSPI
 
 config SPI_DAVINCI
        tristate "Texas Instruments DaVinci/DA8x/OMAP-L/AM1x SoC SPI controller"
-       depends on ARCH_DAVINCI
+       depends on ARCH_DAVINCI || ARCH_KEYSTONE
        select SPI_BITBANG
        select TI_EDMA
        help
          SPI master controller for DaVinci/DA8x/OMAP-L/AM1x SPI modules.
 
+config SPI_EFM32
+       tristate "EFM32 SPI controller"
+       depends on OF && ARM && (ARCH_EFM32 || COMPILE_TEST)
+       select SPI_BITBANG
+       help
+         Driver for the spi controller found on Energy Micro's EFM32 SoCs.
+
 config SPI_EP93XX
        tristate "Cirrus Logic EP93xx SPI controller"
-       depends on ARCH_EP93XX
+       depends on ARCH_EP93XX || COMPILE_TEST
        help
          This enables using the Cirrus EP93xx SPI controller in master
          mode.
@@ -191,7 +205,7 @@ config SPI_GPIO
 
 config SPI_IMX
        tristate "Freescale i.MX SPI controllers"
-       depends on ARCH_MXC
+       depends on ARCH_MXC || COMPILE_TEST
        select SPI_BITBANG
        default m if IMX_HAVE_PLATFORM_SPI_IMX
        help
@@ -248,6 +262,13 @@ config SPI_FSL_SPI
          This also enables using the Aeroflex Gaisler GRLIB SPI controller in
          master mode.
 
+config SPI_FSL_DSPI
+       tristate "Freescale DSPI controller"
+       select SPI_BITBANG
+       help
+         This enables support for the Freescale DSPI controller in master
+         mode. VF610 platform uses the controller.
+
 config SPI_FSL_ESPI
        bool "Freescale eSPI controller"
        depends on FSL_SOC
@@ -280,20 +301,20 @@ config SPI_OMAP_UWIRE
 
 config SPI_OMAP24XX
        tristate "McSPI driver for OMAP"
-       depends on ARCH_OMAP2PLUS
+       depends on ARCH_OMAP2PLUS || COMPILE_TEST
        help
          SPI master controller for OMAP24XX and later Multichannel SPI
          (McSPI) modules.
 
 config SPI_OMAP_100K
        tristate "OMAP SPI 100K"
-       depends on ARCH_OMAP850 || ARCH_OMAP730
+       depends on ARCH_OMAP850 || ARCH_OMAP730 || COMPILE_TEST
        help
          OMAP SPI 100K master controller for omap7xx boards.
 
 config SPI_ORION
        tristate "Orion SPI master"
-       depends on PLAT_ORION
+       depends on PLAT_ORION || COMPILE_TEST
        help
          This enables using the SPI master controller on the Orion chips.
 
@@ -341,7 +362,7 @@ config SPI_PXA2XX_PCI
 
 config SPI_RSPI
        tristate "Renesas RSPI controller"
-       depends on SUPERH
+       depends on SUPERH && SH_DMAE_BASE
        help
          SPI driver for Renesas RSPI blocks.
 
@@ -385,7 +406,7 @@ config SPI_SH_MSIOF
 
 config SPI_SH
        tristate "SuperH SPI controller"
-       depends on SUPERH
+       depends on SUPERH || COMPILE_TEST
        help
          SPI driver for SuperH SPI blocks.
 
@@ -398,7 +419,7 @@ config SPI_SH_SCI
 
 config SPI_SH_HSPI
        tristate "SuperH HSPI controller"
-       depends on ARCH_SHMOBILE
+       depends on ARCH_SHMOBILE || COMPILE_TEST
        help
          SPI driver for SuperH HSPI blocks.
 
@@ -418,7 +439,7 @@ config SPI_MXS
 
 config SPI_TEGRA114
        tristate "NVIDIA Tegra114 SPI Controller"
-       depends on ARCH_TEGRA && TEGRA20_APB_DMA
+       depends on (ARCH_TEGRA && TEGRA20_APB_DMA) || COMPILE_TEST
        help
          SPI driver for NVIDIA Tegra114 SPI Controller interface. This controller
          is different than the older SoCs SPI controller and also register interface
@@ -426,7 +447,7 @@ config SPI_TEGRA114
 
 config SPI_TEGRA20_SFLASH
        tristate "Nvidia Tegra20 Serial flash Controller"
-       depends on ARCH_TEGRA
+       depends on ARCH_TEGRA || COMPILE_TEST
        help
          SPI driver for Nvidia Tegra20 Serial flash Controller interface.
          The main usecase of this controller is to use spi flash as boot
@@ -434,7 +455,7 @@ config SPI_TEGRA20_SFLASH
 
 config SPI_TEGRA20_SLINK
        tristate "Nvidia Tegra20/Tegra30 SLINK Controller"
-       depends on ARCH_TEGRA && TEGRA20_APB_DMA
+       depends on (ARCH_TEGRA && TEGRA20_APB_DMA) || COMPILE_TEST
        help
          SPI driver for Nvidia Tegra20/Tegra30 SLINK Controller interface.
 
@@ -457,7 +478,7 @@ config SPI_TOPCLIFF_PCH
 
 config SPI_TXX9
        tristate "Toshiba TXx9 SPI controller"
-       depends on GPIOLIB && CPU_TX49XX
+       depends on GPIOLIB && (CPU_TX49XX || COMPILE_TEST)
        help
          SPI driver for Toshiba TXx9 MIPS SoCs
 
index 33f9c09..985d7ba 100644 (file)
@@ -17,6 +17,7 @@ obj-$(CONFIG_SPI_AU1550)              += spi-au1550.o
 obj-$(CONFIG_SPI_BCM2835)              += spi-bcm2835.o
 obj-$(CONFIG_SPI_BCM63XX)              += spi-bcm63xx.o
 obj-$(CONFIG_SPI_BFIN5XX)              += spi-bfin5xx.o
+obj-$(CONFIG_SPI_BFIN_V3)               += spi-bfin-v3.o
 obj-$(CONFIG_SPI_BFIN_SPORT)           += spi-bfin-sport.o
 obj-$(CONFIG_SPI_BITBANG)              += spi-bitbang.o
 obj-$(CONFIG_SPI_BUTTERFLY)            += spi-butterfly.o
@@ -27,9 +28,11 @@ obj-$(CONFIG_SPI_DESIGNWARE)         += spi-dw.o
 obj-$(CONFIG_SPI_DW_MMIO)              += spi-dw-mmio.o
 obj-$(CONFIG_SPI_DW_PCI)               += spi-dw-midpci.o
 spi-dw-midpci-objs                     := spi-dw-pci.o spi-dw-mid.o
+obj-$(CONFIG_SPI_EFM32)                        += spi-efm32.o
 obj-$(CONFIG_SPI_EP93XX)               += spi-ep93xx.o
 obj-$(CONFIG_SPI_FALCON)               += spi-falcon.o
 obj-$(CONFIG_SPI_FSL_CPM)              += spi-fsl-cpm.o
+obj-$(CONFIG_SPI_FSL_DSPI)             += spi-fsl-dspi.o
 obj-$(CONFIG_SPI_FSL_LIB)              += spi-fsl-lib.o
 obj-$(CONFIG_SPI_FSL_ESPI)             += spi-fsl-espi.o
 obj-$(CONFIG_SPI_FSL_SPI)              += spi-fsl-spi.o
index 81b9adb..156eb88 100644 (file)
@@ -103,16 +103,6 @@ static void altera_spi_chipsel(struct spi_device *spi, int value)
        }
 }
 
-static int altera_spi_setupxfer(struct spi_device *spi, struct spi_transfer *t)
-{
-       return 0;
-}
-
-static int altera_spi_setup(struct spi_device *spi)
-{
-       return 0;
-}
-
 static inline unsigned int hw_txbyte(struct altera_spi *hw, int count)
 {
        if (hw->tx) {
@@ -134,7 +124,7 @@ static int altera_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
        hw->tx = t->tx_buf;
        hw->rx = t->rx_buf;
        hw->count = 0;
-       hw->bytes_per_word = t->bits_per_word / 8;
+       hw->bytes_per_word = DIV_ROUND_UP(t->bits_per_word, 8);
        hw->len = t->len / hw->bytes_per_word;
 
        if (hw->irq >= 0) {
@@ -150,12 +140,12 @@ static int altera_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
                hw->imr &= ~ALTERA_SPI_CONTROL_IRRDY_MSK;
                writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
        } else {
-               /* send the first byte */
-               writel(hw_txbyte(hw, 0), hw->base + ALTERA_SPI_TXDATA);
-
-               while (1) {
+               while (hw->count < hw->len) {
                        unsigned int rxd;
 
+                       writel(hw_txbyte(hw, hw->count),
+                              hw->base + ALTERA_SPI_TXDATA);
+
                        while (!(readl(hw->base + ALTERA_SPI_STATUS) &
                                 ALTERA_SPI_STATUS_RRDY_MSK))
                                cpu_relax();
@@ -174,14 +164,7 @@ static int altera_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
                        }
 
                        hw->count++;
-
-                       if (hw->count < hw->len)
-                               writel(hw_txbyte(hw, hw->count),
-                                      hw->base + ALTERA_SPI_TXDATA);
-                       else
-                               break;
                }
-
        }
 
        return hw->count * hw->bytes_per_word;
@@ -231,7 +214,6 @@ static int altera_spi_probe(struct platform_device *pdev)
        master->bus_num = pdev->id;
        master->num_chipselect = 16;
        master->mode_bits = SPI_CS_HIGH;
-       master->setup = altera_spi_setup;
 
        hw = spi_master_get_devdata(master);
        platform_set_drvdata(pdev, hw);
@@ -240,21 +222,16 @@ static int altera_spi_probe(struct platform_device *pdev)
        hw->bitbang.master = spi_master_get(master);
        if (!hw->bitbang.master)
                return err;
-       hw->bitbang.setup_transfer = altera_spi_setupxfer;
        hw->bitbang.chipselect = altera_spi_chipsel;
        hw->bitbang.txrx_bufs = altera_spi_txrx;
 
        /* find and map our resources */
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res)
-               goto exit_busy;
-       if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res),
-                                    pdev->name))
-               goto exit_busy;
-       hw->base = devm_ioremap_nocache(&pdev->dev, res->start,
-                                       resource_size(res));
-       if (!hw->base)
-               goto exit_busy;
+       hw->base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(hw->base)) {
+               err = PTR_ERR(hw->base);
+               goto exit;
+       }
        /* program defaults into the registers */
        hw->imr = 0;            /* disable spi interrupts */
        writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
@@ -281,9 +258,6 @@ static int altera_spi_probe(struct platform_device *pdev)
        dev_info(&pdev->dev, "base %p, irq %d\n", hw->base, hw->irq);
 
        return 0;
-
-exit_busy:
-       err = -EBUSY;
 exit:
        spi_master_put(master);
        return err;
index ea1ec00..fd7cc56 100644 (file)
@@ -360,12 +360,12 @@ static void cs_deactivate(struct atmel_spi *as, struct spi_device *spi)
                gpio_set_value(asd->npcs_pin, !active);
 }
 
-static void atmel_spi_lock(struct atmel_spi *as)
+static void atmel_spi_lock(struct atmel_spi *as) __acquires(&as->lock)
 {
        spin_lock_irqsave(&as->lock, as->flags);
 }
 
-static void atmel_spi_unlock(struct atmel_spi *as)
+static void atmel_spi_unlock(struct atmel_spi *as) __releases(&as->lock)
 {
        spin_unlock_irqrestore(&as->lock, as->flags);
 }
@@ -629,9 +629,9 @@ static int atmel_spi_next_xfer_dma_submit(struct spi_master *master,
                goto err_dma;
 
        dev_dbg(master->dev.parent,
-               "  start dma xfer %p: len %u tx %p/%08x rx %p/%08x\n",
-               xfer, xfer->len, xfer->tx_buf, xfer->tx_dma,
-               xfer->rx_buf, xfer->rx_dma);
+               "  start dma xfer %p: len %u tx %p/%08llx rx %p/%08llx\n",
+               xfer, xfer->len, xfer->tx_buf, (unsigned long long)xfer->tx_dma,
+               xfer->rx_buf, (unsigned long long)xfer->rx_dma);
 
        /* Enable relevant interrupts */
        spi_writel(as, IER, SPI_BIT(OVRES));
@@ -732,9 +732,10 @@ static void atmel_spi_pdc_next_xfer(struct spi_master *master,
                spi_writel(as, TCR, len);
 
                dev_dbg(&msg->spi->dev,
-                       "  start xfer %p: len %u tx %p/%08x rx %p/%08x\n",
-                       xfer, xfer->len, xfer->tx_buf, xfer->tx_dma,
-                       xfer->rx_buf, xfer->rx_dma);
+                       "  start xfer %p: len %u tx %p/%08llx rx %p/%08llx\n",
+                       xfer, xfer->len, xfer->tx_buf,
+                       (unsigned long long)xfer->tx_dma, xfer->rx_buf,
+                       (unsigned long long)xfer->rx_dma);
        } else {
                xfer = as->next_transfer;
                remaining = as->next_remaining_bytes;
@@ -771,9 +772,10 @@ static void atmel_spi_pdc_next_xfer(struct spi_master *master,
                spi_writel(as, TNCR, len);
 
                dev_dbg(&msg->spi->dev,
-                       "  next xfer %p: len %u tx %p/%08x rx %p/%08x\n",
-                       xfer, xfer->len, xfer->tx_buf, xfer->tx_dma,
-                       xfer->rx_buf, xfer->rx_dma);
+                       "  next xfer %p: len %u tx %p/%08llx rx %p/%08llx\n",
+                       xfer, xfer->len, xfer->tx_buf,
+                       (unsigned long long)xfer->tx_dma, xfer->rx_buf,
+                       (unsigned long long)xfer->rx_dma);
                ieval = SPI_BIT(ENDRX) | SPI_BIT(OVRES);
        } else {
                spi_writel(as, RNCR, 0);
@@ -1579,7 +1581,9 @@ static int atmel_spi_probe(struct platform_device *pdev)
                goto out_unmap_regs;
 
        /* Initialize the hardware */
-       clk_enable(clk);
+       ret = clk_prepare_enable(clk);
+       if (ret)
+               goto out_unmap_regs;
        spi_writel(as, CR, SPI_BIT(SWRST));
        spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */
        if (as->caps.has_wdrbt) {
@@ -1609,7 +1613,7 @@ out_free_dma:
 
        spi_writel(as, CR, SPI_BIT(SWRST));
        spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */
-       clk_disable(clk);
+       clk_disable_unprepare(clk);
        free_irq(irq, master);
 out_unmap_regs:
        iounmap(as->regs);
@@ -1661,7 +1665,7 @@ static int atmel_spi_remove(struct platform_device *pdev)
        dma_free_coherent(&pdev->dev, BUFFER_SIZE, as->buffer,
                        as->buffer_dma);
 
-       clk_disable(as->clk);
+       clk_disable_unprepare(as->clk);
        clk_put(as->clk);
        free_irq(as->irq, master);
        iounmap(as->regs);
@@ -1678,7 +1682,7 @@ static int atmel_spi_suspend(struct platform_device *pdev, pm_message_t mesg)
        struct spi_master       *master = platform_get_drvdata(pdev);
        struct atmel_spi        *as = spi_master_get_devdata(master);
 
-       clk_disable(as->clk);
+       clk_disable_unprepare(as->clk);
        return 0;
 }
 
@@ -1687,7 +1691,7 @@ static int atmel_spi_resume(struct platform_device *pdev)
        struct spi_master       *master = platform_get_drvdata(pdev);
        struct atmel_spi        *as = spi_master_get_devdata(master);
 
-       clk_enable(as->clk);
+       return clk_prepare_enable(as->clk);
        return 0;
 }
 
index a4185e4..52c8148 100644 (file)
@@ -314,7 +314,7 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, master);
 
        master->mode_bits = BCM2835_SPI_MODE_BITS;
-       master->bits_per_word_mask = BIT(8 - 1);
+       master->bits_per_word_mask = SPI_BPW_MASK(8);
        master->bus_num = -1;
        master->num_chipselect = 3;
        master->transfer_one_message = bcm2835_spi_transfer_one;
@@ -325,12 +325,6 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
        init_completion(&bs->done);
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(&pdev->dev, "could not get memory resource\n");
-               err = -ENODEV;
-               goto out_master_put;
-       }
-
        bs->regs = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(bs->regs)) {
                err = PTR_ERR(bs->regs);
@@ -383,7 +377,7 @@ out_master_put:
 
 static int bcm2835_spi_remove(struct platform_device *pdev)
 {
-       struct spi_master *master = platform_get_drvdata(pdev);
+       struct spi_master *master = spi_master_get(platform_get_drvdata(pdev));
        struct bcm2835_spi *bs = spi_master_get_devdata(master);
 
        free_irq(bs->irq, master);
index 9fd7a39..a21fef4 100644 (file)
@@ -360,13 +360,6 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
        struct bcm63xx_spi *bs;
        int ret;
 
-       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!r) {
-               dev_err(dev, "no iomem\n");
-               ret = -ENXIO;
-               goto out;
-       }
-
        irq = platform_get_irq(pdev, 0);
        if (irq < 0) {
                dev_err(dev, "no irq\n");
@@ -393,6 +386,7 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, master);
        bs->pdev = pdev;
 
+       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        bs->regs = devm_ioremap_resource(&pdev->dev, r);
        if (IS_ERR(bs->regs)) {
                ret = PTR_ERR(bs->regs);
diff --git a/drivers/spi/spi-bfin-v3.c b/drivers/spi/spi-bfin-v3.c
new file mode 100644 (file)
index 0000000..e4394eb
--- /dev/null
@@ -0,0 +1,965 @@
+/*
+ * Analog Devices SPI3 controller driver
+ *
+ * Copyright (c) 2013 Analog Devices Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/errno.h>
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+#include <linux/types.h>
+
+#include <asm/bfin_spi3.h>
+#include <asm/cacheflush.h>
+#include <asm/dma.h>
+#include <asm/portmux.h>
+
+enum bfin_spi_state {
+       START_STATE,
+       RUNNING_STATE,
+       DONE_STATE,
+       ERROR_STATE
+};
+
+struct bfin_spi_master;
+
+struct bfin_spi_transfer_ops {
+       void (*write) (struct bfin_spi_master *);
+       void (*read) (struct bfin_spi_master *);
+       void (*duplex) (struct bfin_spi_master *);
+};
+
+/* runtime info for spi master */
+struct bfin_spi_master {
+       /* SPI framework hookup */
+       struct spi_master *master;
+
+       /* Regs base of SPI controller */
+       struct bfin_spi_regs __iomem *regs;
+
+       /* Pin request list */
+       u16 *pin_req;
+
+       /* Message Transfer pump */
+       struct tasklet_struct pump_transfers;
+
+       /* Current message transfer state info */
+       struct spi_message *cur_msg;
+       struct spi_transfer *cur_transfer;
+       struct bfin_spi_device *cur_chip;
+       unsigned transfer_len;
+
+       /* transfer buffer */
+       void *tx;
+       void *tx_end;
+       void *rx;
+       void *rx_end;
+
+       /* dma info */
+       unsigned int tx_dma;
+       unsigned int rx_dma;
+       dma_addr_t tx_dma_addr;
+       dma_addr_t rx_dma_addr;
+       unsigned long dummy_buffer; /* used in unidirectional transfer */
+       unsigned long tx_dma_size;
+       unsigned long rx_dma_size;
+       int tx_num;
+       int rx_num;
+
+       /* store register value for suspend/resume */
+       u32 control;
+       u32 ssel;
+
+       unsigned long sclk;
+       enum bfin_spi_state state;
+
+       const struct bfin_spi_transfer_ops *ops;
+};
+
+struct bfin_spi_device {
+       u32 control;
+       u32 clock;
+       u32 ssel;
+
+       u8 cs;
+       u16 cs_chg_udelay; /* Some devices require > 255usec delay */
+       u32 cs_gpio;
+       u32 tx_dummy_val; /* tx value for rx only transfer */
+       bool enable_dma;
+       const struct bfin_spi_transfer_ops *ops;
+};
+
+static void bfin_spi_enable(struct bfin_spi_master *drv_data)
+{
+       bfin_write_or(&drv_data->regs->control, SPI_CTL_EN);
+}
+
+static void bfin_spi_disable(struct bfin_spi_master *drv_data)
+{
+       bfin_write_and(&drv_data->regs->control, ~SPI_CTL_EN);
+}
+
+/* Caculate the SPI_CLOCK register value based on input HZ */
+static u32 hz_to_spi_clock(u32 sclk, u32 speed_hz)
+{
+       u32 spi_clock = sclk / speed_hz;
+
+       if (spi_clock)
+               spi_clock--;
+       return spi_clock;
+}
+
+static int bfin_spi_flush(struct bfin_spi_master *drv_data)
+{
+       unsigned long limit = loops_per_jiffy << 1;
+
+       /* wait for stop and clear stat */
+       while (!(bfin_read(&drv_data->regs->status) & SPI_STAT_SPIF) && --limit)
+               cpu_relax();
+
+       bfin_write(&drv_data->regs->status, 0xFFFFFFFF);
+
+       return limit;
+}
+
+/* Chip select operation functions for cs_change flag */
+static void bfin_spi_cs_active(struct bfin_spi_master *drv_data, struct bfin_spi_device *chip)
+{
+       if (likely(chip->cs < MAX_CTRL_CS))
+               bfin_write_and(&drv_data->regs->ssel, ~chip->ssel);
+       else
+               gpio_set_value(chip->cs_gpio, 0);
+}
+
+static void bfin_spi_cs_deactive(struct bfin_spi_master *drv_data,
+                               struct bfin_spi_device *chip)
+{
+       if (likely(chip->cs < MAX_CTRL_CS))
+               bfin_write_or(&drv_data->regs->ssel, chip->ssel);
+       else
+               gpio_set_value(chip->cs_gpio, 1);
+
+       /* Move delay here for consistency */
+       if (chip->cs_chg_udelay)
+               udelay(chip->cs_chg_udelay);
+}
+
+/* enable or disable the pin muxed by GPIO and SPI CS to work as SPI CS */
+static inline void bfin_spi_cs_enable(struct bfin_spi_master *drv_data,
+                                       struct bfin_spi_device *chip)
+{
+       if (chip->cs < MAX_CTRL_CS)
+               bfin_write_or(&drv_data->regs->ssel, chip->ssel >> 8);
+}
+
+static inline void bfin_spi_cs_disable(struct bfin_spi_master *drv_data,
+                                       struct bfin_spi_device *chip)
+{
+       if (chip->cs < MAX_CTRL_CS)
+               bfin_write_and(&drv_data->regs->ssel, ~(chip->ssel >> 8));
+}
+
+/* stop controller and re-config current chip*/
+static void bfin_spi_restore_state(struct bfin_spi_master *drv_data)
+{
+       struct bfin_spi_device *chip = drv_data->cur_chip;
+
+       /* Clear status and disable clock */
+       bfin_write(&drv_data->regs->status, 0xFFFFFFFF);
+       bfin_write(&drv_data->regs->rx_control, 0x0);
+       bfin_write(&drv_data->regs->tx_control, 0x0);
+       bfin_spi_disable(drv_data);
+
+       SSYNC();
+
+       /* Load the registers */
+       bfin_write(&drv_data->regs->control, chip->control);
+       bfin_write(&drv_data->regs->clock, chip->clock);
+
+       bfin_spi_enable(drv_data);
+       drv_data->tx_num = drv_data->rx_num = 0;
+       /* we always choose tx transfer initiate */
+       bfin_write(&drv_data->regs->rx_control, SPI_RXCTL_REN);
+       bfin_write(&drv_data->regs->tx_control,
+                       SPI_TXCTL_TEN | SPI_TXCTL_TTI);
+       bfin_spi_cs_active(drv_data, chip);
+}
+
+/* discard invalid rx data and empty rfifo */
+static inline void dummy_read(struct bfin_spi_master *drv_data)
+{
+       while (!(bfin_read(&drv_data->regs->status) & SPI_STAT_RFE))
+               bfin_read(&drv_data->regs->rfifo);
+}
+
+static void bfin_spi_u8_write(struct bfin_spi_master *drv_data)
+{
+       dummy_read(drv_data);
+       while (drv_data->tx < drv_data->tx_end) {
+               bfin_write(&drv_data->regs->tfifo, (*(u8 *)(drv_data->tx++)));
+               while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE)
+                       cpu_relax();
+               bfin_read(&drv_data->regs->rfifo);
+       }
+}
+
+static void bfin_spi_u8_read(struct bfin_spi_master *drv_data)
+{
+       u32 tx_val = drv_data->cur_chip->tx_dummy_val;
+
+       dummy_read(drv_data);
+       while (drv_data->rx < drv_data->rx_end) {
+               bfin_write(&drv_data->regs->tfifo, tx_val);
+               while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE)
+                       cpu_relax();
+               *(u8 *)(drv_data->rx++) = bfin_read(&drv_data->regs->rfifo);
+       }
+}
+
+static void bfin_spi_u8_duplex(struct bfin_spi_master *drv_data)
+{
+       dummy_read(drv_data);
+       while (drv_data->rx < drv_data->rx_end) {
+               bfin_write(&drv_data->regs->tfifo, (*(u8 *)(drv_data->tx++)));
+               while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE)
+                       cpu_relax();
+               *(u8 *)(drv_data->rx++) = bfin_read(&drv_data->regs->rfifo);
+       }
+}
+
+static const struct bfin_spi_transfer_ops bfin_bfin_spi_transfer_ops_u8 = {
+       .write  = bfin_spi_u8_write,
+       .read   = bfin_spi_u8_read,
+       .duplex = bfin_spi_u8_duplex,
+};
+
+static void bfin_spi_u16_write(struct bfin_spi_master *drv_data)
+{
+       dummy_read(drv_data);
+       while (drv_data->tx < drv_data->tx_end) {
+               bfin_write(&drv_data->regs->tfifo, (*(u16 *)drv_data->tx));
+               drv_data->tx += 2;
+               while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE)
+                       cpu_relax();
+               bfin_read(&drv_data->regs->rfifo);
+       }
+}
+
+static void bfin_spi_u16_read(struct bfin_spi_master *drv_data)
+{
+       u32 tx_val = drv_data->cur_chip->tx_dummy_val;
+
+       dummy_read(drv_data);
+       while (drv_data->rx < drv_data->rx_end) {
+               bfin_write(&drv_data->regs->tfifo, tx_val);
+               while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE)
+                       cpu_relax();
+               *(u16 *)drv_data->rx = bfin_read(&drv_data->regs->rfifo);
+               drv_data->rx += 2;
+       }
+}
+
+static void bfin_spi_u16_duplex(struct bfin_spi_master *drv_data)
+{
+       dummy_read(drv_data);
+       while (drv_data->rx < drv_data->rx_end) {
+               bfin_write(&drv_data->regs->tfifo, (*(u16 *)drv_data->tx));
+               drv_data->tx += 2;
+               while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE)
+                       cpu_relax();
+               *(u16 *)drv_data->rx = bfin_read(&drv_data->regs->rfifo);
+               drv_data->rx += 2;
+       }
+}
+
+static const struct bfin_spi_transfer_ops bfin_bfin_spi_transfer_ops_u16 = {
+       .write  = bfin_spi_u16_write,
+       .read   = bfin_spi_u16_read,
+       .duplex = bfin_spi_u16_duplex,
+};
+
+static void bfin_spi_u32_write(struct bfin_spi_master *drv_data)
+{
+       dummy_read(drv_data);
+       while (drv_data->tx < drv_data->tx_end) {
+               bfin_write(&drv_data->regs->tfifo, (*(u32 *)drv_data->tx));
+               drv_data->tx += 4;
+               while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE)
+                       cpu_relax();
+               bfin_read(&drv_data->regs->rfifo);
+       }
+}
+
+static void bfin_spi_u32_read(struct bfin_spi_master *drv_data)
+{
+       u32 tx_val = drv_data->cur_chip->tx_dummy_val;
+
+       dummy_read(drv_data);
+       while (drv_data->rx < drv_data->rx_end) {
+               bfin_write(&drv_data->regs->tfifo, tx_val);
+               while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE)
+                       cpu_relax();
+               *(u32 *)drv_data->rx = bfin_read(&drv_data->regs->rfifo);
+               drv_data->rx += 4;
+       }
+}
+
+static void bfin_spi_u32_duplex(struct bfin_spi_master *drv_data)
+{
+       dummy_read(drv_data);
+       while (drv_data->rx < drv_data->rx_end) {
+               bfin_write(&drv_data->regs->tfifo, (*(u32 *)drv_data->tx));
+               drv_data->tx += 4;
+               while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE)
+                       cpu_relax();
+               *(u32 *)drv_data->rx = bfin_read(&drv_data->regs->rfifo);
+               drv_data->rx += 4;
+       }
+}
+
+static const struct bfin_spi_transfer_ops bfin_bfin_spi_transfer_ops_u32 = {
+       .write  = bfin_spi_u32_write,
+       .read   = bfin_spi_u32_read,
+       .duplex = bfin_spi_u32_duplex,
+};
+
+
+/* test if there is more transfer to be done */
+static void bfin_spi_next_transfer(struct bfin_spi_master *drv)
+{
+       struct spi_message *msg = drv->cur_msg;
+       struct spi_transfer *t = drv->cur_transfer;
+
+       /* Move to next transfer */
+       if (t->transfer_list.next != &msg->transfers) {
+               drv->cur_transfer = list_entry(t->transfer_list.next,
+                              struct spi_transfer, transfer_list);
+               drv->state = RUNNING_STATE;
+       } else {
+               drv->state = DONE_STATE;
+               drv->cur_transfer = NULL;
+       }
+}
+
+static void bfin_spi_giveback(struct bfin_spi_master *drv_data)
+{
+       struct bfin_spi_device *chip = drv_data->cur_chip;
+
+       bfin_spi_cs_deactive(drv_data, chip);
+       spi_finalize_current_message(drv_data->master);
+}
+
+static int bfin_spi_setup_transfer(struct bfin_spi_master *drv)
+{
+       struct spi_transfer *t = drv->cur_transfer;
+       u32 cr, cr_width;
+
+       if (t->tx_buf) {
+               drv->tx = (void *)t->tx_buf;
+               drv->tx_end = drv->tx + t->len;
+       } else {
+               drv->tx = NULL;
+       }
+
+       if (t->rx_buf) {
+               drv->rx = t->rx_buf;
+               drv->rx_end = drv->rx + t->len;
+       } else {
+               drv->rx = NULL;
+       }
+
+       drv->transfer_len = t->len;
+
+       /* bits per word setup */
+       switch (t->bits_per_word) {
+       case 8:
+               cr_width = SPI_CTL_SIZE08;
+               drv->ops = &bfin_bfin_spi_transfer_ops_u8;
+               break;
+       case 16:
+               cr_width = SPI_CTL_SIZE16;
+               drv->ops = &bfin_bfin_spi_transfer_ops_u16;
+               break;
+       case 32:
+               cr_width = SPI_CTL_SIZE32;
+               drv->ops = &bfin_bfin_spi_transfer_ops_u32;
+               break;
+       default:
+               return -EINVAL;
+       }
+       cr = bfin_read(&drv->regs->control) & ~SPI_CTL_SIZE;
+       cr |= cr_width;
+       bfin_write(&drv->regs->control, cr);
+
+       /* speed setup */
+       bfin_write(&drv->regs->clock,
+                       hz_to_spi_clock(drv->sclk, t->speed_hz));
+       return 0;
+}
+
+static int bfin_spi_dma_xfer(struct bfin_spi_master *drv_data)
+{
+       struct spi_transfer *t = drv_data->cur_transfer;
+       struct spi_message *msg = drv_data->cur_msg;
+       struct bfin_spi_device *chip = drv_data->cur_chip;
+       u32 dma_config;
+       unsigned long word_count, word_size;
+       void *tx_buf, *rx_buf;
+
+       switch (t->bits_per_word) {
+       case 8:
+               dma_config = WDSIZE_8 | PSIZE_8;
+               word_count = drv_data->transfer_len;
+               word_size = 1;
+               break;
+       case 16:
+               dma_config = WDSIZE_16 | PSIZE_16;
+               word_count = drv_data->transfer_len / 2;
+               word_size = 2;
+               break;
+       default:
+               dma_config = WDSIZE_32 | PSIZE_32;
+               word_count = drv_data->transfer_len / 4;
+               word_size = 4;
+               break;
+       }
+
+       if (!drv_data->rx) {
+               tx_buf = drv_data->tx;
+               rx_buf = &drv_data->dummy_buffer;
+               drv_data->tx_dma_size = drv_data->transfer_len;
+               drv_data->rx_dma_size = sizeof(drv_data->dummy_buffer);
+               set_dma_x_modify(drv_data->tx_dma, word_size);
+               set_dma_x_modify(drv_data->rx_dma, 0);
+       } else if (!drv_data->tx) {
+               drv_data->dummy_buffer = chip->tx_dummy_val;
+               tx_buf = &drv_data->dummy_buffer;
+               rx_buf = drv_data->rx;
+               drv_data->tx_dma_size = sizeof(drv_data->dummy_buffer);
+               drv_data->rx_dma_size = drv_data->transfer_len;
+               set_dma_x_modify(drv_data->tx_dma, 0);
+               set_dma_x_modify(drv_data->rx_dma, word_size);
+       } else {
+               tx_buf = drv_data->tx;
+               rx_buf = drv_data->rx;
+               drv_data->tx_dma_size = drv_data->rx_dma_size
+                                       = drv_data->transfer_len;
+               set_dma_x_modify(drv_data->tx_dma, word_size);
+               set_dma_x_modify(drv_data->rx_dma, word_size);
+       }
+
+       drv_data->tx_dma_addr = dma_map_single(&msg->spi->dev,
+                               (void *)tx_buf,
+                               drv_data->tx_dma_size,
+                               DMA_TO_DEVICE);
+       if (dma_mapping_error(&msg->spi->dev,
+                               drv_data->tx_dma_addr))
+               return -ENOMEM;
+
+       drv_data->rx_dma_addr = dma_map_single(&msg->spi->dev,
+                               (void *)rx_buf,
+                               drv_data->rx_dma_size,
+                               DMA_FROM_DEVICE);
+       if (dma_mapping_error(&msg->spi->dev,
+                               drv_data->rx_dma_addr)) {
+               dma_unmap_single(&msg->spi->dev,
+                               drv_data->tx_dma_addr,
+                               drv_data->tx_dma_size,
+                               DMA_TO_DEVICE);
+               return -ENOMEM;
+       }
+
+       dummy_read(drv_data);
+       set_dma_x_count(drv_data->tx_dma, word_count);
+       set_dma_x_count(drv_data->rx_dma, word_count);
+       set_dma_start_addr(drv_data->tx_dma, drv_data->tx_dma_addr);
+       set_dma_start_addr(drv_data->rx_dma, drv_data->rx_dma_addr);
+       dma_config |= DMAFLOW_STOP | RESTART | DI_EN;
+       set_dma_config(drv_data->tx_dma, dma_config);
+       set_dma_config(drv_data->rx_dma, dma_config | WNR);
+       enable_dma(drv_data->tx_dma);
+       enable_dma(drv_data->rx_dma);
+       SSYNC();
+
+       bfin_write(&drv_data->regs->rx_control, SPI_RXCTL_REN | SPI_RXCTL_RDR_NE);
+       SSYNC();
+       bfin_write(&drv_data->regs->tx_control,
+                       SPI_TXCTL_TEN | SPI_TXCTL_TTI | SPI_TXCTL_TDR_NF);
+
+       return 0;
+}
+
+static int bfin_spi_pio_xfer(struct bfin_spi_master *drv_data)
+{
+       struct spi_message *msg = drv_data->cur_msg;
+
+       if (!drv_data->rx) {
+               /* write only half duplex */
+               drv_data->ops->write(drv_data);
+               if (drv_data->tx != drv_data->tx_end)
+                       return -EIO;
+       } else if (!drv_data->tx) {
+               /* read only half duplex */
+               drv_data->ops->read(drv_data);
+               if (drv_data->rx != drv_data->rx_end)
+                       return -EIO;
+       } else {
+               /* full duplex mode */
+               drv_data->ops->duplex(drv_data);
+               if (drv_data->tx != drv_data->tx_end)
+                       return -EIO;
+       }
+
+       if (!bfin_spi_flush(drv_data))
+               return -EIO;
+       msg->actual_length += drv_data->transfer_len;
+       tasklet_schedule(&drv_data->pump_transfers);
+       return 0;
+}
+
+static void bfin_spi_pump_transfers(unsigned long data)
+{
+       struct bfin_spi_master *drv_data = (struct bfin_spi_master *)data;
+       struct spi_message *msg = NULL;
+       struct spi_transfer *t = NULL;
+       struct bfin_spi_device *chip = NULL;
+       int ret;
+
+       /* Get current state information */
+       msg = drv_data->cur_msg;
+       t = drv_data->cur_transfer;
+       chip = drv_data->cur_chip;
+
+       /* Handle for abort */
+       if (drv_data->state == ERROR_STATE) {
+               msg->status = -EIO;
+               bfin_spi_giveback(drv_data);
+               return;
+       }
+
+       if (drv_data->state == RUNNING_STATE) {
+               if (t->delay_usecs)
+                       udelay(t->delay_usecs);
+               if (t->cs_change)
+                       bfin_spi_cs_deactive(drv_data, chip);
+               bfin_spi_next_transfer(drv_data);
+               t = drv_data->cur_transfer;
+       }
+       /* Handle end of message */
+       if (drv_data->state == DONE_STATE) {
+               msg->status = 0;
+               bfin_spi_giveback(drv_data);
+               return;
+       }
+
+       if ((t->len == 0) || (t->tx_buf == NULL && t->rx_buf == NULL)) {
+               /* Schedule next transfer tasklet */
+               tasklet_schedule(&drv_data->pump_transfers);
+               return;
+       }
+
+       ret = bfin_spi_setup_transfer(drv_data);
+       if (ret) {
+               msg->status = ret;
+               bfin_spi_giveback(drv_data);
+       }
+
+       bfin_write(&drv_data->regs->status, 0xFFFFFFFF);
+       bfin_spi_cs_active(drv_data, chip);
+       drv_data->state = RUNNING_STATE;
+
+       if (chip->enable_dma)
+               ret = bfin_spi_dma_xfer(drv_data);
+       else
+               ret = bfin_spi_pio_xfer(drv_data);
+       if (ret) {
+               msg->status = ret;
+               bfin_spi_giveback(drv_data);
+       }
+}
+
+static int bfin_spi_transfer_one_message(struct spi_master *master,
+                                       struct spi_message *m)
+{
+       struct bfin_spi_master *drv_data = spi_master_get_devdata(master);
+
+       drv_data->cur_msg = m;
+       drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi);
+       bfin_spi_restore_state(drv_data);
+
+       drv_data->state = START_STATE;
+       drv_data->cur_transfer = list_entry(drv_data->cur_msg->transfers.next,
+                                           struct spi_transfer, transfer_list);
+
+       tasklet_schedule(&drv_data->pump_transfers);
+       return 0;
+}
+
+#define MAX_SPI_SSEL   7
+
+static const u16 ssel[][MAX_SPI_SSEL] = {
+       {P_SPI0_SSEL1, P_SPI0_SSEL2, P_SPI0_SSEL3,
+       P_SPI0_SSEL4, P_SPI0_SSEL5,
+       P_SPI0_SSEL6, P_SPI0_SSEL7},
+
+       {P_SPI1_SSEL1, P_SPI1_SSEL2, P_SPI1_SSEL3,
+       P_SPI1_SSEL4, P_SPI1_SSEL5,
+       P_SPI1_SSEL6, P_SPI1_SSEL7},
+
+       {P_SPI2_SSEL1, P_SPI2_SSEL2, P_SPI2_SSEL3,
+       P_SPI2_SSEL4, P_SPI2_SSEL5,
+       P_SPI2_SSEL6, P_SPI2_SSEL7},
+};
+
+static int bfin_spi_setup(struct spi_device *spi)
+{
+       struct bfin_spi_master *drv_data = spi_master_get_devdata(spi->master);
+       struct bfin_spi_device *chip = spi_get_ctldata(spi);
+       u32 bfin_ctl_reg = SPI_CTL_ODM | SPI_CTL_PSSE;
+       int ret = -EINVAL;
+
+       if (!chip) {
+               struct bfin_spi3_chip *chip_info = spi->controller_data;
+
+               chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+               if (!chip) {
+                       dev_err(&spi->dev, "can not allocate chip data\n");
+                       return -ENOMEM;
+               }
+               if (chip_info) {
+                       if (chip_info->control & ~bfin_ctl_reg) {
+                               dev_err(&spi->dev,
+                                       "do not set bits that the SPI framework manages\n");
+                               goto error;
+                       }
+                       chip->control = chip_info->control;
+                       chip->cs_chg_udelay = chip_info->cs_chg_udelay;
+                       chip->tx_dummy_val = chip_info->tx_dummy_val;
+                       chip->enable_dma = chip_info->enable_dma;
+               }
+               chip->cs = spi->chip_select;
+               if (chip->cs < MAX_CTRL_CS) {
+                       chip->ssel = (1 << chip->cs) << 8;
+                       ret = peripheral_request(ssel[spi->master->bus_num]
+                                       [chip->cs-1], dev_name(&spi->dev));
+                       if (ret) {
+                               dev_err(&spi->dev, "peripheral_request() error\n");
+                               goto error;
+                       }
+               } else {
+                       chip->cs_gpio = chip->cs - MAX_CTRL_CS;
+                       ret = gpio_request_one(chip->cs_gpio, GPIOF_OUT_INIT_HIGH,
+                                               dev_name(&spi->dev));
+                       if (ret) {
+                               dev_err(&spi->dev, "gpio_request_one() error\n");
+                               goto error;
+                       }
+               }
+               spi_set_ctldata(spi, chip);
+       }
+
+       /* force a default base state */
+       chip->control &= bfin_ctl_reg;
+
+       if (spi->mode & SPI_CPOL)
+               chip->control |= SPI_CTL_CPOL;
+       if (spi->mode & SPI_CPHA)
+               chip->control |= SPI_CTL_CPHA;
+       if (spi->mode & SPI_LSB_FIRST)
+               chip->control |= SPI_CTL_LSBF;
+       chip->control |= SPI_CTL_MSTR;
+       /* we choose software to controll cs */
+       chip->control &= ~SPI_CTL_ASSEL;
+
+       chip->clock = hz_to_spi_clock(drv_data->sclk, spi->max_speed_hz);
+
+       bfin_spi_cs_enable(drv_data, chip);
+       bfin_spi_cs_deactive(drv_data, chip);
+
+       return 0;
+error:
+       if (chip) {
+               kfree(chip);
+               spi_set_ctldata(spi, NULL);
+       }
+
+       return ret;
+}
+
+static void bfin_spi_cleanup(struct spi_device *spi)
+{
+       struct bfin_spi_device *chip = spi_get_ctldata(spi);
+       struct bfin_spi_master *drv_data = spi_master_get_devdata(spi->master);
+
+       if (!chip)
+               return;
+
+       if (chip->cs < MAX_CTRL_CS) {
+               peripheral_free(ssel[spi->master->bus_num]
+                                       [chip->cs-1]);
+               bfin_spi_cs_disable(drv_data, chip);
+       } else {
+               gpio_free(chip->cs_gpio);
+       }
+
+       kfree(chip);
+       spi_set_ctldata(spi, NULL);
+}
+
+static irqreturn_t bfin_spi_tx_dma_isr(int irq, void *dev_id)
+{
+       struct bfin_spi_master *drv_data = dev_id;
+       u32 dma_stat = get_dma_curr_irqstat(drv_data->tx_dma);
+
+       clear_dma_irqstat(drv_data->tx_dma);
+       if (dma_stat & DMA_DONE) {
+               drv_data->tx_num++;
+       } else {
+               dev_err(&drv_data->master->dev,
+                               "spi tx dma error: %d\n", dma_stat);
+               if (drv_data->tx)
+                       drv_data->state = ERROR_STATE;
+       }
+       bfin_write_and(&drv_data->regs->tx_control, ~SPI_TXCTL_TDR_NF);
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t bfin_spi_rx_dma_isr(int irq, void *dev_id)
+{
+       struct bfin_spi_master *drv_data = dev_id;
+       struct spi_message *msg = drv_data->cur_msg;
+       u32 dma_stat = get_dma_curr_irqstat(drv_data->rx_dma);
+
+       clear_dma_irqstat(drv_data->rx_dma);
+       if (dma_stat & DMA_DONE) {
+               drv_data->rx_num++;
+               /* we may fail on tx dma */
+               if (drv_data->state != ERROR_STATE)
+                       msg->actual_length += drv_data->transfer_len;
+       } else {
+               drv_data->state = ERROR_STATE;
+               dev_err(&drv_data->master->dev,
+                               "spi rx dma error: %d\n", dma_stat);
+       }
+       bfin_write(&drv_data->regs->tx_control, 0);
+       bfin_write(&drv_data->regs->rx_control, 0);
+       if (drv_data->rx_num != drv_data->tx_num)
+               dev_dbg(&drv_data->master->dev,
+                               "dma interrupt missing: tx=%d,rx=%d\n",
+                               drv_data->tx_num, drv_data->rx_num);
+       tasklet_schedule(&drv_data->pump_transfers);
+       return IRQ_HANDLED;
+}
+
+static int bfin_spi_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct bfin_spi3_master *info = dev->platform_data;
+       struct spi_master *master;
+       struct bfin_spi_master *drv_data;
+       struct resource *mem, *res;
+       unsigned int tx_dma, rx_dma;
+       unsigned long sclk;
+       int ret;
+
+       if (!info) {
+               dev_err(dev, "platform data missing!\n");
+               return -ENODEV;
+       }
+
+       sclk = get_sclk1();
+       if (!sclk) {
+               dev_err(dev, "can not get sclk1\n");
+               return -ENXIO;
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+       if (!res) {
+               dev_err(dev, "can not get tx dma resource\n");
+               return -ENXIO;
+       }
+       tx_dma = res->start;
+
+       res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+       if (!res) {
+               dev_err(dev, "can not get rx dma resource\n");
+               return -ENXIO;
+       }
+       rx_dma = res->start;
+
+       /* allocate master with space for drv_data */
+       master = spi_alloc_master(dev, sizeof(*drv_data));
+       if (!master) {
+               dev_err(dev, "can not alloc spi_master\n");
+               return -ENOMEM;
+       }
+       platform_set_drvdata(pdev, master);
+
+       /* the mode bits supported by this driver */
+       master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST;
+
+       master->bus_num = pdev->id;
+       master->num_chipselect = info->num_chipselect;
+       master->cleanup = bfin_spi_cleanup;
+       master->setup = bfin_spi_setup;
+       master->transfer_one_message = bfin_spi_transfer_one_message;
+       master->bits_per_word_mask = BIT(32 - 1) | BIT(16 - 1) | BIT(8 - 1);
+
+       drv_data = spi_master_get_devdata(master);
+       drv_data->master = master;
+       drv_data->tx_dma = tx_dma;
+       drv_data->rx_dma = rx_dma;
+       drv_data->pin_req = info->pin_req;
+       drv_data->sclk = sclk;
+
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       drv_data->regs = devm_ioremap_resource(dev, mem);
+       if (IS_ERR(drv_data->regs)) {
+               ret = PTR_ERR(drv_data->regs);
+               goto err_put_master;
+       }
+
+       /* request tx and rx dma */
+       ret = request_dma(tx_dma, "SPI_TX_DMA");
+       if (ret) {
+               dev_err(dev, "can not request SPI TX DMA channel\n");
+               goto err_put_master;
+       }
+       set_dma_callback(tx_dma, bfin_spi_tx_dma_isr, drv_data);
+
+       ret = request_dma(rx_dma, "SPI_RX_DMA");
+       if (ret) {
+               dev_err(dev, "can not request SPI RX DMA channel\n");
+               goto err_free_tx_dma;
+       }
+       set_dma_callback(drv_data->rx_dma, bfin_spi_rx_dma_isr, drv_data);
+
+       /* request CLK, MOSI and MISO */
+       ret = peripheral_request_list(drv_data->pin_req, "bfin-spi3");
+       if (ret < 0) {
+               dev_err(dev, "can not request spi pins\n");
+               goto err_free_rx_dma;
+       }
+
+       bfin_write(&drv_data->regs->control, SPI_CTL_MSTR | SPI_CTL_CPHA);
+       bfin_write(&drv_data->regs->ssel, 0x0000FE00);
+       bfin_write(&drv_data->regs->delay, 0x0);
+
+       tasklet_init(&drv_data->pump_transfers,
+                       bfin_spi_pump_transfers, (unsigned long)drv_data);
+       /* register with the SPI framework */
+       ret = spi_register_master(master);
+       if (ret) {
+               dev_err(dev, "can not  register spi master\n");
+               goto err_free_peripheral;
+       }
+
+       return ret;
+
+err_free_peripheral:
+       peripheral_free_list(drv_data->pin_req);
+err_free_rx_dma:
+       free_dma(rx_dma);
+err_free_tx_dma:
+       free_dma(tx_dma);
+err_put_master:
+       spi_master_put(master);
+
+       return ret;
+}
+
+static int bfin_spi_remove(struct platform_device *pdev)
+{
+       struct spi_master *master = platform_get_drvdata(pdev);
+       struct bfin_spi_master *drv_data = spi_master_get_devdata(master);
+
+       bfin_spi_disable(drv_data);
+
+       peripheral_free_list(drv_data->pin_req);
+       free_dma(drv_data->rx_dma);
+       free_dma(drv_data->tx_dma);
+
+       spi_unregister_master(drv_data->master);
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int bfin_spi_suspend(struct device *dev)
+{
+       struct spi_master *master = dev_get_drvdata(dev);
+       struct bfin_spi_master *drv_data = spi_master_get_devdata(master);
+
+       spi_master_suspend(master);
+
+       drv_data->control = bfin_read(&drv_data->regs->control);
+       drv_data->ssel = bfin_read(&drv_data->regs->ssel);
+
+       bfin_write(&drv_data->regs->control, SPI_CTL_MSTR | SPI_CTL_CPHA);
+       bfin_write(&drv_data->regs->ssel, 0x0000FE00);
+       dma_disable_irq(drv_data->rx_dma);
+       dma_disable_irq(drv_data->tx_dma);
+
+       return 0;
+}
+
+static int bfin_spi_resume(struct device *dev)
+{
+       struct spi_master *master = dev_get_drvdata(dev);
+       struct bfin_spi_master *drv_data = spi_master_get_devdata(master);
+       int ret = 0;
+
+       /* bootrom may modify spi and dma status when resume in spi boot mode */
+       disable_dma(drv_data->rx_dma);
+
+       dma_enable_irq(drv_data->rx_dma);
+       dma_enable_irq(drv_data->tx_dma);
+       bfin_write(&drv_data->regs->control, drv_data->control);
+       bfin_write(&drv_data->regs->ssel, drv_data->ssel);
+
+       ret = spi_master_resume(master);
+       if (ret) {
+               free_dma(drv_data->rx_dma);
+               free_dma(drv_data->tx_dma);
+       }
+
+       return ret;
+}
+#endif
+static const struct dev_pm_ops bfin_spi_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(bfin_spi_suspend, bfin_spi_resume)
+};
+
+MODULE_ALIAS("platform:bfin-spi3");
+static struct platform_driver bfin_spi_driver = {
+       .driver = {
+               .name   = "bfin-spi3",
+               .owner  = THIS_MODULE,
+               .pm     = &bfin_spi_pm_ops,
+       },
+       .remove         = bfin_spi_remove,
+};
+
+module_platform_driver_probe(bfin_spi_driver, bfin_spi_probe);
+
+MODULE_DESCRIPTION("Analog Devices SPI3 controller driver");
+MODULE_AUTHOR("Scott Jiang <Scott.Jiang.Linux@gmail.com>");
+MODULE_LICENSE("GPL v2");
index a63d7da..e3946e4 100644 (file)
@@ -255,150 +255,140 @@ static int spi_bitbang_bufs(struct spi_device *spi, struct spi_transfer *t)
  * Drivers can provide word-at-a-time i/o primitives, or provide
  * transfer-at-a-time ones to leverage dma or fifo hardware.
  */
-static void bitbang_work(struct work_struct *work)
+
+static int spi_bitbang_prepare_hardware(struct spi_master *spi)
 {
-       struct spi_bitbang      *bitbang =
-               container_of(work, struct spi_bitbang, work);
+       struct spi_bitbang      *bitbang;
        unsigned long           flags;
-       struct spi_message      *m, *_m;
+
+       bitbang = spi_master_get_devdata(spi);
 
        spin_lock_irqsave(&bitbang->lock, flags);
        bitbang->busy = 1;
-       list_for_each_entry_safe(m, _m, &bitbang->queue, queue) {
-               struct spi_device       *spi;
-               unsigned                nsecs;
-               struct spi_transfer     *t = NULL;
-               unsigned                tmp;
-               unsigned                cs_change;
-               int                     status;
-               int                     do_setup = -1;
-
-               list_del(&m->queue);
-               spin_unlock_irqrestore(&bitbang->lock, flags);
-
-               /* FIXME this is made-up ... the correct value is known to
-                * word-at-a-time bitbang code, and presumably chipselect()
-                * should enforce these requirements too?
-                */
-               nsecs = 100;
+       spin_unlock_irqrestore(&bitbang->lock, flags);
 
-               spi = m->spi;
-               tmp = 0;
-               cs_change = 1;
-               status = 0;
+       return 0;
+}
 
-               list_for_each_entry (t, &m->transfers, transfer_list) {
-
-                       /* override speed or wordsize? */
-                       if (t->speed_hz || t->bits_per_word)
-                               do_setup = 1;
-
-                       /* init (-1) or override (1) transfer params */
-                       if (do_setup != 0) {
-                               status = bitbang->setup_transfer(spi, t);
-                               if (status < 0)
-                                       break;
-                               if (do_setup == -1)
-                                       do_setup = 0;
-                       }
-
-                       /* set up default clock polarity, and activate chip;
-                        * this implicitly updates clock and spi modes as
-                        * previously recorded for this device via setup().
-                        * (and also deselects any other chip that might be
-                        * selected ...)
-                        */
-                       if (cs_change) {
-                               bitbang->chipselect(spi, BITBANG_CS_ACTIVE);
-                               ndelay(nsecs);
-                       }
-                       cs_change = t->cs_change;
-                       if (!t->tx_buf && !t->rx_buf && t->len) {
-                               status = -EINVAL;
-                               break;
-                       }
+static int spi_bitbang_transfer_one(struct spi_master *master,
+                                   struct spi_message *m)
+{
+       struct spi_bitbang      *bitbang;
+       unsigned                nsecs;
+       struct spi_transfer     *t = NULL;
+       unsigned                cs_change;
+       int                     status;
+       int                     do_setup = -1;
+       struct spi_device       *spi = m->spi;
+
+       bitbang = spi_master_get_devdata(master);
+
+       /* FIXME this is made-up ... the correct value is known to
+        * word-at-a-time bitbang code, and presumably chipselect()
+        * should enforce these requirements too?
+        */
+       nsecs = 100;
 
-                       /* transfer data.  the lower level code handles any
-                        * new dma mappings it needs. our caller always gave
-                        * us dma-safe buffers.
-                        */
-                       if (t->len) {
-                               /* REVISIT dma API still needs a designated
-                                * DMA_ADDR_INVALID; ~0 might be better.
-                                */
-                               if (!m->is_dma_mapped)
-                                       t->rx_dma = t->tx_dma = 0;
-                               status = bitbang->txrx_bufs(spi, t);
-                       }
-                       if (status > 0)
-                               m->actual_length += status;
-                       if (status != t->len) {
-                               /* always report some kind of error */
-                               if (status >= 0)
-                                       status = -EREMOTEIO;
+       cs_change = 1;
+       status = 0;
+
+       list_for_each_entry (t, &m->transfers, transfer_list) {
+
+               /* override speed or wordsize? */
+               if (t->speed_hz || t->bits_per_word)
+                       do_setup = 1;
+
+               /* init (-1) or override (1) transfer params */
+               if (do_setup != 0) {
+                       status = bitbang->setup_transfer(spi, t);
+                       if (status < 0)
                                break;
-                       }
-                       status = 0;
-
-                       /* protocol tweaks before next transfer */
-                       if (t->delay_usecs)
-                               udelay(t->delay_usecs);
-
-                       if (cs_change && !list_is_last(&t->transfer_list, &m->transfers)) {
-                               /* sometimes a short mid-message deselect of the chip
-                                * may be needed to terminate a mode or command
-                                */
-                               ndelay(nsecs);
-                               bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
-                               ndelay(nsecs);
-                       }
+                       if (do_setup == -1)
+                               do_setup = 0;
                }
 
-               m->status = status;
-               m->complete(m->context);
+               /* set up default clock polarity, and activate chip;
+                * this implicitly updates clock and spi modes as
+                * previously recorded for this device via setup().
+                * (and also deselects any other chip that might be
+                * selected ...)
+                */
+               if (cs_change) {
+                       bitbang->chipselect(spi, BITBANG_CS_ACTIVE);
+                       ndelay(nsecs);
+               }
+               cs_change = t->cs_change;
+               if (!t->tx_buf && !t->rx_buf && t->len) {
+                       status = -EINVAL;
+                       break;
+               }
 
-               /* normally deactivate chipselect ... unless no error and
-                * cs_change has hinted that the next message will probably
-                * be for this chip too.
+               /* transfer data.  the lower level code handles any
+                * new dma mappings it needs. our caller always gave
+                * us dma-safe buffers.
                 */
-               if (!(status == 0 && cs_change)) {
+               if (t->len) {
+                       /* REVISIT dma API still needs a designated
+                        * DMA_ADDR_INVALID; ~0 might be better.
+                        */
+                       if (!m->is_dma_mapped)
+                               t->rx_dma = t->tx_dma = 0;
+                       status = bitbang->txrx_bufs(spi, t);
+               }
+               if (status > 0)
+                       m->actual_length += status;
+               if (status != t->len) {
+                       /* always report some kind of error */
+                       if (status >= 0)
+                               status = -EREMOTEIO;
+                       break;
+               }
+               status = 0;
+
+               /* protocol tweaks before next transfer */
+               if (t->delay_usecs)
+                       udelay(t->delay_usecs);
+
+               if (cs_change && !list_is_last(&t->transfer_list, &m->transfers)) {
+                       /* sometimes a short mid-message deselect of the chip
+                        * may be needed to terminate a mode or command
+                        */
                        ndelay(nsecs);
                        bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
                        ndelay(nsecs);
                }
+       }
+
+       m->status = status;
 
-               spin_lock_irqsave(&bitbang->lock, flags);
+       /* normally deactivate chipselect ... unless no error and
+        * cs_change has hinted that the next message will probably
+        * be for this chip too.
+        */
+       if (!(status == 0 && cs_change)) {
+               ndelay(nsecs);
+               bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
+               ndelay(nsecs);
        }
-       bitbang->busy = 0;
-       spin_unlock_irqrestore(&bitbang->lock, flags);
+
+       spi_finalize_current_message(master);
+
+       return status;
 }
 
-/**
- * spi_bitbang_transfer - default submit to transfer queue
- */
-int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m)
+static int spi_bitbang_unprepare_hardware(struct spi_master *spi)
 {
-       struct spi_bitbang      *bitbang;
+       struct spi_bitbang      *bitbang;
        unsigned long           flags;
-       int                     status = 0;
 
-       m->actual_length = 0;
-       m->status = -EINPROGRESS;
-
-       bitbang = spi_master_get_devdata(spi->master);
+       bitbang = spi_master_get_devdata(spi);
 
        spin_lock_irqsave(&bitbang->lock, flags);
-       if (!spi->max_speed_hz)
-               status = -ENETDOWN;
-       else {
-               list_add_tail(&m->queue, &bitbang->queue);
-               queue_work(bitbang->workqueue, &bitbang->work);
-       }
+       bitbang->busy = 0;
        spin_unlock_irqrestore(&bitbang->lock, flags);
 
-       return status;
+       return 0;
 }
-EXPORT_SYMBOL_GPL(spi_bitbang_transfer);
 
 /*----------------------------------------------------------------------*/
 
@@ -428,20 +418,22 @@ EXPORT_SYMBOL_GPL(spi_bitbang_transfer);
 int spi_bitbang_start(struct spi_bitbang *bitbang)
 {
        struct spi_master *master = bitbang->master;
-       int status;
 
        if (!master || !bitbang->chipselect)
                return -EINVAL;
 
-       INIT_WORK(&bitbang->work, bitbang_work);
        spin_lock_init(&bitbang->lock);
-       INIT_LIST_HEAD(&bitbang->queue);
 
        if (!master->mode_bits)
                master->mode_bits = SPI_CPOL | SPI_CPHA | bitbang->flags;
 
-       if (!master->transfer)
-               master->transfer = spi_bitbang_transfer;
+       if (master->transfer || master->transfer_one_message)
+               return -EINVAL;
+
+       master->prepare_transfer_hardware = spi_bitbang_prepare_hardware;
+       master->unprepare_transfer_hardware = spi_bitbang_unprepare_hardware;
+       master->transfer_one_message = spi_bitbang_transfer_one;
+
        if (!bitbang->txrx_bufs) {
                bitbang->use_dma = 0;
                bitbang->txrx_bufs = spi_bitbang_bufs;
@@ -452,34 +444,12 @@ int spi_bitbang_start(struct spi_bitbang *bitbang)
                        master->setup = spi_bitbang_setup;
                        master->cleanup = spi_bitbang_cleanup;
                }
-       } else if (!master->setup)
-               return -EINVAL;
-       if (master->transfer == spi_bitbang_transfer &&
-                       !bitbang->setup_transfer)
-               return -EINVAL;
-
-       /* this task is the only thing to touch the SPI bits */
-       bitbang->busy = 0;
-       bitbang->workqueue = create_singlethread_workqueue(
-                       dev_name(master->dev.parent));
-       if (bitbang->workqueue == NULL) {
-               status = -EBUSY;
-               goto err1;
        }
 
        /* driver may get busy before register() returns, especially
         * if someone registered boardinfo for devices
         */
-       status = spi_register_master(master);
-       if (status < 0)
-               goto err2;
-
-       return status;
-
-err2:
-       destroy_workqueue(bitbang->workqueue);
-err1:
-       return status;
+       return spi_register_master(master);
 }
 EXPORT_SYMBOL_GPL(spi_bitbang_start);
 
@@ -490,10 +460,6 @@ int spi_bitbang_stop(struct spi_bitbang *bitbang)
 {
        spi_unregister_master(bitbang->master);
 
-       WARN_ON(!list_empty(&bitbang->queue));
-
-       destroy_workqueue(bitbang->workqueue);
-
        return 0;
 }
 EXPORT_SYMBOL_GPL(spi_bitbang_stop);
index 17965fe..5655acf 100644 (file)
@@ -239,11 +239,8 @@ static int spi_clps711x_probe(struct platform_device *pdev)
        }
 
        dev_err(&pdev->dev, "Failed to register master\n");
-       devm_free_irq(&pdev->dev, IRQ_SSEOTI, hw);
 
 clk_out:
-       devm_clk_put(&pdev->dev, hw->spi_clk);
-
 err_out:
        while (--i >= 0)
                if (gpio_is_valid(hw->chipselect[i]))
@@ -261,13 +258,10 @@ static int spi_clps711x_remove(struct platform_device *pdev)
        struct spi_master *master = platform_get_drvdata(pdev);
        struct spi_clps711x_data *hw = spi_master_get_devdata(master);
 
-       devm_free_irq(&pdev->dev, IRQ_SSEOTI, hw);
-
        for (i = 0; i < master->num_chipselect; i++)
                if (gpio_is_valid(hw->chipselect[i]))
                        gpio_free(hw->chipselect[i]);
 
-       devm_clk_put(&pdev->dev, hw->spi_clk);
        spi_unregister_master(master);
        kfree(master);
 
diff --git a/drivers/spi/spi-efm32.c b/drivers/spi/spi-efm32.c
new file mode 100644 (file)
index 0000000..7d84418
--- /dev/null
@@ -0,0 +1,516 @@
+/*
+ * Copyright (C) 2012-2013 Uwe Kleine-Koenig for Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_data/efm32-spi.h>
+
+#define DRIVER_NAME "efm32-spi"
+
+#define MASK_VAL(mask, val)            ((val << __ffs(mask)) & mask)
+
+#define REG_CTRL               0x00
+#define REG_CTRL_SYNC                  0x0001
+#define REG_CTRL_CLKPOL                        0x0100
+#define REG_CTRL_CLKPHA                        0x0200
+#define REG_CTRL_MSBF                  0x0400
+#define REG_CTRL_TXBIL                 0x1000
+
+#define REG_FRAME              0x04
+#define REG_FRAME_DATABITS__MASK       0x000f
+#define REG_FRAME_DATABITS(n)          ((n) - 3)
+
+#define REG_CMD                        0x0c
+#define REG_CMD_RXEN                   0x0001
+#define REG_CMD_RXDIS                  0x0002
+#define REG_CMD_TXEN                   0x0004
+#define REG_CMD_TXDIS                  0x0008
+#define REG_CMD_MASTEREN               0x0010
+
+#define REG_STATUS             0x10
+#define REG_STATUS_TXENS               0x0002
+#define REG_STATUS_TXC                 0x0020
+#define REG_STATUS_TXBL                        0x0040
+#define REG_STATUS_RXDATAV             0x0080
+
+#define REG_CLKDIV             0x14
+
+#define REG_RXDATAX            0x18
+#define REG_RXDATAX_RXDATA__MASK       0x01ff
+#define REG_RXDATAX_PERR               0x4000
+#define REG_RXDATAX_FERR               0x8000
+
+#define REG_TXDATA             0x34
+
+#define REG_IF         0x40
+#define REG_IF_TXBL                    0x0002
+#define REG_IF_RXDATAV                 0x0004
+
+#define REG_IFS                0x44
+#define REG_IFC                0x48
+#define REG_IEN                0x4c
+
+#define REG_ROUTE              0x54
+#define REG_ROUTE_RXPEN                        0x0001
+#define REG_ROUTE_TXPEN                        0x0002
+#define REG_ROUTE_CLKPEN               0x0008
+#define REG_ROUTE_LOCATION__MASK       0x0700
+#define REG_ROUTE_LOCATION(n)          MASK_VAL(REG_ROUTE_LOCATION__MASK, (n))
+
+struct efm32_spi_ddata {
+       struct spi_bitbang bitbang;
+
+       spinlock_t lock;
+
+       struct clk *clk;
+       void __iomem *base;
+       unsigned int rxirq, txirq;
+       struct efm32_spi_pdata pdata;
+
+       /* irq data */
+       struct completion done;
+       const u8 *tx_buf;
+       u8 *rx_buf;
+       unsigned tx_len, rx_len;
+
+       /* chip selects */
+       unsigned csgpio[];
+};
+
+#define ddata_to_dev(ddata)    (&(ddata->bitbang.master->dev))
+#define efm32_spi_vdbg(ddata, format, arg...)  \
+       dev_vdbg(ddata_to_dev(ddata), format, ##arg)
+
+static void efm32_spi_write32(struct efm32_spi_ddata *ddata,
+               u32 value, unsigned offset)
+{
+       writel_relaxed(value, ddata->base + offset);
+}
+
+static u32 efm32_spi_read32(struct efm32_spi_ddata *ddata, unsigned offset)
+{
+       return readl_relaxed(ddata->base + offset);
+}
+
+static void efm32_spi_chipselect(struct spi_device *spi, int is_on)
+{
+       struct efm32_spi_ddata *ddata = spi_master_get_devdata(spi->master);
+       int value = !(spi->mode & SPI_CS_HIGH) == !(is_on == BITBANG_CS_ACTIVE);
+
+       gpio_set_value(ddata->csgpio[spi->chip_select], value);
+}
+
+static int efm32_spi_setup_transfer(struct spi_device *spi,
+               struct spi_transfer *t)
+{
+       struct efm32_spi_ddata *ddata = spi_master_get_devdata(spi->master);
+
+       unsigned bpw = t->bits_per_word ?: spi->bits_per_word;
+       unsigned speed = t->speed_hz ?: spi->max_speed_hz;
+       unsigned long clkfreq = clk_get_rate(ddata->clk);
+       u32 clkdiv;
+
+       efm32_spi_write32(ddata, REG_CTRL_SYNC | REG_CTRL_MSBF |
+                       (spi->mode & SPI_CPHA ? REG_CTRL_CLKPHA : 0) |
+                       (spi->mode & SPI_CPOL ? REG_CTRL_CLKPOL : 0), REG_CTRL);
+
+       efm32_spi_write32(ddata,
+                       REG_FRAME_DATABITS(bpw), REG_FRAME);
+
+       if (2 * speed >= clkfreq)
+               clkdiv = 0;
+       else
+               clkdiv = 64 * (DIV_ROUND_UP(2 * clkfreq, speed) - 4);
+
+       if (clkdiv > (1U << 21))
+               return -EINVAL;
+
+       efm32_spi_write32(ddata, clkdiv, REG_CLKDIV);
+       efm32_spi_write32(ddata, REG_CMD_MASTEREN, REG_CMD);
+       efm32_spi_write32(ddata, REG_CMD_RXEN | REG_CMD_TXEN, REG_CMD);
+
+       return 0;
+}
+
+static void efm32_spi_tx_u8(struct efm32_spi_ddata *ddata)
+{
+       u8 val = 0;
+
+       if (ddata->tx_buf) {
+               val = *ddata->tx_buf;
+               ddata->tx_buf++;
+       }
+
+       ddata->tx_len--;
+       efm32_spi_write32(ddata, val, REG_TXDATA);
+       efm32_spi_vdbg(ddata, "%s: tx 0x%x\n", __func__, val);
+}
+
+static void efm32_spi_rx_u8(struct efm32_spi_ddata *ddata)
+{
+       u32 rxdata = efm32_spi_read32(ddata, REG_RXDATAX);
+       efm32_spi_vdbg(ddata, "%s: rx 0x%x\n", __func__, rxdata);
+
+       if (ddata->rx_buf) {
+               *ddata->rx_buf = rxdata;
+               ddata->rx_buf++;
+       }
+
+       ddata->rx_len--;
+}
+
+static void efm32_spi_filltx(struct efm32_spi_ddata *ddata)
+{
+       while (ddata->tx_len &&
+                       ddata->tx_len + 2 > ddata->rx_len &&
+                       efm32_spi_read32(ddata, REG_STATUS) & REG_STATUS_TXBL) {
+               efm32_spi_tx_u8(ddata);
+       }
+}
+
+static int efm32_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
+{
+       struct efm32_spi_ddata *ddata = spi_master_get_devdata(spi->master);
+       int ret = -EBUSY;
+
+       spin_lock_irq(&ddata->lock);
+
+       if (ddata->tx_buf || ddata->rx_buf)
+               goto out_unlock;
+
+       ddata->tx_buf = t->tx_buf;
+       ddata->rx_buf = t->rx_buf;
+       ddata->tx_len = ddata->rx_len =
+               t->len * DIV_ROUND_UP(t->bits_per_word, 8);
+
+       efm32_spi_filltx(ddata);
+
+       init_completion(&ddata->done);
+
+       efm32_spi_write32(ddata, REG_IF_TXBL | REG_IF_RXDATAV, REG_IEN);
+
+       spin_unlock_irq(&ddata->lock);
+
+       wait_for_completion(&ddata->done);
+
+       spin_lock_irq(&ddata->lock);
+
+       ret = t->len - max(ddata->tx_len, ddata->rx_len);
+
+       efm32_spi_write32(ddata, 0, REG_IEN);
+       ddata->tx_buf = ddata->rx_buf = NULL;
+
+out_unlock:
+       spin_unlock_irq(&ddata->lock);
+
+       return ret;
+}
+
+static irqreturn_t efm32_spi_rxirq(int irq, void *data)
+{
+       struct efm32_spi_ddata *ddata = data;
+       irqreturn_t ret = IRQ_NONE;
+
+       spin_lock(&ddata->lock);
+
+       while (ddata->rx_len > 0 &&
+                       efm32_spi_read32(ddata, REG_STATUS) &
+                       REG_STATUS_RXDATAV) {
+               efm32_spi_rx_u8(ddata);
+
+               ret = IRQ_HANDLED;
+       }
+
+       if (!ddata->rx_len) {
+               u32 ien = efm32_spi_read32(ddata, REG_IEN);
+
+               ien &= ~REG_IF_RXDATAV;
+
+               efm32_spi_write32(ddata, ien, REG_IEN);
+
+               complete(&ddata->done);
+       }
+
+       spin_unlock(&ddata->lock);
+
+       return ret;
+}
+
+static irqreturn_t efm32_spi_txirq(int irq, void *data)
+{
+       struct efm32_spi_ddata *ddata = data;
+
+       efm32_spi_vdbg(ddata,
+                       "%s: txlen = %u, rxlen = %u, if=0x%08x, stat=0x%08x\n",
+                       __func__, ddata->tx_len, ddata->rx_len,
+                       efm32_spi_read32(ddata, REG_IF),
+                       efm32_spi_read32(ddata, REG_STATUS));
+
+       spin_lock(&ddata->lock);
+
+       efm32_spi_filltx(ddata);
+
+       efm32_spi_vdbg(ddata, "%s: txlen = %u, rxlen = %u\n",
+                       __func__, ddata->tx_len, ddata->rx_len);
+
+       if (!ddata->tx_len) {
+               u32 ien = efm32_spi_read32(ddata, REG_IEN);
+
+               ien &= ~REG_IF_TXBL;
+
+               efm32_spi_write32(ddata, ien, REG_IEN);
+               efm32_spi_vdbg(ddata, "disable TXBL\n");
+       }
+
+       spin_unlock(&ddata->lock);
+
+       return IRQ_HANDLED;
+}
+
+static const struct efm32_spi_pdata efm32_spi_pdata_default = {
+       .location = 1,
+};
+
+static u32 efm32_spi_get_configured_location(struct efm32_spi_ddata *ddata)
+{
+       u32 reg = efm32_spi_read32(ddata, REG_ROUTE);
+
+       return (reg & REG_ROUTE_LOCATION__MASK) >> __ffs(REG_ROUTE_LOCATION__MASK);
+}
+
+static int efm32_spi_probe_dt(struct platform_device *pdev,
+               struct spi_master *master, struct efm32_spi_ddata *ddata)
+{
+       struct device_node *np = pdev->dev.of_node;
+       u32 location;
+       int ret;
+
+       if (!np)
+               return 1;
+
+       ret = of_property_read_u32(np, "location", &location);
+       if (!ret) {
+               dev_dbg(&pdev->dev, "using location %u\n", location);
+       } else {
+               /* default to location configured in hardware */
+               location = efm32_spi_get_configured_location(ddata);
+
+               dev_info(&pdev->dev, "fall back to location %u\n", location);
+       }
+
+       ddata->pdata.location = location;
+
+       /* spi core takes care about the bus number using an alias */
+       master->bus_num = -1;
+
+       return 0;
+}
+
+static int efm32_spi_probe(struct platform_device *pdev)
+{
+       struct efm32_spi_ddata *ddata;
+       struct resource *res;
+       int ret;
+       struct spi_master *master;
+       struct device_node *np = pdev->dev.of_node;
+       unsigned int num_cs, i;
+
+       num_cs = of_gpio_named_count(np, "cs-gpios");
+
+       master = spi_alloc_master(&pdev->dev,
+                       sizeof(*ddata) + num_cs * sizeof(unsigned));
+       if (!master) {
+               dev_dbg(&pdev->dev,
+                               "failed to allocate spi master controller\n");
+               return -ENOMEM;
+       }
+       platform_set_drvdata(pdev, master);
+
+       master->dev.of_node = pdev->dev.of_node;
+
+       master->num_chipselect = num_cs;
+       master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
+       master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16);
+
+       ddata = spi_master_get_devdata(master);
+
+       ddata->bitbang.master = spi_master_get(master);
+       ddata->bitbang.chipselect = efm32_spi_chipselect;
+       ddata->bitbang.setup_transfer = efm32_spi_setup_transfer;
+       ddata->bitbang.txrx_bufs = efm32_spi_txrx_bufs;
+
+       spin_lock_init(&ddata->lock);
+
+       ddata->clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(ddata->clk)) {
+               ret = PTR_ERR(ddata->clk);
+               dev_err(&pdev->dev, "failed to get clock: %d\n", ret);
+               goto err;
+       }
+
+       for (i = 0; i < num_cs; ++i) {
+               ret = of_get_named_gpio(np, "cs-gpios", i);
+               if (ret < 0) {
+                       dev_err(&pdev->dev, "failed to get csgpio#%u (%d)\n",
+                                       i, ret);
+                       goto err;
+               }
+               ddata->csgpio[i] = ret;
+               dev_dbg(&pdev->dev, "csgpio#%u = %u\n", i, ddata->csgpio[i]);
+               ret = devm_gpio_request_one(&pdev->dev, ddata->csgpio[i],
+                               GPIOF_OUT_INIT_LOW, DRIVER_NAME);
+               if (ret < 0) {
+                       dev_err(&pdev->dev,
+                                       "failed to configure csgpio#%u (%d)\n",
+                                       i, ret);
+                       goto err;
+               }
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               ret = -ENODEV;
+               dev_err(&pdev->dev, "failed to determine base address\n");
+               goto err;
+       }
+
+       if (resource_size(res) < 60) {
+               ret = -EINVAL;
+               dev_err(&pdev->dev, "memory resource too small\n");
+               goto err;
+       }
+
+       ddata->base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(ddata->base)) {
+               ret = PTR_ERR(ddata->base);
+               goto err;
+       }
+
+       ret = platform_get_irq(pdev, 0);
+       if (ret <= 0) {
+               dev_err(&pdev->dev, "failed to get rx irq (%d)\n", ret);
+               goto err;
+       }
+
+       ddata->rxirq = ret;
+
+       ret = platform_get_irq(pdev, 1);
+       if (ret <= 0)
+               ret = ddata->rxirq + 1;
+
+       ddata->txirq = ret;
+
+       ret = clk_prepare_enable(ddata->clk);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "failed to enable clock (%d)\n", ret);
+               goto err;
+       }
+
+       ret = efm32_spi_probe_dt(pdev, master, ddata);
+       if (ret > 0) {
+               /* not created by device tree */
+               const struct efm32_spi_pdata *pdata =
+                       dev_get_platdata(&pdev->dev);
+
+               if (pdata)
+                       ddata->pdata = *pdata;
+               else
+                       ddata->pdata.location =
+                               efm32_spi_get_configured_location(ddata);
+
+               master->bus_num = pdev->id;
+
+       } else if (ret < 0) {
+               goto err_disable_clk;
+       }
+
+       efm32_spi_write32(ddata, 0, REG_IEN);
+       efm32_spi_write32(ddata, REG_ROUTE_TXPEN | REG_ROUTE_RXPEN |
+                       REG_ROUTE_CLKPEN |
+                       REG_ROUTE_LOCATION(ddata->pdata.location), REG_ROUTE);
+
+       ret = request_irq(ddata->rxirq, efm32_spi_rxirq,
+                       0, DRIVER_NAME " rx", ddata);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to register rxirq (%d)\n", ret);
+               goto err_disable_clk;
+       }
+
+       ret = request_irq(ddata->txirq, efm32_spi_txirq,
+                       0, DRIVER_NAME " tx", ddata);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to register txirq (%d)\n", ret);
+               goto err_free_rx_irq;
+       }
+
+       ret = spi_bitbang_start(&ddata->bitbang);
+       if (ret) {
+               dev_err(&pdev->dev, "spi_bitbang_start failed (%d)\n", ret);
+
+               free_irq(ddata->txirq, ddata);
+err_free_rx_irq:
+               free_irq(ddata->rxirq, ddata);
+err_disable_clk:
+               clk_disable_unprepare(ddata->clk);
+err:
+               spi_master_put(master);
+               kfree(master);
+       }
+
+       return ret;
+}
+
+static int efm32_spi_remove(struct platform_device *pdev)
+{
+       struct spi_master *master = platform_get_drvdata(pdev);
+       struct efm32_spi_ddata *ddata = spi_master_get_devdata(master);
+
+       efm32_spi_write32(ddata, 0, REG_IEN);
+
+       free_irq(ddata->txirq, ddata);
+       free_irq(ddata->rxirq, ddata);
+       clk_disable_unprepare(ddata->clk);
+       spi_master_put(master);
+       kfree(master);
+
+       return 0;
+}
+
+static const struct of_device_id efm32_spi_dt_ids[] = {
+       {
+               .compatible = "efm32,spi",
+       }, {
+               /* sentinel */
+       }
+};
+MODULE_DEVICE_TABLE(of, efm32_spi_dt_ids);
+
+static struct platform_driver efm32_spi_driver = {
+       .probe = efm32_spi_probe,
+       .remove = efm32_spi_remove,
+
+       .driver = {
+               .name = DRIVER_NAME,
+               .owner = THIS_MODULE,
+               .of_match_table = efm32_spi_dt_ids,
+       },
+};
+module_platform_driver(efm32_spi_driver);
+
+MODULE_AUTHOR("Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>");
+MODULE_DESCRIPTION("EFM32 SPI driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRIVER_NAME);
index cad30b8..31611f7 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
-#include <linux/workqueue.h>
 #include <linux/sched.h>
 #include <linux/scatterlist.h>
 #include <linux/spi/spi.h>
 
 /**
  * struct ep93xx_spi - EP93xx SPI controller structure
- * @lock: spinlock that protects concurrent accesses to fields @running,
- *        @current_msg and @msg_queue
  * @pdev: pointer to platform device
  * @clk: clock for the controller
  * @regs_base: pointer to ioremap()'d registers
  * @sspdr_phys: physical address of the SSPDR register
  * @min_rate: minimum clock rate (in Hz) supported by the controller
  * @max_rate: maximum clock rate (in Hz) supported by the controller
- * @running: is the queue running
- * @wq: workqueue used by the driver
- * @msg_work: work that is queued for the driver
  * @wait: wait here until given transfer is completed
- * @msg_queue: queue for the messages
  * @current_msg: message that is currently processed (or %NULL if none)
  * @tx: current byte in transfer to transmit
  * @rx: current byte in transfer to receive
  * @tx_sgt: sg table for TX transfers
  * @zeropage: dummy page used as RX buffer when only TX buffer is passed in by
  *            the client
- *
- * This structure holds EP93xx SPI controller specific information. When
- * @running is %true, driver accepts transfer requests from protocol drivers.
- * @current_msg is used to hold pointer to the message that is currently
- * processed. If @current_msg is %NULL, it means that no processing is going
- * on.
- *
- * Most of the fields are only written once and they can be accessed without
- * taking the @lock. Fields that are accessed concurrently are: @current_msg,
- * @running, and @msg_queue.
  */
 struct ep93xx_spi {
-       spinlock_t                      lock;
        const struct platform_device    *pdev;
        struct clk                      *clk;
        void __iomem                    *regs_base;
        unsigned long                   sspdr_phys;
        unsigned long                   min_rate;
        unsigned long                   max_rate;
-       bool                            running;
-       struct workqueue_struct         *wq;
-       struct work_struct              msg_work;
        struct completion               wait;
-       struct list_head                msg_queue;
        struct spi_message              *current_msg;
        size_t                          tx;
        size_t                          rx;
@@ -136,50 +114,36 @@ struct ep93xx_spi {
 /**
  * struct ep93xx_spi_chip - SPI device hardware settings
  * @spi: back pointer to the SPI device
- * @rate: max rate in hz this chip supports
- * @div_cpsr: cpsr (pre-scaler) divider
- * @div_scr: scr divider
- * @dss: bits per word (4 - 16 bits)
  * @ops: private chip operations
- *
- * This structure is used to store hardware register specific settings for each
- * SPI device. Settings are written to hardware by function
- * ep93xx_spi_chip_setup().
  */
 struct ep93xx_spi_chip {
        const struct spi_device         *spi;
-       unsigned long                   rate;
-       u8                              div_cpsr;
-       u8                              div_scr;
-       u8                              dss;
        struct ep93xx_spi_chip_ops      *ops;
 };
 
 /* converts bits per word to CR0.DSS value */
 #define bits_per_word_to_dss(bpw)      ((bpw) - 1)
 
-static inline void
-ep93xx_spi_write_u8(const struct ep93xx_spi *espi, u16 reg, u8 value)
+static void ep93xx_spi_write_u8(const struct ep93xx_spi *espi,
+                               u16 reg, u8 value)
 {
-       __raw_writeb(value, espi->regs_base + reg);
+       writeb(value, espi->regs_base + reg);
 }
 
-static inline u8
-ep93xx_spi_read_u8(const struct ep93xx_spi *spi, u16 reg)
+static u8 ep93xx_spi_read_u8(const struct ep93xx_spi *spi, u16 reg)
 {
-       return __raw_readb(spi->regs_base + reg);
+       return readb(spi->regs_base + reg);
 }
 
-static inline void
-ep93xx_spi_write_u16(const struct ep93xx_spi *espi, u16 reg, u16 value)
+static void ep93xx_spi_write_u16(const struct ep93xx_spi *espi,
+                                u16 reg, u16 value)
 {
-       __raw_writew(value, espi->regs_base + reg);
+       writew(value, espi->regs_base + reg);
 }
 
-static inline u16
-ep93xx_spi_read_u16(const struct ep93xx_spi *spi, u16 reg)
+static u16 ep93xx_spi_read_u16(const struct ep93xx_spi *spi, u16 reg)
 {
-       return __raw_readw(spi->regs_base + reg);
+       return readw(spi->regs_base + reg);
 }
 
 static int ep93xx_spi_enable(const struct ep93xx_spi *espi)
@@ -230,17 +194,13 @@ static void ep93xx_spi_disable_interrupts(const struct ep93xx_spi *espi)
 /**
  * ep93xx_spi_calc_divisors() - calculates SPI clock divisors
  * @espi: ep93xx SPI controller struct
- * @chip: divisors are calculated for this chip
  * @rate: desired SPI output clock rate
- *
- * Function calculates cpsr (clock pre-scaler) and scr divisors based on
- * given @rate and places them to @chip->div_cpsr and @chip->div_scr. If,
- * for some reason, divisors cannot be calculated nothing is stored and
- * %-EINVAL is returned.
+ * @div_cpsr: pointer to return the cpsr (pre-scaler) divider
+ * @div_scr: pointer to return the scr divider
  */
 static int ep93xx_spi_calc_divisors(const struct ep93xx_spi *espi,
-                                   struct ep93xx_spi_chip *chip,
-                                   unsigned long rate)
+                                   unsigned long rate,
+                                   u8 *div_cpsr, u8 *div_scr)
 {
        unsigned long spi_clk_rate = clk_get_rate(espi->clk);
        int cpsr, scr;
@@ -248,7 +208,7 @@ static int ep93xx_spi_calc_divisors(const struct ep93xx_spi *espi,
        /*
         * Make sure that max value is between values supported by the
         * controller. Note that minimum value is already checked in
-        * ep93xx_spi_transfer().
+        * ep93xx_spi_transfer_one_message().
         */
        rate = clamp(rate, espi->min_rate, espi->max_rate);
 
@@ -263,8 +223,8 @@ static int ep93xx_spi_calc_divisors(const struct ep93xx_spi *espi,
        for (cpsr = 2; cpsr <= 254; cpsr += 2) {
                for (scr = 0; scr <= 255; scr++) {
                        if ((spi_clk_rate / (cpsr * (scr + 1))) <= rate) {
-                               chip->div_scr = (u8)scr;
-                               chip->div_cpsr = (u8)cpsr;
+                               *div_scr = (u8)scr;
+                               *div_cpsr = (u8)cpsr;
                                return 0;
                        }
                }
@@ -319,73 +279,11 @@ static int ep93xx_spi_setup(struct spi_device *spi)
                spi_set_ctldata(spi, chip);
        }
 
-       if (spi->max_speed_hz != chip->rate) {
-               int err;
-
-               err = ep93xx_spi_calc_divisors(espi, chip, spi->max_speed_hz);
-               if (err != 0) {
-                       spi_set_ctldata(spi, NULL);
-                       kfree(chip);
-                       return err;
-               }
-               chip->rate = spi->max_speed_hz;
-       }
-
-       chip->dss = bits_per_word_to_dss(spi->bits_per_word);
-
        ep93xx_spi_cs_control(spi, false);
        return 0;
 }
 
 /**
- * ep93xx_spi_transfer() - queue message to be transferred
- * @spi: target SPI device
- * @msg: message to be transferred
- *
- * This function is called by SPI device drivers when they are going to transfer
- * a new message. It simply puts the message in the queue and schedules
- * workqueue to perform the actual transfer later on.
- *
- * Returns %0 on success and negative error in case of failure.
- */
-static int ep93xx_spi_transfer(struct spi_device *spi, struct spi_message *msg)
-{
-       struct ep93xx_spi *espi = spi_master_get_devdata(spi->master);
-       struct spi_transfer *t;
-       unsigned long flags;
-
-       if (!msg || !msg->complete)
-               return -EINVAL;
-
-       /* first validate each transfer */
-       list_for_each_entry(t, &msg->transfers, transfer_list) {
-               if (t->speed_hz && t->speed_hz < espi->min_rate)
-                               return -EINVAL;
-       }
-
-       /*
-        * Now that we own the message, let's initialize it so that it is
-        * suitable for us. We use @msg->status to signal whether there was
-        * error in transfer and @msg->state is used to hold pointer to the
-        * current transfer (or %NULL if no active current transfer).
-        */
-       msg->state = NULL;
-       msg->status = 0;
-       msg->actual_length = 0;
-
-       spin_lock_irqsave(&espi->lock, flags);
-       if (!espi->running) {
-               spin_unlock_irqrestore(&espi->lock, flags);
-               return -ESHUTDOWN;
-       }
-       list_add_tail(&msg->queue, &espi->msg_queue);
-       queue_work(espi->wq, &espi->msg_work);
-       spin_unlock_irqrestore(&espi->lock, flags);
-
-       return 0;
-}
-
-/**
  * ep93xx_spi_cleanup() - cleans up master controller specific state
  * @spi: SPI device to cleanup
  *
@@ -409,39 +307,40 @@ static void ep93xx_spi_cleanup(struct spi_device *spi)
  * ep93xx_spi_chip_setup() - configures hardware according to given @chip
  * @espi: ep93xx SPI controller struct
  * @chip: chip specific settings
- *
- * This function sets up the actual hardware registers with settings given in
- * @chip. Note that no validation is done so make sure that callers validate
- * settings before calling this.
+ * @speed_hz: transfer speed
+ * @bits_per_word: transfer bits_per_word
  */
-static void ep93xx_spi_chip_setup(const struct ep93xx_spi *espi,
-                                 const struct ep93xx_spi_chip *chip)
+static int ep93xx_spi_chip_setup(const struct ep93xx_spi *espi,
+                                const struct ep93xx_spi_chip *chip,
+                                u32 speed_hz, u8 bits_per_word)
 {
+       u8 dss = bits_per_word_to_dss(bits_per_word);
+       u8 div_cpsr = 0;
+       u8 div_scr = 0;
        u16 cr0;
+       int err;
 
-       cr0 = chip->div_scr << SSPCR0_SCR_SHIFT;
+       err = ep93xx_spi_calc_divisors(espi, speed_hz, &div_cpsr, &div_scr);
+       if (err)
+               return err;
+
+       cr0 = div_scr << SSPCR0_SCR_SHIFT;
        cr0 |= (chip->spi->mode & (SPI_CPHA|SPI_CPOL)) << SSPCR0_MODE_SHIFT;
-       cr0 |= chip->dss;
+       cr0 |= dss;
 
        dev_dbg(&espi->pdev->dev, "setup: mode %d, cpsr %d, scr %d, dss %d\n",
-               chip->spi->mode, chip->div_cpsr, chip->div_scr, chip->dss);
+               chip->spi->mode, div_cpsr, div_scr, dss);
        dev_dbg(&espi->pdev->dev, "setup: cr0 %#x", cr0);
 
-       ep93xx_spi_write_u8(espi, SSPCPSR, chip->div_cpsr);
+       ep93xx_spi_write_u8(espi, SSPCPSR, div_cpsr);
        ep93xx_spi_write_u16(espi, SSPCR0, cr0);
-}
-
-static inline int bits_per_word(const struct ep93xx_spi *espi)
-{
-       struct spi_message *msg = espi->current_msg;
-       struct spi_transfer *t = msg->state;
 
-       return t->bits_per_word;
+       return 0;
 }
 
 static void ep93xx_do_write(struct ep93xx_spi *espi, struct spi_transfer *t)
 {
-       if (bits_per_word(espi) > 8) {
+       if (t->bits_per_word > 8) {
                u16 tx_val = 0;
 
                if (t->tx_buf)
@@ -460,7 +359,7 @@ static void ep93xx_do_write(struct ep93xx_spi *espi, struct spi_transfer *t)
 
 static void ep93xx_do_read(struct ep93xx_spi *espi, struct spi_transfer *t)
 {
-       if (bits_per_word(espi) > 8) {
+       if (t->bits_per_word > 8) {
                u16 rx_val;
 
                rx_val = ep93xx_spi_read_u16(espi, SSPDR);
@@ -546,7 +445,7 @@ ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_transfer_direction dir)
        size_t len = t->len;
        int i, ret, nents;
 
-       if (bits_per_word(espi) > 8)
+       if (t->bits_per_word > 8)
                buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
        else
                buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE;
@@ -610,7 +509,7 @@ ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_transfer_direction dir)
        }
 
        if (WARN_ON(len)) {
-               dev_warn(&espi->pdev->dev, "len = %d expected 0!", len);
+               dev_warn(&espi->pdev->dev, "len = %zu expected 0!", len);
                return ERR_PTR(-EINVAL);
        }
 
@@ -708,37 +607,16 @@ static void ep93xx_spi_process_transfer(struct ep93xx_spi *espi,
                                        struct spi_transfer *t)
 {
        struct ep93xx_spi_chip *chip = spi_get_ctldata(msg->spi);
+       int err;
 
        msg->state = t;
 
-       /*
-        * Handle any transfer specific settings if needed. We use
-        * temporary chip settings here and restore original later when
-        * the transfer is finished.
-        */
-       if (t->speed_hz || t->bits_per_word) {
-               struct ep93xx_spi_chip tmp_chip = *chip;
-
-               if (t->speed_hz) {
-                       int err;
-
-                       err = ep93xx_spi_calc_divisors(espi, &tmp_chip,
-                                                      t->speed_hz);
-                       if (err) {
-                               dev_err(&espi->pdev->dev,
-                                       "failed to adjust speed\n");
-                               msg->status = err;
-                               return;
-                       }
-               }
-
-               if (t->bits_per_word)
-                       tmp_chip.dss = bits_per_word_to_dss(t->bits_per_word);
-
-               /*
-                * Set up temporary new hw settings for this transfer.
-                */
-               ep93xx_spi_chip_setup(espi, &tmp_chip);
+       err = ep93xx_spi_chip_setup(espi, chip, t->speed_hz, t->bits_per_word);
+       if (err) {
+               dev_err(&espi->pdev->dev,
+                       "failed to setup chip for transfer\n");
+               msg->status = err;
+               return;
        }
 
        espi->rx = 0;
@@ -783,9 +661,6 @@ static void ep93xx_spi_process_transfer(struct ep93xx_spi *espi,
                        ep93xx_spi_cs_control(msg->spi, true);
                }
        }
-
-       if (t->speed_hz || t->bits_per_word)
-               ep93xx_spi_chip_setup(espi, chip);
 }
 
 /*
@@ -838,10 +713,8 @@ static void ep93xx_spi_process_message(struct ep93xx_spi *espi,
        espi->fifo_level = 0;
 
        /*
-        * Update SPI controller registers according to spi device and assert
-        * the chipselect.
+        * Assert the chipselect.
         */
-       ep93xx_spi_chip_setup(espi, spi_get_ctldata(msg->spi));
        ep93xx_spi_cs_control(msg->spi, true);
 
        list_for_each_entry(t, &msg->transfers, transfer_list) {
@@ -858,50 +731,29 @@ static void ep93xx_spi_process_message(struct ep93xx_spi *espi,
        ep93xx_spi_disable(espi);
 }
 
-#define work_to_espi(work) (container_of((work), struct ep93xx_spi, msg_work))
-
-/**
- * ep93xx_spi_work() - EP93xx SPI workqueue worker function
- * @work: work struct
- *
- * Workqueue worker function. This function is called when there are new
- * SPI messages to be processed. Message is taken out from the queue and then
- * passed to ep93xx_spi_process_message().
- *
- * After message is transferred, protocol driver is notified by calling
- * @msg->complete(). In case of error, @msg->status is set to negative error
- * number, otherwise it contains zero (and @msg->actual_length is updated).
- */
-static void ep93xx_spi_work(struct work_struct *work)
+static int ep93xx_spi_transfer_one_message(struct spi_master *master,
+                                          struct spi_message *msg)
 {
-       struct ep93xx_spi *espi = work_to_espi(work);
-       struct spi_message *msg;
+       struct ep93xx_spi *espi = spi_master_get_devdata(master);
+       struct spi_transfer *t;
 
-       spin_lock_irq(&espi->lock);
-       if (!espi->running || espi->current_msg ||
-               list_empty(&espi->msg_queue)) {
-               spin_unlock_irq(&espi->lock);
-               return;
+       /* first validate each transfer */
+       list_for_each_entry(t, &msg->transfers, transfer_list) {
+               if (t->speed_hz < espi->min_rate)
+                       return -EINVAL;
        }
-       msg = list_first_entry(&espi->msg_queue, struct spi_message, queue);
-       list_del_init(&msg->queue);
-       espi->current_msg = msg;
-       spin_unlock_irq(&espi->lock);
 
-       ep93xx_spi_process_message(espi, msg);
+       msg->state = NULL;
+       msg->status = 0;
+       msg->actual_length = 0;
 
-       /*
-        * Update the current message and re-schedule ourselves if there are
-        * more messages in the queue.
-        */
-       spin_lock_irq(&espi->lock);
+       espi->current_msg = msg;
+       ep93xx_spi_process_message(espi, msg);
        espi->current_msg = NULL;
-       if (espi->running && !list_empty(&espi->msg_queue))
-               queue_work(espi->wq, &espi->msg_work);
-       spin_unlock_irq(&espi->lock);
 
-       /* notify the protocol driver that we are done with this message */
-       msg->complete(msg->context);
+       spi_finalize_current_message(master);
+
+       return 0;
 }
 
 static irqreturn_t ep93xx_spi_interrupt(int irq, void *dev_id)
@@ -1024,14 +876,24 @@ static int ep93xx_spi_probe(struct platform_device *pdev)
 
        info = pdev->dev.platform_data;
 
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
+               dev_err(&pdev->dev, "failed to get irq resources\n");
+               return -EBUSY;
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               dev_err(&pdev->dev, "unable to get iomem resource\n");
+               return -ENODEV;
+       }
+
        master = spi_alloc_master(&pdev->dev, sizeof(*espi));
-       if (!master) {
-               dev_err(&pdev->dev, "failed to allocate spi master\n");
+       if (!master)
                return -ENOMEM;
-       }
 
        master->setup = ep93xx_spi_setup;
-       master->transfer = ep93xx_spi_transfer;
+       master->transfer_one_message = ep93xx_spi_transfer_one_message;
        master->cleanup = ep93xx_spi_cleanup;
        master->bus_num = pdev->id;
        master->num_chipselect = info->num_chipselect;
@@ -1042,14 +904,13 @@ static int ep93xx_spi_probe(struct platform_device *pdev)
 
        espi = spi_master_get_devdata(master);
 
-       espi->clk = clk_get(&pdev->dev, NULL);
+       espi->clk = devm_clk_get(&pdev->dev, NULL);
        if (IS_ERR(espi->clk)) {
                dev_err(&pdev->dev, "unable to get spi clock\n");
                error = PTR_ERR(espi->clk);
                goto fail_release_master;
        }
 
-       spin_lock_init(&espi->lock);
        init_completion(&espi->wait);
 
        /*
@@ -1060,55 +921,31 @@ static int ep93xx_spi_probe(struct platform_device *pdev)
        espi->min_rate = clk_get_rate(espi->clk) / (254 * 256);
        espi->pdev = pdev;
 
-       irq = platform_get_irq(pdev, 0);
-       if (irq < 0) {
-               error = -EBUSY;
-               dev_err(&pdev->dev, "failed to get irq resources\n");
-               goto fail_put_clock;
-       }
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(&pdev->dev, "unable to get iomem resource\n");
-               error = -ENODEV;
-               goto fail_put_clock;
-       }
-
        espi->sspdr_phys = res->start + SSPDR;
 
        espi->regs_base = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(espi->regs_base)) {
                error = PTR_ERR(espi->regs_base);
-               goto fail_put_clock;
+               goto fail_release_master;
        }
 
        error = devm_request_irq(&pdev->dev, irq, ep93xx_spi_interrupt,
                                0, "ep93xx-spi", espi);
        if (error) {
                dev_err(&pdev->dev, "failed to request irq\n");
-               goto fail_put_clock;
+               goto fail_release_master;
        }
 
        if (info->use_dma && ep93xx_spi_setup_dma(espi))
                dev_warn(&pdev->dev, "DMA setup failed. Falling back to PIO\n");
 
-       espi->wq = create_singlethread_workqueue("ep93xx_spid");
-       if (!espi->wq) {
-               dev_err(&pdev->dev, "unable to create workqueue\n");
-               error = -ENOMEM;
-               goto fail_free_dma;
-       }
-       INIT_WORK(&espi->msg_work, ep93xx_spi_work);
-       INIT_LIST_HEAD(&espi->msg_queue);
-       espi->running = true;
-
        /* make sure that the hardware is disabled */
        ep93xx_spi_write_u8(espi, SSPCR1, 0);
 
        error = spi_register_master(master);
        if (error) {
                dev_err(&pdev->dev, "failed to register SPI master\n");
-               goto fail_free_queue;
+               goto fail_free_dma;
        }
 
        dev_info(&pdev->dev, "EP93xx SPI Controller at 0x%08lx irq %d\n",
@@ -1116,12 +953,8 @@ static int ep93xx_spi_probe(struct platform_device *pdev)
 
        return 0;
 
-fail_free_queue:
-       destroy_workqueue(espi->wq);
 fail_free_dma:
        ep93xx_spi_release_dma(espi);
-fail_put_clock:
-       clk_put(espi->clk);
 fail_release_master:
        spi_master_put(master);
 
@@ -1133,31 +966,7 @@ static int ep93xx_spi_remove(struct platform_device *pdev)
        struct spi_master *master = platform_get_drvdata(pdev);
        struct ep93xx_spi *espi = spi_master_get_devdata(master);
 
-       spin_lock_irq(&espi->lock);
-       espi->running = false;
-       spin_unlock_irq(&espi->lock);
-
-       destroy_workqueue(espi->wq);
-
-       /*
-        * Complete remaining messages with %-ESHUTDOWN status.
-        */
-       spin_lock_irq(&espi->lock);
-       while (!list_empty(&espi->msg_queue)) {
-               struct spi_message *msg;
-
-               msg = list_first_entry(&espi->msg_queue,
-                                      struct spi_message, queue);
-               list_del_init(&msg->queue);
-               msg->status = -ESHUTDOWN;
-               spin_unlock_irq(&espi->lock);
-               msg->complete(msg->context);
-               spin_lock_irq(&espi->lock);
-       }
-       spin_unlock_irq(&espi->lock);
-
        ep93xx_spi_release_dma(espi);
-       clk_put(espi->clk);
 
        spi_unregister_master(master);
        return 0;
diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c
new file mode 100644 (file)
index 0000000..6cd07d1
--- /dev/null
@@ -0,0 +1,557 @@
+/*
+ * drivers/spi/spi-fsl-dspi.c
+ *
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * Freescale DSPI driver
+ * This file contains a driver for the Freescale DSPI
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+#include <linux/pm_runtime.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+
+#define DRIVER_NAME "fsl-dspi"
+
+#define TRAN_STATE_RX_VOID             0x01
+#define TRAN_STATE_TX_VOID             0x02
+#define TRAN_STATE_WORD_ODD_NUM        0x04
+
+#define DSPI_FIFO_SIZE                 4
+
+#define SPI_MCR                0x00
+#define SPI_MCR_MASTER         (1 << 31)
+#define SPI_MCR_PCSIS          (0x3F << 16)
+#define SPI_MCR_CLR_TXF        (1 << 11)
+#define SPI_MCR_CLR_RXF        (1 << 10)
+
+#define SPI_TCR                        0x08
+
+#define SPI_CTAR(x)            (0x0c + (x * 4))
+#define SPI_CTAR_FMSZ(x)       (((x) & 0x0000000f) << 27)
+#define SPI_CTAR_CPOL(x)       ((x) << 26)
+#define SPI_CTAR_CPHA(x)       ((x) << 25)
+#define SPI_CTAR_LSBFE(x)      ((x) << 24)
+#define SPI_CTAR_PCSSCR(x)     (((x) & 0x00000003) << 22)
+#define SPI_CTAR_PASC(x)       (((x) & 0x00000003) << 20)
+#define SPI_CTAR_PDT(x)        (((x) & 0x00000003) << 18)
+#define SPI_CTAR_PBR(x)        (((x) & 0x00000003) << 16)
+#define SPI_CTAR_CSSCK(x)      (((x) & 0x0000000f) << 12)
+#define SPI_CTAR_ASC(x)        (((x) & 0x0000000f) << 8)
+#define SPI_CTAR_DT(x)         (((x) & 0x0000000f) << 4)
+#define SPI_CTAR_BR(x)         ((x) & 0x0000000f)
+
+#define SPI_CTAR0_SLAVE        0x0c
+
+#define SPI_SR                 0x2c
+#define SPI_SR_EOQF            0x10000000
+
+#define SPI_RSER               0x30
+#define SPI_RSER_EOQFE         0x10000000
+
+#define SPI_PUSHR              0x34
+#define SPI_PUSHR_CONT         (1 << 31)
+#define SPI_PUSHR_CTAS(x)      (((x) & 0x00000007) << 28)
+#define SPI_PUSHR_EOQ          (1 << 27)
+#define SPI_PUSHR_CTCNT        (1 << 26)
+#define SPI_PUSHR_PCS(x)       (((1 << x) & 0x0000003f) << 16)
+#define SPI_PUSHR_TXDATA(x)    ((x) & 0x0000ffff)
+
+#define SPI_PUSHR_SLAVE        0x34
+
+#define SPI_POPR               0x38
+#define SPI_POPR_RXDATA(x)     ((x) & 0x0000ffff)
+
+#define SPI_TXFR0              0x3c
+#define SPI_TXFR1              0x40
+#define SPI_TXFR2              0x44
+#define SPI_TXFR3              0x48
+#define SPI_RXFR0              0x7c
+#define SPI_RXFR1              0x80
+#define SPI_RXFR2              0x84
+#define SPI_RXFR3              0x88
+
+#define SPI_FRAME_BITS(bits)   SPI_CTAR_FMSZ((bits) - 1)
+#define SPI_FRAME_BITS_MASK    SPI_CTAR_FMSZ(0xf)
+#define SPI_FRAME_BITS_16      SPI_CTAR_FMSZ(0xf)
+#define SPI_FRAME_BITS_8       SPI_CTAR_FMSZ(0x7)
+
+#define SPI_CS_INIT            0x01
+#define SPI_CS_ASSERT          0x02
+#define SPI_CS_DROP            0x04
+
+struct chip_data {
+       u32 mcr_val;
+       u32 ctar_val;
+       u16 void_write_data;
+};
+
+struct fsl_dspi {
+       struct spi_bitbang      bitbang;
+       struct platform_device  *pdev;
+
+       void                    *base;
+       int                     irq;
+       struct clk              *clk;
+
+       struct spi_transfer     *cur_transfer;
+       struct chip_data        *cur_chip;
+       size_t                  len;
+       void                    *tx;
+       void                    *tx_end;
+       void                    *rx;
+       void                    *rx_end;
+       char                    dataflags;
+       u8                      cs;
+       u16                     void_write_data;
+
+       wait_queue_head_t       waitq;
+       u32                     waitflags;
+};
+
+static inline int is_double_byte_mode(struct fsl_dspi *dspi)
+{
+       return ((readl(dspi->base + SPI_CTAR(dspi->cs)) & SPI_FRAME_BITS_MASK)
+                       == SPI_FRAME_BITS(8)) ? 0 : 1;
+}
+
+static void set_bit_mode(struct fsl_dspi *dspi, unsigned char bits)
+{
+       u32 temp;
+
+       temp = readl(dspi->base + SPI_CTAR(dspi->cs));
+       temp &= ~SPI_FRAME_BITS_MASK;
+       temp |= SPI_FRAME_BITS(bits);
+       writel(temp, dspi->base + SPI_CTAR(dspi->cs));
+}
+
+static void hz_to_spi_baud(char *pbr, char *br, int speed_hz,
+               unsigned long clkrate)
+{
+       /* Valid baud rate pre-scaler values */
+       int pbr_tbl[4] = {2, 3, 5, 7};
+       int brs[16] = { 2,      4,      6,      8,
+               16,     32,     64,     128,
+               256,    512,    1024,   2048,
+               4096,   8192,   16384,  32768 };
+       int temp, i = 0, j = 0;
+
+       temp = clkrate / 2 / speed_hz;
+
+       for (i = 0; i < ARRAY_SIZE(pbr_tbl); i++)
+               for (j = 0; j < ARRAY_SIZE(brs); j++) {
+                       if (pbr_tbl[i] * brs[j] >= temp) {
+                               *pbr = i;
+                               *br = j;
+                               return;
+                       }
+               }
+
+       pr_warn("Can not find valid buad rate,speed_hz is %d,clkrate is %ld\
+               ,we use the max prescaler value.\n", speed_hz, clkrate);
+       *pbr = ARRAY_SIZE(pbr_tbl) - 1;
+       *br =  ARRAY_SIZE(brs) - 1;
+}
+
+static int dspi_transfer_write(struct fsl_dspi *dspi)
+{
+       int tx_count = 0;
+       int tx_word;
+       u16 d16;
+       u8  d8;
+       u32 dspi_pushr = 0;
+       int first = 1;
+
+       tx_word = is_double_byte_mode(dspi);
+
+       /* If we are in word mode, but only have a single byte to transfer
+        * then switch to byte mode temporarily.  Will switch back at the
+        * end of the transfer.
+        */
+       if (tx_word && (dspi->len == 1)) {
+               dspi->dataflags |= TRAN_STATE_WORD_ODD_NUM;
+               set_bit_mode(dspi, 8);
+               tx_word = 0;
+       }
+
+       while (dspi->len && (tx_count < DSPI_FIFO_SIZE)) {
+               if (tx_word) {
+                       if (dspi->len == 1)
+                               break;
+
+                       if (!(dspi->dataflags & TRAN_STATE_TX_VOID)) {
+                               d16 = *(u16 *)dspi->tx;
+                               dspi->tx += 2;
+                       } else {
+                               d16 = dspi->void_write_data;
+                       }
+
+                       dspi_pushr = SPI_PUSHR_TXDATA(d16) |
+                               SPI_PUSHR_PCS(dspi->cs) |
+                               SPI_PUSHR_CTAS(dspi->cs) |
+                               SPI_PUSHR_CONT;
+
+                       dspi->len -= 2;
+               } else {
+                       if (!(dspi->dataflags & TRAN_STATE_TX_VOID)) {
+
+                               d8 = *(u8 *)dspi->tx;
+                               dspi->tx++;
+                       } else {
+                               d8 = (u8)dspi->void_write_data;
+                       }
+
+                       dspi_pushr = SPI_PUSHR_TXDATA(d8) |
+                               SPI_PUSHR_PCS(dspi->cs) |
+                               SPI_PUSHR_CTAS(dspi->cs) |
+                               SPI_PUSHR_CONT;
+
+                       dspi->len--;
+               }
+
+               if (dspi->len == 0 || tx_count == DSPI_FIFO_SIZE - 1) {
+                       /* last transfer in the transfer */
+                       dspi_pushr |= SPI_PUSHR_EOQ;
+               } else if (tx_word && (dspi->len == 1))
+                       dspi_pushr |= SPI_PUSHR_EOQ;
+
+               if (first) {
+                       first = 0;
+                       dspi_pushr |= SPI_PUSHR_CTCNT; /* clear counter */
+               }
+
+               writel(dspi_pushr, dspi->base + SPI_PUSHR);
+               tx_count++;
+       }
+
+       return tx_count * (tx_word + 1);
+}
+
+static int dspi_transfer_read(struct fsl_dspi *dspi)
+{
+       int rx_count = 0;
+       int rx_word = is_double_byte_mode(dspi);
+       u16 d;
+       while ((dspi->rx < dspi->rx_end)
+                       && (rx_count < DSPI_FIFO_SIZE)) {
+               if (rx_word) {
+                       if ((dspi->rx_end - dspi->rx) == 1)
+                               break;
+
+                       d = SPI_POPR_RXDATA(readl(dspi->base + SPI_POPR));
+
+                       if (!(dspi->dataflags & TRAN_STATE_RX_VOID))
+                               *(u16 *)dspi->rx = d;
+                       dspi->rx += 2;
+
+               } else {
+                       d = SPI_POPR_RXDATA(readl(dspi->base + SPI_POPR));
+                       if (!(dspi->dataflags & TRAN_STATE_RX_VOID))
+                               *(u8 *)dspi->rx = d;
+                       dspi->rx++;
+               }
+               rx_count++;
+       }
+
+       return rx_count;
+}
+
+static int dspi_txrx_transfer(struct spi_device *spi, struct spi_transfer *t)
+{
+       struct fsl_dspi *dspi = spi_master_get_devdata(spi->master);
+       dspi->cur_transfer = t;
+       dspi->cur_chip = spi_get_ctldata(spi);
+       dspi->cs = spi->chip_select;
+       dspi->void_write_data = dspi->cur_chip->void_write_data;
+
+       dspi->dataflags = 0;
+       dspi->tx = (void *)t->tx_buf;
+       dspi->tx_end = dspi->tx + t->len;
+       dspi->rx = t->rx_buf;
+       dspi->rx_end = dspi->rx + t->len;
+       dspi->len = t->len;
+
+       if (!dspi->rx)
+               dspi->dataflags |= TRAN_STATE_RX_VOID;
+
+       if (!dspi->tx)
+               dspi->dataflags |= TRAN_STATE_TX_VOID;
+
+       writel(dspi->cur_chip->mcr_val, dspi->base + SPI_MCR);
+       writel(dspi->cur_chip->ctar_val, dspi->base + SPI_CTAR(dspi->cs));
+       writel(SPI_RSER_EOQFE, dspi->base + SPI_RSER);
+
+       if (t->speed_hz)
+               writel(dspi->cur_chip->ctar_val,
+                               dspi->base + SPI_CTAR(dspi->cs));
+
+       dspi_transfer_write(dspi);
+
+       if (wait_event_interruptible(dspi->waitq, dspi->waitflags))
+               dev_err(&dspi->pdev->dev, "wait transfer complete fail!\n");
+       dspi->waitflags = 0;
+
+       return t->len - dspi->len;
+}
+
+static void dspi_chipselect(struct spi_device *spi, int value)
+{
+       struct fsl_dspi *dspi = spi_master_get_devdata(spi->master);
+       u32 pushr = readl(dspi->base + SPI_PUSHR);
+
+       switch (value) {
+       case BITBANG_CS_ACTIVE:
+               pushr |= SPI_PUSHR_CONT;
+       case BITBANG_CS_INACTIVE:
+               pushr &= ~SPI_PUSHR_CONT;
+       }
+
+       writel(pushr, dspi->base + SPI_PUSHR);
+}
+
+static int dspi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
+{
+       struct chip_data *chip;
+       struct fsl_dspi *dspi = spi_master_get_devdata(spi->master);
+       unsigned char br = 0, pbr = 0, fmsz = 0;
+
+       /* Only alloc on first setup */
+       chip = spi_get_ctldata(spi);
+       if (chip == NULL) {
+               chip = kcalloc(1, sizeof(struct chip_data), GFP_KERNEL);
+               if (!chip)
+                       return -ENOMEM;
+       }
+
+       chip->mcr_val = SPI_MCR_MASTER | SPI_MCR_PCSIS |
+               SPI_MCR_CLR_TXF | SPI_MCR_CLR_RXF;
+       if ((spi->bits_per_word >= 4) && (spi->bits_per_word <= 16)) {
+               fmsz = spi->bits_per_word - 1;
+       } else {
+               pr_err("Invalid wordsize\n");
+               kfree(chip);
+               return -ENODEV;
+       }
+
+       chip->void_write_data = 0;
+
+       hz_to_spi_baud(&pbr, &br,
+                       spi->max_speed_hz, clk_get_rate(dspi->clk));
+
+       chip->ctar_val =  SPI_CTAR_FMSZ(fmsz)
+               | SPI_CTAR_CPOL(spi->mode & SPI_CPOL ? 1 : 0)
+               | SPI_CTAR_CPHA(spi->mode & SPI_CPHA ? 1 : 0)
+               | SPI_CTAR_LSBFE(spi->mode & SPI_LSB_FIRST ? 1 : 0)
+               | SPI_CTAR_PBR(pbr)
+               | SPI_CTAR_BR(br);
+
+       spi_set_ctldata(spi, chip);
+
+       return 0;
+}
+
+static int dspi_setup(struct spi_device *spi)
+{
+       if (!spi->max_speed_hz)
+               return -EINVAL;
+
+       if (!spi->bits_per_word)
+               spi->bits_per_word = 8;
+
+       return dspi_setup_transfer(spi, NULL);
+}
+
+static irqreturn_t dspi_interrupt(int irq, void *dev_id)
+{
+       struct fsl_dspi *dspi = (struct fsl_dspi *)dev_id;
+
+       writel(SPI_SR_EOQF, dspi->base + SPI_SR);
+
+       dspi_transfer_read(dspi);
+
+       if (!dspi->len) {
+               if (dspi->dataflags & TRAN_STATE_WORD_ODD_NUM)
+                       set_bit_mode(dspi, 16);
+               dspi->waitflags = 1;
+               wake_up_interruptible(&dspi->waitq);
+       } else {
+               dspi_transfer_write(dspi);
+
+               return IRQ_HANDLED;
+       }
+
+       return IRQ_HANDLED;
+}
+
+static struct of_device_id fsl_dspi_dt_ids[] = {
+       { .compatible = "fsl,vf610-dspi", .data = NULL, },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, fsl_dspi_dt_ids);
+
+#ifdef CONFIG_PM_SLEEP
+static int dspi_suspend(struct device *dev)
+{
+       struct spi_master *master = dev_get_drvdata(dev);
+       struct fsl_dspi *dspi = spi_master_get_devdata(master);
+
+       spi_master_suspend(master);
+       clk_disable_unprepare(dspi->clk);
+
+       return 0;
+}
+
+static int dspi_resume(struct device *dev)
+{
+
+       struct spi_master *master = dev_get_drvdata(dev);
+       struct fsl_dspi *dspi = spi_master_get_devdata(master);
+
+       clk_prepare_enable(dspi->clk);
+       spi_master_resume(master);
+
+       return 0;
+}
+#endif /* CONFIG_PM_SLEEP */
+
+static const struct dev_pm_ops dspi_pm = {
+       SET_SYSTEM_SLEEP_PM_OPS(dspi_suspend, dspi_resume)
+};
+
+static int dspi_probe(struct platform_device *pdev)
+{
+       struct device_node *np = pdev->dev.of_node;
+       struct spi_master *master;
+       struct fsl_dspi *dspi;
+       struct resource *res;
+       int ret = 0, cs_num, bus_num;
+
+       master = spi_alloc_master(&pdev->dev, sizeof(struct fsl_dspi));
+       if (!master)
+               return -ENOMEM;
+
+       dspi = spi_master_get_devdata(master);
+       dspi->pdev = pdev;
+       dspi->bitbang.master = spi_master_get(master);
+       dspi->bitbang.chipselect = dspi_chipselect;
+       dspi->bitbang.setup_transfer = dspi_setup_transfer;
+       dspi->bitbang.txrx_bufs = dspi_txrx_transfer;
+       dspi->bitbang.master->setup = dspi_setup;
+       dspi->bitbang.master->dev.of_node = pdev->dev.of_node;
+
+       master->mode_bits = SPI_CPOL | SPI_CPHA;
+       master->bits_per_word_mask = SPI_BPW_MASK(4) | SPI_BPW_MASK(8) |
+                                       SPI_BPW_MASK(16);
+
+       ret = of_property_read_u32(np, "spi-num-chipselects", &cs_num);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "can't get spi-num-chipselects\n");
+               goto out_master_put;
+       }
+       master->num_chipselect = cs_num;
+
+       ret = of_property_read_u32(np, "bus-num", &bus_num);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "can't get bus-num\n");
+               goto out_master_put;
+       }
+       master->bus_num = bus_num;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               dev_err(&pdev->dev, "can't get platform resource\n");
+               ret = -EINVAL;
+               goto out_master_put;
+       }
+
+       dspi->base = devm_ioremap_resource(&pdev->dev, res);
+       if (!dspi->base) {
+               ret = -EINVAL;
+               goto out_master_put;
+       }
+
+       dspi->irq = platform_get_irq(pdev, 0);
+       if (dspi->irq < 0) {
+               dev_err(&pdev->dev, "can't get platform irq\n");
+               ret = dspi->irq;
+               goto out_master_put;
+       }
+
+       ret = devm_request_irq(&pdev->dev, dspi->irq, dspi_interrupt, 0,
+                       pdev->name, dspi);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Unable to attach DSPI interrupt\n");
+               goto out_master_put;
+       }
+
+       dspi->clk = devm_clk_get(&pdev->dev, "dspi");
+       if (IS_ERR(dspi->clk)) {
+               ret = PTR_ERR(dspi->clk);
+               dev_err(&pdev->dev, "unable to get clock\n");
+               goto out_master_put;
+       }
+       clk_prepare_enable(dspi->clk);
+
+       init_waitqueue_head(&dspi->waitq);
+       platform_set_drvdata(pdev, dspi);
+
+       ret = spi_bitbang_start(&dspi->bitbang);
+       if (ret != 0) {
+               dev_err(&pdev->dev, "Problem registering DSPI master\n");
+               goto out_clk_put;
+       }
+
+       pr_info(KERN_INFO "Freescale DSPI master initialized\n");
+       return ret;
+
+out_clk_put:
+       clk_disable_unprepare(dspi->clk);
+out_master_put:
+       spi_master_put(master);
+       platform_set_drvdata(pdev, NULL);
+
+       return ret;
+}
+
+static int dspi_remove(struct platform_device *pdev)
+{
+       struct fsl_dspi *dspi = platform_get_drvdata(pdev);
+
+       /* Disconnect from the SPI framework */
+       spi_bitbang_stop(&dspi->bitbang);
+       spi_master_put(dspi->bitbang.master);
+
+       return 0;
+}
+
+static struct platform_driver fsl_dspi_driver = {
+       .driver.name    = DRIVER_NAME,
+       .driver.of_match_table = fsl_dspi_dt_ids,
+       .driver.owner   = THIS_MODULE,
+       .driver.pm = &dspi_pm,
+       .probe          = dspi_probe,
+       .remove         = dspi_remove,
+};
+module_platform_driver(fsl_dspi_driver);
+
+MODULE_DESCRIPTION("Freescale DSPI Controller Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRIVER_NAME);
index 7db4f43..15323d8 100644 (file)
@@ -619,6 +619,7 @@ static const struct of_device_id spi_imx_dt_ids[] = {
        { .compatible = "fsl,imx51-ecspi", .data = &imx51_ecspi_devtype_data, },
        { /* sentinel */ }
 };
+MODULE_DEVICE_TABLE(of, spi_imx_dt_ids);
 
 static void spi_imx_chipselect(struct spi_device *spi, int is_active)
 {
@@ -796,10 +797,11 @@ static int spi_imx_probe(struct platform_device *pdev)
                if (!gpio_is_valid(cs_gpio))
                        continue;
 
-               ret = gpio_request(spi_imx->chipselect[i], DRIVER_NAME);
+               ret = devm_gpio_request(&pdev->dev, spi_imx->chipselect[i],
+                                       DRIVER_NAME);
                if (ret) {
                        dev_err(&pdev->dev, "can't get cs gpios\n");
-                       goto out_gpio_free;
+                       goto out_master_put;
                }
        }
 
@@ -816,50 +818,44 @@ static int spi_imx_probe(struct platform_device *pdev)
                (struct spi_imx_devtype_data *) pdev->id_entry->driver_data;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(&pdev->dev, "can't get platform resource\n");
-               ret = -ENOMEM;
-               goto out_gpio_free;
-       }
-
-       if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
-               dev_err(&pdev->dev, "request_mem_region failed\n");
-               ret = -EBUSY;
-               goto out_gpio_free;
-       }
-
-       spi_imx->base = ioremap(res->start, resource_size(res));
-       if (!spi_imx->base) {
-               ret = -EINVAL;
-               goto out_release_mem;
+       spi_imx->base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(spi_imx->base)) {
+               ret = PTR_ERR(spi_imx->base);
+               goto out_master_put;
        }
 
        spi_imx->irq = platform_get_irq(pdev, 0);
        if (spi_imx->irq < 0) {
                ret = -EINVAL;
-               goto out_iounmap;
+               goto out_master_put;
        }
 
-       ret = request_irq(spi_imx->irq, spi_imx_isr, 0, DRIVER_NAME, spi_imx);
+       ret = devm_request_irq(&pdev->dev, spi_imx->irq, spi_imx_isr, 0,
+                              DRIVER_NAME, spi_imx);
        if (ret) {
                dev_err(&pdev->dev, "can't get irq%d: %d\n", spi_imx->irq, ret);
-               goto out_iounmap;
+               goto out_master_put;
        }
 
        spi_imx->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
        if (IS_ERR(spi_imx->clk_ipg)) {
                ret = PTR_ERR(spi_imx->clk_ipg);
-               goto out_free_irq;
+               goto out_master_put;
        }
 
        spi_imx->clk_per = devm_clk_get(&pdev->dev, "per");
        if (IS_ERR(spi_imx->clk_per)) {
                ret = PTR_ERR(spi_imx->clk_per);
-               goto out_free_irq;
+               goto out_master_put;
        }
 
-       clk_prepare_enable(spi_imx->clk_per);
-       clk_prepare_enable(spi_imx->clk_ipg);
+       ret = clk_prepare_enable(spi_imx->clk_per);
+       if (ret)
+               goto out_master_put;
+
+       ret = clk_prepare_enable(spi_imx->clk_ipg);
+       if (ret)
+               goto out_put_per;
 
        spi_imx->spi_clk = clk_get_rate(spi_imx->clk_per);
 
@@ -879,47 +875,27 @@ static int spi_imx_probe(struct platform_device *pdev)
        return ret;
 
 out_clk_put:
-       clk_disable_unprepare(spi_imx->clk_per);
        clk_disable_unprepare(spi_imx->clk_ipg);
-out_free_irq:
-       free_irq(spi_imx->irq, spi_imx);
-out_iounmap:
-       iounmap(spi_imx->base);
-out_release_mem:
-       release_mem_region(res->start, resource_size(res));
-out_gpio_free:
-       while (--i >= 0) {
-               if (gpio_is_valid(spi_imx->chipselect[i]))
-                       gpio_free(spi_imx->chipselect[i]);
-       }
+out_put_per:
+       clk_disable_unprepare(spi_imx->clk_per);
+out_master_put:
        spi_master_put(master);
-       kfree(master);
+
        return ret;
 }
 
 static int spi_imx_remove(struct platform_device *pdev)
 {
        struct spi_master *master = platform_get_drvdata(pdev);
-       struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
-       int i;
 
        spi_bitbang_stop(&spi_imx->bitbang);
 
        writel(0, spi_imx->base + MXC_CSPICTRL);
-       clk_disable_unprepare(spi_imx->clk_per);
        clk_disable_unprepare(spi_imx->clk_ipg);
-       free_irq(spi_imx->irq, spi_imx);
-       iounmap(spi_imx->base);
-
-       for (i = 0; i < master->num_chipselect; i++)
-               if (gpio_is_valid(spi_imx->chipselect[i]))
-                       gpio_free(spi_imx->chipselect[i]);
-
+       clk_disable_unprepare(spi_imx->clk_per);
        spi_master_put(master);
 
-       release_mem_region(res->start, resource_size(res));
-
        return 0;
 }
 
index 150d854..2ad3d74 100644 (file)
@@ -174,17 +174,6 @@ static void nuc900_spi_gobusy(struct nuc900_spi *hw)
        spin_unlock_irqrestore(&hw->lock, flags);
 }
 
-static int nuc900_spi_setupxfer(struct spi_device *spi,
-                                struct spi_transfer *t)
-{
-       return 0;
-}
-
-static int nuc900_spi_setup(struct spi_device *spi)
-{
-       return 0;
-}
-
 static inline unsigned int hw_txbyte(struct nuc900_spi *hw, int count)
 {
        return hw->tx ? hw->tx[count] : 0;
@@ -377,10 +366,8 @@ static int nuc900_spi_probe(struct platform_device *pdev)
        master->num_chipselect     = hw->pdata->num_cs;
        master->bus_num            = hw->pdata->bus_num;
        hw->bitbang.master         = hw->master;
-       hw->bitbang.setup_transfer = nuc900_spi_setupxfer;
        hw->bitbang.chipselect     = nuc900_spi_chipsel;
        hw->bitbang.txrx_bufs      = nuc900_spi_txrx;
-       hw->bitbang.master->setup  = nuc900_spi_setup;
 
        hw->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (hw->res == NULL) {
index 58deb79..d36ba90 100644 (file)
@@ -315,15 +315,11 @@ static int tiny_spi_probe(struct platform_device *pdev)
 
        /* find and map our resources */
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res)
-               goto exit_busy;
-       if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res),
-                                    pdev->name))
-               goto exit_busy;
-       hw->base = devm_ioremap_nocache(&pdev->dev, res->start,
-                                       resource_size(res));
-       if (!hw->base)
-               goto exit_busy;
+       hw->base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(hw->base)) {
+               err = PTR_ERR(hw->base);
+               goto exit;
+       }
        /* irq is optional */
        hw->irq = platform_get_irq(pdev, 0);
        if (hw->irq >= 0) {
@@ -337,8 +333,10 @@ static int tiny_spi_probe(struct platform_device *pdev)
        if (platp) {
                hw->gpio_cs_count = platp->gpio_cs_count;
                hw->gpio_cs = platp->gpio_cs;
-               if (platp->gpio_cs_count && !platp->gpio_cs)
-                       goto exit_busy;
+               if (platp->gpio_cs_count && !platp->gpio_cs) {
+                       err = -EBUSY;
+                       goto exit;
+               }
                hw->freq = platp->freq;
                hw->baudwidth = platp->baudwidth;
        } else {
@@ -365,8 +363,6 @@ static int tiny_spi_probe(struct platform_device *pdev)
 exit_gpio:
        while (i-- > 0)
                gpio_free(hw->gpio_cs[i]);
-exit_busy:
-       err = -EBUSY;
 exit:
        spi_master_put(master);
        return err;
index 5d90beb..d1bae77 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/clk.h>
+#include <linux/sizes.h>
 #include <asm/unaligned.h>
 
 #define DRIVER_NAME                    "orion_spi"
index 09a9428..fb56fcf 100644 (file)
@@ -233,21 +233,6 @@ static int xilinx_spi_setup_transfer(struct spi_device *spi,
        return 0;
 }
 
-static int xilinx_spi_setup(struct spi_device *spi)
-{
-       /* always return 0, we can not check the number of bits.
-        * There are cases when SPI setup is called before any driver is
-        * there, in that case the SPI core defaults to 8 bits, which we
-        * do not support in some cases. But if we return an error, the
-        * SPI device would not be registered and no driver can get hold of it
-        * When the driver is there, it will call SPI setup again with the
-        * correct number of bits per transfer.
-        * If a driver setups with the wrong bit number, it will fail when
-        * it tries to do a transfer
-        */
-       return 0;
-}
-
 static void xilinx_spi_fill_tx_fifo(struct xilinx_spi *xspi)
 {
        u8 sr;
@@ -375,7 +360,6 @@ struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem,
        xspi->bitbang.chipselect = xilinx_spi_chipselect;
        xspi->bitbang.setup_transfer = xilinx_spi_setup_transfer;
        xspi->bitbang.txrx_bufs = xilinx_spi_txrx_bufs;
-       xspi->bitbang.master->setup = xilinx_spi_setup;
        init_completion(&xspi->done);
 
        if (!request_mem_region(mem->start, resource_size(mem),
index 978dda2..8bc7de0 100644 (file)
@@ -774,7 +774,7 @@ static int spi_queued_transfer(struct spi_device *spi, struct spi_message *msg)
        msg->status = -EINPROGRESS;
 
        list_add_tail(&msg->queue, &master->queue);
-       if (master->running && !master->busy)
+       if (!master->busy)
                queue_kthread_work(&master->kworker, &master->pump_messages);
 
        spin_unlock_irqrestore(&master->queue_lock, flags);
@@ -1169,7 +1169,7 @@ int spi_register_master(struct spi_master *master)
        else {
                status = spi_master_initialize_queue(master);
                if (status) {
-                       device_unregister(&master->dev);
+                       device_del(&master->dev);
                        goto done;
                }
        }
@@ -1351,6 +1351,11 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message)
        struct spi_master *master = spi->master;
        struct spi_transfer *xfer;
 
+       if (list_empty(&message->transfers))
+               return -EINVAL;
+       if (!message->complete)
+               return -EINVAL;
+
        /* Half-duplex links include original MicroWire, and ones with
         * only one data pin like SPI_3WIRE (switches direction) or where
         * either MOSI or MISO is missing.  They can also be caused by
@@ -1377,8 +1382,13 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message)
        list_for_each_entry(xfer, &message->transfers, transfer_list) {
                if (!xfer->bits_per_word)
                        xfer->bits_per_word = spi->bits_per_word;
-               if (!xfer->speed_hz)
+               if (!xfer->speed_hz) {
                        xfer->speed_hz = spi->max_speed_hz;
+                       if (master->max_speed_hz &&
+                           xfer->speed_hz > master->max_speed_hz)
+                               xfer->speed_hz = master->max_speed_hz;
+               }
+
                if (master->bits_per_word_mask) {
                        /* Only 32 bits fit in the mask */
                        if (xfer->bits_per_word > 32)
@@ -1387,6 +1397,13 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message)
                                        BIT(xfer->bits_per_word - 1)))
                                return -EINVAL;
                }
+
+               if (xfer->speed_hz && master->min_speed_hz &&
+                   xfer->speed_hz < master->min_speed_hz)
+                       return -EINVAL;
+               if (xfer->speed_hz && master->max_speed_hz &&
+                   xfer->speed_hz > master->max_speed_hz)
+                       return -EINVAL;
        }
 
        message->spi = spi;
index e25eba5..b3b5125 100644 (file)
@@ -482,7 +482,7 @@ int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it)
                ret = comedi_device_postconfig(dev);
        if (ret < 0) {
                comedi_device_detach(dev);
-               module_put(dev->driver->module);
+               module_put(driv->module);
        }
        /* On success, the driver module count has been incremented. */
        return ret;
index 08613e2..0f1d193 100644 (file)
@@ -304,6 +304,11 @@ static int __init ohci_pci_init(void)
        pr_info("%s: " DRIVER_DESC "\n", hcd_name);
 
        ohci_init_driver(&ohci_pci_hc_driver, &pci_overrides);
+
+       /* Entries for the PCI suspend/resume callbacks are special */
+       ohci_pci_hc_driver.pci_suspend = ohci_suspend;
+       ohci_pci_hc_driver.pci_resume = ohci_resume;
+
        return pci_register_driver(&ohci_pci_driver);
 }
 module_init(ohci_pci_init);
index ca26628..e1859b8 100644 (file)
@@ -15,7 +15,7 @@
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include "otg_fsm.h"
+#include "phy-fsm-usb.h"
 #include <linux/usb/otg.h>
 #include <linux/ioctl.h>
 
index c520b35..7f45966 100644 (file)
@@ -29,7 +29,7 @@
 #include <linux/usb/gadget.h>
 #include <linux/usb/otg.h>
 
-#include "phy-otg-fsm.h"
+#include "phy-fsm-usb.h"
 
 /* Change USB protocol when there is a protocol change */
 static int otg_set_protocol(struct otg_fsm *fsm, int protocol)
index a58ac43..5e8be46 100644 (file)
@@ -348,7 +348,7 @@ static void init_evtchn_cpu_bindings(void)
 
        for_each_possible_cpu(i)
                memset(per_cpu(cpu_evtchn_mask, i),
-                      (i == 0) ? ~0 : 0, sizeof(*per_cpu(cpu_evtchn_mask, i)));
+                      (i == 0) ? ~0 : 0, NR_EVENT_CHANNELS/8);
 }
 
 static inline void clear_evtchn(int port)
@@ -1493,8 +1493,10 @@ void rebind_evtchn_irq(int evtchn, int irq)
 /* Rebind an evtchn so that it gets delivered to a specific cpu */
 static int rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
 {
+       struct shared_info *s = HYPERVISOR_shared_info;
        struct evtchn_bind_vcpu bind_vcpu;
        int evtchn = evtchn_from_irq(irq);
+       int masked;
 
        if (!VALID_EVTCHN(evtchn))
                return -1;
@@ -1511,6 +1513,12 @@ static int rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
        bind_vcpu.vcpu = tcpu;
 
        /*
+        * Mask the event while changing the VCPU binding to prevent
+        * it being delivered on an unexpected VCPU.
+        */
+       masked = sync_test_and_set_bit(evtchn, BM(s->evtchn_mask));
+
+       /*
         * If this fails, it usually just indicates that we're dealing with a
         * virq or IPI channel, which don't actually need to be rebound. Ignore
         * it, but don't do the xenlinux-level rebind in that case.
@@ -1518,6 +1526,9 @@ static int rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
        if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_vcpu, &bind_vcpu) >= 0)
                bind_evtchn_to_cpu(evtchn, tcpu);
 
+       if (!masked)
+               unmask_evtchn(evtchn);
+
        return 0;
 }
 
index 5e376bb..8defc6b 100644 (file)
@@ -40,7 +40,7 @@ struct inode *bfs_iget(struct super_block *sb, unsigned long ino)
        int block, off;
 
        inode = iget_locked(sb, ino);
-       if (IS_ERR(inode))
+       if (!inode)
                return ERR_PTR(-ENOMEM);
        if (!(inode->i_state & I_NEW))
                return inode;
index 94bbc04..c5eae72 100644 (file)
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -1045,12 +1045,22 @@ static int __bio_copy_iov(struct bio *bio, struct bio_vec *iovecs,
 int bio_uncopy_user(struct bio *bio)
 {
        struct bio_map_data *bmd = bio->bi_private;
-       int ret = 0;
+       struct bio_vec *bvec;
+       int ret = 0, i;
 
-       if (!bio_flagged(bio, BIO_NULL_MAPPED))
-               ret = __bio_copy_iov(bio, bmd->iovecs, bmd->sgvecs,
-                                    bmd->nr_sgvecs, bio_data_dir(bio) == READ,
-                                    0, bmd->is_our_pages);
+       if (!bio_flagged(bio, BIO_NULL_MAPPED)) {
+               /*
+                * if we're in a workqueue, the request is orphaned, so
+                * don't copy into a random user address space, just free.
+                */
+               if (current->mm)
+                       ret = __bio_copy_iov(bio, bmd->iovecs, bmd->sgvecs,
+                                            bmd->nr_sgvecs, bio_data_dir(bio) == READ,
+                                            0, bmd->is_our_pages);
+               else if (bmd->is_our_pages)
+                       bio_for_each_segment_all(bvec, bio, i)
+                               __free_page(bvec->bv_page);
+       }
        bio_free_map_data(bmd);
        bio_put(bio);
        return ret;
index 87bdb53..83cfb83 100644 (file)
@@ -2724,6 +2724,17 @@ char *dynamic_dname(struct dentry *dentry, char *buffer, int buflen,
        return memcpy(buffer, temp, sz);
 }
 
+char *simple_dname(struct dentry *dentry, char *buffer, int buflen)
+{
+       char *end = buffer + buflen;
+       /* these dentries are never renamed, so d_lock is not needed */
+       if (prepend(&end, &buflen, " (deleted)", 11) ||
+           prepend_name(&end, &buflen, &dentry->d_name) ||
+           prepend(&end, &buflen, "/", 1))  
+               end = ERR_PTR(-ENAMETOOLONG);
+       return end;  
+}
+
 /*
  * Write full pathname from the root of the filesystem into the buffer.
  */
index f3913eb..d15ccf2 100644 (file)
@@ -57,7 +57,7 @@ struct inode *efs_iget(struct super_block *super, unsigned long ino)
        struct inode *inode;
 
        inode = iget_locked(super, ino);
-       if (IS_ERR(inode))
+       if (!inode)
                return ERR_PTR(-ENOMEM);
        if (!(inode->i_state & I_NEW))
                return inode;
index 9435384..544a809 100644 (file)
@@ -1838,14 +1838,14 @@ int __init gfs2_glock_init(void)
 
        glock_workqueue = alloc_workqueue("glock_workqueue", WQ_MEM_RECLAIM |
                                          WQ_HIGHPRI | WQ_FREEZABLE, 0);
-       if (IS_ERR(glock_workqueue))
-               return PTR_ERR(glock_workqueue);
+       if (!glock_workqueue)
+               return -ENOMEM;
        gfs2_delete_workqueue = alloc_workqueue("delete_workqueue",
                                                WQ_MEM_RECLAIM | WQ_FREEZABLE,
                                                0);
-       if (IS_ERR(gfs2_delete_workqueue)) {
+       if (!gfs2_delete_workqueue) {
                destroy_workqueue(glock_workqueue);
-               return PTR_ERR(gfs2_delete_workqueue);
+               return -ENOMEM;
        }
 
        register_shrinker(&glock_shrinker);
index 5f2e522..e2e0a90 100644 (file)
@@ -47,7 +47,8 @@ static void gfs2_ail_error(struct gfs2_glock *gl, const struct buffer_head *bh)
  * None of the buffers should be dirty, locked, or pinned.
  */
 
-static void __gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
+static void __gfs2_ail_flush(struct gfs2_glock *gl, bool fsync,
+                            unsigned int nr_revokes)
 {
        struct gfs2_sbd *sdp = gl->gl_sbd;
        struct list_head *head = &gl->gl_ail_list;
@@ -57,7 +58,9 @@ static void __gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
 
        gfs2_log_lock(sdp);
        spin_lock(&sdp->sd_ail_lock);
-       list_for_each_entry_safe(bd, tmp, head, bd_ail_gl_list) {
+       list_for_each_entry_safe_reverse(bd, tmp, head, bd_ail_gl_list) {
+               if (nr_revokes == 0)
+                       break;
                bh = bd->bd_bh;
                if (bh->b_state & b_state) {
                        if (fsync)
@@ -65,6 +68,7 @@ static void __gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
                        gfs2_ail_error(gl, bh);
                }
                gfs2_trans_add_revoke(sdp, bd);
+               nr_revokes--;
        }
        GLOCK_BUG_ON(gl, !fsync && atomic_read(&gl->gl_ail_count));
        spin_unlock(&sdp->sd_ail_lock);
@@ -91,7 +95,7 @@ static void gfs2_ail_empty_gl(struct gfs2_glock *gl)
        WARN_ON_ONCE(current->journal_info);
        current->journal_info = &tr;
 
-       __gfs2_ail_flush(gl, 0);
+       __gfs2_ail_flush(gl, 0, tr.tr_revokes);
 
        gfs2_trans_end(sdp);
        gfs2_log_flush(sdp, NULL);
@@ -101,15 +105,19 @@ void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
 {
        struct gfs2_sbd *sdp = gl->gl_sbd;
        unsigned int revokes = atomic_read(&gl->gl_ail_count);
+       unsigned int max_revokes = (sdp->sd_sb.sb_bsize - sizeof(struct gfs2_log_descriptor)) / sizeof(u64);
        int ret;
 
        if (!revokes)
                return;
 
-       ret = gfs2_trans_begin(sdp, 0, revokes);
+       while (revokes > max_revokes)
+               max_revokes += (sdp->sd_sb.sb_bsize - sizeof(struct gfs2_meta_header)) / sizeof(u64);
+
+       ret = gfs2_trans_begin(sdp, 0, max_revokes);
        if (ret)
                return;
-       __gfs2_ail_flush(gl, fsync);
+       __gfs2_ail_flush(gl, fsync, max_revokes);
        gfs2_trans_end(sdp);
        gfs2_log_flush(sdp, NULL);
 }
index bbb2715..64915ee 100644 (file)
@@ -594,7 +594,7 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
                }
                gfs2_glock_dq_uninit(ghs);
                if (IS_ERR(d))
-                       return PTR_RET(d);
+                       return PTR_ERR(d);
                return error;
        } else if (error != -ENOENT) {
                goto fail_gunlock;
@@ -1750,6 +1750,10 @@ static ssize_t gfs2_getxattr(struct dentry *dentry, const char *name,
        struct gfs2_holder gh;
        int ret;
 
+       /* For selinux during lookup */
+       if (gfs2_glock_is_locked_by_me(ip->i_gl))
+               return generic_getxattr(dentry, name, data, size);
+
        gfs2_holder_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &gh);
        ret = gfs2_glock_nq(&gh);
        if (ret == 0) {
index e04d0e0..7b0f504 100644 (file)
@@ -155,7 +155,7 @@ static int __init init_gfs2_fs(void)
                goto fail_wq;
 
        gfs2_control_wq = alloc_workqueue("gfs2_control",
-                              WQ_NON_REENTRANT | WQ_UNBOUND | WQ_FREEZABLE, 0);
+                                         WQ_UNBOUND | WQ_FREEZABLE, 0);
        if (!gfs2_control_wq)
                goto fail_recovery;
 
index 3442397..d19b30a 100644 (file)
@@ -926,14 +926,8 @@ static int get_hstate_idx(int page_size_log)
        return h - hstates;
 }
 
-static char *hugetlb_dname(struct dentry *dentry, char *buffer, int buflen)
-{
-       return dynamic_dname(dentry, buffer, buflen, "/%s (deleted)",
-                               dentry->d_name.name);
-}
-
 static struct dentry_operations anon_ops = {
-       .d_dname = hugetlb_dname
+       .d_dname = simple_dname
 };
 
 /*
index 7b1ca9b..a45ba4f 100644 (file)
@@ -1429,7 +1429,7 @@ struct vfsmount *collect_mounts(struct path *path)
                         CL_COPY_ALL | CL_PRIVATE);
        namespace_unlock();
        if (IS_ERR(tree))
-               return NULL;
+               return ERR_CAST(tree);
        return &tree->mnt;
 }
 
index dc9a913..2d8be51 100644 (file)
@@ -345,8 +345,7 @@ static void nilfs_end_bio_write(struct bio *bio, int err)
 
        if (err == -EOPNOTSUPP) {
                set_bit(BIO_EOPNOTSUPP, &bio->bi_flags);
-               bio_put(bio);
-               /* to be detected by submit_seg_bio() */
+               /* to be detected by nilfs_segbuf_submit_bio() */
        }
 
        if (!uptodate)
@@ -377,12 +376,12 @@ static int nilfs_segbuf_submit_bio(struct nilfs_segment_buffer *segbuf,
        bio->bi_private = segbuf;
        bio_get(bio);
        submit_bio(mode, bio);
+       segbuf->sb_nbio++;
        if (bio_flagged(bio, BIO_EOPNOTSUPP)) {
                bio_put(bio);
                err = -EOPNOTSUPP;
                goto failed;
        }
-       segbuf->sb_nbio++;
        bio_put(bio);
 
        wi->bio = NULL;
index 75f2890..0ff80f9 100644 (file)
@@ -230,8 +230,6 @@ static int proc_readfd_common(struct file *file, struct dir_context *ctx,
 
        if (!dir_emit_dots(file, ctx))
                goto out;
-       if (!dir_emit_dots(file, ctx))
-               goto out;
        files = get_files_struct(p);
        if (!files)
                goto out;
index 94441a4..737e156 100644 (file)
@@ -271,7 +271,7 @@ int proc_readdir_de(struct proc_dir_entry *de, struct file *file,
                de = next;
        } while (de);
        spin_unlock(&proc_subdir_lock);
-       return 0;
+       return 1;
 }
 
 int proc_readdir(struct file *file, struct dir_context *ctx)
index 229e366..e0a790d 100644 (file)
@@ -205,7 +205,9 @@ static struct dentry *proc_root_lookup(struct inode * dir, struct dentry * dentr
 static int proc_root_readdir(struct file *file, struct dir_context *ctx)
 {
        if (ctx->pos < FIRST_PROCESS_ENTRY) {
-               proc_readdir(file, ctx);
+               int error = proc_readdir(file, ctx);
+               if (unlikely(error <= 0))
+                       return error;
                ctx->pos = FIRST_PROCESS_ENTRY;
        }
 
index b90337c..4a12532 100644 (file)
@@ -336,6 +336,7 @@ extern int d_validate(struct dentry *, struct dentry *);
  * helper function for dentry_operations.d_dname() members
  */
 extern char *dynamic_dname(struct dentry *, char *, int, const char *, ...);
+extern char *simple_dname(struct dentry *, char *, int);
 
 extern char *__d_path(const struct path *, const struct path *, char *, int);
 extern char *d_absolute_path(const struct path *, char *, int);
index b99cd23..79640e0 100644 (file)
@@ -5,45 +5,13 @@
 
 #include <linux/bitmap.h>
 #include <linux/if.h>
+#include <linux/ip.h>
 #include <linux/netdevice.h>
 #include <linux/rcupdate.h>
 #include <linux/timer.h>
 #include <linux/sysctl.h>
 #include <linux/rtnetlink.h>
 
-enum
-{
-       IPV4_DEVCONF_FORWARDING=1,
-       IPV4_DEVCONF_MC_FORWARDING,
-       IPV4_DEVCONF_PROXY_ARP,
-       IPV4_DEVCONF_ACCEPT_REDIRECTS,
-       IPV4_DEVCONF_SECURE_REDIRECTS,
-       IPV4_DEVCONF_SEND_REDIRECTS,
-       IPV4_DEVCONF_SHARED_MEDIA,
-       IPV4_DEVCONF_RP_FILTER,
-       IPV4_DEVCONF_ACCEPT_SOURCE_ROUTE,
-       IPV4_DEVCONF_BOOTP_RELAY,
-       IPV4_DEVCONF_LOG_MARTIANS,
-       IPV4_DEVCONF_TAG,
-       IPV4_DEVCONF_ARPFILTER,
-       IPV4_DEVCONF_MEDIUM_ID,
-       IPV4_DEVCONF_NOXFRM,
-       IPV4_DEVCONF_NOPOLICY,
-       IPV4_DEVCONF_FORCE_IGMP_VERSION,
-       IPV4_DEVCONF_ARP_ANNOUNCE,
-       IPV4_DEVCONF_ARP_IGNORE,
-       IPV4_DEVCONF_PROMOTE_SECONDARIES,
-       IPV4_DEVCONF_ARP_ACCEPT,
-       IPV4_DEVCONF_ARP_NOTIFY,
-       IPV4_DEVCONF_ACCEPT_LOCAL,
-       IPV4_DEVCONF_SRC_VMARK,
-       IPV4_DEVCONF_PROXY_ARP_PVLAN,
-       IPV4_DEVCONF_ROUTE_LOCALNET,
-       __IPV4_DEVCONF_MAX
-};
-
-#define IPV4_DEVCONF_MAX (__IPV4_DEVCONF_MAX - 1)
-
 struct ipv4_devconf {
        void    *sysctl;
        int     data[IPV4_DEVCONF_MAX];
index 850e95b..b8b7dc7 100644 (file)
@@ -101,6 +101,7 @@ struct inet6_skb_parm {
 #define IP6SKB_FORWARDED       2
 #define IP6SKB_REROUTED                4
 #define IP6SKB_ROUTERALERT     8
+#define IP6SKB_FRAGMENTED      16
 };
 
 #define IP6CB(skb)     ((struct inet6_skb_parm*)((skb)->cb))
index fb425aa..faf4b7c 100644 (file)
@@ -332,6 +332,7 @@ struct mm_struct {
                                unsigned long pgoff, unsigned long flags);
 #endif
        unsigned long mmap_base;                /* base of mmap area */
+       unsigned long mmap_legacy_base;         /* base of mmap area in bottom-up allocations */
        unsigned long task_size;                /* size of task vm space */
        unsigned long highest_vm_end;           /* highest vma end address */
        pgd_t * pgd;
diff --git a/include/linux/platform_data/efm32-spi.h b/include/linux/platform_data/efm32-spi.h
new file mode 100644 (file)
index 0000000..31b19ca
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef __LINUX_PLATFORM_DATA_EFM32_SPI_H__
+#define __LINUX_PLATFORM_DATA_EFM32_SPI_H__
+
+#include <linux/types.h>
+
+/**
+ * struct efm32_spi_pdata
+ * @location: pinmux location for the I/O pins (to be written to the ROUTE
+ *     register)
+ */
+struct efm32_spi_pdata {
+       u8 location;
+};
+#endif /* ifndef __LINUX_PLATFORM_DATA_EFM32_SPI_H__ */
index e9995eb..078066d 100644 (file)
@@ -314,7 +314,6 @@ struct nsproxy;
 struct user_namespace;
 
 #ifdef CONFIG_MMU
-extern unsigned long mmap_legacy_base(void);
 extern void arch_pick_mmap_layout(struct mm_struct *mm);
 extern unsigned long
 arch_get_unmapped_area(struct file *, unsigned long, unsigned long,
index 28e440b..47854f3 100644 (file)
@@ -233,6 +233,8 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
  *     suported. If set, the SPI core will reject any transfer with an
  *     unsupported bits_per_word. If not set, this value is simply ignored,
  *     and it's up to the individual driver to perform any validation.
+ * @min_speed_hz: Lowest supported transfer speed
+ * @max_speed_hz: Highest supported transfer speed
  * @flags: other constraints relevant to this driver
  * @bus_lock_spinlock: spinlock for SPI bus locking
  * @bus_lock_mutex: mutex for SPI bus locking
@@ -309,9 +311,13 @@ struct spi_master {
        /* bitmask of supported bits_per_word for transfers */
        u32                     bits_per_word_mask;
 #define SPI_BPW_MASK(bits) BIT((bits) - 1)
-#define SPI_BIT_MASK(bits) (((bits) == 32) ? ~0UL : (BIT(bits) - 1))
+#define SPI_BIT_MASK(bits) (((bits) == 32) ? ~0U : (BIT(bits) - 1))
 #define SPI_BPW_RANGE_MASK(min, max) (SPI_BIT_MASK(max) - SPI_BIT_MASK(min - 1))
 
+       /* limits on transfer speed */
+       u32                     min_speed_hz;
+       u32                     max_speed_hz;
+
        /* other constraints relevant to this driver */
        u16                     flags;
 #define SPI_MASTER_HALF_DUPLEX BIT(0)          /* can't do full duplex */
index f987a2b..daebaba 100644 (file)
@@ -4,11 +4,7 @@
 #include <linux/workqueue.h>
 
 struct spi_bitbang {
-       struct workqueue_struct *workqueue;
-       struct work_struct      work;
-
        spinlock_t              lock;
-       struct list_head        queue;
        u8                      busy;
        u8                      use_dma;
        u8                      flags;          /* extra spi->mode support */
@@ -41,7 +37,6 @@ struct spi_bitbang {
  */
 extern int spi_bitbang_setup(struct spi_device *spi);
 extern void spi_bitbang_cleanup(struct spi_device *spi);
-extern int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m);
 extern int spi_bitbang_setup_transfer(struct spi_device *spi,
                                      struct spi_transfer *t);
 
index f487a47..a67fc16 100644 (file)
@@ -811,6 +811,63 @@ do {                                                                       \
        __ret;                                                          \
 })
 
+#define __wait_event_interruptible_lock_irq_timeout(wq, condition,     \
+                                                   lock, ret)          \
+do {                                                                   \
+       DEFINE_WAIT(__wait);                                            \
+                                                                       \
+       for (;;) {                                                      \
+               prepare_to_wait(&wq, &__wait, TASK_INTERRUPTIBLE);      \
+               if (condition)                                          \
+                       break;                                          \
+               if (signal_pending(current)) {                          \
+                       ret = -ERESTARTSYS;                             \
+                       break;                                          \
+               }                                                       \
+               spin_unlock_irq(&lock);                                 \
+               ret = schedule_timeout(ret);                            \
+               spin_lock_irq(&lock);                                   \
+               if (!ret)                                               \
+                       break;                                          \
+       }                                                               \
+       finish_wait(&wq, &__wait);                                      \
+} while (0)
+
+/**
+ * wait_event_interruptible_lock_irq_timeout - sleep until a condition gets true or a timeout elapses.
+ *             The condition is checked under the lock. This is expected
+ *             to be called with the lock taken.
+ * @wq: the waitqueue to wait on
+ * @condition: a C expression for the event to wait for
+ * @lock: a locked spinlock_t, which will be released before schedule()
+ *       and reacquired afterwards.
+ * @timeout: timeout, in jiffies
+ *
+ * The process is put to sleep (TASK_INTERRUPTIBLE) until the
+ * @condition evaluates to true or signal is received. The @condition is
+ * checked each time the waitqueue @wq is woken up.
+ *
+ * wake_up() has to be called after changing any variable that could
+ * change the result of the wait condition.
+ *
+ * This is supposed to be called while holding the lock. The lock is
+ * dropped before going to sleep and is reacquired afterwards.
+ *
+ * The function returns 0 if the @timeout elapsed, -ERESTARTSYS if it
+ * was interrupted by a signal, and the remaining jiffies otherwise
+ * if the condition evaluated to true before the timeout elapsed.
+ */
+#define wait_event_interruptible_lock_irq_timeout(wq, condition, lock, \
+                                                 timeout)              \
+({                                                                     \
+       int __ret = timeout;                                            \
+                                                                       \
+       if (!(condition))                                               \
+               __wait_event_interruptible_lock_irq_timeout(            \
+                                       wq, condition, lock, __ret);    \
+       __ret;                                                          \
+})
+
 
 /*
  * These are the old interfaces to sleep waiting for an event.
index 260f83f..f667248 100644 (file)
@@ -135,6 +135,8 @@ extern void ip6_update_pmtu(struct sk_buff *skb, struct net *net, __be32 mtu,
 extern void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk,
                               __be32 mtu);
 extern void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark);
+extern void ip6_redirect_no_header(struct sk_buff *skb, struct net *net, int oif,
+                                  u32 mark);
 extern void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk);
 
 struct netlink_callback;
index 6cf06bf..2fee45b 100644 (file)
@@ -133,4 +133,38 @@ struct ip_beet_phdr {
        __u8 reserved;
 };
 
+/* index values for the variables in ipv4_devconf */
+enum
+{
+       IPV4_DEVCONF_FORWARDING=1,
+       IPV4_DEVCONF_MC_FORWARDING,
+       IPV4_DEVCONF_PROXY_ARP,
+       IPV4_DEVCONF_ACCEPT_REDIRECTS,
+       IPV4_DEVCONF_SECURE_REDIRECTS,
+       IPV4_DEVCONF_SEND_REDIRECTS,
+       IPV4_DEVCONF_SHARED_MEDIA,
+       IPV4_DEVCONF_RP_FILTER,
+       IPV4_DEVCONF_ACCEPT_SOURCE_ROUTE,
+       IPV4_DEVCONF_BOOTP_RELAY,
+       IPV4_DEVCONF_LOG_MARTIANS,
+       IPV4_DEVCONF_TAG,
+       IPV4_DEVCONF_ARPFILTER,
+       IPV4_DEVCONF_MEDIUM_ID,
+       IPV4_DEVCONF_NOXFRM,
+       IPV4_DEVCONF_NOPOLICY,
+       IPV4_DEVCONF_FORCE_IGMP_VERSION,
+       IPV4_DEVCONF_ARP_ANNOUNCE,
+       IPV4_DEVCONF_ARP_IGNORE,
+       IPV4_DEVCONF_PROMOTE_SECONDARIES,
+       IPV4_DEVCONF_ARP_ACCEPT,
+       IPV4_DEVCONF_ARP_NOTIFY,
+       IPV4_DEVCONF_ACCEPT_LOCAL,
+       IPV4_DEVCONF_SRC_VMARK,
+       IPV4_DEVCONF_PROXY_ARP_PVLAN,
+       IPV4_DEVCONF_ROUTE_LOCALNET,
+       __IPV4_DEVCONF_MAX
+};
+
+#define IPV4_DEVCONF_MAX (__IPV4_DEVCONF_MAX - 1)
+
 #endif /* _UAPI_LINUX_IP_H */
index 247084b..fed81b5 100644 (file)
@@ -955,7 +955,7 @@ config MEMCG_SWAP_ENABLED
          Memory Resource Controller Swap Extension comes with its price in
          a bigger memory consumption. General purpose distribution kernels
          which want to enable the feature but keep it disabled by default
-         and let the user enable it by swapaccount boot command line
+         and let the user enable it by swapaccount=1 boot command line
          parameter should have this option unselected.
          For those who want to have the feature enabled by default should
          select this option (if, for some reason, they need to disable it
index 010a008..ea1966d 100644 (file)
@@ -475,13 +475,17 @@ static int validate_change(const struct cpuset *cur, const struct cpuset *trial)
 
        /*
         * Cpusets with tasks - existing or newly being attached - can't
-        * have empty cpus_allowed or mems_allowed.
+        * be changed to have empty cpus_allowed or mems_allowed.
         */
        ret = -ENOSPC;
-       if ((cgroup_task_count(cur->css.cgroup) || cur->attach_in_progress) &&
-           (cpumask_empty(trial->cpus_allowed) &&
-            nodes_empty(trial->mems_allowed)))
-               goto out;
+       if ((cgroup_task_count(cur->css.cgroup) || cur->attach_in_progress)) {
+               if (!cpumask_empty(cur->cpus_allowed) &&
+                   cpumask_empty(trial->cpus_allowed))
+                       goto out;
+               if (!nodes_empty(cur->mems_allowed) &&
+                   nodes_empty(trial->mems_allowed))
+                       goto out;
+       }
 
        ret = 0;
 out:
index a326f27..0b479a6 100644 (file)
@@ -121,7 +121,7 @@ void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate)
        BUG_ON(bits > 32);
        WARN_ON(!irqs_disabled());
        read_sched_clock = read;
-       sched_clock_mask = (1 << bits) - 1;
+       sched_clock_mask = (1ULL << bits) - 1;
        cd.rate = rate;
 
        /* calculate the mult/shift to convert counter ticks to ns. */
index e77edc9..e8a1516 100644 (file)
@@ -182,7 +182,8 @@ static bool can_stop_full_tick(void)
                 * Don't allow the user to think they can get
                 * full NO_HZ with this machine.
                 */
-               WARN_ONCE(1, "NO_HZ FULL will not work with unstable sched clock");
+               WARN_ONCE(have_nohz_full_mask,
+                         "NO_HZ FULL will not work with unstable sched clock");
                return false;
        }
 #endif
@@ -343,8 +344,6 @@ static int tick_nohz_init_all(void)
 
 void __init tick_nohz_init(void)
 {
-       int cpu;
-
        if (!have_nohz_full_mask) {
                if (tick_nohz_init_all() < 0)
                        return;
index dec68bd..d550920 100644 (file)
@@ -363,8 +363,7 @@ EXPORT_SYMBOL(out_of_line_wait_on_atomic_t);
 
 /**
  * wake_up_atomic_t - Wake up a waiter on a atomic_t
- * @word: The word being waited on, a kernel virtual address
- * @bit: The bit of the word being waited on
+ * @p: The atomic_t being waited on, a kernel virtual address
  *
  * Wake up anyone waiting for the atomic_t to go to zero.
  *
index fd94058..28321d8 100644 (file)
@@ -437,7 +437,7 @@ int lz4_compress(const unsigned char *src, size_t src_len,
 exit:
        return ret;
 }
-EXPORT_SYMBOL_GPL(lz4_compress);
+EXPORT_SYMBOL(lz4_compress);
 
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("Dual BSD/GPL");
 MODULE_DESCRIPTION("LZ4 compressor");
index d3414ea..411be80 100644 (file)
@@ -299,7 +299,7 @@ exit_0:
        return ret;
 }
 #ifndef STATIC
-EXPORT_SYMBOL_GPL(lz4_decompress);
+EXPORT_SYMBOL(lz4_decompress);
 #endif
 
 int lz4_decompress_unknownoutputsize(const char *src, size_t src_len,
@@ -319,8 +319,8 @@ exit_0:
        return ret;
 }
 #ifndef STATIC
-EXPORT_SYMBOL_GPL(lz4_decompress_unknownoutputsize);
+EXPORT_SYMBOL(lz4_decompress_unknownoutputsize);
 
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("Dual BSD/GPL");
 MODULE_DESCRIPTION("LZ4 Decompressor");
 #endif
index eb1a74f..f344f76 100644 (file)
@@ -533,7 +533,7 @@ int lz4hc_compress(const unsigned char *src, size_t src_len,
 exit:
        return ret;
 }
-EXPORT_SYMBOL_GPL(lz4hc_compress);
+EXPORT_SYMBOL(lz4hc_compress);
 
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("Dual BSD/GPL");
 MODULE_DESCRIPTION("LZ4HC compressor");
index c5792a5..0878ff7 100644 (file)
@@ -6969,7 +6969,6 @@ struct cgroup_subsys mem_cgroup_subsys = {
 #ifdef CONFIG_MEMCG_SWAP
 static int __init enable_swap_account(char *s)
 {
-       /* consider enabled if no parameter or 1 is given */
        if (!strcmp(s, "1"))
                really_do_swap_account = 1;
        else if (!strcmp(s, "0"))
index 8335dbd..e43dc55 100644 (file)
@@ -2909,14 +2909,8 @@ EXPORT_SYMBOL_GPL(shmem_truncate_range);
 
 /* common code */
 
-static char *shmem_dname(struct dentry *dentry, char *buffer, int buflen)
-{
-       return dynamic_dname(dentry, buffer, buflen, "/%s (deleted)",
-                               dentry->d_name.name);
-}
-
 static struct dentry_operations anon_ops = {
-       .d_dname = shmem_dname
+       .d_dname = simple_dname
 };
 
 /**
index 688a041..857e1b8 100644 (file)
@@ -432,12 +432,16 @@ find_router:
 
        switch (packet_type) {
        case BATADV_UNICAST:
-               batadv_unicast_prepare_skb(skb, orig_node);
+               if (!batadv_unicast_prepare_skb(skb, orig_node))
+                       goto out;
+
                header_len = sizeof(struct batadv_unicast_packet);
                break;
        case BATADV_UNICAST_4ADDR:
-               batadv_unicast_4addr_prepare_skb(bat_priv, skb, orig_node,
-                                                packet_subtype);
+               if (!batadv_unicast_4addr_prepare_skb(bat_priv, skb, orig_node,
+                                                     packet_subtype))
+                       goto out;
+
                header_len = sizeof(struct batadv_unicast_4addr_packet);
                break;
        default:
index 60aca91..ffd5874 100644 (file)
@@ -161,7 +161,7 @@ void br_fdb_change_mac_address(struct net_bridge *br, const u8 *newaddr)
        if (!pv)
                return;
 
-       for_each_set_bit_from(vid, pv->vlan_bitmap, BR_VLAN_BITMAP_LEN) {
+       for_each_set_bit_from(vid, pv->vlan_bitmap, VLAN_N_VID) {
                f = __br_fdb_get(br, br->dev->dev_addr, vid);
                if (f && f->is_local && !f->dst)
                        fdb_delete(br, f);
@@ -730,7 +730,7 @@ int br_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
                /* VID was specified, so use it. */
                err = __br_fdb_add(ndm, p, addr, nlh_flags, vid);
        } else {
-               if (!pv || bitmap_empty(pv->vlan_bitmap, BR_VLAN_BITMAP_LEN)) {
+               if (!pv || bitmap_empty(pv->vlan_bitmap, VLAN_N_VID)) {
                        err = __br_fdb_add(ndm, p, addr, nlh_flags, 0);
                        goto out;
                }
@@ -739,7 +739,7 @@ int br_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
                 * specify a VLAN.  To be nice, add/update entry for every
                 * vlan on this port.
                 */
-               for_each_set_bit(vid, pv->vlan_bitmap, BR_VLAN_BITMAP_LEN) {
+               for_each_set_bit(vid, pv->vlan_bitmap, VLAN_N_VID) {
                        err = __br_fdb_add(ndm, p, addr, nlh_flags, vid);
                        if (err)
                                goto out;
@@ -817,7 +817,7 @@ int br_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[],
 
                err = __br_fdb_delete(p, addr, vid);
        } else {
-               if (!pv || bitmap_empty(pv->vlan_bitmap, BR_VLAN_BITMAP_LEN)) {
+               if (!pv || bitmap_empty(pv->vlan_bitmap, VLAN_N_VID)) {
                        err = __br_fdb_delete(p, addr, 0);
                        goto out;
                }
@@ -827,7 +827,7 @@ int br_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[],
                 * vlan on this port.
                 */
                err = -ENOENT;
-               for_each_set_bit(vid, pv->vlan_bitmap, BR_VLAN_BITMAP_LEN) {
+               for_each_set_bit(vid, pv->vlan_bitmap, VLAN_N_VID) {
                        err &= __br_fdb_delete(p, addr, vid);
                }
        }
index 1fc30ab..b9259ef 100644 (file)
@@ -132,7 +132,7 @@ static int br_fill_ifinfo(struct sk_buff *skb,
                else
                        pv = br_get_vlan_info(br);
 
-               if (!pv || bitmap_empty(pv->vlan_bitmap, BR_VLAN_BITMAP_LEN))
+               if (!pv || bitmap_empty(pv->vlan_bitmap, VLAN_N_VID))
                        goto done;
 
                af = nla_nest_start(skb, IFLA_AF_SPEC);
@@ -140,7 +140,7 @@ static int br_fill_ifinfo(struct sk_buff *skb,
                        goto nla_put_failure;
 
                pvid = br_get_pvid(pv);
-               for_each_set_bit(vid, pv->vlan_bitmap, BR_VLAN_BITMAP_LEN) {
+               for_each_set_bit(vid, pv->vlan_bitmap, VLAN_N_VID) {
                        vinfo.vid = vid;
                        vinfo.flags = 0;
                        if (vid == pvid)
index bd58b45..9a9ffe7 100644 (file)
@@ -108,7 +108,7 @@ static int __vlan_del(struct net_port_vlans *v, u16 vid)
 
        clear_bit(vid, v->vlan_bitmap);
        v->num_vlans--;
-       if (bitmap_empty(v->vlan_bitmap, BR_VLAN_BITMAP_LEN)) {
+       if (bitmap_empty(v->vlan_bitmap, VLAN_N_VID)) {
                if (v->port_idx)
                        rcu_assign_pointer(v->parent.port->vlan_info, NULL);
                else
@@ -122,7 +122,7 @@ static void __vlan_flush(struct net_port_vlans *v)
 {
        smp_wmb();
        v->pvid = 0;
-       bitmap_zero(v->vlan_bitmap, BR_VLAN_BITMAP_LEN);
+       bitmap_zero(v->vlan_bitmap, VLAN_N_VID);
        if (v->port_idx)
                rcu_assign_pointer(v->parent.port->vlan_info, NULL);
        else
index 5423223..b2f6c74 100644 (file)
@@ -1121,6 +1121,13 @@ new_segment:
                                        goto wait_for_memory;
 
                                /*
+                                * All packets are restored as if they have
+                                * already been sent.
+                                */
+                               if (tp->repair)
+                                       TCP_SKB_CB(skb)->when = tcp_time_stamp;
+
+                               /*
                                 * Check whether we can use HW checksum.
                                 */
                                if (sk->sk_route_caps & NETIF_F_ALL_CSUM)
index da4241c..498ea99 100644 (file)
@@ -1126,12 +1126,10 @@ retry:
        if (ifp->flags & IFA_F_OPTIMISTIC)
                addr_flags |= IFA_F_OPTIMISTIC;
 
-       ift = !max_addresses ||
-             ipv6_count_addresses(idev) < max_addresses ?
-               ipv6_add_addr(idev, &addr, NULL, tmp_plen,
-                             ipv6_addr_scope(&addr), addr_flags,
-                             tmp_valid_lft, tmp_prefered_lft) : NULL;
-       if (IS_ERR_OR_NULL(ift)) {
+       ift = ipv6_add_addr(idev, &addr, NULL, tmp_plen,
+                           ipv6_addr_scope(&addr), addr_flags,
+                           tmp_valid_lft, tmp_prefered_lft);
+       if (IS_ERR(ift)) {
                in6_ifa_put(ifp);
                in6_dev_put(idev);
                pr_info("%s: retry temporary address regeneration\n", __func__);
index 79aa965..04d31c2 100644 (file)
@@ -1369,8 +1369,10 @@ static void ndisc_redirect_rcv(struct sk_buff *skb)
        if (!ndisc_parse_options(msg->opt, ndoptlen, &ndopts))
                return;
 
-       if (!ndopts.nd_opts_rh)
+       if (!ndopts.nd_opts_rh) {
+               ip6_redirect_no_header(skb, dev_net(skb->dev), 0, 0);
                return;
+       }
 
        hdr = (u8 *)ndopts.nd_opts_rh;
        hdr += 8;
index 790d9f4..1aeb473 100644 (file)
@@ -490,6 +490,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev,
        ipv6_hdr(head)->payload_len = htons(payload_len);
        ipv6_change_dsfield(ipv6_hdr(head), 0xff, ecn);
        IP6CB(head)->nhoff = nhoff;
+       IP6CB(head)->flags |= IP6SKB_FRAGMENTED;
 
        /* Yes, and fold redundant checksum back. 8) */
        if (head->ip_summed == CHECKSUM_COMPLETE)
@@ -524,6 +525,9 @@ static int ipv6_frag_rcv(struct sk_buff *skb)
        struct net *net = dev_net(skb_dst(skb)->dev);
        int evicted;
 
+       if (IP6CB(skb)->flags & IP6SKB_FRAGMENTED)
+               goto fail_hdr;
+
        IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_REASMREQDS);
 
        /* Jumbo payload inhibits frag. header */
@@ -544,6 +548,7 @@ static int ipv6_frag_rcv(struct sk_buff *skb)
                                 ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_REASMOKS);
 
                IP6CB(skb)->nhoff = (u8 *)fhdr - skb_network_header(skb);
+               IP6CB(skb)->flags |= IP6SKB_FRAGMENTED;
                return 1;
        }
 
index b70f897..8d9a93e 100644 (file)
@@ -1178,6 +1178,27 @@ void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark)
 }
 EXPORT_SYMBOL_GPL(ip6_redirect);
 
+void ip6_redirect_no_header(struct sk_buff *skb, struct net *net, int oif,
+                           u32 mark)
+{
+       const struct ipv6hdr *iph = ipv6_hdr(skb);
+       const struct rd_msg *msg = (struct rd_msg *)icmp6_hdr(skb);
+       struct dst_entry *dst;
+       struct flowi6 fl6;
+
+       memset(&fl6, 0, sizeof(fl6));
+       fl6.flowi6_oif = oif;
+       fl6.flowi6_mark = mark;
+       fl6.flowi6_flags = 0;
+       fl6.daddr = msg->dest;
+       fl6.saddr = iph->daddr;
+
+       dst = ip6_route_output(net, NULL, &fl6);
+       if (!dst->error)
+               rt6_do_redirect(dst, NULL, skb);
+       dst_release(dst);
+}
+
 void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk)
 {
        ip6_redirect(skb, sock_net(sk), sk->sk_bound_dev_if, sk->sk_mark);
index f85f8a2..512718a 100644 (file)
@@ -789,10 +789,6 @@ static int ctrl_dumpfamily(struct sk_buff *skb, struct netlink_callback *cb)
        struct net *net = sock_net(skb->sk);
        int chains_to_skip = cb->args[0];
        int fams_to_skip = cb->args[1];
-       bool need_locking = chains_to_skip || fams_to_skip;
-
-       if (need_locking)
-               genl_lock();
 
        for (i = chains_to_skip; i < GENL_FAM_TAB_SIZE; i++) {
                n = 0;
@@ -814,9 +810,6 @@ errout:
        cb->args[0] = i;
        cb->args[1] = n;
 
-       if (need_locking)
-               genl_unlock();
-
        return skb->len;
 }
 
index 4b66c75..75c8bbf 100644 (file)
@@ -3259,9 +3259,11 @@ static int packet_getsockopt(struct socket *sock, int level, int optname,
 
                if (po->tp_version == TPACKET_V3) {
                        lv = sizeof(struct tpacket_stats_v3);
+                       st.stats3.tp_packets += st.stats3.tp_drops;
                        data = &st.stats3;
                } else {
                        lv = sizeof(struct tpacket_stats);
+                       st.stats1.tp_packets += st.stats1.tp_drops;
                        data = &st.stats1;
                }
 
index 3fcba69..5f6e982 100644 (file)
@@ -2622,8 +2622,8 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
 
        hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
                             NL80211_CMD_NEW_KEY);
-       if (IS_ERR(hdr))
-               return PTR_ERR(hdr);
+       if (!hdr)
+               return -ENOBUFS;
 
        cookie.msg = msg;
        cookie.idx = key_idx;
@@ -6507,6 +6507,9 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
                                           NL80211_CMD_TESTMODE);
                struct nlattr *tmdata;
 
+               if (!hdr)
+                       break;
+
                if (nla_put_u32(skb, NL80211_ATTR_WIPHY, phy_idx)) {
                        genlmsg_cancel(skb, hdr);
                        break;
@@ -6951,9 +6954,8 @@ static int nl80211_remain_on_channel(struct sk_buff *skb,
 
        hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
                             NL80211_CMD_REMAIN_ON_CHANNEL);
-
-       if (IS_ERR(hdr)) {
-               err = PTR_ERR(hdr);
+       if (!hdr) {
+               err = -ENOBUFS;
                goto free_msg;
        }
 
@@ -7251,9 +7253,8 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
 
                hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
                                     NL80211_CMD_FRAME);
-
-               if (IS_ERR(hdr)) {
-                       err = PTR_ERR(hdr);
+               if (!hdr) {
+                       err = -ENOBUFS;
                        goto free_msg;
                }
        }
@@ -8132,9 +8133,8 @@ static int nl80211_probe_client(struct sk_buff *skb,
 
        hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
                             NL80211_CMD_PROBE_CLIENT);
-
-       if (IS_ERR(hdr)) {
-               err = PTR_ERR(hdr);
+       if (!hdr) {
+               err = -ENOBUFS;
                goto free_msg;
        }
 
index 81c8a10..20e86a9 100644 (file)
@@ -976,21 +976,19 @@ int cfg80211_disconnect(struct cfg80211_registered_device *rdev,
                        struct net_device *dev, u16 reason, bool wextev)
 {
        struct wireless_dev *wdev = dev->ieee80211_ptr;
-       int err;
+       int err = 0;
 
        ASSERT_WDEV_LOCK(wdev);
 
        kfree(wdev->connect_keys);
        wdev->connect_keys = NULL;
 
-       if (wdev->conn) {
+       if (wdev->conn)
                err = cfg80211_sme_disconnect(wdev, reason);
-       } else if (!rdev->ops->disconnect) {
+       else if (!rdev->ops->disconnect)
                cfg80211_mlme_down(rdev, dev);
-               err = 0;
-       } else {
+       else if (wdev->current_bss)
                err = rdev_disconnect(rdev, dev, reason);
-       }
 
        return err;
 }