Merge tag 'regulator-v3.12' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie...
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 3 Sep 2013 17:09:29 +0000 (10:09 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 3 Sep 2013 17:09:29 +0000 (10:09 -0700)
Pull regulator updates from Mark Brown:
 "Not much exciting going on with the regulator API this time around,
  lots of driver fixes and enhancements - the main thing is the addition
  of a new API to help make the stubbing code do the right thing for
  missing regulator mappings.

  Highlights:

   - A new regulator_get_optional() API call for regulators that can be
     absent in normal operation.  This currently does nothing but will
     be used to improve the stubbing code for unspecified regulators,
     helping avoid some of the issues we've seen with adding new
     regulator support.
   - Helpers for devices with multiple linear ranges of voltages in the
     same regulator.
   - Moved the helpers into a separate file since core.c is getting
     rather large.
   - New drivers for Dialog DA9210 and DA9063, Freescale pfuze100 and
     Marvell 88pm800"

* tag 'regulator-v3.12' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator: (70 commits)
  regulator: da9063: Statize da9063_ldo_lim_event
  regulator: lp872x: Make REGULATOR_LP872X depend on I2C rather than I2C=y
  regulator: tps65217: Convert to use linear ranges
  regulator: da9063: Use IS_ERR to check return value of regulator_register()
  regulator: da9063: Optimize da9063_set_current_limit implementation
  regulator: build: Allow most regulators to be built as modules
  regulator: Add devm_regulator_get_exclusive()
  regulator: da9063: Add Dialog DA9063 voltage regulators support.
  regulator: ti-abb: simplify platform_get_resource_byname/devm_ioremap_resource
  hwmon: (sht15) Use devm_regulator_get_optional()
  regulator: core: Use bool for exclusivitity flag
  regulator: 88pm800: forever loop in pm800_regulator_probe()
  cpufreq: cpufreq-cpu0: Use devm_regulator_get_optional()
  regulator: da9210: Remove redundant MODULE_ALIAS
  regulator: 88pm800: Fix checking whether num_regulator is valid
  regulator: s2mps11: Fix setting ramp_delay
  regulator: s2mps11: Fix wrong arguments for regmap_update_bits() call
  regulator: palmas: Update the DT binding doc for smps10 out1 and out2
  regulator: palmas: model SMPS10 as two regulators
  regulator: core: Move list_voltage_{linear,linear_range,table} to helpers.c
  ...

168 files changed:
Documentation/devicetree/bindings/spi/efm32-spi.txt [new file with mode: 0644]
Documentation/devicetree/bindings/spi/spi-bus.txt
Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt [new file with mode: 0644]
Documentation/devicetree/bindings/spi/ti_qspi.txt [new file with mode: 0644]
Documentation/spi/spi-summary
MAINTAINERS
Makefile
arch/arm/mach-prima2/common.c
arch/powerpc/Kconfig
arch/powerpc/include/asm/page.h
arch/powerpc/kernel/lparcfg.c
arch/x86/Kconfig
arch/x86/include/asm/spinlock.h
arch/x86/mm/init.c
drivers/base/memory.c
drivers/base/regmap/internal.h
drivers/base/regmap/regcache-rbtree.c
drivers/base/regmap/regcache.c
drivers/base/regmap/regmap-debugfs.c
drivers/base/regmap/regmap-irq.c
drivers/base/regmap/regmap.c
drivers/dma/Kconfig
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c
drivers/input/joystick/xpad.c
drivers/input/mouse/elantech.c
drivers/input/mouse/elantech.h
drivers/input/serio/Kconfig
drivers/input/tablet/wacom_wac.c
drivers/irqchip/irq-sirfsoc.c
drivers/isdn/mISDN/dsp_core.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h
drivers/net/ethernet/emulex/benet/be_main.c
drivers/net/ethernet/freescale/fec_main.c
drivers/net/ethernet/jme.c
drivers/net/ethernet/qlogic/netxen/netxen_nic.h
drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
drivers/net/ethernet/toshiba/ps3_gelic_net.c
drivers/net/ethernet/toshiba/ps3_gelic_net.h
drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c
drivers/net/usb/cdc_mbim.c
drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
drivers/net/wireless/ath/ath9k/init.c
drivers/net/wireless/ath/ath9k/main.c
drivers/net/wireless/ath/carl9170/main.c
drivers/net/wireless/iwlegacy/4965-mac.c
drivers/net/wireless/rt2x00/rt2800lib.c
drivers/scsi/pm8001/pm8001_hwi.c
drivers/scsi/pm8001/pm80xx_hwi.c
drivers/spi/Kconfig
drivers/spi/Makefile
drivers/spi/spi-altera.c
drivers/spi/spi-ath79.c
drivers/spi/spi-atmel.c
drivers/spi/spi-au1550.c
drivers/spi/spi-bcm2835.c
drivers/spi/spi-bcm63xx.c
drivers/spi/spi-bfin-sport.c
drivers/spi/spi-bfin-v3.c [new file with mode: 0644]
drivers/spi/spi-bfin5xx.c
drivers/spi/spi-bitbang.c
drivers/spi/spi-clps711x.c
drivers/spi/spi-coldfire-qspi.c
drivers/spi/spi-davinci.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-fsl-espi.c
drivers/spi/spi-fsl-lib.c
drivers/spi/spi-fsl-spi.c
drivers/spi/spi-gpio.c
drivers/spi/spi-imx.c
drivers/spi/spi-mpc512x-psc.c
drivers/spi/spi-mpc52xx-psc.c
drivers/spi/spi-mxs.c
drivers/spi/spi-nuc900.c
drivers/spi/spi-oc-tiny.c
drivers/spi/spi-octeon.c
drivers/spi/spi-omap-100k.c
drivers/spi/spi-omap2-mcspi.c
drivers/spi/spi-orion.c
drivers/spi/spi-pl022.c
drivers/spi/spi-pxa2xx.c
drivers/spi/spi-rspi.c
drivers/spi/spi-s3c24xx.c
drivers/spi/spi-s3c64xx.c
drivers/spi/spi-sh-hspi.c
drivers/spi/spi-sh-msiof.c
drivers/spi/spi-sh-sci.c
drivers/spi/spi-sirf.c
drivers/spi/spi-tegra114.c
drivers/spi/spi-tegra20-sflash.c
drivers/spi/spi-tegra20-slink.c
drivers/spi/spi-ti-qspi.c [new file with mode: 0644]
drivers/spi/spi-ti-ssp.c
drivers/spi/spi-tle62x0.c
drivers/spi/spi-topcliff-pch.c
drivers/spi/spi-txx9.c
drivers/spi/spi-xilinx.c
drivers/spi/spi.c
drivers/tty/hvc/hvsi_lib.c
drivers/usb/host/ohci-pci.c
fs/dcache.c
fs/jfs/jfs_dtree.c
fs/namei.c
fs/ocfs2/super.c
include/linux/dcache.h
include/linux/lockref.h [new file with mode: 0644]
include/linux/nsproxy.h
include/linux/platform_data/efm32-spi.h [new file with mode: 0644]
include/linux/regmap.h
include/linux/spi/spi.h
include/linux/spi/spi_bitbang.h
include/net/busy_poll.h
include/net/genetlink.h
include/net/mac80211.h
include/net/route.h
include/net/xfrm.h
include/uapi/linux/cm4000_cs.h
ipc/msg.c
kernel/cgroup.c
kernel/fork.c
kernel/nsproxy.c
kernel/pid_namespace.c
kernel/time/timer_list.c
kernel/workqueue.c
lib/Kconfig
lib/Makefile
lib/lockref.c [new file with mode: 0644]
mm/mremap.c
mm/slab.h
net/bridge/br_device.c
net/bridge/br_input.c
net/bridge/br_mdb.c
net/bridge/br_multicast.c
net/bridge/br_private.h
net/core/flow_dissector.c
net/core/scm.c
net/ipv4/ip_output.c
net/ipv4/ipip.c
net/ipv4/raw.c
net/ipv4/tcp_input.c
net/ipv4/tcp_output.c
net/ipv4/xfrm4_output.c
net/ipv4/xfrm4_state.c
net/ipv6/ip6_gre.c
net/ipv6/ip6_output.c
net/ipv6/ip6_tunnel.c
net/ipv6/raw.c
net/ipv6/sit.c
net/ipv6/xfrm6_output.c
net/ipv6/xfrm6_state.c
net/mac80211/ibss.c
net/mac80211/rc80211_minstrel_ht.c
net/netlink/genetlink.c
net/sunrpc/xdr.c
net/tipc/socket.c
net/xfrm/xfrm_output.c
net/xfrm/xfrm_policy.c
net/xfrm/xfrm_state.c
sound/isa/opti9xx/opti92x-ad1848.c
sound/pci/hda/patch_hdmi.c
sound/pci/hda/patch_realtek.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";
+       };
+};
index 296015e..800dafe 100644 (file)
@@ -55,6 +55,16 @@ contain the following properties.
                chip select active high
 - spi-3wire       - (optional) Empty property indicating device requires
                    3-wire mode.
+- spi-tx-bus-width - (optional) The bus width(number of data wires) that
+                      used for MOSI. Defaults to 1 if not present.
+- spi-rx-bus-width - (optional) The bus width(number of data wires) that
+                      used for MISO. Defaults to 1 if not present.
+
+Some SPI controllers and devices support Dual and Quad SPI transfer mode.
+It allows data in SPI system transfered in 2 wires(DUAL) or 4 wires(QUAD).
+Now the value that spi-tx-bus-width and spi-rx-bus-width can receive is
+only 1(SINGLE), 2(DUAL) and 4(QUAD).
+Dual/Quad mode is not allowed when 3-wire mode is used.
 
 If a gpio chipselect is used for the SPI slave the gpio number will be passed
 via the cs_gpio
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";
+       };
+};
+
+
diff --git a/Documentation/devicetree/bindings/spi/ti_qspi.txt b/Documentation/devicetree/bindings/spi/ti_qspi.txt
new file mode 100644 (file)
index 0000000..1f9641a
--- /dev/null
@@ -0,0 +1,22 @@
+TI QSPI controller.
+
+Required properties:
+- compatible : should be "ti,dra7xxx-qspi" or "ti,am4372-qspi".
+- reg: Should contain QSPI registers location and length.
+- #address-cells, #size-cells : Must be present if the device has sub-nodes
+- ti,hwmods: Name of the hwmod associated to the QSPI
+
+Recommended properties:
+- spi-max-frequency: Definition as per
+                     Documentation/devicetree/bindings/spi/spi-bus.txt
+
+Example:
+
+qspi: qspi@4b300000 {
+       compatible = "ti,dra7xxx-qspi";
+       reg = <0x4b300000 0x100>;
+       #address-cells = <1>;
+       #size-cells = <0>;
+       spi-max-frequency = <25000000>;
+       ti,hwmods = "qspi";
+};
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 8197fbd..b140c81 100644 (file)
@@ -6066,7 +6066,7 @@ M:        Rob Herring <rob.herring@calxeda.com>
 M:     Pawel Moll <pawel.moll@arm.com>
 M:     Mark Rutland <mark.rutland@arm.com>
 M:     Stephen Warren <swarren@wwwdotorg.org>
-M:     Ian Campbell <ian.campbell@citrix.com>
+M:     Ian Campbell <ijc+devicetree@hellion.org.uk>
 L:     devicetree@vger.kernel.org
 S:     Maintained
 F:     Documentation/devicetree/
index 369882e..fe8204b 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 3
 PATCHLEVEL = 11
 SUBLEVEL = 0
-EXTRAVERSION = -rc7
+EXTRAVERSION =
 NAME = Linux for Workgroups
 
 # *DOCUMENTATION*
index 2c70f74..e110b6d 100644 (file)
@@ -42,7 +42,6 @@ static const char *atlas6_dt_match[] __initdata = {
 
 DT_MACHINE_START(ATLAS6_DT, "Generic ATLAS6 (Flattened Device Tree)")
        /* Maintainer: Barry Song <baohua.song@csr.com> */
-       .nr_irqs        = 128,
        .map_io         = sirfsoc_map_io,
        .init_time      = sirfsoc_init_time,
        .init_late      = sirfsoc_init_late,
@@ -59,7 +58,6 @@ static const char *prima2_dt_match[] __initdata = {
 
 DT_MACHINE_START(PRIMA2_DT, "Generic PRIMA2 (Flattened Device Tree)")
        /* Maintainer: Barry Song <baohua.song@csr.com> */
-       .nr_irqs        = 128,
        .map_io         = sirfsoc_map_io,
        .init_time      = sirfsoc_init_time,
        .dma_zone_size  = SZ_256M,
index dbd9d3c..9cf5981 100644 (file)
@@ -979,6 +979,7 @@ config RELOCATABLE
          must live at a different physical address than the primary
          kernel.
 
+# This value must have zeroes in the bottom 60 bits otherwise lots will break
 config PAGE_OFFSET
        hex
        default "0xc000000000000000"
index 988c812..b9f4262 100644 (file)
@@ -211,9 +211,19 @@ extern long long virt_phys_offset;
 #define __va(x) ((void *)(unsigned long)((phys_addr_t)(x) + VIRT_PHYS_OFFSET))
 #define __pa(x) ((unsigned long)(x) - VIRT_PHYS_OFFSET)
 #else
+#ifdef CONFIG_PPC64
+/*
+ * gcc miscompiles (unsigned long)(&static_var) - PAGE_OFFSET
+ * with -mcmodel=medium, so we use & and | instead of - and + on 64-bit.
+ */
+#define __va(x) ((void *)(unsigned long)((phys_addr_t)(x) | PAGE_OFFSET))
+#define __pa(x) ((unsigned long)(x) & 0x0fffffffffffffffUL)
+
+#else /* 32-bit, non book E */
 #define __va(x) ((void *)(unsigned long)((phys_addr_t)(x) + PAGE_OFFSET - MEMORY_START))
 #define __pa(x) ((unsigned long)(x) - PAGE_OFFSET + MEMORY_START)
 #endif
+#endif
 
 /*
  * Unfortunately the PLT is in the BSS in the PPC32 ELF ABI,
index d92f387..e2a0a16 100644 (file)
 #include <asm/vdso_datapage.h>
 #include <asm/vio.h>
 #include <asm/mmu.h>
+#include <asm/machdep.h>
 
+
+/*
+ * This isn't a module but we expose that to userspace
+ * via /proc so leave the definitions here
+ */
 #define MODULE_VERS "1.9"
 #define MODULE_NAME "lparcfg"
 
@@ -418,7 +424,8 @@ static void parse_em_data(struct seq_file *m)
 {
        unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
 
-       if (plpar_hcall(H_GET_EM_PARMS, retbuf) == H_SUCCESS)
+       if (firmware_has_feature(FW_FEATURE_LPAR) &&
+           plpar_hcall(H_GET_EM_PARMS, retbuf) == H_SUCCESS)
                seq_printf(m, "power_mode_data=%016lx\n", retbuf[0]);
 }
 
@@ -677,7 +684,6 @@ static int lparcfg_open(struct inode *inode, struct file *file)
 }
 
 static const struct file_operations lparcfg_fops = {
-       .owner          = THIS_MODULE,
        .read           = seq_read,
        .write          = lparcfg_write,
        .open           = lparcfg_open,
@@ -699,14 +705,4 @@ static int __init lparcfg_init(void)
        }
        return 0;
 }
-
-static void __exit lparcfg_cleanup(void)
-{
-       remove_proc_subtree("powerpc/lparcfg", NULL);
-}
-
-module_init(lparcfg_init);
-module_exit(lparcfg_cleanup);
-MODULE_DESCRIPTION("Interface for LPAR configuration data");
-MODULE_AUTHOR("Dave Engebretsen");
-MODULE_LICENSE("GPL");
+machine_device_initcall(pseries, lparcfg_init);
index b32ebf9..67e0074 100644 (file)
@@ -16,6 +16,7 @@ config X86_64
        def_bool y
        depends on 64BIT
        select X86_DEV_DMA_OPS
+       select ARCH_USE_CMPXCHG_LOCKREF
 
 ### Arch settings
 config X86
index e3ddd7d..e0e6684 100644 (file)
 # define UNLOCK_LOCK_PREFIX
 #endif
 
+static __always_inline int arch_spin_value_unlocked(arch_spinlock_t lock)
+{
+       return lock.tickets.head == lock.tickets.tail;
+}
+
 /*
  * Ticket locks are conceptually two parts, one indicating the current head of
  * the queue, and the other indicating the current tail. The lock is acquired
index 2ec29ac..04664cd 100644 (file)
@@ -78,8 +78,8 @@ __ref void *alloc_low_pages(unsigned int num)
        return __va(pfn << PAGE_SHIFT);
 }
 
-/* need 4 4k for initial PMD_SIZE, 4k for 0-ISA_END_ADDRESS */
-#define INIT_PGT_BUF_SIZE      (5 * PAGE_SIZE)
+/* need 3 4k for initial PMD_SIZE,  3 4k for 0-ISA_END_ADDRESS */
+#define INIT_PGT_BUF_SIZE      (6 * PAGE_SIZE)
 RESERVE_BRK(early_pgt_alloc, INIT_PGT_BUF_SIZE);
 void  __init early_alloc_pgt_buf(void)
 {
index 2b7813e..ec386ee 100644 (file)
@@ -141,6 +141,8 @@ static ssize_t show_mem_removable(struct device *dev,
                container_of(dev, struct memory_block, dev);
 
        for (i = 0; i < sections_per_block; i++) {
+               if (!present_section_nr(mem->start_section_nr + i))
+                       continue;
                pfn = section_nr_to_pfn(mem->start_section_nr + i);
                ret &= is_mem_section_removable(pfn, PAGES_PER_SECTION);
        }
index 29c8316..57f7778 100644 (file)
@@ -128,9 +128,6 @@ struct regmap {
        void *cache;
        u32 cache_dirty;
 
-       unsigned long *cache_present;
-       unsigned int cache_present_nbits;
-
        struct reg_default *patch;
        int patch_regs;
 
@@ -203,6 +200,7 @@ int regcache_write(struct regmap *map,
                        unsigned int reg, unsigned int value);
 int regcache_sync(struct regmap *map);
 int regcache_sync_block(struct regmap *map, void *block,
+                       unsigned long *cache_present,
                        unsigned int block_base, unsigned int start,
                        unsigned int end);
 
@@ -218,16 +216,6 @@ unsigned int regcache_get_val(struct regmap *map, const void *base,
 bool regcache_set_val(struct regmap *map, void *base, unsigned int idx,
                      unsigned int val);
 int regcache_lookup_reg(struct regmap *map, unsigned int reg);
-int regcache_set_reg_present(struct regmap *map, unsigned int reg);
-
-static inline bool regcache_reg_present(struct regmap *map, unsigned int reg)
-{
-       if (!map->cache_present)
-               return true;
-       if (reg > map->cache_present_nbits)
-               return false;
-       return map->cache_present[BIT_WORD(reg)] & BIT_MASK(reg);
-}
 
 int _regmap_raw_write(struct regmap *map, unsigned int reg,
                      const void *val, size_t val_len, bool async);
index 5c1435c..930cad4 100644 (file)
@@ -29,6 +29,8 @@ struct regcache_rbtree_node {
        unsigned int base_reg;
        /* block of adjacent registers */
        void *block;
+       /* Which registers are present */
+       long *cache_present;
        /* number of registers available in the block */
        unsigned int blklen;
 } __attribute__ ((packed));
@@ -57,6 +59,7 @@ static void regcache_rbtree_set_register(struct regmap *map,
                                         struct regcache_rbtree_node *rbnode,
                                         unsigned int idx, unsigned int val)
 {
+       set_bit(idx, rbnode->cache_present);
        regcache_set_val(map, rbnode->block, idx, val);
 }
 
@@ -146,13 +149,13 @@ static int rbtree_show(struct seq_file *s, void *ignored)
        map->lock(map->lock_arg);
 
        mem_size = sizeof(*rbtree_ctx);
-       mem_size += BITS_TO_LONGS(map->cache_present_nbits) * sizeof(long);
 
        for (node = rb_first(&rbtree_ctx->root); node != NULL;
             node = rb_next(node)) {
                n = container_of(node, struct regcache_rbtree_node, node);
                mem_size += sizeof(*n);
                mem_size += (n->blklen * map->cache_word_size);
+               mem_size += BITS_TO_LONGS(n->blklen) * sizeof(long);
 
                regcache_rbtree_get_base_top_reg(map, n, &base, &top);
                this_registers = ((top - base) / map->reg_stride) + 1;
@@ -245,6 +248,7 @@ static int regcache_rbtree_exit(struct regmap *map)
                rbtree_node = rb_entry(next, struct regcache_rbtree_node, node);
                next = rb_next(&rbtree_node->node);
                rb_erase(&rbtree_node->node, &rbtree_ctx->root);
+               kfree(rbtree_node->cache_present);
                kfree(rbtree_node->block);
                kfree(rbtree_node);
        }
@@ -265,7 +269,7 @@ static int regcache_rbtree_read(struct regmap *map,
        rbnode = regcache_rbtree_lookup(map, reg);
        if (rbnode) {
                reg_tmp = (reg - rbnode->base_reg) / map->reg_stride;
-               if (!regcache_reg_present(map, reg))
+               if (!test_bit(reg_tmp, rbnode->cache_present))
                        return -ENOENT;
                *value = regcache_rbtree_get_register(map, rbnode, reg_tmp);
        } else {
@@ -278,27 +282,45 @@ static int regcache_rbtree_read(struct regmap *map,
 
 static int regcache_rbtree_insert_to_block(struct regmap *map,
                                           struct regcache_rbtree_node *rbnode,
-                                          unsigned int pos, unsigned int reg,
+                                          unsigned int base_reg,
+                                          unsigned int top_reg,
+                                          unsigned int reg,
                                           unsigned int value)
 {
+       unsigned int blklen;
+       unsigned int pos, offset;
+       unsigned long *present;
        u8 *blk;
 
+       blklen = (top_reg - base_reg) / map->reg_stride + 1;
+       pos = (reg - base_reg) / map->reg_stride;
+       offset = (rbnode->base_reg - base_reg) / map->reg_stride;
+
        blk = krealloc(rbnode->block,
-                      (rbnode->blklen + 1) * map->cache_word_size,
+                      blklen * map->cache_word_size,
                       GFP_KERNEL);
        if (!blk)
                return -ENOMEM;
 
+       present = krealloc(rbnode->cache_present,
+                   BITS_TO_LONGS(blklen) * sizeof(*present), GFP_KERNEL);
+       if (!present) {
+               kfree(blk);
+               return -ENOMEM;
+       }
+
        /* insert the register value in the correct place in the rbnode block */
-       memmove(blk + (pos + 1) * map->cache_word_size,
-               blk + pos * map->cache_word_size,
-               (rbnode->blklen - pos) * map->cache_word_size);
+       if (pos == 0) {
+               memmove(blk + offset * map->cache_word_size,
+                       blk, rbnode->blklen * map->cache_word_size);
+               bitmap_shift_right(present, present, offset, blklen);
+       }
 
        /* update the rbnode block, its size and the base register */
        rbnode->block = blk;
-       rbnode->blklen++;
-       if (!pos)
-               rbnode->base_reg = reg;
+       rbnode->blklen = blklen;
+       rbnode->base_reg = base_reg;
+       rbnode->cache_present = present;
 
        regcache_rbtree_set_register(map, rbnode, pos, value);
        return 0;
@@ -325,25 +347,34 @@ regcache_rbtree_node_alloc(struct regmap *map, unsigned int reg)
 
                if (i != map->rd_table->n_yes_ranges) {
                        range = &map->rd_table->yes_ranges[i];
-                       rbnode->blklen = range->range_max - range->range_min
-                               + 1;
+                       rbnode->blklen = (range->range_max - range->range_min) /
+                               map->reg_stride + 1;
                        rbnode->base_reg = range->range_min;
                }
        }
 
        if (!rbnode->blklen) {
-               rbnode->blklen = sizeof(*rbnode);
+               rbnode->blklen = 1;
                rbnode->base_reg = reg;
        }
 
        rbnode->block = kmalloc(rbnode->blklen * map->cache_word_size,
                                GFP_KERNEL);
-       if (!rbnode->block) {
-               kfree(rbnode);
-               return NULL;
-       }
+       if (!rbnode->block)
+               goto err_free;
+
+       rbnode->cache_present = kzalloc(BITS_TO_LONGS(rbnode->blklen) *
+               sizeof(*rbnode->cache_present), GFP_KERNEL);
+       if (!rbnode->cache_present)
+               goto err_free_block;
 
        return rbnode;
+
+err_free_block:
+       kfree(rbnode->block);
+err_free:
+       kfree(rbnode);
+       return NULL;
 }
 
 static int regcache_rbtree_write(struct regmap *map, unsigned int reg,
@@ -353,15 +384,9 @@ static int regcache_rbtree_write(struct regmap *map, unsigned int reg,
        struct regcache_rbtree_node *rbnode, *rbnode_tmp;
        struct rb_node *node;
        unsigned int reg_tmp;
-       unsigned int pos;
-       int i;
        int ret;
 
        rbtree_ctx = map->cache;
-       /* update the reg_present bitmap, make space if necessary */
-       ret = regcache_set_reg_present(map, reg);
-       if (ret < 0)
-               return ret;
 
        /* if we can't locate it in the cached rbnode we'll have
         * to traverse the rbtree looking for it.
@@ -371,30 +396,43 @@ static int regcache_rbtree_write(struct regmap *map, unsigned int reg,
                reg_tmp = (reg - rbnode->base_reg) / map->reg_stride;
                regcache_rbtree_set_register(map, rbnode, reg_tmp, value);
        } else {
+               unsigned int base_reg, top_reg;
+               unsigned int new_base_reg, new_top_reg;
+               unsigned int min, max;
+               unsigned int max_dist;
+
+               max_dist = map->reg_stride * sizeof(*rbnode_tmp) /
+                       map->cache_word_size;
+               if (reg < max_dist)
+                       min = 0;
+               else
+                       min = reg - max_dist;
+               max = reg + max_dist;
+
                /* look for an adjacent register to the one we are about to add */
                for (node = rb_first(&rbtree_ctx->root); node;
                     node = rb_next(node)) {
                        rbnode_tmp = rb_entry(node, struct regcache_rbtree_node,
                                              node);
-                       for (i = 0; i < rbnode_tmp->blklen; i++) {
-                               reg_tmp = rbnode_tmp->base_reg +
-                                               (i * map->reg_stride);
-                               if (abs(reg_tmp - reg) != map->reg_stride)
-                                       continue;
-                               /* decide where in the block to place our register */
-                               if (reg_tmp + map->reg_stride == reg)
-                                       pos = i + 1;
-                               else
-                                       pos = i;
-                               ret = regcache_rbtree_insert_to_block(map,
-                                                                     rbnode_tmp,
-                                                                     pos, reg,
-                                                                     value);
-                               if (ret)
-                                       return ret;
-                               rbtree_ctx->cached_rbnode = rbnode_tmp;
-                               return 0;
+
+                       regcache_rbtree_get_base_top_reg(map, rbnode_tmp,
+                               &base_reg, &top_reg);
+
+                       if (base_reg <= max && top_reg >= min) {
+                               new_base_reg = min(reg, base_reg);
+                               new_top_reg = max(reg, top_reg);
+                       } else {
+                               continue;
                        }
+
+                       ret = regcache_rbtree_insert_to_block(map, rbnode_tmp,
+                                                             new_base_reg,
+                                                             new_top_reg, reg,
+                                                             value);
+                       if (ret)
+                               return ret;
+                       rbtree_ctx->cached_rbnode = rbnode_tmp;
+                       return 0;
                }
 
                /* We did not manage to find a place to insert it in
@@ -418,30 +456,34 @@ static int regcache_rbtree_sync(struct regmap *map, unsigned int min,
        struct regcache_rbtree_ctx *rbtree_ctx;
        struct rb_node *node;
        struct regcache_rbtree_node *rbnode;
+       unsigned int base_reg, top_reg;
+       unsigned int start, end;
        int ret;
-       int base, end;
 
        rbtree_ctx = map->cache;
        for (node = rb_first(&rbtree_ctx->root); node; node = rb_next(node)) {
                rbnode = rb_entry(node, struct regcache_rbtree_node, node);
 
-               if (rbnode->base_reg > max)
+               regcache_rbtree_get_base_top_reg(map, rbnode, &base_reg,
+                       &top_reg);
+               if (base_reg > max)
                        break;
-               if (rbnode->base_reg + rbnode->blklen < min)
+               if (top_reg < min)
                        continue;
 
-               if (min > rbnode->base_reg)
-                       base = min - rbnode->base_reg;
+               if (min > base_reg)
+                       start = (min - base_reg) / map->reg_stride;
                else
-                       base = 0;
+                       start = 0;
 
-               if (max < rbnode->base_reg + rbnode->blklen)
-                       end = max - rbnode->base_reg + 1;
+               if (max < top_reg)
+                       end = (max - base_reg) / map->reg_stride + 1;
                else
                        end = rbnode->blklen;
 
-               ret = regcache_sync_block(map, rbnode->block, rbnode->base_reg,
-                                         base, end);
+               ret = regcache_sync_block(map, rbnode->block,
+                                         rbnode->cache_present,
+                                         rbnode->base_reg, start, end);
                if (ret != 0)
                        return ret;
        }
@@ -449,6 +491,42 @@ static int regcache_rbtree_sync(struct regmap *map, unsigned int min,
        return regmap_async_complete(map);
 }
 
+static int regcache_rbtree_drop(struct regmap *map, unsigned int min,
+                               unsigned int max)
+{
+       struct regcache_rbtree_ctx *rbtree_ctx;
+       struct regcache_rbtree_node *rbnode;
+       struct rb_node *node;
+       unsigned int base_reg, top_reg;
+       unsigned int start, end;
+
+       rbtree_ctx = map->cache;
+       for (node = rb_first(&rbtree_ctx->root); node; node = rb_next(node)) {
+               rbnode = rb_entry(node, struct regcache_rbtree_node, node);
+
+               regcache_rbtree_get_base_top_reg(map, rbnode, &base_reg,
+                       &top_reg);
+               if (base_reg > max)
+                       break;
+               if (top_reg < min)
+                       continue;
+
+               if (min > base_reg)
+                       start = (min - base_reg) / map->reg_stride;
+               else
+                       start = 0;
+
+               if (max < top_reg)
+                       end = (max - base_reg) / map->reg_stride + 1;
+               else
+                       end = rbnode->blklen;
+
+               bitmap_clear(rbnode->cache_present, start, end - start);
+       }
+
+       return 0;
+}
+
 struct regcache_ops regcache_rbtree_ops = {
        .type = REGCACHE_RBTREE,
        .name = "rbtree",
@@ -456,5 +534,6 @@ struct regcache_ops regcache_rbtree_ops = {
        .exit = regcache_rbtree_exit,
        .read = regcache_rbtree_read,
        .write = regcache_rbtree_write,
-       .sync = regcache_rbtree_sync
+       .sync = regcache_rbtree_sync,
+       .drop = regcache_rbtree_drop,
 };
index 3455f83..d6c2d69 100644 (file)
@@ -121,8 +121,6 @@ int regcache_init(struct regmap *map, const struct regmap_config *config)
        map->reg_defaults_raw = config->reg_defaults_raw;
        map->cache_word_size = DIV_ROUND_UP(config->val_bits, 8);
        map->cache_size_raw = map->cache_word_size * config->num_reg_defaults_raw;
-       map->cache_present = NULL;
-       map->cache_present_nbits = 0;
 
        map->cache = NULL;
        map->cache_ops = cache_types[i];
@@ -181,7 +179,6 @@ void regcache_exit(struct regmap *map)
 
        BUG_ON(!map->cache_ops);
 
-       kfree(map->cache_present);
        kfree(map->reg_defaults);
        if (map->cache_free)
                kfree(map->reg_defaults_raw);
@@ -241,9 +238,6 @@ int regcache_write(struct regmap *map,
 
        BUG_ON(!map->cache_ops);
 
-       if (!regmap_writeable(map, reg))
-               return -EIO;
-
        if (!regmap_volatile(map, reg))
                return map->cache_ops->write(map, reg, value);
 
@@ -410,22 +404,16 @@ EXPORT_SYMBOL_GPL(regcache_sync_region);
 int regcache_drop_region(struct regmap *map, unsigned int min,
                         unsigned int max)
 {
-       unsigned int reg;
        int ret = 0;
 
-       if (!map->cache_present && !(map->cache_ops && map->cache_ops->drop))
+       if (!map->cache_ops || !map->cache_ops->drop)
                return -EINVAL;
 
        map->lock(map->lock_arg);
 
        trace_regcache_drop_region(map->dev, min, max);
 
-       if (map->cache_present)
-               for (reg = min; reg < max + 1; reg++)
-                       clear_bit(reg, map->cache_present);
-
-       if (map->cache_ops && map->cache_ops->drop)
-               ret = map->cache_ops->drop(map, min, max);
+       ret = map->cache_ops->drop(map, min, max);
 
        map->unlock(map->lock_arg);
 
@@ -493,42 +481,6 @@ void regcache_cache_bypass(struct regmap *map, bool enable)
 }
 EXPORT_SYMBOL_GPL(regcache_cache_bypass);
 
-int regcache_set_reg_present(struct regmap *map, unsigned int reg)
-{
-       unsigned long *cache_present;
-       unsigned int cache_present_size;
-       unsigned int nregs;
-       int i;
-
-       nregs = reg + 1;
-       cache_present_size = BITS_TO_LONGS(nregs);
-       cache_present_size *= sizeof(long);
-
-       if (!map->cache_present) {
-               cache_present = kmalloc(cache_present_size, GFP_KERNEL);
-               if (!cache_present)
-                       return -ENOMEM;
-               bitmap_zero(cache_present, nregs);
-               map->cache_present = cache_present;
-               map->cache_present_nbits = nregs;
-       }
-
-       if (nregs > map->cache_present_nbits) {
-               cache_present = krealloc(map->cache_present,
-                                        cache_present_size, GFP_KERNEL);
-               if (!cache_present)
-                       return -ENOMEM;
-               for (i = 0; i < nregs; i++)
-                       if (i >= map->cache_present_nbits)
-                               clear_bit(i, cache_present);
-               map->cache_present = cache_present;
-               map->cache_present_nbits = nregs;
-       }
-
-       set_bit(reg, map->cache_present);
-       return 0;
-}
-
 bool regcache_set_val(struct regmap *map, void *base, unsigned int idx,
                      unsigned int val)
 {
@@ -620,7 +572,16 @@ int regcache_lookup_reg(struct regmap *map, unsigned int reg)
                return -ENOENT;
 }
 
+static bool regcache_reg_present(unsigned long *cache_present, unsigned int idx)
+{
+       if (!cache_present)
+               return true;
+
+       return test_bit(idx, cache_present);
+}
+
 static int regcache_sync_block_single(struct regmap *map, void *block,
+                                     unsigned long *cache_present,
                                      unsigned int block_base,
                                      unsigned int start, unsigned int end)
 {
@@ -630,7 +591,7 @@ static int regcache_sync_block_single(struct regmap *map, void *block,
        for (i = start; i < end; i++) {
                regtmp = block_base + (i * map->reg_stride);
 
-               if (!regcache_reg_present(map, regtmp))
+               if (!regcache_reg_present(cache_present, i))
                        continue;
 
                val = regcache_get_val(map, block, i);
@@ -681,6 +642,7 @@ static int regcache_sync_block_raw_flush(struct regmap *map, const void **data,
 }
 
 static int regcache_sync_block_raw(struct regmap *map, void *block,
+                           unsigned long *cache_present,
                            unsigned int block_base, unsigned int start,
                            unsigned int end)
 {
@@ -693,7 +655,7 @@ static int regcache_sync_block_raw(struct regmap *map, void *block,
        for (i = start; i < end; i++) {
                regtmp = block_base + (i * map->reg_stride);
 
-               if (!regcache_reg_present(map, regtmp)) {
+               if (!regcache_reg_present(cache_present, i)) {
                        ret = regcache_sync_block_raw_flush(map, &data,
                                                            base, regtmp);
                        if (ret != 0)
@@ -724,13 +686,14 @@ static int regcache_sync_block_raw(struct regmap *map, void *block,
 }
 
 int regcache_sync_block(struct regmap *map, void *block,
+                       unsigned long *cache_present,
                        unsigned int block_base, unsigned int start,
                        unsigned int end)
 {
        if (regmap_can_raw_write(map))
-               return regcache_sync_block_raw(map, block, block_base,
-                                              start, end);
+               return regcache_sync_block_raw(map, block, cache_present,
+                                              block_base, start, end);
        else
-               return regcache_sync_block_single(map, block, block_base,
-                                                 start, end);
+               return regcache_sync_block_single(map, block, cache_present,
+                                                 block_base, start, end);
 }
index 5349575..6c2652a 100644 (file)
@@ -85,8 +85,8 @@ static unsigned int regmap_debugfs_get_dump_start(struct regmap *map,
        unsigned int reg_offset;
 
        /* Suppress the cache if we're using a subrange */
-       if (from)
-               return from;
+       if (base)
+               return base;
 
        /*
         * If we don't have a cache build one so we don't have to do a
index 1643e88..d10456f 100644 (file)
@@ -418,6 +418,31 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
                                reg, ret);
                        goto err_alloc;
                }
+
+               if (!chip->init_ack_masked)
+                       continue;
+
+               /* Ack masked but set interrupts */
+               reg = chip->status_base +
+                       (i * map->reg_stride * d->irq_reg_stride);
+               ret = regmap_read(map, reg, &d->status_buf[i]);
+               if (ret != 0) {
+                       dev_err(map->dev, "Failed to read IRQ status: %d\n",
+                               ret);
+                       goto err_alloc;
+               }
+
+               if (d->status_buf[i] && chip->ack_base) {
+                       reg = chip->ack_base +
+                               (i * map->reg_stride * d->irq_reg_stride);
+                       ret = regmap_write(map, reg,
+                                       d->status_buf[i] & d->mask_buf[i]);
+                       if (ret != 0) {
+                               dev_err(map->dev, "Failed to ack 0x%x: %d\n",
+                                       reg, ret);
+                               goto err_alloc;
+                       }
+               }
        }
 
        /* Wake is disabled by default */
index e0d0c7d..7d689a1 100644 (file)
@@ -303,6 +303,7 @@ static void regmap_unlock_mutex(void *__map)
 }
 
 static void regmap_lock_spinlock(void *__map)
+__acquires(&map->spinlock)
 {
        struct regmap *map = __map;
        unsigned long flags;
@@ -312,6 +313,7 @@ static void regmap_lock_spinlock(void *__map)
 }
 
 static void regmap_unlock_spinlock(void *__map)
+__releases(&map->spinlock)
 {
        struct regmap *map = __map;
        spin_unlock_irqrestore(&map->spinlock, map->spinlock_flags);
@@ -687,6 +689,10 @@ skip_format_initialization:
                        unsigned win_max = win_min +
                                           config->ranges[j].window_len - 1;
 
+                       /* Allow data window inside its own virtual range */
+                       if (j == i)
+                               continue;
+
                        if (range_cfg->range_min <= sel_reg &&
                            sel_reg <= range_cfg->range_max) {
                                dev_err(map->dev,
@@ -1261,6 +1267,9 @@ int _regmap_write(struct regmap *map, unsigned int reg,
        int ret;
        void *context = _regmap_map_get_context(map);
 
+       if (!regmap_writeable(map, reg))
+               return -EIO;
+
        if (!map->cache_bypass && !map->defer_caching) {
                ret = regcache_write(map, reg, val);
                if (ret != 0)
@@ -1888,13 +1897,10 @@ EXPORT_SYMBOL_GPL(regmap_async_complete);
 int regmap_register_patch(struct regmap *map, const struct reg_default *regs,
                          int num_regs)
 {
+       struct reg_default *p;
        int i, ret;
        bool bypass;
 
-       /* If needed the implementation can be extended to support this */
-       if (map->patch)
-               return -EBUSY;
-
        map->lock(map->lock_arg);
 
        bypass = map->cache_bypass;
@@ -1911,11 +1917,13 @@ int regmap_register_patch(struct regmap *map, const struct reg_default *regs,
                }
        }
 
-       map->patch = kcalloc(num_regs, sizeof(struct reg_default), GFP_KERNEL);
-       if (map->patch != NULL) {
-               memcpy(map->patch, regs,
-                      num_regs * sizeof(struct reg_default));
-               map->patch_regs = num_regs;
+       p = krealloc(map->patch,
+                    sizeof(struct reg_default) * (map->patch_regs + num_regs),
+                    GFP_KERNEL);
+       if (p) {
+               memcpy(p + map->patch_regs, regs, num_regs * sizeof(*regs));
+               map->patch = p;
+               map->patch_regs += num_regs;
        } else {
                ret = -ENOMEM;
        }
index 6825957..643d7c7 100644 (file)
@@ -194,7 +194,7 @@ config SIRF_DMA
          Enable support for the CSR SiRFprimaII DMA engine.
 
 config TI_EDMA
-       tristate "TI EDMA support"
+       bool "TI EDMA support"
        depends on ARCH_DAVINCI || ARCH_OMAP
        select DMA_ENGINE
        select DMA_VIRTUAL_CHANNELS
index 53cddd9..342f1f3 100644 (file)
 #define EDP_LINK_TRAIN_600MV_0DB_IVB           (0x30 <<22)
 #define EDP_LINK_TRAIN_600MV_3_5DB_IVB         (0x36 <<22)
 #define EDP_LINK_TRAIN_800MV_0DB_IVB           (0x38 <<22)
-#define EDP_LINK_TRAIN_800MV_3_5DB_IVB         (0x33 <<22)
+#define EDP_LINK_TRAIN_800MV_3_5DB_IVB         (0x3e <<22)
 
 /* legacy values */
 #define EDP_LINK_TRAIN_500MV_0DB_IVB           (0x00 <<22)
index 3751730..1a0bf07 100644 (file)
@@ -29,7 +29,9 @@
 #include <drm/drmP.h>
 #include <drm/ttm/ttm_bo_driver.h>
 
-#define VMW_PPN_SIZE sizeof(unsigned long)
+#define VMW_PPN_SIZE (sizeof(unsigned long))
+/* A future safe maximum remap size. */
+#define VMW_PPN_PER_REMAP ((31 * 1024) / VMW_PPN_SIZE)
 
 static int vmw_gmr2_bind(struct vmw_private *dev_priv,
                         struct page *pages[],
@@ -38,43 +40,61 @@ static int vmw_gmr2_bind(struct vmw_private *dev_priv,
 {
        SVGAFifoCmdDefineGMR2 define_cmd;
        SVGAFifoCmdRemapGMR2 remap_cmd;
-       uint32_t define_size = sizeof(define_cmd) + 4;
-       uint32_t remap_size = VMW_PPN_SIZE * num_pages + sizeof(remap_cmd) + 4;
        uint32_t *cmd;
        uint32_t *cmd_orig;
+       uint32_t define_size = sizeof(define_cmd) + sizeof(*cmd);
+       uint32_t remap_num = num_pages / VMW_PPN_PER_REMAP + ((num_pages % VMW_PPN_PER_REMAP) > 0);
+       uint32_t remap_size = VMW_PPN_SIZE * num_pages + (sizeof(remap_cmd) + sizeof(*cmd)) * remap_num;
+       uint32_t remap_pos = 0;
+       uint32_t cmd_size = define_size + remap_size;
        uint32_t i;
 
-       cmd_orig = cmd = vmw_fifo_reserve(dev_priv, define_size + remap_size);
+       cmd_orig = cmd = vmw_fifo_reserve(dev_priv, cmd_size);
        if (unlikely(cmd == NULL))
                return -ENOMEM;
 
        define_cmd.gmrId = gmr_id;
        define_cmd.numPages = num_pages;
 
+       *cmd++ = SVGA_CMD_DEFINE_GMR2;
+       memcpy(cmd, &define_cmd, sizeof(define_cmd));
+       cmd += sizeof(define_cmd) / sizeof(*cmd);
+
+       /*
+        * Need to split the command if there are too many
+        * pages that goes into the gmr.
+        */
+
        remap_cmd.gmrId = gmr_id;
        remap_cmd.flags = (VMW_PPN_SIZE > sizeof(*cmd)) ?
                SVGA_REMAP_GMR2_PPN64 : SVGA_REMAP_GMR2_PPN32;
-       remap_cmd.offsetPages = 0;
-       remap_cmd.numPages = num_pages;
 
-       *cmd++ = SVGA_CMD_DEFINE_GMR2;
-       memcpy(cmd, &define_cmd, sizeof(define_cmd));
-       cmd += sizeof(define_cmd) / sizeof(uint32);
+       while (num_pages > 0) {
+               unsigned long nr = min(num_pages, (unsigned long)VMW_PPN_PER_REMAP);
+
+               remap_cmd.offsetPages = remap_pos;
+               remap_cmd.numPages = nr;
 
-       *cmd++ = SVGA_CMD_REMAP_GMR2;
-       memcpy(cmd, &remap_cmd, sizeof(remap_cmd));
-       cmd += sizeof(remap_cmd) / sizeof(uint32);
+               *cmd++ = SVGA_CMD_REMAP_GMR2;
+               memcpy(cmd, &remap_cmd, sizeof(remap_cmd));
+               cmd += sizeof(remap_cmd) / sizeof(*cmd);
 
-       for (i = 0; i < num_pages; ++i) {
-               if (VMW_PPN_SIZE <= 4)
-                       *cmd = page_to_pfn(*pages++);
-               else
-                       *((uint64_t *)cmd) = page_to_pfn(*pages++);
+               for (i = 0; i < nr; ++i) {
+                       if (VMW_PPN_SIZE <= 4)
+                               *cmd = page_to_pfn(*pages++);
+                       else
+                               *((uint64_t *)cmd) = page_to_pfn(*pages++);
 
-               cmd += VMW_PPN_SIZE / sizeof(*cmd);
+                       cmd += VMW_PPN_SIZE / sizeof(*cmd);
+               }
+
+               num_pages -= nr;
+               remap_pos += nr;
        }
 
-       vmw_fifo_commit(dev_priv, define_size + remap_size);
+       BUG_ON(cmd != cmd_orig + cmd_size / sizeof(*cmd));
+
+       vmw_fifo_commit(dev_priv, cmd_size);
 
        return 0;
 }
index fa061d4..75e3b10 100644 (file)
@@ -167,6 +167,7 @@ static const struct xpad_device {
        { 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
        { 0x146b, 0x0601, "BigBen Interactive XBOX 360 Controller", 0, XTYPE_XBOX360 },
        { 0x1689, 0xfd00, "Razer Onza Tournament Edition", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
+       { 0x1689, 0xfd01, "Razer Onza Classic Edition", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
        { 0x1bad, 0x0002, "Harmonix Rock Band Guitar", 0, XTYPE_XBOX360 },
        { 0x1bad, 0x0003, "Harmonix Rock Band Drumkit", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
        { 0x1bad, 0xf016, "Mad Catz Xbox 360 Controller", 0, XTYPE_XBOX360 },
index 57b2637..8551dca 100644 (file)
@@ -672,6 +672,7 @@ static int elantech_packet_check_v2(struct psmouse *psmouse)
  */
 static int elantech_packet_check_v3(struct psmouse *psmouse)
 {
+       struct elantech_data *etd = psmouse->private;
        const u8 debounce_packet[] = { 0xc4, 0xff, 0xff, 0x02, 0xff, 0xff };
        unsigned char *packet = psmouse->packet;
 
@@ -682,19 +683,48 @@ static int elantech_packet_check_v3(struct psmouse *psmouse)
        if (!memcmp(packet, debounce_packet, sizeof(debounce_packet)))
                return PACKET_DEBOUNCE;
 
-       if ((packet[0] & 0x0c) == 0x04 && (packet[3] & 0xcf) == 0x02)
-               return PACKET_V3_HEAD;
+       /*
+        * If the hardware flag 'crc_enabled' is set the packets have
+        * different signatures.
+        */
+       if (etd->crc_enabled) {
+               if ((packet[3] & 0x09) == 0x08)
+                       return PACKET_V3_HEAD;
+
+               if ((packet[3] & 0x09) == 0x09)
+                       return PACKET_V3_TAIL;
+       } else {
+               if ((packet[0] & 0x0c) == 0x04 && (packet[3] & 0xcf) == 0x02)
+                       return PACKET_V3_HEAD;
 
-       if ((packet[0] & 0x0c) == 0x0c && (packet[3] & 0xce) == 0x0c)
-               return PACKET_V3_TAIL;
+               if ((packet[0] & 0x0c) == 0x0c && (packet[3] & 0xce) == 0x0c)
+                       return PACKET_V3_TAIL;
+       }
 
        return PACKET_UNKNOWN;
 }
 
 static int elantech_packet_check_v4(struct psmouse *psmouse)
 {
+       struct elantech_data *etd = psmouse->private;
        unsigned char *packet = psmouse->packet;
        unsigned char packet_type = packet[3] & 0x03;
+       bool sanity_check;
+
+       /*
+        * Sanity check based on the constant bits of a packet.
+        * The constant bits change depending on the value of
+        * the hardware flag 'crc_enabled' but are the same for
+        * every packet, regardless of the type.
+        */
+       if (etd->crc_enabled)
+               sanity_check = ((packet[3] & 0x08) == 0x00);
+       else
+               sanity_check = ((packet[0] & 0x0c) == 0x04 &&
+                               (packet[3] & 0x1c) == 0x10);
+
+       if (!sanity_check)
+               return PACKET_UNKNOWN;
 
        switch (packet_type) {
        case 0:
@@ -1313,6 +1343,12 @@ static int elantech_set_properties(struct elantech_data *etd)
                        etd->reports_pressure = true;
        }
 
+       /*
+        * The signatures of v3 and v4 packets change depending on the
+        * value of this hardware flag.
+        */
+       etd->crc_enabled = ((etd->fw_version & 0x4000) == 0x4000);
+
        return 0;
 }
 
index 46db3be..036a04a 100644 (file)
@@ -129,6 +129,7 @@ struct elantech_data {
        bool paritycheck;
        bool jumpy_cursor;
        bool reports_pressure;
+       bool crc_enabled;
        unsigned char hw_version;
        unsigned int fw_version;
        unsigned int single_finger_reports;
index 94c17c2..1e691a3 100644 (file)
@@ -22,7 +22,8 @@ config SERIO_I8042
        tristate "i8042 PC Keyboard controller" if EXPERT || !X86
        default y
        depends on !PARISC && (!ARM || ARCH_SHARK || FOOTBRIDGE_HOST) && \
-                  (!SUPERH || SH_CAYMAN) && !M68K && !BLACKFIN && !S390
+                  (!SUPERH || SH_CAYMAN) && !M68K && !BLACKFIN && !S390 && \
+                  !ARC
        help
          i8042 is the chip over which the standard AT keyboard and PS/2
          mouse are connected to the computer. If you use these devices,
index 384fbcd..f3e91f0 100644 (file)
@@ -2112,7 +2112,7 @@ static const struct wacom_features wacom_features_0xDA =
        { "Wacom Bamboo 2FG 4x5 SE", WACOM_PKGLEN_BBFUN,  14720,  9200, 1023,
          31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
          .touch_max = 2 };
-static struct wacom_features wacom_features_0xDB =
+static const struct wacom_features wacom_features_0xDB =
        { "Wacom Bamboo 2FG 6x8 SE", WACOM_PKGLEN_BBFUN,  21648, 13700, 1023,
          31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
          .touch_max = 2 };
@@ -2127,6 +2127,12 @@ static const struct wacom_features wacom_features_0xDF =
         { "Wacom Bamboo 16FG 6x8", WACOM_PKGLEN_BBPEN,    21648, 13700, 1023,
          31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
          .touch_max = 16 };
+static const struct wacom_features wacom_features_0x300 =
+       { "Wacom Bamboo One S",    WACOM_PKGLEN_BBPEN,    14720,  9225, 1023,
+         31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x301 =
+       { "Wacom Bamboo One M",    WACOM_PKGLEN_BBPEN,    21648, 13530, 1023,
+         31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0x6004 =
        { "ISD-V4",               WACOM_PKGLEN_GRAPHIRE,  12800,  8000,  255,
          0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
@@ -2253,6 +2259,8 @@ const struct usb_device_id wacom_ids[] = {
        { USB_DEVICE_WACOM(0x100) },
        { USB_DEVICE_WACOM(0x101) },
        { USB_DEVICE_WACOM(0x10D) },
+       { USB_DEVICE_WACOM(0x300) },
+       { USB_DEVICE_WACOM(0x301) },
        { USB_DEVICE_WACOM(0x304) },
        { USB_DEVICE_WACOM(0x4001) },
        { USB_DEVICE_WACOM(0x47) },
index 69ea44e..4851afa 100644 (file)
@@ -23,7 +23,7 @@
 #define SIRFSOC_INT_RISC_LEVEL1         0x0024
 #define SIRFSOC_INIT_IRQ_ID            0x0038
 
-#define SIRFSOC_NUM_IRQS               128
+#define SIRFSOC_NUM_IRQS               64
 
 static struct irq_domain *sirfsoc_irqdomain;
 
@@ -32,15 +32,18 @@ sirfsoc_alloc_gc(void __iomem *base, unsigned int irq_start, unsigned int num)
 {
        struct irq_chip_generic *gc;
        struct irq_chip_type *ct;
+       int ret;
+       unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
 
-       gc = irq_alloc_generic_chip("SIRFINTC", 1, irq_start, base, handle_level_irq);
-       ct = gc->chip_types;
+       ret = irq_alloc_domain_generic_chips(sirfsoc_irqdomain, num, 1, "irq_sirfsoc",
+               handle_level_irq, clr, 0, IRQ_GC_INIT_MASK_CACHE);
 
+       gc = irq_get_domain_generic_chip(sirfsoc_irqdomain, irq_start);
+       gc->reg_base = base;
+       ct = gc->chip_types;
        ct->chip.irq_mask = irq_gc_mask_clr_bit;
        ct->chip.irq_unmask = irq_gc_mask_set_bit;
        ct->regs.mask = SIRFSOC_INT_RISC_MASK0;
-
-       irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE, IRQ_NOREQUEST, 0);
 }
 
 static asmlinkage void __exception_irq_entry sirfsoc_handle_irq(struct pt_regs *regs)
@@ -60,9 +63,8 @@ static int __init sirfsoc_irq_init(struct device_node *np, struct device_node *p
        if (!base)
                panic("unable to map intc cpu registers\n");
 
-       /* using legacy because irqchip_generic does not work with linear */
-       sirfsoc_irqdomain = irq_domain_add_legacy(np, SIRFSOC_NUM_IRQS, 0, 0,
-                                &irq_domain_simple_ops, base);
+       sirfsoc_irqdomain = irq_domain_add_linear(np, SIRFSOC_NUM_IRQS,
+               &irq_generic_chip_ops, base);
 
        sirfsoc_alloc_gc(base, 0, 32);
        sirfsoc_alloc_gc(base + 4, 32, SIRFSOC_NUM_IRQS - 32);
index 22b720e..77025f5 100644 (file)
@@ -288,8 +288,10 @@ dsp_control_req(struct dsp *dsp, struct mISDNhead *hh, struct sk_buff *skb)
        u8 *data;
        int len;
 
-       if (skb->len < sizeof(int))
+       if (skb->len < sizeof(int)) {
                printk(KERN_ERR "%s: PH_CONTROL message too short\n", __func__);
+               return -EINVAL;
+       }
        cont = *((int *)skb->data);
        len = skb->len - sizeof(int);
        data = skb->data + sizeof(int);
index f2d1ff1..0cc2611 100644 (file)
@@ -53,6 +53,7 @@ static inline void bnx2x_move_fp(struct bnx2x *bp, int from, int to)
        struct bnx2x_fp_stats *to_fp_stats = &bp->fp_stats[to];
        int old_max_eth_txqs, new_max_eth_txqs;
        int old_txdata_index = 0, new_txdata_index = 0;
+       struct bnx2x_agg_info *old_tpa_info = to_fp->tpa_info;
 
        /* Copy the NAPI object as it has been already initialized */
        from_fp->napi = to_fp->napi;
@@ -61,6 +62,11 @@ static inline void bnx2x_move_fp(struct bnx2x *bp, int from, int to)
        memcpy(to_fp, from_fp, sizeof(*to_fp));
        to_fp->index = to;
 
+       /* Retain the tpa_info of the original `to' version as we don't want
+        * 2 FPs to contain the same tpa_info pointer.
+        */
+       to_fp->tpa_info = old_tpa_info;
+
        /* move sp_objs contents as well, as their indices match fp ones */
        memcpy(to_sp_objs, from_sp_objs, sizeof(*to_sp_objs));
 
@@ -2956,8 +2962,9 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode, bool keep_link)
        if (IS_PF(bp)) {
                if (CNIC_LOADED(bp))
                        bnx2x_free_mem_cnic(bp);
-               bnx2x_free_mem(bp);
        }
+       bnx2x_free_mem(bp);
+
        bp->state = BNX2X_STATE_CLOSED;
        bp->cnic_loaded = false;
 
index 8bdc8b9..1627a4e 100644 (file)
@@ -7855,12 +7855,15 @@ void bnx2x_free_mem(struct bnx2x *bp)
 {
        int i;
 
-       BNX2X_PCI_FREE(bp->def_status_blk, bp->def_status_blk_mapping,
-                      sizeof(struct host_sp_status_block));
-
        BNX2X_PCI_FREE(bp->fw_stats, bp->fw_stats_mapping,
                       bp->fw_stats_data_sz + bp->fw_stats_req_sz);
 
+       if (IS_VF(bp))
+               return;
+
+       BNX2X_PCI_FREE(bp->def_status_blk, bp->def_status_blk_mapping,
+                      sizeof(struct host_sp_status_block));
+
        BNX2X_PCI_FREE(bp->slowpath, bp->slowpath_mapping,
                       sizeof(struct bnx2x_slowpath));
 
index ad83f4b..e8706e1 100644 (file)
@@ -522,23 +522,6 @@ static int bnx2x_vfop_set_user_req(struct bnx2x *bp,
        return 0;
 }
 
-static int
-bnx2x_vfop_config_vlan0(struct bnx2x *bp,
-                       struct bnx2x_vlan_mac_ramrod_params *vlan_mac,
-                       bool add)
-{
-       int rc;
-
-       vlan_mac->user_req.cmd = add ? BNX2X_VLAN_MAC_ADD :
-               BNX2X_VLAN_MAC_DEL;
-       vlan_mac->user_req.u.vlan.vlan = 0;
-
-       rc = bnx2x_config_vlan_mac(bp, vlan_mac);
-       if (rc == -EEXIST)
-               rc = 0;
-       return rc;
-}
-
 static int bnx2x_vfop_config_list(struct bnx2x *bp,
                                  struct bnx2x_vfop_filters *filters,
                                  struct bnx2x_vlan_mac_ramrod_params *vlan_mac)
@@ -643,30 +626,14 @@ static void bnx2x_vfop_vlan_mac(struct bnx2x *bp, struct bnx2x_virtf *vf)
 
        case BNX2X_VFOP_VLAN_CONFIG_LIST:
                /* next state */
-               vfop->state = BNX2X_VFOP_VLAN_CONFIG_LIST_0;
-
-               /* remove vlan0 - could be no-op */
-               vfop->rc = bnx2x_vfop_config_vlan0(bp, vlan_mac, false);
-               if (vfop->rc)
-                       goto op_err;
+               vfop->state = BNX2X_VFOP_VLAN_MAC_CHK_DONE;
 
-               /* Do vlan list config. if this operation fails we try to
-                * restore vlan0 to keep the queue is working order
-                */
+               /* do list config */
                vfop->rc = bnx2x_vfop_config_list(bp, filters, vlan_mac);
                if (!vfop->rc) {
                        set_bit(RAMROD_CONT, &vlan_mac->ramrod_flags);
                        vfop->rc = bnx2x_config_vlan_mac(bp, vlan_mac);
                }
-               bnx2x_vfop_finalize(vf, vfop->rc, VFOP_CONT); /* fall-through */
-
-       case BNX2X_VFOP_VLAN_CONFIG_LIST_0:
-               /* next state */
-               vfop->state = BNX2X_VFOP_VLAN_MAC_CHK_DONE;
-
-               if (list_empty(&obj->head))
-                       /* add vlan0 */
-                       vfop->rc = bnx2x_vfop_config_vlan0(bp, vlan_mac, true);
                bnx2x_vfop_finalize(vf, vfop->rc, VFOP_DONE);
 
        default:
@@ -2819,6 +2786,18 @@ int bnx2x_vf_init(struct bnx2x *bp, struct bnx2x_virtf *vf, dma_addr_t *sb_map)
        return 0;
 }
 
+struct set_vf_state_cookie {
+       struct bnx2x_virtf *vf;
+       u8 state;
+};
+
+void bnx2x_set_vf_state(void *cookie)
+{
+       struct set_vf_state_cookie *p = (struct set_vf_state_cookie *)cookie;
+
+       p->vf->state = p->state;
+}
+
 /* VFOP close (teardown the queues, delete mcasts and close HW) */
 static void bnx2x_vfop_close(struct bnx2x *bp, struct bnx2x_virtf *vf)
 {
@@ -2869,7 +2848,19 @@ static void bnx2x_vfop_close(struct bnx2x *bp, struct bnx2x_virtf *vf)
 op_err:
        BNX2X_ERR("VF[%d] CLOSE error: rc %d\n", vf->abs_vfid, vfop->rc);
 op_done:
-       vf->state = VF_ACQUIRED;
+
+       /* need to make sure there are no outstanding stats ramrods which may
+        * cause the device to access the VF's stats buffer which it will free
+        * as soon as we return from the close flow.
+        */
+       {
+               struct set_vf_state_cookie cookie;
+
+               cookie.vf = vf;
+               cookie.state = VF_ACQUIRED;
+               bnx2x_stats_safe_exec(bp, bnx2x_set_vf_state, &cookie);
+       }
+
        DP(BNX2X_MSG_IOV, "set state to acquired\n");
        bnx2x_vfop_end(bp, vf, vfop);
 }
index d63d132..86436c7 100644 (file)
@@ -522,20 +522,16 @@ static void bnx2x_func_stats_init(struct bnx2x *bp)
 /* should be called under stats_sema */
 static void __bnx2x_stats_start(struct bnx2x *bp)
 {
-       /* vfs travel through here as part of the statistics FSM, but no action
-        * is required
-        */
-       if (IS_VF(bp))
-               return;
-
-       if (bp->port.pmf)
-               bnx2x_port_stats_init(bp);
+       if (IS_PF(bp)) {
+               if (bp->port.pmf)
+                       bnx2x_port_stats_init(bp);
 
-       else if (bp->func_stx)
-               bnx2x_func_stats_init(bp);
+               else if (bp->func_stx)
+                       bnx2x_func_stats_init(bp);
 
-       bnx2x_hw_stats_post(bp);
-       bnx2x_storm_stats_post(bp);
+               bnx2x_hw_stats_post(bp);
+               bnx2x_storm_stats_post(bp);
+       }
 
        bp->stats_started = true;
 }
@@ -1997,3 +1993,14 @@ void bnx2x_afex_collect_stats(struct bnx2x *bp, void *void_afex_stats,
                       estats->mac_discard);
        }
 }
+
+void bnx2x_stats_safe_exec(struct bnx2x *bp,
+                          void (func_to_exec)(void *cookie),
+                          void *cookie){
+       if (down_timeout(&bp->stats_sema, HZ/10))
+               BNX2X_ERR("Unable to acquire stats lock\n");
+       bnx2x_stats_comp(bp);
+       func_to_exec(cookie);
+       __bnx2x_stats_start(bp);
+       up(&bp->stats_sema);
+}
index 853824d..f358450 100644 (file)
@@ -539,6 +539,9 @@ struct bnx2x;
 void bnx2x_memset_stats(struct bnx2x *bp);
 void bnx2x_stats_init(struct bnx2x *bp);
 void bnx2x_stats_handle(struct bnx2x *bp, enum bnx2x_stats_event event);
+void bnx2x_stats_safe_exec(struct bnx2x *bp,
+                          void (func_to_exec)(void *cookie),
+                          void *cookie);
 
 /**
  * bnx2x_save_statistics - save statistics when unloading.
index 4559c35..3d91a5e 100644 (file)
@@ -4373,6 +4373,10 @@ static int be_resume(struct pci_dev *pdev)
        pci_set_power_state(pdev, PCI_D0);
        pci_restore_state(pdev);
 
+       status = be_fw_wait_ready(adapter);
+       if (status)
+               return status;
+
        /* tell fw we're ready to fire cmds */
        status = be_cmd_fw_init(adapter);
        if (status)
index 77ea0db..c610a27 100644 (file)
@@ -971,8 +971,7 @@ fec_enet_rx(struct net_device *ndev, int budget)
                                                       htons(ETH_P_8021Q),
                                                       vlan_tag);
 
-                       if (!skb_defer_rx_timestamp(skb))
-                               napi_gro_receive(&fep->napi, skb);
+                       napi_gro_receive(&fep->napi, skb);
                }
 
                bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, data,
index 7fbe6ab..23de82a 100644 (file)
@@ -3069,7 +3069,7 @@ jme_init_one(struct pci_dev *pdev,
                jwrite32(jme, JME_APMC, apmc);
        }
 
-       NETIF_NAPI_SET(netdev, &jme->napi, jme_poll, jme->rx_ring_size >> 2)
+       NETIF_NAPI_SET(netdev, &jme->napi, jme_poll, NAPI_POLL_WEIGHT)
 
        spin_lock_init(&jme->phy_lock);
        spin_lock_init(&jme->macaddr_lock);
index 3fe09ab..32675e1 100644 (file)
@@ -1171,7 +1171,6 @@ typedef struct {
 
 #define NETXEN_DB_MAPSIZE_BYTES        0x1000
 
-#define NETXEN_NETDEV_WEIGHT 128
 #define NETXEN_ADAPTER_UP_MAGIC 777
 #define NETXEN_NIC_PEG_TUNE 0
 
index c401b0b..ec4cf7f 100644 (file)
@@ -197,7 +197,7 @@ netxen_napi_add(struct netxen_adapter *adapter, struct net_device *netdev)
        for (ring = 0; ring < adapter->max_sds_rings; ring++) {
                sds_ring = &recv_ctx->sds_rings[ring];
                netif_napi_add(netdev, &sds_ring->napi,
-                               netxen_nic_poll, NETXEN_NETDEV_WEIGHT);
+                               netxen_nic_poll, NAPI_POLL_WEIGHT);
        }
 
        return 0;
index 03de76c..1c83a44 100644 (file)
@@ -71,14 +71,18 @@ static int stmmac_probe_config_dt(struct platform_device *pdev,
                plat->force_sf_dma_mode = 1;
        }
 
-       dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*dma_cfg), GFP_KERNEL);
-       if (!dma_cfg)
-               return -ENOMEM;
-
-       plat->dma_cfg = dma_cfg;
-       of_property_read_u32(np, "snps,pbl", &dma_cfg->pbl);
-       dma_cfg->fixed_burst = of_property_read_bool(np, "snps,fixed-burst");
-       dma_cfg->mixed_burst = of_property_read_bool(np, "snps,mixed-burst");
+       if (of_find_property(np, "snps,pbl", NULL)) {
+               dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*dma_cfg),
+                                      GFP_KERNEL);
+               if (!dma_cfg)
+                       return -ENOMEM;
+               plat->dma_cfg = dma_cfg;
+               of_property_read_u32(np, "snps,pbl", &dma_cfg->pbl);
+               dma_cfg->fixed_burst =
+                       of_property_read_bool(np, "snps,fixed-burst");
+               dma_cfg->mixed_burst =
+                       of_property_read_bool(np, "snps,mixed-burst");
+       }
 
        return 0;
 }
index ad32af6..9c805e0 100644 (file)
@@ -1466,8 +1466,7 @@ static void gelic_ether_setup_netdev_ops(struct net_device *netdev,
 {
        netdev->watchdog_timeo = GELIC_NET_WATCHDOG_TIMEOUT;
        /* NAPI */
-       netif_napi_add(netdev, napi,
-                      gelic_net_poll, GELIC_NET_NAPI_WEIGHT);
+       netif_napi_add(netdev, napi, gelic_net_poll, NAPI_POLL_WEIGHT);
        netdev->ethtool_ops = &gelic_ether_ethtool_ops;
        netdev->netdev_ops = &gelic_netdevice_ops;
 }
index a93df6a..309abb4 100644 (file)
@@ -37,7 +37,6 @@
 #define GELIC_NET_RXBUF_ALIGN           128
 #define GELIC_CARD_RX_CSUM_DEFAULT      1 /* hw chksum */
 #define GELIC_NET_WATCHDOG_TIMEOUT      5*HZ
-#define GELIC_NET_NAPI_WEIGHT           (GELIC_NET_RX_DESCRIPTORS)
 #define GELIC_NET_BROADCAST_ADDR        0xffffffffffffL
 
 #define GELIC_NET_MC_COUNT_MAX          32 /* multicast address list */
index e90e1f4..64b4639 100644 (file)
@@ -175,6 +175,7 @@ int axienet_mdio_setup(struct axienet_local *lp, struct device_node *np)
                printk(KERN_WARNING "Setting MDIO clock divisor to "
                       "default %d\n", DEFAULT_CLOCK_DIVISOR);
                clk_div = DEFAULT_CLOCK_DIVISOR;
+               of_node_put(np1);
                goto issue;
        }
 
index 8728198..25ba7ec 100644 (file)
@@ -400,6 +400,10 @@ static const struct usb_device_id mbim_devs[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x68a2, USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE),
          .driver_info = (unsigned long)&cdc_mbim_info_zlp,
        },
+       /* HP hs2434 Mobile Broadband Module needs ZLPs */
+       { USB_DEVICE_AND_INTERFACE_INFO(0x3f0, 0x4b1d, USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE),
+         .driver_info = (unsigned long)&cdc_mbim_info_zlp,
+       },
        { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE),
          .driver_info = (unsigned long)&cdc_mbim_info,
        },
index e602c95..c028df7 100644 (file)
@@ -448,6 +448,7 @@ static void ath9k_htc_tx_process(struct ath9k_htc_priv *priv,
        struct ieee80211_conf *cur_conf = &priv->hw->conf;
        bool txok;
        int slot;
+       int hdrlen, padsize;
 
        slot = strip_drv_header(priv, skb);
        if (slot < 0) {
@@ -504,6 +505,15 @@ send_mac80211:
 
        ath9k_htc_tx_clear_slot(priv, slot);
 
+       /* Remove padding before handing frame back to mac80211 */
+       hdrlen = ieee80211_get_hdrlen_from_skb(skb);
+
+       padsize = hdrlen & 3;
+       if (padsize && skb->len > hdrlen + padsize) {
+               memmove(skb->data + padsize, skb->data, hdrlen);
+               skb_pull(skb, padsize);
+       }
+
        /* Send status to mac80211 */
        ieee80211_tx_status(priv->hw, skb);
 }
index 16f8b20..026a2a0 100644 (file)
@@ -802,7 +802,8 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
                IEEE80211_HW_PS_NULLFUNC_STACK |
                IEEE80211_HW_SPECTRUM_MGMT |
                IEEE80211_HW_REPORTS_TX_ACK_STATUS |
-               IEEE80211_HW_SUPPORTS_RC_TABLE;
+               IEEE80211_HW_SUPPORTS_RC_TABLE |
+               IEEE80211_HW_SUPPORTS_HT_CCK_RATES;
 
        if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
                hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION;
index 1737a3e..cb5a655 100644 (file)
@@ -173,8 +173,7 @@ static void ath_restart_work(struct ath_softc *sc)
 {
        ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
 
-       if (AR_SREV_9340(sc->sc_ah) || AR_SREV_9485(sc->sc_ah) ||
-           AR_SREV_9550(sc->sc_ah))
+       if (AR_SREV_9340(sc->sc_ah) || AR_SREV_9330(sc->sc_ah))
                ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work,
                                     msecs_to_jiffies(ATH_PLL_WORK_INTERVAL));
 
index 4a33c6e..349fa22 100644 (file)
@@ -1860,7 +1860,8 @@ void *carl9170_alloc(size_t priv_size)
                     IEEE80211_HW_PS_NULLFUNC_STACK |
                     IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC |
                     IEEE80211_HW_SUPPORTS_RC_TABLE |
-                    IEEE80211_HW_SIGNAL_DBM;
+                    IEEE80211_HW_SIGNAL_DBM |
+                    IEEE80211_HW_SUPPORTS_HT_CCK_RATES;
 
        if (!modparam_noht) {
                /*
index f2ed62e..7acf5ee 100644 (file)
@@ -4464,9 +4464,9 @@ il4965_irq_tasklet(struct il_priv *il)
                        set_bit(S_RFKILL, &il->status);
                } else {
                        clear_bit(S_RFKILL, &il->status);
-                       wiphy_rfkill_set_hw_state(il->hw->wiphy, hw_rf_kill);
                        il_force_reset(il, true);
                }
+               wiphy_rfkill_set_hw_state(il->hw->wiphy, hw_rf_kill);
 
                handled |= CSR_INT_BIT_RF_KILL;
        }
index 1f80ea5..1b41c8e 100644 (file)
@@ -6133,7 +6133,8 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
            IEEE80211_HW_SUPPORTS_PS |
            IEEE80211_HW_PS_NULLFUNC_STACK |
            IEEE80211_HW_AMPDU_AGGREGATION |
-           IEEE80211_HW_REPORTS_TX_ACK_STATUS;
+           IEEE80211_HW_REPORTS_TX_ACK_STATUS |
+           IEEE80211_HW_SUPPORTS_HT_CCK_RATES;
 
        /*
         * Don't set IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING for USB devices
index 5456f5c..4a21957 100644 (file)
@@ -221,7 +221,7 @@ static void init_default_table_values(struct pm8001_hba_info *pm8001_ha)
        pm8001_ha->main_cfg_tbl.pm8001_tbl.fatal_err_interrupt          = 0x01;
        for (i = 0; i < PM8001_MAX_INB_NUM; i++) {
                pm8001_ha->inbnd_q_tbl[i].element_pri_size_cnt  =
-                       PM8001_MPI_QUEUE | (64 << 16) | (0x00<<30);
+                       PM8001_MPI_QUEUE | (pm8001_ha->iomb_size << 16) | (0x00<<30);
                pm8001_ha->inbnd_q_tbl[i].upper_base_addr       =
                        pm8001_ha->memoryMap.region[IB + i].phys_addr_hi;
                pm8001_ha->inbnd_q_tbl[i].lower_base_addr       =
@@ -247,7 +247,7 @@ static void init_default_table_values(struct pm8001_hba_info *pm8001_ha)
        }
        for (i = 0; i < PM8001_MAX_OUTB_NUM; i++) {
                pm8001_ha->outbnd_q_tbl[i].element_size_cnt     =
-                       PM8001_MPI_QUEUE | (64 << 16) | (0x01<<30);
+                       PM8001_MPI_QUEUE | (pm8001_ha->iomb_size << 16) | (0x01<<30);
                pm8001_ha->outbnd_q_tbl[i].upper_base_addr      =
                        pm8001_ha->memoryMap.region[OB + i].phys_addr_hi;
                pm8001_ha->outbnd_q_tbl[i].lower_base_addr      =
index 7f77210..9f91030 100644 (file)
@@ -275,7 +275,7 @@ static void init_default_table_values(struct pm8001_hba_info *pm8001_ha)
 
        for (i = 0; i < PM8001_MAX_SPCV_INB_NUM; i++) {
                pm8001_ha->inbnd_q_tbl[i].element_pri_size_cnt  =
-                       PM8001_MPI_QUEUE | (64 << 16) | (0x00<<30);
+                       PM8001_MPI_QUEUE | (pm8001_ha->iomb_size << 16) | (0x00<<30);
                pm8001_ha->inbnd_q_tbl[i].upper_base_addr       =
                        pm8001_ha->memoryMap.region[IB + i].phys_addr_hi;
                pm8001_ha->inbnd_q_tbl[i].lower_base_addr       =
@@ -301,7 +301,7 @@ static void init_default_table_values(struct pm8001_hba_info *pm8001_ha)
        }
        for (i = 0; i < PM8001_MAX_SPCV_OUTB_NUM; i++) {
                pm8001_ha->outbnd_q_tbl[i].element_size_cnt     =
-                       PM8001_MPI_QUEUE | (64 << 16) | (0x01<<30);
+                       PM8001_MPI_QUEUE | (pm8001_ha->iomb_size << 16) | (0x01<<30);
                pm8001_ha->outbnd_q_tbl[i].upper_base_addr      =
                        pm8001_ha->memoryMap.region[OB + i].phys_addr_hi;
                pm8001_ha->outbnd_q_tbl[i].lower_base_addr      =
index 89cbbab..0170d4c 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,28 @@ 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_TI_QSPI
+       tristate "DRA7xxx QSPI controller support"
+       depends on ARCH_OMAP2PLUS || COMPILE_TEST
+       help
+         QSPI master controller for DRA7xxx used for flash devices.
+         This device supports single, dual and quad read support, while
+         it only supports single write mode.
+
 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 +370,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 +414,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,13 +427,13 @@ 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.
 
 config SPI_SIRF
        tristate "CSR SiRFprimaII SPI controller"
-       depends on ARCH_SIRF
+       depends on SIRF_DMA
        select SPI_BITBANG
        help
          SPI driver for CSR SiRFprimaII SoCs
@@ -418,7 +447,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 +455,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 +463,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 +486,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..ab8d864 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
@@ -46,6 +49,7 @@ obj-$(CONFIG_SPI_OCTEON)              += spi-octeon.o
 obj-$(CONFIG_SPI_OMAP_UWIRE)           += spi-omap-uwire.o
 obj-$(CONFIG_SPI_OMAP_100K)            += spi-omap-100k.o
 obj-$(CONFIG_SPI_OMAP24XX)             += spi-omap2-mcspi.o
+obj-$(CONFIG_SPI_TI_QSPI)              += spi-ti-qspi.o
 obj-$(CONFIG_SPI_ORION)                        += spi-orion.o
 obj-$(CONFIG_SPI_PL022)                        += spi-pl022.o
 obj-$(CONFIG_SPI_PPC4xx)               += spi-ppc4xx.o
index 81b9adb..f38855f 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;
@@ -217,7 +200,7 @@ static irqreturn_t altera_spi_irq(int irq, void *dev)
 
 static int altera_spi_probe(struct platform_device *pdev)
 {
-       struct altera_spi_platform_data *platp = pdev->dev.platform_data;
+       struct altera_spi_platform_data *platp = dev_get_platdata(&pdev->dev);
        struct altera_spi *hw;
        struct spi_master *master;
        struct resource *res;
@@ -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 0e06407..37bad95 100644 (file)
@@ -221,7 +221,7 @@ static int ath79_spi_probe(struct platform_device *pdev)
        sp = spi_master_get_devdata(master);
        platform_set_drvdata(pdev, sp);
 
-       pdata = pdev->dev.platform_data;
+       pdata = dev_get_platdata(&pdev->dev);
 
        master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32);
        master->setup = ath79_spi_setup;
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 e196555..1d00d9b 100644 (file)
@@ -776,7 +776,7 @@ static int au1550_spi_probe(struct platform_device *pdev)
        hw = spi_master_get_devdata(master);
 
        hw->master = spi_master_get(master);
-       hw->pdata = pdev->dev.platform_data;
+       hw->pdata = dev_get_platdata(&pdev->dev);
        hw->dev = &pdev->dev;
 
        if (hw->pdata == NULL) {
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..536b0e3 100644 (file)
@@ -231,24 +231,6 @@ static int bcm63xx_txrx_bufs(struct spi_device *spi, struct spi_transfer *first,
        return 0;
 }
 
-static int bcm63xx_spi_prepare_transfer(struct spi_master *master)
-{
-       struct bcm63xx_spi *bs = spi_master_get_devdata(master);
-
-       pm_runtime_get_sync(&bs->pdev->dev);
-
-       return 0;
-}
-
-static int bcm63xx_spi_unprepare_transfer(struct spi_master *master)
-{
-       struct bcm63xx_spi *bs = spi_master_get_devdata(master);
-
-       pm_runtime_put(&bs->pdev->dev);
-
-       return 0;
-}
-
 static int bcm63xx_spi_transfer_one(struct spi_master *master,
                                        struct spi_message *m)
 {
@@ -353,20 +335,13 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
 {
        struct resource *r;
        struct device *dev = &pdev->dev;
-       struct bcm63xx_spi_pdata *pdata = pdev->dev.platform_data;
+       struct bcm63xx_spi_pdata *pdata = dev_get_platdata(&pdev->dev);
        int irq;
        struct spi_master *master;
        struct clk *clk;
        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 +368,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);
@@ -412,11 +388,10 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
 
        master->bus_num = pdata->bus_num;
        master->num_chipselect = pdata->num_chipselect;
-       master->prepare_transfer_hardware = bcm63xx_spi_prepare_transfer;
-       master->unprepare_transfer_hardware = bcm63xx_spi_unprepare_transfer;
        master->transfer_one_message = bcm63xx_spi_transfer_one;
        master->mode_bits = MODEBITS;
        master->bits_per_word_mask = SPI_BPW_MASK(8);
+       master->auto_runtime_pm = true;
        bs->msg_type_shift = pdata->msg_type_shift;
        bs->msg_ctl_width = pdata->msg_ctl_width;
        bs->tx_io = (u8 *)(bs->regs + bcm63xx_spireg(SPI_MSG_DATA));
@@ -480,8 +455,7 @@ static int bcm63xx_spi_remove(struct platform_device *pdev)
 #ifdef CONFIG_PM
 static int bcm63xx_spi_suspend(struct device *dev)
 {
-       struct spi_master *master =
-                       platform_get_drvdata(to_platform_device(dev));
+       struct spi_master *master = dev_get_drvdata(dev);
        struct bcm63xx_spi *bs = spi_master_get_devdata(master);
 
        spi_master_suspend(master);
@@ -493,8 +467,7 @@ static int bcm63xx_spi_suspend(struct device *dev)
 
 static int bcm63xx_spi_resume(struct device *dev)
 {
-       struct spi_master *master =
-                       platform_get_drvdata(to_platform_device(dev));
+       struct spi_master *master = dev_get_drvdata(dev);
        struct bcm63xx_spi *bs = spi_master_get_devdata(master);
 
        clk_prepare_enable(bs->clk);
index 07ec597..91921b5 100644 (file)
@@ -756,7 +756,7 @@ static int bfin_sport_spi_probe(struct platform_device *pdev)
        struct bfin_sport_spi_master_data *drv_data;
        int status;
 
-       platform_info = dev->platform_data;
+       platform_info = dev_get_platdata(dev);
 
        /* Allocate master with space for drv_data */
        master = spi_alloc_master(dev, sizeof(*master) + 16);
diff --git a/drivers/spi/spi-bfin-v3.c b/drivers/spi/spi-bfin-v3.c
new file mode 100644 (file)
index 0000000..f4bf813
--- /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_get_platdata(dev);
+       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 59a7342..45bdf73 100644 (file)
@@ -1271,7 +1271,7 @@ static int bfin_spi_probe(struct platform_device *pdev)
        struct resource *res;
        int status = 0;
 
-       platform_info = dev->platform_data;
+       platform_info = dev_get_platdata(dev);
 
        /* Allocate master with space for drv_data */
        master = spi_alloc_master(dev, sizeof(*drv_data));
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);
 
index 0631b9d..cc5b75d 100644 (file)
@@ -354,24 +354,6 @@ static int mcfqspi_transfer_one_message(struct spi_master *master,
 
 }
 
-static int mcfqspi_prepare_transfer_hw(struct spi_master *master)
-{
-       struct mcfqspi *mcfqspi = spi_master_get_devdata(master);
-
-       pm_runtime_get_sync(mcfqspi->dev);
-
-       return 0;
-}
-
-static int mcfqspi_unprepare_transfer_hw(struct spi_master *master)
-{
-       struct mcfqspi *mcfqspi = spi_master_get_devdata(master);
-
-       pm_runtime_put_sync(mcfqspi->dev);
-
-       return 0;
-}
-
 static int mcfqspi_setup(struct spi_device *spi)
 {
        if (spi->chip_select >= spi->master->num_chipselect) {
@@ -400,7 +382,7 @@ static int mcfqspi_probe(struct platform_device *pdev)
        struct mcfqspi_platform_data *pdata;
        int status;
 
-       pdata = pdev->dev.platform_data;
+       pdata = dev_get_platdata(&pdev->dev);
        if (!pdata) {
                dev_dbg(&pdev->dev, "platform data is missing\n");
                return -ENOENT;
@@ -473,8 +455,7 @@ static int mcfqspi_probe(struct platform_device *pdev)
        master->bits_per_word_mask = SPI_BPW_RANGE_MASK(8, 16);
        master->setup = mcfqspi_setup;
        master->transfer_one_message = mcfqspi_transfer_one_message;
-       master->prepare_transfer_hardware = mcfqspi_prepare_transfer_hw;
-       master->unprepare_transfer_hardware = mcfqspi_unprepare_transfer_hw;
+       master->auto_runtime_pm = true;
 
        platform_set_drvdata(pdev, master);
 
@@ -558,7 +539,7 @@ static int mcfqspi_resume(struct device *dev)
 #ifdef CONFIG_PM_RUNTIME
 static int mcfqspi_runtime_suspend(struct device *dev)
 {
-       struct mcfqspi *mcfqspi = platform_get_drvdata(to_platform_device(dev));
+       struct mcfqspi *mcfqspi = dev_get_drvdata(dev);
 
        clk_disable(mcfqspi->clk);
 
@@ -567,7 +548,7 @@ static int mcfqspi_runtime_suspend(struct device *dev)
 
 static int mcfqspi_runtime_resume(struct device *dev)
 {
-       struct mcfqspi *mcfqspi = platform_get_drvdata(to_platform_device(dev));
+       struct mcfqspi *mcfqspi = dev_get_drvdata(dev);
 
        clk_enable(mcfqspi->clk);
 
index 707966b..8fbfe24 100644 (file)
@@ -872,8 +872,8 @@ static int davinci_spi_probe(struct platform_device *pdev)
                goto free_master;
        }
 
-       if (pdev->dev.platform_data) {
-               pdata = pdev->dev.platform_data;
+       if (dev_get_platdata(&pdev->dev)) {
+               pdata = dev_get_platdata(&pdev->dev);
                dspi->pdata = *pdata;
        } else {
                /* update dspi pdata with that from the DT */
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..d22c00a 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,72 +279,10 @@ 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)
@@ -1022,16 +874,26 @@ static int ep93xx_spi_probe(struct platform_device *pdev)
        int irq;
        int error;
 
-       info = pdev->dev.platform_data;
+       info = dev_get_platdata(&pdev->dev);
+
+       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 6a74d78..b8f1103 100644 (file)
@@ -584,7 +584,7 @@ static void fsl_espi_remove(struct mpc8xxx_spi *mspi)
 static struct spi_master * fsl_espi_probe(struct device *dev,
                struct resource *mem, unsigned int irq)
 {
-       struct fsl_spi_platform_data *pdata = dev->platform_data;
+       struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
        struct spi_master *master;
        struct mpc8xxx_spi *mpc8xxx_spi;
        struct fsl_espi_reg *reg_base;
@@ -665,7 +665,7 @@ err:
 static int of_fsl_espi_get_chipselects(struct device *dev)
 {
        struct device_node *np = dev->of_node;
-       struct fsl_spi_platform_data *pdata = dev->platform_data;
+       struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
        const u32 *prop;
        int len;
 
index e947f2d..0b75f26 100644 (file)
@@ -122,7 +122,7 @@ const char *mpc8xxx_spi_strmode(unsigned int flags)
 int mpc8xxx_spi_probe(struct device *dev, struct resource *mem,
                        unsigned int irq)
 {
-       struct fsl_spi_platform_data *pdata = dev->platform_data;
+       struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
        struct spi_master *master;
        struct mpc8xxx_spi *mpc8xxx_spi;
        int ret = 0;
index 41e89c3..bbc9429 100644 (file)
@@ -574,7 +574,7 @@ static void fsl_spi_grlib_cs_control(struct spi_device *spi, bool on)
 
 static void fsl_spi_grlib_probe(struct device *dev)
 {
-       struct fsl_spi_platform_data *pdata = dev->platform_data;
+       struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
        struct spi_master *master = dev_get_drvdata(dev);
        struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master);
        struct fsl_spi_reg *reg_base = mpc8xxx_spi->reg_base;
@@ -600,7 +600,7 @@ static void fsl_spi_grlib_probe(struct device *dev)
 static struct spi_master * fsl_spi_probe(struct device *dev,
                struct resource *mem, unsigned int irq)
 {
-       struct fsl_spi_platform_data *pdata = dev->platform_data;
+       struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
        struct spi_master *master;
        struct mpc8xxx_spi *mpc8xxx_spi;
        struct fsl_spi_reg *reg_base;
@@ -700,7 +700,8 @@ err:
 static void fsl_spi_cs_control(struct spi_device *spi, bool on)
 {
        struct device *dev = spi->dev.parent->parent;
-       struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(dev->platform_data);
+       struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
+       struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata);
        u16 cs = spi->chip_select;
        int gpio = pinfo->gpios[cs];
        bool alow = pinfo->alow_flags[cs];
@@ -711,7 +712,7 @@ static void fsl_spi_cs_control(struct spi_device *spi, bool on)
 static int of_fsl_spi_get_chipselects(struct device *dev)
 {
        struct device_node *np = dev->of_node;
-       struct fsl_spi_platform_data *pdata = dev->platform_data;
+       struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
        struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata);
        int ngpios;
        int i = 0;
@@ -790,7 +791,7 @@ err_alloc_flags:
 
 static int of_fsl_spi_free_chipselects(struct device *dev)
 {
-       struct fsl_spi_platform_data *pdata = dev->platform_data;
+       struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
        struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata);
        int i;
 
@@ -889,7 +890,7 @@ static int plat_mpc8xxx_spi_probe(struct platform_device *pdev)
        int irq;
        struct spi_master *master;
 
-       if (!pdev->dev.platform_data)
+       if (!dev_get_platdata(&pdev->dev))
                return -EINVAL;
 
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
index a54524c..68b69fe 100644 (file)
@@ -420,7 +420,7 @@ static int spi_gpio_probe(struct platform_device *pdev)
        if (status > 0)
                use_of = 1;
 
-       pdata = pdev->dev.platform_data;
+       pdata = dev_get_platdata(&pdev->dev);
 #ifdef GENERIC_BITBANG
        if (!pdata || !pdata->num_chipselect)
                return -ENODEV;
@@ -506,7 +506,7 @@ static int spi_gpio_remove(struct platform_device *pdev)
        int                             status;
 
        spi_gpio = platform_get_drvdata(pdev);
-       pdata = pdev->dev.platform_data;
+       pdata = dev_get_platdata(&pdev->dev);
 
        /* stop() unregisters child devices too */
        status = spi_bitbang_stop(&spi_gpio->bitbang);
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 29fce6a..dbc5e99 100644 (file)
@@ -38,7 +38,8 @@ struct mpc512x_psc_spi {
        struct mpc512x_psc_fifo __iomem *fifo;
        unsigned int irq;
        u8 bits_per_word;
-       u32 mclk;
+       struct clk *clk_mclk;
+       u32 mclk_rate;
 
        struct completion txisrdone;
 };
@@ -72,6 +73,7 @@ static void mpc512x_psc_spi_activate_cs(struct spi_device *spi)
        struct mpc52xx_psc __iomem *psc = mps->psc;
        u32 sicr;
        u32 ccr;
+       int speed;
        u16 bclkdiv;
 
        sicr = in_be32(&psc->sicr);
@@ -95,10 +97,10 @@ static void mpc512x_psc_spi_activate_cs(struct spi_device *spi)
 
        ccr = in_be32(&psc->ccr);
        ccr &= 0xFF000000;
-       if (cs->speed_hz)
-               bclkdiv = (mps->mclk / cs->speed_hz) - 1;
-       else
-               bclkdiv = (mps->mclk / 1000000) - 1;    /* default 1MHz */
+       speed = cs->speed_hz;
+       if (!speed)
+               speed = 1000000;        /* default 1MHz */
+       bclkdiv = (mps->mclk_rate / speed) - 1;
 
        ccr |= (((bclkdiv & 0xff) << 16) | (((bclkdiv >> 8) & 0xff) << 8));
        out_be32(&psc->ccr, ccr);
@@ -386,19 +388,11 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master,
 {
        struct mpc52xx_psc __iomem *psc = mps->psc;
        struct mpc512x_psc_fifo __iomem *fifo = mps->fifo;
-       struct clk *spiclk;
-       int ret = 0;
-       char name[32];
        u32 sicr;
        u32 ccr;
+       int speed;
        u16 bclkdiv;
 
-       sprintf(name, "psc%d_mclk", master->bus_num);
-       spiclk = clk_get(&master->dev, name);
-       clk_enable(spiclk);
-       mps->mclk = clk_get_rate(spiclk);
-       clk_put(spiclk);
-
        /* Reset the PSC into a known state */
        out_8(&psc->command, MPC52xx_PSC_RST_RX);
        out_8(&psc->command, MPC52xx_PSC_RST_TX);
@@ -425,7 +419,8 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master,
 
        ccr = in_be32(&psc->ccr);
        ccr &= 0xFF000000;
-       bclkdiv = (mps->mclk / 1000000) - 1;    /* default 1MHz */
+       speed = 1000000;        /* default 1MHz */
+       bclkdiv = (mps->mclk_rate / speed) - 1;
        ccr |= (((bclkdiv & 0xff) << 16) | (((bclkdiv >> 8) & 0xff) << 8));
        out_be32(&psc->ccr, ccr);
 
@@ -445,7 +440,7 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master,
 
        mps->bits_per_word = 8;
 
-       return ret;
+       return 0;
 }
 
 static irqreturn_t mpc512x_psc_spi_isr(int irq, void *dev_id)
@@ -474,11 +469,14 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
                                              u32 size, unsigned int irq,
                                              s16 bus_num)
 {
-       struct fsl_spi_platform_data *pdata = dev->platform_data;
+       struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
        struct mpc512x_psc_spi *mps;
        struct spi_master *master;
        int ret;
        void *tempp;
+       int psc_num;
+       char clk_name[16];
+       struct clk *clk;
 
        master = spi_alloc_master(dev, sizeof *mps);
        if (master == NULL)
@@ -521,16 +519,29 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
                goto free_master;
        init_completion(&mps->txisrdone);
 
+       psc_num = master->bus_num;
+       snprintf(clk_name, sizeof(clk_name), "psc%d_mclk", psc_num);
+       clk = devm_clk_get(dev, clk_name);
+       if (IS_ERR(clk))
+               goto free_irq;
+       ret = clk_prepare_enable(clk);
+       if (ret)
+               goto free_irq;
+       mps->clk_mclk = clk;
+       mps->mclk_rate = clk_get_rate(clk);
+
        ret = mpc512x_psc_spi_port_config(master, mps);
        if (ret < 0)
-               goto free_irq;
+               goto free_clock;
 
        ret = spi_register_master(master);
        if (ret < 0)
-               goto free_irq;
+               goto free_clock;
 
        return ret;
 
+free_clock:
+       clk_disable_unprepare(mps->clk_mclk);
 free_irq:
        free_irq(mps->irq, mps);
 free_master:
@@ -547,6 +558,7 @@ static int mpc512x_psc_spi_do_remove(struct device *dev)
        struct mpc512x_psc_spi *mps = spi_master_get_devdata(master);
 
        spi_unregister_master(master);
+       clk_disable_unprepare(mps->clk_mclk);
        free_irq(mps->irq, mps);
        if (mps->psc)
                iounmap(mps->psc);
index fed0571..6e925dc 100644 (file)
@@ -366,7 +366,7 @@ static irqreturn_t mpc52xx_psc_spi_isr(int irq, void *dev_id)
 static int mpc52xx_psc_spi_do_probe(struct device *dev, u32 regaddr,
                                u32 size, unsigned int irq, s16 bus_num)
 {
-       struct fsl_spi_platform_data *pdata = dev->platform_data;
+       struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
        struct mpc52xx_psc_spi *mps;
        struct spi_master *master;
        int ret;
index 424d38e..de7b114 100644 (file)
@@ -67,13 +67,8 @@ static int mxs_spi_setup_transfer(struct spi_device *dev,
 {
        struct mxs_spi *spi = spi_master_get_devdata(dev->master);
        struct mxs_ssp *ssp = &spi->ssp;
-       uint8_t bits_per_word;
        uint32_t hz = 0;
 
-       bits_per_word = dev->bits_per_word;
-       if (t && t->bits_per_word)
-               bits_per_word = t->bits_per_word;
-
        hz = dev->max_speed_hz;
        if (t && t->speed_hz)
                hz = min(hz, t->speed_hz);
@@ -513,7 +508,7 @@ static int mxs_spi_probe(struct platform_device *pdev)
 
        iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        irq_err = platform_get_irq(pdev, 0);
-       if (!iores || irq_err < 0)
+       if (irq_err < 0)
                return -EINVAL;
 
        base = devm_ioremap_resource(&pdev->dev, iores);
@@ -563,25 +558,31 @@ static int mxs_spi_probe(struct platform_device *pdev)
                goto out_master_free;
        }
 
-       clk_prepare_enable(ssp->clk);
+       ret = clk_prepare_enable(ssp->clk);
+       if (ret)
+               goto out_dma_release;
+
        clk_set_rate(ssp->clk, clk_freq);
        ssp->clk_rate = clk_get_rate(ssp->clk) / 1000;
 
-       stmp_reset_block(ssp->base);
+       ret = stmp_reset_block(ssp->base);
+       if (ret)
+               goto out_disable_clk;
 
        platform_set_drvdata(pdev, master);
 
        ret = spi_register_master(master);
        if (ret) {
                dev_err(&pdev->dev, "Cannot register SPI master, %d\n", ret);
-               goto out_free_dma;
+               goto out_disable_clk;
        }
 
        return 0;
 
-out_free_dma:
-       dma_release_channel(ssp->dmach);
+out_disable_clk:
        clk_disable_unprepare(ssp->clk);
+out_dma_release:
+       dma_release_channel(ssp->dmach);
 out_master_free:
        spi_master_put(master);
        return ret;
@@ -598,11 +599,8 @@ static int mxs_spi_remove(struct platform_device *pdev)
        ssp = &spi->ssp;
 
        spi_unregister_master(master);
-
-       dma_release_channel(ssp->dmach);
-
        clk_disable_unprepare(ssp->clk);
-
+       dma_release_channel(ssp->dmach);
        spi_master_put(master);
 
        return 0;
index 150d854..47a68b4 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;
@@ -361,7 +350,7 @@ static int nuc900_spi_probe(struct platform_device *pdev)
 
        hw = spi_master_get_devdata(master);
        hw->master = spi_master_get(master);
-       hw->pdata  = pdev->dev.platform_data;
+       hw->pdata  = dev_get_platdata(&pdev->dev);
        hw->dev = &pdev->dev;
 
        if (hw->pdata == NULL) {
@@ -373,14 +362,12 @@ static int nuc900_spi_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, hw);
        init_completion(&hw->done);
 
-       master->mode_bits          = SPI_MODE_0;
+       master->mode_bits          = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
        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..333cb1b 100644 (file)
@@ -285,7 +285,7 @@ static int tiny_spi_of_probe(struct platform_device *pdev)
 
 static int tiny_spi_probe(struct platform_device *pdev)
 {
-       struct tiny_spi_platform_data *platp = pdev->dev.platform_data;
+       struct tiny_spi_platform_data *platp = dev_get_platdata(&pdev->dev);
        struct tiny_spi *hw;
        struct spi_master *master;
        struct resource *res;
@@ -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 24daf96..5f28ddb 100644 (file)
@@ -28,7 +28,6 @@
 #define OCTEON_SPI_MAX_CLOCK_HZ 16000000
 
 struct octeon_spi {
-       struct spi_master *my_master;
        u64 register_base;
        u64 last_cfg;
        u64 cs_enax;
@@ -64,7 +63,6 @@ static int octeon_spi_do_transfer(struct octeon_spi *p,
        unsigned int speed_hz;
        int mode;
        bool cpha, cpol;
-       int bits_per_word;
        const u8 *tx_buf;
        u8 *rx_buf;
        int len;
@@ -76,12 +74,9 @@ static int octeon_spi_do_transfer(struct octeon_spi *p,
        mode = msg_setup->mode;
        cpha = mode & SPI_CPHA;
        cpol = mode & SPI_CPOL;
-       bits_per_word = msg_setup->bits_per_word;
 
        if (xfer->speed_hz)
                speed_hz = xfer->speed_hz;
-       if (xfer->bits_per_word)
-               bits_per_word = xfer->bits_per_word;
 
        if (speed_hz > OCTEON_SPI_MAX_CLOCK_HZ)
                speed_hz = OCTEON_SPI_MAX_CLOCK_HZ;
@@ -166,19 +161,6 @@ static int octeon_spi_do_transfer(struct octeon_spi *p,
        return xfer->len;
 }
 
-static int octeon_spi_validate_bpw(struct spi_device *spi, u32 speed)
-{
-       switch (speed) {
-       case 8:
-               break;
-       default:
-               dev_err(&spi->dev, "Error: %d bits per word not supported\n",
-                       speed);
-               return -EINVAL;
-       }
-       return 0;
-}
-
 static int octeon_spi_transfer_one_message(struct spi_master *master,
                                           struct spi_message *msg)
 {
@@ -196,15 +178,6 @@ static int octeon_spi_transfer_one_message(struct spi_master *master,
                goto err;
        }
 
-       list_for_each_entry(xfer, &msg->transfers, transfer_list) {
-               if (xfer->bits_per_word) {
-                       status = octeon_spi_validate_bpw(msg->spi,
-                                                        xfer->bits_per_word);
-                       if (status)
-                               goto err;
-               }
-       }
-
        list_for_each_entry(xfer, &msg->transfers, transfer_list) {
                bool last_xfer = &xfer->transfer_list == msg->transfers.prev;
                int r = octeon_spi_do_transfer(p, msg, xfer, last_xfer);
@@ -236,14 +209,9 @@ static struct octeon_spi_setup *octeon_spi_new_setup(struct spi_device *spi)
 
 static int octeon_spi_setup(struct spi_device *spi)
 {
-       int r;
        struct octeon_spi_setup *new_setup;
        struct octeon_spi_setup *old_setup = spi_get_ctldata(spi);
 
-       r = octeon_spi_validate_bpw(spi, spi->bits_per_word);
-       if (r)
-               return r;
-
        new_setup = octeon_spi_new_setup(spi);
        if (!new_setup)
                return -ENOMEM;
@@ -261,14 +229,8 @@ static void octeon_spi_cleanup(struct spi_device *spi)
        kfree(old_setup);
 }
 
-static int octeon_spi_nop_transfer_hardware(struct spi_master *master)
-{
-       return 0;
-}
-
 static int octeon_spi_probe(struct platform_device *pdev)
 {
-
        struct resource *res_mem;
        struct spi_master *master;
        struct octeon_spi *p;
@@ -278,8 +240,7 @@ static int octeon_spi_probe(struct platform_device *pdev)
        if (!master)
                return -ENOMEM;
        p = spi_master_get_devdata(master);
-       platform_set_drvdata(pdev, p);
-       p->my_master = master;
+       platform_set_drvdata(pdev, master);
 
        res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
@@ -307,9 +268,8 @@ static int octeon_spi_probe(struct platform_device *pdev)
 
        master->setup = octeon_spi_setup;
        master->cleanup = octeon_spi_cleanup;
-       master->prepare_transfer_hardware = octeon_spi_nop_transfer_hardware;
        master->transfer_one_message = octeon_spi_transfer_one_message;
-       master->unprepare_transfer_hardware = octeon_spi_nop_transfer_hardware;
+       master->bits_per_word_mask = SPI_BPW_MASK(8);
 
        master->dev.of_node = pdev->dev.of_node;
        err = spi_register_master(master);
@@ -328,10 +288,11 @@ fail:
 
 static int octeon_spi_remove(struct platform_device *pdev)
 {
-       struct octeon_spi *p = platform_get_drvdata(pdev);
+       struct spi_master *master = platform_get_drvdata(pdev);
+       struct octeon_spi *p = spi_master_get_devdata(master);
        u64 register_base = p->register_base;
 
-       spi_unregister_master(p->my_master);
+       spi_unregister_master(master);
 
        /* Clear the CSENA* and put everything in a known state. */
        cvmx_write_csr(register_base + OCTEON_SPI_CFG, 0);
index ee25670..69ecf05 100644 (file)
 #define SPI_SHUTDOWN   1
 
 struct omap1_spi100k {
-       struct work_struct      work;
-
-       /* lock protects queue and registers */
-       spinlock_t              lock;
-       struct list_head        msg_queue;
        struct spi_master       *master;
        struct clk              *ick;
        struct clk              *fck;
@@ -104,8 +99,6 @@ struct omap1_spi100k_cs {
        int                     word_len;
 };
 
-static struct workqueue_struct *omap1_spi100k_wq;
-
 #define MOD_REG_BIT(val, mask, set) do { \
        if (set) \
                val |= mask; \
@@ -310,170 +303,102 @@ static int omap1_spi100k_setup(struct spi_device *spi)
 
        spi100k_open(spi->master);
 
-       clk_enable(spi100k->ick);
-       clk_enable(spi100k->fck);
+       clk_prepare_enable(spi100k->ick);
+       clk_prepare_enable(spi100k->fck);
 
        ret = omap1_spi100k_setup_transfer(spi, NULL);
 
-       clk_disable(spi100k->ick);
-       clk_disable(spi100k->fck);
+       clk_disable_unprepare(spi100k->ick);
+       clk_disable_unprepare(spi100k->fck);
 
        return ret;
 }
 
-static void omap1_spi100k_work(struct work_struct *work)
+static int omap1_spi100k_prepare_hardware(struct spi_master *master)
 {
-       struct omap1_spi100k    *spi100k;
-       int status = 0;
+       struct omap1_spi100k *spi100k = spi_master_get_devdata(master);
 
-       spi100k = container_of(work, struct omap1_spi100k, work);
-       spin_lock_irq(&spi100k->lock);
+       clk_prepare_enable(spi100k->ick);
+       clk_prepare_enable(spi100k->fck);
 
-       clk_enable(spi100k->ick);
-       clk_enable(spi100k->fck);
+       return 0;
+}
 
-       /* We only enable one channel at a time -- the one whose message is
-        * at the head of the queue -- although this controller would gladly
-        * arbitrate among multiple channels.  This corresponds to "single
-        * channel" master mode.  As a side effect, we need to manage the
-        * chipselect with the FORCE bit ... CS != channel enable.
-        */
-        while (!list_empty(&spi100k->msg_queue)) {
-               struct spi_message              *m;
-               struct spi_device               *spi;
-               struct spi_transfer             *t = NULL;
-               int                             cs_active = 0;
-               struct omap1_spi100k_cs         *cs;
-               int                             par_override = 0;
-
-               m = container_of(spi100k->msg_queue.next, struct spi_message,
-                                queue);
-
-               list_del_init(&m->queue);
-               spin_unlock_irq(&spi100k->lock);
-
-               spi = m->spi;
-               cs = spi->controller_state;
-
-               list_for_each_entry(t, &m->transfers, transfer_list) {
-                       if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) {
-                               status = -EINVAL;
+static int omap1_spi100k_transfer_one_message(struct spi_master *master,
+                                             struct spi_message *m)
+{
+       struct omap1_spi100k *spi100k = spi_master_get_devdata(master);
+       struct spi_device *spi = m->spi;
+       struct spi_transfer *t = NULL;
+       int cs_active = 0;
+       int par_override = 0;
+       int status = 0;
+
+       list_for_each_entry(t, &m->transfers, transfer_list) {
+               if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) {
+                       status = -EINVAL;
+                       break;
+               }
+               if (par_override || t->speed_hz || t->bits_per_word) {
+                       par_override = 1;
+                       status = omap1_spi100k_setup_transfer(spi, t);
+                       if (status < 0)
                                break;
-                       }
-                       if (par_override || t->speed_hz || t->bits_per_word) {
-                               par_override = 1;
-                               status = omap1_spi100k_setup_transfer(spi, t);
-                               if (status < 0)
-                                       break;
-                               if (!t->speed_hz && !t->bits_per_word)
-                                       par_override = 0;
-                       }
+                       if (!t->speed_hz && !t->bits_per_word)
+                               par_override = 0;
+               }
 
-                       if (!cs_active) {
-                               omap1_spi100k_force_cs(spi100k, 1);
-                               cs_active = 1;
-                       }
+               if (!cs_active) {
+                       omap1_spi100k_force_cs(spi100k, 1);
+                       cs_active = 1;
+               }
 
-                       if (t->len) {
-                               unsigned count;
+               if (t->len) {
+                       unsigned count;
 
-                               count = omap1_spi100k_txrx_pio(spi, t);
-                               m->actual_length += count;
+                       count = omap1_spi100k_txrx_pio(spi, t);
+                       m->actual_length += count;
 
-                               if (count != t->len) {
-                                       status = -EIO;
-                                       break;
-                               }
+                       if (count != t->len) {
+                               status = -EIO;
+                               break;
                        }
+               }
 
-                       if (t->delay_usecs)
-                               udelay(t->delay_usecs);
+               if (t->delay_usecs)
+                       udelay(t->delay_usecs);
 
-                       /* ignore the "leave it on after last xfer" hint */
+               /* ignore the "leave it on after last xfer" hint */
 
-                       if (t->cs_change) {
-                               omap1_spi100k_force_cs(spi100k, 0);
-                               cs_active = 0;
-                       }
-               }
-
-               /* Restore defaults if they were overriden */
-               if (par_override) {
-                       par_override = 0;
-                       status = omap1_spi100k_setup_transfer(spi, NULL);
+               if (t->cs_change) {
+                       omap1_spi100k_force_cs(spi100k, 0);
+                       cs_active = 0;
                }
+       }
 
-               if (cs_active)
-                       omap1_spi100k_force_cs(spi100k, 0);
+       /* Restore defaults if they were overriden */
+       if (par_override) {
+               par_override = 0;
+               status = omap1_spi100k_setup_transfer(spi, NULL);
+       }
 
-               m->status = status;
-               m->complete(m->context);
+       if (cs_active)
+               omap1_spi100k_force_cs(spi100k, 0);
 
-               spin_lock_irq(&spi100k->lock);
-       }
+       m->status = status;
 
-       clk_disable(spi100k->ick);
-       clk_disable(spi100k->fck);
-       spin_unlock_irq(&spi100k->lock);
+       spi_finalize_current_message(master);
 
-       if (status < 0)
-               printk(KERN_WARNING "spi transfer failed with %d\n", status);
+       return status;
 }
 
-static int omap1_spi100k_transfer(struct spi_device *spi, struct spi_message *m)
+static int omap1_spi100k_unprepare_hardware(struct spi_master *master)
 {
-       struct omap1_spi100k    *spi100k;
-       unsigned long           flags;
-       struct spi_transfer     *t;
-
-       m->actual_length = 0;
-       m->status = -EINPROGRESS;
-
-       spi100k = spi_master_get_devdata(spi->master);
-
-       /* Don't accept new work if we're shutting down */
-       if (spi100k->state == SPI_SHUTDOWN)
-               return -ESHUTDOWN;
-
-       /* reject invalid messages and transfers */
-       if (list_empty(&m->transfers) || !m->complete)
-               return -EINVAL;
-
-       list_for_each_entry(t, &m->transfers, transfer_list) {
-               const void      *tx_buf = t->tx_buf;
-               void            *rx_buf = t->rx_buf;
-               unsigned        len = t->len;
-
-               if (t->speed_hz > OMAP1_SPI100K_MAX_FREQ
-                               || (len && !(rx_buf || tx_buf))) {
-                       dev_dbg(&spi->dev, "transfer: %d Hz, %d %s%s, %d bpw\n",
-                                       t->speed_hz,
-                                       len,
-                                       tx_buf ? "tx" : "",
-                                       rx_buf ? "rx" : "",
-                                       t->bits_per_word);
-                       return -EINVAL;
-               }
-
-               if (t->speed_hz && t->speed_hz < OMAP1_SPI100K_MAX_FREQ/(1<<16)) {
-                       dev_dbg(&spi->dev, "%d Hz max exceeds %d\n",
-                                       t->speed_hz,
-                                       OMAP1_SPI100K_MAX_FREQ/(1<<16));
-                       return -EINVAL;
-               }
-
-       }
-
-       spin_lock_irqsave(&spi100k->lock, flags);
-       list_add_tail(&m->queue, &spi100k->msg_queue);
-       queue_work(omap1_spi100k_wq, &spi100k->work);
-       spin_unlock_irqrestore(&spi100k->lock, flags);
+       struct omap1_spi100k *spi100k = spi_master_get_devdata(master);
 
-       return 0;
-}
+       clk_disable_unprepare(spi100k->ick);
+       clk_disable_unprepare(spi100k->fck);
 
-static int omap1_spi100k_reset(struct omap1_spi100k *spi100k)
-{
        return 0;
 }
 
@@ -496,11 +421,15 @@ static int omap1_spi100k_probe(struct platform_device *pdev)
               master->bus_num = pdev->id;
 
        master->setup = omap1_spi100k_setup;
-       master->transfer = omap1_spi100k_transfer;
+       master->transfer_one_message = omap1_spi100k_transfer_one_message;
+       master->prepare_transfer_hardware = omap1_spi100k_prepare_hardware;
+       master->unprepare_transfer_hardware = omap1_spi100k_unprepare_hardware;
        master->cleanup = NULL;
        master->num_chipselect = 2;
        master->mode_bits = MODEBITS;
        master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32);
+       master->min_speed_hz = OMAP1_SPI100K_MAX_FREQ/(1<<16);
+       master->max_speed_hz = OMAP1_SPI100K_MAX_FREQ;
 
        platform_set_drvdata(pdev, master);
 
@@ -512,42 +441,31 @@ static int omap1_spi100k_probe(struct platform_device *pdev)
         * You should allocate this with ioremap() before initializing
         * the SPI.
         */
-       spi100k->base = (void __iomem *) pdev->dev.platform_data;
-
-       INIT_WORK(&spi100k->work, omap1_spi100k_work);
+       spi100k->base = (void __iomem *)dev_get_platdata(&pdev->dev);
 
-       spin_lock_init(&spi100k->lock);
-       INIT_LIST_HEAD(&spi100k->msg_queue);
-       spi100k->ick = clk_get(&pdev->dev, "ick");
+       spi100k->ick = devm_clk_get(&pdev->dev, "ick");
        if (IS_ERR(spi100k->ick)) {
                dev_dbg(&pdev->dev, "can't get spi100k_ick\n");
                status = PTR_ERR(spi100k->ick);
-               goto err1;
+               goto err;
        }
 
-       spi100k->fck = clk_get(&pdev->dev, "fck");
+       spi100k->fck = devm_clk_get(&pdev->dev, "fck");
        if (IS_ERR(spi100k->fck)) {
                dev_dbg(&pdev->dev, "can't get spi100k_fck\n");
                status = PTR_ERR(spi100k->fck);
-               goto err2;
+               goto err;
        }
 
-       if (omap1_spi100k_reset(spi100k) < 0)
-               goto err3;
-
        status = spi_register_master(master);
        if (status < 0)
-               goto err3;
+               goto err;
 
        spi100k->state = SPI_RUNNING;
 
        return status;
 
-err3:
-       clk_put(spi100k->fck);
-err2:
-       clk_put(spi100k->ick);
-err1:
+err:
        spi_master_put(master);
        return status;
 }
@@ -557,33 +475,14 @@ static int omap1_spi100k_remove(struct platform_device *pdev)
        struct spi_master       *master;
        struct omap1_spi100k    *spi100k;
        struct resource         *r;
-       unsigned                limit = 500;
-       unsigned long           flags;
        int                     status = 0;
 
        master = platform_get_drvdata(pdev);
        spi100k = spi_master_get_devdata(master);
 
-       spin_lock_irqsave(&spi100k->lock, flags);
-
-       spi100k->state = SPI_SHUTDOWN;
-       while (!list_empty(&spi100k->msg_queue) && limit--) {
-               spin_unlock_irqrestore(&spi100k->lock, flags);
-               msleep(10);
-               spin_lock_irqsave(&spi100k->lock, flags);
-       }
-
-       if (!list_empty(&spi100k->msg_queue))
-               status = -EBUSY;
-
-       spin_unlock_irqrestore(&spi100k->lock, flags);
-
        if (status != 0)
                return status;
 
-       clk_put(spi100k->fck);
-       clk_put(spi100k->ick);
-
        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
        spi_unregister_master(master);
@@ -596,30 +495,11 @@ static struct platform_driver omap1_spi100k_driver = {
                .name           = "omap1_spi100k",
                .owner          = THIS_MODULE,
        },
+       .probe          = omap1_spi100k_probe,
        .remove         = omap1_spi100k_remove,
 };
 
-
-static int __init omap1_spi100k_init(void)
-{
-       omap1_spi100k_wq = create_singlethread_workqueue(
-                       omap1_spi100k_driver.driver.name);
-
-       if (omap1_spi100k_wq == NULL)
-               return -1;
-
-       return platform_driver_probe(&omap1_spi100k_driver, omap1_spi100k_probe);
-}
-
-static void __exit omap1_spi100k_exit(void)
-{
-       platform_driver_unregister(&omap1_spi100k_driver);
-
-       destroy_workqueue(omap1_spi100k_wq);
-}
-
-module_init(omap1_spi100k_init);
-module_exit(omap1_spi100k_exit);
+module_platform_driver(omap1_spi100k_driver);
 
 MODULE_DESCRIPTION("OMAP7xx SPI 100k controller driver");
 MODULE_AUTHOR("Fabrice Crohas <fcrohas@gmail.com>");
index 5994039..ed4af47 100644 (file)
@@ -335,23 +335,6 @@ static void omap2_mcspi_restore_ctx(struct omap2_mcspi *mcspi)
                __raw_writel(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0);
 }
 
-static int omap2_prepare_transfer(struct spi_master *master)
-{
-       struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
-
-       pm_runtime_get_sync(mcspi->dev);
-       return 0;
-}
-
-static int omap2_unprepare_transfer(struct spi_master *master)
-{
-       struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
-
-       pm_runtime_mark_last_busy(mcspi->dev);
-       pm_runtime_put_autosuspend(mcspi->dev);
-       return 0;
-}
-
 static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit)
 {
        unsigned long timeout;
@@ -1318,8 +1301,7 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
        master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
        master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32);
        master->setup = omap2_mcspi_setup;
-       master->prepare_transfer_hardware = omap2_prepare_transfer;
-       master->unprepare_transfer_hardware = omap2_unprepare_transfer;
+       master->auto_runtime_pm = true;
        master->transfer_one_message = omap2_mcspi_transfer_one_message;
        master->cleanup = omap2_mcspi_cleanup;
        master->dev.of_node = node;
@@ -1340,7 +1322,7 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
                if (of_get_property(node, "ti,pindir-d0-out-d1-in", NULL))
                        mcspi->pin_dir = MCSPI_PINDIR_D0_OUT_D1_IN;
        } else {
-               pdata = pdev->dev.platform_data;
+               pdata = dev_get_platdata(&pdev->dev);
                master->num_chipselect = pdata->num_cs;
                if (pdev->id != -1)
                        master->bus_num = pdev->id;
index 5d90beb..1d1d321 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"
@@ -446,30 +447,22 @@ static int orion_spi_probe(struct platform_device *pdev)
        spi->min_speed = DIV_ROUND_UP(tclk_hz, 30);
 
        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (r == NULL) {
-               status = -ENODEV;
+       spi->base = devm_ioremap_resource(&pdev->dev, r);
+       if (IS_ERR(spi->base)) {
+               status = PTR_ERR(spi->base);
                goto out_rel_clk;
        }
 
-       if (!request_mem_region(r->start, resource_size(r),
-                               dev_name(&pdev->dev))) {
-               status = -EBUSY;
-               goto out_rel_clk;
-       }
-       spi->base = ioremap(r->start, SZ_1K);
-
        if (orion_spi_reset(spi) < 0)
-               goto out_rel_mem;
+               goto out_rel_clk;
 
        master->dev.of_node = pdev->dev.of_node;
        status = spi_register_master(master);
        if (status < 0)
-               goto out_rel_mem;
+               goto out_rel_clk;
 
        return status;
 
-out_rel_mem:
-       release_mem_region(r->start, resource_size(r));
 out_rel_clk:
        clk_disable_unprepare(spi->clk);
        clk_put(spi->clk);
@@ -482,7 +475,6 @@ out:
 static int orion_spi_remove(struct platform_device *pdev)
 {
        struct spi_master *master;
-       struct resource *r;
        struct orion_spi *spi;
 
        master = platform_get_drvdata(pdev);
@@ -491,9 +483,6 @@ static int orion_spi_remove(struct platform_device *pdev)
        clk_disable_unprepare(spi->clk);
        clk_put(spi->clk);
 
-       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       release_mem_region(r->start, resource_size(r));
-
        spi_unregister_master(master);
 
        return 0;
index abef061..9c511a9 100644 (file)
@@ -1555,18 +1555,6 @@ static int pl022_transfer_one_message(struct spi_master *master,
        return 0;
 }
 
-static int pl022_prepare_transfer_hardware(struct spi_master *master)
-{
-       struct pl022 *pl022 = spi_master_get_devdata(master);
-
-       /*
-        * Just make sure we have all we need to run the transfer by syncing
-        * with the runtime PM framework.
-        */
-       pm_runtime_get_sync(&pl022->adev->dev);
-       return 0;
-}
-
 static int pl022_unprepare_transfer_hardware(struct spi_master *master)
 {
        struct pl022 *pl022 = spi_master_get_devdata(master);
@@ -1575,13 +1563,6 @@ static int pl022_unprepare_transfer_hardware(struct spi_master *master)
        writew((readw(SSP_CR1(pl022->virtbase)) &
                (~SSP_CR1_MASK_SSE)), SSP_CR1(pl022->virtbase));
 
-       if (pl022->master_info->autosuspend_delay > 0) {
-               pm_runtime_mark_last_busy(&pl022->adev->dev);
-               pm_runtime_put_autosuspend(&pl022->adev->dev);
-       } else {
-               pm_runtime_put(&pl022->adev->dev);
-       }
-
        return 0;
 }
 
@@ -2091,7 +2072,8 @@ pl022_platform_data_dt_get(struct device *dev)
 static int pl022_probe(struct amba_device *adev, const struct amba_id *id)
 {
        struct device *dev = &adev->dev;
-       struct pl022_ssp_controller *platform_info = adev->dev.platform_data;
+       struct pl022_ssp_controller *platform_info =
+                       dev_get_platdata(&adev->dev);
        struct spi_master *master;
        struct pl022 *pl022 = NULL;     /*Data for this driver */
        struct device_node *np = adev->dev.of_node;
@@ -2139,7 +2121,7 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id)
        master->num_chipselect = num_cs;
        master->cleanup = pl022_cleanup;
        master->setup = pl022_setup;
-       master->prepare_transfer_hardware = pl022_prepare_transfer_hardware;
+       master->auto_runtime_pm = true;
        master->transfer_one_message = pl022_transfer_one_message;
        master->unprepare_transfer_hardware = pl022_unprepare_transfer_hardware;
        master->rt = platform_info->rt;
@@ -2193,8 +2175,8 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id)
                status = -ENOMEM;
                goto err_no_ioremap;
        }
-       printk(KERN_INFO "pl022: mapped registers from 0x%08x to %p\n",
-              adev->res.start, pl022->virtbase);
+       printk(KERN_INFO "pl022: mapped registers from %pa to %p\n",
+              &adev->res.start, pl022->virtbase);
 
        pl022->clk = devm_clk_get(&adev->dev, NULL);
        if (IS_ERR(pl022->clk)) {
index f440dce..2eb06ee 100644 (file)
@@ -69,6 +69,8 @@ MODULE_ALIAS("platform:pxa2xx-spi");
 #define LPSS_TX_HITHRESH_DFLT  224
 
 /* Offset from drv_data->lpss_base */
+#define GENERAL_REG            0x08
+#define GENERAL_REG_RXTO_HOLDOFF_DISABLE BIT(24)
 #define SSP_REG                        0x0c
 #define SPI_CS_CONTROL         0x18
 #define SPI_CS_CONTROL_SW_MODE BIT(0)
@@ -142,8 +144,13 @@ detection_done:
        __lpss_ssp_write_priv(drv_data, SPI_CS_CONTROL, value);
 
        /* Enable multiblock DMA transfers */
-       if (drv_data->master_info->enable_dma)
+       if (drv_data->master_info->enable_dma) {
                __lpss_ssp_write_priv(drv_data, SSP_REG, 1);
+
+               value = __lpss_ssp_read_priv(drv_data, GENERAL_REG);
+               value |= GENERAL_REG_RXTO_HOLDOFF_DISABLE;
+               __lpss_ssp_write_priv(drv_data, GENERAL_REG, value);
+       }
 }
 
 static void lpss_ssp_cs_control(struct driver_data *drv_data, bool enable)
@@ -804,14 +811,6 @@ static int pxa2xx_spi_transfer_one_message(struct spi_master *master,
        return 0;
 }
 
-static int pxa2xx_spi_prepare_transfer(struct spi_master *master)
-{
-       struct driver_data *drv_data = spi_master_get_devdata(master);
-
-       pm_runtime_get_sync(&drv_data->pdev->dev);
-       return 0;
-}
-
 static int pxa2xx_spi_unprepare_transfer(struct spi_master *master)
 {
        struct driver_data *drv_data = spi_master_get_devdata(master);
@@ -820,8 +819,6 @@ static int pxa2xx_spi_unprepare_transfer(struct spi_master *master)
        write_SSCR0(read_SSCR0(drv_data->ioaddr) & ~SSCR0_SSE,
                    drv_data->ioaddr);
 
-       pm_runtime_mark_last_busy(&drv_data->pdev->dev);
-       pm_runtime_put_autosuspend(&drv_data->pdev->dev);
        return 0;
 }
 
@@ -1134,8 +1131,8 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
        master->cleanup = cleanup;
        master->setup = setup;
        master->transfer_one_message = pxa2xx_spi_transfer_one_message;
-       master->prepare_transfer_hardware = pxa2xx_spi_prepare_transfer;
        master->unprepare_transfer_hardware = pxa2xx_spi_unprepare_transfer;
+       master->auto_runtime_pm = true;
 
        drv_data->ssp_type = ssp->type;
        drv_data->null_dma_buf = (u32 *)PTR_ALIGN(&drv_data[1], DMA_ALIGNMENT);
index b44a6ac..8719206 100644 (file)
@@ -564,8 +564,12 @@ static void rspi_work(struct work_struct *work)
        unsigned long flags;
        int ret;
 
-       spin_lock_irqsave(&rspi->lock, flags);
-       while (!list_empty(&rspi->queue)) {
+       while (1) {
+               spin_lock_irqsave(&rspi->lock, flags);
+               if (list_empty(&rspi->queue)) {
+                       spin_unlock_irqrestore(&rspi->lock, flags);
+                       break;
+               }
                mesg = list_entry(rspi->queue.next, struct spi_message, queue);
                list_del_init(&mesg->queue);
                spin_unlock_irqrestore(&rspi->lock, flags);
@@ -595,8 +599,6 @@ static void rspi_work(struct work_struct *work)
 
                mesg->status = 0;
                mesg->complete(mesg->context);
-
-               spin_lock_irqsave(&rspi->lock, flags);
        }
 
        return;
@@ -664,12 +666,13 @@ static irqreturn_t rspi_irq(int irq, void *_sr)
 static int rspi_request_dma(struct rspi_data *rspi,
                                      struct platform_device *pdev)
 {
-       struct rspi_plat_data *rspi_pd = pdev->dev.platform_data;
+       struct rspi_plat_data *rspi_pd = dev_get_platdata(&pdev->dev);
+       struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        dma_cap_mask_t mask;
        struct dma_slave_config cfg;
        int ret;
 
-       if (!rspi_pd)
+       if (!res || !rspi_pd)
                return 0;       /* The driver assumes no error. */
 
        rspi->dma_width_16bit = rspi_pd->dma_width_16bit;
@@ -683,6 +686,8 @@ static int rspi_request_dma(struct rspi_data *rspi,
                if (rspi->chan_rx) {
                        cfg.slave_id = rspi_pd->dma_rx_id;
                        cfg.direction = DMA_DEV_TO_MEM;
+                       cfg.dst_addr = 0;
+                       cfg.src_addr = res->start + RSPI_SPDR;
                        ret = dmaengine_slave_config(rspi->chan_rx, &cfg);
                        if (!ret)
                                dev_info(&pdev->dev, "Use DMA when rx.\n");
@@ -698,6 +703,8 @@ static int rspi_request_dma(struct rspi_data *rspi,
                if (rspi->chan_tx) {
                        cfg.slave_id = rspi_pd->dma_tx_id;
                        cfg.direction = DMA_MEM_TO_DEV;
+                       cfg.dst_addr = res->start + RSPI_SPDR;
+                       cfg.src_addr = 0;
                        ret = dmaengine_slave_config(rspi->chan_tx, &cfg);
                        if (!ret)
                                dev_info(&pdev->dev, "Use DMA when tx\n");
@@ -719,7 +726,7 @@ static void rspi_release_dma(struct rspi_data *rspi)
 
 static int rspi_remove(struct platform_device *pdev)
 {
-       struct rspi_data *rspi = platform_get_drvdata(pdev);
+       struct rspi_data *rspi = spi_master_get(platform_get_drvdata(pdev));
 
        spi_unregister_master(rspi->master);
        rspi_release_dma(rspi);
index 68910b3..ce318d9 100644 (file)
@@ -525,7 +525,7 @@ static int s3c24xx_spi_probe(struct platform_device *pdev)
        memset(hw, 0, sizeof(struct s3c24xx_spi));
 
        hw->master = spi_master_get(master);
-       hw->pdata = pdata = pdev->dev.platform_data;
+       hw->pdata = pdata = dev_get_platdata(&pdev->dev);
        hw->dev = &pdev->dev;
 
        if (pdata == NULL) {
@@ -690,7 +690,7 @@ static int s3c24xx_spi_remove(struct platform_device *dev)
 
 static int s3c24xx_spi_suspend(struct device *dev)
 {
-       struct s3c24xx_spi *hw = platform_get_drvdata(to_platform_device(dev));
+       struct s3c24xx_spi *hw = dev_get_drvdata(dev);
 
        if (hw->pdata && hw->pdata->gpio_setup)
                hw->pdata->gpio_setup(hw->pdata, 0);
@@ -701,7 +701,7 @@ static int s3c24xx_spi_suspend(struct device *dev)
 
 static int s3c24xx_spi_resume(struct device *dev)
 {
-       struct s3c24xx_spi *hw = platform_get_drvdata(to_platform_device(dev));
+       struct s3c24xx_spi *hw = dev_get_drvdata(dev);
 
        s3c24xx_spi_initialsetup(hw);
        return 0;
index 63e2070..512b889 100644 (file)
@@ -172,7 +172,6 @@ struct s3c64xx_spi_port_config {
  * @master: Pointer to the SPI Protocol master.
  * @cntrlr_info: Platform specific data for the controller this driver manages.
  * @tgl_spi: Pointer to the last CS left untoggled by the cs_change hint.
- * @queue: To log SPI xfer requests.
  * @lock: Controller specific lock.
  * @state: Set of FLAGS to indicate status.
  * @rx_dmach: Controller's DMA channel for Rx.
@@ -193,7 +192,6 @@ struct s3c64xx_spi_driver_data {
        struct spi_master               *master;
        struct s3c64xx_spi_info  *cntrlr_info;
        struct spi_device               *tgl_spi;
-       struct list_head                queue;
        spinlock_t                      lock;
        unsigned long                   sfr_start;
        struct completion               xfer_completion;
@@ -338,8 +336,10 @@ static int acquire_dma(struct s3c64xx_spi_driver_data *sdd)
        req.cap = DMA_SLAVE;
        req.client = &s3c64xx_spi_dma_client;
 
-       sdd->rx_dma.ch = (void *)sdd->ops->request(sdd->rx_dma.dmach, &req, dev, "rx");
-       sdd->tx_dma.ch = (void *)sdd->ops->request(sdd->tx_dma.dmach, &req, dev, "tx");
+       sdd->rx_dma.ch = (struct dma_chan *)(unsigned long)sdd->ops->request(
+                                       sdd->rx_dma.dmach, &req, dev, "rx");
+       sdd->tx_dma.ch = (struct dma_chan *)(unsigned long)sdd->ops->request(
+                                       sdd->tx_dma.dmach, &req, dev, "tx");
 
        return 1;
 }
@@ -356,8 +356,6 @@ static int s3c64xx_spi_prepare_transfer(struct spi_master *spi)
        while (!is_polling(sdd) && !acquire_dma(sdd))
                usleep_range(10000, 11000);
 
-       pm_runtime_get_sync(&sdd->pdev->dev);
-
        return 0;
 }
 
@@ -372,7 +370,6 @@ static int s3c64xx_spi_unprepare_transfer(struct spi_master *spi)
                sdd->ops->release((enum dma_ch)sdd->tx_dma.ch,
                                        &s3c64xx_spi_dma_client);
        }
-       pm_runtime_put(&sdd->pdev->dev);
 
        return 0;
 }
@@ -389,9 +386,10 @@ static void prepare_dma(struct s3c64xx_spi_dma_data *dma,
 {
        struct s3c64xx_spi_driver_data *sdd;
        struct dma_slave_config config;
-       struct scatterlist sg;
        struct dma_async_tx_descriptor *desc;
 
+       memset(&config, 0, sizeof(config));
+
        if (dma->direction == DMA_DEV_TO_MEM) {
                sdd = container_of((void *)dma,
                        struct s3c64xx_spi_driver_data, rx_dma);
@@ -410,14 +408,8 @@ static void prepare_dma(struct s3c64xx_spi_dma_data *dma,
                dmaengine_slave_config(dma->ch, &config);
        }
 
-       sg_init_table(&sg, 1);
-       sg_dma_len(&sg) = len;
-       sg_set_page(&sg, pfn_to_page(PFN_DOWN(buf)),
-                   len, offset_in_page(buf));
-       sg_dma_address(&sg) = buf;
-
-       desc = dmaengine_prep_slave_sg(dma->ch,
-               &sg, 1, dma->direction, DMA_PREP_INTERRUPT);
+       desc = dmaengine_prep_slave_single(dma->ch, buf, len,
+                                       dma->direction, DMA_PREP_INTERRUPT);
 
        desc->callback = s3c64xx_spi_dmacb;
        desc->callback_param = dma;
@@ -434,27 +426,26 @@ static int s3c64xx_spi_prepare_transfer(struct spi_master *spi)
        dma_cap_mask_t mask;
        int ret;
 
-       if (is_polling(sdd))
-               return 0;
-
-       dma_cap_zero(mask);
-       dma_cap_set(DMA_SLAVE, mask);
-
-       /* Acquire DMA channels */
-       sdd->rx_dma.ch = dma_request_slave_channel_compat(mask, filter,
-                               (void*)sdd->rx_dma.dmach, dev, "rx");
-       if (!sdd->rx_dma.ch) {
-               dev_err(dev, "Failed to get RX DMA channel\n");
-               ret = -EBUSY;
-               goto out;
-       }
+       if (!is_polling(sdd)) {
+               dma_cap_zero(mask);
+               dma_cap_set(DMA_SLAVE, mask);
+
+               /* Acquire DMA channels */
+               sdd->rx_dma.ch = dma_request_slave_channel_compat(mask, filter,
+                                  (void *)sdd->rx_dma.dmach, dev, "rx");
+               if (!sdd->rx_dma.ch) {
+                       dev_err(dev, "Failed to get RX DMA channel\n");
+                       ret = -EBUSY;
+                       goto out;
+               }
 
-       sdd->tx_dma.ch = dma_request_slave_channel_compat(mask, filter,
-                               (void*)sdd->tx_dma.dmach, dev, "tx");
-       if (!sdd->tx_dma.ch) {
-               dev_err(dev, "Failed to get TX DMA channel\n");
-               ret = -EBUSY;
-               goto out_rx;
+               sdd->tx_dma.ch = dma_request_slave_channel_compat(mask, filter,
+                                  (void *)sdd->tx_dma.dmach, dev, "tx");
+               if (!sdd->tx_dma.ch) {
+                       dev_err(dev, "Failed to get TX DMA channel\n");
+                       ret = -EBUSY;
+                       goto out_rx;
+               }
        }
 
        ret = pm_runtime_get_sync(&sdd->pdev->dev);
@@ -1056,8 +1047,6 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
        struct s3c64xx_spi_csinfo *cs = spi->controller_data;
        struct s3c64xx_spi_driver_data *sdd;
        struct s3c64xx_spi_info *sci;
-       struct spi_message *msg;
-       unsigned long flags;
        int err;
 
        sdd = spi_master_get_devdata(spi->master);
@@ -1071,37 +1060,23 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
                return -ENODEV;
        }
 
-       /* Request gpio only if cs line is asserted by gpio pins */
-       if (sdd->cs_gpio) {
-               err = gpio_request_one(cs->line, GPIOF_OUT_INIT_HIGH,
-                                      dev_name(&spi->dev));
-               if (err) {
-                       dev_err(&spi->dev,
-                               "Failed to get /CS gpio [%d]: %d\n",
-                               cs->line, err);
-                       goto err_gpio_req;
+       if (!spi_get_ctldata(spi)) {
+               /* Request gpio only if cs line is asserted by gpio pins */
+               if (sdd->cs_gpio) {
+                       err = gpio_request_one(cs->line, GPIOF_OUT_INIT_HIGH,
+                                       dev_name(&spi->dev));
+                       if (err) {
+                               dev_err(&spi->dev,
+                                       "Failed to get /CS gpio [%d]: %d\n",
+                                       cs->line, err);
+                               goto err_gpio_req;
+                       }
                }
-       }
 
-       if (!spi_get_ctldata(spi))
                spi_set_ctldata(spi, cs);
-
-       sci = sdd->cntrlr_info;
-
-       spin_lock_irqsave(&sdd->lock, flags);
-
-       list_for_each_entry(msg, &sdd->queue, queue) {
-               /* Is some mssg is already queued for this device */
-               if (msg->spi == spi) {
-                       dev_err(&spi->dev,
-                               "setup: attempt while mssg in queue!\n");
-                       spin_unlock_irqrestore(&sdd->lock, flags);
-                       err = -EBUSY;
-                       goto err_msgq;
-               }
        }
 
-       spin_unlock_irqrestore(&sdd->lock, flags);
+       sci = sdd->cntrlr_info;
 
        pm_runtime_get_sync(&sdd->pdev->dev);
 
@@ -1149,7 +1124,6 @@ setup_exit:
        /* setup() returns with device de-selected */
        disable_cs(sdd, spi);
 
-err_msgq:
        gpio_free(cs->line);
        spi_set_ctldata(spi, NULL);
 
@@ -1275,7 +1249,7 @@ static struct s3c64xx_spi_info *s3c64xx_spi_parse_dt(struct device *dev)
 #else
 static struct s3c64xx_spi_info *s3c64xx_spi_parse_dt(struct device *dev)
 {
-       return dev->platform_data;
+       return dev_get_platdata(dev);
 }
 #endif
 
@@ -1300,7 +1274,7 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
        struct resource *mem_res;
        struct resource *res;
        struct s3c64xx_spi_driver_data *sdd;
-       struct s3c64xx_spi_info *sci = pdev->dev.platform_data;
+       struct s3c64xx_spi_info *sci = dev_get_platdata(&pdev->dev);
        struct spi_master *master;
        int ret, irq;
        char clk_name[16];
@@ -1364,16 +1338,14 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
        if (!sdd->pdev->dev.of_node) {
                res = platform_get_resource(pdev, IORESOURCE_DMA,  0);
                if (!res) {
-                       dev_warn(&pdev->dev, "Unable to get SPI tx dma "
-                                       "resource. Switching to poll mode\n");
+                       dev_warn(&pdev->dev, "Unable to get SPI tx dma resource. Switching to poll mode\n");
                        sdd->port_conf->quirks = S3C64XX_SPI_QUIRK_POLL;
                } else
                        sdd->tx_dma.dmach = res->start;
 
                res = platform_get_resource(pdev, IORESOURCE_DMA,  1);
                if (!res) {
-                       dev_warn(&pdev->dev, "Unable to get SPI rx dma "
-                                       "resource. Switching to poll mode\n");
+                       dev_warn(&pdev->dev, "Unable to get SPI rx dma resource. Switching to poll mode\n");
                        sdd->port_conf->quirks = S3C64XX_SPI_QUIRK_POLL;
                } else
                        sdd->rx_dma.dmach = res->start;
@@ -1395,6 +1367,7 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
                                        SPI_BPW_MASK(8);
        /* the spi->mode bits understood by this driver: */
        master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
+       master->auto_runtime_pm = true;
 
        sdd->regs = devm_ioremap_resource(&pdev->dev, mem_res);
        if (IS_ERR(sdd->regs)) {
@@ -1442,7 +1415,6 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
 
        spin_lock_init(&sdd->lock);
        init_completion(&sdd->xfer_completion);
-       INIT_LIST_HEAD(&sdd->queue);
 
        ret = devm_request_irq(&pdev->dev, irq, s3c64xx_spi_irq, 0,
                                "spi-s3c64xx", sdd);
@@ -1464,8 +1436,8 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
 
        dev_dbg(&pdev->dev, "Samsung SoC SPI Driver loaded for Bus SPI-%d with %d Slaves attached\n",
                                        sdd->port_id, master->num_chipselect);
-       dev_dbg(&pdev->dev, "\tIOmem=[0x%x-0x%x]\tDMA=[Rx-%d, Tx-%d]\n",
-                                       mem_res->end, mem_res->start,
+       dev_dbg(&pdev->dev, "\tIOmem=[%pR]\tDMA=[Rx-%d, Tx-%d]\n",
+                                       mem_res,
                                        sdd->rx_dma.dmach, sdd->tx_dma.dmach);
 
        pm_runtime_enable(&pdev->dev);
index 716edf9..0b68cb5 100644 (file)
@@ -99,21 +99,6 @@ static int hspi_status_check_timeout(struct hspi_priv *hspi, u32 mask, u32 val)
 /*
  *             spi master function
  */
-static int hspi_prepare_transfer(struct spi_master *master)
-{
-       struct hspi_priv *hspi = spi_master_get_devdata(master);
-
-       pm_runtime_get_sync(hspi->dev);
-       return 0;
-}
-
-static int hspi_unprepare_transfer(struct spi_master *master)
-{
-       struct hspi_priv *hspi = spi_master_get_devdata(master);
-
-       pm_runtime_put_sync(hspi->dev);
-       return 0;
-}
 
 #define hspi_hw_cs_enable(hspi)                hspi_hw_cs_ctrl(hspi, 0)
 #define hspi_hw_cs_disable(hspi)       hspi_hw_cs_ctrl(hspi, 1)
@@ -316,9 +301,8 @@ static int hspi_probe(struct platform_device *pdev)
        master->setup           = hspi_setup;
        master->cleanup         = hspi_cleanup;
        master->mode_bits       = SPI_CPOL | SPI_CPHA;
-       master->prepare_transfer_hardware       = hspi_prepare_transfer;
+       master->auto_runtime_pm = true;
        master->transfer_one_message            = hspi_transfer_one_message;
-       master->unprepare_transfer_hardware     = hspi_unprepare_transfer;
        ret = spi_register_master(master);
        if (ret < 0) {
                dev_err(&pdev->dev, "spi_register_master error.\n");
@@ -327,8 +311,6 @@ static int hspi_probe(struct platform_device *pdev)
 
        pm_runtime_enable(&pdev->dev);
 
-       dev_info(&pdev->dev, "probed\n");
-
        return 0;
 
  error1:
index 2bc5a6b..2a95435 100644 (file)
@@ -645,7 +645,7 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
        if (pdev->dev.of_node)
                p->info = sh_msiof_spi_parse_dt(&pdev->dev);
        else
-               p->info = pdev->dev.platform_data;
+               p->info = dev_get_platdata(&pdev->dev);
 
        if (!p->info) {
                dev_err(&pdev->dev, "failed to obtain device info\n");
@@ -745,18 +745,6 @@ static int sh_msiof_spi_remove(struct platform_device *pdev)
        return ret;
 }
 
-static int sh_msiof_spi_runtime_nop(struct device *dev)
-{
-       /* Runtime PM callback shared between ->runtime_suspend()
-        * and ->runtime_resume(). Simply returns success.
-        *
-        * This driver re-initializes all registers after
-        * pm_runtime_get_sync() anyway so there is no need
-        * to save and restore registers here.
-        */
-       return 0;
-}
-
 #ifdef CONFIG_OF
 static const struct of_device_id sh_msiof_match[] = {
        { .compatible = "renesas,sh-msiof", },
@@ -766,18 +754,12 @@ static const struct of_device_id sh_msiof_match[] = {
 MODULE_DEVICE_TABLE(of, sh_msiof_match);
 #endif
 
-static struct dev_pm_ops sh_msiof_spi_dev_pm_ops = {
-       .runtime_suspend = sh_msiof_spi_runtime_nop,
-       .runtime_resume = sh_msiof_spi_runtime_nop,
-};
-
 static struct platform_driver sh_msiof_spi_drv = {
        .probe          = sh_msiof_spi_probe,
        .remove         = sh_msiof_spi_remove,
        .driver         = {
                .name           = "spi_sh_msiof",
                .owner          = THIS_MODULE,
-               .pm             = &sh_msiof_spi_dev_pm_ops,
                .of_match_table = of_match_ptr(sh_msiof_match),
        },
 };
index 097e506..8eefeb6 100644 (file)
@@ -130,7 +130,7 @@ static int sh_sci_spi_probe(struct platform_device *dev)
        sp = spi_master_get_devdata(master);
 
        platform_set_drvdata(dev, sp);
-       sp->info = dev->dev.platform_data;
+       sp->info = dev_get_platdata(&dev->dev);
 
        /* setup spi bitbang adaptor */
        sp->bitbang.master = spi_master_get(master);
index fc20bcf..a1f21b7 100644 (file)
 #include <linux/of_gpio.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/spi_bitbang.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-direction.h>
+#include <linux/dma-mapping.h>
+#include <linux/sirfsoc_dma.h>
 
 #define DRIVER_NAME "sirfsoc_spi"
 
 #define SIRFSOC_SPI_FIFO_HC(x)         (((x) & 0x3F) << 20)
 #define SIRFSOC_SPI_FIFO_THD(x)                (((x) & 0xFF) << 2)
 
+/*
+ * only if the rx/tx buffer and transfer size are 4-bytes aligned, we use dma
+ * due to the limitation of dma controller
+ */
+
+#define ALIGNED(x) (!((u32)x & 0x3))
+#define IS_DMA_VALID(x) (x && ALIGNED(x->tx_buf) && ALIGNED(x->rx_buf) && \
+       ALIGNED(x->len) && (x->len < 2 * PAGE_SIZE))
+
 struct sirfsoc_spi {
        struct spi_bitbang bitbang;
-       struct completion done;
+       struct completion rx_done;
+       struct completion tx_done;
 
        void __iomem *base;
        u32 ctrl_freq;  /* SPI controller clock speed */
@@ -137,8 +151,16 @@ struct sirfsoc_spi {
        void (*tx_word) (struct sirfsoc_spi *);
 
        /* number of words left to be tranmitted/received */
-       unsigned int left_tx_cnt;
-       unsigned int left_rx_cnt;
+       unsigned int left_tx_word;
+       unsigned int left_rx_word;
+
+       /* rx & tx DMA channels */
+       struct dma_chan *rx_chan;
+       struct dma_chan *tx_chan;
+       dma_addr_t src_start;
+       dma_addr_t dst_start;
+       void *dummypage;
+       int word_width; /* in bytes */
 
        int chipselect[0];
 };
@@ -155,7 +177,7 @@ static void spi_sirfsoc_rx_word_u8(struct sirfsoc_spi *sspi)
                sspi->rx = rx;
        }
 
-       sspi->left_rx_cnt--;
+       sspi->left_rx_word--;
 }
 
 static void spi_sirfsoc_tx_word_u8(struct sirfsoc_spi *sspi)
@@ -169,7 +191,7 @@ static void spi_sirfsoc_tx_word_u8(struct sirfsoc_spi *sspi)
        }
 
        writel(data, sspi->base + SIRFSOC_SPI_TXFIFO_DATA);
-       sspi->left_tx_cnt--;
+       sspi->left_tx_word--;
 }
 
 static void spi_sirfsoc_rx_word_u16(struct sirfsoc_spi *sspi)
@@ -184,7 +206,7 @@ static void spi_sirfsoc_rx_word_u16(struct sirfsoc_spi *sspi)
                sspi->rx = rx;
        }
 
-       sspi->left_rx_cnt--;
+       sspi->left_rx_word--;
 }
 
 static void spi_sirfsoc_tx_word_u16(struct sirfsoc_spi *sspi)
@@ -198,7 +220,7 @@ static void spi_sirfsoc_tx_word_u16(struct sirfsoc_spi *sspi)
        }
 
        writel(data, sspi->base + SIRFSOC_SPI_TXFIFO_DATA);
-       sspi->left_tx_cnt--;
+       sspi->left_tx_word--;
 }
 
 static void spi_sirfsoc_rx_word_u32(struct sirfsoc_spi *sspi)
@@ -213,7 +235,7 @@ static void spi_sirfsoc_rx_word_u32(struct sirfsoc_spi *sspi)
                sspi->rx = rx;
        }
 
-       sspi->left_rx_cnt--;
+       sspi->left_rx_word--;
 
 }
 
@@ -228,7 +250,7 @@ static void spi_sirfsoc_tx_word_u32(struct sirfsoc_spi *sspi)
        }
 
        writel(data, sspi->base + SIRFSOC_SPI_TXFIFO_DATA);
-       sspi->left_tx_cnt--;
+       sspi->left_tx_word--;
 }
 
 static irqreturn_t spi_sirfsoc_irq(int irq, void *dev_id)
@@ -241,7 +263,7 @@ static irqreturn_t spi_sirfsoc_irq(int irq, void *dev_id)
        /* Error Conditions */
        if (spi_stat & SIRFSOC_SPI_RX_OFLOW ||
                        spi_stat & SIRFSOC_SPI_TX_UFLOW) {
-               complete(&sspi->done);
+               complete(&sspi->rx_done);
                writel(0x0, sspi->base + SIRFSOC_SPI_INT_EN);
        }
 
@@ -249,50 +271,61 @@ static irqreturn_t spi_sirfsoc_irq(int irq, void *dev_id)
                        | SIRFSOC_SPI_RXFIFO_THD_REACH))
                while (!((readl(sspi->base + SIRFSOC_SPI_RXFIFO_STATUS)
                                & SIRFSOC_SPI_FIFO_EMPTY)) &&
-                               sspi->left_rx_cnt)
+                               sspi->left_rx_word)
                        sspi->rx_word(sspi);
 
        if (spi_stat & (SIRFSOC_SPI_FIFO_EMPTY
                        | SIRFSOC_SPI_TXFIFO_THD_REACH))
                while (!((readl(sspi->base + SIRFSOC_SPI_TXFIFO_STATUS)
                                & SIRFSOC_SPI_FIFO_FULL)) &&
-                               sspi->left_tx_cnt)
+                               sspi->left_tx_word)
                        sspi->tx_word(sspi);
 
        /* Received all words */
-       if ((sspi->left_rx_cnt == 0) && (sspi->left_tx_cnt == 0)) {
-               complete(&sspi->done);
+       if ((sspi->left_rx_word == 0) && (sspi->left_tx_word == 0)) {
+               complete(&sspi->rx_done);
                writel(0x0, sspi->base + SIRFSOC_SPI_INT_EN);
        }
        return IRQ_HANDLED;
 }
 
+static void spi_sirfsoc_dma_fini_callback(void *data)
+{
+       struct completion *dma_complete = data;
+
+       complete(dma_complete);
+}
+
 static int spi_sirfsoc_transfer(struct spi_device *spi, struct spi_transfer *t)
 {
        struct sirfsoc_spi *sspi;
        int timeout = t->len * 10;
        sspi = spi_master_get_devdata(spi->master);
 
-       sspi->tx = t->tx_buf;
-       sspi->rx = t->rx_buf;
-       sspi->left_tx_cnt = sspi->left_rx_cnt = t->len;
-       INIT_COMPLETION(sspi->done);
+       sspi->tx = t->tx_buf ? t->tx_buf : sspi->dummypage;
+       sspi->rx = t->rx_buf ? t->rx_buf : sspi->dummypage;
+       sspi->left_tx_word = sspi->left_rx_word = t->len / sspi->word_width;
+       INIT_COMPLETION(sspi->rx_done);
+       INIT_COMPLETION(sspi->tx_done);
 
        writel(SIRFSOC_SPI_INT_MASK_ALL, sspi->base + SIRFSOC_SPI_INT_STATUS);
 
-       if (t->len == 1) {
+       if (sspi->left_tx_word == 1) {
                writel(readl(sspi->base + SIRFSOC_SPI_CTRL) |
                        SIRFSOC_SPI_ENA_AUTO_CLR,
                        sspi->base + SIRFSOC_SPI_CTRL);
                writel(0, sspi->base + SIRFSOC_SPI_TX_DMA_IO_LEN);
                writel(0, sspi->base + SIRFSOC_SPI_RX_DMA_IO_LEN);
-       } else if ((t->len > 1) && (t->len < SIRFSOC_SPI_DAT_FRM_LEN_MAX)) {
+       } else if ((sspi->left_tx_word > 1) && (sspi->left_tx_word <
+                               SIRFSOC_SPI_DAT_FRM_LEN_MAX)) {
                writel(readl(sspi->base + SIRFSOC_SPI_CTRL) |
                                SIRFSOC_SPI_MUL_DAT_MODE |
                                SIRFSOC_SPI_ENA_AUTO_CLR,
                        sspi->base + SIRFSOC_SPI_CTRL);
-               writel(t->len - 1, sspi->base + SIRFSOC_SPI_TX_DMA_IO_LEN);
-               writel(t->len - 1, sspi->base + SIRFSOC_SPI_RX_DMA_IO_LEN);
+               writel(sspi->left_tx_word - 1,
+                               sspi->base + SIRFSOC_SPI_TX_DMA_IO_LEN);
+               writel(sspi->left_tx_word - 1,
+                               sspi->base + SIRFSOC_SPI_RX_DMA_IO_LEN);
        } else {
                writel(readl(sspi->base + SIRFSOC_SPI_CTRL),
                        sspi->base + SIRFSOC_SPI_CTRL);
@@ -305,17 +338,64 @@ static int spi_sirfsoc_transfer(struct spi_device *spi, struct spi_transfer *t)
        writel(SIRFSOC_SPI_FIFO_START, sspi->base + SIRFSOC_SPI_RXFIFO_OP);
        writel(SIRFSOC_SPI_FIFO_START, sspi->base + SIRFSOC_SPI_TXFIFO_OP);
 
-       /* Send the first word to trigger the whole tx/rx process */
-       sspi->tx_word(sspi);
+       if (IS_DMA_VALID(t)) {
+               struct dma_async_tx_descriptor *rx_desc, *tx_desc;
+
+               sspi->dst_start = dma_map_single(&spi->dev, sspi->rx, t->len, DMA_FROM_DEVICE);
+               rx_desc = dmaengine_prep_slave_single(sspi->rx_chan,
+                       sspi->dst_start, t->len, DMA_DEV_TO_MEM,
+                       DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+               rx_desc->callback = spi_sirfsoc_dma_fini_callback;
+               rx_desc->callback_param = &sspi->rx_done;
+
+               sspi->src_start = dma_map_single(&spi->dev, (void *)sspi->tx, t->len, DMA_TO_DEVICE);
+               tx_desc = dmaengine_prep_slave_single(sspi->tx_chan,
+                       sspi->src_start, t->len, DMA_MEM_TO_DEV,
+                       DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+               tx_desc->callback = spi_sirfsoc_dma_fini_callback;
+               tx_desc->callback_param = &sspi->tx_done;
+
+               dmaengine_submit(tx_desc);
+               dmaengine_submit(rx_desc);
+               dma_async_issue_pending(sspi->tx_chan);
+               dma_async_issue_pending(sspi->rx_chan);
+       } else {
+               /* Send the first word to trigger the whole tx/rx process */
+               sspi->tx_word(sspi);
+
+               writel(SIRFSOC_SPI_RX_OFLOW_INT_EN | SIRFSOC_SPI_TX_UFLOW_INT_EN |
+                       SIRFSOC_SPI_RXFIFO_THD_INT_EN | SIRFSOC_SPI_TXFIFO_THD_INT_EN |
+                       SIRFSOC_SPI_FRM_END_INT_EN | SIRFSOC_SPI_RXFIFO_FULL_INT_EN |
+                       SIRFSOC_SPI_TXFIFO_EMPTY_INT_EN, sspi->base + SIRFSOC_SPI_INT_EN);
+       }
 
-       writel(SIRFSOC_SPI_RX_OFLOW_INT_EN | SIRFSOC_SPI_TX_UFLOW_INT_EN |
-               SIRFSOC_SPI_RXFIFO_THD_INT_EN | SIRFSOC_SPI_TXFIFO_THD_INT_EN |
-               SIRFSOC_SPI_FRM_END_INT_EN | SIRFSOC_SPI_RXFIFO_FULL_INT_EN |
-               SIRFSOC_SPI_TXFIFO_EMPTY_INT_EN, sspi->base + SIRFSOC_SPI_INT_EN);
        writel(SIRFSOC_SPI_RX_EN | SIRFSOC_SPI_TX_EN, sspi->base + SIRFSOC_SPI_TX_RX_EN);
 
-       if (wait_for_completion_timeout(&sspi->done, timeout) == 0)
+       if (!IS_DMA_VALID(t)) { /* for PIO */
+               if (wait_for_completion_timeout(&sspi->rx_done, timeout) == 0)
+                       dev_err(&spi->dev, "transfer timeout\n");
+       } else if (wait_for_completion_timeout(&sspi->rx_done, timeout) == 0) {
                dev_err(&spi->dev, "transfer timeout\n");
+               dmaengine_terminate_all(sspi->rx_chan);
+       } else
+               sspi->left_rx_word = 0;
+
+       /*
+        * we only wait tx-done event if transferring by DMA. for PIO,
+        * we get rx data by writing tx data, so if rx is done, tx has
+        * done earlier
+        */
+       if (IS_DMA_VALID(t)) {
+               if (wait_for_completion_timeout(&sspi->tx_done, timeout) == 0) {
+                       dev_err(&spi->dev, "transfer timeout\n");
+                       dmaengine_terminate_all(sspi->tx_chan);
+               }
+       }
+
+       if (IS_DMA_VALID(t)) {
+               dma_unmap_single(&spi->dev, sspi->src_start, t->len, DMA_TO_DEVICE);
+               dma_unmap_single(&spi->dev, sspi->dst_start, t->len, DMA_FROM_DEVICE);
+       }
 
        /* TX, RX FIFO stop */
        writel(0, sspi->base + SIRFSOC_SPI_RXFIFO_OP);
@@ -323,7 +403,7 @@ static int spi_sirfsoc_transfer(struct spi_device *spi, struct spi_transfer *t)
        writel(0, sspi->base + SIRFSOC_SPI_TX_RX_EN);
        writel(0, sspi->base + SIRFSOC_SPI_INT_EN);
 
-       return t->len - sspi->left_rx_cnt;
+       return t->len - sspi->left_rx_word * sspi->word_width;
 }
 
 static void spi_sirfsoc_chipselect(struct spi_device *spi, int value)
@@ -332,7 +412,6 @@ static void spi_sirfsoc_chipselect(struct spi_device *spi, int value)
 
        if (sspi->chipselect[spi->chip_select] == 0) {
                u32 regval = readl(sspi->base + SIRFSOC_SPI_CTRL);
-               regval |= SIRFSOC_SPI_CS_IO_OUT;
                switch (value) {
                case BITBANG_CS_ACTIVE:
                        if (spi->mode & SPI_CS_HIGH)
@@ -369,11 +448,7 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
        bits_per_word = (t) ? t->bits_per_word : spi->bits_per_word;
        hz = t && t->speed_hz ? t->speed_hz : spi->max_speed_hz;
 
-       /* Enable IO mode for RX, TX */
-       writel(SIRFSOC_SPI_IO_MODE_SEL, sspi->base + SIRFSOC_SPI_TX_DMA_IO_CTRL);
-       writel(SIRFSOC_SPI_IO_MODE_SEL, sspi->base + SIRFSOC_SPI_RX_DMA_IO_CTRL);
        regval = (sspi->ctrl_freq / (2 * hz)) - 1;
-
        if (regval > 0xFFFF || regval < 0) {
                dev_err(&spi->dev, "Speed %d not supported\n", hz);
                return -EINVAL;
@@ -388,6 +463,7 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
                                        SIRFSOC_SPI_FIFO_WIDTH_BYTE;
                rxfifo_ctrl = SIRFSOC_SPI_FIFO_THD(SIRFSOC_SPI_FIFO_SIZE / 2) |
                                        SIRFSOC_SPI_FIFO_WIDTH_BYTE;
+               sspi->word_width = 1;
                break;
        case 12:
        case 16:
@@ -399,6 +475,7 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
                                        SIRFSOC_SPI_FIFO_WIDTH_WORD;
                rxfifo_ctrl = SIRFSOC_SPI_FIFO_THD(SIRFSOC_SPI_FIFO_SIZE / 2) |
                                        SIRFSOC_SPI_FIFO_WIDTH_WORD;
+               sspi->word_width = 2;
                break;
        case 32:
                regval |= SIRFSOC_SPI_TRAN_DAT_FORMAT_32;
@@ -408,6 +485,7 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
                                        SIRFSOC_SPI_FIFO_WIDTH_DWORD;
                rxfifo_ctrl = SIRFSOC_SPI_FIFO_THD(SIRFSOC_SPI_FIFO_SIZE / 2) |
                                        SIRFSOC_SPI_FIFO_WIDTH_DWORD;
+               sspi->word_width = 4;
                break;
        default:
                BUG();
@@ -442,6 +520,17 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
        writel(rxfifo_ctrl, sspi->base + SIRFSOC_SPI_RXFIFO_CTRL);
 
        writel(regval, sspi->base + SIRFSOC_SPI_CTRL);
+
+       if (IS_DMA_VALID(t)) {
+               /* Enable DMA mode for RX, TX */
+               writel(0, sspi->base + SIRFSOC_SPI_TX_DMA_IO_CTRL);
+               writel(SIRFSOC_SPI_RX_DMA_FLUSH, sspi->base + SIRFSOC_SPI_RX_DMA_IO_CTRL);
+       } else {
+               /* Enable IO mode for RX, TX */
+               writel(SIRFSOC_SPI_IO_MODE_SEL, sspi->base + SIRFSOC_SPI_TX_DMA_IO_CTRL);
+               writel(SIRFSOC_SPI_IO_MODE_SEL, sspi->base + SIRFSOC_SPI_RX_DMA_IO_CTRL);
+       }
+
        return 0;
 }
 
@@ -466,6 +555,8 @@ static int spi_sirfsoc_probe(struct platform_device *pdev)
        struct spi_master *master;
        struct resource *mem_res;
        int num_cs, cs_gpio, irq;
+       u32 rx_dma_ch, tx_dma_ch;
+       dma_cap_mask_t dma_cap_mask;
        int i;
        int ret;
 
@@ -476,6 +567,20 @@ static int spi_sirfsoc_probe(struct platform_device *pdev)
                goto err_cs;
        }
 
+       ret = of_property_read_u32(pdev->dev.of_node,
+                       "sirf,spi-dma-rx-channel", &rx_dma_ch);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Unable to get rx dma channel\n");
+               goto err_cs;
+       }
+
+       ret = of_property_read_u32(pdev->dev.of_node,
+                       "sirf,spi-dma-tx-channel", &tx_dma_ch);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Unable to get tx dma channel\n");
+               goto err_cs;
+       }
+
        master = spi_alloc_master(&pdev->dev, sizeof(*sspi) + sizeof(int) * num_cs);
        if (!master) {
                dev_err(&pdev->dev, "Unable to allocate SPI master\n");
@@ -484,12 +589,6 @@ static int spi_sirfsoc_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, master);
        sspi = spi_master_get_devdata(master);
 
-       mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!mem_res) {
-               dev_err(&pdev->dev, "Unable to get IO resource\n");
-               ret = -ENODEV;
-               goto free_master;
-       }
        master->num_chipselect = num_cs;
 
        for (i = 0; i < master->num_chipselect; i++) {
@@ -516,6 +615,7 @@ static int spi_sirfsoc_probe(struct platform_device *pdev)
                }
        }
 
+       mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        sspi->base = devm_ioremap_resource(&pdev->dev, mem_res);
        if (IS_ERR(sspi->base)) {
                ret = PTR_ERR(sspi->base);
@@ -538,19 +638,40 @@ static int spi_sirfsoc_probe(struct platform_device *pdev)
        sspi->bitbang.txrx_bufs = spi_sirfsoc_transfer;
        sspi->bitbang.master->setup = spi_sirfsoc_setup;
        master->bus_num = pdev->id;
+       master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST | SPI_CS_HIGH;
        master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(12) |
                                        SPI_BPW_MASK(16) | SPI_BPW_MASK(32);
        sspi->bitbang.master->dev.of_node = pdev->dev.of_node;
 
+       /* request DMA channels */
+       dma_cap_zero(dma_cap_mask);
+       dma_cap_set(DMA_INTERLEAVE, dma_cap_mask);
+
+       sspi->rx_chan = dma_request_channel(dma_cap_mask, (dma_filter_fn)sirfsoc_dma_filter_id,
+               (void *)rx_dma_ch);
+       if (!sspi->rx_chan) {
+               dev_err(&pdev->dev, "can not allocate rx dma channel\n");
+               ret = -ENODEV;
+               goto free_master;
+       }
+       sspi->tx_chan = dma_request_channel(dma_cap_mask, (dma_filter_fn)sirfsoc_dma_filter_id,
+               (void *)tx_dma_ch);
+       if (!sspi->tx_chan) {
+               dev_err(&pdev->dev, "can not allocate tx dma channel\n");
+               ret = -ENODEV;
+               goto free_rx_dma;
+       }
+
        sspi->clk = clk_get(&pdev->dev, NULL);
        if (IS_ERR(sspi->clk)) {
-               ret = -EINVAL;
-               goto free_master;
+               ret = PTR_ERR(sspi->clk);
+               goto free_tx_dma;
        }
        clk_prepare_enable(sspi->clk);
        sspi->ctrl_freq = clk_get_rate(sspi->clk);
 
-       init_completion(&sspi->done);
+       init_completion(&sspi->rx_done);
+       init_completion(&sspi->tx_done);
 
        writel(SIRFSOC_SPI_FIFO_RESET, sspi->base + SIRFSOC_SPI_RXFIFO_OP);
        writel(SIRFSOC_SPI_FIFO_RESET, sspi->base + SIRFSOC_SPI_TXFIFO_OP);
@@ -559,17 +680,28 @@ static int spi_sirfsoc_probe(struct platform_device *pdev)
        /* We are not using dummy delay between command and data */
        writel(0, sspi->base + SIRFSOC_SPI_DUMMY_DELAY_CTL);
 
+       sspi->dummypage = kmalloc(2 * PAGE_SIZE, GFP_KERNEL);
+       if (!sspi->dummypage) {
+               ret = -ENOMEM;
+               goto free_clk;
+       }
+
        ret = spi_bitbang_start(&sspi->bitbang);
        if (ret)
-               goto free_clk;
+               goto free_dummypage;
 
        dev_info(&pdev->dev, "registerred, bus number = %d\n", master->bus_num);
 
        return 0;
-
+free_dummypage:
+       kfree(sspi->dummypage);
 free_clk:
        clk_disable_unprepare(sspi->clk);
        clk_put(sspi->clk);
+free_tx_dma:
+       dma_release_channel(sspi->tx_chan);
+free_rx_dma:
+       dma_release_channel(sspi->rx_chan);
 free_master:
        spi_master_put(master);
 err_cs:
@@ -590,8 +722,11 @@ static int  spi_sirfsoc_remove(struct platform_device *pdev)
                if (sspi->chipselect[i] > 0)
                        gpio_free(sspi->chipselect[i]);
        }
+       kfree(sspi->dummypage);
        clk_disable_unprepare(sspi->clk);
        clk_put(sspi->clk);
+       dma_release_channel(sspi->rx_chan);
+       dma_release_channel(sspi->tx_chan);
        spi_master_put(master);
        return 0;
 }
@@ -599,8 +734,7 @@ static int  spi_sirfsoc_remove(struct platform_device *pdev)
 #ifdef CONFIG_PM
 static int spi_sirfsoc_suspend(struct device *dev)
 {
-       struct platform_device *pdev = to_platform_device(dev);
-       struct spi_master *master = platform_get_drvdata(pdev);
+       struct spi_master *master = dev_get_drvdata(dev);
        struct sirfsoc_spi *sspi = spi_master_get_devdata(master);
 
        clk_disable(sspi->clk);
@@ -609,8 +743,7 @@ static int spi_sirfsoc_suspend(struct device *dev)
 
 static int spi_sirfsoc_resume(struct device *dev)
 {
-       struct platform_device *pdev = to_platform_device(dev);
-       struct spi_master *master = platform_get_drvdata(pdev);
+       struct spi_master *master = dev_get_drvdata(dev);
        struct sirfsoc_spi *sspi = spi_master_get_devdata(master);
 
        clk_enable(sspi->clk);
index e8f542a..145dd43 100644 (file)
@@ -816,14 +816,6 @@ static int tegra_spi_transfer_one_message(struct spi_master *master,
        msg->status = 0;
        msg->actual_length = 0;
 
-       ret = pm_runtime_get_sync(tspi->dev);
-       if (ret < 0) {
-               dev_err(tspi->dev, "runtime PM get failed: %d\n", ret);
-               msg->status = ret;
-               spi_finalize_current_message(master);
-               return ret;
-       }
-
        single_xfer = list_is_singular(&msg->transfers);
        list_for_each_entry(xfer, &msg->transfers, transfer_list) {
                INIT_COMPLETION(tspi->xfer_completion);
@@ -859,7 +851,6 @@ static int tegra_spi_transfer_one_message(struct spi_master *master,
        ret = 0;
 exit:
        tegra_spi_writel(tspi, tspi->def_command1_reg, SPI_COMMAND1);
-       pm_runtime_put(tspi->dev);
        msg->status = ret;
        spi_finalize_current_message(master);
        return ret;
@@ -1053,24 +1044,19 @@ static int tegra_spi_probe(struct platform_device *pdev)
        master->transfer_one_message = tegra_spi_transfer_one_message;
        master->num_chipselect = MAX_CHIP_SELECT;
        master->bus_num = -1;
+       master->auto_runtime_pm = true;
 
        tspi->master = master;
        tspi->dev = &pdev->dev;
        spin_lock_init(&tspi->lock);
 
        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!r) {
-               dev_err(&pdev->dev, "No IO memory resource\n");
-               ret = -ENODEV;
-               goto exit_free_master;
-       }
-       tspi->phys = r->start;
        tspi->base = devm_ioremap_resource(&pdev->dev, r);
        if (IS_ERR(tspi->base)) {
                ret = PTR_ERR(tspi->base);
-               dev_err(&pdev->dev, "ioremap failed: err = %d\n", ret);
                goto exit_free_master;
        }
+       tspi->phys = r->start;
 
        spi_irq = platform_get_irq(pdev, 0);
        tspi->irq = spi_irq;
index c1d5d95..1d814dc 100644 (file)
@@ -335,12 +335,6 @@ static int tegra_sflash_transfer_one_message(struct spi_master *master,
        struct spi_device *spi = msg->spi;
        int ret;
 
-       ret = pm_runtime_get_sync(tsd->dev);
-       if (ret < 0) {
-               dev_err(tsd->dev, "pm_runtime_get() failed, err = %d\n", ret);
-               return ret;
-       }
-
        msg->status = 0;
        msg->actual_length = 0;
        single_xfer = list_is_singular(&msg->transfers);
@@ -380,7 +374,6 @@ exit:
        tegra_sflash_writel(tsd, tsd->def_command_reg, SPI_COMMAND);
        msg->status = ret;
        spi_finalize_current_message(master);
-       pm_runtime_put(tsd->dev);
        return ret;
 }
 
@@ -477,6 +470,7 @@ static int tegra_sflash_probe(struct platform_device *pdev)
        master->mode_bits = SPI_CPOL | SPI_CPHA;
        master->setup = tegra_sflash_setup;
        master->transfer_one_message = tegra_sflash_transfer_one_message;
+       master->auto_runtime_pm = true;
        master->num_chipselect = MAX_CHIP_SELECT;
        master->bus_num = -1;
 
index 80490cc..c703536 100644 (file)
@@ -836,11 +836,6 @@ static int tegra_slink_transfer_one_message(struct spi_master *master,
 
        msg->status = 0;
        msg->actual_length = 0;
-       ret = pm_runtime_get_sync(tspi->dev);
-       if (ret < 0) {
-               dev_err(tspi->dev, "runtime get failed: %d\n", ret);
-               goto done;
-       }
 
        single_xfer = list_is_singular(&msg->transfers);
        list_for_each_entry(xfer, &msg->transfers, transfer_list) {
@@ -878,8 +873,6 @@ static int tegra_slink_transfer_one_message(struct spi_master *master,
 exit:
        tegra_slink_writel(tspi, tspi->def_command_reg, SLINK_COMMAND);
        tegra_slink_writel(tspi, tspi->def_command2_reg, SLINK_COMMAND2);
-       pm_runtime_put(tspi->dev);
-done:
        msg->status = ret;
        spi_finalize_current_message(master);
        return ret;
@@ -1086,6 +1079,7 @@ static int tegra_slink_probe(struct platform_device *pdev)
        master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
        master->setup = tegra_slink_setup;
        master->transfer_one_message = tegra_slink_transfer_one_message;
+       master->auto_runtime_pm = true;
        master->num_chipselect = MAX_CHIP_SELECT;
        master->bus_num = -1;
 
diff --git a/drivers/spi/spi-ti-qspi.c b/drivers/spi/spi-ti-qspi.c
new file mode 100644 (file)
index 0000000..e12d962
--- /dev/null
@@ -0,0 +1,574 @@
+/*
+ * TI QSPI driver
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
+ * Author: Sourav Poddar <sourav.poddar@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GPLv2.
+ *
+ * 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/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
+#include <linux/omap-dma.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/pm_runtime.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/consumer.h>
+
+#include <linux/spi/spi.h>
+
+struct ti_qspi_regs {
+       u32 clkctrl;
+};
+
+struct ti_qspi {
+       struct completion       transfer_complete;
+
+       /* IRQ synchronization */
+       spinlock_t              lock;
+
+       /* list synchronization */
+       struct mutex            list_lock;
+
+       struct spi_master       *master;
+       void __iomem            *base;
+       struct clk              *fclk;
+       struct device           *dev;
+
+       struct ti_qspi_regs     ctx_reg;
+
+       u32 spi_max_frequency;
+       u32 cmd;
+       u32 dc;
+       u32 stat;
+};
+
+#define QSPI_PID                       (0x0)
+#define QSPI_SYSCONFIG                 (0x10)
+#define QSPI_INTR_STATUS_RAW_SET       (0x20)
+#define QSPI_INTR_STATUS_ENABLED_CLEAR (0x24)
+#define QSPI_INTR_ENABLE_SET_REG       (0x28)
+#define QSPI_INTR_ENABLE_CLEAR_REG     (0x2c)
+#define QSPI_SPI_CLOCK_CNTRL_REG       (0x40)
+#define QSPI_SPI_DC_REG                        (0x44)
+#define QSPI_SPI_CMD_REG               (0x48)
+#define QSPI_SPI_STATUS_REG            (0x4c)
+#define QSPI_SPI_DATA_REG              (0x50)
+#define QSPI_SPI_SETUP0_REG            (0x54)
+#define QSPI_SPI_SWITCH_REG            (0x64)
+#define QSPI_SPI_SETUP1_REG            (0x58)
+#define QSPI_SPI_SETUP2_REG            (0x5c)
+#define QSPI_SPI_SETUP3_REG            (0x60)
+#define QSPI_SPI_DATA_REG_1            (0x68)
+#define QSPI_SPI_DATA_REG_2            (0x6c)
+#define QSPI_SPI_DATA_REG_3            (0x70)
+
+#define QSPI_COMPLETION_TIMEOUT                msecs_to_jiffies(2000)
+
+#define QSPI_FCLK                      192000000
+
+/* Clock Control */
+#define QSPI_CLK_EN                    (1 << 31)
+#define QSPI_CLK_DIV_MAX               0xffff
+
+/* Command */
+#define QSPI_EN_CS(n)                  (n << 28)
+#define QSPI_WLEN(n)                   ((n - 1) << 19)
+#define QSPI_3_PIN                     (1 << 18)
+#define QSPI_RD_SNGL                   (1 << 16)
+#define QSPI_WR_SNGL                   (2 << 16)
+#define QSPI_RD_DUAL                   (3 << 16)
+#define QSPI_RD_QUAD                   (7 << 16)
+#define QSPI_INVAL                     (4 << 16)
+#define QSPI_WC_CMD_INT_EN                     (1 << 14)
+#define QSPI_FLEN(n)                   ((n - 1) << 0)
+
+/* STATUS REGISTER */
+#define WC                             0x02
+
+/* INTERRUPT REGISTER */
+#define QSPI_WC_INT_EN                         (1 << 1)
+#define QSPI_WC_INT_DISABLE                    (1 << 1)
+
+/* Device Control */
+#define QSPI_DD(m, n)                  (m << (3 + n * 8))
+#define QSPI_CKPHA(n)                  (1 << (2 + n * 8))
+#define QSPI_CSPOL(n)                  (1 << (1 + n * 8))
+#define QSPI_CKPOL(n)                  (1 << (n * 8))
+
+#define        QSPI_FRAME                      4096
+
+#define QSPI_AUTOSUSPEND_TIMEOUT         2000
+
+static inline unsigned long ti_qspi_read(struct ti_qspi *qspi,
+               unsigned long reg)
+{
+       return readl(qspi->base + reg);
+}
+
+static inline void ti_qspi_write(struct ti_qspi *qspi,
+               unsigned long val, unsigned long reg)
+{
+       writel(val, qspi->base + reg);
+}
+
+static int ti_qspi_setup(struct spi_device *spi)
+{
+       struct ti_qspi  *qspi = spi_master_get_devdata(spi->master);
+       struct ti_qspi_regs *ctx_reg = &qspi->ctx_reg;
+       int clk_div = 0, ret;
+       u32 clk_ctrl_reg, clk_rate, clk_mask;
+
+       if (spi->master->busy) {
+               dev_dbg(qspi->dev, "master busy doing other trasnfers\n");
+               return -EBUSY;
+       }
+
+       if (!qspi->spi_max_frequency) {
+               dev_err(qspi->dev, "spi max frequency not defined\n");
+               return -EINVAL;
+       }
+
+       clk_rate = clk_get_rate(qspi->fclk);
+
+       clk_div = DIV_ROUND_UP(clk_rate, qspi->spi_max_frequency) - 1;
+
+       if (clk_div < 0) {
+               dev_dbg(qspi->dev, "clock divider < 0, using /1 divider\n");
+               return -EINVAL;
+       }
+
+       if (clk_div > QSPI_CLK_DIV_MAX) {
+               dev_dbg(qspi->dev, "clock divider >%d , using /%d divider\n",
+                               QSPI_CLK_DIV_MAX, QSPI_CLK_DIV_MAX + 1);
+               return -EINVAL;
+       }
+
+       dev_dbg(qspi->dev, "hz: %d, clock divider %d\n",
+                       qspi->spi_max_frequency, clk_div);
+
+       ret = pm_runtime_get_sync(qspi->dev);
+       if (ret) {
+               dev_err(qspi->dev, "pm_runtime_get_sync() failed\n");
+               return ret;
+       }
+
+       clk_ctrl_reg = ti_qspi_read(qspi, QSPI_SPI_CLOCK_CNTRL_REG);
+
+       clk_ctrl_reg &= ~QSPI_CLK_EN;
+
+       /* disable SCLK */
+       ti_qspi_write(qspi, clk_ctrl_reg, QSPI_SPI_CLOCK_CNTRL_REG);
+
+       /* enable SCLK */
+       clk_mask = QSPI_CLK_EN | clk_div;
+       ti_qspi_write(qspi, clk_mask, QSPI_SPI_CLOCK_CNTRL_REG);
+       ctx_reg->clkctrl = clk_mask;
+
+       pm_runtime_mark_last_busy(qspi->dev);
+       ret = pm_runtime_put_autosuspend(qspi->dev);
+       if (ret < 0) {
+               dev_err(qspi->dev, "pm_runtime_put_autosuspend() failed\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+static void ti_qspi_restore_ctx(struct ti_qspi *qspi)
+{
+       struct ti_qspi_regs *ctx_reg = &qspi->ctx_reg;
+
+       ti_qspi_write(qspi, ctx_reg->clkctrl, QSPI_SPI_CLOCK_CNTRL_REG);
+}
+
+static int qspi_write_msg(struct ti_qspi *qspi, struct spi_transfer *t)
+{
+       int wlen, count, ret;
+       unsigned int cmd;
+       const u8 *txbuf;
+
+       txbuf = t->tx_buf;
+       cmd = qspi->cmd | QSPI_WR_SNGL;
+       count = t->len;
+       wlen = t->bits_per_word;
+
+       while (count) {
+               switch (wlen) {
+               case 8:
+                       dev_dbg(qspi->dev, "tx cmd %08x dc %08x data %02x\n",
+                                       cmd, qspi->dc, *txbuf);
+                       writeb(*txbuf, qspi->base + QSPI_SPI_DATA_REG);
+                       ti_qspi_write(qspi, cmd, QSPI_SPI_CMD_REG);
+                       ret = wait_for_completion_timeout(&qspi->transfer_complete,
+                                       QSPI_COMPLETION_TIMEOUT);
+                       if (ret == 0) {
+                               dev_err(qspi->dev, "write timed out\n");
+                               return -ETIMEDOUT;
+                       }
+                       txbuf += 1;
+                       count -= 1;
+                       break;
+               case 16:
+                       dev_dbg(qspi->dev, "tx cmd %08x dc %08x data %04x\n",
+                                       cmd, qspi->dc, *txbuf);
+                       writew(*((u16 *)txbuf), qspi->base + QSPI_SPI_DATA_REG);
+                       ti_qspi_write(qspi, cmd, QSPI_SPI_CMD_REG);
+                       ret = wait_for_completion_timeout(&qspi->transfer_complete,
+                               QSPI_COMPLETION_TIMEOUT);
+                       if (ret == 0) {
+                               dev_err(qspi->dev, "write timed out\n");
+                               return -ETIMEDOUT;
+                       }
+                       txbuf += 2;
+                       count -= 2;
+                       break;
+               case 32:
+                       dev_dbg(qspi->dev, "tx cmd %08x dc %08x data %08x\n",
+                                       cmd, qspi->dc, *txbuf);
+                       writel(*((u32 *)txbuf), qspi->base + QSPI_SPI_DATA_REG);
+                       ti_qspi_write(qspi, cmd, QSPI_SPI_CMD_REG);
+                       ret = wait_for_completion_timeout(&qspi->transfer_complete,
+                               QSPI_COMPLETION_TIMEOUT);
+                       if (ret == 0) {
+                               dev_err(qspi->dev, "write timed out\n");
+                               return -ETIMEDOUT;
+                       }
+                       txbuf += 4;
+                       count -= 4;
+                       break;
+               }
+       }
+
+       return 0;
+}
+
+static int qspi_read_msg(struct ti_qspi *qspi, struct spi_transfer *t)
+{
+       int wlen, count, ret;
+       unsigned int cmd;
+       u8 *rxbuf;
+
+       rxbuf = t->rx_buf;
+       cmd = qspi->cmd;
+       switch (t->rx_nbits) {
+       case SPI_NBITS_DUAL:
+               cmd |= QSPI_RD_DUAL;
+               break;
+       case SPI_NBITS_QUAD:
+               cmd |= QSPI_RD_QUAD;
+               break;
+       default:
+               cmd |= QSPI_RD_SNGL;
+               break;
+       }
+       count = t->len;
+       wlen = t->bits_per_word;
+
+       while (count) {
+               dev_dbg(qspi->dev, "rx cmd %08x dc %08x\n", cmd, qspi->dc);
+               ti_qspi_write(qspi, cmd, QSPI_SPI_CMD_REG);
+               ret = wait_for_completion_timeout(&qspi->transfer_complete,
+                               QSPI_COMPLETION_TIMEOUT);
+               if (ret == 0) {
+                       dev_err(qspi->dev, "read timed out\n");
+                       return -ETIMEDOUT;
+               }
+               switch (wlen) {
+               case 8:
+                       *rxbuf = readb(qspi->base + QSPI_SPI_DATA_REG);
+                       rxbuf += 1;
+                       count -= 1;
+                       break;
+               case 16:
+                       *((u16 *)rxbuf) = readw(qspi->base + QSPI_SPI_DATA_REG);
+                       rxbuf += 2;
+                       count -= 2;
+                       break;
+               case 32:
+                       *((u32 *)rxbuf) = readl(qspi->base + QSPI_SPI_DATA_REG);
+                       rxbuf += 4;
+                       count -= 4;
+                       break;
+               }
+       }
+
+       return 0;
+}
+
+static int qspi_transfer_msg(struct ti_qspi *qspi, struct spi_transfer *t)
+{
+       int ret;
+
+       if (t->tx_buf) {
+               ret = qspi_write_msg(qspi, t);
+               if (ret) {
+                       dev_dbg(qspi->dev, "Error while writing\n");
+                       return ret;
+               }
+       }
+
+       if (t->rx_buf) {
+               ret = qspi_read_msg(qspi, t);
+               if (ret) {
+                       dev_dbg(qspi->dev, "Error while reading\n");
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
+static int ti_qspi_start_transfer_one(struct spi_master *master,
+               struct spi_message *m)
+{
+       struct ti_qspi *qspi = spi_master_get_devdata(master);
+       struct spi_device *spi = m->spi;
+       struct spi_transfer *t;
+       int status = 0, ret;
+       int frame_length;
+
+       /* setup device control reg */
+       qspi->dc = 0;
+
+       if (spi->mode & SPI_CPHA)
+               qspi->dc |= QSPI_CKPHA(spi->chip_select);
+       if (spi->mode & SPI_CPOL)
+               qspi->dc |= QSPI_CKPOL(spi->chip_select);
+       if (spi->mode & SPI_CS_HIGH)
+               qspi->dc |= QSPI_CSPOL(spi->chip_select);
+
+       frame_length = (m->frame_length << 3) / spi->bits_per_word;
+
+       frame_length = clamp(frame_length, 0, QSPI_FRAME);
+
+       /* setup command reg */
+       qspi->cmd = 0;
+       qspi->cmd |= QSPI_EN_CS(spi->chip_select);
+       qspi->cmd |= QSPI_FLEN(frame_length);
+       qspi->cmd |= QSPI_WC_CMD_INT_EN;
+
+       ti_qspi_write(qspi, QSPI_WC_INT_EN, QSPI_INTR_ENABLE_SET_REG);
+       ti_qspi_write(qspi, qspi->dc, QSPI_SPI_DC_REG);
+
+       mutex_lock(&qspi->list_lock);
+
+       list_for_each_entry(t, &m->transfers, transfer_list) {
+               qspi->cmd |= QSPI_WLEN(t->bits_per_word);
+
+               ret = qspi_transfer_msg(qspi, t);
+               if (ret) {
+                       dev_dbg(qspi->dev, "transfer message failed\n");
+                       mutex_unlock(&qspi->list_lock);
+                       return -EINVAL;
+               }
+
+               m->actual_length += t->len;
+       }
+
+       mutex_unlock(&qspi->list_lock);
+
+       m->status = status;
+       spi_finalize_current_message(master);
+
+       ti_qspi_write(qspi, qspi->cmd | QSPI_INVAL, QSPI_SPI_CMD_REG);
+
+       return status;
+}
+
+static irqreturn_t ti_qspi_isr(int irq, void *dev_id)
+{
+       struct ti_qspi *qspi = dev_id;
+       u16 int_stat;
+
+       irqreturn_t ret = IRQ_HANDLED;
+
+       spin_lock(&qspi->lock);
+
+       int_stat = ti_qspi_read(qspi, QSPI_INTR_STATUS_ENABLED_CLEAR);
+       qspi->stat = ti_qspi_read(qspi, QSPI_SPI_STATUS_REG);
+
+       if (!int_stat) {
+               dev_dbg(qspi->dev, "No IRQ triggered\n");
+               ret = IRQ_NONE;
+               goto out;
+       }
+
+       ret = IRQ_WAKE_THREAD;
+
+       ti_qspi_write(qspi, QSPI_WC_INT_DISABLE, QSPI_INTR_ENABLE_CLEAR_REG);
+       ti_qspi_write(qspi, QSPI_WC_INT_DISABLE,
+                               QSPI_INTR_STATUS_ENABLED_CLEAR);
+
+out:
+       spin_unlock(&qspi->lock);
+
+       return ret;
+}
+
+static irqreturn_t ti_qspi_threaded_isr(int this_irq, void *dev_id)
+{
+       struct ti_qspi *qspi = dev_id;
+       unsigned long flags;
+
+       spin_lock_irqsave(&qspi->lock, flags);
+
+       if (qspi->stat & WC)
+               complete(&qspi->transfer_complete);
+
+       spin_unlock_irqrestore(&qspi->lock, flags);
+
+       ti_qspi_write(qspi, QSPI_WC_INT_EN, QSPI_INTR_ENABLE_SET_REG);
+
+       return IRQ_HANDLED;
+}
+
+static int ti_qspi_runtime_resume(struct device *dev)
+{
+       struct ti_qspi      *qspi;
+       struct spi_master       *master;
+
+       master = dev_get_drvdata(dev);
+       qspi = spi_master_get_devdata(master);
+       ti_qspi_restore_ctx(qspi);
+
+       return 0;
+}
+
+static const struct of_device_id ti_qspi_match[] = {
+       {.compatible = "ti,dra7xxx-qspi" },
+       {.compatible = "ti,am4372-qspi" },
+       {},
+};
+MODULE_DEVICE_TABLE(of, ti_qspi_match);
+
+static int ti_qspi_probe(struct platform_device *pdev)
+{
+       struct  ti_qspi *qspi;
+       struct spi_master *master;
+       struct resource         *r;
+       struct device_node *np = pdev->dev.of_node;
+       u32 max_freq;
+       int ret = 0, num_cs, irq;
+
+       master = spi_alloc_master(&pdev->dev, sizeof(*qspi));
+       if (!master)
+               return -ENOMEM;
+
+       master->mode_bits = SPI_CPOL | SPI_CPHA;
+
+       master->bus_num = -1;
+       master->flags = SPI_MASTER_HALF_DUPLEX;
+       master->setup = ti_qspi_setup;
+       master->auto_runtime_pm = true;
+       master->transfer_one_message = ti_qspi_start_transfer_one;
+       master->dev.of_node = pdev->dev.of_node;
+       master->bits_per_word_mask = BIT(32 - 1) | BIT(16 - 1) | BIT(8 - 1);
+
+       if (!of_property_read_u32(np, "num-cs", &num_cs))
+               master->num_chipselect = num_cs;
+
+       platform_set_drvdata(pdev, master);
+
+       qspi = spi_master_get_devdata(master);
+       qspi->master = master;
+       qspi->dev = &pdev->dev;
+
+       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
+               dev_err(&pdev->dev, "no irq resource?\n");
+               return irq;
+       }
+
+       spin_lock_init(&qspi->lock);
+       mutex_init(&qspi->list_lock);
+
+       qspi->base = devm_ioremap_resource(&pdev->dev, r);
+       if (IS_ERR(qspi->base)) {
+               ret = PTR_ERR(qspi->base);
+               goto free_master;
+       }
+
+       ret = devm_request_threaded_irq(&pdev->dev, irq, ti_qspi_isr,
+                       ti_qspi_threaded_isr, 0,
+                       dev_name(&pdev->dev), qspi);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Failed to register ISR for IRQ %d\n",
+                               irq);
+               goto free_master;
+       }
+
+       qspi->fclk = devm_clk_get(&pdev->dev, "fck");
+       if (IS_ERR(qspi->fclk)) {
+               ret = PTR_ERR(qspi->fclk);
+               dev_err(&pdev->dev, "could not get clk: %d\n", ret);
+       }
+
+       init_completion(&qspi->transfer_complete);
+
+       pm_runtime_use_autosuspend(&pdev->dev);
+       pm_runtime_set_autosuspend_delay(&pdev->dev, QSPI_AUTOSUSPEND_TIMEOUT);
+       pm_runtime_enable(&pdev->dev);
+
+       if (!of_property_read_u32(np, "spi-max-frequency", &max_freq))
+               qspi->spi_max_frequency = max_freq;
+
+       ret = spi_register_master(master);
+       if (ret)
+               goto free_master;
+
+       return 0;
+
+free_master:
+       spi_master_put(master);
+       return ret;
+}
+
+static int ti_qspi_remove(struct platform_device *pdev)
+{
+       struct  ti_qspi *qspi = platform_get_drvdata(pdev);
+
+       spi_unregister_master(qspi->master);
+
+       return 0;
+}
+
+static const struct dev_pm_ops ti_qspi_pm_ops = {
+       .runtime_resume = ti_qspi_runtime_resume,
+};
+
+static struct platform_driver ti_qspi_driver = {
+       .probe  = ti_qspi_probe,
+       .remove = ti_qspi_remove,
+       .driver = {
+               .name   = "ti,dra7xxx-qspi",
+               .owner  = THIS_MODULE,
+               .pm =   &ti_qspi_pm_ops,
+               .of_match_table = ti_qspi_match,
+       }
+};
+
+module_platform_driver(ti_qspi_driver);
+
+MODULE_AUTHOR("Sourav Poddar <sourav.poddar@ti.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("TI QSPI controller driver");
index 10606fc..7d20e12 100644 (file)
@@ -283,7 +283,7 @@ static int ti_ssp_spi_probe(struct platform_device *pdev)
        struct device *dev = &pdev->dev;
        int error = 0;
 
-       pdata = dev->platform_data;
+       pdata = dev_get_platdata(dev);
        if (!pdata) {
                dev_err(dev, "platform data not found\n");
                return -EINVAL;
index 6b0874d..2d4010d 100644 (file)
@@ -52,8 +52,7 @@ static inline int tle62x0_write(struct tle62x0_state *st)
                buff[1] = gpio_state;
        }
 
-       dev_dbg(&st->us->dev, "buff %02x,%02x,%02x\n",
-               buff[0], buff[1], buff[2]);
+       dev_dbg(&st->us->dev, "buff %3ph\n", buff);
 
        return spi_write(st->us, buff, (st->nr_gpio == 16) ? 3 : 2);
 }
@@ -247,7 +246,7 @@ static int tle62x0_probe(struct spi_device *spi)
        int ptr;
        int ret;
 
-       pdata = spi->dev.platform_data;
+       pdata = dev_get_platdata(&spi->dev);
        if (pdata == NULL) {
                dev_err(&spi->dev, "no device data specified\n");
                return -EINVAL;
index dd55707..eaeeed5 100644 (file)
@@ -1797,3 +1797,5 @@ MODULE_PARM_DESC(use_dma,
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Intel EG20T PCH/LAPIS Semiconductor ML7xxx IOH SPI Driver");
+MODULE_DEVICE_TABLE(pci, pch_spi_pcidev_id);
+
index e9b7681..7c6d157 100644 (file)
@@ -26,7 +26,7 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/module.h>
-#include <asm/gpio.h>
+#include <linux/gpio.h>
 
 
 #define SPI_FIFO_SIZE 4
index 09a9428..0bf1b2c 100644 (file)
@@ -80,10 +80,9 @@ struct xilinx_spi {
        /* bitbang has to be first */
        struct spi_bitbang bitbang;
        struct completion done;
-       struct resource mem; /* phys mem */
        void __iomem    *regs;  /* virt. address of the control registers */
 
-       u32             irq;
+       int             irq;
 
        u8 *rx_ptr;             /* pointer in the Tx buffer */
        const u8 *tx_ptr;       /* pointer in the Rx buffer */
@@ -233,21 +232,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;
@@ -355,17 +339,34 @@ static const struct of_device_id xilinx_spi_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, xilinx_spi_of_match);
 
-struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem,
-       u32 irq, s16 bus_num, int num_cs, int bits_per_word)
+static int xilinx_spi_probe(struct platform_device *pdev)
 {
-       struct spi_master *master;
        struct xilinx_spi *xspi;
-       int ret;
+       struct xspi_platform_data *pdata;
+       struct resource *res;
+       int ret, num_cs = 0, bits_per_word = 8;
+       struct spi_master *master;
        u32 tmp;
+       u8 i;
+
+       pdata = dev_get_platdata(&pdev->dev);
+       if (pdata) {
+               num_cs = pdata->num_chipselect;
+               bits_per_word = pdata->bits_per_word;
+       } else {
+               of_property_read_u32(pdev->dev.of_node, "xlnx,num-ss-bits",
+                                         &num_cs);
+       }
+
+       if (!num_cs) {
+               dev_err(&pdev->dev,
+                       "Missing slave select configuration data\n");
+               return -EINVAL;
+       }
 
-       master = spi_alloc_master(dev, sizeof(struct xilinx_spi));
+       master = spi_alloc_master(&pdev->dev, sizeof(struct xilinx_spi));
        if (!master)
-               return NULL;
+               return -ENODEV;
 
        /* the spi->mode bits understood by this driver: */
        master->mode_bits = SPI_CPOL | SPI_CPHA;
@@ -375,25 +376,18 @@ 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),
-               XILINX_SPI_NAME))
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       xspi->regs = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(xspi->regs)) {
+               ret = PTR_ERR(xspi->regs);
                goto put_master;
-
-       xspi->regs = ioremap(mem->start, resource_size(mem));
-       if (xspi->regs == NULL) {
-               dev_warn(dev, "ioremap failure\n");
-               goto map_failed;
        }
 
-       master->bus_num = bus_num;
+       master->bus_num = pdev->dev.id;
        master->num_chipselect = num_cs;
-       master->dev.of_node = dev->of_node;
-
-       xspi->mem = *mem;
-       xspi->irq = irq;
+       master->dev.of_node = pdev->dev.of_node;
 
        /*
         * Detect endianess on the IP via loop bit in CR. Detection
@@ -423,113 +417,63 @@ struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem,
        } else if (xspi->bits_per_word == 32) {
                xspi->tx_fn = xspi_tx32;
                xspi->rx_fn = xspi_rx32;
-       } else
-               goto unmap_io;
-
+       } else {
+               ret = -EINVAL;
+               goto put_master;
+       }
 
        /* SPI controller initializations */
        xspi_init_hw(xspi);
 
+       xspi->irq = platform_get_irq(pdev, 0);
+       if (xspi->irq < 0) {
+               ret = xspi->irq;
+               goto put_master;
+       }
+
        /* Register for SPI Interrupt */
-       ret = request_irq(xspi->irq, xilinx_spi_irq, 0, XILINX_SPI_NAME, xspi);
+       ret = devm_request_irq(&pdev->dev, xspi->irq, xilinx_spi_irq, 0,
+                              dev_name(&pdev->dev), xspi);
        if (ret)
-               goto unmap_io;
+               goto put_master;
 
        ret = spi_bitbang_start(&xspi->bitbang);
        if (ret) {
-               dev_err(dev, "spi_bitbang_start FAILED\n");
-               goto free_irq;
-       }
-
-       dev_info(dev, "at 0x%08llX mapped to 0x%p, irq=%d\n",
-               (unsigned long long)mem->start, xspi->regs, xspi->irq);
-       return master;
-
-free_irq:
-       free_irq(xspi->irq, xspi);
-unmap_io:
-       iounmap(xspi->regs);
-map_failed:
-       release_mem_region(mem->start, resource_size(mem));
-put_master:
-       spi_master_put(master);
-       return NULL;
-}
-EXPORT_SYMBOL(xilinx_spi_init);
-
-void xilinx_spi_deinit(struct spi_master *master)
-{
-       struct xilinx_spi *xspi;
-
-       xspi = spi_master_get_devdata(master);
-
-       spi_bitbang_stop(&xspi->bitbang);
-       free_irq(xspi->irq, xspi);
-       iounmap(xspi->regs);
-
-       release_mem_region(xspi->mem.start, resource_size(&xspi->mem));
-       spi_master_put(xspi->bitbang.master);
-}
-EXPORT_SYMBOL(xilinx_spi_deinit);
-
-static int xilinx_spi_probe(struct platform_device *dev)
-{
-       struct xspi_platform_data *pdata;
-       struct resource *r;
-       int irq, num_cs = 0, bits_per_word = 8;
-       struct spi_master *master;
-       u8 i;
-
-       pdata = dev->dev.platform_data;
-       if (pdata) {
-               num_cs = pdata->num_chipselect;
-               bits_per_word = pdata->bits_per_word;
-       }
-
-#ifdef CONFIG_OF
-       if (dev->dev.of_node) {
-               const __be32 *prop;
-               int len;
-
-               /* number of slave select bits is required */
-               prop = of_get_property(dev->dev.of_node, "xlnx,num-ss-bits",
-                                      &len);
-               if (prop && len >= sizeof(*prop))
-                       num_cs = __be32_to_cpup(prop);
-       }
-#endif
-
-       if (!num_cs) {
-               dev_err(&dev->dev, "Missing slave select configuration data\n");
-               return -EINVAL;
+               dev_err(&pdev->dev, "spi_bitbang_start FAILED\n");
+               goto put_master;
        }
 
-
-       r = platform_get_resource(dev, IORESOURCE_MEM, 0);
-       if (!r)
-               return -ENODEV;
-
-       irq = platform_get_irq(dev, 0);
-       if (irq < 0)
-               return -ENXIO;
-
-       master = xilinx_spi_init(&dev->dev, r, irq, dev->id, num_cs,
-                                bits_per_word);
-       if (!master)
-               return -ENODEV;
+       dev_info(&pdev->dev, "at 0x%08llX mapped to 0x%p, irq=%d\n",
+               (unsigned long long)res->start, xspi->regs, xspi->irq);
 
        if (pdata) {
                for (i = 0; i < pdata->num_devices; i++)
                        spi_new_device(master, pdata->devices + i);
        }
 
-       platform_set_drvdata(dev, master);
+       platform_set_drvdata(pdev, master);
        return 0;
+
+put_master:
+       spi_master_put(master);
+
+       return ret;
 }
 
-static int xilinx_spi_remove(struct platform_device *dev)
+static int xilinx_spi_remove(struct platform_device *pdev)
 {
-       xilinx_spi_deinit(platform_get_drvdata(dev));
+       struct spi_master *master = platform_get_drvdata(pdev);
+       struct xilinx_spi *xspi = spi_master_get_devdata(master);
+       void __iomem *regs_base = xspi->regs;
+
+       spi_bitbang_stop(&xspi->bitbang);
+
+       /* Disable all the interrupts just in case */
+       xspi->write_fn(0, regs_base + XIPIF_V123B_IIER_OFFSET);
+       /* Disable the global IPIF interrupt */
+       xspi->write_fn(0, regs_base + XIPIF_V123B_DGIER_OFFSET);
+
+       spi_master_put(xspi->bitbang.master);
 
        return 0;
 }
index 978dda2..9e039c6 100644 (file)
@@ -553,6 +553,10 @@ static void spi_pump_messages(struct kthread_work *work)
                    master->unprepare_transfer_hardware(master))
                        dev_err(&master->dev,
                                "failed to unprepare transfer hardware\n");
+               if (master->auto_runtime_pm) {
+                       pm_runtime_mark_last_busy(master->dev.parent);
+                       pm_runtime_put_autosuspend(master->dev.parent);
+               }
                return;
        }
 
@@ -572,11 +576,23 @@ static void spi_pump_messages(struct kthread_work *work)
                master->busy = true;
        spin_unlock_irqrestore(&master->queue_lock, flags);
 
+       if (!was_busy && master->auto_runtime_pm) {
+               ret = pm_runtime_get_sync(master->dev.parent);
+               if (ret < 0) {
+                       dev_err(&master->dev, "Failed to power device: %d\n",
+                               ret);
+                       return;
+               }
+       }
+
        if (!was_busy && master->prepare_transfer_hardware) {
                ret = master->prepare_transfer_hardware(master);
                if (ret) {
                        dev_err(&master->dev,
                                "failed to prepare transfer hardware\n");
+
+                       if (master->auto_runtime_pm)
+                               pm_runtime_put(master->dev.parent);
                        return;
                }
        }
@@ -774,7 +790,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);
@@ -869,6 +885,47 @@ static void of_register_spi_devices(struct spi_master *master)
                if (of_find_property(nc, "spi-3wire", NULL))
                        spi->mode |= SPI_3WIRE;
 
+               /* Device DUAL/QUAD mode */
+               prop = of_get_property(nc, "spi-tx-bus-width", &len);
+               if (prop && len == sizeof(*prop)) {
+                       switch (be32_to_cpup(prop)) {
+                       case SPI_NBITS_SINGLE:
+                               break;
+                       case SPI_NBITS_DUAL:
+                               spi->mode |= SPI_TX_DUAL;
+                               break;
+                       case SPI_NBITS_QUAD:
+                               spi->mode |= SPI_TX_QUAD;
+                               break;
+                       default:
+                               dev_err(&master->dev,
+                                       "spi-tx-bus-width %d not supported\n",
+                                       be32_to_cpup(prop));
+                               spi_dev_put(spi);
+                               continue;
+                       }
+               }
+
+               prop = of_get_property(nc, "spi-rx-bus-width", &len);
+               if (prop && len == sizeof(*prop)) {
+                       switch (be32_to_cpup(prop)) {
+                       case SPI_NBITS_SINGLE:
+                               break;
+                       case SPI_NBITS_DUAL:
+                               spi->mode |= SPI_RX_DUAL;
+                               break;
+                       case SPI_NBITS_QUAD:
+                               spi->mode |= SPI_RX_QUAD;
+                               break;
+                       default:
+                               dev_err(&master->dev,
+                                       "spi-rx-bus-width %d not supported\n",
+                                       be32_to_cpup(prop));
+                               spi_dev_put(spi);
+                               continue;
+                       }
+               }
+
                /* Device speed */
                prop = of_get_property(nc, "spi-max-frequency", &len);
                if (!prop || len < sizeof(*prop)) {
@@ -1169,7 +1226,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;
                }
        }
@@ -1316,6 +1373,19 @@ int spi_setup(struct spi_device *spi)
        unsigned        bad_bits;
        int             status = 0;
 
+       /* check mode to prevent that DUAL and QUAD set at the same time
+        */
+       if (((spi->mode & SPI_TX_DUAL) && (spi->mode & SPI_TX_QUAD)) ||
+               ((spi->mode & SPI_RX_DUAL) && (spi->mode & SPI_RX_QUAD))) {
+               dev_err(&spi->dev,
+               "setup: can not select dual and quad at the same time\n");
+               return -EINVAL;
+       }
+       /* if it is SPI_3WIRE mode, DUAL and QUAD should be forbidden
+        */
+       if ((spi->mode & SPI_3WIRE) && (spi->mode &
+               (SPI_TX_DUAL | SPI_TX_QUAD | SPI_RX_DUAL | SPI_RX_QUAD)))
+               return -EINVAL;
        /* help drivers fail *cleanly* when they need options
         * that aren't supported with their current master
         */
@@ -1351,6 +1421,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
@@ -1373,12 +1448,20 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message)
        /**
         * Set transfer bits_per_word and max speed as spi device default if
         * it is not set for this transfer.
+        * Set transfer tx_nbits and rx_nbits as single transfer default
+        * (SPI_NBITS_SINGLE) if it is not set for this transfer.
         */
        list_for_each_entry(xfer, &message->transfers, transfer_list) {
+               message->frame_length += xfer->len;
                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 +1470,54 @@ 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;
+
+               if (xfer->tx_buf && !xfer->tx_nbits)
+                       xfer->tx_nbits = SPI_NBITS_SINGLE;
+               if (xfer->rx_buf && !xfer->rx_nbits)
+                       xfer->rx_nbits = SPI_NBITS_SINGLE;
+               /* check transfer tx/rx_nbits:
+                * 1. keep the value is not out of single, dual and quad
+                * 2. keep tx/rx_nbits is contained by mode in spi_device
+                * 3. if SPI_3WIRE, tx/rx_nbits should be in single
+                */
+               if (xfer->tx_buf) {
+                       if (xfer->tx_nbits != SPI_NBITS_SINGLE &&
+                               xfer->tx_nbits != SPI_NBITS_DUAL &&
+                               xfer->tx_nbits != SPI_NBITS_QUAD)
+                               return -EINVAL;
+                       if ((xfer->tx_nbits == SPI_NBITS_DUAL) &&
+                               !(spi->mode & (SPI_TX_DUAL | SPI_TX_QUAD)))
+                               return -EINVAL;
+                       if ((xfer->tx_nbits == SPI_NBITS_QUAD) &&
+                               !(spi->mode & SPI_TX_QUAD))
+                               return -EINVAL;
+                       if ((spi->mode & SPI_3WIRE) &&
+                               (xfer->tx_nbits != SPI_NBITS_SINGLE))
+                               return -EINVAL;
+               }
+               /* check transfer rx_nbits */
+               if (xfer->rx_buf) {
+                       if (xfer->rx_nbits != SPI_NBITS_SINGLE &&
+                               xfer->rx_nbits != SPI_NBITS_DUAL &&
+                               xfer->rx_nbits != SPI_NBITS_QUAD)
+                               return -EINVAL;
+                       if ((xfer->rx_nbits == SPI_NBITS_DUAL) &&
+                               !(spi->mode & (SPI_RX_DUAL | SPI_RX_QUAD)))
+                               return -EINVAL;
+                       if ((xfer->rx_nbits == SPI_NBITS_QUAD) &&
+                               !(spi->mode & SPI_RX_QUAD))
+                               return -EINVAL;
+                       if ((spi->mode & SPI_3WIRE) &&
+                               (xfer->rx_nbits != SPI_NBITS_SINGLE))
+                               return -EINVAL;
+               }
        }
 
        message->spi = spi;
index 3396eb9..ac27671 100644 (file)
@@ -341,8 +341,8 @@ void hvsilib_establish(struct hvsi_priv *pv)
 
        pr_devel("HVSI@%x:   ... waiting handshake\n", pv->termno);
 
-       /* Try for up to 200s */
-       for (timeout = 0; timeout < 20; timeout++) {
+       /* Try for up to 400ms */
+       for (timeout = 0; timeout < 40; timeout++) {
                if (pv->established)
                        goto established;
                if (!hvsi_get_packet(pv))
index 0f1d193..279b049 100644 (file)
@@ -305,9 +305,11 @@ static int __init ohci_pci_init(void)
 
        ohci_init_driver(&ohci_pci_hc_driver, &pci_overrides);
 
+#ifdef CONFIG_PM
        /* 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;
+#endif
 
        return pci_register_driver(&ohci_pci_driver);
 }
index 83cfb83..96655f4 100644 (file)
@@ -229,7 +229,7 @@ static void __d_free(struct rcu_head *head)
  */
 static void d_free(struct dentry *dentry)
 {
-       BUG_ON(dentry->d_count);
+       BUG_ON(dentry->d_lockref.count);
        this_cpu_dec(nr_dentry);
        if (dentry->d_op && dentry->d_op->d_release)
                dentry->d_op->d_release(dentry);
@@ -467,7 +467,7 @@ relock:
        }
 
        if (ref)
-               dentry->d_count--;
+               dentry->d_lockref.count--;
        /*
         * inform the fs via d_prune that this dentry is about to be
         * unhashed and destroyed.
@@ -513,15 +513,10 @@ void dput(struct dentry *dentry)
                return;
 
 repeat:
-       if (dentry->d_count == 1)
+       if (dentry->d_lockref.count == 1)
                might_sleep();
-       spin_lock(&dentry->d_lock);
-       BUG_ON(!dentry->d_count);
-       if (dentry->d_count > 1) {
-               dentry->d_count--;
-               spin_unlock(&dentry->d_lock);
+       if (lockref_put_or_lock(&dentry->d_lockref))
                return;
-       }
 
        if (dentry->d_flags & DCACHE_OP_DELETE) {
                if (dentry->d_op->d_delete(dentry))
@@ -535,7 +530,7 @@ repeat:
        dentry->d_flags |= DCACHE_REFERENCED;
        dentry_lru_add(dentry);
 
-       dentry->d_count--;
+       dentry->d_lockref.count--;
        spin_unlock(&dentry->d_lock);
        return;
 
@@ -590,7 +585,7 @@ int d_invalidate(struct dentry * dentry)
         * We also need to leave mountpoints alone,
         * directory or not.
         */
-       if (dentry->d_count > 1 && dentry->d_inode) {
+       if (dentry->d_lockref.count > 1 && dentry->d_inode) {
                if (S_ISDIR(dentry->d_inode->i_mode) || d_mountpoint(dentry)) {
                        spin_unlock(&dentry->d_lock);
                        return -EBUSY;
@@ -606,20 +601,33 @@ EXPORT_SYMBOL(d_invalidate);
 /* This must be called with d_lock held */
 static inline void __dget_dlock(struct dentry *dentry)
 {
-       dentry->d_count++;
+       dentry->d_lockref.count++;
 }
 
 static inline void __dget(struct dentry *dentry)
 {
-       spin_lock(&dentry->d_lock);
-       __dget_dlock(dentry);
-       spin_unlock(&dentry->d_lock);
+       lockref_get(&dentry->d_lockref);
 }
 
 struct dentry *dget_parent(struct dentry *dentry)
 {
+       int gotref;
        struct dentry *ret;
 
+       /*
+        * Do optimistic parent lookup without any
+        * locking.
+        */
+       rcu_read_lock();
+       ret = ACCESS_ONCE(dentry->d_parent);
+       gotref = lockref_get_not_zero(&ret->d_lockref);
+       rcu_read_unlock();
+       if (likely(gotref)) {
+               if (likely(ret == ACCESS_ONCE(dentry->d_parent)))
+                       return ret;
+               dput(ret);
+       }
+
 repeat:
        /*
         * Don't need rcu_dereference because we re-check it was correct under
@@ -634,8 +642,8 @@ repeat:
                goto repeat;
        }
        rcu_read_unlock();
-       BUG_ON(!ret->d_count);
-       ret->d_count++;
+       BUG_ON(!ret->d_lockref.count);
+       ret->d_lockref.count++;
        spin_unlock(&ret->d_lock);
        return ret;
 }
@@ -718,7 +726,7 @@ restart:
        spin_lock(&inode->i_lock);
        hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) {
                spin_lock(&dentry->d_lock);
-               if (!dentry->d_count) {
+               if (!dentry->d_lockref.count) {
                        __dget_dlock(dentry);
                        __d_drop(dentry);
                        spin_unlock(&dentry->d_lock);
@@ -763,12 +771,8 @@ static void try_prune_one_dentry(struct dentry *dentry)
        /* Prune ancestors. */
        dentry = parent;
        while (dentry) {
-               spin_lock(&dentry->d_lock);
-               if (dentry->d_count > 1) {
-                       dentry->d_count--;
-                       spin_unlock(&dentry->d_lock);
+               if (lockref_put_or_lock(&dentry->d_lockref))
                        return;
-               }
                dentry = dentry_kill(dentry, 1);
        }
 }
@@ -793,7 +797,7 @@ static void shrink_dentry_list(struct list_head *list)
                 * the LRU because of laziness during lookup.  Do not free
                 * it - just keep it off the LRU list.
                 */
-               if (dentry->d_count) {
+               if (dentry->d_lockref.count) {
                        dentry_lru_del(dentry);
                        spin_unlock(&dentry->d_lock);
                        continue;
@@ -913,7 +917,7 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry)
                        dentry_lru_del(dentry);
                        __d_shrink(dentry);
 
-                       if (dentry->d_count != 0) {
+                       if (dentry->d_lockref.count != 0) {
                                printk(KERN_ERR
                                       "BUG: Dentry %p{i=%lx,n=%s}"
                                       " still in use (%d)"
@@ -922,7 +926,7 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry)
                                       dentry->d_inode ?
                                       dentry->d_inode->i_ino : 0UL,
                                       dentry->d_name.name,
-                                      dentry->d_count,
+                                      dentry->d_lockref.count,
                                       dentry->d_sb->s_type->name,
                                       dentry->d_sb->s_id);
                                BUG();
@@ -933,7 +937,7 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry)
                                list_del(&dentry->d_u.d_child);
                        } else {
                                parent = dentry->d_parent;
-                               parent->d_count--;
+                               parent->d_lockref.count--;
                                list_del(&dentry->d_u.d_child);
                        }
 
@@ -981,7 +985,7 @@ void shrink_dcache_for_umount(struct super_block *sb)
 
        dentry = sb->s_root;
        sb->s_root = NULL;
-       dentry->d_count--;
+       dentry->d_lockref.count--;
        shrink_dcache_for_umount_subtree(dentry);
 
        while (!hlist_bl_empty(&sb->s_anon)) {
@@ -1147,7 +1151,7 @@ resume:
                 * loop in shrink_dcache_parent() might not make any progress
                 * and loop forever.
                 */
-               if (dentry->d_count) {
+               if (dentry->d_lockref.count) {
                        dentry_lru_del(dentry);
                } else if (!(dentry->d_flags & DCACHE_SHRINK_LIST)) {
                        dentry_lru_move_list(dentry, dispose);
@@ -1269,7 +1273,7 @@ struct dentry *__d_alloc(struct super_block *sb, const struct qstr *name)
        smp_wmb();
        dentry->d_name.name = dname;
 
-       dentry->d_count = 1;
+       dentry->d_lockref.count = 1;
        dentry->d_flags = 0;
        spin_lock_init(&dentry->d_lock);
        seqcount_init(&dentry->d_seq);
@@ -1782,7 +1786,7 @@ static noinline enum slow_d_compare slow_dentry_cmp(
  * without taking d_lock and checking d_seq sequence count against @seq
  * returned here.
  *
- * A refcount may be taken on the found dentry with the __d_rcu_to_refcount
+ * A refcount may be taken on the found dentry with the d_rcu_to_refcount
  * function.
  *
  * Alternatively, __d_lookup_rcu may be called again to look up the child of
@@ -1970,7 +1974,7 @@ struct dentry *__d_lookup(const struct dentry *parent, const struct qstr *name)
                                goto next;
                }
 
-               dentry->d_count++;
+               dentry->d_lockref.count++;
                found = dentry;
                spin_unlock(&dentry->d_lock);
                break;
@@ -2069,7 +2073,7 @@ again:
        spin_lock(&dentry->d_lock);
        inode = dentry->d_inode;
        isdir = S_ISDIR(inode->i_mode);
-       if (dentry->d_count == 1) {
+       if (dentry->d_lockref.count == 1) {
                if (!spin_trylock(&inode->i_lock)) {
                        spin_unlock(&dentry->d_lock);
                        cpu_relax();
@@ -2948,7 +2952,7 @@ resume:
                }
                if (!(dentry->d_flags & DCACHE_GENOCIDE)) {
                        dentry->d_flags |= DCACHE_GENOCIDE;
-                       dentry->d_count--;
+                       dentry->d_lockref.count--;
                }
                spin_unlock(&dentry->d_lock);
        }
@@ -2956,7 +2960,7 @@ resume:
                struct dentry *child = this_parent;
                if (!(this_parent->d_flags & DCACHE_GENOCIDE)) {
                        this_parent->d_flags |= DCACHE_GENOCIDE;
-                       this_parent->d_count--;
+                       this_parent->d_lockref.count--;
                }
                this_parent = try_to_ascend(this_parent, locked, seq);
                if (!this_parent)
index 8743ba9..984c2bb 100644 (file)
@@ -3047,6 +3047,14 @@ int jfs_readdir(struct file *file, struct dir_context *ctx)
 
                dir_index = (u32) ctx->pos;
 
+               /*
+                * NFSv4 reserves cookies 1 and 2 for . and .. so the value
+                * we return to the vfs is one greater than the one we use
+                * internally.
+                */
+               if (dir_index)
+                       dir_index--;
+
                if (dir_index > 1) {
                        struct dir_table_slot dirtab_slot;
 
@@ -3086,7 +3094,7 @@ int jfs_readdir(struct file *file, struct dir_context *ctx)
                        if (p->header.flag & BT_INTERNAL) {
                                jfs_err("jfs_readdir: bad index table");
                                DT_PUTPAGE(mp);
-                               ctx->pos = -1;
+                               ctx->pos = DIREND;
                                return 0;
                        }
                } else {
@@ -3094,14 +3102,14 @@ int jfs_readdir(struct file *file, struct dir_context *ctx)
                                /*
                                 * self "."
                                 */
-                               ctx->pos = 0;
+                               ctx->pos = 1;
                                if (!dir_emit(ctx, ".", 1, ip->i_ino, DT_DIR))
                                        return 0;
                        }
                        /*
                         * parent ".."
                         */
-                       ctx->pos = 1;
+                       ctx->pos = 2;
                        if (!dir_emit(ctx, "..", 2, PARENT(ip), DT_DIR))
                                return 0;
 
@@ -3122,22 +3130,23 @@ int jfs_readdir(struct file *file, struct dir_context *ctx)
                /*
                 * Legacy filesystem - OS/2 & Linux JFS < 0.3.6
                 *
-                * pn = index = 0:      First entry "."
-                * pn = 0; index = 1:   Second entry ".."
+                * pn = 0; index = 1:   First entry "."
+                * pn = 0; index = 2:   Second entry ".."
                 * pn > 0:              Real entries, pn=1 -> leftmost page
                 * pn = index = -1:     No more entries
                 */
                dtpos = ctx->pos;
-               if (dtpos == 0) {
+               if (dtpos < 2) {
                        /* build "." entry */
+                       ctx->pos = 1;
                        if (!dir_emit(ctx, ".", 1, ip->i_ino, DT_DIR))
                                return 0;
-                       dtoffset->index = 1;
+                       dtoffset->index = 2;
                        ctx->pos = dtpos;
                }
 
                if (dtoffset->pn == 0) {
-                       if (dtoffset->index == 1) {
+                       if (dtoffset->index == 2) {
                                /* build ".." entry */
                                if (!dir_emit(ctx, "..", 2, PARENT(ip), DT_DIR))
                                        return 0;
@@ -3228,6 +3237,12 @@ int jfs_readdir(struct file *file, struct dir_context *ctx)
                                        }
                                        jfs_dirent->position = unique_pos++;
                                }
+                               /*
+                                * We add 1 to the index because we may
+                                * use a value of 2 internally, and NFSv4
+                                * doesn't like that.
+                                */
+                               jfs_dirent->position++;
                        } else {
                                jfs_dirent->position = dtpos;
                                len = min(d_namleft, DTLHDRDATALEN_LEGACY);
index 89a612e..2c30c84 100644 (file)
@@ -494,6 +494,50 @@ static inline void unlock_rcu_walk(void)
        br_read_unlock(&vfsmount_lock);
 }
 
+/*
+ * When we move over from the RCU domain to properly refcounted
+ * long-lived dentries, we need to check the sequence numbers
+ * we got before lookup very carefully.
+ *
+ * We cannot blindly increment a dentry refcount - even if it
+ * is not locked - if it is zero, because it may have gone
+ * through the final d_kill() logic already.
+ *
+ * So for a zero refcount, we need to get the spinlock (which is
+ * safe even for a dead dentry because the de-allocation is
+ * RCU-delayed), and check the sequence count under the lock.
+ *
+ * Once we have checked the sequence count, we know it is live,
+ * and since we hold the spinlock it cannot die from under us.
+ *
+ * In contrast, if the reference count wasn't zero, we can just
+ * increment the lockref without having to take the spinlock.
+ * Even if the sequence number ends up being stale, we haven't
+ * gone through the final dput() and killed the dentry yet.
+ */
+static inline int d_rcu_to_refcount(struct dentry *dentry, seqcount_t *validate, unsigned seq)
+{
+       int gotref;
+
+       gotref = lockref_get_or_lock(&dentry->d_lockref);
+
+       /* Does the sequence number still match? */
+       if (read_seqcount_retry(validate, seq)) {
+               if (gotref)
+                       dput(dentry);
+               else
+                       spin_unlock(&dentry->d_lock);
+               return -ECHILD;
+       }
+
+       /* Get the ref now, if we couldn't get it originally */
+       if (!gotref) {
+               dentry->d_lockref.count++;
+               spin_unlock(&dentry->d_lock);
+       }
+       return 0;
+}
+
 /**
  * unlazy_walk - try to switch to ref-walk mode.
  * @nd: nameidata pathwalk data
@@ -518,29 +562,28 @@ static int unlazy_walk(struct nameidata *nd, struct dentry *dentry)
                                nd->root.dentry != fs->root.dentry)
                        goto err_root;
        }
-       spin_lock(&parent->d_lock);
+
+       /*
+        * For a negative lookup, the lookup sequence point is the parents
+        * sequence point, and it only needs to revalidate the parent dentry.
+        *
+        * For a positive lookup, we need to move both the parent and the
+        * dentry from the RCU domain to be properly refcounted. And the
+        * sequence number in the dentry validates *both* dentry counters,
+        * since we checked the sequence number of the parent after we got
+        * the child sequence number. So we know the parent must still
+        * be valid if the child sequence number is still valid.
+        */
        if (!dentry) {
-               if (!__d_rcu_to_refcount(parent, nd->seq))
-                       goto err_parent;
+               if (d_rcu_to_refcount(parent, &parent->d_seq, nd->seq) < 0)
+                       goto err_root;
                BUG_ON(nd->inode != parent->d_inode);
        } else {
-               if (dentry->d_parent != parent)
+               if (d_rcu_to_refcount(dentry, &dentry->d_seq, nd->seq) < 0)
+                       goto err_root;
+               if (d_rcu_to_refcount(parent, &dentry->d_seq, nd->seq) < 0)
                        goto err_parent;
-               spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
-               if (!__d_rcu_to_refcount(dentry, nd->seq))
-                       goto err_child;
-               /*
-                * If the sequence check on the child dentry passed, then
-                * the child has not been removed from its parent. This
-                * means the parent dentry must be valid and able to take
-                * a reference at this point.
-                */
-               BUG_ON(!IS_ROOT(dentry) && dentry->d_parent != parent);
-               BUG_ON(!parent->d_count);
-               parent->d_count++;
-               spin_unlock(&dentry->d_lock);
        }
-       spin_unlock(&parent->d_lock);
        if (want_root) {
                path_get(&nd->root);
                spin_unlock(&fs->lock);
@@ -551,10 +594,8 @@ static int unlazy_walk(struct nameidata *nd, struct dentry *dentry)
        nd->flags &= ~LOOKUP_RCU;
        return 0;
 
-err_child:
-       spin_unlock(&dentry->d_lock);
 err_parent:
-       spin_unlock(&parent->d_lock);
+       dput(dentry);
 err_root:
        if (want_root)
                spin_unlock(&fs->lock);
@@ -585,14 +626,11 @@ static int complete_walk(struct nameidata *nd)
                nd->flags &= ~LOOKUP_RCU;
                if (!(nd->flags & LOOKUP_ROOT))
                        nd->root.mnt = NULL;
-               spin_lock(&dentry->d_lock);
-               if (unlikely(!__d_rcu_to_refcount(dentry, nd->seq))) {
-                       spin_unlock(&dentry->d_lock);
+
+               if (d_rcu_to_refcount(dentry, &dentry->d_seq, nd->seq) < 0) {
                        unlock_rcu_walk();
                        return -ECHILD;
                }
-               BUG_ON(nd->inode != dentry->d_inode);
-               spin_unlock(&dentry->d_lock);
                mntget(nd->path.mnt);
                unlock_rcu_walk();
        }
@@ -3327,7 +3365,7 @@ void dentry_unhash(struct dentry *dentry)
 {
        shrink_dcache_parent(dentry);
        spin_lock(&dentry->d_lock);
-       if (dentry->d_count == 1)
+       if (dentry->d_lockref.count == 1)
                __d_drop(dentry);
        spin_unlock(&dentry->d_lock);
 }
@@ -3671,11 +3709,15 @@ SYSCALL_DEFINE5(linkat, int, olddfd, const char __user *, oldname,
        if ((flags & ~(AT_SYMLINK_FOLLOW | AT_EMPTY_PATH)) != 0)
                return -EINVAL;
        /*
-        * Using empty names is equivalent to using AT_SYMLINK_FOLLOW
-        * on /proc/self/fd/<fd>.
+        * To use null names we require CAP_DAC_READ_SEARCH
+        * This ensures that not everyone will be able to create
+        * handlink using the passed filedescriptor.
         */
-       if (flags & AT_EMPTY_PATH)
+       if (flags & AT_EMPTY_PATH) {
+               if (!capable(CAP_DAC_READ_SEARCH))
+                       return -ENOENT;
                how = LOOKUP_EMPTY;
+       }
 
        if (flags & AT_SYMLINK_FOLLOW)
                how |= LOOKUP_FOLLOW;
index 854d809..121da2d 100644 (file)
@@ -1022,7 +1022,7 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
        struct inode *inode = NULL;
        struct ocfs2_super *osb = NULL;
        struct buffer_head *bh = NULL;
-       char nodestr[8];
+       char nodestr[12];
        struct ocfs2_blockcheck_stats stats;
 
        trace_ocfs2_fill_super(sb, data, silent);
index 4a12532..9169b91 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/seqlock.h>
 #include <linux/cache.h>
 #include <linux/rcupdate.h>
+#include <linux/lockref.h>
 
 struct nameidata;
 struct path;
@@ -100,6 +101,8 @@ extern unsigned int full_name_hash(const unsigned char *, unsigned int);
 # endif
 #endif
 
+#define d_lock d_lockref.lock
+
 struct dentry {
        /* RCU lookup touched fields */
        unsigned int d_flags;           /* protected by d_lock */
@@ -112,8 +115,7 @@ struct dentry {
        unsigned char d_iname[DNAME_INLINE_LEN];        /* small names */
 
        /* Ref lookup also touches following */
-       unsigned int d_count;           /* protected by d_lock */
-       spinlock_t d_lock;              /* per dentry lock */
+       struct lockref d_lockref;       /* per-dentry lock and refcount */
        const struct dentry_operations *d_op;
        struct super_block *d_sb;       /* The root of the dentry tree */
        unsigned long d_time;           /* used by d_revalidate */
@@ -302,31 +304,9 @@ extern struct dentry *__d_lookup(const struct dentry *, const struct qstr *);
 extern struct dentry *__d_lookup_rcu(const struct dentry *parent,
                                const struct qstr *name, unsigned *seq);
 
-/**
- * __d_rcu_to_refcount - take a refcount on dentry if sequence check is ok
- * @dentry: dentry to take a ref on
- * @seq: seqcount to verify against
- * Returns: 0 on failure, else 1.
- *
- * __d_rcu_to_refcount operates on a dentry,seq pair that was returned
- * by __d_lookup_rcu, to get a reference on an rcu-walk dentry.
- */
-static inline int __d_rcu_to_refcount(struct dentry *dentry, unsigned seq)
-{
-       int ret = 0;
-
-       assert_spin_locked(&dentry->d_lock);
-       if (!read_seqcount_retry(&dentry->d_seq, seq)) {
-               ret = 1;
-               dentry->d_count++;
-       }
-
-       return ret;
-}
-
 static inline unsigned d_count(const struct dentry *dentry)
 {
-       return dentry->d_count;
+       return dentry->d_lockref.count;
 }
 
 /* validate "insecure" dentry pointer */
@@ -357,17 +337,14 @@ extern char *dentry_path(struct dentry *, char *, int);
 static inline struct dentry *dget_dlock(struct dentry *dentry)
 {
        if (dentry)
-               dentry->d_count++;
+               dentry->d_lockref.count++;
        return dentry;
 }
 
 static inline struct dentry *dget(struct dentry *dentry)
 {
-       if (dentry) {
-               spin_lock(&dentry->d_lock);
-               dget_dlock(dentry);
-               spin_unlock(&dentry->d_lock);
-       }
+       if (dentry)
+               lockref_get(&dentry->d_lockref);
        return dentry;
 }
 
diff --git a/include/linux/lockref.h b/include/linux/lockref.h
new file mode 100644 (file)
index 0000000..ca07b50
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef __LINUX_LOCKREF_H
+#define __LINUX_LOCKREF_H
+
+/*
+ * Locked reference counts.
+ *
+ * These are different from just plain atomic refcounts in that they
+ * are atomic with respect to the spinlock that goes with them.  In
+ * particular, there can be implementations that don't actually get
+ * the spinlock for the common decrement/increment operations, but they
+ * still have to check that the operation is done semantically as if
+ * the spinlock had been taken (using a cmpxchg operation that covers
+ * both the lock and the count word, or using memory transactions, for
+ * example).
+ */
+
+#include <linux/spinlock.h>
+
+struct lockref {
+       union {
+#ifdef CONFIG_CMPXCHG_LOCKREF
+               aligned_u64 lock_count;
+#endif
+               struct {
+                       spinlock_t lock;
+                       unsigned int count;
+               };
+       };
+};
+
+extern void lockref_get(struct lockref *);
+extern int lockref_get_not_zero(struct lockref *);
+extern int lockref_get_or_lock(struct lockref *);
+extern int lockref_put_or_lock(struct lockref *);
+
+#endif /* __LINUX_LOCKREF_H */
index 10e5947..b4ec59d 100644 (file)
@@ -14,6 +14,10 @@ struct fs_struct;
  * A structure to contain pointers to all per-process
  * namespaces - fs (mount), uts, network, sysvipc, etc.
  *
+ * The pid namespace is an exception -- it's accessed using
+ * task_active_pid_ns.  The pid namespace here is the
+ * namespace that children will use.
+ *
  * 'count' is the number of tasks holding a reference.
  * The count for each namespace, then, will be the number
  * of nsproxies pointing to it, not the number of tasks.
@@ -27,7 +31,7 @@ struct nsproxy {
        struct uts_namespace *uts_ns;
        struct ipc_namespace *ipc_ns;
        struct mnt_namespace *mnt_ns;
-       struct pid_namespace *pid_ns;
+       struct pid_namespace *pid_ns_for_children;
        struct net           *net_ns;
 };
 extern struct nsproxy init_nsproxy;
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 580a532..a10380b 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/list.h>
 #include <linux/rbtree.h>
 #include <linux/err.h>
+#include <linux/bug.h>
 
 struct module;
 struct device;
@@ -471,6 +472,9 @@ struct regmap_irq {
  * @ack_base:    Base ack address.  If zero then the chip is clear on read.
  * @wake_base:   Base address for wake enables.  If zero unsupported.
  * @irq_reg_stride:  Stride to use for chips where registers are not contiguous.
+ * @init_ack_masked: Ack all masked interrupts once during initalization.
+ * @mask_invert: Inverted mask register: cleared bits are masked out.
+ * @wake_invert: Inverted wake register: cleared bits are wake enabled.
  * @runtime_pm:  Hold a runtime PM lock on the device when accessing it.
  *
  * @num_regs:    Number of registers in each control bank.
@@ -486,9 +490,10 @@ struct regmap_irq_chip {
        unsigned int ack_base;
        unsigned int wake_base;
        unsigned int irq_reg_stride;
-       unsigned int mask_invert;
-       unsigned int wake_invert;
-       bool runtime_pm;
+       bool init_ack_masked:1;
+       bool mask_invert:1;
+       bool wake_invert:1;
+       bool runtime_pm:1;
 
        int num_regs;
 
index 28e440b..887116d 100644 (file)
@@ -74,7 +74,7 @@ struct spi_device {
        struct spi_master       *master;
        u32                     max_speed_hz;
        u8                      chip_select;
-       u                     mode;
+       u16                     mode;
 #define        SPI_CPHA        0x01                    /* clock phase */
 #define        SPI_CPOL        0x02                    /* clock polarity */
 #define        SPI_MODE_0      (0|0)                   /* (original MicroWire) */
@@ -87,6 +87,10 @@ struct spi_device {
 #define        SPI_LOOP        0x20                    /* loopback mode */
 #define        SPI_NO_CS       0x40                    /* 1 dev/bus, no chipselect */
 #define        SPI_READY       0x80                    /* slave pulls low to pause */
+#define        SPI_TX_DUAL     0x100                   /* transmit with 2 wires */
+#define        SPI_TX_QUAD     0x200                   /* transmit with 4 wires */
+#define        SPI_RX_DUAL     0x400                   /* receive with 2 wires */
+#define        SPI_RX_QUAD     0x800                   /* receive with 4 wires */
        u8                      bits_per_word;
        int                     irq;
        void                    *controller_state;
@@ -233,6 +237,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
@@ -254,6 +260,9 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
  * @busy: message pump is busy
  * @running: message pump is running
  * @rt: whether this queue is set to run as a realtime task
+ * @auto_runtime_pm: the core should ensure a runtime PM reference is held
+ *                   while the hardware is prepared, using the parent
+ *                   device for the spidev
  * @prepare_transfer_hardware: a message will soon arrive from the queue
  *     so the subsystem requests the driver to prepare the transfer hardware
  *     by issuing this call
@@ -309,9 +318,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 */
@@ -374,11 +387,13 @@ struct spi_master {
        bool                            busy;
        bool                            running;
        bool                            rt;
+       bool                            auto_runtime_pm;
 
        int (*prepare_transfer_hardware)(struct spi_master *master);
        int (*transfer_one_message)(struct spi_master *master,
                                    struct spi_message *mesg);
        int (*unprepare_transfer_hardware)(struct spi_master *master);
+
        /* gpio chip select */
        int                     *cs_gpios;
 };
@@ -448,6 +463,10 @@ extern struct spi_master *spi_busnum_to_master(u16 busnum);
  * @rx_buf: data to be read (dma-safe memory), or NULL
  * @tx_dma: DMA address of tx_buf, if @spi_message.is_dma_mapped
  * @rx_dma: DMA address of rx_buf, if @spi_message.is_dma_mapped
+ * @tx_nbits: number of bits used for writting. If 0 the default
+ *      (SPI_NBITS_SINGLE) is used.
+ * @rx_nbits: number of bits used for reading. If 0 the default
+ *      (SPI_NBITS_SINGLE) is used.
  * @len: size of rx and tx buffers (in bytes)
  * @speed_hz: Select a speed other than the device default for this
  *      transfer. If 0 the default (from @spi_device) is used.
@@ -502,6 +521,11 @@ extern struct spi_master *spi_busnum_to_master(u16 busnum);
  * by the results of previous messages and where the whole transaction
  * ends when the chipselect goes intactive.
  *
+ * When SPI can transfer in 1x,2x or 4x. It can get this tranfer information
+ * from device through @tx_nbits and @rx_nbits. In Bi-direction, these
+ * two should both be set. User can set transfer mode with SPI_NBITS_SINGLE(1x)
+ * SPI_NBITS_DUAL(2x) and SPI_NBITS_QUAD(4x) to support these three transfer.
+ *
  * The code that submits an spi_message (and its spi_transfers)
  * to the lower layers is responsible for managing its memory.
  * Zero-initialize every field you don't set up explicitly, to
@@ -522,6 +546,11 @@ struct spi_transfer {
        dma_addr_t      rx_dma;
 
        unsigned        cs_change:1;
+       u8              tx_nbits;
+       u8              rx_nbits;
+#define        SPI_NBITS_SINGLE        0x01 /* 1bit transfer */
+#define        SPI_NBITS_DUAL          0x02 /* 2bits transfer */
+#define        SPI_NBITS_QUAD          0x04 /* 4bits transfer */
        u8              bits_per_word;
        u16             delay_usecs;
        u32             speed_hz;
@@ -578,6 +607,7 @@ struct spi_message {
        /* completion is reported through a callback */
        void                    (*complete)(void *context);
        void                    *context;
+       unsigned                frame_length;
        unsigned                actual_length;
        int                     status;
 
@@ -869,7 +899,7 @@ struct spi_board_info {
        /* mode becomes spi_device.mode, and is essential for chips
         * where the default of SPI_CS_HIGH = 0 is wrong.
         */
-       u             mode;
+       u16             mode;
 
        /* ... may need additional spi_device chip config data here.
         * avoid stuff protocol drivers can set; but include stuff
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 8a358a2..829627d 100644 (file)
@@ -123,6 +123,7 @@ static inline bool sk_busy_loop(struct sock *sk, int nonblock)
                        /* local bh are disabled so it is ok to use _BH */
                        NET_ADD_STATS_BH(sock_net(sk),
                                         LINUX_MIB_BUSYPOLLRXPACKETS, rc);
+               cpu_relax();
 
        } while (!nonblock && skb_queue_empty(&sk->sk_receive_queue) &&
                 !need_resched() && !busy_loop_timeout(end_time));
index 93024a4..8e0b6c8 100644 (file)
@@ -61,6 +61,7 @@ struct genl_family {
        struct list_head        ops_list;       /* private */
        struct list_head        family_list;    /* private */
        struct list_head        mcast_groups;   /* private */
+       struct module           *module;
 };
 
 /**
@@ -121,9 +122,24 @@ struct genl_ops {
        struct list_head        ops_list;
 };
 
-extern int genl_register_family(struct genl_family *family);
-extern int genl_register_family_with_ops(struct genl_family *family,
+extern int __genl_register_family(struct genl_family *family);
+
+static inline int genl_register_family(struct genl_family *family)
+{
+       family->module = THIS_MODULE;
+       return __genl_register_family(family);
+}
+
+extern int __genl_register_family_with_ops(struct genl_family *family,
        struct genl_ops *ops, size_t n_ops);
+
+static inline int genl_register_family_with_ops(struct genl_family *family,
+       struct genl_ops *ops, size_t n_ops)
+{
+       family->module = THIS_MODULE;
+       return __genl_register_family_with_ops(family, ops, n_ops);
+}
+
 extern int genl_unregister_family(struct genl_family *family);
 extern int genl_register_ops(struct genl_family *, struct genl_ops *ops);
 extern int genl_unregister_ops(struct genl_family *, struct genl_ops *ops);
index 5b7a3da..551ba6a 100644 (file)
@@ -1499,6 +1499,7 @@ enum ieee80211_hw_flags {
        IEEE80211_HW_SUPPORTS_RC_TABLE                  = 1<<24,
        IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF              = 1<<25,
        IEEE80211_HW_TIMING_BEACON_ONLY                 = 1<<26,
+       IEEE80211_HW_SUPPORTS_HT_CCK_RATES              = 1<<27,
 };
 
 /**
index 2ea40c1..afdeeb5 100644 (file)
@@ -317,4 +317,12 @@ static inline int ip4_dst_hoplimit(const struct dst_entry *dst)
        return hoplimit;
 }
 
+static inline int ip_skb_dst_mtu(struct sk_buff *skb)
+{
+       struct inet_sock *inet = skb->sk ? inet_sk(skb->sk) : NULL;
+
+       return (inet && inet->pmtudisc == IP_PMTUDISC_PROBE) ?
+              skb_dst(skb)->dev->mtu : dst_mtu(skb_dst(skb));
+}
+
 #endif /* _ROUTE_H */
index 94ce082..e823786 100644 (file)
@@ -341,10 +341,13 @@ struct xfrm_state_afinfo {
                                                  struct sk_buff *skb);
        int                     (*transport_finish)(struct sk_buff *skb,
                                                    int async);
+       void                    (*local_error)(struct sk_buff *skb, u32 mtu);
 };
 
 extern int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo);
 extern int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo);
+extern struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family);
+extern void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo);
 
 extern void xfrm_state_delete_tunnel(struct xfrm_state *x);
 
@@ -1477,6 +1480,7 @@ extern int xfrm_input_resume(struct sk_buff *skb, int nexthdr);
 extern int xfrm_output_resume(struct sk_buff *skb, int err);
 extern int xfrm_output(struct sk_buff *skb);
 extern int xfrm_inner_extract_output(struct xfrm_state *x, struct sk_buff *skb);
+extern void xfrm_local_error(struct sk_buff *skb, int mtu);
 extern int xfrm4_extract_header(struct sk_buff *skb);
 extern int xfrm4_extract_input(struct xfrm_state *x, struct sk_buff *skb);
 extern int xfrm4_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi,
@@ -1497,6 +1501,7 @@ extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short fam
 extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family);
 extern int xfrm4_mode_tunnel_input_register(struct xfrm_tunnel *handler);
 extern int xfrm4_mode_tunnel_input_deregister(struct xfrm_tunnel *handler);
+extern void xfrm4_local_error(struct sk_buff *skb, u32 mtu);
 extern int xfrm6_extract_header(struct sk_buff *skb);
 extern int xfrm6_extract_input(struct xfrm_state *x, struct sk_buff *skb);
 extern int xfrm6_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi);
@@ -1514,6 +1519,7 @@ extern int xfrm6_output(struct sk_buff *skb);
 extern int xfrm6_output_finish(struct sk_buff *skb);
 extern int xfrm6_find_1stfragopt(struct xfrm_state *x, struct sk_buff *skb,
                                 u8 **prevhdr);
+extern void xfrm6_local_error(struct sk_buff *skb, u32 mtu);
 
 #ifdef CONFIG_XFRM
 extern int xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb);
index bc51f77..1217f75 100644 (file)
@@ -2,6 +2,7 @@
 #define _UAPI_CM4000_H_
 
 #include <linux/types.h>
+#include <linux/ioctl.h>
 
 #define        MAX_ATR                 33
 
index bd60d7e..9f29d9e 100644 (file)
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -839,7 +839,7 @@ static inline void free_copy(struct msg_msg *copy)
 
 static struct msg_msg *find_msg(struct msg_queue *msq, long *msgtyp, int mode)
 {
-       struct msg_msg *msg;
+       struct msg_msg *msg, *found = NULL;
        long count = 0;
 
        list_for_each_entry(msg, &msq->q_messages, m_list) {
@@ -848,6 +848,7 @@ static struct msg_msg *find_msg(struct msg_queue *msq, long *msgtyp, int mode)
                                               *msgtyp, mode)) {
                        if (mode == SEARCH_LESSEQUAL && msg->m_type != 1) {
                                *msgtyp = msg->m_type - 1;
+                               found = msg;
                        } else if (mode == SEARCH_NUMBER) {
                                if (*msgtyp == count)
                                        return msg;
@@ -857,7 +858,7 @@ static struct msg_msg *find_msg(struct msg_queue *msq, long *msgtyp, int mode)
                }
        }
 
-       return ERR_PTR(-EAGAIN);
+       return found ?: ERR_PTR(-EAGAIN);
 }
 
 long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, int msgflg,
index 781845a..e919633 100644 (file)
@@ -4480,6 +4480,7 @@ static int cgroup_destroy_locked(struct cgroup *cgrp)
        struct dentry *d = cgrp->dentry;
        struct cgroup_event *event, *tmp;
        struct cgroup_subsys *ss;
+       struct cgroup *child;
        bool empty;
 
        lockdep_assert_held(&d->d_inode->i_mutex);
@@ -4490,11 +4491,27 @@ static int cgroup_destroy_locked(struct cgroup *cgrp)
         * @cgrp from being removed while __put_css_set() is in progress.
         */
        read_lock(&css_set_lock);
-       empty = list_empty(&cgrp->cset_links) && list_empty(&cgrp->children);
+       empty = list_empty(&cgrp->cset_links);
        read_unlock(&css_set_lock);
        if (!empty)
                return -EBUSY;
 
+       /*
+        * Make sure there's no live children.  We can't test ->children
+        * emptiness as dead children linger on it while being destroyed;
+        * otherwise, "rmdir parent/child parent" may fail with -EBUSY.
+        */
+       empty = true;
+       rcu_read_lock();
+       list_for_each_entry_rcu(child, &cgrp->children, sibling) {
+               empty = cgroup_is_dead(child);
+               if (!empty)
+                       break;
+       }
+       rcu_read_unlock();
+       if (!empty)
+               return -EBUSY;
+
        /*
         * Block new css_tryget() by killing css refcnts.  cgroup core
         * guarantees that, by the time ->css_offline() is invoked, no new
index e23bb19..bf46287 100644 (file)
@@ -1177,7 +1177,8 @@ static struct task_struct *copy_process(unsigned long clone_flags,
         * don't allow the creation of threads.
         */
        if ((clone_flags & (CLONE_VM|CLONE_NEWPID)) &&
-           (task_active_pid_ns(current) != current->nsproxy->pid_ns))
+           (task_active_pid_ns(current) !=
+            current->nsproxy->pid_ns_for_children))
                return ERR_PTR(-EINVAL);
 
        retval = security_task_create(clone_flags);
@@ -1351,7 +1352,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
 
        if (pid != &init_struct_pid) {
                retval = -ENOMEM;
-               pid = alloc_pid(p->nsproxy->pid_ns);
+               pid = alloc_pid(p->nsproxy->pid_ns_for_children);
                if (!pid)
                        goto bad_fork_cleanup_io;
        }
index 364ceab..997cbb9 100644 (file)
 static struct kmem_cache *nsproxy_cachep;
 
 struct nsproxy init_nsproxy = {
-       .count  = ATOMIC_INIT(1),
-       .uts_ns = &init_uts_ns,
+       .count                  = ATOMIC_INIT(1),
+       .uts_ns                 = &init_uts_ns,
 #if defined(CONFIG_POSIX_MQUEUE) || defined(CONFIG_SYSVIPC)
-       .ipc_ns = &init_ipc_ns,
+       .ipc_ns                 = &init_ipc_ns,
 #endif
-       .mnt_ns = NULL,
-       .pid_ns = &init_pid_ns,
+       .mnt_ns                 = NULL,
+       .pid_ns_for_children    = &init_pid_ns,
 #ifdef CONFIG_NET
-       .net_ns = &init_net,
+       .net_ns                 = &init_net,
 #endif
 };
 
@@ -85,9 +85,10 @@ static struct nsproxy *create_new_namespaces(unsigned long flags,
                goto out_ipc;
        }
 
-       new_nsp->pid_ns = copy_pid_ns(flags, user_ns, tsk->nsproxy->pid_ns);
-       if (IS_ERR(new_nsp->pid_ns)) {
-               err = PTR_ERR(new_nsp->pid_ns);
+       new_nsp->pid_ns_for_children =
+               copy_pid_ns(flags, user_ns, tsk->nsproxy->pid_ns_for_children);
+       if (IS_ERR(new_nsp->pid_ns_for_children)) {
+               err = PTR_ERR(new_nsp->pid_ns_for_children);
                goto out_pid;
        }
 
@@ -100,8 +101,8 @@ static struct nsproxy *create_new_namespaces(unsigned long flags,
        return new_nsp;
 
 out_net:
-       if (new_nsp->pid_ns)
-               put_pid_ns(new_nsp->pid_ns);
+       if (new_nsp->pid_ns_for_children)
+               put_pid_ns(new_nsp->pid_ns_for_children);
 out_pid:
        if (new_nsp->ipc_ns)
                put_ipc_ns(new_nsp->ipc_ns);
@@ -174,8 +175,8 @@ void free_nsproxy(struct nsproxy *ns)
                put_uts_ns(ns->uts_ns);
        if (ns->ipc_ns)
                put_ipc_ns(ns->ipc_ns);
-       if (ns->pid_ns)
-               put_pid_ns(ns->pid_ns);
+       if (ns->pid_ns_for_children)
+               put_pid_ns(ns->pid_ns_for_children);
        put_net(ns->net_ns);
        kmem_cache_free(nsproxy_cachep, ns);
 }
index 6917e8e..601bb36 100644 (file)
@@ -349,8 +349,8 @@ static int pidns_install(struct nsproxy *nsproxy, void *ns)
        if (ancestor != active)
                return -EINVAL;
 
-       put_pid_ns(nsproxy->pid_ns);
-       nsproxy->pid_ns = get_pid_ns(new);
+       put_pid_ns(nsproxy->pid_ns_for_children);
+       nsproxy->pid_ns_for_children = get_pid_ns(new);
        return 0;
 }
 
index 3bdf283..61ed862 100644 (file)
@@ -265,10 +265,9 @@ static inline void timer_list_header(struct seq_file *m, u64 now)
 static int timer_list_show(struct seq_file *m, void *v)
 {
        struct timer_list_iter *iter = v;
-       u64 now = ktime_to_ns(ktime_get());
 
        if (iter->cpu == -1 && !iter->second_pass)
-               timer_list_header(m, now);
+               timer_list_header(m, iter->now);
        else if (!iter->second_pass)
                print_cpu(m, iter->cpu, iter->now);
 #ifdef CONFIG_GENERIC_CLOCKEVENTS
@@ -298,33 +297,41 @@ void sysrq_timer_list_show(void)
        return;
 }
 
-static void *timer_list_start(struct seq_file *file, loff_t *offset)
+static void *move_iter(struct timer_list_iter *iter, loff_t offset)
 {
-       struct timer_list_iter *iter = file->private;
-
-       if (!*offset) {
-               iter->cpu = -1;
-               iter->now = ktime_to_ns(ktime_get());
-       } else if (iter->cpu >= nr_cpu_ids) {
+       for (; offset; offset--) {
+               iter->cpu = cpumask_next(iter->cpu, cpu_online_mask);
+               if (iter->cpu >= nr_cpu_ids) {
 #ifdef CONFIG_GENERIC_CLOCKEVENTS
-               if (!iter->second_pass) {
-                       iter->cpu = -1;
-                       iter->second_pass = true;
-               } else
-                       return NULL;
+                       if (!iter->second_pass) {
+                               iter->cpu = -1;
+                               iter->second_pass = true;
+                       } else
+                               return NULL;
 #else
-               return NULL;
+                       return NULL;
 #endif
+               }
        }
        return iter;
 }
 
+static void *timer_list_start(struct seq_file *file, loff_t *offset)
+{
+       struct timer_list_iter *iter = file->private;
+
+       if (!*offset)
+               iter->now = ktime_to_ns(ktime_get());
+       iter->cpu = -1;
+       iter->second_pass = false;
+       return move_iter(iter, *offset);
+}
+
 static void *timer_list_next(struct seq_file *file, void *v, loff_t *offset)
 {
        struct timer_list_iter *iter = file->private;
-       iter->cpu = cpumask_next(iter->cpu, cpu_online_mask);
        ++*offset;
-       return timer_list_start(file, offset);
+       return move_iter(iter, 1);
 }
 
 static void timer_list_stop(struct seq_file *seq, void *v)
index 7f5d4be..e93f7b9 100644 (file)
@@ -2201,6 +2201,15 @@ __acquires(&pool->lock)
                dump_stack();
        }
 
+       /*
+        * The following prevents a kworker from hogging CPU on !PREEMPT
+        * kernels, where a requeueing work item waiting for something to
+        * happen could deadlock with stop_machine as such work item could
+        * indefinitely requeue itself while all other CPUs are trapped in
+        * stop_machine.
+        */
+       cond_resched();
+
        spin_lock_irq(&pool->lock);
 
        /* clear cpu intensive status */
index 71d9f81..6556171 100644 (file)
@@ -48,6 +48,16 @@ config STMP_DEVICE
 config PERCPU_RWSEM
        boolean
 
+config ARCH_USE_CMPXCHG_LOCKREF
+       bool
+
+config CMPXCHG_LOCKREF
+       def_bool y if ARCH_USE_CMPXCHG_LOCKREF
+       depends on SMP
+       depends on !GENERIC_LOCKBREAK
+       depends on !DEBUG_SPINLOCK
+       depends on !DEBUG_LOCK_ALLOC
+
 config CRC_CCITT
        tristate "CRC-CCITT functions"
        help
index 7baccfd..f2cb308 100644 (file)
@@ -20,6 +20,7 @@ lib-$(CONFIG_MMU) += ioremap.o
 lib-$(CONFIG_SMP) += cpumask.o
 
 lib-y  += kobject.o klist.o
+obj-y  += lockref.o
 
 obj-y += bcd.o div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \
         bust_spinlocks.o hexdump.o kasprintf.o bitmap.o scatterlist.o \
diff --git a/lib/lockref.c b/lib/lockref.c
new file mode 100644 (file)
index 0000000..7819c2d
--- /dev/null
@@ -0,0 +1,127 @@
+#include <linux/export.h>
+#include <linux/lockref.h>
+
+#ifdef CONFIG_CMPXCHG_LOCKREF
+
+/*
+ * Note that the "cmpxchg()" reloads the "old" value for the
+ * failure case.
+ */
+#define CMPXCHG_LOOP(CODE, SUCCESS) do {                                       \
+       struct lockref old;                                                     \
+       BUILD_BUG_ON(sizeof(old) != 8);                                         \
+       old.lock_count = ACCESS_ONCE(lockref->lock_count);                      \
+       while (likely(arch_spin_value_unlocked(old.lock.rlock.raw_lock))) {     \
+               struct lockref new = old, prev = old;                           \
+               CODE                                                            \
+               old.lock_count = cmpxchg(&lockref->lock_count,                  \
+                                        old.lock_count, new.lock_count);       \
+               if (likely(old.lock_count == prev.lock_count)) {                \
+                       SUCCESS;                                                \
+               }                                                               \
+       }                                                                       \
+} while (0)
+
+#else
+
+#define CMPXCHG_LOOP(CODE, SUCCESS) do { } while (0)
+
+#endif
+
+/**
+ * lockref_get - Increments reference count unconditionally
+ * @lockcnt: pointer to lockref structure
+ *
+ * This operation is only valid if you already hold a reference
+ * to the object, so you know the count cannot be zero.
+ */
+void lockref_get(struct lockref *lockref)
+{
+       CMPXCHG_LOOP(
+               new.count++;
+       ,
+               return;
+       );
+
+       spin_lock(&lockref->lock);
+       lockref->count++;
+       spin_unlock(&lockref->lock);
+}
+EXPORT_SYMBOL(lockref_get);
+
+/**
+ * lockref_get_not_zero - Increments count unless the count is 0
+ * @lockcnt: pointer to lockref structure
+ * Return: 1 if count updated successfully or 0 if count was zero
+ */
+int lockref_get_not_zero(struct lockref *lockref)
+{
+       int retval;
+
+       CMPXCHG_LOOP(
+               new.count++;
+               if (!old.count)
+                       return 0;
+       ,
+               return 1;
+       );
+
+       spin_lock(&lockref->lock);
+       retval = 0;
+       if (lockref->count) {
+               lockref->count++;
+               retval = 1;
+       }
+       spin_unlock(&lockref->lock);
+       return retval;
+}
+EXPORT_SYMBOL(lockref_get_not_zero);
+
+/**
+ * lockref_get_or_lock - Increments count unless the count is 0
+ * @lockcnt: pointer to lockref structure
+ * Return: 1 if count updated successfully or 0 if count was zero
+ * and we got the lock instead.
+ */
+int lockref_get_or_lock(struct lockref *lockref)
+{
+       CMPXCHG_LOOP(
+               new.count++;
+               if (!old.count)
+                       break;
+       ,
+               return 1;
+       );
+
+       spin_lock(&lockref->lock);
+       if (!lockref->count)
+               return 0;
+       lockref->count++;
+       spin_unlock(&lockref->lock);
+       return 1;
+}
+EXPORT_SYMBOL(lockref_get_or_lock);
+
+/**
+ * lockref_put_or_lock - decrements count unless count <= 1 before decrement
+ * @lockcnt: pointer to lockref structure
+ * Return: 1 if count updated successfully or 0 if count <= 1 and lock taken
+ */
+int lockref_put_or_lock(struct lockref *lockref)
+{
+       CMPXCHG_LOOP(
+               new.count--;
+               if (old.count <= 1)
+                       break;
+       ,
+               return 1;
+       );
+
+       spin_lock(&lockref->lock);
+       if (lockref->count <= 1)
+               return 0;
+       lockref->count--;
+       spin_unlock(&lockref->lock);
+       return 1;
+}
+EXPORT_SYMBOL(lockref_put_or_lock);
index 457d34e..0843feb 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/swap.h>
 #include <linux/capability.h>
 #include <linux/fs.h>
+#include <linux/swapops.h>
 #include <linux/highmem.h>
 #include <linux/security.h>
 #include <linux/syscalls.h>
@@ -69,6 +70,23 @@ static pmd_t *alloc_new_pmd(struct mm_struct *mm, struct vm_area_struct *vma,
        return pmd;
 }
 
+static pte_t move_soft_dirty_pte(pte_t pte)
+{
+       /*
+        * Set soft dirty bit so we can notice
+        * in userspace the ptes were moved.
+        */
+#ifdef CONFIG_MEM_SOFT_DIRTY
+       if (pte_present(pte))
+               pte = pte_mksoft_dirty(pte);
+       else if (is_swap_pte(pte))
+               pte = pte_swp_mksoft_dirty(pte);
+       else if (pte_file(pte))
+               pte = pte_file_mksoft_dirty(pte);
+#endif
+       return pte;
+}
+
 static void move_ptes(struct vm_area_struct *vma, pmd_t *old_pmd,
                unsigned long old_addr, unsigned long old_end,
                struct vm_area_struct *new_vma, pmd_t *new_pmd,
@@ -126,7 +144,8 @@ static void move_ptes(struct vm_area_struct *vma, pmd_t *old_pmd,
                        continue;
                pte = ptep_get_and_clear(mm, old_addr, old_pte);
                pte = move_pte(pte, new_vma->vm_page_prot, old_addr, new_addr);
-               set_pte_at(mm, new_addr, new_pte, pte_mksoft_dirty(pte));
+               pte = move_soft_dirty_pte(pte);
+               set_pte_at(mm, new_addr, new_pte, pte);
        }
 
        arch_leave_lazy_mmu_mode();
index 620ceed..a535033 100644 (file)
--- a/mm/slab.h
+++ b/mm/slab.h
@@ -162,6 +162,8 @@ static inline const char *cache_name(struct kmem_cache *s)
 
 static inline struct kmem_cache *cache_from_memcg(struct kmem_cache *s, int idx)
 {
+       if (!s->memcg_params)
+               return NULL;
        return s->memcg_params->memcg_caches[idx];
 }
 
index 69363bd..89659d4 100644 (file)
@@ -71,7 +71,7 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
 
                mdst = br_mdb_get(br, skb, vid);
                if ((mdst || BR_INPUT_SKB_CB_MROUTERS_ONLY(skb)) &&
-                   br_multicast_querier_exists(br))
+                   br_multicast_querier_exists(br, eth_hdr(skb)))
                        br_multicast_deliver(mdst, skb);
                else
                        br_flood_deliver(br, skb, false);
index 8c561c0..a2fd37e 100644 (file)
@@ -102,7 +102,7 @@ int br_handle_frame_finish(struct sk_buff *skb)
        } else if (is_multicast_ether_addr(dest)) {
                mdst = br_mdb_get(br, skb, vid);
                if ((mdst || BR_INPUT_SKB_CB_MROUTERS_ONLY(skb)) &&
-                   br_multicast_querier_exists(br)) {
+                   br_multicast_querier_exists(br, eth_hdr(skb))) {
                        if ((mdst && mdst->mglist) ||
                            br_multicast_is_router(br))
                                skb2 = skb;
index 0daae3e..6319c43 100644 (file)
@@ -414,16 +414,20 @@ static int __br_mdb_del(struct net_bridge *br, struct br_mdb_entry *entry)
        if (!netif_running(br->dev) || br->multicast_disabled)
                return -EINVAL;
 
-       if (timer_pending(&br->multicast_querier_timer))
-               return -EBUSY;
-
        ip.proto = entry->addr.proto;
-       if (ip.proto == htons(ETH_P_IP))
+       if (ip.proto == htons(ETH_P_IP)) {
+               if (timer_pending(&br->ip4_querier.timer))
+                       return -EBUSY;
+
                ip.u.ip4 = entry->addr.u.ip4;
 #if IS_ENABLED(CONFIG_IPV6)
-       else
+       } else {
+               if (timer_pending(&br->ip6_querier.timer))
+                       return -EBUSY;
+
                ip.u.ip6 = entry->addr.u.ip6;
 #endif
+       }
 
        spin_lock_bh(&br->multicast_lock);
        mdb = mlock_dereference(br->mdb, br);
index 08e576a..bbcb435 100644 (file)
@@ -33,7 +33,8 @@
 
 #include "br_private.h"
 
-static void br_multicast_start_querier(struct net_bridge *br);
+static void br_multicast_start_querier(struct net_bridge *br,
+                                      struct bridge_mcast_query *query);
 unsigned int br_mdb_rehash_seq;
 
 static inline int br_ip_equal(const struct br_ip *a, const struct br_ip *b)
@@ -755,20 +756,35 @@ static void br_multicast_local_router_expired(unsigned long data)
 {
 }
 
-static void br_multicast_querier_expired(unsigned long data)
+static void br_multicast_querier_expired(struct net_bridge *br,
+                                        struct bridge_mcast_query *query)
 {
-       struct net_bridge *br = (void *)data;
-
        spin_lock(&br->multicast_lock);
        if (!netif_running(br->dev) || br->multicast_disabled)
                goto out;
 
-       br_multicast_start_querier(br);
+       br_multicast_start_querier(br, query);
 
 out:
        spin_unlock(&br->multicast_lock);
 }
 
+static void br_ip4_multicast_querier_expired(unsigned long data)
+{
+       struct net_bridge *br = (void *)data;
+
+       br_multicast_querier_expired(br, &br->ip4_query);
+}
+
+#if IS_ENABLED(CONFIG_IPV6)
+static void br_ip6_multicast_querier_expired(unsigned long data)
+{
+       struct net_bridge *br = (void *)data;
+
+       br_multicast_querier_expired(br, &br->ip6_query);
+}
+#endif
+
 static void __br_multicast_send_query(struct net_bridge *br,
                                      struct net_bridge_port *port,
                                      struct br_ip *ip)
@@ -789,37 +805,45 @@ static void __br_multicast_send_query(struct net_bridge *br,
 }
 
 static void br_multicast_send_query(struct net_bridge *br,
-                                   struct net_bridge_port *port, u32 sent)
+                                   struct net_bridge_port *port,
+                                   struct bridge_mcast_query *query)
 {
        unsigned long time;
        struct br_ip br_group;
+       struct bridge_mcast_querier *querier = NULL;
 
        if (!netif_running(br->dev) || br->multicast_disabled ||
-           !br->multicast_querier ||
-           timer_pending(&br->multicast_querier_timer))
+           !br->multicast_querier)
                return;
 
        memset(&br_group.u, 0, sizeof(br_group.u));
 
-       br_group.proto = htons(ETH_P_IP);
-       __br_multicast_send_query(br, port, &br_group);
-
+       if (port ? (query == &port->ip4_query) :
+                  (query == &br->ip4_query)) {
+               querier = &br->ip4_querier;
+               br_group.proto = htons(ETH_P_IP);
 #if IS_ENABLED(CONFIG_IPV6)
-       br_group.proto = htons(ETH_P_IPV6);
-       __br_multicast_send_query(br, port, &br_group);
+       } else {
+               querier = &br->ip6_querier;
+               br_group.proto = htons(ETH_P_IPV6);
 #endif
+       }
+
+       if (!querier || timer_pending(&querier->timer))
+               return;
+
+       __br_multicast_send_query(br, port, &br_group);
 
        time = jiffies;
-       time += sent < br->multicast_startup_query_count ?
+       time += query->startup_sent < br->multicast_startup_query_count ?
                br->multicast_startup_query_interval :
                br->multicast_query_interval;
-       mod_timer(port ? &port->multicast_query_timer :
-                        &br->multicast_query_timer, time);
+       mod_timer(&query->timer, time);
 }
 
-static void br_multicast_port_query_expired(unsigned long data)
+static void br_multicast_port_query_expired(struct net_bridge_port *port,
+                                           struct bridge_mcast_query *query)
 {
-       struct net_bridge_port *port = (void *)data;
        struct net_bridge *br = port->br;
 
        spin_lock(&br->multicast_lock);
@@ -827,25 +851,43 @@ static void br_multicast_port_query_expired(unsigned long data)
            port->state == BR_STATE_BLOCKING)
                goto out;
 
-       if (port->multicast_startup_queries_sent <
-           br->multicast_startup_query_count)
-               port->multicast_startup_queries_sent++;
+       if (query->startup_sent < br->multicast_startup_query_count)
+               query->startup_sent++;
 
-       br_multicast_send_query(port->br, port,
-                               port->multicast_startup_queries_sent);
+       br_multicast_send_query(port->br, port, query);
 
 out:
        spin_unlock(&br->multicast_lock);
 }
 
+static void br_ip4_multicast_port_query_expired(unsigned long data)
+{
+       struct net_bridge_port *port = (void *)data;
+
+       br_multicast_port_query_expired(port, &port->ip4_query);
+}
+
+#if IS_ENABLED(CONFIG_IPV6)
+static void br_ip6_multicast_port_query_expired(unsigned long data)
+{
+       struct net_bridge_port *port = (void *)data;
+
+       br_multicast_port_query_expired(port, &port->ip6_query);
+}
+#endif
+
 void br_multicast_add_port(struct net_bridge_port *port)
 {
        port->multicast_router = 1;
 
        setup_timer(&port->multicast_router_timer, br_multicast_router_expired,
                    (unsigned long)port);
-       setup_timer(&port->multicast_query_timer,
-                   br_multicast_port_query_expired, (unsigned long)port);
+       setup_timer(&port->ip4_query.timer, br_ip4_multicast_port_query_expired,
+                   (unsigned long)port);
+#if IS_ENABLED(CONFIG_IPV6)
+       setup_timer(&port->ip6_query.timer, br_ip6_multicast_port_query_expired,
+                   (unsigned long)port);
+#endif
 }
 
 void br_multicast_del_port(struct net_bridge_port *port)
@@ -853,13 +895,13 @@ void br_multicast_del_port(struct net_bridge_port *port)
        del_timer_sync(&port->multicast_router_timer);
 }
 
-static void __br_multicast_enable_port(struct net_bridge_port *port)
+static void br_multicast_enable(struct bridge_mcast_query *query)
 {
-       port->multicast_startup_queries_sent = 0;
+       query->startup_sent = 0;
 
-       if (try_to_del_timer_sync(&port->multicast_query_timer) >= 0 ||
-           del_timer(&port->multicast_query_timer))
-               mod_timer(&port->multicast_query_timer, jiffies);
+       if (try_to_del_timer_sync(&query->timer) >= 0 ||
+           del_timer(&query->timer))
+               mod_timer(&query->timer, jiffies);
 }
 
 void br_multicast_enable_port(struct net_bridge_port *port)
@@ -870,7 +912,10 @@ void br_multicast_enable_port(struct net_bridge_port *port)
        if (br->multicast_disabled || !netif_running(br->dev))
                goto out;
 
-       __br_multicast_enable_port(port);
+       br_multicast_enable(&port->ip4_query);
+#if IS_ENABLED(CONFIG_IPV6)
+       br_multicast_enable(&port->ip6_query);
+#endif
 
 out:
        spin_unlock(&br->multicast_lock);
@@ -889,7 +934,10 @@ void br_multicast_disable_port(struct net_bridge_port *port)
        if (!hlist_unhashed(&port->rlist))
                hlist_del_init_rcu(&port->rlist);
        del_timer(&port->multicast_router_timer);
-       del_timer(&port->multicast_query_timer);
+       del_timer(&port->ip4_query.timer);
+#if IS_ENABLED(CONFIG_IPV6)
+       del_timer(&port->ip6_query.timer);
+#endif
        spin_unlock(&br->multicast_lock);
 }
 
@@ -1014,14 +1062,15 @@ static int br_ip6_multicast_mld2_report(struct net_bridge *br,
 }
 #endif
 
-static void br_multicast_update_querier_timer(struct net_bridge *br,
-                                             unsigned long max_delay)
+static void
+br_multicast_update_querier_timer(struct net_bridge *br,
+                                 struct bridge_mcast_querier *querier,
+                                 unsigned long max_delay)
 {
-       if (!timer_pending(&br->multicast_querier_timer))
-               br->multicast_querier_delay_time = jiffies + max_delay;
+       if (!timer_pending(&querier->timer))
+               querier->delay_time = jiffies + max_delay;
 
-       mod_timer(&br->multicast_querier_timer,
-                 jiffies + br->multicast_querier_interval);
+       mod_timer(&querier->timer, jiffies + br->multicast_querier_interval);
 }
 
 /*
@@ -1074,12 +1123,13 @@ timer:
 
 static void br_multicast_query_received(struct net_bridge *br,
                                        struct net_bridge_port *port,
+                                       struct bridge_mcast_querier *querier,
                                        int saddr,
                                        unsigned long max_delay)
 {
        if (saddr)
-               br_multicast_update_querier_timer(br, max_delay);
-       else if (timer_pending(&br->multicast_querier_timer))
+               br_multicast_update_querier_timer(br, querier, max_delay);
+       else if (timer_pending(&querier->timer))
                return;
 
        br_multicast_mark_router(br, port);
@@ -1129,7 +1179,8 @@ static int br_ip4_multicast_query(struct net_bridge *br,
                            IGMPV3_MRC(ih3->code) * (HZ / IGMP_TIMER_SCALE) : 1;
        }
 
-       br_multicast_query_received(br, port, !!iph->saddr, max_delay);
+       br_multicast_query_received(br, port, &br->ip4_querier, !!iph->saddr,
+                                   max_delay);
 
        if (!group)
                goto out;
@@ -1203,11 +1254,12 @@ static int br_ip6_multicast_query(struct net_bridge *br,
                mld2q = (struct mld2_query *)icmp6_hdr(skb);
                if (!mld2q->mld2q_nsrcs)
                        group = &mld2q->mld2q_mca;
-               max_delay = mld2q->mld2q_mrc ? MLDV2_MRC(ntohs(mld2q->mld2q_mrc)) : 1;
+
+               max_delay = max(msecs_to_jiffies(MLDV2_MRC(ntohs(mld2q->mld2q_mrc))), 1UL);
        }
 
-       br_multicast_query_received(br, port, !ipv6_addr_any(&ip6h->saddr),
-                                   max_delay);
+       br_multicast_query_received(br, port, &br->ip6_querier,
+                                   !ipv6_addr_any(&ip6h->saddr), max_delay);
 
        if (!group)
                goto out;
@@ -1244,7 +1296,9 @@ out:
 
 static void br_multicast_leave_group(struct net_bridge *br,
                                     struct net_bridge_port *port,
-                                    struct br_ip *group)
+                                    struct br_ip *group,
+                                    struct bridge_mcast_querier *querier,
+                                    struct bridge_mcast_query *query)
 {
        struct net_bridge_mdb_htable *mdb;
        struct net_bridge_mdb_entry *mp;
@@ -1255,7 +1309,7 @@ static void br_multicast_leave_group(struct net_bridge *br,
        spin_lock(&br->multicast_lock);
        if (!netif_running(br->dev) ||
            (port && port->state == BR_STATE_DISABLED) ||
-           timer_pending(&br->multicast_querier_timer))
+           timer_pending(&querier->timer))
                goto out;
 
        mdb = mlock_dereference(br->mdb, br);
@@ -1263,14 +1317,13 @@ static void br_multicast_leave_group(struct net_bridge *br,
        if (!mp)
                goto out;
 
-       if (br->multicast_querier &&
-           !timer_pending(&br->multicast_querier_timer)) {
+       if (br->multicast_querier) {
                __br_multicast_send_query(br, port, &mp->addr);
 
                time = jiffies + br->multicast_last_member_count *
                                 br->multicast_last_member_interval;
-               mod_timer(port ? &port->multicast_query_timer :
-                                &br->multicast_query_timer, time);
+
+               mod_timer(&query->timer, time);
 
                for (p = mlock_dereference(mp->ports, br);
                     p != NULL;
@@ -1323,7 +1376,6 @@ static void br_multicast_leave_group(struct net_bridge *br,
                        mod_timer(&mp->timer, time);
                }
        }
-
 out:
        spin_unlock(&br->multicast_lock);
 }
@@ -1334,6 +1386,8 @@ static void br_ip4_multicast_leave_group(struct net_bridge *br,
                                         __u16 vid)
 {
        struct br_ip br_group;
+       struct bridge_mcast_query *query = port ? &port->ip4_query :
+                                                 &br->ip4_query;
 
        if (ipv4_is_local_multicast(group))
                return;
@@ -1342,7 +1396,7 @@ static void br_ip4_multicast_leave_group(struct net_bridge *br,
        br_group.proto = htons(ETH_P_IP);
        br_group.vid = vid;
 
-       br_multicast_leave_group(br, port, &br_group);
+       br_multicast_leave_group(br, port, &br_group, &br->ip4_querier, query);
 }
 
 #if IS_ENABLED(CONFIG_IPV6)
@@ -1352,6 +1406,9 @@ static void br_ip6_multicast_leave_group(struct net_bridge *br,
                                         __u16 vid)
 {
        struct br_ip br_group;
+       struct bridge_mcast_query *query = port ? &port->ip6_query :
+                                                 &br->ip6_query;
+
 
        if (!ipv6_is_transient_multicast(group))
                return;
@@ -1360,7 +1417,7 @@ static void br_ip6_multicast_leave_group(struct net_bridge *br,
        br_group.proto = htons(ETH_P_IPV6);
        br_group.vid = vid;
 
-       br_multicast_leave_group(br, port, &br_group);
+       br_multicast_leave_group(br, port, &br_group, &br->ip6_querier, query);
 }
 #endif
 
@@ -1622,19 +1679,32 @@ int br_multicast_rcv(struct net_bridge *br, struct net_bridge_port *port,
        return 0;
 }
 
-static void br_multicast_query_expired(unsigned long data)
+static void br_multicast_query_expired(struct net_bridge *br,
+                                      struct bridge_mcast_query *query)
+{
+       spin_lock(&br->multicast_lock);
+       if (query->startup_sent < br->multicast_startup_query_count)
+               query->startup_sent++;
+
+       br_multicast_send_query(br, NULL, query);
+       spin_unlock(&br->multicast_lock);
+}
+
+static void br_ip4_multicast_query_expired(unsigned long data)
 {
        struct net_bridge *br = (void *)data;
 
-       spin_lock(&br->multicast_lock);
-       if (br->multicast_startup_queries_sent <
-           br->multicast_startup_query_count)
-               br->multicast_startup_queries_sent++;
+       br_multicast_query_expired(br, &br->ip4_query);
+}
 
-       br_multicast_send_query(br, NULL, br->multicast_startup_queries_sent);
+#if IS_ENABLED(CONFIG_IPV6)
+static void br_ip6_multicast_query_expired(unsigned long data)
+{
+       struct net_bridge *br = (void *)data;
 
-       spin_unlock(&br->multicast_lock);
+       br_multicast_query_expired(br, &br->ip6_query);
 }
+#endif
 
 void br_multicast_init(struct net_bridge *br)
 {
@@ -1654,25 +1724,43 @@ void br_multicast_init(struct net_bridge *br)
        br->multicast_querier_interval = 255 * HZ;
        br->multicast_membership_interval = 260 * HZ;
 
-       br->multicast_querier_delay_time = 0;
+       br->ip4_querier.delay_time = 0;
+#if IS_ENABLED(CONFIG_IPV6)
+       br->ip6_querier.delay_time = 0;
+#endif
 
        spin_lock_init(&br->multicast_lock);
        setup_timer(&br->multicast_router_timer,
                    br_multicast_local_router_expired, 0);
-       setup_timer(&br->multicast_querier_timer,
-                   br_multicast_querier_expired, (unsigned long)br);
-       setup_timer(&br->multicast_query_timer, br_multicast_query_expired,
+       setup_timer(&br->ip4_querier.timer, br_ip4_multicast_querier_expired,
+                   (unsigned long)br);
+       setup_timer(&br->ip4_query.timer, br_ip4_multicast_query_expired,
                    (unsigned long)br);
+#if IS_ENABLED(CONFIG_IPV6)
+       setup_timer(&br->ip6_querier.timer, br_ip6_multicast_querier_expired,
+                   (unsigned long)br);
+       setup_timer(&br->ip6_query.timer, br_ip6_multicast_query_expired,
+                   (unsigned long)br);
+#endif
 }
 
-void br_multicast_open(struct net_bridge *br)
+static void __br_multicast_open(struct net_bridge *br,
+                               struct bridge_mcast_query *query)
 {
-       br->multicast_startup_queries_sent = 0;
+       query->startup_sent = 0;
 
        if (br->multicast_disabled)
                return;
 
-       mod_timer(&br->multicast_query_timer, jiffies);
+       mod_timer(&query->timer, jiffies);
+}
+
+void br_multicast_open(struct net_bridge *br)
+{
+       __br_multicast_open(br, &br->ip4_query);
+#if IS_ENABLED(CONFIG_IPV6)
+       __br_multicast_open(br, &br->ip6_query);
+#endif
 }
 
 void br_multicast_stop(struct net_bridge *br)
@@ -1684,8 +1772,12 @@ void br_multicast_stop(struct net_bridge *br)
        int i;
 
        del_timer_sync(&br->multicast_router_timer);
-       del_timer_sync(&br->multicast_querier_timer);
-       del_timer_sync(&br->multicast_query_timer);
+       del_timer_sync(&br->ip4_querier.timer);
+       del_timer_sync(&br->ip4_query.timer);
+#if IS_ENABLED(CONFIG_IPV6)
+       del_timer_sync(&br->ip6_querier.timer);
+       del_timer_sync(&br->ip6_query.timer);
+#endif
 
        spin_lock_bh(&br->multicast_lock);
        mdb = mlock_dereference(br->mdb, br);
@@ -1788,18 +1880,24 @@ unlock:
        return err;
 }
 
-static void br_multicast_start_querier(struct net_bridge *br)
+static void br_multicast_start_querier(struct net_bridge *br,
+                                      struct bridge_mcast_query *query)
 {
        struct net_bridge_port *port;
 
-       br_multicast_open(br);
+       __br_multicast_open(br, query);
 
        list_for_each_entry(port, &br->port_list, list) {
                if (port->state == BR_STATE_DISABLED ||
                    port->state == BR_STATE_BLOCKING)
                        continue;
 
-               __br_multicast_enable_port(port);
+               if (query == &br->ip4_query)
+                       br_multicast_enable(&port->ip4_query);
+#if IS_ENABLED(CONFIG_IPV6)
+               else
+                       br_multicast_enable(&port->ip6_query);
+#endif
        }
 }
 
@@ -1834,7 +1932,10 @@ rollback:
                        goto rollback;
        }
 
-       br_multicast_start_querier(br);
+       br_multicast_start_querier(br, &br->ip4_query);
+#if IS_ENABLED(CONFIG_IPV6)
+       br_multicast_start_querier(br, &br->ip6_query);
+#endif
 
 unlock:
        spin_unlock_bh(&br->multicast_lock);
@@ -1857,10 +1958,18 @@ int br_multicast_set_querier(struct net_bridge *br, unsigned long val)
                goto unlock;
 
        max_delay = br->multicast_query_response_interval;
-       if (!timer_pending(&br->multicast_querier_timer))
-               br->multicast_querier_delay_time = jiffies + max_delay;
 
-       br_multicast_start_querier(br);
+       if (!timer_pending(&br->ip4_querier.timer))
+               br->ip4_querier.delay_time = jiffies + max_delay;
+
+       br_multicast_start_querier(br, &br->ip4_query);
+
+#if IS_ENABLED(CONFIG_IPV6)
+       if (!timer_pending(&br->ip6_querier.timer))
+               br->ip6_querier.delay_time = jiffies + max_delay;
+
+       br_multicast_start_querier(br, &br->ip6_query);
+#endif
 
 unlock:
        spin_unlock_bh(&br->multicast_lock);
index 2f7da41..263ba90 100644 (file)
@@ -66,6 +66,20 @@ struct br_ip
        __u16           vid;
 };
 
+#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
+/* our own querier */
+struct bridge_mcast_query {
+       struct timer_list       timer;
+       u32                     startup_sent;
+};
+
+/* other querier */
+struct bridge_mcast_querier {
+       struct timer_list               timer;
+       unsigned long                   delay_time;
+};
+#endif
+
 struct net_port_vlans {
        u16                             port_idx;
        u16                             pvid;
@@ -162,10 +176,12 @@ struct net_bridge_port
 #define BR_FLOOD               0x00000040
 
 #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
-       u32                             multicast_startup_queries_sent;
+       struct bridge_mcast_query       ip4_query;
+#if IS_ENABLED(CONFIG_IPV6)
+       struct bridge_mcast_query       ip6_query;
+#endif /* IS_ENABLED(CONFIG_IPV6) */
        unsigned char                   multicast_router;
        struct timer_list               multicast_router_timer;
-       struct timer_list               multicast_query_timer;
        struct hlist_head               mglist;
        struct hlist_node               rlist;
 #endif
@@ -258,7 +274,6 @@ struct net_bridge
        u32                             hash_max;
 
        u32                             multicast_last_member_count;
-       u32                             multicast_startup_queries_sent;
        u32                             multicast_startup_query_count;
 
        unsigned long                   multicast_last_member_interval;
@@ -267,15 +282,18 @@ struct net_bridge
        unsigned long                   multicast_query_interval;
        unsigned long                   multicast_query_response_interval;
        unsigned long                   multicast_startup_query_interval;
-       unsigned long                   multicast_querier_delay_time;
 
        spinlock_t                      multicast_lock;
        struct net_bridge_mdb_htable __rcu *mdb;
        struct hlist_head               router_list;
 
        struct timer_list               multicast_router_timer;
-       struct timer_list               multicast_querier_timer;
-       struct timer_list               multicast_query_timer;
+       struct bridge_mcast_querier     ip4_querier;
+       struct bridge_mcast_query       ip4_query;
+#if IS_ENABLED(CONFIG_IPV6)
+       struct bridge_mcast_querier     ip6_querier;
+       struct bridge_mcast_query       ip6_query;
+#endif /* IS_ENABLED(CONFIG_IPV6) */
 #endif
 
        struct timer_list               hello_timer;
@@ -503,11 +521,27 @@ static inline bool br_multicast_is_router(struct net_bridge *br)
                timer_pending(&br->multicast_router_timer));
 }
 
-static inline bool br_multicast_querier_exists(struct net_bridge *br)
+static inline bool
+__br_multicast_querier_exists(struct net_bridge *br,
+                             struct bridge_mcast_querier *querier)
+{
+       return time_is_before_jiffies(querier->delay_time) &&
+              (br->multicast_querier || timer_pending(&querier->timer));
+}
+
+static inline bool br_multicast_querier_exists(struct net_bridge *br,
+                                              struct ethhdr *eth)
 {
-       return time_is_before_jiffies(br->multicast_querier_delay_time) &&
-              (br->multicast_querier ||
-               timer_pending(&br->multicast_querier_timer));
+       switch (eth->h_proto) {
+       case (htons(ETH_P_IP)):
+               return __br_multicast_querier_exists(br, &br->ip4_querier);
+#if IS_ENABLED(CONFIG_IPV6)
+       case (htons(ETH_P_IPV6)):
+               return __br_multicast_querier_exists(br, &br->ip6_querier);
+#endif
+       default:
+               return false;
+       }
 }
 #else
 static inline int br_multicast_rcv(struct net_bridge *br,
@@ -565,7 +599,8 @@ static inline bool br_multicast_is_router(struct net_bridge *br)
 {
        return 0;
 }
-static inline bool br_multicast_querier_exists(struct net_bridge *br)
+static inline bool br_multicast_querier_exists(struct net_bridge *br,
+                                              struct ethhdr *eth)
 {
        return false;
 }
index b84a1b1..d12e3a9 100644 (file)
@@ -346,14 +346,9 @@ u16 __netdev_pick_tx(struct net_device *dev, struct sk_buff *skb)
                if (new_index < 0)
                        new_index = skb_tx_hash(dev, skb);
 
-               if (queue_index != new_index && sk) {
-                       struct dst_entry *dst =
-                                   rcu_dereference_check(sk->sk_dst_cache, 1);
-
-                       if (dst && skb_dst(skb) == dst)
-                               sk_tx_queue_set(sk, queue_index);
-
-               }
+               if (queue_index != new_index && sk &&
+                   rcu_access_pointer(sk->sk_dst_cache))
+                       sk_tx_queue_set(sk, queue_index);
 
                queue_index = new_index;
        }
index 03795d0..b4da80b 100644 (file)
@@ -54,7 +54,7 @@ static __inline__ int scm_check_creds(struct ucred *creds)
                return -EINVAL;
 
        if ((creds->pid == task_tgid_vnr(current) ||
-            ns_capable(current->nsproxy->pid_ns->user_ns, CAP_SYS_ADMIN)) &&
+            ns_capable(task_active_pid_ns(current)->user_ns, CAP_SYS_ADMIN)) &&
            ((uid_eq(uid, cred->uid)   || uid_eq(uid, cred->euid) ||
              uid_eq(uid, cred->suid)) || nsown_capable(CAP_SETUID)) &&
            ((gid_eq(gid, cred->gid)   || gid_eq(gid, cred->egid) ||
index 4bcabf3..9ee17e3 100644 (file)
@@ -211,14 +211,6 @@ static inline int ip_finish_output2(struct sk_buff *skb)
        return -EINVAL;
 }
 
-static inline int ip_skb_dst_mtu(struct sk_buff *skb)
-{
-       struct inet_sock *inet = skb->sk ? inet_sk(skb->sk) : NULL;
-
-       return (inet && inet->pmtudisc == IP_PMTUDISC_PROBE) ?
-              skb_dst(skb)->dev->mtu : dst_mtu(skb_dst(skb));
-}
-
 static int ip_finish_output(struct sk_buff *skb)
 {
 #if defined(CONFIG_NETFILTER) && defined(CONFIG_XFRM)
index 51fc2a1..b3ac3c3 100644 (file)
@@ -190,15 +190,14 @@ static int ipip_rcv(struct sk_buff *skb)
        struct ip_tunnel *tunnel;
        const struct iphdr *iph;
 
-       if (iptunnel_pull_header(skb, 0, tpi.proto))
-               goto drop;
-
        iph = ip_hdr(skb);
        tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, TUNNEL_NO_KEY,
                        iph->saddr, iph->daddr, 0);
        if (tunnel) {
                if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
                        goto drop;
+               if (iptunnel_pull_header(skb, 0, tpi.proto))
+                       goto drop;
                return ip_tunnel_rcv(tunnel, skb, &tpi, log_ecn_error);
        }
 
index dd44e0a..61e60d6 100644 (file)
@@ -571,7 +571,8 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
        flowi4_init_output(&fl4, ipc.oif, sk->sk_mark, tos,
                           RT_SCOPE_UNIVERSE,
                           inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol,
-                          inet_sk_flowi_flags(sk) | FLOWI_FLAG_CAN_SLEEP,
+                          inet_sk_flowi_flags(sk) | FLOWI_FLAG_CAN_SLEEP |
+                           (inet->hdrincl ? FLOWI_FLAG_KNOWN_NH : 0),
                           daddr, saddr, 0, 0);
 
        if (!inet->hdrincl) {
index 28af45a..3ca2139 100644 (file)
@@ -3535,7 +3535,10 @@ static bool tcp_parse_aligned_timestamp(struct tcp_sock *tp, const struct tcphdr
                ++ptr;
                tp->rx_opt.rcv_tsval = ntohl(*ptr);
                ++ptr;
-               tp->rx_opt.rcv_tsecr = ntohl(*ptr) - tp->tsoffset;
+               if (*ptr)
+                       tp->rx_opt.rcv_tsecr = ntohl(*ptr) - tp->tsoffset;
+               else
+                       tp->rx_opt.rcv_tsecr = 0;
                return true;
        }
        return false;
@@ -3560,7 +3563,7 @@ static bool tcp_fast_parse_options(const struct sk_buff *skb,
        }
 
        tcp_parse_options(skb, &tp->rx_opt, 1, NULL);
-       if (tp->rx_opt.saw_tstamp)
+       if (tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr)
                tp->rx_opt.rcv_tsecr -= tp->tsoffset;
 
        return true;
@@ -5316,7 +5319,7 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
        int saved_clamp = tp->rx_opt.mss_clamp;
 
        tcp_parse_options(skb, &tp->rx_opt, 0, &foc);
-       if (tp->rx_opt.saw_tstamp)
+       if (tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr)
                tp->rx_opt.rcv_tsecr -= tp->tsoffset;
 
        if (th->ack) {
index 92fde8d..170737a 100644 (file)
@@ -2670,7 +2670,7 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,
        int tcp_header_size;
        int mss;
 
-       skb = alloc_skb(MAX_TCP_HEADER + 15, sk_gfp_atomic(sk, GFP_ATOMIC));
+       skb = sock_wmalloc(sk, MAX_TCP_HEADER + 15, 1, GFP_ATOMIC);
        if (unlikely(!skb)) {
                dst_release(dst);
                return NULL;
@@ -2814,6 +2814,8 @@ void tcp_connect_init(struct sock *sk)
 
        if (likely(!tp->repair))
                tp->rcv_nxt = 0;
+       else
+               tp->rcv_tstamp = tcp_time_stamp;
        tp->rcv_wup = tp->rcv_nxt;
        tp->copied_seq = tp->rcv_nxt;
 
index 327a617..baa0f63 100644 (file)
@@ -21,7 +21,6 @@
 static int xfrm4_tunnel_check_size(struct sk_buff *skb)
 {
        int mtu, ret = 0;
-       struct dst_entry *dst;
 
        if (IPCB(skb)->flags & IPSKB_XFRM_TUNNEL_SIZE)
                goto out;
@@ -29,12 +28,10 @@ static int xfrm4_tunnel_check_size(struct sk_buff *skb)
        if (!(ip_hdr(skb)->frag_off & htons(IP_DF)) || skb->local_df)
                goto out;
 
-       dst = skb_dst(skb);
-       mtu = dst_mtu(dst);
+       mtu = dst_mtu(skb_dst(skb));
        if (skb->len > mtu) {
                if (skb->sk)
-                       ip_local_error(skb->sk, EMSGSIZE, ip_hdr(skb)->daddr,
-                                      inet_sk(skb->sk)->inet_dport, mtu);
+                       xfrm_local_error(skb, mtu);
                else
                        icmp_send(skb, ICMP_DEST_UNREACH,
                                  ICMP_FRAG_NEEDED, htonl(mtu));
@@ -99,3 +96,12 @@ int xfrm4_output(struct sk_buff *skb)
                            x->outer_mode->afinfo->output_finish,
                            !(IPCB(skb)->flags & IPSKB_REROUTED));
 }
+
+void xfrm4_local_error(struct sk_buff *skb, u32 mtu)
+{
+       struct iphdr *hdr;
+
+       hdr = skb->encapsulation ? inner_ip_hdr(skb) : ip_hdr(skb);
+       ip_local_error(skb->sk, EMSGSIZE, hdr->daddr,
+                      inet_sk(skb->sk)->inet_dport, mtu);
+}
index 9258e75..0b2a064 100644 (file)
@@ -83,6 +83,7 @@ static struct xfrm_state_afinfo xfrm4_state_afinfo = {
        .extract_input          = xfrm4_extract_input,
        .extract_output         = xfrm4_extract_output,
        .transport_finish       = xfrm4_transport_finish,
+       .local_error            = xfrm4_local_error,
 };
 
 void __init xfrm4_state_init(void)
index ecd6073..90747f1 100644 (file)
@@ -724,6 +724,11 @@ static netdev_tx_t ip6gre_xmit2(struct sk_buff *skb,
                ipv6_push_nfrag_opts(skb, &opt.ops, &proto, NULL);
        }
 
+       if (likely(!skb->encapsulation)) {
+               skb_reset_inner_headers(skb);
+               skb->encapsulation = 1;
+       }
+
        skb_push(skb, gre_hlen);
        skb_reset_network_header(skb);
        skb_set_transport_header(skb, sizeof(*ipv6h));
index 6e3ddf8..e7ceb6c 100644 (file)
@@ -238,6 +238,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6,
        hdr->saddr = fl6->saddr;
        hdr->daddr = *first_hop;
 
+       skb->protocol = htons(ETH_P_IPV6);
        skb->priority = sk->sk_priority;
        skb->mark = sk->sk_mark;
 
@@ -1057,6 +1058,7 @@ static inline int ip6_ufo_append_data(struct sock *sk,
                /* initialize protocol header pointer */
                skb->transport_header = skb->network_header + fragheaderlen;
 
+               skb->protocol = htons(ETH_P_IPV6);
                skb->ip_summed = CHECKSUM_PARTIAL;
                skb->csum = 0;
        }
@@ -1359,6 +1361,7 @@ alloc_new_skb:
                        /*
                         *      Fill in the control structures
                         */
+                       skb->protocol = htons(ETH_P_IPV6);
                        skb->ip_summed = CHECKSUM_NONE;
                        skb->csum = 0;
                        /* reserve for fragmentation and ipsec header */
index 1e55866..46ba243 100644 (file)
@@ -1027,6 +1027,12 @@ static int ip6_tnl_xmit2(struct sk_buff *skb,
                init_tel_txopt(&opt, encap_limit);
                ipv6_push_nfrag_opts(skb, &opt.ops, &proto, NULL);
        }
+
+       if (likely(!skb->encapsulation)) {
+               skb_reset_inner_headers(skb);
+               skb->encapsulation = 1;
+       }
+
        skb_push(skb, sizeof(struct ipv6hdr));
        skb_reset_network_header(skb);
        ipv6h = ipv6_hdr(skb);
index c45f7a5..cdaed47 100644 (file)
@@ -628,6 +628,7 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length,
                goto error;
        skb_reserve(skb, hlen);
 
+       skb->protocol = htons(ETH_P_IPV6);
        skb->priority = sk->sk_priority;
        skb->mark = sk->sk_mark;
        skb_dst_set(skb, &rt->dst);
index a3437a4..21b25dd 100644 (file)
@@ -645,11 +645,7 @@ static int ipip_rcv(struct sk_buff *skb)
        const struct iphdr *iph;
        struct ip_tunnel *tunnel;
 
-       if (iptunnel_pull_header(skb, 0, tpi.proto))
-               goto drop;
-
        iph = ip_hdr(skb);
-
        tunnel = ipip6_tunnel_lookup(dev_net(skb->dev), skb->dev,
                                     iph->saddr, iph->daddr);
        if (tunnel != NULL) {
@@ -659,6 +655,8 @@ static int ipip_rcv(struct sk_buff *skb)
 
                if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
                        goto drop;
+               if (iptunnel_pull_header(skb, 0, tpi.proto))
+                       goto drop;
                return ip_tunnel_rcv(tunnel, skb, &tpi, log_ecn_error);
        }
 
@@ -888,6 +886,11 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
                ttl = iph6->hop_limit;
        tos = INET_ECN_encapsulate(tos, ipv6_get_dsfield(iph6));
 
+       if (likely(!skb->encapsulation)) {
+               skb_reset_inner_headers(skb);
+               skb->encapsulation = 1;
+       }
+
        err = iptunnel_xmit(dev_net(dev), rt, skb, fl4.saddr, fl4.daddr,
                            IPPROTO_IPV6, tos, ttl, df);
        iptunnel_xmit_stats(err, &dev->stats, dev->tstats);
index 8755a30..6cd625e 100644 (file)
@@ -34,8 +34,10 @@ static int xfrm6_local_dontfrag(struct sk_buff *skb)
        struct sock *sk = skb->sk;
 
        if (sk) {
-               proto = sk->sk_protocol;
+               if (sk->sk_family != AF_INET6)
+                       return 0;
 
+               proto = sk->sk_protocol;
                if (proto == IPPROTO_UDP || proto == IPPROTO_RAW)
                        return inet6_sk(sk)->dontfrag;
        }
@@ -54,13 +56,15 @@ static void xfrm6_local_rxpmtu(struct sk_buff *skb, u32 mtu)
        ipv6_local_rxpmtu(sk, &fl6, mtu);
 }
 
-static void xfrm6_local_error(struct sk_buff *skb, u32 mtu)
+void xfrm6_local_error(struct sk_buff *skb, u32 mtu)
 {
        struct flowi6 fl6;
+       const struct ipv6hdr *hdr;
        struct sock *sk = skb->sk;
 
+       hdr = skb->encapsulation ? inner_ipv6_hdr(skb) : ipv6_hdr(skb);
        fl6.fl6_dport = inet_sk(sk)->inet_dport;
-       fl6.daddr = ipv6_hdr(skb)->daddr;
+       fl6.daddr = hdr->daddr;
 
        ipv6_local_error(sk, EMSGSIZE, &fl6, mtu);
 }
@@ -80,7 +84,7 @@ static int xfrm6_tunnel_check_size(struct sk_buff *skb)
                if (xfrm6_local_dontfrag(skb))
                        xfrm6_local_rxpmtu(skb, mtu);
                else if (skb->sk)
-                       xfrm6_local_error(skb, mtu);
+                       xfrm_local_error(skb, mtu);
                else
                        icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
                ret = -EMSGSIZE;
@@ -136,13 +140,18 @@ static int __xfrm6_output(struct sk_buff *skb)
 {
        struct dst_entry *dst = skb_dst(skb);
        struct xfrm_state *x = dst->xfrm;
-       int mtu = ip6_skb_dst_mtu(skb);
+       int mtu;
+
+       if (skb->protocol == htons(ETH_P_IPV6))
+               mtu = ip6_skb_dst_mtu(skb);
+       else
+               mtu = dst_mtu(skb_dst(skb));
 
        if (skb->len > mtu && xfrm6_local_dontfrag(skb)) {
                xfrm6_local_rxpmtu(skb, mtu);
                return -EMSGSIZE;
        } else if (!skb->local_df && skb->len > mtu && skb->sk) {
-               xfrm6_local_error(skb, mtu);
+               xfrm_local_error(skb, mtu);
                return -EMSGSIZE;
        }
 
index d8c70b8..3fc9701 100644 (file)
@@ -183,6 +183,7 @@ static struct xfrm_state_afinfo xfrm6_state_afinfo = {
        .extract_input          = xfrm6_extract_input,
        .extract_output         = xfrm6_extract_output,
        .transport_finish       = xfrm6_transport_finish,
+       .local_error            = xfrm6_local_error,
 };
 
 int __init xfrm6_state_init(void)
index ea7b9c2..2d45643 100644 (file)
@@ -36,7 +36,7 @@
 
 static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
                                      const u8 *bssid, const int beacon_int,
-                                     struct ieee80211_channel *chan,
+                                     struct cfg80211_chan_def *req_chandef,
                                      const u32 basic_rates,
                                      const u16 capability, u64 tsf,
                                      bool creator)
@@ -51,6 +51,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
        u32 bss_change;
        u8 supp_rates[IEEE80211_MAX_SUPP_RATES];
        struct cfg80211_chan_def chandef;
+       struct ieee80211_channel *chan;
        struct beacon_data *presp;
        int frame_len;
 
@@ -81,7 +82,9 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
 
        sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0;
 
-       chandef = ifibss->chandef;
+       /* make a copy of the chandef, it could be modified below. */
+       chandef = *req_chandef;
+       chan = chandef.chan;
        if (!cfg80211_reg_can_beacon(local->hw.wiphy, &chandef)) {
                chandef.width = NL80211_CHAN_WIDTH_20;
                chandef.center_freq1 = chan->center_freq;
@@ -259,10 +262,12 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
        struct cfg80211_bss *cbss =
                container_of((void *)bss, struct cfg80211_bss, priv);
        struct ieee80211_supported_band *sband;
+       struct cfg80211_chan_def chandef;
        u32 basic_rates;
        int i, j;
        u16 beacon_int = cbss->beacon_interval;
        const struct cfg80211_bss_ies *ies;
+       enum nl80211_channel_type chan_type;
        u64 tsf;
 
        sdata_assert_lock(sdata);
@@ -270,6 +275,26 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
        if (beacon_int < 10)
                beacon_int = 10;
 
+       switch (sdata->u.ibss.chandef.width) {
+       case NL80211_CHAN_WIDTH_20_NOHT:
+       case NL80211_CHAN_WIDTH_20:
+       case NL80211_CHAN_WIDTH_40:
+               chan_type = cfg80211_get_chandef_type(&sdata->u.ibss.chandef);
+               cfg80211_chandef_create(&chandef, cbss->channel, chan_type);
+               break;
+       case NL80211_CHAN_WIDTH_5:
+       case NL80211_CHAN_WIDTH_10:
+               cfg80211_chandef_create(&chandef, cbss->channel,
+                                       NL80211_CHAN_WIDTH_20_NOHT);
+               chandef.width = sdata->u.ibss.chandef.width;
+               break;
+       default:
+               /* fall back to 20 MHz for unsupported modes */
+               cfg80211_chandef_create(&chandef, cbss->channel,
+                                       NL80211_CHAN_WIDTH_20_NOHT);
+               break;
+       }
+
        sband = sdata->local->hw.wiphy->bands[cbss->channel->band];
 
        basic_rates = 0;
@@ -294,7 +319,7 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
 
        __ieee80211_sta_join_ibss(sdata, cbss->bssid,
                                  beacon_int,
-                                 cbss->channel,
+                                 &chandef,
                                  basic_rates,
                                  cbss->capability,
                                  tsf, false);
@@ -736,7 +761,7 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
                sdata->drop_unencrypted = 0;
 
        __ieee80211_sta_join_ibss(sdata, bssid, sdata->vif.bss_conf.beacon_int,
-                                 ifibss->chandef.chan, ifibss->basic_rates,
+                                 &ifibss->chandef, ifibss->basic_rates,
                                  capability, 0, true);
 }
 
@@ -1138,6 +1163,7 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
        clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state);
        ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED |
                                                BSS_CHANGED_IBSS);
+       ieee80211_vif_release_channel(sdata);
        synchronize_rcu();
        kfree(presp);
 
index f5aed96..f3bbea1 100644 (file)
@@ -828,6 +828,9 @@ minstrel_ht_update_cck(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
        if (sband->band != IEEE80211_BAND_2GHZ)
                return;
 
+       if (!(mp->hw->flags & IEEE80211_HW_SUPPORTS_HT_CCK_RATES))
+               return;
+
        mi->cck_supported = 0;
        mi->cck_supported_short = 0;
        for (i = 0; i < 4; i++) {
index 512718a..0c741ce 100644 (file)
@@ -364,7 +364,7 @@ int genl_unregister_ops(struct genl_family *family, struct genl_ops *ops)
 EXPORT_SYMBOL(genl_unregister_ops);
 
 /**
- * genl_register_family - register a generic netlink family
+ * __genl_register_family - register a generic netlink family
  * @family: generic netlink family
  *
  * Registers the specified family after validating it first. Only one
@@ -374,7 +374,7 @@ EXPORT_SYMBOL(genl_unregister_ops);
  *
  * Return 0 on success or a negative error code.
  */
-int genl_register_family(struct genl_family *family)
+int __genl_register_family(struct genl_family *family)
 {
        int err = -EINVAL;
 
@@ -430,10 +430,10 @@ errout_locked:
 errout:
        return err;
 }
-EXPORT_SYMBOL(genl_register_family);
+EXPORT_SYMBOL(__genl_register_family);
 
 /**
- * genl_register_family_with_ops - register a generic netlink family
+ * __genl_register_family_with_ops - register a generic netlink family
  * @family: generic netlink family
  * @ops: operations to be registered
  * @n_ops: number of elements to register
@@ -457,12 +457,12 @@ EXPORT_SYMBOL(genl_register_family);
  *
  * Return 0 on success or a negative error code.
  */
-int genl_register_family_with_ops(struct genl_family *family,
+int __genl_register_family_with_ops(struct genl_family *family,
        struct genl_ops *ops, size_t n_ops)
 {
        int err, i;
 
-       err = genl_register_family(family);
+       err = __genl_register_family(family);
        if (err)
                return err;
 
@@ -476,7 +476,7 @@ err_out:
        genl_unregister_family(family);
        return err;
 }
-EXPORT_SYMBOL(genl_register_family_with_ops);
+EXPORT_SYMBOL(__genl_register_family_with_ops);
 
 /**
  * genl_unregister_family - unregister generic netlink family
@@ -544,6 +544,30 @@ void *genlmsg_put(struct sk_buff *skb, u32 portid, u32 seq,
 }
 EXPORT_SYMBOL(genlmsg_put);
 
+static int genl_lock_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
+{
+       struct genl_ops *ops = cb->data;
+       int rc;
+
+       genl_lock();
+       rc = ops->dumpit(skb, cb);
+       genl_unlock();
+       return rc;
+}
+
+static int genl_lock_done(struct netlink_callback *cb)
+{
+       struct genl_ops *ops = cb->data;
+       int rc = 0;
+
+       if (ops->done) {
+               genl_lock();
+               rc = ops->done(cb);
+               genl_unlock();
+       }
+       return rc;
+}
+
 static int genl_family_rcv_msg(struct genl_family *family,
                               struct sk_buff *skb,
                               struct nlmsghdr *nlh)
@@ -572,15 +596,34 @@ static int genl_family_rcv_msg(struct genl_family *family,
                return -EPERM;
 
        if ((nlh->nlmsg_flags & NLM_F_DUMP) == NLM_F_DUMP) {
-               struct netlink_dump_control c = {
-                       .dump = ops->dumpit,
-                       .done = ops->done,
-               };
+               int rc;
 
                if (ops->dumpit == NULL)
                        return -EOPNOTSUPP;
 
-               return netlink_dump_start(net->genl_sock, skb, nlh, &c);
+               if (!family->parallel_ops) {
+                       struct netlink_dump_control c = {
+                               .module = family->module,
+                               .data = ops,
+                               .dump = genl_lock_dumpit,
+                               .done = genl_lock_done,
+                       };
+
+                       genl_unlock();
+                       rc = __netlink_dump_start(net->genl_sock, skb, nlh, &c);
+                       genl_lock();
+
+               } else {
+                       struct netlink_dump_control c = {
+                               .module = family->module,
+                               .dump = ops->dumpit,
+                               .done = ops->done,
+                       };
+
+                       rc = __netlink_dump_start(net->genl_sock, skb, nlh, &c);
+               }
+
+               return rc;
        }
 
        if (ops->doit == NULL)
index 75edcfa..1504bb1 100644 (file)
@@ -207,10 +207,13 @@ _shift_data_right_pages(struct page **pages, size_t pgto_base,
                pgfrom_base -= copy;
 
                vto = kmap_atomic(*pgto);
-               vfrom = kmap_atomic(*pgfrom);
-               memmove(vto + pgto_base, vfrom + pgfrom_base, copy);
+               if (*pgto != *pgfrom) {
+                       vfrom = kmap_atomic(*pgfrom);
+                       memcpy(vto + pgto_base, vfrom + pgfrom_base, copy);
+                       kunmap_atomic(vfrom);
+               } else
+                       memmove(vto + pgto_base, vto + pgfrom_base, copy);
                flush_dcache_page(*pgto);
-               kunmap_atomic(vfrom);
                kunmap_atomic(vto);
 
        } while ((len -= copy) != 0);
index ce8249c..6cc7ddd 100644 (file)
@@ -1257,7 +1257,7 @@ static u32 filter_connect(struct tipc_sock *tsock, struct sk_buff **buf)
                /* Accept only ACK or NACK message */
                if (unlikely(msg_errcode(msg))) {
                        sock->state = SS_DISCONNECTING;
-                       sk->sk_err = -ECONNREFUSED;
+                       sk->sk_err = ECONNREFUSED;
                        retval = TIPC_OK;
                        break;
                }
@@ -1268,7 +1268,7 @@ static u32 filter_connect(struct tipc_sock *tsock, struct sk_buff **buf)
                res = auto_connect(sock, msg);
                if (res) {
                        sock->state = SS_DISCONNECTING;
-                       sk->sk_err = res;
+                       sk->sk_err = -res;
                        retval = TIPC_OK;
                        break;
                }
index eb4a842..3bb2cdc 100644 (file)
@@ -214,5 +214,26 @@ int xfrm_inner_extract_output(struct xfrm_state *x, struct sk_buff *skb)
        return inner_mode->afinfo->extract_output(x, skb);
 }
 
+void xfrm_local_error(struct sk_buff *skb, int mtu)
+{
+       unsigned int proto;
+       struct xfrm_state_afinfo *afinfo;
+
+       if (skb->protocol == htons(ETH_P_IP))
+               proto = AF_INET;
+       else if (skb->protocol == htons(ETH_P_IPV6))
+               proto = AF_INET6;
+       else
+               return;
+
+       afinfo = xfrm_state_get_afinfo(proto);
+       if (!afinfo)
+               return;
+
+       afinfo->local_error(skb, mtu);
+       xfrm_state_put_afinfo(afinfo);
+}
+
 EXPORT_SYMBOL_GPL(xfrm_output);
 EXPORT_SYMBOL_GPL(xfrm_inner_extract_output);
+EXPORT_SYMBOL_GPL(xfrm_local_error);
index e52cab3..f77c371 100644 (file)
@@ -320,10 +320,8 @@ static void xfrm_queue_purge(struct sk_buff_head *list)
 {
        struct sk_buff *skb;
 
-       while ((skb = skb_dequeue(list)) != NULL) {
-               dev_put(skb->dev);
+       while ((skb = skb_dequeue(list)) != NULL)
                kfree_skb(skb);
-       }
 }
 
 /* Rule must be locked. Release descentant resources, announce
@@ -1758,7 +1756,6 @@ static void xfrm_policy_queue_process(unsigned long arg)
        struct sk_buff *skb;
        struct sock *sk;
        struct dst_entry *dst;
-       struct net_device *dev;
        struct xfrm_policy *pol = (struct xfrm_policy *)arg;
        struct xfrm_policy_queue *pq = &pol->polq;
        struct flowi fl;
@@ -1805,7 +1802,6 @@ static void xfrm_policy_queue_process(unsigned long arg)
                dst = xfrm_lookup(xp_net(pol), skb_dst(skb)->path,
                                  &fl, skb->sk, 0);
                if (IS_ERR(dst)) {
-                       dev_put(skb->dev);
                        kfree_skb(skb);
                        continue;
                }
@@ -1814,9 +1810,7 @@ static void xfrm_policy_queue_process(unsigned long arg)
                skb_dst_drop(skb);
                skb_dst_set(skb, dst);
 
-               dev = skb->dev;
                err = dst_output(skb);
-               dev_put(dev);
        }
 
        return;
@@ -1839,7 +1833,6 @@ static int xdst_queue_output(struct sk_buff *skb)
        }
 
        skb_dst_force(skb);
-       dev_hold(skb->dev);
 
        spin_lock_bh(&pq->hold_queue.lock);
 
index 78f66fa..54c0acd 100644 (file)
@@ -39,9 +39,6 @@ static DEFINE_SPINLOCK(xfrm_state_lock);
 
 static unsigned int xfrm_state_hashmax __read_mostly = 1 * 1024 * 1024;
 
-static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family);
-static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo);
-
 static inline unsigned int xfrm_dst_hash(struct net *net,
                                         const xfrm_address_t *daddr,
                                         const xfrm_address_t *saddr,
@@ -1860,7 +1857,7 @@ int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo)
 }
 EXPORT_SYMBOL(xfrm_state_unregister_afinfo);
 
-static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family)
+struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family)
 {
        struct xfrm_state_afinfo *afinfo;
        if (unlikely(family >= NPROTO))
@@ -1872,7 +1869,7 @@ static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family)
        return afinfo;
 }
 
-static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo)
+void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo)
 {
        rcu_read_unlock();
 }
index 103b333..6effe99 100644 (file)
@@ -173,11 +173,7 @@ MODULE_DEVICE_TABLE(pnp_card, snd_opti9xx_pnpids);
 
 #endif /* CONFIG_PNP */
 
-#ifdef OPTi93X
-#define DEV_NAME "opti93x"
-#else
-#define DEV_NAME "opti92x"
-#endif
+#define DEV_NAME KBUILD_MODNAME
 
 static char * snd_opti9xx_names[] = {
        "unknown",
@@ -1167,7 +1163,7 @@ static int snd_opti9xx_pnp_resume(struct pnp_card_link *pcard)
 
 static struct pnp_card_driver opti9xx_pnpc_driver = {
        .flags          = PNP_DRIVER_RES_DISABLE,
-       .name           = "opti9xx",
+       .name           = DEV_NAME,
        .id_table       = snd_opti9xx_pnpids,
        .probe          = snd_opti9xx_pnp_probe,
        .remove         = snd_opti9xx_pnp_remove,
index 030ca86..9f35862 100644 (file)
@@ -1781,6 +1781,9 @@ static int generic_hdmi_build_controls(struct hda_codec *codec)
                struct snd_pcm_chmap *chmap;
                struct snd_kcontrol *kctl;
                int i;
+
+               if (!codec->pcm_info[pin_idx].pcm)
+                       break;
                err = snd_pcm_add_chmap_ctls(codec->pcm_info[pin_idx].pcm,
                                             SNDRV_PCM_STREAM_PLAYBACK,
                                             NULL, 0, pin_idx, &chmap);
index f303cd8..389db4c 100644 (file)
@@ -4336,6 +4336,7 @@ static const struct hda_fixup alc662_fixups[] = {
 
 static const struct snd_pci_quirk alc662_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1019, 0x9087, "ECS", ALC662_FIXUP_ASUS_MODE2),
+       SND_PCI_QUIRK(0x1025, 0x022f, "Acer Aspire One", ALC662_FIXUP_INV_DMIC),
        SND_PCI_QUIRK(0x1025, 0x0308, "Acer Aspire 8942G", ALC662_FIXUP_ASPIRE),
        SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE),
        SND_PCI_QUIRK(0x1025, 0x0349, "eMachines eM250", ALC662_FIXUP_INV_DMIC),