Merge remote-tracking branch 'spi/topic/topcliff' into spi-next
authorMark Brown <broonie@linaro.org>
Sun, 1 Sep 2013 12:49:17 +0000 (13:49 +0100)
committerMark Brown <broonie@linaro.org>
Sun, 1 Sep 2013 12:49:17 +0000 (13:49 +0100)
372 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/kernel-parameters.txt
Documentation/spi/spi-summary
MAINTAINERS
Makefile
arch/Kconfig
arch/arc/lib/strchr-700.S
arch/arm/boot/dts/at91sam9n12ek.dts
arch/arm/boot/dts/at91sam9x5ek.dtsi
arch/arm/boot/dts/tegra20-seaboard.dts
arch/arm/boot/dts/tegra20-trimslice.dts
arch/arm/boot/dts/tegra20-whistler.dts
arch/arm/include/asm/smp_plat.h
arch/arm/include/asm/spinlock.h
arch/arm/include/asm/tlb.h
arch/arm/kernel/entry-armv.S
arch/arm/kernel/fiq.c
arch/arm/kernel/machine_kexec.c
arch/arm/kernel/perf_event.c
arch/arm/kernel/process.c
arch/arm/kernel/smp.c
arch/arm/kvm/coproc.c
arch/arm/kvm/coproc.h
arch/arm/kvm/coproc_a15.c
arch/arm/kvm/mmio.c
arch/arm/kvm/mmu.c
arch/arm/mach-at91/at91sam9x5.c
arch/arm/mach-davinci/board-dm355-leopard.c
arch/arm/mach-davinci/board-dm644x-evm.c
arch/arm/mach-davinci/board-dm646x-evm.c
arch/arm/mach-davinci/board-neuros-osd2.c
arch/arm/mach-omap2/board-n8x0.c
arch/arm/mach-omap2/board-rx51.c
arch/arm/mach-omap2/usb-musb.c
arch/arm/mm/Kconfig
arch/arm/plat-samsung/init.c
arch/arm/xen/enlighten.c
arch/arm64/include/asm/kvm_asm.h
arch/arm64/include/asm/kvm_host.h
arch/arm64/include/asm/tlb.h
arch/arm64/kernel/perf_event.c
arch/arm64/kvm/hyp.S
arch/arm64/kvm/sys_regs.c
arch/hexagon/Kconfig
arch/ia64/include/asm/tlb.h
arch/m68k/emu/natfeat.c
arch/m68k/include/asm/div64.h
arch/microblaze/Kconfig
arch/mips/math-emu/cp1emu.c
arch/openrisc/Kconfig
arch/s390/include/asm/tlb.h
arch/score/Kconfig
arch/sh/include/asm/tlb.h
arch/um/include/asm/tlb.h
arch/x86/include/asm/bootparam_utils.h
arch/x86/include/asm/microcode_amd.h
arch/x86/include/asm/pgtable-2level.h
arch/x86/include/asm/pgtable-3level.h
arch/x86/include/asm/pgtable.h
arch/x86/include/asm/pgtable_types.h
arch/x86/include/asm/spinlock.h
arch/x86/kernel/cpu/amd.c
arch/x86/kernel/cpu/perf_event_intel.c
arch/x86/kernel/cpu/perf_event_intel_uncore.c
arch/x86/kernel/microcode_amd.c
arch/x86/kernel/microcode_amd_early.c
arch/x86/kernel/sys_x86_64.c
arch/x86/mm/mmap.c
arch/x86/xen/setup.c
arch/x86/xen/smp.c
drivers/acpi/video.c
drivers/ata/libata-pmp.c
drivers/ata/sata_fsl.c
drivers/ata/sata_highbank.c
drivers/block/aoe/aoecmd.c
drivers/clk/samsung/clk-exynos4.c
drivers/clk/zynq/clkc.c
drivers/gpu/drm/gma500/psb_intel_sdvo.c
drivers/gpu/drm/i915/i915_gem_dmabuf.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_ringbuffer.c
drivers/gpu/drm/nouveau/core/core/mm.c
drivers/gpu/drm/nouveau/core/include/subdev/mc.h
drivers/gpu/drm/nouveau/core/subdev/fb/ramnv49.c
drivers/gpu/drm/nouveau/core/subdev/fb/ramnv4e.c
drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c
drivers/gpu/drm/nouveau/core/subdev/mc/base.c
drivers/gpu/drm/nouveau/core/subdev/mc/nv04.c
drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c
drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c
drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c
drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c
drivers/gpu/drm/nouveau/dispnv04/crtc.c
drivers/gpu/drm/nouveau/dispnv04/disp.h
drivers/gpu/drm/nouveau/nouveau_display.c
drivers/gpu/drm/nouveau/nv40_pm.c
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_uvd.c
drivers/gpu/drm/radeon/rv770.c
drivers/iio/light/adjd_s311.c
drivers/md/dm-cache-policy-mq.c
drivers/net/bonding/bond_main.c
drivers/net/can/usb/peak_usb/pcan_usb.c
drivers/net/ethernet/arc/emac_main.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h
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/tg3.c
drivers/net/ethernet/chelsio/cxgb3/sge.c
drivers/net/ethernet/emulex/benet/be_cmds.c
drivers/net/ethernet/emulex/benet/be_cmds.h
drivers/net/ethernet/emulex/benet/be_main.c
drivers/net/ethernet/marvell/skge.c
drivers/net/ethernet/mellanox/mlx5/core/cmd.c
drivers/net/ethernet/mellanox/mlx5/core/eq.c
drivers/net/ethernet/mellanox/mlx5/core/fw.c
drivers/net/ethernet/mellanox/mlx5/core/health.c
drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
drivers/net/ethernet/realtek/8139cp.c
drivers/net/ethernet/realtek/r8169.c
drivers/net/ethernet/sfc/filter.c
drivers/net/ethernet/stmicro/stmmac/ring_mode.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/via/via-velocity.c
drivers/net/irda/via-ircc.c
drivers/net/macvlan.c
drivers/net/macvtap.c
drivers/net/phy/realtek.c
drivers/net/tun.c
drivers/net/usb/hso.c
drivers/net/vxlan.c
drivers/net/wireless/cw1200/sta.c
drivers/net/wireless/hostap/hostap_ioctl.c
drivers/net/wireless/iwlegacy/4965-mac.c
drivers/net/wireless/iwlegacy/common.c
drivers/net/wireless/iwlwifi/dvm/mac80211.c
drivers/net/wireless/iwlwifi/iwl-prph.h
drivers/net/wireless/iwlwifi/mvm/time-event.c
drivers/net/wireless/iwlwifi/pcie/rx.c
drivers/net/wireless/iwlwifi/pcie/trans.c
drivers/net/wireless/zd1201.c
drivers/of/fdt.c
drivers/pinctrl/pinctrl-sunxi.c
drivers/pinctrl/pinctrl-sunxi.h
drivers/platform/olpc/olpc-ec.c
drivers/platform/x86/hp-wmi.c
drivers/platform/x86/sony-laptop.c
drivers/rtc/rtc-stmp3xxx.c
drivers/s390/scsi/zfcp_erp.c
drivers/s390/scsi/zfcp_qdio.c
drivers/s390/scsi/zfcp_sysfs.c
drivers/scsi/Kconfig
drivers/spi/Kconfig
drivers/spi/Makefile
drivers/spi/spi-altera.c
drivers/spi/spi-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-xilinx.c
drivers/spi/spi.c
drivers/staging/comedi/drivers.c
drivers/usb/class/usbtmc.c
drivers/usb/core/quirks.c
drivers/usb/host/ehci-sched.c
drivers/usb/host/ohci-pci.c
drivers/usb/misc/adutux.c
drivers/usb/phy/phy-fsl-usb.h
drivers/usb/phy/phy-fsm-usb.c
drivers/usb/serial/keyspan.c
drivers/usb/serial/mos7720.c
drivers/usb/serial/mos7840.c
drivers/usb/serial/ti_usb_3410_5052.c
drivers/usb/serial/usb_wwan.c
drivers/usb/wusbcore/wa-xfer.c
drivers/xen/events.c
fs/bfs/inode.c
fs/bio.c
fs/cifs/cifsencrypt.c
fs/cifs/cifsfs.c
fs/cifs/cifsglob.h
fs/cifs/cifsproto.h
fs/cifs/connect.c
fs/cifs/file.c
fs/cifs/link.c
fs/cifs/readdir.c
fs/cifs/sess.c
fs/cifs/smb1ops.c
fs/cifs/smb2transport.c
fs/dcache.c
fs/efs/inode.c
fs/exec.c
fs/ext4/ext4.h
fs/ext4/ext4_jbd2.c
fs/ext4/file.c
fs/ext4/inode.c
fs/ext4/ioctl.c
fs/ext4/super.c
fs/gfs2/glock.c
fs/gfs2/glops.c
fs/gfs2/inode.c
fs/gfs2/main.c
fs/hugetlbfs/inode.c
fs/namespace.c
fs/nilfs2/segbuf.c
fs/ocfs2/aops.c
fs/ocfs2/dir.c
fs/ocfs2/file.c
fs/ocfs2/journal.h
fs/ocfs2/move_extents.c
fs/ocfs2/refcounttree.c
fs/ocfs2/refcounttree.h
fs/proc/fd.c
fs/proc/generic.c
fs/proc/root.c
fs/proc/task_mmu.c
include/asm-generic/pgtable.h
include/asm-generic/tlb.h
include/linux/dcache.h
include/linux/inetdevice.h
include/linux/ipv6.h
include/linux/mlx5/device.h
include/linux/mlx5/driver.h
include/linux/mm_types.h
include/linux/platform_data/efm32-spi.h [new file with mode: 0644]
include/linux/sched.h
include/linux/spi/spi.h
include/linux/spi/spi_bitbang.h
include/linux/spinlock.h
include/linux/swapops.h
include/linux/syscalls.h
include/linux/wait.h
include/net/busy_poll.h
include/net/ip6_route.h
include/net/ip_tunnels.h
include/net/sch_generic.h
include/uapi/linux/ip.h
include/uapi/linux/pkt_sched.h
include/uapi/linux/snmp.h
init/Kconfig
kernel/cpuset.c
kernel/fork.c
kernel/mutex.c
kernel/power/qos.c
kernel/sched/core.c
kernel/sched/cpupri.c
kernel/sched/fair.c
kernel/time/sched_clock.c
kernel/time/tick-sched.c
kernel/wait.c
lib/lz4/lz4_compress.c
lib/lz4/lz4_decompress.c
lib/lz4/lz4hc_compress.c
mm/fremap.c
mm/hugetlb.c
mm/memcontrol.c
mm/memory.c
mm/mmap.c
mm/rmap.c
mm/shmem.c
mm/swapfile.c
net/8021q/vlan_core.c
net/batman-adv/bridge_loop_avoidance.c
net/batman-adv/gateway_client.c
net/batman-adv/gateway_client.h
net/batman-adv/soft-interface.c
net/batman-adv/unicast.c
net/bridge/br_fdb.c
net/bridge/br_multicast.c
net/bridge/br_netlink.c
net/bridge/br_sysfs_br.c
net/bridge/br_vlan.c
net/core/flow_dissector.c
net/core/neighbour.c
net/core/rtnetlink.c
net/ipv4/esp4.c
net/ipv4/fib_trie.c
net/ipv4/ip_gre.c
net/ipv4/ip_tunnel_core.c
net/ipv4/proc.c
net/ipv4/tcp.c
net/ipv4/tcp_cubic.c
net/ipv6/addrconf.c
net/ipv6/esp6.c
net/ipv6/ip6_fib.c
net/ipv6/ndisc.c
net/ipv6/reassembly.c
net/ipv6/route.c
net/mac80211/mlme.c
net/netfilter/nf_conntrack_proto_tcp.c
net/netfilter/nfnetlink_log.c
net/netfilter/nfnetlink_queue_core.c
net/netfilter/xt_TCPMSS.c
net/netfilter/xt_TCPOPTSTRIP.c
net/openvswitch/actions.c
net/openvswitch/datapath.c
net/openvswitch/flow.c
net/packet/af_packet.c
net/sched/sch_api.c
net/sched/sch_generic.c
net/sched/sch_htb.c
net/sctp/associola.c
net/sctp/transport.c
net/tipc/bearer.c
net/vmw_vsock/af_vsock.c
net/wireless/core.c
net/wireless/nl80211.c
net/wireless/sme.c
sound/pci/hda/hda_generic.c
sound/pci/hda/patch_realtek.c
sound/soc/codecs/cs42l52.c
sound/soc/codecs/sgtl5000.c
sound/soc/soc-dapm.c
sound/soc/tegra/tegra30_i2s.c
sound/usb/6fire/midi.c
sound/usb/6fire/midi.h
sound/usb/6fire/pcm.c
sound/usb/6fire/pcm.h
sound/usb/mixer.c
sound/usb/quirks.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 15356ac..7f9d4f5 100644 (file)
@@ -2953,7 +2953,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        improve throughput, but will also increase the
                        amount of memory reserved for use by the client.
 
-       swapaccount[=0|1]
+       swapaccount=[0|1]
                        [KNL] Enable accounting of swap in memory resource
                        controller if no parameter or 1 is given or disable
                        it if 0 is given (See Documentation/cgroups/memory.txt)
index 2331eb2..f21edb9 100644 (file)
@@ -215,7 +215,7 @@ So for example arch/.../mach-*/board-*.c files might have code like:
        /* if your mach-* infrastructure doesn't support kernels that can
         * run on multiple boards, pdata wouldn't benefit from "__init".
         */
-       static struct mysoc_spi_data __initdata pdata = { ... };
+       static struct mysoc_spi_data pdata __initdata = { ... };
 
        static __init board_init(void)
        {
index 7cacc88..8197fbd 100644 (file)
@@ -5581,9 +5581,9 @@ S:        Maintained
 F:     drivers/media/tuners/mxl5007t.*
 
 MYRICOM MYRI-10G 10GbE DRIVER (MYRI10GE)
-M:     Andrew Gallatin <gallatin@myri.com>
+M:     Hyong-Youb Kim <hykim@myri.com>
 L:     netdev@vger.kernel.org
-W:     http://www.myri.com/scs/download-Myri10GE.html
+W:     https://www.myricom.com/support/downloads/myri10ge.html
 S:     Supported
 F:     drivers/net/ethernet/myricom/myri10ge/
 
@@ -5884,7 +5884,7 @@ F:        drivers/i2c/busses/i2c-omap.c
 F:     include/linux/i2c-omap.h
 
 OMAP DEVICE TREE SUPPORT
-M:     Benoît Cousson <b-cousson@ti.com>
+M:     Benoît Cousson <bcousson@baylibre.com>
 M:     Tony Lindgren <tony@atomide.com>
 L:     linux-omap@vger.kernel.org
 L:     devicetree@vger.kernel.org
@@ -5964,14 +5964,14 @@ S:      Maintained
 F:     drivers/char/hw_random/omap-rng.c
 
 OMAP HWMOD SUPPORT
-M:     Benoît Cousson <b-cousson@ti.com>
+M:     Benoît Cousson <bcousson@baylibre.com>
 M:     Paul Walmsley <paul@pwsan.com>
 L:     linux-omap@vger.kernel.org
 S:     Maintained
 F:     arch/arm/mach-omap2/omap_hwmod.*
 
 OMAP HWMOD DATA FOR OMAP4-BASED DEVICES
-M:     Benoît Cousson <b-cousson@ti.com>
+M:     Benoît Cousson <bcousson@baylibre.com>
 L:     linux-omap@vger.kernel.org
 S:     Maintained
 F:     arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -7366,7 +7366,6 @@ F:        drivers/net/ethernet/sfc/
 
 SGI GRU DRIVER
 M:     Dimitri Sivanich <sivanich@sgi.com>
-M:     Robin Holt <holt@sgi.com>
 S:     Maintained
 F:     drivers/misc/sgi-gru/
 
@@ -7386,7 +7385,8 @@ S:        Maintained for 2.6.
 F:     Documentation/sgi-visws.txt
 
 SGI XP/XPC/XPNET DRIVER
-M:     Robin Holt <holt@sgi.com>
+M:     Cliff Whickman <cpw@sgi.com>
+M:     Robin Holt <robinmholt@gmail.com>
 S:     Maintained
 F:     drivers/misc/sgi-xp/
 
index 6e48848..369882e 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 3
 PATCHLEVEL = 11
 SUBLEVEL = 0
-EXTRAVERSION = -rc5
+EXTRAVERSION = -rc7
 NAME = Linux for Workgroups
 
 # *DOCUMENTATION*
index 8d2ae24..1feb169 100644 (file)
@@ -407,6 +407,12 @@ config CLONE_BACKWARDS2
        help
          Architecture has the first two arguments of clone(2) swapped.
 
+config CLONE_BACKWARDS3
+       bool
+       help
+         Architecture has tls passed as the 3rd argument of clone(2),
+         not the 5th one.
+
 config ODD_RT_SIGACTION
        bool
        help
index 99c1047..9c548c7 100644 (file)
@@ -39,9 +39,18 @@ ARC_ENTRY strchr
        ld.a    r2,[r0,4]
        sub     r12,r6,r7
        bic     r12,r12,r6
+#ifdef __LITTLE_ENDIAN__
        and     r7,r12,r4
        breq    r7,0,.Loop ; For speed, we want this branch to be unaligned.
        b       .Lfound_char ; Likewise this one.
+#else
+       and     r12,r12,r4
+       breq    r12,0,.Loop ; For speed, we want this branch to be unaligned.
+       lsr_s   r12,r12,7
+       bic     r2,r7,r6
+       b.d     .Lfound_char_b
+       and_s   r2,r2,r12
+#endif
 ; /* We require this code address to be unaligned for speed...  */
 .Laligned:
        ld_s    r2,[r0]
@@ -95,6 +104,7 @@ ARC_ENTRY strchr
        lsr     r7,r7,7
 
        bic     r2,r7,r6
+.Lfound_char_b:
        norm    r2,r2
        sub_s   r0,r0,4
        asr_s   r2,r2,3
index d59b70c..3d77dbe 100644 (file)
        compatible = "atmel,at91sam9n12ek", "atmel,at91sam9n12", "atmel,at91sam9";
 
        chosen {
-               bootargs = "mem=128M console=ttyS0,115200 root=/dev/mtdblock1 rw rootfstype=jffs2";
+               bootargs = "console=ttyS0,115200 root=/dev/mtdblock1 rw rootfstype=jffs2";
        };
 
        memory {
-               reg = <0x20000000 0x10000000>;
+               reg = <0x20000000 0x8000000>;
        };
 
        clocks {
index b753855..49e3c45 100644 (file)
@@ -94,8 +94,9 @@
 
                usb0: ohci@00600000 {
                        status = "okay";
-                       num-ports = <2>;
-                       atmel,vbus-gpio = <&pioD 19 GPIO_ACTIVE_LOW
+                       num-ports = <3>;
+                       atmel,vbus-gpio = <0 /* &pioD 18 GPIO_ACTIVE_LOW *//* Activate to have access to port A */
+                                          &pioD 19 GPIO_ACTIVE_LOW
                                           &pioD 20 GPIO_ACTIVE_LOW
                                          >;
                };
index 365760b..40e6fb2 100644 (file)
                        regulator-max-microvolt = <5000000>;
                        enable-active-high;
                        gpio = <&gpio 24 0>; /* PD0 */
+                       regulator-always-on;
+                       regulator-boot-on;
                };
        };
 
index ed4b901..37c93d3 100644 (file)
                        regulator-max-microvolt = <5000000>;
                        enable-active-high;
                        gpio = <&gpio 170 0>; /* PV2 */
+                       regulator-always-on;
+                       regulator-boot-on;
                };
        };
 
index ab67c94..a3d0eba 100644 (file)
                        regulator-max-microvolt = <5000000>;
                        enable-active-high;
                        gpio = <&tca6416 0 0>; /* GPIO_PMU0 */
+                       regulator-always-on;
+                       regulator-boot-on;
                };
 
                vbus3_reg: regulator@3 {
                        regulator-max-microvolt = <5000000>;
                        enable-active-high;
                        gpio = <&tca6416 1 0>; /* GPIO_PMU1 */
+                       regulator-always-on;
+                       regulator-boot-on;
                };
        };
 
index 6462a72..a252c0b 100644 (file)
@@ -88,4 +88,7 @@ static inline u32 mpidr_hash_size(void)
 {
        return 1 << mpidr_hash.bits;
 }
+
+extern int platform_can_cpu_hotplug(void);
+
 #endif
index f8b8965..b07c09e 100644 (file)
@@ -107,7 +107,7 @@ static inline int arch_spin_trylock(arch_spinlock_t *lock)
                "       subs    %1, %0, %0, ror #16\n"
                "       addeq   %0, %0, %4\n"
                "       strexeq %2, %0, [%3]"
-               : "=&r" (slock), "=&r" (contended), "=r" (res)
+               : "=&r" (slock), "=&r" (contended), "=&r" (res)
                : "r" (&lock->slock), "I" (1 << TICKET_SHIFT)
                : "cc");
        } while (res);
@@ -168,17 +168,20 @@ static inline void arch_write_lock(arch_rwlock_t *rw)
 
 static inline int arch_write_trylock(arch_rwlock_t *rw)
 {
-       unsigned long tmp;
+       unsigned long contended, res;
 
-       __asm__ __volatile__(
-"      ldrex   %0, [%1]\n"
-"      teq     %0, #0\n"
-"      strexeq %0, %2, [%1]"
-       : "=&r" (tmp)
-       : "r" (&rw->lock), "r" (0x80000000)
-       : "cc");
+       do {
+               __asm__ __volatile__(
+               "       ldrex   %0, [%2]\n"
+               "       mov     %1, #0\n"
+               "       teq     %0, #0\n"
+               "       strexeq %1, %3, [%2]"
+               : "=&r" (contended), "=&r" (res)
+               : "r" (&rw->lock), "r" (0x80000000)
+               : "cc");
+       } while (res);
 
-       if (tmp == 0) {
+       if (!contended) {
                smp_mb();
                return 1;
        } else {
@@ -254,18 +257,26 @@ static inline void arch_read_unlock(arch_rwlock_t *rw)
 
 static inline int arch_read_trylock(arch_rwlock_t *rw)
 {
-       unsigned long tmp, tmp2 = 1;
+       unsigned long contended, res;
 
-       __asm__ __volatile__(
-"      ldrex   %0, [%2]\n"
-"      adds    %0, %0, #1\n"
-"      strexpl %1, %0, [%2]\n"
-       : "=&r" (tmp), "+r" (tmp2)
-       : "r" (&rw->lock)
-       : "cc");
+       do {
+               __asm__ __volatile__(
+               "       ldrex   %0, [%2]\n"
+               "       mov     %1, #0\n"
+               "       adds    %0, %0, #1\n"
+               "       strexpl %1, %0, [%2]"
+               : "=&r" (contended), "=&r" (res)
+               : "r" (&rw->lock)
+               : "cc");
+       } while (res);
 
-       smp_mb();
-       return tmp2 == 0;
+       /* If the lock is negative, then it is already held for write. */
+       if (contended < 0x80000000) {
+               smp_mb();
+               return 1;
+       } else {
+               return 0;
+       }
 }
 
 /* read_can_lock - would read_trylock() succeed? */
index 46e7cfb..0baf7f0 100644 (file)
@@ -43,6 +43,7 @@ struct mmu_gather {
        struct mm_struct        *mm;
        unsigned int            fullmm;
        struct vm_area_struct   *vma;
+       unsigned long           start, end;
        unsigned long           range_start;
        unsigned long           range_end;
        unsigned int            nr;
@@ -107,10 +108,12 @@ static inline void tlb_flush_mmu(struct mmu_gather *tlb)
 }
 
 static inline void
-tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned int fullmm)
+tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned long start, unsigned long end)
 {
        tlb->mm = mm;
-       tlb->fullmm = fullmm;
+       tlb->fullmm = !(start | (end+1));
+       tlb->start = start;
+       tlb->end = end;
        tlb->vma = NULL;
        tlb->max = ARRAY_SIZE(tlb->local);
        tlb->pages = tlb->local;
index d40d0ef..9cbe70c 100644 (file)
@@ -357,7 +357,8 @@ ENDPROC(__pabt_svc)
        .endm
 
        .macro  kuser_cmpxchg_check
-#if !defined(CONFIG_CPU_32v6K) && !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG)
+#if !defined(CONFIG_CPU_32v6K) && defined(CONFIG_KUSER_HELPERS) && \
+    !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG)
 #ifndef CONFIG_MMU
 #warning "NPTL on non MMU needs fixing"
 #else
index 25442f4..918875d 100644 (file)
@@ -84,17 +84,14 @@ int show_fiq_list(struct seq_file *p, int prec)
 
 void set_fiq_handler(void *start, unsigned int length)
 {
-#if defined(CONFIG_CPU_USE_DOMAINS)
-       void *base = (void *)0xffff0000;
-#else
        void *base = vectors_page;
-#endif
        unsigned offset = FIQ_OFFSET;
 
        memcpy(base + offset, start, length);
+       if (!cache_is_vipt_nonaliasing())
+               flush_icache_range((unsigned long)base + offset, offset +
+                                  length);
        flush_icache_range(0xffff0000 + offset, 0xffff0000 + offset + length);
-       if (!vectors_high())
-               flush_icache_range(offset, offset + length);
 }
 
 int claim_fiq(struct fiq_handler *f)
index 4fb074c..57221e3 100644 (file)
@@ -15,6 +15,7 @@
 #include <asm/mmu_context.h>
 #include <asm/cacheflush.h>
 #include <asm/mach-types.h>
+#include <asm/smp_plat.h>
 #include <asm/system_misc.h>
 
 extern const unsigned char relocate_new_kernel[];
@@ -38,6 +39,14 @@ int machine_kexec_prepare(struct kimage *image)
        __be32 header;
        int i, err;
 
+       /*
+        * Validate that if the current HW supports SMP, then the SW supports
+        * and implements CPU hotplug for the current HW. If not, we won't be
+        * able to kexec reliably, so fail the prepare operation.
+        */
+       if (num_possible_cpus() > 1 && !platform_can_cpu_hotplug())
+               return -EINVAL;
+
        /*
         * No segment at default ATAGs address. try to locate
         * a dtb using magic.
@@ -73,6 +82,7 @@ void machine_crash_nonpanic_core(void *unused)
        crash_save_cpu(&regs, smp_processor_id());
        flush_cache_all();
 
+       set_cpu_online(smp_processor_id(), false);
        atomic_dec(&waiting_for_crash_ipi);
        while (1)
                cpu_relax();
@@ -134,10 +144,13 @@ void machine_kexec(struct kimage *image)
        unsigned long reboot_code_buffer_phys;
        void *reboot_code_buffer;
 
-       if (num_online_cpus() > 1) {
-               pr_err("kexec: error: multiple CPUs still online\n");
-               return;
-       }
+       /*
+        * This can only happen if machine_shutdown() failed to disable some
+        * CPU, and that can only happen if the checks in
+        * machine_kexec_prepare() were not correct. If this fails, we can't
+        * reliably kexec anyway, so BUG_ON is appropriate.
+        */
+       BUG_ON(num_online_cpus() > 1);
 
        page_list = image->head & PAGE_MASK;
 
index d9f5cd4..e186ee1 100644 (file)
@@ -53,7 +53,12 @@ armpmu_map_cache_event(const unsigned (*cache_map)
 static int
 armpmu_map_hw_event(const unsigned (*event_map)[PERF_COUNT_HW_MAX], u64 config)
 {
-       int mapping = (*event_map)[config];
+       int mapping;
+
+       if (config >= PERF_COUNT_HW_MAX)
+               return -EINVAL;
+
+       mapping = (*event_map)[config];
        return mapping == HW_OP_UNSUPPORTED ? -ENOENT : mapping;
 }
 
@@ -253,6 +258,9 @@ validate_event(struct pmu_hw_events *hw_events,
        struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
        struct pmu *leader_pmu = event->group_leader->pmu;
 
+       if (is_software_event(event))
+               return 1;
+
        if (event->pmu != leader_pmu || event->state < PERF_EVENT_STATE_OFF)
                return 1;
 
index 536c85f..94f6b05 100644 (file)
@@ -462,7 +462,7 @@ int in_gate_area_no_mm(unsigned long addr)
 {
        return in_gate_area(NULL, addr);
 }
-#define is_gate_vma(vma)       ((vma) = &gate_vma)
+#define is_gate_vma(vma)       ((vma) == &gate_vma)
 #else
 #define is_gate_vma(vma)       0
 #endif
index c2b4f8f..2dc1934 100644 (file)
@@ -145,6 +145,16 @@ int boot_secondary(unsigned int cpu, struct task_struct *idle)
        return -ENOSYS;
 }
 
+int platform_can_cpu_hotplug(void)
+{
+#ifdef CONFIG_HOTPLUG_CPU
+       if (smp_ops.cpu_kill)
+               return 1;
+#endif
+
+       return 0;
+}
+
 #ifdef CONFIG_HOTPLUG_CPU
 static void percpu_timer_stop(void);
 
index 4a51990..db9cf69 100644 (file)
@@ -146,7 +146,11 @@ static bool pm_fake(struct kvm_vcpu *vcpu,
 #define access_pmintenclr pm_fake
 
 /* Architected CP15 registers.
- * Important: Must be sorted ascending by CRn, CRM, Op1, Op2
+ * CRn denotes the primary register number, but is copied to the CRm in the
+ * user space API for 64-bit register access in line with the terminology used
+ * in the ARM ARM.
+ * Important: Must be sorted ascending by CRn, CRM, Op1, Op2 and with 64-bit
+ *            registers preceding 32-bit ones.
  */
 static const struct coproc_reg cp15_regs[] = {
        /* CSSELR: swapped by interrupt.S. */
@@ -154,8 +158,8 @@ static const struct coproc_reg cp15_regs[] = {
                        NULL, reset_unknown, c0_CSSELR },
 
        /* TTBR0/TTBR1: swapped by interrupt.S. */
-       { CRm( 2), Op1( 0), is64, NULL, reset_unknown64, c2_TTBR0 },
-       { CRm( 2), Op1( 1), is64, NULL, reset_unknown64, c2_TTBR1 },
+       { CRm64( 2), Op1( 0), is64, NULL, reset_unknown64, c2_TTBR0 },
+       { CRm64( 2), Op1( 1), is64, NULL, reset_unknown64, c2_TTBR1 },
 
        /* TTBCR: swapped by interrupt.S. */
        { CRn( 2), CRm( 0), Op1( 0), Op2( 2), is32,
@@ -182,7 +186,7 @@ static const struct coproc_reg cp15_regs[] = {
                        NULL, reset_unknown, c6_IFAR },
 
        /* PAR swapped by interrupt.S */
-       { CRn( 7), Op1( 0), is64, NULL, reset_unknown64, c7_PAR },
+       { CRm64( 7), Op1( 0), is64, NULL, reset_unknown64, c7_PAR },
 
        /*
         * DC{C,I,CI}SW operations:
@@ -399,12 +403,13 @@ static bool index_to_params(u64 id, struct coproc_params *params)
                              | KVM_REG_ARM_OPC1_MASK))
                        return false;
                params->is_64bit = true;
-               params->CRm = ((id & KVM_REG_ARM_CRM_MASK)
+               /* CRm to CRn: see cp15_to_index for details */
+               params->CRn = ((id & KVM_REG_ARM_CRM_MASK)
                               >> KVM_REG_ARM_CRM_SHIFT);
                params->Op1 = ((id & KVM_REG_ARM_OPC1_MASK)
                               >> KVM_REG_ARM_OPC1_SHIFT);
                params->Op2 = 0;
-               params->CRn = 0;
+               params->CRm = 0;
                return true;
        default:
                return false;
@@ -898,7 +903,14 @@ static u64 cp15_to_index(const struct coproc_reg *reg)
        if (reg->is_64) {
                val |= KVM_REG_SIZE_U64;
                val |= (reg->Op1 << KVM_REG_ARM_OPC1_SHIFT);
-               val |= (reg->CRm << KVM_REG_ARM_CRM_SHIFT);
+               /*
+                * CRn always denotes the primary coproc. reg. nr. for the
+                * in-kernel representation, but the user space API uses the
+                * CRm for the encoding, because it is modelled after the
+                * MRRC/MCRR instructions: see the ARM ARM rev. c page
+                * B3-1445
+                */
+               val |= (reg->CRn << KVM_REG_ARM_CRM_SHIFT);
        } else {
                val |= KVM_REG_SIZE_U32;
                val |= (reg->Op1 << KVM_REG_ARM_OPC1_SHIFT);
index b7301d3..0461d5c 100644 (file)
@@ -135,6 +135,8 @@ static inline int cmp_reg(const struct coproc_reg *i1,
                return -1;
        if (i1->CRn != i2->CRn)
                return i1->CRn - i2->CRn;
+       if (i1->is_64 != i2->is_64)
+               return i2->is_64 - i1->is_64;
        if (i1->CRm != i2->CRm)
                return i1->CRm - i2->CRm;
        if (i1->Op1 != i2->Op1)
@@ -145,6 +147,7 @@ static inline int cmp_reg(const struct coproc_reg *i1,
 
 #define CRn(_x)                .CRn = _x
 #define CRm(_x)        .CRm = _x
+#define CRm64(_x)       .CRn = _x, .CRm = 0
 #define Op1(_x)        .Op1 = _x
 #define Op2(_x)        .Op2 = _x
 #define is64           .is_64 = true
index 685063a..cf93472 100644 (file)
@@ -114,7 +114,11 @@ static bool access_l2ectlr(struct kvm_vcpu *vcpu,
 
 /*
  * A15-specific CP15 registers.
- * Important: Must be sorted ascending by CRn, CRM, Op1, Op2
+ * CRn denotes the primary register number, but is copied to the CRm in the
+ * user space API for 64-bit register access in line with the terminology used
+ * in the ARM ARM.
+ * Important: Must be sorted ascending by CRn, CRM, Op1, Op2 and with 64-bit
+ *            registers preceding 32-bit ones.
  */
 static const struct coproc_reg a15_regs[] = {
        /* MPIDR: we use VMPIDR for guest access. */
index b8e06b7..0c25d94 100644 (file)
@@ -63,7 +63,8 @@ int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run)
 static int decode_hsr(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
                      struct kvm_exit_mmio *mmio)
 {
-       unsigned long rt, len;
+       unsigned long rt;
+       int len;
        bool is_write, sign_extend;
 
        if (kvm_vcpu_dabt_isextabt(vcpu)) {
index ca6bea4..0988d9e 100644 (file)
@@ -85,6 +85,12 @@ static void *mmu_memory_cache_alloc(struct kvm_mmu_memory_cache *mc)
        return p;
 }
 
+static bool page_empty(void *ptr)
+{
+       struct page *ptr_page = virt_to_page(ptr);
+       return page_count(ptr_page) == 1;
+}
+
 static void clear_pud_entry(struct kvm *kvm, pud_t *pud, phys_addr_t addr)
 {
        pmd_t *pmd_table = pmd_offset(pud, 0);
@@ -103,12 +109,6 @@ static void clear_pmd_entry(struct kvm *kvm, pmd_t *pmd, phys_addr_t addr)
        put_page(virt_to_page(pmd));
 }
 
-static bool pmd_empty(pmd_t *pmd)
-{
-       struct page *pmd_page = virt_to_page(pmd);
-       return page_count(pmd_page) == 1;
-}
-
 static void clear_pte_entry(struct kvm *kvm, pte_t *pte, phys_addr_t addr)
 {
        if (pte_present(*pte)) {
@@ -118,12 +118,6 @@ static void clear_pte_entry(struct kvm *kvm, pte_t *pte, phys_addr_t addr)
        }
 }
 
-static bool pte_empty(pte_t *pte)
-{
-       struct page *pte_page = virt_to_page(pte);
-       return page_count(pte_page) == 1;
-}
-
 static void unmap_range(struct kvm *kvm, pgd_t *pgdp,
                        unsigned long long start, u64 size)
 {
@@ -132,37 +126,37 @@ static void unmap_range(struct kvm *kvm, pgd_t *pgdp,
        pmd_t *pmd;
        pte_t *pte;
        unsigned long long addr = start, end = start + size;
-       u64 range;
+       u64 next;
 
        while (addr < end) {
                pgd = pgdp + pgd_index(addr);
                pud = pud_offset(pgd, addr);
                if (pud_none(*pud)) {
-                       addr += PUD_SIZE;
+                       addr = pud_addr_end(addr, end);
                        continue;
                }
 
                pmd = pmd_offset(pud, addr);
                if (pmd_none(*pmd)) {
-                       addr += PMD_SIZE;
+                       addr = pmd_addr_end(addr, end);
                        continue;
                }
 
                pte = pte_offset_kernel(pmd, addr);
                clear_pte_entry(kvm, pte, addr);
-               range = PAGE_SIZE;
+               next = addr + PAGE_SIZE;
 
                /* If we emptied the pte, walk back up the ladder */
-               if (pte_empty(pte)) {
+               if (page_empty(pte)) {
                        clear_pmd_entry(kvm, pmd, addr);
-                       range = PMD_SIZE;
-                       if (pmd_empty(pmd)) {
+                       next = pmd_addr_end(addr, end);
+                       if (page_empty(pmd) && !page_empty(pud)) {
                                clear_pud_entry(kvm, pud, addr);
-                               range = PUD_SIZE;
+                               next = pud_addr_end(addr, end);
                        }
                }
 
-               addr += range;
+               addr = next;
        }
 }
 
index 2abee66..916e5a1 100644 (file)
@@ -227,6 +227,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_DEV_ID("usart", "f8020000.serial", &usart1_clk),
        CLKDEV_CON_DEV_ID("usart", "f8024000.serial", &usart2_clk),
        CLKDEV_CON_DEV_ID("usart", "f8028000.serial", &usart3_clk),
+       CLKDEV_CON_DEV_ID("usart", "f8040000.serial", &uart0_clk),
+       CLKDEV_CON_DEV_ID("usart", "f8044000.serial", &uart1_clk),
        CLKDEV_CON_DEV_ID("t0_clk", "f8008000.timer", &tcb0_clk),
        CLKDEV_CON_DEV_ID("t0_clk", "f800c000.timer", &tcb0_clk),
        CLKDEV_CON_DEV_ID("mci_clk", "f0008000.mmc", &mmc0_clk),
index dff4ddc..139e42d 100644 (file)
@@ -75,6 +75,7 @@ static struct davinci_nand_pdata davinci_nand_data = {
        .parts                  = davinci_nand_partitions,
        .nr_parts               = ARRAY_SIZE(davinci_nand_partitions),
        .ecc_mode               = NAND_ECC_HW_SYNDROME,
+       .ecc_bits               = 4,
        .bbt_options            = NAND_BBT_USE_FLASH,
 };
 
index a33686a..fa4bfaf 100644 (file)
@@ -153,6 +153,7 @@ static struct davinci_nand_pdata davinci_evm_nandflash_data = {
        .parts          = davinci_evm_nandflash_partition,
        .nr_parts       = ARRAY_SIZE(davinci_evm_nandflash_partition),
        .ecc_mode       = NAND_ECC_HW,
+       .ecc_bits       = 1,
        .bbt_options    = NAND_BBT_USE_FLASH,
        .timing         = &davinci_evm_nandflash_timing,
 };
index fbb8e5a..0c005e8 100644 (file)
@@ -90,6 +90,7 @@ static struct davinci_nand_pdata davinci_nand_data = {
        .parts                  = davinci_nand_partitions,
        .nr_parts               = ARRAY_SIZE(davinci_nand_partitions),
        .ecc_mode               = NAND_ECC_HW,
+       .ecc_bits               = 1,
        .options                = 0,
 };
 
index 2bc112a..808233b 100644 (file)
@@ -88,6 +88,7 @@ static struct davinci_nand_pdata davinci_ntosd2_nandflash_data = {
        .parts          = davinci_ntosd2_nandflash_partition,
        .nr_parts       = ARRAY_SIZE(davinci_ntosd2_nandflash_partition),
        .ecc_mode       = NAND_ECC_HW,
+       .ecc_bits       = 1,
        .bbt_options    = NAND_BBT_USE_FLASH,
 };
 
index f6eeb87..827d150 100644 (file)
@@ -122,11 +122,7 @@ static struct musb_hdrc_config musb_config = {
 };
 
 static struct musb_hdrc_platform_data tusb_data = {
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
        .mode           = MUSB_OTG,
-#else
-       .mode           = MUSB_HOST,
-#endif
        .set_power      = tusb_set_power,
        .min_power      = 25,   /* x2 = 50 mA drawn from VBUS as peripheral */
        .power          = 100,  /* Max 100 mA VBUS for host mode */
index d2ea68e..7735105 100644 (file)
@@ -85,7 +85,7 @@ static struct omap_board_mux board_mux[] __initdata = {
 
 static struct omap_musb_board_data musb_board_data = {
        .interface_type         = MUSB_INTERFACE_ULPI,
-       .mode                   = MUSB_PERIPHERAL,
+       .mode                   = MUSB_OTG,
        .power                  = 0,
 };
 
index 8c4de27..bc89723 100644 (file)
@@ -38,11 +38,8 @@ static struct musb_hdrc_config musb_config = {
 };
 
 static struct musb_hdrc_platform_data musb_plat = {
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
        .mode           = MUSB_OTG,
-#else
-       .mode           = MUSB_HOST,
-#endif
+
        /* .clock is set dynamically */
        .config         = &musb_config,
 
index db5c2ca..cd2c88e 100644 (file)
@@ -809,15 +809,18 @@ config KUSER_HELPERS
          the CPU type fitted to the system.  This permits binaries to be
          run on ARMv4 through to ARMv7 without modification.
 
+         See Documentation/arm/kernel_user_helpers.txt for details.
+
          However, the fixed address nature of these helpers can be used
          by ROP (return orientated programming) authors when creating
          exploits.
 
          If all of the binaries and libraries which run on your platform
          are built specifically for your platform, and make no use of
-         these helpers, then you can turn this option off.  However,
-         when such an binary or library is run, it will receive a SIGILL
-         signal, which will terminate the program.
+         these helpers, then you can turn this option off to hinder
+         such exploits. However, in that case, if a binary or library
+         relying on those helpers is run, it will receive a SIGILL signal,
+         which will terminate the program.
 
          Say N here only if you are absolutely certain that you do not
          need these helpers; otherwise, the safe option is to say Y.
index 3e5c461..50a3ea0 100644 (file)
@@ -55,12 +55,13 @@ void __init s3c_init_cpu(unsigned long idcode,
 
        printk("CPU %s (id 0x%08lx)\n", cpu->name, idcode);
 
-       if (cpu->map_io == NULL || cpu->init == NULL) {
+       if (cpu->init == NULL) {
                printk(KERN_ERR "CPU %s support not enabled\n", cpu->name);
                panic("Unsupported Samsung CPU");
        }
 
-       cpu->map_io();
+       if (cpu->map_io)
+               cpu->map_io();
 }
 
 /* s3c24xx_init_clocks
index c9770ba..8a6295c 100644 (file)
@@ -170,6 +170,7 @@ static void __init xen_percpu_init(void *unused)
        per_cpu(xen_vcpu, cpu) = vcpup;
 
        enable_percpu_irq(xen_events_irq, 0);
+       put_cpu();
 }
 
 static void xen_restart(enum reboot_mode reboot_mode, const char *cmd)
index c92de41..b25763b 100644 (file)
 #define        TPIDR_EL1       18      /* Thread ID, Privileged */
 #define        AMAIR_EL1       19      /* Aux Memory Attribute Indirection Register */
 #define        CNTKCTL_EL1     20      /* Timer Control Register (EL1) */
+#define        PAR_EL1         21      /* Physical Address Register */
 /* 32bit specific registers. Keep them at the end of the range */
-#define        DACR32_EL2      21      /* Domain Access Control Register */
-#define        IFSR32_EL2      22      /* Instruction Fault Status Register */
-#define        FPEXC32_EL2     23      /* Floating-Point Exception Control Register */
-#define        DBGVCR32_EL2    24      /* Debug Vector Catch Register */
-#define        TEECR32_EL1     25      /* ThumbEE Configuration Register */
-#define        TEEHBR32_EL1    26      /* ThumbEE Handler Base Register */
-#define        NR_SYS_REGS     27
+#define        DACR32_EL2      22      /* Domain Access Control Register */
+#define        IFSR32_EL2      23      /* Instruction Fault Status Register */
+#define        FPEXC32_EL2     24      /* Floating-Point Exception Control Register */
+#define        DBGVCR32_EL2    25      /* Debug Vector Catch Register */
+#define        TEECR32_EL1     26      /* ThumbEE Configuration Register */
+#define        TEEHBR32_EL1    27      /* ThumbEE Handler Base Register */
+#define        NR_SYS_REGS     28
 
 /* 32bit mapping */
 #define c0_MPIDR       (MPIDR_EL1 * 2) /* MultiProcessor ID Register */
@@ -69,6 +70,8 @@
 #define c5_AIFSR       (AFSR1_EL1 * 2) /* Auxiliary Instr Fault Status R */
 #define c6_DFAR                (FAR_EL1 * 2)   /* Data Fault Address Register */
 #define c6_IFAR                (c6_DFAR + 1)   /* Instruction Fault Address Register */
+#define c7_PAR         (PAR_EL1 * 2)   /* Physical Address Register */
+#define c7_PAR_high    (c7_PAR + 1)    /* PAR top 32 bits */
 #define c10_PRRR       (MAIR_EL1 * 2)  /* Primary Region Remap Register */
 #define c10_NMRR       (c10_PRRR + 1)  /* Normal Memory Remap Register */
 #define c12_VBAR       (VBAR_EL1 * 2)  /* Vector Base Address Register */
index 644d739..0859a4d 100644 (file)
@@ -129,7 +129,7 @@ struct kvm_vcpu_arch {
        struct kvm_mmu_memory_cache mmu_page_cache;
 
        /* Target CPU and feature flags */
-       u32 target;
+       int target;
        DECLARE_BITMAP(features, KVM_VCPU_MAX_FEATURES);
 
        /* Detect first run of a vcpu */
index 46b3beb..717031a 100644 (file)
@@ -35,6 +35,7 @@ struct mmu_gather {
        struct mm_struct        *mm;
        unsigned int            fullmm;
        struct vm_area_struct   *vma;
+       unsigned long           start, end;
        unsigned long           range_start;
        unsigned long           range_end;
        unsigned int            nr;
@@ -97,10 +98,12 @@ static inline void tlb_flush_mmu(struct mmu_gather *tlb)
 }
 
 static inline void
-tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned int fullmm)
+tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned long start, unsigned long end)
 {
        tlb->mm = mm;
-       tlb->fullmm = fullmm;
+       tlb->fullmm = !(start | (end+1));
+       tlb->start = start;
+       tlb->end = end;
        tlb->vma = NULL;
        tlb->max = ARRAY_SIZE(tlb->local);
        tlb->pages = tlb->local;
index 9ba33c4..12e6ccb 100644 (file)
@@ -107,7 +107,12 @@ armpmu_map_cache_event(const unsigned (*cache_map)
 static int
 armpmu_map_event(const unsigned (*event_map)[PERF_COUNT_HW_MAX], u64 config)
 {
-       int mapping = (*event_map)[config];
+       int mapping;
+
+       if (config >= PERF_COUNT_HW_MAX)
+               return -EINVAL;
+
+       mapping = (*event_map)[config];
        return mapping == HW_OP_UNSUPPORTED ? -ENOENT : mapping;
 }
 
@@ -317,6 +322,9 @@ validate_event(struct pmu_hw_events *hw_events,
        struct hw_perf_event fake_event = event->hw;
        struct pmu *leader_pmu = event->group_leader->pmu;
 
+       if (is_software_event(event))
+               return 1;
+
        if (event->pmu != leader_pmu || event->state <= PERF_EVENT_STATE_OFF)
                return 1;
 
index ff985e3..1ac0bbb 100644 (file)
@@ -214,6 +214,7 @@ __kvm_hyp_code_start:
        mrs     x21,    tpidr_el1
        mrs     x22,    amair_el1
        mrs     x23,    cntkctl_el1
+       mrs     x24,    par_el1
 
        stp     x4, x5, [x3]
        stp     x6, x7, [x3, #16]
@@ -225,6 +226,7 @@ __kvm_hyp_code_start:
        stp     x18, x19, [x3, #112]
        stp     x20, x21, [x3, #128]
        stp     x22, x23, [x3, #144]
+       str     x24, [x3, #160]
 .endm
 
 .macro restore_sysregs
@@ -243,6 +245,7 @@ __kvm_hyp_code_start:
        ldp     x18, x19, [x3, #112]
        ldp     x20, x21, [x3, #128]
        ldp     x22, x23, [x3, #144]
+       ldr     x24, [x3, #160]
 
        msr     vmpidr_el2,     x4
        msr     csselr_el1,     x5
@@ -264,6 +267,7 @@ __kvm_hyp_code_start:
        msr     tpidr_el1,      x21
        msr     amair_el1,      x22
        msr     cntkctl_el1,    x23
+       msr     par_el1,        x24
 .endm
 
 .macro skip_32bit_state tmp, target
@@ -600,6 +604,8 @@ END(__kvm_vcpu_run)
 
 // void __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa);
 ENTRY(__kvm_tlb_flush_vmid_ipa)
+       dsb     ishst
+
        kern_hyp_va     x0
        ldr     x2, [x0, #KVM_VTTBR]
        msr     vttbr_el2, x2
@@ -621,6 +627,7 @@ ENTRY(__kvm_tlb_flush_vmid_ipa)
 ENDPROC(__kvm_tlb_flush_vmid_ipa)
 
 ENTRY(__kvm_flush_vm_context)
+       dsb     ishst
        tlbi    alle1is
        ic      ialluis
        dsb     sy
@@ -753,6 +760,10 @@ el1_trap:
         */
        tbnz    x1, #7, 1f      // S1PTW is set
 
+       /* Preserve PAR_EL1 */
+       mrs     x3, par_el1
+       push    x3, xzr
+
        /*
         * Permission fault, HPFAR_EL2 is invalid.
         * Resolve the IPA the hard way using the guest VA.
@@ -766,6 +777,8 @@ el1_trap:
 
        /* Read result */
        mrs     x3, par_el1
+       pop     x0, xzr                 // Restore PAR_EL1 from the stack
+       msr     par_el1, x0
        tbnz    x3, #0, 3f              // Bail out if we failed the translation
        ubfx    x3, x3, #12, #36        // Extract IPA
        lsl     x3, x3, #4              // and present it like HPFAR
index 9492360..02e9d09 100644 (file)
@@ -211,6 +211,9 @@ static const struct sys_reg_desc sys_reg_descs[] = {
        /* FAR_EL1 */
        { Op0(0b11), Op1(0b000), CRn(0b0110), CRm(0b0000), Op2(0b000),
          NULL, reset_unknown, FAR_EL1 },
+       /* PAR_EL1 */
+       { Op0(0b11), Op1(0b000), CRn(0b0111), CRm(0b0100), Op2(0b000),
+         NULL, reset_unknown, PAR_EL1 },
 
        /* PMINTENSET_EL1 */
        { Op0(0b11), Op1(0b000), CRn(0b1001), CRm(0b1110), Op2(0b001),
index 33a9792..77d442a 100644 (file)
@@ -158,6 +158,7 @@ source "kernel/Kconfig.hz"
 endmenu
 
 source "init/Kconfig"
+source "kernel/Kconfig.freezer"
 source "drivers/Kconfig"
 source "fs/Kconfig"
 
index ef3a9de..bc5efc7 100644 (file)
@@ -22,7 +22,7 @@
  * unmapping a portion of the virtual address space, these hooks are called according to
  * the following template:
  *
- *     tlb <- tlb_gather_mmu(mm, full_mm_flush);       // start unmap for address space MM
+ *     tlb <- tlb_gather_mmu(mm, start, end);          // start unmap for address space MM
  *     {
  *       for each vma that needs a shootdown do {
  *         tlb_start_vma(tlb, vma);
@@ -58,6 +58,7 @@ struct mmu_gather {
        unsigned int            max;
        unsigned char           fullmm;         /* non-zero means full mm flush */
        unsigned char           need_flush;     /* really unmapped some PTEs? */
+       unsigned long           start, end;
        unsigned long           start_addr;
        unsigned long           end_addr;
        struct page             **pages;
@@ -155,13 +156,15 @@ static inline void __tlb_alloc_page(struct mmu_gather *tlb)
 
 
 static inline void
-tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned int full_mm_flush)
+tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned long start, unsigned long end)
 {
        tlb->mm = mm;
        tlb->max = ARRAY_SIZE(tlb->local);
        tlb->pages = tlb->local;
        tlb->nr = 0;
-       tlb->fullmm = full_mm_flush;
+       tlb->fullmm = !(start | (end+1));
+       tlb->start = start;
+       tlb->end = end;
        tlb->start_addr = ~0UL;
 }
 
index 2291a7d..fa277ae 100644 (file)
 #include <asm/machdep.h>
 #include <asm/natfeat.h>
 
+extern long nf_get_id2(const char *feature_name);
+
 asm("\n"
-"      .global nf_get_id,nf_call\n"
-"nf_get_id:\n"
+"      .global nf_get_id2,nf_call\n"
+"nf_get_id2:\n"
 "      .short  0x7300\n"
 "      rts\n"
 "nf_call:\n"
@@ -29,12 +31,25 @@ asm("\n"
 "1:    moveq.l #0,%d0\n"
 "      rts\n"
 "      .section __ex_table,\"a\"\n"
-"      .long   nf_get_id,1b\n"
+"      .long   nf_get_id2,1b\n"
 "      .long   nf_call,1b\n"
 "      .previous");
-EXPORT_SYMBOL_GPL(nf_get_id);
 EXPORT_SYMBOL_GPL(nf_call);
 
+long nf_get_id(const char *feature_name)
+{
+       /* feature_name may be in vmalloc()ed memory, so make a copy */
+       char name_copy[32];
+       size_t n;
+
+       n = strlcpy(name_copy, feature_name, sizeof(name_copy));
+       if (n >= sizeof(name_copy))
+               return 0;
+
+       return nf_get_id2(name_copy);
+}
+EXPORT_SYMBOL_GPL(nf_get_id);
+
 void nfprint(const char *fmt, ...)
 {
        static char buf[256];
index 444ea8a..ef881cf 100644 (file)
                unsigned long long n64;                         \
        } __n;                                                  \
        unsigned long __rem, __upper;                           \
+       unsigned long __base = (base);                          \
                                                                \
        __n.n64 = (n);                                          \
        if ((__upper = __n.n32[0])) {                           \
                asm ("divul.l %2,%1:%0"                         \
-                       : "=d" (__n.n32[0]), "=d" (__upper)     \
-                       : "d" (base), "0" (__n.n32[0]));        \
+                    : "=d" (__n.n32[0]), "=d" (__upper)        \
+                    : "d" (__base), "0" (__n.n32[0]));         \
        }                                                       \
        asm ("divu.l %2,%1:%0"                                  \
-               : "=d" (__n.n32[1]), "=d" (__rem)               \
-               : "d" (base), "1" (__upper), "0" (__n.n32[1])); \
+            : "=d" (__n.n32[1]), "=d" (__rem)                  \
+            : "d" (__base), "1" (__upper), "0" (__n.n32[1]));  \
        (n) = __n.n64;                                          \
        __rem;                                                  \
 })
index d22a4ec..4fab522 100644 (file)
@@ -28,7 +28,7 @@ config MICROBLAZE
        select GENERIC_CLOCKEVENTS
        select GENERIC_IDLE_POLL_SETUP
        select MODULES_USE_ELF_RELA
-       select CLONE_BACKWARDS
+       select CLONE_BACKWARDS3
 
 config SWAP
        def_bool n
index e773659..46048d2 100644 (file)
@@ -803,6 +803,32 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
                                dec_insn.next_pc_inc;
                return 1;
                break;
+#ifdef CONFIG_CPU_CAVIUM_OCTEON
+       case lwc2_op: /* This is bbit0 on Octeon */
+               if ((regs->regs[insn.i_format.rs] & (1ull<<insn.i_format.rt)) == 0)
+                       *contpc = regs->cp0_epc + 4 + (insn.i_format.simmediate << 2);
+               else
+                       *contpc = regs->cp0_epc + 8;
+               return 1;
+       case ldc2_op: /* This is bbit032 on Octeon */
+               if ((regs->regs[insn.i_format.rs] & (1ull<<(insn.i_format.rt + 32))) == 0)
+                       *contpc = regs->cp0_epc + 4 + (insn.i_format.simmediate << 2);
+               else
+                       *contpc = regs->cp0_epc + 8;
+               return 1;
+       case swc2_op: /* This is bbit1 on Octeon */
+               if (regs->regs[insn.i_format.rs] & (1ull<<insn.i_format.rt))
+                       *contpc = regs->cp0_epc + 4 + (insn.i_format.simmediate << 2);
+               else
+                       *contpc = regs->cp0_epc + 8;
+               return 1;
+       case sdc2_op: /* This is bbit132 on Octeon */
+               if (regs->regs[insn.i_format.rs] & (1ull<<(insn.i_format.rt + 32)))
+                       *contpc = regs->cp0_epc + 4 + (insn.i_format.simmediate << 2);
+               else
+                       *contpc = regs->cp0_epc + 8;
+               return 1;
+#endif
        case cop0_op:
        case cop1_op:
        case cop2_op:
index 99dbab1..d60bf98 100644 (file)
@@ -55,6 +55,7 @@ config GENERIC_CSUM
 
 source "init/Kconfig"
 
+source "kernel/Kconfig.freezer"
 
 menu "Processor type and features"
 
index b75d7d6..6d6d92b 100644 (file)
@@ -32,6 +32,7 @@ struct mmu_gather {
        struct mm_struct *mm;
        struct mmu_table_batch *batch;
        unsigned int fullmm;
+       unsigned long start, end;
 };
 
 struct mmu_table_batch {
@@ -48,10 +49,13 @@ extern void tlb_remove_table(struct mmu_gather *tlb, void *table);
 
 static inline void tlb_gather_mmu(struct mmu_gather *tlb,
                                  struct mm_struct *mm,
-                                 unsigned int full_mm_flush)
+                                 unsigned long start,
+                                 unsigned long end)
 {
        tlb->mm = mm;
-       tlb->fullmm = full_mm_flush;
+       tlb->start = start;
+       tlb->end = end;
+       tlb->fullmm = !(start | (end+1));
        tlb->batch = NULL;
        if (tlb->fullmm)
                __tlb_flush_mm(mm);
index c8def8b..5fc2375 100644 (file)
@@ -87,6 +87,8 @@ config STACKTRACE_SUPPORT
 
 source "init/Kconfig"
 
+source "kernel/Kconfig.freezer"
+
 config MMU
        def_bool y
 
index e61d43d..362192e 100644 (file)
@@ -36,10 +36,12 @@ static inline void init_tlb_gather(struct mmu_gather *tlb)
 }
 
 static inline void
-tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned int full_mm_flush)
+tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned long start, unsigned long end)
 {
        tlb->mm = mm;
-       tlb->fullmm = full_mm_flush;
+       tlb->start = start;
+       tlb->end = end;
+       tlb->fullmm = !(start | (end+1));
 
        init_tlb_gather(tlb);
 }
index 4febacd..29b0301 100644 (file)
@@ -45,10 +45,12 @@ static inline void init_tlb_gather(struct mmu_gather *tlb)
 }
 
 static inline void
-tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned int full_mm_flush)
+tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned long start, unsigned long end)
 {
        tlb->mm = mm;
-       tlb->fullmm = full_mm_flush;
+       tlb->start = start;
+       tlb->end = end;
+       tlb->fullmm = !(start | (end+1));
 
        init_tlb_gather(tlb);
 }
index 653668d..4a8cb8d 100644 (file)
@@ -35,9 +35,9 @@ static void sanitize_boot_params(struct boot_params *boot_params)
         */
        if (boot_params->sentinel) {
                /* fields in boot_params are left uninitialized, clear them */
-               memset(&boot_params->olpc_ofw_header, 0,
+               memset(&boot_params->ext_ramdisk_image, 0,
                       (char *)&boot_params->efi_info -
-                       (char *)&boot_params->olpc_ofw_header);
+                       (char *)&boot_params->ext_ramdisk_image);
                memset(&boot_params->kbd_status, 0,
                       (char *)&boot_params->hdr -
                       (char *)&boot_params->kbd_status);
index 50e5c58..4c01917 100644 (file)
@@ -59,7 +59,7 @@ static inline u16 find_equiv_id(struct equiv_cpu_entry *equiv_cpu_table,
 
 extern int __apply_microcode_amd(struct microcode_amd *mc_amd);
 extern int apply_microcode_amd(int cpu);
-extern enum ucode_state load_microcode_amd(int cpu, const u8 *data, size_t size);
+extern enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t size);
 
 #ifdef CONFIG_MICROCODE_AMD_EARLY
 #ifdef CONFIG_X86_32
index f2b489c..3bf2dd0 100644 (file)
@@ -55,9 +55,53 @@ static inline pmd_t native_pmdp_get_and_clear(pmd_t *xp)
 #define native_pmdp_get_and_clear(xp) native_local_pmdp_get_and_clear(xp)
 #endif
 
+#ifdef CONFIG_MEM_SOFT_DIRTY
+
+/*
+ * Bits _PAGE_BIT_PRESENT, _PAGE_BIT_FILE, _PAGE_BIT_SOFT_DIRTY and
+ * _PAGE_BIT_PROTNONE are taken, split up the 28 bits of offset
+ * into this range.
+ */
+#define PTE_FILE_MAX_BITS      28
+#define PTE_FILE_SHIFT1                (_PAGE_BIT_PRESENT + 1)
+#define PTE_FILE_SHIFT2                (_PAGE_BIT_FILE + 1)
+#define PTE_FILE_SHIFT3                (_PAGE_BIT_PROTNONE + 1)
+#define PTE_FILE_SHIFT4                (_PAGE_BIT_SOFT_DIRTY + 1)
+#define PTE_FILE_BITS1         (PTE_FILE_SHIFT2 - PTE_FILE_SHIFT1 - 1)
+#define PTE_FILE_BITS2         (PTE_FILE_SHIFT3 - PTE_FILE_SHIFT2 - 1)
+#define PTE_FILE_BITS3         (PTE_FILE_SHIFT4 - PTE_FILE_SHIFT3 - 1)
+
+#define pte_to_pgoff(pte)                                              \
+       ((((pte).pte_low >> (PTE_FILE_SHIFT1))                          \
+         & ((1U << PTE_FILE_BITS1) - 1)))                              \
+       + ((((pte).pte_low >> (PTE_FILE_SHIFT2))                        \
+           & ((1U << PTE_FILE_BITS2) - 1))                             \
+          << (PTE_FILE_BITS1))                                         \
+       + ((((pte).pte_low >> (PTE_FILE_SHIFT3))                        \
+           & ((1U << PTE_FILE_BITS3) - 1))                             \
+          << (PTE_FILE_BITS1 + PTE_FILE_BITS2))                        \
+       + ((((pte).pte_low >> (PTE_FILE_SHIFT4)))                       \
+           << (PTE_FILE_BITS1 + PTE_FILE_BITS2 + PTE_FILE_BITS3))
+
+#define pgoff_to_pte(off)                                              \
+       ((pte_t) { .pte_low =                                           \
+        ((((off)) & ((1U << PTE_FILE_BITS1) - 1)) << PTE_FILE_SHIFT1)  \
+        + ((((off) >> PTE_FILE_BITS1)                                  \
+            & ((1U << PTE_FILE_BITS2) - 1))                            \
+           << PTE_FILE_SHIFT2)                                         \
+        + ((((off) >> (PTE_FILE_BITS1 + PTE_FILE_BITS2))               \
+            & ((1U << PTE_FILE_BITS3) - 1))                            \
+           << PTE_FILE_SHIFT3)                                         \
+        + ((((off) >>                                                  \
+             (PTE_FILE_BITS1 + PTE_FILE_BITS2 + PTE_FILE_BITS3)))      \
+           << PTE_FILE_SHIFT4)                                         \
+        + _PAGE_FILE })
+
+#else /* CONFIG_MEM_SOFT_DIRTY */
+
 /*
  * Bits _PAGE_BIT_PRESENT, _PAGE_BIT_FILE and _PAGE_BIT_PROTNONE are taken,
- * split up the 29 bits of offset into this range:
+ * split up the 29 bits of offset into this range.
  */
 #define PTE_FILE_MAX_BITS      29
 #define PTE_FILE_SHIFT1                (_PAGE_BIT_PRESENT + 1)
@@ -88,6 +132,8 @@ static inline pmd_t native_pmdp_get_and_clear(pmd_t *xp)
            << PTE_FILE_SHIFT3)                                         \
         + _PAGE_FILE })
 
+#endif /* CONFIG_MEM_SOFT_DIRTY */
+
 /* Encode and de-code a swap entry */
 #if _PAGE_BIT_FILE < _PAGE_BIT_PROTNONE
 #define SWP_TYPE_BITS (_PAGE_BIT_FILE - _PAGE_BIT_PRESENT - 1)
index 4cc9f2b..81bb91b 100644 (file)
@@ -179,6 +179,9 @@ static inline pmd_t native_pmdp_get_and_clear(pmd_t *pmdp)
 /*
  * Bits 0, 6 and 7 are taken in the low part of the pte,
  * put the 32 bits of offset into the high part.
+ *
+ * For soft-dirty tracking 11 bit is taken from
+ * the low part of pte as well.
  */
 #define pte_to_pgoff(pte) ((pte).pte_high)
 #define pgoff_to_pte(off)                                              \
index 7dc305a..1c00631 100644 (file)
@@ -314,6 +314,36 @@ static inline pmd_t pmd_mksoft_dirty(pmd_t pmd)
        return pmd_set_flags(pmd, _PAGE_SOFT_DIRTY);
 }
 
+static inline pte_t pte_swp_mksoft_dirty(pte_t pte)
+{
+       return pte_set_flags(pte, _PAGE_SWP_SOFT_DIRTY);
+}
+
+static inline int pte_swp_soft_dirty(pte_t pte)
+{
+       return pte_flags(pte) & _PAGE_SWP_SOFT_DIRTY;
+}
+
+static inline pte_t pte_swp_clear_soft_dirty(pte_t pte)
+{
+       return pte_clear_flags(pte, _PAGE_SWP_SOFT_DIRTY);
+}
+
+static inline pte_t pte_file_clear_soft_dirty(pte_t pte)
+{
+       return pte_clear_flags(pte, _PAGE_SOFT_DIRTY);
+}
+
+static inline pte_t pte_file_mksoft_dirty(pte_t pte)
+{
+       return pte_set_flags(pte, _PAGE_SOFT_DIRTY);
+}
+
+static inline int pte_file_soft_dirty(pte_t pte)
+{
+       return pte_flags(pte) & _PAGE_SOFT_DIRTY;
+}
+
 /*
  * Mask out unsupported bits in a present pgprot.  Non-present pgprots
  * can use those bits for other purposes, so leave them be.
index c98ac63..f4843e0 100644 (file)
  * they do not conflict with each other.
  */
 
+#define _PAGE_BIT_SOFT_DIRTY   _PAGE_BIT_HIDDEN
+
 #ifdef CONFIG_MEM_SOFT_DIRTY
-#define _PAGE_SOFT_DIRTY       (_AT(pteval_t, 1) << _PAGE_BIT_HIDDEN)
+#define _PAGE_SOFT_DIRTY       (_AT(pteval_t, 1) << _PAGE_BIT_SOFT_DIRTY)
 #else
 #define _PAGE_SOFT_DIRTY       (_AT(pteval_t, 0))
 #endif
 
+/*
+ * Tracking soft dirty bit when a page goes to a swap is tricky.
+ * We need a bit which can be stored in pte _and_ not conflict
+ * with swap entry format. On x86 bits 6 and 7 are *not* involved
+ * into swap entry computation, but bit 6 is used for nonlinear
+ * file mapping, so we borrow bit 7 for soft dirty tracking.
+ */
+#ifdef CONFIG_MEM_SOFT_DIRTY
+#define _PAGE_SWP_SOFT_DIRTY   _PAGE_PSE
+#else
+#define _PAGE_SWP_SOFT_DIRTY   (_AT(pteval_t, 0))
+#endif
+
 #if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE)
 #define _PAGE_NX       (_AT(pteval_t, 1) << _PAGE_BIT_NX)
 #else
index 33692ea..e3ddd7d 100644 (file)
@@ -233,8 +233,4 @@ static inline void arch_write_unlock(arch_rwlock_t *rw)
 #define arch_read_relax(lock)  cpu_relax()
 #define arch_write_relax(lock) cpu_relax()
 
-/* The {read|write|spin}_lock() on x86 are full memory barriers. */
-static inline void smp_mb__after_lock(void) { }
-#define ARCH_HAS_SMP_MB_AFTER_LOCK
-
 #endif /* _ASM_X86_SPINLOCK_H */
index f654ece..08a0890 100644 (file)
@@ -512,7 +512,7 @@ static void early_init_amd(struct cpuinfo_x86 *c)
 
 static const int amd_erratum_383[];
 static const int amd_erratum_400[];
-static bool cpu_has_amd_erratum(const int *erratum);
+static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum);
 
 static void init_amd(struct cpuinfo_x86 *c)
 {
@@ -729,11 +729,11 @@ static void init_amd(struct cpuinfo_x86 *c)
                value &= ~(1ULL << 24);
                wrmsrl_safe(MSR_AMD64_BU_CFG2, value);
 
-               if (cpu_has_amd_erratum(amd_erratum_383))
+               if (cpu_has_amd_erratum(c, amd_erratum_383))
                        set_cpu_bug(c, X86_BUG_AMD_TLB_MMATCH);
        }
 
-       if (cpu_has_amd_erratum(amd_erratum_400))
+       if (cpu_has_amd_erratum(c, amd_erratum_400))
                set_cpu_bug(c, X86_BUG_AMD_APIC_C1E);
 
        rdmsr_safe(MSR_AMD64_PATCH_LEVEL, &c->microcode, &dummy);
@@ -878,23 +878,13 @@ static const int amd_erratum_400[] =
 static const int amd_erratum_383[] =
        AMD_OSVW_ERRATUM(3, AMD_MODEL_RANGE(0x10, 0, 0, 0xff, 0xf));
 
-static bool cpu_has_amd_erratum(const int *erratum)
+
+static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum)
 {
-       struct cpuinfo_x86 *cpu = __this_cpu_ptr(&cpu_info);
        int osvw_id = *erratum++;
        u32 range;
        u32 ms;
 
-       /*
-        * If called early enough that current_cpu_data hasn't been initialized
-        * yet, fall back to boot_cpu_data.
-        */
-       if (cpu->x86 == 0)
-               cpu = &boot_cpu_data;
-
-       if (cpu->x86_vendor != X86_VENDOR_AMD)
-               return false;
-
        if (osvw_id >= 0 && osvw_id < 65536 &&
            cpu_has(cpu, X86_FEATURE_OSVW)) {
                u64 osvw_len;
index fbc9210..a45d8d4 100644 (file)
@@ -2270,6 +2270,7 @@ __init int intel_pmu_init(void)
        case 70:
        case 71:
        case 63:
+       case 69:
                x86_pmu.late_ack = true;
                memcpy(hw_cache_event_ids, snb_hw_cache_event_ids, sizeof(hw_cache_event_ids));
                memcpy(hw_cache_extra_regs, snb_hw_cache_extra_regs, sizeof(hw_cache_extra_regs));
index cad791d..1fb6c72 100644 (file)
@@ -314,8 +314,8 @@ static struct uncore_event_desc snbep_uncore_imc_events[] = {
 static struct uncore_event_desc snbep_uncore_qpi_events[] = {
        INTEL_UNCORE_EVENT_DESC(clockticks,       "event=0x14"),
        INTEL_UNCORE_EVENT_DESC(txl_flits_active, "event=0x00,umask=0x06"),
-       INTEL_UNCORE_EVENT_DESC(drs_data,         "event=0x02,umask=0x08"),
-       INTEL_UNCORE_EVENT_DESC(ncb_data,         "event=0x03,umask=0x04"),
+       INTEL_UNCORE_EVENT_DESC(drs_data,         "event=0x102,umask=0x08"),
+       INTEL_UNCORE_EVENT_DESC(ncb_data,         "event=0x103,umask=0x04"),
        { /* end: all zeroes */ },
 };
 
index 7a0adb7..7123b5d 100644 (file)
@@ -145,10 +145,9 @@ static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig)
        return 0;
 }
 
-static unsigned int verify_patch_size(int cpu, u32 patch_size,
+static unsigned int verify_patch_size(u8 family, u32 patch_size,
                                      unsigned int size)
 {
-       struct cpuinfo_x86 *c = &cpu_data(cpu);
        u32 max_size;
 
 #define F1XH_MPB_MAX_SIZE 2048
@@ -156,7 +155,7 @@ static unsigned int verify_patch_size(int cpu, u32 patch_size,
 #define F15H_MPB_MAX_SIZE 4096
 #define F16H_MPB_MAX_SIZE 3458
 
-       switch (c->x86) {
+       switch (family) {
        case 0x14:
                max_size = F14H_MPB_MAX_SIZE;
                break;
@@ -277,9 +276,8 @@ static void cleanup(void)
  * driver cannot continue functioning normally. In such cases, we tear
  * down everything we've used up so far and exit.
  */
-static int verify_and_add_patch(unsigned int cpu, u8 *fw, unsigned int leftover)
+static int verify_and_add_patch(u8 family, u8 *fw, unsigned int leftover)
 {
-       struct cpuinfo_x86 *c = &cpu_data(cpu);
        struct microcode_header_amd *mc_hdr;
        struct ucode_patch *patch;
        unsigned int patch_size, crnt_size, ret;
@@ -299,7 +297,7 @@ static int verify_and_add_patch(unsigned int cpu, u8 *fw, unsigned int leftover)
 
        /* check if patch is for the current family */
        proc_fam = ((proc_fam >> 8) & 0xf) + ((proc_fam >> 20) & 0xff);
-       if (proc_fam != c->x86)
+       if (proc_fam != family)
                return crnt_size;
 
        if (mc_hdr->nb_dev_id || mc_hdr->sb_dev_id) {
@@ -308,7 +306,7 @@ static int verify_and_add_patch(unsigned int cpu, u8 *fw, unsigned int leftover)
                return crnt_size;
        }
 
-       ret = verify_patch_size(cpu, patch_size, leftover);
+       ret = verify_patch_size(family, patch_size, leftover);
        if (!ret) {
                pr_err("Patch-ID 0x%08x: size mismatch.\n", mc_hdr->patch_id);
                return crnt_size;
@@ -339,7 +337,8 @@ static int verify_and_add_patch(unsigned int cpu, u8 *fw, unsigned int leftover)
        return crnt_size;
 }
 
-static enum ucode_state __load_microcode_amd(int cpu, const u8 *data, size_t size)
+static enum ucode_state __load_microcode_amd(u8 family, const u8 *data,
+                                            size_t size)
 {
        enum ucode_state ret = UCODE_ERROR;
        unsigned int leftover;
@@ -362,7 +361,7 @@ static enum ucode_state __load_microcode_amd(int cpu, const u8 *data, size_t siz
        }
 
        while (leftover) {
-               crnt_size = verify_and_add_patch(cpu, fw, leftover);
+               crnt_size = verify_and_add_patch(family, fw, leftover);
                if (crnt_size < 0)
                        return ret;
 
@@ -373,22 +372,22 @@ static enum ucode_state __load_microcode_amd(int cpu, const u8 *data, size_t siz
        return UCODE_OK;
 }
 
-enum ucode_state load_microcode_amd(int cpu, const u8 *data, size_t size)
+enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t size)
 {
        enum ucode_state ret;
 
        /* free old equiv table */
        free_equiv_cpu_table();
 
-       ret = __load_microcode_amd(cpu, data, size);
+       ret = __load_microcode_amd(family, data, size);
 
        if (ret != UCODE_OK)
                cleanup();
 
 #if defined(CONFIG_MICROCODE_AMD_EARLY) && defined(CONFIG_X86_32)
        /* save BSP's matching patch for early load */
-       if (cpu_data(cpu).cpu_index == boot_cpu_data.cpu_index) {
-               struct ucode_patch *p = find_patch(cpu);
+       if (cpu_data(smp_processor_id()).cpu_index == boot_cpu_data.cpu_index) {
+               struct ucode_patch *p = find_patch(smp_processor_id());
                if (p) {
                        memset(amd_bsp_mpb, 0, MPB_MAX_SIZE);
                        memcpy(amd_bsp_mpb, p->data, min_t(u32, ksize(p->data),
@@ -441,7 +440,7 @@ static enum ucode_state request_microcode_amd(int cpu, struct device *device,
                goto fw_release;
        }
 
-       ret = load_microcode_amd(cpu, fw->data, fw->size);
+       ret = load_microcode_amd(c->x86, fw->data, fw->size);
 
  fw_release:
        release_firmware(fw);
index 1d14ffe..6073104 100644 (file)
@@ -238,25 +238,17 @@ static void __init collect_cpu_sig_on_bsp(void *arg)
        uci->cpu_sig.sig = cpuid_eax(0x00000001);
 }
 #else
-static void collect_cpu_info_amd_early(struct cpuinfo_x86 *c,
-                                                struct ucode_cpu_info *uci)
+void load_ucode_amd_ap(void)
 {
+       unsigned int cpu = smp_processor_id();
+       struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
        u32 rev, eax;
 
        rdmsr(MSR_AMD64_PATCH_LEVEL, rev, eax);
        eax = cpuid_eax(0x00000001);
 
-       uci->cpu_sig.sig = eax;
        uci->cpu_sig.rev = rev;
-       c->microcode = rev;
-       c->x86 = ((eax >> 8) & 0xf) + ((eax >> 20) & 0xff);
-}
-
-void load_ucode_amd_ap(void)
-{
-       unsigned int cpu = smp_processor_id();
-
-       collect_cpu_info_amd_early(&cpu_data(cpu), ucode_cpu_info + cpu);
+       uci->cpu_sig.sig = eax;
 
        if (cpu && !ucode_loaded) {
                void *ucode;
@@ -265,8 +257,10 @@ void load_ucode_amd_ap(void)
                        return;
 
                ucode = (void *)(initrd_start + ucode_offset);
-               if (load_microcode_amd(0, ucode, ucode_size) != UCODE_OK)
+               eax   = ((eax >> 8) & 0xf) + ((eax >> 20) & 0xff);
+               if (load_microcode_amd(eax, ucode, ucode_size) != UCODE_OK)
                        return;
+
                ucode_loaded = true;
        }
 
@@ -278,6 +272,8 @@ int __init save_microcode_in_initrd_amd(void)
 {
        enum ucode_state ret;
        void *ucode;
+       u32 eax;
+
 #ifdef CONFIG_X86_32
        unsigned int bsp = boot_cpu_data.cpu_index;
        struct ucode_cpu_info *uci = ucode_cpu_info + bsp;
@@ -293,7 +289,10 @@ int __init save_microcode_in_initrd_amd(void)
                return 0;
 
        ucode = (void *)(initrd_start + ucode_offset);
-       ret = load_microcode_amd(0, ucode, ucode_size);
+       eax   = cpuid_eax(0x00000001);
+       eax   = ((eax >> 8) & 0xf) + ((eax >> 20) & 0xff);
+
+       ret = load_microcode_amd(eax, ucode, ucode_size);
        if (ret != UCODE_OK)
                return -EINVAL;
 
index dbded5a..30277e2 100644 (file)
@@ -101,7 +101,7 @@ static void find_start_end(unsigned long flags, unsigned long *begin,
                                *begin = new_begin;
                }
        } else {
-               *begin = TASK_UNMAPPED_BASE;
+               *begin = current->mm->mmap_legacy_base;
                *end = TASK_SIZE;
        }
 }
index 62c29a5..25e7e13 100644 (file)
@@ -112,11 +112,13 @@ static unsigned long mmap_legacy_base(void)
  */
 void arch_pick_mmap_layout(struct mm_struct *mm)
 {
+       mm->mmap_legacy_base = mmap_legacy_base();
+       mm->mmap_base = mmap_base();
+
        if (mmap_is_legacy()) {
-               mm->mmap_base = mmap_legacy_base();
+               mm->mmap_base = mm->mmap_legacy_base;
                mm->get_unmapped_area = arch_get_unmapped_area;
        } else {
-               mm->mmap_base = mmap_base();
                mm->get_unmapped_area = arch_get_unmapped_area_topdown;
        }
 }
index 056d11f..8f3eea6 100644 (file)
@@ -313,6 +313,17 @@ static void xen_align_and_add_e820_region(u64 start, u64 size, int type)
        e820_add_region(start, end - start, type);
 }
 
+void xen_ignore_unusable(struct e820entry *list, size_t map_size)
+{
+       struct e820entry *entry;
+       unsigned int i;
+
+       for (i = 0, entry = list; i < map_size; i++, entry++) {
+               if (entry->type == E820_UNUSABLE)
+                       entry->type = E820_RAM;
+       }
+}
+
 /**
  * machine_specific_memory_setup - Hook for machine specific memory setup.
  **/
@@ -353,6 +364,17 @@ char * __init xen_memory_setup(void)
        }
        BUG_ON(rc);
 
+       /*
+        * Xen won't allow a 1:1 mapping to be created to UNUSABLE
+        * regions, so if we're using the machine memory map leave the
+        * region as RAM as it is in the pseudo-physical map.
+        *
+        * UNUSABLE regions in domUs are not handled and will need
+        * a patch in the future.
+        */
+       if (xen_initial_domain())
+               xen_ignore_unusable(map, memmap.nr_entries);
+
        /* Make sure the Xen-supplied memory map is well-ordered. */
        sanitize_e820_map(map, memmap.nr_entries, &memmap.nr_entries);
 
index ca92754..b81c88e 100644 (file)
@@ -694,8 +694,15 @@ static void __init xen_hvm_smp_prepare_cpus(unsigned int max_cpus)
 static int xen_hvm_cpu_up(unsigned int cpu, struct task_struct *tidle)
 {
        int rc;
-       rc = native_cpu_up(cpu, tidle);
-       WARN_ON (xen_smp_intr_init(cpu));
+       /*
+        * xen_smp_intr_init() needs to run before native_cpu_up()
+        * so that IPI vectors are set up on the booting CPU before
+        * it is marked online in native_cpu_up().
+       */
+       rc = xen_smp_intr_init(cpu);
+       WARN_ON(rc);
+       if (!rc)
+               rc =  native_cpu_up(cpu, tidle);
        return rc;
 }
 
index e1284b8..3270d3c 100644 (file)
@@ -908,9 +908,6 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
                device->cap._DDC = 1;
        }
 
-       if (acpi_video_init_brightness(device))
-               return;
-
        if (acpi_video_backlight_support()) {
                struct backlight_properties props;
                struct pci_dev *pdev;
@@ -920,6 +917,9 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
                static int count = 0;
                char *name;
 
+               result = acpi_video_init_brightness(device);
+               if (result)
+                       return;
                name = kasprintf(GFP_KERNEL, "acpi_video%d", count);
                if (!name)
                        return;
@@ -979,11 +979,6 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
                if (result)
                        printk(KERN_ERR PREFIX "Create sysfs link\n");
 
-       } else {
-               /* Remove the brightness object. */
-               kfree(device->brightness->levels);
-               kfree(device->brightness);
-               device->brightness = NULL;
        }
 }
 
index 1c41722..20fd337 100644 (file)
@@ -289,24 +289,24 @@ static int sata_pmp_configure(struct ata_device *dev, int print_info)
 
        /* Disable sending Early R_OK.
         * With "cached read" HDD testing and multiple ports busy on a SATA
-        * host controller, 3726 PMP will very rarely drop a deferred
+        * host controller, 3x26 PMP will very rarely drop a deferred
         * R_OK that was intended for the host. Symptom will be all
         * 5 drives under test will timeout, get reset, and recover.
         */
-       if (vendor == 0x1095 && devid == 0x3726) {
+       if (vendor == 0x1095 && (devid == 0x3726 || devid == 0x3826)) {
                u32 reg;
 
                err_mask = sata_pmp_read(&ap->link, PMP_GSCR_SII_POL, &reg);
                if (err_mask) {
                        rc = -EIO;
-                       reason = "failed to read Sil3726 Private Register";
+                       reason = "failed to read Sil3x26 Private Register";
                        goto fail;
                }
                reg &= ~0x1;
                err_mask = sata_pmp_write(&ap->link, PMP_GSCR_SII_POL, reg);
                if (err_mask) {
                        rc = -EIO;
-                       reason = "failed to write Sil3726 Private Register";
+                       reason = "failed to write Sil3x26 Private Register";
                        goto fail;
                }
        }
@@ -383,8 +383,8 @@ static void sata_pmp_quirks(struct ata_port *ap)
        u16 devid = sata_pmp_gscr_devid(gscr);
        struct ata_link *link;
 
-       if (vendor == 0x1095 && devid == 0x3726) {
-               /* sil3726 quirks */
+       if (vendor == 0x1095 && (devid == 0x3726 || devid == 0x3826)) {
+               /* sil3x26 quirks */
                ata_for_each_link(link, ap, EDGE) {
                        /* link reports offline after LPM */
                        link->flags |= ATA_LFLAG_NO_LPM;
index 19720a0..851bd3f 100644 (file)
@@ -293,6 +293,7 @@ static void fsl_sata_set_irq_coalescing(struct ata_host *host,
 {
        struct sata_fsl_host_priv *host_priv = host->private_data;
        void __iomem *hcr_base = host_priv->hcr_base;
+       unsigned long flags;
 
        if (count > ICC_MAX_INT_COUNT_THRESHOLD)
                count = ICC_MAX_INT_COUNT_THRESHOLD;
@@ -305,12 +306,12 @@ static void fsl_sata_set_irq_coalescing(struct ata_host *host,
                        (count > ICC_MIN_INT_COUNT_THRESHOLD))
                ticks = ICC_SAFE_INT_TICKS;
 
-       spin_lock(&host->lock);
+       spin_lock_irqsave(&host->lock, flags);
        iowrite32((count << 24 | ticks), hcr_base + ICC);
 
        intr_coalescing_count = count;
        intr_coalescing_ticks = ticks;
-       spin_unlock(&host->lock);
+       spin_unlock_irqrestore(&host->lock, flags);
 
        DPRINTK("interrupt coalescing, count = 0x%x, ticks = %x\n",
                        intr_coalescing_count, intr_coalescing_ticks);
index d047d92..e9a4f46 100644 (file)
@@ -86,11 +86,11 @@ struct ecx_plat_data {
 
 #define SGPIO_SIGNALS                  3
 #define ECX_ACTIVITY_BITS              0x300000
-#define ECX_ACTIVITY_SHIFT             2
+#define ECX_ACTIVITY_SHIFT             0
 #define ECX_LOCATE_BITS                        0x80000
 #define ECX_LOCATE_SHIFT               1
 #define ECX_FAULT_BITS                 0x400000
-#define ECX_FAULT_SHIFT                        0
+#define ECX_FAULT_SHIFT                        2
 static inline int sgpio_bit_shift(struct ecx_plat_data *pdata, u32 port,
                                u32 shift)
 {
index 99cb944..4d45dba 100644 (file)
@@ -906,16 +906,10 @@ bio_pageinc(struct bio *bio)
        int i;
 
        bio_for_each_segment(bv, bio, i) {
-               page = bv->bv_page;
                /* Non-zero page count for non-head members of
-                * compound pages is no longer allowed by the kernel,
-                * but this has never been seen here.
+                * compound pages is no longer allowed by the kernel.
                 */
-               if (unlikely(PageCompound(page)))
-                       if (compound_trans_head(page) != page) {
-                               pr_crit("page tail used for block I/O\n");
-                               BUG();
-                       }
+               page = compound_trans_head(bv->bv_page);
                atomic_inc(&page->_count);
        }
 }
@@ -924,10 +918,13 @@ static void
 bio_pagedec(struct bio *bio)
 {
        struct bio_vec *bv;
+       struct page *page;
        int i;
 
-       bio_for_each_segment(bv, bio, i)
-               atomic_dec(&bv->bv_page->_count);
+       bio_for_each_segment(bv, bio, i) {
+               page = compound_trans_head(bv->bv_page);
+               atomic_dec(&page->_count);
+       }
 }
 
 static void
index 1bdb882..4e57397 100644 (file)
@@ -581,11 +581,15 @@ struct samsung_div_clock exynos4x12_div_clks[] __initdata = {
        DIV(none, "div_spi1_isp", "mout_spi1_isp", E4X12_DIV_ISP, 16, 4),
        DIV(none, "div_spi1_isp_pre", "div_spi1_isp", E4X12_DIV_ISP, 20, 8),
        DIV(none, "div_uart_isp", "mout_uart_isp", E4X12_DIV_ISP, 28, 4),
-       DIV(div_isp0, "div_isp0", "aclk200", E4X12_DIV_ISP0, 0, 3),
-       DIV(div_isp1, "div_isp1", "aclk200", E4X12_DIV_ISP0, 4, 3),
+       DIV_F(div_isp0, "div_isp0", "aclk200", E4X12_DIV_ISP0, 0, 3,
+                                               CLK_GET_RATE_NOCACHE, 0),
+       DIV_F(div_isp1, "div_isp1", "aclk200", E4X12_DIV_ISP0, 4, 3,
+                                               CLK_GET_RATE_NOCACHE, 0),
        DIV(none, "div_mpwm", "div_isp1", E4X12_DIV_ISP1, 0, 3),
-       DIV(div_mcuisp0, "div_mcuisp0", "aclk400_mcuisp", E4X12_DIV_ISP1, 4, 3),
-       DIV(div_mcuisp1, "div_mcuisp1", "div_mcuisp0", E4X12_DIV_ISP1, 8, 3),
+       DIV_F(div_mcuisp0, "div_mcuisp0", "aclk400_mcuisp", E4X12_DIV_ISP1,
+                                               4, 3, CLK_GET_RATE_NOCACHE, 0),
+       DIV_F(div_mcuisp1, "div_mcuisp1", "div_mcuisp0", E4X12_DIV_ISP1,
+                                               8, 3, CLK_GET_RATE_NOCACHE, 0),
        DIV(sclk_fimg2d, "sclk_fimg2d", "mout_g2d", DIV_DMC1, 0, 4),
 };
 
@@ -863,57 +867,57 @@ struct samsung_gate_clock exynos4x12_gate_clks[] __initdata = {
        GATE_DA(i2s0, "samsung-i2s.0", "i2s0", "aclk100",
                        E4X12_GATE_IP_MAUDIO, 3, 0, 0, "iis"),
        GATE(fimc_isp, "isp", "aclk200", E4X12_GATE_ISP0, 0,
-                       CLK_IGNORE_UNUSED, 0),
+                       CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
        GATE(fimc_drc, "drc", "aclk200", E4X12_GATE_ISP0, 1,
-                       CLK_IGNORE_UNUSED, 0),
+                       CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
        GATE(fimc_fd, "fd", "aclk200", E4X12_GATE_ISP0, 2,
-                       CLK_IGNORE_UNUSED, 0),
+                       CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
        GATE(fimc_lite0, "lite0", "aclk200", E4X12_GATE_ISP0, 3,
-                       CLK_IGNORE_UNUSED, 0),
+                       CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
        GATE(fimc_lite1, "lite1", "aclk200", E4X12_GATE_ISP0, 4,
-                       CLK_IGNORE_UNUSED, 0),
+                       CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
        GATE(mcuisp, "mcuisp", "aclk200", E4X12_GATE_ISP0, 5,
-                       CLK_IGNORE_UNUSED, 0),
+                       CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
        GATE(gicisp, "gicisp", "aclk200", E4X12_GATE_ISP0, 7,
-                       CLK_IGNORE_UNUSED, 0),
+                       CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
        GATE(smmu_isp, "smmu_isp", "aclk200", E4X12_GATE_ISP0, 8,
-                       CLK_IGNORE_UNUSED, 0),
+                       CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
        GATE(smmu_drc, "smmu_drc", "aclk200", E4X12_GATE_ISP0, 9,
-                       CLK_IGNORE_UNUSED, 0),
+                       CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
        GATE(smmu_fd, "smmu_fd", "aclk200", E4X12_GATE_ISP0, 10,
-                       CLK_IGNORE_UNUSED, 0),
+                       CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
        GATE(smmu_lite0, "smmu_lite0", "aclk200", E4X12_GATE_ISP0, 11,
-                       CLK_IGNORE_UNUSED, 0),
+                       CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
        GATE(smmu_lite1, "smmu_lite1", "aclk200", E4X12_GATE_ISP0, 12,
-                       CLK_IGNORE_UNUSED, 0),
+                       CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
        GATE(ppmuispmx, "ppmuispmx", "aclk200", E4X12_GATE_ISP0, 20,
-                       CLK_IGNORE_UNUSED, 0),
+                       CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
        GATE(ppmuispx, "ppmuispx", "aclk200", E4X12_GATE_ISP0, 21,
-                       CLK_IGNORE_UNUSED, 0),
+                       CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
        GATE(mcuctl_isp, "mcuctl_isp", "aclk200", E4X12_GATE_ISP0, 23,
-                       CLK_IGNORE_UNUSED, 0),
+                       CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
        GATE(mpwm_isp, "mpwm_isp", "aclk200", E4X12_GATE_ISP0, 24,
-                       CLK_IGNORE_UNUSED, 0),
+                       CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
        GATE(i2c0_isp, "i2c0_isp", "aclk200", E4X12_GATE_ISP0, 25,
-                       CLK_IGNORE_UNUSED, 0),
+                       CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
        GATE(i2c1_isp, "i2c1_isp", "aclk200", E4X12_GATE_ISP0, 26,
-                       CLK_IGNORE_UNUSED, 0),
+                       CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
        GATE(mtcadc_isp, "mtcadc_isp", "aclk200", E4X12_GATE_ISP0, 27,
-                       CLK_IGNORE_UNUSED, 0),
+                       CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
        GATE(pwm_isp, "pwm_isp", "aclk200", E4X12_GATE_ISP0, 28,
-                       CLK_IGNORE_UNUSED, 0),
+                       CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
        GATE(wdt_isp, "wdt_isp", "aclk200", E4X12_GATE_ISP0, 30,
-                       CLK_IGNORE_UNUSED, 0),
+                       CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
        GATE(uart_isp, "uart_isp", "aclk200", E4X12_GATE_ISP0, 31,
-                       CLK_IGNORE_UNUSED, 0),
+                       CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
        GATE(asyncaxim, "asyncaxim", "aclk200", E4X12_GATE_ISP1, 0,
-                       CLK_IGNORE_UNUSED, 0),
+                       CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
        GATE(smmu_ispcx, "smmu_ispcx", "aclk200", E4X12_GATE_ISP1, 4,
-                       CLK_IGNORE_UNUSED, 0),
+                       CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
        GATE(spi0_isp, "spi0_isp", "aclk200", E4X12_GATE_ISP1, 12,
-                       CLK_IGNORE_UNUSED, 0),
+                       CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
        GATE(spi1_isp, "spi1_isp", "aclk200", E4X12_GATE_ISP1, 13,
-                       CLK_IGNORE_UNUSED, 0),
+                       CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
        GATE(g2d, "g2d", "aclk200", GATE_IP_DMC, 23, 0, 0),
 };
 
index 5c205b6..089d3e3 100644 (file)
@@ -71,6 +71,7 @@ static DEFINE_SPINLOCK(armpll_lock);
 static DEFINE_SPINLOCK(ddrpll_lock);
 static DEFINE_SPINLOCK(iopll_lock);
 static DEFINE_SPINLOCK(armclk_lock);
+static DEFINE_SPINLOCK(swdtclk_lock);
 static DEFINE_SPINLOCK(ddrclk_lock);
 static DEFINE_SPINLOCK(dciclk_lock);
 static DEFINE_SPINLOCK(gem0clk_lock);
@@ -293,7 +294,7 @@ static void __init zynq_clk_setup(struct device_node *np)
        }
        clks[swdt] = clk_register_mux(NULL, clk_output_name[swdt],
                        swdt_ext_clk_mux_parents, 2, CLK_SET_RATE_PARENT,
-                       SLCR_SWDT_CLK_SEL, 0, 1, 0, &gem0clk_lock);
+                       SLCR_SWDT_CLK_SEL, 0, 1, 0, &swdtclk_lock);
 
        /* DDR clocks */
        clk = clk_register_divider(NULL, "ddr2x_div", "ddrpll", 0,
@@ -364,8 +365,9 @@ static void __init zynq_clk_setup(struct device_node *np)
                        CLK_SET_RATE_PARENT, SLCR_GEM0_CLK_CTRL, 20, 6,
                        CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
                        &gem0clk_lock);
-       clk = clk_register_mux(NULL, "gem0_emio_mux", gem0_mux_parents, 2, 0,
-                       SLCR_GEM0_CLK_CTRL, 6, 1, 0, &gem0clk_lock);
+       clk = clk_register_mux(NULL, "gem0_emio_mux", gem0_mux_parents, 2,
+                       CLK_SET_RATE_PARENT, SLCR_GEM0_CLK_CTRL, 6, 1, 0,
+                       &gem0clk_lock);
        clks[gem0] = clk_register_gate(NULL, clk_output_name[gem0],
                        "gem0_emio_mux", CLK_SET_RATE_PARENT,
                        SLCR_GEM0_CLK_CTRL, 0, 0, &gem0clk_lock);
@@ -386,8 +388,9 @@ static void __init zynq_clk_setup(struct device_node *np)
                        CLK_SET_RATE_PARENT, SLCR_GEM1_CLK_CTRL, 20, 6,
                        CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
                        &gem1clk_lock);
-       clk = clk_register_mux(NULL, "gem1_emio_mux", gem1_mux_parents, 2, 0,
-                       SLCR_GEM1_CLK_CTRL, 6, 1, 0, &gem1clk_lock);
+       clk = clk_register_mux(NULL, "gem1_emio_mux", gem1_mux_parents, 2,
+                       CLK_SET_RATE_PARENT, SLCR_GEM1_CLK_CTRL, 6, 1, 0,
+                       &gem1clk_lock);
        clks[gem1] = clk_register_gate(NULL, clk_output_name[gem1],
                        "gem1_emio_mux", CLK_SET_RATE_PARENT,
                        SLCR_GEM1_CLK_CTRL, 0, 0, &gem1clk_lock);
index 19e3660..3bc8414 100644 (file)
@@ -500,7 +500,8 @@ static bool psb_intel_sdvo_read_response(struct psb_intel_sdvo *psb_intel_sdvo,
                                  &status))
                goto log_fail;
 
-       while (status == SDVO_CMD_STATUS_PENDING && retry--) {
+       while ((status == SDVO_CMD_STATUS_PENDING ||
+               status == SDVO_CMD_STATUS_TARGET_NOT_SPECIFIED) && retry--) {
                udelay(15);
                if (!psb_intel_sdvo_read_byte(psb_intel_sdvo,
                                          SDVO_I2C_CMD_STATUS,
index dc53a52..9e65783 100644 (file)
@@ -85,9 +85,17 @@ static void i915_gem_unmap_dma_buf(struct dma_buf_attachment *attachment,
                                   struct sg_table *sg,
                                   enum dma_data_direction dir)
 {
+       struct drm_i915_gem_object *obj = attachment->dmabuf->priv;
+
+       mutex_lock(&obj->base.dev->struct_mutex);
+
        dma_unmap_sg(attachment->dev, sg->sgl, sg->nents, dir);
        sg_free_table(sg);
        kfree(sg);
+
+       i915_gem_object_unpin_pages(obj);
+
+       mutex_unlock(&obj->base.dev->struct_mutex);
 }
 
 static void i915_gem_dmabuf_release(struct dma_buf *dma_buf)
index 6f51429..53cddd9 100644 (file)
                                        will not assert AGPBUSY# and will only
                                        be delivered when out of C3. */
 #define   INSTPM_FORCE_ORDERING                                (1<<7) /* GEN6+ */
+#define   INSTPM_TLB_INVALIDATE        (1<<9)
+#define   INSTPM_SYNC_FLUSH    (1<<5)
 #define ACTHD          0x020c8
 #define FW_BLC         0x020d8
 #define FW_BLC2                0x020dc
index e38b457..be79f47 100644 (file)
@@ -10042,6 +10042,8 @@ struct intel_display_error_state {
 
        u32 power_well_driver;
 
+       int num_transcoders;
+
        struct intel_cursor_error_state {
                u32 control;
                u32 position;
@@ -10050,16 +10052,7 @@ struct intel_display_error_state {
        } cursor[I915_MAX_PIPES];
 
        struct intel_pipe_error_state {
-               enum transcoder cpu_transcoder;
-               u32 conf;
                u32 source;
-
-               u32 htotal;
-               u32 hblank;
-               u32 hsync;
-               u32 vtotal;
-               u32 vblank;
-               u32 vsync;
        } pipe[I915_MAX_PIPES];
 
        struct intel_plane_error_state {
@@ -10071,6 +10064,19 @@ struct intel_display_error_state {
                u32 surface;
                u32 tile_offset;
        } plane[I915_MAX_PIPES];
+
+       struct intel_transcoder_error_state {
+               enum transcoder cpu_transcoder;
+
+               u32 conf;
+
+               u32 htotal;
+               u32 hblank;
+               u32 hsync;
+               u32 vtotal;
+               u32 vblank;
+               u32 vsync;
+       } transcoder[4];
 };
 
 struct intel_display_error_state *
@@ -10078,9 +10084,17 @@ intel_display_capture_error_state(struct drm_device *dev)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
        struct intel_display_error_state *error;
-       enum transcoder cpu_transcoder;
+       int transcoders[] = {
+               TRANSCODER_A,
+               TRANSCODER_B,
+               TRANSCODER_C,
+               TRANSCODER_EDP,
+       };
        int i;
 
+       if (INTEL_INFO(dev)->num_pipes == 0)
+               return NULL;
+
        error = kmalloc(sizeof(*error), GFP_ATOMIC);
        if (error == NULL)
                return NULL;
@@ -10089,9 +10103,6 @@ intel_display_capture_error_state(struct drm_device *dev)
                error->power_well_driver = I915_READ(HSW_PWR_WELL_DRIVER);
 
        for_each_pipe(i) {
-               cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv, i);
-               error->pipe[i].cpu_transcoder = cpu_transcoder;
-
                if (INTEL_INFO(dev)->gen <= 6 || IS_VALLEYVIEW(dev)) {
                        error->cursor[i].control = I915_READ(CURCNTR(i));
                        error->cursor[i].position = I915_READ(CURPOS(i));
@@ -10115,14 +10126,25 @@ intel_display_capture_error_state(struct drm_device *dev)
                        error->plane[i].tile_offset = I915_READ(DSPTILEOFF(i));
                }
 
-               error->pipe[i].conf = I915_READ(PIPECONF(cpu_transcoder));
                error->pipe[i].source = I915_READ(PIPESRC(i));
-               error->pipe[i].htotal = I915_READ(HTOTAL(cpu_transcoder));
-               error->pipe[i].hblank = I915_READ(HBLANK(cpu_transcoder));
-               error->pipe[i].hsync = I915_READ(HSYNC(cpu_transcoder));
-               error->pipe[i].vtotal = I915_READ(VTOTAL(cpu_transcoder));
-               error->pipe[i].vblank = I915_READ(VBLANK(cpu_transcoder));
-               error->pipe[i].vsync = I915_READ(VSYNC(cpu_transcoder));
+       }
+
+       error->num_transcoders = INTEL_INFO(dev)->num_pipes;
+       if (HAS_DDI(dev_priv->dev))
+               error->num_transcoders++; /* Account for eDP. */
+
+       for (i = 0; i < error->num_transcoders; i++) {
+               enum transcoder cpu_transcoder = transcoders[i];
+
+               error->transcoder[i].cpu_transcoder = cpu_transcoder;
+
+               error->transcoder[i].conf = I915_READ(PIPECONF(cpu_transcoder));
+               error->transcoder[i].htotal = I915_READ(HTOTAL(cpu_transcoder));
+               error->transcoder[i].hblank = I915_READ(HBLANK(cpu_transcoder));
+               error->transcoder[i].hsync = I915_READ(HSYNC(cpu_transcoder));
+               error->transcoder[i].vtotal = I915_READ(VTOTAL(cpu_transcoder));
+               error->transcoder[i].vblank = I915_READ(VBLANK(cpu_transcoder));
+               error->transcoder[i].vsync = I915_READ(VSYNC(cpu_transcoder));
        }
 
        /* In the code above we read the registers without checking if the power
@@ -10144,22 +10166,16 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m,
 {
        int i;
 
+       if (!error)
+               return;
+
        err_printf(m, "Num Pipes: %d\n", INTEL_INFO(dev)->num_pipes);
        if (HAS_POWER_WELL(dev))
                err_printf(m, "PWR_WELL_CTL2: %08x\n",
                           error->power_well_driver);
        for_each_pipe(i) {
                err_printf(m, "Pipe [%d]:\n", i);
-               err_printf(m, "  CPU transcoder: %c\n",
-                          transcoder_name(error->pipe[i].cpu_transcoder));
-               err_printf(m, "  CONF: %08x\n", error->pipe[i].conf);
                err_printf(m, "  SRC: %08x\n", error->pipe[i].source);
-               err_printf(m, "  HTOTAL: %08x\n", error->pipe[i].htotal);
-               err_printf(m, "  HBLANK: %08x\n", error->pipe[i].hblank);
-               err_printf(m, "  HSYNC: %08x\n", error->pipe[i].hsync);
-               err_printf(m, "  VTOTAL: %08x\n", error->pipe[i].vtotal);
-               err_printf(m, "  VBLANK: %08x\n", error->pipe[i].vblank);
-               err_printf(m, "  VSYNC: %08x\n", error->pipe[i].vsync);
 
                err_printf(m, "Plane [%d]:\n", i);
                err_printf(m, "  CNTR: %08x\n", error->plane[i].control);
@@ -10180,5 +10196,17 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m,
                err_printf(m, "  POS: %08x\n", error->cursor[i].position);
                err_printf(m, "  BASE: %08x\n", error->cursor[i].base);
        }
+
+       for (i = 0; i < error->num_transcoders; i++) {
+               err_printf(m, "  CPU transcoder: %c\n",
+                          transcoder_name(error->transcoder[i].cpu_transcoder));
+               err_printf(m, "  CONF: %08x\n", error->transcoder[i].conf);
+               err_printf(m, "  HTOTAL: %08x\n", error->transcoder[i].htotal);
+               err_printf(m, "  HBLANK: %08x\n", error->transcoder[i].hblank);
+               err_printf(m, "  HSYNC: %08x\n", error->transcoder[i].hsync);
+               err_printf(m, "  VTOTAL: %08x\n", error->transcoder[i].vtotal);
+               err_printf(m, "  VBLANK: %08x\n", error->transcoder[i].vblank);
+               err_printf(m, "  VSYNC: %08x\n", error->transcoder[i].vsync);
+       }
 }
 #endif
index 664118d..079ef01 100644 (file)
@@ -968,6 +968,18 @@ void intel_ring_setup_status_page(struct intel_ring_buffer *ring)
 
        I915_WRITE(mmio, (u32)ring->status_page.gfx_addr);
        POSTING_READ(mmio);
+
+       /* Flush the TLB for this page */
+       if (INTEL_INFO(dev)->gen >= 6) {
+               u32 reg = RING_INSTPM(ring->mmio_base);
+               I915_WRITE(reg,
+                          _MASKED_BIT_ENABLE(INSTPM_TLB_INVALIDATE |
+                                             INSTPM_SYNC_FLUSH));
+               if (wait_for((I915_READ(reg) & INSTPM_SYNC_FLUSH) == 0,
+                            1000))
+                       DRM_ERROR("%s: wait for SyncFlush to complete for TLB invalidation timed out\n",
+                                 ring->name);
+       }
 }
 
 static int
index d829172..7a4e089 100644 (file)
@@ -98,6 +98,8 @@ nouveau_mm_head(struct nouveau_mm *mm, u8 type, u32 size_max, u32 size_min,
        u32 splitoff;
        u32 s, e;
 
+       BUG_ON(!type);
+
        list_for_each_entry(this, &mm->free, fl_entry) {
                e = this->offset + this->length;
                s = this->offset;
@@ -162,6 +164,8 @@ nouveau_mm_tail(struct nouveau_mm *mm, u8 type, u32 size_max, u32 size_min,
        struct nouveau_mm_node *prev, *this, *next;
        u32 mask = align - 1;
 
+       BUG_ON(!type);
+
        list_for_each_entry_reverse(this, &mm->free, fl_entry) {
                u32 e = this->offset + this->length;
                u32 s = this->offset;
index d550226..9d2cd20 100644 (file)
@@ -20,8 +20,8 @@ nouveau_mc(void *obj)
        return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_MC];
 }
 
-#define nouveau_mc_create(p,e,o,d)                                             \
-       nouveau_mc_create_((p), (e), (o), sizeof(**d), (void **)d)
+#define nouveau_mc_create(p,e,o,m,d)                                           \
+       nouveau_mc_create_((p), (e), (o), (m), sizeof(**d), (void **)d)
 #define nouveau_mc_destroy(p) ({                                               \
        struct nouveau_mc *pmc = (p); _nouveau_mc_dtor(nv_object(pmc));        \
 })
@@ -33,7 +33,8 @@ nouveau_mc(void *obj)
 })
 
 int  nouveau_mc_create_(struct nouveau_object *, struct nouveau_object *,
-                       struct nouveau_oclass *, int, void **);
+                       struct nouveau_oclass *, const struct nouveau_mc_intr *,
+                       int, void **);
 void _nouveau_mc_dtor(struct nouveau_object *);
 int  _nouveau_mc_init(struct nouveau_object *);
 int  _nouveau_mc_fini(struct nouveau_object *, bool);
index 19e3a9a..ab7ef0a 100644 (file)
@@ -40,15 +40,15 @@ nv49_ram_create(struct nouveau_object *parent, struct nouveau_object *engine,
                return ret;
 
        switch (pfb914 & 0x00000003) {
-       case 0x00000000: pfb->ram->type = NV_MEM_TYPE_DDR1; break;
-       case 0x00000001: pfb->ram->type = NV_MEM_TYPE_DDR2; break;
-       case 0x00000002: pfb->ram->type = NV_MEM_TYPE_GDDR3; break;
+       case 0x00000000: ram->type = NV_MEM_TYPE_DDR1; break;
+       case 0x00000001: ram->type = NV_MEM_TYPE_DDR2; break;
+       case 0x00000002: ram->type = NV_MEM_TYPE_GDDR3; break;
        case 0x00000003: break;
        }
 
-       pfb->ram->size  =  nv_rd32(pfb, 0x10020c) & 0xff000000;
-       pfb->ram->parts = (nv_rd32(pfb, 0x100200) & 0x00000003) + 1;
-       pfb->ram->tags  =  nv_rd32(pfb, 0x100320);
+       ram->size  =  nv_rd32(pfb, 0x10020c) & 0xff000000;
+       ram->parts = (nv_rd32(pfb, 0x100200) & 0x00000003) + 1;
+       ram->tags  =  nv_rd32(pfb, 0x100320);
        return 0;
 }
 
index 7192aa6..63a6aab 100644 (file)
@@ -38,8 +38,8 @@ nv4e_ram_create(struct nouveau_object *parent, struct nouveau_object *engine,
        if (ret)
                return ret;
 
-       pfb->ram->size = nv_rd32(pfb, 0x10020c) & 0xff000000;
-       pfb->ram->type = NV_MEM_TYPE_STOLEN;
+       ram->size = nv_rd32(pfb, 0x10020c) & 0xff000000;
+       ram->type = NV_MEM_TYPE_STOLEN;
        return 0;
 }
 
index bcca883..cce65cc 100644 (file)
@@ -30,8 +30,9 @@ struct nvc0_ltcg_priv {
        struct nouveau_ltcg base;
        u32 part_nr;
        u32 subp_nr;
-       struct nouveau_mm tags;
        u32 num_tags;
+       u32 tag_base;
+       struct nouveau_mm tags;
        struct nouveau_mm_node *tag_ram;
 };
 
@@ -117,10 +118,6 @@ nvc0_ltcg_init_tag_ram(struct nouveau_fb *pfb, struct nvc0_ltcg_priv *priv)
        u32 tag_size, tag_margin, tag_align;
        int ret;
 
-       nv_wr32(priv, 0x17e8d8, priv->part_nr);
-       if (nv_device(pfb)->card_type >= NV_E0)
-               nv_wr32(priv, 0x17e000, priv->part_nr);
-
        /* tags for 1/4 of VRAM should be enough (8192/4 per GiB of VRAM) */
        priv->num_tags = (pfb->ram->size >> 17) / 4;
        if (priv->num_tags > (1 << 17))
@@ -142,7 +139,7 @@ nvc0_ltcg_init_tag_ram(struct nouveau_fb *pfb, struct nvc0_ltcg_priv *priv)
        tag_size += tag_align;
        tag_size  = (tag_size + 0xfff) >> 12; /* round up */
 
-       ret = nouveau_mm_tail(&pfb->vram, 0, tag_size, tag_size, 1,
+       ret = nouveau_mm_tail(&pfb->vram, 1, tag_size, tag_size, 1,
                              &priv->tag_ram);
        if (ret) {
                priv->num_tags = 0;
@@ -152,7 +149,7 @@ nvc0_ltcg_init_tag_ram(struct nouveau_fb *pfb, struct nvc0_ltcg_priv *priv)
                tag_base += tag_align - 1;
                ret = do_div(tag_base, tag_align);
 
-               nv_wr32(priv, 0x17e8d4, tag_base);
+               priv->tag_base = tag_base;
        }
        ret = nouveau_mm_init(&priv->tags, 0, priv->num_tags, 1);
 
@@ -182,8 +179,6 @@ nvc0_ltcg_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        }
        priv->subp_nr = nv_rd32(priv, 0x17e8dc) >> 28;
 
-       nv_mask(priv, 0x17e820, 0x00100000, 0x00000000); /* INTR_EN &= ~0x10 */
-
        ret = nvc0_ltcg_init_tag_ram(pfb, priv);
        if (ret)
                return ret;
@@ -209,13 +204,32 @@ nvc0_ltcg_dtor(struct nouveau_object *object)
        nouveau_ltcg_destroy(ltcg);
 }
 
+static int
+nvc0_ltcg_init(struct nouveau_object *object)
+{
+       struct nouveau_ltcg *ltcg = (struct nouveau_ltcg *)object;
+       struct nvc0_ltcg_priv *priv = (struct nvc0_ltcg_priv *)ltcg;
+       int ret;
+
+       ret = nouveau_ltcg_init(ltcg);
+       if (ret)
+               return ret;
+
+       nv_mask(priv, 0x17e820, 0x00100000, 0x00000000); /* INTR_EN &= ~0x10 */
+       nv_wr32(priv, 0x17e8d8, priv->part_nr);
+       if (nv_device(ltcg)->card_type >= NV_E0)
+               nv_wr32(priv, 0x17e000, priv->part_nr);
+       nv_wr32(priv, 0x17e8d4, priv->tag_base);
+       return 0;
+}
+
 struct nouveau_oclass
 nvc0_ltcg_oclass = {
        .handle = NV_SUBDEV(LTCG, 0xc0),
        .ofuncs = &(struct nouveau_ofuncs) {
                .ctor = nvc0_ltcg_ctor,
                .dtor = nvc0_ltcg_dtor,
-               .init = _nouveau_ltcg_init,
+               .init = nvc0_ltcg_init,
                .fini = _nouveau_ltcg_fini,
        },
 };
index 1c0330b..ec9cd6f 100644 (file)
@@ -80,7 +80,9 @@ _nouveau_mc_dtor(struct nouveau_object *object)
 
 int
 nouveau_mc_create_(struct nouveau_object *parent, struct nouveau_object *engine,
-                  struct nouveau_oclass *oclass, int length, void **pobject)
+                  struct nouveau_oclass *oclass,
+                  const struct nouveau_mc_intr *intr_map,
+                  int length, void **pobject)
 {
        struct nouveau_device *device = nv_device(parent);
        struct nouveau_mc *pmc;
@@ -92,6 +94,8 @@ nouveau_mc_create_(struct nouveau_object *parent, struct nouveau_object *engine,
        if (ret)
                return ret;
 
+       pmc->intr_map = intr_map;
+
        ret = request_irq(device->pdev->irq, nouveau_mc_intr,
                          IRQF_SHARED, "nouveau", pmc);
        if (ret < 0)
index 8c76971..64aa4ed 100644 (file)
@@ -50,12 +50,11 @@ nv04_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nv04_mc_priv *priv;
        int ret;
 
-       ret = nouveau_mc_create(parent, engine, oclass, &priv);
+       ret = nouveau_mc_create(parent, engine, oclass, nv04_mc_intr, &priv);
        *pobject = nv_object(priv);
        if (ret)
                return ret;
 
-       priv->base.intr_map = nv04_mc_intr;
        return 0;
 }
 
index 5191937..d989178 100644 (file)
@@ -36,12 +36,11 @@ nv44_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nv44_mc_priv *priv;
        int ret;
 
-       ret = nouveau_mc_create(parent, engine, oclass, &priv);
+       ret = nouveau_mc_create(parent, engine, oclass, nv04_mc_intr, &priv);
        *pobject = nv_object(priv);
        if (ret)
                return ret;
 
-       priv->base.intr_map = nv04_mc_intr;
        return 0;
 }
 
index f25fc5f..2b1afe2 100644 (file)
@@ -53,12 +53,11 @@ nv50_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nv50_mc_priv *priv;
        int ret;
 
-       ret = nouveau_mc_create(parent, engine, oclass, &priv);
+       ret = nouveau_mc_create(parent, engine, oclass, nv50_mc_intr, &priv);
        *pobject = nv_object(priv);
        if (ret)
                return ret;
 
-       priv->base.intr_map = nv50_mc_intr;
        return 0;
 }
 
index e82fd21..0d57b4d 100644 (file)
@@ -54,12 +54,11 @@ nv98_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nv98_mc_priv *priv;
        int ret;
 
-       ret = nouveau_mc_create(parent, engine, oclass, &priv);
+       ret = nouveau_mc_create(parent, engine, oclass, nv98_mc_intr, &priv);
        *pobject = nv_object(priv);
        if (ret)
                return ret;
 
-       priv->base.intr_map = nv98_mc_intr;
        return 0;
 }
 
index c5da3ba..104175c 100644 (file)
@@ -57,12 +57,11 @@ nvc0_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nvc0_mc_priv *priv;
        int ret;
 
-       ret = nouveau_mc_create(parent, engine, oclass, &priv);
+       ret = nouveau_mc_create(parent, engine, oclass, nvc0_mc_intr, &priv);
        *pobject = nv_object(priv);
        if (ret)
                return ret;
 
-       priv->base.intr_map = nvc0_mc_intr;
        return 0;
 }
 
index 0782bd2..6a13ffb 100644 (file)
@@ -606,6 +606,24 @@ nv_crtc_mode_set_regs(struct drm_crtc *crtc, struct drm_display_mode * mode)
        regp->ramdac_a34 = 0x1;
 }
 
+static int
+nv_crtc_swap_fbs(struct drm_crtc *crtc, struct drm_framebuffer *old_fb)
+{
+       struct nv04_display *disp = nv04_display(crtc->dev);
+       struct nouveau_framebuffer *nvfb = nouveau_framebuffer(crtc->fb);
+       struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+       int ret;
+
+       ret = nouveau_bo_pin(nvfb->nvbo, TTM_PL_FLAG_VRAM);
+       if (ret == 0) {
+               if (disp->image[nv_crtc->index])
+                       nouveau_bo_unpin(disp->image[nv_crtc->index]);
+               nouveau_bo_ref(nvfb->nvbo, &disp->image[nv_crtc->index]);
+       }
+
+       return ret;
+}
+
 /**
  * Sets up registers for the given mode/adjusted_mode pair.
  *
@@ -622,10 +640,15 @@ nv_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
        struct drm_device *dev = crtc->dev;
        struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
        struct nouveau_drm *drm = nouveau_drm(dev);
+       int ret;
 
        NV_DEBUG(drm, "CTRC mode on CRTC %d:\n", nv_crtc->index);
        drm_mode_debug_printmodeline(adjusted_mode);
 
+       ret = nv_crtc_swap_fbs(crtc, old_fb);
+       if (ret)
+               return ret;
+
        /* unlock must come after turning off FP_TG_CONTROL in output_prepare */
        nv_lock_vga_crtc_shadow(dev, nv_crtc->index, -1);
 
@@ -722,6 +745,7 @@ static void nv_crtc_commit(struct drm_crtc *crtc)
 
 static void nv_crtc_destroy(struct drm_crtc *crtc)
 {
+       struct nv04_display *disp = nv04_display(crtc->dev);
        struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
 
        if (!nv_crtc)
@@ -729,6 +753,10 @@ static void nv_crtc_destroy(struct drm_crtc *crtc)
 
        drm_crtc_cleanup(crtc);
 
+       if (disp->image[nv_crtc->index])
+               nouveau_bo_unpin(disp->image[nv_crtc->index]);
+       nouveau_bo_ref(NULL, &disp->image[nv_crtc->index]);
+
        nouveau_bo_unmap(nv_crtc->cursor.nvbo);
        nouveau_bo_unpin(nv_crtc->cursor.nvbo);
        nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo);
@@ -753,6 +781,16 @@ nv_crtc_gamma_load(struct drm_crtc *crtc)
        nouveau_hw_load_state_palette(dev, nv_crtc->index, &nv04_display(dev)->mode_reg);
 }
 
+static void
+nv_crtc_disable(struct drm_crtc *crtc)
+{
+       struct nv04_display *disp = nv04_display(crtc->dev);
+       struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+       if (disp->image[nv_crtc->index])
+               nouveau_bo_unpin(disp->image[nv_crtc->index]);
+       nouveau_bo_ref(NULL, &disp->image[nv_crtc->index]);
+}
+
 static void
 nv_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, uint32_t start,
                  uint32_t size)
@@ -791,7 +829,6 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,
        struct drm_framebuffer *drm_fb;
        struct nouveau_framebuffer *fb;
        int arb_burst, arb_lwm;
-       int ret;
 
        NV_DEBUG(drm, "index %d\n", nv_crtc->index);
 
@@ -801,10 +838,8 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,
                return 0;
        }
 
-
        /* If atomic, we want to switch to the fb we were passed, so
-        * now we update pointers to do that.  (We don't pin; just
-        * assume we're already pinned and update the base address.)
+        * now we update pointers to do that.
         */
        if (atomic) {
                drm_fb = passed_fb;
@@ -812,17 +847,6 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,
        } else {
                drm_fb = crtc->fb;
                fb = nouveau_framebuffer(crtc->fb);
-               /* If not atomic, we can go ahead and pin, and unpin the
-                * old fb we were passed.
-                */
-               ret = nouveau_bo_pin(fb->nvbo, TTM_PL_FLAG_VRAM);
-               if (ret)
-                       return ret;
-
-               if (passed_fb) {
-                       struct nouveau_framebuffer *ofb = nouveau_framebuffer(passed_fb);
-                       nouveau_bo_unpin(ofb->nvbo);
-               }
        }
 
        nv_crtc->fb.offset = fb->nvbo->bo.offset;
@@ -877,6 +901,9 @@ static int
 nv04_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
                        struct drm_framebuffer *old_fb)
 {
+       int ret = nv_crtc_swap_fbs(crtc, old_fb);
+       if (ret)
+               return ret;
        return nv04_crtc_do_mode_set_base(crtc, old_fb, x, y, false);
 }
 
@@ -1027,6 +1054,7 @@ static const struct drm_crtc_helper_funcs nv04_crtc_helper_funcs = {
        .mode_set_base = nv04_crtc_mode_set_base,
        .mode_set_base_atomic = nv04_crtc_mode_set_base_atomic,
        .load_lut = nv_crtc_gamma_load,
+       .disable = nv_crtc_disable,
 };
 
 int
index a0a031d..9928187 100644 (file)
@@ -81,6 +81,7 @@ struct nv04_display {
        uint32_t saved_vga_font[4][16384];
        uint32_t dac_users[4];
        struct nouveau_object *core;
+       struct nouveau_bo *image[2];
 };
 
 static inline struct nv04_display *
index 907d20e..a03e75d 100644 (file)
@@ -577,6 +577,9 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
                ret = nv50_display_flip_next(crtc, fb, chan, 0);
                if (ret)
                        goto fail_unreserve;
+       } else {
+               struct nv04_display *dispnv04 = nv04_display(dev);
+               nouveau_bo_ref(new_bo, &dispnv04->image[nouveau_crtc(crtc)->index]);
        }
 
        ret = nouveau_page_flip_emit(chan, old_bo, new_bo, s, &fence);
index 3af5bcd..625f80d 100644 (file)
@@ -131,7 +131,7 @@ nv40_calc_pll(struct drm_device *dev, u32 reg, struct nvbios_pll *pll,
        if (clk < pll->vco1.max_freq)
                pll->vco2.max_freq = 0;
 
-       pclk->pll_calc(pclk, pll, clk, &coef);
+       ret = pclk->pll_calc(pclk, pll, clk, &coef);
        if (ret == 0)
                return -ERANGE;
 
index 274b8e1..9f19259 100644 (file)
@@ -2163,7 +2163,7 @@ void cik_mm_wdoorbell(struct radeon_device *rdev, u32 offset, u32 v);
                WREG32(reg, tmp_);                              \
        } while (0)
 #define WREG32_AND(reg, and) WREG32_P(reg, 0, and)
-#define WREG32_OR(reg, or) WREG32_P(reg, or, ~or)
+#define WREG32_OR(reg, or) WREG32_P(reg, or, ~(or))
 #define WREG32_PLL_P(reg, val, mask)                           \
        do {                                                    \
                uint32_t tmp_ = RREG32_PLL(reg);                \
index f1c1575..b79f4f5 100644 (file)
@@ -356,6 +356,14 @@ static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo,
                return -EINVAL;
        }
 
+       if (bo->tbo.sync_obj) {
+               r = radeon_fence_wait(bo->tbo.sync_obj, false);
+               if (r) {
+                       DRM_ERROR("Failed waiting for UVD message (%d)!\n", r);
+                       return r;
+               }
+       }
+
        r = radeon_bo_kmap(bo, &ptr);
        if (r) {
                DRM_ERROR("Failed mapping the UVD message (%d)!\n", r);
index bcc68ec..f5e92cf 100644 (file)
@@ -744,10 +744,10 @@ static void rv770_init_golden_registers(struct radeon_device *rdev)
                                                 (const u32)ARRAY_SIZE(r7xx_golden_dyn_gpr_registers));
                radeon_program_register_sequence(rdev,
                                                 rv730_golden_registers,
-                                                (const u32)ARRAY_SIZE(rv770_golden_registers));
+                                                (const u32)ARRAY_SIZE(rv730_golden_registers));
                radeon_program_register_sequence(rdev,
                                                 rv730_mgcg_init,
-                                                (const u32)ARRAY_SIZE(rv770_mgcg_init));
+                                                (const u32)ARRAY_SIZE(rv730_mgcg_init));
                break;
        case CHIP_RV710:
                radeon_program_register_sequence(rdev,
@@ -758,18 +758,18 @@ static void rv770_init_golden_registers(struct radeon_device *rdev)
                                                 (const u32)ARRAY_SIZE(r7xx_golden_dyn_gpr_registers));
                radeon_program_register_sequence(rdev,
                                                 rv710_golden_registers,
-                                                (const u32)ARRAY_SIZE(rv770_golden_registers));
+                                                (const u32)ARRAY_SIZE(rv710_golden_registers));
                radeon_program_register_sequence(rdev,
                                                 rv710_mgcg_init,
-                                                (const u32)ARRAY_SIZE(rv770_mgcg_init));
+                                                (const u32)ARRAY_SIZE(rv710_mgcg_init));
                break;
        case CHIP_RV740:
                radeon_program_register_sequence(rdev,
                                                 rv740_golden_registers,
-                                                (const u32)ARRAY_SIZE(rv770_golden_registers));
+                                                (const u32)ARRAY_SIZE(rv740_golden_registers));
                radeon_program_register_sequence(rdev,
                                                 rv740_mgcg_init,
-                                                (const u32)ARRAY_SIZE(rv770_mgcg_init));
+                                                (const u32)ARRAY_SIZE(rv740_mgcg_init));
                break;
        default:
                break;
index 5f4749e..c1cd569 100644 (file)
@@ -232,7 +232,8 @@ static int adjd_s311_read_raw(struct iio_dev *indio_dev,
 
        switch (mask) {
        case IIO_CHAN_INFO_RAW:
-               ret = adjd_s311_read_data(indio_dev, chan->address, val);
+               ret = adjd_s311_read_data(indio_dev,
+                       ADJD_S311_DATA_REG(chan->address), val);
                if (ret < 0)
                        return ret;
                return IIO_VAL_INT;
index dc112a7..4296155 100644 (file)
@@ -959,23 +959,21 @@ out:
        return r;
 }
 
-static void remove_mapping(struct mq_policy *mq, dm_oblock_t oblock)
+static void mq_remove_mapping(struct dm_cache_policy *p, dm_oblock_t oblock)
 {
-       struct entry *e = hash_lookup(mq, oblock);
+       struct mq_policy *mq = to_mq_policy(p);
+       struct entry *e;
+
+       mutex_lock(&mq->lock);
+
+       e = hash_lookup(mq, oblock);
 
        BUG_ON(!e || !e->in_cache);
 
        del(mq, e);
        e->in_cache = false;
        push(mq, e);
-}
 
-static void mq_remove_mapping(struct dm_cache_policy *p, dm_oblock_t oblock)
-{
-       struct mq_policy *mq = to_mq_policy(p);
-
-       mutex_lock(&mq->lock);
-       remove_mapping(mq, oblock);
        mutex_unlock(&mq->lock);
 }
 
index 07f257d..e48cb33 100644 (file)
@@ -3714,11 +3714,17 @@ static int bond_neigh_init(struct neighbour *n)
  * The bonding ndo_neigh_setup is called at init time beofre any
  * slave exists. So we must declare proxy setup function which will
  * be used at run time to resolve the actual slave neigh param setup.
+ *
+ * It's also called by master devices (such as vlans) to setup their
+ * underlying devices. In that case - do nothing, we're already set up from
+ * our init.
  */
 static int bond_neigh_setup(struct net_device *dev,
                            struct neigh_parms *parms)
 {
-       parms->neigh_setup   = bond_neigh_init;
+       /* modify only our neigh_parms */
+       if (parms->dev == dev)
+               parms->neigh_setup = bond_neigh_init;
 
        return 0;
 }
index 25723d8..925ab8e 100644 (file)
@@ -649,7 +649,7 @@ static int pcan_usb_decode_data(struct pcan_usb_msg_context *mc, u8 status_len)
                if ((mc->ptr + rec_len) > mc->end)
                        goto decode_failed;
 
-               memcpy(cf->data, mc->ptr, rec_len);
+               memcpy(cf->data, mc->ptr, cf->can_dlc);
                mc->ptr += rec_len;
        }
 
index f1b121e..55d79cb 100644 (file)
@@ -199,7 +199,7 @@ static int arc_emac_rx(struct net_device *ndev, int budget)
        struct arc_emac_priv *priv = netdev_priv(ndev);
        unsigned int work_done;
 
-       for (work_done = 0; work_done <= budget; work_done++) {
+       for (work_done = 0; work_done < budget; work_done++) {
                unsigned int *last_rx_bd = &priv->last_rx_bd;
                struct net_device_stats *stats = &priv->stats;
                struct buffer_state *rx_buff = &priv->rx_buff[*last_rx_bd];
index d80e34b..00b88cb 100644 (file)
@@ -1333,6 +1333,8 @@ enum {
        BNX2X_SP_RTNL_VFPF_CHANNEL_DOWN,
        BNX2X_SP_RTNL_VFPF_STORM_RX_MODE,
        BNX2X_SP_RTNL_HYPERVISOR_VLAN,
+       BNX2X_SP_RTNL_TX_STOP,
+       BNX2X_SP_RTNL_TX_RESUME,
 };
 
 struct bnx2x_prev_path_list {
@@ -1502,6 +1504,7 @@ struct bnx2x {
 #define BC_SUPPORTS_DCBX_MSG_NON_PMF   (1 << 21)
 #define IS_VF_FLAG                     (1 << 22)
 #define INTERRUPTS_ENABLED_FLAG                (1 << 23)
+#define BC_SUPPORTS_RMMOD_CMD          (1 << 24)
 
 #define BP_NOMCP(bp)                   ((bp)->flags & NO_MCP_FLAG)
 
@@ -1830,6 +1833,8 @@ struct bnx2x {
 
        int fp_array_size;
        u32 dump_preset_idx;
+       bool                                    stats_started;
+       struct semaphore                        stats_sema;
 };
 
 /* Tx queues may be less or equal to Rx queues */
@@ -2451,4 +2456,6 @@ enum bnx2x_pci_bus_speed {
        BNX2X_PCI_LINK_SPEED_5000 = 5000,
        BNX2X_PCI_LINK_SPEED_8000 = 8000
 };
+
+void bnx2x_set_local_cmng(struct bnx2x *bp);
 #endif /* bnx2x.h */
index 0c94df4..fcf2761 100644 (file)
 #include "bnx2x_dcb.h"
 
 /* forward declarations of dcbx related functions */
-static int bnx2x_dcbx_stop_hw_tx(struct bnx2x *bp);
 static void bnx2x_pfc_set_pfc(struct bnx2x *bp);
 static void bnx2x_dcbx_update_ets_params(struct bnx2x *bp);
-static int bnx2x_dcbx_resume_hw_tx(struct bnx2x *bp);
 static void bnx2x_dcbx_get_ets_pri_pg_tbl(struct bnx2x *bp,
                                          u32 *set_configuration_ets_pg,
                                          u32 *pri_pg_tbl);
@@ -425,30 +423,52 @@ static void bnx2x_pfc_set_pfc(struct bnx2x *bp)
                bnx2x_pfc_clear(bp);
 }
 
-static int bnx2x_dcbx_stop_hw_tx(struct bnx2x *bp)
+int bnx2x_dcbx_stop_hw_tx(struct bnx2x *bp)
 {
        struct bnx2x_func_state_params func_params = {NULL};
+       int rc;
 
        func_params.f_obj = &bp->func_obj;
        func_params.cmd = BNX2X_F_CMD_TX_STOP;
 
+       __set_bit(RAMROD_COMP_WAIT, &func_params.ramrod_flags);
+       __set_bit(RAMROD_RETRY, &func_params.ramrod_flags);
+
        DP(BNX2X_MSG_DCB, "STOP TRAFFIC\n");
-       return bnx2x_func_state_change(bp, &func_params);
+
+       rc = bnx2x_func_state_change(bp, &func_params);
+       if (rc) {
+               BNX2X_ERR("Unable to hold traffic for HW configuration\n");
+               bnx2x_panic();
+       }
+
+       return rc;
 }
 
-static int bnx2x_dcbx_resume_hw_tx(struct bnx2x *bp)
+int bnx2x_dcbx_resume_hw_tx(struct bnx2x *bp)
 {
        struct bnx2x_func_state_params func_params = {NULL};
        struct bnx2x_func_tx_start_params *tx_params =
                &func_params.params.tx_start;
+       int rc;
 
        func_params.f_obj = &bp->func_obj;
        func_params.cmd = BNX2X_F_CMD_TX_START;
 
+       __set_bit(RAMROD_COMP_WAIT, &func_params.ramrod_flags);
+       __set_bit(RAMROD_RETRY, &func_params.ramrod_flags);
+
        bnx2x_dcbx_fw_struct(bp, tx_params);
 
        DP(BNX2X_MSG_DCB, "START TRAFFIC\n");
-       return bnx2x_func_state_change(bp, &func_params);
+
+       rc = bnx2x_func_state_change(bp, &func_params);
+       if (rc) {
+               BNX2X_ERR("Unable to resume traffic after HW configuration\n");
+               bnx2x_panic();
+       }
+
+       return rc;
 }
 
 static void bnx2x_dcbx_2cos_limit_update_ets_config(struct bnx2x *bp)
@@ -744,7 +764,9 @@ void bnx2x_dcbx_set_params(struct bnx2x *bp, u32 state)
                        if (IS_MF(bp))
                                bnx2x_link_sync_notify(bp);
 
-                       bnx2x_dcbx_stop_hw_tx(bp);
+                       set_bit(BNX2X_SP_RTNL_TX_STOP, &bp->sp_rtnl_state);
+
+                       schedule_delayed_work(&bp->sp_rtnl_task, 0);
 
                        return;
                }
@@ -753,7 +775,13 @@ void bnx2x_dcbx_set_params(struct bnx2x *bp, u32 state)
                bnx2x_pfc_set_pfc(bp);
 
                bnx2x_dcbx_update_ets_params(bp);
-               bnx2x_dcbx_resume_hw_tx(bp);
+
+               /* ets may affect cmng configuration: reinit it in hw */
+               bnx2x_set_local_cmng(bp);
+
+               set_bit(BNX2X_SP_RTNL_TX_RESUME, &bp->sp_rtnl_state);
+
+               schedule_delayed_work(&bp->sp_rtnl_task, 0);
 
                return;
        case BNX2X_DCBX_STATE_TX_RELEASED:
@@ -2363,21 +2391,24 @@ static u8 bnx2x_dcbnl_get_featcfg(struct net_device *netdev, int featid,
                case DCB_FEATCFG_ATTR_PG:
                        if (bp->dcbx_local_feat.ets.enabled)
                                *flags |= DCB_FEATCFG_ENABLE;
-                       if (bp->dcbx_error & DCBX_LOCAL_ETS_ERROR)
+                       if (bp->dcbx_error & (DCBX_LOCAL_ETS_ERROR |
+                                             DCBX_REMOTE_MIB_ERROR))
                                *flags |= DCB_FEATCFG_ERROR;
                        break;
                case DCB_FEATCFG_ATTR_PFC:
                        if (bp->dcbx_local_feat.pfc.enabled)
                                *flags |= DCB_FEATCFG_ENABLE;
                        if (bp->dcbx_error & (DCBX_LOCAL_PFC_ERROR |
-                           DCBX_LOCAL_PFC_MISMATCH))
+                                             DCBX_LOCAL_PFC_MISMATCH |
+                                             DCBX_REMOTE_MIB_ERROR))
                                *flags |= DCB_FEATCFG_ERROR;
                        break;
                case DCB_FEATCFG_ATTR_APP:
                        if (bp->dcbx_local_feat.app.enabled)
                                *flags |= DCB_FEATCFG_ENABLE;
                        if (bp->dcbx_error & (DCBX_LOCAL_APP_ERROR |
-                           DCBX_LOCAL_APP_MISMATCH))
+                                             DCBX_LOCAL_APP_MISMATCH |
+                                             DCBX_REMOTE_MIB_ERROR))
                                *flags |= DCB_FEATCFG_ERROR;
                        break;
                default:
index 125bd1b..804b8f6 100644 (file)
@@ -199,4 +199,7 @@ extern const struct dcbnl_rtnl_ops bnx2x_dcbnl_ops;
 int bnx2x_dcbnl_update_applist(struct bnx2x *bp, bool delall);
 #endif /* BCM_DCBNL */
 
+int bnx2x_dcbx_stop_hw_tx(struct bnx2x *bp);
+int bnx2x_dcbx_resume_hw_tx(struct bnx2x *bp);
+
 #endif /* BNX2X_DCB_H */
index 5018e52..32767f6 100644 (file)
@@ -1300,6 +1300,9 @@ struct drv_func_mb {
 
        #define DRV_MSG_CODE_EEE_RESULTS_ACK            0xda000000
 
+       #define DRV_MSG_CODE_RMMOD                      0xdb000000
+       #define REQ_BC_VER_4_RMMOD_CMD                  0x0007080f
+
        #define DRV_MSG_CODE_SET_MF_BW                  0xe0000000
        #define REQ_BC_VER_4_SET_MF_BW                  0x00060202
        #define DRV_MSG_CODE_SET_MF_BW_ACK              0xe1000000
@@ -1372,6 +1375,8 @@ struct drv_func_mb {
 
        #define FW_MSG_CODE_EEE_RESULS_ACK              0xda100000
 
+       #define FW_MSG_CODE_RMMOD_ACK                   0xdb100000
+
        #define FW_MSG_CODE_SET_MF_BW_SENT              0xe0000000
        #define FW_MSG_CODE_SET_MF_BW_DONE              0xe1000000
 
index e06186c..8bdc8b9 100644 (file)
@@ -2261,6 +2261,23 @@ static void bnx2x_set_requested_fc(struct bnx2x *bp)
                bp->link_params.req_fc_auto_adv = BNX2X_FLOW_CTRL_BOTH;
 }
 
+static void bnx2x_init_dropless_fc(struct bnx2x *bp)
+{
+       u32 pause_enabled = 0;
+
+       if (!CHIP_IS_E1(bp) && bp->dropless_fc && bp->link_vars.link_up) {
+               if (bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_TX)
+                       pause_enabled = 1;
+
+               REG_WR(bp, BAR_USTRORM_INTMEM +
+                          USTORM_ETH_PAUSE_ENABLED_OFFSET(BP_PORT(bp)),
+                      pause_enabled);
+       }
+
+       DP(NETIF_MSG_IFUP | NETIF_MSG_LINK, "dropless_fc is %s\n",
+          pause_enabled ? "enabled" : "disabled");
+}
+
 int bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode)
 {
        int rc, cfx_idx = bnx2x_get_link_cfg_idx(bp);
@@ -2294,6 +2311,8 @@ int bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode)
 
                bnx2x_release_phy_lock(bp);
 
+               bnx2x_init_dropless_fc(bp);
+
                bnx2x_calc_fc_adv(bp);
 
                if (bp->link_vars.link_up) {
@@ -2315,6 +2334,8 @@ void bnx2x_link_set(struct bnx2x *bp)
                bnx2x_phy_init(&bp->link_params, &bp->link_vars);
                bnx2x_release_phy_lock(bp);
 
+               bnx2x_init_dropless_fc(bp);
+
                bnx2x_calc_fc_adv(bp);
        } else
                BNX2X_ERR("Bootcode is missing - can not set link\n");
@@ -2476,7 +2497,7 @@ static void bnx2x_cmng_fns_init(struct bnx2x *bp, u8 read_cfg, u8 cmng_type)
 
        input.port_rate = bp->link_vars.line_speed;
 
-       if (cmng_type == CMNG_FNS_MINMAX) {
+       if (cmng_type == CMNG_FNS_MINMAX && input.port_rate) {
                int vn;
 
                /* read mf conf from shmem */
@@ -2533,6 +2554,21 @@ static void storm_memset_cmng(struct bnx2x *bp,
        }
 }
 
+/* init cmng mode in HW according to local configuration */
+void bnx2x_set_local_cmng(struct bnx2x *bp)
+{
+       int cmng_fns = bnx2x_get_cmng_fns_mode(bp);
+
+       if (cmng_fns != CMNG_FNS_NONE) {
+               bnx2x_cmng_fns_init(bp, false, cmng_fns);
+               storm_memset_cmng(bp, &bp->cmng, BP_PORT(bp));
+       } else {
+               /* rate shaping and fairness are disabled */
+               DP(NETIF_MSG_IFUP,
+                  "single function mode without fairness\n");
+       }
+}
+
 /* This function is called upon link interrupt */
 static void bnx2x_link_attn(struct bnx2x *bp)
 {
@@ -2541,20 +2577,9 @@ static void bnx2x_link_attn(struct bnx2x *bp)
 
        bnx2x_link_update(&bp->link_params, &bp->link_vars);
 
-       if (bp->link_vars.link_up) {
+       bnx2x_init_dropless_fc(bp);
 
-               /* dropless flow control */
-               if (!CHIP_IS_E1(bp) && bp->dropless_fc) {
-                       int port = BP_PORT(bp);
-                       u32 pause_enabled = 0;
-
-                       if (bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_TX)
-                               pause_enabled = 1;
-
-                       REG_WR(bp, BAR_USTRORM_INTMEM +
-                              USTORM_ETH_PAUSE_ENABLED_OFFSET(port),
-                              pause_enabled);
-               }
+       if (bp->link_vars.link_up) {
 
                if (bp->link_vars.mac_type != MAC_TYPE_EMAC) {
                        struct host_port_stats *pstats;
@@ -2568,17 +2593,8 @@ static void bnx2x_link_attn(struct bnx2x *bp)
                        bnx2x_stats_handle(bp, STATS_EVENT_LINK_UP);
        }
 
-       if (bp->link_vars.link_up && bp->link_vars.line_speed) {
-               int cmng_fns = bnx2x_get_cmng_fns_mode(bp);
-
-               if (cmng_fns != CMNG_FNS_NONE) {
-                       bnx2x_cmng_fns_init(bp, false, cmng_fns);
-                       storm_memset_cmng(bp, &bp->cmng, BP_PORT(bp));
-               } else
-                       /* rate shaping and fairness are disabled */
-                       DP(NETIF_MSG_IFUP,
-                          "single function mode without fairness\n");
-       }
+       if (bp->link_vars.link_up && bp->link_vars.line_speed)
+               bnx2x_set_local_cmng(bp);
 
        __bnx2x_link_report(bp);
 
@@ -9639,6 +9655,12 @@ sp_rtnl_not_reset:
                               &bp->sp_rtnl_state))
                bnx2x_pf_set_vfs_vlan(bp);
 
+       if (test_and_clear_bit(BNX2X_SP_RTNL_TX_STOP, &bp->sp_rtnl_state))
+               bnx2x_dcbx_stop_hw_tx(bp);
+
+       if (test_and_clear_bit(BNX2X_SP_RTNL_TX_RESUME, &bp->sp_rtnl_state))
+               bnx2x_dcbx_resume_hw_tx(bp);
+
        /* work which needs rtnl lock not-taken (as it takes the lock itself and
         * can be called from other contexts as well)
         */
@@ -10362,6 +10384,10 @@ static void bnx2x_get_common_hwinfo(struct bnx2x *bp)
 
        bp->flags |= (val >= REQ_BC_VER_4_DCBX_ADMIN_MSG_NON_PMF) ?
                        BC_SUPPORTS_DCBX_MSG_NON_PMF : 0;
+
+       bp->flags |= (val >= REQ_BC_VER_4_RMMOD_CMD) ?
+                       BC_SUPPORTS_RMMOD_CMD : 0;
+
        boot_mode = SHMEM_RD(bp,
                        dev_info.port_feature_config[BP_PORT(bp)].mba_config) &
                        PORT_FEATURE_MBA_BOOT_AGENT_TYPE_MASK;
@@ -11137,6 +11163,9 @@ static bool bnx2x_get_dropless_info(struct bnx2x *bp)
        int tmp;
        u32 cfg;
 
+       if (IS_VF(bp))
+               return 0;
+
        if (IS_MF(bp) && !CHIP_IS_E1x(bp)) {
                /* Take function: tmp = func */
                tmp = BP_ABS_FUNC(bp);
@@ -11524,6 +11553,7 @@ static int bnx2x_init_bp(struct bnx2x *bp)
        mutex_init(&bp->port.phy_mutex);
        mutex_init(&bp->fw_mb_mutex);
        spin_lock_init(&bp->stats_lock);
+       sema_init(&bp->stats_sema, 1);
 
        INIT_DELAYED_WORK(&bp->sp_task, bnx2x_sp_task);
        INIT_DELAYED_WORK(&bp->sp_rtnl_task, bnx2x_sp_rtnl_task);
@@ -12817,13 +12847,17 @@ static void __bnx2x_remove(struct pci_dev *pdev,
        bnx2x_dcbnl_update_applist(bp, true);
 #endif
 
+       if (IS_PF(bp) &&
+           !BP_NOMCP(bp) &&
+           (bp->flags & BC_SUPPORTS_RMMOD_CMD))
+               bnx2x_fw_command(bp, DRV_MSG_CODE_RMMOD, 0);
+
        /* Close the interface - either directly or implicitly */
        if (remove_netdev) {
                unregister_netdev(dev);
        } else {
                rtnl_lock();
-               if (netif_running(dev))
-                       bnx2x_close(dev);
+               dev_close(dev);
                rtnl_unlock();
        }
 
index 95861ef..ad83f4b 100644 (file)
@@ -1747,11 +1747,8 @@ void bnx2x_iov_init_dq(struct bnx2x *bp)
 
 void bnx2x_iov_init_dmae(struct bnx2x *bp)
 {
-       DP(BNX2X_MSG_IOV, "SRIOV is %s\n", IS_SRIOV(bp) ? "ON" : "OFF");
-       if (!IS_SRIOV(bp))
-               return;
-
-       REG_WR(bp, DMAE_REG_BACKWARD_COMP_EN, 0);
+       if (pci_find_ext_capability(bp->pdev, PCI_EXT_CAP_ID_SRIOV))
+               REG_WR(bp, DMAE_REG_BACKWARD_COMP_EN, 0);
 }
 
 static int bnx2x_vf_bus(struct bnx2x *bp, int vfid)
@@ -3084,8 +3081,9 @@ void bnx2x_disable_sriov(struct bnx2x *bp)
        pci_disable_sriov(bp->pdev);
 }
 
-static int bnx2x_vf_ndo_sanity(struct bnx2x *bp, int vfidx,
-                              struct bnx2x_virtf *vf)
+static int bnx2x_vf_ndo_prep(struct bnx2x *bp, int vfidx,
+                            struct bnx2x_virtf **vf,
+                            struct pf_vf_bulletin_content **bulletin)
 {
        if (bp->state != BNX2X_STATE_OPEN) {
                BNX2X_ERR("vf ndo called though PF is down\n");
@@ -3103,12 +3101,22 @@ static int bnx2x_vf_ndo_sanity(struct bnx2x *bp, int vfidx,
                return -EINVAL;
        }
 
-       if (!vf) {
+       /* init members */
+       *vf = BP_VF(bp, vfidx);
+       *bulletin = BP_VF_BULLETIN(bp, vfidx);
+
+       if (!*vf) {
                BNX2X_ERR("vf ndo called but vf was null. vfidx was %d\n",
                          vfidx);
                return -EINVAL;
        }
 
+       if (!*bulletin) {
+               BNX2X_ERR("vf ndo called but Bulletin Board struct is null. vfidx was %d\n",
+                         vfidx);
+               return -EINVAL;
+       }
+
        return 0;
 }
 
@@ -3116,17 +3124,19 @@ int bnx2x_get_vf_config(struct net_device *dev, int vfidx,
                        struct ifla_vf_info *ivi)
 {
        struct bnx2x *bp = netdev_priv(dev);
-       struct bnx2x_virtf *vf = BP_VF(bp, vfidx);
-       struct bnx2x_vlan_mac_obj *mac_obj = &bnx2x_vfq(vf, 0, mac_obj);
-       struct bnx2x_vlan_mac_obj *vlan_obj = &bnx2x_vfq(vf, 0, vlan_obj);
-       struct pf_vf_bulletin_content *bulletin = BP_VF_BULLETIN(bp, vfidx);
+       struct bnx2x_virtf *vf = NULL;
+       struct pf_vf_bulletin_content *bulletin = NULL;
+       struct bnx2x_vlan_mac_obj *mac_obj;
+       struct bnx2x_vlan_mac_obj *vlan_obj;
        int rc;
 
-       /* sanity */
-       rc = bnx2x_vf_ndo_sanity(bp, vfidx, vf);
+       /* sanity and init */
+       rc = bnx2x_vf_ndo_prep(bp, vfidx, &vf, &bulletin);
        if (rc)
                return rc;
-       if (!mac_obj || !vlan_obj || !bulletin) {
+       mac_obj = &bnx2x_vfq(vf, 0, mac_obj);
+       vlan_obj = &bnx2x_vfq(vf, 0, vlan_obj);
+       if (!mac_obj || !vlan_obj) {
                BNX2X_ERR("VF partially initialized\n");
                return -EINVAL;
        }
@@ -3183,11 +3193,11 @@ int bnx2x_set_vf_mac(struct net_device *dev, int vfidx, u8 *mac)
 {
        struct bnx2x *bp = netdev_priv(dev);
        int rc, q_logical_state;
-       struct bnx2x_virtf *vf = BP_VF(bp, vfidx);
-       struct pf_vf_bulletin_content *bulletin = BP_VF_BULLETIN(bp, vfidx);
+       struct bnx2x_virtf *vf = NULL;
+       struct pf_vf_bulletin_content *bulletin = NULL;
 
-       /* sanity */
-       rc = bnx2x_vf_ndo_sanity(bp, vfidx, vf);
+       /* sanity and init */
+       rc = bnx2x_vf_ndo_prep(bp, vfidx, &vf, &bulletin);
        if (rc)
                return rc;
        if (!is_valid_ether_addr(mac)) {
@@ -3249,11 +3259,11 @@ int bnx2x_set_vf_vlan(struct net_device *dev, int vfidx, u16 vlan, u8 qos)
 {
        struct bnx2x *bp = netdev_priv(dev);
        int rc, q_logical_state;
-       struct bnx2x_virtf *vf = BP_VF(bp, vfidx);
-       struct pf_vf_bulletin_content *bulletin = BP_VF_BULLETIN(bp, vfidx);
+       struct bnx2x_virtf *vf = NULL;
+       struct pf_vf_bulletin_content *bulletin = NULL;
 
-       /* sanity */
-       rc = bnx2x_vf_ndo_sanity(bp, vfidx, vf);
+       /* sanity and init */
+       rc = bnx2x_vf_ndo_prep(bp, vfidx, &vf, &bulletin);
        if (rc)
                return rc;
 
@@ -3463,7 +3473,7 @@ int bnx2x_vf_pci_alloc(struct bnx2x *bp)
 alloc_mem_err:
        BNX2X_PCI_FREE(bp->vf2pf_mbox, bp->vf2pf_mbox_mapping,
                       sizeof(struct bnx2x_vf_mbx_msg));
-       BNX2X_PCI_FREE(bp->vf2pf_mbox, bp->vf2pf_mbox_mapping,
+       BNX2X_PCI_FREE(bp->vf2pf_mbox, bp->pf2vf_bulletin_mapping,
                       sizeof(union pf_vf_bulletin));
        return -ENOMEM;
 }
index 98366ab..d63d132 100644 (file)
@@ -221,7 +221,8 @@ static int bnx2x_stats_comp(struct bnx2x *bp)
  * Statistics service functions
  */
 
-static void bnx2x_stats_pmf_update(struct bnx2x *bp)
+/* should be called under stats_sema */
+static void __bnx2x_stats_pmf_update(struct bnx2x *bp)
 {
        struct dmae_command *dmae;
        u32 opcode;
@@ -518,7 +519,8 @@ static void bnx2x_func_stats_init(struct bnx2x *bp)
        *stats_comp = 0;
 }
 
-static void bnx2x_stats_start(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
@@ -534,13 +536,34 @@ static void bnx2x_stats_start(struct bnx2x *bp)
 
        bnx2x_hw_stats_post(bp);
        bnx2x_storm_stats_post(bp);
+
+       bp->stats_started = true;
+}
+
+static void bnx2x_stats_start(struct bnx2x *bp)
+{
+       if (down_timeout(&bp->stats_sema, HZ/10))
+               BNX2X_ERR("Unable to acquire stats lock\n");
+       __bnx2x_stats_start(bp);
+       up(&bp->stats_sema);
 }
 
 static void bnx2x_stats_pmf_start(struct bnx2x *bp)
 {
+       if (down_timeout(&bp->stats_sema, HZ/10))
+               BNX2X_ERR("Unable to acquire stats lock\n");
        bnx2x_stats_comp(bp);
-       bnx2x_stats_pmf_update(bp);
-       bnx2x_stats_start(bp);
+       __bnx2x_stats_pmf_update(bp);
+       __bnx2x_stats_start(bp);
+       up(&bp->stats_sema);
+}
+
+static void bnx2x_stats_pmf_update(struct bnx2x *bp)
+{
+       if (down_timeout(&bp->stats_sema, HZ/10))
+               BNX2X_ERR("Unable to acquire stats lock\n");
+       __bnx2x_stats_pmf_update(bp);
+       up(&bp->stats_sema);
 }
 
 static void bnx2x_stats_restart(struct bnx2x *bp)
@@ -550,8 +573,11 @@ static void bnx2x_stats_restart(struct bnx2x *bp)
         */
        if (IS_VF(bp))
                return;
+       if (down_timeout(&bp->stats_sema, HZ/10))
+               BNX2X_ERR("Unable to acquire stats lock\n");
        bnx2x_stats_comp(bp);
-       bnx2x_stats_start(bp);
+       __bnx2x_stats_start(bp);
+       up(&bp->stats_sema);
 }
 
 static void bnx2x_bmac_stats_update(struct bnx2x *bp)
@@ -888,9 +914,7 @@ static int bnx2x_storm_stats_validate_counters(struct bnx2x *bp)
        /* Make sure we use the value of the counter
         * used for sending the last stats ramrod.
         */
-       spin_lock_bh(&bp->stats_lock);
        cur_stats_counter = bp->stats_counter - 1;
-       spin_unlock_bh(&bp->stats_lock);
 
        /* are storm stats valid? */
        if (le16_to_cpu(counters->xstats_counter) != cur_stats_counter) {
@@ -1227,12 +1251,18 @@ static void bnx2x_stats_update(struct bnx2x *bp)
 {
        u32 *stats_comp = bnx2x_sp(bp, stats_comp);
 
-       if (bnx2x_edebug_stats_stopped(bp))
+       /* we run update from timer context, so give up
+        * if somebody is in the middle of transition
+        */
+       if (down_trylock(&bp->stats_sema))
                return;
 
+       if (bnx2x_edebug_stats_stopped(bp) || !bp->stats_started)
+               goto out;
+
        if (IS_PF(bp)) {
                if (*stats_comp != DMAE_COMP_VAL)
-                       return;
+                       goto out;
 
                if (bp->port.pmf)
                        bnx2x_hw_stats_update(bp);
@@ -1242,7 +1272,7 @@ static void bnx2x_stats_update(struct bnx2x *bp)
                                BNX2X_ERR("storm stats were not updated for 3 times\n");
                                bnx2x_panic();
                        }
-                       return;
+                       goto out;
                }
        } else {
                /* vf doesn't collect HW statistics, and doesn't get completions
@@ -1256,7 +1286,7 @@ static void bnx2x_stats_update(struct bnx2x *bp)
 
        /* vf is done */
        if (IS_VF(bp))
-               return;
+               goto out;
 
        if (netif_msg_timer(bp)) {
                struct bnx2x_eth_stats *estats = &bp->eth_stats;
@@ -1267,6 +1297,9 @@ static void bnx2x_stats_update(struct bnx2x *bp)
 
        bnx2x_hw_stats_post(bp);
        bnx2x_storm_stats_post(bp);
+
+out:
+       up(&bp->stats_sema);
 }
 
 static void bnx2x_port_stats_stop(struct bnx2x *bp)
@@ -1332,6 +1365,11 @@ static void bnx2x_stats_stop(struct bnx2x *bp)
 {
        int update = 0;
 
+       if (down_timeout(&bp->stats_sema, HZ/10))
+               BNX2X_ERR("Unable to acquire stats lock\n");
+
+       bp->stats_started = false;
+
        bnx2x_stats_comp(bp);
 
        if (bp->port.pmf)
@@ -1348,6 +1386,8 @@ static void bnx2x_stats_stop(struct bnx2x *bp)
                bnx2x_hw_stats_post(bp);
                bnx2x_stats_comp(bp);
        }
+
+       up(&bp->stats_sema);
 }
 
 static void bnx2x_stats_do_nothing(struct bnx2x *bp)
@@ -1376,15 +1416,17 @@ static const struct {
 void bnx2x_stats_handle(struct bnx2x *bp, enum bnx2x_stats_event event)
 {
        enum bnx2x_stats_state state;
+       void (*action)(struct bnx2x *bp);
        if (unlikely(bp->panic))
                return;
 
        spin_lock_bh(&bp->stats_lock);
        state = bp->stats_state;
        bp->stats_state = bnx2x_stats_stm[state][event].next_state;
+       action = bnx2x_stats_stm[state][event].action;
        spin_unlock_bh(&bp->stats_lock);
 
-       bnx2x_stats_stm[state][event].action(bp);
+       action(bp);
 
        if ((event != STATS_EVENT_UPDATE) || netif_msg_timer(bp))
                DP(BNX2X_MSG_STATS, "state %d -> event %d -> state %d\n",
index ddebc7a..0da2214 100644 (file)
@@ -17796,8 +17796,10 @@ static pci_ers_result_t tg3_io_error_detected(struct pci_dev *pdev,
 
 done:
        if (state == pci_channel_io_perm_failure) {
-               tg3_napi_enable(tp);
-               dev_close(netdev);
+               if (netdev) {
+                       tg3_napi_enable(tp);
+                       dev_close(netdev);
+               }
                err = PCI_ERS_RESULT_DISCONNECT;
        } else {
                pci_disable_device(pdev);
@@ -17827,7 +17829,8 @@ static pci_ers_result_t tg3_io_slot_reset(struct pci_dev *pdev)
        rtnl_lock();
 
        if (pci_enable_device(pdev)) {
-               netdev_err(netdev, "Cannot re-enable PCI device after reset.\n");
+               dev_err(&pdev->dev,
+                       "Cannot re-enable PCI device after reset.\n");
                goto done;
        }
 
@@ -17835,7 +17838,7 @@ static pci_ers_result_t tg3_io_slot_reset(struct pci_dev *pdev)
        pci_restore_state(pdev);
        pci_save_state(pdev);
 
-       if (!netif_running(netdev)) {
+       if (!netdev || !netif_running(netdev)) {
                rc = PCI_ERS_RESULT_RECOVERED;
                goto done;
        }
@@ -17847,7 +17850,7 @@ static pci_ers_result_t tg3_io_slot_reset(struct pci_dev *pdev)
        rc = PCI_ERS_RESULT_RECOVERED;
 
 done:
-       if (rc != PCI_ERS_RESULT_RECOVERED && netif_running(netdev)) {
+       if (rc != PCI_ERS_RESULT_RECOVERED && netdev && netif_running(netdev)) {
                tg3_napi_enable(tp);
                dev_close(netdev);
        }
index 687ec4a..9c89dc8 100644 (file)
@@ -455,11 +455,6 @@ static int alloc_pg_chunk(struct adapter *adapter, struct sge_fl *q,
                q->pg_chunk.offset = 0;
                mapping = pci_map_page(adapter->pdev, q->pg_chunk.page,
                                       0, q->alloc_size, PCI_DMA_FROMDEVICE);
-               if (unlikely(pci_dma_mapping_error(adapter->pdev, mapping))) {
-                       __free_pages(q->pg_chunk.page, order);
-                       q->pg_chunk.page = NULL;
-                       return -EIO;
-               }
                q->pg_chunk.mapping = mapping;
        }
        sd->pg_chunk = q->pg_chunk;
@@ -954,75 +949,40 @@ static inline unsigned int calc_tx_descs(const struct sk_buff *skb)
        return flits_to_desc(flits);
 }
 
-
-/*     map_skb - map a packet main body and its page fragments
- *     @pdev: the PCI device
- *     @skb: the packet
- *     @addr: placeholder to save the mapped addresses
- *
- *     map the main body of an sk_buff and its page fragments, if any.
- */
-static int map_skb(struct pci_dev *pdev, const struct sk_buff *skb,
-                  dma_addr_t *addr)
-{
-       const skb_frag_t *fp, *end;
-       const struct skb_shared_info *si;
-
-       *addr = pci_map_single(pdev, skb->data, skb_headlen(skb),
-                              PCI_DMA_TODEVICE);
-       if (pci_dma_mapping_error(pdev, *addr))
-               goto out_err;
-
-       si = skb_shinfo(skb);
-       end = &si->frags[si->nr_frags];
-
-       for (fp = si->frags; fp < end; fp++) {
-               *++addr = skb_frag_dma_map(&pdev->dev, fp, 0, skb_frag_size(fp),
-                                          DMA_TO_DEVICE);
-               if (pci_dma_mapping_error(pdev, *addr))
-                       goto unwind;
-       }
-       return 0;
-
-unwind:
-       while (fp-- > si->frags)
-               dma_unmap_page(&pdev->dev, *--addr, skb_frag_size(fp),
-                              DMA_TO_DEVICE);
-
-       pci_unmap_single(pdev, addr[-1], skb_headlen(skb), PCI_DMA_TODEVICE);
-out_err:
-       return -ENOMEM;
-}
-
 /**
- *     write_sgl - populate a scatter/gather list for a packet
+ *     make_sgl - populate a scatter/gather list for a packet
  *     @skb: the packet
  *     @sgp: the SGL to populate
  *     @start: start address of skb main body data to include in the SGL
  *     @len: length of skb main body data to include in the SGL
- *     @addr: the list of the mapped addresses
+ *     @pdev: the PCI device
  *
- *     Copies the scatter/gather list for the buffers that make up a packet
+ *     Generates a scatter/gather list for the buffers that make up a packet
  *     and returns the SGL size in 8-byte words.  The caller must size the SGL
  *     appropriately.
  */
-static inline unsigned int write_sgl(const struct sk_buff *skb,
+static inline unsigned int make_sgl(const struct sk_buff *skb,
                                    struct sg_ent *sgp, unsigned char *start,
-                                   unsigned int len, const dma_addr_t *addr)
+                                   unsigned int len, struct pci_dev *pdev)
 {
-       unsigned int i, j = 0, k = 0, nfrags;
+       dma_addr_t mapping;
+       unsigned int i, j = 0, nfrags;
 
        if (len) {
+               mapping = pci_map_single(pdev, start, len, PCI_DMA_TODEVICE);
                sgp->len[0] = cpu_to_be32(len);
-               sgp->addr[j++] = cpu_to_be64(addr[k++]);
+               sgp->addr[0] = cpu_to_be64(mapping);
+               j = 1;
        }
 
        nfrags = skb_shinfo(skb)->nr_frags;
        for (i = 0; i < nfrags; i++) {
                const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
 
+               mapping = skb_frag_dma_map(&pdev->dev, frag, 0, skb_frag_size(frag),
+                                          DMA_TO_DEVICE);
                sgp->len[j] = cpu_to_be32(skb_frag_size(frag));
-               sgp->addr[j] = cpu_to_be64(addr[k++]);
+               sgp->addr[j] = cpu_to_be64(mapping);
                j ^= 1;
                if (j == 0)
                        ++sgp;
@@ -1178,7 +1138,7 @@ static void write_tx_pkt_wr(struct adapter *adap, struct sk_buff *skb,
                            const struct port_info *pi,
                            unsigned int pidx, unsigned int gen,
                            struct sge_txq *q, unsigned int ndesc,
-                           unsigned int compl, const dma_addr_t *addr)
+                           unsigned int compl)
 {
        unsigned int flits, sgl_flits, cntrl, tso_info;
        struct sg_ent *sgp, sgl[MAX_SKB_FRAGS / 2 + 1];
@@ -1236,7 +1196,7 @@ static void write_tx_pkt_wr(struct adapter *adap, struct sk_buff *skb,
        }
 
        sgp = ndesc == 1 ? (struct sg_ent *)&d->flit[flits] : sgl;
-       sgl_flits = write_sgl(skb, sgp, skb->data, skb_headlen(skb), addr);
+       sgl_flits = make_sgl(skb, sgp, skb->data, skb_headlen(skb), adap->pdev);
 
        write_wr_hdr_sgl(ndesc, skb, d, pidx, q, sgl, flits, sgl_flits, gen,
                         htonl(V_WR_OP(FW_WROPCODE_TUNNEL_TX_PKT) | compl),
@@ -1267,7 +1227,6 @@ netdev_tx_t t3_eth_xmit(struct sk_buff *skb, struct net_device *dev)
        struct netdev_queue *txq;
        struct sge_qset *qs;
        struct sge_txq *q;
-       dma_addr_t addr[MAX_SKB_FRAGS + 1];
 
        /*
         * The chip min packet length is 9 octets but play safe and reject
@@ -1296,11 +1255,6 @@ netdev_tx_t t3_eth_xmit(struct sk_buff *skb, struct net_device *dev)
                return NETDEV_TX_BUSY;
        }
 
-       if (unlikely(map_skb(adap->pdev, skb, addr) < 0)) {
-               dev_kfree_skb(skb);
-               return NETDEV_TX_OK;
-       }
-
        q->in_use += ndesc;
        if (unlikely(credits - ndesc < q->stop_thres)) {
                t3_stop_tx_queue(txq, qs, q);
@@ -1358,7 +1312,7 @@ netdev_tx_t t3_eth_xmit(struct sk_buff *skb, struct net_device *dev)
        if (likely(!skb_shared(skb)))
                skb_orphan(skb);
 
-       write_tx_pkt_wr(adap, skb, pi, pidx, gen, q, ndesc, compl, addr);
+       write_tx_pkt_wr(adap, skb, pi, pidx, gen, q, ndesc, compl);
        check_ring_tx_db(adap, q);
        return NETDEV_TX_OK;
 }
@@ -1623,8 +1577,7 @@ static void setup_deferred_unmapping(struct sk_buff *skb, struct pci_dev *pdev,
  */
 static void write_ofld_wr(struct adapter *adap, struct sk_buff *skb,
                          struct sge_txq *q, unsigned int pidx,
-                         unsigned int gen, unsigned int ndesc,
-                         const dma_addr_t *addr)
+                         unsigned int gen, unsigned int ndesc)
 {
        unsigned int sgl_flits, flits;
        struct work_request_hdr *from;
@@ -1645,9 +1598,9 @@ static void write_ofld_wr(struct adapter *adap, struct sk_buff *skb,
 
        flits = skb_transport_offset(skb) / 8;
        sgp = ndesc == 1 ? (struct sg_ent *)&d->flit[flits] : sgl;
-       sgl_flits = write_sgl(skb, sgp, skb_transport_header(skb),
-                            skb_tail_pointer(skb) -
-                            skb_transport_header(skb), addr);
+       sgl_flits = make_sgl(skb, sgp, skb_transport_header(skb),
+                            skb->tail - skb->transport_header,
+                            adap->pdev);
        if (need_skb_unmap()) {
                setup_deferred_unmapping(skb, adap->pdev, sgp, sgl_flits);
                skb->destructor = deferred_unmap_destructor;
@@ -1705,11 +1658,6 @@ again:   reclaim_completed_tx(adap, q, TX_RECLAIM_CHUNK);
                goto again;
        }
 
-       if (map_skb(adap->pdev, skb, (dma_addr_t *)skb->head)) {
-               spin_unlock(&q->lock);
-               return NET_XMIT_SUCCESS;
-       }
-
        gen = q->gen;
        q->in_use += ndesc;
        pidx = q->pidx;
@@ -1720,7 +1668,7 @@ again:    reclaim_completed_tx(adap, q, TX_RECLAIM_CHUNK);
        }
        spin_unlock(&q->lock);
 
-       write_ofld_wr(adap, skb, q, pidx, gen, ndesc, (dma_addr_t *)skb->head);
+       write_ofld_wr(adap, skb, q, pidx, gen, ndesc);
        check_ring_tx_db(adap, q);
        return NET_XMIT_SUCCESS;
 }
@@ -1738,7 +1686,6 @@ static void restart_offloadq(unsigned long data)
        struct sge_txq *q = &qs->txq[TXQ_OFLD];
        const struct port_info *pi = netdev_priv(qs->netdev);
        struct adapter *adap = pi->adapter;
-       unsigned int written = 0;
 
        spin_lock(&q->lock);
 again: reclaim_completed_tx(adap, q, TX_RECLAIM_CHUNK);
@@ -1758,14 +1705,10 @@ again:  reclaim_completed_tx(adap, q, TX_RECLAIM_CHUNK);
                        break;
                }
 
-               if (map_skb(adap->pdev, skb, (dma_addr_t *)skb->head))
-                       break;
-
                gen = q->gen;
                q->in_use += ndesc;
                pidx = q->pidx;
                q->pidx += ndesc;
-               written += ndesc;
                if (q->pidx >= q->size) {
                        q->pidx -= q->size;
                        q->gen ^= 1;
@@ -1773,8 +1716,7 @@ again:    reclaim_completed_tx(adap, q, TX_RECLAIM_CHUNK);
                __skb_unlink(skb, &q->sendq);
                spin_unlock(&q->lock);
 
-               write_ofld_wr(adap, skb, q, pidx, gen, ndesc,
-                            (dma_addr_t *)skb->head);
+               write_ofld_wr(adap, skb, q, pidx, gen, ndesc);
                spin_lock(&q->lock);
        }
        spin_unlock(&q->lock);
@@ -1784,9 +1726,8 @@ again:    reclaim_completed_tx(adap, q, TX_RECLAIM_CHUNK);
        set_bit(TXQ_LAST_PKT_DB, &q->flags);
 #endif
        wmb();
-       if (likely(written))
-               t3_write_reg(adap, A_SG_KDOORBELL,
-                            F_SELEGRCNTX | V_EGRCNTX(q->cntxt_id));
+       t3_write_reg(adap, A_SG_KDOORBELL,
+                    F_SELEGRCNTX | V_EGRCNTX(q->cntxt_id));
 }
 
 /**
index 6e6e0a1..8ec5d74 100644 (file)
@@ -3048,6 +3048,9 @@ int be_cmd_get_func_config(struct be_adapter *adapter)
 
                adapter->max_event_queues = le16_to_cpu(desc->eq_count);
                adapter->if_cap_flags = le32_to_cpu(desc->cap_flags);
+
+               /* Clear flags that driver is not interested in */
+               adapter->if_cap_flags &=  BE_IF_CAP_FLAGS_WANT;
        }
 err:
        mutex_unlock(&adapter->mbox_lock);
index 5228d88..1b3b9e8 100644 (file)
@@ -563,6 +563,12 @@ enum be_if_flags {
        BE_IF_FLAGS_MULTICAST = 0x1000
 };
 
+#define BE_IF_CAP_FLAGS_WANT (BE_IF_FLAGS_RSS | BE_IF_FLAGS_PROMISCUOUS |\
+                        BE_IF_FLAGS_BROADCAST | BE_IF_FLAGS_VLAN_PROMISCUOUS |\
+                        BE_IF_FLAGS_VLAN | BE_IF_FLAGS_MCAST_PROMISCUOUS |\
+                        BE_IF_FLAGS_PASS_L3L4_ERRORS | BE_IF_FLAGS_MULTICAST |\
+                        BE_IF_FLAGS_UNTAGGED)
+
 /* An RX interface is an object with one or more MAC addresses and
  * filtering capabilities. */
 struct be_cmd_req_if_create {
index 181edb5..4559c35 100644 (file)
@@ -2563,8 +2563,8 @@ static int be_close(struct net_device *netdev)
        /* Wait for all pending tx completions to arrive so that
         * all tx skbs are freed.
         */
-       be_tx_compl_clean(adapter);
        netif_tx_disable(netdev);
+       be_tx_compl_clean(adapter);
 
        be_rx_qs_destroy(adapter);
 
index c896079..ef94a59 100644 (file)
@@ -931,17 +931,20 @@ static int skge_ring_alloc(struct skge_ring *ring, void *vaddr, u32 base)
 }
 
 /* Allocate and setup a new buffer for receiving */
-static void skge_rx_setup(struct skge_port *skge, struct skge_element *e,
-                         struct sk_buff *skb, unsigned int bufsize)
+static int skge_rx_setup(struct skge_port *skge, struct skge_element *e,
+                        struct sk_buff *skb, unsigned int bufsize)
 {
        struct skge_rx_desc *rd = e->desc;
-       u64 map;
+       dma_addr_t map;
 
        map = pci_map_single(skge->hw->pdev, skb->data, bufsize,
                             PCI_DMA_FROMDEVICE);
 
-       rd->dma_lo = map;
-       rd->dma_hi = map >> 32;
+       if (pci_dma_mapping_error(skge->hw->pdev, map))
+               return -1;
+
+       rd->dma_lo = lower_32_bits(map);
+       rd->dma_hi = upper_32_bits(map);
        e->skb = skb;
        rd->csum1_start = ETH_HLEN;
        rd->csum2_start = ETH_HLEN;
@@ -953,6 +956,7 @@ static void skge_rx_setup(struct skge_port *skge, struct skge_element *e,
        rd->control = BMU_OWN | BMU_STF | BMU_IRQ_EOF | BMU_TCP_CHECK | bufsize;
        dma_unmap_addr_set(e, mapaddr, map);
        dma_unmap_len_set(e, maplen, bufsize);
+       return 0;
 }
 
 /* Resume receiving using existing skb,
@@ -1014,7 +1018,10 @@ static int skge_rx_fill(struct net_device *dev)
                        return -ENOMEM;
 
                skb_reserve(skb, NET_IP_ALIGN);
-               skge_rx_setup(skge, e, skb, skge->rx_buf_size);
+               if (skge_rx_setup(skge, e, skb, skge->rx_buf_size) < 0) {
+                       dev_kfree_skb(skb);
+                       return -EIO;
+               }
        } while ((e = e->next) != ring->start);
 
        ring->to_clean = ring->start;
@@ -2544,7 +2551,7 @@ static int skge_up(struct net_device *dev)
 
        BUG_ON(skge->dma & 7);
 
-       if ((u64)skge->dma >> 32 != ((u64) skge->dma + skge->mem_size) >> 32) {
+       if (upper_32_bits(skge->dma) != upper_32_bits(skge->dma + skge->mem_size)) {
                dev_err(&hw->pdev->dev, "pci_alloc_consistent region crosses 4G boundary\n");
                err = -EINVAL;
                goto free_pci_mem;
@@ -2729,7 +2736,7 @@ static netdev_tx_t skge_xmit_frame(struct sk_buff *skb,
        struct skge_tx_desc *td;
        int i;
        u32 control, len;
-       u64 map;
+       dma_addr_t map;
 
        if (skb_padto(skb, ETH_ZLEN))
                return NETDEV_TX_OK;
@@ -2743,11 +2750,14 @@ static netdev_tx_t skge_xmit_frame(struct sk_buff *skb,
        e->skb = skb;
        len = skb_headlen(skb);
        map = pci_map_single(hw->pdev, skb->data, len, PCI_DMA_TODEVICE);
+       if (pci_dma_mapping_error(hw->pdev, map))
+               goto mapping_error;
+
        dma_unmap_addr_set(e, mapaddr, map);
        dma_unmap_len_set(e, maplen, len);
 
-       td->dma_lo = map;
-       td->dma_hi = map >> 32;
+       td->dma_lo = lower_32_bits(map);
+       td->dma_hi = upper_32_bits(map);
 
        if (skb->ip_summed == CHECKSUM_PARTIAL) {
                const int offset = skb_checksum_start_offset(skb);
@@ -2778,14 +2788,16 @@ static netdev_tx_t skge_xmit_frame(struct sk_buff *skb,
 
                        map = skb_frag_dma_map(&hw->pdev->dev, frag, 0,
                                               skb_frag_size(frag), DMA_TO_DEVICE);
+                       if (dma_mapping_error(&hw->pdev->dev, map))
+                               goto mapping_unwind;
 
                        e = e->next;
                        e->skb = skb;
                        tf = e->desc;
                        BUG_ON(tf->control & BMU_OWN);
 
-                       tf->dma_lo = map;
-                       tf->dma_hi = (u64) map >> 32;
+                       tf->dma_lo = lower_32_bits(map);
+                       tf->dma_hi = upper_32_bits(map);
                        dma_unmap_addr_set(e, mapaddr, map);
                        dma_unmap_len_set(e, maplen, skb_frag_size(frag));
 
@@ -2815,6 +2827,26 @@ static netdev_tx_t skge_xmit_frame(struct sk_buff *skb,
        }
 
        return NETDEV_TX_OK;
+
+mapping_unwind:
+       e = skge->tx_ring.to_use;
+       pci_unmap_single(hw->pdev,
+                        dma_unmap_addr(e, mapaddr),
+                        dma_unmap_len(e, maplen),
+                        PCI_DMA_TODEVICE);
+       while (i-- > 0) {
+               e = e->next;
+               pci_unmap_page(hw->pdev,
+                              dma_unmap_addr(e, mapaddr),
+                              dma_unmap_len(e, maplen),
+                              PCI_DMA_TODEVICE);
+       }
+
+mapping_error:
+       if (net_ratelimit())
+               dev_warn(&hw->pdev->dev, "%s: tx mapping error\n", dev->name);
+       dev_kfree_skb(skb);
+       return NETDEV_TX_OK;
 }
 
 
@@ -3045,11 +3077,13 @@ static struct sk_buff *skge_rx_get(struct net_device *dev,
 
                pci_dma_sync_single_for_cpu(skge->hw->pdev,
                                            dma_unmap_addr(e, mapaddr),
-                                           len, PCI_DMA_FROMDEVICE);
+                                           dma_unmap_len(e, maplen),
+                                           PCI_DMA_FROMDEVICE);
                skb_copy_from_linear_data(e->skb, skb->data, len);
                pci_dma_sync_single_for_device(skge->hw->pdev,
                                               dma_unmap_addr(e, mapaddr),
-                                              len, PCI_DMA_FROMDEVICE);
+                                              dma_unmap_len(e, maplen),
+                                              PCI_DMA_FROMDEVICE);
                skge_rx_reuse(e, skge->rx_buf_size);
        } else {
                struct sk_buff *nskb;
@@ -3058,13 +3092,17 @@ static struct sk_buff *skge_rx_get(struct net_device *dev,
                if (!nskb)
                        goto resubmit;
 
+               if (skge_rx_setup(skge, e, nskb, skge->rx_buf_size) < 0) {
+                       dev_kfree_skb(nskb);
+                       goto resubmit;
+               }
+
                pci_unmap_single(skge->hw->pdev,
                                 dma_unmap_addr(e, mapaddr),
                                 dma_unmap_len(e, maplen),
                                 PCI_DMA_FROMDEVICE);
                skb = e->skb;
                prefetch(skb->data);
-               skge_rx_setup(skge, e, nskb, skge->rx_buf_size);
        }
 
        skb_put(skb, len);
index c571de8..5472cbd 100644 (file)
@@ -46,7 +46,7 @@
 #include "mlx5_core.h"
 
 enum {
-       CMD_IF_REV = 4,
+       CMD_IF_REV = 5,
 };
 
 enum {
index c02cbcf..443cc4d 100644 (file)
@@ -268,7 +268,7 @@ static int mlx5_eq_int(struct mlx5_core_dev *dev, struct mlx5_eq *eq)
                case MLX5_EVENT_TYPE_PAGE_REQUEST:
                        {
                                u16 func_id = be16_to_cpu(eqe->data.req_pages.func_id);
-                               s16 npages = be16_to_cpu(eqe->data.req_pages.num_pages);
+                               s32 npages = be32_to_cpu(eqe->data.req_pages.num_pages);
 
                                mlx5_core_dbg(dev, "page request for func 0x%x, napges %d\n", func_id, npages);
                                mlx5_core_req_pages_handler(dev, func_id, npages);
index 72a5222..f012658 100644 (file)
@@ -113,7 +113,7 @@ int mlx5_cmd_query_hca_cap(struct mlx5_core_dev *dev,
        caps->log_max_srq = out->hca_cap.log_max_srqs & 0x1f;
        caps->local_ca_ack_delay = out->hca_cap.local_ca_ack_delay & 0x1f;
        caps->log_max_mcg = out->hca_cap.log_max_mcg;
-       caps->max_qp_mcg = be16_to_cpu(out->hca_cap.max_qp_mcg);
+       caps->max_qp_mcg = be32_to_cpu(out->hca_cap.max_qp_mcg) & 0xffffff;
        caps->max_ra_res_qp = 1 << (out->hca_cap.log_max_ra_res_qp & 0x3f);
        caps->max_ra_req_qp = 1 << (out->hca_cap.log_max_ra_req_qp & 0x3f);
        caps->max_srq_wqes = 1 << out->hca_cap.log_max_srq_sz;
index 748f10a..3e6670c 100644 (file)
@@ -55,33 +55,9 @@ enum {
 };
 
 static DEFINE_SPINLOCK(health_lock);
-
 static LIST_HEAD(health_list);
 static struct work_struct health_work;
 
-static health_handler_t reg_handler;
-int mlx5_register_health_report_handler(health_handler_t handler)
-{
-       spin_lock_irq(&health_lock);
-       if (reg_handler) {
-               spin_unlock_irq(&health_lock);
-               return -EEXIST;
-       }
-       reg_handler = handler;
-       spin_unlock_irq(&health_lock);
-
-       return 0;
-}
-EXPORT_SYMBOL(mlx5_register_health_report_handler);
-
-void mlx5_unregister_health_report_handler(void)
-{
-       spin_lock_irq(&health_lock);
-       reg_handler = NULL;
-       spin_unlock_irq(&health_lock);
-}
-EXPORT_SYMBOL(mlx5_unregister_health_report_handler);
-
 static void health_care(struct work_struct *work)
 {
        struct mlx5_core_health *health, *n;
@@ -98,11 +74,8 @@ static void health_care(struct work_struct *work)
                priv = container_of(health, struct mlx5_priv, health);
                dev = container_of(priv, struct mlx5_core_dev, priv);
                mlx5_core_warn(dev, "handling bad device here\n");
+               /* nothing yet */
                spin_lock_irq(&health_lock);
-               if (reg_handler)
-                       reg_handler(dev->pdev, health->health,
-                                   sizeof(health->health));
-
                list_del_init(&health->list);
                spin_unlock_irq(&health_lock);
        }
index 4a3e137..3a2408d 100644 (file)
@@ -43,10 +43,16 @@ enum {
        MLX5_PAGES_TAKE         = 2
 };
 
+enum {
+       MLX5_BOOT_PAGES         = 1,
+       MLX5_INIT_PAGES         = 2,
+       MLX5_POST_INIT_PAGES    = 3
+};
+
 struct mlx5_pages_req {
        struct mlx5_core_dev *dev;
        u32     func_id;
-       s16     npages;
+       s32     npages;
        struct work_struct work;
 };
 
@@ -64,27 +70,23 @@ struct mlx5_query_pages_inbox {
 
 struct mlx5_query_pages_outbox {
        struct mlx5_outbox_hdr  hdr;
-       __be16                  num_boot_pages;
+       __be16                  rsvd;
        __be16                  func_id;
-       __be16                  init_pages;
-       __be16                  num_pages;
+       __be32                  num_pages;
 };
 
 struct mlx5_manage_pages_inbox {
        struct mlx5_inbox_hdr   hdr;
-       __be16                  rsvd0;
+       __be16                  rsvd;
        __be16                  func_id;
-       __be16                  rsvd1;
-       __be16                  num_entries;
-       u8                      rsvd2[16];
+       __be32                  num_entries;
        __be64                  pas[0];
 };
 
 struct mlx5_manage_pages_outbox {
        struct mlx5_outbox_hdr  hdr;
-       u8                      rsvd0[2];
-       __be16                  num_entries;
-       u8                      rsvd1[20];
+       __be32                  num_entries;
+       u8                      rsvd[4];
        __be64                  pas[0];
 };
 
@@ -146,7 +148,7 @@ static struct page *remove_page(struct mlx5_core_dev *dev, u64 addr)
 }
 
 static int mlx5_cmd_query_pages(struct mlx5_core_dev *dev, u16 *func_id,
-                               s16 *pages, s16 *init_pages, u16 *boot_pages)
+                               s32 *npages, int boot)
 {
        struct mlx5_query_pages_inbox   in;
        struct mlx5_query_pages_outbox  out;
@@ -155,6 +157,8 @@ static int mlx5_cmd_query_pages(struct mlx5_core_dev *dev, u16 *func_id,
        memset(&in, 0, sizeof(in));
        memset(&out, 0, sizeof(out));
        in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_QUERY_PAGES);
+       in.hdr.opmod = boot ? cpu_to_be16(MLX5_BOOT_PAGES) : cpu_to_be16(MLX5_INIT_PAGES);
+
        err = mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out));
        if (err)
                return err;
@@ -162,15 +166,7 @@ static int mlx5_cmd_query_pages(struct mlx5_core_dev *dev, u16 *func_id,
        if (out.hdr.status)
                return mlx5_cmd_status_to_err(&out.hdr);
 
-       if (pages)
-               *pages = be16_to_cpu(out.num_pages);
-
-       if (init_pages)
-               *init_pages = be16_to_cpu(out.init_pages);
-
-       if (boot_pages)
-               *boot_pages = be16_to_cpu(out.num_boot_pages);
-
+       *npages = be32_to_cpu(out.num_pages);
        *func_id = be16_to_cpu(out.func_id);
 
        return err;
@@ -224,7 +220,7 @@ static int give_pages(struct mlx5_core_dev *dev, u16 func_id, int npages,
        in->hdr.opcode = cpu_to_be16(MLX5_CMD_OP_MANAGE_PAGES);
        in->hdr.opmod = cpu_to_be16(MLX5_PAGES_GIVE);
        in->func_id = cpu_to_be16(func_id);
-       in->num_entries = cpu_to_be16(npages);
+       in->num_entries = cpu_to_be32(npages);
        err = mlx5_cmd_exec(dev, in, inlen, &out, sizeof(out));
        mlx5_core_dbg(dev, "err %d\n", err);
        if (err) {
@@ -292,7 +288,7 @@ static int reclaim_pages(struct mlx5_core_dev *dev, u32 func_id, int npages,
        in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_MANAGE_PAGES);
        in.hdr.opmod = cpu_to_be16(MLX5_PAGES_TAKE);
        in.func_id = cpu_to_be16(func_id);
-       in.num_entries = cpu_to_be16(npages);
+       in.num_entries = cpu_to_be32(npages);
        mlx5_core_dbg(dev, "npages %d, outlen %d\n", npages, outlen);
        err = mlx5_cmd_exec(dev, &in, sizeof(in), out, outlen);
        if (err) {
@@ -306,7 +302,7 @@ static int reclaim_pages(struct mlx5_core_dev *dev, u32 func_id, int npages,
                goto out_free;
        }
 
-       num_claimed = be16_to_cpu(out->num_entries);
+       num_claimed = be32_to_cpu(out->num_entries);
        if (nclaimed)
                *nclaimed = num_claimed;
 
@@ -345,7 +341,7 @@ static void pages_work_handler(struct work_struct *work)
 }
 
 void mlx5_core_req_pages_handler(struct mlx5_core_dev *dev, u16 func_id,
-                                s16 npages)
+                                s32 npages)
 {
        struct mlx5_pages_req *req;
 
@@ -364,20 +360,18 @@ void mlx5_core_req_pages_handler(struct mlx5_core_dev *dev, u16 func_id,
 
 int mlx5_satisfy_startup_pages(struct mlx5_core_dev *dev, int boot)
 {
-       u16 uninitialized_var(boot_pages);
-       s16 uninitialized_var(init_pages);
        u16 uninitialized_var(func_id);
+       s32 uninitialized_var(npages);
        int err;
 
-       err = mlx5_cmd_query_pages(dev, &func_id, NULL, &init_pages,
-                                  &boot_pages);
+       err = mlx5_cmd_query_pages(dev, &func_id, &npages, boot);
        if (err)
                return err;
 
+       mlx5_core_dbg(dev, "requested %d %s pages for func_id 0x%x\n",
+                     npages, boot ? "boot" : "init", func_id);
 
-       mlx5_core_dbg(dev, "requested %d init pages and %d boot pages for func_id 0x%x\n",
-                     init_pages, boot_pages, func_id);
-       return give_pages(dev, func_id, boot ? boot_pages : init_pages, 0);
+       return give_pages(dev, func_id, npages, 0);
 }
 
 static int optimal_reclaimed_pages(void)
index 92da998..9d4bb7f 100644 (file)
@@ -3266,6 +3266,11 @@ int qlcnic_83xx_interrupt_test(struct net_device *netdev)
        u8 val;
        int ret, max_sds_rings = adapter->max_sds_rings;
 
+       if (test_bit(__QLCNIC_RESETTING, &adapter->state)) {
+               netdev_info(netdev, "Device is resetting\n");
+               return -EBUSY;
+       }
+
        if (qlcnic_get_diag_lock(adapter)) {
                netdev_info(netdev, "Device in diagnostics mode\n");
                return -EBUSY;
index 9f4b8d5..345d987 100644 (file)
@@ -629,7 +629,8 @@ int qlcnic_83xx_idc_reattach_driver(struct qlcnic_adapter *adapter)
                return -EIO;
        }
 
-       qlcnic_set_drv_version(adapter);
+       if (adapter->portnum == 0)
+               qlcnic_set_drv_version(adapter);
        qlcnic_83xx_idc_attach_driver(adapter);
 
        return 0;
index ee013fc..bc05d01 100644 (file)
@@ -2165,7 +2165,8 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (err)
                goto err_out_disable_mbx_intr;
 
-       qlcnic_set_drv_version(adapter);
+       if (adapter->portnum == 0)
+               qlcnic_set_drv_version(adapter);
 
        pci_set_drvdata(pdev, adapter);
 
@@ -3085,7 +3086,8 @@ done:
        adapter->fw_fail_cnt = 0;
        adapter->flags &= ~QLCNIC_FW_HANG;
        clear_bit(__QLCNIC_RESETTING, &adapter->state);
-       qlcnic_set_drv_version(adapter);
+       if (adapter->portnum == 0)
+               qlcnic_set_drv_version(adapter);
 
        if (!qlcnic_clr_drv_state(adapter))
                qlcnic_schedule_work(adapter, qlcnic_fw_poll_work,
index 10ed82b..660c3f5 100644 (file)
@@ -170,9 +170,9 @@ static int qlcnic_82xx_store_beacon(struct qlcnic_adapter *adapter,
 
        if (ahw->extra_capability[0] & QLCNIC_FW_CAPABILITY_2_BEACON) {
                err = qlcnic_get_beacon_state(adapter, &h_beacon_state);
-               if (!err) {
-                       dev_info(&adapter->pdev->dev,
-                                "Failed to get current beacon state\n");
+               if (err) {
+                       netdev_err(adapter->netdev,
+                                  "Failed to get current beacon state\n");
                } else {
                        if (h_beacon_state == QLCNIC_BEACON_DISABLE)
                                ahw->beacon_state = 0;
index 6f35f84..d2e5919 100644 (file)
@@ -524,6 +524,7 @@ rx_status_loop:
                                         PCI_DMA_FROMDEVICE);
                if (dma_mapping_error(&cp->pdev->dev, new_mapping)) {
                        dev->stats.rx_dropped++;
+                       kfree_skb(new_skb);
                        goto rx_next;
                }
 
index b5eb419..85e5c97 100644 (file)
@@ -7088,7 +7088,7 @@ rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        RTL_W8(Cfg9346, Cfg9346_Unlock);
        RTL_W8(Config1, RTL_R8(Config1) | PMEnable);
-       RTL_W8(Config5, RTL_R8(Config5) & PMEStatus);
+       RTL_W8(Config5, RTL_R8(Config5) & (BWF | MWF | UWF | LanWake | PMEStatus));
        if ((RTL_R8(Config3) & (LinkUp | MagicPacket)) != 0)
                tp->features |= RTL_FEATURE_WOL;
        if ((RTL_R8(Config5) & (UWF | BWF | MWF)) != 0)
index 2a469b2..30d7442 100644 (file)
@@ -675,7 +675,7 @@ s32 efx_filter_insert_filter(struct efx_nic *efx, struct efx_filter_spec *spec,
                BUILD_BUG_ON(EFX_FILTER_INDEX_UC_DEF != 0);
                BUILD_BUG_ON(EFX_FILTER_INDEX_MC_DEF !=
                             EFX_FILTER_MC_DEF - EFX_FILTER_UC_DEF);
-               rep_index = spec->type - EFX_FILTER_INDEX_UC_DEF;
+               rep_index = spec->type - EFX_FILTER_UC_DEF;
                ins_index = rep_index;
 
                spin_lock_bh(&state->lock);
index c9d942a..1ef9d8a 100644 (file)
@@ -33,10 +33,15 @@ static unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
        struct stmmac_priv *priv = (struct stmmac_priv *)p;
        unsigned int txsize = priv->dma_tx_size;
        unsigned int entry = priv->cur_tx % txsize;
-       struct dma_desc *desc = priv->dma_tx + entry;
+       struct dma_desc *desc;
        unsigned int nopaged_len = skb_headlen(skb);
        unsigned int bmax, len;
 
+       if (priv->extend_desc)
+               desc = (struct dma_desc *)(priv->dma_etx + entry);
+       else
+               desc = priv->dma_tx + entry;
+
        if (priv->plat->enh_desc)
                bmax = BUF_SIZE_8KiB;
        else
@@ -54,7 +59,11 @@ static unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
                                                STMMAC_RING_MODE);
                wmb();
                entry = (++priv->cur_tx) % txsize;
-               desc = priv->dma_tx + entry;
+
+               if (priv->extend_desc)
+                       desc = (struct dma_desc *)(priv->dma_etx + entry);
+               else
+                       desc = priv->dma_tx + entry;
 
                desc->des2 = dma_map_single(priv->device, skb->data + bmax,
                                            len, DMA_TO_DEVICE);
index f2ccb36..0a9bb9d 100644 (file)
@@ -939,15 +939,20 @@ static int stmmac_init_rx_buffers(struct stmmac_priv *priv, struct dma_desc *p,
 
        skb = __netdev_alloc_skb(priv->dev, priv->dma_buf_sz + NET_IP_ALIGN,
                                 GFP_KERNEL);
-       if (unlikely(skb == NULL)) {
+       if (!skb) {
                pr_err("%s: Rx init fails; skb is NULL\n", __func__);
-               return 1;
+               return -ENOMEM;
        }
        skb_reserve(skb, NET_IP_ALIGN);
        priv->rx_skbuff[i] = skb;
        priv->rx_skbuff_dma[i] = dma_map_single(priv->device, skb->data,
                                                priv->dma_buf_sz,
                                                DMA_FROM_DEVICE);
+       if (dma_mapping_error(priv->device, priv->rx_skbuff_dma[i])) {
+               pr_err("%s: DMA mapping error\n", __func__);
+               dev_kfree_skb_any(skb);
+               return -EINVAL;
+       }
 
        p->des2 = priv->rx_skbuff_dma[i];
 
@@ -958,6 +963,16 @@ static int stmmac_init_rx_buffers(struct stmmac_priv *priv, struct dma_desc *p,
        return 0;
 }
 
+static void stmmac_free_rx_buffers(struct stmmac_priv *priv, int i)
+{
+       if (priv->rx_skbuff[i]) {
+               dma_unmap_single(priv->device, priv->rx_skbuff_dma[i],
+                                priv->dma_buf_sz, DMA_FROM_DEVICE);
+               dev_kfree_skb_any(priv->rx_skbuff[i]);
+       }
+       priv->rx_skbuff[i] = NULL;
+}
+
 /**
  * init_dma_desc_rings - init the RX/TX descriptor rings
  * @dev: net device structure
@@ -965,13 +980,14 @@ static int stmmac_init_rx_buffers(struct stmmac_priv *priv, struct dma_desc *p,
  * and allocates the socket buffers. It suppors the chained and ring
  * modes.
  */
-static void init_dma_desc_rings(struct net_device *dev)
+static int init_dma_desc_rings(struct net_device *dev)
 {
        int i;
        struct stmmac_priv *priv = netdev_priv(dev);
        unsigned int txsize = priv->dma_tx_size;
        unsigned int rxsize = priv->dma_rx_size;
        unsigned int bfsize = 0;
+       int ret = -ENOMEM;
 
        /* Set the max buffer size according to the DESC mode
         * and the MTU. Note that RING mode allows 16KiB bsize.
@@ -992,34 +1008,60 @@ static void init_dma_desc_rings(struct net_device *dev)
                                                          dma_extended_desc),
                                                   &priv->dma_rx_phy,
                                                   GFP_KERNEL);
+               if (!priv->dma_erx)
+                       goto err_dma;
+
                priv->dma_etx = dma_alloc_coherent(priv->device, txsize *
                                                   sizeof(struct
                                                          dma_extended_desc),
                                                   &priv->dma_tx_phy,
                                                   GFP_KERNEL);
-               if ((!priv->dma_erx) || (!priv->dma_etx))
-                       return;
+               if (!priv->dma_etx) {
+                       dma_free_coherent(priv->device, priv->dma_rx_size *
+                                       sizeof(struct dma_extended_desc),
+                                       priv->dma_erx, priv->dma_rx_phy);
+                       goto err_dma;
+               }
        } else {
                priv->dma_rx = dma_alloc_coherent(priv->device, rxsize *
                                                  sizeof(struct dma_desc),
                                                  &priv->dma_rx_phy,
                                                  GFP_KERNEL);
+               if (!priv->dma_rx)
+                       goto err_dma;
+
                priv->dma_tx = dma_alloc_coherent(priv->device, txsize *
                                                  sizeof(struct dma_desc),
                                                  &priv->dma_tx_phy,
                                                  GFP_KERNEL);
-               if ((!priv->dma_rx) || (!priv->dma_tx))
-                       return;
+               if (!priv->dma_tx) {
+                       dma_free_coherent(priv->device, priv->dma_rx_size *
+                                       sizeof(struct dma_desc),
+                                       priv->dma_rx, priv->dma_rx_phy);
+                       goto err_dma;
+               }
        }
 
        priv->rx_skbuff_dma = kmalloc_array(rxsize, sizeof(dma_addr_t),
                                            GFP_KERNEL);
+       if (!priv->rx_skbuff_dma)
+               goto err_rx_skbuff_dma;
+
        priv->rx_skbuff = kmalloc_array(rxsize, sizeof(struct sk_buff *),
                                        GFP_KERNEL);
+       if (!priv->rx_skbuff)
+               goto err_rx_skbuff;
+
        priv->tx_skbuff_dma = kmalloc_array(txsize, sizeof(dma_addr_t),
                                            GFP_KERNEL);
+       if (!priv->tx_skbuff_dma)
+               goto err_tx_skbuff_dma;
+
        priv->tx_skbuff = kmalloc_array(txsize, sizeof(struct sk_buff *),
                                        GFP_KERNEL);
+       if (!priv->tx_skbuff)
+               goto err_tx_skbuff;
+
        if (netif_msg_probe(priv)) {
                pr_debug("(%s) dma_rx_phy=0x%08x dma_tx_phy=0x%08x\n", __func__,
                         (u32) priv->dma_rx_phy, (u32) priv->dma_tx_phy);
@@ -1034,8 +1076,9 @@ static void init_dma_desc_rings(struct net_device *dev)
                else
                        p = priv->dma_rx + i;
 
-               if (stmmac_init_rx_buffers(priv, p, i))
-                       break;
+               ret = stmmac_init_rx_buffers(priv, p, i);
+               if (ret)
+                       goto err_init_rx_buffers;
 
                if (netif_msg_probe(priv))
                        pr_debug("[%p]\t[%p]\t[%x]\n", priv->rx_skbuff[i],
@@ -1081,20 +1124,44 @@ static void init_dma_desc_rings(struct net_device *dev)
 
        if (netif_msg_hw(priv))
                stmmac_display_rings(priv);
+
+       return 0;
+err_init_rx_buffers:
+       while (--i >= 0)
+               stmmac_free_rx_buffers(priv, i);
+       kfree(priv->tx_skbuff);
+err_tx_skbuff:
+       kfree(priv->tx_skbuff_dma);
+err_tx_skbuff_dma:
+       kfree(priv->rx_skbuff);
+err_rx_skbuff:
+       kfree(priv->rx_skbuff_dma);
+err_rx_skbuff_dma:
+       if (priv->extend_desc) {
+               dma_free_coherent(priv->device, priv->dma_tx_size *
+                                 sizeof(struct dma_extended_desc),
+                                 priv->dma_etx, priv->dma_tx_phy);
+               dma_free_coherent(priv->device, priv->dma_rx_size *
+                                 sizeof(struct dma_extended_desc),
+                                 priv->dma_erx, priv->dma_rx_phy);
+       } else {
+               dma_free_coherent(priv->device,
+                               priv->dma_tx_size * sizeof(struct dma_desc),
+                               priv->dma_tx, priv->dma_tx_phy);
+               dma_free_coherent(priv->device,
+                               priv->dma_rx_size * sizeof(struct dma_desc),
+                               priv->dma_rx, priv->dma_rx_phy);
+       }
+err_dma:
+       return ret;
 }
 
 static void dma_free_rx_skbufs(struct stmmac_priv *priv)
 {
        int i;
 
-       for (i = 0; i < priv->dma_rx_size; i++) {
-               if (priv->rx_skbuff[i]) {
-                       dma_unmap_single(priv->device, priv->rx_skbuff_dma[i],
-                                        priv->dma_buf_sz, DMA_FROM_DEVICE);
-                       dev_kfree_skb_any(priv->rx_skbuff[i]);
-               }
-               priv->rx_skbuff[i] = NULL;
-       }
+       for (i = 0; i < priv->dma_rx_size; i++)
+               stmmac_free_rx_buffers(priv, i);
 }
 
 static void dma_free_tx_skbufs(struct stmmac_priv *priv)
@@ -1560,12 +1627,17 @@ static int stmmac_open(struct net_device *dev)
        priv->dma_tx_size = STMMAC_ALIGN(dma_txsize);
        priv->dma_rx_size = STMMAC_ALIGN(dma_rxsize);
        priv->dma_buf_sz = STMMAC_ALIGN(buf_sz);
-       init_dma_desc_rings(dev);
+
+       ret = init_dma_desc_rings(dev);
+       if (ret < 0) {
+               pr_err("%s: DMA descriptors initialization failed\n", __func__);
+               goto dma_desc_error;
+       }
 
        /* DMA initialization and SW reset */
        ret = stmmac_init_dma_engine(priv);
        if (ret < 0) {
-               pr_err("%s: DMA initialization failed\n", __func__);
+               pr_err("%s: DMA engine initialization failed\n", __func__);
                goto init_error;
        }
 
@@ -1672,6 +1744,7 @@ wolirq_error:
 
 init_error:
        free_dma_desc_resources(priv);
+dma_desc_error:
        if (priv->phydev)
                phy_disconnect(priv->phydev);
 phy_error:
index 1d6dc41..d01cacf 100644 (file)
@@ -2100,7 +2100,7 @@ static int velocity_receive_frame(struct velocity_info *vptr, int idx)
 
                __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vid);
        }
-       netif_rx(skb);
+       netif_receive_skb(skb);
 
        stats->rx_bytes += pkt_len;
        stats->rx_packets++;
@@ -2884,6 +2884,7 @@ out:
        return ret;
 
 err_iounmap:
+       netif_napi_del(&vptr->napi);
        iounmap(regs);
 err_free_dev:
        free_netdev(netdev);
@@ -2904,6 +2905,7 @@ static int velocity_remove(struct device *dev)
        struct velocity_info *vptr = netdev_priv(netdev);
 
        unregister_netdev(netdev);
+       netif_napi_del(&vptr->napi);
        iounmap(vptr->mac_regs);
        free_netdev(netdev);
        velocity_nics--;
index 51f2bc3..2dcc60f 100644 (file)
@@ -210,8 +210,7 @@ static int via_init_one(struct pci_dev *pcidev, const struct pci_device_id *id)
                        pci_write_config_byte(pcidev,0x42,(bTmp | 0xf0));
                        pci_write_config_byte(pcidev,0x5a,0xc0);
                        WriteLPCReg(0x28, 0x70 );
-                       if (via_ircc_open(pcidev, &info, 0x3076) == 0)
-                               rc=0;
+                       rc = via_ircc_open(pcidev, &info, 0x3076);
                } else
                        rc = -ENODEV; //IR not turn on   
        } else { //Not VT1211
@@ -249,8 +248,7 @@ static int via_init_one(struct pci_dev *pcidev, const struct pci_device_id *id)
                        info.irq=FirIRQ;
                        info.dma=FirDRQ1;
                        info.dma2=FirDRQ0;
-                       if (via_ircc_open(pcidev, &info, 0x3096) == 0)
-                               rc=0;
+                       rc = via_ircc_open(pcidev, &info, 0x3096);
                } else
                        rc = -ENODEV; //IR not turn on !!!!!
        }//Not VT1211
index d0f9c2f..16b43bf 100644 (file)
@@ -739,6 +739,10 @@ static int macvlan_validate(struct nlattr *tb[], struct nlattr *data[])
                        return -EADDRNOTAVAIL;
        }
 
+       if (data && data[IFLA_MACVLAN_FLAGS] &&
+           nla_get_u16(data[IFLA_MACVLAN_FLAGS]) & ~MACVLAN_FLAG_NOPROMISC)
+               return -EINVAL;
+
        if (data && data[IFLA_MACVLAN_MODE]) {
                switch (nla_get_u32(data[IFLA_MACVLAN_MODE])) {
                case MACVLAN_MODE_PRIVATE:
index a98fb0e..ea53abb 100644 (file)
@@ -68,6 +68,8 @@ static const struct proto_ops macvtap_socket_ops;
 #define TUN_OFFLOADS (NETIF_F_HW_CSUM | NETIF_F_TSO_ECN | NETIF_F_TSO | \
                      NETIF_F_TSO6 | NETIF_F_UFO)
 #define RX_OFFLOADS (NETIF_F_GRO | NETIF_F_LRO)
+#define TAP_FEATURES (NETIF_F_GSO | NETIF_F_SG)
+
 /*
  * RCU usage:
  * The macvtap_queue and the macvlan_dev are loosely coupled, the
@@ -278,7 +280,8 @@ static int macvtap_forward(struct net_device *dev, struct sk_buff *skb)
 {
        struct macvlan_dev *vlan = netdev_priv(dev);
        struct macvtap_queue *q = macvtap_get_queue(dev, skb);
-       netdev_features_t features;
+       netdev_features_t features = TAP_FEATURES;
+
        if (!q)
                goto drop;
 
@@ -287,9 +290,11 @@ static int macvtap_forward(struct net_device *dev, struct sk_buff *skb)
 
        skb->dev = dev;
        /* Apply the forward feature mask so that we perform segmentation
-        * according to users wishes.
+        * according to users wishes.  This only works if VNET_HDR is
+        * enabled.
         */
-       features = netif_skb_features(skb) & vlan->tap_features;
+       if (q->flags & IFF_VNET_HDR)
+               features |= vlan->tap_features;
        if (netif_needs_gso(skb, features)) {
                struct sk_buff *segs = __skb_gso_segment(skb, features, false);
 
@@ -818,10 +823,13 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m,
                skb_shinfo(skb)->tx_flags |= SKBTX_DEV_ZEROCOPY;
                skb_shinfo(skb)->tx_flags |= SKBTX_SHARED_FRAG;
        }
-       if (vlan)
+       if (vlan) {
+               local_bh_disable();
                macvlan_start_xmit(skb, vlan->dev);
-       else
+               local_bh_enable();
+       } else {
                kfree_skb(skb);
+       }
        rcu_read_unlock();
 
        return total_len;
@@ -912,8 +920,11 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q,
 done:
        rcu_read_lock();
        vlan = rcu_dereference(q->vlan);
-       if (vlan)
+       if (vlan) {
+               preempt_disable();
                macvlan_count_rx(vlan, copied - vnet_hdr_len, ret == 0, 0);
+               preempt_enable();
+       }
        rcu_read_unlock();
 
        return ret ? ret : copied;
@@ -1058,8 +1069,7 @@ static int set_offload(struct macvtap_queue *q, unsigned long arg)
        /* tap_features are the same as features on tun/tap and
         * reflect user expectations.
         */
-       vlan->tap_features = vlan->dev->features &
-                           (feature_mask | ~TUN_OFFLOADS);
+       vlan->tap_features = feature_mask;
        vlan->set_features = features;
        netdev_update_features(vlan->dev);
 
@@ -1155,10 +1165,6 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd,
                            TUN_F_TSO_ECN | TUN_F_UFO))
                        return -EINVAL;
 
-               /* TODO: only accept frames with the features that
-                        got enabled for forwarded frames */
-               if (!(q->flags & IFF_VNET_HDR))
-                       return  -EINVAL;
                rtnl_lock();
                ret = set_offload(q, arg);
                rtnl_unlock();
index 8e7af83..138de83 100644 (file)
@@ -23,7 +23,7 @@
 #define RTL821x_INER_INIT      0x6400
 #define RTL821x_INSR           0x13
 
-#define        RTL8211E_INER_LINK_STAT 0x10
+#define        RTL8211E_INER_LINK_STATUS       0x400
 
 MODULE_DESCRIPTION("Realtek PHY driver");
 MODULE_AUTHOR("Johnson Leung");
@@ -57,7 +57,7 @@ static int rtl8211e_config_intr(struct phy_device *phydev)
 
        if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
                err = phy_write(phydev, RTL821x_INER,
-                               RTL8211E_INER_LINK_STAT);
+                               RTL8211E_INER_LINK_STATUS);
        else
                err = phy_write(phydev, RTL821x_INER, 0);
 
index db690a3..71af122 100644 (file)
@@ -1074,8 +1074,9 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
        u32 rxhash;
 
        if (!(tun->flags & TUN_NO_PI)) {
-               if ((len -= sizeof(pi)) > total_len)
+               if (len < sizeof(pi))
                        return -EINVAL;
+               len -= sizeof(pi);
 
                if (memcpy_fromiovecend((void *)&pi, iv, 0, sizeof(pi)))
                        return -EFAULT;
@@ -1083,8 +1084,9 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
        }
 
        if (tun->flags & TUN_VNET_HDR) {
-               if ((len -= tun->vnet_hdr_sz) > total_len)
+               if (len < tun->vnet_hdr_sz)
                        return -EINVAL;
+               len -= tun->vnet_hdr_sz;
 
                if (memcpy_fromiovecend((void *)&gso, iv, offset, sizeof(gso)))
                        return -EFAULT;
index cba1d46..86292e6 100644 (file)
@@ -2816,13 +2816,16 @@ exit:
 static int hso_get_config_data(struct usb_interface *interface)
 {
        struct usb_device *usbdev = interface_to_usbdev(interface);
-       u8 config_data[17];
+       u8 *config_data = kmalloc(17, GFP_KERNEL);
        u32 if_num = interface->altsetting->desc.bInterfaceNumber;
        s32 result;
 
+       if (!config_data)
+               return -ENOMEM;
        if (usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0),
                            0x86, 0xC0, 0, 0, config_data, 17,
                            USB_CTRL_SET_TIMEOUT) != 0x11) {
+               kfree(config_data);
                return -EIO;
        }
 
@@ -2873,6 +2876,7 @@ static int hso_get_config_data(struct usb_interface *interface)
        if (config_data[16] & 0x1)
                result |= HSO_INFO_CRC_BUG;
 
+       kfree(config_data);
        return result;
 }
 
@@ -2886,6 +2890,11 @@ static int hso_probe(struct usb_interface *interface,
        struct hso_shared_int *shared_int;
        struct hso_device *tmp_dev = NULL;
 
+       if (interface->cur_altsetting->desc.bInterfaceClass != 0xFF) {
+               dev_err(&interface->dev, "Not our interface\n");
+               return -ENODEV;
+       }
+
        if_num = interface->altsetting->desc.bInterfaceNumber;
 
        /* Get the interface/port specification from either driver_info or from
@@ -2895,10 +2904,6 @@ static int hso_probe(struct usb_interface *interface,
        else
                port_spec = hso_get_config_data(interface);
 
-       if (interface->cur_altsetting->desc.bInterfaceClass != 0xFF) {
-               dev_err(&interface->dev, "Not our interface\n");
-               return -ENODEV;
-       }
        /* Check if we need to switch to alt interfaces prior to port
         * configuration */
        if (interface->num_altsetting > 1)
index f4c6db4..767f7af 100644 (file)
@@ -1386,7 +1386,7 @@ static int vxlan_open(struct net_device *dev)
                return -ENOTCONN;
 
        if (IN_MULTICAST(ntohl(vxlan->default_dst.remote_ip)) &&
-           vxlan_group_used(vn, vxlan->default_dst.remote_ip)) {
+           vxlan_group_used(vn, vxlan->default_dst.remote_ip)) {
                vxlan_sock_hold(vs);
                dev_hold(dev);
                queue_work(vxlan_wq, &vxlan->igmp_join);
@@ -1793,8 +1793,6 @@ static void vxlan_dellink(struct net_device *dev, struct list_head *head)
        struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id);
        struct vxlan_dev *vxlan = netdev_priv(dev);
 
-       flush_workqueue(vxlan_wq);
-
        spin_lock(&vn->sock_lock);
        hlist_del_rcu(&vxlan->hlist);
        spin_unlock(&vn->sock_lock);
index 7365674..010b252 100644 (file)
@@ -1406,11 +1406,8 @@ static void cw1200_do_unjoin(struct cw1200_common *priv)
        if (!priv->join_status)
                goto done;
 
-       if (priv->join_status > CW1200_JOIN_STATUS_IBSS) {
-               wiphy_err(priv->hw->wiphy, "Unexpected: join status: %d\n",
-                         priv->join_status);
-               BUG_ON(1);
-       }
+       if (priv->join_status == CW1200_JOIN_STATUS_AP)
+               goto done;
 
        cancel_work_sync(&priv->update_filtering_work);
        cancel_work_sync(&priv->set_beacon_wakeup_period_work);
index ac07473..e509030 100644 (file)
@@ -523,9 +523,9 @@ static int prism2_ioctl_giwaplist(struct net_device *dev,
 
        data->length = prism2_ap_get_sta_qual(local, addr, qual, IW_MAX_AP, 1);
 
-       memcpy(extra, &addr, sizeof(struct sockaddr) * data->length);
+       memcpy(extra, addr, sizeof(struct sockaddr) * data->length);
        data->flags = 1; /* has quality information */
-       memcpy(extra + sizeof(struct sockaddr) * data->length, &qual,
+       memcpy(extra + sizeof(struct sockaddr) * data->length, qual,
               sizeof(struct iw_quality) * data->length);
 
        kfree(addr);
index b9b2bb5..f2ed62e 100644 (file)
@@ -4460,12 +4460,12 @@ il4965_irq_tasklet(struct il_priv *il)
                 * is killed. Hence update the killswitch state here. The
                 * rfkill handler will care about restarting if needed.
                 */
-               if (!test_bit(S_ALIVE, &il->status)) {
-                       if (hw_rf_kill)
-                               set_bit(S_RFKILL, &il->status);
-                       else
-                               clear_bit(S_RFKILL, &il->status);
+               if (hw_rf_kill) {
+                       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);
                }
 
                handled |= CSR_INT_BIT_RF_KILL;
@@ -5334,6 +5334,9 @@ il4965_alive_start(struct il_priv *il)
 
        il->active_rate = RATES_MASK;
 
+       il_power_update_mode(il, true);
+       D_INFO("Updated power mode\n");
+
        if (il_is_associated(il)) {
                struct il_rxon_cmd *active_rxon =
                    (struct il_rxon_cmd *)&il->active;
@@ -5364,9 +5367,6 @@ il4965_alive_start(struct il_priv *il)
        D_INFO("ALIVE processing complete.\n");
        wake_up(&il->wait_command_queue);
 
-       il_power_update_mode(il, true);
-       D_INFO("Updated power mode\n");
-
        return;
 
 restart:
index 3195aad..b03e22e 100644 (file)
@@ -4660,6 +4660,7 @@ il_force_reset(struct il_priv *il, bool external)
 
        return 0;
 }
+EXPORT_SYMBOL(il_force_reset);
 
 int
 il_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
index 822f1a0..3193872 100644 (file)
@@ -1068,7 +1068,10 @@ void iwl_chswitch_done(struct iwl_priv *priv, bool is_success)
        if (test_bit(STATUS_EXIT_PENDING, &priv->status))
                return;
 
-       if (test_and_clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status))
+       if (!test_and_clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status))
+               return;
+
+       if (ctx->vif)
                ieee80211_chswitch_done(ctx->vif, is_success);
 }
 
index a70c7b9..ff8cc75 100644 (file)
@@ -97,8 +97,6 @@
 
 #define APMG_PCIDEV_STT_VAL_L1_ACT_DIS         (0x00000800)
 
-#define APMG_RTC_INT_STT_RFKILL                (0x10000000)
-
 /* Device system time */
 #define DEVICE_SYSTEM_TIME_REG 0xA0206C
 
index ad9bbca..7fd6fbf 100644 (file)
@@ -138,6 +138,20 @@ static void iwl_mvm_roc_finished(struct iwl_mvm *mvm)
        schedule_work(&mvm->roc_done_wk);
 }
 
+static bool iwl_mvm_te_check_disconnect(struct iwl_mvm *mvm,
+                                       struct ieee80211_vif *vif,
+                                       const char *errmsg)
+{
+       if (vif->type != NL80211_IFTYPE_STATION)
+               return false;
+       if (vif->bss_conf.assoc && vif->bss_conf.dtim_period)
+               return false;
+       if (errmsg)
+               IWL_ERR(mvm, "%s\n", errmsg);
+       ieee80211_connection_loss(vif);
+       return true;
+}
+
 /*
  * Handles a FW notification for an event that is known to the driver.
  *
@@ -163,8 +177,13 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm,
         * P2P Device discoveribility, while there are other higher priority
         * events in the system).
         */
-       WARN_ONCE(!le32_to_cpu(notif->status),
-                 "Failed to schedule time event\n");
+       if (WARN_ONCE(!le32_to_cpu(notif->status),
+                     "Failed to schedule time event\n")) {
+               if (iwl_mvm_te_check_disconnect(mvm, te_data->vif, NULL)) {
+                       iwl_mvm_te_clear_data(mvm, te_data);
+                       return;
+               }
+       }
 
        if (le32_to_cpu(notif->action) & TE_NOTIF_HOST_EVENT_END) {
                IWL_DEBUG_TE(mvm,
@@ -180,14 +199,8 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm,
                 * By now, we should have finished association
                 * and know the dtim period.
                 */
-               if (te_data->vif->type == NL80211_IFTYPE_STATION &&
-                   (!te_data->vif->bss_conf.assoc ||
-                    !te_data->vif->bss_conf.dtim_period)) {
-                       IWL_ERR(mvm,
-                               "No assocation and the time event is over already...\n");
-                       ieee80211_connection_loss(te_data->vif);
-               }
-
+               iwl_mvm_te_check_disconnect(mvm, te_data->vif,
+                       "No assocation and the time event is over already...");
                iwl_mvm_te_clear_data(mvm, te_data);
        } else if (le32_to_cpu(notif->action) & TE_NOTIF_HOST_EVENT_START) {
                te_data->running = true;
index f600e68..fd848cd 100644 (file)
@@ -888,14 +888,6 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
 
                iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill);
                if (hw_rfkill) {
-                       /*
-                        * Clear the interrupt in APMG if the NIC is going down.
-                        * Note that when the NIC exits RFkill (else branch), we
-                        * can't access prph and the NIC will be reset in
-                        * start_hw anyway.
-                        */
-                       iwl_write_prph(trans, APMG_RTC_INT_STT_REG,
-                                      APMG_RTC_INT_STT_RFKILL);
                        set_bit(STATUS_RFKILL, &trans_pcie->status);
                        if (test_and_clear_bit(STATUS_HCMD_ACTIVE,
                                               &trans_pcie->status))
index 96cfcdd..390e2f0 100644 (file)
@@ -1502,16 +1502,16 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
        spin_lock_init(&trans_pcie->reg_lock);
        init_waitqueue_head(&trans_pcie->ucode_write_waitq);
 
-       /* W/A - seems to solve weird behavior. We need to remove this if we
-        * don't want to stay in L1 all the time. This wastes a lot of power */
-       pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
-                              PCIE_LINK_STATE_CLKPM);
-
        if (pci_enable_device(pdev)) {
                err = -ENODEV;
                goto out_no_pci;
        }
 
+       /* W/A - seems to solve weird behavior. We need to remove this if we
+        * don't want to stay in L1 all the time. This wastes a lot of power */
+       pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
+                              PCIE_LINK_STATE_CLKPM);
+
        pci_set_master(pdev);
 
        err = pci_set_dma_mask(pdev, DMA_BIT_MASK(36));
index 4941f20..b8ba1f9 100644 (file)
@@ -98,10 +98,12 @@ static int zd1201_fw_upload(struct usb_device *dev, int apfw)
                goto exit;
 
        err = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), 0x4,
-           USB_DIR_IN | 0x40, 0,0, &ret, sizeof(ret), ZD1201_FW_TIMEOUT);
+           USB_DIR_IN | 0x40, 0, 0, buf, sizeof(ret), ZD1201_FW_TIMEOUT);
        if (err < 0)
                goto exit;
 
+       memcpy(&ret, buf, sizeof(ret));
+
        if (ret & 0x80) {
                err = -EIO;
                goto exit;
index 6bb7cf2..b10ba00 100644 (file)
@@ -392,6 +392,8 @@ static void __unflatten_device_tree(struct boot_param_header *blob,
        mem = (unsigned long)
                dt_alloc(size + 4, __alignof__(struct device_node));
 
+       memset((void *)mem, 0, size);
+
        ((__be32 *)mem)[size / 4] = cpu_to_be32(0xdeadbeef);
 
        pr_debug("  unflattening %lx...\n", mem);
index c47fd1e..94716c7 100644 (file)
@@ -278,6 +278,7 @@ static int sunxi_pconf_group_set(struct pinctrl_dev *pctldev,
 {
        struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
        struct sunxi_pinctrl_group *g = &pctl->groups[group];
+       unsigned long flags;
        u32 val, mask;
        u16 strength;
        u8 dlevel;
@@ -295,22 +296,35 @@ static int sunxi_pconf_group_set(struct pinctrl_dev *pctldev,
                 *   3: 40mA
                 */
                dlevel = strength / 10 - 1;
+
+               spin_lock_irqsave(&pctl->lock, flags);
+
                val = readl(pctl->membase + sunxi_dlevel_reg(g->pin));
                mask = DLEVEL_PINS_MASK << sunxi_dlevel_offset(g->pin);
                writel((val & ~mask) | dlevel << sunxi_dlevel_offset(g->pin),
                        pctl->membase + sunxi_dlevel_reg(g->pin));
+
+               spin_unlock_irqrestore(&pctl->lock, flags);
                break;
        case PIN_CONFIG_BIAS_PULL_UP:
+               spin_lock_irqsave(&pctl->lock, flags);
+
                val = readl(pctl->membase + sunxi_pull_reg(g->pin));
                mask = PULL_PINS_MASK << sunxi_pull_offset(g->pin);
                writel((val & ~mask) | 1 << sunxi_pull_offset(g->pin),
                        pctl->membase + sunxi_pull_reg(g->pin));
+
+               spin_unlock_irqrestore(&pctl->lock, flags);
                break;
        case PIN_CONFIG_BIAS_PULL_DOWN:
+               spin_lock_irqsave(&pctl->lock, flags);
+
                val = readl(pctl->membase + sunxi_pull_reg(g->pin));
                mask = PULL_PINS_MASK << sunxi_pull_offset(g->pin);
                writel((val & ~mask) | 2 << sunxi_pull_offset(g->pin),
                        pctl->membase + sunxi_pull_reg(g->pin));
+
+               spin_unlock_irqrestore(&pctl->lock, flags);
                break;
        default:
                break;
@@ -360,11 +374,17 @@ static void sunxi_pmx_set(struct pinctrl_dev *pctldev,
                                 u8 config)
 {
        struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+       unsigned long flags;
+       u32 val, mask;
+
+       spin_lock_irqsave(&pctl->lock, flags);
 
-       u32 val = readl(pctl->membase + sunxi_mux_reg(pin));
-       u32 mask = MUX_PINS_MASK << sunxi_mux_offset(pin);
+       val = readl(pctl->membase + sunxi_mux_reg(pin));
+       mask = MUX_PINS_MASK << sunxi_mux_offset(pin);
        writel((val & ~mask) | config << sunxi_mux_offset(pin),
                pctl->membase + sunxi_mux_reg(pin));
+
+       spin_unlock_irqrestore(&pctl->lock, flags);
 }
 
 static int sunxi_pmx_enable(struct pinctrl_dev *pctldev,
@@ -464,8 +484,21 @@ static void sunxi_pinctrl_gpio_set(struct gpio_chip *chip,
        struct sunxi_pinctrl *pctl = dev_get_drvdata(chip->dev);
        u32 reg = sunxi_data_reg(offset);
        u8 index = sunxi_data_offset(offset);
+       unsigned long flags;
+       u32 regval;
+
+       spin_lock_irqsave(&pctl->lock, flags);
+
+       regval = readl(pctl->membase + reg);
 
-       writel((value & DATA_PINS_MASK) << index, pctl->membase + reg);
+       if (value)
+               regval |= BIT(index);
+       else
+               regval &= ~(BIT(index));
+
+       writel(regval, pctl->membase + reg);
+
+       spin_unlock_irqrestore(&pctl->lock, flags);
 }
 
 static int sunxi_pinctrl_gpio_of_xlate(struct gpio_chip *gc,
@@ -526,6 +559,8 @@ static int sunxi_pinctrl_irq_set_type(struct irq_data *d,
        struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
        u32 reg = sunxi_irq_cfg_reg(d->hwirq);
        u8 index = sunxi_irq_cfg_offset(d->hwirq);
+       unsigned long flags;
+       u32 regval;
        u8 mode;
 
        switch (type) {
@@ -548,7 +583,13 @@ static int sunxi_pinctrl_irq_set_type(struct irq_data *d,
                return -EINVAL;
        }
 
-       writel((mode & IRQ_CFG_IRQ_MASK) << index, pctl->membase + reg);
+       spin_lock_irqsave(&pctl->lock, flags);
+
+       regval = readl(pctl->membase + reg);
+       regval &= ~IRQ_CFG_IRQ_MASK;
+       writel(regval | (mode << index), pctl->membase + reg);
+
+       spin_unlock_irqrestore(&pctl->lock, flags);
 
        return 0;
 }
@@ -560,14 +601,19 @@ static void sunxi_pinctrl_irq_mask_ack(struct irq_data *d)
        u8 ctrl_idx = sunxi_irq_ctrl_offset(d->hwirq);
        u32 status_reg = sunxi_irq_status_reg(d->hwirq);
        u8 status_idx = sunxi_irq_status_offset(d->hwirq);
+       unsigned long flags;
        u32 val;
 
+       spin_lock_irqsave(&pctl->lock, flags);
+
        /* Mask the IRQ */
        val = readl(pctl->membase + ctrl_reg);
        writel(val & ~(1 << ctrl_idx), pctl->membase + ctrl_reg);
 
        /* Clear the IRQ */
        writel(1 << status_idx, pctl->membase + status_reg);
+
+       spin_unlock_irqrestore(&pctl->lock, flags);
 }
 
 static void sunxi_pinctrl_irq_mask(struct irq_data *d)
@@ -575,11 +621,16 @@ static void sunxi_pinctrl_irq_mask(struct irq_data *d)
        struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
        u32 reg = sunxi_irq_ctrl_reg(d->hwirq);
        u8 idx = sunxi_irq_ctrl_offset(d->hwirq);
+       unsigned long flags;
        u32 val;
 
+       spin_lock_irqsave(&pctl->lock, flags);
+
        /* Mask the IRQ */
        val = readl(pctl->membase + reg);
        writel(val & ~(1 << idx), pctl->membase + reg);
+
+       spin_unlock_irqrestore(&pctl->lock, flags);
 }
 
 static void sunxi_pinctrl_irq_unmask(struct irq_data *d)
@@ -588,6 +639,7 @@ static void sunxi_pinctrl_irq_unmask(struct irq_data *d)
        struct sunxi_desc_function *func;
        u32 reg = sunxi_irq_ctrl_reg(d->hwirq);
        u8 idx = sunxi_irq_ctrl_offset(d->hwirq);
+       unsigned long flags;
        u32 val;
 
        func = sunxi_pinctrl_desc_find_function_by_pin(pctl,
@@ -597,9 +649,13 @@ static void sunxi_pinctrl_irq_unmask(struct irq_data *d)
        /* Change muxing to INT mode */
        sunxi_pmx_set(pctl->pctl_dev, pctl->irq_array[d->hwirq], func->muxval);
 
+       spin_lock_irqsave(&pctl->lock, flags);
+
        /* Unmask the IRQ */
        val = readl(pctl->membase + reg);
        writel(val | (1 << idx), pctl->membase + reg);
+
+       spin_unlock_irqrestore(&pctl->lock, flags);
 }
 
 static struct irq_chip sunxi_pinctrl_irq_chip = {
@@ -752,6 +808,8 @@ static int sunxi_pinctrl_probe(struct platform_device *pdev)
                return -ENOMEM;
        platform_set_drvdata(pdev, pctl);
 
+       spin_lock_init(&pctl->lock);
+
        pctl->membase = of_iomap(node, 0);
        if (!pctl->membase)
                return -ENOMEM;
index d68047d..01c494f 100644 (file)
@@ -14,6 +14,7 @@
 #define __PINCTRL_SUNXI_H
 
 #include <linux/kernel.h>
+#include <linux/spinlock.h>
 
 #define PA_BASE        0
 #define PB_BASE        32
@@ -407,6 +408,7 @@ struct sunxi_pinctrl {
        unsigned                        ngroups;
        int                             irq;
        int                             irq_array[SUNXI_IRQ_NUMBER];
+       spinlock_t                      lock;
        struct pinctrl_dev              *pctl_dev;
 };
 
index 0f9f859..f911952 100644 (file)
@@ -330,7 +330,7 @@ static int __init olpc_ec_init_module(void)
        return platform_driver_register(&olpc_ec_plat_driver);
 }
 
-module_init(olpc_ec_init_module);
+arch_initcall(olpc_ec_init_module);
 
 MODULE_AUTHOR("Andres Salomon <dilinger@queued.net>");
 MODULE_LICENSE("GPL");
index 97bb05e..d6970f4 100644 (file)
@@ -53,7 +53,6 @@ MODULE_ALIAS("wmi:5FB7F034-2C63-45e9-BE91-3D44E2C707E4");
 #define HPWMI_ALS_QUERY 0x3
 #define HPWMI_HARDWARE_QUERY 0x4
 #define HPWMI_WIRELESS_QUERY 0x5
-#define HPWMI_BIOS_QUERY 0x9
 #define HPWMI_HOTKEY_QUERY 0xc
 #define HPWMI_WIRELESS2_QUERY 0x1b
 #define HPWMI_POSTCODEERROR_QUERY 0x2a
@@ -293,19 +292,6 @@ static int hp_wmi_tablet_state(void)
        return (state & 0x4) ? 1 : 0;
 }
 
-static int hp_wmi_enable_hotkeys(void)
-{
-       int ret;
-       int query = 0x6e;
-
-       ret = hp_wmi_perform_query(HPWMI_BIOS_QUERY, 1, &query, sizeof(query),
-                                  0);
-
-       if (ret)
-               return -EINVAL;
-       return 0;
-}
-
 static int hp_wmi_set_block(void *data, bool blocked)
 {
        enum hp_wmi_radio r = (enum hp_wmi_radio) data;
@@ -1009,8 +995,6 @@ static int __init hp_wmi_init(void)
                err = hp_wmi_input_setup();
                if (err)
                        return err;
-
-               hp_wmi_enable_hotkeys();
        }
 
        if (bios_capable) {
index 2ac045f..3a1b6bf 100644 (file)
@@ -2440,7 +2440,10 @@ static ssize_t sony_nc_gfx_switch_status_show(struct device *dev,
        if (pos < 0)
                return pos;
 
-       return snprintf(buffer, PAGE_SIZE, "%s\n", pos ? "speed" : "stamina");
+       return snprintf(buffer, PAGE_SIZE, "%s\n",
+                                       pos == SPEED ? "speed" :
+                                       pos == STAMINA ? "stamina" :
+                                       pos == AUTO ? "auto" : "unknown");
 }
 
 static int sony_nc_gfx_switch_setup(struct platform_device *pd,
@@ -4320,7 +4323,8 @@ static int sony_pic_add(struct acpi_device *device)
                goto err_free_resources;
        }
 
-       if (sonypi_compat_init())
+       result = sonypi_compat_init();
+       if (result)
                goto err_remove_input;
 
        /* request io port */
index 767fee2..2601953 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
+#include <linux/delay.h>
 #include <linux/rtc.h>
 #include <linux/slab.h>
 #include <linux/of_device.h>
@@ -119,24 +120,39 @@ static void stmp3xxx_wdt_register(struct platform_device *rtc_pdev)
 }
 #endif /* CONFIG_STMP3XXX_RTC_WATCHDOG */
 
-static void stmp3xxx_wait_time(struct stmp3xxx_rtc_data *rtc_data)
+static int stmp3xxx_wait_time(struct stmp3xxx_rtc_data *rtc_data)
 {
+       int timeout = 5000; /* 3ms according to i.MX28 Ref Manual */
        /*
-        * The datasheet doesn't say which way round the
-        * NEW_REGS/STALE_REGS bitfields go. In fact it's 0x1=P0,
-        * 0x2=P1, .., 0x20=P5, 0x40=ALARM, 0x80=SECONDS
+        * The i.MX28 Applications Processor Reference Manual, Rev. 1, 2010
+        * states:
+        * | The order in which registers are updated is
+        * | Persistent 0, 1, 2, 3, 4, 5, Alarm, Seconds.
+        * | (This list is in bitfield order, from LSB to MSB, as they would
+        * | appear in the STALE_REGS and NEW_REGS bitfields of the HW_RTC_STAT
+        * | register. For example, the Seconds register corresponds to
+        * | STALE_REGS or NEW_REGS containing 0x80.)
         */
-       while (readl(rtc_data->io + STMP3XXX_RTC_STAT) &
-                       (0x80 << STMP3XXX_RTC_STAT_STALE_SHIFT))
-               cpu_relax();
+       do {
+               if (!(readl(rtc_data->io + STMP3XXX_RTC_STAT) &
+                               (0x80 << STMP3XXX_RTC_STAT_STALE_SHIFT)))
+                       return 0;
+               udelay(1);
+       } while (--timeout > 0);
+       return (readl(rtc_data->io + STMP3XXX_RTC_STAT) &
+               (0x80 << STMP3XXX_RTC_STAT_STALE_SHIFT)) ? -ETIME : 0;
 }
 
 /* Time read/write */
 static int stmp3xxx_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
 {
+       int ret;
        struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
 
-       stmp3xxx_wait_time(rtc_data);
+       ret = stmp3xxx_wait_time(rtc_data);
+       if (ret)
+               return ret;
+
        rtc_time_to_tm(readl(rtc_data->io + STMP3XXX_RTC_SECONDS), rtc_tm);
        return 0;
 }
@@ -146,8 +162,7 @@ static int stmp3xxx_rtc_set_mmss(struct device *dev, unsigned long t)
        struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
 
        writel(t, rtc_data->io + STMP3XXX_RTC_SECONDS);
-       stmp3xxx_wait_time(rtc_data);
-       return 0;
+       return stmp3xxx_wait_time(rtc_data);
 }
 
 /* interrupt(s) handler */
index 1d4c8fe..c82fe65 100644 (file)
@@ -102,10 +102,13 @@ static void zfcp_erp_action_dismiss_port(struct zfcp_port *port)
 
        if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_INUSE)
                zfcp_erp_action_dismiss(&port->erp_action);
-       else
-               shost_for_each_device(sdev, port->adapter->scsi_host)
+       else {
+               spin_lock(port->adapter->scsi_host->host_lock);
+               __shost_for_each_device(sdev, port->adapter->scsi_host)
                        if (sdev_to_zfcp(sdev)->port == port)
                                zfcp_erp_action_dismiss_lun(sdev);
+               spin_unlock(port->adapter->scsi_host->host_lock);
+       }
 }
 
 static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter)
@@ -592,9 +595,11 @@ static void _zfcp_erp_lun_reopen_all(struct zfcp_port *port, int clear,
 {
        struct scsi_device *sdev;
 
-       shost_for_each_device(sdev, port->adapter->scsi_host)
+       spin_lock(port->adapter->scsi_host->host_lock);
+       __shost_for_each_device(sdev, port->adapter->scsi_host)
                if (sdev_to_zfcp(sdev)->port == port)
                        _zfcp_erp_lun_reopen(sdev, clear, id, 0);
+       spin_unlock(port->adapter->scsi_host->host_lock);
 }
 
 static void zfcp_erp_strategy_followup_failed(struct zfcp_erp_action *act)
@@ -1434,8 +1439,10 @@ void zfcp_erp_set_adapter_status(struct zfcp_adapter *adapter, u32 mask)
                atomic_set_mask(common_mask, &port->status);
        read_unlock_irqrestore(&adapter->port_list_lock, flags);
 
-       shost_for_each_device(sdev, adapter->scsi_host)
+       spin_lock_irqsave(adapter->scsi_host->host_lock, flags);
+       __shost_for_each_device(sdev, adapter->scsi_host)
                atomic_set_mask(common_mask, &sdev_to_zfcp(sdev)->status);
+       spin_unlock_irqrestore(adapter->scsi_host->host_lock, flags);
 }
 
 /**
@@ -1469,11 +1476,13 @@ void zfcp_erp_clear_adapter_status(struct zfcp_adapter *adapter, u32 mask)
        }
        read_unlock_irqrestore(&adapter->port_list_lock, flags);
 
-       shost_for_each_device(sdev, adapter->scsi_host) {
+       spin_lock_irqsave(adapter->scsi_host->host_lock, flags);
+       __shost_for_each_device(sdev, adapter->scsi_host) {
                atomic_clear_mask(common_mask, &sdev_to_zfcp(sdev)->status);
                if (clear_counter)
                        atomic_set(&sdev_to_zfcp(sdev)->erp_counter, 0);
        }
+       spin_unlock_irqrestore(adapter->scsi_host->host_lock, flags);
 }
 
 /**
@@ -1487,16 +1496,19 @@ void zfcp_erp_set_port_status(struct zfcp_port *port, u32 mask)
 {
        struct scsi_device *sdev;
        u32 common_mask = mask & ZFCP_COMMON_FLAGS;
+       unsigned long flags;
 
        atomic_set_mask(mask, &port->status);
 
        if (!common_mask)
                return;
 
-       shost_for_each_device(sdev, port->adapter->scsi_host)
+       spin_lock_irqsave(port->adapter->scsi_host->host_lock, flags);
+       __shost_for_each_device(sdev, port->adapter->scsi_host)
                if (sdev_to_zfcp(sdev)->port == port)
                        atomic_set_mask(common_mask,
                                        &sdev_to_zfcp(sdev)->status);
+       spin_unlock_irqrestore(port->adapter->scsi_host->host_lock, flags);
 }
 
 /**
@@ -1511,6 +1523,7 @@ void zfcp_erp_clear_port_status(struct zfcp_port *port, u32 mask)
        struct scsi_device *sdev;
        u32 common_mask = mask & ZFCP_COMMON_FLAGS;
        u32 clear_counter = mask & ZFCP_STATUS_COMMON_ERP_FAILED;
+       unsigned long flags;
 
        atomic_clear_mask(mask, &port->status);
 
@@ -1520,13 +1533,15 @@ void zfcp_erp_clear_port_status(struct zfcp_port *port, u32 mask)
        if (clear_counter)
                atomic_set(&port->erp_counter, 0);
 
-       shost_for_each_device(sdev, port->adapter->scsi_host)
+       spin_lock_irqsave(port->adapter->scsi_host->host_lock, flags);
+       __shost_for_each_device(sdev, port->adapter->scsi_host)
                if (sdev_to_zfcp(sdev)->port == port) {
                        atomic_clear_mask(common_mask,
                                          &sdev_to_zfcp(sdev)->status);
                        if (clear_counter)
                                atomic_set(&sdev_to_zfcp(sdev)->erp_counter, 0);
                }
+       spin_unlock_irqrestore(port->adapter->scsi_host->host_lock, flags);
 }
 
 /**
index 665e3cf..de0598e 100644 (file)
@@ -224,11 +224,9 @@ int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req,
 
 static int zfcp_qdio_sbal_check(struct zfcp_qdio *qdio)
 {
-       spin_lock_irq(&qdio->req_q_lock);
        if (atomic_read(&qdio->req_q_free) ||
            !(atomic_read(&qdio->adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP))
                return 1;
-       spin_unlock_irq(&qdio->req_q_lock);
        return 0;
 }
 
@@ -246,9 +244,8 @@ int zfcp_qdio_sbal_get(struct zfcp_qdio *qdio)
 {
        long ret;
 
-       spin_unlock_irq(&qdio->req_q_lock);
-       ret = wait_event_interruptible_timeout(qdio->req_q_wq,
-                              zfcp_qdio_sbal_check(qdio), 5 * HZ);
+       ret = wait_event_interruptible_lock_irq_timeout(qdio->req_q_wq,
+                      zfcp_qdio_sbal_check(qdio), qdio->req_q_lock, 5 * HZ);
 
        if (!(atomic_read(&qdio->adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP))
                return -EIO;
@@ -262,7 +259,6 @@ int zfcp_qdio_sbal_get(struct zfcp_qdio *qdio)
                zfcp_erp_adapter_reopen(qdio->adapter, 0, "qdsbg_1");
        }
 
-       spin_lock_irq(&qdio->req_q_lock);
        return -EIO;
 }
 
index 3f01bbf..8906392 100644 (file)
@@ -27,6 +27,16 @@ static ssize_t zfcp_sysfs_##_feat##_##_name##_show(struct device *dev,              \
 static ZFCP_DEV_ATTR(_feat, _name, S_IRUGO,                                   \
                     zfcp_sysfs_##_feat##_##_name##_show, NULL);
 
+#define ZFCP_DEFINE_ATTR_CONST(_feat, _name, _format, _value)                 \
+static ssize_t zfcp_sysfs_##_feat##_##_name##_show(struct device *dev,        \
+                                                  struct device_attribute *at,\
+                                                  char *buf)                  \
+{                                                                             \
+       return sprintf(buf, _format, _value);                                  \
+}                                                                             \
+static ZFCP_DEV_ATTR(_feat, _name, S_IRUGO,                                   \
+                    zfcp_sysfs_##_feat##_##_name##_show, NULL);
+
 #define ZFCP_DEFINE_A_ATTR(_name, _format, _value)                          \
 static ssize_t zfcp_sysfs_adapter_##_name##_show(struct device *dev,        \
                                                 struct device_attribute *at,\
@@ -75,6 +85,8 @@ ZFCP_DEFINE_ATTR(zfcp_unit, unit, in_recovery, "%d\n",
 ZFCP_DEFINE_ATTR(zfcp_unit, unit, access_denied, "%d\n",
                 (zfcp_unit_sdev_status(unit) &
                  ZFCP_STATUS_COMMON_ACCESS_DENIED) != 0);
+ZFCP_DEFINE_ATTR_CONST(unit, access_shared, "%d\n", 0);
+ZFCP_DEFINE_ATTR_CONST(unit, access_readonly, "%d\n", 0);
 
 static ssize_t zfcp_sysfs_port_failed_show(struct device *dev,
                                           struct device_attribute *attr,
@@ -347,6 +359,8 @@ static struct attribute *zfcp_unit_attrs[] = {
        &dev_attr_unit_in_recovery.attr,
        &dev_attr_unit_status.attr,
        &dev_attr_unit_access_denied.attr,
+       &dev_attr_unit_access_shared.attr,
+       &dev_attr_unit_access_readonly.attr,
        NULL
 };
 static struct attribute_group zfcp_unit_attr_group = {
index 48b2918..92ff027 100644 (file)
@@ -1353,7 +1353,6 @@ config SCSI_LPFC
        tristate "Emulex LightPulse Fibre Channel Support"
        depends on PCI && SCSI
        select SCSI_FC_ATTRS
-       select GENERIC_CSUM
        select CRC_T10DIF
        help
           This lpfc driver supports the Emulex LightPulse
index 89cbbab..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 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 e25eba5..b3b5125 100644 (file)
@@ -482,7 +482,7 @@ int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it)
                ret = comedi_device_postconfig(dev);
        if (ret < 0) {
                comedi_device_detach(dev);
-               module_put(dev->driver->module);
+               module_put(driv->module);
        }
        /* On success, the driver module count has been incremented. */
        return ret;
index 609dbc2..83b4ef4 100644 (file)
@@ -1119,11 +1119,11 @@ static int usbtmc_probe(struct usb_interface *intf,
        /* Determine if it is a Rigol or not */
        data->rigol_quirk = 0;
        dev_dbg(&intf->dev, "Trying to find if device Vendor 0x%04X Product 0x%04X has the RIGOL quirk\n",
-               data->usb_dev->descriptor.idVendor,
-               data->usb_dev->descriptor.idProduct);
+               le16_to_cpu(data->usb_dev->descriptor.idVendor),
+               le16_to_cpu(data->usb_dev->descriptor.idProduct));
        for(n = 0; usbtmc_id_quirk[n].idVendor > 0; n++) {
-               if ((usbtmc_id_quirk[n].idVendor == data->usb_dev->descriptor.idVendor) &&
-                   (usbtmc_id_quirk[n].idProduct == data->usb_dev->descriptor.idProduct)) {
+               if ((usbtmc_id_quirk[n].idVendor == le16_to_cpu(data->usb_dev->descriptor.idVendor)) &&
+                   (usbtmc_id_quirk[n].idProduct == le16_to_cpu(data->usb_dev->descriptor.idProduct))) {
                        dev_dbg(&intf->dev, "Setting this device as having the RIGOL quirk\n");
                        data->rigol_quirk = 1;
                        break;
index a635988..5b44cd4 100644 (file)
@@ -78,6 +78,12 @@ static const struct usb_device_id usb_quirk_list[] = {
        { USB_DEVICE(0x04d8, 0x000c), .driver_info =
                        USB_QUIRK_CONFIG_INTF_STRINGS },
 
+       /* CarrolTouch 4000U */
+       { USB_DEVICE(0x04e7, 0x0009), .driver_info = USB_QUIRK_RESET_RESUME },
+
+       /* CarrolTouch 4500U */
+       { USB_DEVICE(0x04e7, 0x0030), .driver_info = USB_QUIRK_RESET_RESUME },
+
        /* Samsung Android phone modem - ID conflict with SPH-I500 */
        { USB_DEVICE(0x04e8, 0x6601), .driver_info =
                        USB_QUIRK_CONFIG_INTF_STRINGS },
index f80d033..8e3c878 100644 (file)
@@ -1391,21 +1391,20 @@ iso_stream_schedule (
 
                /* Behind the scheduling threshold? */
                if (unlikely(start < next)) {
+                       unsigned now2 = (now - base) & (mod - 1);
 
                        /* USB_ISO_ASAP: Round up to the first available slot */
                        if (urb->transfer_flags & URB_ISO_ASAP)
                                start += (next - start + period - 1) & -period;
 
                        /*
-                        * Not ASAP: Use the next slot in the stream.  If
-                        * the entire URB falls before the threshold, fail.
+                        * Not ASAP: Use the next slot in the stream,
+                        * no matter what.
                         */
-                       else if (start + span - period < next) {
-                               ehci_dbg(ehci, "iso urb late %p (%u+%u < %u)\n",
+                       else if (start + span - period < now2) {
+                               ehci_dbg(ehci, "iso underrun %p (%u+%u < %u)\n",
                                                urb, start + base,
-                                               span - period, next + base);
-                               status = -EXDEV;
-                               goto fail;
+                                               span - period, now2 + base);
                        }
                }
 
index 08613e2..0f1d193 100644 (file)
@@ -304,6 +304,11 @@ static int __init ohci_pci_init(void)
        pr_info("%s: " DRIVER_DESC "\n", hcd_name);
 
        ohci_init_driver(&ohci_pci_hc_driver, &pci_overrides);
+
+       /* Entries for the PCI suspend/resume callbacks are special */
+       ohci_pci_hc_driver.pci_suspend = ohci_suspend;
+       ohci_pci_hc_driver.pci_resume = ohci_resume;
+
        return pci_register_driver(&ohci_pci_driver);
 }
 module_init(ohci_pci_init);
index eb3c8c1..eeb2720 100644 (file)
@@ -830,7 +830,7 @@ static int adu_probe(struct usb_interface *interface,
 
        /* let the user know what node this device is now attached to */
        dev_info(&interface->dev, "ADU%d %s now attached to /dev/usb/adutux%d\n",
-                udev->descriptor.idProduct, dev->serial_number,
+                le16_to_cpu(udev->descriptor.idProduct), dev->serial_number,
                 (dev->minor - ADU_MINOR_BASE));
 exit:
        dbg(2, " %s : leave, return value %p (dev)", __func__, dev);
index ca26628..e1859b8 100644 (file)
@@ -15,7 +15,7 @@
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include "otg_fsm.h"
+#include "phy-fsm-usb.h"
 #include <linux/usb/otg.h>
 #include <linux/ioctl.h>
 
index c520b35..7f45966 100644 (file)
@@ -29,7 +29,7 @@
 #include <linux/usb/gadget.h>
 #include <linux/usb/otg.h>
 
-#include "phy-otg-fsm.h"
+#include "phy-fsm-usb.h"
 
 /* Change USB protocol when there is a protocol change */
 static int otg_set_protocol(struct otg_fsm *fsm, int protocol)
index 5a97972..58c17fd 100644 (file)
@@ -2303,7 +2303,7 @@ static int keyspan_startup(struct usb_serial *serial)
        if (d_details == NULL) {
                dev_err(&serial->dev->dev, "%s - unknown product id %x\n",
                    __func__, le16_to_cpu(serial->dev->descriptor.idProduct));
-               return 1;
+               return -ENODEV;
        }
 
        /* Setup private data for serial driver */
index 51da424..b013001 100644 (file)
@@ -90,6 +90,7 @@ struct urbtracker {
        struct list_head        urblist_entry;
        struct kref             ref_count;
        struct urb              *urb;
+       struct usb_ctrlrequest  *setup;
 };
 
 enum mos7715_pp_modes {
@@ -271,6 +272,7 @@ static void destroy_urbtracker(struct kref *kref)
        struct mos7715_parport *mos_parport = urbtrack->mos_parport;
 
        usb_free_urb(urbtrack->urb);
+       kfree(urbtrack->setup);
        kfree(urbtrack);
        kref_put(&mos_parport->ref_count, destroy_mos_parport);
 }
@@ -355,7 +357,6 @@ static int write_parport_reg_nonblock(struct mos7715_parport *mos_parport,
        struct urbtracker *urbtrack;
        int ret_val;
        unsigned long flags;
-       struct usb_ctrlrequest setup;
        struct usb_serial *serial = mos_parport->serial;
        struct usb_device *usbdev = serial->dev;
 
@@ -373,14 +374,20 @@ static int write_parport_reg_nonblock(struct mos7715_parport *mos_parport,
                kfree(urbtrack);
                return -ENOMEM;
        }
-       setup.bRequestType = (__u8)0x40;
-       setup.bRequest = (__u8)0x0e;
-       setup.wValue = get_reg_value(reg, dummy);
-       setup.wIndex = get_reg_index(reg);
-       setup.wLength = 0;
+       urbtrack->setup = kmalloc(sizeof(*urbtrack->setup), GFP_KERNEL);
+       if (!urbtrack->setup) {
+               usb_free_urb(urbtrack->urb);
+               kfree(urbtrack);
+               return -ENOMEM;
+       }
+       urbtrack->setup->bRequestType = (__u8)0x40;
+       urbtrack->setup->bRequest = (__u8)0x0e;
+       urbtrack->setup->wValue = get_reg_value(reg, dummy);
+       urbtrack->setup->wIndex = get_reg_index(reg);
+       urbtrack->setup->wLength = 0;
        usb_fill_control_urb(urbtrack->urb, usbdev,
                             usb_sndctrlpipe(usbdev, 0),
-                            (unsigned char *)&setup,
+                            (unsigned char *)urbtrack->setup,
                             NULL, 0, async_complete, urbtrack);
        kref_init(&urbtrack->ref_count);
        INIT_LIST_HEAD(&urbtrack->urblist_entry);
index d953d67..3bac469 100644 (file)
@@ -2193,7 +2193,7 @@ static int mos7810_check(struct usb_serial *serial)
 static int mos7840_probe(struct usb_serial *serial,
                                const struct usb_device_id *id)
 {
-       u16 product = serial->dev->descriptor.idProduct;
+       u16 product = le16_to_cpu(serial->dev->descriptor.idProduct);
        u8 *buf;
        int device_type;
 
index 375b5a4..5c9f9b1 100644 (file)
@@ -1536,14 +1536,15 @@ static int ti_download_firmware(struct ti_device *tdev)
        char buf[32];
 
        /* try ID specific firmware first, then try generic firmware */
-       sprintf(buf, "ti_usb-v%04x-p%04x.fw", dev->descriptor.idVendor,
-           dev->descriptor.idProduct);
+       sprintf(buf, "ti_usb-v%04x-p%04x.fw",
+                       le16_to_cpu(dev->descriptor.idVendor),
+                       le16_to_cpu(dev->descriptor.idProduct));
        status = request_firmware(&fw_p, buf, &dev->dev);
 
        if (status != 0) {
                buf[0] = '\0';
-               if (dev->descriptor.idVendor == MTS_VENDOR_ID) {
-                       switch (dev->descriptor.idProduct) {
+               if (le16_to_cpu(dev->descriptor.idVendor) == MTS_VENDOR_ID) {
+                       switch (le16_to_cpu(dev->descriptor.idProduct)) {
                        case MTS_CDMA_PRODUCT_ID:
                                strcpy(buf, "mts_cdma.fw");
                                break;
index 8257d30..8536578 100644 (file)
@@ -291,18 +291,18 @@ static void usb_wwan_indat_callback(struct urb *urb)
                        tty_flip_buffer_push(&port->port);
                } else
                        dev_dbg(dev, "%s: empty read urb received\n", __func__);
-
-               /* Resubmit urb so we continue receiving */
-               err = usb_submit_urb(urb, GFP_ATOMIC);
-               if (err) {
-                       if (err != -EPERM) {
-                               dev_err(dev, "%s: resubmit read urb failed. (%d)\n", __func__, err);
-                               /* busy also in error unless we are killed */
-                               usb_mark_last_busy(port->serial->dev);
-                       }
-               } else {
+       }
+       /* Resubmit urb so we continue receiving */
+       err = usb_submit_urb(urb, GFP_ATOMIC);
+       if (err) {
+               if (err != -EPERM) {
+                       dev_err(dev, "%s: resubmit read urb failed. (%d)\n",
+                               __func__, err);
+                       /* busy also in error unless we are killed */
                        usb_mark_last_busy(port->serial->dev);
                }
+       } else {
+               usb_mark_last_busy(port->serial->dev);
        }
 }
 
index 16968c8..d3493ca 100644 (file)
@@ -1226,6 +1226,12 @@ int wa_urb_dequeue(struct wahc *wa, struct urb *urb)
        }
        spin_lock_irqsave(&xfer->lock, flags);
        rpipe = xfer->ep->hcpriv;
+       if (rpipe == NULL) {
+               pr_debug("%s: xfer id 0x%08X has no RPIPE.  %s",
+                       __func__, wa_xfer_id(xfer),
+                       "Probably already aborted.\n" );
+               goto out_unlock;
+       }
        /* Check the delayed list -> if there, release and complete */
        spin_lock_irqsave(&wa->xfer_list_lock, flags2);
        if (!list_empty(&xfer->list_node) && xfer->seg == NULL)
@@ -1644,8 +1650,7 @@ static void wa_xfer_result_cb(struct urb *urb)
                        break;
                }
                usb_status = xfer_result->bTransferStatus & 0x3f;
-               if (usb_status == WA_XFER_STATUS_ABORTED
-                   || usb_status == WA_XFER_STATUS_NOT_FOUND)
+               if (usb_status == WA_XFER_STATUS_NOT_FOUND)
                        /* taken care of already */
                        break;
                xfer_id = xfer_result->dwTransferID;
index a58ac43..5e8be46 100644 (file)
@@ -348,7 +348,7 @@ static void init_evtchn_cpu_bindings(void)
 
        for_each_possible_cpu(i)
                memset(per_cpu(cpu_evtchn_mask, i),
-                      (i == 0) ? ~0 : 0, sizeof(*per_cpu(cpu_evtchn_mask, i)));
+                      (i == 0) ? ~0 : 0, NR_EVENT_CHANNELS/8);
 }
 
 static inline void clear_evtchn(int port)
@@ -1493,8 +1493,10 @@ void rebind_evtchn_irq(int evtchn, int irq)
 /* Rebind an evtchn so that it gets delivered to a specific cpu */
 static int rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
 {
+       struct shared_info *s = HYPERVISOR_shared_info;
        struct evtchn_bind_vcpu bind_vcpu;
        int evtchn = evtchn_from_irq(irq);
+       int masked;
 
        if (!VALID_EVTCHN(evtchn))
                return -1;
@@ -1510,6 +1512,12 @@ static int rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
        bind_vcpu.port = evtchn;
        bind_vcpu.vcpu = tcpu;
 
+       /*
+        * Mask the event while changing the VCPU binding to prevent
+        * it being delivered on an unexpected VCPU.
+        */
+       masked = sync_test_and_set_bit(evtchn, BM(s->evtchn_mask));
+
        /*
         * If this fails, it usually just indicates that we're dealing with a
         * virq or IPI channel, which don't actually need to be rebound. Ignore
@@ -1518,6 +1526,9 @@ static int rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
        if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_vcpu, &bind_vcpu) >= 0)
                bind_evtchn_to_cpu(evtchn, tcpu);
 
+       if (!masked)
+               unmask_evtchn(evtchn);
+
        return 0;
 }
 
index 5e376bb..8defc6b 100644 (file)
@@ -40,7 +40,7 @@ struct inode *bfs_iget(struct super_block *sb, unsigned long ino)
        int block, off;
 
        inode = iget_locked(sb, ino);
-       if (IS_ERR(inode))
+       if (!inode)
                return ERR_PTR(-ENOMEM);
        if (!(inode->i_state & I_NEW))
                return inode;
index 94bbc04..c5eae72 100644 (file)
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -1045,12 +1045,22 @@ static int __bio_copy_iov(struct bio *bio, struct bio_vec *iovecs,
 int bio_uncopy_user(struct bio *bio)
 {
        struct bio_map_data *bmd = bio->bi_private;
-       int ret = 0;
+       struct bio_vec *bvec;
+       int ret = 0, i;
 
-       if (!bio_flagged(bio, BIO_NULL_MAPPED))
-               ret = __bio_copy_iov(bio, bmd->iovecs, bmd->sgvecs,
-                                    bmd->nr_sgvecs, bio_data_dir(bio) == READ,
-                                    0, bmd->is_our_pages);
+       if (!bio_flagged(bio, BIO_NULL_MAPPED)) {
+               /*
+                * if we're in a workqueue, the request is orphaned, so
+                * don't copy into a random user address space, just free.
+                */
+               if (current->mm)
+                       ret = __bio_copy_iov(bio, bmd->iovecs, bmd->sgvecs,
+                                            bmd->nr_sgvecs, bio_data_dir(bio) == READ,
+                                            0, bmd->is_our_pages);
+               else if (bmd->is_our_pages)
+                       bio_for_each_segment_all(bvec, bio, i)
+                               __free_page(bvec->bv_page);
+       }
        bio_free_map_data(bmd);
        bio_put(bio);
        return ret;
index 45e57cc..fc6f4f3 100644 (file)
@@ -43,17 +43,18 @@ cifs_crypto_shash_md5_allocate(struct TCP_Server_Info *server)
        server->secmech.md5 = crypto_alloc_shash("md5", 0, 0);
        if (IS_ERR(server->secmech.md5)) {
                cifs_dbg(VFS, "could not allocate crypto md5\n");
-               return PTR_ERR(server->secmech.md5);
+               rc = PTR_ERR(server->secmech.md5);
+               server->secmech.md5 = NULL;
+               return rc;
        }
 
        size = sizeof(struct shash_desc) +
                        crypto_shash_descsize(server->secmech.md5);
        server->secmech.sdescmd5 = kmalloc(size, GFP_KERNEL);
        if (!server->secmech.sdescmd5) {
-               rc = -ENOMEM;
                crypto_free_shash(server->secmech.md5);
                server->secmech.md5 = NULL;
-               return rc;
+               return -ENOMEM;
        }
        server->secmech.sdescmd5->shash.tfm = server->secmech.md5;
        server->secmech.sdescmd5->shash.flags = 0x0;
@@ -421,7 +422,7 @@ find_domain_name(struct cifs_ses *ses, const struct nls_table *nls_cp)
                if (blobptr + attrsize > blobend)
                        break;
                if (type == NTLMSSP_AV_NB_DOMAIN_NAME) {
-                       if (!attrsize)
+                       if (!attrsize || attrsize >= CIFS_MAX_DOMAINNAME_LEN)
                                break;
                        if (!ses->domainName) {
                                ses->domainName =
@@ -591,6 +592,7 @@ CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash)
 
 static int crypto_hmacmd5_alloc(struct TCP_Server_Info *server)
 {
+       int rc;
        unsigned int size;
 
        /* check if already allocated */
@@ -600,7 +602,9 @@ static int crypto_hmacmd5_alloc(struct TCP_Server_Info *server)
        server->secmech.hmacmd5 = crypto_alloc_shash("hmac(md5)", 0, 0);
        if (IS_ERR(server->secmech.hmacmd5)) {
                cifs_dbg(VFS, "could not allocate crypto hmacmd5\n");
-               return PTR_ERR(server->secmech.hmacmd5);
+               rc = PTR_ERR(server->secmech.hmacmd5);
+               server->secmech.hmacmd5 = NULL;
+               return rc;
        }
 
        size = sizeof(struct shash_desc) +
index 4bdd547..85ea98d 100644 (file)
@@ -147,18 +147,17 @@ cifs_read_super(struct super_block *sb)
                goto out_no_root;
        }
 
+       if (cifs_sb_master_tcon(cifs_sb)->nocase)
+               sb->s_d_op = &cifs_ci_dentry_ops;
+       else
+               sb->s_d_op = &cifs_dentry_ops;
+
        sb->s_root = d_make_root(inode);
        if (!sb->s_root) {
                rc = -ENOMEM;
                goto out_no_root;
        }
 
-       /* do that *after* d_make_root() - we want NULL ->d_op for root here */
-       if (cifs_sb_master_tcon(cifs_sb)->nocase)
-               sb->s_d_op = &cifs_ci_dentry_ops;
-       else
-               sb->s_d_op = &cifs_dentry_ops;
-
 #ifdef CONFIG_CIFS_NFSD_EXPORT
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
                cifs_dbg(FYI, "export ops supported\n");
index 1fdc370..52ca861 100644 (file)
@@ -44,6 +44,7 @@
 #define MAX_TREE_SIZE (2 + MAX_SERVER_SIZE + 1 + MAX_SHARE_SIZE + 1)
 #define MAX_SERVER_SIZE 15
 #define MAX_SHARE_SIZE 80
+#define CIFS_MAX_DOMAINNAME_LEN 256 /* max domain name length */
 #define MAX_USERNAME_SIZE 256  /* reasonable maximum for current servers */
 #define MAX_PASSWORD_SIZE 512  /* max for windows seems to be 256 wide chars */
 
@@ -369,6 +370,9 @@ struct smb_version_operations {
        void (*generate_signingkey)(struct TCP_Server_Info *server);
        int (*calc_signature)(struct smb_rqst *rqst,
                                   struct TCP_Server_Info *server);
+       int (*query_mf_symlink)(const unsigned char *path, char *pbuf,
+                       unsigned int *pbytes_read, struct cifs_sb_info *cifs_sb,
+                       unsigned int xid);
 };
 
 struct smb_version_values {
index f7e584d..b29a012 100644 (file)
@@ -497,5 +497,7 @@ void cifs_writev_complete(struct work_struct *work);
 struct cifs_writedata *cifs_writedata_alloc(unsigned int nr_pages,
                                                work_func_t complete);
 void cifs_writedata_release(struct kref *refcount);
-
+int open_query_close_cifs_symlink(const unsigned char *path, char *pbuf,
+                       unsigned int *pbytes_read, struct cifs_sb_info *cifs_sb,
+                       unsigned int xid);
 #endif                 /* _CIFSPROTO_H */
index fa68813..d67c550 100644 (file)
@@ -1675,7 +1675,8 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
                        if (string == NULL)
                                goto out_nomem;
 
-                       if (strnlen(string, 256) == 256) {
+                       if (strnlen(string, CIFS_MAX_DOMAINNAME_LEN)
+                                       == CIFS_MAX_DOMAINNAME_LEN) {
                                printk(KERN_WARNING "CIFS: domain name too"
                                                    " long\n");
                                goto cifs_parse_mount_err;
@@ -2276,8 +2277,8 @@ cifs_put_smb_ses(struct cifs_ses *ses)
 
 #ifdef CONFIG_KEYS
 
-/* strlen("cifs:a:") + INET6_ADDRSTRLEN + 1 */
-#define CIFSCREDS_DESC_SIZE (7 + INET6_ADDRSTRLEN + 1)
+/* strlen("cifs:a:") + CIFS_MAX_DOMAINNAME_LEN + 1 */
+#define CIFSCREDS_DESC_SIZE (7 + CIFS_MAX_DOMAINNAME_LEN + 1)
 
 /* Populate username and pw fields from keyring if possible */
 static int
index 1e57f36..7e36ae3 100644 (file)
@@ -647,6 +647,7 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush)
                                     oflags, &oplock, &cfile->fid.netfid, xid);
                if (rc == 0) {
                        cifs_dbg(FYI, "posix reopen succeeded\n");
+                       oparms.reconnect = true;
                        goto reopen_success;
                }
                /*
index b83c3f5..562044f 100644 (file)
@@ -305,67 +305,89 @@ CIFSCouldBeMFSymlink(const struct cifs_fattr *fattr)
 }
 
 int
-CIFSCheckMFSymlink(struct cifs_fattr *fattr,
-                  const unsigned char *path,
-                  struct cifs_sb_info *cifs_sb, unsigned int xid)
+open_query_close_cifs_symlink(const unsigned char *path, char *pbuf,
+                       unsigned int *pbytes_read, struct cifs_sb_info *cifs_sb,
+                       unsigned int xid)
 {
        int rc;
        int oplock = 0;
        __u16 netfid = 0;
        struct tcon_link *tlink;
-       struct cifs_tcon *pTcon;
+       struct cifs_tcon *ptcon;
        struct cifs_io_parms io_parms;
-       u8 *buf;
-       char *pbuf;
-       unsigned int bytes_read = 0;
        int buf_type = CIFS_NO_BUFFER;
-       unsigned int link_len = 0;
        FILE_ALL_INFO file_info;
 
-       if (!CIFSCouldBeMFSymlink(fattr))
-               /* it's not a symlink */
-               return 0;
-
        tlink = cifs_sb_tlink(cifs_sb);
        if (IS_ERR(tlink))
                return PTR_ERR(tlink);
-       pTcon = tlink_tcon(tlink);
+       ptcon = tlink_tcon(tlink);
 
-       rc = CIFSSMBOpen(xid, pTcon, path, FILE_OPEN, GENERIC_READ,
+       rc = CIFSSMBOpen(xid, ptcon, path, FILE_OPEN, GENERIC_READ,
                         CREATE_NOT_DIR, &netfid, &oplock, &file_info,
                         cifs_sb->local_nls,
                         cifs_sb->mnt_cifs_flags &
                                CIFS_MOUNT_MAP_SPECIAL_CHR);
-       if (rc != 0)
-               goto out;
+       if (rc != 0) {
+               cifs_put_tlink(tlink);
+               return rc;
+       }
 
        if (file_info.EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) {
-               CIFSSMBClose(xid, pTcon, netfid);
+               CIFSSMBClose(xid, ptcon, netfid);
+               cifs_put_tlink(tlink);
                /* it's not a symlink */
-               goto out;
+               return rc;
        }
 
-       buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL);
-       if (!buf) {
-               rc = -ENOMEM;
-               goto out;
-       }
-       pbuf = buf;
        io_parms.netfid = netfid;
        io_parms.pid = current->tgid;
-       io_parms.tcon = pTcon;
+       io_parms.tcon = ptcon;
        io_parms.offset = 0;
        io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;
 
-       rc = CIFSSMBRead(xid, &io_parms, &bytes_read, &pbuf, &buf_type);
-       CIFSSMBClose(xid, pTcon, netfid);
-       if (rc != 0) {
-               kfree(buf);
+       rc = CIFSSMBRead(xid, &io_parms, pbytes_read, &pbuf, &buf_type);
+       CIFSSMBClose(xid, ptcon, netfid);
+       cifs_put_tlink(tlink);
+       return rc;
+}
+
+
+int
+CIFSCheckMFSymlink(struct cifs_fattr *fattr,
+                  const unsigned char *path,
+                  struct cifs_sb_info *cifs_sb, unsigned int xid)
+{
+       int rc = 0;
+       u8 *buf = NULL;
+       unsigned int link_len = 0;
+       unsigned int bytes_read = 0;
+       struct cifs_tcon *ptcon;
+
+       if (!CIFSCouldBeMFSymlink(fattr))
+               /* it's not a symlink */
+               return 0;
+
+       buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL);
+       if (!buf) {
+               rc = -ENOMEM;
                goto out;
        }
 
+       ptcon = tlink_tcon(cifs_sb_tlink(cifs_sb));
+       if ((ptcon->ses) && (ptcon->ses->server->ops->query_mf_symlink))
+               rc = ptcon->ses->server->ops->query_mf_symlink(path, buf,
+                                                &bytes_read, cifs_sb, xid);
+       else
+               goto out;
+
+       if (rc != 0)
+               goto out;
+
+       if (bytes_read == 0) /* not a symlink */
+               goto out;
+
        rc = CIFSParseMFSymlink(buf, bytes_read, &link_len, NULL);
-       kfree(buf);
        if (rc == -EINVAL) {
                /* it's not a symlink */
                rc = 0;
@@ -381,7 +403,7 @@ CIFSCheckMFSymlink(struct cifs_fattr *fattr,
        fattr->cf_mode |= S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO;
        fattr->cf_dtype = DT_LNK;
 out:
-       cifs_put_tlink(tlink);
+       kfree(buf);
        return rc;
 }
 
index ab87784..69d2c82 100644 (file)
@@ -111,6 +111,14 @@ cifs_prime_dcache(struct dentry *parent, struct qstr *name,
                        return;
        }
 
+       /*
+        * If we know that the inode will need to be revalidated immediately,
+        * then don't create a new dentry for it. We'll end up doing an on
+        * the wire call either way and this spares us an invalidation.
+        */
+       if (fattr->cf_flags & CIFS_FATTR_NEED_REVAL)
+               return;
+
        dentry = d_alloc(parent, name);
        if (!dentry)
                return;
index 79358e3..08dd37b 100644 (file)
@@ -197,7 +197,7 @@ static void unicode_domain_string(char **pbcc_area, struct cifs_ses *ses,
                bytes_ret = 0;
        } else
                bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, ses->domainName,
-                                           256, nls_cp);
+                                           CIFS_MAX_DOMAINNAME_LEN, nls_cp);
        bcc_ptr += 2 * bytes_ret;
        bcc_ptr += 2;  /* account for null terminator */
 
@@ -255,8 +255,8 @@ static void ascii_ssetup_strings(char **pbcc_area, struct cifs_ses *ses,
 
        /* copy domain */
        if (ses->domainName != NULL) {
-               strncpy(bcc_ptr, ses->domainName, 256);
-               bcc_ptr += strnlen(ses->domainName, 256);
+               strncpy(bcc_ptr, ses->domainName, CIFS_MAX_DOMAINNAME_LEN);
+               bcc_ptr += strnlen(ses->domainName, CIFS_MAX_DOMAINNAME_LEN);
        } /* else we will send a null domain name
             so the server will default to its own domain */
        *bcc_ptr = 0;
index 6457690..6094397 100644 (file)
@@ -944,6 +944,7 @@ struct smb_version_operations smb1_operations = {
        .mand_lock = cifs_mand_lock,
        .mand_unlock_range = cifs_unlock_range,
        .push_mand_locks = cifs_push_mandatory_locks,
+       .query_mf_symlink = open_query_close_cifs_symlink,
 };
 
 struct smb_version_values smb1_values = {
index 301b191..4f2300d 100644 (file)
@@ -42,6 +42,7 @@
 static int
 smb2_crypto_shash_allocate(struct TCP_Server_Info *server)
 {
+       int rc;
        unsigned int size;
 
        if (server->secmech.sdeschmacsha256 != NULL)
@@ -50,7 +51,9 @@ smb2_crypto_shash_allocate(struct TCP_Server_Info *server)
        server->secmech.hmacsha256 = crypto_alloc_shash("hmac(sha256)", 0, 0);
        if (IS_ERR(server->secmech.hmacsha256)) {
                cifs_dbg(VFS, "could not allocate crypto hmacsha256\n");
-               return PTR_ERR(server->secmech.hmacsha256);
+               rc = PTR_ERR(server->secmech.hmacsha256);
+               server->secmech.hmacsha256 = NULL;
+               return rc;
        }
 
        size = sizeof(struct shash_desc) +
@@ -87,7 +90,9 @@ smb3_crypto_shash_allocate(struct TCP_Server_Info *server)
                server->secmech.sdeschmacsha256 = NULL;
                crypto_free_shash(server->secmech.hmacsha256);
                server->secmech.hmacsha256 = NULL;
-               return PTR_ERR(server->secmech.cmacaes);
+               rc = PTR_ERR(server->secmech.cmacaes);
+               server->secmech.cmacaes = NULL;
+               return rc;
        }
 
        size = sizeof(struct shash_desc) +
index 87bdb53..83cfb83 100644 (file)
@@ -2724,6 +2724,17 @@ char *dynamic_dname(struct dentry *dentry, char *buffer, int buflen,
        return memcpy(buffer, temp, sz);
 }
 
+char *simple_dname(struct dentry *dentry, char *buffer, int buflen)
+{
+       char *end = buffer + buflen;
+       /* these dentries are never renamed, so d_lock is not needed */
+       if (prepend(&end, &buflen, " (deleted)", 11) ||
+           prepend_name(&end, &buflen, &dentry->d_name) ||
+           prepend(&end, &buflen, "/", 1))  
+               end = ERR_PTR(-ENAMETOOLONG);
+       return end;  
+}
+
 /*
  * Write full pathname from the root of the filesystem into the buffer.
  */
index f3913eb..d15ccf2 100644 (file)
@@ -57,7 +57,7 @@ struct inode *efs_iget(struct super_block *super, unsigned long ino)
        struct inode *inode;
 
        inode = iget_locked(super, ino);
-       if (IS_ERR(inode))
+       if (!inode)
                return ERR_PTR(-ENOMEM);
        if (!(inode->i_state & I_NEW))
                return inode;
index 9c73def..fd774c7 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -608,7 +608,7 @@ static int shift_arg_pages(struct vm_area_struct *vma, unsigned long shift)
                return -ENOMEM;
 
        lru_add_drain();
-       tlb_gather_mmu(&tlb, mm, 0);
+       tlb_gather_mmu(&tlb, mm, old_start, old_end);
        if (new_end > old_start) {
                /*
                 * when the old and new regions overlap clear from new_end.
@@ -625,7 +625,7 @@ static int shift_arg_pages(struct vm_area_struct *vma, unsigned long shift)
                free_pgd_range(&tlb, old_start, old_end, new_end,
                        vma->vm_next ? vma->vm_next->vm_start : USER_PGTABLES_CEILING);
        }
-       tlb_finish_mmu(&tlb, new_end, old_end);
+       tlb_finish_mmu(&tlb, old_start, old_end);
 
        /*
         * Shrink the vma to just the new range.  Always succeeds.
index b577e45..0ab26fb 100644 (file)
@@ -2086,6 +2086,7 @@ extern int  ext4_sync_inode(handle_t *, struct inode *);
 extern void ext4_dirty_inode(struct inode *, int);
 extern int ext4_change_inode_journal_flag(struct inode *, int);
 extern int ext4_get_inode_loc(struct inode *, struct ext4_iloc *);
+extern int ext4_inode_attach_jinode(struct inode *inode);
 extern int ext4_can_truncate(struct inode *inode);
 extern void ext4_truncate(struct inode *);
 extern int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length);
index 72a3600..17ac112 100644 (file)
@@ -255,10 +255,10 @@ int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
        set_buffer_prio(bh);
        if (ext4_handle_valid(handle)) {
                err = jbd2_journal_dirty_metadata(handle, bh);
-               if (err) {
-                       /* Errors can only happen if there is a bug */
-                       handle->h_err = err;
-                       __ext4_journal_stop(where, line, handle);
+               /* Errors can only happen if there is a bug */
+               if (WARN_ON_ONCE(err)) {
+                       ext4_journal_abort_handle(where, line, __func__, bh,
+                                                 handle, err);
                }
        } else {
                if (inode)
index 6f4cc56..319c9d2 100644 (file)
@@ -219,7 +219,6 @@ static int ext4_file_open(struct inode * inode, struct file * filp)
 {
        struct super_block *sb = inode->i_sb;
        struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
-       struct ext4_inode_info *ei = EXT4_I(inode);
        struct vfsmount *mnt = filp->f_path.mnt;
        struct path path;
        char buf[64], *cp;
@@ -259,22 +258,10 @@ static int ext4_file_open(struct inode * inode, struct file * filp)
         * Set up the jbd2_inode if we are opening the inode for
         * writing and the journal is present
         */
-       if (sbi->s_journal && !ei->jinode && (filp->f_mode & FMODE_WRITE)) {
-               struct jbd2_inode *jinode = jbd2_alloc_inode(GFP_KERNEL);
-
-               spin_lock(&inode->i_lock);
-               if (!ei->jinode) {
-                       if (!jinode) {
-                               spin_unlock(&inode->i_lock);
-                               return -ENOMEM;
-                       }
-                       ei->jinode = jinode;
-                       jbd2_journal_init_jbd_inode(ei->jinode, inode);
-                       jinode = NULL;
-               }
-               spin_unlock(&inode->i_lock);
-               if (unlikely(jinode != NULL))
-                       jbd2_free_inode(jinode);
+       if (filp->f_mode & FMODE_WRITE) {
+               int ret = ext4_inode_attach_jinode(inode);
+               if (ret < 0)
+                       return ret;
        }
        return dquot_file_open(inode, filp);
 }
index dd32a2e..c2ca04e 100644 (file)
@@ -3533,6 +3533,18 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)
                   offset;
        }
 
+       if (offset & (sb->s_blocksize - 1) ||
+           (offset + length) & (sb->s_blocksize - 1)) {
+               /*
+                * Attach jinode to inode for jbd2 if we do any zeroing of
+                * partial block
+                */
+               ret = ext4_inode_attach_jinode(inode);
+               if (ret < 0)
+                       goto out_mutex;
+
+       }
+
        first_block_offset = round_up(offset, sb->s_blocksize);
        last_block_offset = round_down((offset + length), sb->s_blocksize) - 1;
 
@@ -3601,6 +3613,31 @@ out_mutex:
        return ret;
 }
 
+int ext4_inode_attach_jinode(struct inode *inode)
+{
+       struct ext4_inode_info *ei = EXT4_I(inode);
+       struct jbd2_inode *jinode;
+
+       if (ei->jinode || !EXT4_SB(inode->i_sb)->s_journal)
+               return 0;
+
+       jinode = jbd2_alloc_inode(GFP_KERNEL);
+       spin_lock(&inode->i_lock);
+       if (!ei->jinode) {
+               if (!jinode) {
+                       spin_unlock(&inode->i_lock);
+                       return -ENOMEM;
+               }
+               ei->jinode = jinode;
+               jbd2_journal_init_jbd_inode(ei->jinode, inode);
+               jinode = NULL;
+       }
+       spin_unlock(&inode->i_lock);
+       if (unlikely(jinode != NULL))
+               jbd2_free_inode(jinode);
+       return 0;
+}
+
 /*
  * ext4_truncate()
  *
@@ -3661,6 +3698,12 @@ void ext4_truncate(struct inode *inode)
                        return;
        }
 
+       /* If we zero-out tail of the page, we have to create jinode for jbd2 */
+       if (inode->i_size & (inode->i_sb->s_blocksize - 1)) {
+               if (ext4_inode_attach_jinode(inode) < 0)
+                       return;
+       }
+
        if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
                credits = ext4_writepage_trans_blocks(inode);
        else
index 9491ac0..c0427e2 100644 (file)
@@ -77,8 +77,10 @@ static void swap_inode_data(struct inode *inode1, struct inode *inode2)
        memswap(ei1->i_data, ei2->i_data, sizeof(ei1->i_data));
        memswap(&ei1->i_flags, &ei2->i_flags, sizeof(ei1->i_flags));
        memswap(&ei1->i_disksize, &ei2->i_disksize, sizeof(ei1->i_disksize));
-       memswap(&ei1->i_es_tree, &ei2->i_es_tree, sizeof(ei1->i_es_tree));
-       memswap(&ei1->i_es_lru_nr, &ei2->i_es_lru_nr, sizeof(ei1->i_es_lru_nr));
+       ext4_es_remove_extent(inode1, 0, EXT_MAX_BLOCKS);
+       ext4_es_remove_extent(inode2, 0, EXT_MAX_BLOCKS);
+       ext4_es_lru_del(inode1);
+       ext4_es_lru_del(inode2);
 
        isize = i_size_read(inode1);
        i_size_write(inode1, i_size_read(inode2));
index 36b141e..b59373b 100644 (file)
@@ -1359,7 +1359,7 @@ static const struct mount_opts {
        {Opt_delalloc, EXT4_MOUNT_DELALLOC,
         MOPT_EXT4_ONLY | MOPT_SET | MOPT_EXPLICIT},
        {Opt_nodelalloc, EXT4_MOUNT_DELALLOC,
-        MOPT_EXT4_ONLY | MOPT_CLEAR | MOPT_EXPLICIT},
+        MOPT_EXT4_ONLY | MOPT_CLEAR},
        {Opt_journal_checksum, EXT4_MOUNT_JOURNAL_CHECKSUM,
         MOPT_EXT4_ONLY | MOPT_SET},
        {Opt_journal_async_commit, (EXT4_MOUNT_JOURNAL_ASYNC_COMMIT |
@@ -3483,7 +3483,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
                }
                if (test_opt(sb, DIOREAD_NOLOCK)) {
                        ext4_msg(sb, KERN_ERR, "can't mount with "
-                                "both data=journal and delalloc");
+                                "both data=journal and dioread_nolock");
                        goto failed_mount;
                }
                if (test_opt(sb, DELALLOC))
@@ -4727,6 +4727,21 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
                goto restore_opts;
        }
 
+       if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) {
+               if (test_opt2(sb, EXPLICIT_DELALLOC)) {
+                       ext4_msg(sb, KERN_ERR, "can't mount with "
+                                "both data=journal and delalloc");
+                       err = -EINVAL;
+                       goto restore_opts;
+               }
+               if (test_opt(sb, DIOREAD_NOLOCK)) {
+                       ext4_msg(sb, KERN_ERR, "can't mount with "
+                                "both data=journal and dioread_nolock");
+                       err = -EINVAL;
+                       goto restore_opts;
+               }
+       }
+
        if (sbi->s_mount_flags & EXT4_MF_FS_ABORTED)
                ext4_abort(sb, "Abort forced by user");
 
index 9435384..544a809 100644 (file)
@@ -1838,14 +1838,14 @@ int __init gfs2_glock_init(void)
 
        glock_workqueue = alloc_workqueue("glock_workqueue", WQ_MEM_RECLAIM |
                                          WQ_HIGHPRI | WQ_FREEZABLE, 0);
-       if (IS_ERR(glock_workqueue))
-               return PTR_ERR(glock_workqueue);
+       if (!glock_workqueue)
+               return -ENOMEM;
        gfs2_delete_workqueue = alloc_workqueue("delete_workqueue",
                                                WQ_MEM_RECLAIM | WQ_FREEZABLE,
                                                0);
-       if (IS_ERR(gfs2_delete_workqueue)) {
+       if (!gfs2_delete_workqueue) {
                destroy_workqueue(glock_workqueue);
-               return PTR_ERR(gfs2_delete_workqueue);
+               return -ENOMEM;
        }
 
        register_shrinker(&glock_shrinker);
index 5f2e522..e2e0a90 100644 (file)
@@ -47,7 +47,8 @@ static void gfs2_ail_error(struct gfs2_glock *gl, const struct buffer_head *bh)
  * None of the buffers should be dirty, locked, or pinned.
  */
 
-static void __gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
+static void __gfs2_ail_flush(struct gfs2_glock *gl, bool fsync,
+                            unsigned int nr_revokes)
 {
        struct gfs2_sbd *sdp = gl->gl_sbd;
        struct list_head *head = &gl->gl_ail_list;
@@ -57,7 +58,9 @@ static void __gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
 
        gfs2_log_lock(sdp);
        spin_lock(&sdp->sd_ail_lock);
-       list_for_each_entry_safe(bd, tmp, head, bd_ail_gl_list) {
+       list_for_each_entry_safe_reverse(bd, tmp, head, bd_ail_gl_list) {
+               if (nr_revokes == 0)
+                       break;
                bh = bd->bd_bh;
                if (bh->b_state & b_state) {
                        if (fsync)
@@ -65,6 +68,7 @@ static void __gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
                        gfs2_ail_error(gl, bh);
                }
                gfs2_trans_add_revoke(sdp, bd);
+               nr_revokes--;
        }
        GLOCK_BUG_ON(gl, !fsync && atomic_read(&gl->gl_ail_count));
        spin_unlock(&sdp->sd_ail_lock);
@@ -91,7 +95,7 @@ static void gfs2_ail_empty_gl(struct gfs2_glock *gl)
        WARN_ON_ONCE(current->journal_info);
        current->journal_info = &tr;
 
-       __gfs2_ail_flush(gl, 0);
+       __gfs2_ail_flush(gl, 0, tr.tr_revokes);
 
        gfs2_trans_end(sdp);
        gfs2_log_flush(sdp, NULL);
@@ -101,15 +105,19 @@ void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
 {
        struct gfs2_sbd *sdp = gl->gl_sbd;
        unsigned int revokes = atomic_read(&gl->gl_ail_count);
+       unsigned int max_revokes = (sdp->sd_sb.sb_bsize - sizeof(struct gfs2_log_descriptor)) / sizeof(u64);
        int ret;
 
        if (!revokes)
                return;
 
-       ret = gfs2_trans_begin(sdp, 0, revokes);
+       while (revokes > max_revokes)
+               max_revokes += (sdp->sd_sb.sb_bsize - sizeof(struct gfs2_meta_header)) / sizeof(u64);
+
+       ret = gfs2_trans_begin(sdp, 0, max_revokes);
        if (ret)
                return;
-       __gfs2_ail_flush(gl, fsync);
+       __gfs2_ail_flush(gl, fsync, max_revokes);
        gfs2_trans_end(sdp);
        gfs2_log_flush(sdp, NULL);
 }
index bbb2715..64915ee 100644 (file)
@@ -594,7 +594,7 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
                }
                gfs2_glock_dq_uninit(ghs);
                if (IS_ERR(d))
-                       return PTR_RET(d);
+                       return PTR_ERR(d);
                return error;
        } else if (error != -ENOENT) {
                goto fail_gunlock;
@@ -1750,6 +1750,10 @@ static ssize_t gfs2_getxattr(struct dentry *dentry, const char *name,
        struct gfs2_holder gh;
        int ret;
 
+       /* For selinux during lookup */
+       if (gfs2_glock_is_locked_by_me(ip->i_gl))
+               return generic_getxattr(dentry, name, data, size);
+
        gfs2_holder_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &gh);
        ret = gfs2_glock_nq(&gh);
        if (ret == 0) {
index e04d0e0..7b0f504 100644 (file)
@@ -155,7 +155,7 @@ static int __init init_gfs2_fs(void)
                goto fail_wq;
 
        gfs2_control_wq = alloc_workqueue("gfs2_control",
-                              WQ_NON_REENTRANT | WQ_UNBOUND | WQ_FREEZABLE, 0);
+                                         WQ_UNBOUND | WQ_FREEZABLE, 0);
        if (!gfs2_control_wq)
                goto fail_recovery;
 
index a3f868a..d19b30a 100644 (file)
@@ -463,6 +463,14 @@ static struct inode *hugetlbfs_get_root(struct super_block *sb,
        return inode;
 }
 
+/*
+ * Hugetlbfs is not reclaimable; therefore its i_mmap_mutex will never
+ * be taken from reclaim -- unlike regular filesystems. This needs an
+ * annotation because huge_pmd_share() does an allocation under
+ * i_mmap_mutex.
+ */
+struct lock_class_key hugetlbfs_i_mmap_mutex_key;
+
 static struct inode *hugetlbfs_get_inode(struct super_block *sb,
                                        struct inode *dir,
                                        umode_t mode, dev_t dev)
@@ -474,6 +482,8 @@ static struct inode *hugetlbfs_get_inode(struct super_block *sb,
                struct hugetlbfs_inode_info *info;
                inode->i_ino = get_next_ino();
                inode_init_owner(inode, dir, mode);
+               lockdep_set_class(&inode->i_mapping->i_mmap_mutex,
+                               &hugetlbfs_i_mmap_mutex_key);
                inode->i_mapping->a_ops = &hugetlbfs_aops;
                inode->i_mapping->backing_dev_info =&hugetlbfs_backing_dev_info;
                inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
@@ -916,14 +926,8 @@ static int get_hstate_idx(int page_size_log)
        return h - hstates;
 }
 
-static char *hugetlb_dname(struct dentry *dentry, char *buffer, int buflen)
-{
-       return dynamic_dname(dentry, buffer, buflen, "/%s (deleted)",
-                               dentry->d_name.name);
-}
-
 static struct dentry_operations anon_ops = {
-       .d_dname = hugetlb_dname
+       .d_dname = simple_dname
 };
 
 /*
index 7b1ca9b..a45ba4f 100644 (file)
@@ -1429,7 +1429,7 @@ struct vfsmount *collect_mounts(struct path *path)
                         CL_COPY_ALL | CL_PRIVATE);
        namespace_unlock();
        if (IS_ERR(tree))
-               return NULL;
+               return ERR_CAST(tree);
        return &tree->mnt;
 }
 
index dc9a913..2d8be51 100644 (file)
@@ -345,8 +345,7 @@ static void nilfs_end_bio_write(struct bio *bio, int err)
 
        if (err == -EOPNOTSUPP) {
                set_bit(BIO_EOPNOTSUPP, &bio->bi_flags);
-               bio_put(bio);
-               /* to be detected by submit_seg_bio() */
+               /* to be detected by nilfs_segbuf_submit_bio() */
        }
 
        if (!uptodate)
@@ -377,12 +376,12 @@ static int nilfs_segbuf_submit_bio(struct nilfs_segment_buffer *segbuf,
        bio->bi_private = segbuf;
        bio_get(bio);
        submit_bio(mode, bio);
+       segbuf->sb_nbio++;
        if (bio_flagged(bio, BIO_EOPNOTSUPP)) {
                bio_put(bio);
                err = -EOPNOTSUPP;
                goto failed;
        }
-       segbuf->sb_nbio++;
        bio_put(bio);
 
        wi->bio = NULL;
index 79736a2..2abf97b 100644 (file)
@@ -1757,7 +1757,7 @@ try_again:
                goto out;
        } else if (ret == 1) {
                clusters_need = wc->w_clen;
-               ret = ocfs2_refcount_cow(inode, filp, di_bh,
+               ret = ocfs2_refcount_cow(inode, di_bh,
                                         wc->w_cpos, wc->w_clen, UINT_MAX);
                if (ret) {
                        mlog_errno(ret);
index eb760d8..30544ce 100644 (file)
@@ -2153,11 +2153,9 @@ int ocfs2_empty_dir(struct inode *inode)
 {
        int ret;
        struct ocfs2_empty_dir_priv priv = {
-               .ctx.actor = ocfs2_empty_dir_filldir
+               .ctx.actor = ocfs2_empty_dir_filldir,
        };
 
-       memset(&priv, 0, sizeof(priv));
-
        if (ocfs2_dir_indexed(inode)) {
                ret = ocfs2_empty_dir_dx(inode, &priv);
                if (ret)
index 41000f2..3261d71 100644 (file)
@@ -370,7 +370,7 @@ static int ocfs2_cow_file_pos(struct inode *inode,
        if (!(ext_flags & OCFS2_EXT_REFCOUNTED))
                goto out;
 
-       return ocfs2_refcount_cow(inode, NULL, fe_bh, cpos, 1, cpos+1);
+       return ocfs2_refcount_cow(inode, fe_bh, cpos, 1, cpos+1);
 
 out:
        return status;
@@ -899,7 +899,7 @@ static int ocfs2_zero_extend_get_range(struct inode *inode,
                zero_clusters = last_cpos - zero_cpos;
 
        if (needs_cow) {
-               rc = ocfs2_refcount_cow(inode, NULL, di_bh, zero_cpos,
+               rc = ocfs2_refcount_cow(inode, di_bh, zero_cpos,
                                        zero_clusters, UINT_MAX);
                if (rc) {
                        mlog_errno(rc);
@@ -2078,7 +2078,7 @@ static int ocfs2_prepare_inode_for_refcount(struct inode *inode,
 
        *meta_level = 1;
 
-       ret = ocfs2_refcount_cow(inode, file, di_bh, cpos, clusters, UINT_MAX);
+       ret = ocfs2_refcount_cow(inode, di_bh, cpos, clusters, UINT_MAX);
        if (ret)
                mlog_errno(ret);
 out:
index 96f9ac2..0a99273 100644 (file)
@@ -537,7 +537,7 @@ static inline int ocfs2_calc_extend_credits(struct super_block *sb,
        extent_blocks = 1 + 1 + le16_to_cpu(root_el->l_tree_depth);
 
        return bitmap_blocks + sysfile_bitmap_blocks + extent_blocks +
-              ocfs2_quota_trans_credits(sb) + bits_wanted;
+              ocfs2_quota_trans_credits(sb);
 }
 
 static inline int ocfs2_calc_symlink_credits(struct super_block *sb)
index f1fc172..452068b 100644 (file)
@@ -69,7 +69,7 @@ static int __ocfs2_move_extent(handle_t *handle,
        u64 ino = ocfs2_metadata_cache_owner(context->et.et_ci);
        u64 old_blkno = ocfs2_clusters_to_blocks(inode->i_sb, p_cpos);
 
-       ret = ocfs2_duplicate_clusters_by_page(handle, context->file, cpos,
+       ret = ocfs2_duplicate_clusters_by_page(handle, inode, cpos,
                                               p_cpos, new_p_cpos, len);
        if (ret) {
                mlog_errno(ret);
index 9f6b96a..a70d604 100644 (file)
@@ -49,7 +49,6 @@
 
 struct ocfs2_cow_context {
        struct inode *inode;
-       struct file *file;
        u32 cow_start;
        u32 cow_len;
        struct ocfs2_extent_tree data_et;
@@ -66,7 +65,7 @@ struct ocfs2_cow_context {
                            u32 *num_clusters,
                            unsigned int *extent_flags);
        int (*cow_duplicate_clusters)(handle_t *handle,
-                                     struct file *file,
+                                     struct inode *inode,
                                      u32 cpos, u32 old_cluster,
                                      u32 new_cluster, u32 new_len);
 };
@@ -2922,14 +2921,12 @@ static int ocfs2_clear_cow_buffer(handle_t *handle, struct buffer_head *bh)
 }
 
 int ocfs2_duplicate_clusters_by_page(handle_t *handle,
-                                    struct file *file,
+                                    struct inode *inode,
                                     u32 cpos, u32 old_cluster,
                                     u32 new_cluster, u32 new_len)
 {
        int ret = 0, partial;
-       struct inode *inode = file_inode(file);
-       struct ocfs2_caching_info *ci = INODE_CACHE(inode);
-       struct super_block *sb = ocfs2_metadata_cache_get_super(ci);
+       struct super_block *sb = inode->i_sb;
        u64 new_block = ocfs2_clusters_to_blocks(sb, new_cluster);
        struct page *page;
        pgoff_t page_index;
@@ -2978,13 +2975,6 @@ int ocfs2_duplicate_clusters_by_page(handle_t *handle,
                if (PAGE_CACHE_SIZE <= OCFS2_SB(sb)->s_clustersize)
                        BUG_ON(PageDirty(page));
 
-               if (PageReadahead(page)) {
-                       page_cache_async_readahead(mapping,
-                                                  &file->f_ra, file,
-                                                  page, page_index,
-                                                  readahead_pages);
-               }
-
                if (!PageUptodate(page)) {
                        ret = block_read_full_page(page, ocfs2_get_block);
                        if (ret) {
@@ -3004,7 +2994,8 @@ int ocfs2_duplicate_clusters_by_page(handle_t *handle,
                        }
                }
 
-               ocfs2_map_and_dirty_page(inode, handle, from, to,
+               ocfs2_map_and_dirty_page(inode,
+                                        handle, from, to,
                                         page, 0, &new_block);
                mark_page_accessed(page);
 unlock:
@@ -3020,12 +3011,11 @@ unlock:
 }
 
 int ocfs2_duplicate_clusters_by_jbd(handle_t *handle,
-                                   struct file *file,
+                                   struct inode *inode,
                                    u32 cpos, u32 old_cluster,
                                    u32 new_cluster, u32 new_len)
 {
        int ret = 0;
-       struct inode *inode = file_inode(file);
        struct super_block *sb = inode->i_sb;
        struct ocfs2_caching_info *ci = INODE_CACHE(inode);
        int i, blocks = ocfs2_clusters_to_blocks(sb, new_len);
@@ -3150,7 +3140,7 @@ static int ocfs2_replace_clusters(handle_t *handle,
 
        /*If the old clusters is unwritten, no need to duplicate. */
        if (!(ext_flags & OCFS2_EXT_UNWRITTEN)) {
-               ret = context->cow_duplicate_clusters(handle, context->file,
+               ret = context->cow_duplicate_clusters(handle, context->inode,
                                                      cpos, old, new, len);
                if (ret) {
                        mlog_errno(ret);
@@ -3428,35 +3418,12 @@ static int ocfs2_replace_cow(struct ocfs2_cow_context *context)
        return ret;
 }
 
-static void ocfs2_readahead_for_cow(struct inode *inode,
-                                   struct file *file,
-                                   u32 start, u32 len)
-{
-       struct address_space *mapping;
-       pgoff_t index;
-       unsigned long num_pages;
-       int cs_bits = OCFS2_SB(inode->i_sb)->s_clustersize_bits;
-
-       if (!file)
-               return;
-
-       mapping = file->f_mapping;
-       num_pages = (len << cs_bits) >> PAGE_CACHE_SHIFT;
-       if (!num_pages)
-               num_pages = 1;
-
-       index = ((loff_t)start << cs_bits) >> PAGE_CACHE_SHIFT;
-       page_cache_sync_readahead(mapping, &file->f_ra, file,
-                                 index, num_pages);
-}
-
 /*
  * Starting at cpos, try to CoW write_len clusters.  Don't CoW
  * past max_cpos.  This will stop when it runs into a hole or an
  * unrefcounted extent.
  */
 static int ocfs2_refcount_cow_hunk(struct inode *inode,
-                                  struct file *file,
                                   struct buffer_head *di_bh,
                                   u32 cpos, u32 write_len, u32 max_cpos)
 {
@@ -3485,8 +3452,6 @@ static int ocfs2_refcount_cow_hunk(struct inode *inode,
 
        BUG_ON(cow_len == 0);
 
-       ocfs2_readahead_for_cow(inode, file, cow_start, cow_len);
-
        context = kzalloc(sizeof(struct ocfs2_cow_context), GFP_NOFS);
        if (!context) {
                ret = -ENOMEM;
@@ -3508,7 +3473,6 @@ static int ocfs2_refcount_cow_hunk(struct inode *inode,
        context->ref_root_bh = ref_root_bh;
        context->cow_duplicate_clusters = ocfs2_duplicate_clusters_by_page;
        context->get_clusters = ocfs2_di_get_clusters;
-       context->file = file;
 
        ocfs2_init_dinode_extent_tree(&context->data_et,
                                      INODE_CACHE(inode), di_bh);
@@ -3537,7 +3501,6 @@ out:
  * clusters between cpos and cpos+write_len are safe to modify.
  */
 int ocfs2_refcount_cow(struct inode *inode,
-                      struct file *file,
                       struct buffer_head *di_bh,
                       u32 cpos, u32 write_len, u32 max_cpos)
 {
@@ -3557,7 +3520,7 @@ int ocfs2_refcount_cow(struct inode *inode,
                        num_clusters = write_len;
 
                if (ext_flags & OCFS2_EXT_REFCOUNTED) {
-                       ret = ocfs2_refcount_cow_hunk(inode, file, di_bh, cpos,
+                       ret = ocfs2_refcount_cow_hunk(inode, di_bh, cpos,
                                                      num_clusters, max_cpos);
                        if (ret) {
                                mlog_errno(ret);
index 7754608..6422bbc 100644 (file)
@@ -53,7 +53,7 @@ int ocfs2_prepare_refcount_change_for_del(struct inode *inode,
                                          int *credits,
                                          int *ref_blocks);
 int ocfs2_refcount_cow(struct inode *inode,
-                      struct file *filep, struct buffer_head *di_bh,
+                      struct buffer_head *di_bh,
                       u32 cpos, u32 write_len, u32 max_cpos);
 
 typedef int (ocfs2_post_refcount_func)(struct inode *inode,
@@ -85,11 +85,11 @@ int ocfs2_refcount_cow_xattr(struct inode *inode,
                             u32 cpos, u32 write_len,
                             struct ocfs2_post_refcount *post);
 int ocfs2_duplicate_clusters_by_page(handle_t *handle,
-                                    struct file *file,
+                                    struct inode *inode,
                                     u32 cpos, u32 old_cluster,
                                     u32 new_cluster, u32 new_len);
 int ocfs2_duplicate_clusters_by_jbd(handle_t *handle,
-                                   struct file *file,
+                                   struct inode *inode,
                                    u32 cpos, u32 old_cluster,
                                    u32 new_cluster, u32 new_len);
 int ocfs2_cow_sync_writeback(struct super_block *sb,
index 75f2890..0ff80f9 100644 (file)
@@ -228,8 +228,6 @@ static int proc_readfd_common(struct file *file, struct dir_context *ctx,
        if (!p)
                return -ENOENT;
 
-       if (!dir_emit_dots(file, ctx))
-               goto out;
        if (!dir_emit_dots(file, ctx))
                goto out;
        files = get_files_struct(p);
index 94441a4..737e156 100644 (file)
@@ -271,7 +271,7 @@ int proc_readdir_de(struct proc_dir_entry *de, struct file *file,
                de = next;
        } while (de);
        spin_unlock(&proc_subdir_lock);
-       return 0;
+       return 1;
 }
 
 int proc_readdir(struct file *file, struct dir_context *ctx)
index 229e366..e0a790d 100644 (file)
@@ -205,7 +205,9 @@ static struct dentry *proc_root_lookup(struct inode * dir, struct dentry * dentr
 static int proc_root_readdir(struct file *file, struct dir_context *ctx)
 {
        if (ctx->pos < FIRST_PROCESS_ENTRY) {
-               proc_readdir(file, ctx);
+               int error = proc_readdir(file, ctx);
+               if (unlikely(error <= 0))
+                       return error;
                ctx->pos = FIRST_PROCESS_ENTRY;
        }
 
index dbf61f6..107d026 100644 (file)
@@ -730,8 +730,16 @@ static inline void clear_soft_dirty(struct vm_area_struct *vma,
         * of how soft-dirty works.
         */
        pte_t ptent = *pte;
-       ptent = pte_wrprotect(ptent);
-       ptent = pte_clear_flags(ptent, _PAGE_SOFT_DIRTY);
+
+       if (pte_present(ptent)) {
+               ptent = pte_wrprotect(ptent);
+               ptent = pte_clear_flags(ptent, _PAGE_SOFT_DIRTY);
+       } else if (is_swap_pte(ptent)) {
+               ptent = pte_swp_clear_soft_dirty(ptent);
+       } else if (pte_file(ptent)) {
+               ptent = pte_file_clear_soft_dirty(ptent);
+       }
+
        set_pte_at(vma->vm_mm, addr, pte, ptent);
 #endif
 }
@@ -752,14 +760,15 @@ static int clear_refs_pte_range(pmd_t *pmd, unsigned long addr,
        pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
        for (; addr != end; pte++, addr += PAGE_SIZE) {
                ptent = *pte;
-               if (!pte_present(ptent))
-                       continue;
 
                if (cp->type == CLEAR_REFS_SOFT_DIRTY) {
                        clear_soft_dirty(vma, addr, pte);
                        continue;
                }
 
+               if (!pte_present(ptent))
+                       continue;
+
                page = vm_normal_page(vma, addr, ptent);
                if (!page)
                        continue;
@@ -859,7 +868,7 @@ typedef struct {
 } pagemap_entry_t;
 
 struct pagemapread {
-       int pos, len;
+       int pos, len;           /* units: PM_ENTRY_BYTES, not bytes */
        pagemap_entry_t *buffer;
        bool v2;
 };
@@ -867,7 +876,7 @@ struct pagemapread {
 #define PAGEMAP_WALK_SIZE      (PMD_SIZE)
 #define PAGEMAP_WALK_MASK      (PMD_MASK)
 
-#define PM_ENTRY_BYTES      sizeof(u64)
+#define PM_ENTRY_BYTES      sizeof(pagemap_entry_t)
 #define PM_STATUS_BITS      3
 #define PM_STATUS_OFFSET    (64 - PM_STATUS_BITS)
 #define PM_STATUS_MASK      (((1LL << PM_STATUS_BITS) - 1) << PM_STATUS_OFFSET)
@@ -930,8 +939,10 @@ static void pte_to_pagemap_entry(pagemap_entry_t *pme, struct pagemapread *pm,
                flags = PM_PRESENT;
                page = vm_normal_page(vma, addr, pte);
        } else if (is_swap_pte(pte)) {
-               swp_entry_t entry = pte_to_swp_entry(pte);
-
+               swp_entry_t entry;
+               if (pte_swp_soft_dirty(pte))
+                       flags2 |= __PM_SOFT_DIRTY;
+               entry = pte_to_swp_entry(pte);
                frame = swp_type(entry) |
                        (swp_offset(entry) << MAX_SWAPFILES_SHIFT);
                flags = PM_SWAP;
@@ -1116,8 +1127,8 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
                goto out_task;
 
        pm.v2 = soft_dirty_cleared;
-       pm.len = PM_ENTRY_BYTES * (PAGEMAP_WALK_SIZE >> PAGE_SHIFT);
-       pm.buffer = kmalloc(pm.len, GFP_TEMPORARY);
+       pm.len = (PAGEMAP_WALK_SIZE >> PAGE_SHIFT);
+       pm.buffer = kmalloc(pm.len * PM_ENTRY_BYTES, GFP_TEMPORARY);
        ret = -ENOMEM;
        if (!pm.buffer)
                goto out_task;
index 2f47ade..0807ddf 100644 (file)
@@ -417,6 +417,36 @@ static inline pmd_t pmd_mksoft_dirty(pmd_t pmd)
 {
        return pmd;
 }
+
+static inline pte_t pte_swp_mksoft_dirty(pte_t pte)
+{
+       return pte;
+}
+
+static inline int pte_swp_soft_dirty(pte_t pte)
+{
+       return 0;
+}
+
+static inline pte_t pte_swp_clear_soft_dirty(pte_t pte)
+{
+       return pte;
+}
+
+static inline pte_t pte_file_clear_soft_dirty(pte_t pte)
+{
+       return pte;
+}
+
+static inline pte_t pte_file_mksoft_dirty(pte_t pte)
+{
+       return pte;
+}
+
+static inline int pte_file_soft_dirty(pte_t pte)
+{
+       return 0;
+}
 #endif
 
 #ifndef __HAVE_PFNMAP_TRACKING
index 13821c3..5672d7e 100644 (file)
@@ -112,7 +112,7 @@ struct mmu_gather {
 
 #define HAVE_GENERIC_MMU_GATHER
 
-void tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, bool fullmm);
+void tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned long start, unsigned long end);
 void tlb_flush_mmu(struct mmu_gather *tlb);
 void tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start,
                                                        unsigned long end);
index b90337c..4a12532 100644 (file)
@@ -336,6 +336,7 @@ extern int d_validate(struct dentry *, struct dentry *);
  * helper function for dentry_operations.d_dname() members
  */
 extern char *dynamic_dname(struct dentry *, char *, int, const char *, ...);
+extern char *simple_dname(struct dentry *, char *, int);
 
 extern char *__d_path(const struct path *, const struct path *, char *, int);
 extern char *d_absolute_path(const struct path *, char *, int);
index b99cd23..79640e0 100644 (file)
@@ -5,45 +5,13 @@
 
 #include <linux/bitmap.h>
 #include <linux/if.h>
+#include <linux/ip.h>
 #include <linux/netdevice.h>
 #include <linux/rcupdate.h>
 #include <linux/timer.h>
 #include <linux/sysctl.h>
 #include <linux/rtnetlink.h>
 
-enum
-{
-       IPV4_DEVCONF_FORWARDING=1,
-       IPV4_DEVCONF_MC_FORWARDING,
-       IPV4_DEVCONF_PROXY_ARP,
-       IPV4_DEVCONF_ACCEPT_REDIRECTS,
-       IPV4_DEVCONF_SECURE_REDIRECTS,
-       IPV4_DEVCONF_SEND_REDIRECTS,
-       IPV4_DEVCONF_SHARED_MEDIA,
-       IPV4_DEVCONF_RP_FILTER,
-       IPV4_DEVCONF_ACCEPT_SOURCE_ROUTE,
-       IPV4_DEVCONF_BOOTP_RELAY,
-       IPV4_DEVCONF_LOG_MARTIANS,
-       IPV4_DEVCONF_TAG,
-       IPV4_DEVCONF_ARPFILTER,
-       IPV4_DEVCONF_MEDIUM_ID,
-       IPV4_DEVCONF_NOXFRM,
-       IPV4_DEVCONF_NOPOLICY,
-       IPV4_DEVCONF_FORCE_IGMP_VERSION,
-       IPV4_DEVCONF_ARP_ANNOUNCE,
-       IPV4_DEVCONF_ARP_IGNORE,
-       IPV4_DEVCONF_PROMOTE_SECONDARIES,
-       IPV4_DEVCONF_ARP_ACCEPT,
-       IPV4_DEVCONF_ARP_NOTIFY,
-       IPV4_DEVCONF_ACCEPT_LOCAL,
-       IPV4_DEVCONF_SRC_VMARK,
-       IPV4_DEVCONF_PROXY_ARP_PVLAN,
-       IPV4_DEVCONF_ROUTE_LOCALNET,
-       __IPV4_DEVCONF_MAX
-};
-
-#define IPV4_DEVCONF_MAX (__IPV4_DEVCONF_MAX - 1)
-
 struct ipv4_devconf {
        void    *sysctl;
        int     data[IPV4_DEVCONF_MAX];
index 850e95b..b8b7dc7 100644 (file)
@@ -101,6 +101,7 @@ struct inet6_skb_parm {
 #define IP6SKB_FORWARDED       2
 #define IP6SKB_REROUTED                4
 #define IP6SKB_ROUTERALERT     8
+#define IP6SKB_FRAGMENTED      16
 };
 
 #define IP6CB(skb)     ((struct inet6_skb_parm*)((skb)->cb))
index 737685e..68029b3 100644 (file)
@@ -309,21 +309,20 @@ struct mlx5_hca_cap {
        __be16  max_desc_sz_rq;
        u8      rsvd21[2];
        __be16  max_desc_sz_sq_dc;
-       u8      rsvd22[4];
-       __be16  max_qp_mcg;
-       u8      rsvd23;
+       __be32  max_qp_mcg;
+       u8      rsvd22[3];
        u8      log_max_mcg;
-       u8      rsvd24;
+       u8      rsvd23;
        u8      log_max_pd;
-       u8      rsvd25;
+       u8      rsvd24;
        u8      log_max_xrcd;
-       u8      rsvd26[42];
+       u8      rsvd25[42];
        __be16  log_uar_page_sz;
-       u8      rsvd27[28];
+       u8      rsvd26[28];
        u8      log_msx_atomic_size_qp;
-       u8      rsvd28[2];
+       u8      rsvd27[2];
        u8      log_msx_atomic_size_dc;
-       u8      rsvd29[76];
+       u8      rsvd28[76];
 };
 
 
@@ -472,9 +471,8 @@ struct mlx5_eqe_cmd {
 struct mlx5_eqe_page_req {
        u8              rsvd0[2];
        __be16          func_id;
-       u8              rsvd1[2];
-       __be16          num_pages;
-       __be32          rsvd2[5];
+       __be32          num_pages;
+       __be32          rsvd1[5];
 };
 
 union ev_data {
index 2aa258b..8888381 100644 (file)
@@ -358,7 +358,7 @@ struct mlx5_caps {
        u32     reserved_lkey;
        u8      local_ca_ack_delay;
        u8      log_max_mcg;
-       u16     max_qp_mcg;
+       u32     max_qp_mcg;
        int     min_page_sz;
 };
 
@@ -691,7 +691,7 @@ void mlx5_pagealloc_cleanup(struct mlx5_core_dev *dev);
 int mlx5_pagealloc_start(struct mlx5_core_dev *dev);
 void mlx5_pagealloc_stop(struct mlx5_core_dev *dev);
 void mlx5_core_req_pages_handler(struct mlx5_core_dev *dev, u16 func_id,
-                                s16 npages);
+                                s32 npages);
 int mlx5_satisfy_startup_pages(struct mlx5_core_dev *dev, int boot);
 int mlx5_reclaim_startup_pages(struct mlx5_core_dev *dev);
 void mlx5_register_debugfs(void);
@@ -731,9 +731,6 @@ void mlx5_cq_debugfs_cleanup(struct mlx5_core_dev *dev);
 int mlx5_db_alloc(struct mlx5_core_dev *dev, struct mlx5_db *db);
 void mlx5_db_free(struct mlx5_core_dev *dev, struct mlx5_db *db);
 
-typedef void (*health_handler_t)(struct pci_dev *pdev, struct health_buffer __iomem *buf, int size);
-int mlx5_register_health_report_handler(health_handler_t handler);
-void mlx5_unregister_health_report_handler(void);
 const char *mlx5_command_str(int command);
 int mlx5_cmdif_debugfs_init(struct mlx5_core_dev *dev);
 void mlx5_cmdif_debugfs_cleanup(struct mlx5_core_dev *dev);
index fb425aa..faf4b7c 100644 (file)
@@ -332,6 +332,7 @@ struct mm_struct {
                                unsigned long pgoff, unsigned long flags);
 #endif
        unsigned long mmap_base;                /* base of mmap area */
+       unsigned long mmap_legacy_base;         /* base of mmap area in bottom-up allocations */
        unsigned long task_size;                /* size of task vm space */
        unsigned long highest_vm_end;           /* highest vma end address */
        pgd_t * pgd;
diff --git a/include/linux/platform_data/efm32-spi.h b/include/linux/platform_data/efm32-spi.h
new file mode 100644 (file)
index 0000000..31b19ca
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef __LINUX_PLATFORM_DATA_EFM32_SPI_H__
+#define __LINUX_PLATFORM_DATA_EFM32_SPI_H__
+
+#include <linux/types.h>
+
+/**
+ * struct efm32_spi_pdata
+ * @location: pinmux location for the I/O pins (to be written to the ROUTE
+ *     register)
+ */
+struct efm32_spi_pdata {
+       u8 location;
+};
+#endif /* ifndef __LINUX_PLATFORM_DATA_EFM32_SPI_H__ */
index d722490..078066d 100644 (file)
@@ -1532,6 +1532,8 @@ static inline pid_t task_pgrp_nr(struct task_struct *tsk)
  * Test if a process is not yet dead (at most zombie state)
  * If pid_alive fails, then pointers within the task structure
  * can be stale and must not be dereferenced.
+ *
+ * Return: 1 if the process is alive. 0 otherwise.
  */
 static inline int pid_alive(struct task_struct *p)
 {
@@ -1543,6 +1545,8 @@ static inline int pid_alive(struct task_struct *p)
  * @tsk: Task structure to be checked.
  *
  * Check if a task structure is the first user space task the kernel created.
+ *
+ * Return: 1 if the task structure is init. 0 otherwise.
  */
 static inline int is_global_init(struct task_struct *tsk)
 {
@@ -1894,6 +1898,8 @@ extern struct task_struct *idle_task(int cpu);
 /**
  * is_idle_task - is the specified task an idle task?
  * @p: the task in question.
+ *
+ * Return: 1 if @p is an idle task. 0 otherwise.
  */
 static inline bool is_idle_task(const struct task_struct *p)
 {
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 7d537ce..75f3494 100644 (file)
@@ -117,9 +117,17 @@ do {                                                               \
 #endif /*arch_spin_is_contended*/
 #endif
 
-/* The lock does not imply full memory barrier. */
-#ifndef ARCH_HAS_SMP_MB_AFTER_LOCK
-static inline void smp_mb__after_lock(void) { smp_mb(); }
+/*
+ * Despite its name it doesn't necessarily has to be a full barrier.
+ * It should only guarantee that a STORE before the critical section
+ * can not be reordered with a LOAD inside this section.
+ * spin_lock() is the one-way barrier, this LOAD can not escape out
+ * of the region. So the default implementation simply ensures that
+ * a STORE can not move into the critical section, smp_wmb() should
+ * serialize it with another STORE done by spin_lock().
+ */
+#ifndef smp_mb__before_spinlock
+#define smp_mb__before_spinlock()      smp_wmb()
 #endif
 
 /**
index c5fd30d..8d4fa82 100644 (file)
@@ -67,6 +67,8 @@ static inline swp_entry_t pte_to_swp_entry(pte_t pte)
        swp_entry_t arch_entry;
 
        BUG_ON(pte_file(pte));
+       if (pte_swp_soft_dirty(pte))
+               pte = pte_swp_clear_soft_dirty(pte);
        arch_entry = __pte_to_swp_entry(pte);
        return swp_entry(__swp_type(arch_entry), __swp_offset(arch_entry));
 }
index 4147d70..84662ec 100644 (file)
@@ -802,9 +802,14 @@ asmlinkage long sys_vfork(void);
 asmlinkage long sys_clone(unsigned long, unsigned long, int __user *, int,
               int __user *);
 #else
+#ifdef CONFIG_CLONE_BACKWARDS3
+asmlinkage long sys_clone(unsigned long, unsigned long, int, int __user *,
+                         int __user *, int);
+#else
 asmlinkage long sys_clone(unsigned long, unsigned long, int __user *,
               int __user *, int);
 #endif
+#endif
 
 asmlinkage long sys_execve(const char __user *filename,
                const char __user *const __user *argv,
index f487a47..a67fc16 100644 (file)
@@ -811,6 +811,63 @@ do {                                                                       \
        __ret;                                                          \
 })
 
+#define __wait_event_interruptible_lock_irq_timeout(wq, condition,     \
+                                                   lock, ret)          \
+do {                                                                   \
+       DEFINE_WAIT(__wait);                                            \
+                                                                       \
+       for (;;) {                                                      \
+               prepare_to_wait(&wq, &__wait, TASK_INTERRUPTIBLE);      \
+               if (condition)                                          \
+                       break;                                          \
+               if (signal_pending(current)) {                          \
+                       ret = -ERESTARTSYS;                             \
+                       break;                                          \
+               }                                                       \
+               spin_unlock_irq(&lock);                                 \
+               ret = schedule_timeout(ret);                            \
+               spin_lock_irq(&lock);                                   \
+               if (!ret)                                               \
+                       break;                                          \
+       }                                                               \
+       finish_wait(&wq, &__wait);                                      \
+} while (0)
+
+/**
+ * wait_event_interruptible_lock_irq_timeout - sleep until a condition gets true or a timeout elapses.
+ *             The condition is checked under the lock. This is expected
+ *             to be called with the lock taken.
+ * @wq: the waitqueue to wait on
+ * @condition: a C expression for the event to wait for
+ * @lock: a locked spinlock_t, which will be released before schedule()
+ *       and reacquired afterwards.
+ * @timeout: timeout, in jiffies
+ *
+ * The process is put to sleep (TASK_INTERRUPTIBLE) until the
+ * @condition evaluates to true or signal is received. The @condition is
+ * checked each time the waitqueue @wq is woken up.
+ *
+ * wake_up() has to be called after changing any variable that could
+ * change the result of the wait condition.
+ *
+ * This is supposed to be called while holding the lock. The lock is
+ * dropped before going to sleep and is reacquired afterwards.
+ *
+ * The function returns 0 if the @timeout elapsed, -ERESTARTSYS if it
+ * was interrupted by a signal, and the remaining jiffies otherwise
+ * if the condition evaluated to true before the timeout elapsed.
+ */
+#define wait_event_interruptible_lock_irq_timeout(wq, condition, lock, \
+                                                 timeout)              \
+({                                                                     \
+       int __ret = timeout;                                            \
+                                                                       \
+       if (!(condition))                                               \
+               __wait_event_interruptible_lock_irq_timeout(            \
+                                       wq, condition, lock, __ret);    \
+       __ret;                                                          \
+})
+
 
 /*
  * These are the old interfaces to sleep waiting for an event.
index f18b919..8a358a2 100644 (file)
@@ -122,7 +122,7 @@ static inline bool sk_busy_loop(struct sock *sk, int nonblock)
                if (rc > 0)
                        /* local bh are disabled so it is ok to use _BH */
                        NET_ADD_STATS_BH(sock_net(sk),
-                                        LINUX_MIB_LOWLATENCYRXPACKETS, rc);
+                                        LINUX_MIB_BUSYPOLLRXPACKETS, rc);
 
        } while (!nonblock && skb_queue_empty(&sk->sk_receive_queue) &&
                 !need_resched() && !busy_loop_timeout(end_time));
@@ -162,11 +162,6 @@ static inline bool sk_can_busy_loop(struct sock *sk)
        return false;
 }
 
-static inline bool sk_busy_poll(struct sock *sk, int nonblock)
-{
-       return false;
-}
-
 static inline void skb_mark_napi_id(struct sk_buff *skb,
                                    struct napi_struct *napi)
 {
index 260f83f..f667248 100644 (file)
@@ -135,6 +135,8 @@ extern void ip6_update_pmtu(struct sk_buff *skb, struct net *net, __be32 mtu,
 extern void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk,
                               __be32 mtu);
 extern void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark);
+extern void ip6_redirect_no_header(struct sk_buff *skb, struct net *net, int oif,
+                                  u32 mark);
 extern void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk);
 
 struct netlink_callback;
index 781b3cf..a354db5 100644 (file)
@@ -145,20 +145,6 @@ static inline u8 ip_tunnel_ecn_encap(u8 tos, const struct iphdr *iph,
        return INET_ECN_encapsulate(tos, inner);
 }
 
-static inline void tunnel_ip_select_ident(struct sk_buff *skb,
-                                         const struct iphdr  *old_iph,
-                                         struct dst_entry *dst)
-{
-       struct iphdr *iph = ip_hdr(skb);
-
-       /* Use inner packet iph-id if possible. */
-       if (skb->protocol == htons(ETH_P_IP) && old_iph->id)
-               iph->id = old_iph->id;
-       else
-               __ip_select_ident(iph, dst,
-                                 (skb_shinfo(skb)->gso_segs ?: 1) - 1);
-}
-
 int iptunnel_pull_header(struct sk_buff *skb, int hdr_len, __be16 inner_proto);
 int iptunnel_xmit(struct net *net, struct rtable *rt,
                  struct sk_buff *skb,
index 6eab633..e5ae0c5 100644 (file)
@@ -683,13 +683,19 @@ struct psched_ratecfg {
        u64     rate_bytes_ps; /* bytes per second */
        u32     mult;
        u16     overhead;
+       u8      linklayer;
        u8      shift;
 };
 
 static inline u64 psched_l2t_ns(const struct psched_ratecfg *r,
                                unsigned int len)
 {
-       return ((u64)(len + r->overhead) * r->mult) >> r->shift;
+       len += r->overhead;
+
+       if (unlikely(r->linklayer == TC_LINKLAYER_ATM))
+               return ((u64)(DIV_ROUND_UP(len,48)*53) * r->mult) >> r->shift;
+
+       return ((u64)len * r->mult) >> r->shift;
 }
 
 extern void psched_ratecfg_precompute(struct psched_ratecfg *r, const struct tc_ratespec *conf);
@@ -700,6 +706,7 @@ static inline void psched_ratecfg_getrate(struct tc_ratespec *res,
        memset(res, 0, sizeof(*res));
        res->rate = r->rate_bytes_ps;
        res->overhead = r->overhead;
+       res->linklayer = (r->linklayer & TC_LINKLAYER_MASK);
 }
 
 #endif
index 6cf06bf..2fee45b 100644 (file)
@@ -133,4 +133,38 @@ struct ip_beet_phdr {
        __u8 reserved;
 };
 
+/* index values for the variables in ipv4_devconf */
+enum
+{
+       IPV4_DEVCONF_FORWARDING=1,
+       IPV4_DEVCONF_MC_FORWARDING,
+       IPV4_DEVCONF_PROXY_ARP,
+       IPV4_DEVCONF_ACCEPT_REDIRECTS,
+       IPV4_DEVCONF_SECURE_REDIRECTS,
+       IPV4_DEVCONF_SEND_REDIRECTS,
+       IPV4_DEVCONF_SHARED_MEDIA,
+       IPV4_DEVCONF_RP_FILTER,
+       IPV4_DEVCONF_ACCEPT_SOURCE_ROUTE,
+       IPV4_DEVCONF_BOOTP_RELAY,
+       IPV4_DEVCONF_LOG_MARTIANS,
+       IPV4_DEVCONF_TAG,
+       IPV4_DEVCONF_ARPFILTER,
+       IPV4_DEVCONF_MEDIUM_ID,
+       IPV4_DEVCONF_NOXFRM,
+       IPV4_DEVCONF_NOPOLICY,
+       IPV4_DEVCONF_FORCE_IGMP_VERSION,
+       IPV4_DEVCONF_ARP_ANNOUNCE,
+       IPV4_DEVCONF_ARP_IGNORE,
+       IPV4_DEVCONF_PROMOTE_SECONDARIES,
+       IPV4_DEVCONF_ARP_ACCEPT,
+       IPV4_DEVCONF_ARP_NOTIFY,
+       IPV4_DEVCONF_ACCEPT_LOCAL,
+       IPV4_DEVCONF_SRC_VMARK,
+       IPV4_DEVCONF_PROXY_ARP_PVLAN,
+       IPV4_DEVCONF_ROUTE_LOCALNET,
+       __IPV4_DEVCONF_MAX
+};
+
+#define IPV4_DEVCONF_MAX (__IPV4_DEVCONF_MAX - 1)
+
 #endif /* _UAPI_LINUX_IP_H */
index dbd71b0..09d62b9 100644 (file)
@@ -73,9 +73,17 @@ struct tc_estimator {
 #define TC_H_ROOT      (0xFFFFFFFFU)
 #define TC_H_INGRESS    (0xFFFFFFF1U)
 
+/* Need to corrospond to iproute2 tc/tc_core.h "enum link_layer" */
+enum tc_link_layer {
+       TC_LINKLAYER_UNAWARE, /* Indicate unaware old iproute2 util */
+       TC_LINKLAYER_ETHERNET,
+       TC_LINKLAYER_ATM,
+};
+#define TC_LINKLAYER_MASK 0x0F /* limit use to lower 4 bits */
+
 struct tc_ratespec {
        unsigned char   cell_log;
-       unsigned char   __reserved;
+       __u8            linklayer; /* lower 4 bits */
        unsigned short  overhead;
        short           cell_align;
        unsigned short  mpu;
index af0a674..a1356d3 100644 (file)
@@ -253,7 +253,7 @@ enum
        LINUX_MIB_TCPFASTOPENLISTENOVERFLOW,    /* TCPFastOpenListenOverflow */
        LINUX_MIB_TCPFASTOPENCOOKIEREQD,        /* TCPFastOpenCookieReqd */
        LINUX_MIB_TCPSPURIOUS_RTX_HOSTQUEUES, /* TCPSpuriousRtxHostQueues */
-       LINUX_MIB_LOWLATENCYRXPACKETS,          /* LowLatencyRxPackets */
+       LINUX_MIB_BUSYPOLLRXPACKETS,            /* BusyPollRxPackets */
        __LINUX_MIB_MAX
 };
 
index 247084b..fed81b5 100644 (file)
@@ -955,7 +955,7 @@ config MEMCG_SWAP_ENABLED
          Memory Resource Controller Swap Extension comes with its price in
          a bigger memory consumption. General purpose distribution kernels
          which want to enable the feature but keep it disabled by default
-         and let the user enable it by swapaccount boot command line
+         and let the user enable it by swapaccount=1 boot command line
          parameter should have this option unselected.
          For those who want to have the feature enabled by default should
          select this option (if, for some reason, they need to disable it
index e565778..ea1966d 100644 (file)
@@ -475,13 +475,17 @@ static int validate_change(const struct cpuset *cur, const struct cpuset *trial)
 
        /*
         * Cpusets with tasks - existing or newly being attached - can't
-        * have empty cpus_allowed or mems_allowed.
+        * be changed to have empty cpus_allowed or mems_allowed.
         */
        ret = -ENOSPC;
-       if ((cgroup_task_count(cur->css.cgroup) || cur->attach_in_progress) &&
-           (cpumask_empty(trial->cpus_allowed) &&
-            nodes_empty(trial->mems_allowed)))
-               goto out;
+       if ((cgroup_task_count(cur->css.cgroup) || cur->attach_in_progress)) {
+               if (!cpumask_empty(cur->cpus_allowed) &&
+                   cpumask_empty(trial->cpus_allowed))
+                       goto out;
+               if (!nodes_empty(cur->mems_allowed) &&
+                   nodes_empty(trial->mems_allowed))
+                       goto out;
+       }
 
        ret = 0;
 out:
@@ -1608,11 +1612,13 @@ static int cpuset_write_u64(struct cgroup *cgrp, struct cftype *cft, u64 val)
 {
        struct cpuset *cs = cgroup_cs(cgrp);
        cpuset_filetype_t type = cft->private;
-       int retval = -ENODEV;
+       int retval = 0;
 
        mutex_lock(&cpuset_mutex);
-       if (!is_cpuset_online(cs))
+       if (!is_cpuset_online(cs)) {
+               retval = -ENODEV;
                goto out_unlock;
+       }
 
        switch (type) {
        case FILE_CPU_EXCLUSIVE:
index 403d2bb..e23bb19 100644 (file)
@@ -1679,6 +1679,12 @@ SYSCALL_DEFINE5(clone, unsigned long, newsp, unsigned long, clone_flags,
                 int __user *, parent_tidptr,
                 int __user *, child_tidptr,
                 int, tls_val)
+#elif defined(CONFIG_CLONE_BACKWARDS3)
+SYSCALL_DEFINE6(clone, unsigned long, clone_flags, unsigned long, newsp,
+               int, stack_size,
+               int __user *, parent_tidptr,
+               int __user *, child_tidptr,
+               int, tls_val)
 #else
 SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp,
                 int __user *, parent_tidptr,
index ff05f4b..a52ee7b 100644 (file)
@@ -686,7 +686,7 @@ __ww_mutex_lock(struct ww_mutex *lock, struct ww_acquire_ctx *ctx)
        might_sleep();
        ret =  __mutex_lock_common(&lock->base, TASK_UNINTERRUPTIBLE,
                                   0, &ctx->dep_map, _RET_IP_, ctx);
-       if (!ret && ctx->acquired > 0)
+       if (!ret && ctx->acquired > 1)
                return ww_mutex_deadlock_injection(lock, ctx);
 
        return ret;
@@ -702,7 +702,7 @@ __ww_mutex_lock_interruptible(struct ww_mutex *lock, struct ww_acquire_ctx *ctx)
        ret = __mutex_lock_common(&lock->base, TASK_INTERRUPTIBLE,
                                  0, &ctx->dep_map, _RET_IP_, ctx);
 
-       if (!ret && ctx->acquired > 0)
+       if (!ret && ctx->acquired > 1)
                return ww_mutex_deadlock_injection(lock, ctx);
 
        return ret;
index 06fe285..a394297 100644 (file)
@@ -296,6 +296,17 @@ int pm_qos_request_active(struct pm_qos_request *req)
 }
 EXPORT_SYMBOL_GPL(pm_qos_request_active);
 
+static void __pm_qos_update_request(struct pm_qos_request *req,
+                          s32 new_value)
+{
+       trace_pm_qos_update_request(req->pm_qos_class, new_value);
+
+       if (new_value != req->node.prio)
+               pm_qos_update_target(
+                       pm_qos_array[req->pm_qos_class]->constraints,
+                       &req->node, PM_QOS_UPDATE_REQ, new_value);
+}
+
 /**
  * pm_qos_work_fn - the timeout handler of pm_qos_update_request_timeout
  * @work: work struct for the delayed work (timeout)
@@ -308,7 +319,7 @@ static void pm_qos_work_fn(struct work_struct *work)
                                                  struct pm_qos_request,
                                                  work);
 
-       pm_qos_update_request(req, PM_QOS_DEFAULT_VALUE);
+       __pm_qos_update_request(req, PM_QOS_DEFAULT_VALUE);
 }
 
 /**
@@ -364,12 +375,7 @@ void pm_qos_update_request(struct pm_qos_request *req,
        }
 
        cancel_delayed_work_sync(&req->work);
-
-       trace_pm_qos_update_request(req->pm_qos_class, new_value);
-       if (new_value != req->node.prio)
-               pm_qos_update_target(
-                       pm_qos_array[req->pm_qos_class]->constraints,
-                       &req->node, PM_QOS_UPDATE_REQ, new_value);
+       __pm_qos_update_request(req, new_value);
 }
 EXPORT_SYMBOL_GPL(pm_qos_update_request);
 
index b7c32cb..05c39f0 100644 (file)
@@ -933,6 +933,8 @@ static int effective_prio(struct task_struct *p)
 /**
  * task_curr - is this task currently executing on a CPU?
  * @p: the task in question.
+ *
+ * Return: 1 if the task is currently executing. 0 otherwise.
  */
 inline int task_curr(const struct task_struct *p)
 {
@@ -1482,7 +1484,7 @@ static void ttwu_queue(struct task_struct *p, int cpu)
  * the simpler "current->state = TASK_RUNNING" to mark yourself
  * runnable without the overhead of this.
  *
- * Returns %true if @p was woken up, %false if it was already running
+ * Return: %true if @p was woken up, %false if it was already running.
  * or @state didn't match @p's state.
  */
 static int
@@ -1491,7 +1493,13 @@ try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags)
        unsigned long flags;
        int cpu, success = 0;
 
-       smp_wmb();
+       /*
+        * If we are going to wake up a thread waiting for CONDITION we
+        * need to ensure that CONDITION=1 done by the caller can not be
+        * reordered with p->state check below. This pairs with mb() in
+        * set_current_state() the waiting thread does.
+        */
+       smp_mb__before_spinlock();
        raw_spin_lock_irqsave(&p->pi_lock, flags);
        if (!(p->state & state))
                goto out;
@@ -1577,8 +1585,9 @@ out:
  * @p: The process to be woken up.
  *
  * Attempt to wake up the nominated process and move it to the set of runnable
- * processes.  Returns 1 if the process was woken up, 0 if it was already
- * running.
+ * processes.
+ *
+ * Return: 1 if the process was woken up, 0 if it was already running.
  *
  * It may be assumed that this function implies a write memory barrier before
  * changing the task state if and only if any tasks are woken up.
@@ -2191,6 +2200,8 @@ void scheduler_tick(void)
  * This makes sure that uptime, CFS vruntime, load
  * balancing, etc... continue to move forward, even
  * with a very low granularity.
+ *
+ * Return: Maximum deferment in nanoseconds.
  */
 u64 scheduler_tick_max_deferment(void)
 {
@@ -2394,6 +2405,12 @@ need_resched:
        if (sched_feat(HRTICK))
                hrtick_clear(rq);
 
+       /*
+        * Make sure that signal_pending_state()->signal_pending() below
+        * can't be reordered with __set_current_state(TASK_INTERRUPTIBLE)
+        * done by the caller to avoid the race with signal_wake_up().
+        */
+       smp_mb__before_spinlock();
        raw_spin_lock_irq(&rq->lock);
 
        switch_count = &prev->nivcsw;
@@ -2796,8 +2813,8 @@ EXPORT_SYMBOL(wait_for_completion);
  * specified timeout to expire. The timeout is in jiffies. It is not
  * interruptible.
  *
- * The return value is 0 if timed out, and positive (at least 1, or number of
- * jiffies left till timeout) if completed.
+ * Return: 0 if timed out, and positive (at least 1, or number of jiffies left
+ * till timeout) if completed.
  */
 unsigned long __sched
 wait_for_completion_timeout(struct completion *x, unsigned long timeout)
@@ -2829,8 +2846,8 @@ EXPORT_SYMBOL(wait_for_completion_io);
  * specified timeout to expire. The timeout is in jiffies. It is not
  * interruptible. The caller is accounted as waiting for IO.
  *
- * The return value is 0 if timed out, and positive (at least 1, or number of
- * jiffies left till timeout) if completed.
+ * Return: 0 if timed out, and positive (at least 1, or number of jiffies left
+ * till timeout) if completed.
  */
 unsigned long __sched
 wait_for_completion_io_timeout(struct completion *x, unsigned long timeout)
@@ -2846,7 +2863,7 @@ EXPORT_SYMBOL(wait_for_completion_io_timeout);
  * This waits for completion of a specific task to be signaled. It is
  * interruptible.
  *
- * The return value is -ERESTARTSYS if interrupted, 0 if completed.
+ * Return: -ERESTARTSYS if interrupted, 0 if completed.
  */
 int __sched wait_for_completion_interruptible(struct completion *x)
 {
@@ -2865,8 +2882,8 @@ EXPORT_SYMBOL(wait_for_completion_interruptible);
  * This waits for either a completion of a specific task to be signaled or for a
  * specified timeout to expire. It is interruptible. The timeout is in jiffies.
  *
- * The return value is -ERESTARTSYS if interrupted, 0 if timed out,
- * positive (at least 1, or number of jiffies left till timeout) if completed.
+ * Return: -ERESTARTSYS if interrupted, 0 if timed out, positive (at least 1,
+ * or number of jiffies left till timeout) if completed.
  */
 long __sched
 wait_for_completion_interruptible_timeout(struct completion *x,
@@ -2883,7 +2900,7 @@ EXPORT_SYMBOL(wait_for_completion_interruptible_timeout);
  * This waits to be signaled for completion of a specific task. It can be
  * interrupted by a kill signal.
  *
- * The return value is -ERESTARTSYS if interrupted, 0 if completed.
+ * Return: -ERESTARTSYS if interrupted, 0 if completed.
  */
 int __sched wait_for_completion_killable(struct completion *x)
 {
@@ -2903,8 +2920,8 @@ EXPORT_SYMBOL(wait_for_completion_killable);
  * signaled or for a specified timeout to expire. It can be
  * interrupted by a kill signal. The timeout is in jiffies.
  *
- * The return value is -ERESTARTSYS if interrupted, 0 if timed out,
- * positive (at least 1, or number of jiffies left till timeout) if completed.
+ * Return: -ERESTARTSYS if interrupted, 0 if timed out, positive (at least 1,
+ * or number of jiffies left till timeout) if completed.
  */
 long __sched
 wait_for_completion_killable_timeout(struct completion *x,
@@ -2918,7 +2935,7 @@ EXPORT_SYMBOL(wait_for_completion_killable_timeout);
  *     try_wait_for_completion - try to decrement a completion without blocking
  *     @x:     completion structure
  *
- *     Returns: 0 if a decrement cannot be done without blocking
+ *     Return: 0 if a decrement cannot be done without blocking
  *              1 if a decrement succeeded.
  *
  *     If a completion is being used as a counting completion,
@@ -2945,7 +2962,7 @@ EXPORT_SYMBOL(try_wait_for_completion);
  *     completion_done - Test to see if a completion has any waiters
  *     @x:     completion structure
  *
- *     Returns: 0 if there are waiters (wait_for_completion() in progress)
+ *     Return: 0 if there are waiters (wait_for_completion() in progress)
  *              1 if there are no waiters.
  *
  */
@@ -3182,7 +3199,7 @@ SYSCALL_DEFINE1(nice, int, increment)
  * task_prio - return the priority value of a given task.
  * @p: the task in question.
  *
- * This is the priority value as seen by users in /proc.
+ * Return: The priority value as seen by users in /proc.
  * RT tasks are offset by -200. Normal tasks are centered
  * around 0, value goes from -16 to +15.
  */
@@ -3194,6 +3211,8 @@ int task_prio(const struct task_struct *p)
 /**
  * task_nice - return the nice value of a given task.
  * @p: the task in question.
+ *
+ * Return: The nice value [ -20 ... 0 ... 19 ].
  */
 int task_nice(const struct task_struct *p)
 {
@@ -3204,6 +3223,8 @@ EXPORT_SYMBOL(task_nice);
 /**
  * idle_cpu - is a given cpu idle currently?
  * @cpu: the processor in question.
+ *
+ * Return: 1 if the CPU is currently idle. 0 otherwise.
  */
 int idle_cpu(int cpu)
 {
@@ -3226,6 +3247,8 @@ int idle_cpu(int cpu)
 /**
  * idle_task - return the idle task for a given cpu.
  * @cpu: the processor in question.
+ *
+ * Return: The idle task for the cpu @cpu.
  */
 struct task_struct *idle_task(int cpu)
 {
@@ -3235,6 +3258,8 @@ struct task_struct *idle_task(int cpu)
 /**
  * find_process_by_pid - find a process with a matching PID value.
  * @pid: the pid in question.
+ *
+ * The task of @pid, if found. %NULL otherwise.
  */
 static struct task_struct *find_process_by_pid(pid_t pid)
 {
@@ -3432,6 +3457,8 @@ recheck:
  * @policy: new policy.
  * @param: structure containing the new RT priority.
  *
+ * Return: 0 on success. An error code otherwise.
+ *
  * NOTE that the task may be already dead.
  */
 int sched_setscheduler(struct task_struct *p, int policy,
@@ -3451,6 +3478,8 @@ EXPORT_SYMBOL_GPL(sched_setscheduler);
  * current context has permission.  For example, this is needed in
  * stop_machine(): we create temporary high priority worker threads,
  * but our caller might not have that capability.
+ *
+ * Return: 0 on success. An error code otherwise.
  */
 int sched_setscheduler_nocheck(struct task_struct *p, int policy,
                               const struct sched_param *param)
@@ -3485,6 +3514,8 @@ do_sched_setscheduler(pid_t pid, int policy, struct sched_param __user *param)
  * @pid: the pid in question.
  * @policy: new policy.
  * @param: structure containing the new RT priority.
+ *
+ * Return: 0 on success. An error code otherwise.
  */
 SYSCALL_DEFINE3(sched_setscheduler, pid_t, pid, int, policy,
                struct sched_param __user *, param)
@@ -3500,6 +3531,8 @@ SYSCALL_DEFINE3(sched_setscheduler, pid_t, pid, int, policy,
  * sys_sched_setparam - set/change the RT priority of a thread
  * @pid: the pid in question.
  * @param: structure containing the new RT priority.
+ *
+ * Return: 0 on success. An error code otherwise.
  */
 SYSCALL_DEFINE2(sched_setparam, pid_t, pid, struct sched_param __user *, param)
 {
@@ -3509,6 +3542,9 @@ SYSCALL_DEFINE2(sched_setparam, pid_t, pid, struct sched_param __user *, param)
 /**
  * sys_sched_getscheduler - get the policy (scheduling class) of a thread
  * @pid: the pid in question.
+ *
+ * Return: On success, the policy of the thread. Otherwise, a negative error
+ * code.
  */
 SYSCALL_DEFINE1(sched_getscheduler, pid_t, pid)
 {
@@ -3535,6 +3571,9 @@ SYSCALL_DEFINE1(sched_getscheduler, pid_t, pid)
  * sys_sched_getparam - get the RT priority of a thread
  * @pid: the pid in question.
  * @param: structure containing the RT priority.
+ *
+ * Return: On success, 0 and the RT priority is in @param. Otherwise, an error
+ * code.
  */
 SYSCALL_DEFINE2(sched_getparam, pid_t, pid, struct sched_param __user *, param)
 {
@@ -3659,6 +3698,8 @@ static int get_user_cpu_mask(unsigned long __user *user_mask_ptr, unsigned len,
  * @pid: pid of the process
  * @len: length in bytes of the bitmask pointed to by user_mask_ptr
  * @user_mask_ptr: user-space pointer to the new cpu mask
+ *
+ * Return: 0 on success. An error code otherwise.
  */
 SYSCALL_DEFINE3(sched_setaffinity, pid_t, pid, unsigned int, len,
                unsigned long __user *, user_mask_ptr)
@@ -3710,6 +3751,8 @@ out_unlock:
  * @pid: pid of the process
  * @len: length in bytes of the bitmask pointed to by user_mask_ptr
  * @user_mask_ptr: user-space pointer to hold the current cpu mask
+ *
+ * Return: 0 on success. An error code otherwise.
  */
 SYSCALL_DEFINE3(sched_getaffinity, pid_t, pid, unsigned int, len,
                unsigned long __user *, user_mask_ptr)
@@ -3744,6 +3787,8 @@ SYSCALL_DEFINE3(sched_getaffinity, pid_t, pid, unsigned int, len,
  *
  * This function yields the current CPU to other tasks. If there are no
  * other threads running on this CPU then this function will return.
+ *
+ * Return: 0.
  */
 SYSCALL_DEFINE0(sched_yield)
 {
@@ -3869,7 +3914,7 @@ EXPORT_SYMBOL(yield);
  * It's the caller's job to ensure that the target task struct
  * can't go away on us before we can do any checks.
  *
- * Returns:
+ * Return:
  *     true (>0) if we indeed boosted the target task.
  *     false (0) if we failed to boost the target.
  *     -ESRCH if there's no task to yield to.
@@ -3972,8 +4017,9 @@ long __sched io_schedule_timeout(long timeout)
  * sys_sched_get_priority_max - return maximum RT priority.
  * @policy: scheduling class.
  *
- * this syscall returns the maximum rt_priority that can be used
- * by a given scheduling class.
+ * Return: On success, this syscall returns the maximum
+ * rt_priority that can be used by a given scheduling class.
+ * On failure, a negative error code is returned.
  */
 SYSCALL_DEFINE1(sched_get_priority_max, int, policy)
 {
@@ -3997,8 +4043,9 @@ SYSCALL_DEFINE1(sched_get_priority_max, int, policy)
  * sys_sched_get_priority_min - return minimum RT priority.
  * @policy: scheduling class.
  *
- * this syscall returns the minimum rt_priority that can be used
- * by a given scheduling class.
+ * Return: On success, this syscall returns the minimum
+ * rt_priority that can be used by a given scheduling class.
+ * On failure, a negative error code is returned.
  */
 SYSCALL_DEFINE1(sched_get_priority_min, int, policy)
 {
@@ -4024,6 +4071,9 @@ SYSCALL_DEFINE1(sched_get_priority_min, int, policy)
  *
  * this syscall writes the default timeslice value of a given process
  * into the user-space timespec buffer. A value of '0' means infinity.
+ *
+ * Return: On success, 0 and the timeslice is in @interval. Otherwise,
+ * an error code.
  */
 SYSCALL_DEFINE2(sched_rr_get_interval, pid_t, pid,
                struct timespec __user *, interval)
@@ -6632,6 +6682,8 @@ void normalize_rt_tasks(void)
  * @cpu: the processor in question.
  *
  * ONLY VALID WHEN THE WHOLE SYSTEM IS STOPPED!
+ *
+ * Return: The current task for @cpu.
  */
 struct task_struct *curr_task(int cpu)
 {
index 1095e87..8b836b3 100644 (file)
@@ -62,7 +62,7 @@ static int convert_prio(int prio)
  * any discrepancies created by racing against the uncertainty of the current
  * priority configuration.
  *
- * Returns: (int)bool - CPUs were found
+ * Return: (int)bool - CPUs were found
  */
 int cpupri_find(struct cpupri *cp, struct task_struct *p,
                struct cpumask *lowest_mask)
@@ -203,7 +203,7 @@ void cpupri_set(struct cpupri *cp, int cpu, int newpri)
  * cpupri_init - initialize the cpupri structure
  * @cp: The cpupri context
  *
- * Returns: -ENOMEM if memory fails.
+ * Return: -ENOMEM on memory allocation failure.
  */
 int cpupri_init(struct cpupri *cp)
 {
index 9565645..68f1609 100644 (file)
@@ -2032,6 +2032,7 @@ entity_tick(struct cfs_rq *cfs_rq, struct sched_entity *curr, int queued)
         */
        update_entity_load_avg(curr, 1);
        update_cfs_rq_blocked_load(cfs_rq, 1);
+       update_cfs_shares(cfs_rq);
 
 #ifdef CONFIG_SCHED_HRTICK
        /*
@@ -4280,6 +4281,8 @@ struct sg_lb_stats {
  * get_sd_load_idx - Obtain the load index for a given sched domain.
  * @sd: The sched_domain whose load_idx is to be obtained.
  * @idle: The Idle status of the CPU for whose sd load_icx is obtained.
+ *
+ * Return: The load index.
  */
 static inline int get_sd_load_idx(struct sched_domain *sd,
                                        enum cpu_idle_type idle)
@@ -4574,6 +4577,9 @@ static inline void update_sg_lb_stats(struct lb_env *env,
  *
  * Determine if @sg is a busier group than the previously selected
  * busiest group.
+ *
+ * Return: %true if @sg is a busier group than the previously selected
+ * busiest group. %false otherwise.
  */
 static bool update_sd_pick_busiest(struct lb_env *env,
                                   struct sd_lb_stats *sds,
@@ -4691,7 +4697,7 @@ static inline void update_sd_lb_stats(struct lb_env *env,
  * assuming lower CPU number will be equivalent to lower a SMT thread
  * number.
  *
- * Returns 1 when packing is required and a task should be moved to
+ * Return: 1 when packing is required and a task should be moved to
  * this CPU.  The amount of the imbalance is returned in *imbalance.
  *
  * @env: The load balancing environment.
@@ -4869,7 +4875,7 @@ static inline void calculate_imbalance(struct lb_env *env, struct sd_lb_stats *s
  * @balance: Pointer to a variable indicating if this_cpu
  *     is the appropriate cpu to perform load balancing at this_level.
  *
- * Returns:    - the busiest group if imbalance exists.
+ * Return:     - The busiest group if imbalance exists.
  *             - If no imbalance and user has opted for power-savings balance,
  *                return the least loaded group whose CPUs can be
  *                put to idle by rebalancing its tasks onto our group.
index a326f27..0b479a6 100644 (file)
@@ -121,7 +121,7 @@ void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate)
        BUG_ON(bits > 32);
        WARN_ON(!irqs_disabled());
        read_sched_clock = read;
-       sched_clock_mask = (1 << bits) - 1;
+       sched_clock_mask = (1ULL << bits) - 1;
        cd.rate = rate;
 
        /* calculate the mult/shift to convert counter ticks to ns. */
index e77edc9..e8a1516 100644 (file)
@@ -182,7 +182,8 @@ static bool can_stop_full_tick(void)
                 * Don't allow the user to think they can get
                 * full NO_HZ with this machine.
                 */
-               WARN_ONCE(1, "NO_HZ FULL will not work with unstable sched clock");
+               WARN_ONCE(have_nohz_full_mask,
+                         "NO_HZ FULL will not work with unstable sched clock");
                return false;
        }
 #endif
@@ -343,8 +344,6 @@ static int tick_nohz_init_all(void)
 
 void __init tick_nohz_init(void)
 {
-       int cpu;
-
        if (!have_nohz_full_mask) {
                if (tick_nohz_init_all() < 0)
                        return;
index dec68bd..d550920 100644 (file)
@@ -363,8 +363,7 @@ EXPORT_SYMBOL(out_of_line_wait_on_atomic_t);
 
 /**
  * wake_up_atomic_t - Wake up a waiter on a atomic_t
- * @word: The word being waited on, a kernel virtual address
- * @bit: The bit of the word being waited on
+ * @p: The atomic_t being waited on, a kernel virtual address
  *
  * Wake up anyone waiting for the atomic_t to go to zero.
  *
index fd94058..28321d8 100644 (file)
@@ -437,7 +437,7 @@ int lz4_compress(const unsigned char *src, size_t src_len,
 exit:
        return ret;
 }
-EXPORT_SYMBOL_GPL(lz4_compress);
+EXPORT_SYMBOL(lz4_compress);
 
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("Dual BSD/GPL");
 MODULE_DESCRIPTION("LZ4 compressor");
index d3414ea..411be80 100644 (file)
@@ -299,7 +299,7 @@ exit_0:
        return ret;
 }
 #ifndef STATIC
-EXPORT_SYMBOL_GPL(lz4_decompress);
+EXPORT_SYMBOL(lz4_decompress);
 #endif
 
 int lz4_decompress_unknownoutputsize(const char *src, size_t src_len,
@@ -319,8 +319,8 @@ exit_0:
        return ret;
 }
 #ifndef STATIC
-EXPORT_SYMBOL_GPL(lz4_decompress_unknownoutputsize);
+EXPORT_SYMBOL(lz4_decompress_unknownoutputsize);
 
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("Dual BSD/GPL");
 MODULE_DESCRIPTION("LZ4 Decompressor");
 #endif
index eb1a74f..f344f76 100644 (file)
@@ -533,7 +533,7 @@ int lz4hc_compress(const unsigned char *src, size_t src_len,
 exit:
        return ret;
 }
-EXPORT_SYMBOL_GPL(lz4hc_compress);
+EXPORT_SYMBOL(lz4hc_compress);
 
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("Dual BSD/GPL");
 MODULE_DESCRIPTION("LZ4HC compressor");
index 87da359..5bff081 100644 (file)
@@ -57,17 +57,22 @@ static int install_file_pte(struct mm_struct *mm, struct vm_area_struct *vma,
                unsigned long addr, unsigned long pgoff, pgprot_t prot)
 {
        int err = -ENOMEM;
-       pte_t *pte;
+       pte_t *pte, ptfile;
        spinlock_t *ptl;
 
        pte = get_locked_pte(mm, addr, &ptl);
        if (!pte)
                goto out;
 
-       if (!pte_none(*pte))
+       ptfile = pgoff_to_pte(pgoff);
+
+       if (!pte_none(*pte)) {
+               if (pte_present(*pte) && pte_soft_dirty(*pte))
+                       pte_file_mksoft_dirty(ptfile);
                zap_pte(mm, vma, addr, pte);
+       }
 
-       set_pte_at(mm, addr, pte, pgoff_to_pte(pgoff));
+       set_pte_at(mm, addr, pte, ptfile);
        /*
         * We don't need to run update_mmu_cache() here because the "file pte"
         * being installed by install_file_pte() is not a real pte - it's a
index 83aff0a..b60f330 100644 (file)
@@ -2490,7 +2490,7 @@ void unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start,
 
        mm = vma->vm_mm;
 
-       tlb_gather_mmu(&tlb, mm, 0);
+       tlb_gather_mmu(&tlb, mm, start, end);
        __unmap_hugepage_range(&tlb, vma, start, end, ref_page);
        tlb_finish_mmu(&tlb, start, end);
 }
index c290a1c..0878ff7 100644 (file)
@@ -3195,11 +3195,11 @@ int memcg_register_cache(struct mem_cgroup *memcg, struct kmem_cache *s,
        if (!s->memcg_params)
                return -ENOMEM;
 
-       INIT_WORK(&s->memcg_params->destroy,
-                       kmem_cache_destroy_work_func);
        if (memcg) {
                s->memcg_params->memcg = memcg;
                s->memcg_params->root_cache = root_cache;
+               INIT_WORK(&s->memcg_params->destroy,
+                               kmem_cache_destroy_work_func);
        } else
                s->memcg_params->is_root_cache = true;
 
@@ -6969,7 +6969,6 @@ struct cgroup_subsys mem_cgroup_subsys = {
 #ifdef CONFIG_MEMCG_SWAP
 static int __init enable_swap_account(char *s)
 {
-       /* consider enabled if no parameter or 1 is given */
        if (!strcmp(s, "1"))
                really_do_swap_account = 1;
        else if (!strcmp(s, "0"))
index 1ce2e2a..af84bc0 100644 (file)
@@ -209,14 +209,15 @@ static int tlb_next_batch(struct mmu_gather *tlb)
  *     tear-down from @mm. The @fullmm argument is used when @mm is without
  *     users and we're going to destroy the full address space (exit/execve).
  */
-void tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, bool fullmm)
+void tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned long start, unsigned long end)
 {
        tlb->mm = mm;
 
-       tlb->fullmm     = fullmm;
+       /* Is it from 0 to ~0? */
+       tlb->fullmm     = !(start | (end+1));
        tlb->need_flush_all = 0;
-       tlb->start      = -1UL;
-       tlb->end        = 0;
+       tlb->start      = start;
+       tlb->end        = end;
        tlb->need_flush = 0;
        tlb->local.next = NULL;
        tlb->local.nr   = 0;
@@ -256,8 +257,6 @@ void tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long e
 {
        struct mmu_gather_batch *batch, *next;
 
-       tlb->start = start;
-       tlb->end   = end;
        tlb_flush_mmu(tlb);
 
        /* keep the page table cache within bounds */
@@ -1099,7 +1098,6 @@ static unsigned long zap_pte_range(struct mmu_gather *tlb,
        spinlock_t *ptl;
        pte_t *start_pte;
        pte_t *pte;
-       unsigned long range_start = addr;
 
 again:
        init_rss_vec(rss);
@@ -1141,9 +1139,12 @@ again:
                                continue;
                        if (unlikely(details) && details->nonlinear_vma
                            && linear_page_index(details->nonlinear_vma,
-                                               addr) != page->index)
-                               set_pte_at(mm, addr, pte,
-                                          pgoff_to_pte(page->index));
+                                               addr) != page->index) {
+                               pte_t ptfile = pgoff_to_pte(page->index);
+                               if (pte_soft_dirty(ptent))
+                                       pte_file_mksoft_dirty(ptfile);
+                               set_pte_at(mm, addr, pte, ptfile);
+                       }
                        if (PageAnon(page))
                                rss[MM_ANONPAGES]--;
                        else {
@@ -1202,17 +1203,25 @@ again:
         * and page-free while holding it.
         */
        if (force_flush) {
+               unsigned long old_end;
+
                force_flush = 0;
 
-#ifdef HAVE_GENERIC_MMU_GATHER
-               tlb->start = range_start;
+               /*
+                * Flush the TLB just for the previous segment,
+                * then update the range to be the remaining
+                * TLB range.
+                */
+               old_end = tlb->end;
                tlb->end = addr;
-#endif
+
                tlb_flush_mmu(tlb);
-               if (addr != end) {
-                       range_start = addr;
+
+               tlb->start = addr;
+               tlb->end = old_end;
+
+               if (addr != end)
                        goto again;
-               }
        }
 
        return addr;
@@ -1397,7 +1406,7 @@ void zap_page_range(struct vm_area_struct *vma, unsigned long start,
        unsigned long end = start + size;
 
        lru_add_drain();
-       tlb_gather_mmu(&tlb, mm, 0);
+       tlb_gather_mmu(&tlb, mm, start, end);
        update_hiwater_rss(mm);
        mmu_notifier_invalidate_range_start(mm, start, end);
        for ( ; vma && vma->vm_start < end; vma = vma->vm_next)
@@ -1423,7 +1432,7 @@ static void zap_page_range_single(struct vm_area_struct *vma, unsigned long addr
        unsigned long end = address + size;
 
        lru_add_drain();
-       tlb_gather_mmu(&tlb, mm, 0);
+       tlb_gather_mmu(&tlb, mm, address, end);
        update_hiwater_rss(mm);
        mmu_notifier_invalidate_range_start(mm, address, end);
        unmap_single_vma(&tlb, vma, address, end, details);
@@ -3115,6 +3124,8 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma,
                exclusive = 1;
        }
        flush_icache_page(vma, page);
+       if (pte_swp_soft_dirty(orig_pte))
+               pte = pte_mksoft_dirty(pte);
        set_pte_at(mm, address, page_table, pte);
        if (page == swapcache)
                do_page_add_anon_rmap(page, vma, address, exclusive);
@@ -3408,6 +3419,8 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma,
                entry = mk_pte(page, vma->vm_page_prot);
                if (flags & FAULT_FLAG_WRITE)
                        entry = maybe_mkwrite(pte_mkdirty(entry), vma);
+               else if (pte_file(orig_pte) && pte_file_soft_dirty(orig_pte))
+                       pte_mksoft_dirty(entry);
                if (anon) {
                        inc_mm_counter_fast(mm, MM_ANONPAGES);
                        page_add_new_anon_rmap(page, vma, address);
index 1edbaa3..f9c97d1 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -2336,7 +2336,7 @@ static void unmap_region(struct mm_struct *mm,
        struct mmu_gather tlb;
 
        lru_add_drain();
-       tlb_gather_mmu(&tlb, mm, 0);
+       tlb_gather_mmu(&tlb, mm, start, end);
        update_hiwater_rss(mm);
        unmap_vmas(&tlb, vma, start, end);
        free_pgtables(&tlb, vma, prev ? prev->vm_end : FIRST_USER_ADDRESS,
@@ -2709,7 +2709,7 @@ void exit_mmap(struct mm_struct *mm)
 
        lru_add_drain();
        flush_cache_mm(mm);
-       tlb_gather_mmu(&tlb, mm, 1);
+       tlb_gather_mmu(&tlb, mm, 0, -1);
        /* update_hiwater_rss(mm) here? but nobody should be looking */
        /* Use -1 here to ensure all VMAs in the mm are unmapped */
        unmap_vmas(&tlb, vma, 0, -1);
index cd356df..b2e29ac 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -1236,6 +1236,7 @@ int try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
                           swp_entry_to_pte(make_hwpoison_entry(page)));
        } else if (PageAnon(page)) {
                swp_entry_t entry = { .val = page_private(page) };
+               pte_t swp_pte;
 
                if (PageSwapCache(page)) {
                        /*
@@ -1264,7 +1265,10 @@ int try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
                        BUG_ON(TTU_ACTION(flags) != TTU_MIGRATION);
                        entry = make_migration_entry(page, pte_write(pteval));
                }
-               set_pte_at(mm, address, pte, swp_entry_to_pte(entry));
+               swp_pte = swp_entry_to_pte(entry);
+               if (pte_soft_dirty(pteval))
+                       swp_pte = pte_swp_mksoft_dirty(swp_pte);
+               set_pte_at(mm, address, pte, swp_pte);
                BUG_ON(pte_file(*pte));
        } else if (IS_ENABLED(CONFIG_MIGRATION) &&
                   (TTU_ACTION(flags) == TTU_MIGRATION)) {
@@ -1401,8 +1405,12 @@ static int try_to_unmap_cluster(unsigned long cursor, unsigned int *mapcount,
                pteval = ptep_clear_flush(vma, address, pte);
 
                /* If nonlinear, store the file page offset in the pte. */
-               if (page->index != linear_page_index(vma, address))
-                       set_pte_at(mm, address, pte, pgoff_to_pte(page->index));
+               if (page->index != linear_page_index(vma, address)) {
+                       pte_t ptfile = pgoff_to_pte(page->index);
+                       if (pte_soft_dirty(pteval))
+                               pte_file_mksoft_dirty(ptfile);
+                       set_pte_at(mm, address, pte, ptfile);
+               }
 
                /* Move the dirty bit to the physical page now the pte is gone. */
                if (pte_dirty(pteval))
index 8335dbd..e43dc55 100644 (file)
@@ -2909,14 +2909,8 @@ EXPORT_SYMBOL_GPL(shmem_truncate_range);
 
 /* common code */
 
-static char *shmem_dname(struct dentry *dentry, char *buffer, int buflen)
-{
-       return dynamic_dname(dentry, buffer, buflen, "/%s (deleted)",
-                               dentry->d_name.name);
-}
-
 static struct dentry_operations anon_ops = {
-       .d_dname = shmem_dname
+       .d_dname = simple_dname
 };
 
 /**
index 36af6ee..6cf2e60 100644 (file)
@@ -866,6 +866,21 @@ unsigned int count_swap_pages(int type, int free)
 }
 #endif /* CONFIG_HIBERNATION */
 
+static inline int maybe_same_pte(pte_t pte, pte_t swp_pte)
+{
+#ifdef CONFIG_MEM_SOFT_DIRTY
+       /*
+        * When pte keeps soft dirty bit the pte generated
+        * from swap entry does not has it, still it's same
+        * pte from logical point of view.
+        */
+       pte_t swp_pte_dirty = pte_swp_mksoft_dirty(swp_pte);
+       return pte_same(pte, swp_pte) || pte_same(pte, swp_pte_dirty);
+#else
+       return pte_same(pte, swp_pte);
+#endif
+}
+
 /*
  * No need to decide whether this PTE shares the swap entry with others,
  * just let do_wp_page work it out if a write is requested later - to
@@ -892,7 +907,7 @@ static int unuse_pte(struct vm_area_struct *vma, pmd_t *pmd,
        }
 
        pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
-       if (unlikely(!pte_same(*pte, swp_entry_to_pte(entry)))) {
+       if (unlikely(!maybe_same_pte(*pte, swp_entry_to_pte(entry)))) {
                mem_cgroup_cancel_charge_swapin(memcg);
                ret = 0;
                goto out;
@@ -947,7 +962,7 @@ static int unuse_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
                 * swapoff spends a _lot_ of time in this loop!
                 * Test inline before going to call unuse_pte.
                 */
-               if (unlikely(pte_same(*pte, swp_pte))) {
+               if (unlikely(maybe_same_pte(*pte, swp_pte))) {
                        pte_unmap(pte);
                        ret = unuse_pte(vma, pmd, addr, entry, page);
                        if (ret)
index 4a78c4d..6ee48aa 100644 (file)
@@ -91,7 +91,12 @@ EXPORT_SYMBOL(__vlan_find_dev_deep);
 
 struct net_device *vlan_dev_real_dev(const struct net_device *dev)
 {
-       return vlan_dev_priv(dev)->real_dev;
+       struct net_device *ret = vlan_dev_priv(dev)->real_dev;
+
+       while (is_vlan_dev(ret))
+               ret = vlan_dev_priv(ret)->real_dev;
+
+       return ret;
 }
 EXPORT_SYMBOL(vlan_dev_real_dev);
 
index e14531f..264de88 100644 (file)
@@ -1529,6 +1529,8 @@ out:
  * in these cases, the skb is further handled by this function and
  * returns 1, otherwise it returns 0 and the caller shall further
  * process the skb.
+ *
+ * This call might reallocate skb data.
  */
 int batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb,
                  unsigned short vid)
index f105219..7614af3 100644 (file)
@@ -508,6 +508,7 @@ out:
        return 0;
 }
 
+/* this call might reallocate skb data */
 static bool batadv_is_type_dhcprequest(struct sk_buff *skb, int header_len)
 {
        int ret = false;
@@ -568,6 +569,7 @@ out:
        return ret;
 }
 
+/* this call might reallocate skb data */
 bool batadv_gw_is_dhcp_target(struct sk_buff *skb, unsigned int *header_len)
 {
        struct ethhdr *ethhdr;
@@ -619,6 +621,12 @@ bool batadv_gw_is_dhcp_target(struct sk_buff *skb, unsigned int *header_len)
 
        if (!pskb_may_pull(skb, *header_len + sizeof(*udphdr)))
                return false;
+
+       /* skb->data might have been reallocated by pskb_may_pull() */
+       ethhdr = (struct ethhdr *)skb->data;
+       if (ntohs(ethhdr->h_proto) == ETH_P_8021Q)
+               ethhdr = (struct ethhdr *)(skb->data + VLAN_HLEN);
+
        udphdr = (struct udphdr *)(skb->data + *header_len);
        *header_len += sizeof(*udphdr);
 
@@ -634,12 +642,14 @@ bool batadv_gw_is_dhcp_target(struct sk_buff *skb, unsigned int *header_len)
        return true;
 }
 
+/* this call might reallocate skb data */
 bool batadv_gw_out_of_range(struct batadv_priv *bat_priv,
-                           struct sk_buff *skb, struct ethhdr *ethhdr)
+                           struct sk_buff *skb)
 {
        struct batadv_neigh_node *neigh_curr = NULL, *neigh_old = NULL;
        struct batadv_orig_node *orig_dst_node = NULL;
        struct batadv_gw_node *curr_gw = NULL;
+       struct ethhdr *ethhdr;
        bool ret, out_of_range = false;
        unsigned int header_len = 0;
        uint8_t curr_tq_avg;
@@ -648,6 +658,7 @@ bool batadv_gw_out_of_range(struct batadv_priv *bat_priv,
        if (!ret)
                goto out;
 
+       ethhdr = (struct ethhdr *)skb->data;
        orig_dst_node = batadv_transtable_search(bat_priv, ethhdr->h_source,
                                                 ethhdr->h_dest);
        if (!orig_dst_node)
index 039902d..1037d75 100644 (file)
@@ -34,7 +34,6 @@ void batadv_gw_node_delete(struct batadv_priv *bat_priv,
 void batadv_gw_node_purge(struct batadv_priv *bat_priv);
 int batadv_gw_client_seq_print_text(struct seq_file *seq, void *offset);
 bool batadv_gw_is_dhcp_target(struct sk_buff *skb, unsigned int *header_len);
-bool batadv_gw_out_of_range(struct batadv_priv *bat_priv,
-                           struct sk_buff *skb, struct ethhdr *ethhdr);
+bool batadv_gw_out_of_range(struct batadv_priv *bat_priv, struct sk_buff *skb);
 
 #endif /* _NET_BATMAN_ADV_GATEWAY_CLIENT_H_ */
index 700d0b4..0f04e1c 100644 (file)
@@ -180,6 +180,9 @@ static int batadv_interface_tx(struct sk_buff *skb,
        if (batadv_bla_tx(bat_priv, skb, vid))
                goto dropped;
 
+       /* skb->data might have been reallocated by batadv_bla_tx() */
+       ethhdr = (struct ethhdr *)skb->data;
+
        /* Register the client MAC in the transtable */
        if (!is_multicast_ether_addr(ethhdr->h_source))
                batadv_tt_local_add(soft_iface, ethhdr->h_source, skb->skb_iif);
@@ -220,6 +223,10 @@ static int batadv_interface_tx(struct sk_buff *skb,
                default:
                        break;
                }
+
+               /* reminder: ethhdr might have become unusable from here on
+                * (batadv_gw_is_dhcp_target() might have reallocated skb data)
+                */
        }
 
        /* ethernet packet should be broadcasted */
@@ -266,7 +273,7 @@ static int batadv_interface_tx(struct sk_buff *skb,
        /* unicast packet */
        } else {
                if (atomic_read(&bat_priv->gw_mode) != BATADV_GW_MODE_OFF) {
-                       ret = batadv_gw_out_of_range(bat_priv, skb, ethhdr);
+                       ret = batadv_gw_out_of_range(bat_priv, skb);
                        if (ret)
                                goto dropped;
                }
index dc8b5d4..857e1b8 100644 (file)
@@ -326,7 +326,9 @@ static bool batadv_unicast_push_and_fill_skb(struct sk_buff *skb, int hdr_size,
  * @skb: the skb containing the payload to encapsulate
  * @orig_node: the destination node
  *
- * Returns false if the payload could not be encapsulated or true otherwise
+ * Returns false if the payload could not be encapsulated or true otherwise.
+ *
+ * This call might reallocate skb data.
  */
 static bool batadv_unicast_prepare_skb(struct sk_buff *skb,
                                       struct batadv_orig_node *orig_node)
@@ -343,7 +345,9 @@ static bool batadv_unicast_prepare_skb(struct sk_buff *skb,
  * @orig_node: the destination node
  * @packet_subtype: the batman 4addr packet subtype to use
  *
- * Returns false if the payload could not be encapsulated or true otherwise
+ * Returns false if the payload could not be encapsulated or true otherwise.
+ *
+ * This call might reallocate skb data.
  */
 bool batadv_unicast_4addr_prepare_skb(struct batadv_priv *bat_priv,
                                      struct sk_buff *skb,
@@ -401,7 +405,7 @@ int batadv_unicast_generic_send_skb(struct batadv_priv *bat_priv,
        struct batadv_neigh_node *neigh_node;
        int data_len = skb->len;
        int ret = NET_RX_DROP;
-       unsigned int dev_mtu;
+       unsigned int dev_mtu, header_len;
 
        /* get routing information */
        if (is_multicast_ether_addr(ethhdr->h_dest)) {
@@ -428,11 +432,17 @@ find_router:
 
        switch (packet_type) {
        case BATADV_UNICAST:
-               batadv_unicast_prepare_skb(skb, orig_node);
+               if (!batadv_unicast_prepare_skb(skb, orig_node))
+                       goto out;
+
+               header_len = sizeof(struct batadv_unicast_packet);
                break;
        case BATADV_UNICAST_4ADDR:
-               batadv_unicast_4addr_prepare_skb(bat_priv, skb, orig_node,
-                                                packet_subtype);
+               if (!batadv_unicast_4addr_prepare_skb(bat_priv, skb, orig_node,
+                                                     packet_subtype))
+                       goto out;
+
+               header_len = sizeof(struct batadv_unicast_4addr_packet);
                break;
        default:
                /* this function supports UNICAST and UNICAST_4ADDR only. It
@@ -441,6 +451,7 @@ find_router:
                goto out;
        }
 
+       ethhdr = (struct ethhdr *)(skb->data + header_len);
        unicast_packet = (struct batadv_unicast_packet *)skb->data;
 
        /* inform the destination node that we are still missing a correct route
index 60aca91..ffd5874 100644 (file)
@@ -161,7 +161,7 @@ void br_fdb_change_mac_address(struct net_bridge *br, const u8 *newaddr)
        if (!pv)
                return;
 
-       for_each_set_bit_from(vid, pv->vlan_bitmap, BR_VLAN_BITMAP_LEN) {
+       for_each_set_bit_from(vid, pv->vlan_bitmap, VLAN_N_VID) {
                f = __br_fdb_get(br, br->dev->dev_addr, vid);
                if (f && f->is_local && !f->dst)
                        fdb_delete(br, f);
@@ -730,7 +730,7 @@ int br_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
                /* VID was specified, so use it. */
                err = __br_fdb_add(ndm, p, addr, nlh_flags, vid);
        } else {
-               if (!pv || bitmap_empty(pv->vlan_bitmap, BR_VLAN_BITMAP_LEN)) {
+               if (!pv || bitmap_empty(pv->vlan_bitmap, VLAN_N_VID)) {
                        err = __br_fdb_add(ndm, p, addr, nlh_flags, 0);
                        goto out;
                }
@@ -739,7 +739,7 @@ int br_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
                 * specify a VLAN.  To be nice, add/update entry for every
                 * vlan on this port.
                 */
-               for_each_set_bit(vid, pv->vlan_bitmap, BR_VLAN_BITMAP_LEN) {
+               for_each_set_bit(vid, pv->vlan_bitmap, VLAN_N_VID) {
                        err = __br_fdb_add(ndm, p, addr, nlh_flags, vid);
                        if (err)
                                goto out;
@@ -817,7 +817,7 @@ int br_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[],
 
                err = __br_fdb_delete(p, addr, vid);
        } else {
-               if (!pv || bitmap_empty(pv->vlan_bitmap, BR_VLAN_BITMAP_LEN)) {
+               if (!pv || bitmap_empty(pv->vlan_bitmap, VLAN_N_VID)) {
                        err = __br_fdb_delete(p, addr, 0);
                        goto out;
                }
@@ -827,7 +827,7 @@ int br_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[],
                 * vlan on this port.
                 */
                err = -ENOENT;
-               for_each_set_bit(vid, pv->vlan_bitmap, BR_VLAN_BITMAP_LEN) {
+               for_each_set_bit(vid, pv->vlan_bitmap, VLAN_N_VID) {
                        err &= __br_fdb_delete(p, addr, vid);
                }
        }
index 61c5e81..08e576a 100644 (file)
@@ -1195,7 +1195,7 @@ static int br_ip6_multicast_query(struct net_bridge *br,
                max_delay = msecs_to_jiffies(ntohs(mld->mld_maxdelay));
                if (max_delay)
                        group = &mld->mld_mca;
-       } else if (skb->len >= sizeof(*mld2q)) {
+       } else {
                if (!pskb_may_pull(skb, sizeof(*mld2q))) {
                        err = -EINVAL;
                        goto out;
index 1fc30ab..b9259ef 100644 (file)
@@ -132,7 +132,7 @@ static int br_fill_ifinfo(struct sk_buff *skb,
                else
                        pv = br_get_vlan_info(br);
 
-               if (!pv || bitmap_empty(pv->vlan_bitmap, BR_VLAN_BITMAP_LEN))
+               if (!pv || bitmap_empty(pv->vlan_bitmap, VLAN_N_VID))
                        goto done;
 
                af = nla_nest_start(skb, IFLA_AF_SPEC);
@@ -140,7 +140,7 @@ static int br_fill_ifinfo(struct sk_buff *skb,
                        goto nla_put_failure;
 
                pvid = br_get_pvid(pv);
-               for_each_set_bit(vid, pv->vlan_bitmap, BR_VLAN_BITMAP_LEN) {
+               for_each_set_bit(vid, pv->vlan_bitmap, VLAN_N_VID) {
                        vinfo.vid = vid;
                        vinfo.flags = 0;
                        if (vid == pvid)
index 394bb96..3b9637f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *     Sysfs attributes of bridge ports
+ *     Sysfs attributes of bridge
  *     Linux ethernet bridge
  *
  *     Authors:
index bd58b45..9a9ffe7 100644 (file)
@@ -108,7 +108,7 @@ static int __vlan_del(struct net_port_vlans *v, u16 vid)
 
        clear_bit(vid, v->vlan_bitmap);
        v->num_vlans--;
-       if (bitmap_empty(v->vlan_bitmap, BR_VLAN_BITMAP_LEN)) {
+       if (bitmap_empty(v->vlan_bitmap, VLAN_N_VID)) {
                if (v->port_idx)
                        rcu_assign_pointer(v->parent.port->vlan_info, NULL);
                else
@@ -122,7 +122,7 @@ static void __vlan_flush(struct net_port_vlans *v)
 {
        smp_wmb();
        v->pvid = 0;
-       bitmap_zero(v->vlan_bitmap, BR_VLAN_BITMAP_LEN);
+       bitmap_zero(v->vlan_bitmap, VLAN_N_VID);
        if (v->port_idx)
                rcu_assign_pointer(v->parent.port->vlan_info, NULL);
        else
index 00ee068..b84a1b1 100644 (file)
@@ -65,6 +65,7 @@ ipv6:
                nhoff += sizeof(struct ipv6hdr);
                break;
        }
+       case __constant_htons(ETH_P_8021AD):
        case __constant_htons(ETH_P_8021Q): {
                const struct vlan_hdr *vlan;
                struct vlan_hdr _vlan;
index 9232c68..60533db 100644 (file)
@@ -1441,16 +1441,18 @@ struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
                atomic_set(&p->refcnt, 1);
                p->reachable_time =
                                neigh_rand_reach_time(p->base_reachable_time);
+               dev_hold(dev);
+               p->dev = dev;
+               write_pnet(&p->net, hold_net(net));
+               p->sysctl_table = NULL;
 
                if (ops->ndo_neigh_setup && ops->ndo_neigh_setup(dev, p)) {
+                       release_net(net);
+                       dev_put(dev);
                        kfree(p);
                        return NULL;
                }
 
-               dev_hold(dev);
-               p->dev = dev;
-               write_pnet(&p->net, hold_net(net));
-               p->sysctl_table = NULL;
                write_lock_bh(&tbl->lock);
                p->next         = tbl->parms.next;
                tbl->parms.next = p;
index 3de7408..ca198c1 100644 (file)
@@ -2156,7 +2156,7 @@ int ndo_dflt_fdb_del(struct ndmsg *ndm,
        /* If aging addresses are supported device will need to
         * implement its own handler for this.
         */
-       if (ndm->ndm_state & NUD_PERMANENT) {
+       if (!(ndm->ndm_state & NUD_PERMANENT)) {
                pr_info("%s: FDB only supports static addresses\n", dev->name);
                return -EINVAL;
        }
@@ -2384,7 +2384,7 @@ static int rtnl_bridge_getlink(struct sk_buff *skb, struct netlink_callback *cb)
        struct nlattr *extfilt;
        u32 filter_mask = 0;
 
-       extfilt = nlmsg_find_attr(cb->nlh, sizeof(struct rtgenmsg),
+       extfilt = nlmsg_find_attr(cb->nlh, sizeof(struct ifinfomsg),
                                  IFLA_EXT_MASK);
        if (extfilt)
                filter_mask = nla_get_u32(extfilt);
index ab3d814..109ee89 100644 (file)
@@ -477,7 +477,7 @@ static u32 esp4_get_mtu(struct xfrm_state *x, int mtu)
        }
 
        return ((mtu - x->props.header_len - crypto_aead_authsize(esp->aead) -
-                net_adj) & ~(align - 1)) + (net_adj - 2);
+                net_adj) & ~(align - 1)) + net_adj - 2;
 }
 
 static void esp4_err(struct sk_buff *skb, u32 info)
index 108a1e9..3df6d3e 100644 (file)
@@ -71,7 +71,6 @@
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/slab.h>
-#include <linux/prefetch.h>
 #include <linux/export.h>
 #include <net/net_namespace.h>
 #include <net/ip.h>
@@ -1761,10 +1760,8 @@ static struct leaf *leaf_walk_rcu(struct tnode *p, struct rt_trie_node *c)
                        if (!c)
                                continue;
 
-                       if (IS_LEAF(c)) {
-                               prefetch(rcu_dereference_rtnl(p->child[idx]));
+                       if (IS_LEAF(c))
                                return (struct leaf *) c;
-                       }
 
                        /* Rescan start scanning in new node */
                        p = (struct tnode *) c;
index 1f6eab6..8d6939e 100644 (file)
@@ -383,7 +383,7 @@ static int ipgre_header(struct sk_buff *skb, struct net_device *dev,
        if (daddr)
                memcpy(&iph->daddr, daddr, 4);
        if (iph->daddr)
-               return t->hlen;
+               return t->hlen + sizeof(*iph);
 
        return -(t->hlen + sizeof(*iph));
 }
index 7167b08..850525b 100644 (file)
@@ -76,9 +76,7 @@ int iptunnel_xmit(struct net *net, struct rtable *rt,
        iph->daddr      =       dst;
        iph->saddr      =       src;
        iph->ttl        =       ttl;
-       tunnel_ip_select_ident(skb,
-                              (const struct iphdr *)skb_inner_network_header(skb),
-                              &rt->dst);
+       __ip_select_ident(iph, &rt->dst, (skb_shinfo(skb)->gso_segs ?: 1) - 1);
 
        err = ip_local_out(skb);
        if (unlikely(net_xmit_eval(err)))
index 6577a11..463bd12 100644 (file)
@@ -273,7 +273,7 @@ static const struct snmp_mib snmp4_net_list[] = {
        SNMP_MIB_ITEM("TCPFastOpenListenOverflow", LINUX_MIB_TCPFASTOPENLISTENOVERFLOW),
        SNMP_MIB_ITEM("TCPFastOpenCookieReqd", LINUX_MIB_TCPFASTOPENCOOKIEREQD),
        SNMP_MIB_ITEM("TCPSpuriousRtxHostQueues", LINUX_MIB_TCPSPURIOUS_RTX_HOSTQUEUES),
-       SNMP_MIB_ITEM("LowLatencyRxPackets", LINUX_MIB_LOWLATENCYRXPACKETS),
+       SNMP_MIB_ITEM("BusyPollRxPackets", LINUX_MIB_BUSYPOLLRXPACKETS),
        SNMP_MIB_SENTINEL
 };
 
index 5423223..b2f6c74 100644 (file)
@@ -1120,6 +1120,13 @@ new_segment:
                                if (!skb)
                                        goto wait_for_memory;
 
+                               /*
+                                * All packets are restored as if they have
+                                * already been sent.
+                                */
+                               if (tp->repair)
+                                       TCP_SKB_CB(skb)->when = tcp_time_stamp;
+
                                /*
                                 * Check whether we can use HW checksum.
                                 */
index a9077f4..b6ae92a 100644 (file)
@@ -206,8 +206,8 @@ static u32 cubic_root(u64 a)
  */
 static inline void bictcp_update(struct bictcp *ca, u32 cwnd)
 {
-       u64 offs;
-       u32 delta, t, bic_target, max_cnt;
+       u32 delta, bic_target, max_cnt;
+       u64 offs, t;
 
        ca->ack_cnt++;  /* count the number of ACKs */
 
@@ -250,9 +250,11 @@ static inline void bictcp_update(struct bictcp *ca, u32 cwnd)
         * if the cwnd < 1 million packets !!!
         */
 
+       t = (s32)(tcp_time_stamp - ca->epoch_start);
+       t += msecs_to_jiffies(ca->delay_min >> 3);
        /* change the unit from HZ to bictcp_HZ */
-       t = ((tcp_time_stamp + msecs_to_jiffies(ca->delay_min>>3)
-             - ca->epoch_start) << BICTCP_HZ) / HZ;
+       t <<= BICTCP_HZ;
+       do_div(t, HZ);
 
        if (t < ca->bic_K)              /* t - K */
                offs = ca->bic_K - t;
@@ -414,7 +416,7 @@ static void bictcp_acked(struct sock *sk, u32 cnt, s32 rtt_us)
                return;
 
        /* Discard delay samples right after fast recovery */
-       if ((s32)(tcp_time_stamp - ca->epoch_start) < HZ)
+       if (ca->epoch_start && (s32)(tcp_time_stamp - ca->epoch_start) < HZ)
                return;
 
        delay = (rtt_us << 3) / USEC_PER_MSEC;
index da4241c..498ea99 100644 (file)
@@ -1126,12 +1126,10 @@ retry:
        if (ifp->flags & IFA_F_OPTIMISTIC)
                addr_flags |= IFA_F_OPTIMISTIC;
 
-       ift = !max_addresses ||
-             ipv6_count_addresses(idev) < max_addresses ?
-               ipv6_add_addr(idev, &addr, NULL, tmp_plen,
-                             ipv6_addr_scope(&addr), addr_flags,
-                             tmp_valid_lft, tmp_prefered_lft) : NULL;
-       if (IS_ERR_OR_NULL(ift)) {
+       ift = ipv6_add_addr(idev, &addr, NULL, tmp_plen,
+                           ipv6_addr_scope(&addr), addr_flags,
+                           tmp_valid_lft, tmp_prefered_lft);
+       if (IS_ERR(ift)) {
                in6_ifa_put(ifp);
                in6_dev_put(idev);
                pr_info("%s: retry temporary address regeneration\n", __func__);
index 40ffd72..aeac0dc 100644 (file)
@@ -425,7 +425,7 @@ static u32 esp6_get_mtu(struct xfrm_state *x, int mtu)
                net_adj = 0;
 
        return ((mtu - x->props.header_len - crypto_aead_authsize(esp->aead) -
-                net_adj) & ~(align - 1)) + (net_adj - 2);
+                net_adj) & ~(align - 1)) + net_adj - 2;
 }
 
 static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
index bff3d82..c4ff5bb 100644 (file)
@@ -993,14 +993,22 @@ static struct fib6_node * fib6_lookup_1(struct fib6_node *root,
 
                        if (ipv6_prefix_equal(&key->addr, args->addr, key->plen)) {
 #ifdef CONFIG_IPV6_SUBTREES
-                               if (fn->subtree)
-                                       fn = fib6_lookup_1(fn->subtree, args + 1);
+                               if (fn->subtree) {
+                                       struct fib6_node *sfn;
+                                       sfn = fib6_lookup_1(fn->subtree,
+                                                           args + 1);
+                                       if (!sfn)
+                                               goto backtrack;
+                                       fn = sfn;
+                               }
 #endif
-                               if (!fn || fn->fn_flags & RTN_RTINFO)
+                               if (fn->fn_flags & RTN_RTINFO)
                                        return fn;
                        }
                }
-
+#ifdef CONFIG_IPV6_SUBTREES
+backtrack:
+#endif
                if (fn->fn_flags & RTN_ROOT)
                        break;
 
index 79aa965..04d31c2 100644 (file)
@@ -1369,8 +1369,10 @@ static void ndisc_redirect_rcv(struct sk_buff *skb)
        if (!ndisc_parse_options(msg->opt, ndoptlen, &ndopts))
                return;
 
-       if (!ndopts.nd_opts_rh)
+       if (!ndopts.nd_opts_rh) {
+               ip6_redirect_no_header(skb, dev_net(skb->dev), 0, 0);
                return;
+       }
 
        hdr = (u8 *)ndopts.nd_opts_rh;
        hdr += 8;
index 790d9f4..1aeb473 100644 (file)
@@ -490,6 +490,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev,
        ipv6_hdr(head)->payload_len = htons(payload_len);
        ipv6_change_dsfield(ipv6_hdr(head), 0xff, ecn);
        IP6CB(head)->nhoff = nhoff;
+       IP6CB(head)->flags |= IP6SKB_FRAGMENTED;
 
        /* Yes, and fold redundant checksum back. 8) */
        if (head->ip_summed == CHECKSUM_COMPLETE)
@@ -524,6 +525,9 @@ static int ipv6_frag_rcv(struct sk_buff *skb)
        struct net *net = dev_net(skb_dst(skb)->dev);
        int evicted;
 
+       if (IP6CB(skb)->flags & IP6SKB_FRAGMENTED)
+               goto fail_hdr;
+
        IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_REASMREQDS);
 
        /* Jumbo payload inhibits frag. header */
@@ -544,6 +548,7 @@ static int ipv6_frag_rcv(struct sk_buff *skb)
                                 ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_REASMOKS);
 
                IP6CB(skb)->nhoff = (u8 *)fhdr - skb_network_header(skb);
+               IP6CB(skb)->flags |= IP6SKB_FRAGMENTED;
                return 1;
        }
 
index b70f897..8d9a93e 100644 (file)
@@ -1178,6 +1178,27 @@ void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark)
 }
 EXPORT_SYMBOL_GPL(ip6_redirect);
 
+void ip6_redirect_no_header(struct sk_buff *skb, struct net *net, int oif,
+                           u32 mark)
+{
+       const struct ipv6hdr *iph = ipv6_hdr(skb);
+       const struct rd_msg *msg = (struct rd_msg *)icmp6_hdr(skb);
+       struct dst_entry *dst;
+       struct flowi6 fl6;
+
+       memset(&fl6, 0, sizeof(fl6));
+       fl6.flowi6_oif = oif;
+       fl6.flowi6_mark = mark;
+       fl6.flowi6_flags = 0;
+       fl6.daddr = msg->dest;
+       fl6.saddr = iph->daddr;
+
+       dst = ip6_route_output(net, NULL, &fl6);
+       if (!dst->error)
+               rt6_do_redirect(dst, NULL, skb);
+       dst_release(dst);
+}
+
 void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk)
 {
        ip6_redirect(skb, sock_net(sk), sk->sk_bound_dev_if, sk->sk_mark);
index ae31968..cc9e02d 100644 (file)
 #include "led.h"
 
 #define IEEE80211_AUTH_TIMEOUT         (HZ / 5)
+#define IEEE80211_AUTH_TIMEOUT_LONG    (HZ / 2)
 #define IEEE80211_AUTH_TIMEOUT_SHORT   (HZ / 10)
 #define IEEE80211_AUTH_MAX_TRIES       3
 #define IEEE80211_AUTH_WAIT_ASSOC      (HZ * 5)
 #define IEEE80211_ASSOC_TIMEOUT                (HZ / 5)
+#define IEEE80211_ASSOC_TIMEOUT_LONG   (HZ / 2)
 #define IEEE80211_ASSOC_TIMEOUT_SHORT  (HZ / 10)
 #define IEEE80211_ASSOC_MAX_TRIES      3
 
@@ -209,8 +211,9 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
                             struct ieee80211_channel *channel,
                             const struct ieee80211_ht_operation *ht_oper,
                             const struct ieee80211_vht_operation *vht_oper,
-                            struct cfg80211_chan_def *chandef, bool verbose)
+                            struct cfg80211_chan_def *chandef, bool tracking)
 {
+       struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
        struct cfg80211_chan_def vht_chandef;
        u32 ht_cfreq, ret;
 
@@ -229,7 +232,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
        ht_cfreq = ieee80211_channel_to_frequency(ht_oper->primary_chan,
                                                  channel->band);
        /* check that channel matches the right operating channel */
-       if (channel->center_freq != ht_cfreq) {
+       if (!tracking && channel->center_freq != ht_cfreq) {
                /*
                 * It's possible that some APs are confused here;
                 * Netgear WNDR3700 sometimes reports 4 higher than
@@ -237,11 +240,10 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
                 * since we look at probe response/beacon data here
                 * it should be OK.
                 */
-               if (verbose)
-                       sdata_info(sdata,
-                                  "Wrong control channel: center-freq: %d ht-cfreq: %d ht->primary_chan: %d band: %d - Disabling HT\n",
-                                  channel->center_freq, ht_cfreq,
-                                  ht_oper->primary_chan, channel->band);
+               sdata_info(sdata,
+                          "Wrong control channel: center-freq: %d ht-cfreq: %d ht->primary_chan: %d band: %d - Disabling HT\n",
+                          channel->center_freq, ht_cfreq,
+                          ht_oper->primary_chan, channel->band);
                ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT;
                goto out;
        }
@@ -295,7 +297,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
                                channel->band);
                break;
        default:
-               if (verbose)
+               if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT))
                        sdata_info(sdata,
                                   "AP VHT operation IE has invalid channel width (%d), disable VHT\n",
                                   vht_oper->chan_width);
@@ -304,7 +306,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
        }
 
        if (!cfg80211_chandef_valid(&vht_chandef)) {
-               if (verbose)
+               if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT))
                        sdata_info(sdata,
                                   "AP VHT information is invalid, disable VHT\n");
                ret = IEEE80211_STA_DISABLE_VHT;
@@ -317,7 +319,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
        }
 
        if (!cfg80211_chandef_compatible(chandef, &vht_chandef)) {
-               if (verbose)
+               if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT))
                        sdata_info(sdata,
                                   "AP VHT information doesn't match HT, disable VHT\n");
                ret = IEEE80211_STA_DISABLE_VHT;
@@ -333,18 +335,27 @@ out:
        if (ret & IEEE80211_STA_DISABLE_VHT)
                vht_chandef = *chandef;
 
+       /*
+        * Ignore the DISABLED flag when we're already connected and only
+        * tracking the APs beacon for bandwidth changes - otherwise we
+        * might get disconnected here if we connect to an AP, update our
+        * regulatory information based on the AP's country IE and the
+        * information we have is wrong/outdated and disables the channel
+        * that we're actually using for the connection to the AP.
+        */
        while (!cfg80211_chandef_usable(sdata->local->hw.wiphy, chandef,
-                                       IEEE80211_CHAN_DISABLED)) {
+                                       tracking ? 0 :
+                                                  IEEE80211_CHAN_DISABLED)) {
                if (WARN_ON(chandef->width == NL80211_CHAN_WIDTH_20_NOHT)) {
                        ret = IEEE80211_STA_DISABLE_HT |
                              IEEE80211_STA_DISABLE_VHT;
-                       goto out;
+                       break;
                }
 
                ret |= chandef_downgrade(chandef);
        }
 
-       if (chandef->width != vht_chandef.width && verbose)
+       if (chandef->width != vht_chandef.width && !tracking)
                sdata_info(sdata,
                           "capabilities/regulatory prevented using AP HT/VHT configuration, downgraded\n");
 
@@ -384,7 +395,7 @@ static int ieee80211_config_bw(struct ieee80211_sub_if_data *sdata,
 
        /* calculate new channel (type) based on HT/VHT operation IEs */
        flags = ieee80211_determine_chantype(sdata, sband, chan, ht_oper,
-                                            vht_oper, &chandef, false);
+                                            vht_oper, &chandef, true);
 
        /*
         * Downgrade the new channel if we associated with restricted
@@ -3394,10 +3405,13 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata)
 
        if (tx_flags == 0) {
                auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
-               ifmgd->auth_data->timeout_started = true;
+               auth_data->timeout_started = true;
                run_again(sdata, auth_data->timeout);
        } else {
-               auth_data->timeout_started = false;
+               auth_data->timeout =
+                       round_jiffies_up(jiffies + IEEE80211_AUTH_TIMEOUT_LONG);
+               auth_data->timeout_started = true;
+               run_again(sdata, auth_data->timeout);
        }
 
        return 0;
@@ -3434,7 +3448,11 @@ static int ieee80211_do_assoc(struct ieee80211_sub_if_data *sdata)
                assoc_data->timeout_started = true;
                run_again(sdata, assoc_data->timeout);
        } else {
-               assoc_data->timeout_started = false;
+               assoc_data->timeout =
+                       round_jiffies_up(jiffies +
+                                        IEEE80211_ASSOC_TIMEOUT_LONG);
+               assoc_data->timeout_started = true;
+               run_again(sdata, assoc_data->timeout);
        }
 
        return 0;
@@ -3829,7 +3847,7 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
        ifmgd->flags |= ieee80211_determine_chantype(sdata, sband,
                                                     cbss->channel,
                                                     ht_oper, vht_oper,
-                                                    &chandef, true);
+                                                    &chandef, false);
 
        sdata->needed_rx_chains = min(ieee80211_ht_vht_rx_chains(sdata, cbss),
                                      local->rx_chains);
index 7dcc376..2f80107 100644 (file)
@@ -526,7 +526,7 @@ static bool tcp_in_window(const struct nf_conn *ct,
        const struct nf_conntrack_tuple *tuple = &ct->tuplehash[dir].tuple;
        __u32 seq, ack, sack, end, win, swin;
        s16 receiver_offset;
-       bool res;
+       bool res, in_recv_win;
 
        /*
         * Get the required data from the packet.
@@ -649,14 +649,18 @@ static bool tcp_in_window(const struct nf_conn *ct,
                 receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
                 receiver->td_scale);
 
+       /* Is the ending sequence in the receive window (if available)? */
+       in_recv_win = !receiver->td_maxwin ||
+                     after(end, sender->td_end - receiver->td_maxwin - 1);
+
        pr_debug("tcp_in_window: I=%i II=%i III=%i IV=%i\n",
                 before(seq, sender->td_maxend + 1),
-                after(end, sender->td_end - receiver->td_maxwin - 1),
+                (in_recv_win ? 1 : 0),
                 before(sack, receiver->td_end + 1),
                 after(sack, receiver->td_end - MAXACKWINDOW(sender) - 1));
 
        if (before(seq, sender->td_maxend + 1) &&
-           after(end, sender->td_end - receiver->td_maxwin - 1) &&
+           in_recv_win &&
            before(sack, receiver->td_end + 1) &&
            after(sack, receiver->td_end - MAXACKWINDOW(sender) - 1)) {
                /*
@@ -725,7 +729,7 @@ static bool tcp_in_window(const struct nf_conn *ct,
                        nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
                        "nf_ct_tcp: %s ",
                        before(seq, sender->td_maxend + 1) ?
-                       after(end, sender->td_end - receiver->td_maxwin - 1) ?
+                       in_recv_win ?
                        before(sack, receiver->td_end + 1) ?
                        after(sack, receiver->td_end - MAXACKWINDOW(sender) - 1) ? "BUG"
                        : "ACK is under the lower bound (possible overly delayed ACK)"
index 962e979..d92cc31 100644 (file)
@@ -419,6 +419,7 @@ __build_packet_message(struct nfnl_log_net *log,
        nfmsg->version = NFNETLINK_V0;
        nfmsg->res_id = htons(inst->group_num);
 
+       memset(&pmsg, 0, sizeof(pmsg));
        pmsg.hw_protocol        = skb->protocol;
        pmsg.hook               = hooknum;
 
@@ -498,7 +499,10 @@ __build_packet_message(struct nfnl_log_net *log,
        if (indev && skb->dev &&
            skb->mac_header != skb->network_header) {
                struct nfulnl_msg_packet_hw phw;
-               int len = dev_parse_header(skb, phw.hw_addr);
+               int len;
+
+               memset(&phw, 0, sizeof(phw));
+               len = dev_parse_header(skb, phw.hw_addr);
                if (len > 0) {
                        phw.hw_addrlen = htons(len);
                        if (nla_put(inst->skb, NFULA_HWADDR, sizeof(phw), &phw))
index 971ea14..8a703c3 100644 (file)
@@ -463,7 +463,10 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
        if (indev && entskb->dev &&
            entskb->mac_header != entskb->network_header) {
                struct nfqnl_msg_packet_hw phw;
-               int len = dev_parse_header(entskb, phw.hw_addr);
+               int len;
+
+               memset(&phw, 0, sizeof(phw));
+               len = dev_parse_header(entskb, phw.hw_addr);
                if (len) {
                        phw.hw_addrlen = htons(len);
                        if (nla_put(skb, NFQA_HWADDR, sizeof(phw), &phw))
index 7011c71..6113cc7 100644 (file)
@@ -52,7 +52,8 @@ tcpmss_mangle_packet(struct sk_buff *skb,
 {
        const struct xt_tcpmss_info *info = par->targinfo;
        struct tcphdr *tcph;
-       unsigned int tcplen, i;
+       int len, tcp_hdrlen;
+       unsigned int i;
        __be16 oldval;
        u16 newmss;
        u8 *opt;
@@ -64,11 +65,14 @@ tcpmss_mangle_packet(struct sk_buff *skb,
        if (!skb_make_writable(skb, skb->len))
                return -1;
 
-       tcplen = skb->len - tcphoff;
+       len = skb->len - tcphoff;
+       if (len < (int)sizeof(struct tcphdr))
+               return -1;
+
        tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff);
+       tcp_hdrlen = tcph->doff * 4;
 
-       /* Header cannot be larger than the packet */
-       if (tcplen < tcph->doff*4)
+       if (len < tcp_hdrlen)
                return -1;
 
        if (info->mss == XT_TCPMSS_CLAMP_PMTU) {
@@ -87,9 +91,8 @@ tcpmss_mangle_packet(struct sk_buff *skb,
                newmss = info->mss;
 
        opt = (u_int8_t *)tcph;
-       for (i = sizeof(struct tcphdr); i < tcph->doff*4; i += optlen(opt, i)) {
-               if (opt[i] == TCPOPT_MSS && tcph->doff*4 - i >= TCPOLEN_MSS &&
-                   opt[i+1] == TCPOLEN_MSS) {
+       for (i = sizeof(struct tcphdr); i <= tcp_hdrlen - TCPOLEN_MSS; i += optlen(opt, i)) {
+               if (opt[i] == TCPOPT_MSS && opt[i+1] == TCPOLEN_MSS) {
                        u_int16_t oldmss;
 
                        oldmss = (opt[i+2] << 8) | opt[i+3];
@@ -112,9 +115,10 @@ tcpmss_mangle_packet(struct sk_buff *skb,
        }
 
        /* There is data after the header so the option can't be added
-          without moving it, and doing so may make the SYN packet
-          itself too large. Accept the packet unmodified instead. */
-       if (tcplen > tcph->doff*4)
+        * without moving it, and doing so may make the SYN packet
+        * itself too large. Accept the packet unmodified instead.
+        */
+       if (len > tcp_hdrlen)
                return 0;
 
        /*
@@ -143,10 +147,10 @@ tcpmss_mangle_packet(struct sk_buff *skb,
                newmss = min(newmss, (u16)1220);
 
        opt = (u_int8_t *)tcph + sizeof(struct tcphdr);
-       memmove(opt + TCPOLEN_MSS, opt, tcplen - sizeof(struct tcphdr));
+       memmove(opt + TCPOLEN_MSS, opt, len - sizeof(struct tcphdr));
 
        inet_proto_csum_replace2(&tcph->check, skb,
-                                htons(tcplen), htons(tcplen + TCPOLEN_MSS), 1);
+                                htons(len), htons(len + TCPOLEN_MSS), 1);
        opt[0] = TCPOPT_MSS;
        opt[1] = TCPOLEN_MSS;
        opt[2] = (newmss & 0xff00) >> 8;
index b68fa19..625fa1d 100644 (file)
@@ -38,7 +38,7 @@ tcpoptstrip_mangle_packet(struct sk_buff *skb,
        struct tcphdr *tcph;
        u_int16_t n, o;
        u_int8_t *opt;
-       int len;
+       int len, tcp_hdrlen;
 
        /* This is a fragment, no TCP header is available */
        if (par->fragoff != 0)
@@ -52,7 +52,9 @@ tcpoptstrip_mangle_packet(struct sk_buff *skb,
                return NF_DROP;
 
        tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff);
-       if (tcph->doff * 4 > len)
+       tcp_hdrlen = tcph->doff * 4;
+
+       if (len < tcp_hdrlen)
                return NF_DROP;
 
        opt  = (u_int8_t *)tcph;
@@ -61,10 +63,10 @@ tcpoptstrip_mangle_packet(struct sk_buff *skb,
         * Walk through all TCP options - if we find some option to remove,
         * set all octets to %TCPOPT_NOP and adjust checksum.
         */
-       for (i = sizeof(struct tcphdr); i < tcp_hdrlen(skb); i += optl) {
+       for (i = sizeof(struct tcphdr); i < tcp_hdrlen - 1; i += optl) {
                optl = optlen(opt, i);
 
-               if (i + optl > tcp_hdrlen(skb))
+               if (i + optl > tcp_hdrlen)
                        break;
 
                if (!tcpoptstrip_test_bit(info->strip_bmap, opt[i]))
index 22c5f39..ab101f7 100644 (file)
@@ -535,6 +535,7 @@ int ovs_execute_actions(struct datapath *dp, struct sk_buff *skb)
 {
        struct sw_flow_actions *acts = rcu_dereference(OVS_CB(skb)->flow->sf_acts);
 
+       OVS_CB(skb)->tun_key = NULL;
        return do_execute_actions(dp, skb, acts->actions,
                                         acts->actions_len, false);
 }
index f7e3a0d..f2ed760 100644 (file)
@@ -2076,9 +2076,6 @@ static int ovs_vport_cmd_set(struct sk_buff *skb, struct genl_info *info)
        ovs_notify(reply, info, &ovs_dp_vport_multicast_group);
        return 0;
 
-       rtnl_unlock();
-       return 0;
-
 exit_free:
        kfree_skb(reply);
 exit_unlock:
index 5c519b1..1aa84dc 100644 (file)
@@ -240,7 +240,7 @@ static struct flex_array *alloc_buckets(unsigned int n_buckets)
        struct flex_array *buckets;
        int i, err;
 
-       buckets = flex_array_alloc(sizeof(struct hlist_head *),
+       buckets = flex_array_alloc(sizeof(struct hlist_head),
                                   n_buckets, GFP_KERNEL);
        if (!buckets)
                return NULL;
index 4b66c75..75c8bbf 100644 (file)
@@ -3259,9 +3259,11 @@ static int packet_getsockopt(struct socket *sock, int level, int optname,
 
                if (po->tp_version == TPACKET_V3) {
                        lv = sizeof(struct tpacket_stats_v3);
+                       st.stats3.tp_packets += st.stats3.tp_drops;
                        data = &st.stats3;
                } else {
                        lv = sizeof(struct tpacket_stats);
+                       st.stats1.tp_packets += st.stats1.tp_drops;
                        data = &st.stats1;
                }
 
index 281c1bd..51b968d 100644 (file)
@@ -285,6 +285,45 @@ static struct Qdisc_ops *qdisc_lookup_ops(struct nlattr *kind)
        return q;
 }
 
+/* The linklayer setting were not transferred from iproute2, in older
+ * versions, and the rate tables lookup systems have been dropped in
+ * the kernel. To keep backward compatible with older iproute2 tc
+ * utils, we detect the linklayer setting by detecting if the rate
+ * table were modified.
+ *
+ * For linklayer ATM table entries, the rate table will be aligned to
+ * 48 bytes, thus some table entries will contain the same value.  The
+ * mpu (min packet unit) is also encoded into the old rate table, thus
+ * starting from the mpu, we find low and high table entries for
+ * mapping this cell.  If these entries contain the same value, when
+ * the rate tables have been modified for linklayer ATM.
+ *
+ * This is done by rounding mpu to the nearest 48 bytes cell/entry,
+ * and then roundup to the next cell, calc the table entry one below,
+ * and compare.
+ */
+static __u8 __detect_linklayer(struct tc_ratespec *r, __u32 *rtab)
+{
+       int low       = roundup(r->mpu, 48);
+       int high      = roundup(low+1, 48);
+       int cell_low  = low >> r->cell_log;
+       int cell_high = (high >> r->cell_log) - 1;
+
+       /* rtab is too inaccurate at rates > 100Mbit/s */
+       if ((r->rate > (100000000/8)) || (rtab[0] == 0)) {
+               pr_debug("TC linklayer: Giving up ATM detection\n");
+               return TC_LINKLAYER_ETHERNET;
+       }
+
+       if ((cell_high > cell_low) && (cell_high < 256)
+           && (rtab[cell_low] == rtab[cell_high])) {
+               pr_debug("TC linklayer: Detected ATM, low(%d)=high(%d)=%u\n",
+                        cell_low, cell_high, rtab[cell_high]);
+               return TC_LINKLAYER_ATM;
+       }
+       return TC_LINKLAYER_ETHERNET;
+}
+
 static struct qdisc_rate_table *qdisc_rtab_list;
 
 struct qdisc_rate_table *qdisc_get_rtab(struct tc_ratespec *r, struct nlattr *tab)
@@ -308,6 +347,8 @@ struct qdisc_rate_table *qdisc_get_rtab(struct tc_ratespec *r, struct nlattr *ta
                rtab->rate = *r;
                rtab->refcnt = 1;
                memcpy(rtab->data, nla_data(tab), 1024);
+               if (r->linklayer == TC_LINKLAYER_UNAWARE)
+                       r->linklayer = __detect_linklayer(r, rtab->data);
                rtab->next = qdisc_rtab_list;
                qdisc_rtab_list = rtab;
        }
index 4626cef..48be3d5 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/rcupdate.h>
 #include <linux/list.h>
 #include <linux/slab.h>
+#include <linux/if_vlan.h>
 #include <net/sch_generic.h>
 #include <net/pkt_sched.h>
 #include <net/dst.h>
@@ -207,15 +208,19 @@ void __qdisc_run(struct Qdisc *q)
 
 unsigned long dev_trans_start(struct net_device *dev)
 {
-       unsigned long val, res = dev->trans_start;
+       unsigned long val, res;
        unsigned int i;
 
+       if (is_vlan_dev(dev))
+               dev = vlan_dev_real_dev(dev);
+       res = dev->trans_start;
        for (i = 0; i < dev->num_tx_queues; i++) {
                val = netdev_get_tx_queue(dev, i)->trans_start;
                if (val && time_after(val, res))
                        res = val;
        }
        dev->trans_start = res;
+
        return res;
 }
 EXPORT_SYMBOL(dev_trans_start);
@@ -904,6 +909,7 @@ void psched_ratecfg_precompute(struct psched_ratecfg *r,
        memset(r, 0, sizeof(*r));
        r->overhead = conf->overhead;
        r->rate_bytes_ps = conf->rate;
+       r->linklayer = (conf->linklayer & TC_LINKLAYER_MASK);
        r->mult = 1;
        /*
         * The deal here is to replace a divide by a reciprocal one
index 45e7515..c2178b1 100644 (file)
@@ -1329,6 +1329,7 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
        struct htb_sched *q = qdisc_priv(sch);
        struct htb_class *cl = (struct htb_class *)*arg, *parent;
        struct nlattr *opt = tca[TCA_OPTIONS];
+       struct qdisc_rate_table *rtab = NULL, *ctab = NULL;
        struct nlattr *tb[TCA_HTB_MAX + 1];
        struct tc_htb_opt *hopt;
 
@@ -1350,6 +1351,18 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
        if (!hopt->rate.rate || !hopt->ceil.rate)
                goto failure;
 
+       /* Keeping backward compatible with rate_table based iproute2 tc */
+       if (hopt->rate.linklayer == TC_LINKLAYER_UNAWARE) {
+               rtab = qdisc_get_rtab(&hopt->rate, tb[TCA_HTB_RTAB]);
+               if (rtab)
+                       qdisc_put_rtab(rtab);
+       }
+       if (hopt->ceil.linklayer == TC_LINKLAYER_UNAWARE) {
+               ctab = qdisc_get_rtab(&hopt->ceil, tb[TCA_HTB_CTAB]);
+               if (ctab)
+                       qdisc_put_rtab(ctab);
+       }
+
        if (!cl) {              /* new class */
                struct Qdisc *new_q;
                int prio;
index bce5b79..ab67efc 100644 (file)
@@ -846,12 +846,12 @@ void sctp_assoc_control_transport(struct sctp_association *asoc,
                else
                        spc_state = SCTP_ADDR_AVAILABLE;
                /* Don't inform ULP about transition from PF to
-                * active state and set cwnd to 1, see SCTP
+                * active state and set cwnd to 1 MTU, see SCTP
                 * Quick failover draft section 5.1, point 5
                 */
                if (transport->state == SCTP_PF) {
                        ulp_notify = false;
-                       transport->cwnd = 1;
+                       transport->cwnd = asoc->pathmtu;
                }
                transport->state = SCTP_ACTIVE;
                break;
index bdbbc3f..8fdd160 100644 (file)
@@ -181,12 +181,12 @@ static void sctp_transport_destroy(struct sctp_transport *transport)
                return;
        }
 
-       call_rcu(&transport->rcu, sctp_transport_destroy_rcu);
-
        sctp_packet_free(&transport->packet);
 
        if (transport->asoc)
                sctp_association_put(transport->asoc);
+
+       call_rcu(&transport->rcu, sctp_transport_destroy_rcu);
 }
 
 /* Start T3_rtx timer if it is not already running and update the heartbeat
index cb29ef7..609c30c 100644 (file)
@@ -460,6 +460,7 @@ static void bearer_disable(struct tipc_bearer *b_ptr)
 {
        struct tipc_link *l_ptr;
        struct tipc_link *temp_l_ptr;
+       struct tipc_link_req *temp_req;
 
        pr_info("Disabling bearer <%s>\n", b_ptr->name);
        spin_lock_bh(&b_ptr->lock);
@@ -468,9 +469,13 @@ static void bearer_disable(struct tipc_bearer *b_ptr)
        list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) {
                tipc_link_delete(l_ptr);
        }
-       if (b_ptr->link_req)
-               tipc_disc_delete(b_ptr->link_req);
+       temp_req = b_ptr->link_req;
+       b_ptr->link_req = NULL;
        spin_unlock_bh(&b_ptr->lock);
+
+       if (temp_req)
+               tipc_disc_delete(temp_req);
+
        memset(b_ptr, 0, sizeof(struct tipc_bearer));
 }
 
index 593071d..4d93346 100644 (file)
@@ -347,7 +347,7 @@ void vsock_for_each_connected_socket(void (*fn)(struct sock *sk))
        for (i = 0; i < ARRAY_SIZE(vsock_connected_table); i++) {
                struct vsock_sock *vsk;
                list_for_each_entry(vsk, &vsock_connected_table[i],
-                                   connected_table);
+                                   connected_table)
                        fn(sk_vsock(vsk));
        }
 
index 4f9f216..a8c29fa 100644 (file)
@@ -765,6 +765,7 @@ void cfg80211_leave(struct cfg80211_registered_device *rdev,
                cfg80211_leave_mesh(rdev, dev);
                break;
        case NL80211_IFTYPE_AP:
+       case NL80211_IFTYPE_P2P_GO:
                cfg80211_stop_ap(rdev, dev);
                break;
        default:
index 25d217d..5f6e982 100644 (file)
@@ -441,10 +441,12 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb,
                        goto out_unlock;
                }
                *rdev = wiphy_to_dev((*wdev)->wiphy);
-               cb->args[0] = (*rdev)->wiphy_idx;
+               /* 0 is the first index - add 1 to parse only once */
+               cb->args[0] = (*rdev)->wiphy_idx + 1;
                cb->args[1] = (*wdev)->identifier;
        } else {
-               struct wiphy *wiphy = wiphy_idx_to_wiphy(cb->args[0]);
+               /* subtract the 1 again here */
+               struct wiphy *wiphy = wiphy_idx_to_wiphy(cb->args[0] - 1);
                struct wireless_dev *tmp;
 
                if (!wiphy) {
@@ -2620,8 +2622,8 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
 
        hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
                             NL80211_CMD_NEW_KEY);
-       if (IS_ERR(hdr))
-               return PTR_ERR(hdr);
+       if (!hdr)
+               return -ENOBUFS;
 
        cookie.msg = msg;
        cookie.idx = key_idx;
@@ -6505,6 +6507,9 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
                                           NL80211_CMD_TESTMODE);
                struct nlattr *tmdata;
 
+               if (!hdr)
+                       break;
+
                if (nla_put_u32(skb, NL80211_ATTR_WIPHY, phy_idx)) {
                        genlmsg_cancel(skb, hdr);
                        break;
@@ -6949,9 +6954,8 @@ static int nl80211_remain_on_channel(struct sk_buff *skb,
 
        hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
                             NL80211_CMD_REMAIN_ON_CHANNEL);
-
-       if (IS_ERR(hdr)) {
-               err = PTR_ERR(hdr);
+       if (!hdr) {
+               err = -ENOBUFS;
                goto free_msg;
        }
 
@@ -7249,9 +7253,8 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
 
                hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
                                     NL80211_CMD_FRAME);
-
-               if (IS_ERR(hdr)) {
-                       err = PTR_ERR(hdr);
+               if (!hdr) {
+                       err = -ENOBUFS;
                        goto free_msg;
                }
        }
@@ -8130,9 +8133,8 @@ static int nl80211_probe_client(struct sk_buff *skb,
 
        hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
                             NL80211_CMD_PROBE_CLIENT);
-
-       if (IS_ERR(hdr)) {
-               err = PTR_ERR(hdr);
+       if (!hdr) {
+               err = -ENOBUFS;
                goto free_msg;
        }
 
index 81c8a10..20e86a9 100644 (file)
@@ -976,21 +976,19 @@ int cfg80211_disconnect(struct cfg80211_registered_device *rdev,
                        struct net_device *dev, u16 reason, bool wextev)
 {
        struct wireless_dev *wdev = dev->ieee80211_ptr;
-       int err;
+       int err = 0;
 
        ASSERT_WDEV_LOCK(wdev);
 
        kfree(wdev->connect_keys);
        wdev->connect_keys = NULL;
 
-       if (wdev->conn) {
+       if (wdev->conn)
                err = cfg80211_sme_disconnect(wdev, reason);
-       } else if (!rdev->ops->disconnect) {
+       else if (!rdev->ops->disconnect)
                cfg80211_mlme_down(rdev, dev);
-               err = 0;
-       } else {
+       else if (wdev->current_bss)
                err = rdev_disconnect(rdev, dev, reason);
-       }
 
        return err;
 }
index 8e77cbb..e3c7ba8 100644 (file)
@@ -522,7 +522,7 @@ static bool same_amp_caps(struct hda_codec *codec, hda_nid_t nid1,
 }
 
 #define nid_has_mute(codec, nid, dir) \
-       check_amp_caps(codec, nid, dir, AC_AMPCAP_MUTE)
+       check_amp_caps(codec, nid, dir, (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE))
 #define nid_has_volume(codec, nid, dir) \
        check_amp_caps(codec, nid, dir, AC_AMPCAP_NUM_STEPS)
 
@@ -624,7 +624,7 @@ static int get_amp_val_to_activate(struct hda_codec *codec, hda_nid_t nid,
                if (enable)
                        val = (caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT;
        }
-       if (caps & AC_AMPCAP_MUTE) {
+       if (caps & (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE)) {
                if (!enable)
                        val |= HDA_AMP_MUTE;
        }
@@ -648,7 +648,7 @@ static unsigned int get_amp_mask_to_modify(struct hda_codec *codec,
 {
        unsigned int mask = 0xff;
 
-       if (caps & AC_AMPCAP_MUTE) {
+       if (caps & (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE)) {
                if (is_ctl_associated(codec, nid, dir, idx, NID_PATH_MUTE_CTL))
                        mask &= ~0x80;
        }
index 8bd2261..f303cd8 100644 (file)
@@ -1031,6 +1031,7 @@ enum {
        ALC880_FIXUP_GPIO2,
        ALC880_FIXUP_MEDION_RIM,
        ALC880_FIXUP_LG,
+       ALC880_FIXUP_LG_LW25,
        ALC880_FIXUP_W810,
        ALC880_FIXUP_EAPD_COEF,
        ALC880_FIXUP_TCL_S700,
@@ -1089,6 +1090,14 @@ static const struct hda_fixup alc880_fixups[] = {
                        { }
                }
        },
+       [ALC880_FIXUP_LG_LW25] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = (const struct hda_pintbl[]) {
+                       { 0x1a, 0x0181344f }, /* line-in */
+                       { 0x1b, 0x0321403f }, /* headphone */
+                       { }
+               }
+       },
        [ALC880_FIXUP_W810] = {
                .type = HDA_FIXUP_PINS,
                .v.pins = (const struct hda_pintbl[]) {
@@ -1341,6 +1350,7 @@ static const struct snd_pci_quirk alc880_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_FIXUP_LG),
        SND_PCI_QUIRK(0x1854, 0x005f, "LG P1 Express", ALC880_FIXUP_LG),
        SND_PCI_QUIRK(0x1854, 0x0068, "LG w1", ALC880_FIXUP_LG),
+       SND_PCI_QUIRK(0x1854, 0x0077, "LG LW25", ALC880_FIXUP_LG_LW25),
        SND_PCI_QUIRK(0x19db, 0x4188, "TCL S700", ALC880_FIXUP_TCL_S700),
 
        /* Below is the copied entries from alc880_quirks.c.
@@ -4329,6 +4339,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = {
        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),
+       SND_PCI_QUIRK(0x1025, 0x034a, "Gateway LT27", ALC662_FIXUP_INV_DMIC),
        SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE),
        SND_PCI_QUIRK(0x1028, 0x05d8, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x05db, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
index 987f728..be2ba1b 100644 (file)
@@ -195,6 +195,8 @@ static DECLARE_TLV_DB_SCALE(pga_tlv, -600, 50, 0);
 
 static DECLARE_TLV_DB_SCALE(mix_tlv, -50, 50, 0);
 
+static DECLARE_TLV_DB_SCALE(beep_tlv, -56, 200, 0);
+
 static const unsigned int limiter_tlv[] = {
        TLV_DB_RANGE_HEAD(2),
        0, 2, TLV_DB_SCALE_ITEM(-3000, 600, 0),
@@ -451,7 +453,8 @@ static const struct snd_kcontrol_new cs42l52_snd_controls[] = {
        SOC_ENUM("Beep Pitch", beep_pitch_enum),
        SOC_ENUM("Beep on Time", beep_ontime_enum),
        SOC_ENUM("Beep off Time", beep_offtime_enum),
-       SOC_SINGLE_TLV("Beep Volume", CS42L52_BEEP_VOL, 0, 0x1f, 0x07, hl_tlv),
+       SOC_SINGLE_SX_TLV("Beep Volume", CS42L52_BEEP_VOL,
+                       0, 0x07, 0x1f, beep_tlv),
        SOC_SINGLE("Beep Mixer Switch", CS42L52_BEEP_TONE_CTL, 5, 1, 1),
        SOC_ENUM("Beep Treble Corner Freq", beep_treble_enum),
        SOC_ENUM("Beep Bass Corner Freq", beep_bass_enum),
index 6c8a9e7..760e8bf 100644 (file)
@@ -153,6 +153,8 @@ static int mic_bias_event(struct snd_soc_dapm_widget *w,
 static int power_vag_event(struct snd_soc_dapm_widget *w,
        struct snd_kcontrol *kcontrol, int event)
 {
+       const u32 mask = SGTL5000_DAC_POWERUP | SGTL5000_ADC_POWERUP;
+
        switch (event) {
        case SND_SOC_DAPM_POST_PMU:
                snd_soc_update_bits(w->codec, SGTL5000_CHIP_ANA_POWER,
@@ -160,9 +162,17 @@ static int power_vag_event(struct snd_soc_dapm_widget *w,
                break;
 
        case SND_SOC_DAPM_PRE_PMD:
-               snd_soc_update_bits(w->codec, SGTL5000_CHIP_ANA_POWER,
-                       SGTL5000_VAG_POWERUP, 0);
-               msleep(400);
+               /*
+                * Don't clear VAG_POWERUP, when both DAC and ADC are
+                * operational to prevent inadvertently starving the
+                * other one of them.
+                */
+               if ((snd_soc_read(w->codec, SGTL5000_CHIP_ANA_POWER) &
+                               mask) != mask) {
+                       snd_soc_update_bits(w->codec, SGTL5000_CHIP_ANA_POWER,
+                               SGTL5000_VAG_POWERUP, 0);
+                       msleep(400);
+               }
                break;
        default:
                break;
@@ -388,7 +398,7 @@ static const struct snd_kcontrol_new sgtl5000_snd_controls[] = {
        SOC_DOUBLE("Capture Volume", SGTL5000_CHIP_ANA_ADC_CTRL, 0, 4, 0xf, 0),
        SOC_SINGLE_TLV("Capture Attenuate Switch (-6dB)",
                        SGTL5000_CHIP_ANA_ADC_CTRL,
-                       8, 2, 0, capture_6db_attenuate),
+                       8, 1, 0, capture_6db_attenuate),
        SOC_SINGLE("Capture ZC Switch", SGTL5000_CHIP_ANA_CTRL, 1, 1, 0),
 
        SOC_DOUBLE_TLV("Headphone Playback Volume",
index bd16010..4375c9f 100644 (file)
@@ -679,13 +679,14 @@ static int dapm_new_mux(struct snd_soc_dapm_widget *w)
                return -EINVAL;
        }
 
-       path = list_first_entry(&w->sources, struct snd_soc_dapm_path,
-                               list_sink);
-       if (!path) {
+       if (list_empty(&w->sources)) {
                dev_err(dapm->dev, "ASoC: mux %s has no paths\n", w->name);
                return -EINVAL;
        }
 
+       path = list_first_entry(&w->sources, struct snd_soc_dapm_path,
+                               list_sink);
+
        ret = dapm_create_or_share_mixmux_kcontrol(w, 0, path);
        if (ret < 0)
                return ret;
index d04146c..47565fd 100644 (file)
@@ -228,7 +228,7 @@ static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream,
                reg = TEGRA30_I2S_CIF_RX_CTRL;
        } else {
                val |= TEGRA30_AUDIOCIF_CTRL_DIRECTION_TX;
-               reg = TEGRA30_I2S_CIF_RX_CTRL;
+               reg = TEGRA30_I2S_CIF_TX_CTRL;
        }
 
        regmap_write(i2s->regmap, reg, val);
index 2672242..f3dd726 100644 (file)
 #include "chip.h"
 #include "comm.h"
 
+enum {
+       MIDI_BUFSIZE = 64
+};
+
 static void usb6fire_midi_out_handler(struct urb *urb)
 {
        struct midi_runtime *rt = urb->context;
@@ -156,6 +160,12 @@ int usb6fire_midi_init(struct sfire_chip *chip)
        if (!rt)
                return -ENOMEM;
 
+       rt->out_buffer = kzalloc(MIDI_BUFSIZE, GFP_KERNEL);
+       if (!rt->out_buffer) {
+               kfree(rt);
+               return -ENOMEM;
+       }
+
        rt->chip = chip;
        rt->in_received = usb6fire_midi_in_received;
        rt->out_buffer[0] = 0x80; /* 'send midi' command */
@@ -169,6 +179,7 @@ int usb6fire_midi_init(struct sfire_chip *chip)
 
        ret = snd_rawmidi_new(chip->card, "6FireUSB", 0, 1, 1, &rt->instance);
        if (ret < 0) {
+               kfree(rt->out_buffer);
                kfree(rt);
                snd_printk(KERN_ERR PREFIX "unable to create midi.\n");
                return ret;
@@ -197,6 +208,9 @@ void usb6fire_midi_abort(struct sfire_chip *chip)
 
 void usb6fire_midi_destroy(struct sfire_chip *chip)
 {
-       kfree(chip->midi);
+       struct midi_runtime *rt = chip->midi;
+
+       kfree(rt->out_buffer);
+       kfree(rt);
        chip->midi = NULL;
 }
index c321006..84851b9 100644 (file)
 
 #include "common.h"
 
-enum {
-       MIDI_BUFSIZE = 64
-};
-
 struct midi_runtime {
        struct sfire_chip *chip;
        struct snd_rawmidi *instance;
@@ -32,7 +28,7 @@ struct midi_runtime {
        struct snd_rawmidi_substream *out;
        struct urb out_urb;
        u8 out_serial; /* serial number of out packet */
-       u8 out_buffer[MIDI_BUFSIZE];
+       u8 *out_buffer;
        int buffer_offset;
 
        void (*in_received)(struct midi_runtime *rt, u8 *data, int length);
index 3d2551c..b5eb97f 100644 (file)
@@ -582,6 +582,33 @@ static void usb6fire_pcm_init_urb(struct pcm_urb *urb,
        urb->instance.number_of_packets = PCM_N_PACKETS_PER_URB;
 }
 
+static int usb6fire_pcm_buffers_init(struct pcm_runtime *rt)
+{
+       int i;
+
+       for (i = 0; i < PCM_N_URBS; i++) {
+               rt->out_urbs[i].buffer = kzalloc(PCM_N_PACKETS_PER_URB
+                               * PCM_MAX_PACKET_SIZE, GFP_KERNEL);
+               if (!rt->out_urbs[i].buffer)
+                       return -ENOMEM;
+               rt->in_urbs[i].buffer = kzalloc(PCM_N_PACKETS_PER_URB
+                               * PCM_MAX_PACKET_SIZE, GFP_KERNEL);
+               if (!rt->in_urbs[i].buffer)
+                       return -ENOMEM;
+       }
+       return 0;
+}
+
+static void usb6fire_pcm_buffers_destroy(struct pcm_runtime *rt)
+{
+       int i;
+
+       for (i = 0; i < PCM_N_URBS; i++) {
+               kfree(rt->out_urbs[i].buffer);
+               kfree(rt->in_urbs[i].buffer);
+       }
+}
+
 int usb6fire_pcm_init(struct sfire_chip *chip)
 {
        int i;
@@ -593,6 +620,13 @@ int usb6fire_pcm_init(struct sfire_chip *chip)
        if (!rt)
                return -ENOMEM;
 
+       ret = usb6fire_pcm_buffers_init(rt);
+       if (ret) {
+               usb6fire_pcm_buffers_destroy(rt);
+               kfree(rt);
+               return ret;
+       }
+
        rt->chip = chip;
        rt->stream_state = STREAM_DISABLED;
        rt->rate = ARRAY_SIZE(rates);
@@ -614,6 +648,7 @@ int usb6fire_pcm_init(struct sfire_chip *chip)
 
        ret = snd_pcm_new(chip->card, "DMX6FireUSB", 0, 1, 1, &pcm);
        if (ret < 0) {
+               usb6fire_pcm_buffers_destroy(rt);
                kfree(rt);
                snd_printk(KERN_ERR PREFIX "cannot create pcm instance.\n");
                return ret;
@@ -625,6 +660,7 @@ int usb6fire_pcm_init(struct sfire_chip *chip)
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcm_ops);
 
        if (ret) {
+               usb6fire_pcm_buffers_destroy(rt);
                kfree(rt);
                snd_printk(KERN_ERR PREFIX
                                "error preallocating pcm buffers.\n");
@@ -669,6 +705,9 @@ void usb6fire_pcm_abort(struct sfire_chip *chip)
 
 void usb6fire_pcm_destroy(struct sfire_chip *chip)
 {
-       kfree(chip->pcm);
+       struct pcm_runtime *rt = chip->pcm;
+
+       usb6fire_pcm_buffers_destroy(rt);
+       kfree(rt);
        chip->pcm = NULL;
 }
index 9b01133..f5779d6 100644 (file)
@@ -32,7 +32,7 @@ struct pcm_urb {
        struct urb instance;
        struct usb_iso_packet_descriptor packets[PCM_N_PACKETS_PER_URB];
        /* END DO NOT SEPARATE */
-       u8 buffer[PCM_N_PACKETS_PER_URB * PCM_MAX_PACKET_SIZE];
+       u8 *buffer;
 
        struct pcm_urb *peer;
 };
index d543808..95558ef 100644 (file)
@@ -888,6 +888,7 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval,
        case USB_ID(0x046d, 0x081b): /* HD Webcam c310 */
        case USB_ID(0x046d, 0x081d): /* HD Webcam c510 */
        case USB_ID(0x046d, 0x0825): /* HD Webcam c270 */
+       case USB_ID(0x046d, 0x0826): /* HD Webcam c525 */
        case USB_ID(0x046d, 0x0991):
        /* Most audio usb devices lie about volume resolution.
         * Most Logitech webcams have res = 384.
index 1bc45e7..0df9ede 100644 (file)
@@ -319,19 +319,19 @@ static int create_auto_midi_quirk(struct snd_usb_audio *chip,
        if (altsd->bNumEndpoints < 1)
                return -ENODEV;
        epd = get_endpoint(alts, 0);
-       if (!usb_endpoint_xfer_bulk(epd) ||
+       if (!usb_endpoint_xfer_bulk(epd) &&
            !usb_endpoint_xfer_int(epd))
                return -ENODEV;
 
        switch (USB_ID_VENDOR(chip->usb_id)) {
        case 0x0499: /* Yamaha */
                err = create_yamaha_midi_quirk(chip, iface, driver, alts);
-               if (err < 0 && err != -ENODEV)
+               if (err != -ENODEV)
                        return err;
                break;
        case 0x0582: /* Roland */
                err = create_roland_midi_quirk(chip, iface, driver, alts);
-               if (err < 0 && err != -ENODEV)
+               if (err != -ENODEV)
                        return err;
                break;
        }