summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/vfio.txt2
-rw-r--r--MAINTAINERS14
-rw-r--r--Makefile4
-rw-r--r--arch/arm/boot/compressed/head.S1
-rw-r--r--arch/arm/boot/dts/at91sam9260.dtsi3
-rw-r--r--arch/arm/boot/dts/at91sam9263.dtsi5
-rw-r--r--arch/arm/boot/dts/at91sam9g45.dtsi5
-rw-r--r--arch/arm/boot/dts/at91sam9n12.dtsi4
-rw-r--r--arch/arm/boot/dts/at91sam9x5.dtsi4
-rw-r--r--arch/arm/include/asm/unistd.h2
-rw-r--r--arch/arm/kernel/calls.S1
-rw-r--r--arch/arm/kernel/smp_twd.c48
-rw-r--r--arch/arm/mach-imx/clk-imx25.c2
-rw-r--r--arch/arm/mach-imx/mach-armadillo5x0.c3
-rw-r--r--arch/arm/mach-mxs/mach-mxs.c2
-rw-r--r--arch/arm/mach-orion5x/common.c7
-rw-r--r--arch/arm/mach-shmobile/board-kzm9g.c4
-rw-r--r--arch/arm/mm/dma-mapping.c2
-rw-r--r--arch/arm/plat-mxc/include/mach/mx25.h1
-rw-r--r--arch/arm/plat-samsung/clock.c10
-rw-r--r--arch/c6x/include/asm/Kbuild1
-rw-r--r--arch/c6x/include/asm/barrier.h27
-rw-r--r--arch/m68k/platform/coldfire/clk.c6
-rw-r--r--arch/mips/kernel/smp-cmp.c2
-rw-r--r--arch/mips/mm/gup.c2
-rw-r--r--arch/mips/mti-malta/malta-int.c9
-rw-r--r--arch/mips/mti-malta/malta-platform.c5
-rw-r--r--arch/s390/include/asm/hugetlb.h24
-rw-r--r--arch/s390/include/asm/tlbflush.h2
-rw-r--r--arch/s390/kernel/setup.c2
-rw-r--r--arch/s390/lib/uaccess_pt.c142
-rw-r--r--arch/sh/kernel/cpu/sh5/entry.S2
-rw-r--r--arch/sh/kernel/entry-common.S2
-rw-r--r--arch/sparc/kernel/module.c13
-rw-r--r--arch/tile/include/gxio/iorpc_trio.h24
-rw-r--r--arch/um/include/asm/processor-generic.h9
-rw-r--r--arch/um/include/shared/common-offsets.h10
-rw-r--r--arch/um/include/shared/user.h11
-rw-r--r--arch/um/kernel/exec.c25
-rw-r--r--arch/um/kernel/process.c8
-rw-r--r--arch/um/kernel/signal.c6
-rw-r--r--arch/um/kernel/syscall.c24
-rw-r--r--arch/um/scripts/Makefile.rules2
-rw-r--r--arch/x86/Kconfig8
-rw-r--r--arch/x86/Makefile2
-rw-r--r--arch/x86/include/asm/xen/page.h3
-rw-r--r--arch/x86/kernel/cpu/perf_event.h2
-rw-r--r--arch/x86/kernel/cpu/perf_event_amd_ibs.c12
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel.c24
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel_ds.c14
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel_uncore.c6
-rw-r--r--arch/x86/mm/init.c2
-rw-r--r--arch/x86/um/Kconfig1
-rw-r--r--arch/x86/um/shared/sysdep/kernel-offsets.h3
-rw-r--r--arch/x86/um/shared/sysdep/syscalls.h2
-rw-r--r--arch/x86/um/signal.c6
-rw-r--r--arch/x86/um/sys_call_table_32.c2
-rw-r--r--arch/x86/um/syscalls_32.c27
-rw-r--r--arch/x86/um/syscalls_64.c23
-rw-r--r--arch/x86/xen/enlighten.c4
-rw-r--r--arch/x86/xen/p2m.c27
-rw-r--r--arch/x86/xen/setup.c4
-rw-r--r--block/blk-core.c8
-rw-r--r--block/ioctl.c2
-rw-r--r--drivers/acpi/bus.c10
-rw-r--r--drivers/acpi/power.c36
-rw-r--r--drivers/block/aoe/aoecmd.c1
-rw-r--r--drivers/block/cciss_scsi.c1
-rw-r--r--drivers/block/mtip32xx/mtip32xx.c38
-rw-r--r--drivers/block/mtip32xx/mtip32xx.h10
-rw-r--r--drivers/block/nbd.c9
-rw-r--r--drivers/block/rbd.c7
-rw-r--r--drivers/block/xen-blkback/blkback.c2
-rw-r--r--drivers/clk/Makefile1
-rw-r--r--drivers/clk/clk-devres.c55
-rw-r--r--drivers/clk/clkdev.c45
-rw-r--r--drivers/cpufreq/powernow-k8.c63
-rw-r--r--drivers/dma/at_hdmac.c13
-rw-r--r--drivers/dma/pl330.c21
-rw-r--r--drivers/edac/edac_mc.c57
-rw-r--r--drivers/edac/i3200_edac.c2
-rw-r--r--drivers/edac/i5000_edac.c4
-rw-r--r--drivers/edac/sb_edac.c7
-rw-r--r--drivers/extcon/extcon-max77693.c19
-rw-r--r--drivers/gpio/gpio-lpc32xx.c5
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c3
-rw-r--r--drivers/gpu/drm/i915/intel_display.c12
-rw-r--r--drivers/gpu/drm/i915/intel_hdmi.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_abi16.c2
-rw-r--r--drivers/gpu/drm/nouveau/nv50_gpio.c15
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_fb.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_fifo.c3
-rw-r--r--drivers/gpu/drm/nouveau/nve0_fifo.c3
-rw-r--r--drivers/gpu/drm/radeon/atombios_crtc.c163
-rw-r--r--drivers/gpu/drm/radeon/r100.c3
-rw-r--r--drivers/gpu/drm/udl/udl_connector.c7
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_fence.c2
-rw-r--r--drivers/hid/hid-lenovo-tpkbd.c2
-rw-r--r--drivers/hid/hid-logitech-dj.c45
-rw-r--r--drivers/hid/hid-logitech-dj.h1
-rw-r--r--drivers/hwmon/ad7314.c8
-rw-r--r--drivers/hwmon/ads7871.c9
-rw-r--r--drivers/hwmon/applesmc.c4
-rw-r--r--drivers/hwmon/coretemp.c5
-rw-r--r--drivers/hwmon/fam15h_power.c15
-rw-r--r--drivers/hwmon/via-cputemp.c5
-rw-r--r--drivers/hwspinlock/hwspinlock_core.c3
-rw-r--r--drivers/infiniband/hw/cxgb4/cm.c2
-rw-r--r--drivers/infiniband/hw/ocrdma/ocrdma_verbs.c8
-rw-r--r--drivers/infiniband/hw/qib/qib_mad.c3
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib.h5
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c93
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_multicast.c2
-rw-r--r--drivers/input/keyboard/imx_keypad.c4
-rw-r--r--drivers/input/misc/ab8500-ponkey.c4
-rw-r--r--drivers/input/mouse/sentelic.c11
-rw-r--r--drivers/input/serio/ambakmi.c6
-rw-r--r--drivers/input/serio/i8042-x86ia64io.h6
-rw-r--r--drivers/input/touchscreen/edt-ft5x06.c9
-rw-r--r--drivers/input/touchscreen/usbtouchscreen.c40
-rw-r--r--drivers/md/dm-mpath.c11
-rw-r--r--drivers/md/dm-table.c61
-rw-r--r--drivers/md/dm-thin.c135
-rw-r--r--drivers/md/dm-verity.c8
-rw-r--r--drivers/md/dm.c71
-rw-r--r--drivers/md/dm.h1
-rw-r--r--drivers/md/md.c6
-rw-r--r--drivers/md/raid10.c8
-rw-r--r--drivers/md/raid5.c7
-rw-r--r--drivers/mfd/88pm800.c5
-rw-r--r--drivers/mfd/88pm805.c3
-rw-r--r--drivers/mfd/88pm860x-core.c21
-rw-r--r--drivers/mfd/aat2870-core.c2
-rw-r--r--drivers/mfd/ab3100-core.c2
-rw-r--r--drivers/mfd/ab8500-core.c10
-rw-r--r--drivers/mfd/arizona-core.c6
-rw-r--r--drivers/mfd/asic3.c6
-rw-r--r--drivers/mfd/cs5535-mfd.c2
-rw-r--r--drivers/mfd/da9052-core.c2
-rw-r--r--drivers/mfd/davinci_voicecodec.c2
-rw-r--r--drivers/mfd/db8500-prcmu.c2
-rw-r--r--drivers/mfd/htc-pasic3.c5
-rw-r--r--drivers/mfd/intel_msic.c4
-rw-r--r--drivers/mfd/janz-cmodio.c2
-rw-r--r--drivers/mfd/jz4740-adc.c3
-rw-r--r--drivers/mfd/lm3533-core.c7
-rw-r--r--drivers/mfd/lpc_ich.c24
-rw-r--r--drivers/mfd/lpc_sch.c6
-rw-r--r--drivers/mfd/max77686.c2
-rw-r--r--drivers/mfd/max77693-irq.c36
-rw-r--r--drivers/mfd/max77693.c16
-rw-r--r--drivers/mfd/max8925-core.c12
-rw-r--r--drivers/mfd/max8997.c2
-rw-r--r--drivers/mfd/max8998.c8
-rw-r--r--drivers/mfd/mc13xxx-core.c2
-rw-r--r--drivers/mfd/mfd-core.c12
-rw-r--r--drivers/mfd/palmas.c3
-rw-r--r--drivers/mfd/rc5t583.c2
-rw-r--r--drivers/mfd/rdc321x-southbridge.c3
-rw-r--r--drivers/mfd/sec-core.c8
-rw-r--r--drivers/mfd/sta2x11-mfd.c4
-rw-r--r--drivers/mfd/stmpe.c2
-rw-r--r--drivers/mfd/t7l66xb.c2
-rw-r--r--drivers/mfd/tc3589x.c8
-rw-r--r--drivers/mfd/tc6387xb.c2
-rw-r--r--drivers/mfd/tc6393xb.c4
-rw-r--r--drivers/mfd/ti-ssp.c2
-rw-r--r--drivers/mfd/timberdale.c12
-rw-r--r--drivers/mfd/tps6105x.c2
-rw-r--r--drivers/mfd/tps6507x.c2
-rw-r--r--drivers/mfd/tps65090.c2
-rw-r--r--drivers/mfd/tps65217.c130
-rw-r--r--drivers/mfd/tps6586x.c3
-rw-r--r--drivers/mfd/tps65910.c2
-rw-r--r--drivers/mfd/tps65912-core.c2
-rw-r--r--drivers/mfd/twl4030-audio.c2
-rw-r--r--drivers/mfd/twl6040-core.c2
-rw-r--r--drivers/mfd/vx855.c2
-rw-r--r--drivers/mfd/wl1273-core.c2
-rw-r--r--drivers/mfd/wm831x-core.c16
-rw-r--r--drivers/mfd/wm8400-core.c2
-rw-r--r--drivers/mfd/wm8994-core.c4
-rw-r--r--drivers/net/can/c_can/c_can.c3
-rw-r--r--drivers/net/can/janz-ican3.c4
-rw-r--r--drivers/net/can/ti_hecc.c2
-rw-r--r--drivers/net/ethernet/broadcom/bnx2.c2
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c12
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c11
-rw-r--r--drivers/net/ethernet/broadcom/tg3.c525
-rw-r--r--drivers/net/ethernet/broadcom/tg3.h9
-rw-r--r--drivers/net/ethernet/cadence/at91_ether.c2
-rw-r--r--drivers/net/ethernet/emulex/benet/be.h1
-rw-r--r--drivers/net/ethernet/emulex/benet/be_cmds.c53
-rw-r--r--drivers/net/ethernet/emulex/benet/be_cmds.h6
-rw-r--r--drivers/net/ethernet/emulex/benet/be_ethtool.c57
-rw-r--r--drivers/net/ethernet/emulex/benet/be_main.c60
-rw-r--r--drivers/net/ethernet/freescale/gianfar_ethtool.c1
-rw-r--r--drivers/net/ethernet/freescale/gianfar_ptp.c4
-rw-r--r--drivers/net/ethernet/intel/e1000/e1000_main.c11
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/icm.c30
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/icm.h10
-rw-r--r--drivers/net/ethernet/octeon/octeon_mgmt.c4
-rw-r--r--drivers/net/ethernet/pasemi/pasemi_mac.c4
-rw-r--r--drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c4
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c4
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_main.c10
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_timer.c8
-rw-r--r--drivers/net/irda/sh_sir.c2
-rw-r--r--drivers/net/phy/bcm87xx.c2
-rw-r--r--drivers/net/phy/micrel.c45
-rw-r--r--drivers/net/phy/smsc.c28
-rw-r--r--drivers/net/ppp/pppoe.c2
-rw-r--r--drivers/net/team/team.c13
-rw-r--r--drivers/net/usb/asix_devices.c4
-rw-r--r--drivers/net/usb/qmi_wwan.c4
-rw-r--r--drivers/net/usb/smsc75xx.c239
-rw-r--r--drivers/net/usb/smsc95xx.c560
-rw-r--r--drivers/net/usb/smsc95xx.h12
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_eeprom.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/debug.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.h3
-rw-r--r--drivers/net/wireless/ath/ath9k/link.c2
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c2
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c26
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c6
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/channel.c2
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/trans.c1
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192ce/def.h1
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192ce/hw.c12
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192ce/sw.c6
-rw-r--r--drivers/pwm/pwm-tiecap.c7
-rw-r--r--drivers/pwm/pwm-tiehrpwm.c29
-rw-r--r--drivers/regulator/tps65217-regulator.c124
-rw-r--r--drivers/rpmsg/virtio_rpmsg_bus.c6
-rw-r--r--drivers/rtc/rtc-twl.c5
-rw-r--r--drivers/s390/block/dasd.c17
-rw-r--r--drivers/s390/block/dasd_alias.c27
-rw-r--r--drivers/s390/block/dasd_eckd.c32
-rw-r--r--drivers/s390/cio/device.c7
-rw-r--r--drivers/scsi/bnx2i/bnx2i_hwi.c3
-rw-r--r--drivers/scsi/hpsa.c3
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.c7
-rw-r--r--drivers/scsi/virtio_scsi.c2
-rw-r--r--drivers/sh/intc/core.c2
-rw-r--r--drivers/sh/pfc/pinctrl.c5
-rw-r--r--drivers/staging/nvec/nvec.c2
-rw-r--r--drivers/target/iscsi/iscsi_target_login.c11
-rw-r--r--drivers/target/target_core_alua.c7
-rw-r--r--drivers/target/target_core_device.c7
-rw-r--r--drivers/target/target_core_iblock.c17
-rw-r--r--drivers/target/target_core_pr.c8
-rw-r--r--drivers/target/target_core_pscsi.c29
-rw-r--r--drivers/target/target_core_spc.c35
-rw-r--r--drivers/target/target_core_transport.c148
-rw-r--r--drivers/usb/core/devices.c2
-rw-r--r--drivers/usb/core/hcd.c6
-rw-r--r--drivers/usb/host/ohci-at91.c3
-rw-r--r--drivers/vfio/pci/vfio_pci_intrs.c76
-rw-r--r--drivers/watchdog/hpwdt.c3
-rw-r--r--drivers/watchdog/watchdog_core.c3
-rw-r--r--drivers/xen/gntdev.c5
-rw-r--r--drivers/xen/grant-table.c6
-rw-r--r--fs/btrfs/qgroup.c8
-rw-r--r--fs/cifs/cifs_unicode.c2
-rw-r--r--fs/dcache.c6
-rw-r--r--fs/debugfs/file.c76
-rw-r--r--fs/lockd/svclock.c3
-rw-r--r--fs/namespace.c10
-rw-r--r--fs/proc/proc_sysctl.c5
-rw-r--r--fs/xfs/xfs_buf.c5
-rw-r--r--fs/xfs/xfs_buf.h41
-rw-r--r--fs/xfs/xfs_super.c1
-rw-r--r--include/asm-generic/unistd.h4
-rw-r--r--include/linux/atmel-ssc.h1
-rw-r--r--include/linux/compiler-gcc4.h7
-rw-r--r--include/linux/compiler.h4
-rw-r--r--include/linux/dcache.h2
-rw-r--r--include/linux/kernel.h2
-rw-r--r--include/linux/memory.h2
-rw-r--r--include/linux/mfd/core.h4
-rw-r--r--include/linux/mfd/tps65217.h12
-rw-r--r--include/linux/micrel_phy.h19
-rw-r--r--include/linux/perf_event.h2
-rw-r--r--include/linux/sched.h1
-rw-r--r--include/linux/security.h1
-rw-r--r--include/linux/xfrm.h2
-rw-r--r--include/net/ip6_fib.h5
-rw-r--r--include/net/net_namespace.h10
-rw-r--r--include/net/netns/ipv4.h1
-rw-r--r--include/net/sock.h2
-rw-r--r--include/target/target_core_backend.h4
-rw-r--r--include/target/target_core_base.h1
-rw-r--r--include/trace/events/kmem.h4
-rw-r--r--include/xen/grant_table.h3
-rw-r--r--kernel/pid_namespace.c6
-rw-r--r--kernel/sched/core.c39
-rw-r--r--kernel/sched/fair.c28
-rw-r--r--kernel/time/timekeeping.c19
-rw-r--r--kernel/workqueue.c37
-rw-r--r--lib/flex_proportions.c2
-rw-r--r--mm/huge_memory.c1
-rw-r--r--mm/memory_hotplug.c16
-rw-r--r--mm/page_alloc.c2
-rw-r--r--mm/slab.c6
-rw-r--r--mm/slub.c15
-rw-r--r--mm/vmscan.c1
-rw-r--r--net/batman-adv/bat_iv_ogm.c7
-rw-r--r--net/batman-adv/bitarray.h6
-rw-r--r--net/batman-adv/soft-interface.c7
-rw-r--r--net/bluetooth/bnep/sock.c4
-rw-r--r--net/bluetooth/cmtp/sock.c4
-rw-r--r--net/bluetooth/hci_core.c2
-rw-r--r--net/bluetooth/hci_sock.c16
-rw-r--r--net/bluetooth/hidp/sock.c4
-rw-r--r--net/bluetooth/l2cap_core.c2
-rw-r--r--net/bluetooth/mgmt.c16
-rw-r--r--net/ceph/messenger.c5
-rw-r--r--net/core/dev.c5
-rw-r--r--net/core/skbuff.c4
-rw-r--r--net/core/sock.c3
-rw-r--r--net/ipv4/devinet.c4
-rw-r--r--net/ipv4/inetpeer.c5
-rw-r--r--net/ipv4/raw.c14
-rw-r--r--net/ipv4/route.c9
-rw-r--r--net/ipv4/tcp.c23
-rw-r--r--net/ipv4/tcp_input.c5
-rw-r--r--net/ipv6/inet6_connection_sock.c23
-rw-r--r--net/ipv6/ip6_fib.c18
-rw-r--r--net/ipv6/mip6.c20
-rw-r--r--net/ipv6/raw.c21
-rw-r--r--net/ipv6/route.c19
-rw-r--r--net/l2tp/l2tp_netlink.c12
-rw-r--r--net/netfilter/xt_limit.c8
-rw-r--r--net/netrom/af_netrom.c2
-rw-r--r--net/sched/sch_qfq.c5
-rw-r--r--net/wireless/reg.c12
-rw-r--r--net/xfrm/xfrm_policy.c3
-rw-r--r--net/xfrm/xfrm_user.c57
-rw-r--r--scripts/Makefile.fwinst4
-rwxr-xr-xscripts/checksyscalls.sh2
-rw-r--r--security/selinux/include/xfrm.h1
-rw-r--r--sound/pci/hda/hda_intel.c1
-rw-r--r--sound/soc/codecs/arizona.c2
-rw-r--r--sound/soc/codecs/mc13783.c8
-rw-r--r--sound/soc/codecs/wm2000.c2
-rw-r--r--sound/soc/codecs/wm8904.c2
-rw-r--r--sound/soc/fsl/imx-sgtl5000.c2
-rw-r--r--sound/soc/omap/am3517evm.c2
-rw-r--r--sound/soc/samsung/dma.c8
-rw-r--r--sound/soc/soc-dapm.c5
-rw-r--r--sound/soc/spear/spear_pcm.c2
-rw-r--r--sound/soc/tegra/tegra_alc5632.c1
-rw-r--r--sound/soc/tegra/tegra_pcm.c4
-rw-r--r--sound/soc/ux500/ux500_msp_i2s.c25
-rw-r--r--sound/usb/endpoint.c8
356 files changed, 3509 insertions, 2113 deletions
diff --git a/Documentation/vfio.txt b/Documentation/vfio.txt
index 0cb6685..8eda363 100644
--- a/Documentation/vfio.txt
+++ b/Documentation/vfio.txt
@@ -133,7 +133,7 @@ character devices for this group:
$ lspci -n -s 0000:06:0d.0
06:0d.0 0401: 1102:0002 (rev 08)
# echo 0000:06:0d.0 > /sys/bus/pci/devices/0000:06:0d.0/driver/unbind
-# echo 1102 0002 > /sys/bus/pci/drivers/vfio/new_id
+# echo 1102 0002 > /sys/bus/pci/drivers/vfio-pci/new_id
Now we need to look at what other devices are in the group to free
it for use by VFIO:
diff --git a/MAINTAINERS b/MAINTAINERS
index eb30279..64458f0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3552,11 +3552,12 @@ K: \b(ABS|SYN)_MT_
INTEL C600 SERIES SAS CONTROLLER DRIVER
M: Intel SCU Linux support <intel-linux-scu@intel.com>
+M: Lukasz Dorau <lukasz.dorau@intel.com>
+M: Maciej Patelczyk <maciej.patelczyk@intel.com>
M: Dave Jiang <dave.jiang@intel.com>
-M: Ed Nadolski <edmund.nadolski@intel.com>
L: linux-scsi@vger.kernel.org
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/djbw/isci.git
-S: Maintained
+T: git git://git.code.sf.net/p/intel-sas/isci
+S: Supported
F: drivers/scsi/isci/
F: firmware/isci/
@@ -3666,11 +3667,12 @@ F: Documentation/networking/README.ipw2200
F: drivers/net/wireless/ipw2x00/
INTEL(R) TRUSTED EXECUTION TECHNOLOGY (TXT)
-M: Joseph Cihula <joseph.cihula@intel.com>
+M: Richard L Maliszewski <richard.l.maliszewski@intel.com>
+M: Gang Wei <gang.wei@intel.com>
M: Shane Wang <shane.wang@intel.com>
L: tboot-devel@lists.sourceforge.net
W: http://tboot.sourceforge.net
-T: Mercurial http://www.bughost.org/repos.hg/tboot.hg
+T: hg http://tboot.hg.sourceforge.net:8000/hgroot/tboot/tboot
S: Supported
F: Documentation/intel_txt.txt
F: include/linux/tboot.h
@@ -5544,6 +5546,8 @@ F: Documentation/devicetree/bindings/pwm/
F: include/linux/pwm.h
F: include/linux/of_pwm.h
F: drivers/pwm/
+F: drivers/video/backlight/pwm_bl.c
+F: include/linux/pwm_backlight.h
PXA2xx/PXA3xx SUPPORT
M: Eric Miao <eric.y.miao@gmail.com>
diff --git a/Makefile b/Makefile
index 0f66f14..a3c11d5 100644
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,8 @@
VERSION = 3
PATCHLEVEL = 6
SUBLEVEL = 0
-EXTRAVERSION = -rc5
-NAME = Saber-toothed Squirrel
+EXTRAVERSION = -rc7
+NAME = Terrified Chipmunk
# *DOCUMENTATION*
# To see a list of typical targets execute "make help"
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index 81769c1..bc67cbf 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -653,6 +653,7 @@ __armv7_mmu_cache_on:
mcrne p15, 0, r0, c8, c7, 0 @ flush I,D TLBs
#endif
mrc p15, 0, r0, c1, c0, 0 @ read control reg
+ bic r0, r0, #1 << 28 @ clear SCTLR.TRE
orr r0, r0, #0x5000 @ I-cache enable, RR cache replacement
orr r0, r0, #0x003c @ write buffer
#ifdef CONFIG_MMU
diff --git a/arch/arm/boot/dts/at91sam9260.dtsi b/arch/arm/boot/dts/at91sam9260.dtsi
index 66389c1..7c95f76 100644
--- a/arch/arm/boot/dts/at91sam9260.dtsi
+++ b/arch/arm/boot/dts/at91sam9260.dtsi
@@ -104,6 +104,7 @@
#gpio-cells = <2>;
gpio-controller;
interrupt-controller;
+ #interrupt-cells = <2>;
};
pioB: gpio@fffff600 {
@@ -113,6 +114,7 @@
#gpio-cells = <2>;
gpio-controller;
interrupt-controller;
+ #interrupt-cells = <2>;
};
pioC: gpio@fffff800 {
@@ -122,6 +124,7 @@
#gpio-cells = <2>;
gpio-controller;
interrupt-controller;
+ #interrupt-cells = <2>;
};
dbgu: serial@fffff200 {
diff --git a/arch/arm/boot/dts/at91sam9263.dtsi b/arch/arm/boot/dts/at91sam9263.dtsi
index b460d6c..195019b 100644
--- a/arch/arm/boot/dts/at91sam9263.dtsi
+++ b/arch/arm/boot/dts/at91sam9263.dtsi
@@ -95,6 +95,7 @@
#gpio-cells = <2>;
gpio-controller;
interrupt-controller;
+ #interrupt-cells = <2>;
};
pioB: gpio@fffff400 {
@@ -104,6 +105,7 @@
#gpio-cells = <2>;
gpio-controller;
interrupt-controller;
+ #interrupt-cells = <2>;
};
pioC: gpio@fffff600 {
@@ -113,6 +115,7 @@
#gpio-cells = <2>;
gpio-controller;
interrupt-controller;
+ #interrupt-cells = <2>;
};
pioD: gpio@fffff800 {
@@ -122,6 +125,7 @@
#gpio-cells = <2>;
gpio-controller;
interrupt-controller;
+ #interrupt-cells = <2>;
};
pioE: gpio@fffffa00 {
@@ -131,6 +135,7 @@
#gpio-cells = <2>;
gpio-controller;
interrupt-controller;
+ #interrupt-cells = <2>;
};
dbgu: serial@ffffee00 {
diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi
index bafa880..63751b1 100644
--- a/arch/arm/boot/dts/at91sam9g45.dtsi
+++ b/arch/arm/boot/dts/at91sam9g45.dtsi
@@ -113,6 +113,7 @@
#gpio-cells = <2>;
gpio-controller;
interrupt-controller;
+ #interrupt-cells = <2>;
};
pioB: gpio@fffff400 {
@@ -122,6 +123,7 @@
#gpio-cells = <2>;
gpio-controller;
interrupt-controller;
+ #interrupt-cells = <2>;
};
pioC: gpio@fffff600 {
@@ -131,6 +133,7 @@
#gpio-cells = <2>;
gpio-controller;
interrupt-controller;
+ #interrupt-cells = <2>;
};
pioD: gpio@fffff800 {
@@ -140,6 +143,7 @@
#gpio-cells = <2>;
gpio-controller;
interrupt-controller;
+ #interrupt-cells = <2>;
};
pioE: gpio@fffffa00 {
@@ -149,6 +153,7 @@
#gpio-cells = <2>;
gpio-controller;
interrupt-controller;
+ #interrupt-cells = <2>;
};
dbgu: serial@ffffee00 {
diff --git a/arch/arm/boot/dts/at91sam9n12.dtsi b/arch/arm/boot/dts/at91sam9n12.dtsi
index bfac0df..ef9336a 100644
--- a/arch/arm/boot/dts/at91sam9n12.dtsi
+++ b/arch/arm/boot/dts/at91sam9n12.dtsi
@@ -107,6 +107,7 @@
#gpio-cells = <2>;
gpio-controller;
interrupt-controller;
+ #interrupt-cells = <2>;
};
pioB: gpio@fffff600 {
@@ -116,6 +117,7 @@
#gpio-cells = <2>;
gpio-controller;
interrupt-controller;
+ #interrupt-cells = <2>;
};
pioC: gpio@fffff800 {
@@ -125,6 +127,7 @@
#gpio-cells = <2>;
gpio-controller;
interrupt-controller;
+ #interrupt-cells = <2>;
};
pioD: gpio@fffffa00 {
@@ -134,6 +137,7 @@
#gpio-cells = <2>;
gpio-controller;
interrupt-controller;
+ #interrupt-cells = <2>;
};
dbgu: serial@fffff200 {
diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi
index 4a18c39..8a387a8 100644
--- a/arch/arm/boot/dts/at91sam9x5.dtsi
+++ b/arch/arm/boot/dts/at91sam9x5.dtsi
@@ -115,6 +115,7 @@
#gpio-cells = <2>;
gpio-controller;
interrupt-controller;
+ #interrupt-cells = <2>;
};
pioB: gpio@fffff600 {
@@ -124,6 +125,7 @@
#gpio-cells = <2>;
gpio-controller;
interrupt-controller;
+ #interrupt-cells = <2>;
};
pioC: gpio@fffff800 {
@@ -133,6 +135,7 @@
#gpio-cells = <2>;
gpio-controller;
interrupt-controller;
+ #interrupt-cells = <2>;
};
pioD: gpio@fffffa00 {
@@ -142,6 +145,7 @@
#gpio-cells = <2>;
gpio-controller;
interrupt-controller;
+ #interrupt-cells = <2>;
};
dbgu: serial@fffff200 {
diff --git a/arch/arm/include/asm/unistd.h b/arch/arm/include/asm/unistd.h
index 0cab47d..2fde5fd 100644
--- a/arch/arm/include/asm/unistd.h
+++ b/arch/arm/include/asm/unistd.h
@@ -404,6 +404,7 @@
#define __NR_setns (__NR_SYSCALL_BASE+375)
#define __NR_process_vm_readv (__NR_SYSCALL_BASE+376)
#define __NR_process_vm_writev (__NR_SYSCALL_BASE+377)
+ /* 378 for kcmp */
/*
* The following SWIs are ARM private.
@@ -483,6 +484,7 @@
*/
#define __IGNORE_fadvise64_64
#define __IGNORE_migrate_pages
+#define __IGNORE_kcmp
#endif /* __KERNEL__ */
#endif /* __ASM_ARM_UNISTD_H */
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
index 463ff4a..e337879 100644
--- a/arch/arm/kernel/calls.S
+++ b/arch/arm/kernel/calls.S
@@ -387,6 +387,7 @@
/* 375 */ CALL(sys_setns)
CALL(sys_process_vm_readv)
CALL(sys_process_vm_writev)
+ CALL(sys_ni_syscall) /* reserved for sys_kcmp */
#ifndef syscalls_counted
.equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
#define syscalls_counted
diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c
index fef42b2..e1f9069 100644
--- a/arch/arm/kernel/smp_twd.c
+++ b/arch/arm/kernel/smp_twd.c
@@ -11,7 +11,6 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/clk.h>
-#include <linux/cpufreq.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/err.h>
@@ -96,7 +95,52 @@ static void twd_timer_stop(struct clock_event_device *clk)
disable_percpu_irq(clk->irq);
}
-#ifdef CONFIG_CPU_FREQ
+#ifdef CONFIG_COMMON_CLK
+
+/*
+ * Updates clockevent frequency when the cpu frequency changes.
+ * Called on the cpu that is changing frequency with interrupts disabled.
+ */
+static void twd_update_frequency(void *new_rate)
+{
+ twd_timer_rate = *((unsigned long *) new_rate);
+
+ clockevents_update_freq(*__this_cpu_ptr(twd_evt), twd_timer_rate);
+}
+
+static int twd_rate_change(struct notifier_block *nb,
+ unsigned long flags, void *data)
+{
+ struct clk_notifier_data *cnd = data;
+
+ /*
+ * The twd clock events must be reprogrammed to account for the new
+ * frequency. The timer is local to a cpu, so cross-call to the
+ * changing cpu.
+ */
+ if (flags == POST_RATE_CHANGE)
+ smp_call_function(twd_update_frequency,
+ (void *)&cnd->new_rate, 1);
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block twd_clk_nb = {
+ .notifier_call = twd_rate_change,
+};
+
+static int twd_clk_init(void)
+{
+ if (twd_evt && *__this_cpu_ptr(twd_evt) && !IS_ERR(twd_clk))
+ return clk_notifier_register(twd_clk, &twd_clk_nb);
+
+ return 0;
+}
+core_initcall(twd_clk_init);
+
+#elif defined (CONFIG_CPU_FREQ)
+
+#include <linux/cpufreq.h>
/*
* Updates clockevent frequency when the cpu frequency changes.
diff --git a/arch/arm/mach-imx/clk-imx25.c b/arch/arm/mach-imx/clk-imx25.c
index 4431a62..d20d479 100644
--- a/arch/arm/mach-imx/clk-imx25.c
+++ b/arch/arm/mach-imx/clk-imx25.c
@@ -241,6 +241,6 @@ int __init mx25_clocks_init(void)
clk_register_clkdev(clk[sdma_ahb], "ahb", "imx35-sdma");
clk_register_clkdev(clk[iim_ipg], "iim", NULL);
- mxc_timer_init(MX25_IO_ADDRESS(MX25_GPT1_BASE_ADDR), 54);
+ mxc_timer_init(MX25_IO_ADDRESS(MX25_GPT1_BASE_ADDR), MX25_INT_GPT1);
return 0;
}
diff --git a/arch/arm/mach-imx/mach-armadillo5x0.c b/arch/arm/mach-imx/mach-armadillo5x0.c
index 2c6ab32..5985ed1 100644
--- a/arch/arm/mach-imx/mach-armadillo5x0.c
+++ b/arch/arm/mach-imx/mach-armadillo5x0.c
@@ -526,7 +526,8 @@ static void __init armadillo5x0_init(void)
imx31_add_mxc_nand(&armadillo5x0_nand_board_info);
/* set NAND page size to 2k if not configured via boot mode pins */
- __raw_writel(__raw_readl(MXC_CCM_RCSR) | (1 << 30), MXC_CCM_RCSR);
+ __raw_writel(__raw_readl(mx3_ccm_base + MXC_CCM_RCSR) |
+ (1 << 30), mx3_ccm_base + MXC_CCM_RCSR);
/* RTC */
/* Get RTC IRQ and register the chip */
diff --git a/arch/arm/mach-mxs/mach-mxs.c b/arch/arm/mach-mxs/mach-mxs.c
index 8dabfe8..ff886e0 100644
--- a/arch/arm/mach-mxs/mach-mxs.c
+++ b/arch/arm/mach-mxs/mach-mxs.c
@@ -261,7 +261,7 @@ static void __init apx4devkit_init(void)
enable_clk_enet_out();
if (IS_BUILTIN(CONFIG_PHYLIB))
- phy_register_fixup_for_uid(PHY_ID_KS8051, MICREL_PHY_ID_MASK,
+ phy_register_fixup_for_uid(PHY_ID_KSZ8051, MICREL_PHY_ID_MASK,
apx4devkit_phy_fixup);
mxsfb_pdata.mode_list = apx4devkit_video_modes;
diff --git a/arch/arm/mach-orion5x/common.c b/arch/arm/mach-orion5x/common.c
index 410291c..a6cd14a 100644
--- a/arch/arm/mach-orion5x/common.c
+++ b/arch/arm/mach-orion5x/common.c
@@ -204,6 +204,13 @@ void __init orion5x_wdt_init(void)
void __init orion5x_init_early(void)
{
orion_time_set_base(TIMER_VIRT_BASE);
+
+ /*
+ * Some Orion5x devices allocate their coherent buffers from atomic
+ * context. Increase size of atomic coherent pool to make sure such
+ * the allocations won't fail.
+ */
+ init_dma_coherent_pool_size(SZ_1M);
}
int orion5x_tclk;
diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c
index 53b7ea9..3b8a017 100644
--- a/arch/arm/mach-shmobile/board-kzm9g.c
+++ b/arch/arm/mach-shmobile/board-kzm9g.c
@@ -346,11 +346,11 @@ static struct resource sh_mmcif_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = gic_spi(141),
+ .start = gic_spi(140),
.flags = IORESOURCE_IRQ,
},
[2] = {
- .start = gic_spi(140),
+ .start = gic_spi(141),
.flags = IORESOURCE_IRQ,
},
};
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index e59c4ab..13f555d 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -346,6 +346,8 @@ static int __init atomic_pool_init(void)
(unsigned)pool->size / 1024);
return 0;
}
+
+ kfree(pages);
no_pages:
kfree(bitmap);
no_bitmap:
diff --git a/arch/arm/plat-mxc/include/mach/mx25.h b/arch/arm/plat-mxc/include/mach/mx25.h
index 627d94f..ec46640 100644
--- a/arch/arm/plat-mxc/include/mach/mx25.h
+++ b/arch/arm/plat-mxc/include/mach/mx25.h
@@ -98,6 +98,7 @@
#define MX25_INT_UART1 (NR_IRQS_LEGACY + 45)
#define MX25_INT_GPIO2 (NR_IRQS_LEGACY + 51)
#define MX25_INT_GPIO1 (NR_IRQS_LEGACY + 52)
+#define MX25_INT_GPT1 (NR_IRQS_LEGACY + 54)
#define MX25_INT_FEC (NR_IRQS_LEGACY + 57)
#define MX25_DMA_REQ_SSI2_RX1 22
diff --git a/arch/arm/plat-samsung/clock.c b/arch/arm/plat-samsung/clock.c
index 65c5eca..d1116e2 100644
--- a/arch/arm/plat-samsung/clock.c
+++ b/arch/arm/plat-samsung/clock.c
@@ -144,6 +144,7 @@ long clk_round_rate(struct clk *clk, unsigned long rate)
int clk_set_rate(struct clk *clk, unsigned long rate)
{
+ unsigned long flags;
int ret;
if (IS_ERR(clk))
@@ -159,9 +160,9 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
if (clk->ops == NULL || clk->ops->set_rate == NULL)
return -EINVAL;
- spin_lock(&clocks_lock);
+ spin_lock_irqsave(&clocks_lock, flags);
ret = (clk->ops->set_rate)(clk, rate);
- spin_unlock(&clocks_lock);
+ spin_unlock_irqrestore(&clocks_lock, flags);
return ret;
}
@@ -173,17 +174,18 @@ struct clk *clk_get_parent(struct clk *clk)
int clk_set_parent(struct clk *clk, struct clk *parent)
{
+ unsigned long flags;
int ret = 0;
if (IS_ERR(clk))
return -EINVAL;
- spin_lock(&clocks_lock);
+ spin_lock_irqsave(&clocks_lock, flags);
if (clk->ops && clk->ops->set_parent)
ret = (clk->ops->set_parent)(clk, parent);
- spin_unlock(&clocks_lock);
+ spin_unlock_irqrestore(&clocks_lock, flags);
return ret;
}
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index 3af601e..f08e891 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -2,6 +2,7 @@ include include/asm-generic/Kbuild.asm
generic-y += atomic.h
generic-y += auxvec.h
+generic-y += barrier.h
generic-y += bitsperlong.h
generic-y += bugs.h
generic-y += cputime.h
diff --git a/arch/c6x/include/asm/barrier.h b/arch/c6x/include/asm/barrier.h
deleted file mode 100644
index 538240e..0000000
--- a/arch/c6x/include/asm/barrier.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Port on Texas Instruments TMS320C6x architecture
- *
- * Copyright (C) 2004, 2009, 2010, 2011 Texas Instruments Incorporated
- * Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.com)
- *
- * 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.
- */
-#ifndef _ASM_C6X_BARRIER_H
-#define _ASM_C6X_BARRIER_H
-
-#define nop() asm("NOP\n");
-
-#define mb() barrier()
-#define rmb() barrier()
-#define wmb() barrier()
-#define set_mb(var, value) do { var = value; mb(); } while (0)
-#define set_wmb(var, value) do { var = value; wmb(); } while (0)
-
-#define smp_mb() barrier()
-#define smp_rmb() barrier()
-#define smp_wmb() barrier()
-#define smp_read_barrier_depends() do { } while (0)
-
-#endif /* _ASM_C6X_BARRIER_H */
diff --git a/arch/m68k/platform/coldfire/clk.c b/arch/m68k/platform/coldfire/clk.c
index 75f9ee9..9cd13b4 100644
--- a/arch/m68k/platform/coldfire/clk.c
+++ b/arch/m68k/platform/coldfire/clk.c
@@ -146,9 +146,3 @@ struct clk_ops clk_ops1 = {
};
#endif /* MCFPM_PPMCR1 */
#endif /* MCFPM_PPMCR0 */
-
-struct clk *devm_clk_get(struct device *dev, const char *id)
-{
- return NULL;
-}
-EXPORT_SYMBOL(devm_clk_get);
diff --git a/arch/mips/kernel/smp-cmp.c b/arch/mips/kernel/smp-cmp.c
index e7e03ec..afc379c 100644
--- a/arch/mips/kernel/smp-cmp.c
+++ b/arch/mips/kernel/smp-cmp.c
@@ -102,7 +102,7 @@ static void cmp_init_secondary(void)
c->vpe_id = (read_c0_tcbind() >> TCBIND_CURVPE_SHIFT) & TCBIND_CURVPE;
#endif
#ifdef CONFIG_MIPS_MT_SMTC
- c->tc_id = (read_c0_tcbind() >> TCBIND_CURTC_SHIFT) & TCBIND_CURTC;
+ c->tc_id = (read_c0_tcbind() & TCBIND_CURTC) >> TCBIND_CURTC_SHIFT;
#endif
}
diff --git a/arch/mips/mm/gup.c b/arch/mips/mm/gup.c
index 33aadbc..dcfd573 100644
--- a/arch/mips/mm/gup.c
+++ b/arch/mips/mm/gup.c
@@ -152,6 +152,8 @@ static int gup_huge_pud(pud_t pud, unsigned long addr, unsigned long end,
do {
VM_BUG_ON(compound_head(page) != head);
pages[*nr] = page;
+ if (PageTail(page))
+ get_huge_page_tail(page);
(*nr)++;
page++;
refs++;
diff --git a/arch/mips/mti-malta/malta-int.c b/arch/mips/mti-malta/malta-int.c
index 7b13a4c..fea823f 100644
--- a/arch/mips/mti-malta/malta-int.c
+++ b/arch/mips/mti-malta/malta-int.c
@@ -273,16 +273,19 @@ asmlinkage void plat_irq_dispatch(void)
unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
int irq;
+ if (unlikely(!pending)) {
+ spurious_interrupt();
+ return;
+ }
+
irq = irq_ffs(pending);
if (irq == MIPSCPU_INT_I8259A)
malta_hw0_irqdispatch();
else if (gic_present && ((1 << irq) & ipi_map[smp_processor_id()]))
malta_ipi_irqdispatch();
- else if (irq >= 0)
- do_IRQ(MIPS_CPU_IRQ_BASE + irq);
else
- spurious_interrupt();
+ do_IRQ(MIPS_CPU_IRQ_BASE + irq);
}
#ifdef CONFIG_MIPS_MT_SMP
diff --git a/arch/mips/mti-malta/malta-platform.c b/arch/mips/mti-malta/malta-platform.c
index 4c35301..80562b8 100644
--- a/arch/mips/mti-malta/malta-platform.c
+++ b/arch/mips/mti-malta/malta-platform.c
@@ -138,11 +138,6 @@ static int __init malta_add_devices(void)
if (err)
return err;
- /*
- * Set RTC to BCD mode to support current alarm code.
- */
- CMOS_WRITE(CMOS_READ(RTC_CONTROL) & ~RTC_DM_BINARY, RTC_CONTROL);
-
return 0;
}
diff --git a/arch/s390/include/asm/hugetlb.h b/arch/s390/include/asm/hugetlb.h
index 799ed0f..2d6e6e3 100644
--- a/arch/s390/include/asm/hugetlb.h
+++ b/arch/s390/include/asm/hugetlb.h
@@ -66,16 +66,6 @@ static inline pte_t huge_ptep_get(pte_t *ptep)
return pte;
}
-static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
- unsigned long addr, pte_t *ptep)
-{
- pte_t pte = huge_ptep_get(ptep);
-
- mm->context.flush_mm = 1;
- pmd_clear((pmd_t *) ptep);
- return pte;
-}
-
static inline void __pmd_csp(pmd_t *pmdp)
{
register unsigned long reg2 asm("2") = pmd_val(*pmdp);
@@ -117,6 +107,15 @@ static inline void huge_ptep_invalidate(struct mm_struct *mm,
__pmd_csp(pmdp);
}
+static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
+ unsigned long addr, pte_t *ptep)
+{
+ pte_t pte = huge_ptep_get(ptep);
+
+ huge_ptep_invalidate(mm, addr, ptep);
+ return pte;
+}
+
#define huge_ptep_set_access_flags(__vma, __addr, __ptep, __entry, __dirty) \
({ \
int __changed = !pte_same(huge_ptep_get(__ptep), __entry); \
@@ -131,10 +130,7 @@ static inline void huge_ptep_invalidate(struct mm_struct *mm,
({ \
pte_t __pte = huge_ptep_get(__ptep); \
if (pte_write(__pte)) { \
- (__mm)->context.flush_mm = 1; \
- if (atomic_read(&(__mm)->context.attach_count) > 1 || \
- (__mm) != current->active_mm) \
- huge_ptep_invalidate(__mm, __addr, __ptep); \
+ huge_ptep_invalidate(__mm, __addr, __ptep); \
set_huge_pte_at(__mm, __addr, __ptep, \
huge_pte_wrprotect(__pte)); \
} \
diff --git a/arch/s390/include/asm/tlbflush.h b/arch/s390/include/asm/tlbflush.h
index 9fde315..1d8fe2b 100644
--- a/arch/s390/include/asm/tlbflush.h
+++ b/arch/s390/include/asm/tlbflush.h
@@ -90,12 +90,10 @@ static inline void __tlb_flush_mm(struct mm_struct * mm)
static inline void __tlb_flush_mm_cond(struct mm_struct * mm)
{
- spin_lock(&mm->page_table_lock);
if (mm->context.flush_mm) {
__tlb_flush_mm(mm);
mm->context.flush_mm = 0;
}
- spin_unlock(&mm->page_table_lock);
}
/*
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index f86c81e..40b5769 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -974,11 +974,13 @@ static void __init setup_hwcaps(void)
if (MACHINE_HAS_HPAGE)
elf_hwcap |= HWCAP_S390_HPAGE;
+#if defined(CONFIG_64BIT)
/*
* 64-bit register support for 31-bit processes
* HWCAP_S390_HIGH_GPRS is bit 9.
*/
elf_hwcap |= HWCAP_S390_HIGH_GPRS;
+#endif
get_cpu_id(&cpu_id);
switch (cpu_id.machine) {
diff --git a/arch/s390/lib/uaccess_pt.c b/arch/s390/lib/uaccess_pt.c
index 60ee2b8..2d37bb8 100644
--- a/arch/s390/lib/uaccess_pt.c
+++ b/arch/s390/lib/uaccess_pt.c
@@ -2,69 +2,82 @@
* User access functions based on page table walks for enhanced
* system layout without hardware support.
*
- * Copyright IBM Corp. 2006
+ * Copyright IBM Corp. 2006, 2012
* Author(s): Gerald Schaefer (gerald.schaefer@de.ibm.com)
*/
#include <linux/errno.h>
#include <linux/hardirq.h>
#include <linux/mm.h>
+#include <linux/hugetlb.h>
#include <asm/uaccess.h>
#include <asm/futex.h>
#include "uaccess.h"
-static inline pte_t *follow_table(struct mm_struct *mm, unsigned long addr)
+
+/*
+ * Returns kernel address for user virtual address. If the returned address is
+ * >= -4095 (IS_ERR_VALUE(x) returns true), a fault has occured and the address
+ * contains the (negative) exception code.
+ */
+static __always_inline unsigned long follow_table(struct mm_struct *mm,
+ unsigned long addr, int write)
{
pgd_t *pgd;
pud_t *pud;
pmd_t *pmd;
+ pte_t *ptep;
pgd = pgd_offset(mm, addr);
if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd)))
- return (pte_t *) 0x3a;
+ return -0x3aUL;
pud = pud_offset(pgd, addr);
if (pud_none(*pud) || unlikely(pud_bad(*pud)))
- return (pte_t *) 0x3b;
+ return -0x3bUL;
pmd = pmd_offset(pud, addr);
- if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd)))
- return (pte_t *) 0x10;
+ if (pmd_none(*pmd))
+ return -0x10UL;
+ if (pmd_huge(*pmd)) {
+ if (write && (pmd_val(*pmd) & _SEGMENT_ENTRY_RO))
+ return -0x04UL;
+ return (pmd_val(*pmd) & HPAGE_MASK) + (addr & ~HPAGE_MASK);
+ }
+ if (unlikely(pmd_bad(*pmd)))
+ return -0x10UL;
+
+ ptep = pte_offset_map(pmd, addr);
+ if (!pte_present(*ptep))
+ return -0x11UL;
+ if (write && !pte_write(*ptep))
+ return -0x04UL;
- return pte_offset_map(pmd, addr);
+ return (pte_val(*ptep) & PAGE_MASK) + (addr & ~PAGE_MASK);
}
static __always_inline size_t __user_copy_pt(unsigned long uaddr, void *kptr,
size_t n, int write_user)
{
struct mm_struct *mm = current->mm;
- unsigned long offset, pfn, done, size;
- pte_t *pte;
+ unsigned long offset, done, size, kaddr;
void *from, *to;
done = 0;
retry:
spin_lock(&mm->page_table_lock);
do {
- pte = follow_table(mm, uaddr);
- if ((unsigned long) pte < 0x1000)
+ kaddr = follow_table(mm, uaddr, write_user);
+ if (IS_ERR_VALUE(kaddr))
goto fault;
- if (!pte_present(*pte)) {
- pte = (pte_t *) 0x11;
- goto fault;
- } else if (write_user && !pte_write(*pte)) {
- pte = (pte_t *) 0x04;
- goto fault;
- }
- pfn = pte_pfn(*pte);
- offset = uaddr & (PAGE_SIZE - 1);
+ offset = uaddr & ~PAGE_MASK;
size = min(n - done, PAGE_SIZE - offset);
if (write_user) {
- to = (void *)((pfn << PAGE_SHIFT) + offset);
+ to = (void *) kaddr;
from = kptr + done;
} else {
- from = (void *)((pfn << PAGE_SHIFT) + offset);
+ from = (void *) kaddr;
to = kptr + done;
}
memcpy(to, from, size);
@@ -75,7 +88,7 @@ retry:
return n - done;
fault:
spin_unlock(&mm->page_table_lock);
- if (__handle_fault(uaddr, (unsigned long) pte, write_user))
+ if (__handle_fault(uaddr, -kaddr, write_user))
return n - done;
goto retry;
}
@@ -84,27 +97,22 @@ fault:
* Do DAT for user address by page table walk, return kernel address.
* This function needs to be called with current->mm->page_table_lock held.
*/
-static __always_inline unsigned long __dat_user_addr(unsigned long uaddr)
+static __always_inline unsigned long __dat_user_addr(unsigned long uaddr,
+ int write)
{
struct mm_struct *mm = current->mm;
- unsigned long pfn;
- pte_t *pte;
+ unsigned long kaddr;
int rc;
retry:
- pte = follow_table(mm, uaddr);
- if ((unsigned long) pte < 0x1000)
- goto fault;
- if (!pte_present(*pte)) {
- pte = (pte_t *) 0x11;
+ kaddr = follow_table(mm, uaddr, write);
+ if (IS_ERR_VALUE(kaddr))
goto fault;
- }
- pfn = pte_pfn(*pte);
- return (pfn << PAGE_SHIFT) + (uaddr & (PAGE_SIZE - 1));
+ return kaddr;
fault:
spin_unlock(&mm->page_table_lock);
- rc = __handle_fault(uaddr, (unsigned long) pte, 0);
+ rc = __handle_fault(uaddr, -kaddr, write);
spin_lock(&mm->page_table_lock);
if (!rc)
goto retry;
@@ -159,11 +167,9 @@ static size_t clear_user_pt(size_t n, void __user *to)
static size_t strnlen_user_pt(size_t count, const char __user *src)
{
- char *addr;
unsigned long uaddr = (unsigned long) src;
struct mm_struct *mm = current->mm;
- unsigned long offset, pfn, done, len;
- pte_t *pte;
+ unsigned long offset, done, len, kaddr;
size_t len_str;
if (segment_eq(get_fs(), KERNEL_DS))
@@ -172,19 +178,13 @@ static size_t strnlen_user_pt(size_t count, const char __user *src)
retry:
spin_lock(&mm->page_table_lock);
do {
- pte = follow_table(mm, uaddr);
- if ((unsigned long) pte < 0x1000)
- goto fault;
- if (!pte_present(*pte)) {
- pte = (pte_t *) 0x11;
+ kaddr = follow_table(mm, uaddr, 0);
+ if (IS_ERR_VALUE(kaddr))
goto fault;
- }
- pfn = pte_pfn(*pte);
- offset = uaddr & (PAGE_SIZE-1);
- addr = (char *)(pfn << PAGE_SHIFT) + offset;
+ offset = uaddr & ~PAGE_MASK;
len = min(count - done, PAGE_SIZE - offset);
- len_str = strnlen(addr, len);
+ len_str = strnlen((char *) kaddr, len);
done += len_str;
uaddr += len_str;
} while ((len_str == len) && (done < count));
@@ -192,7 +192,7 @@ retry:
return done + 1;
fault:
spin_unlock(&mm->page_table_lock);
- if (__handle_fault(uaddr, (unsigned long) pte, 0))
+ if (__handle_fault(uaddr, -kaddr, 0))
return 0;
goto retry;
}
@@ -225,11 +225,10 @@ static size_t copy_in_user_pt(size_t n, void __user *to,
const void __user *from)
{
struct mm_struct *mm = current->mm;
- unsigned long offset_from, offset_to, offset_max, pfn_from, pfn_to,
- uaddr, done, size, error_code;
+ unsigned long offset_max, uaddr, done, size, error_code;
unsigned long uaddr_from = (unsigned long) from;
unsigned long uaddr_to = (unsigned long) to;
- pte_t *pte_from, *pte_to;
+ unsigned long kaddr_to, kaddr_from;
int write_user;
if (segment_eq(get_fs(), KERNEL_DS)) {
@@ -242,38 +241,23 @@ retry:
do {
write_user = 0;
uaddr = uaddr_from;
- pte_from = follow_table(mm, uaddr_from);
- error_code = (unsigned long) pte_from;
- if (error_code < 0x1000)
- goto fault;
- if (!pte_present(*pte_from)) {
- error_code = 0x11;
+ kaddr_from = follow_table(mm, uaddr_from, 0);
+ error_code = kaddr_from;
+ if (IS_ERR_VALUE(error_code))
goto fault;
- }
write_user = 1;
uaddr = uaddr_to;
- pte_to = follow_table(mm, uaddr_to);
- error_code = (unsigned long) pte_to;
- if (error_code < 0x1000)
- goto fault;
- if (!pte_present(*pte_to)) {
- error_code = 0x11;
+ kaddr_to = follow_table(mm, uaddr_to, 1);
+ error_code = (unsigned long) kaddr_to;
+ if (IS_ERR_VALUE(error_code))
goto fault;
- } else if (!pte_write(*pte_to)) {
- error_code = 0x04;
- goto fault;
- }
- pfn_from = pte_pfn(*pte_from);
- pfn_to = pte_pfn(*pte_to);
- offset_from = uaddr_from & (PAGE_SIZE-1);
- offset_to = uaddr_from & (PAGE_SIZE-1);
- offset_max = max(offset_from, offset_to);
+ offset_max = max(uaddr_from & ~PAGE_MASK,
+ uaddr_to & ~PAGE_MASK);
size = min(n - done, PAGE_SIZE - offset_max);
- memcpy((void *)(pfn_to << PAGE_SHIFT) + offset_to,
- (void *)(pfn_from << PAGE_SHIFT) + offset_from, size);
+ memcpy((void *) kaddr_to, (void *) kaddr_from, size);
done += size;
uaddr_from += size;
uaddr_to += size;
@@ -282,7 +266,7 @@ retry:
return n - done;
fault:
spin_unlock(&mm->page_table_lock);
- if (__handle_fault(uaddr, error_code, write_user))
+ if (__handle_fault(uaddr, -error_code, write_user))
return n - done;
goto retry;
}
@@ -341,7 +325,7 @@ int futex_atomic_op_pt(int op, u32 __user *uaddr, int oparg, int *old)
return __futex_atomic_op_pt(op, uaddr, oparg, old);
spin_lock(&current->mm->page_table_lock);
uaddr = (u32 __force __user *)
- __dat_user_addr((__force unsigned long) uaddr);
+ __dat_user_addr((__force unsigned long) uaddr, 1);
if (!uaddr) {
spin_unlock(&current->mm->page_table_lock);
return -EFAULT;
@@ -378,7 +362,7 @@ int futex_atomic_cmpxchg_pt(u32 *uval, u32 __user *uaddr,
return __futex_atomic_cmpxchg_pt(uval, uaddr, oldval, newval);
spin_lock(&current->mm->page_table_lock);
uaddr = (u32 __force __user *)
- __dat_user_addr((__force unsigned long) uaddr);
+ __dat_user_addr((__force unsigned long) uaddr, 1);
if (!uaddr) {
spin_unlock(&current->mm->page_table_lock);
return -EFAULT;
diff --git a/arch/sh/kernel/cpu/sh5/entry.S b/arch/sh/kernel/cpu/sh5/entry.S
index b7cf6a5..7e605b9 100644
--- a/arch/sh/kernel/cpu/sh5/entry.S
+++ b/arch/sh/kernel/cpu/sh5/entry.S
@@ -933,7 +933,7 @@ ret_with_reschedule:
pta restore_all, tr1
- movi _TIF_SIGPENDING, r8
+ movi (_TIF_SIGPENDING|_TIF_NOTIFY_RESUME), r8
and r8, r7, r8
pta work_notifysig, tr0
bne r8, ZERO, tr0
diff --git a/arch/sh/kernel/entry-common.S b/arch/sh/kernel/entry-common.S
index f67601c..b96489d 100644
--- a/arch/sh/kernel/entry-common.S
+++ b/arch/sh/kernel/entry-common.S
@@ -139,7 +139,7 @@ work_pending:
! r8: current_thread_info
! t: result of "tst #_TIF_NEED_RESCHED, r0"
bf/s work_resched
- tst #_TIF_SIGPENDING, r0
+ tst #(_TIF_SIGPENDING | _TIF_NOTIFY_RESUME), r0
work_notifysig:
bt/s __restore_all
mov r15, r4
diff --git a/arch/sparc/kernel/module.c b/arch/sparc/kernel/module.c
index 15e0a16..f1ddc0d 100644
--- a/arch/sparc/kernel/module.c
+++ b/arch/sparc/kernel/module.c
@@ -48,9 +48,7 @@ void *module_alloc(unsigned long size)
return NULL;
ret = module_map(size);
- if (!ret)
- ret = ERR_PTR(-ENOMEM);
- else
+ if (ret)
memset(ret, 0, size);
return ret;
@@ -116,6 +114,10 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
v = sym->st_value + rel[i].r_addend;
switch (ELF_R_TYPE(rel[i].r_info) & 0xff) {
+ case R_SPARC_DISP32:
+ v -= (Elf_Addr) location;
+ *loc32 = v;
+ break;
#ifdef CONFIG_SPARC64
case R_SPARC_64:
location[0] = v >> 56;
@@ -128,11 +130,6 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
location[7] = v >> 0;
break;
- case R_SPARC_DISP32:
- v -= (Elf_Addr) location;
- *loc32 = v;
- break;
-
case R_SPARC_WDISP19:
v -= (Elf_Addr) location;
*loc32 = (*loc32 & ~0x7ffff) |
diff --git a/arch/tile/include/gxio/iorpc_trio.h b/arch/tile/include/gxio/iorpc_trio.h
index 15fb779..58105c3 100644
--- a/arch/tile/include/gxio/iorpc_trio.h
+++ b/arch/tile/include/gxio/iorpc_trio.h
@@ -25,21 +25,23 @@
#include <linux/module.h>
#include <asm/pgtable.h>
-#define GXIO_TRIO_OP_ALLOC_ASIDS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1400)
+#define GXIO_TRIO_OP_DEALLOC_ASID IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1400)
+#define GXIO_TRIO_OP_ALLOC_ASIDS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1401)
-#define GXIO_TRIO_OP_ALLOC_MEMORY_MAPS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1402)
+#define GXIO_TRIO_OP_ALLOC_MEMORY_MAPS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1404)
-#define GXIO_TRIO_OP_ALLOC_PIO_REGIONS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x140e)
-#define GXIO_TRIO_OP_INIT_PIO_REGION_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x140f)
+#define GXIO_TRIO_OP_ALLOC_PIO_REGIONS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1412)
-#define GXIO_TRIO_OP_INIT_MEMORY_MAP_MMU_AUX IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x1417)
-#define GXIO_TRIO_OP_GET_PORT_PROPERTY IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x1418)
-#define GXIO_TRIO_OP_CONFIG_LEGACY_INTR IORPC_OPCODE(IORPC_FORMAT_KERNEL_INTERRUPT, 0x1419)
-#define GXIO_TRIO_OP_CONFIG_MSI_INTR IORPC_OPCODE(IORPC_FORMAT_KERNEL_INTERRUPT, 0x141a)
+#define GXIO_TRIO_OP_INIT_PIO_REGION_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1414)
-#define GXIO_TRIO_OP_SET_MPS_MRS IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x141c)
-#define GXIO_TRIO_OP_FORCE_RC_LINK_UP IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x141d)
-#define GXIO_TRIO_OP_FORCE_EP_LINK_UP IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x141e)
+#define GXIO_TRIO_OP_INIT_MEMORY_MAP_MMU_AUX IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x141e)
+#define GXIO_TRIO_OP_GET_PORT_PROPERTY IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x141f)
+#define GXIO_TRIO_OP_CONFIG_LEGACY_INTR IORPC_OPCODE(IORPC_FORMAT_KERNEL_INTERRUPT, 0x1420)
+#define GXIO_TRIO_OP_CONFIG_MSI_INTR IORPC_OPCODE(IORPC_FORMAT_KERNEL_INTERRUPT, 0x1421)
+
+#define GXIO_TRIO_OP_SET_MPS_MRS IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x1423)
+#define GXIO_TRIO_OP_FORCE_RC_LINK_UP IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x1424)
+#define GXIO_TRIO_OP_FORCE_EP_LINK_UP IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x1425)
#define GXIO_TRIO_OP_GET_MMIO_BASE IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x8000)
#define GXIO_TRIO_OP_CHECK_MMIO_OFFSET IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x8001)
diff --git a/arch/um/include/asm/processor-generic.h b/arch/um/include/asm/processor-generic.h
index 69f1c57..33a6a24 100644
--- a/arch/um/include/asm/processor-generic.h
+++ b/arch/um/include/asm/processor-generic.h
@@ -20,14 +20,6 @@ struct mm_struct;
struct thread_struct {
struct task_struct *saved_task;
- /*
- * This flag is set to 1 before calling do_fork (and analyzed in
- * copy_thread) to mark that we are begin called from userspace (fork /
- * vfork / clone), and reset to 0 after. It is left to 0 when called
- * from kernelspace (i.e. kernel_thread() or fork_idle(),
- * as of 2.6.11).
- */
- int forking;
struct pt_regs regs;
int singlestep_syscall;
void *fault_addr;
@@ -58,7 +50,6 @@ struct thread_struct {
#define INIT_THREAD \
{ \
- .forking = 0, \
.regs = EMPTY_REGS, \
.fault_addr = NULL, \
.prev_sched = NULL, \
diff --git a/arch/um/include/shared/common-offsets.h b/arch/um/include/shared/common-offsets.h
index 40db8f7..2df313b 100644
--- a/arch/um/include/shared/common-offsets.h
+++ b/arch/um/include/shared/common-offsets.h
@@ -7,16 +7,6 @@ DEFINE(UM_KERN_PAGE_MASK, PAGE_MASK);
DEFINE(UM_KERN_PAGE_SHIFT, PAGE_SHIFT);
DEFINE(UM_NSEC_PER_SEC, NSEC_PER_SEC);
-DEFINE_STR(UM_KERN_EMERG, KERN_EMERG);
-DEFINE_STR(UM_KERN_ALERT, KERN_ALERT);
-DEFINE_STR(UM_KERN_CRIT, KERN_CRIT);
-DEFINE_STR(UM_KERN_ERR, KERN_ERR);
-DEFINE_STR(UM_KERN_WARNING, KERN_WARNING);
-DEFINE_STR(UM_KERN_NOTICE, KERN_NOTICE);
-DEFINE_STR(UM_KERN_INFO, KERN_INFO);
-DEFINE_STR(UM_KERN_DEBUG, KERN_DEBUG);
-DEFINE_STR(UM_KERN_CONT, KERN_CONT);
-
DEFINE(UM_ELF_CLASS, ELF_CLASS);
DEFINE(UM_ELFCLASS32, ELFCLASS32);
DEFINE(UM_ELFCLASS64, ELFCLASS64);
diff --git a/arch/um/include/shared/user.h b/arch/um/include/shared/user.h
index 4fa82c0..cef0685 100644
--- a/arch/um/include/shared/user.h
+++ b/arch/um/include/shared/user.h
@@ -26,6 +26,17 @@
extern void panic(const char *fmt, ...)
__attribute__ ((format (printf, 1, 2)));
+/* Requires preincluding include/linux/kern_levels.h */
+#define UM_KERN_EMERG KERN_EMERG
+#define UM_KERN_ALERT KERN_ALERT
+#define UM_KERN_CRIT KERN_CRIT
+#define UM_KERN_ERR KERN_ERR
+#define UM_KERN_WARNING KERN_WARNING
+#define UM_KERN_NOTICE KERN_NOTICE
+#define UM_KERN_INFO KERN_INFO
+#define UM_KERN_DEBUG KERN_DEBUG
+#define UM_KERN_CONT KERN_CONT
+
#ifdef UML_CONFIG_PRINTK
extern int printk(const char *fmt, ...)
__attribute__ ((format (printf, 1, 2)));
diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c
index 6cade93..8c82786 100644
--- a/arch/um/kernel/exec.c
+++ b/arch/um/kernel/exec.c
@@ -39,34 +39,21 @@ void flush_thread(void)
void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp)
{
+ get_safe_registers(regs->regs.gp, regs->regs.fp);
PT_REGS_IP(regs) = eip;
PT_REGS_SP(regs) = esp;
-}
-EXPORT_SYMBOL(start_thread);
-
-static long execve1(const char *file,
- const char __user *const __user *argv,
- const char __user *const __user *env)
-{
- long error;
-
- error = do_execve(file, argv, env, &current->thread.regs);
- if (error == 0) {
- task_lock(current);
- current->ptrace &= ~PT_DTRACE;
+ current->ptrace &= ~PT_DTRACE;
#ifdef SUBARCH_EXECVE1
- SUBARCH_EXECVE1(&current->thread.regs.regs);
+ SUBARCH_EXECVE1(regs->regs);
#endif
- task_unlock(current);
- }
- return error;
}
+EXPORT_SYMBOL(start_thread);
long um_execve(const char *file, const char __user *const __user *argv, const char __user *const __user *env)
{
long err;
- err = execve1(file, argv, env);
+ err = do_execve(file, argv, env, &current->thread.regs);
if (!err)
UML_LONGJMP(current->thread.exec_buf, 1);
return err;
@@ -81,7 +68,7 @@ long sys_execve(const char __user *file, const char __user *const __user *argv,
filename = getname(file);
error = PTR_ERR(filename);
if (IS_ERR(filename)) goto out;
- error = execve1(filename, argv, env);
+ error = do_execve(filename, argv, env, &current->thread.regs);
putname(filename);
out:
return error;
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c
index 57fc702..c5f5afa 100644
--- a/arch/um/kernel/process.c
+++ b/arch/um/kernel/process.c
@@ -181,11 +181,12 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
struct pt_regs *regs)
{
void (*handler)(void);
+ int kthread = current->flags & PF_KTHREAD;
int ret = 0;
p->thread = (struct thread_struct) INIT_THREAD;
- if (current->thread.forking) {
+ if (!kthread) {
memcpy(&p->thread.regs.regs, &regs->regs,
sizeof(p->thread.regs.regs));
PT_REGS_SET_SYSCALL_RETURN(&p->thread.regs, 0);
@@ -195,8 +196,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
handler = fork_handler;
arch_copy_thread(&current->thread.arch, &p->thread.arch);
- }
- else {
+ } else {
get_safe_registers(p->thread.regs.regs.gp, p->thread.regs.regs.fp);
p->thread.request.u.thread = current->thread.request.u.thread;
handler = new_thread_handler;
@@ -204,7 +204,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
new_thread(task_stack_page(p), &p->thread.switch_buf, handler);
- if (current->thread.forking) {
+ if (!kthread) {
clear_flushed_tls(p);
/*
diff --git a/arch/um/kernel/signal.c b/arch/um/kernel/signal.c
index 7362d58..cc9c235 100644
--- a/arch/um/kernel/signal.c
+++ b/arch/um/kernel/signal.c
@@ -22,9 +22,13 @@ static void handle_signal(struct pt_regs *regs, unsigned long signr,
struct k_sigaction *ka, siginfo_t *info)
{
sigset_t *oldset = sigmask_to_save();
+ int singlestep = 0;
unsigned long sp;
int err;
+ if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED))
+ singlestep = 1;
+
/* Did we come from a system call? */
if (PT_REGS_SYSCALL_NR(regs) >= 0) {
/* If so, check system call restarting.. */
@@ -61,7 +65,7 @@ static void handle_signal(struct pt_regs *regs, unsigned long signr,
if (err)
force_sigsegv(signr, current);
else
- signal_delivered(signr, info, ka, regs, 0);
+ signal_delivered(signr, info, ka, regs, singlestep);
}
static int kern_do_signal(struct pt_regs *regs)
diff --git a/arch/um/kernel/syscall.c b/arch/um/kernel/syscall.c
index f958cb8..a4c6d8e 100644
--- a/arch/um/kernel/syscall.c
+++ b/arch/um/kernel/syscall.c
@@ -17,25 +17,25 @@
long sys_fork(void)
{
- long ret;
-
- current->thread.forking = 1;
- ret = do_fork(SIGCHLD, UPT_SP(&current->thread.regs.regs),
+ return do_fork(SIGCHLD, UPT_SP(&current->thread.regs.regs),
&current->thread.regs, 0, NULL, NULL);
- current->thread.forking = 0;
- return ret;
}
long sys_vfork(void)
{
- long ret;
-
- current->thread.forking = 1;
- ret = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD,
+ return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD,
UPT_SP(&current->thread.regs.regs),
&current->thread.regs, 0, NULL, NULL);
- current->thread.forking = 0;
- return ret;
+}
+
+long sys_clone(unsigned long clone_flags, unsigned long newsp,
+ void __user *parent_tid, void __user *child_tid)
+{
+ if (!newsp)
+ newsp = UPT_SP(&current->thread.regs.regs);
+
+ return do_fork(clone_flags, newsp, &current->thread.regs, 0, parent_tid,
+ child_tid);
}
long old_mmap(unsigned long addr, unsigned long len,
diff --git a/arch/um/scripts/Makefile.rules b/arch/um/scripts/Makefile.rules
index d50270d..15889df 100644
--- a/arch/um/scripts/Makefile.rules
+++ b/arch/um/scripts/Makefile.rules
@@ -8,7 +8,7 @@ USER_OBJS += $(filter %_user.o,$(obj-y) $(obj-m) $(USER_SINGLE_OBJS))
USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
$(USER_OBJS:.o=.%): \
- c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) -include user.h $(CFLAGS_$(basetarget).o)
+ c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) -include $(srctree)/include/linux/kern_levels.h -include user.h $(CFLAGS_$(basetarget).o)
# These are like USER_OBJS but filter USER_CFLAGS through unprofile instead of
# using it directly.
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 8ec3a1a..50a1d1f 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -746,10 +746,10 @@ config SWIOTLB
def_bool y if X86_64
---help---
Support for software bounce buffers used on x86-64 systems
- which don't have a hardware IOMMU (e.g. the current generation
- of Intel's x86-64 CPUs). Using this PCI devices which can only
- access 32-bits of memory can be used on systems with more than
- 3 GB of memory. If unsure, say Y.
+ which don't have a hardware IOMMU. Using this PCI devices
+ which can only access 32-bits of memory can be used on systems
+ with more than 3 GB of memory.
+ If unsure, say Y.
config IOMMU_HELPER
def_bool (CALGARY_IOMMU || GART_IOMMU || SWIOTLB || AMD_IOMMU)
diff --git a/arch/x86/Makefile b/arch/x86/Makefile
index 682e9c2..474ca35 100644
--- a/arch/x86/Makefile
+++ b/arch/x86/Makefile
@@ -142,7 +142,7 @@ KBUILD_CFLAGS += $(call cc-option,-mno-avx,)
KBUILD_CFLAGS += $(mflags-y)
KBUILD_AFLAGS += $(mflags-y)
-archscripts:
+archscripts: scripts_basic
$(Q)$(MAKE) $(build)=arch/x86/tools relocs
###
diff --git a/arch/x86/include/asm/xen/page.h b/arch/x86/include/asm/xen/page.h
index 93971e8..472b9b7 100644
--- a/arch/x86/include/asm/xen/page.h
+++ b/arch/x86/include/asm/xen/page.h
@@ -51,7 +51,8 @@ extern unsigned long set_phys_range_identity(unsigned long pfn_s,
extern int m2p_add_override(unsigned long mfn, struct page *page,
struct gnttab_map_grant_ref *kmap_op);
-extern int m2p_remove_override(struct page *page, bool clear_pte);
+extern int m2p_remove_override(struct page *page,
+ struct gnttab_map_grant_ref *kmap_op);
extern struct page *m2p_find_override(unsigned long mfn);
extern unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn);
diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h
index 6605a81..8b6defe 100644
--- a/arch/x86/kernel/cpu/perf_event.h
+++ b/arch/x86/kernel/cpu/perf_event.h
@@ -586,6 +586,8 @@ extern struct event_constraint intel_westmere_pebs_event_constraints[];
extern struct event_constraint intel_snb_pebs_event_constraints[];
+extern struct event_constraint intel_ivb_pebs_event_constraints[];
+
struct event_constraint *intel_pebs_constraints(struct perf_event *event);
void intel_pmu_pebs_enable(struct perf_event *event);
diff --git a/arch/x86/kernel/cpu/perf_event_amd_ibs.c b/arch/x86/kernel/cpu/perf_event_amd_ibs.c
index 7bfb5be..eebd5ff 100644
--- a/arch/x86/kernel/cpu/perf_event_amd_ibs.c
+++ b/arch/x86/kernel/cpu/perf_event_amd_ibs.c
@@ -209,6 +209,15 @@ static int perf_ibs_precise_event(struct perf_event *event, u64 *config)
return -EOPNOTSUPP;
}
+static const struct perf_event_attr ibs_notsupp = {
+ .exclude_user = 1,
+ .exclude_kernel = 1,
+ .exclude_hv = 1,
+ .exclude_idle = 1,
+ .exclude_host = 1,
+ .exclude_guest = 1,
+};
+
static int perf_ibs_init(struct perf_event *event)
{
struct hw_perf_event *hwc = &event->hw;
@@ -229,6 +238,9 @@ static int perf_ibs_init(struct perf_event *event)
if (event->pmu != &perf_ibs->pmu)
return -ENOENT;
+ if (perf_flags(&event->attr) & perf_flags(&ibs_notsupp))
+ return -EINVAL;
+
if (config & ~perf_ibs->config_mask)
return -EINVAL;
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c
index 0d3d63a..6bca492 100644
--- a/arch/x86/kernel/cpu/perf_event_intel.c
+++ b/arch/x86/kernel/cpu/perf_event_intel.c
@@ -2048,7 +2048,6 @@ __init int intel_pmu_init(void)
case 42: /* SandyBridge */
case 45: /* SandyBridge, "Romely-EP" */
x86_add_quirk(intel_sandybridge_quirk);
- case 58: /* IvyBridge */
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,
@@ -2073,6 +2072,29 @@ __init int intel_pmu_init(void)
pr_cont("SandyBridge events, ");
break;
+ case 58: /* IvyBridge */
+ 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));
+
+ intel_pmu_lbr_init_snb();
+
+ x86_pmu.event_constraints = intel_snb_event_constraints;
+ x86_pmu.pebs_constraints = intel_ivb_pebs_event_constraints;
+ x86_pmu.pebs_aliases = intel_pebs_aliases_snb;
+ x86_pmu.extra_regs = intel_snb_extra_regs;
+ /* all extra regs are per-cpu when HT is on */
+ x86_pmu.er_flags |= ERF_HAS_RSP_1;
+ x86_pmu.er_flags |= ERF_NO_HT_SHARING;
+
+ /* UOPS_ISSUED.ANY,c=1,i=1 to count stall cycles */
+ intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] =
+ X86_CONFIG(.event=0x0e, .umask=0x01, .inv=1, .cmask=1);
+
+ pr_cont("IvyBridge events, ");
+ break;
+
default:
switch (x86_pmu.version) {
diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c
index e38d97b..826054a 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_ds.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c
@@ -407,6 +407,20 @@ struct event_constraint intel_snb_pebs_event_constraints[] = {
EVENT_CONSTRAINT_END
};
+struct event_constraint intel_ivb_pebs_event_constraints[] = {
+ INTEL_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PRECDIST */
+ INTEL_UEVENT_CONSTRAINT(0x01c2, 0xf), /* UOPS_RETIRED.ALL */
+ INTEL_UEVENT_CONSTRAINT(0x02c2, 0xf), /* UOPS_RETIRED.RETIRE_SLOTS */
+ INTEL_EVENT_CONSTRAINT(0xc4, 0xf), /* BR_INST_RETIRED.* */
+ INTEL_EVENT_CONSTRAINT(0xc5, 0xf), /* BR_MISP_RETIRED.* */
+ INTEL_EVENT_CONSTRAINT(0xcd, 0x8), /* MEM_TRANS_RETIRED.* */
+ INTEL_EVENT_CONSTRAINT(0xd0, 0xf), /* MEM_UOP_RETIRED.* */
+ INTEL_EVENT_CONSTRAINT(0xd1, 0xf), /* MEM_LOAD_UOPS_RETIRED.* */
+ INTEL_EVENT_CONSTRAINT(0xd2, 0xf), /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.* */
+ INTEL_EVENT_CONSTRAINT(0xd3, 0xf), /* MEM_LOAD_UOPS_LLC_MISS_RETIRED.* */
+ EVENT_CONSTRAINT_END
+};
+
struct event_constraint *intel_pebs_constraints(struct perf_event *event)
{
struct event_constraint *c;
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c
index 0a55710..38e4894 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_uncore.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.c
@@ -661,6 +661,11 @@ static void snb_uncore_msr_init_box(struct intel_uncore_box *box)
}
}
+static struct uncore_event_desc snb_uncore_events[] = {
+ INTEL_UNCORE_EVENT_DESC(clockticks, "event=0xff,umask=0x00"),
+ { /* end: all zeroes */ },
+};
+
static struct attribute *snb_uncore_formats_attr[] = {
&format_attr_event.attr,
&format_attr_umask.attr,
@@ -704,6 +709,7 @@ static struct intel_uncore_type snb_uncore_cbox = {
.constraints = snb_uncore_cbox_constraints,
.ops = &snb_uncore_msr_ops,
.format_group = &snb_uncore_format_group,
+ .event_descs = snb_uncore_events,
};
static struct intel_uncore_type *snb_msr_uncores[] = {
diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
index e0e6990..ab1f6a9 100644
--- a/arch/x86/mm/init.c
+++ b/arch/x86/mm/init.c
@@ -319,7 +319,7 @@ unsigned long __init_refok init_memory_mapping(unsigned long start,
*/
int devmem_is_allowed(unsigned long pagenr)
{
- if (pagenr <= 256)
+ if (pagenr < 256)
return 1;
if (iomem_is_exclusive(pagenr << PAGE_SHIFT))
return 0;
diff --git a/arch/x86/um/Kconfig b/arch/x86/um/Kconfig
index 9926e11..aeaff8b 100644
--- a/arch/x86/um/Kconfig
+++ b/arch/x86/um/Kconfig
@@ -21,6 +21,7 @@ config 64BIT
config X86_32
def_bool !64BIT
select HAVE_AOUT
+ select ARCH_WANT_IPC_PARSE_VERSION
config X86_64
def_bool 64BIT
diff --git a/arch/x86/um/shared/sysdep/kernel-offsets.h b/arch/x86/um/shared/sysdep/kernel-offsets.h
index 5868526..46a9df9 100644
--- a/arch/x86/um/shared/sysdep/kernel-offsets.h
+++ b/arch/x86/um/shared/sysdep/kernel-offsets.h
@@ -7,9 +7,6 @@
#define DEFINE(sym, val) \
asm volatile("\n->" #sym " %0 " #val : : "i" (val))
-#define STR(x) #x
-#define DEFINE_STR(sym, val) asm volatile("\n->" #sym " " STR(val) " " #val: : )
-
#define BLANK() asm volatile("\n->" : : )
#define OFFSET(sym, str, mem) \
diff --git a/arch/x86/um/shared/sysdep/syscalls.h b/arch/x86/um/shared/sysdep/syscalls.h
index bd9a89b..ca255a8 100644
--- a/arch/x86/um/shared/sysdep/syscalls.h
+++ b/arch/x86/um/shared/sysdep/syscalls.h
@@ -1,3 +1,5 @@
+extern long sys_clone(unsigned long clone_flags, unsigned long newsp,
+ void __user *parent_tid, void __user *child_tid);
#ifdef __i386__
#include "syscalls_32.h"
#else
diff --git a/arch/x86/um/signal.c b/arch/x86/um/signal.c
index a508cea1..ba7363e 100644
--- a/arch/x86/um/signal.c
+++ b/arch/x86/um/signal.c
@@ -416,9 +416,6 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig,
PT_REGS_AX(regs) = (unsigned long) sig;
PT_REGS_DX(regs) = (unsigned long) 0;
PT_REGS_CX(regs) = (unsigned long) 0;
-
- if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED))
- ptrace_notify(SIGTRAP);
return 0;
}
@@ -466,9 +463,6 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
PT_REGS_AX(regs) = (unsigned long) sig;
PT_REGS_DX(regs) = (unsigned long) &frame->info;
PT_REGS_CX(regs) = (unsigned long) &frame->uc;
-
- if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED))
- ptrace_notify(SIGTRAP);
return 0;
}
diff --git a/arch/x86/um/sys_call_table_32.c b/arch/x86/um/sys_call_table_32.c
index 68d1dc9..b5408ce 100644
--- a/arch/x86/um/sys_call_table_32.c
+++ b/arch/x86/um/sys_call_table_32.c
@@ -28,7 +28,7 @@
#define ptregs_execve sys_execve
#define ptregs_iopl sys_iopl
#define ptregs_vm86old sys_vm86old
-#define ptregs_clone sys_clone
+#define ptregs_clone i386_clone
#define ptregs_vm86 sys_vm86
#define ptregs_sigaltstack sys_sigaltstack
#define ptregs_vfork sys_vfork
diff --git a/arch/x86/um/syscalls_32.c b/arch/x86/um/syscalls_32.c
index b853e86..db444c7 100644
--- a/arch/x86/um/syscalls_32.c
+++ b/arch/x86/um/syscalls_32.c
@@ -3,37 +3,24 @@
* Licensed under the GPL
*/
-#include "linux/sched.h"
-#include "linux/shm.h"
-#include "linux/ipc.h"
-#include "linux/syscalls.h"
-#include "asm/mman.h"
-#include "asm/uaccess.h"
-#include "asm/unistd.h"
+#include <linux/syscalls.h>
+#include <sysdep/syscalls.h>
/*
* The prototype on i386 is:
*
- * int clone(int flags, void * child_stack, int * parent_tidptr, struct user_desc * newtls, int * child_tidptr)
+ * int clone(int flags, void * child_stack, int * parent_tidptr, struct user_desc * newtls
*
* and the "newtls" arg. on i386 is read by copy_thread directly from the
* register saved on the stack.
*/
-long sys_clone(unsigned long clone_flags, unsigned long newsp,
- int __user *parent_tid, void *newtls, int __user *child_tid)
+long i386_clone(unsigned long clone_flags, unsigned long newsp,
+ int __user *parent_tid, void *newtls, int __user *child_tid)
{
- long ret;
-
- if (!newsp)
- newsp = UPT_SP(&current->thread.regs.regs);
-
- current->thread.forking = 1;
- ret = do_fork(clone_flags, newsp, &current->thread.regs, 0, parent_tid,
- child_tid);
- current->thread.forking = 0;
- return ret;
+ return sys_clone(clone_flags, newsp, parent_tid, child_tid);
}
+
long sys_sigaction(int sig, const struct old_sigaction __user *act,
struct old_sigaction __user *oact)
{
diff --git a/arch/x86/um/syscalls_64.c b/arch/x86/um/syscalls_64.c
index f3d82bb..adb08eb 100644
--- a/arch/x86/um/syscalls_64.c
+++ b/arch/x86/um/syscalls_64.c
@@ -5,12 +5,9 @@
* Licensed under the GPL
*/
-#include "linux/linkage.h"
-#include "linux/personality.h"
-#include "linux/utsname.h"
-#include "asm/prctl.h" /* XXX This should get the constants from libc */
-#include "asm/uaccess.h"
-#include "os.h"
+#include <linux/sched.h>
+#include <asm/prctl.h> /* XXX This should get the constants from libc */
+#include <os.h>
long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr)
{
@@ -79,20 +76,6 @@ long sys_arch_prctl(int code, unsigned long addr)
return arch_prctl(current, code, (unsigned long __user *) addr);
}
-long sys_clone(unsigned long clone_flags, unsigned long newsp,
- void __user *parent_tid, void __user *child_tid)
-{
- long ret;
-
- if (!newsp)
- newsp = UPT_SP(&current->thread.regs.regs);
- current->thread.forking = 1;
- ret = do_fork(clone_flags, newsp, &current->thread.regs, 0, parent_tid,
- child_tid);
- current->thread.forking = 0;
- return ret;
-}
-
void arch_switch_to(struct task_struct *to)
{
if ((to->thread.arch.fs == 0) || (to->mm == NULL))
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 9642d4a..1fbe75a 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -1452,6 +1452,10 @@ asmlinkage void __init xen_start_kernel(void)
pci_request_acs();
xen_acpi_sleep_register();
+
+ /* Avoid searching for BIOS MP tables */
+ x86_init.mpparse.find_smp_config = x86_init_noop;
+ x86_init.mpparse.get_smp_config = x86_init_uint_noop;
}
#ifdef CONFIG_PCI
/* PCI BIOS service won't work from a PV guest. */
diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c
index 76ba0e9..72213da 100644
--- a/arch/x86/xen/p2m.c
+++ b/arch/x86/xen/p2m.c
@@ -828,9 +828,6 @@ int m2p_add_override(unsigned long mfn, struct page *page,
xen_mc_issue(PARAVIRT_LAZY_MMU);
}
- /* let's use dev_bus_addr to record the old mfn instead */
- kmap_op->dev_bus_addr = page->index;
- page->index = (unsigned long) kmap_op;
}
spin_lock_irqsave(&m2p_override_lock, flags);
list_add(&page->lru, &m2p_overrides[mfn_hash(mfn)]);
@@ -857,7 +854,8 @@ int m2p_add_override(unsigned long mfn, struct page *page,
return 0;
}
EXPORT_SYMBOL_GPL(m2p_add_override);
-int m2p_remove_override(struct page *page, bool clear_pte)
+int m2p_remove_override(struct page *page,
+ struct gnttab_map_grant_ref *kmap_op)
{
unsigned long flags;
unsigned long mfn;
@@ -887,10 +885,8 @@ int m2p_remove_override(struct page *page, bool clear_pte)
WARN_ON(!PagePrivate(page));
ClearPagePrivate(page);
- if (clear_pte) {
- struct gnttab_map_grant_ref *map_op =
- (struct gnttab_map_grant_ref *) page->index;
- set_phys_to_machine(pfn, map_op->dev_bus_addr);
+ set_phys_to_machine(pfn, page->index);
+ if (kmap_op != NULL) {
if (!PageHighMem(page)) {
struct multicall_space mcs;
struct gnttab_unmap_grant_ref *unmap_op;
@@ -902,13 +898,13 @@ int m2p_remove_override(struct page *page, bool clear_pte)
* issued. In this case handle is going to -1 because
* it hasn't been modified yet.
*/
- if (map_op->handle == -1)
+ if (kmap_op->handle == -1)
xen_mc_flush();
/*
- * Now if map_op->handle is negative it means that the
+ * Now if kmap_op->handle is negative it means that the
* hypercall actually returned an error.
*/
- if (map_op->handle == GNTST_general_error) {
+ if (kmap_op->handle == GNTST_general_error) {
printk(KERN_WARNING "m2p_remove_override: "
"pfn %lx mfn %lx, failed to modify kernel mappings",
pfn, mfn);
@@ -918,8 +914,8 @@ int m2p_remove_override(struct page *page, bool clear_pte)
mcs = xen_mc_entry(
sizeof(struct gnttab_unmap_grant_ref));
unmap_op = mcs.args;
- unmap_op->host_addr = map_op->host_addr;
- unmap_op->handle = map_op->handle;
+ unmap_op->host_addr = kmap_op->host_addr;
+ unmap_op->handle = kmap_op->handle;
unmap_op->dev_bus_addr = 0;
MULTI_grant_table_op(mcs.mc,
@@ -930,10 +926,9 @@ int m2p_remove_override(struct page *page, bool clear_pte)
set_pte_at(&init_mm, address, ptep,
pfn_pte(pfn, PAGE_KERNEL));
__flush_tlb_single(address);
- map_op->host_addr = 0;
+ kmap_op->host_addr = 0;
}
- } else
- set_phys_to_machine(pfn, page->index);
+ }
/* p2m(m2p(mfn)) == FOREIGN_FRAME(mfn): the mfn is already present
* somewhere in this domain, even before being added to the
diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c
index d11ca11..e2d62d6 100644
--- a/arch/x86/xen/setup.c
+++ b/arch/x86/xen/setup.c
@@ -17,6 +17,7 @@
#include <asm/e820.h>
#include <asm/setup.h>
#include <asm/acpi.h>
+#include <asm/numa.h>
#include <asm/xen/hypervisor.h>
#include <asm/xen/hypercall.h>
@@ -544,4 +545,7 @@ void __init xen_arch_setup(void)
disable_cpufreq();
WARN_ON(set_pm_idle_to_default());
fiddle_vdso();
+#ifdef CONFIG_NUMA
+ numa_off = 1;
+#endif
}
diff --git a/block/blk-core.c b/block/blk-core.c
index 4b4dbdf..ee3cb3a 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -2254,9 +2254,11 @@ bool blk_update_request(struct request *req, int error, unsigned int nr_bytes)
error_type = "I/O";
break;
}
- printk(KERN_ERR "end_request: %s error, dev %s, sector %llu\n",
- error_type, req->rq_disk ? req->rq_disk->disk_name : "?",
- (unsigned long long)blk_rq_pos(req));
+ printk_ratelimited(KERN_ERR "end_request: %s error, dev %s, sector %llu\n",
+ error_type, req->rq_disk ?
+ req->rq_disk->disk_name : "?",
+ (unsigned long long)blk_rq_pos(req));
+
}
blk_account_io_completion(req, nr_bytes);
diff --git a/block/ioctl.c b/block/ioctl.c
index 4476e0e8..4a85096 100644
--- a/block/ioctl.c
+++ b/block/ioctl.c
@@ -41,7 +41,7 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user
sizeof(long long) > sizeof(long)) {
long pstart = start, plength = length;
if (pstart != start || plength != length
- || pstart < 0 || plength < 0)
+ || pstart < 0 || plength < 0 || partno > 65535)
return -EINVAL;
}
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 9628652..e059695 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -237,6 +237,16 @@ static int __acpi_bus_get_power(struct acpi_device *device, int *state)
} else if (result == ACPI_STATE_D3_HOT) {
result = ACPI_STATE_D3;
}
+
+ /*
+ * If we were unsure about the device parent's power state up to this
+ * point, the fact that the device is in D0 implies that the parent has
+ * to be in D0 too.
+ */
+ if (device->parent && device->parent->power.state == ACPI_STATE_UNKNOWN
+ && result == ACPI_STATE_D0)
+ device->parent->power.state = ACPI_STATE_D0;
+
*state = result;
out:
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index fc18034..40e38a0 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -107,6 +107,7 @@ struct acpi_power_resource {
/* List of devices relying on this power resource */
struct acpi_power_resource_device *devices;
+ struct mutex devices_lock;
};
static struct list_head acpi_power_resource_list;
@@ -225,7 +226,6 @@ static void acpi_power_on_device(struct acpi_power_managed_device *device)
static int __acpi_power_on(struct acpi_power_resource *resource)
{
- struct acpi_power_resource_device *device_list = resource->devices;
acpi_status status = AE_OK;
status = acpi_evaluate_object(resource->device->handle, "_ON", NULL, NULL);
@@ -238,19 +238,15 @@ static int __acpi_power_on(struct acpi_power_resource *resource)
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Power resource [%s] turned on\n",
resource->name));
- while (device_list) {
- acpi_power_on_device(device_list->device);
-
- device_list = device_list->next;
- }
-
return 0;
}
static int acpi_power_on(acpi_handle handle)
{
int result = 0;
+ bool resume_device = false;
struct acpi_power_resource *resource = NULL;
+ struct acpi_power_resource_device *device_list;
result = acpi_power_get_context(handle, &resource);
if (result)
@@ -266,10 +262,25 @@ static int acpi_power_on(acpi_handle handle)
result = __acpi_power_on(resource);
if (result)
resource->ref_count--;
+ else
+ resume_device = true;
}
mutex_unlock(&resource->resource_lock);
+ if (!resume_device)
+ return result;
+
+ mutex_lock(&resource->devices_lock);
+
+ device_list = resource->devices;
+ while (device_list) {
+ acpi_power_on_device(device_list->device);
+ device_list = device_list->next;
+ }
+
+ mutex_unlock(&resource->devices_lock);
+
return result;
}
@@ -355,7 +366,7 @@ static void __acpi_power_resource_unregister_device(struct device *dev,
if (acpi_power_get_context(res_handle, &resource))
return;
- mutex_lock(&resource->resource_lock);
+ mutex_lock(&resource->devices_lock);
prev = NULL;
curr = resource->devices;
while (curr) {
@@ -372,7 +383,7 @@ static void __acpi_power_resource_unregister_device(struct device *dev,
prev = curr;
curr = curr->next;
}
- mutex_unlock(&resource->resource_lock);
+ mutex_unlock(&resource->devices_lock);
}
/* Unlink dev from all power resources in _PR0 */
@@ -414,10 +425,10 @@ static int __acpi_power_resource_register_device(
power_resource_device->device = powered_device;
- mutex_lock(&resource->resource_lock);
+ mutex_lock(&resource->devices_lock);
power_resource_device->next = resource->devices;
resource->devices = power_resource_device;
- mutex_unlock(&resource->resource_lock);
+ mutex_unlock(&resource->devices_lock);
return 0;
}
@@ -462,7 +473,7 @@ int acpi_power_resource_register_device(struct device *dev, acpi_handle handle)
return ret;
no_power_resource:
- printk(KERN_WARNING PREFIX "Invalid Power Resource to register!");
+ printk(KERN_DEBUG PREFIX "Invalid Power Resource to register!");
return -ENODEV;
}
EXPORT_SYMBOL_GPL(acpi_power_resource_register_device);
@@ -721,6 +732,7 @@ static int acpi_power_add(struct acpi_device *device)
resource->device = device;
mutex_init(&resource->resource_lock);
+ mutex_init(&resource->devices_lock);
strcpy(resource->name, device->pnp.bus_id);
strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_POWER_CLASS);
diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c
index de0435e..887f68f 100644
--- a/drivers/block/aoe/aoecmd.c
+++ b/drivers/block/aoe/aoecmd.c
@@ -35,6 +35,7 @@ new_skb(ulong len)
skb_reset_mac_header(skb);
skb_reset_network_header(skb);
skb->protocol = __constant_htons(ETH_P_AOE);
+ skb_checksum_none_assert(skb);
}
return skb;
}
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
index 38aa6dd..da33111 100644
--- a/drivers/block/cciss_scsi.c
+++ b/drivers/block/cciss_scsi.c
@@ -795,6 +795,7 @@ static void complete_scsi_command(CommandList_struct *c, int timeout,
}
break;
case CMD_PROTOCOL_ERR:
+ cmd->result = DID_ERROR << 16;
dev_warn(&h->pdev->dev,
"%p has protocol error\n", c);
break;
diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c
index a8fddeb..f946d31 100644
--- a/drivers/block/mtip32xx/mtip32xx.c
+++ b/drivers/block/mtip32xx/mtip32xx.c
@@ -1148,11 +1148,15 @@ static bool mtip_pause_ncq(struct mtip_port *port,
reply = port->rxfis + RX_FIS_D2H_REG;
task_file_data = readl(port->mmio+PORT_TFDATA);
- if ((task_file_data & 1) || (fis->command == ATA_CMD_SEC_ERASE_UNIT))
+ if (fis->command == ATA_CMD_SEC_ERASE_UNIT)
+ clear_bit(MTIP_DDF_SEC_LOCK_BIT, &port->dd->dd_flag);
+
+ if ((task_file_data & 1))
return false;
if (fis->command == ATA_CMD_SEC_ERASE_PREP) {
set_bit(MTIP_PF_SE_ACTIVE_BIT, &port->flags);
+ set_bit(MTIP_DDF_SEC_LOCK_BIT, &port->dd->dd_flag);
port->ic_pause_timer = jiffies;
return true;
} else if ((fis->command == ATA_CMD_DOWNLOAD_MICRO) &&
@@ -1900,7 +1904,7 @@ static int exec_drive_command(struct mtip_port *port, u8 *command,
int rv = 0, xfer_sz = command[3];
if (xfer_sz) {
- if (user_buffer)
+ if (!user_buffer)
return -EFAULT;
buf = dmam_alloc_coherent(&port->dd->pdev->dev,
@@ -2043,7 +2047,7 @@ static void mtip_set_timeout(struct host_to_dev_fis *fis, unsigned int *timeout)
*timeout = 240000; /* 4 minutes */
break;
case ATA_CMD_STANDBYNOW1:
- *timeout = 10000; /* 10 seconds */
+ *timeout = 120000; /* 2 minutes */
break;
case 0xF7:
case 0xFA:
@@ -2588,9 +2592,6 @@ static ssize_t mtip_hw_read_registers(struct file *f, char __user *ubuf,
if (!len || size)
return 0;
- if (size < 0)
- return -EINVAL;
-
size += sprintf(&buf[size], "H/ S ACTive : [ 0x");
for (n = dd->slot_groups-1; n >= 0; n--)
@@ -2660,9 +2661,6 @@ static ssize_t mtip_hw_read_flags(struct file *f, char __user *ubuf,
if (!len || size)
return 0;
- if (size < 0)
- return -EINVAL;
-
size += sprintf(&buf[size], "Flag-port : [ %08lX ]\n",
dd->port->flags);
size += sprintf(&buf[size], "Flag-dd : [ %08lX ]\n",
@@ -3214,8 +3212,8 @@ static int mtip_hw_init(struct driver_data *dd)
"Unable to check write protect progress\n");
else
dev_info(&dd->pdev->dev,
- "Write protect progress: %d%% (%d blocks)\n",
- attr242.cur, attr242.data);
+ "Write protect progress: %u%% (%u blocks)\n",
+ attr242.cur, le32_to_cpu(attr242.data));
return rv;
out3:
@@ -3619,6 +3617,10 @@ static void mtip_make_request(struct request_queue *queue, struct bio *bio)
bio_endio(bio, -ENODATA);
return;
}
+ if (unlikely(test_bit(MTIP_DDF_SEC_LOCK_BIT, &dd->dd_flag))) {
+ bio_endio(bio, -ENODATA);
+ return;
+ }
}
if (unlikely(!bio_has_data(bio))) {
@@ -4168,7 +4170,13 @@ static void mtip_pci_shutdown(struct pci_dev *pdev)
/* Table of device ids supported by this driver. */
static DEFINE_PCI_DEVICE_TABLE(mtip_pci_tbl) = {
- { PCI_DEVICE(PCI_VENDOR_ID_MICRON, P320_DEVICE_ID) },
+ { PCI_DEVICE(PCI_VENDOR_ID_MICRON, P320H_DEVICE_ID) },
+ { PCI_DEVICE(PCI_VENDOR_ID_MICRON, P320M_DEVICE_ID) },
+ { PCI_DEVICE(PCI_VENDOR_ID_MICRON, P320S_DEVICE_ID) },
+ { PCI_DEVICE(PCI_VENDOR_ID_MICRON, P325M_DEVICE_ID) },
+ { PCI_DEVICE(PCI_VENDOR_ID_MICRON, P420H_DEVICE_ID) },
+ { PCI_DEVICE(PCI_VENDOR_ID_MICRON, P420M_DEVICE_ID) },
+ { PCI_DEVICE(PCI_VENDOR_ID_MICRON, P425M_DEVICE_ID) },
{ 0 }
};
@@ -4199,12 +4207,12 @@ static int __init mtip_init(void)
{
int error;
- printk(KERN_INFO MTIP_DRV_NAME " Version " MTIP_DRV_VERSION "\n");
+ pr_info(MTIP_DRV_NAME " Version " MTIP_DRV_VERSION "\n");
/* Allocate a major block device number to use with this driver. */
error = register_blkdev(0, MTIP_DRV_NAME);
if (error <= 0) {
- printk(KERN_ERR "Unable to register block device (%d)\n",
+ pr_err("Unable to register block device (%d)\n",
error);
return -EBUSY;
}
@@ -4213,7 +4221,7 @@ static int __init mtip_init(void)
if (!dfs_parent) {
dfs_parent = debugfs_create_dir("rssd", NULL);
if (IS_ERR_OR_NULL(dfs_parent)) {
- printk(KERN_WARNING "Error creating debugfs parent\n");
+ pr_warn("Error creating debugfs parent\n");
dfs_parent = NULL;
}
}
diff --git a/drivers/block/mtip32xx/mtip32xx.h b/drivers/block/mtip32xx/mtip32xx.h
index f51fc23..18627a1 100644
--- a/drivers/block/mtip32xx/mtip32xx.h
+++ b/drivers/block/mtip32xx/mtip32xx.h
@@ -76,7 +76,13 @@
/* Micron Vendor ID & P320x SSD Device ID */
#define PCI_VENDOR_ID_MICRON 0x1344
-#define P320_DEVICE_ID 0x5150
+#define P320H_DEVICE_ID 0x5150
+#define P320M_DEVICE_ID 0x5151
+#define P320S_DEVICE_ID 0x5152
+#define P325M_DEVICE_ID 0x5153
+#define P420H_DEVICE_ID 0x5160
+#define P420M_DEVICE_ID 0x5161
+#define P425M_DEVICE_ID 0x5163
/* Driver name and version strings */
#define MTIP_DRV_NAME "mtip32xx"
@@ -131,10 +137,12 @@ enum {
MTIP_PF_SVC_THD_STOP_BIT = 8,
/* below are bit numbers in 'dd_flag' defined in driver_data */
+ MTIP_DDF_SEC_LOCK_BIT = 0,
MTIP_DDF_REMOVE_PENDING_BIT = 1,
MTIP_DDF_OVER_TEMP_BIT = 2,
MTIP_DDF_WRITE_PROTECT_BIT = 3,
MTIP_DDF_STOP_IO = ((1 << MTIP_DDF_REMOVE_PENDING_BIT) | \
+ (1 << MTIP_DDF_SEC_LOCK_BIT) | \
(1 << MTIP_DDF_OVER_TEMP_BIT) | \
(1 << MTIP_DDF_WRITE_PROTECT_BIT)),
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index d07c9f7..0c03411 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -449,6 +449,14 @@ static void nbd_clear_que(struct nbd_device *nbd)
req->errors++;
nbd_end_request(req);
}
+
+ while (!list_empty(&nbd->waiting_queue)) {
+ req = list_entry(nbd->waiting_queue.next, struct request,
+ queuelist);
+ list_del_init(&req->queuelist);
+ req->errors++;
+ nbd_end_request(req);
+ }
}
@@ -598,6 +606,7 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
nbd->file = NULL;
nbd_clear_que(nbd);
BUG_ON(!list_empty(&nbd->queue_head));
+ BUG_ON(!list_empty(&nbd->waiting_queue));
if (file)
fput(file);
return 0;
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index 9917943..54a55f0 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -246,13 +246,12 @@ static int rbd_open(struct block_device *bdev, fmode_t mode)
{
struct rbd_device *rbd_dev = bdev->bd_disk->private_data;
- rbd_get_dev(rbd_dev);
-
- set_device_ro(bdev, rbd_dev->read_only);
-
if ((mode & FMODE_WRITE) && rbd_dev->read_only)
return -EROFS;
+ rbd_get_dev(rbd_dev);
+ set_device_ro(bdev, rbd_dev->read_only);
+
return 0;
}
diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c
index 73f196c..c6decb9 100644
--- a/drivers/block/xen-blkback/blkback.c
+++ b/drivers/block/xen-blkback/blkback.c
@@ -337,7 +337,7 @@ static void xen_blkbk_unmap(struct pending_req *req)
invcount++;
}
- ret = gnttab_unmap_refs(unmap, pages, invcount, false);
+ ret = gnttab_unmap_refs(unmap, NULL, pages, invcount);
BUG_ON(ret);
}
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 5869ea3..72ce247 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -1,4 +1,5 @@
# common clock types
+obj-$(CONFIG_HAVE_CLK) += clk-devres.o
obj-$(CONFIG_CLKDEV_LOOKUP) += clkdev.o
obj-$(CONFIG_COMMON_CLK) += clk.o clk-fixed-rate.o clk-gate.o \
clk-mux.o clk-divider.o clk-fixed-factor.o
diff --git a/drivers/clk/clk-devres.c b/drivers/clk/clk-devres.c
new file mode 100644
index 0000000..8f57154
--- /dev/null
+++ b/drivers/clk/clk-devres.c
@@ -0,0 +1,55 @@
+/*
+ * 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/clk.h>
+#include <linux/device.h>
+#include <linux/export.h>
+#include <linux/gfp.h>
+
+static void devm_clk_release(struct device *dev, void *res)
+{
+ clk_put(*(struct clk **)res);
+}
+
+struct clk *devm_clk_get(struct device *dev, const char *id)
+{
+ struct clk **ptr, *clk;
+
+ ptr = devres_alloc(devm_clk_release, sizeof(*ptr), GFP_KERNEL);
+ if (!ptr)
+ return ERR_PTR(-ENOMEM);
+
+ clk = clk_get(dev, id);
+ if (!IS_ERR(clk)) {
+ *ptr = clk;
+ devres_add(dev, ptr);
+ } else {
+ devres_free(ptr);
+ }
+
+ return clk;
+}
+EXPORT_SYMBOL(devm_clk_get);
+
+static int devm_clk_match(struct device *dev, void *res, void *data)
+{
+ struct clk **c = res;
+ if (!c || !*c) {
+ WARN_ON(!c || !*c);
+ return 0;
+ }
+ return *c == data;
+}
+
+void devm_clk_put(struct device *dev, struct clk *clk)
+{
+ int ret;
+
+ ret = devres_release(dev, devm_clk_release, devm_clk_match, clk);
+
+ WARN_ON(ret);
+}
+EXPORT_SYMBOL(devm_clk_put);
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index d423c9b..442a313 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -171,51 +171,6 @@ void clk_put(struct clk *clk)
}
EXPORT_SYMBOL(clk_put);
-static void devm_clk_release(struct device *dev, void *res)
-{
- clk_put(*(struct clk **)res);
-}
-
-struct clk *devm_clk_get(struct device *dev, const char *id)
-{
- struct clk **ptr, *clk;
-
- ptr = devres_alloc(devm_clk_release, sizeof(*ptr), GFP_KERNEL);
- if (!ptr)
- return ERR_PTR(-ENOMEM);
-
- clk = clk_get(dev, id);
- if (!IS_ERR(clk)) {
- *ptr = clk;
- devres_add(dev, ptr);
- } else {
- devres_free(ptr);
- }
-
- return clk;
-}
-EXPORT_SYMBOL(devm_clk_get);
-
-static int devm_clk_match(struct device *dev, void *res, void *data)
-{
- struct clk **c = res;
- if (!c || !*c) {
- WARN_ON(!c || !*c);
- return 0;
- }
- return *c == data;
-}
-
-void devm_clk_put(struct device *dev, struct clk *clk)
-{
- int ret;
-
- ret = devres_destroy(dev, devm_clk_release, devm_clk_match, clk);
-
- WARN_ON(ret);
-}
-EXPORT_SYMBOL(devm_clk_put);
-
void clkdev_add(struct clk_lookup *cl)
{
mutex_lock(&clocks_mutex);
diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c
index c0e8164..1a40935 100644
--- a/drivers/cpufreq/powernow-k8.c
+++ b/drivers/cpufreq/powernow-k8.c
@@ -35,7 +35,6 @@
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/cpumask.h>
-#include <linux/sched.h> /* for current / set_cpus_allowed() */
#include <linux/io.h>
#include <linux/delay.h>
@@ -1139,16 +1138,23 @@ static int transition_frequency_pstate(struct powernow_k8_data *data,
return res;
}
-/* Driver entry point to switch to the target frequency */
-static int powernowk8_target(struct cpufreq_policy *pol,
- unsigned targfreq, unsigned relation)
+struct powernowk8_target_arg {
+ struct cpufreq_policy *pol;
+ unsigned targfreq;
+ unsigned relation;
+};
+
+static long powernowk8_target_fn(void *arg)
{
- cpumask_var_t oldmask;
+ struct powernowk8_target_arg *pta = arg;
+ struct cpufreq_policy *pol = pta->pol;
+ unsigned targfreq = pta->targfreq;
+ unsigned relation = pta->relation;
struct powernow_k8_data *data = per_cpu(powernow_data, pol->cpu);
u32 checkfid;
u32 checkvid;
unsigned int newstate;
- int ret = -EIO;
+ int ret;
if (!data)
return -EINVAL;
@@ -1156,29 +1162,16 @@ static int powernowk8_target(struct cpufreq_policy *pol,
checkfid = data->currfid;
checkvid = data->currvid;
- /* only run on specific CPU from here on. */
- /* This is poor form: use a workqueue or smp_call_function_single */
- if (!alloc_cpumask_var(&oldmask, GFP_KERNEL))
- return -ENOMEM;
-
- cpumask_copy(oldmask, tsk_cpus_allowed(current));
- set_cpus_allowed_ptr(current, cpumask_of(pol->cpu));
-
- if (smp_processor_id() != pol->cpu) {
- printk(KERN_ERR PFX "limiting to cpu %u failed\n", pol->cpu);
- goto err_out;
- }
-
if (pending_bit_stuck()) {
printk(KERN_ERR PFX "failing targ, change pending bit set\n");
- goto err_out;
+ return -EIO;
}
pr_debug("targ: cpu %d, %d kHz, min %d, max %d, relation %d\n",
pol->cpu, targfreq, pol->min, pol->max, relation);
if (query_current_values_with_pending_wait(data))
- goto err_out;
+ return -EIO;
if (cpu_family != CPU_HW_PSTATE) {
pr_debug("targ: curr fid 0x%x, vid 0x%x\n",
@@ -1196,7 +1189,7 @@ static int powernowk8_target(struct cpufreq_policy *pol,
if (cpufreq_frequency_table_target(pol, data->powernow_table,
targfreq, relation, &newstate))
- goto err_out;
+ return -EIO;
mutex_lock(&fidvid_mutex);
@@ -1209,9 +1202,8 @@ static int powernowk8_target(struct cpufreq_policy *pol,
ret = transition_frequency_fidvid(data, newstate);
if (ret) {
printk(KERN_ERR PFX "transition frequency failed\n");
- ret = 1;
mutex_unlock(&fidvid_mutex);
- goto err_out;
+ return 1;
}
mutex_unlock(&fidvid_mutex);
@@ -1220,12 +1212,25 @@ static int powernowk8_target(struct cpufreq_policy *pol,
data->powernow_table[newstate].index);
else
pol->cur = find_khz_freq_from_fid(data->currfid);
- ret = 0;
-err_out:
- set_cpus_allowed_ptr(current, oldmask);
- free_cpumask_var(oldmask);
- return ret;
+ return 0;
+}
+
+/* Driver entry point to switch to the target frequency */
+static int powernowk8_target(struct cpufreq_policy *pol,
+ unsigned targfreq, unsigned relation)
+{
+ struct powernowk8_target_arg pta = { .pol = pol, .targfreq = targfreq,
+ .relation = relation };
+
+ /*
+ * Must run on @pol->cpu. cpufreq core is responsible for ensuring
+ * that we're bound to the current CPU and pol->cpu stays online.
+ */
+ if (smp_processor_id() == pol->cpu)
+ return powernowk8_target_fn(&pta);
+ else
+ return work_on_cpu(pol->cpu, powernowk8_target_fn, &pta);
}
/* Driver entry point to verify the policy and range of frequencies */
diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c
index 3934fcc..7ab6e26 100644
--- a/drivers/dma/at_hdmac.c
+++ b/drivers/dma/at_hdmac.c
@@ -661,7 +661,7 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
flags);
if (unlikely(!atslave || !sg_len)) {
- dev_dbg(chan2dev(chan), "prep_dma_memcpy: length is zero!\n");
+ dev_dbg(chan2dev(chan), "prep_slave_sg: sg length is zero!\n");
return NULL;
}
@@ -689,6 +689,11 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
mem = sg_dma_address(sg);
len = sg_dma_len(sg);
+ if (unlikely(!len)) {
+ dev_dbg(chan2dev(chan),
+ "prep_slave_sg: sg(%d) data length is zero\n", i);
+ goto err;
+ }
mem_width = 2;
if (unlikely(mem & 3 || len & 3))
mem_width = 0;
@@ -724,6 +729,11 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
mem = sg_dma_address(sg);
len = sg_dma_len(sg);
+ if (unlikely(!len)) {
+ dev_dbg(chan2dev(chan),
+ "prep_slave_sg: sg(%d) data length is zero\n", i);
+ goto err;
+ }
mem_width = 2;
if (unlikely(mem & 3 || len & 3))
mem_width = 0;
@@ -757,6 +767,7 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
err_desc_get:
dev_err(chan2dev(chan), "not enough descriptors available\n");
+err:
atc_desc_put(atchan, first);
return NULL;
}
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index e4feba6..f5843bc 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -1567,17 +1567,19 @@ static int pl330_submit_req(void *ch_id, struct pl330_req *r)
goto xfer_exit;
}
- /* Prefer Secure Channel */
- if (!_manager_ns(thrd))
- r->cfg->nonsecure = 0;
- else
- r->cfg->nonsecure = 1;
/* Use last settings, if not provided */
- if (r->cfg)
+ if (r->cfg) {
+ /* Prefer Secure Channel */
+ if (!_manager_ns(thrd))
+ r->cfg->nonsecure = 0;
+ else
+ r->cfg->nonsecure = 1;
+
ccr = _prepare_ccr(r->cfg);
- else
+ } else {
ccr = readl(regs + CC(thrd->id));
+ }
/* If this req doesn't have valid xfer settings */
if (!_is_valid(ccr)) {
@@ -2928,6 +2930,11 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
num_chan = max_t(int, pi->pcfg.num_peri, pi->pcfg.num_chan);
pdmac->peripherals = kzalloc(num_chan * sizeof(*pch), GFP_KERNEL);
+ if (!pdmac->peripherals) {
+ ret = -ENOMEM;
+ dev_err(&adev->dev, "unable to allocate pdmac->peripherals\n");
+ goto probe_err5;
+ }
for (i = 0; i < num_chan; i++) {
pch = &pdmac->peripherals[i];
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c
index 616d90b..d5dc9da 100644
--- a/drivers/edac/edac_mc.c
+++ b/drivers/edac/edac_mc.c
@@ -199,6 +199,36 @@ void *edac_align_ptr(void **p, unsigned size, int n_elems)
return (void *)(((unsigned long)ptr) + align - r);
}
+static void _edac_mc_free(struct mem_ctl_info *mci)
+{
+ int i, chn, row;
+ struct csrow_info *csr;
+ const unsigned int tot_dimms = mci->tot_dimms;
+ const unsigned int tot_channels = mci->num_cschannel;
+ const unsigned int tot_csrows = mci->nr_csrows;
+
+ if (mci->dimms) {
+ for (i = 0; i < tot_dimms; i++)
+ kfree(mci->dimms[i]);
+ kfree(mci->dimms);
+ }
+ if (mci->csrows) {
+ for (row = 0; row < tot_csrows; row++) {
+ csr = mci->csrows[row];
+ if (csr) {
+ if (csr->channels) {
+ for (chn = 0; chn < tot_channels; chn++)
+ kfree(csr->channels[chn]);
+ kfree(csr->channels);
+ }
+ kfree(csr);
+ }
+ }
+ kfree(mci->csrows);
+ }
+ kfree(mci);
+}
+
/**
* edac_mc_alloc: Allocate and partially fill a struct mem_ctl_info structure
* @mc_num: Memory controller number
@@ -413,24 +443,7 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num,
return mci;
error:
- if (mci->dimms) {
- for (i = 0; i < tot_dimms; i++)
- kfree(mci->dimms[i]);
- kfree(mci->dimms);
- }
- if (mci->csrows) {
- for (chn = 0; chn < tot_channels; chn++) {
- csr = mci->csrows[chn];
- if (csr) {
- for (chn = 0; chn < tot_channels; chn++)
- kfree(csr->channels[chn]);
- kfree(csr);
- }
- kfree(mci->csrows[i]);
- }
- kfree(mci->csrows);
- }
- kfree(mci);
+ _edac_mc_free(mci);
return NULL;
}
@@ -445,6 +458,14 @@ void edac_mc_free(struct mem_ctl_info *mci)
{
edac_dbg(1, "\n");
+ /* If we're not yet registered with sysfs free only what was allocated
+ * in edac_mc_alloc().
+ */
+ if (!device_is_registered(&mci->dev)) {
+ _edac_mc_free(mci);
+ return;
+ }
+
/* the mci instance is freed here, when the sysfs object is dropped */
edac_unregister_sysfs(mci);
}
diff --git a/drivers/edac/i3200_edac.c b/drivers/edac/i3200_edac.c
index 47180a0..b6653a6 100644
--- a/drivers/edac/i3200_edac.c
+++ b/drivers/edac/i3200_edac.c
@@ -391,7 +391,7 @@ static int i3200_probe1(struct pci_dev *pdev, int dev_idx)
for (j = 0; j < nr_channels; j++) {
struct dimm_info *dimm = csrow->channels[j]->dimm;
- dimm->nr_pages = nr_pages / nr_channels;
+ dimm->nr_pages = nr_pages;
dimm->grain = nr_pages << PAGE_SHIFT;
dimm->mtype = MEM_DDR2;
dimm->dtype = DEV_UNKNOWN;
diff --git a/drivers/edac/i5000_edac.c b/drivers/edac/i5000_edac.c
index 39c6375..6a49dd0 100644
--- a/drivers/edac/i5000_edac.c
+++ b/drivers/edac/i5000_edac.c
@@ -1012,6 +1012,10 @@ static void handle_channel(struct i5000_pvt *pvt, int slot, int channel,
/* add the number of COLUMN bits */
addrBits += MTR_DIMM_COLS_ADDR_BITS(mtr);
+ /* Dual-rank memories have twice the size */
+ if (dinfo->dual_rank)
+ addrBits++;
+
addrBits += 6; /* add 64 bits per DIMM */
addrBits -= 20; /* divide by 2^^20 */
addrBits -= 3; /* 8 bits per bytes */
diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c
index f3b1f9f..5715b7c 100644
--- a/drivers/edac/sb_edac.c
+++ b/drivers/edac/sb_edac.c
@@ -513,7 +513,8 @@ static int get_dimm_config(struct mem_ctl_info *mci)
{
struct sbridge_pvt *pvt = mci->pvt_info;
struct dimm_info *dimm;
- int i, j, banks, ranks, rows, cols, size, npages;
+ unsigned i, j, banks, ranks, rows, cols, npages;
+ u64 size;
u32 reg;
enum edac_type mode;
enum mem_type mtype;
@@ -585,10 +586,10 @@ static int get_dimm_config(struct mem_ctl_info *mci)
cols = numcol(mtr);
/* DDR3 has 8 I/O banks */
- size = (rows * cols * banks * ranks) >> (20 - 3);
+ size = ((u64)rows * cols * banks * ranks) >> (20 - 3);
npages = MiB_TO_PAGES(size);
- edac_dbg(0, "mc#%d: channel %d, dimm %d, %d Mb (%d pages) bank: %d, rank: %d, row: %#x, col: %#x\n",
+ edac_dbg(0, "mc#%d: channel %d, dimm %d, %Ld Mb (%d pages) bank: %d, rank: %d, row: %#x, col: %#x\n",
pvt->sbridge_dev->mc, i, j,
size, npages,
banks, ranks, rows, cols);
diff --git a/drivers/extcon/extcon-max77693.c b/drivers/extcon/extcon-max77693.c
index 920a609..38f9e52 100644
--- a/drivers/extcon/extcon-max77693.c
+++ b/drivers/extcon/extcon-max77693.c
@@ -669,13 +669,18 @@ static int __devinit max77693_muic_probe(struct platform_device *pdev)
}
info->dev = &pdev->dev;
info->max77693 = max77693;
- info->max77693->regmap_muic = regmap_init_i2c(info->max77693->muic,
- &max77693_muic_regmap_config);
- if (IS_ERR(info->max77693->regmap_muic)) {
- ret = PTR_ERR(info->max77693->regmap_muic);
- dev_err(max77693->dev,
- "failed to allocate register map: %d\n", ret);
- goto err_regmap;
+ if (info->max77693->regmap_muic)
+ dev_dbg(&pdev->dev, "allocate register map\n");
+ else {
+ info->max77693->regmap_muic = devm_regmap_init_i2c(
+ info->max77693->muic,
+ &max77693_muic_regmap_config);
+ if (IS_ERR(info->max77693->regmap_muic)) {
+ ret = PTR_ERR(info->max77693->regmap_muic);
+ dev_err(max77693->dev,
+ "failed to allocate register map: %d\n", ret);
+ goto err_regmap;
+ }
}
platform_set_drvdata(pdev, info);
mutex_init(&info->mutex);
diff --git a/drivers/gpio/gpio-lpc32xx.c b/drivers/gpio/gpio-lpc32xx.c
index 8a420f1..ed94b4e 100644
--- a/drivers/gpio/gpio-lpc32xx.c
+++ b/drivers/gpio/gpio-lpc32xx.c
@@ -308,6 +308,7 @@ static int lpc32xx_gpio_dir_output_p012(struct gpio_chip *chip, unsigned pin,
{
struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
+ __set_gpio_level_p012(group, pin, value);
__set_gpio_dir_p012(group, pin, 0);
return 0;
@@ -318,6 +319,7 @@ static int lpc32xx_gpio_dir_output_p3(struct gpio_chip *chip, unsigned pin,
{
struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
+ __set_gpio_level_p3(group, pin, value);
__set_gpio_dir_p3(group, pin, 0);
return 0;
@@ -326,6 +328,9 @@ static int lpc32xx_gpio_dir_output_p3(struct gpio_chip *chip, unsigned pin,
static int lpc32xx_gpio_dir_out_always(struct gpio_chip *chip, unsigned pin,
int value)
{
+ struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
+
+ __set_gpo_level_p3(group, pin, value);
return 0;
}
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 489e2b1..274d25d 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -3242,7 +3242,8 @@ i915_gem_object_pin(struct drm_i915_gem_object *obj,
{
int ret;
- BUG_ON(obj->pin_count == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT);
+ if (WARN_ON(obj->pin_count == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT))
+ return -EBUSY;
if (obj->gtt_space != NULL) {
if ((alignment && obj->gtt_offset & (alignment - 1)) ||
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index bc2ad34..c040aee 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -4191,12 +4191,6 @@ static void i8xx_update_pll(struct drm_crtc *crtc,
POSTING_READ(DPLL(pipe));
udelay(150);
- I915_WRITE(DPLL(pipe), dpll);
-
- /* Wait for the clocks to stabilize. */
- POSTING_READ(DPLL(pipe));
- udelay(150);
-
/* The LVDS pin pair needs to be on before the DPLLs are enabled.
* This is an exception to the general rule that mode_set doesn't turn
* things on.
@@ -4204,6 +4198,12 @@ static void i8xx_update_pll(struct drm_crtc *crtc,
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))
intel_update_lvds(crtc, clock, adjusted_mode);
+ I915_WRITE(DPLL(pipe), dpll);
+
+ /* Wait for the clocks to stabilize. */
+ POSTING_READ(DPLL(pipe));
+ udelay(150);
+
/* The pixel multiplier can only be updated once the
* DPLL is enabled and the clocks are stable.
*
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 98f6024..12dc330 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -609,7 +609,7 @@ static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode)
u32 temp;
u32 enable_bits = SDVO_ENABLE;
- if (intel_hdmi->has_audio)
+ if (intel_hdmi->has_audio || mode != DRM_MODE_DPMS_ON)
enable_bits |= SDVO_AUDIO_ENABLE;
temp = I915_READ(intel_hdmi->sdvox_reg);
diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.c b/drivers/gpu/drm/nouveau/nouveau_abi16.c
index ff23d88..3ca240b 100644
--- a/drivers/gpu/drm/nouveau/nouveau_abi16.c
+++ b/drivers/gpu/drm/nouveau/nouveau_abi16.c
@@ -179,7 +179,7 @@ nouveau_abi16_ioctl_grobj_alloc(ABI16_IOCTL_ARGS)
return 0;
} else
if (init->class == 0x906e) {
- NV_ERROR(dev, "906e not supported yet\n");
+ NV_DEBUG(dev, "906e not supported yet\n");
return -EINVAL;
}
diff --git a/drivers/gpu/drm/nouveau/nv50_gpio.c b/drivers/gpu/drm/nouveau/nv50_gpio.c
index f034905..c399d51 100644
--- a/drivers/gpu/drm/nouveau/nv50_gpio.c
+++ b/drivers/gpu/drm/nouveau/nv50_gpio.c
@@ -22,6 +22,7 @@
* Authors: Ben Skeggs
*/
+#include <linux/dmi.h>
#include "drmP.h"
#include "nouveau_drv.h"
#include "nouveau_hw.h"
@@ -110,13 +111,25 @@ nv50_gpio_isr(struct drm_device *dev)
nv_wr32(dev, 0xe074, intr1);
}
+static struct dmi_system_id gpio_reset_ids[] = {
+ {
+ .ident = "Apple Macbook 10,1",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro10,1"),
+ }
+ },
+ { }
+};
+
int
nv50_gpio_init(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
/* initialise gpios and routing to vbios defaults */
- nouveau_gpio_reset(dev);
+ if (dmi_check_system(gpio_reset_ids))
+ nouveau_gpio_reset(dev);
/* disable, and ack any pending gpio interrupts */
nv_wr32(dev, 0xe050, 0x00000000);
diff --git a/drivers/gpu/drm/nouveau/nvc0_fb.c b/drivers/gpu/drm/nouveau/nvc0_fb.c
index f704e94..f376c39 100644
--- a/drivers/gpu/drm/nouveau/nvc0_fb.c
+++ b/drivers/gpu/drm/nouveau/nvc0_fb.c
@@ -124,6 +124,7 @@ nvc0_fb_init(struct drm_device *dev)
priv = dev_priv->engine.fb.priv;
nv_wr32(dev, 0x100c10, priv->r100c10 >> 8);
+ nv_mask(dev, 0x17e820, 0x00100000, 0x00000000); /* NV_PLTCG_INTR_EN */
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nvc0_fifo.c b/drivers/gpu/drm/nouveau/nvc0_fifo.c
index 7d85553..cd39eb9 100644
--- a/drivers/gpu/drm/nouveau/nvc0_fifo.c
+++ b/drivers/gpu/drm/nouveau/nvc0_fifo.c
@@ -373,7 +373,8 @@ nvc0_fifo_isr_subfifo_intr(struct drm_device *dev, int unit)
static void
nvc0_fifo_isr(struct drm_device *dev)
{
- u32 stat = nv_rd32(dev, 0x002100);
+ u32 mask = nv_rd32(dev, 0x002140);
+ u32 stat = nv_rd32(dev, 0x002100) & mask;
if (stat & 0x00000100) {
NV_INFO(dev, "PFIFO: unknown status 0x00000100\n");
diff --git a/drivers/gpu/drm/nouveau/nve0_fifo.c b/drivers/gpu/drm/nouveau/nve0_fifo.c
index e98d144..281bece 100644
--- a/drivers/gpu/drm/nouveau/nve0_fifo.c
+++ b/drivers/gpu/drm/nouveau/nve0_fifo.c
@@ -345,7 +345,8 @@ nve0_fifo_isr_subfifo_intr(struct drm_device *dev, int unit)
static void
nve0_fifo_isr(struct drm_device *dev)
{
- u32 stat = nv_rd32(dev, 0x002100);
+ u32 mask = nv_rd32(dev, 0x002140);
+ u32 stat = nv_rd32(dev, 0x002100) & mask;
if (stat & 0x00000100) {
NV_INFO(dev, "PFIFO: unknown status 0x00000100\n");
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
index e721e30..2817101 100644
--- a/drivers/gpu/drm/radeon/atombios_crtc.c
+++ b/drivers/gpu/drm/radeon/atombios_crtc.c
@@ -1479,98 +1479,14 @@ static void radeon_legacy_atom_fixup(struct drm_crtc *crtc)
}
}
-/**
- * radeon_get_pll_use_mask - look up a mask of which pplls are in use
- *
- * @crtc: drm crtc
- *
- * Returns the mask of which PPLLs (Pixel PLLs) are in use.
- */
-static u32 radeon_get_pll_use_mask(struct drm_crtc *crtc)
-{
- struct drm_device *dev = crtc->dev;
- struct drm_crtc *test_crtc;
- struct radeon_crtc *radeon_test_crtc;
- u32 pll_in_use = 0;
-
- list_for_each_entry(test_crtc, &dev->mode_config.crtc_list, head) {
- if (crtc == test_crtc)
- continue;
-
- radeon_test_crtc = to_radeon_crtc(test_crtc);
- if (radeon_test_crtc->pll_id != ATOM_PPLL_INVALID)
- pll_in_use |= (1 << radeon_test_crtc->pll_id);
- }
- return pll_in_use;
-}
-
-/**
- * radeon_get_shared_dp_ppll - return the PPLL used by another crtc for DP
- *
- * @crtc: drm crtc
- *
- * Returns the PPLL (Pixel PLL) used by another crtc/encoder which is
- * also in DP mode. For DP, a single PPLL can be used for all DP
- * crtcs/encoders.
- */
-static int radeon_get_shared_dp_ppll(struct drm_crtc *crtc)
-{
- struct drm_device *dev = crtc->dev;
- struct drm_encoder *test_encoder;
- struct radeon_crtc *radeon_test_crtc;
-
- list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) {
- if (test_encoder->crtc && (test_encoder->crtc != crtc)) {
- if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_encoder))) {
- /* for DP use the same PLL for all */
- radeon_test_crtc = to_radeon_crtc(test_encoder->crtc);
- if (radeon_test_crtc->pll_id != ATOM_PPLL_INVALID)
- return radeon_test_crtc->pll_id;
- }
- }
- }
- return ATOM_PPLL_INVALID;
-}
-
-/**
- * radeon_atom_pick_pll - Allocate a PPLL for use by the crtc.
- *
- * @crtc: drm crtc
- *
- * Returns the PPLL (Pixel PLL) to be used by the crtc. For DP monitors
- * a single PPLL can be used for all DP crtcs/encoders. For non-DP
- * monitors a dedicated PPLL must be used. If a particular board has
- * an external DP PLL, return ATOM_PPLL_INVALID to skip PLL programming
- * as there is no need to program the PLL itself. If we are not able to
- * allocate a PLL, return ATOM_PPLL_INVALID to skip PLL programming to
- * avoid messing up an existing monitor.
- *
- * Asic specific PLL information
- *
- * DCE 6.1
- * - PPLL2 is only available to UNIPHYA (both DP and non-DP)
- * - PPLL0, PPLL1 are available for UNIPHYB/C/D/E/F (both DP and non-DP)
- *
- * DCE 6.0
- * - PPLL0 is available to all UNIPHY (DP only)
- * - PPLL1, PPLL2 are available for all UNIPHY (both DP and non-DP) and DAC
- *
- * DCE 5.0
- * - DCPLL is available to all UNIPHY (DP only)
- * - PPLL1, PPLL2 are available for all UNIPHY (both DP and non-DP) and DAC
- *
- * DCE 3.0/4.0/4.1
- * - PPLL1, PPLL2 are available for all UNIPHY (both DP and non-DP) and DAC
- *
- */
static int radeon_atom_pick_pll(struct drm_crtc *crtc)
{
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
struct drm_device *dev = crtc->dev;
struct radeon_device *rdev = dev->dev_private;
struct drm_encoder *test_encoder;
- u32 pll_in_use;
- int pll;
+ struct drm_crtc *test_crtc;
+ uint32_t pll_in_use = 0;
if (ASIC_IS_DCE61(rdev)) {
list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) {
@@ -1582,40 +1498,32 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc)
if ((test_radeon_encoder->encoder_id ==
ENCODER_OBJECT_ID_INTERNAL_UNIPHY) &&
- (dig->linkb == false))
- /* UNIPHY A uses PPLL2 */
+ (dig->linkb == false)) /* UNIPHY A uses PPLL2 */
return ATOM_PPLL2;
- else if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_encoder))) {
- /* UNIPHY B/C/D/E/F */
- if (rdev->clock.dp_extclk)
- /* skip PPLL programming if using ext clock */
- return ATOM_PPLL_INVALID;
- else {
- /* use the same PPLL for all DP monitors */
- pll = radeon_get_shared_dp_ppll(crtc);
- if (pll != ATOM_PPLL_INVALID)
- return pll;
- }
- }
- break;
}
}
/* UNIPHY B/C/D/E/F */
- pll_in_use = radeon_get_pll_use_mask(crtc);
- if (!(pll_in_use & (1 << ATOM_PPLL0)))
+ list_for_each_entry(test_crtc, &dev->mode_config.crtc_list, head) {
+ struct radeon_crtc *radeon_test_crtc;
+
+ if (crtc == test_crtc)
+ continue;
+
+ radeon_test_crtc = to_radeon_crtc(test_crtc);
+ if ((radeon_test_crtc->pll_id == ATOM_PPLL0) ||
+ (radeon_test_crtc->pll_id == ATOM_PPLL1))
+ pll_in_use |= (1 << radeon_test_crtc->pll_id);
+ }
+ if (!(pll_in_use & 4))
return ATOM_PPLL0;
- if (!(pll_in_use & (1 << ATOM_PPLL1)))
- return ATOM_PPLL1;
- DRM_ERROR("unable to allocate a PPLL\n");
- return ATOM_PPLL_INVALID;
+ return ATOM_PPLL1;
} else if (ASIC_IS_DCE4(rdev)) {
list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) {
if (test_encoder->crtc && (test_encoder->crtc == crtc)) {
/* in DP mode, the DP ref clock can come from PPLL, DCPLL, or ext clock,
* depending on the asic:
* DCE4: PPLL or ext clock
- * DCE5: PPLL, DCPLL, or ext clock
- * DCE6: PPLL, PPLL0, or ext clock
+ * DCE5: DCPLL or ext clock
*
* Setting ATOM_PPLL_INVALID will cause SetPixelClock to skip
* PPLL/DCPLL programming and only program the DP DTO for the
@@ -1623,34 +1531,31 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc)
*/
if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_encoder))) {
if (rdev->clock.dp_extclk)
- /* skip PPLL programming if using ext clock */
return ATOM_PPLL_INVALID;
else if (ASIC_IS_DCE6(rdev))
- /* use PPLL0 for all DP */
return ATOM_PPLL0;
else if (ASIC_IS_DCE5(rdev))
- /* use DCPLL for all DP */
return ATOM_DCPLL;
- else {
- /* use the same PPLL for all DP monitors */
- pll = radeon_get_shared_dp_ppll(crtc);
- if (pll != ATOM_PPLL_INVALID)
- return pll;
- }
}
- break;
}
}
- /* all other cases */
- pll_in_use = radeon_get_pll_use_mask(crtc);
- if (!(pll_in_use & (1 << ATOM_PPLL2)))
- return ATOM_PPLL2;
- if (!(pll_in_use & (1 << ATOM_PPLL1)))
+
+ /* otherwise, pick one of the plls */
+ list_for_each_entry(test_crtc, &dev->mode_config.crtc_list, head) {
+ struct radeon_crtc *radeon_test_crtc;
+
+ if (crtc == test_crtc)
+ continue;
+
+ radeon_test_crtc = to_radeon_crtc(test_crtc);
+ if ((radeon_test_crtc->pll_id >= ATOM_PPLL1) &&
+ (radeon_test_crtc->pll_id <= ATOM_PPLL2))
+ pll_in_use |= (1 << radeon_test_crtc->pll_id);
+ }
+ if (!(pll_in_use & 1))
return ATOM_PPLL1;
- DRM_ERROR("unable to allocate a PPLL\n");
- return ATOM_PPLL_INVALID;
+ return ATOM_PPLL2;
} else
- /* use PPLL1 or PPLL2 */
return radeon_crtc->crtc_id;
}
@@ -1792,7 +1697,7 @@ static void atombios_crtc_disable(struct drm_crtc *crtc)
break;
}
done:
- radeon_crtc->pll_id = ATOM_PPLL_INVALID;
+ radeon_crtc->pll_id = -1;
}
static const struct drm_crtc_helper_funcs atombios_helper_funcs = {
@@ -1841,6 +1746,6 @@ void radeon_atombios_init_crtc(struct drm_device *dev,
else
radeon_crtc->crtc_offset = 0;
}
- radeon_crtc->pll_id = ATOM_PPLL_INVALID;
+ radeon_crtc->pll_id = -1;
drm_crtc_helper_add(&radeon_crtc->base, &atombios_helper_funcs);
}
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index 8acb34f..8d7e33a 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -1182,7 +1182,8 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size)
ring->ready = true;
radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size);
- if (radeon_ring_supports_scratch_reg(rdev, ring)) {
+ if (!ring->rptr_save_reg /* not resuming from suspend */
+ && radeon_ring_supports_scratch_reg(rdev, ring)) {
r = radeon_scratch_get(rdev, &ring->rptr_save_reg);
if (r) {
DRM_ERROR("failed to get scratch reg for rptr save (%d).\n", r);
diff --git a/drivers/gpu/drm/udl/udl_connector.c b/drivers/gpu/drm/udl/udl_connector.c
index ba055e9..8d9dc44 100644
--- a/drivers/gpu/drm/udl/udl_connector.c
+++ b/drivers/gpu/drm/udl/udl_connector.c
@@ -69,6 +69,13 @@ static int udl_get_modes(struct drm_connector *connector)
static int udl_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
{
+ struct udl_device *udl = connector->dev->dev_private;
+ if (!udl->sku_pixel_limit)
+ return 0;
+
+ if (mode->vdisplay * mode->hdisplay > udl->sku_pixel_limit)
+ return MODE_VIRTUAL_Y;
+
return 0;
}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
index f2fb8f1..7e07433 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
@@ -1018,7 +1018,7 @@ int vmw_event_fence_action_create(struct drm_file *file_priv,
}
- event = kzalloc(sizeof(event->event), GFP_KERNEL);
+ event = kzalloc(sizeof(*event), GFP_KERNEL);
if (unlikely(event == NULL)) {
DRM_ERROR("Failed to allocate an event.\n");
ret = -ENOMEM;
diff --git a/drivers/hid/hid-lenovo-tpkbd.c b/drivers/hid/hid-lenovo-tpkbd.c
index 77d2df0..60c4e1e 100644
--- a/drivers/hid/hid-lenovo-tpkbd.c
+++ b/drivers/hid/hid-lenovo-tpkbd.c
@@ -519,6 +519,8 @@ static void tpkbd_remove_tp(struct hid_device *hdev)
led_classdev_unregister(&data_pointer->led_mute);
hid_set_drvdata(hdev, NULL);
+ kfree(data_pointer->led_micmute.name);
+ kfree(data_pointer->led_mute.name);
kfree(data_pointer);
}
diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c
index 4d524b5..9500f2f 100644
--- a/drivers/hid/hid-logitech-dj.c
+++ b/drivers/hid/hid-logitech-dj.c
@@ -193,6 +193,7 @@ static struct hid_ll_driver logi_dj_ll_driver;
static int logi_dj_output_hidraw_report(struct hid_device *hid, u8 * buf,
size_t count,
unsigned char report_type);
+static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev);
static void logi_dj_recv_destroy_djhid_device(struct dj_receiver_dev *djrcv_dev,
struct dj_report *dj_report)
@@ -233,6 +234,7 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev,
if (dj_report->report_params[DEVICE_PAIRED_PARAM_SPFUNCTION] &
SPFUNCTION_DEVICE_LIST_EMPTY) {
dbg_hid("%s: device list is empty\n", __func__);
+ djrcv_dev->querying_devices = false;
return;
}
@@ -243,6 +245,12 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev,
return;
}
+ if (djrcv_dev->paired_dj_devices[dj_report->device_index]) {
+ /* The device is already known. No need to reallocate it. */
+ dbg_hid("%s: device is already known\n", __func__);
+ return;
+ }
+
dj_hiddev = hid_allocate_device();
if (IS_ERR(dj_hiddev)) {
dev_err(&djrcv_hdev->dev, "%s: hid_allocate_device failed\n",
@@ -306,6 +314,7 @@ static void delayedwork_callback(struct work_struct *work)
struct dj_report dj_report;
unsigned long flags;
int count;
+ int retval;
dbg_hid("%s\n", __func__);
@@ -338,6 +347,25 @@ static void delayedwork_callback(struct work_struct *work)
logi_dj_recv_destroy_djhid_device(djrcv_dev, &dj_report);
break;
default:
+ /* A normal report (i. e. not belonging to a pair/unpair notification)
+ * arriving here, means that the report arrived but we did not have a
+ * paired dj_device associated to the report's device_index, this
+ * means that the original "device paired" notification corresponding
+ * to this dj_device never arrived to this driver. The reason is that
+ * hid-core discards all packets coming from a device while probe() is
+ * executing. */
+ if (!djrcv_dev->paired_dj_devices[dj_report.device_index]) {
+ /* ok, we don't know the device, just re-ask the
+ * receiver for the list of connected devices. */
+ retval = logi_dj_recv_query_paired_devices(djrcv_dev);
+ if (!retval) {
+ /* everything went fine, so just leave */
+ break;
+ }
+ dev_err(&djrcv_dev->hdev->dev,
+ "%s:logi_dj_recv_query_paired_devices "
+ "error:%d\n", __func__, retval);
+ }
dbg_hid("%s: unexpected report type\n", __func__);
}
}
@@ -368,6 +396,12 @@ static void logi_dj_recv_forward_null_report(struct dj_receiver_dev *djrcv_dev,
if (!djdev) {
dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]"
" is NULL, index %d\n", dj_report->device_index);
+ kfifo_in(&djrcv_dev->notif_fifo, dj_report, sizeof(struct dj_report));
+
+ if (schedule_work(&djrcv_dev->work) == 0) {
+ dbg_hid("%s: did not schedule the work item, was already "
+ "queued\n", __func__);
+ }
return;
}
@@ -398,6 +432,12 @@ static void logi_dj_recv_forward_report(struct dj_receiver_dev *djrcv_dev,
if (dj_device == NULL) {
dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]"
" is NULL, index %d\n", dj_report->device_index);
+ kfifo_in(&djrcv_dev->notif_fifo, dj_report, sizeof(struct dj_report));
+
+ if (schedule_work(&djrcv_dev->work) == 0) {
+ dbg_hid("%s: did not schedule the work item, was already "
+ "queued\n", __func__);
+ }
return;
}
@@ -439,6 +479,10 @@ static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev)
struct dj_report *dj_report;
int retval;
+ /* no need to protect djrcv_dev->querying_devices */
+ if (djrcv_dev->querying_devices)
+ return 0;
+
dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL);
if (!dj_report)
return -ENOMEM;
@@ -450,6 +494,7 @@ static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev)
return retval;
}
+
static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev,
unsigned timeout)
{
diff --git a/drivers/hid/hid-logitech-dj.h b/drivers/hid/hid-logitech-dj.h
index fd28a5e..4a40003 100644
--- a/drivers/hid/hid-logitech-dj.h
+++ b/drivers/hid/hid-logitech-dj.h
@@ -101,6 +101,7 @@ struct dj_receiver_dev {
struct work_struct work;
struct kfifo notif_fifo;
spinlock_t lock;
+ bool querying_devices;
};
struct dj_device {
diff --git a/drivers/hwmon/ad7314.c b/drivers/hwmon/ad7314.c
index cfec802..f915eb1 100644
--- a/drivers/hwmon/ad7314.c
+++ b/drivers/hwmon/ad7314.c
@@ -87,10 +87,18 @@ static ssize_t ad7314_show_temperature(struct device *dev,
}
}
+static ssize_t ad7314_show_name(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ return sprintf(buf, "%s\n", to_spi_device(dev)->modalias);
+}
+
+static DEVICE_ATTR(name, S_IRUGO, ad7314_show_name, NULL);
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO,
ad7314_show_temperature, NULL, 0);
static struct attribute *ad7314_attributes[] = {
+ &dev_attr_name.attr,
&sensor_dev_attr_temp1_input.dev_attr.attr,
NULL,
};
diff --git a/drivers/hwmon/ads7871.c b/drivers/hwmon/ads7871.c
index e65c6e4..7bf4ce3 100644
--- a/drivers/hwmon/ads7871.c
+++ b/drivers/hwmon/ads7871.c
@@ -139,6 +139,12 @@ static ssize_t show_voltage(struct device *dev,
}
}
+static ssize_t ads7871_show_name(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ return sprintf(buf, "%s\n", to_spi_device(dev)->modalias);
+}
+
static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, show_voltage, NULL, 0);
static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_voltage, NULL, 1);
static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_voltage, NULL, 2);
@@ -148,6 +154,8 @@ static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, show_voltage, NULL, 5);
static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, show_voltage, NULL, 6);
static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, show_voltage, NULL, 7);
+static DEVICE_ATTR(name, S_IRUGO, ads7871_show_name, NULL);
+
static struct attribute *ads7871_attributes[] = {
&sensor_dev_attr_in0_input.dev_attr.attr,
&sensor_dev_attr_in1_input.dev_attr.attr,
@@ -157,6 +165,7 @@ static struct attribute *ads7871_attributes[] = {
&sensor_dev_attr_in5_input.dev_attr.attr,
&sensor_dev_attr_in6_input.dev_attr.attr,
&sensor_dev_attr_in7_input.dev_attr.attr,
+ &dev_attr_name.attr,
NULL
};
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
index 2827088..8f3f6f2 100644
--- a/drivers/hwmon/applesmc.c
+++ b/drivers/hwmon/applesmc.c
@@ -53,10 +53,10 @@
#define APPLESMC_MAX_DATA_LENGTH 32
-/* wait up to 32 ms for a status change. */
+/* wait up to 128 ms for a status change. */
#define APPLESMC_MIN_WAIT 0x0010
#define APPLESMC_RETRY_WAIT 0x0100
-#define APPLESMC_MAX_WAIT 0x8000
+#define APPLESMC_MAX_WAIT 0x20000
#define APPLESMC_READ_CMD 0x10
#define APPLESMC_WRITE_CMD 0x11
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c
index 0fa356f..984a3f1 100644
--- a/drivers/hwmon/coretemp.c
+++ b/drivers/hwmon/coretemp.c
@@ -815,17 +815,20 @@ static int __init coretemp_init(void)
if (err)
goto exit;
+ get_online_cpus();
for_each_online_cpu(i)
get_core_online(i);
#ifndef CONFIG_HOTPLUG_CPU
if (list_empty(&pdev_list)) {
+ put_online_cpus();
err = -ENODEV;
goto exit_driver_unreg;
}
#endif
register_hotcpu_notifier(&coretemp_cpu_notifier);
+ put_online_cpus();
return 0;
#ifndef CONFIG_HOTPLUG_CPU
@@ -840,6 +843,7 @@ static void __exit coretemp_exit(void)
{
struct pdev_entry *p, *n;
+ get_online_cpus();
unregister_hotcpu_notifier(&coretemp_cpu_notifier);
mutex_lock(&pdev_list_mutex);
list_for_each_entry_safe(p, n, &pdev_list, list) {
@@ -848,6 +852,7 @@ static void __exit coretemp_exit(void)
kfree(p);
}
mutex_unlock(&pdev_list_mutex);
+ put_online_cpus();
platform_driver_unregister(&coretemp_driver);
}
diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c
index 2764b78..af69073 100644
--- a/drivers/hwmon/fam15h_power.c
+++ b/drivers/hwmon/fam15h_power.c
@@ -129,12 +129,12 @@ static bool __devinit fam15h_power_is_internal_node0(struct pci_dev *f4)
* counter saturations resulting in bogus power readings.
* We correct this value ourselves to cope with older BIOSes.
*/
-static DEFINE_PCI_DEVICE_TABLE(affected_device) = {
+static const struct pci_device_id affected_device[] = {
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F4) },
{ 0 }
};
-static void __devinit tweak_runavg_range(struct pci_dev *pdev)
+static void tweak_runavg_range(struct pci_dev *pdev)
{
u32 val;
@@ -158,6 +158,16 @@ static void __devinit tweak_runavg_range(struct pci_dev *pdev)
REG_TDP_RUNNING_AVERAGE, val);
}
+#ifdef CONFIG_PM
+static int fam15h_power_resume(struct pci_dev *pdev)
+{
+ tweak_runavg_range(pdev);
+ return 0;
+}
+#else
+#define fam15h_power_resume NULL
+#endif
+
static void __devinit fam15h_power_init_data(struct pci_dev *f4,
struct fam15h_power_data *data)
{
@@ -256,6 +266,7 @@ static struct pci_driver fam15h_power_driver = {
.id_table = fam15h_power_id_table,
.probe = fam15h_power_probe,
.remove = __devexit_p(fam15h_power_remove),
+ .resume = fam15h_power_resume,
};
module_pci_driver(fam15h_power_driver);
diff --git a/drivers/hwmon/via-cputemp.c b/drivers/hwmon/via-cputemp.c
index ee4ebc1..2e56c6c 100644
--- a/drivers/hwmon/via-cputemp.c
+++ b/drivers/hwmon/via-cputemp.c
@@ -328,6 +328,7 @@ static int __init via_cputemp_init(void)
if (err)
goto exit;
+ get_online_cpus();
for_each_online_cpu(i) {
struct cpuinfo_x86 *c = &cpu_data(i);
@@ -347,12 +348,14 @@ static int __init via_cputemp_init(void)
#ifndef CONFIG_HOTPLUG_CPU
if (list_empty(&pdev_list)) {
+ put_online_cpus();
err = -ENODEV;
goto exit_driver_unreg;
}
#endif
register_hotcpu_notifier(&via_cputemp_cpu_notifier);
+ put_online_cpus();
return 0;
#ifndef CONFIG_HOTPLUG_CPU
@@ -367,6 +370,7 @@ static void __exit via_cputemp_exit(void)
{
struct pdev_entry *p, *n;
+ get_online_cpus();
unregister_hotcpu_notifier(&via_cputemp_cpu_notifier);
mutex_lock(&pdev_list_mutex);
list_for_each_entry_safe(p, n, &pdev_list, list) {
@@ -375,6 +379,7 @@ static void __exit via_cputemp_exit(void)
kfree(p);
}
mutex_unlock(&pdev_list_mutex);
+ put_online_cpus();
platform_driver_unregister(&via_cputemp_driver);
}
diff --git a/drivers/hwspinlock/hwspinlock_core.c b/drivers/hwspinlock/hwspinlock_core.c
index 1201a15..db713c0 100644
--- a/drivers/hwspinlock/hwspinlock_core.c
+++ b/drivers/hwspinlock/hwspinlock_core.c
@@ -552,7 +552,7 @@ EXPORT_SYMBOL_GPL(hwspin_lock_request_specific);
*/
int hwspin_lock_free(struct hwspinlock *hwlock)
{
- struct device *dev = hwlock->bank->dev;
+ struct device *dev;
struct hwspinlock *tmp;
int ret;
@@ -561,6 +561,7 @@ int hwspin_lock_free(struct hwspinlock *hwlock)
return -EINVAL;
}
+ dev = hwlock->bank->dev;
mutex_lock(&hwspinlock_tree_lock);
/* make sure the hwspinlock is used */
diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c
index 51f4206..6cfd4d8 100644
--- a/drivers/infiniband/hw/cxgb4/cm.c
+++ b/drivers/infiniband/hw/cxgb4/cm.c
@@ -1361,11 +1361,11 @@ static int abort_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
struct tid_info *t = dev->rdev.lldi.tids;
ep = lookup_tid(t, tid);
- PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
if (!ep) {
printk(KERN_WARNING MOD "Abort rpl to freed endpoint\n");
return 0;
}
+ PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
mutex_lock(&ep->com.mutex);
switch (ep->com.state) {
case ABORTING:
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
index cb5b7f7..b29a424 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
@@ -2219,7 +2219,6 @@ static bool ocrdma_poll_success_scqe(struct ocrdma_qp *qp,
u32 wqe_idx;
if (!qp->wqe_wr_id_tbl[tail].signaled) {
- expand = true; /* CQE cannot be consumed yet */
*polled = false; /* WC cannot be consumed yet */
} else {
ibwc->status = IB_WC_SUCCESS;
@@ -2227,10 +2226,11 @@ static bool ocrdma_poll_success_scqe(struct ocrdma_qp *qp,
ibwc->qp = &qp->ibqp;
ocrdma_update_wc(qp, ibwc, tail);
*polled = true;
- wqe_idx = le32_to_cpu(cqe->wq.wqeidx) & OCRDMA_CQE_WQEIDX_MASK;
- if (tail != wqe_idx)
- expand = true; /* Coalesced CQE can't be consumed yet */
}
+ wqe_idx = le32_to_cpu(cqe->wq.wqeidx) & OCRDMA_CQE_WQEIDX_MASK;
+ if (tail != wqe_idx)
+ expand = true; /* Coalesced CQE can't be consumed yet */
+
ocrdma_hwq_inc_tail(&qp->sq);
return expand;
}
diff --git a/drivers/infiniband/hw/qib/qib_mad.c b/drivers/infiniband/hw/qib/qib_mad.c
index 19f1e6c..ccb1191 100644
--- a/drivers/infiniband/hw/qib/qib_mad.c
+++ b/drivers/infiniband/hw/qib/qib_mad.c
@@ -471,9 +471,10 @@ static int subn_get_portinfo(struct ib_smp *smp, struct ib_device *ibdev,
if (port_num != port) {
ibp = to_iport(ibdev, port_num);
ret = check_mkey(ibp, smp, 0);
- if (ret)
+ if (ret) {
ret = IB_MAD_RESULT_FAILURE;
goto bail;
+ }
}
}
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index 381f51b..ac48f86 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -266,7 +266,10 @@ struct ipoib_ethtool_st {
u16 max_coalesced_frames;
};
+struct ipoib_neigh_table;
+
struct ipoib_neigh_hash {
+ struct ipoib_neigh_table *ntbl;
struct ipoib_neigh __rcu **buckets;
struct rcu_head rcu;
u32 mask;
@@ -275,9 +278,9 @@ struct ipoib_neigh_hash {
struct ipoib_neigh_table {
struct ipoib_neigh_hash __rcu *htbl;
- rwlock_t rwlock;
atomic_t entries;
struct completion flushed;
+ struct completion deleted;
};
/*
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index b3e9709..128fab1 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -551,15 +551,15 @@ static void neigh_add_path(struct sk_buff *skb, u8 *daddr,
struct ipoib_neigh *neigh;
unsigned long flags;
+ spin_lock_irqsave(&priv->lock, flags);
neigh = ipoib_neigh_alloc(daddr, dev);
if (!neigh) {
+ spin_unlock_irqrestore(&priv->lock, flags);
++dev->stats.tx_dropped;
dev_kfree_skb_any(skb);
return;
}
- spin_lock_irqsave(&priv->lock, flags);
-
path = __path_find(dev, daddr + 4);
if (!path) {
path = path_rec_create(dev, daddr + 4);
@@ -868,10 +868,10 @@ static void __ipoib_reap_neigh(struct ipoib_dev_priv *priv)
if (test_bit(IPOIB_STOP_NEIGH_GC, &priv->flags))
return;
- write_lock_bh(&ntbl->rwlock);
+ spin_lock_irqsave(&priv->lock, flags);
htbl = rcu_dereference_protected(ntbl->htbl,
- lockdep_is_held(&ntbl->rwlock));
+ lockdep_is_held(&priv->lock));
if (!htbl)
goto out_unlock;
@@ -888,16 +888,14 @@ static void __ipoib_reap_neigh(struct ipoib_dev_priv *priv)
struct ipoib_neigh __rcu **np = &htbl->buckets[i];
while ((neigh = rcu_dereference_protected(*np,
- lockdep_is_held(&ntbl->rwlock))) != NULL) {
+ lockdep_is_held(&priv->lock))) != NULL) {
/* was the neigh idle for two GC periods */
if (time_after(neigh_obsolete, neigh->alive)) {
rcu_assign_pointer(*np,
rcu_dereference_protected(neigh->hnext,
- lockdep_is_held(&ntbl->rwlock)));
+ lockdep_is_held(&priv->lock)));
/* remove from path/mc list */
- spin_lock_irqsave(&priv->lock, flags);
list_del(&neigh->list);
- spin_unlock_irqrestore(&priv->lock, flags);
call_rcu(&neigh->rcu, ipoib_neigh_reclaim);
} else {
np = &neigh->hnext;
@@ -907,7 +905,7 @@ static void __ipoib_reap_neigh(struct ipoib_dev_priv *priv)
}
out_unlock:
- write_unlock_bh(&ntbl->rwlock);
+ spin_unlock_irqrestore(&priv->lock, flags);
}
static void ipoib_reap_neigh(struct work_struct *work)
@@ -952,10 +950,8 @@ struct ipoib_neigh *ipoib_neigh_alloc(u8 *daddr,
struct ipoib_neigh *neigh;
u32 hash_val;
- write_lock_bh(&ntbl->rwlock);
-
htbl = rcu_dereference_protected(ntbl->htbl,
- lockdep_is_held(&ntbl->rwlock));
+ lockdep_is_held(&priv->lock));
if (!htbl) {
neigh = NULL;
goto out_unlock;
@@ -966,10 +962,10 @@ struct ipoib_neigh *ipoib_neigh_alloc(u8 *daddr,
*/
hash_val = ipoib_addr_hash(htbl, daddr);
for (neigh = rcu_dereference_protected(htbl->buckets[hash_val],
- lockdep_is_held(&ntbl->rwlock));
+ lockdep_is_held(&priv->lock));
neigh != NULL;
neigh = rcu_dereference_protected(neigh->hnext,
- lockdep_is_held(&ntbl->rwlock))) {
+ lockdep_is_held(&priv->lock))) {
if (memcmp(daddr, neigh->daddr, INFINIBAND_ALEN) == 0) {
/* found, take one ref on behalf of the caller */
if (!atomic_inc_not_zero(&neigh->refcnt)) {
@@ -992,12 +988,11 @@ struct ipoib_neigh *ipoib_neigh_alloc(u8 *daddr,
/* put in hash */
rcu_assign_pointer(neigh->hnext,
rcu_dereference_protected(htbl->buckets[hash_val],
- lockdep_is_held(&ntbl->rwlock)));
+ lockdep_is_held(&priv->lock)));
rcu_assign_pointer(htbl->buckets[hash_val], neigh);
atomic_inc(&ntbl->entries);
out_unlock:
- write_unlock_bh(&ntbl->rwlock);
return neigh;
}
@@ -1045,35 +1040,29 @@ void ipoib_neigh_free(struct ipoib_neigh *neigh)
struct ipoib_neigh *n;
u32 hash_val;
- write_lock_bh(&ntbl->rwlock);
-
htbl = rcu_dereference_protected(ntbl->htbl,
- lockdep_is_held(&ntbl->rwlock));
+ lockdep_is_held(&priv->lock));
if (!htbl)
- goto out_unlock;
+ return;
hash_val = ipoib_addr_hash(htbl, neigh->daddr);
np = &htbl->buckets[hash_val];
for (n = rcu_dereference_protected(*np,
- lockdep_is_held(&ntbl->rwlock));
+ lockdep_is_held(&priv->lock));
n != NULL;
n = rcu_dereference_protected(*np,
- lockdep_is_held(&ntbl->rwlock))) {
+ lockdep_is_held(&priv->lock))) {
if (n == neigh) {
/* found */
rcu_assign_pointer(*np,
rcu_dereference_protected(neigh->hnext,
- lockdep_is_held(&ntbl->rwlock)));
+ lockdep_is_held(&priv->lock)));
call_rcu(&neigh->rcu, ipoib_neigh_reclaim);
- goto out_unlock;
+ return;
} else {
np = &n->hnext;
}
}
-
-out_unlock:
- write_unlock_bh(&ntbl->rwlock);
-
}
static int ipoib_neigh_hash_init(struct ipoib_dev_priv *priv)
@@ -1085,7 +1074,6 @@ static int ipoib_neigh_hash_init(struct ipoib_dev_priv *priv)
clear_bit(IPOIB_NEIGH_TBL_FLUSH, &priv->flags);
ntbl->htbl = NULL;
- rwlock_init(&ntbl->rwlock);
htbl = kzalloc(sizeof(*htbl), GFP_KERNEL);
if (!htbl)
return -ENOMEM;
@@ -1100,6 +1088,7 @@ static int ipoib_neigh_hash_init(struct ipoib_dev_priv *priv)
htbl->mask = (size - 1);
htbl->buckets = buckets;
ntbl->htbl = htbl;
+ htbl->ntbl = ntbl;
atomic_set(&ntbl->entries, 0);
/* start garbage collection */
@@ -1116,9 +1105,11 @@ static void neigh_hash_free_rcu(struct rcu_head *head)
struct ipoib_neigh_hash,
rcu);
struct ipoib_neigh __rcu **buckets = htbl->buckets;
+ struct ipoib_neigh_table *ntbl = htbl->ntbl;
kfree(buckets);
kfree(htbl);
+ complete(&ntbl->deleted);
}
void ipoib_del_neighs_by_gid(struct net_device *dev, u8 *gid)
@@ -1130,10 +1121,10 @@ void ipoib_del_neighs_by_gid(struct net_device *dev, u8 *gid)
int i;
/* remove all neigh connected to a given path or mcast */
- write_lock_bh(&ntbl->rwlock);
+ spin_lock_irqsave(&priv->lock, flags);
htbl = rcu_dereference_protected(ntbl->htbl,
- lockdep_is_held(&ntbl->rwlock));
+ lockdep_is_held(&priv->lock));
if (!htbl)
goto out_unlock;
@@ -1143,16 +1134,14 @@ void ipoib_del_neighs_by_gid(struct net_device *dev, u8 *gid)
struct ipoib_neigh __rcu **np = &htbl->buckets[i];
while ((neigh = rcu_dereference_protected(*np,
- lockdep_is_held(&ntbl->rwlock))) != NULL) {
+ lockdep_is_held(&priv->lock))) != NULL) {
/* delete neighs belong to this parent */
if (!memcmp(gid, neigh->daddr + 4, sizeof (union ib_gid))) {
rcu_assign_pointer(*np,
rcu_dereference_protected(neigh->hnext,
- lockdep_is_held(&ntbl->rwlock)));
+ lockdep_is_held(&priv->lock)));
/* remove from parent list */
- spin_lock_irqsave(&priv->lock, flags);
list_del(&neigh->list);
- spin_unlock_irqrestore(&priv->lock, flags);
call_rcu(&neigh->rcu, ipoib_neigh_reclaim);
} else {
np = &neigh->hnext;
@@ -1161,7 +1150,7 @@ void ipoib_del_neighs_by_gid(struct net_device *dev, u8 *gid)
}
}
out_unlock:
- write_unlock_bh(&ntbl->rwlock);
+ spin_unlock_irqrestore(&priv->lock, flags);
}
static void ipoib_flush_neighs(struct ipoib_dev_priv *priv)
@@ -1169,37 +1158,44 @@ static void ipoib_flush_neighs(struct ipoib_dev_priv *priv)
struct ipoib_neigh_table *ntbl = &priv->ntbl;
struct ipoib_neigh_hash *htbl;
unsigned long flags;
- int i;
+ int i, wait_flushed = 0;
- write_lock_bh(&ntbl->rwlock);
+ init_completion(&priv->ntbl.flushed);
+
+ spin_lock_irqsave(&priv->lock, flags);
htbl = rcu_dereference_protected(ntbl->htbl,
- lockdep_is_held(&ntbl->rwlock));
+ lockdep_is_held(&priv->lock));
if (!htbl)
goto out_unlock;
+ wait_flushed = atomic_read(&priv->ntbl.entries);
+ if (!wait_flushed)
+ goto free_htbl;
+
for (i = 0; i < htbl->size; i++) {
struct ipoib_neigh *neigh;
struct ipoib_neigh __rcu **np = &htbl->buckets[i];
while ((neigh = rcu_dereference_protected(*np,
- lockdep_is_held(&ntbl->rwlock))) != NULL) {
+ lockdep_is_held(&priv->lock))) != NULL) {
rcu_assign_pointer(*np,
rcu_dereference_protected(neigh->hnext,
- lockdep_is_held(&ntbl->rwlock)));
+ lockdep_is_held(&priv->lock)));
/* remove from path/mc list */
- spin_lock_irqsave(&priv->lock, flags);
list_del(&neigh->list);
- spin_unlock_irqrestore(&priv->lock, flags);
call_rcu(&neigh->rcu, ipoib_neigh_reclaim);
}
}
+free_htbl:
rcu_assign_pointer(ntbl->htbl, NULL);
call_rcu(&htbl->rcu, neigh_hash_free_rcu);
out_unlock:
- write_unlock_bh(&ntbl->rwlock);
+ spin_unlock_irqrestore(&priv->lock, flags);
+ if (wait_flushed)
+ wait_for_completion(&priv->ntbl.flushed);
}
static void ipoib_neigh_hash_uninit(struct net_device *dev)
@@ -1208,7 +1204,7 @@ static void ipoib_neigh_hash_uninit(struct net_device *dev)
int stopped;
ipoib_dbg(priv, "ipoib_neigh_hash_uninit\n");
- init_completion(&priv->ntbl.flushed);
+ init_completion(&priv->ntbl.deleted);
set_bit(IPOIB_NEIGH_TBL_FLUSH, &priv->flags);
/* Stop GC if called at init fail need to cancel work */
@@ -1216,10 +1212,9 @@ static void ipoib_neigh_hash_uninit(struct net_device *dev)
if (!stopped)
cancel_delayed_work(&priv->neigh_reap_task);
- if (atomic_read(&priv->ntbl.entries)) {
- ipoib_flush_neighs(priv);
- wait_for_completion(&priv->ntbl.flushed);
- }
+ ipoib_flush_neighs(priv);
+
+ wait_for_completion(&priv->ntbl.deleted);
}
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index 13f4aa7..7536724 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -707,9 +707,7 @@ out:
neigh = ipoib_neigh_get(dev, daddr);
spin_lock_irqsave(&priv->lock, flags);
if (!neigh) {
- spin_unlock_irqrestore(&priv->lock, flags);
neigh = ipoib_neigh_alloc(daddr, dev);
- spin_lock_irqsave(&priv->lock, flags);
if (neigh) {
kref_get(&mcast->ah->ref);
neigh->ah = mcast->ah;
diff --git a/drivers/input/keyboard/imx_keypad.c b/drivers/input/keyboard/imx_keypad.c
index ce68e36..cdc2526 100644
--- a/drivers/input/keyboard/imx_keypad.c
+++ b/drivers/input/keyboard/imx_keypad.c
@@ -516,9 +516,9 @@ static int __devinit imx_keypad_probe(struct platform_device *pdev)
input_set_drvdata(input_dev, keypad);
/* Ensure that the keypad will stay dormant until opened */
- clk_enable(keypad->clk);
+ clk_prepare_enable(keypad->clk);
imx_keypad_inhibit(keypad);
- clk_disable(keypad->clk);
+ clk_disable_unprepare(keypad->clk);
error = request_irq(irq, imx_keypad_irq_handler, 0,
pdev->name, keypad);
diff --git a/drivers/input/misc/ab8500-ponkey.c b/drivers/input/misc/ab8500-ponkey.c
index f06231b..84ec691 100644
--- a/drivers/input/misc/ab8500-ponkey.c
+++ b/drivers/input/misc/ab8500-ponkey.c
@@ -74,8 +74,8 @@ static int __devinit ab8500_ponkey_probe(struct platform_device *pdev)
ponkey->idev = input;
ponkey->ab8500 = ab8500;
- ponkey->irq_dbf = ab8500_irq_get_virq(ab8500, irq_dbf);
- ponkey->irq_dbr = ab8500_irq_get_virq(ab8500, irq_dbr);
+ ponkey->irq_dbf = irq_dbf;
+ ponkey->irq_dbr = irq_dbr;
input->name = "AB8500 POn(PowerOn) Key";
input->dev.parent = &pdev->dev;
diff --git a/drivers/input/mouse/sentelic.c b/drivers/input/mouse/sentelic.c
index 3f5649f..a261d85 100644
--- a/drivers/input/mouse/sentelic.c
+++ b/drivers/input/mouse/sentelic.c
@@ -721,6 +721,17 @@ static psmouse_ret_t fsp_process_byte(struct psmouse *psmouse)
switch (psmouse->packet[0] >> FSP_PKT_TYPE_SHIFT) {
case FSP_PKT_TYPE_ABS:
+
+ if ((packet[0] == 0x48 || packet[0] == 0x49) &&
+ packet[1] == 0 && packet[2] == 0) {
+ /*
+ * Ignore coordinate noise when finger leaving the
+ * surface, otherwise cursor may jump to upper-left
+ * corner.
+ */
+ packet[3] &= 0xf0;
+ }
+
abs_x = GET_ABS_X(packet);
abs_y = GET_ABS_Y(packet);
diff --git a/drivers/input/serio/ambakmi.c b/drivers/input/serio/ambakmi.c
index 2ffd110..2e77246 100644
--- a/drivers/input/serio/ambakmi.c
+++ b/drivers/input/serio/ambakmi.c
@@ -72,7 +72,7 @@ static int amba_kmi_open(struct serio *io)
unsigned int divisor;
int ret;
- ret = clk_enable(kmi->clk);
+ ret = clk_prepare_enable(kmi->clk);
if (ret)
goto out;
@@ -92,7 +92,7 @@ static int amba_kmi_open(struct serio *io)
return 0;
clk_disable:
- clk_disable(kmi->clk);
+ clk_disable_unprepare(kmi->clk);
out:
return ret;
}
@@ -104,7 +104,7 @@ static void amba_kmi_close(struct serio *io)
writeb(0, KMICR);
free_irq(kmi->irq, kmi);
- clk_disable(kmi->clk);
+ clk_disable_unprepare(kmi->clk);
}
static int __devinit amba_kmi_probe(struct amba_device *dev,
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
index 6918773..d6cc77a 100644
--- a/drivers/input/serio/i8042-x86ia64io.h
+++ b/drivers/input/serio/i8042-x86ia64io.h
@@ -335,6 +335,12 @@ static const struct dmi_system_id __initconst i8042_dmi_nomux_table[] = {
},
{
.matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE C850D"),
+ },
+ },
+ {
+ .matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ALIENWARE"),
DMI_MATCH(DMI_PRODUCT_NAME, "Sentia"),
},
diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c
index b06a5e3..6495777 100644
--- a/drivers/input/touchscreen/edt-ft5x06.c
+++ b/drivers/input/touchscreen/edt-ft5x06.c
@@ -566,9 +566,12 @@ static ssize_t edt_ft5x06_debugfs_raw_data_read(struct file *file,
}
read = min_t(size_t, count, tsdata->raw_bufsize - *off);
- error = copy_to_user(buf, tsdata->raw_buffer + *off, read);
- if (!error)
- *off += read;
+ if (copy_to_user(buf, tsdata->raw_buffer + *off, read)) {
+ error = -EFAULT;
+ goto out;
+ }
+
+ *off += read;
out:
mutex_unlock(&tsdata->mutex);
return error ?: read;
diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c
index e32709e..721fdb3 100644
--- a/drivers/input/touchscreen/usbtouchscreen.c
+++ b/drivers/input/touchscreen/usbtouchscreen.c
@@ -304,6 +304,45 @@ static int e2i_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
#define EGALAX_PKT_TYPE_REPT 0x80
#define EGALAX_PKT_TYPE_DIAG 0x0A
+static int egalax_init(struct usbtouch_usb *usbtouch)
+{
+ int ret, i;
+ unsigned char *buf;
+ struct usb_device *udev = interface_to_usbdev(usbtouch->interface);
+
+ /*
+ * An eGalax diagnostic packet kicks the device into using the right
+ * protocol. We send a "check active" packet. The response will be
+ * read later and ignored.
+ */
+
+ buf = kmalloc(3, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ buf[0] = EGALAX_PKT_TYPE_DIAG;
+ buf[1] = 1; /* length */
+ buf[2] = 'A'; /* command - check active */
+
+ for (i = 0; i < 3; i++) {
+ ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ 0,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 0, 0, buf, 3,
+ USB_CTRL_SET_TIMEOUT);
+ if (ret >= 0) {
+ ret = 0;
+ break;
+ }
+ if (ret != -EPIPE)
+ break;
+ }
+
+ kfree(buf);
+
+ return ret;
+}
+
static int egalax_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
{
if ((pkt[0] & EGALAX_PKT_TYPE_MASK) != EGALAX_PKT_TYPE_REPT)
@@ -1056,6 +1095,7 @@ static struct usbtouch_device_info usbtouch_dev_info[] = {
.process_pkt = usbtouch_process_multi,
.get_pkt_len = egalax_get_pkt_len,
.read_data = egalax_read_data,
+ .init = egalax_init,
},
#endif
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index d8abb90..034233e 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -1555,6 +1555,7 @@ static int multipath_ioctl(struct dm_target *ti, unsigned int cmd,
unsigned long arg)
{
struct multipath *m = ti->private;
+ struct pgpath *pgpath;
struct block_device *bdev;
fmode_t mode;
unsigned long flags;
@@ -1570,12 +1571,14 @@ again:
if (!m->current_pgpath)
__choose_pgpath(m, 0);
- if (m->current_pgpath) {
- bdev = m->current_pgpath->path.dev->bdev;
- mode = m->current_pgpath->path.dev->mode;
+ pgpath = m->current_pgpath;
+
+ if (pgpath) {
+ bdev = pgpath->path.dev->bdev;
+ mode = pgpath->path.dev->mode;
}
- if (m->queue_io)
+ if ((pgpath && m->queue_io) || (!pgpath && m->queue_if_no_path))
r = -EAGAIN;
else if (!bdev)
r = -EIO;
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index f900690..100368e 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -1212,6 +1212,41 @@ struct dm_target *dm_table_find_target(struct dm_table *t, sector_t sector)
return &t->targets[(KEYS_PER_NODE * n) + k];
}
+static int count_device(struct dm_target *ti, struct dm_dev *dev,
+ sector_t start, sector_t len, void *data)
+{
+ unsigned *num_devices = data;
+
+ (*num_devices)++;
+
+ return 0;
+}
+
+/*
+ * Check whether a table has no data devices attached using each
+ * target's iterate_devices method.
+ * Returns false if the result is unknown because a target doesn't
+ * support iterate_devices.
+ */
+bool dm_table_has_no_data_devices(struct dm_table *table)
+{
+ struct dm_target *uninitialized_var(ti);
+ unsigned i = 0, num_devices = 0;
+
+ while (i < dm_table_get_num_targets(table)) {
+ ti = dm_table_get_target(table, i++);
+
+ if (!ti->type->iterate_devices)
+ return false;
+
+ ti->type->iterate_devices(ti, count_device, &num_devices);
+ if (num_devices)
+ return false;
+ }
+
+ return true;
+}
+
/*
* Establish the new table's queue_limits and validate them.
*/
@@ -1354,17 +1389,25 @@ static int device_is_nonrot(struct dm_target *ti, struct dm_dev *dev,
return q && blk_queue_nonrot(q);
}
-static bool dm_table_is_nonrot(struct dm_table *t)
+static int device_is_not_random(struct dm_target *ti, struct dm_dev *dev,
+ sector_t start, sector_t len, void *data)
+{
+ struct request_queue *q = bdev_get_queue(dev->bdev);
+
+ return q && !blk_queue_add_random(q);
+}
+
+static bool dm_table_all_devices_attribute(struct dm_table *t,
+ iterate_devices_callout_fn func)
{
struct dm_target *ti;
unsigned i = 0;
- /* Ensure that all underlying device are non-rotational. */
while (i < dm_table_get_num_targets(t)) {
ti = dm_table_get_target(t, i++);
if (!ti->type->iterate_devices ||
- !ti->type->iterate_devices(ti, device_is_nonrot, NULL))
+ !ti->type->iterate_devices(ti, func, NULL))
return 0;
}
@@ -1396,7 +1439,8 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
if (!dm_table_discard_zeroes_data(t))
q->limits.discard_zeroes_data = 0;
- if (dm_table_is_nonrot(t))
+ /* Ensure that all underlying devices are non-rotational. */
+ if (dm_table_all_devices_attribute(t, device_is_nonrot))
queue_flag_set_unlocked(QUEUE_FLAG_NONROT, q);
else
queue_flag_clear_unlocked(QUEUE_FLAG_NONROT, q);
@@ -1404,6 +1448,15 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
dm_table_set_integrity(t);
/*
+ * Determine whether or not this queue's I/O timings contribute
+ * to the entropy pool, Only request-based targets use this.
+ * Clear QUEUE_FLAG_ADD_RANDOM if any underlying device does not
+ * have it set.
+ */
+ if (blk_queue_add_random(q) && dm_table_all_devices_attribute(t, device_is_not_random))
+ queue_flag_clear_unlocked(QUEUE_FLAG_ADD_RANDOM, q);
+
+ /*
* QUEUE_FLAG_STACKABLE must be set after all queue settings are
* visible to other CPUs because, once the flag is set, incoming bios
* are processed by request-based dm, which refers to the queue
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
index af1fc3b..c29410a 100644
--- a/drivers/md/dm-thin.c
+++ b/drivers/md/dm-thin.c
@@ -509,9 +509,9 @@ enum pool_mode {
struct pool_features {
enum pool_mode mode;
- unsigned zero_new_blocks:1;
- unsigned discard_enabled:1;
- unsigned discard_passdown:1;
+ bool zero_new_blocks:1;
+ bool discard_enabled:1;
+ bool discard_passdown:1;
};
struct thin_c;
@@ -580,7 +580,8 @@ struct pool_c {
struct dm_target_callbacks callbacks;
dm_block_t low_water_blocks;
- struct pool_features pf;
+ struct pool_features requested_pf; /* Features requested during table load */
+ struct pool_features adjusted_pf; /* Features used after adjusting for constituent devices */
};
/*
@@ -1839,6 +1840,47 @@ static void __requeue_bios(struct pool *pool)
/*----------------------------------------------------------------
* Binding of control targets to a pool object
*--------------------------------------------------------------*/
+static bool data_dev_supports_discard(struct pool_c *pt)
+{
+ struct request_queue *q = bdev_get_queue(pt->data_dev->bdev);
+
+ return q && blk_queue_discard(q);
+}
+
+/*
+ * If discard_passdown was enabled verify that the data device
+ * supports discards. Disable discard_passdown if not.
+ */
+static void disable_passdown_if_not_supported(struct pool_c *pt)
+{
+ struct pool *pool = pt->pool;
+ struct block_device *data_bdev = pt->data_dev->bdev;
+ struct queue_limits *data_limits = &bdev_get_queue(data_bdev)->limits;
+ sector_t block_size = pool->sectors_per_block << SECTOR_SHIFT;
+ const char *reason = NULL;
+ char buf[BDEVNAME_SIZE];
+
+ if (!pt->adjusted_pf.discard_passdown)
+ return;
+
+ if (!data_dev_supports_discard(pt))
+ reason = "discard unsupported";
+
+ else if (data_limits->max_discard_sectors < pool->sectors_per_block)
+ reason = "max discard sectors smaller than a block";
+
+ else if (data_limits->discard_granularity > block_size)
+ reason = "discard granularity larger than a block";
+
+ else if (block_size & (data_limits->discard_granularity - 1))
+ reason = "discard granularity not a factor of block size";
+
+ if (reason) {
+ DMWARN("Data device (%s) %s: Disabling discard passdown.", bdevname(data_bdev, buf), reason);
+ pt->adjusted_pf.discard_passdown = false;
+ }
+}
+
static int bind_control_target(struct pool *pool, struct dm_target *ti)
{
struct pool_c *pt = ti->private;
@@ -1847,31 +1889,16 @@ static int bind_control_target(struct pool *pool, struct dm_target *ti)
* We want to make sure that degraded pools are never upgraded.
*/
enum pool_mode old_mode = pool->pf.mode;
- enum pool_mode new_mode = pt->pf.mode;
+ enum pool_mode new_mode = pt->adjusted_pf.mode;
if (old_mode > new_mode)
new_mode = old_mode;
pool->ti = ti;
pool->low_water_blocks = pt->low_water_blocks;
- pool->pf = pt->pf;
- set_pool_mode(pool, new_mode);
+ pool->pf = pt->adjusted_pf;
- /*
- * If discard_passdown was enabled verify that the data device
- * supports discards. Disable discard_passdown if not; otherwise
- * -EOPNOTSUPP will be returned.
- */
- /* FIXME: pull this out into a sep fn. */
- if (pt->pf.discard_passdown) {
- struct request_queue *q = bdev_get_queue(pt->data_dev->bdev);
- if (!q || !blk_queue_discard(q)) {
- char buf[BDEVNAME_SIZE];
- DMWARN("Discard unsupported by data device (%s): Disabling discard passdown.",
- bdevname(pt->data_dev->bdev, buf));
- pool->pf.discard_passdown = 0;
- }
- }
+ set_pool_mode(pool, new_mode);
return 0;
}
@@ -1889,9 +1916,9 @@ static void unbind_control_target(struct pool *pool, struct dm_target *ti)
static void pool_features_init(struct pool_features *pf)
{
pf->mode = PM_WRITE;
- pf->zero_new_blocks = 1;
- pf->discard_enabled = 1;
- pf->discard_passdown = 1;
+ pf->zero_new_blocks = true;
+ pf->discard_enabled = true;
+ pf->discard_passdown = true;
}
static void __pool_destroy(struct pool *pool)
@@ -2119,13 +2146,13 @@ static int parse_pool_features(struct dm_arg_set *as, struct pool_features *pf,
argc--;
if (!strcasecmp(arg_name, "skip_block_zeroing"))
- pf->zero_new_blocks = 0;
+ pf->zero_new_blocks = false;
else if (!strcasecmp(arg_name, "ignore_discard"))
- pf->discard_enabled = 0;
+ pf->discard_enabled = false;
else if (!strcasecmp(arg_name, "no_discard_passdown"))
- pf->discard_passdown = 0;
+ pf->discard_passdown = false;
else if (!strcasecmp(arg_name, "read_only"))
pf->mode = PM_READ_ONLY;
@@ -2259,8 +2286,9 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
pt->metadata_dev = metadata_dev;
pt->data_dev = data_dev;
pt->low_water_blocks = low_water_blocks;
- pt->pf = pf;
+ pt->adjusted_pf = pt->requested_pf = pf;
ti->num_flush_requests = 1;
+
/*
* Only need to enable discards if the pool should pass
* them down to the data device. The thin device's discard
@@ -2268,12 +2296,14 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
*/
if (pf.discard_enabled && pf.discard_passdown) {
ti->num_discard_requests = 1;
+
/*
* Setting 'discards_supported' circumvents the normal
* stacking of discard limits (this keeps the pool and
* thin devices' discard limits consistent).
*/
ti->discards_supported = true;
+ ti->discard_zeroes_data_unsupported = true;
}
ti->private = pt;
@@ -2703,7 +2733,7 @@ static int pool_status(struct dm_target *ti, status_type_t type,
format_dev_t(buf2, pt->data_dev->bdev->bd_dev),
(unsigned long)pool->sectors_per_block,
(unsigned long long)pt->low_water_blocks);
- emit_flags(&pt->pf, result, sz, maxlen);
+ emit_flags(&pt->requested_pf, result, sz, maxlen);
break;
}
@@ -2732,20 +2762,21 @@ static int pool_merge(struct dm_target *ti, struct bvec_merge_data *bvm,
return min(max_size, q->merge_bvec_fn(q, bvm, biovec));
}
-static void set_discard_limits(struct pool *pool, struct queue_limits *limits)
+static void set_discard_limits(struct pool_c *pt, struct queue_limits *limits)
{
- /*
- * FIXME: these limits may be incompatible with the pool's data device
- */
+ struct pool *pool = pt->pool;
+ struct queue_limits *data_limits;
+
limits->max_discard_sectors = pool->sectors_per_block;
/*
- * This is just a hint, and not enforced. We have to cope with
- * bios that cover a block partially. A discard that spans a block
- * boundary is not sent to this target.
+ * discard_granularity is just a hint, and not enforced.
*/
- limits->discard_granularity = pool->sectors_per_block << SECTOR_SHIFT;
- limits->discard_zeroes_data = pool->pf.zero_new_blocks;
+ if (pt->adjusted_pf.discard_passdown) {
+ data_limits = &bdev_get_queue(pt->data_dev->bdev)->limits;
+ limits->discard_granularity = data_limits->discard_granularity;
+ } else
+ limits->discard_granularity = pool->sectors_per_block << SECTOR_SHIFT;
}
static void pool_io_hints(struct dm_target *ti, struct queue_limits *limits)
@@ -2755,15 +2786,25 @@ static void pool_io_hints(struct dm_target *ti, struct queue_limits *limits)
blk_limits_io_min(limits, 0);
blk_limits_io_opt(limits, pool->sectors_per_block << SECTOR_SHIFT);
- if (pool->pf.discard_enabled)
- set_discard_limits(pool, limits);
+
+ /*
+ * pt->adjusted_pf is a staging area for the actual features to use.
+ * They get transferred to the live pool in bind_control_target()
+ * called from pool_preresume().
+ */
+ if (!pt->adjusted_pf.discard_enabled)
+ return;
+
+ disable_passdown_if_not_supported(pt);
+
+ set_discard_limits(pt, limits);
}
static struct target_type pool_target = {
.name = "thin-pool",
.features = DM_TARGET_SINGLETON | DM_TARGET_ALWAYS_WRITEABLE |
DM_TARGET_IMMUTABLE,
- .version = {1, 3, 0},
+ .version = {1, 4, 0},
.module = THIS_MODULE,
.ctr = pool_ctr,
.dtr = pool_dtr,
@@ -3042,19 +3083,19 @@ static int thin_iterate_devices(struct dm_target *ti,
return 0;
}
+/*
+ * A thin device always inherits its queue limits from its pool.
+ */
static void thin_io_hints(struct dm_target *ti, struct queue_limits *limits)
{
struct thin_c *tc = ti->private;
- struct pool *pool = tc->pool;
- blk_limits_io_min(limits, 0);
- blk_limits_io_opt(limits, pool->sectors_per_block << SECTOR_SHIFT);
- set_discard_limits(pool, limits);
+ *limits = bdev_get_queue(tc->pool_dev->bdev)->limits;
}
static struct target_type thin_target = {
.name = "thin",
- .version = {1, 3, 0},
+ .version = {1, 4, 0},
.module = THIS_MODULE,
.ctr = thin_ctr,
.dtr = thin_dtr,
diff --git a/drivers/md/dm-verity.c b/drivers/md/dm-verity.c
index 254d192..892ae27 100644
--- a/drivers/md/dm-verity.c
+++ b/drivers/md/dm-verity.c
@@ -718,8 +718,8 @@ static int verity_ctr(struct dm_target *ti, unsigned argc, char **argv)
v->hash_dev_block_bits = ffs(num) - 1;
if (sscanf(argv[5], "%llu%c", &num_ll, &dummy) != 1 ||
- num_ll << (v->data_dev_block_bits - SECTOR_SHIFT) !=
- (sector_t)num_ll << (v->data_dev_block_bits - SECTOR_SHIFT)) {
+ (sector_t)(num_ll << (v->data_dev_block_bits - SECTOR_SHIFT))
+ >> (v->data_dev_block_bits - SECTOR_SHIFT) != num_ll) {
ti->error = "Invalid data blocks";
r = -EINVAL;
goto bad;
@@ -733,8 +733,8 @@ static int verity_ctr(struct dm_target *ti, unsigned argc, char **argv)
}
if (sscanf(argv[6], "%llu%c", &num_ll, &dummy) != 1 ||
- num_ll << (v->hash_dev_block_bits - SECTOR_SHIFT) !=
- (sector_t)num_ll << (v->hash_dev_block_bits - SECTOR_SHIFT)) {
+ (sector_t)(num_ll << (v->hash_dev_block_bits - SECTOR_SHIFT))
+ >> (v->hash_dev_block_bits - SECTOR_SHIFT) != num_ll) {
ti->error = "Invalid hash start";
r = -EINVAL;
goto bad;
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 4e09b6f..67ffa39 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -865,10 +865,14 @@ static void dm_done(struct request *clone, int error, bool mapped)
{
int r = error;
struct dm_rq_target_io *tio = clone->end_io_data;
- dm_request_endio_fn rq_end_io = tio->ti->type->rq_end_io;
+ dm_request_endio_fn rq_end_io = NULL;
- if (mapped && rq_end_io)
- r = rq_end_io(tio->ti, clone, error, &tio->info);
+ if (tio->ti) {
+ rq_end_io = tio->ti->type->rq_end_io;
+
+ if (mapped && rq_end_io)
+ r = rq_end_io(tio->ti, clone, error, &tio->info);
+ }
if (r <= 0)
/* The target wants to complete the I/O */
@@ -1588,15 +1592,6 @@ static int map_request(struct dm_target *ti, struct request *clone,
int r, requeued = 0;
struct dm_rq_target_io *tio = clone->end_io_data;
- /*
- * Hold the md reference here for the in-flight I/O.
- * We can't rely on the reference count by device opener,
- * because the device may be closed during the request completion
- * when all bios are completed.
- * See the comment in rq_completed() too.
- */
- dm_get(md);
-
tio->ti = ti;
r = ti->type->map_rq(ti, clone, &tio->info);
switch (r) {
@@ -1628,6 +1623,26 @@ static int map_request(struct dm_target *ti, struct request *clone,
return requeued;
}
+static struct request *dm_start_request(struct mapped_device *md, struct request *orig)
+{
+ struct request *clone;
+
+ blk_start_request(orig);
+ clone = orig->special;
+ atomic_inc(&md->pending[rq_data_dir(clone)]);
+
+ /*
+ * Hold the md reference here for the in-flight I/O.
+ * We can't rely on the reference count by device opener,
+ * because the device may be closed during the request completion
+ * when all bios are completed.
+ * See the comment in rq_completed() too.
+ */
+ dm_get(md);
+
+ return clone;
+}
+
/*
* q->request_fn for request-based dm.
* Called with the queue lock held.
@@ -1657,14 +1672,21 @@ static void dm_request_fn(struct request_queue *q)
pos = blk_rq_pos(rq);
ti = dm_table_find_target(map, pos);
- BUG_ON(!dm_target_is_valid(ti));
+ if (!dm_target_is_valid(ti)) {
+ /*
+ * Must perform setup, that dm_done() requires,
+ * before calling dm_kill_unmapped_request
+ */
+ DMERR_LIMIT("request attempted access beyond the end of device");
+ clone = dm_start_request(md, rq);
+ dm_kill_unmapped_request(clone, -EIO);
+ continue;
+ }
if (ti->type->busy && ti->type->busy(ti))
goto delay_and_out;
- blk_start_request(rq);
- clone = rq->special;
- atomic_inc(&md->pending[rq_data_dir(clone)]);
+ clone = dm_start_request(md, rq);
spin_unlock(q->queue_lock);
if (map_request(ti, clone, md))
@@ -1684,8 +1706,6 @@ delay_and_out:
blk_delay_queue(q, HZ / 10);
out:
dm_table_put(map);
-
- return;
}
int dm_underlying_device_busy(struct request_queue *q)
@@ -2409,7 +2429,7 @@ static void dm_queue_flush(struct mapped_device *md)
*/
struct dm_table *dm_swap_table(struct mapped_device *md, struct dm_table *table)
{
- struct dm_table *map = ERR_PTR(-EINVAL);
+ struct dm_table *live_map, *map = ERR_PTR(-EINVAL);
struct queue_limits limits;
int r;
@@ -2419,6 +2439,19 @@ struct dm_table *dm_swap_table(struct mapped_device *md, struct dm_table *table)
if (!dm_suspended_md(md))
goto out;
+ /*
+ * If the new table has no data devices, retain the existing limits.
+ * This helps multipath with queue_if_no_path if all paths disappear,
+ * then new I/O is queued based on these limits, and then some paths
+ * reappear.
+ */
+ if (dm_table_has_no_data_devices(table)) {
+ live_map = dm_get_live_table(md);
+ if (live_map)
+ limits = md->queue->limits;
+ dm_table_put(live_map);
+ }
+
r = dm_calculate_queue_limits(table, &limits);
if (r) {
map = ERR_PTR(r);
diff --git a/drivers/md/dm.h b/drivers/md/dm.h
index 52eef49..6a99fef 100644
--- a/drivers/md/dm.h
+++ b/drivers/md/dm.h
@@ -54,6 +54,7 @@ void dm_table_event_callback(struct dm_table *t,
void (*fn)(void *), void *context);
struct dm_target *dm_table_get_target(struct dm_table *t, unsigned int index);
struct dm_target *dm_table_find_target(struct dm_table *t, sector_t sector);
+bool dm_table_has_no_data_devices(struct dm_table *table);
int dm_calculate_queue_limits(struct dm_table *table,
struct queue_limits *limits);
void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 3f6203a..308e87b 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -7619,6 +7619,8 @@ static int remove_and_add_spares(struct mddev *mddev)
}
}
}
+ if (removed)
+ set_bit(MD_CHANGE_DEVS, &mddev->flags);
return spares;
}
@@ -7632,9 +7634,11 @@ static void reap_sync_thread(struct mddev *mddev)
!test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) {
/* success...*/
/* activate any spares */
- if (mddev->pers->spare_active(mddev))
+ if (mddev->pers->spare_active(mddev)) {
sysfs_notify(&mddev->kobj, NULL,
"degraded");
+ set_bit(MD_CHANGE_DEVS, &mddev->flags);
+ }
}
if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) &&
mddev->pers->finish_reshape)
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 1c2eb38..0138a72 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -1512,14 +1512,16 @@ static int _enough(struct r10conf *conf, struct geom *geo, int ignore)
do {
int n = conf->copies;
int cnt = 0;
+ int this = first;
while (n--) {
- if (conf->mirrors[first].rdev &&
- first != ignore)
+ if (conf->mirrors[this].rdev &&
+ this != ignore)
cnt++;
- first = (first+1) % geo->raid_disks;
+ this = (this+1) % geo->raid_disks;
}
if (cnt == 0)
return 0;
+ first = (first + geo->near_copies) % geo->raid_disks;
} while (first != 0);
return 1;
}
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index adda94d..0689173 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -393,6 +393,8 @@ static int calc_degraded(struct r5conf *conf)
degraded = 0;
for (i = 0; i < conf->previous_raid_disks; i++) {
struct md_rdev *rdev = rcu_dereference(conf->disks[i].rdev);
+ if (rdev && test_bit(Faulty, &rdev->flags))
+ rdev = rcu_dereference(conf->disks[i].replacement);
if (!rdev || test_bit(Faulty, &rdev->flags))
degraded++;
else if (test_bit(In_sync, &rdev->flags))
@@ -417,6 +419,8 @@ static int calc_degraded(struct r5conf *conf)
degraded2 = 0;
for (i = 0; i < conf->raid_disks; i++) {
struct md_rdev *rdev = rcu_dereference(conf->disks[i].rdev);
+ if (rdev && test_bit(Faulty, &rdev->flags))
+ rdev = rcu_dereference(conf->disks[i].replacement);
if (!rdev || test_bit(Faulty, &rdev->flags))
degraded2++;
else if (test_bit(In_sync, &rdev->flags))
@@ -1587,6 +1591,7 @@ static int resize_stripes(struct r5conf *conf, int newsize)
#ifdef CONFIG_MULTICORE_RAID456
init_waitqueue_head(&nsh->ops.wait_for_ops);
#endif
+ spin_lock_init(&nsh->stripe_lock);
list_add(&nsh->lru, &newstripes);
}
@@ -4192,7 +4197,7 @@ static void make_request(struct mddev *mddev, struct bio * bi)
finish_wait(&conf->wait_for_overlap, &w);
set_bit(STRIPE_HANDLE, &sh->state);
clear_bit(STRIPE_DELAYED, &sh->state);
- if ((bi->bi_rw & REQ_NOIDLE) &&
+ if ((bi->bi_rw & REQ_SYNC) &&
!test_and_set_bit(STRIPE_PREREAD_ACTIVE, &sh->state))
atomic_inc(&conf->preread_active_stripes);
release_stripe_plug(mddev, sh);
diff --git a/drivers/mfd/88pm800.c b/drivers/mfd/88pm800.c
index b67a301..ce229ea 100644
--- a/drivers/mfd/88pm800.c
+++ b/drivers/mfd/88pm800.c
@@ -470,7 +470,8 @@ static int __devinit device_800_init(struct pm80x_chip *chip,
ret =
mfd_add_devices(chip->dev, 0, &onkey_devs[0],
- ARRAY_SIZE(onkey_devs), &onkey_resources[0], 0);
+ ARRAY_SIZE(onkey_devs), &onkey_resources[0], 0,
+ NULL);
if (ret < 0) {
dev_err(chip->dev, "Failed to add onkey subdev\n");
goto out_dev;
@@ -481,7 +482,7 @@ static int __devinit device_800_init(struct pm80x_chip *chip,
rtc_devs[0].platform_data = pdata->rtc;
rtc_devs[0].pdata_size = sizeof(struct pm80x_rtc_pdata);
ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0],
- ARRAY_SIZE(rtc_devs), NULL, 0);
+ ARRAY_SIZE(rtc_devs), NULL, 0, NULL);
if (ret < 0) {
dev_err(chip->dev, "Failed to add rtc subdev\n");
goto out_dev;
diff --git a/drivers/mfd/88pm805.c b/drivers/mfd/88pm805.c
index 6146583..c20a311 100644
--- a/drivers/mfd/88pm805.c
+++ b/drivers/mfd/88pm805.c
@@ -216,7 +216,8 @@ static int __devinit device_805_init(struct pm80x_chip *chip)
}
ret = mfd_add_devices(chip->dev, 0, &codec_devs[0],
- ARRAY_SIZE(codec_devs), &codec_resources[0], 0);
+ ARRAY_SIZE(codec_devs), &codec_resources[0], 0,
+ NULL);
if (ret < 0) {
dev_err(chip->dev, "Failed to add codec subdev\n");
goto out_codec;
diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c
index d09918c..b73f033 100644
--- a/drivers/mfd/88pm860x-core.c
+++ b/drivers/mfd/88pm860x-core.c
@@ -637,7 +637,7 @@ static void __devinit device_bk_init(struct pm860x_chip *chip,
bk_devs[i].resources = &bk_resources[j];
ret = mfd_add_devices(chip->dev, 0,
&bk_devs[i], 1,
- &bk_resources[j], 0);
+ &bk_resources[j], 0, NULL);
if (ret < 0) {
dev_err(chip->dev, "Failed to add "
"backlight subdev\n");
@@ -672,7 +672,7 @@ static void __devinit device_led_init(struct pm860x_chip *chip,
led_devs[i].resources = &led_resources[j],
ret = mfd_add_devices(chip->dev, 0,
&led_devs[i], 1,
- &led_resources[j], 0);
+ &led_resources[j], 0, NULL);
if (ret < 0) {
dev_err(chip->dev, "Failed to add "
"led subdev\n");
@@ -709,7 +709,7 @@ static void __devinit device_regulator_init(struct pm860x_chip *chip,
regulator_devs[i].resources = &regulator_resources[seq];
ret = mfd_add_devices(chip->dev, 0, &regulator_devs[i], 1,
- &regulator_resources[seq], 0);
+ &regulator_resources[seq], 0, NULL);
if (ret < 0) {
dev_err(chip->dev, "Failed to add regulator subdev\n");
goto out;
@@ -733,7 +733,7 @@ static void __devinit device_rtc_init(struct pm860x_chip *chip,
rtc_devs[0].resources = &rtc_resources[0];
ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0],
ARRAY_SIZE(rtc_devs), &rtc_resources[0],
- chip->irq_base);
+ chip->irq_base, NULL);
if (ret < 0)
dev_err(chip->dev, "Failed to add rtc subdev\n");
}
@@ -752,7 +752,7 @@ static void __devinit device_touch_init(struct pm860x_chip *chip,
touch_devs[0].resources = &touch_resources[0];
ret = mfd_add_devices(chip->dev, 0, &touch_devs[0],
ARRAY_SIZE(touch_devs), &touch_resources[0],
- chip->irq_base);
+ chip->irq_base, NULL);
if (ret < 0)
dev_err(chip->dev, "Failed to add touch subdev\n");
}
@@ -770,7 +770,7 @@ static void __devinit device_power_init(struct pm860x_chip *chip,
power_devs[0].num_resources = ARRAY_SIZE(battery_resources);
power_devs[0].resources = &battery_resources[0],
ret = mfd_add_devices(chip->dev, 0, &power_devs[0], 1,
- &battery_resources[0], chip->irq_base);
+ &battery_resources[0], chip->irq_base, NULL);
if (ret < 0)
dev_err(chip->dev, "Failed to add battery subdev\n");
@@ -779,7 +779,7 @@ static void __devinit device_power_init(struct pm860x_chip *chip,
power_devs[1].num_resources = ARRAY_SIZE(charger_resources);
power_devs[1].resources = &charger_resources[0],
ret = mfd_add_devices(chip->dev, 0, &power_devs[1], 1,
- &charger_resources[0], chip->irq_base);
+ &charger_resources[0], chip->irq_base, NULL);
if (ret < 0)
dev_err(chip->dev, "Failed to add charger subdev\n");
@@ -788,7 +788,7 @@ static void __devinit device_power_init(struct pm860x_chip *chip,
power_devs[2].num_resources = ARRAY_SIZE(preg_resources);
power_devs[2].resources = &preg_resources[0],
ret = mfd_add_devices(chip->dev, 0, &power_devs[2], 1,
- &preg_resources[0], chip->irq_base);
+ &preg_resources[0], chip->irq_base, NULL);
if (ret < 0)
dev_err(chip->dev, "Failed to add preg subdev\n");
}
@@ -802,7 +802,7 @@ static void __devinit device_onkey_init(struct pm860x_chip *chip,
onkey_devs[0].resources = &onkey_resources[0],
ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0],
ARRAY_SIZE(onkey_devs), &onkey_resources[0],
- chip->irq_base);
+ chip->irq_base, NULL);
if (ret < 0)
dev_err(chip->dev, "Failed to add onkey subdev\n");
}
@@ -815,7 +815,8 @@ static void __devinit device_codec_init(struct pm860x_chip *chip,
codec_devs[0].num_resources = ARRAY_SIZE(codec_resources);
codec_devs[0].resources = &codec_resources[0],
ret = mfd_add_devices(chip->dev, 0, &codec_devs[0],
- ARRAY_SIZE(codec_devs), &codec_resources[0], 0);
+ ARRAY_SIZE(codec_devs), &codec_resources[0], 0,
+ NULL);
if (ret < 0)
dev_err(chip->dev, "Failed to add codec subdev\n");
}
diff --git a/drivers/mfd/aat2870-core.c b/drivers/mfd/aat2870-core.c
index 44a3fdb..f1beb49 100644
--- a/drivers/mfd/aat2870-core.c
+++ b/drivers/mfd/aat2870-core.c
@@ -424,7 +424,7 @@ static int aat2870_i2c_probe(struct i2c_client *client,
}
ret = mfd_add_devices(aat2870->dev, 0, aat2870_devs,
- ARRAY_SIZE(aat2870_devs), NULL, 0);
+ ARRAY_SIZE(aat2870_devs), NULL, 0, NULL);
if (ret != 0) {
dev_err(aat2870->dev, "Failed to add subdev: %d\n", ret);
goto out_disable;
diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c
index 78fca29..01781ae 100644
--- a/drivers/mfd/ab3100-core.c
+++ b/drivers/mfd/ab3100-core.c
@@ -946,7 +946,7 @@ static int __devinit ab3100_probe(struct i2c_client *client,
}
err = mfd_add_devices(&client->dev, 0, ab3100_devs,
- ARRAY_SIZE(ab3100_devs), NULL, 0);
+ ARRAY_SIZE(ab3100_devs), NULL, 0, NULL);
ab3100_setup_debugfs(ab3100);
diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c
index 626b4ec..47adf80 100644
--- a/drivers/mfd/ab8500-core.c
+++ b/drivers/mfd/ab8500-core.c
@@ -1418,25 +1418,25 @@ static int __devinit ab8500_probe(struct platform_device *pdev)
ret = mfd_add_devices(ab8500->dev, 0, abx500_common_devs,
ARRAY_SIZE(abx500_common_devs), NULL,
- ab8500->irq_base);
+ ab8500->irq_base, ab8500->domain);
if (ret)
goto out_freeirq;
if (is_ab9540(ab8500))
ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs,
ARRAY_SIZE(ab9540_devs), NULL,
- ab8500->irq_base);
+ ab8500->irq_base, ab8500->domain);
else
ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs,
ARRAY_SIZE(ab8500_devs), NULL,
- ab8500->irq_base);
+ ab8500->irq_base, ab8500->domain);
if (ret)
goto out_freeirq;
if (is_ab9540(ab8500) || is_ab8505(ab8500))
ret = mfd_add_devices(ab8500->dev, 0, ab9540_ab8505_devs,
ARRAY_SIZE(ab9540_ab8505_devs), NULL,
- ab8500->irq_base);
+ ab8500->irq_base, ab8500->domain);
if (ret)
goto out_freeirq;
@@ -1444,7 +1444,7 @@ static int __devinit ab8500_probe(struct platform_device *pdev)
/* Add battery management devices */
ret = mfd_add_devices(ab8500->dev, 0, ab8500_bm_devs,
ARRAY_SIZE(ab8500_bm_devs), NULL,
- ab8500->irq_base);
+ ab8500->irq_base, ab8500->domain);
if (ret)
dev_err(ab8500->dev, "error adding bm devices\n");
}
diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c
index c7983e8..1b48f20 100644
--- a/drivers/mfd/arizona-core.c
+++ b/drivers/mfd/arizona-core.c
@@ -316,7 +316,7 @@ int __devinit arizona_dev_init(struct arizona *arizona)
}
ret = mfd_add_devices(arizona->dev, -1, early_devs,
- ARRAY_SIZE(early_devs), NULL, 0);
+ ARRAY_SIZE(early_devs), NULL, 0, NULL);
if (ret != 0) {
dev_err(dev, "Failed to add early children: %d\n", ret);
return ret;
@@ -516,11 +516,11 @@ int __devinit arizona_dev_init(struct arizona *arizona)
switch (arizona->type) {
case WM5102:
ret = mfd_add_devices(arizona->dev, -1, wm5102_devs,
- ARRAY_SIZE(wm5102_devs), NULL, 0);
+ ARRAY_SIZE(wm5102_devs), NULL, 0, NULL);
break;
case WM5110:
ret = mfd_add_devices(arizona->dev, -1, wm5110_devs,
- ARRAY_SIZE(wm5102_devs), NULL, 0);
+ ARRAY_SIZE(wm5102_devs), NULL, 0, NULL);
break;
}
diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c
index 683e18a..62f0883 100644
--- a/drivers/mfd/asic3.c
+++ b/drivers/mfd/asic3.c
@@ -913,14 +913,14 @@ static int __init asic3_mfd_probe(struct platform_device *pdev,
if (pdata->clock_rate) {
ds1wm_pdata.clock_rate = pdata->clock_rate;
ret = mfd_add_devices(&pdev->dev, pdev->id,
- &asic3_cell_ds1wm, 1, mem, asic->irq_base);
+ &asic3_cell_ds1wm, 1, mem, asic->irq_base, NULL);
if (ret < 0)
goto out;
}
if (mem_sdio && (irq >= 0)) {
ret = mfd_add_devices(&pdev->dev, pdev->id,
- &asic3_cell_mmc, 1, mem_sdio, irq);
+ &asic3_cell_mmc, 1, mem_sdio, irq, NULL);
if (ret < 0)
goto out;
}
@@ -934,7 +934,7 @@ static int __init asic3_mfd_probe(struct platform_device *pdev,
asic3_cell_leds[i].pdata_size = sizeof(pdata->leds[i]);
}
ret = mfd_add_devices(&pdev->dev, 0,
- asic3_cell_leds, ASIC3_NUM_LEDS, NULL, 0);
+ asic3_cell_leds, ASIC3_NUM_LEDS, NULL, 0, NULL);
}
out:
diff --git a/drivers/mfd/cs5535-mfd.c b/drivers/mfd/cs5535-mfd.c
index 3419e72..2b28213 100644
--- a/drivers/mfd/cs5535-mfd.c
+++ b/drivers/mfd/cs5535-mfd.c
@@ -149,7 +149,7 @@ static int __devinit cs5535_mfd_probe(struct pci_dev *pdev,
}
err = mfd_add_devices(&pdev->dev, -1, cs5535_mfd_cells,
- ARRAY_SIZE(cs5535_mfd_cells), NULL, 0);
+ ARRAY_SIZE(cs5535_mfd_cells), NULL, 0, NULL);
if (err) {
dev_err(&pdev->dev, "MFD add devices failed: %d\n", err);
goto err_disable;
diff --git a/drivers/mfd/da9052-core.c b/drivers/mfd/da9052-core.c
index 2544910..a0a62b2 100644
--- a/drivers/mfd/da9052-core.c
+++ b/drivers/mfd/da9052-core.c
@@ -803,7 +803,7 @@ int __devinit da9052_device_init(struct da9052 *da9052, u8 chip_id)
dev_err(da9052->dev, "DA9052 ADC IRQ failed ret=%d\n", ret);
ret = mfd_add_devices(da9052->dev, -1, da9052_subdev_info,
- ARRAY_SIZE(da9052_subdev_info), NULL, 0);
+ ARRAY_SIZE(da9052_subdev_info), NULL, 0, NULL);
if (ret)
goto err;
diff --git a/drivers/mfd/davinci_voicecodec.c b/drivers/mfd/davinci_voicecodec.c
index 4e2af2c..45e83a6 100644
--- a/drivers/mfd/davinci_voicecodec.c
+++ b/drivers/mfd/davinci_voicecodec.c
@@ -129,7 +129,7 @@ static int __init davinci_vc_probe(struct platform_device *pdev)
cell->pdata_size = sizeof(*davinci_vc);
ret = mfd_add_devices(&pdev->dev, pdev->id, davinci_vc->cells,
- DAVINCI_VC_CELLS, NULL, 0);
+ DAVINCI_VC_CELLS, NULL, 0, NULL);
if (ret != 0) {
dev_err(&pdev->dev, "fail to register client devices\n");
goto fail4;
diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c
index 7040a00..0e63cdd 100644
--- a/drivers/mfd/db8500-prcmu.c
+++ b/drivers/mfd/db8500-prcmu.c
@@ -3010,7 +3010,7 @@ static int __devinit db8500_prcmu_probe(struct platform_device *pdev)
prcmu_config_esram0_deep_sleep(ESRAM0_DEEP_SLEEP_STATE_RET);
err = mfd_add_devices(&pdev->dev, 0, db8500_prcmu_devs,
- ARRAY_SIZE(db8500_prcmu_devs), NULL, 0);
+ ARRAY_SIZE(db8500_prcmu_devs), NULL, 0, NULL);
if (err) {
pr_err("prcmu: Failed to add subdevices\n");
return err;
diff --git a/drivers/mfd/htc-pasic3.c b/drivers/mfd/htc-pasic3.c
index 04c7093..9e5453d 100644
--- a/drivers/mfd/htc-pasic3.c
+++ b/drivers/mfd/htc-pasic3.c
@@ -168,7 +168,7 @@ static int __init pasic3_probe(struct platform_device *pdev)
/* the first 5 PASIC3 registers control the DS1WM */
ds1wm_resources[0].end = (5 << asic->bus_shift) - 1;
ret = mfd_add_devices(&pdev->dev, pdev->id,
- &ds1wm_cell, 1, r, irq);
+ &ds1wm_cell, 1, r, irq, NULL);
if (ret < 0)
dev_warn(dev, "failed to register DS1WM\n");
}
@@ -176,7 +176,8 @@ static int __init pasic3_probe(struct platform_device *pdev)
if (pdata && pdata->led_pdata) {
led_cell.platform_data = pdata->led_pdata;
led_cell.pdata_size = sizeof(struct pasic3_leds_machinfo);
- ret = mfd_add_devices(&pdev->dev, pdev->id, &led_cell, 1, r, 0);
+ ret = mfd_add_devices(&pdev->dev, pdev->id, &led_cell, 1, r,
+ 0, NULL);
if (ret < 0)
dev_warn(dev, "failed to register LED device\n");
}
diff --git a/drivers/mfd/intel_msic.c b/drivers/mfd/intel_msic.c
index 59df558..266bdc5b 100644
--- a/drivers/mfd/intel_msic.c
+++ b/drivers/mfd/intel_msic.c
@@ -344,13 +344,13 @@ static int __devinit intel_msic_init_devices(struct intel_msic *msic)
continue;
ret = mfd_add_devices(&pdev->dev, -1, &msic_devs[i], 1, NULL,
- pdata->irq[i]);
+ pdata->irq[i], NULL);
if (ret)
goto fail;
}
ret = mfd_add_devices(&pdev->dev, 0, msic_other_devs,
- ARRAY_SIZE(msic_other_devs), NULL, 0);
+ ARRAY_SIZE(msic_other_devs), NULL, 0, NULL);
if (ret)
goto fail;
diff --git a/drivers/mfd/janz-cmodio.c b/drivers/mfd/janz-cmodio.c
index 2ea9998..965c480 100644
--- a/drivers/mfd/janz-cmodio.c
+++ b/drivers/mfd/janz-cmodio.c
@@ -147,7 +147,7 @@ static int __devinit cmodio_probe_submodules(struct cmodio_device *priv)
}
return mfd_add_devices(&pdev->dev, 0, priv->cells,
- num_probed, NULL, pdev->irq);
+ num_probed, NULL, pdev->irq, NULL);
}
/*
diff --git a/drivers/mfd/jz4740-adc.c b/drivers/mfd/jz4740-adc.c
index 87662a1..c6b6d7d 100644
--- a/drivers/mfd/jz4740-adc.c
+++ b/drivers/mfd/jz4740-adc.c
@@ -287,7 +287,8 @@ static int __devinit jz4740_adc_probe(struct platform_device *pdev)
writeb(0xff, adc->base + JZ_REG_ADC_CTRL);
ret = mfd_add_devices(&pdev->dev, 0, jz4740_adc_cells,
- ARRAY_SIZE(jz4740_adc_cells), mem_base, irq_base);
+ ARRAY_SIZE(jz4740_adc_cells), mem_base,
+ irq_base, NULL);
if (ret < 0)
goto err_clk_put;
diff --git a/drivers/mfd/lm3533-core.c b/drivers/mfd/lm3533-core.c
index 0b2879b..24212f4 100644
--- a/drivers/mfd/lm3533-core.c
+++ b/drivers/mfd/lm3533-core.c
@@ -393,7 +393,8 @@ static int __devinit lm3533_device_als_init(struct lm3533 *lm3533)
lm3533_als_devs[0].platform_data = pdata->als;
lm3533_als_devs[0].pdata_size = sizeof(*pdata->als);
- ret = mfd_add_devices(lm3533->dev, 0, lm3533_als_devs, 1, NULL, 0);
+ ret = mfd_add_devices(lm3533->dev, 0, lm3533_als_devs, 1, NULL,
+ 0, NULL);
if (ret) {
dev_err(lm3533->dev, "failed to add ALS device\n");
return ret;
@@ -422,7 +423,7 @@ static int __devinit lm3533_device_bl_init(struct lm3533 *lm3533)
}
ret = mfd_add_devices(lm3533->dev, 0, lm3533_bl_devs,
- pdata->num_backlights, NULL, 0);
+ pdata->num_backlights, NULL, 0, NULL);
if (ret) {
dev_err(lm3533->dev, "failed to add backlight devices\n");
return ret;
@@ -451,7 +452,7 @@ static int __devinit lm3533_device_led_init(struct lm3533 *lm3533)
}
ret = mfd_add_devices(lm3533->dev, 0, lm3533_led_devs,
- pdata->num_leds, NULL, 0);
+ pdata->num_leds, NULL, 0, NULL);
if (ret) {
dev_err(lm3533->dev, "failed to add LED devices\n");
return ret;
diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c
index 027cc8f..092ad4b 100644
--- a/drivers/mfd/lpc_ich.c
+++ b/drivers/mfd/lpc_ich.c
@@ -750,7 +750,7 @@ gpe0_done:
lpc_ich_finalize_cell(&lpc_ich_cells[LPC_GPIO], id);
ret = mfd_add_devices(&dev->dev, -1, &lpc_ich_cells[LPC_GPIO],
- 1, NULL, 0);
+ 1, NULL, 0, NULL);
gpio_done:
if (acpi_conflict)
@@ -765,7 +765,6 @@ static int __devinit lpc_ich_init_wdt(struct pci_dev *dev,
u32 base_addr_cfg;
u32 base_addr;
int ret;
- bool acpi_conflict = false;
struct resource *res;
/* Setup power management base register */
@@ -780,20 +779,11 @@ static int __devinit lpc_ich_init_wdt(struct pci_dev *dev,
res = wdt_io_res(ICH_RES_IO_TCO);
res->start = base_addr + ACPIBASE_TCO_OFF;
res->end = base_addr + ACPIBASE_TCO_END;
- ret = acpi_check_resource_conflict(res);
- if (ret) {
- acpi_conflict = true;
- goto wdt_done;
- }
res = wdt_io_res(ICH_RES_IO_SMI);
res->start = base_addr + ACPIBASE_SMI_OFF;
res->end = base_addr + ACPIBASE_SMI_END;
- ret = acpi_check_resource_conflict(res);
- if (ret) {
- acpi_conflict = true;
- goto wdt_done;
- }
+
lpc_ich_enable_acpi_space(dev);
/*
@@ -813,21 +803,13 @@ static int __devinit lpc_ich_init_wdt(struct pci_dev *dev,
res = wdt_mem_res(ICH_RES_MEM_GCS);
res->start = base_addr + ACPIBASE_GCS_OFF;
res->end = base_addr + ACPIBASE_GCS_END;
- ret = acpi_check_resource_conflict(res);
- if (ret) {
- acpi_conflict = true;
- goto wdt_done;
- }
}
lpc_ich_finalize_cell(&lpc_ich_cells[LPC_WDT], id);
ret = mfd_add_devices(&dev->dev, -1, &lpc_ich_cells[LPC_WDT],
- 1, NULL, 0);
+ 1, NULL, 0, NULL);
wdt_done:
- if (acpi_conflict)
- pr_warn("Resource conflict(s) found affecting %s\n",
- lpc_ich_cells[LPC_WDT].name);
return ret;
}
diff --git a/drivers/mfd/lpc_sch.c b/drivers/mfd/lpc_sch.c
index 9f20abc..f6b9c5c 100644
--- a/drivers/mfd/lpc_sch.c
+++ b/drivers/mfd/lpc_sch.c
@@ -127,7 +127,8 @@ static int __devinit lpc_sch_probe(struct pci_dev *dev,
lpc_sch_cells[i].id = id->device;
ret = mfd_add_devices(&dev->dev, 0,
- lpc_sch_cells, ARRAY_SIZE(lpc_sch_cells), NULL, 0);
+ lpc_sch_cells, ARRAY_SIZE(lpc_sch_cells), NULL,
+ 0, NULL);
if (ret)
goto out_dev;
@@ -153,7 +154,8 @@ static int __devinit lpc_sch_probe(struct pci_dev *dev,
tunnelcreek_cells[i].id = id->device;
ret = mfd_add_devices(&dev->dev, 0, tunnelcreek_cells,
- ARRAY_SIZE(tunnelcreek_cells), NULL, 0);
+ ARRAY_SIZE(tunnelcreek_cells), NULL,
+ 0, NULL);
}
return ret;
diff --git a/drivers/mfd/max77686.c b/drivers/mfd/max77686.c
index c03e12b..d9e24c8 100644
--- a/drivers/mfd/max77686.c
+++ b/drivers/mfd/max77686.c
@@ -126,7 +126,7 @@ static int max77686_i2c_probe(struct i2c_client *i2c,
max77686_irq_init(max77686);
ret = mfd_add_devices(max77686->dev, -1, max77686_devs,
- ARRAY_SIZE(max77686_devs), NULL, 0);
+ ARRAY_SIZE(max77686_devs), NULL, 0, NULL);
if (ret < 0)
goto err_mfd;
diff --git a/drivers/mfd/max77693-irq.c b/drivers/mfd/max77693-irq.c
index 2b40356..1029d01 100644
--- a/drivers/mfd/max77693-irq.c
+++ b/drivers/mfd/max77693-irq.c
@@ -137,6 +137,9 @@ static void max77693_irq_mask(struct irq_data *data)
const struct max77693_irq_data *irq_data =
irq_to_max77693_irq(max77693, data->irq);
+ if (irq_data->group >= MAX77693_IRQ_GROUP_NR)
+ return;
+
if (irq_data->group >= MUIC_INT1 && irq_data->group <= MUIC_INT3)
max77693->irq_masks_cur[irq_data->group] &= ~irq_data->mask;
else
@@ -149,6 +152,9 @@ static void max77693_irq_unmask(struct irq_data *data)
const struct max77693_irq_data *irq_data =
irq_to_max77693_irq(max77693, data->irq);
+ if (irq_data->group >= MAX77693_IRQ_GROUP_NR)
+ return;
+
if (irq_data->group >= MUIC_INT1 && irq_data->group <= MUIC_INT3)
max77693->irq_masks_cur[irq_data->group] |= irq_data->mask;
else
@@ -200,7 +206,7 @@ static irqreturn_t max77693_irq_thread(int irq, void *data)
if (irq_src & MAX77693_IRQSRC_MUIC)
/* MUIC INT1 ~ INT3 */
- max77693_bulk_read(max77693->regmap, MAX77693_MUIC_REG_INT1,
+ max77693_bulk_read(max77693->regmap_muic, MAX77693_MUIC_REG_INT1,
MAX77693_NUM_IRQ_MUIC_REGS, &irq_reg[MUIC_INT1]);
/* Apply masking */
@@ -255,7 +261,8 @@ int max77693_irq_init(struct max77693_dev *max77693)
{
struct irq_domain *domain;
int i;
- int ret;
+ int ret = 0;
+ u8 intsrc_mask;
mutex_init(&max77693->irqlock);
@@ -287,19 +294,38 @@ int max77693_irq_init(struct max77693_dev *max77693)
&max77693_irq_domain_ops, max77693);
if (!domain) {
dev_err(max77693->dev, "could not create irq domain\n");
- return -ENODEV;
+ ret = -ENODEV;
+ goto err_irq;
}
max77693->irq_domain = domain;
+ /* Unmask max77693 interrupt */
+ ret = max77693_read_reg(max77693->regmap,
+ MAX77693_PMIC_REG_INTSRC_MASK, &intsrc_mask);
+ if (ret < 0) {
+ dev_err(max77693->dev, "fail to read PMIC register\n");
+ goto err_irq;
+ }
+
+ intsrc_mask &= ~(MAX77693_IRQSRC_CHG);
+ intsrc_mask &= ~(MAX77693_IRQSRC_FLASH);
+ intsrc_mask &= ~(MAX77693_IRQSRC_MUIC);
+ ret = max77693_write_reg(max77693->regmap,
+ MAX77693_PMIC_REG_INTSRC_MASK, intsrc_mask);
+ if (ret < 0) {
+ dev_err(max77693->dev, "fail to write PMIC register\n");
+ goto err_irq;
+ }
+
ret = request_threaded_irq(max77693->irq, NULL, max77693_irq_thread,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
"max77693-irq", max77693);
-
if (ret)
dev_err(max77693->dev, "Failed to request IRQ %d: %d\n",
max77693->irq, ret);
- return 0;
+err_irq:
+ return ret;
}
void max77693_irq_exit(struct max77693_dev *max77693)
diff --git a/drivers/mfd/max77693.c b/drivers/mfd/max77693.c
index a1811cb..cc5155e 100644
--- a/drivers/mfd/max77693.c
+++ b/drivers/mfd/max77693.c
@@ -152,6 +152,20 @@ static int max77693_i2c_probe(struct i2c_client *i2c,
max77693->haptic = i2c_new_dummy(i2c->adapter, I2C_ADDR_HAPTIC);
i2c_set_clientdata(max77693->haptic, max77693);
+ /*
+ * Initialize register map for MUIC device because use regmap-muic
+ * instance of MUIC device when irq of max77693 is initialized
+ * before call max77693-muic probe() function.
+ */
+ max77693->regmap_muic = devm_regmap_init_i2c(max77693->muic,
+ &max77693_regmap_config);
+ if (IS_ERR(max77693->regmap_muic)) {
+ ret = PTR_ERR(max77693->regmap_muic);
+ dev_err(max77693->dev,
+ "failed to allocate register map: %d\n", ret);
+ goto err_regmap;
+ }
+
ret = max77693_irq_init(max77693);
if (ret < 0)
goto err_irq;
@@ -159,7 +173,7 @@ static int max77693_i2c_probe(struct i2c_client *i2c,
pm_runtime_set_active(max77693->dev);
ret = mfd_add_devices(max77693->dev, -1, max77693_devs,
- ARRAY_SIZE(max77693_devs), NULL, 0);
+ ARRAY_SIZE(max77693_devs), NULL, 0, NULL);
if (ret < 0)
goto err_mfd;
diff --git a/drivers/mfd/max8925-core.c b/drivers/mfd/max8925-core.c
index 825a7f0..ee53757 100644
--- a/drivers/mfd/max8925-core.c
+++ b/drivers/mfd/max8925-core.c
@@ -598,7 +598,7 @@ int __devinit max8925_device_init(struct max8925_chip *chip,
ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0],
ARRAY_SIZE(rtc_devs),
- &rtc_resources[0], chip->irq_base);
+ &rtc_resources[0], chip->irq_base, NULL);
if (ret < 0) {
dev_err(chip->dev, "Failed to add rtc subdev\n");
goto out;
@@ -606,7 +606,7 @@ int __devinit max8925_device_init(struct max8925_chip *chip,
ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0],
ARRAY_SIZE(onkey_devs),
- &onkey_resources[0], 0);
+ &onkey_resources[0], 0, NULL);
if (ret < 0) {
dev_err(chip->dev, "Failed to add onkey subdev\n");
goto out_dev;
@@ -615,7 +615,7 @@ int __devinit max8925_device_init(struct max8925_chip *chip,
if (pdata) {
ret = mfd_add_devices(chip->dev, 0, &regulator_devs[0],
ARRAY_SIZE(regulator_devs),
- &regulator_resources[0], 0);
+ &regulator_resources[0], 0, NULL);
if (ret < 0) {
dev_err(chip->dev, "Failed to add regulator subdev\n");
goto out_dev;
@@ -625,7 +625,7 @@ int __devinit max8925_device_init(struct max8925_chip *chip,
if (pdata && pdata->backlight) {
ret = mfd_add_devices(chip->dev, 0, &backlight_devs[0],
ARRAY_SIZE(backlight_devs),
- &backlight_resources[0], 0);
+ &backlight_resources[0], 0, NULL);
if (ret < 0) {
dev_err(chip->dev, "Failed to add backlight subdev\n");
goto out_dev;
@@ -635,7 +635,7 @@ int __devinit max8925_device_init(struct max8925_chip *chip,
if (pdata && pdata->power) {
ret = mfd_add_devices(chip->dev, 0, &power_devs[0],
ARRAY_SIZE(power_devs),
- &power_supply_resources[0], 0);
+ &power_supply_resources[0], 0, NULL);
if (ret < 0) {
dev_err(chip->dev, "Failed to add power supply "
"subdev\n");
@@ -646,7 +646,7 @@ int __devinit max8925_device_init(struct max8925_chip *chip,
if (pdata && pdata->touch) {
ret = mfd_add_devices(chip->dev, 0, &touch_devs[0],
ARRAY_SIZE(touch_devs),
- &touch_resources[0], 0);
+ &touch_resources[0], 0, NULL);
if (ret < 0) {
dev_err(chip->dev, "Failed to add touch subdev\n");
goto out_dev;
diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c
index 10b629c..f1235170 100644
--- a/drivers/mfd/max8997.c
+++ b/drivers/mfd/max8997.c
@@ -160,7 +160,7 @@ static int max8997_i2c_probe(struct i2c_client *i2c,
mfd_add_devices(max8997->dev, -1, max8997_devs,
ARRAY_SIZE(max8997_devs),
- NULL, 0);
+ NULL, 0, NULL);
/*
* TODO: enable others (flash, muic, rtc, battery, ...) and
diff --git a/drivers/mfd/max8998.c b/drivers/mfd/max8998.c
index 6ef56d2..d7218cc 100644
--- a/drivers/mfd/max8998.c
+++ b/drivers/mfd/max8998.c
@@ -161,13 +161,13 @@ static int max8998_i2c_probe(struct i2c_client *i2c,
switch (id->driver_data) {
case TYPE_LP3974:
ret = mfd_add_devices(max8998->dev, -1,
- lp3974_devs, ARRAY_SIZE(lp3974_devs),
- NULL, 0);
+ lp3974_devs, ARRAY_SIZE(lp3974_devs),
+ NULL, 0, NULL);
break;
case TYPE_MAX8998:
ret = mfd_add_devices(max8998->dev, -1,
- max8998_devs, ARRAY_SIZE(max8998_devs),
- NULL, 0);
+ max8998_devs, ARRAY_SIZE(max8998_devs),
+ NULL, 0, NULL);
break;
default:
ret = -EINVAL;
diff --git a/drivers/mfd/mc13xxx-core.c b/drivers/mfd/mc13xxx-core.c
index b801dc7..1ec79b5 100644
--- a/drivers/mfd/mc13xxx-core.c
+++ b/drivers/mfd/mc13xxx-core.c
@@ -612,7 +612,7 @@ static int mc13xxx_add_subdevice_pdata(struct mc13xxx *mc13xxx,
if (!cell.name)
return -ENOMEM;
- return mfd_add_devices(mc13xxx->dev, -1, &cell, 1, NULL, 0);
+ return mfd_add_devices(mc13xxx->dev, -1, &cell, 1, NULL, 0, NULL);
}
static int mc13xxx_add_subdevice(struct mc13xxx *mc13xxx, const char *format)
diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
index 0c3a01c..f8b7771 100644
--- a/drivers/mfd/mfd-core.c
+++ b/drivers/mfd/mfd-core.c
@@ -74,12 +74,11 @@ static int mfd_platform_add_cell(struct platform_device *pdev,
static int mfd_add_device(struct device *parent, int id,
const struct mfd_cell *cell,
struct resource *mem_base,
- int irq_base)
+ int irq_base, struct irq_domain *domain)
{
struct resource *res;
struct platform_device *pdev;
struct device_node *np = NULL;
- struct irq_domain *domain = NULL;
int ret = -ENOMEM;
int r;
@@ -97,7 +96,6 @@ static int mfd_add_device(struct device *parent, int id,
for_each_child_of_node(parent->of_node, np) {
if (of_device_is_compatible(np, cell->of_compatible)) {
pdev->dev.of_node = np;
- domain = irq_find_host(parent->of_node);
break;
}
}
@@ -177,7 +175,7 @@ fail_alloc:
int mfd_add_devices(struct device *parent, int id,
struct mfd_cell *cells, int n_devs,
struct resource *mem_base,
- int irq_base)
+ int irq_base, struct irq_domain *domain)
{
int i;
int ret = 0;
@@ -191,7 +189,8 @@ int mfd_add_devices(struct device *parent, int id,
for (i = 0; i < n_devs; i++) {
atomic_set(&cnts[i], 0);
cells[i].usage_count = &cnts[i];
- ret = mfd_add_device(parent, id, cells + i, mem_base, irq_base);
+ ret = mfd_add_device(parent, id, cells + i, mem_base,
+ irq_base, domain);
if (ret)
break;
}
@@ -247,7 +246,8 @@ int mfd_clone_cell(const char *cell, const char **clones, size_t n_clones)
for (i = 0; i < n_clones; i++) {
cell_entry.name = clones[i];
/* don't give up if a single call fails; just report error */
- if (mfd_add_device(pdev->dev.parent, -1, &cell_entry, NULL, 0))
+ if (mfd_add_device(pdev->dev.parent, -1, &cell_entry, NULL, 0,
+ NULL))
dev_err(dev, "failed to create platform device '%s'\n",
clones[i]);
}
diff --git a/drivers/mfd/palmas.c b/drivers/mfd/palmas.c
index c4a69f1..a345f9bb 100644
--- a/drivers/mfd/palmas.c
+++ b/drivers/mfd/palmas.c
@@ -453,7 +453,8 @@ static int __devinit palmas_i2c_probe(struct i2c_client *i2c,
ret = mfd_add_devices(palmas->dev, -1,
children, ARRAY_SIZE(palmas_children),
- NULL, regmap_irq_chip_get_base(palmas->irq_data));
+ NULL, regmap_irq_chip_get_base(palmas->irq_data),
+ NULL);
kfree(children);
if (ret < 0)
diff --git a/drivers/mfd/rc5t583.c b/drivers/mfd/rc5t583.c
index cdc1df7..3a8fa88 100644
--- a/drivers/mfd/rc5t583.c
+++ b/drivers/mfd/rc5t583.c
@@ -289,7 +289,7 @@ static int __devinit rc5t583_i2c_probe(struct i2c_client *i2c,
}
ret = mfd_add_devices(rc5t583->dev, -1, rc5t583_subdevs,
- ARRAY_SIZE(rc5t583_subdevs), NULL, 0);
+ ARRAY_SIZE(rc5t583_subdevs), NULL, 0, NULL);
if (ret) {
dev_err(&i2c->dev, "add mfd devices failed: %d\n", ret);
goto err_add_devs;
diff --git a/drivers/mfd/rdc321x-southbridge.c b/drivers/mfd/rdc321x-southbridge.c
index 685d61e..0f70dce 100644
--- a/drivers/mfd/rdc321x-southbridge.c
+++ b/drivers/mfd/rdc321x-southbridge.c
@@ -87,7 +87,8 @@ static int __devinit rdc321x_sb_probe(struct pci_dev *pdev,
rdc321x_wdt_pdata.sb_pdev = pdev;
return mfd_add_devices(&pdev->dev, -1,
- rdc321x_sb_cells, ARRAY_SIZE(rdc321x_sb_cells), NULL, 0);
+ rdc321x_sb_cells, ARRAY_SIZE(rdc321x_sb_cells),
+ NULL, 0, NULL);
}
static void __devexit rdc321x_sb_remove(struct pci_dev *pdev)
diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c
index 2988efd..49d361a 100644
--- a/drivers/mfd/sec-core.c
+++ b/drivers/mfd/sec-core.c
@@ -141,19 +141,19 @@ static int sec_pmic_probe(struct i2c_client *i2c,
switch (sec_pmic->device_type) {
case S5M8751X:
ret = mfd_add_devices(sec_pmic->dev, -1, s5m8751_devs,
- ARRAY_SIZE(s5m8751_devs), NULL, 0);
+ ARRAY_SIZE(s5m8751_devs), NULL, 0, NULL);
break;
case S5M8763X:
ret = mfd_add_devices(sec_pmic->dev, -1, s5m8763_devs,
- ARRAY_SIZE(s5m8763_devs), NULL, 0);
+ ARRAY_SIZE(s5m8763_devs), NULL, 0, NULL);
break;
case S5M8767X:
ret = mfd_add_devices(sec_pmic->dev, -1, s5m8767_devs,
- ARRAY_SIZE(s5m8767_devs), NULL, 0);
+ ARRAY_SIZE(s5m8767_devs), NULL, 0, NULL);
break;
case S2MPS11X:
ret = mfd_add_devices(sec_pmic->dev, -1, s2mps11_devs,
- ARRAY_SIZE(s2mps11_devs), NULL, 0);
+ ARRAY_SIZE(s2mps11_devs), NULL, 0, NULL);
break;
default:
/* If this happens the probe function is problem */
diff --git a/drivers/mfd/sta2x11-mfd.c b/drivers/mfd/sta2x11-mfd.c
index d31fed0..d35da68 100644
--- a/drivers/mfd/sta2x11-mfd.c
+++ b/drivers/mfd/sta2x11-mfd.c
@@ -407,7 +407,7 @@ static int __devinit sta2x11_mfd_probe(struct pci_dev *pdev,
sta2x11_mfd_bar0,
ARRAY_SIZE(sta2x11_mfd_bar0),
&pdev->resource[0],
- 0);
+ 0, NULL);
if (err) {
dev_err(&pdev->dev, "mfd_add_devices[0] failed: %d\n", err);
goto err_disable;
@@ -417,7 +417,7 @@ static int __devinit sta2x11_mfd_probe(struct pci_dev *pdev,
sta2x11_mfd_bar1,
ARRAY_SIZE(sta2x11_mfd_bar1),
&pdev->resource[1],
- 0);
+ 0, NULL);
if (err) {
dev_err(&pdev->dev, "mfd_add_devices[1] failed: %d\n", err);
goto err_disable;
diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c
index 2dd8d49..c94f521 100644
--- a/drivers/mfd/stmpe.c
+++ b/drivers/mfd/stmpe.c
@@ -962,7 +962,7 @@ static int __devinit stmpe_add_device(struct stmpe *stmpe,
struct mfd_cell *cell, int irq)
{
return mfd_add_devices(stmpe->dev, stmpe->pdata->id, cell, 1,
- NULL, stmpe->irq_base + irq);
+ NULL, stmpe->irq_base + irq, NULL);
}
static int __devinit stmpe_devices_init(struct stmpe *stmpe)
diff --git a/drivers/mfd/t7l66xb.c b/drivers/mfd/t7l66xb.c
index 2d9e879..b32940e 100644
--- a/drivers/mfd/t7l66xb.c
+++ b/drivers/mfd/t7l66xb.c
@@ -388,7 +388,7 @@ static int t7l66xb_probe(struct platform_device *dev)
ret = mfd_add_devices(&dev->dev, dev->id,
t7l66xb_cells, ARRAY_SIZE(t7l66xb_cells),
- iomem, t7l66xb->irq_base);
+ iomem, t7l66xb->irq_base, NULL);
if (!ret)
return 0;
diff --git a/drivers/mfd/tc3589x.c b/drivers/mfd/tc3589x.c
index 048bf05..b56ba6b 100644
--- a/drivers/mfd/tc3589x.c
+++ b/drivers/mfd/tc3589x.c
@@ -262,8 +262,8 @@ static int __devinit tc3589x_device_init(struct tc3589x *tc3589x)
if (blocks & TC3589x_BLOCK_GPIO) {
ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_dev_gpio,
- ARRAY_SIZE(tc3589x_dev_gpio), NULL,
- tc3589x->irq_base);
+ ARRAY_SIZE(tc3589x_dev_gpio), NULL,
+ tc3589x->irq_base, NULL);
if (ret) {
dev_err(tc3589x->dev, "failed to add gpio child\n");
return ret;
@@ -273,8 +273,8 @@ static int __devinit tc3589x_device_init(struct tc3589x *tc3589x)
if (blocks & TC3589x_BLOCK_KEYPAD) {
ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_dev_keypad,
- ARRAY_SIZE(tc3589x_dev_keypad), NULL,
- tc3589x->irq_base);
+ ARRAY_SIZE(tc3589x_dev_keypad), NULL,
+ tc3589x->irq_base, NULL);
if (ret) {
dev_err(tc3589x->dev, "failed to keypad child\n");
return ret;
diff --git a/drivers/mfd/tc6387xb.c b/drivers/mfd/tc6387xb.c
index d20a284..413c891 100644
--- a/drivers/mfd/tc6387xb.c
+++ b/drivers/mfd/tc6387xb.c
@@ -192,7 +192,7 @@ static int __devinit tc6387xb_probe(struct platform_device *dev)
printk(KERN_INFO "Toshiba tc6387xb initialised\n");
ret = mfd_add_devices(&dev->dev, dev->id, tc6387xb_cells,
- ARRAY_SIZE(tc6387xb_cells), iomem, irq);
+ ARRAY_SIZE(tc6387xb_cells), iomem, irq, NULL);
if (!ret)
return 0;
diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c
index 9612264..dcab026 100644
--- a/drivers/mfd/tc6393xb.c
+++ b/drivers/mfd/tc6393xb.c
@@ -700,8 +700,8 @@ static int __devinit tc6393xb_probe(struct platform_device *dev)
tc6393xb_cells[TC6393XB_CELL_FB].pdata_size = sizeof(*tcpd->fb_data);
ret = mfd_add_devices(&dev->dev, dev->id,
- tc6393xb_cells, ARRAY_SIZE(tc6393xb_cells),
- iomem, tcpd->irq_base);
+ tc6393xb_cells, ARRAY_SIZE(tc6393xb_cells),
+ iomem, tcpd->irq_base, NULL);
if (!ret)
return 0;
diff --git a/drivers/mfd/ti-ssp.c b/drivers/mfd/ti-ssp.c
index 4fb0e6c..7c3675a 100644
--- a/drivers/mfd/ti-ssp.c
+++ b/drivers/mfd/ti-ssp.c
@@ -412,7 +412,7 @@ static int __devinit ti_ssp_probe(struct platform_device *pdev)
cells[id].data_size = data->pdata_size;
}
- error = mfd_add_devices(dev, 0, cells, 2, NULL, 0);
+ error = mfd_add_devices(dev, 0, cells, 2, NULL, 0, NULL);
if (error < 0) {
dev_err(dev, "cannot add mfd cells\n");
goto error_enable;
diff --git a/drivers/mfd/timberdale.c b/drivers/mfd/timberdale.c
index a447f4e..cccc626 100644
--- a/drivers/mfd/timberdale.c
+++ b/drivers/mfd/timberdale.c
@@ -757,25 +757,25 @@ static int __devinit timb_probe(struct pci_dev *dev,
err = mfd_add_devices(&dev->dev, -1,
timberdale_cells_bar0_cfg0,
ARRAY_SIZE(timberdale_cells_bar0_cfg0),
- &dev->resource[0], msix_entries[0].vector);
+ &dev->resource[0], msix_entries[0].vector, NULL);
break;
case TIMB_HW_VER1:
err = mfd_add_devices(&dev->dev, -1,
timberdale_cells_bar0_cfg1,
ARRAY_SIZE(timberdale_cells_bar0_cfg1),
- &dev->resource[0], msix_entries[0].vector);
+ &dev->resource[0], msix_entries[0].vector, NULL);
break;
case TIMB_HW_VER2:
err = mfd_add_devices(&dev->dev, -1,
timberdale_cells_bar0_cfg2,
ARRAY_SIZE(timberdale_cells_bar0_cfg2),
- &dev->resource[0], msix_entries[0].vector);
+ &dev->resource[0], msix_entries[0].vector, NULL);
break;
case TIMB_HW_VER3:
err = mfd_add_devices(&dev->dev, -1,
timberdale_cells_bar0_cfg3,
ARRAY_SIZE(timberdale_cells_bar0_cfg3),
- &dev->resource[0], msix_entries[0].vector);
+ &dev->resource[0], msix_entries[0].vector, NULL);
break;
default:
dev_err(&dev->dev, "Uknown IP setup: %d.%d.%d\n",
@@ -792,7 +792,7 @@ static int __devinit timb_probe(struct pci_dev *dev,
err = mfd_add_devices(&dev->dev, 0,
timberdale_cells_bar1, ARRAY_SIZE(timberdale_cells_bar1),
- &dev->resource[1], msix_entries[0].vector);
+ &dev->resource[1], msix_entries[0].vector, NULL);
if (err) {
dev_err(&dev->dev, "mfd_add_devices failed: %d\n", err);
goto err_mfd2;
@@ -803,7 +803,7 @@ static int __devinit timb_probe(struct pci_dev *dev,
((priv->fw.config & TIMB_HW_VER_MASK) == TIMB_HW_VER3)) {
err = mfd_add_devices(&dev->dev, 1, timberdale_cells_bar2,
ARRAY_SIZE(timberdale_cells_bar2),
- &dev->resource[2], msix_entries[0].vector);
+ &dev->resource[2], msix_entries[0].vector, NULL);
if (err) {
dev_err(&dev->dev, "mfd_add_devices failed: %d\n", err);
goto err_mfd2;
diff --git a/drivers/mfd/tps6105x.c b/drivers/mfd/tps6105x.c
index a293b97..14051bd 100644
--- a/drivers/mfd/tps6105x.c
+++ b/drivers/mfd/tps6105x.c
@@ -188,7 +188,7 @@ static int __devinit tps6105x_probe(struct i2c_client *client,
}
ret = mfd_add_devices(&client->dev, 0, tps6105x_cells,
- ARRAY_SIZE(tps6105x_cells), NULL, 0);
+ ARRAY_SIZE(tps6105x_cells), NULL, 0, NULL);
if (ret)
goto fail;
diff --git a/drivers/mfd/tps6507x.c b/drivers/mfd/tps6507x.c
index 33ba772..1b20349 100644
--- a/drivers/mfd/tps6507x.c
+++ b/drivers/mfd/tps6507x.c
@@ -100,7 +100,7 @@ static int tps6507x_i2c_probe(struct i2c_client *i2c,
ret = mfd_add_devices(tps6507x->dev, -1,
tps6507x_devs, ARRAY_SIZE(tps6507x_devs),
- NULL, 0);
+ NULL, 0, NULL);
if (ret < 0)
goto err;
diff --git a/drivers/mfd/tps65090.c b/drivers/mfd/tps65090.c
index 80e24f4..50fd87c 100644
--- a/drivers/mfd/tps65090.c
+++ b/drivers/mfd/tps65090.c
@@ -292,7 +292,7 @@ static int __devinit tps65090_i2c_probe(struct i2c_client *client,
}
ret = mfd_add_devices(tps65090->dev, -1, tps65090s,
- ARRAY_SIZE(tps65090s), NULL, 0);
+ ARRAY_SIZE(tps65090s), NULL, 0, NULL);
if (ret) {
dev_err(&client->dev, "add mfd devices failed with err: %d\n",
ret);
diff --git a/drivers/mfd/tps65217.c b/drivers/mfd/tps65217.c
index 61c097a..a95e942 100644
--- a/drivers/mfd/tps65217.c
+++ b/drivers/mfd/tps65217.c
@@ -24,11 +24,18 @@
#include <linux/slab.h>
#include <linux/regmap.h>
#include <linux/err.h>
-#include <linux/regulator/of_regulator.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/mfd/core.h>
#include <linux/mfd/tps65217.h>
+static struct mfd_cell tps65217s[] = {
+ {
+ .name = "tps65217-pmic",
+ },
+};
+
/**
* tps65217_reg_read: Read a single tps65217 register.
*
@@ -133,83 +140,48 @@ int tps65217_clear_bits(struct tps65217 *tps, unsigned int reg,
}
EXPORT_SYMBOL_GPL(tps65217_clear_bits);
-#ifdef CONFIG_OF
-static struct of_regulator_match reg_matches[] = {
- { .name = "dcdc1", .driver_data = (void *)TPS65217_DCDC_1 },
- { .name = "dcdc2", .driver_data = (void *)TPS65217_DCDC_2 },
- { .name = "dcdc3", .driver_data = (void *)TPS65217_DCDC_3 },
- { .name = "ldo1", .driver_data = (void *)TPS65217_LDO_1 },
- { .name = "ldo2", .driver_data = (void *)TPS65217_LDO_2 },
- { .name = "ldo3", .driver_data = (void *)TPS65217_LDO_3 },
- { .name = "ldo4", .driver_data = (void *)TPS65217_LDO_4 },
-};
-
-static struct tps65217_board *tps65217_parse_dt(struct i2c_client *client)
-{
- struct device_node *node = client->dev.of_node;
- struct tps65217_board *pdata;
- struct device_node *regs;
- int count = ARRAY_SIZE(reg_matches);
- int ret, i;
-
- regs = of_find_node_by_name(node, "regulators");
- if (!regs)
- return NULL;
-
- ret = of_regulator_match(&client->dev, regs, reg_matches, count);
- of_node_put(regs);
- if ((ret < 0) || (ret > count))
- return NULL;
-
- count = ret;
- pdata = devm_kzalloc(&client->dev, count * sizeof(*pdata), GFP_KERNEL);
- if (!pdata)
- return NULL;
-
- for (i = 0; i < count; i++) {
- if (!reg_matches[i].init_data || !reg_matches[i].of_node)
- continue;
-
- pdata->tps65217_init_data[i] = reg_matches[i].init_data;
- pdata->of_node[i] = reg_matches[i].of_node;
- }
-
- return pdata;
-}
-
-static struct of_device_id tps65217_of_match[] = {
- { .compatible = "ti,tps65217", },
- { },
-};
-#else
-static struct tps65217_board *tps65217_parse_dt(struct i2c_client *client)
-{
- return NULL;
-}
-#endif
-
static struct regmap_config tps65217_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
};
+static const struct of_device_id tps65217_of_match[] = {
+ { .compatible = "ti,tps65217", .data = (void *)TPS65217 },
+ { /* sentinel */ },
+};
+
static int __devinit tps65217_probe(struct i2c_client *client,
const struct i2c_device_id *ids)
{
struct tps65217 *tps;
- struct regulator_init_data *reg_data;
- struct tps65217_board *pdata = client->dev.platform_data;
- int i, ret;
unsigned int version;
+ unsigned int chip_id = ids->driver_data;
+ const struct of_device_id *match;
+ int ret;
- if (!pdata && client->dev.of_node)
- pdata = tps65217_parse_dt(client);
+ if (client->dev.of_node) {
+ match = of_match_device(tps65217_of_match, &client->dev);
+ if (!match) {
+ dev_err(&client->dev,
+ "Failed to find matching dt id\n");
+ return -EINVAL;
+ }
+ chip_id = (unsigned int)match->data;
+ }
+
+ if (!chip_id) {
+ dev_err(&client->dev, "id is null.\n");
+ return -ENODEV;
+ }
tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL);
if (!tps)
return -ENOMEM;
- tps->pdata = pdata;
+ i2c_set_clientdata(client, tps);
+ tps->dev = &client->dev;
+ tps->id = chip_id;
+
tps->regmap = devm_regmap_init_i2c(client, &tps65217_regmap_config);
if (IS_ERR(tps->regmap)) {
ret = PTR_ERR(tps->regmap);
@@ -218,8 +190,12 @@ static int __devinit tps65217_probe(struct i2c_client *client,
return ret;
}
- i2c_set_clientdata(client, tps);
- tps->dev = &client->dev;
+ ret = mfd_add_devices(tps->dev, -1, tps65217s,
+ ARRAY_SIZE(tps65217s), NULL, 0, NULL);
+ if (ret < 0) {
+ dev_err(tps->dev, "mfd_add_devices failed: %d\n", ret);
+ return ret;
+ }
ret = tps65217_reg_read(tps, TPS65217_REG_CHIPID, &version);
if (ret < 0) {
@@ -232,41 +208,21 @@ static int __devinit tps65217_probe(struct i2c_client *client,
(version & TPS65217_CHIPID_CHIP_MASK) >> 4,
version & TPS65217_CHIPID_REV_MASK);
- for (i = 0; i < TPS65217_NUM_REGULATOR; i++) {
- struct platform_device *pdev;
-
- pdev = platform_device_alloc("tps65217-pmic", i);
- if (!pdev) {
- dev_err(tps->dev, "Cannot create regulator %d\n", i);
- continue;
- }
-
- pdev->dev.parent = tps->dev;
- pdev->dev.of_node = pdata->of_node[i];
- reg_data = pdata->tps65217_init_data[i];
- platform_device_add_data(pdev, reg_data, sizeof(*reg_data));
- tps->regulator_pdev[i] = pdev;
-
- platform_device_add(pdev);
- }
-
return 0;
}
static int __devexit tps65217_remove(struct i2c_client *client)
{
struct tps65217 *tps = i2c_get_clientdata(client);
- int i;
- for (i = 0; i < TPS65217_NUM_REGULATOR; i++)
- platform_device_unregister(tps->regulator_pdev[i]);
+ mfd_remove_devices(tps->dev);
return 0;
}
static const struct i2c_device_id tps65217_id_table[] = {
- {"tps65217", 0xF0},
- {/* end of list */}
+ {"tps65217", TPS65217},
+ { /* sentinel */ }
};
MODULE_DEVICE_TABLE(i2c, tps65217_id_table);
diff --git a/drivers/mfd/tps6586x.c b/drivers/mfd/tps6586x.c
index 353c348..5f58370 100644
--- a/drivers/mfd/tps6586x.c
+++ b/drivers/mfd/tps6586x.c
@@ -493,7 +493,8 @@ static int __devinit tps6586x_i2c_probe(struct i2c_client *client,
}
ret = mfd_add_devices(tps6586x->dev, -1,
- tps6586x_cell, ARRAY_SIZE(tps6586x_cell), NULL, 0);
+ tps6586x_cell, ARRAY_SIZE(tps6586x_cell),
+ NULL, 0, NULL);
if (ret < 0) {
dev_err(&client->dev, "mfd_add_devices failed: %d\n", ret);
goto err_mfd_add;
diff --git a/drivers/mfd/tps65910.c b/drivers/mfd/tps65910.c
index 1c56379..d3ce4d5 100644
--- a/drivers/mfd/tps65910.c
+++ b/drivers/mfd/tps65910.c
@@ -254,7 +254,7 @@ static __devinit int tps65910_i2c_probe(struct i2c_client *i2c,
ret = mfd_add_devices(tps65910->dev, -1,
tps65910s, ARRAY_SIZE(tps65910s),
- NULL, 0);
+ NULL, 0, NULL);
if (ret < 0) {
dev_err(&i2c->dev, "mfd_add_devices failed: %d\n", ret);
return ret;
diff --git a/drivers/mfd/tps65912-core.c b/drivers/mfd/tps65912-core.c
index 74fd8cb..4658b5b 100644
--- a/drivers/mfd/tps65912-core.c
+++ b/drivers/mfd/tps65912-core.c
@@ -146,7 +146,7 @@ int tps65912_device_init(struct tps65912 *tps65912)
ret = mfd_add_devices(tps65912->dev, -1,
tps65912s, ARRAY_SIZE(tps65912s),
- NULL, 0);
+ NULL, 0, NULL);
if (ret < 0)
goto err;
diff --git a/drivers/mfd/twl4030-audio.c b/drivers/mfd/twl4030-audio.c
index 838ce4e..77c9acb 100644
--- a/drivers/mfd/twl4030-audio.c
+++ b/drivers/mfd/twl4030-audio.c
@@ -223,7 +223,7 @@ static int __devinit twl4030_audio_probe(struct platform_device *pdev)
if (childs)
ret = mfd_add_devices(&pdev->dev, pdev->id, audio->cells,
- childs, NULL, 0);
+ childs, NULL, 0, NULL);
else {
dev_err(&pdev->dev, "No platform data found for childs\n");
ret = -ENODEV;
diff --git a/drivers/mfd/twl6040-core.c b/drivers/mfd/twl6040-core.c
index b0fad0f..3dca5c1 100644
--- a/drivers/mfd/twl6040-core.c
+++ b/drivers/mfd/twl6040-core.c
@@ -632,7 +632,7 @@ static int __devinit twl6040_probe(struct i2c_client *client,
}
ret = mfd_add_devices(&client->dev, -1, twl6040->cells, children,
- NULL, 0);
+ NULL, 0, NULL);
if (ret)
goto mfd_err;
diff --git a/drivers/mfd/vx855.c b/drivers/mfd/vx855.c
index 872aff2..b9a636d 100644
--- a/drivers/mfd/vx855.c
+++ b/drivers/mfd/vx855.c
@@ -102,7 +102,7 @@ static __devinit int vx855_probe(struct pci_dev *pdev,
vx855_gpio_resources[1].end = vx855_gpio_resources[1].start + 3;
ret = mfd_add_devices(&pdev->dev, -1, vx855_cells, ARRAY_SIZE(vx855_cells),
- NULL, 0);
+ NULL, 0, NULL);
/* we always return -ENODEV here in order to enable other
* drivers like old, not-yet-platform_device ported i2c-viapro */
diff --git a/drivers/mfd/wl1273-core.c b/drivers/mfd/wl1273-core.c
index f39b756..86e0e43 100644
--- a/drivers/mfd/wl1273-core.c
+++ b/drivers/mfd/wl1273-core.c
@@ -241,7 +241,7 @@ static int __devinit wl1273_core_probe(struct i2c_client *client,
__func__, children);
r = mfd_add_devices(&client->dev, -1, core->cells,
- children, NULL, 0);
+ children, NULL, 0, NULL);
if (r)
goto err;
diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c
index 946698f..3017310 100644
--- a/drivers/mfd/wm831x-core.c
+++ b/drivers/mfd/wm831x-core.c
@@ -1813,27 +1813,27 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
case WM8310:
ret = mfd_add_devices(wm831x->dev, wm831x_num,
wm8310_devs, ARRAY_SIZE(wm8310_devs),
- NULL, 0);
+ NULL, 0, NULL);
break;
case WM8311:
ret = mfd_add_devices(wm831x->dev, wm831x_num,
wm8311_devs, ARRAY_SIZE(wm8311_devs),
- NULL, 0);
+ NULL, 0, NULL);
if (!pdata || !pdata->disable_touch)
mfd_add_devices(wm831x->dev, wm831x_num,
touch_devs, ARRAY_SIZE(touch_devs),
- NULL, 0);
+ NULL, 0, NULL);
break;
case WM8312:
ret = mfd_add_devices(wm831x->dev, wm831x_num,
wm8312_devs, ARRAY_SIZE(wm8312_devs),
- NULL, 0);
+ NULL, 0, NULL);
if (!pdata || !pdata->disable_touch)
mfd_add_devices(wm831x->dev, wm831x_num,
touch_devs, ARRAY_SIZE(touch_devs),
- NULL, 0);
+ NULL, 0, NULL);
break;
case WM8320:
@@ -1842,7 +1842,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
case WM8326:
ret = mfd_add_devices(wm831x->dev, wm831x_num,
wm8320_devs, ARRAY_SIZE(wm8320_devs),
- NULL, 0);
+ NULL, 0, NULL);
break;
default:
@@ -1867,7 +1867,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
if (ret & WM831X_XTAL_ENA) {
ret = mfd_add_devices(wm831x->dev, wm831x_num,
rtc_devs, ARRAY_SIZE(rtc_devs),
- NULL, 0);
+ NULL, 0, NULL);
if (ret != 0) {
dev_err(wm831x->dev, "Failed to add RTC: %d\n", ret);
goto err_irq;
@@ -1880,7 +1880,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
/* Treat errors as non-critical */
ret = mfd_add_devices(wm831x->dev, wm831x_num, backlight_devs,
ARRAY_SIZE(backlight_devs), NULL,
- 0);
+ 0, NULL);
if (ret < 0)
dev_err(wm831x->dev, "Failed to add backlight: %d\n",
ret);
diff --git a/drivers/mfd/wm8400-core.c b/drivers/mfd/wm8400-core.c
index 4b7d378..639ca35 100644
--- a/drivers/mfd/wm8400-core.c
+++ b/drivers/mfd/wm8400-core.c
@@ -70,7 +70,7 @@ static int wm8400_register_codec(struct wm8400 *wm8400)
.pdata_size = sizeof(*wm8400),
};
- return mfd_add_devices(wm8400->dev, -1, &cell, 1, NULL, 0);
+ return mfd_add_devices(wm8400->dev, -1, &cell, 1, NULL, 0, NULL);
}
/*
diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c
index eec74aa..2febf88 100644
--- a/drivers/mfd/wm8994-core.c
+++ b/drivers/mfd/wm8994-core.c
@@ -414,7 +414,7 @@ static __devinit int wm8994_device_init(struct wm8994 *wm8994, int irq)
ret = mfd_add_devices(wm8994->dev, -1,
wm8994_regulator_devs,
ARRAY_SIZE(wm8994_regulator_devs),
- NULL, 0);
+ NULL, 0, NULL);
if (ret != 0) {
dev_err(wm8994->dev, "Failed to add children: %d\n", ret);
goto err;
@@ -648,7 +648,7 @@ static __devinit int wm8994_device_init(struct wm8994 *wm8994, int irq)
ret = mfd_add_devices(wm8994->dev, -1,
wm8994_devs, ARRAY_SIZE(wm8994_devs),
- NULL, 0);
+ NULL, 0, NULL);
if (ret != 0) {
dev_err(wm8994->dev, "Failed to add children: %d\n", ret);
goto err_irq;
diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
index 2c4a21f..e5180dfd 100644
--- a/drivers/net/can/c_can/c_can.c
+++ b/drivers/net/can/c_can/c_can.c
@@ -1265,9 +1265,6 @@ void unregister_c_can_dev(struct net_device *dev)
{
struct c_can_priv *priv = netdev_priv(dev);
- /* disable all interrupts */
- c_can_enable_all_interrupts(priv, DISABLE_ALL_INTERRUPTS);
-
unregister_candev(dev);
c_can_pm_runtime_disable(priv);
diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c
index 98ee438..7edadee 100644
--- a/drivers/net/can/janz-ican3.c
+++ b/drivers/net/can/janz-ican3.c
@@ -1391,7 +1391,6 @@ static irqreturn_t ican3_irq(int irq, void *dev_id)
*/
static int ican3_reset_module(struct ican3_dev *mod)
{
- u8 val = 1 << mod->num;
unsigned long start;
u8 runold, runnew;
@@ -1405,8 +1404,7 @@ static int ican3_reset_module(struct ican3_dev *mod)
runold = ioread8(mod->dpm + TARGET_RUNNING);
/* reset the module */
- iowrite8(val, &mod->ctrl->reset_assert);
- iowrite8(val, &mod->ctrl->reset_deassert);
+ iowrite8(0x00, &mod->dpmctrl->hwreset);
/* wait until the module has finished resetting and is running */
start = jiffies;
diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c
index 527dbcf..9ded21e 100644
--- a/drivers/net/can/ti_hecc.c
+++ b/drivers/net/can/ti_hecc.c
@@ -984,12 +984,12 @@ static int __devexit ti_hecc_remove(struct platform_device *pdev)
struct net_device *ndev = platform_get_drvdata(pdev);
struct ti_hecc_priv *priv = netdev_priv(ndev);
+ unregister_candev(ndev);
clk_disable(priv->clk);
clk_put(priv->clk);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
iounmap(priv->base);
release_mem_region(res->start, resource_size(res));
- unregister_candev(ndev);
free_candev(ndev);
platform_set_drvdata(pdev, NULL);
diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c
index 79cebd8..e48312f 100644
--- a/drivers/net/ethernet/broadcom/bnx2.c
+++ b/drivers/net/ethernet/broadcom/bnx2.c
@@ -8564,7 +8564,7 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
return 0;
error:
- iounmap(bp->regview);
+ pci_iounmap(pdev, bp->regview);
pci_release_regions(pdev);
pci_disable_device(pdev);
pci_set_drvdata(pdev, NULL);
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index ca80487..f67e700 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -662,14 +662,16 @@ void bnx2x_csum_validate(struct sk_buff *skb, union eth_rx_cqe *cqe,
struct bnx2x_fastpath *fp,
struct bnx2x_eth_q_stats *qstats)
{
- /* Do nothing if no IP/L4 csum validation was done */
-
+ /* Do nothing if no L4 csum validation was done.
+ * We do not check whether IP csum was validated. For IPv4 we assume
+ * that if the card got as far as validating the L4 csum, it also
+ * validated the IP csum. IPv6 has no IP csum.
+ */
if (cqe->fast_path_cqe.status_flags &
- (ETH_FAST_PATH_RX_CQE_IP_XSUM_NO_VALIDATION_FLG |
- ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG))
+ ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG)
return;
- /* If both IP/L4 validation were done, check if an error was found. */
+ /* If L4 validation was done, check if an error was found. */
if (cqe->fast_path_cqe.type_error_flags &
(ETH_FAST_PATH_RX_CQE_IP_BAD_XSUM_FLG |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index 7a91570..c319e4c 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -9841,12 +9841,13 @@ static void __devinit bnx2x_get_igu_cam_info(struct bnx2x *bp)
}
#ifdef CONFIG_PCI_MSI
- /*
- * It's expected that number of CAM entries for this functions is equal
- * to the number evaluated based on the MSI-X table size. We want a
- * harsh warning if these values are different!
+ /* Due to new PF resource allocation by MFW T7.4 and above, it's
+ * optional that number of CAM entries will not be equal to the value
+ * advertised in PCI.
+ * Driver should use the minimal value of both as the actual status
+ * block count
*/
- WARN_ON(bp->igu_sb_cnt != igu_sb_cnt);
+ bp->igu_sb_cnt = min_t(int, bp->igu_sb_cnt, igu_sb_cnt);
#endif
if (igu_sb_cnt == 0)
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index bf906c5..24f6623 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -92,10 +92,10 @@ static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits)
#define DRV_MODULE_NAME "tg3"
#define TG3_MAJ_NUM 3
-#define TG3_MIN_NUM 124
+#define TG3_MIN_NUM 125
#define DRV_MODULE_VERSION \
__stringify(TG3_MAJ_NUM) "." __stringify(TG3_MIN_NUM)
-#define DRV_MODULE_RELDATE "March 21, 2012"
+#define DRV_MODULE_RELDATE "September 26, 2012"
#define RESET_KIND_SHUTDOWN 0
#define RESET_KIND_INIT 1
@@ -6278,7 +6278,7 @@ static int tg3_poll_work(struct tg3_napi *tnapi, int work_done, int budget)
u32 jmb_prod_idx = dpr->rx_jmb_prod_idx;
tp->rx_refill = false;
- for (i = 1; i < tp->irq_cnt; i++)
+ for (i = 1; i <= tp->rxq_cnt; i++)
err |= tg3_rx_prodring_xfer(tp, dpr,
&tp->napi[i].prodring);
@@ -7607,15 +7607,11 @@ static int tg3_init_rings(struct tg3 *tp)
return 0;
}
-/*
- * Must not be invoked with interrupt sources disabled and
- * the hardware shutdown down.
- */
-static void tg3_free_consistent(struct tg3 *tp)
+static void tg3_mem_tx_release(struct tg3 *tp)
{
int i;
- for (i = 0; i < tp->irq_cnt; i++) {
+ for (i = 0; i < tp->irq_max; i++) {
struct tg3_napi *tnapi = &tp->napi[i];
if (tnapi->tx_ring) {
@@ -7626,17 +7622,114 @@ static void tg3_free_consistent(struct tg3 *tp)
kfree(tnapi->tx_buffers);
tnapi->tx_buffers = NULL;
+ }
+}
- if (tnapi->rx_rcb) {
- dma_free_coherent(&tp->pdev->dev,
- TG3_RX_RCB_RING_BYTES(tp),
- tnapi->rx_rcb,
- tnapi->rx_rcb_mapping);
- tnapi->rx_rcb = NULL;
- }
+static int tg3_mem_tx_acquire(struct tg3 *tp)
+{
+ int i;
+ struct tg3_napi *tnapi = &tp->napi[0];
+
+ /* If multivector TSS is enabled, vector 0 does not handle
+ * tx interrupts. Don't allocate any resources for it.
+ */
+ if (tg3_flag(tp, ENABLE_TSS))
+ tnapi++;
+
+ for (i = 0; i < tp->txq_cnt; i++, tnapi++) {
+ tnapi->tx_buffers = kzalloc(sizeof(struct tg3_tx_ring_info) *
+ TG3_TX_RING_SIZE, GFP_KERNEL);
+ if (!tnapi->tx_buffers)
+ goto err_out;
+
+ tnapi->tx_ring = dma_alloc_coherent(&tp->pdev->dev,
+ TG3_TX_RING_BYTES,
+ &tnapi->tx_desc_mapping,
+ GFP_KERNEL);
+ if (!tnapi->tx_ring)
+ goto err_out;
+ }
+
+ return 0;
+
+err_out:
+ tg3_mem_tx_release(tp);
+ return -ENOMEM;
+}
+
+static void tg3_mem_rx_release(struct tg3 *tp)
+{
+ int i;
+
+ for (i = 0; i < tp->irq_max; i++) {
+ struct tg3_napi *tnapi = &tp->napi[i];
tg3_rx_prodring_fini(tp, &tnapi->prodring);
+ if (!tnapi->rx_rcb)
+ continue;
+
+ dma_free_coherent(&tp->pdev->dev,
+ TG3_RX_RCB_RING_BYTES(tp),
+ tnapi->rx_rcb,
+ tnapi->rx_rcb_mapping);
+ tnapi->rx_rcb = NULL;
+ }
+}
+
+static int tg3_mem_rx_acquire(struct tg3 *tp)
+{
+ unsigned int i, limit;
+
+ limit = tp->rxq_cnt;
+
+ /* If RSS is enabled, we need a (dummy) producer ring
+ * set on vector zero. This is the true hw prodring.
+ */
+ if (tg3_flag(tp, ENABLE_RSS))
+ limit++;
+
+ for (i = 0; i < limit; i++) {
+ struct tg3_napi *tnapi = &tp->napi[i];
+
+ if (tg3_rx_prodring_init(tp, &tnapi->prodring))
+ goto err_out;
+
+ /* If multivector RSS is enabled, vector 0
+ * does not handle rx or tx interrupts.
+ * Don't allocate any resources for it.
+ */
+ if (!i && tg3_flag(tp, ENABLE_RSS))
+ continue;
+
+ tnapi->rx_rcb = dma_alloc_coherent(&tp->pdev->dev,
+ TG3_RX_RCB_RING_BYTES(tp),
+ &tnapi->rx_rcb_mapping,
+ GFP_KERNEL);
+ if (!tnapi->rx_rcb)
+ goto err_out;
+
+ memset(tnapi->rx_rcb, 0, TG3_RX_RCB_RING_BYTES(tp));
+ }
+
+ return 0;
+
+err_out:
+ tg3_mem_rx_release(tp);
+ return -ENOMEM;
+}
+
+/*
+ * Must not be invoked with interrupt sources disabled and
+ * the hardware shutdown down.
+ */
+static void tg3_free_consistent(struct tg3 *tp)
+{
+ int i;
+
+ for (i = 0; i < tp->irq_cnt; i++) {
+ struct tg3_napi *tnapi = &tp->napi[i];
+
if (tnapi->hw_status) {
dma_free_coherent(&tp->pdev->dev, TG3_HW_STATUS_SIZE,
tnapi->hw_status,
@@ -7645,6 +7738,9 @@ static void tg3_free_consistent(struct tg3 *tp)
}
}
+ tg3_mem_rx_release(tp);
+ tg3_mem_tx_release(tp);
+
if (tp->hw_stats) {
dma_free_coherent(&tp->pdev->dev, sizeof(struct tg3_hw_stats),
tp->hw_stats, tp->stats_mapping);
@@ -7683,72 +7779,38 @@ static int tg3_alloc_consistent(struct tg3 *tp)
memset(tnapi->hw_status, 0, TG3_HW_STATUS_SIZE);
sblk = tnapi->hw_status;
- if (tg3_rx_prodring_init(tp, &tnapi->prodring))
- goto err_out;
+ if (tg3_flag(tp, ENABLE_RSS)) {
+ u16 *prodptr = 0;
- /* If multivector TSS is enabled, vector 0 does not handle
- * tx interrupts. Don't allocate any resources for it.
- */
- if ((!i && !tg3_flag(tp, ENABLE_TSS)) ||
- (i && tg3_flag(tp, ENABLE_TSS))) {
- tnapi->tx_buffers = kzalloc(
- sizeof(struct tg3_tx_ring_info) *
- TG3_TX_RING_SIZE, GFP_KERNEL);
- if (!tnapi->tx_buffers)
- goto err_out;
-
- tnapi->tx_ring = dma_alloc_coherent(&tp->pdev->dev,
- TG3_TX_RING_BYTES,
- &tnapi->tx_desc_mapping,
- GFP_KERNEL);
- if (!tnapi->tx_ring)
- goto err_out;
- }
-
- /*
- * When RSS is enabled, the status block format changes
- * slightly. The "rx_jumbo_consumer", "reserved",
- * and "rx_mini_consumer" members get mapped to the
- * other three rx return ring producer indexes.
- */
- switch (i) {
- default:
- if (tg3_flag(tp, ENABLE_RSS)) {
- tnapi->rx_rcb_prod_idx = NULL;
+ /*
+ * When RSS is enabled, the status block format changes
+ * slightly. The "rx_jumbo_consumer", "reserved",
+ * and "rx_mini_consumer" members get mapped to the
+ * other three rx return ring producer indexes.
+ */
+ switch (i) {
+ case 1:
+ prodptr = &sblk->idx[0].rx_producer;
+ break;
+ case 2:
+ prodptr = &sblk->rx_jumbo_consumer;
+ break;
+ case 3:
+ prodptr = &sblk->reserved;
+ break;
+ case 4:
+ prodptr = &sblk->rx_mini_consumer;
break;
}
- /* Fall through */
- case 1:
+ tnapi->rx_rcb_prod_idx = prodptr;
+ } else {
tnapi->rx_rcb_prod_idx = &sblk->idx[0].rx_producer;
- break;
- case 2:
- tnapi->rx_rcb_prod_idx = &sblk->rx_jumbo_consumer;
- break;
- case 3:
- tnapi->rx_rcb_prod_idx = &sblk->reserved;
- break;
- case 4:
- tnapi->rx_rcb_prod_idx = &sblk->rx_mini_consumer;
- break;
}
-
- /*
- * If multivector RSS is enabled, vector 0 does not handle
- * rx or tx interrupts. Don't allocate any resources for it.
- */
- if (!i && tg3_flag(tp, ENABLE_RSS))
- continue;
-
- tnapi->rx_rcb = dma_alloc_coherent(&tp->pdev->dev,
- TG3_RX_RCB_RING_BYTES(tp),
- &tnapi->rx_rcb_mapping,
- GFP_KERNEL);
- if (!tnapi->rx_rcb)
- goto err_out;
-
- memset(tnapi->rx_rcb, 0, TG3_RX_RCB_RING_BYTES(tp));
}
+ if (tg3_mem_tx_acquire(tp) || tg3_mem_rx_acquire(tp))
+ goto err_out;
+
return 0;
err_out:
@@ -8269,9 +8331,10 @@ static void tg3_set_bdinfo(struct tg3 *tp, u32 bdinfo_addr,
nic_addr);
}
-static void __tg3_set_coalesce(struct tg3 *tp, struct ethtool_coalesce *ec)
+
+static void tg3_coal_tx_init(struct tg3 *tp, struct ethtool_coalesce *ec)
{
- int i;
+ int i = 0;
if (!tg3_flag(tp, ENABLE_TSS)) {
tw32(HOSTCC_TXCOL_TICKS, ec->tx_coalesce_usecs);
@@ -8281,31 +8344,43 @@ static void __tg3_set_coalesce(struct tg3 *tp, struct ethtool_coalesce *ec)
tw32(HOSTCC_TXCOL_TICKS, 0);
tw32(HOSTCC_TXMAX_FRAMES, 0);
tw32(HOSTCC_TXCOAL_MAXF_INT, 0);
+
+ for (; i < tp->txq_cnt; i++) {
+ u32 reg;
+
+ reg = HOSTCC_TXCOL_TICKS_VEC1 + i * 0x18;
+ tw32(reg, ec->tx_coalesce_usecs);
+ reg = HOSTCC_TXMAX_FRAMES_VEC1 + i * 0x18;
+ tw32(reg, ec->tx_max_coalesced_frames);
+ reg = HOSTCC_TXCOAL_MAXF_INT_VEC1 + i * 0x18;
+ tw32(reg, ec->tx_max_coalesced_frames_irq);
+ }
+ }
+
+ for (; i < tp->irq_max - 1; i++) {
+ tw32(HOSTCC_TXCOL_TICKS_VEC1 + i * 0x18, 0);
+ tw32(HOSTCC_TXMAX_FRAMES_VEC1 + i * 0x18, 0);
+ tw32(HOSTCC_TXCOAL_MAXF_INT_VEC1 + i * 0x18, 0);
}
+}
+
+static void tg3_coal_rx_init(struct tg3 *tp, struct ethtool_coalesce *ec)
+{
+ int i = 0;
+ u32 limit = tp->rxq_cnt;
if (!tg3_flag(tp, ENABLE_RSS)) {
tw32(HOSTCC_RXCOL_TICKS, ec->rx_coalesce_usecs);
tw32(HOSTCC_RXMAX_FRAMES, ec->rx_max_coalesced_frames);
tw32(HOSTCC_RXCOAL_MAXF_INT, ec->rx_max_coalesced_frames_irq);
+ limit--;
} else {
tw32(HOSTCC_RXCOL_TICKS, 0);
tw32(HOSTCC_RXMAX_FRAMES, 0);
tw32(HOSTCC_RXCOAL_MAXF_INT, 0);
}
- if (!tg3_flag(tp, 5705_PLUS)) {
- u32 val = ec->stats_block_coalesce_usecs;
-
- tw32(HOSTCC_RXCOAL_TICK_INT, ec->rx_coalesce_usecs_irq);
- tw32(HOSTCC_TXCOAL_TICK_INT, ec->tx_coalesce_usecs_irq);
-
- if (!netif_carrier_ok(tp->dev))
- val = 0;
-
- tw32(HOSTCC_STAT_COAL_TICKS, val);
- }
-
- for (i = 0; i < tp->irq_cnt - 1; i++) {
+ for (; i < limit; i++) {
u32 reg;
reg = HOSTCC_RXCOL_TICKS_VEC1 + i * 0x18;
@@ -8314,27 +8389,30 @@ static void __tg3_set_coalesce(struct tg3 *tp, struct ethtool_coalesce *ec)
tw32(reg, ec->rx_max_coalesced_frames);
reg = HOSTCC_RXCOAL_MAXF_INT_VEC1 + i * 0x18;
tw32(reg, ec->rx_max_coalesced_frames_irq);
-
- if (tg3_flag(tp, ENABLE_TSS)) {
- reg = HOSTCC_TXCOL_TICKS_VEC1 + i * 0x18;
- tw32(reg, ec->tx_coalesce_usecs);
- reg = HOSTCC_TXMAX_FRAMES_VEC1 + i * 0x18;
- tw32(reg, ec->tx_max_coalesced_frames);
- reg = HOSTCC_TXCOAL_MAXF_INT_VEC1 + i * 0x18;
- tw32(reg, ec->tx_max_coalesced_frames_irq);
- }
}
for (; i < tp->irq_max - 1; i++) {
tw32(HOSTCC_RXCOL_TICKS_VEC1 + i * 0x18, 0);
tw32(HOSTCC_RXMAX_FRAMES_VEC1 + i * 0x18, 0);
tw32(HOSTCC_RXCOAL_MAXF_INT_VEC1 + i * 0x18, 0);
+ }
+}
- if (tg3_flag(tp, ENABLE_TSS)) {
- tw32(HOSTCC_TXCOL_TICKS_VEC1 + i * 0x18, 0);
- tw32(HOSTCC_TXMAX_FRAMES_VEC1 + i * 0x18, 0);
- tw32(HOSTCC_TXCOAL_MAXF_INT_VEC1 + i * 0x18, 0);
- }
+static void __tg3_set_coalesce(struct tg3 *tp, struct ethtool_coalesce *ec)
+{
+ tg3_coal_tx_init(tp, ec);
+ tg3_coal_rx_init(tp, ec);
+
+ if (!tg3_flag(tp, 5705_PLUS)) {
+ u32 val = ec->stats_block_coalesce_usecs;
+
+ tw32(HOSTCC_RXCOAL_TICK_INT, ec->rx_coalesce_usecs_irq);
+ tw32(HOSTCC_TXCOAL_TICK_INT, ec->tx_coalesce_usecs_irq);
+
+ if (!netif_carrier_ok(tp->dev))
+ val = 0;
+
+ tw32(HOSTCC_STAT_COAL_TICKS, val);
}
}
@@ -8592,13 +8670,12 @@ static void __tg3_set_rx_mode(struct net_device *dev)
}
}
-static void tg3_rss_init_dflt_indir_tbl(struct tg3 *tp)
+static void tg3_rss_init_dflt_indir_tbl(struct tg3 *tp, u32 qcnt)
{
int i;
for (i = 0; i < TG3_RSS_INDIR_TBL_SIZE; i++)
- tp->rss_ind_tbl[i] =
- ethtool_rxfh_indir_default(i, tp->irq_cnt - 1);
+ tp->rss_ind_tbl[i] = ethtool_rxfh_indir_default(i, qcnt);
}
static void tg3_rss_check_indir_tbl(struct tg3 *tp)
@@ -8620,7 +8697,7 @@ static void tg3_rss_check_indir_tbl(struct tg3 *tp)
}
if (i != TG3_RSS_INDIR_TBL_SIZE)
- tg3_rss_init_dflt_indir_tbl(tp);
+ tg3_rss_init_dflt_indir_tbl(tp, tp->rxq_cnt);
}
static void tg3_rss_write_indir_tbl(struct tg3 *tp)
@@ -10141,21 +10218,43 @@ static int tg3_request_firmware(struct tg3 *tp)
return 0;
}
-static bool tg3_enable_msix(struct tg3 *tp)
+static u32 tg3_irq_count(struct tg3 *tp)
{
- int i, rc;
- struct msix_entry msix_ent[tp->irq_max];
+ u32 irq_cnt = max(tp->rxq_cnt, tp->txq_cnt);
- tp->irq_cnt = netif_get_num_default_rss_queues();
- if (tp->irq_cnt > 1) {
+ if (irq_cnt > 1) {
/* We want as many rx rings enabled as there are cpus.
* In multiqueue MSI-X mode, the first MSI-X vector
* only deals with link interrupts, etc, so we add
* one to the number of vectors we are requesting.
*/
- tp->irq_cnt = min_t(unsigned, tp->irq_cnt + 1, tp->irq_max);
+ irq_cnt = min_t(unsigned, irq_cnt + 1, tp->irq_max);
}
+ return irq_cnt;
+}
+
+static bool tg3_enable_msix(struct tg3 *tp)
+{
+ int i, rc;
+ struct msix_entry msix_ent[tp->irq_max];
+
+ tp->txq_cnt = tp->txq_req;
+ tp->rxq_cnt = tp->rxq_req;
+ if (!tp->rxq_cnt)
+ tp->rxq_cnt = netif_get_num_default_rss_queues();
+ if (tp->rxq_cnt > tp->rxq_max)
+ tp->rxq_cnt = tp->rxq_max;
+
+ /* Disable multiple TX rings by default. Simple round-robin hardware
+ * scheduling of the TX rings can cause starvation of rings with
+ * small packets when other rings have TSO or jumbo packets.
+ */
+ if (!tp->txq_req)
+ tp->txq_cnt = 1;
+
+ tp->irq_cnt = tg3_irq_count(tp);
+
for (i = 0; i < tp->irq_max; i++) {
msix_ent[i].entry = i;
msix_ent[i].vector = 0;
@@ -10170,27 +10269,28 @@ static bool tg3_enable_msix(struct tg3 *tp)
netdev_notice(tp->dev, "Requested %d MSI-X vectors, received %d\n",
tp->irq_cnt, rc);
tp->irq_cnt = rc;
+ tp->rxq_cnt = max(rc - 1, 1);
+ if (tp->txq_cnt)
+ tp->txq_cnt = min(tp->rxq_cnt, tp->txq_max);
}
for (i = 0; i < tp->irq_max; i++)
tp->napi[i].irq_vec = msix_ent[i].vector;
- netif_set_real_num_tx_queues(tp->dev, 1);
- rc = tp->irq_cnt > 1 ? tp->irq_cnt - 1 : 1;
- if (netif_set_real_num_rx_queues(tp->dev, rc)) {
+ if (netif_set_real_num_rx_queues(tp->dev, tp->rxq_cnt)) {
pci_disable_msix(tp->pdev);
return false;
}
- if (tp->irq_cnt > 1) {
- tg3_flag_set(tp, ENABLE_RSS);
+ if (tp->irq_cnt == 1)
+ return true;
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) {
- tg3_flag_set(tp, ENABLE_TSS);
- netif_set_real_num_tx_queues(tp->dev, tp->irq_cnt - 1);
- }
- }
+ tg3_flag_set(tp, ENABLE_RSS);
+
+ if (tp->txq_cnt > 1)
+ tg3_flag_set(tp, ENABLE_TSS);
+
+ netif_set_real_num_tx_queues(tp->dev, tp->txq_cnt);
return true;
}
@@ -10224,6 +10324,11 @@ defcfg:
if (!tg3_flag(tp, USING_MSIX)) {
tp->irq_cnt = 1;
tp->napi[0].irq_vec = tp->pdev->irq;
+ }
+
+ if (tp->irq_cnt == 1) {
+ tp->txq_cnt = 1;
+ tp->rxq_cnt = 1;
netif_set_real_num_tx_queues(tp->dev, 1);
netif_set_real_num_rx_queues(tp->dev, 1);
}
@@ -10241,38 +10346,11 @@ static void tg3_ints_fini(struct tg3 *tp)
tg3_flag_clear(tp, ENABLE_TSS);
}
-static int tg3_open(struct net_device *dev)
+static int tg3_start(struct tg3 *tp, bool reset_phy, bool test_irq)
{
- struct tg3 *tp = netdev_priv(dev);
+ struct net_device *dev = tp->dev;
int i, err;
- if (tp->fw_needed) {
- err = tg3_request_firmware(tp);
- if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0) {
- if (err)
- return err;
- } else if (err) {
- netdev_warn(tp->dev, "TSO capability disabled\n");
- tg3_flag_clear(tp, TSO_CAPABLE);
- } else if (!tg3_flag(tp, TSO_CAPABLE)) {
- netdev_notice(tp->dev, "TSO capability restored\n");
- tg3_flag_set(tp, TSO_CAPABLE);
- }
- }
-
- netif_carrier_off(tp->dev);
-
- err = tg3_power_up(tp);
- if (err)
- return err;
-
- tg3_full_lock(tp, 0);
-
- tg3_disable_ints(tp);
- tg3_flag_clear(tp, INIT_COMPLETE);
-
- tg3_full_unlock(tp);
-
/*
* Setup interrupts first so we know how
* many NAPI resources to allocate
@@ -10306,7 +10384,7 @@ static int tg3_open(struct net_device *dev)
tg3_full_lock(tp, 0);
- err = tg3_init_hw(tp, 1);
+ err = tg3_init_hw(tp, reset_phy);
if (err) {
tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
tg3_free_rings(tp);
@@ -10317,7 +10395,7 @@ static int tg3_open(struct net_device *dev)
if (err)
goto err_out3;
- if (tg3_flag(tp, USING_MSI)) {
+ if (test_irq && tg3_flag(tp, USING_MSI)) {
err = tg3_test_msi(tp);
if (err) {
@@ -10373,20 +10451,18 @@ err_out2:
err_out1:
tg3_ints_fini(tp);
- tg3_frob_aux_power(tp, false);
- pci_set_power_state(tp->pdev, PCI_D3hot);
+
return err;
}
-static int tg3_close(struct net_device *dev)
+static void tg3_stop(struct tg3 *tp)
{
int i;
- struct tg3 *tp = netdev_priv(dev);
tg3_napi_disable(tp);
tg3_reset_task_cancel(tp);
- netif_tx_stop_all_queues(dev);
+ netif_tx_disable(tp->dev);
tg3_timer_stop(tp);
@@ -10411,13 +10487,60 @@ static int tg3_close(struct net_device *dev)
tg3_ints_fini(tp);
- /* Clear stats across close / open calls */
- memset(&tp->net_stats_prev, 0, sizeof(tp->net_stats_prev));
- memset(&tp->estats_prev, 0, sizeof(tp->estats_prev));
-
tg3_napi_fini(tp);
tg3_free_consistent(tp);
+}
+
+static int tg3_open(struct net_device *dev)
+{
+ struct tg3 *tp = netdev_priv(dev);
+ int err;
+
+ if (tp->fw_needed) {
+ err = tg3_request_firmware(tp);
+ if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0) {
+ if (err)
+ return err;
+ } else if (err) {
+ netdev_warn(tp->dev, "TSO capability disabled\n");
+ tg3_flag_clear(tp, TSO_CAPABLE);
+ } else if (!tg3_flag(tp, TSO_CAPABLE)) {
+ netdev_notice(tp->dev, "TSO capability restored\n");
+ tg3_flag_set(tp, TSO_CAPABLE);
+ }
+ }
+
+ netif_carrier_off(tp->dev);
+
+ err = tg3_power_up(tp);
+ if (err)
+ return err;
+
+ tg3_full_lock(tp, 0);
+
+ tg3_disable_ints(tp);
+ tg3_flag_clear(tp, INIT_COMPLETE);
+
+ tg3_full_unlock(tp);
+
+ err = tg3_start(tp, true, true);
+ if (err) {
+ tg3_frob_aux_power(tp, false);
+ pci_set_power_state(tp->pdev, PCI_D3hot);
+ }
+ return err;
+}
+
+static int tg3_close(struct net_device *dev)
+{
+ struct tg3 *tp = netdev_priv(dev);
+
+ tg3_stop(tp);
+
+ /* Clear stats across close / open calls */
+ memset(&tp->net_stats_prev, 0, sizeof(tp->net_stats_prev));
+ memset(&tp->estats_prev, 0, sizeof(tp->estats_prev));
tg3_power_down(tp);
@@ -11207,11 +11330,11 @@ static int tg3_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info,
switch (info->cmd) {
case ETHTOOL_GRXRINGS:
if (netif_running(tp->dev))
- info->data = tp->irq_cnt;
+ info->data = tp->rxq_cnt;
else {
info->data = num_online_cpus();
- if (info->data > TG3_IRQ_MAX_VECS_RSS)
- info->data = TG3_IRQ_MAX_VECS_RSS;
+ if (info->data > TG3_RSS_MAX_NUM_QS)
+ info->data = TG3_RSS_MAX_NUM_QS;
}
/* The first interrupt vector only
@@ -11268,6 +11391,58 @@ static int tg3_set_rxfh_indir(struct net_device *dev, const u32 *indir)
return 0;
}
+static void tg3_get_channels(struct net_device *dev,
+ struct ethtool_channels *channel)
+{
+ struct tg3 *tp = netdev_priv(dev);
+ u32 deflt_qs = netif_get_num_default_rss_queues();
+
+ channel->max_rx = tp->rxq_max;
+ channel->max_tx = tp->txq_max;
+
+ if (netif_running(dev)) {
+ channel->rx_count = tp->rxq_cnt;
+ channel->tx_count = tp->txq_cnt;
+ } else {
+ if (tp->rxq_req)
+ channel->rx_count = tp->rxq_req;
+ else
+ channel->rx_count = min(deflt_qs, tp->rxq_max);
+
+ if (tp->txq_req)
+ channel->tx_count = tp->txq_req;
+ else
+ channel->tx_count = min(deflt_qs, tp->txq_max);
+ }
+}
+
+static int tg3_set_channels(struct net_device *dev,
+ struct ethtool_channels *channel)
+{
+ struct tg3 *tp = netdev_priv(dev);
+
+ if (!tg3_flag(tp, SUPPORT_MSIX))
+ return -EOPNOTSUPP;
+
+ if (channel->rx_count > tp->rxq_max ||
+ channel->tx_count > tp->txq_max)
+ return -EINVAL;
+
+ tp->rxq_req = channel->rx_count;
+ tp->txq_req = channel->tx_count;
+
+ if (!netif_running(dev))
+ return 0;
+
+ tg3_stop(tp);
+
+ netif_carrier_off(dev);
+
+ tg3_start(tp, true, false);
+
+ return 0;
+}
+
static void tg3_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
{
switch (stringset) {
@@ -12516,6 +12691,8 @@ static const struct ethtool_ops tg3_ethtool_ops = {
.get_rxfh_indir_size = tg3_get_rxfh_indir_size,
.get_rxfh_indir = tg3_get_rxfh_indir,
.set_rxfh_indir = tg3_set_rxfh_indir,
+ .get_channels = tg3_get_channels,
+ .set_channels = tg3_set_channels,
.get_ts_info = ethtool_op_get_ts_info,
};
@@ -14532,10 +14709,20 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
if (tg3_flag(tp, 57765_PLUS)) {
tg3_flag_set(tp, SUPPORT_MSIX);
tp->irq_max = TG3_IRQ_MAX_VECS;
- tg3_rss_init_dflt_indir_tbl(tp);
}
}
+ tp->txq_max = 1;
+ tp->rxq_max = 1;
+ if (tp->irq_max > 1) {
+ tp->rxq_max = TG3_RSS_MAX_NUM_QS;
+ tg3_rss_init_dflt_indir_tbl(tp, TG3_RSS_MAX_NUM_QS);
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720)
+ tp->txq_max = tp->irq_max - 1;
+ }
+
if (tg3_flag(tp, 5755_PLUS) ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
tg3_flag_set(tp, SHORT_DMA_BUG);
diff --git a/drivers/net/ethernet/broadcom/tg3.h b/drivers/net/ethernet/broadcom/tg3.h
index 6d52cb2..d9308c32 100644
--- a/drivers/net/ethernet/broadcom/tg3.h
+++ b/drivers/net/ethernet/broadcom/tg3.h
@@ -2860,7 +2860,8 @@ struct tg3_rx_prodring_set {
dma_addr_t rx_jmb_mapping;
};
-#define TG3_IRQ_MAX_VECS_RSS 5
+#define TG3_RSS_MAX_NUM_QS 4
+#define TG3_IRQ_MAX_VECS_RSS (TG3_RSS_MAX_NUM_QS + 1)
#define TG3_IRQ_MAX_VECS TG3_IRQ_MAX_VECS_RSS
struct tg3_napi {
@@ -3037,6 +3038,9 @@ struct tg3 {
void (*write32_tx_mbox) (struct tg3 *, u32,
u32);
u32 dma_limit;
+ u32 txq_req;
+ u32 txq_cnt;
+ u32 txq_max;
/* begin "rx thread" cacheline section */
struct tg3_napi napi[TG3_IRQ_MAX_VECS];
@@ -3051,6 +3055,9 @@ struct tg3 {
u32 rx_std_max_post;
u32 rx_offset;
u32 rx_pkt_map_sz;
+ u32 rxq_req;
+ u32 rxq_cnt;
+ u32 rxq_max;
bool rx_refill;
diff --git a/drivers/net/ethernet/cadence/at91_ether.c b/drivers/net/ethernet/cadence/at91_ether.c
index 7788419..4e980a78 100644
--- a/drivers/net/ethernet/cadence/at91_ether.c
+++ b/drivers/net/ethernet/cadence/at91_ether.c
@@ -1086,7 +1086,7 @@ static int __init at91ether_probe(struct platform_device *pdev)
/* Clock */
lp->ether_clk = clk_get(&pdev->dev, "ether_clk");
if (IS_ERR(lp->ether_clk)) {
- res = -ENODEV;
+ res = PTR_ERR(lp->ether_clk);
goto err_ioumap;
}
clk_enable(lp->ether_clk);
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
index 5b622993..cf4c05b 100644
--- a/drivers/net/ethernet/emulex/benet/be.h
+++ b/drivers/net/ethernet/emulex/benet/be.h
@@ -337,7 +337,6 @@ struct phy_info {
u16 auto_speeds_supported;
u16 fixed_speeds_supported;
int link_speed;
- int forced_port_speed;
u32 dac_cable_len;
u32 advertising;
u32 supported;
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
index 701b3e9..af60bb2 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
@@ -165,14 +165,13 @@ static void be_async_grp5_cos_priority_process(struct be_adapter *adapter,
}
}
-/* Grp5 QOS Speed evt */
+/* Grp5 QOS Speed evt: qos_link_speed is in units of 10 Mbps */
static void be_async_grp5_qos_speed_process(struct be_adapter *adapter,
struct be_async_event_grp5_qos_link_speed *evt)
{
- if (evt->physical_port == adapter->port_num) {
- /* qos_link_speed is in units of 10 Mbps */
- adapter->phy.link_speed = evt->qos_link_speed * 10;
- }
+ if (adapter->phy.link_speed >= 0 &&
+ evt->physical_port == adapter->port_num)
+ adapter->phy.link_speed = le16_to_cpu(evt->qos_link_speed) * 10;
}
/*Grp5 PVID evt*/
@@ -717,7 +716,7 @@ int be_cmd_eq_create(struct be_adapter *adapter,
/* Use MCC */
int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr,
- u8 type, bool permanent, u32 if_handle, u32 pmac_id)
+ bool permanent, u32 if_handle, u32 pmac_id)
{
struct be_mcc_wrb *wrb;
struct be_cmd_req_mac_query *req;
@@ -734,7 +733,7 @@ int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr,
be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
OPCODE_COMMON_NTWK_MAC_QUERY, sizeof(*req), wrb, NULL);
- req->type = type;
+ req->type = MAC_ADDRESS_TYPE_NETWORK;
if (permanent) {
req->permanent = 1;
} else {
@@ -1326,9 +1325,28 @@ err:
return status;
}
-/* Uses synchronous mcc */
-int be_cmd_link_status_query(struct be_adapter *adapter, u8 *mac_speed,
- u16 *link_speed, u8 *link_status, u32 dom)
+static int be_mac_to_link_speed(int mac_speed)
+{
+ switch (mac_speed) {
+ case PHY_LINK_SPEED_ZERO:
+ return 0;
+ case PHY_LINK_SPEED_10MBPS:
+ return 10;
+ case PHY_LINK_SPEED_100MBPS:
+ return 100;
+ case PHY_LINK_SPEED_1GBPS:
+ return 1000;
+ case PHY_LINK_SPEED_10GBPS:
+ return 10000;
+ }
+ return 0;
+}
+
+/* Uses synchronous mcc
+ * Returns link_speed in Mbps
+ */
+int be_cmd_link_status_query(struct be_adapter *adapter, u16 *link_speed,
+ u8 *link_status, u32 dom)
{
struct be_mcc_wrb *wrb;
struct be_cmd_req_link_status *req;
@@ -1357,11 +1375,13 @@ int be_cmd_link_status_query(struct be_adapter *adapter, u8 *mac_speed,
status = be_mcc_notify_wait(adapter);
if (!status) {
struct be_cmd_resp_link_status *resp = embedded_payload(wrb);
- if (resp->mac_speed != PHY_LINK_SPEED_ZERO) {
- if (link_speed)
- *link_speed = le16_to_cpu(resp->link_speed);
- if (mac_speed)
- *mac_speed = resp->mac_speed;
+ if (link_speed) {
+ *link_speed = resp->link_speed ?
+ le16_to_cpu(resp->link_speed) * 10 :
+ be_mac_to_link_speed(resp->mac_speed);
+
+ if (!resp->logical_link_status)
+ *link_speed = 0;
}
if (link_status)
*link_status = resp->logical_link_status;
@@ -2405,6 +2425,9 @@ int be_cmd_req_native_mode(struct be_adapter *adapter)
struct be_cmd_resp_set_func_cap *resp = embedded_payload(wrb);
adapter->be3_native = le32_to_cpu(resp->cap_flags) &
CAPABILITY_BE3_NATIVE_ERX_API;
+ if (!adapter->be3_native)
+ dev_warn(&adapter->pdev->dev,
+ "adapter not in advanced mode\n");
}
err:
mutex_unlock(&adapter->mbox_lock);
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h
index 250f19b..0936e21 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.h
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.h
@@ -1687,7 +1687,7 @@ struct be_cmd_req_set_ext_fat_caps {
extern int be_pci_fnum_get(struct be_adapter *adapter);
extern int be_fw_wait_ready(struct be_adapter *adapter);
extern int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr,
- u8 type, bool permanent, u32 if_handle, u32 pmac_id);
+ bool permanent, u32 if_handle, u32 pmac_id);
extern int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr,
u32 if_id, u32 *pmac_id, u32 domain);
extern int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id,
@@ -1714,8 +1714,8 @@ extern int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q,
int type);
extern int be_cmd_rxq_destroy(struct be_adapter *adapter,
struct be_queue_info *q);
-extern int be_cmd_link_status_query(struct be_adapter *adapter, u8 *mac_speed,
- u16 *link_speed, u8 *link_status, u32 dom);
+extern int be_cmd_link_status_query(struct be_adapter *adapter, u16 *link_speed,
+ u8 *link_status, u32 dom);
extern int be_cmd_reset(struct be_adapter *adapter);
extern int be_cmd_get_stats(struct be_adapter *adapter,
struct be_dma_mem *nonemb_cmd);
diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c
index c0e7006..8e6fb0b 100644
--- a/drivers/net/ethernet/emulex/benet/be_ethtool.c
+++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c
@@ -512,28 +512,6 @@ static u32 convert_to_et_setting(u32 if_type, u32 if_speeds)
return val;
}
-static int convert_to_et_speed(u32 be_speed)
-{
- int et_speed = SPEED_10000;
-
- switch (be_speed) {
- case PHY_LINK_SPEED_10MBPS:
- et_speed = SPEED_10;
- break;
- case PHY_LINK_SPEED_100MBPS:
- et_speed = SPEED_100;
- break;
- case PHY_LINK_SPEED_1GBPS:
- et_speed = SPEED_1000;
- break;
- case PHY_LINK_SPEED_10GBPS:
- et_speed = SPEED_10000;
- break;
- }
-
- return et_speed;
-}
-
bool be_pause_supported(struct be_adapter *adapter)
{
return (adapter->phy.interface_type == PHY_TYPE_SFP_PLUS_10GB ||
@@ -544,27 +522,16 @@ bool be_pause_supported(struct be_adapter *adapter)
static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
{
struct be_adapter *adapter = netdev_priv(netdev);
- u8 port_speed = 0;
- u16 link_speed = 0;
u8 link_status;
- u32 et_speed = 0;
+ u16 link_speed = 0;
int status;
- if (adapter->phy.link_speed < 0 || !(netdev->flags & IFF_UP)) {
- if (adapter->phy.forced_port_speed < 0) {
- status = be_cmd_link_status_query(adapter, &port_speed,
- &link_speed, &link_status, 0);
- if (!status)
- be_link_status_update(adapter, link_status);
- if (link_speed)
- et_speed = link_speed * 10;
- else if (link_status)
- et_speed = convert_to_et_speed(port_speed);
- } else {
- et_speed = adapter->phy.forced_port_speed;
- }
-
- ethtool_cmd_speed_set(ecmd, et_speed);
+ if (adapter->phy.link_speed < 0) {
+ status = be_cmd_link_status_query(adapter, &link_speed,
+ &link_status, 0);
+ if (!status)
+ be_link_status_update(adapter, link_status);
+ ethtool_cmd_speed_set(ecmd, link_speed);
status = be_cmd_get_phy_info(adapter);
if (status)
@@ -773,8 +740,8 @@ static void
be_self_test(struct net_device *netdev, struct ethtool_test *test, u64 *data)
{
struct be_adapter *adapter = netdev_priv(netdev);
- u8 mac_speed = 0;
- u16 qos_link_speed = 0;
+ int status;
+ u8 link_status = 0;
memset(data, 0, sizeof(u64) * ETHTOOL_TESTS_NUM);
@@ -798,11 +765,11 @@ be_self_test(struct net_device *netdev, struct ethtool_test *test, u64 *data)
test->flags |= ETH_TEST_FL_FAILED;
}
- if (be_cmd_link_status_query(adapter, &mac_speed,
- &qos_link_speed, NULL, 0) != 0) {
+ status = be_cmd_link_status_query(adapter, NULL, &link_status, 0);
+ if (status) {
test->flags |= ETH_TEST_FL_FAILED;
data[4] = -1;
- } else if (!mac_speed) {
+ } else if (!link_status) {
test->flags |= ETH_TEST_FL_FAILED;
data[4] = 1;
}
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index 84379f4..6accb0c 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -241,9 +241,8 @@ static int be_mac_addr_set(struct net_device *netdev, void *p)
if (!is_valid_ether_addr(addr->sa_data))
return -EADDRNOTAVAIL;
- status = be_cmd_mac_addr_query(adapter, current_mac,
- MAC_ADDRESS_TYPE_NETWORK, false,
- adapter->if_handle, 0);
+ status = be_cmd_mac_addr_query(adapter, current_mac, false,
+ adapter->if_handle, 0);
if (status)
goto err;
@@ -1897,6 +1896,8 @@ static int be_tx_qs_create(struct be_adapter *adapter)
return status;
}
+ dev_info(&adapter->pdev->dev, "created %d TX queue(s)\n",
+ adapter->num_tx_qs);
return 0;
}
@@ -1947,10 +1948,9 @@ static int be_rx_cqs_create(struct be_adapter *adapter)
return rc;
}
- if (adapter->num_rx_qs != MAX_RX_QS)
- dev_info(&adapter->pdev->dev,
- "Created only %d receive queues\n", adapter->num_rx_qs);
-
+ dev_info(&adapter->pdev->dev,
+ "created %d RSS queue(s) and 1 default RX queue\n",
+ adapter->num_rx_qs - 1);
return 0;
}
@@ -2188,6 +2188,7 @@ static void be_msix_enable(struct be_adapter *adapter)
{
#define BE_MIN_MSIX_VECTORS 1
int i, status, num_vec, num_roce_vec = 0;
+ struct device *dev = &adapter->pdev->dev;
/* If RSS queues are not used, need a vec for default RX Q */
num_vec = min(be_num_rss_want(adapter), num_online_cpus());
@@ -2212,6 +2213,8 @@ static void be_msix_enable(struct be_adapter *adapter)
num_vec) == 0)
goto done;
}
+
+ dev_warn(dev, "MSIx enable failed\n");
return;
done:
if (be_roce_supported(adapter)) {
@@ -2225,6 +2228,7 @@ done:
}
} else
adapter->num_msix_vec = num_vec;
+ dev_info(dev, "enabled %d MSI-x vector(s)\n", adapter->num_msix_vec);
return;
}
@@ -2441,8 +2445,7 @@ static int be_open(struct net_device *netdev)
be_eq_notify(adapter, eqo->q.id, true, false, 0);
}
- status = be_cmd_link_status_query(adapter, NULL, NULL,
- &link_status, 0);
+ status = be_cmd_link_status_query(adapter, NULL, &link_status, 0);
if (!status)
be_link_status_update(adapter, link_status);
@@ -2671,7 +2674,6 @@ static void be_setup_init(struct be_adapter *adapter)
adapter->be3_native = false;
adapter->promiscuous = false;
adapter->eq_next_idx = 0;
- adapter->phy.forced_port_speed = -1;
}
static int be_get_mac_addr(struct be_adapter *adapter, u8 *mac, u32 if_handle,
@@ -2693,21 +2695,16 @@ static int be_get_mac_addr(struct be_adapter *adapter, u8 *mac, u32 if_handle,
status = be_cmd_get_mac_from_list(adapter, mac,
active_mac, pmac_id, 0);
if (*active_mac) {
- status = be_cmd_mac_addr_query(adapter, mac,
- MAC_ADDRESS_TYPE_NETWORK,
- false, if_handle,
- *pmac_id);
+ status = be_cmd_mac_addr_query(adapter, mac, false,
+ if_handle, *pmac_id);
}
} else if (be_physfn(adapter)) {
/* For BE3, for PF get permanent MAC */
- status = be_cmd_mac_addr_query(adapter, mac,
- MAC_ADDRESS_TYPE_NETWORK, true,
- 0, 0);
+ status = be_cmd_mac_addr_query(adapter, mac, true, 0, 0);
*active_mac = false;
} else {
/* For BE3, for VF get soft MAC assigned by PF*/
- status = be_cmd_mac_addr_query(adapter, mac,
- MAC_ADDRESS_TYPE_NETWORK, false,
+ status = be_cmd_mac_addr_query(adapter, mac, false,
if_handle, 0);
*active_mac = true;
}
@@ -3805,6 +3802,23 @@ static bool be_reset_required(struct be_adapter *adapter)
return be_find_vfs(adapter, ENABLED) > 0 ? false : true;
}
+static char *mc_name(struct be_adapter *adapter)
+{
+ if (adapter->function_mode & FLEX10_MODE)
+ return "FLEX10";
+ else if (adapter->function_mode & VNIC_MODE)
+ return "vNIC";
+ else if (adapter->function_mode & UMC_ENABLED)
+ return "UMC";
+ else
+ return "";
+}
+
+static inline char *func_name(struct be_adapter *adapter)
+{
+ return be_physfn(adapter) ? "PF" : "VF";
+}
+
static int __devinit be_probe(struct pci_dev *pdev,
const struct pci_device_id *pdev_id)
{
@@ -3895,7 +3909,7 @@ static int __devinit be_probe(struct pci_dev *pdev,
status = be_setup(adapter);
if (status)
- goto msix_disable;
+ goto stats_clean;
be_netdev_init(netdev);
status = register_netdev(netdev);
@@ -3909,15 +3923,13 @@ static int __devinit be_probe(struct pci_dev *pdev,
be_cmd_query_port_name(adapter, &port_name);
- dev_info(&pdev->dev, "%s: %s port %c\n", netdev->name, nic_name(pdev),
- port_name);
+ dev_info(&pdev->dev, "%s: %s %s port %c\n", nic_name(pdev),
+ func_name(adapter), mc_name(adapter), port_name);
return 0;
unsetup:
be_clear(adapter);
-msix_disable:
- be_msix_disable(adapter);
stats_clean:
be_stats_cleanup(adapter);
ctrl_clean:
diff --git a/drivers/net/ethernet/freescale/gianfar_ethtool.c b/drivers/net/ethernet/freescale/gianfar_ethtool.c
index 8971921..ab6762c 100644
--- a/drivers/net/ethernet/freescale/gianfar_ethtool.c
+++ b/drivers/net/ethernet/freescale/gianfar_ethtool.c
@@ -1773,6 +1773,7 @@ static int gfar_get_nfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
}
int gfar_phc_index = -1;
+EXPORT_SYMBOL(gfar_phc_index);
static int gfar_get_ts_info(struct net_device *dev,
struct ethtool_ts_info *info)
diff --git a/drivers/net/ethernet/freescale/gianfar_ptp.c b/drivers/net/ethernet/freescale/gianfar_ptp.c
index 18762a3..b9db0e0 100644
--- a/drivers/net/ethernet/freescale/gianfar_ptp.c
+++ b/drivers/net/ethernet/freescale/gianfar_ptp.c
@@ -515,7 +515,7 @@ static int gianfar_ptp_probe(struct platform_device *dev)
err = PTR_ERR(etsects->clock);
goto no_clock;
}
- gfar_phc_clock = ptp_clock_index(etsects->clock);
+ gfar_phc_index = ptp_clock_index(etsects->clock);
dev_set_drvdata(&dev->dev, etsects);
@@ -539,7 +539,7 @@ static int gianfar_ptp_remove(struct platform_device *dev)
gfar_write(&etsects->regs->tmr_temask, 0);
gfar_write(&etsects->regs->tmr_ctrl, 0);
- gfar_phc_clock = -1;
+ gfar_phc_index = -1;
ptp_clock_unregister(etsects->clock);
iounmap(etsects->regs);
release_resource(etsects->rsrc);
diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c
index 3a8368e..f9ac229 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_main.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_main.c
@@ -3150,6 +3150,17 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
return NETDEV_TX_OK;
}
+ /* On PCI/PCI-X HW, if packet size is less than ETH_ZLEN,
+ * packets may get corrupted during padding by HW.
+ * To WA this issue, pad all small packets manually.
+ */
+ if (skb->len < ETH_ZLEN) {
+ if (skb_pad(skb, ETH_ZLEN - skb->len))
+ return NETDEV_TX_OK;
+ skb->len = ETH_ZLEN;
+ skb_set_tail_pointer(skb, ETH_ZLEN);
+ }
+
mss = skb_shinfo(skb)->gso_size;
/* The controller does a simple calculation to
* make sure there is enough room in the FIFO before
diff --git a/drivers/net/ethernet/mellanox/mlx4/icm.c b/drivers/net/ethernet/mellanox/mlx4/icm.c
index daf4179..31d0264 100644
--- a/drivers/net/ethernet/mellanox/mlx4/icm.c
+++ b/drivers/net/ethernet/mellanox/mlx4/icm.c
@@ -227,9 +227,10 @@ int mlx4_UNMAP_ICM_AUX(struct mlx4_dev *dev)
MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
}
-int mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj)
+int mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, u32 obj)
{
- int i = (obj & (table->num_obj - 1)) / (MLX4_TABLE_CHUNK_SIZE / table->obj_size);
+ u32 i = (obj & (table->num_obj - 1)) /
+ (MLX4_TABLE_CHUNK_SIZE / table->obj_size);
int ret = 0;
mutex_lock(&table->mutex);
@@ -262,16 +263,18 @@ out:
return ret;
}
-void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj)
+void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, u32 obj)
{
- int i;
+ u32 i;
+ u64 offset;
i = (obj & (table->num_obj - 1)) / (MLX4_TABLE_CHUNK_SIZE / table->obj_size);
mutex_lock(&table->mutex);
if (--table->icm[i]->refcount == 0) {
- mlx4_UNMAP_ICM(dev, table->virt + i * MLX4_TABLE_CHUNK_SIZE,
+ offset = (u64) i * MLX4_TABLE_CHUNK_SIZE;
+ mlx4_UNMAP_ICM(dev, table->virt + offset,
MLX4_TABLE_CHUNK_SIZE / MLX4_ICM_PAGE_SIZE);
mlx4_free_icm(dev, table->icm[i], table->coherent);
table->icm[i] = NULL;
@@ -280,9 +283,11 @@ void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj)
mutex_unlock(&table->mutex);
}
-void *mlx4_table_find(struct mlx4_icm_table *table, int obj, dma_addr_t *dma_handle)
+void *mlx4_table_find(struct mlx4_icm_table *table, u32 obj,
+ dma_addr_t *dma_handle)
{
- int idx, offset, dma_offset, i;
+ int offset, dma_offset, i;
+ u64 idx;
struct mlx4_icm_chunk *chunk;
struct mlx4_icm *icm;
struct page *page = NULL;
@@ -292,7 +297,7 @@ void *mlx4_table_find(struct mlx4_icm_table *table, int obj, dma_addr_t *dma_han
mutex_lock(&table->mutex);
- idx = (obj & (table->num_obj - 1)) * table->obj_size;
+ idx = (u64) (obj & (table->num_obj - 1)) * table->obj_size;
icm = table->icm[idx / MLX4_TABLE_CHUNK_SIZE];
dma_offset = offset = idx % MLX4_TABLE_CHUNK_SIZE;
@@ -326,10 +331,11 @@ out:
}
int mlx4_table_get_range(struct mlx4_dev *dev, struct mlx4_icm_table *table,
- int start, int end)
+ u32 start, u32 end)
{
int inc = MLX4_TABLE_CHUNK_SIZE / table->obj_size;
- int i, err;
+ int err;
+ u32 i;
for (i = start; i <= end; i += inc) {
err = mlx4_table_get(dev, table, i);
@@ -349,9 +355,9 @@ fail:
}
void mlx4_table_put_range(struct mlx4_dev *dev, struct mlx4_icm_table *table,
- int start, int end)
+ u32 start, u32 end)
{
- int i;
+ u32 i;
for (i = start; i <= end; i += MLX4_TABLE_CHUNK_SIZE / table->obj_size)
mlx4_table_put(dev, table, i);
diff --git a/drivers/net/ethernet/mellanox/mlx4/icm.h b/drivers/net/ethernet/mellanox/mlx4/icm.h
index a67744f..dee67fa 100644
--- a/drivers/net/ethernet/mellanox/mlx4/icm.h
+++ b/drivers/net/ethernet/mellanox/mlx4/icm.h
@@ -71,17 +71,17 @@ struct mlx4_icm *mlx4_alloc_icm(struct mlx4_dev *dev, int npages,
gfp_t gfp_mask, int coherent);
void mlx4_free_icm(struct mlx4_dev *dev, struct mlx4_icm *icm, int coherent);
-int mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj);
-void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj);
+int mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, u32 obj);
+void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, u32 obj);
int mlx4_table_get_range(struct mlx4_dev *dev, struct mlx4_icm_table *table,
- int start, int end);
+ u32 start, u32 end);
void mlx4_table_put_range(struct mlx4_dev *dev, struct mlx4_icm_table *table,
- int start, int end);
+ u32 start, u32 end);
int mlx4_init_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table,
u64 virt, int obj_size, u32 nobj, int reserved,
int use_lowmem, int use_coherent);
void mlx4_cleanup_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table);
-void *mlx4_table_find(struct mlx4_icm_table *table, int obj, dma_addr_t *dma_handle);
+void *mlx4_table_find(struct mlx4_icm_table *table, u32 obj, dma_addr_t *dma_handle);
static inline void mlx4_icm_first(struct mlx4_icm *icm,
struct mlx4_icm_iter *iter)
diff --git a/drivers/net/ethernet/octeon/octeon_mgmt.c b/drivers/net/ethernet/octeon/octeon_mgmt.c
index c42bbb1..a688a2d 100644
--- a/drivers/net/ethernet/octeon/octeon_mgmt.c
+++ b/drivers/net/ethernet/octeon/octeon_mgmt.c
@@ -722,10 +722,8 @@ static int octeon_mgmt_init_phy(struct net_device *netdev)
octeon_mgmt_adjust_link, 0,
PHY_INTERFACE_MODE_MII);
- if (IS_ERR(p->phydev)) {
- p->phydev = NULL;
+ if (!p->phydev)
return -1;
- }
phy_start_aneg(p->phydev);
diff --git a/drivers/net/ethernet/pasemi/pasemi_mac.c b/drivers/net/ethernet/pasemi/pasemi_mac.c
index e559dfa..6fa74d5 100644
--- a/drivers/net/ethernet/pasemi/pasemi_mac.c
+++ b/drivers/net/ethernet/pasemi/pasemi_mac.c
@@ -1101,9 +1101,9 @@ static int pasemi_mac_phy_init(struct net_device *dev)
phydev = of_phy_connect(dev, phy_dn, &pasemi_adjust_link, 0,
PHY_INTERFACE_MODE_SGMII);
- if (IS_ERR(phydev)) {
+ if (!phydev) {
printk(KERN_ERR "%s: Could not attach to phy\n", dev->name);
- return PTR_ERR(phydev);
+ return -ENODEV;
}
mac->phydev = phydev;
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
index 342b3a7..a77c558 100644
--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
@@ -1378,6 +1378,10 @@ static void netxen_mask_aer_correctable(struct netxen_adapter *adapter)
struct pci_dev *root = pdev->bus->self;
u32 aer_pos;
+ /* root bus? */
+ if (!root)
+ return;
+
if (adapter->ahw.board_type != NETXEN_BRDTYPE_P3_4_GB_MM &&
adapter->ahw.board_type != NETXEN_BRDTYPE_P3_10G_TP)
return;
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
index b8ead69..2a179d0 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
@@ -15,7 +15,7 @@ qlcnic_poll_rsp(struct qlcnic_adapter *adapter)
do {
/* give atleast 1ms for firmware to respond */
- msleep(1);
+ mdelay(1);
if (++timeout > QLCNIC_OS_CRB_RETRY_COUNT)
return QLCNIC_CDRP_RSP_TIMEOUT;
@@ -601,7 +601,7 @@ void qlcnic_fw_destroy_ctx(struct qlcnic_adapter *adapter)
qlcnic_fw_cmd_destroy_tx_ctx(adapter);
/* Allow dma queues to drain after context reset */
- msleep(20);
+ mdelay(20);
}
}
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index c136162..3be8833 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -1066,7 +1066,7 @@ static int stmmac_open(struct net_device *dev)
} else
priv->tm->enable = 1;
#endif
- clk_enable(priv->stmmac_clk);
+ clk_prepare_enable(priv->stmmac_clk);
stmmac_check_ether_addr(priv);
@@ -1188,7 +1188,7 @@ open_error:
if (priv->phydev)
phy_disconnect(priv->phydev);
- clk_disable(priv->stmmac_clk);
+ clk_disable_unprepare(priv->stmmac_clk);
return ret;
}
@@ -1246,7 +1246,7 @@ static int stmmac_release(struct net_device *dev)
#ifdef CONFIG_STMMAC_DEBUG_FS
stmmac_exit_fs();
#endif
- clk_disable(priv->stmmac_clk);
+ clk_disable_unprepare(priv->stmmac_clk);
return 0;
}
@@ -2178,7 +2178,7 @@ int stmmac_suspend(struct net_device *ndev)
else {
stmmac_set_mac(priv->ioaddr, false);
/* Disable clock in case of PWM is off */
- clk_disable(priv->stmmac_clk);
+ clk_disable_unprepare(priv->stmmac_clk);
}
spin_unlock_irqrestore(&priv->lock, flags);
return 0;
@@ -2203,7 +2203,7 @@ int stmmac_resume(struct net_device *ndev)
priv->hw->mac->pmt(priv->ioaddr, 0);
else
/* enable the clk prevously disabled */
- clk_enable(priv->stmmac_clk);
+ clk_prepare_enable(priv->stmmac_clk);
netif_device_attach(ndev);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.c
index 2a0e1ab..4ccd4e2 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.c
@@ -97,19 +97,19 @@ static struct clk *timer_clock;
static void stmmac_tmu_start(unsigned int new_freq)
{
clk_set_rate(timer_clock, new_freq);
- clk_enable(timer_clock);
+ clk_prepare_enable(timer_clock);
}
static void stmmac_tmu_stop(void)
{
- clk_disable(timer_clock);
+ clk_disable_unprepare(timer_clock);
}
int stmmac_open_ext_timer(struct net_device *dev, struct stmmac_timer *tm)
{
timer_clock = clk_get(NULL, TMU_CHANNEL);
- if (timer_clock == NULL)
+ if (IS_ERR(timer_clock))
return -1;
if (tmu2_register_user(stmmac_timer_handler, (void *)dev) < 0) {
@@ -126,7 +126,7 @@ int stmmac_open_ext_timer(struct net_device *dev, struct stmmac_timer *tm)
int stmmac_close_ext_timer(void)
{
- clk_disable(timer_clock);
+ clk_disable_unprepare(timer_clock);
tmu2_unregister_user();
clk_put(timer_clock);
return 0;
diff --git a/drivers/net/irda/sh_sir.c b/drivers/net/irda/sh_sir.c
index 256eddf..7951094 100644
--- a/drivers/net/irda/sh_sir.c
+++ b/drivers/net/irda/sh_sir.c
@@ -280,7 +280,7 @@ static int sh_sir_set_baudrate(struct sh_sir_self *self, u32 baudrate)
}
clk = clk_get(NULL, "irda_clk");
- if (!clk) {
+ if (IS_ERR(clk)) {
dev_err(dev, "can not get irda_clk\n");
return -EIO;
}
diff --git a/drivers/net/phy/bcm87xx.c b/drivers/net/phy/bcm87xx.c
index 2346b38..7997895 100644
--- a/drivers/net/phy/bcm87xx.c
+++ b/drivers/net/phy/bcm87xx.c
@@ -229,3 +229,5 @@ static void __exit bcm87xx_exit(void)
ARRAY_SIZE(bcm87xx_driver));
}
module_exit(bcm87xx_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index cf287e0..2165d5f 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -21,6 +21,12 @@
#include <linux/phy.h>
#include <linux/micrel_phy.h>
+/* Operation Mode Strap Override */
+#define MII_KSZPHY_OMSO 0x16
+#define KSZPHY_OMSO_B_CAST_OFF (1 << 9)
+#define KSZPHY_OMSO_RMII_OVERRIDE (1 << 1)
+#define KSZPHY_OMSO_MII_OVERRIDE (1 << 0)
+
/* general Interrupt control/status reg in vendor specific block. */
#define MII_KSZPHY_INTCS 0x1B
#define KSZPHY_INTCS_JABBER (1 << 15)
@@ -101,6 +107,13 @@ static int kszphy_config_init(struct phy_device *phydev)
return 0;
}
+static int ksz8021_config_init(struct phy_device *phydev)
+{
+ const u16 val = KSZPHY_OMSO_B_CAST_OFF | KSZPHY_OMSO_RMII_OVERRIDE;
+ phy_write(phydev, MII_KSZPHY_OMSO, val);
+ return 0;
+}
+
static int ks8051_config_init(struct phy_device *phydev)
{
int regval;
@@ -128,9 +141,22 @@ static struct phy_driver ksphy_driver[] = {
.config_intr = ks8737_config_intr,
.driver = { .owner = THIS_MODULE,},
}, {
- .phy_id = PHY_ID_KS8041,
+ .phy_id = PHY_ID_KSZ8021,
+ .phy_id_mask = 0x00ffffff,
+ .name = "Micrel KSZ8021",
+ .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause |
+ SUPPORTED_Asym_Pause),
+ .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
+ .config_init = ksz8021_config_init,
+ .config_aneg = genphy_config_aneg,
+ .read_status = genphy_read_status,
+ .ack_interrupt = kszphy_ack_interrupt,
+ .config_intr = kszphy_config_intr,
+ .driver = { .owner = THIS_MODULE,},
+}, {
+ .phy_id = PHY_ID_KSZ8041,
.phy_id_mask = 0x00fffff0,
- .name = "Micrel KS8041",
+ .name = "Micrel KSZ8041",
.features = (PHY_BASIC_FEATURES | SUPPORTED_Pause
| SUPPORTED_Asym_Pause),
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
@@ -141,9 +167,9 @@ static struct phy_driver ksphy_driver[] = {
.config_intr = kszphy_config_intr,
.driver = { .owner = THIS_MODULE,},
}, {
- .phy_id = PHY_ID_KS8051,
+ .phy_id = PHY_ID_KSZ8051,
.phy_id_mask = 0x00fffff0,
- .name = "Micrel KS8051",
+ .name = "Micrel KSZ8051",
.features = (PHY_BASIC_FEATURES | SUPPORTED_Pause
| SUPPORTED_Asym_Pause),
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
@@ -154,8 +180,8 @@ static struct phy_driver ksphy_driver[] = {
.config_intr = kszphy_config_intr,
.driver = { .owner = THIS_MODULE,},
}, {
- .phy_id = PHY_ID_KS8001,
- .name = "Micrel KS8001 or KS8721",
+ .phy_id = PHY_ID_KSZ8001,
+ .name = "Micrel KSZ8001 or KS8721",
.phy_id_mask = 0x00ffffff,
.features = (PHY_BASIC_FEATURES | SUPPORTED_Pause),
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
@@ -201,10 +227,11 @@ MODULE_LICENSE("GPL");
static struct mdio_device_id __maybe_unused micrel_tbl[] = {
{ PHY_ID_KSZ9021, 0x000ffffe },
- { PHY_ID_KS8001, 0x00ffffff },
+ { PHY_ID_KSZ8001, 0x00ffffff },
{ PHY_ID_KS8737, 0x00fffff0 },
- { PHY_ID_KS8041, 0x00fffff0 },
- { PHY_ID_KS8051, 0x00fffff0 },
+ { PHY_ID_KSZ8021, 0x00ffffff },
+ { PHY_ID_KSZ8041, 0x00fffff0 },
+ { PHY_ID_KSZ8051, 0x00fffff0 },
{ }
};
diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c
index 6d61923..88e3991 100644
--- a/drivers/net/phy/smsc.c
+++ b/drivers/net/phy/smsc.c
@@ -56,6 +56,32 @@ static int smsc_phy_config_init(struct phy_device *phydev)
return smsc_phy_ack_interrupt (phydev);
}
+static int lan87xx_config_init(struct phy_device *phydev)
+{
+ /*
+ * Make sure the EDPWRDOWN bit is NOT set. Setting this bit on
+ * LAN8710/LAN8720 PHY causes the PHY to misbehave, likely due
+ * to a bug on the chip.
+ *
+ * When the system is powered on with the network cable being
+ * disconnected all the way until after ifconfig ethX up is
+ * issued for the LAN port with this PHY, connecting the cable
+ * afterwards does not cause LINK change detection, while the
+ * expected behavior is the Link UP being detected.
+ */
+ int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
+ if (rc < 0)
+ return rc;
+
+ rc &= ~MII_LAN83C185_EDPWRDOWN;
+
+ rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS, rc);
+ if (rc < 0)
+ return rc;
+
+ return smsc_phy_ack_interrupt(phydev);
+}
+
static int lan911x_config_init(struct phy_device *phydev)
{
return smsc_phy_ack_interrupt(phydev);
@@ -162,7 +188,7 @@ static struct phy_driver smsc_phy_driver[] = {
/* basic functions */
.config_aneg = genphy_config_aneg,
.read_status = genphy_read_status,
- .config_init = smsc_phy_config_init,
+ .config_init = lan87xx_config_init,
/* IRQ related */
.ack_interrupt = smsc_phy_ack_interrupt,
diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c
index cbf7047..20f31d0 100644
--- a/drivers/net/ppp/pppoe.c
+++ b/drivers/net/ppp/pppoe.c
@@ -570,7 +570,7 @@ static int pppoe_release(struct socket *sock)
po = pppox_sk(sk);
- if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND)) {
+ if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND | PPPOX_ZOMBIE)) {
dev_put(po->pppoe_dev);
po->pppoe_dev = NULL;
}
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index 9ce0c51..5c7547c 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -967,7 +967,6 @@ static struct netpoll_info *team_netpoll_info(struct team *team)
#endif
static void __team_port_change_port_added(struct team_port *port, bool linkup);
-
static int team_dev_type_check_change(struct net_device *dev,
struct net_device *port_dev);
@@ -1890,8 +1889,8 @@ static int team_nl_cmd_noop(struct sk_buff *skb, struct genl_info *info)
hdr = genlmsg_put(msg, info->snd_portid, info->snd_seq,
&team_nl_family, 0, TEAM_CMD_NOOP);
- if (IS_ERR(hdr)) {
- err = PTR_ERR(hdr);
+ if (!hdr) {
+ err = -EMSGSIZE;
goto err_msg_put;
}
@@ -2091,8 +2090,8 @@ start_again:
hdr = genlmsg_put(skb, portid, seq, &team_nl_family, flags | NLM_F_MULTI,
TEAM_CMD_OPTIONS_GET);
- if (IS_ERR(hdr))
- return PTR_ERR(hdr);
+ if (!hdr)
+ return -EMSGSIZE;
if (nla_put_u32(skb, TEAM_ATTR_TEAM_IFINDEX, team->dev->ifindex))
goto nla_put_failure;
@@ -2317,8 +2316,8 @@ static int team_nl_fill_port_list_get(struct sk_buff *skb,
hdr = genlmsg_put(skb, portid, seq, &team_nl_family, flags,
TEAM_CMD_PORT_LIST_GET);
- if (IS_ERR(hdr))
- return PTR_ERR(hdr);
+ if (!hdr)
+ return -EMSGSIZE;
if (nla_put_u32(skb, TEAM_ATTR_TEAM_IFINDEX, team->dev->ifindex))
goto nla_put_failure;
diff --git a/drivers/net/usb/asix_devices.c b/drivers/net/usb/asix_devices.c
index 8d5fdf1..1df77f2 100644
--- a/drivers/net/usb/asix_devices.c
+++ b/drivers/net/usb/asix_devices.c
@@ -966,6 +966,10 @@ static const struct usb_device_id products [] = {
USB_DEVICE (0x2001, 0x3c05),
.driver_info = (unsigned long) &ax88772_info,
}, {
+ // DLink DUB-E100 H/W Ver C1
+ USB_DEVICE (0x2001, 0x1a02),
+ .driver_info = (unsigned long) &ax88772_info,
+}, {
// Linksys USB1000
USB_DEVICE (0x1737, 0x0039),
.driver_info = (unsigned long) &ax88178_info,
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index ca25320..6883c37 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -353,7 +353,7 @@ static const struct usb_device_id products[] = {
},
/* 2. Combined interface devices matching on class+protocol */
- { /* Huawei E367 and possibly others in "Windows mode" */
+ { /* Huawei E367 and possibly others in "Windows mode" */
USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 1, 7),
.driver_info = (unsigned long)&qmi_wwan_info,
},
@@ -361,7 +361,7 @@ static const struct usb_device_id products[] = {
USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 1, 17),
.driver_info = (unsigned long)&qmi_wwan_info,
},
- { /* Pantech UML290, P4200 and more */
+ { /* Pantech UML290, P4200 and more */
USB_VENDOR_AND_INTERFACE_INFO(0x106c, USB_CLASS_VENDOR_SPEC, 0xf0, 0xff),
.driver_info = (unsigned long)&qmi_wwan_info,
},
diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c
index f5ab6e6..b77ae76 100644
--- a/drivers/net/usb/smsc75xx.c
+++ b/drivers/net/usb/smsc75xx.c
@@ -52,6 +52,7 @@
#define USB_PRODUCT_ID_LAN7500 (0x7500)
#define USB_PRODUCT_ID_LAN7505 (0x7505)
#define RXW_PADDING 2
+#define SUPPORTED_WAKE (WAKE_MAGIC)
#define check_warn(ret, fmt, args...) \
({ if (ret < 0) netdev_warn(dev->net, fmt, ##args); })
@@ -65,6 +66,7 @@
struct smsc75xx_priv {
struct usbnet *dev;
u32 rfe_ctl;
+ u32 wolopts;
u32 multicast_hash_table[DP_SEL_VHF_HASH_LEN];
struct mutex dataport_mutex;
spinlock_t rfe_ctl_lock;
@@ -135,6 +137,30 @@ static int __must_check smsc75xx_write_reg(struct usbnet *dev, u32 index,
return ret;
}
+static int smsc75xx_set_feature(struct usbnet *dev, u32 feature)
+{
+ if (WARN_ON_ONCE(!dev))
+ return -EINVAL;
+
+ cpu_to_le32s(&feature);
+
+ return usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
+ USB_REQ_SET_FEATURE, USB_RECIP_DEVICE, feature, 0, NULL, 0,
+ USB_CTRL_SET_TIMEOUT);
+}
+
+static int smsc75xx_clear_feature(struct usbnet *dev, u32 feature)
+{
+ if (WARN_ON_ONCE(!dev))
+ return -EINVAL;
+
+ cpu_to_le32s(&feature);
+
+ return usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
+ USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE, feature, 0, NULL, 0,
+ USB_CTRL_SET_TIMEOUT);
+}
+
/* Loop until the read is completed with timeout
* called with phy_mutex held */
static int smsc75xx_phy_wait_not_busy(struct usbnet *dev)
@@ -578,6 +604,26 @@ static int smsc75xx_ethtool_set_eeprom(struct net_device *netdev,
return smsc75xx_write_eeprom(dev, ee->offset, ee->len, data);
}
+static void smsc75xx_ethtool_get_wol(struct net_device *net,
+ struct ethtool_wolinfo *wolinfo)
+{
+ struct usbnet *dev = netdev_priv(net);
+ struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
+
+ wolinfo->supported = SUPPORTED_WAKE;
+ wolinfo->wolopts = pdata->wolopts;
+}
+
+static int smsc75xx_ethtool_set_wol(struct net_device *net,
+ struct ethtool_wolinfo *wolinfo)
+{
+ struct usbnet *dev = netdev_priv(net);
+ struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
+
+ pdata->wolopts = wolinfo->wolopts & SUPPORTED_WAKE;
+ return 0;
+}
+
static const struct ethtool_ops smsc75xx_ethtool_ops = {
.get_link = usbnet_get_link,
.nway_reset = usbnet_nway_reset,
@@ -589,6 +635,8 @@ static const struct ethtool_ops smsc75xx_ethtool_ops = {
.get_eeprom_len = smsc75xx_ethtool_get_eeprom_len,
.get_eeprom = smsc75xx_ethtool_get_eeprom,
.set_eeprom = smsc75xx_ethtool_set_eeprom,
+ .get_wol = smsc75xx_ethtool_get_wol,
+ .set_wol = smsc75xx_ethtool_set_wol,
};
static int smsc75xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
@@ -756,6 +804,26 @@ static int smsc75xx_set_features(struct net_device *netdev,
return 0;
}
+static int smsc75xx_wait_ready(struct usbnet *dev)
+{
+ int timeout = 0;
+
+ do {
+ u32 buf;
+ int ret = smsc75xx_read_reg(dev, PMT_CTL, &buf);
+ check_warn_return(ret, "Failed to read PMT_CTL: %d", ret);
+
+ if (buf & PMT_CTL_DEV_RDY)
+ return 0;
+
+ msleep(10);
+ timeout++;
+ } while (timeout < 100);
+
+ netdev_warn(dev->net, "timeout waiting for device ready");
+ return -EIO;
+}
+
static int smsc75xx_reset(struct usbnet *dev)
{
struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
@@ -764,6 +832,9 @@ static int smsc75xx_reset(struct usbnet *dev)
netif_dbg(dev, ifup, dev->net, "entering smsc75xx_reset");
+ ret = smsc75xx_wait_ready(dev);
+ check_warn_return(ret, "device not ready in smsc75xx_reset");
+
ret = smsc75xx_read_reg(dev, HW_CFG, &buf);
check_warn_return(ret, "Failed to read HW_CFG: %d", ret);
@@ -1083,6 +1154,169 @@ static void smsc75xx_unbind(struct usbnet *dev, struct usb_interface *intf)
}
}
+static int smsc75xx_suspend(struct usb_interface *intf, pm_message_t message)
+{
+ struct usbnet *dev = usb_get_intfdata(intf);
+ struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
+ int ret;
+ u32 val;
+
+ ret = usbnet_suspend(intf, message);
+ check_warn_return(ret, "usbnet_suspend error");
+
+ /* if no wol options set, enter lowest power SUSPEND2 mode */
+ if (!(pdata->wolopts & SUPPORTED_WAKE)) {
+ netdev_info(dev->net, "entering SUSPEND2 mode");
+
+ /* disable energy detect (link up) & wake up events */
+ ret = smsc75xx_read_reg(dev, WUCSR, &val);
+ check_warn_return(ret, "Error reading WUCSR");
+
+ val &= ~(WUCSR_MPEN | WUCSR_WUEN);
+
+ ret = smsc75xx_write_reg(dev, WUCSR, val);
+ check_warn_return(ret, "Error writing WUCSR");
+
+ ret = smsc75xx_read_reg(dev, PMT_CTL, &val);
+ check_warn_return(ret, "Error reading PMT_CTL");
+
+ val &= ~(PMT_CTL_ED_EN | PMT_CTL_WOL_EN);
+
+ ret = smsc75xx_write_reg(dev, PMT_CTL, val);
+ check_warn_return(ret, "Error writing PMT_CTL");
+
+ /* enter suspend2 mode */
+ ret = smsc75xx_read_reg(dev, PMT_CTL, &val);
+ check_warn_return(ret, "Error reading PMT_CTL");
+
+ val &= ~(PMT_CTL_SUS_MODE | PMT_CTL_WUPS | PMT_CTL_PHY_RST);
+ val |= PMT_CTL_SUS_MODE_2;
+
+ ret = smsc75xx_write_reg(dev, PMT_CTL, val);
+ check_warn_return(ret, "Error writing PMT_CTL");
+
+ return 0;
+ }
+
+ if (pdata->wolopts & WAKE_MAGIC) {
+ /* clear any pending magic packet status */
+ ret = smsc75xx_read_reg(dev, WUCSR, &val);
+ check_warn_return(ret, "Error reading WUCSR");
+
+ val |= WUCSR_MPR;
+
+ ret = smsc75xx_write_reg(dev, WUCSR, val);
+ check_warn_return(ret, "Error writing WUCSR");
+ }
+
+ /* enable/disable magic packup wake */
+ ret = smsc75xx_read_reg(dev, WUCSR, &val);
+ check_warn_return(ret, "Error reading WUCSR");
+
+ if (pdata->wolopts & WAKE_MAGIC) {
+ netdev_info(dev->net, "enabling magic packet wakeup");
+ val |= WUCSR_MPEN;
+ } else {
+ netdev_info(dev->net, "disabling magic packet wakeup");
+ val &= ~WUCSR_MPEN;
+ }
+
+ ret = smsc75xx_write_reg(dev, WUCSR, val);
+ check_warn_return(ret, "Error writing WUCSR");
+
+ /* enable wol wakeup source */
+ ret = smsc75xx_read_reg(dev, PMT_CTL, &val);
+ check_warn_return(ret, "Error reading PMT_CTL");
+
+ val |= PMT_CTL_WOL_EN;
+
+ ret = smsc75xx_write_reg(dev, PMT_CTL, val);
+ check_warn_return(ret, "Error writing PMT_CTL");
+
+ /* enable receiver */
+ ret = smsc75xx_read_reg(dev, MAC_RX, &val);
+ check_warn_return(ret, "Failed to read MAC_RX: %d", ret);
+
+ val |= MAC_RX_RXEN;
+
+ ret = smsc75xx_write_reg(dev, MAC_RX, val);
+ check_warn_return(ret, "Failed to write MAC_RX: %d", ret);
+
+ /* some wol options are enabled, so enter SUSPEND0 */
+ netdev_info(dev->net, "entering SUSPEND0 mode");
+
+ ret = smsc75xx_read_reg(dev, PMT_CTL, &val);
+ check_warn_return(ret, "Error reading PMT_CTL");
+
+ val &= (~(PMT_CTL_SUS_MODE | PMT_CTL_WUPS | PMT_CTL_PHY_RST));
+ val |= PMT_CTL_SUS_MODE_0;
+
+ ret = smsc75xx_write_reg(dev, PMT_CTL, val);
+ check_warn_return(ret, "Error writing PMT_CTL");
+
+ /* clear wol status */
+ val &= ~PMT_CTL_WUPS;
+ val |= PMT_CTL_WUPS_WOL;
+ ret = smsc75xx_write_reg(dev, PMT_CTL, val);
+ check_warn_return(ret, "Error writing PMT_CTL");
+
+ /* read back PMT_CTL */
+ ret = smsc75xx_read_reg(dev, PMT_CTL, &val);
+ check_warn_return(ret, "Error reading PMT_CTL");
+
+ smsc75xx_set_feature(dev, USB_DEVICE_REMOTE_WAKEUP);
+
+ return 0;
+}
+
+static int smsc75xx_resume(struct usb_interface *intf)
+{
+ struct usbnet *dev = usb_get_intfdata(intf);
+ struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
+ int ret;
+ u32 val;
+
+ if (pdata->wolopts & WAKE_MAGIC) {
+ netdev_info(dev->net, "resuming from SUSPEND0");
+
+ smsc75xx_clear_feature(dev, USB_DEVICE_REMOTE_WAKEUP);
+
+ /* Disable magic packup wake */
+ ret = smsc75xx_read_reg(dev, WUCSR, &val);
+ check_warn_return(ret, "Error reading WUCSR");
+
+ val &= ~WUCSR_MPEN;
+
+ ret = smsc75xx_write_reg(dev, WUCSR, val);
+ check_warn_return(ret, "Error writing WUCSR");
+
+ /* clear wake-up status */
+ ret = smsc75xx_read_reg(dev, PMT_CTL, &val);
+ check_warn_return(ret, "Error reading PMT_CTL");
+
+ val &= ~PMT_CTL_WOL_EN;
+ val |= PMT_CTL_WUPS;
+
+ ret = smsc75xx_write_reg(dev, PMT_CTL, val);
+ check_warn_return(ret, "Error writing PMT_CTL");
+ } else {
+ netdev_info(dev->net, "resuming from SUSPEND2");
+
+ ret = smsc75xx_read_reg(dev, PMT_CTL, &val);
+ check_warn_return(ret, "Error reading PMT_CTL");
+
+ val |= PMT_CTL_PHY_PWRUP;
+
+ ret = smsc75xx_write_reg(dev, PMT_CTL, val);
+ check_warn_return(ret, "Error writing PMT_CTL");
+ }
+
+ ret = smsc75xx_wait_ready(dev);
+ check_warn_return(ret, "device not ready in smsc75xx_resume");
+
+ return usbnet_resume(intf);
+}
+
static void smsc75xx_rx_csum_offload(struct usbnet *dev, struct sk_buff *skb,
u32 rx_cmd_a, u32 rx_cmd_b)
{
@@ -1251,8 +1485,9 @@ static struct usb_driver smsc75xx_driver = {
.name = SMSC_CHIPNAME,
.id_table = products,
.probe = usbnet_probe,
- .suspend = usbnet_suspend,
- .resume = usbnet_resume,
+ .suspend = smsc75xx_suspend,
+ .resume = smsc75xx_resume,
+ .reset_resume = smsc75xx_resume,
.disconnect = usbnet_disconnect,
.disable_hub_initiated_lpm = 1,
};
diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
index d45e539..7479a57 100644
--- a/drivers/net/usb/smsc95xx.c
+++ b/drivers/net/usb/smsc95xx.c
@@ -46,11 +46,22 @@
#define SMSC95XX_INTERNAL_PHY_ID (1)
#define SMSC95XX_TX_OVERHEAD (8)
#define SMSC95XX_TX_OVERHEAD_CSUM (12)
+#define SUPPORTED_WAKE (WAKE_MAGIC)
+
+#define check_warn(ret, fmt, args...) \
+ ({ if (ret < 0) netdev_warn(dev->net, fmt, ##args); })
+
+#define check_warn_return(ret, fmt, args...) \
+ ({ if (ret < 0) { netdev_warn(dev->net, fmt, ##args); return ret; } })
+
+#define check_warn_goto_done(ret, fmt, args...) \
+ ({ if (ret < 0) { netdev_warn(dev->net, fmt, ##args); goto done; } })
struct smsc95xx_priv {
u32 mac_cr;
u32 hash_hi;
u32 hash_lo;
+ u32 wolopts;
spinlock_t mac_cr_lock;
};
@@ -63,7 +74,8 @@ static bool turbo_mode = true;
module_param(turbo_mode, bool, 0644);
MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction");
-static int smsc95xx_read_reg(struct usbnet *dev, u32 index, u32 *data)
+static int __must_check smsc95xx_read_reg(struct usbnet *dev, u32 index,
+ u32 *data)
{
u32 *buf = kmalloc(4, GFP_KERNEL);
int ret;
@@ -88,7 +100,8 @@ static int smsc95xx_read_reg(struct usbnet *dev, u32 index, u32 *data)
return ret;
}
-static int smsc95xx_write_reg(struct usbnet *dev, u32 index, u32 data)
+static int __must_check smsc95xx_write_reg(struct usbnet *dev, u32 index,
+ u32 data)
{
u32 *buf = kmalloc(4, GFP_KERNEL);
int ret;
@@ -114,15 +127,41 @@ static int smsc95xx_write_reg(struct usbnet *dev, u32 index, u32 data)
return ret;
}
+static int smsc95xx_set_feature(struct usbnet *dev, u32 feature)
+{
+ if (WARN_ON_ONCE(!dev))
+ return -EINVAL;
+
+ cpu_to_le32s(&feature);
+
+ return usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
+ USB_REQ_SET_FEATURE, USB_RECIP_DEVICE, feature, 0, NULL, 0,
+ USB_CTRL_SET_TIMEOUT);
+}
+
+static int smsc95xx_clear_feature(struct usbnet *dev, u32 feature)
+{
+ if (WARN_ON_ONCE(!dev))
+ return -EINVAL;
+
+ cpu_to_le32s(&feature);
+
+ return usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
+ USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE, feature, 0, NULL, 0,
+ USB_CTRL_SET_TIMEOUT);
+}
+
/* Loop until the read is completed with timeout
* called with phy_mutex held */
-static int smsc95xx_phy_wait_not_busy(struct usbnet *dev)
+static int __must_check smsc95xx_phy_wait_not_busy(struct usbnet *dev)
{
unsigned long start_time = jiffies;
u32 val;
+ int ret;
do {
- smsc95xx_read_reg(dev, MII_ADDR, &val);
+ ret = smsc95xx_read_reg(dev, MII_ADDR, &val);
+ check_warn_return(ret, "Error reading MII_ACCESS");
if (!(val & MII_BUSY_))
return 0;
} while (!time_after(jiffies, start_time + HZ));
@@ -134,33 +173,32 @@ static int smsc95xx_mdio_read(struct net_device *netdev, int phy_id, int idx)
{
struct usbnet *dev = netdev_priv(netdev);
u32 val, addr;
+ int ret;
mutex_lock(&dev->phy_mutex);
/* confirm MII not busy */
- if (smsc95xx_phy_wait_not_busy(dev)) {
- netdev_warn(dev->net, "MII is busy in smsc95xx_mdio_read\n");
- mutex_unlock(&dev->phy_mutex);
- return -EIO;
- }
+ ret = smsc95xx_phy_wait_not_busy(dev);
+ check_warn_goto_done(ret, "MII is busy in smsc95xx_mdio_read");
/* set the address, index & direction (read from PHY) */
phy_id &= dev->mii.phy_id_mask;
idx &= dev->mii.reg_num_mask;
addr = (phy_id << 11) | (idx << 6) | MII_READ_;
- smsc95xx_write_reg(dev, MII_ADDR, addr);
+ ret = smsc95xx_write_reg(dev, MII_ADDR, addr);
+ check_warn_goto_done(ret, "Error writing MII_ADDR");
- if (smsc95xx_phy_wait_not_busy(dev)) {
- netdev_warn(dev->net, "Timed out reading MII reg %02X\n", idx);
- mutex_unlock(&dev->phy_mutex);
- return -EIO;
- }
+ ret = smsc95xx_phy_wait_not_busy(dev);
+ check_warn_goto_done(ret, "Timed out reading MII reg %02X", idx);
- smsc95xx_read_reg(dev, MII_DATA, &val);
+ ret = smsc95xx_read_reg(dev, MII_DATA, &val);
+ check_warn_goto_done(ret, "Error reading MII_DATA");
- mutex_unlock(&dev->phy_mutex);
+ ret = (u16)(val & 0xFFFF);
- return (u16)(val & 0xFFFF);
+done:
+ mutex_unlock(&dev->phy_mutex);
+ return ret;
}
static void smsc95xx_mdio_write(struct net_device *netdev, int phy_id, int idx,
@@ -168,38 +206,41 @@ static void smsc95xx_mdio_write(struct net_device *netdev, int phy_id, int idx,
{
struct usbnet *dev = netdev_priv(netdev);
u32 val, addr;
+ int ret;
mutex_lock(&dev->phy_mutex);
/* confirm MII not busy */
- if (smsc95xx_phy_wait_not_busy(dev)) {
- netdev_warn(dev->net, "MII is busy in smsc95xx_mdio_write\n");
- mutex_unlock(&dev->phy_mutex);
- return;
- }
+ ret = smsc95xx_phy_wait_not_busy(dev);
+ check_warn_goto_done(ret, "MII is busy in smsc95xx_mdio_write");
val = regval;
- smsc95xx_write_reg(dev, MII_DATA, val);
+ ret = smsc95xx_write_reg(dev, MII_DATA, val);
+ check_warn_goto_done(ret, "Error writing MII_DATA");
/* set the address, index & direction (write to PHY) */
phy_id &= dev->mii.phy_id_mask;
idx &= dev->mii.reg_num_mask;
addr = (phy_id << 11) | (idx << 6) | MII_WRITE_;
- smsc95xx_write_reg(dev, MII_ADDR, addr);
+ ret = smsc95xx_write_reg(dev, MII_ADDR, addr);
+ check_warn_goto_done(ret, "Error writing MII_ADDR");
- if (smsc95xx_phy_wait_not_busy(dev))
- netdev_warn(dev->net, "Timed out writing MII reg %02X\n", idx);
+ ret = smsc95xx_phy_wait_not_busy(dev);
+ check_warn_goto_done(ret, "Timed out writing MII reg %02X", idx);
+done:
mutex_unlock(&dev->phy_mutex);
}
-static int smsc95xx_wait_eeprom(struct usbnet *dev)
+static int __must_check smsc95xx_wait_eeprom(struct usbnet *dev)
{
unsigned long start_time = jiffies;
u32 val;
+ int ret;
do {
- smsc95xx_read_reg(dev, E2P_CMD, &val);
+ ret = smsc95xx_read_reg(dev, E2P_CMD, &val);
+ check_warn_return(ret, "Error reading E2P_CMD");
if (!(val & E2P_CMD_BUSY_) || (val & E2P_CMD_TIMEOUT_))
break;
udelay(40);
@@ -213,13 +254,15 @@ static int smsc95xx_wait_eeprom(struct usbnet *dev)
return 0;
}
-static int smsc95xx_eeprom_confirm_not_busy(struct usbnet *dev)
+static int __must_check smsc95xx_eeprom_confirm_not_busy(struct usbnet *dev)
{
unsigned long start_time = jiffies;
u32 val;
+ int ret;
do {
- smsc95xx_read_reg(dev, E2P_CMD, &val);
+ ret = smsc95xx_read_reg(dev, E2P_CMD, &val);
+ check_warn_return(ret, "Error reading E2P_CMD");
if (!(val & E2P_CMD_BUSY_))
return 0;
@@ -246,13 +289,15 @@ static int smsc95xx_read_eeprom(struct usbnet *dev, u32 offset, u32 length,
for (i = 0; i < length; i++) {
val = E2P_CMD_BUSY_ | E2P_CMD_READ_ | (offset & E2P_CMD_ADDR_);
- smsc95xx_write_reg(dev, E2P_CMD, val);
+ ret = smsc95xx_write_reg(dev, E2P_CMD, val);
+ check_warn_return(ret, "Error writing E2P_CMD");
ret = smsc95xx_wait_eeprom(dev);
if (ret < 0)
return ret;
- smsc95xx_read_reg(dev, E2P_DATA, &val);
+ ret = smsc95xx_read_reg(dev, E2P_DATA, &val);
+ check_warn_return(ret, "Error reading E2P_DATA");
data[i] = val & 0xFF;
offset++;
@@ -276,7 +321,8 @@ static int smsc95xx_write_eeprom(struct usbnet *dev, u32 offset, u32 length,
/* Issue write/erase enable command */
val = E2P_CMD_BUSY_ | E2P_CMD_EWEN_;
- smsc95xx_write_reg(dev, E2P_CMD, val);
+ ret = smsc95xx_write_reg(dev, E2P_CMD, val);
+ check_warn_return(ret, "Error writing E2P_DATA");
ret = smsc95xx_wait_eeprom(dev);
if (ret < 0)
@@ -286,11 +332,13 @@ static int smsc95xx_write_eeprom(struct usbnet *dev, u32 offset, u32 length,
/* Fill data register */
val = data[i];
- smsc95xx_write_reg(dev, E2P_DATA, val);
+ ret = smsc95xx_write_reg(dev, E2P_DATA, val);
+ check_warn_return(ret, "Error writing E2P_DATA");
/* Send "write" command */
val = E2P_CMD_BUSY_ | E2P_CMD_WRITE_ | (offset & E2P_CMD_ADDR_);
- smsc95xx_write_reg(dev, E2P_CMD, val);
+ ret = smsc95xx_write_reg(dev, E2P_CMD, val);
+ check_warn_return(ret, "Error writing E2P_CMD");
ret = smsc95xx_wait_eeprom(dev);
if (ret < 0)
@@ -308,14 +356,14 @@ static void smsc95xx_async_cmd_callback(struct urb *urb)
struct usbnet *dev = usb_context->dev;
int status = urb->status;
- if (status < 0)
- netdev_warn(dev->net, "async callback failed with %d\n", status);
+ check_warn(status, "async callback failed with %d\n", status);
kfree(usb_context);
usb_free_urb(urb);
}
-static int smsc95xx_write_reg_async(struct usbnet *dev, u16 index, u32 *data)
+static int __must_check smsc95xx_write_reg_async(struct usbnet *dev, u16 index,
+ u32 *data)
{
struct usb_context *usb_context;
int status;
@@ -371,6 +419,7 @@ static void smsc95xx_set_multicast(struct net_device *netdev)
struct usbnet *dev = netdev_priv(netdev);
struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
unsigned long flags;
+ int ret;
pdata->hash_hi = 0;
pdata->hash_lo = 0;
@@ -411,21 +460,23 @@ static void smsc95xx_set_multicast(struct net_device *netdev)
spin_unlock_irqrestore(&pdata->mac_cr_lock, flags);
/* Initiate async writes, as we can't wait for completion here */
- smsc95xx_write_reg_async(dev, HASHH, &pdata->hash_hi);
- smsc95xx_write_reg_async(dev, HASHL, &pdata->hash_lo);
- smsc95xx_write_reg_async(dev, MAC_CR, &pdata->mac_cr);
+ ret = smsc95xx_write_reg_async(dev, HASHH, &pdata->hash_hi);
+ check_warn(ret, "failed to initiate async write to HASHH");
+
+ ret = smsc95xx_write_reg_async(dev, HASHL, &pdata->hash_lo);
+ check_warn(ret, "failed to initiate async write to HASHL");
+
+ ret = smsc95xx_write_reg_async(dev, MAC_CR, &pdata->mac_cr);
+ check_warn(ret, "failed to initiate async write to MAC_CR");
}
-static void smsc95xx_phy_update_flowcontrol(struct usbnet *dev, u8 duplex,
- u16 lcladv, u16 rmtadv)
+static int smsc95xx_phy_update_flowcontrol(struct usbnet *dev, u8 duplex,
+ u16 lcladv, u16 rmtadv)
{
u32 flow, afc_cfg = 0;
int ret = smsc95xx_read_reg(dev, AFC_CFG, &afc_cfg);
- if (ret < 0) {
- netdev_warn(dev->net, "error reading AFC_CFG\n");
- return;
- }
+ check_warn_return(ret, "Error reading AFC_CFG");
if (duplex == DUPLEX_FULL) {
u8 cap = mii_resolve_flowctrl_fdx(lcladv, rmtadv);
@@ -449,8 +500,13 @@ static void smsc95xx_phy_update_flowcontrol(struct usbnet *dev, u8 duplex,
afc_cfg |= 0xF;
}
- smsc95xx_write_reg(dev, FLOW, flow);
- smsc95xx_write_reg(dev, AFC_CFG, afc_cfg);
+ ret = smsc95xx_write_reg(dev, FLOW, flow);
+ check_warn_return(ret, "Error writing FLOW");
+
+ ret = smsc95xx_write_reg(dev, AFC_CFG, afc_cfg);
+ check_warn_return(ret, "Error writing AFC_CFG");
+
+ return 0;
}
static int smsc95xx_link_reset(struct usbnet *dev)
@@ -460,12 +516,14 @@ static int smsc95xx_link_reset(struct usbnet *dev)
struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET };
unsigned long flags;
u16 lcladv, rmtadv;
- u32 intdata;
+ int ret;
/* clear interrupt status */
- smsc95xx_mdio_read(dev->net, mii->phy_id, PHY_INT_SRC);
- intdata = 0xFFFFFFFF;
- smsc95xx_write_reg(dev, INT_STS, intdata);
+ ret = smsc95xx_mdio_read(dev->net, mii->phy_id, PHY_INT_SRC);
+ check_warn_return(ret, "Error reading PHY_INT_SRC");
+
+ ret = smsc95xx_write_reg(dev, INT_STS, INT_STS_CLEAR_ALL_);
+ check_warn_return(ret, "Error writing INT_STS");
mii_check_media(mii, 1, 1);
mii_ethtool_gset(&dev->mii, &ecmd);
@@ -486,9 +544,11 @@ static int smsc95xx_link_reset(struct usbnet *dev)
}
spin_unlock_irqrestore(&pdata->mac_cr_lock, flags);
- smsc95xx_write_reg(dev, MAC_CR, pdata->mac_cr);
+ ret = smsc95xx_write_reg(dev, MAC_CR, pdata->mac_cr);
+ check_warn_return(ret, "Error writing MAC_CR");
- smsc95xx_phy_update_flowcontrol(dev, ecmd.duplex, lcladv, rmtadv);
+ ret = smsc95xx_phy_update_flowcontrol(dev, ecmd.duplex, lcladv, rmtadv);
+ check_warn_return(ret, "Error updating PHY flow control");
return 0;
}
@@ -524,10 +584,7 @@ static int smsc95xx_set_features(struct net_device *netdev,
int ret;
ret = smsc95xx_read_reg(dev, COE_CR, &read_buf);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to read COE_CR: %d\n", ret);
- return ret;
- }
+ check_warn_return(ret, "Failed to read COE_CR: %d\n", ret);
if (features & NETIF_F_HW_CSUM)
read_buf |= Tx_COE_EN_;
@@ -540,10 +597,7 @@ static int smsc95xx_set_features(struct net_device *netdev,
read_buf &= ~Rx_COE_EN_;
ret = smsc95xx_write_reg(dev, COE_CR, read_buf);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to write COE_CR: %d\n", ret);
- return ret;
- }
+ check_warn_return(ret, "Failed to write COE_CR: %d\n", ret);
netif_dbg(dev, hw, dev->net, "COE_CR = 0x%08x\n", read_buf);
return 0;
@@ -608,6 +662,26 @@ smsc95xx_ethtool_getregs(struct net_device *netdev, struct ethtool_regs *regs,
}
}
+static void smsc95xx_ethtool_get_wol(struct net_device *net,
+ struct ethtool_wolinfo *wolinfo)
+{
+ struct usbnet *dev = netdev_priv(net);
+ struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+
+ wolinfo->supported = SUPPORTED_WAKE;
+ wolinfo->wolopts = pdata->wolopts;
+}
+
+static int smsc95xx_ethtool_set_wol(struct net_device *net,
+ struct ethtool_wolinfo *wolinfo)
+{
+ struct usbnet *dev = netdev_priv(net);
+ struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+
+ pdata->wolopts = wolinfo->wolopts & SUPPORTED_WAKE;
+ return 0;
+}
+
static const struct ethtool_ops smsc95xx_ethtool_ops = {
.get_link = usbnet_get_link,
.nway_reset = usbnet_nway_reset,
@@ -621,6 +695,8 @@ static const struct ethtool_ops smsc95xx_ethtool_ops = {
.set_eeprom = smsc95xx_ethtool_set_eeprom,
.get_regs_len = smsc95xx_ethtool_getregslen,
.get_regs = smsc95xx_ethtool_getregs,
+ .get_wol = smsc95xx_ethtool_get_wol,
+ .set_wol = smsc95xx_ethtool_set_wol,
};
static int smsc95xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
@@ -658,55 +734,56 @@ static int smsc95xx_set_mac_address(struct usbnet *dev)
int ret;
ret = smsc95xx_write_reg(dev, ADDRL, addr_lo);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to write ADDRL: %d\n", ret);
- return ret;
- }
+ check_warn_return(ret, "Failed to write ADDRL: %d\n", ret);
ret = smsc95xx_write_reg(dev, ADDRH, addr_hi);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to write ADDRH: %d\n", ret);
- return ret;
- }
+ check_warn_return(ret, "Failed to write ADDRH: %d\n", ret);
return 0;
}
/* starts the TX path */
-static void smsc95xx_start_tx_path(struct usbnet *dev)
+static int smsc95xx_start_tx_path(struct usbnet *dev)
{
struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
unsigned long flags;
- u32 reg_val;
+ int ret;
/* Enable Tx at MAC */
spin_lock_irqsave(&pdata->mac_cr_lock, flags);
pdata->mac_cr |= MAC_CR_TXEN_;
spin_unlock_irqrestore(&pdata->mac_cr_lock, flags);
- smsc95xx_write_reg(dev, MAC_CR, pdata->mac_cr);
+ ret = smsc95xx_write_reg(dev, MAC_CR, pdata->mac_cr);
+ check_warn_return(ret, "Failed to write MAC_CR: %d\n", ret);
/* Enable Tx at SCSRs */
- reg_val = TX_CFG_ON_;
- smsc95xx_write_reg(dev, TX_CFG, reg_val);
+ ret = smsc95xx_write_reg(dev, TX_CFG, TX_CFG_ON_);
+ check_warn_return(ret, "Failed to write TX_CFG: %d\n", ret);
+
+ return 0;
}
/* Starts the Receive path */
-static void smsc95xx_start_rx_path(struct usbnet *dev)
+static int smsc95xx_start_rx_path(struct usbnet *dev)
{
struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
unsigned long flags;
+ int ret;
spin_lock_irqsave(&pdata->mac_cr_lock, flags);
pdata->mac_cr |= MAC_CR_RXEN_;
spin_unlock_irqrestore(&pdata->mac_cr_lock, flags);
- smsc95xx_write_reg(dev, MAC_CR, pdata->mac_cr);
+ ret = smsc95xx_write_reg(dev, MAC_CR, pdata->mac_cr);
+ check_warn_return(ret, "Failed to write MAC_CR: %d\n", ret);
+
+ return 0;
}
static int smsc95xx_phy_initialize(struct usbnet *dev)
{
- int bmcr, timeout = 0;
+ int bmcr, ret, timeout = 0;
/* Initialize MII structure */
dev->mii.dev = dev->net;
@@ -735,7 +812,8 @@ static int smsc95xx_phy_initialize(struct usbnet *dev)
ADVERTISE_PAUSE_ASYM);
/* read to clear */
- smsc95xx_mdio_read(dev->net, dev->mii.phy_id, PHY_INT_SRC);
+ ret = smsc95xx_mdio_read(dev->net, dev->mii.phy_id, PHY_INT_SRC);
+ check_warn_return(ret, "Failed to read PHY_INT_SRC during init");
smsc95xx_mdio_write(dev->net, dev->mii.phy_id, PHY_INT_MASK,
PHY_INT_MASK_DEFAULT_);
@@ -753,22 +831,14 @@ static int smsc95xx_reset(struct usbnet *dev)
netif_dbg(dev, ifup, dev->net, "entering smsc95xx_reset\n");
- write_buf = HW_CFG_LRST_;
- ret = smsc95xx_write_reg(dev, HW_CFG, write_buf);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to write HW_CFG_LRST_ bit in HW_CFG register, ret = %d\n",
- ret);
- return ret;
- }
+ ret = smsc95xx_write_reg(dev, HW_CFG, HW_CFG_LRST_);
+ check_warn_return(ret, "Failed to write HW_CFG_LRST_ bit in HW_CFG\n");
timeout = 0;
do {
- ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret);
- return ret;
- }
msleep(10);
+ ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf);
+ check_warn_return(ret, "Failed to read HW_CFG: %d\n", ret);
timeout++;
} while ((read_buf & HW_CFG_LRST_) && (timeout < 100));
@@ -777,21 +847,14 @@ static int smsc95xx_reset(struct usbnet *dev)
return ret;
}
- write_buf = PM_CTL_PHY_RST_;
- ret = smsc95xx_write_reg(dev, PM_CTRL, write_buf);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to write PM_CTRL: %d\n", ret);
- return ret;
- }
+ ret = smsc95xx_write_reg(dev, PM_CTRL, PM_CTL_PHY_RST_);
+ check_warn_return(ret, "Failed to write PM_CTRL: %d\n", ret);
timeout = 0;
do {
- ret = smsc95xx_read_reg(dev, PM_CTRL, &read_buf);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to read PM_CTRL: %d\n", ret);
- return ret;
- }
msleep(10);
+ ret = smsc95xx_read_reg(dev, PM_CTRL, &read_buf);
+ check_warn_return(ret, "Failed to read PM_CTRL: %d\n", ret);
timeout++;
} while ((read_buf & PM_CTL_PHY_RST_) && (timeout < 100));
@@ -808,10 +871,7 @@ static int smsc95xx_reset(struct usbnet *dev)
"MAC Address: %pM\n", dev->net->dev_addr);
ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret);
- return ret;
- }
+ check_warn_return(ret, "Failed to read HW_CFG: %d\n", ret);
netif_dbg(dev, ifup, dev->net,
"Read Value from HW_CFG : 0x%08x\n", read_buf);
@@ -819,17 +879,10 @@ static int smsc95xx_reset(struct usbnet *dev)
read_buf |= HW_CFG_BIR_;
ret = smsc95xx_write_reg(dev, HW_CFG, read_buf);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to write HW_CFG_BIR_ bit in HW_CFG register, ret = %d\n",
- ret);
- return ret;
- }
+ check_warn_return(ret, "Failed to write HW_CFG_BIR_ bit in HW_CFG\n");
ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret);
- return ret;
- }
+ check_warn_return(ret, "Failed to read HW_CFG: %d\n", ret);
netif_dbg(dev, ifup, dev->net,
"Read Value from HW_CFG after writing HW_CFG_BIR_: 0x%08x\n",
read_buf);
@@ -849,41 +902,28 @@ static int smsc95xx_reset(struct usbnet *dev)
"rx_urb_size=%ld\n", (ulong)dev->rx_urb_size);
ret = smsc95xx_write_reg(dev, BURST_CAP, burst_cap);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to write BURST_CAP: %d\n", ret);
- return ret;
- }
+ check_warn_return(ret, "Failed to write BURST_CAP: %d\n", ret);
ret = smsc95xx_read_reg(dev, BURST_CAP, &read_buf);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to read BURST_CAP: %d\n", ret);
- return ret;
- }
+ check_warn_return(ret, "Failed to read BURST_CAP: %d\n", ret);
+
netif_dbg(dev, ifup, dev->net,
"Read Value from BURST_CAP after writing: 0x%08x\n",
read_buf);
- read_buf = DEFAULT_BULK_IN_DELAY;
- ret = smsc95xx_write_reg(dev, BULK_IN_DLY, read_buf);
- if (ret < 0) {
- netdev_warn(dev->net, "ret = %d\n", ret);
- return ret;
- }
+ ret = smsc95xx_write_reg(dev, BULK_IN_DLY, DEFAULT_BULK_IN_DELAY);
+ check_warn_return(ret, "Failed to write BULK_IN_DLY: %d\n", ret);
ret = smsc95xx_read_reg(dev, BULK_IN_DLY, &read_buf);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to read BULK_IN_DLY: %d\n", ret);
- return ret;
- }
+ check_warn_return(ret, "Failed to read BULK_IN_DLY: %d\n", ret);
+
netif_dbg(dev, ifup, dev->net,
"Read Value from BULK_IN_DLY after writing: 0x%08x\n",
read_buf);
ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret);
- return ret;
- }
+ check_warn_return(ret, "Failed to read HW_CFG: %d\n", ret);
+
netif_dbg(dev, ifup, dev->net,
"Read Value from HW_CFG: 0x%08x\n", read_buf);
@@ -896,101 +936,66 @@ static int smsc95xx_reset(struct usbnet *dev)
read_buf |= NET_IP_ALIGN << 9;
ret = smsc95xx_write_reg(dev, HW_CFG, read_buf);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to write HW_CFG register, ret=%d\n",
- ret);
- return ret;
- }
+ check_warn_return(ret, "Failed to write HW_CFG: %d\n", ret);
ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret);
- return ret;
- }
+ check_warn_return(ret, "Failed to read HW_CFG: %d\n", ret);
+
netif_dbg(dev, ifup, dev->net,
"Read Value from HW_CFG after writing: 0x%08x\n", read_buf);
- write_buf = 0xFFFFFFFF;
- ret = smsc95xx_write_reg(dev, INT_STS, write_buf);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to write INT_STS register, ret=%d\n",
- ret);
- return ret;
- }
+ ret = smsc95xx_write_reg(dev, INT_STS, INT_STS_CLEAR_ALL_);
+ check_warn_return(ret, "Failed to write INT_STS: %d\n", ret);
ret = smsc95xx_read_reg(dev, ID_REV, &read_buf);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to read ID_REV: %d\n", ret);
- return ret;
- }
+ check_warn_return(ret, "Failed to read ID_REV: %d\n", ret);
netif_dbg(dev, ifup, dev->net, "ID_REV = 0x%08x\n", read_buf);
/* Configure GPIO pins as LED outputs */
write_buf = LED_GPIO_CFG_SPD_LED | LED_GPIO_CFG_LNK_LED |
LED_GPIO_CFG_FDX_LED;
ret = smsc95xx_write_reg(dev, LED_GPIO_CFG, write_buf);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to write LED_GPIO_CFG register, ret=%d\n",
- ret);
- return ret;
- }
+ check_warn_return(ret, "Failed to write LED_GPIO_CFG: %d\n", ret);
/* Init Tx */
- write_buf = 0;
- ret = smsc95xx_write_reg(dev, FLOW, write_buf);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to write FLOW: %d\n", ret);
- return ret;
- }
+ ret = smsc95xx_write_reg(dev, FLOW, 0);
+ check_warn_return(ret, "Failed to write FLOW: %d\n", ret);
- read_buf = AFC_CFG_DEFAULT;
- ret = smsc95xx_write_reg(dev, AFC_CFG, read_buf);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to write AFC_CFG: %d\n", ret);
- return ret;
- }
+ ret = smsc95xx_write_reg(dev, AFC_CFG, AFC_CFG_DEFAULT);
+ check_warn_return(ret, "Failed to write AFC_CFG: %d\n", ret);
/* Don't need mac_cr_lock during initialisation */
ret = smsc95xx_read_reg(dev, MAC_CR, &pdata->mac_cr);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to read MAC_CR: %d\n", ret);
- return ret;
- }
+ check_warn_return(ret, "Failed to read MAC_CR: %d\n", ret);
/* Init Rx */
/* Set Vlan */
- write_buf = (u32)ETH_P_8021Q;
- ret = smsc95xx_write_reg(dev, VLAN1, write_buf);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to write VAN1: %d\n", ret);
- return ret;
- }
+ ret = smsc95xx_write_reg(dev, VLAN1, (u32)ETH_P_8021Q);
+ check_warn_return(ret, "Failed to write VLAN1: %d\n", ret);
/* Enable or disable checksum offload engines */
- smsc95xx_set_features(dev->net, dev->net->features);
+ ret = smsc95xx_set_features(dev->net, dev->net->features);
+ check_warn_return(ret, "Failed to set checksum offload features");
smsc95xx_set_multicast(dev->net);
- if (smsc95xx_phy_initialize(dev) < 0)
- return -EIO;
+ ret = smsc95xx_phy_initialize(dev);
+ check_warn_return(ret, "Failed to init PHY");
ret = smsc95xx_read_reg(dev, INT_EP_CTL, &read_buf);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to read INT_EP_CTL: %d\n", ret);
- return ret;
- }
+ check_warn_return(ret, "Failed to read INT_EP_CTL: %d\n", ret);
/* enable PHY interrupts */
read_buf |= INT_EP_CTL_PHY_INT_;
ret = smsc95xx_write_reg(dev, INT_EP_CTL, read_buf);
- if (ret < 0) {
- netdev_warn(dev->net, "Failed to write INT_EP_CTL: %d\n", ret);
- return ret;
- }
+ check_warn_return(ret, "Failed to write INT_EP_CTL: %d\n", ret);
- smsc95xx_start_tx_path(dev);
- smsc95xx_start_rx_path(dev);
+ ret = smsc95xx_start_tx_path(dev);
+ check_warn_return(ret, "Failed to start TX path");
+
+ ret = smsc95xx_start_rx_path(dev);
+ check_warn_return(ret, "Failed to start RX path");
netif_dbg(dev, ifup, dev->net, "smsc95xx_reset, return 0\n");
return 0;
@@ -1017,10 +1022,7 @@ static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf)
printk(KERN_INFO SMSC_CHIPNAME " v" SMSC_DRIVER_VERSION "\n");
ret = usbnet_get_endpoints(dev, intf);
- if (ret < 0) {
- netdev_warn(dev->net, "usbnet_get_endpoints failed: %d\n", ret);
- return ret;
- }
+ check_warn_return(ret, "usbnet_get_endpoints failed: %d\n", ret);
dev->data[0] = (unsigned long)kzalloc(sizeof(struct smsc95xx_priv),
GFP_KERNEL);
@@ -1064,6 +1066,153 @@ static void smsc95xx_unbind(struct usbnet *dev, struct usb_interface *intf)
}
}
+static int smsc95xx_suspend(struct usb_interface *intf, pm_message_t message)
+{
+ struct usbnet *dev = usb_get_intfdata(intf);
+ struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+ int ret;
+ u32 val;
+
+ ret = usbnet_suspend(intf, message);
+ check_warn_return(ret, "usbnet_suspend error");
+
+ /* if no wol options set, enter lowest power SUSPEND2 mode */
+ if (!(pdata->wolopts & SUPPORTED_WAKE)) {
+ netdev_info(dev->net, "entering SUSPEND2 mode");
+
+ /* disable energy detect (link up) & wake up events */
+ ret = smsc95xx_read_reg(dev, WUCSR, &val);
+ check_warn_return(ret, "Error reading WUCSR");
+
+ val &= ~(WUCSR_MPEN_ | WUCSR_WAKE_EN_);
+
+ ret = smsc95xx_write_reg(dev, WUCSR, val);
+ check_warn_return(ret, "Error writing WUCSR");
+
+ ret = smsc95xx_read_reg(dev, PM_CTRL, &val);
+ check_warn_return(ret, "Error reading PM_CTRL");
+
+ val &= ~(PM_CTL_ED_EN_ | PM_CTL_WOL_EN_);
+
+ ret = smsc95xx_write_reg(dev, PM_CTRL, val);
+ check_warn_return(ret, "Error writing PM_CTRL");
+
+ /* enter suspend2 mode */
+ ret = smsc95xx_read_reg(dev, PM_CTRL, &val);
+ check_warn_return(ret, "Error reading PM_CTRL");
+
+ val &= ~(PM_CTL_SUS_MODE_ | PM_CTL_WUPS_ | PM_CTL_PHY_RST_);
+ val |= PM_CTL_SUS_MODE_2;
+
+ ret = smsc95xx_write_reg(dev, PM_CTRL, val);
+ check_warn_return(ret, "Error writing PM_CTRL");
+
+ return 0;
+ }
+
+ if (pdata->wolopts & WAKE_MAGIC) {
+ /* clear any pending magic packet status */
+ ret = smsc95xx_read_reg(dev, WUCSR, &val);
+ check_warn_return(ret, "Error reading WUCSR");
+
+ val |= WUCSR_MPR_;
+
+ ret = smsc95xx_write_reg(dev, WUCSR, val);
+ check_warn_return(ret, "Error writing WUCSR");
+ }
+
+ /* enable/disable magic packup wake */
+ ret = smsc95xx_read_reg(dev, WUCSR, &val);
+ check_warn_return(ret, "Error reading WUCSR");
+
+ if (pdata->wolopts & WAKE_MAGIC) {
+ netdev_info(dev->net, "enabling magic packet wakeup");
+ val |= WUCSR_MPEN_;
+ } else {
+ netdev_info(dev->net, "disabling magic packet wakeup");
+ val &= ~WUCSR_MPEN_;
+ }
+
+ ret = smsc95xx_write_reg(dev, WUCSR, val);
+ check_warn_return(ret, "Error writing WUCSR");
+
+ /* enable wol wakeup source */
+ ret = smsc95xx_read_reg(dev, PM_CTRL, &val);
+ check_warn_return(ret, "Error reading PM_CTRL");
+
+ val |= PM_CTL_WOL_EN_;
+
+ ret = smsc95xx_write_reg(dev, PM_CTRL, val);
+ check_warn_return(ret, "Error writing PM_CTRL");
+
+ /* enable receiver */
+ smsc95xx_start_rx_path(dev);
+
+ /* some wol options are enabled, so enter SUSPEND0 */
+ netdev_info(dev->net, "entering SUSPEND0 mode");
+
+ ret = smsc95xx_read_reg(dev, PM_CTRL, &val);
+ check_warn_return(ret, "Error reading PM_CTRL");
+
+ val &= (~(PM_CTL_SUS_MODE_ | PM_CTL_WUPS_ | PM_CTL_PHY_RST_));
+ val |= PM_CTL_SUS_MODE_0;
+
+ ret = smsc95xx_write_reg(dev, PM_CTRL, val);
+ check_warn_return(ret, "Error writing PM_CTRL");
+
+ /* clear wol status */
+ val &= ~PM_CTL_WUPS_;
+ val |= PM_CTL_WUPS_WOL_;
+ ret = smsc95xx_write_reg(dev, PM_CTRL, val);
+ check_warn_return(ret, "Error writing PM_CTRL");
+
+ /* read back PM_CTRL */
+ ret = smsc95xx_read_reg(dev, PM_CTRL, &val);
+ check_warn_return(ret, "Error reading PM_CTRL");
+
+ smsc95xx_set_feature(dev, USB_DEVICE_REMOTE_WAKEUP);
+
+ return 0;
+}
+
+static int smsc95xx_resume(struct usb_interface *intf)
+{
+ struct usbnet *dev = usb_get_intfdata(intf);
+ struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+ int ret;
+ u32 val;
+
+ BUG_ON(!dev);
+
+ if (pdata->wolopts & WAKE_MAGIC) {
+ smsc95xx_clear_feature(dev, USB_DEVICE_REMOTE_WAKEUP);
+
+ /* Disable magic packup wake */
+ ret = smsc95xx_read_reg(dev, WUCSR, &val);
+ check_warn_return(ret, "Error reading WUCSR");
+
+ val &= ~WUCSR_MPEN_;
+
+ ret = smsc95xx_write_reg(dev, WUCSR, val);
+ check_warn_return(ret, "Error writing WUCSR");
+
+ /* clear wake-up status */
+ ret = smsc95xx_read_reg(dev, PM_CTRL, &val);
+ check_warn_return(ret, "Error reading PM_CTRL");
+
+ val &= ~PM_CTL_WOL_EN_;
+ val |= PM_CTL_WUPS_;
+
+ ret = smsc95xx_write_reg(dev, PM_CTRL, val);
+ check_warn_return(ret, "Error writing PM_CTRL");
+ }
+
+ return usbnet_resume(intf);
+ check_warn_return(ret, "usbnet_resume error");
+
+ return 0;
+}
+
static void smsc95xx_rx_csum_offload(struct sk_buff *skb)
{
skb->csum = *(u16 *)(skb_tail_pointer(skb) - 2);
@@ -1326,8 +1475,9 @@ static struct usb_driver smsc95xx_driver = {
.name = "smsc95xx",
.id_table = products,
.probe = usbnet_probe,
- .suspend = usbnet_suspend,
- .resume = usbnet_resume,
+ .suspend = smsc95xx_suspend,
+ .resume = smsc95xx_resume,
+ .reset_resume = smsc95xx_resume,
.disconnect = usbnet_disconnect,
.disable_hub_initiated_lpm = 1,
};
diff --git a/drivers/net/usb/smsc95xx.h b/drivers/net/usb/smsc95xx.h
index 86bc449..2ff9815 100644
--- a/drivers/net/usb/smsc95xx.h
+++ b/drivers/net/usb/smsc95xx.h
@@ -63,6 +63,7 @@
#define INT_STS_TDFO_ (0x00001000)
#define INT_STS_RXDF_ (0x00000800)
#define INT_STS_GPIOS_ (0x000007FF)
+#define INT_STS_CLEAR_ALL_ (0xFFFFFFFF)
#define RX_CFG (0x0C)
#define RX_FIFO_FLUSH_ (0x00000001)
@@ -83,12 +84,16 @@
#define HW_CFG_BCE_ (0x00000002)
#define HW_CFG_SRST_ (0x00000001)
+#define RX_FIFO_INF (0x18)
+
#define PM_CTRL (0x20)
+#define PM_CTL_RES_CLR_WKP_STS (0x00000200)
#define PM_CTL_DEV_RDY_ (0x00000080)
#define PM_CTL_SUS_MODE_ (0x00000060)
#define PM_CTL_SUS_MODE_0 (0x00000000)
#define PM_CTL_SUS_MODE_1 (0x00000020)
-#define PM_CTL_SUS_MODE_2 (0x00000060)
+#define PM_CTL_SUS_MODE_2 (0x00000040)
+#define PM_CTL_SUS_MODE_3 (0x00000060)
#define PM_CTL_PHY_RST_ (0x00000010)
#define PM_CTL_WOL_EN_ (0x00000008)
#define PM_CTL_ED_EN_ (0x00000004)
@@ -200,6 +205,11 @@
#define WUFF (0x128)
#define WUCSR (0x12C)
+#define WUCSR_GUE_ (0x00000200)
+#define WUCSR_WUFR_ (0x00000040)
+#define WUCSR_MPR_ (0x00000020)
+#define WUCSR_WAKE_EN_ (0x00000004)
+#define WUCSR_MPEN_ (0x00000002)
#define COE_CR (0x130)
#define Tx_COE_EN_ (0x00010000)
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
index e65aad0..5bbe505 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
@@ -2987,6 +2987,10 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah,
case EEP_RX_MASK:
return pBase->txrxMask & 0xf;
case EEP_PAPRD:
+ if (AR_SREV_9462(ah))
+ return false;
+ if (!ah->config.enable_paprd);
+ return false;
return !!(pBase->featureEnable & BIT(5));
case EEP_CHAIN_MASK_REDUCE:
return (pBase->miscConfiguration >> 0x3) & 0x1;
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index ab3bc85..e1041a6 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -1580,6 +1580,8 @@ int ath9k_init_debug(struct ath_hw *ah)
sc->debug.debugfs_phy, sc, &fops_tx_chainmask);
debugfs_create_file("disable_ani", S_IRUSR | S_IWUSR,
sc->debug.debugfs_phy, sc, &fops_disable_ani);
+ debugfs_create_bool("paprd", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
+ &sc->sc_ah->config.enable_paprd);
debugfs_create_file("regidx", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
sc, &fops_regidx);
debugfs_create_file("regval", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 2cc08a7..f9a6ec5 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -2511,10 +2511,6 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
pCap->rx_status_len = sizeof(struct ar9003_rxs);
pCap->tx_desc_len = sizeof(struct ar9003_txc);
pCap->txs_len = sizeof(struct ar9003_txs);
- if (!ah->config.paprd_disable &&
- ah->eep_ops->get_eeprom(ah, EEP_PAPRD) &&
- !AR_SREV_9462(ah))
- pCap->hw_caps |= ATH9K_HW_CAP_PAPRD;
} else {
pCap->tx_desc_len = sizeof(struct ath_desc);
if (AR_SREV_9280_20(ah))
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index 17203b5..566a4ce 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -237,7 +237,6 @@ enum ath9k_hw_caps {
ATH9K_HW_CAP_LDPC = BIT(6),
ATH9K_HW_CAP_FASTCLOCK = BIT(7),
ATH9K_HW_CAP_SGI_20 = BIT(8),
- ATH9K_HW_CAP_PAPRD = BIT(9),
ATH9K_HW_CAP_ANT_DIV_COMB = BIT(10),
ATH9K_HW_CAP_2GHZ = BIT(11),
ATH9K_HW_CAP_5GHZ = BIT(12),
@@ -288,12 +287,12 @@ struct ath9k_ops_config {
u8 pcie_clock_req;
u32 pcie_waen;
u8 analog_shiftreg;
- u8 paprd_disable;
u32 ofdm_trig_low;
u32 ofdm_trig_high;
u32 cck_trig_high;
u32 cck_trig_low;
u32 enable_ani;
+ u32 enable_paprd;
int serialize_regmode;
bool rx_intr_mitigation;
bool tx_intr_mitigation;
diff --git a/drivers/net/wireless/ath/ath9k/link.c b/drivers/net/wireless/ath/ath9k/link.c
index 825a29c..7b88b9c 100644
--- a/drivers/net/wireless/ath/ath9k/link.c
+++ b/drivers/net/wireless/ath/ath9k/link.c
@@ -423,7 +423,7 @@ set_timer:
cal_interval = min(cal_interval, (u32)short_cal_interval);
mod_timer(&common->ani.timer, jiffies + msecs_to_jiffies(cal_interval));
- if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_PAPRD) && ah->caldata) {
+ if (ah->eep_ops->get_eeprom(ah, EEP_PAPRD) && ah->caldata) {
if (!ah->caldata->paprd_done)
ieee80211_queue_work(sc->hw, &sc->paprd_work);
else if (!ah->paprd_table_write_done)
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
index 70f21a43..c3247d5 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
@@ -615,6 +615,8 @@ static int brcmf_sdio_pd_probe(struct platform_device *pdev)
oobirq_entry = kzalloc(sizeof(struct brcmf_sdio_oobirq),
GFP_KERNEL);
+ if (!oobirq_entry)
+ return -ENOMEM;
oobirq_entry->irq = res->start;
oobirq_entry->flags = res->flags & IRQF_TRIGGER_MASK;
list_add_tail(&oobirq_entry->list, &oobirq_lh);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
index fbecde7..aa4f719 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
@@ -767,8 +767,11 @@ static void brcmf_c_arp_offload_set(struct brcmf_pub *drvr, int arp_mode)
{
char iovbuf[32];
int retcode;
+ __le32 arp_mode_le;
- brcmf_c_mkiovar("arp_ol", (char *)&arp_mode, 4, iovbuf, sizeof(iovbuf));
+ arp_mode_le = cpu_to_le32(arp_mode);
+ brcmf_c_mkiovar("arp_ol", (char *)&arp_mode_le, 4, iovbuf,
+ sizeof(iovbuf));
retcode = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR,
iovbuf, sizeof(iovbuf));
retcode = retcode >= 0 ? 0 : retcode;
@@ -784,8 +787,11 @@ static void brcmf_c_arp_offload_enable(struct brcmf_pub *drvr, int arp_enable)
{
char iovbuf[32];
int retcode;
+ __le32 arp_enable_le;
- brcmf_c_mkiovar("arpoe", (char *)&arp_enable, 4,
+ arp_enable_le = cpu_to_le32(arp_enable);
+
+ brcmf_c_mkiovar("arpoe", (char *)&arp_enable_le, 4,
iovbuf, sizeof(iovbuf));
retcode = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR,
iovbuf, sizeof(iovbuf));
@@ -803,10 +809,10 @@ int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr)
char iovbuf[BRCMF_EVENTING_MASK_LEN + 12]; /* Room for
"event_msgs" + '\0' + bitvec */
char buf[128], *ptr;
- u32 roaming = 1;
- uint bcn_timeout = 3;
- int scan_assoc_time = 40;
- int scan_unassoc_time = 40;
+ __le32 roaming_le = cpu_to_le32(1);
+ __le32 bcn_timeout_le = cpu_to_le32(3);
+ __le32 scan_assoc_time_le = cpu_to_le32(40);
+ __le32 scan_unassoc_time_le = cpu_to_le32(40);
int i;
struct brcmf_bus_dcmd *cmdlst;
struct list_head *cur, *q;
@@ -832,14 +838,14 @@ int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr)
/* Setup timeout if Beacons are lost and roam is off to report
link down */
- brcmf_c_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf,
+ brcmf_c_mkiovar("bcn_timeout", (char *)&bcn_timeout_le, 4, iovbuf,
sizeof(iovbuf));
brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
sizeof(iovbuf));
/* Enable/Disable build-in roaming to allowed ext supplicant to take
of romaing */
- brcmf_c_mkiovar("roam_off", (char *)&roaming, 4,
+ brcmf_c_mkiovar("roam_off", (char *)&roaming_le, 4,
iovbuf, sizeof(iovbuf));
brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
sizeof(iovbuf));
@@ -851,9 +857,9 @@ int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr)
sizeof(iovbuf));
brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_SCAN_CHANNEL_TIME,
- (char *)&scan_assoc_time, sizeof(scan_assoc_time));
+ (char *)&scan_assoc_time_le, sizeof(scan_assoc_time_le));
brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_SCAN_UNASSOC_TIME,
- (char *)&scan_unassoc_time, sizeof(scan_unassoc_time));
+ (char *)&scan_unassoc_time_le, sizeof(scan_unassoc_time_le));
/* Set and enable ARP offload feature */
brcmf_c_arp_offload_set(drvr, BRCMF_ARPOL_MODE);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
index e40cfe8..af396e4 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
@@ -513,8 +513,10 @@ static void brcmf_iscan_prep(struct brcmf_scan_params_le *params_le,
params_le->active_time = cpu_to_le32(-1);
params_le->passive_time = cpu_to_le32(-1);
params_le->home_time = cpu_to_le32(-1);
- if (ssid && ssid->SSID_len)
- memcpy(&params_le->ssid_le, ssid, sizeof(struct brcmf_ssid));
+ if (ssid && ssid->SSID_len) {
+ params_le->ssid_le.SSID_len = cpu_to_le32(ssid->SSID_len);
+ memcpy(&params_le->ssid_le.SSID, ssid->SSID, ssid->SSID_len);
+ }
}
static s32
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/channel.c b/drivers/net/wireless/brcm80211/brcmsmac/channel.c
index 7ed7d75..64a48f0 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/channel.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/channel.c
@@ -77,7 +77,7 @@
NL80211_RRF_NO_IBSS)
static const struct ieee80211_regdomain brcms_regdom_x2 = {
- .n_reg_rules = 7,
+ .n_reg_rules = 6,
.alpha2 = "X2",
.reg_rules = {
BRCM_2GHZ_2412_2462,
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c
index d0c0fe7..34aee06 100644
--- a/drivers/net/wireless/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/iwlwifi/pcie/trans.c
@@ -1467,6 +1467,7 @@ static int iwl_trans_pcie_start_hw(struct iwl_trans *trans)
return err;
err_free_irq:
+ trans_pcie->irq_requested = false;
free_irq(trans_pcie->irq, trans);
error:
iwl_free_isr_ict(trans);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/def.h b/drivers/net/wireless/rtlwifi/rtl8192ce/def.h
index 04c3aef..2925094 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/def.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/def.h
@@ -117,6 +117,7 @@
#define CHIP_VER_B BIT(4)
#define CHIP_92C_BITMASK BIT(0)
+#define CHIP_UNKNOWN BIT(7)
#define CHIP_92C_1T2R 0x03
#define CHIP_92C 0x01
#define CHIP_88C 0x00
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
index cc89582..86d73b3 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
@@ -994,8 +994,16 @@ static enum version_8192c _rtl92ce_read_chip_version(struct ieee80211_hw *hw)
version = (value32 & TYPE_ID) ? VERSION_A_CHIP_92C :
VERSION_A_CHIP_88C;
} else {
- version = (value32 & TYPE_ID) ? VERSION_B_CHIP_92C :
- VERSION_B_CHIP_88C;
+ version = (enum version_8192c) (CHIP_VER_B |
+ ((value32 & TYPE_ID) ? CHIP_92C_BITMASK : 0) |
+ ((value32 & VENDOR_ID) ? CHIP_VENDOR_UMC : 0));
+ if ((!IS_CHIP_VENDOR_UMC(version)) && (value32 &
+ CHIP_VER_RTL_MASK)) {
+ version = (enum version_8192c)(version |
+ ((((value32 & CHIP_VER_RTL_MASK) == BIT(12))
+ ? CHIP_VENDOR_UMC_B_CUT : CHIP_UNKNOWN) |
+ CHIP_VENDOR_UMC));
+ }
}
switch (version) {
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
index 60451ee..ea2e1bd 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
@@ -162,10 +162,12 @@ int rtl92c_init_sw_vars(struct ieee80211_hw *hw)
/* request fw */
if (IS_VENDOR_UMC_A_CUT(rtlhal->version) &&
- !IS_92C_SERIAL(rtlhal->version))
+ !IS_92C_SERIAL(rtlhal->version)) {
rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cfwU.bin";
- else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version))
+ } else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) {
rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cfwU_B.bin";
+ pr_info("****** This B_CUT device may not work with kernels 3.6 and earlier\n");
+ }
rtlpriv->max_fw_size = 0x4000;
pr_info("Using firmware %s\n", rtlpriv->cfg->fw_name);
diff --git a/drivers/pwm/pwm-tiecap.c b/drivers/pwm/pwm-tiecap.c
index 0b66d0f..4b66889 100644
--- a/drivers/pwm/pwm-tiecap.c
+++ b/drivers/pwm/pwm-tiecap.c
@@ -100,6 +100,13 @@ static int ecap_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
writel(period_cycles, pc->mmio_base + CAP3);
}
+ if (!test_bit(PWMF_ENABLED, &pwm->flags)) {
+ reg_val = readw(pc->mmio_base + ECCTL2);
+ /* Disable APWM mode to put APWM output Low */
+ reg_val &= ~ECCTL2_APWM_MODE;
+ writew(reg_val, pc->mmio_base + ECCTL2);
+ }
+
pm_runtime_put_sync(pc->chip.dev);
return 0;
}
diff --git a/drivers/pwm/pwm-tiehrpwm.c b/drivers/pwm/pwm-tiehrpwm.c
index c3756d1..b1996bc 100644
--- a/drivers/pwm/pwm-tiehrpwm.c
+++ b/drivers/pwm/pwm-tiehrpwm.c
@@ -104,6 +104,7 @@ struct ehrpwm_pwm_chip {
struct pwm_chip chip;
unsigned int clk_rate;
void __iomem *mmio_base;
+ unsigned long period_cycles[NUM_PWM_CHANNEL];
};
static inline struct ehrpwm_pwm_chip *to_ehrpwm_pwm_chip(struct pwm_chip *chip)
@@ -210,6 +211,7 @@ static int ehrpwm_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
unsigned long long c;
unsigned long period_cycles, duty_cycles;
unsigned short ps_divval, tb_divval;
+ int i;
if (period_ns < 0 || duty_ns < 0 || period_ns > NSEC_PER_SEC)
return -ERANGE;
@@ -229,6 +231,28 @@ static int ehrpwm_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
duty_cycles = (unsigned long)c;
}
+ /*
+ * Period values should be same for multiple PWM channels as IP uses
+ * same period register for multiple channels.
+ */
+ for (i = 0; i < NUM_PWM_CHANNEL; i++) {
+ if (pc->period_cycles[i] &&
+ (pc->period_cycles[i] != period_cycles)) {
+ /*
+ * Allow channel to reconfigure period if no other
+ * channels being configured.
+ */
+ if (i == pwm->hwpwm)
+ continue;
+
+ dev_err(chip->dev, "Period value conflicts with channel %d\n",
+ i);
+ return -EINVAL;
+ }
+ }
+
+ pc->period_cycles[pwm->hwpwm] = period_cycles;
+
/* Configure clock prescaler to support Low frequency PWM wave */
if (set_prescale_div(period_cycles/PERIOD_MAX, &ps_divval,
&tb_divval)) {
@@ -320,10 +344,15 @@ static void ehrpwm_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
static void ehrpwm_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
{
+ struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip);
+
if (test_bit(PWMF_ENABLED, &pwm->flags)) {
dev_warn(chip->dev, "Removing PWM device without disabling\n");
pm_runtime_put_sync(chip->dev);
}
+
+ /* set period value to zero on free */
+ pc->period_cycles[pwm->hwpwm] = 0;
}
static const struct pwm_ops ehrpwm_pwm_ops = {
diff --git a/drivers/regulator/tps65217-regulator.c b/drivers/regulator/tps65217-regulator.c
index 6caa222..ab00cab 100644
--- a/drivers/regulator/tps65217-regulator.c
+++ b/drivers/regulator/tps65217-regulator.c
@@ -22,6 +22,7 @@
#include <linux/err.h>
#include <linux/platform_device.h>
+#include <linux/regulator/of_regulator.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/mfd/tps65217.h>
@@ -281,37 +282,130 @@ static const struct regulator_desc regulators[] = {
NULL),
};
+#ifdef CONFIG_OF
+static struct of_regulator_match reg_matches[] = {
+ { .name = "dcdc1", .driver_data = (void *)TPS65217_DCDC_1 },
+ { .name = "dcdc2", .driver_data = (void *)TPS65217_DCDC_2 },
+ { .name = "dcdc3", .driver_data = (void *)TPS65217_DCDC_3 },
+ { .name = "ldo1", .driver_data = (void *)TPS65217_LDO_1 },
+ { .name = "ldo2", .driver_data = (void *)TPS65217_LDO_2 },
+ { .name = "ldo3", .driver_data = (void *)TPS65217_LDO_3 },
+ { .name = "ldo4", .driver_data = (void *)TPS65217_LDO_4 },
+};
+
+static struct tps65217_board *tps65217_parse_dt(struct platform_device *pdev)
+{
+ struct tps65217 *tps = dev_get_drvdata(pdev->dev.parent);
+ struct device_node *node = tps->dev->of_node;
+ struct tps65217_board *pdata;
+ struct device_node *regs;
+ int i, count;
+
+ regs = of_find_node_by_name(node, "regulators");
+ if (!regs)
+ return NULL;
+
+ count = of_regulator_match(pdev->dev.parent, regs,
+ reg_matches, TPS65217_NUM_REGULATOR);
+ of_node_put(regs);
+ if ((count < 0) || (count > TPS65217_NUM_REGULATOR))
+ return NULL;
+
+ pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return NULL;
+
+ for (i = 0; i < count; i++) {
+ if (!reg_matches[i].init_data || !reg_matches[i].of_node)
+ continue;
+
+ pdata->tps65217_init_data[i] = reg_matches[i].init_data;
+ pdata->of_node[i] = reg_matches[i].of_node;
+ }
+
+ return pdata;
+}
+#else
+static struct tps65217_board *tps65217_parse_dt(struct platform_device *pdev)
+{
+ return NULL;
+}
+#endif
+
static int __devinit tps65217_regulator_probe(struct platform_device *pdev)
{
+ struct tps65217 *tps = dev_get_drvdata(pdev->dev.parent);
+ struct tps65217_board *pdata = dev_get_platdata(tps->dev);
+ struct regulator_init_data *reg_data;
struct regulator_dev *rdev;
- struct tps65217 *tps;
- struct tps_info *info = &tps65217_pmic_regs[pdev->id];
struct regulator_config config = { };
+ int i, ret;
- /* Already set by core driver */
- tps = dev_to_tps65217(pdev->dev.parent);
- tps->info[pdev->id] = info;
+ if (tps->dev->of_node)
+ pdata = tps65217_parse_dt(pdev);
- config.dev = &pdev->dev;
- config.of_node = pdev->dev.of_node;
- config.init_data = pdev->dev.platform_data;
- config.driver_data = tps;
+ if (!pdata) {
+ dev_err(&pdev->dev, "Platform data not found\n");
+ return -EINVAL;
+ }
- rdev = regulator_register(&regulators[pdev->id], &config);
- if (IS_ERR(rdev))
- return PTR_ERR(rdev);
+ if (tps65217_chip_id(tps) != TPS65217) {
+ dev_err(&pdev->dev, "Invalid tps chip version\n");
+ return -ENODEV;
+ }
- platform_set_drvdata(pdev, rdev);
+ platform_set_drvdata(pdev, tps);
+ for (i = 0; i < TPS65217_NUM_REGULATOR; i++) {
+
+ reg_data = pdata->tps65217_init_data[i];
+
+ /*
+ * Regulator API handles empty constraints but not NULL
+ * constraints
+ */
+ if (!reg_data)
+ continue;
+
+ /* Register the regulators */
+ tps->info[i] = &tps65217_pmic_regs[i];
+
+ config.dev = tps->dev;
+ config.init_data = reg_data;
+ config.driver_data = tps;
+ config.regmap = tps->regmap;
+ if (tps->dev->of_node)
+ config.of_node = pdata->of_node[i];
+
+ rdev = regulator_register(&regulators[i], &config);
+ if (IS_ERR(rdev)) {
+ dev_err(tps->dev, "failed to register %s regulator\n",
+ pdev->name);
+ ret = PTR_ERR(rdev);
+ goto err_unregister_regulator;
+ }
+
+ /* Save regulator for cleanup */
+ tps->rdev[i] = rdev;
+ }
return 0;
+
+err_unregister_regulator:
+ while (--i >= 0)
+ regulator_unregister(tps->rdev[i]);
+
+ return ret;
}
static int __devexit tps65217_regulator_remove(struct platform_device *pdev)
{
- struct regulator_dev *rdev = platform_get_drvdata(pdev);
+ struct tps65217 *tps = platform_get_drvdata(pdev);
+ unsigned int i;
+
+ for (i = 0; i < TPS65217_NUM_REGULATOR; i++)
+ regulator_unregister(tps->rdev[i]);
platform_set_drvdata(pdev, NULL);
- regulator_unregister(rdev);
return 0;
}
diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index 590cfaf..1859f71 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -1008,8 +1008,8 @@ static int rpmsg_probe(struct virtio_device *vdev)
return 0;
free_coherent:
- dma_free_coherent(vdev->dev.parent, RPMSG_TOTAL_BUF_SPACE, bufs_va,
- vrp->bufs_dma);
+ dma_free_coherent(vdev->dev.parent->parent, RPMSG_TOTAL_BUF_SPACE,
+ bufs_va, vrp->bufs_dma);
vqs_del:
vdev->config->del_vqs(vrp->vdev);
free_vrp:
@@ -1043,7 +1043,7 @@ static void __devexit rpmsg_remove(struct virtio_device *vdev)
vdev->config->del_vqs(vrp->vdev);
- dma_free_coherent(vdev->dev.parent, RPMSG_TOTAL_BUF_SPACE,
+ dma_free_coherent(vdev->dev.parent->parent, RPMSG_TOTAL_BUF_SPACE,
vrp->rbufs, vrp->bufs_dma);
kfree(vrp);
diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c
index c5d06fe..9277d94 100644
--- a/drivers/rtc/rtc-twl.c
+++ b/drivers/rtc/rtc-twl.c
@@ -495,6 +495,11 @@ static int __devinit twl_rtc_probe(struct platform_device *pdev)
if (ret < 0)
goto out1;
+ /* ensure interrupts are disabled, bootloaders can be strange */
+ ret = twl_rtc_write_u8(0, REG_RTC_INTERRUPTS_REG);
+ if (ret < 0)
+ dev_warn(&pdev->dev, "unable to disable interrupt\n");
+
/* init cached IRQ enable bits */
ret = twl_rtc_read_u8(&rtc_irq_bits, REG_RTC_INTERRUPTS_REG);
if (ret < 0)
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 15370a2..0595c76 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -534,11 +534,11 @@ static void dasd_change_state(struct dasd_device *device)
if (rc)
device->target = device->state;
- if (device->state == device->target)
- wake_up(&dasd_init_waitq);
-
/* let user-space know that the device status changed */
kobject_uevent(&device->cdev->dev.kobj, KOBJ_CHANGE);
+
+ if (device->state == device->target)
+ wake_up(&dasd_init_waitq);
}
/*
@@ -2157,6 +2157,7 @@ static int _dasd_sleep_on(struct dasd_ccw_req *maincqr, int interruptible)
test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags) &&
(!dasd_eer_enabled(device))) {
cqr->status = DASD_CQR_FAILED;
+ cqr->intrc = -EAGAIN;
continue;
}
/* Don't try to start requests if device is stopped */
@@ -3270,6 +3271,16 @@ void dasd_generic_path_event(struct ccw_device *cdev, int *path_event)
dasd_schedule_device_bh(device);
}
if (path_event[chp] & PE_PATHGROUP_ESTABLISHED) {
+ if (!(device->path_data.opm & eventlpm) &&
+ !(device->path_data.tbvpm & eventlpm)) {
+ /*
+ * we can not establish a pathgroup on an
+ * unavailable path, so trigger a path
+ * verification first
+ */
+ device->path_data.tbvpm |= eventlpm;
+ dasd_schedule_device_bh(device);
+ }
DBF_DEV_EVENT(DBF_WARNING, device, "%s",
"Pathgroup re-established\n");
if (device->discipline->kick_validate)
diff --git a/drivers/s390/block/dasd_alias.c b/drivers/s390/block/dasd_alias.c
index 157defe..6b55699 100644
--- a/drivers/s390/block/dasd_alias.c
+++ b/drivers/s390/block/dasd_alias.c
@@ -384,6 +384,29 @@ static void _remove_device_from_lcu(struct alias_lcu *lcu,
group->next = NULL;
};
+static int
+suborder_not_supported(struct dasd_ccw_req *cqr)
+{
+ char *sense;
+ char reason;
+ char msg_format;
+ char msg_no;
+
+ sense = dasd_get_sense(&cqr->irb);
+ if (!sense)
+ return 0;
+
+ reason = sense[0];
+ msg_format = (sense[7] & 0xF0);
+ msg_no = (sense[7] & 0x0F);
+
+ /* command reject, Format 0 MSG 4 - invalid parameter */
+ if ((reason == 0x80) && (msg_format == 0x00) && (msg_no == 0x04))
+ return 1;
+
+ return 0;
+}
+
static int read_unit_address_configuration(struct dasd_device *device,
struct alias_lcu *lcu)
{
@@ -435,6 +458,8 @@ static int read_unit_address_configuration(struct dasd_device *device,
do {
rc = dasd_sleep_on(cqr);
+ if (rc && suborder_not_supported(cqr))
+ return -EOPNOTSUPP;
} while (rc && (cqr->retries > 0));
if (rc) {
spin_lock_irqsave(&lcu->lock, flags);
@@ -521,7 +546,7 @@ static void lcu_update_work(struct work_struct *work)
* processing the data
*/
spin_lock_irqsave(&lcu->lock, flags);
- if (rc || (lcu->flags & NEED_UAC_UPDATE)) {
+ if ((rc && (rc != -EOPNOTSUPP)) || (lcu->flags & NEED_UAC_UPDATE)) {
DBF_DEV_EVENT(DBF_WARNING, device, "could not update"
" alias data in lcu (rc = %d), retry later", rc);
schedule_delayed_work(&lcu->ruac_data.dwork, 30*HZ);
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index 2fb2b9e..c48c72a 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -1507,7 +1507,8 @@ static struct dasd_ccw_req *dasd_eckd_build_psf_ssc(struct dasd_device *device,
* call might change behaviour of DASD devices.
*/
static int
-dasd_eckd_psf_ssc(struct dasd_device *device, int enable_pav)
+dasd_eckd_psf_ssc(struct dasd_device *device, int enable_pav,
+ unsigned long flags)
{
struct dasd_ccw_req *cqr;
int rc;
@@ -1516,10 +1517,19 @@ dasd_eckd_psf_ssc(struct dasd_device *device, int enable_pav)
if (IS_ERR(cqr))
return PTR_ERR(cqr);
+ /*
+ * set flags e.g. turn on failfast, to prevent blocking
+ * the calling function should handle failed requests
+ */
+ cqr->flags |= flags;
+
rc = dasd_sleep_on(cqr);
if (!rc)
/* trigger CIO to reprobe devices */
css_schedule_reprobe();
+ else if (cqr->intrc == -EAGAIN)
+ rc = -EAGAIN;
+
dasd_sfree_request(cqr, cqr->memdev);
return rc;
}
@@ -1527,7 +1537,8 @@ dasd_eckd_psf_ssc(struct dasd_device *device, int enable_pav)
/*
* Valide storage server of current device.
*/
-static void dasd_eckd_validate_server(struct dasd_device *device)
+static int dasd_eckd_validate_server(struct dasd_device *device,
+ unsigned long flags)
{
int rc;
struct dasd_eckd_private *private;
@@ -1536,17 +1547,18 @@ static void dasd_eckd_validate_server(struct dasd_device *device)
private = (struct dasd_eckd_private *) device->private;
if (private->uid.type == UA_BASE_PAV_ALIAS ||
private->uid.type == UA_HYPER_PAV_ALIAS)
- return;
+ return 0;
if (dasd_nopav || MACHINE_IS_VM)
enable_pav = 0;
else
enable_pav = 1;
- rc = dasd_eckd_psf_ssc(device, enable_pav);
+ rc = dasd_eckd_psf_ssc(device, enable_pav, flags);
/* may be requested feature is not available on server,
* therefore just report error and go ahead */
DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "PSF-SSC for SSID %04x "
"returned rc=%d", private->uid.ssid, rc);
+ return rc;
}
/*
@@ -1556,7 +1568,13 @@ static void dasd_eckd_do_validate_server(struct work_struct *work)
{
struct dasd_device *device = container_of(work, struct dasd_device,
kick_validate);
- dasd_eckd_validate_server(device);
+ if (dasd_eckd_validate_server(device, DASD_CQR_FLAGS_FAILFAST)
+ == -EAGAIN) {
+ /* schedule worker again if failed */
+ schedule_work(&device->kick_validate);
+ return;
+ }
+
dasd_put_device(device);
}
@@ -1685,7 +1703,7 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
if (rc)
goto out_err2;
- dasd_eckd_validate_server(device);
+ dasd_eckd_validate_server(device, 0);
/* device may report different configuration data after LCU setup */
rc = dasd_eckd_read_conf(device);
@@ -4153,7 +4171,7 @@ static int dasd_eckd_restore_device(struct dasd_device *device)
rc = dasd_alias_make_device_known_to_lcu(device);
if (rc)
return rc;
- dasd_eckd_validate_server(device);
+ dasd_eckd_validate_server(device, DASD_CQR_FLAGS_FAILFAST);
/* RE-Read Configuration Data */
rc = dasd_eckd_read_conf(device);
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index ed25c87..fc916f5 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -1426,6 +1426,8 @@ static enum io_sch_action sch_get_action(struct subchannel *sch)
return IO_SCH_REPROBE;
if (cdev->online)
return IO_SCH_VERIFY;
+ if (cdev->private->state == DEV_STATE_NOT_OPER)
+ return IO_SCH_UNREG_ATTACH;
return IO_SCH_NOP;
}
@@ -1519,11 +1521,14 @@ static int io_subchannel_sch_event(struct subchannel *sch, int process)
goto out;
break;
case IO_SCH_UNREG_ATTACH:
+ spin_lock_irqsave(sch->lock, flags);
if (cdev->private->flags.resuming) {
/* Device will be handled later. */
rc = 0;
- goto out;
+ goto out_unlock;
}
+ sch_set_cdev(sch, NULL);
+ spin_unlock_irqrestore(sch->lock, flags);
/* Unregister ccw device. */
ccw_device_unregister(cdev);
break;
diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hwi.c
index 33d6630..91eec60 100644
--- a/drivers/scsi/bnx2i/bnx2i_hwi.c
+++ b/drivers/scsi/bnx2i/bnx2i_hwi.c
@@ -1264,6 +1264,9 @@ int bnx2i_send_fw_iscsi_init_msg(struct bnx2i_hba *hba)
int rc = 0;
u64 mask64;
+ memset(&iscsi_init, 0x00, sizeof(struct iscsi_kwqe_init1));
+ memset(&iscsi_init2, 0x00, sizeof(struct iscsi_kwqe_init2));
+
bnx2i_adjust_qp_size(hba);
iscsi_init.flags =
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 796482b..2b4261c 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -1315,8 +1315,9 @@ static void complete_scsi_command(struct CommandList *cp)
}
break;
case CMD_PROTOCOL_ERR:
+ cmd->result = DID_ERROR << 16;
dev_warn(&h->pdev->dev, "cp %p has "
- "protocol error \n", cp);
+ "protocol error\n", cp);
break;
case CMD_HARDWARE_ERR:
cmd->result = DID_ERROR << 16;
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c
index b25757d..9d5a56c 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.c
@@ -1209,6 +1209,13 @@ _base_check_enable_msix(struct MPT2SAS_ADAPTER *ioc)
u16 message_control;
+ /* Check whether controller SAS2008 B0 controller,
+ if it is SAS2008 B0 controller use IO-APIC instead of MSIX */
+ if (ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2008 &&
+ ioc->pdev->revision == 0x01) {
+ return -EINVAL;
+ }
+
base = pci_find_capability(ioc->pdev, PCI_CAP_ID_MSIX);
if (!base) {
dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "msix not "
diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c
index c7030fb..3e79a2f 100644
--- a/drivers/scsi/virtio_scsi.c
+++ b/drivers/scsi/virtio_scsi.c
@@ -331,7 +331,7 @@ static void virtscsi_map_sgl(struct scatterlist *sg, unsigned int *p_idx,
int i;
for_each_sg(table->sgl, sg_elem, table->nents, i)
- sg_set_buf(&sg[idx++], sg_virt(sg_elem), sg_elem->length);
+ sg[idx++] = *sg_elem;
*p_idx = idx;
}
diff --git a/drivers/sh/intc/core.c b/drivers/sh/intc/core.c
index 32c26d7..8f32a13 100644
--- a/drivers/sh/intc/core.c
+++ b/drivers/sh/intc/core.c
@@ -355,7 +355,7 @@ int __init register_intc_controller(struct intc_desc *desc)
if (unlikely(res)) {
if (res == -EEXIST) {
res = irq_domain_associate(d->domain,
- irq, irq);
+ irq2, irq2);
if (unlikely(res)) {
pr_err("domain association "
"failure\n");
diff --git a/drivers/sh/pfc/pinctrl.c b/drivers/sh/pfc/pinctrl.c
index 2804eaa..0646bf6 100644
--- a/drivers/sh/pfc/pinctrl.c
+++ b/drivers/sh/pfc/pinctrl.c
@@ -208,10 +208,13 @@ static int sh_pfc_gpio_request_enable(struct pinctrl_dev *pctldev,
break;
case PINMUX_TYPE_GPIO:
+ case PINMUX_TYPE_INPUT:
+ case PINMUX_TYPE_OUTPUT:
break;
default:
pr_err("Unsupported mux type (%d), bailing...\n", pinmux_type);
- return -ENOTSUPP;
+ ret = -ENOTSUPP;
+ goto err;
}
ret = 0;
diff --git a/drivers/staging/nvec/nvec.c b/drivers/staging/nvec/nvec.c
index 695ea35..d0a7e40 100644
--- a/drivers/staging/nvec/nvec.c
+++ b/drivers/staging/nvec/nvec.c
@@ -837,7 +837,7 @@ static int __devinit tegra_nvec_probe(struct platform_device *pdev)
}
ret = mfd_add_devices(nvec->dev, -1, nvec_devices,
- ARRAY_SIZE(nvec_devices), base, 0);
+ ARRAY_SIZE(nvec_devices), base, 0, NULL);
if (ret)
dev_err(nvec->dev, "error adding subdevices\n");
diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c
index 0694d9b..6aba439 100644
--- a/drivers/target/iscsi/iscsi_target_login.c
+++ b/drivers/target/iscsi/iscsi_target_login.c
@@ -221,6 +221,7 @@ static int iscsi_login_zero_tsih_s1(
{
struct iscsi_session *sess = NULL;
struct iscsi_login_req *pdu = (struct iscsi_login_req *)buf;
+ int ret;
sess = kzalloc(sizeof(struct iscsi_session), GFP_KERNEL);
if (!sess) {
@@ -257,9 +258,17 @@ static int iscsi_login_zero_tsih_s1(
return -ENOMEM;
}
spin_lock(&sess_idr_lock);
- idr_get_new(&sess_idr, NULL, &sess->session_index);
+ ret = idr_get_new(&sess_idr, NULL, &sess->session_index);
spin_unlock(&sess_idr_lock);
+ if (ret < 0) {
+ pr_err("idr_get_new() for sess_idr failed\n");
+ iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
+ ISCSI_LOGIN_STATUS_NO_RESOURCES);
+ kfree(sess);
+ return -ENOMEM;
+ }
+
sess->creation_time = get_jiffies_64();
spin_lock_init(&sess->session_stats_lock);
/*
diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c
index 9179997..41641ba 100644
--- a/drivers/target/target_core_alua.c
+++ b/drivers/target/target_core_alua.c
@@ -218,6 +218,13 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd)
cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
return -EINVAL;
}
+ if (cmd->data_length < 4) {
+ pr_warn("SET TARGET PORT GROUPS parameter list length %u too"
+ " small\n", cmd->data_length);
+ cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
+ return -EINVAL;
+ }
+
buf = transport_kmap_data_sg(cmd);
/*
diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c
index cf2c66f..9fc9a60 100644
--- a/drivers/target/target_core_device.c
+++ b/drivers/target/target_core_device.c
@@ -669,6 +669,13 @@ int target_report_luns(struct se_cmd *se_cmd)
unsigned char *buf;
u32 lun_count = 0, offset = 8, i;
+ if (se_cmd->data_length < 16) {
+ pr_warn("REPORT LUNS allocation length %u too small\n",
+ se_cmd->data_length);
+ se_cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
+ return -EINVAL;
+ }
+
buf = transport_kmap_data_sg(se_cmd);
if (!buf)
return -ENOMEM;
diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c
index 76db75e..9ba4954 100644
--- a/drivers/target/target_core_iblock.c
+++ b/drivers/target/target_core_iblock.c
@@ -325,17 +325,30 @@ static int iblock_execute_unmap(struct se_cmd *cmd)
struct iblock_dev *ibd = dev->dev_ptr;
unsigned char *buf, *ptr = NULL;
sector_t lba;
- int size = cmd->data_length;
+ int size;
u32 range;
int ret = 0;
int dl, bd_dl;
+ if (cmd->data_length < 8) {
+ pr_warn("UNMAP parameter list length %u too small\n",
+ cmd->data_length);
+ cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
+ return -EINVAL;
+ }
+
buf = transport_kmap_data_sg(cmd);
dl = get_unaligned_be16(&buf[0]);
bd_dl = get_unaligned_be16(&buf[2]);
- size = min(size - 8, bd_dl);
+ size = cmd->data_length - 8;
+ if (bd_dl > size)
+ pr_warn("UNMAP parameter list length %u too small, ignoring bd_dl %u\n",
+ cmd->data_length, bd_dl);
+ else
+ size = bd_dl;
+
if (size / 16 > dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count) {
cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
ret = -EINVAL;
diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c
index 1e94650..956c84c 100644
--- a/drivers/target/target_core_pr.c
+++ b/drivers/target/target_core_pr.c
@@ -1540,6 +1540,14 @@ static int core_scsi3_decode_spec_i_port(
tidh_new->dest_local_nexus = 1;
list_add_tail(&tidh_new->dest_list, &tid_dest_list);
+ if (cmd->data_length < 28) {
+ pr_warn("SPC-PR: Received PR OUT parameter list"
+ " length too small: %u\n", cmd->data_length);
+ cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
+ ret = -EINVAL;
+ goto out;
+ }
+
buf = transport_kmap_data_sg(cmd);
/*
* For a PERSISTENT RESERVE OUT specify initiator ports payload,
diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c
index 5552fa7..9d7ce3d 100644
--- a/drivers/target/target_core_pscsi.c
+++ b/drivers/target/target_core_pscsi.c
@@ -667,7 +667,8 @@ static void pscsi_free_device(void *p)
kfree(pdv);
}
-static int pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg)
+static void pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg,
+ unsigned char *sense_buffer)
{
struct pscsi_dev_virt *pdv = cmd->se_dev->dev_ptr;
struct scsi_device *sd = pdv->pdv_sd;
@@ -679,7 +680,7 @@ static int pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg)
* not been allocated because TCM is handling the emulation directly.
*/
if (!pt)
- return 0;
+ return;
cdb = &pt->pscsi_cdb[0];
result = pt->pscsi_result;
@@ -687,11 +688,11 @@ static int pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg)
* Hack to make sure that Write-Protect modepage is set if R/O mode is
* forced.
*/
+ if (!cmd->se_deve || !cmd->data_length)
+ goto after_mode_sense;
+
if (((cdb[0] == MODE_SENSE) || (cdb[0] == MODE_SENSE_10)) &&
(status_byte(result) << 1) == SAM_STAT_GOOD) {
- if (!cmd->se_deve)
- goto after_mode_sense;
-
if (cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY) {
unsigned char *buf = transport_kmap_data_sg(cmd);
@@ -708,7 +709,7 @@ static int pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg)
}
after_mode_sense:
- if (sd->type != TYPE_TAPE)
+ if (sd->type != TYPE_TAPE || !cmd->data_length)
goto after_mode_select;
/*
@@ -750,10 +751,10 @@ after_mode_sense:
}
after_mode_select:
- if (status_byte(result) & CHECK_CONDITION)
- return 1;
-
- return 0;
+ if (sense_buffer && (status_byte(result) & CHECK_CONDITION)) {
+ memcpy(sense_buffer, pt->pscsi_sense, TRANSPORT_SENSE_BUFFER);
+ cmd->se_cmd_flags |= SCF_TRANSPORT_TASK_SENSE;
+ }
}
enum {
@@ -1184,13 +1185,6 @@ fail:
return -ENOMEM;
}
-static unsigned char *pscsi_get_sense_buffer(struct se_cmd *cmd)
-{
- struct pscsi_plugin_task *pt = cmd->priv;
-
- return pt->pscsi_sense;
-}
-
/* pscsi_get_device_rev():
*
*
@@ -1273,7 +1267,6 @@ static struct se_subsystem_api pscsi_template = {
.check_configfs_dev_params = pscsi_check_configfs_dev_params,
.set_configfs_dev_params = pscsi_set_configfs_dev_params,
.show_configfs_dev_params = pscsi_show_configfs_dev_params,
- .get_sense_buffer = pscsi_get_sense_buffer,
.get_device_rev = pscsi_get_device_rev,
.get_device_type = pscsi_get_device_type,
.get_blocks = pscsi_get_blocks,
diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c
index 4c861de..388a922 100644
--- a/drivers/target/target_core_spc.c
+++ b/drivers/target/target_core_spc.c
@@ -877,9 +877,11 @@ static int spc_emulate_modesense(struct se_cmd *cmd)
static int spc_emulate_request_sense(struct se_cmd *cmd)
{
unsigned char *cdb = cmd->t_task_cdb;
- unsigned char *buf;
+ unsigned char *rbuf;
u8 ua_asc = 0, ua_ascq = 0;
- int err = 0;
+ unsigned char buf[SE_SENSE_BUF];
+
+ memset(buf, 0, SE_SENSE_BUF);
if (cdb[1] & 0x01) {
pr_err("REQUEST_SENSE description emulation not"
@@ -888,20 +890,21 @@ static int spc_emulate_request_sense(struct se_cmd *cmd)
return -ENOSYS;
}
- buf = transport_kmap_data_sg(cmd);
-
- if (!core_scsi3_ua_clear_for_request_sense(cmd, &ua_asc, &ua_ascq)) {
+ rbuf = transport_kmap_data_sg(cmd);
+ if (cmd->scsi_sense_reason != 0) {
+ /*
+ * Out of memory. We will fail with CHECK CONDITION, so
+ * we must not clear the unit attention condition.
+ */
+ target_complete_cmd(cmd, CHECK_CONDITION);
+ return 0;
+ } else if (!core_scsi3_ua_clear_for_request_sense(cmd, &ua_asc, &ua_ascq)) {
/*
* CURRENT ERROR, UNIT ATTENTION
*/
buf[0] = 0x70;
buf[SPC_SENSE_KEY_OFFSET] = UNIT_ATTENTION;
- if (cmd->data_length < 18) {
- buf[7] = 0x00;
- err = -EINVAL;
- goto end;
- }
/*
* The Additional Sense Code (ASC) from the UNIT ATTENTION
*/
@@ -915,11 +918,6 @@ static int spc_emulate_request_sense(struct se_cmd *cmd)
buf[0] = 0x70;
buf[SPC_SENSE_KEY_OFFSET] = NO_SENSE;
- if (cmd->data_length < 18) {
- buf[7] = 0x00;
- err = -EINVAL;
- goto end;
- }
/*
* NO ADDITIONAL SENSE INFORMATION
*/
@@ -927,8 +925,11 @@ static int spc_emulate_request_sense(struct se_cmd *cmd)
buf[7] = 0x0A;
}
-end:
- transport_kunmap_data_sg(cmd);
+ if (rbuf) {
+ memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length));
+ transport_kunmap_data_sg(cmd);
+ }
+
target_complete_cmd(cmd, GOOD);
return 0;
}
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 4de3186dc..269f544 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -567,6 +567,34 @@ static void target_complete_failure_work(struct work_struct *work)
transport_generic_request_failure(cmd);
}
+/*
+ * Used when asking transport to copy Sense Data from the underlying
+ * Linux/SCSI struct scsi_cmnd
+ */
+static unsigned char *transport_get_sense_buffer(struct se_cmd *cmd)
+{
+ unsigned char *buffer = cmd->sense_buffer;
+ struct se_device *dev = cmd->se_dev;
+ u32 offset = 0;
+
+ WARN_ON(!cmd->se_lun);
+
+ if (!dev)
+ return NULL;
+
+ if (cmd->se_cmd_flags & SCF_SENT_CHECK_CONDITION)
+ return NULL;
+
+ offset = cmd->se_tfo->set_fabric_sense_len(cmd, TRANSPORT_SENSE_BUFFER);
+
+ /* Automatically padded */
+ cmd->scsi_sense_length = TRANSPORT_SENSE_BUFFER + offset;
+
+ pr_debug("HBA_[%u]_PLUG[%s]: Requesting sense for SAM STATUS: 0x%02x\n",
+ dev->se_hba->hba_id, dev->transport->name, cmd->scsi_status);
+ return &buffer[offset];
+}
+
void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status)
{
struct se_device *dev = cmd->se_dev;
@@ -580,11 +608,11 @@ void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status)
cmd->transport_state &= ~CMD_T_BUSY;
if (dev && dev->transport->transport_complete) {
- if (dev->transport->transport_complete(cmd,
- cmd->t_data_sg) != 0) {
- cmd->se_cmd_flags |= SCF_TRANSPORT_TASK_SENSE;
+ dev->transport->transport_complete(cmd,
+ cmd->t_data_sg,
+ transport_get_sense_buffer(cmd));
+ if (cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE)
success = 1;
- }
}
/*
@@ -1181,15 +1209,20 @@ int target_cmd_size_check(struct se_cmd *cmd, unsigned int size)
/* Returns CHECK_CONDITION + INVALID_CDB_FIELD */
goto out_invalid_cdb_field;
}
-
+ /*
+ * For the overflow case keep the existing fabric provided
+ * ->data_length. Otherwise for the underflow case, reset
+ * ->data_length to the smaller SCSI expected data transfer
+ * length.
+ */
if (size > cmd->data_length) {
cmd->se_cmd_flags |= SCF_OVERFLOW_BIT;
cmd->residual_count = (size - cmd->data_length);
} else {
cmd->se_cmd_flags |= SCF_UNDERFLOW_BIT;
cmd->residual_count = (cmd->data_length - size);
+ cmd->data_length = size;
}
- cmd->data_length = size;
}
return 0;
@@ -1816,61 +1849,6 @@ execute:
EXPORT_SYMBOL(target_execute_cmd);
/*
- * Used to obtain Sense Data from underlying Linux/SCSI struct scsi_cmnd
- */
-static int transport_get_sense_data(struct se_cmd *cmd)
-{
- unsigned char *buffer = cmd->sense_buffer, *sense_buffer = NULL;
- struct se_device *dev = cmd->se_dev;
- unsigned long flags;
- u32 offset = 0;
-
- WARN_ON(!cmd->se_lun);
-
- if (!dev)
- return 0;
-
- spin_lock_irqsave(&cmd->t_state_lock, flags);
- if (cmd->se_cmd_flags & SCF_SENT_CHECK_CONDITION) {
- spin_unlock_irqrestore(&cmd->t_state_lock, flags);
- return 0;
- }
-
- if (!(cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE))
- goto out;
-
- if (!dev->transport->get_sense_buffer) {
- pr_err("dev->transport->get_sense_buffer is NULL\n");
- goto out;
- }
-
- sense_buffer = dev->transport->get_sense_buffer(cmd);
- if (!sense_buffer) {
- pr_err("ITT 0x%08x cmd %p: Unable to locate"
- " sense buffer for task with sense\n",
- cmd->se_tfo->get_task_tag(cmd), cmd);
- goto out;
- }
-
- spin_unlock_irqrestore(&cmd->t_state_lock, flags);
-
- offset = cmd->se_tfo->set_fabric_sense_len(cmd, TRANSPORT_SENSE_BUFFER);
-
- memcpy(&buffer[offset], sense_buffer, TRANSPORT_SENSE_BUFFER);
-
- /* Automatically padded */
- cmd->scsi_sense_length = TRANSPORT_SENSE_BUFFER + offset;
-
- pr_debug("HBA_[%u]_PLUG[%s]: Set SAM STATUS: 0x%02x and sense\n",
- dev->se_hba->hba_id, dev->transport->name, cmd->scsi_status);
- return 0;
-
-out:
- spin_unlock_irqrestore(&cmd->t_state_lock, flags);
- return -1;
-}
-
-/*
* Process all commands up to the last received ORDERED task attribute which
* requires another blocking boundary
*/
@@ -1985,7 +1963,7 @@ static void transport_handle_queue_full(
static void target_complete_ok_work(struct work_struct *work)
{
struct se_cmd *cmd = container_of(work, struct se_cmd, work);
- int reason = 0, ret;
+ int ret;
/*
* Check if we need to move delayed/dormant tasks from cmds on the
@@ -2002,23 +1980,19 @@ static void target_complete_ok_work(struct work_struct *work)
schedule_work(&cmd->se_dev->qf_work_queue);
/*
- * Check if we need to retrieve a sense buffer from
+ * Check if we need to send a sense buffer from
* the struct se_cmd in question.
*/
if (cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) {
- if (transport_get_sense_data(cmd) < 0)
- reason = TCM_NON_EXISTENT_LUN;
-
- if (cmd->scsi_status) {
- ret = transport_send_check_condition_and_sense(
- cmd, reason, 1);
- if (ret == -EAGAIN || ret == -ENOMEM)
- goto queue_full;
+ WARN_ON(!cmd->scsi_status);
+ ret = transport_send_check_condition_and_sense(
+ cmd, 0, 1);
+ if (ret == -EAGAIN || ret == -ENOMEM)
+ goto queue_full;
- transport_lun_remove_cmd(cmd);
- transport_cmd_check_stop_to_fabric(cmd);
- return;
- }
+ transport_lun_remove_cmd(cmd);
+ transport_cmd_check_stop_to_fabric(cmd);
+ return;
}
/*
* Check for a callback, used by amongst other things
@@ -2216,7 +2190,6 @@ void *transport_kmap_data_sg(struct se_cmd *cmd)
struct page **pages;
int i;
- BUG_ON(!sg);
/*
* We need to take into account a possible offset here for fabrics like
* tcm_loop who may be using a contig buffer from the SCSI midlayer for
@@ -2224,13 +2197,17 @@ void *transport_kmap_data_sg(struct se_cmd *cmd)
*/
if (!cmd->t_data_nents)
return NULL;
- else if (cmd->t_data_nents == 1)
+
+ BUG_ON(!sg);
+ if (cmd->t_data_nents == 1)
return kmap(sg_page(sg)) + sg->offset;
/* >1 page. use vmap */
pages = kmalloc(sizeof(*pages) * cmd->t_data_nents, GFP_KERNEL);
- if (!pages)
+ if (!pages) {
+ cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
return NULL;
+ }
/* convert sg[] to pages[] */
for_each_sg(cmd->t_data_sg, sg, cmd->t_data_nents, i) {
@@ -2239,8 +2216,10 @@ void *transport_kmap_data_sg(struct se_cmd *cmd)
cmd->t_data_vmap = vmap(pages, cmd->t_data_nents, VM_MAP, PAGE_KERNEL);
kfree(pages);
- if (!cmd->t_data_vmap)
+ if (!cmd->t_data_vmap) {
+ cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
return NULL;
+ }
return cmd->t_data_vmap + cmd->t_data_sg[0].offset;
}
@@ -2326,19 +2305,14 @@ int transport_generic_new_cmd(struct se_cmd *cmd)
* into the fabric for data transfers, go ahead and complete it right
* away.
*/
- if (!cmd->data_length) {
+ if (!cmd->data_length &&
+ cmd->t_task_cdb[0] != REQUEST_SENSE &&
+ cmd->se_dev->transport->transport_type != TRANSPORT_PLUGIN_PHBA_PDEV) {
spin_lock_irq(&cmd->t_state_lock);
cmd->t_state = TRANSPORT_COMPLETE;
cmd->transport_state |= CMD_T_ACTIVE;
spin_unlock_irq(&cmd->t_state_lock);
- if (cmd->t_task_cdb[0] == REQUEST_SENSE) {
- u8 ua_asc = 0, ua_ascq = 0;
-
- core_scsi3_ua_clear_for_request_sense(cmd,
- &ua_asc, &ua_ascq);
- }
-
INIT_WORK(&cmd->work, target_complete_ok_work);
queue_work(target_completion_wq, &cmd->work);
return 0;
diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
index d956965..3440812 100644
--- a/drivers/usb/core/devices.c
+++ b/drivers/usb/core/devices.c
@@ -624,7 +624,7 @@ static ssize_t usb_device_read(struct file *file, char __user *buf,
/* print devices for all busses */
list_for_each_entry(bus, &usb_bus_list, bus_list) {
/* recurse through all children of the root hub */
- if (!bus->root_hub)
+ if (!bus_to_hcd(bus)->rh_registered)
continue;
usb_lock_device(bus->root_hub);
ret = usb_device_dump(&buf, &nbytes, &skip_bytes, ppos,
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index bc84106..75ba209 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -1011,10 +1011,7 @@ static int register_root_hub(struct usb_hcd *hcd)
if (retval) {
dev_err (parent_dev, "can't register root hub for %s, %d\n",
dev_name(&usb_dev->dev), retval);
- }
- mutex_unlock(&usb_bus_list_lock);
-
- if (retval == 0) {
+ } else {
spin_lock_irq (&hcd_root_hub_lock);
hcd->rh_registered = 1;
spin_unlock_irq (&hcd_root_hub_lock);
@@ -1023,6 +1020,7 @@ static int register_root_hub(struct usb_hcd *hcd)
if (HCD_DEAD(hcd))
usb_hc_died (hcd); /* This time clean up */
}
+ mutex_unlock(&usb_bus_list_lock);
return retval;
}
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
index aaa8d2b..0bf72f9 100644
--- a/drivers/usb/host/ohci-at91.c
+++ b/drivers/usb/host/ohci-at91.c
@@ -467,7 +467,8 @@ static irqreturn_t ohci_hcd_at91_overcurrent_irq(int irq, void *data)
/* From the GPIO notifying the over-current situation, find
* out the corresponding port */
at91_for_each_port(port) {
- if (gpio_to_irq(pdata->overcurrent_pin[port]) == irq) {
+ if (gpio_is_valid(pdata->overcurrent_pin[port]) &&
+ gpio_to_irq(pdata->overcurrent_pin[port]) == irq) {
gpio = pdata->overcurrent_pin[port];
break;
}
diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c
index 211a492..d8dedc7 100644
--- a/drivers/vfio/pci/vfio_pci_intrs.c
+++ b/drivers/vfio/pci/vfio_pci_intrs.c
@@ -76,9 +76,24 @@ static int virqfd_wakeup(wait_queue_t *wait, unsigned mode, int sync, void *key)
schedule_work(&virqfd->inject);
}
- if (flags & POLLHUP)
- /* The eventfd is closing, detach from VFIO */
- virqfd_deactivate(virqfd);
+ if (flags & POLLHUP) {
+ unsigned long flags;
+ spin_lock_irqsave(&virqfd->vdev->irqlock, flags);
+
+ /*
+ * The eventfd is closing, if the virqfd has not yet been
+ * queued for release, as determined by testing whether the
+ * vdev pointer to it is still valid, queue it now. As
+ * with kvm irqfds, we know we won't race against the virqfd
+ * going away because we hold wqh->lock to get here.
+ */
+ if (*(virqfd->pvirqfd) == virqfd) {
+ *(virqfd->pvirqfd) = NULL;
+ virqfd_deactivate(virqfd);
+ }
+
+ spin_unlock_irqrestore(&virqfd->vdev->irqlock, flags);
+ }
return 0;
}
@@ -93,7 +108,6 @@ static void virqfd_ptable_queue_proc(struct file *file,
static void virqfd_shutdown(struct work_struct *work)
{
struct virqfd *virqfd = container_of(work, struct virqfd, shutdown);
- struct virqfd **pvirqfd = virqfd->pvirqfd;
u64 cnt;
eventfd_ctx_remove_wait_queue(virqfd->eventfd, &virqfd->wait, &cnt);
@@ -101,7 +115,6 @@ static void virqfd_shutdown(struct work_struct *work)
eventfd_ctx_put(virqfd->eventfd);
kfree(virqfd);
- *pvirqfd = NULL;
}
static void virqfd_inject(struct work_struct *work)
@@ -122,15 +135,11 @@ static int virqfd_enable(struct vfio_pci_device *vdev,
int ret = 0;
unsigned int events;
- if (*pvirqfd)
- return -EBUSY;
-
virqfd = kzalloc(sizeof(*virqfd), GFP_KERNEL);
if (!virqfd)
return -ENOMEM;
virqfd->pvirqfd = pvirqfd;
- *pvirqfd = virqfd;
virqfd->vdev = vdev;
virqfd->handler = handler;
virqfd->thread = thread;
@@ -154,6 +163,23 @@ static int virqfd_enable(struct vfio_pci_device *vdev,
virqfd->eventfd = ctx;
/*
+ * virqfds can be released by closing the eventfd or directly
+ * through ioctl. These are both done through a workqueue, so
+ * we update the pointer to the virqfd under lock to avoid
+ * pushing multiple jobs to release the same virqfd.
+ */
+ spin_lock_irq(&vdev->irqlock);
+
+ if (*pvirqfd) {
+ spin_unlock_irq(&vdev->irqlock);
+ ret = -EBUSY;
+ goto fail;
+ }
+ *pvirqfd = virqfd;
+
+ spin_unlock_irq(&vdev->irqlock);
+
+ /*
* Install our own custom wake-up handling so we are notified via
* a callback whenever someone signals the underlying eventfd.
*/
@@ -187,19 +213,29 @@ fail:
fput(file);
kfree(virqfd);
- *pvirqfd = NULL;
return ret;
}
-static void virqfd_disable(struct virqfd *virqfd)
+static void virqfd_disable(struct vfio_pci_device *vdev,
+ struct virqfd **pvirqfd)
{
- if (!virqfd)
- return;
+ unsigned long flags;
+
+ spin_lock_irqsave(&vdev->irqlock, flags);
+
+ if (*pvirqfd) {
+ virqfd_deactivate(*pvirqfd);
+ *pvirqfd = NULL;
+ }
- virqfd_deactivate(virqfd);
+ spin_unlock_irqrestore(&vdev->irqlock, flags);
- /* Block until we know all outstanding shutdown jobs have completed. */
+ /*
+ * Block until we know all outstanding shutdown jobs have completed.
+ * Even if we don't queue the job, flush the wq to be sure it's
+ * been released.
+ */
flush_workqueue(vfio_irqfd_cleanup_wq);
}
@@ -392,8 +428,8 @@ static int vfio_intx_set_signal(struct vfio_pci_device *vdev, int fd)
static void vfio_intx_disable(struct vfio_pci_device *vdev)
{
vfio_intx_set_signal(vdev, -1);
- virqfd_disable(vdev->ctx[0].unmask);
- virqfd_disable(vdev->ctx[0].mask);
+ virqfd_disable(vdev, &vdev->ctx[0].unmask);
+ virqfd_disable(vdev, &vdev->ctx[0].mask);
vdev->irq_type = VFIO_PCI_NUM_IRQS;
vdev->num_ctx = 0;
kfree(vdev->ctx);
@@ -539,8 +575,8 @@ static void vfio_msi_disable(struct vfio_pci_device *vdev, bool msix)
vfio_msi_set_block(vdev, 0, vdev->num_ctx, NULL, msix);
for (i = 0; i < vdev->num_ctx; i++) {
- virqfd_disable(vdev->ctx[i].unmask);
- virqfd_disable(vdev->ctx[i].mask);
+ virqfd_disable(vdev, &vdev->ctx[i].unmask);
+ virqfd_disable(vdev, &vdev->ctx[i].mask);
}
if (msix) {
@@ -577,7 +613,7 @@ static int vfio_pci_set_intx_unmask(struct vfio_pci_device *vdev,
vfio_send_intx_eventfd, NULL,
&vdev->ctx[0].unmask, fd);
- virqfd_disable(vdev->ctx[0].unmask);
+ virqfd_disable(vdev, &vdev->ctx[0].unmask);
}
return 0;
diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c
index 1eff743..ae60406 100644
--- a/drivers/watchdog/hpwdt.c
+++ b/drivers/watchdog/hpwdt.c
@@ -814,6 +814,9 @@ static int __devinit hpwdt_init_one(struct pci_dev *dev,
hpwdt_timer_reg = pci_mem_addr + 0x70;
hpwdt_timer_con = pci_mem_addr + 0x72;
+ /* Make sure that timer is disabled until /dev/watchdog is opened */
+ hpwdt_stop();
+
/* Make sure that we have a valid soft_margin */
if (hpwdt_change_timer(soft_margin))
hpwdt_change_timer(DEFAULT_MARGIN);
diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c
index 6aa46a9..3796434 100644
--- a/drivers/watchdog/watchdog_core.c
+++ b/drivers/watchdog/watchdog_core.c
@@ -128,11 +128,12 @@ EXPORT_SYMBOL_GPL(watchdog_register_device);
void watchdog_unregister_device(struct watchdog_device *wdd)
{
int ret;
- int devno = wdd->cdev.dev;
+ int devno;
if (wdd == NULL)
return;
+ devno = wdd->cdev.dev;
ret = watchdog_dev_unregister(wdd);
if (ret)
pr_err("error unregistering /dev/watchdog (err=%d)\n", ret);
diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c
index 1ffd03b..7f12416 100644
--- a/drivers/xen/gntdev.c
+++ b/drivers/xen/gntdev.c
@@ -314,8 +314,9 @@ static int __unmap_grant_pages(struct grant_map *map, int offset, int pages)
}
}
- err = gnttab_unmap_refs(map->unmap_ops + offset, map->pages + offset,
- pages, true);
+ err = gnttab_unmap_refs(map->unmap_ops + offset,
+ use_ptemod ? map->kmap_ops + offset : NULL, map->pages + offset,
+ pages);
if (err)
return err;
diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c
index 0bfc1ef..0067266 100644
--- a/drivers/xen/grant-table.c
+++ b/drivers/xen/grant-table.c
@@ -870,7 +870,8 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
EXPORT_SYMBOL_GPL(gnttab_map_refs);
int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
- struct page **pages, unsigned int count, bool clear_pte)
+ struct gnttab_map_grant_ref *kmap_ops,
+ struct page **pages, unsigned int count)
{
int i, ret;
bool lazy = false;
@@ -888,7 +889,8 @@ int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
}
for (i = 0; i < count; i++) {
- ret = m2p_remove_override(pages[i], clear_pte);
+ ret = m2p_remove_override(pages[i], kmap_ops ?
+ &kmap_ops[i] : NULL);
if (ret)
return ret;
}
diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
index 38b42e7..b650155 100644
--- a/fs/btrfs/qgroup.c
+++ b/fs/btrfs/qgroup.c
@@ -1371,10 +1371,8 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans,
if (srcid) {
srcgroup = find_qgroup_rb(fs_info, srcid);
- if (!srcgroup) {
- ret = -EINVAL;
+ if (!srcgroup)
goto unlock;
- }
dstgroup->rfer = srcgroup->rfer - level_size;
dstgroup->rfer_cmpr = srcgroup->rfer_cmpr - level_size;
srcgroup->excl = level_size;
@@ -1383,10 +1381,8 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans,
qgroup_dirty(fs_info, srcgroup);
}
- if (!inherit) {
- ret = -EINVAL;
+ if (!inherit)
goto unlock;
- }
i_qgroups = (u64 *)(inherit + 1);
for (i = 0; i < inherit->num_qgroups; ++i) {
diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c
index 7dab9c0..53cf2aa 100644
--- a/fs/cifs/cifs_unicode.c
+++ b/fs/cifs/cifs_unicode.c
@@ -328,7 +328,7 @@ cifsConvertToUTF16(__le16 *target, const char *source, int srclen,
}
ctoUTF16_out:
- return i;
+ return j;
}
#ifdef CONFIG_CIFS_SMB2
diff --git a/fs/dcache.c b/fs/dcache.c
index 8086636..0364af2 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -389,7 +389,7 @@ static struct dentry *d_kill(struct dentry *dentry, struct dentry *parent)
* Inform try_to_ascend() that we are no longer attached to the
* dentry tree
*/
- dentry->d_flags |= DCACHE_DISCONNECTED;
+ dentry->d_flags |= DCACHE_DENTRY_KILLED;
if (parent)
spin_unlock(&parent->d_lock);
dentry_iput(dentry);
@@ -1048,7 +1048,7 @@ static struct dentry *try_to_ascend(struct dentry *old, int locked, unsigned seq
* or deletion
*/
if (new != old->d_parent ||
- (old->d_flags & DCACHE_DISCONNECTED) ||
+ (old->d_flags & DCACHE_DENTRY_KILLED) ||
(!locked && read_seqretry(&rename_lock, seq))) {
spin_unlock(&new->d_lock);
new = NULL;
@@ -1141,7 +1141,7 @@ rename_retry:
EXPORT_SYMBOL(have_submounts);
/*
- * Search the dentry child list for the specified parent,
+ * Search the dentry child list of the specified parent,
* and move any unused dentries to the end of the unused
* list for prune_dcache(). We descend to the next level
* whenever the d_subdirs list is non-empty and continue
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
index 2340f69..c5ca6ae 100644
--- a/fs/debugfs/file.c
+++ b/fs/debugfs/file.c
@@ -526,73 +526,51 @@ struct array_data {
u32 elements;
};
-static int u32_array_open(struct inode *inode, struct file *file)
-{
- file->private_data = NULL;
- return nonseekable_open(inode, file);
-}
-
-static size_t format_array(char *buf, size_t bufsize, const char *fmt,
- u32 *array, u32 array_size)
+static size_t u32_format_array(char *buf, size_t bufsize,
+ u32 *array, int array_size)
{
size_t ret = 0;
- u32 i;
- for (i = 0; i < array_size; i++) {
+ while (--array_size >= 0) {
size_t len;
+ char term = array_size ? ' ' : '\n';
- len = snprintf(buf, bufsize, fmt, array[i]);
- len++; /* ' ' or '\n' */
+ len = snprintf(buf, bufsize, "%u%c", *array++, term);
ret += len;
- if (buf) {
- buf += len;
- bufsize -= len;
- buf[-1] = (i == array_size-1) ? '\n' : ' ';
- }
+ buf += len;
+ bufsize -= len;
}
-
- ret++; /* \0 */
- if (buf)
- *buf = '\0';
-
return ret;
}
-static char *format_array_alloc(const char *fmt, u32 *array,
- u32 array_size)
+static int u32_array_open(struct inode *inode, struct file *file)
{
- size_t len = format_array(NULL, 0, fmt, array, array_size);
- char *ret;
-
- ret = kmalloc(len, GFP_KERNEL);
- if (ret == NULL)
- return NULL;
+ struct array_data *data = inode->i_private;
+ int size, elements = data->elements;
+ char *buf;
+
+ /*
+ * Max size:
+ * - 10 digits + ' '/'\n' = 11 bytes per number
+ * - terminating NUL character
+ */
+ size = elements*11;
+ buf = kmalloc(size+1, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+ buf[size] = 0;
+
+ file->private_data = buf;
+ u32_format_array(buf, size, data->array, data->elements);
- format_array(ret, len, fmt, array, array_size);
- return ret;
+ return nonseekable_open(inode, file);
}
static ssize_t u32_array_read(struct file *file, char __user *buf, size_t len,
loff_t *ppos)
{
- struct inode *inode = file->f_path.dentry->d_inode;
- struct array_data *data = inode->i_private;
- size_t size;
-
- if (*ppos == 0) {
- if (file->private_data) {
- kfree(file->private_data);
- file->private_data = NULL;
- }
-
- file->private_data = format_array_alloc("%u", data->array,
- data->elements);
- }
-
- size = 0;
- if (file->private_data)
- size = strlen(file->private_data);
+ size_t size = strlen(file->private_data);
return simple_read_from_buffer(buf, len, ppos,
file->private_data, size);
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
index fb1a2be..8d80c99 100644
--- a/fs/lockd/svclock.c
+++ b/fs/lockd/svclock.c
@@ -289,7 +289,6 @@ static void nlmsvc_free_block(struct kref *kref)
dprintk("lockd: freeing block %p...\n", block);
/* Remove block from file's list of blocks */
- mutex_lock(&file->f_mutex);
list_del_init(&block->b_flist);
mutex_unlock(&file->f_mutex);
@@ -303,7 +302,7 @@ static void nlmsvc_free_block(struct kref *kref)
static void nlmsvc_release_block(struct nlm_block *block)
{
if (block != NULL)
- kref_put(&block->b_count, nlmsvc_free_block);
+ kref_put_mutex(&block->b_count, nlmsvc_free_block, &block->b_file->f_mutex);
}
/*
diff --git a/fs/namespace.c b/fs/namespace.c
index 4d31f73..7bdf790 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -1886,8 +1886,14 @@ static int do_add_mount(struct mount *newmnt, struct path *path, int mnt_flags)
return err;
err = -EINVAL;
- if (!(mnt_flags & MNT_SHRINKABLE) && !check_mnt(real_mount(path->mnt)))
- goto unlock;
+ if (unlikely(!check_mnt(real_mount(path->mnt)))) {
+ /* that's acceptable only for automounts done in private ns */
+ if (!(mnt_flags & MNT_SHRINKABLE))
+ goto unlock;
+ /* ... and for those we'd better have mountpoint still alive */
+ if (!real_mount(path->mnt)->mnt_ns)
+ goto unlock;
+ }
/* Refuse the same filesystem on the same mount point */
err = -EBUSY;
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index dfafeb2..eb7cc91 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -462,9 +462,6 @@ static struct dentry *proc_sys_lookup(struct inode *dir, struct dentry *dentry,
err = ERR_PTR(-ENOMEM);
inode = proc_sys_make_inode(dir->i_sb, h ? h : head, p);
- if (h)
- sysctl_head_finish(h);
-
if (!inode)
goto out;
@@ -473,6 +470,8 @@ static struct dentry *proc_sys_lookup(struct inode *dir, struct dentry *dentry,
d_add(dentry, inode);
out:
+ if (h)
+ sysctl_head_finish(h);
sysctl_head_finish(head);
return err;
}
diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c
index d7a9dd7..933b793 100644
--- a/fs/xfs/xfs_buf.c
+++ b/fs/xfs/xfs_buf.c
@@ -96,6 +96,7 @@ xfs_buf_lru_add(
atomic_inc(&bp->b_hold);
list_add_tail(&bp->b_lru, &btp->bt_lru);
btp->bt_lru_nr++;
+ bp->b_lru_flags &= ~_XBF_LRU_DISPOSE;
}
spin_unlock(&btp->bt_lru_lock);
}
@@ -154,7 +155,8 @@ xfs_buf_stale(
struct xfs_buftarg *btp = bp->b_target;
spin_lock(&btp->bt_lru_lock);
- if (!list_empty(&bp->b_lru)) {
+ if (!list_empty(&bp->b_lru) &&
+ !(bp->b_lru_flags & _XBF_LRU_DISPOSE)) {
list_del_init(&bp->b_lru);
btp->bt_lru_nr--;
atomic_dec(&bp->b_hold);
@@ -1501,6 +1503,7 @@ xfs_buftarg_shrink(
*/
list_move(&bp->b_lru, &dispose);
btp->bt_lru_nr--;
+ bp->b_lru_flags |= _XBF_LRU_DISPOSE;
}
spin_unlock(&btp->bt_lru_lock);
diff --git a/fs/xfs/xfs_buf.h b/fs/xfs/xfs_buf.h
index d03b73b..7c0b6a0 100644
--- a/fs/xfs/xfs_buf.h
+++ b/fs/xfs/xfs_buf.h
@@ -38,27 +38,28 @@ typedef enum {
XBRW_ZERO = 3, /* Zero target memory */
} xfs_buf_rw_t;
-#define XBF_READ (1 << 0) /* buffer intended for reading from device */
-#define XBF_WRITE (1 << 1) /* buffer intended for writing to device */
-#define XBF_READ_AHEAD (1 << 2) /* asynchronous read-ahead */
-#define XBF_ASYNC (1 << 4) /* initiator will not wait for completion */
-#define XBF_DONE (1 << 5) /* all pages in the buffer uptodate */
-#define XBF_STALE (1 << 6) /* buffer has been staled, do not find it */
+#define XBF_READ (1 << 0) /* buffer intended for reading from device */
+#define XBF_WRITE (1 << 1) /* buffer intended for writing to device */
+#define XBF_READ_AHEAD (1 << 2) /* asynchronous read-ahead */
+#define XBF_ASYNC (1 << 4) /* initiator will not wait for completion */
+#define XBF_DONE (1 << 5) /* all pages in the buffer uptodate */
+#define XBF_STALE (1 << 6) /* buffer has been staled, do not find it */
/* I/O hints for the BIO layer */
-#define XBF_SYNCIO (1 << 10)/* treat this buffer as synchronous I/O */
-#define XBF_FUA (1 << 11)/* force cache write through mode */
-#define XBF_FLUSH (1 << 12)/* flush the disk cache before a write */
+#define XBF_SYNCIO (1 << 10)/* treat this buffer as synchronous I/O */
+#define XBF_FUA (1 << 11)/* force cache write through mode */
+#define XBF_FLUSH (1 << 12)/* flush the disk cache before a write */
/* flags used only as arguments to access routines */
-#define XBF_TRYLOCK (1 << 16)/* lock requested, but do not wait */
-#define XBF_UNMAPPED (1 << 17)/* do not map the buffer */
+#define XBF_TRYLOCK (1 << 16)/* lock requested, but do not wait */
+#define XBF_UNMAPPED (1 << 17)/* do not map the buffer */
/* flags used only internally */
-#define _XBF_PAGES (1 << 20)/* backed by refcounted pages */
-#define _XBF_KMEM (1 << 21)/* backed by heap memory */
-#define _XBF_DELWRI_Q (1 << 22)/* buffer on a delwri queue */
-#define _XBF_COMPOUND (1 << 23)/* compound buffer */
+#define _XBF_PAGES (1 << 20)/* backed by refcounted pages */
+#define _XBF_KMEM (1 << 21)/* backed by heap memory */
+#define _XBF_DELWRI_Q (1 << 22)/* buffer on a delwri queue */
+#define _XBF_COMPOUND (1 << 23)/* compound buffer */
+#define _XBF_LRU_DISPOSE (1 << 24)/* buffer being discarded */
typedef unsigned int xfs_buf_flags_t;
@@ -72,12 +73,13 @@ typedef unsigned int xfs_buf_flags_t;
{ XBF_SYNCIO, "SYNCIO" }, \
{ XBF_FUA, "FUA" }, \
{ XBF_FLUSH, "FLUSH" }, \
- { XBF_TRYLOCK, "TRYLOCK" }, /* should never be set */\
+ { XBF_TRYLOCK, "TRYLOCK" }, /* should never be set */\
{ XBF_UNMAPPED, "UNMAPPED" }, /* ditto */\
{ _XBF_PAGES, "PAGES" }, \
{ _XBF_KMEM, "KMEM" }, \
{ _XBF_DELWRI_Q, "DELWRI_Q" }, \
- { _XBF_COMPOUND, "COMPOUND" }
+ { _XBF_COMPOUND, "COMPOUND" }, \
+ { _XBF_LRU_DISPOSE, "LRU_DISPOSE" }
typedef struct xfs_buftarg {
dev_t bt_dev;
@@ -124,7 +126,12 @@ typedef struct xfs_buf {
xfs_buf_flags_t b_flags; /* status flags */
struct semaphore b_sema; /* semaphore for lockables */
+ /*
+ * concurrent access to b_lru and b_lru_flags are protected by
+ * bt_lru_lock and not by b_sema
+ */
struct list_head b_lru; /* lru list */
+ xfs_buf_flags_t b_lru_flags; /* internal lru status flags */
wait_queue_head_t b_waiters; /* unpin waiters */
struct list_head b_list;
struct xfs_perag *b_pag; /* contains rbtree root */
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index bdaf4cb..19e2380 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -919,6 +919,7 @@ xfs_fs_put_super(
struct xfs_mount *mp = XFS_M(sb);
xfs_filestream_unmount(mp);
+ cancel_delayed_work_sync(&mp->m_sync_work);
xfs_unmountfs(mp);
xfs_syncd_stop(mp);
xfs_freesb(mp);
diff --git a/include/asm-generic/unistd.h b/include/asm-generic/unistd.h
index 991ef01..3748ec92 100644
--- a/include/asm-generic/unistd.h
+++ b/include/asm-generic/unistd.h
@@ -691,9 +691,11 @@ __SC_COMP(__NR_process_vm_readv, sys_process_vm_readv, \
#define __NR_process_vm_writev 271
__SC_COMP(__NR_process_vm_writev, sys_process_vm_writev, \
compat_sys_process_vm_writev)
+#define __NR_kcmp 272
+__SYSCALL(__NR_kcmp, sys_kcmp)
#undef __NR_syscalls
-#define __NR_syscalls 272
+#define __NR_syscalls 273
/*
* All syscalls below here should go away really,
diff --git a/include/linux/atmel-ssc.h b/include/linux/atmel-ssc.h
index 0602339..4eb3175 100644
--- a/include/linux/atmel-ssc.h
+++ b/include/linux/atmel-ssc.h
@@ -3,6 +3,7 @@
#include <linux/platform_device.h>
#include <linux/list.h>
+#include <linux/io.h>
struct ssc_device {
struct list_head list;
diff --git a/include/linux/compiler-gcc4.h b/include/linux/compiler-gcc4.h
index 2f40791..934bc34 100644
--- a/include/linux/compiler-gcc4.h
+++ b/include/linux/compiler-gcc4.h
@@ -49,6 +49,13 @@
#endif
#endif
+#if __GNUC_MINOR__ >= 6
+/*
+ * Tell the optimizer that something else uses this function or variable.
+ */
+#define __visible __attribute__((externally_visible))
+#endif
+
#if __GNUC_MINOR__ > 0
#define __compiletime_object_size(obj) __builtin_object_size(obj, 0)
#endif
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index 923d093..f430e41 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -278,6 +278,10 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect);
# define __section(S) __attribute__ ((__section__(#S)))
#endif
+#ifndef __visible
+#define __visible
+#endif
+
/* Are two types/vars the same type (ignoring qualifiers)? */
#ifndef __same_type
# define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index caa34e5..5920079 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -206,6 +206,8 @@ struct dentry_operations {
#define DCACHE_MANAGED_DENTRY \
(DCACHE_MOUNTED|DCACHE_NEED_AUTOMOUNT|DCACHE_MANAGE_TRANSIT)
+#define DCACHE_DENTRY_KILLED 0x100000
+
extern seqlock_t rename_lock;
static inline int dname_external(struct dentry *dentry)
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 594b419..2451f1f 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -91,7 +91,7 @@
{ \
typeof(x) __x = x; \
typeof(divisor) __d = divisor; \
- (((typeof(x))-1) >= 0 || (__x) >= 0) ? \
+ (((typeof(x))-1) > 0 || (__x) > 0) ? \
(((__x) + ((__d) / 2)) / (__d)) : \
(((__x) - ((__d) / 2)) / (__d)); \
} \
diff --git a/include/linux/memory.h b/include/linux/memory.h
index 1ac7f6e..ff9a9f8 100644
--- a/include/linux/memory.h
+++ b/include/linux/memory.h
@@ -19,7 +19,7 @@
#include <linux/compiler.h>
#include <linux/mutex.h>
-#define MIN_MEMORY_BLOCK_SIZE (1 << SECTION_SIZE_BITS)
+#define MIN_MEMORY_BLOCK_SIZE (1UL << SECTION_SIZE_BITS)
struct memory_block {
unsigned long start_section_nr;
diff --git a/include/linux/mfd/core.h b/include/linux/mfd/core.h
index 3a8435a..cebe97e 100644
--- a/include/linux/mfd/core.h
+++ b/include/linux/mfd/core.h
@@ -16,6 +16,8 @@
#include <linux/platform_device.h>
+struct irq_domain;
+
/*
* This struct describes the MFD part ("cell").
* After registration the copy of this structure will become the platform data
@@ -98,7 +100,7 @@ static inline const struct mfd_cell *mfd_get_cell(struct platform_device *pdev)
extern int mfd_add_devices(struct device *parent, int id,
struct mfd_cell *cells, int n_devs,
struct resource *mem_base,
- int irq_base);
+ int irq_base, struct irq_domain *irq_domain);
extern void mfd_remove_devices(struct device *parent);
diff --git a/include/linux/mfd/tps65217.h b/include/linux/mfd/tps65217.h
index 12c0687..7cd83d8 100644
--- a/include/linux/mfd/tps65217.h
+++ b/include/linux/mfd/tps65217.h
@@ -22,6 +22,9 @@
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
+/* TPS chip id list */
+#define TPS65217 0xF0
+
/* I2C ID for TPS65217 part */
#define TPS65217_I2C_ID 0x24
@@ -248,13 +251,11 @@ struct tps_info {
struct tps65217 {
struct device *dev;
struct tps65217_board *pdata;
+ unsigned int id;
struct regulator_desc desc[TPS65217_NUM_REGULATOR];
struct regulator_dev *rdev[TPS65217_NUM_REGULATOR];
struct tps_info *info[TPS65217_NUM_REGULATOR];
struct regmap *regmap;
-
- /* Client devices */
- struct platform_device *regulator_pdev[TPS65217_NUM_REGULATOR];
};
static inline struct tps65217 *dev_to_tps65217(struct device *dev)
@@ -262,6 +263,11 @@ static inline struct tps65217 *dev_to_tps65217(struct device *dev)
return dev_get_drvdata(dev);
}
+static inline int tps65217_chip_id(struct tps65217 *tps65217)
+{
+ return tps65217->id;
+}
+
int tps65217_reg_read(struct tps65217 *tps, unsigned int reg,
unsigned int *val);
int tps65217_reg_write(struct tps65217 *tps, unsigned int reg,
diff --git a/include/linux/micrel_phy.h b/include/linux/micrel_phy.h
index 61f0905..de20120 100644
--- a/include/linux/micrel_phy.h
+++ b/include/linux/micrel_phy.h
@@ -1,3 +1,15 @@
+/*
+ * include/linux/micrel_phy.h
+ *
+ * Micrel PHY IDs
+ *
+ * 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.
+ *
+ */
+
#ifndef _MICREL_PHY_H
#define _MICREL_PHY_H
@@ -5,10 +17,11 @@
#define PHY_ID_KSZ9021 0x00221610
#define PHY_ID_KS8737 0x00221720
-#define PHY_ID_KS8041 0x00221510
-#define PHY_ID_KS8051 0x00221550
+#define PHY_ID_KSZ8021 0x00221555
+#define PHY_ID_KSZ8041 0x00221510
+#define PHY_ID_KSZ8051 0x00221550
/* both for ks8001 Rev. A/B, and for ks8721 Rev 3. */
-#define PHY_ID_KS8001 0x0022161A
+#define PHY_ID_KSZ8001 0x0022161A
/* struct phy_device dev_flags definitions */
#define MICREL_PHY_50MHZ_CLK 0x00000001
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 33ed9d6..bdb4161 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -274,6 +274,8 @@ struct perf_event_attr {
__u64 branch_sample_type; /* enum branch_sample_type */
};
+#define perf_flags(attr) (*(&(attr)->read_format + 1))
+
/*
* Ioctls that can be done on a perf event fd:
*/
diff --git a/include/linux/sched.h b/include/linux/sched.h
index a8e2413..439d35a 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -954,7 +954,6 @@ struct sched_domain {
unsigned int smt_gain;
int flags; /* See SD_* */
int level;
- int idle_buddy; /* cpu assigned to select_idle_sibling() */
/* Runtime fields. */
unsigned long last_balance; /* init to jiffies. units in jiffies */
diff --git a/include/linux/security.h b/include/linux/security.h
index 3dea6a9..d143b8e 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -118,6 +118,7 @@ void reset_security_ops(void);
extern unsigned long mmap_min_addr;
extern unsigned long dac_mmap_min_addr;
#else
+#define mmap_min_addr 0UL
#define dac_mmap_min_addr 0UL
#endif
diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h
index 22e61fd..28e493b 100644
--- a/include/linux/xfrm.h
+++ b/include/linux/xfrm.h
@@ -84,6 +84,8 @@ struct xfrm_replay_state {
__u32 bitmap;
};
+#define XFRMA_REPLAY_ESN_MAX 4096
+
struct xfrm_replay_state_esn {
unsigned int bmp_len;
__u32 oseq;
diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index cd64cf3..8a2a203 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -112,9 +112,8 @@ struct rt6_info {
struct inet6_dev *rt6i_idev;
unsigned long _rt6i_peer;
-#ifdef CONFIG_XFRM
- u32 rt6i_flow_cache_genid;
-#endif
+ u32 rt6i_genid;
+
/* more non-fragment space at head required */
unsigned short rt6i_nfheader_len;
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index d61e2b3..4faf661 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -110,6 +110,7 @@ struct net {
#endif
struct netns_ipvs *ipvs;
struct sock *diag_nlsk;
+ atomic_t rt_genid;
};
/*
@@ -315,5 +316,14 @@ static inline void unregister_net_sysctl_table(struct ctl_table_header *header)
}
#endif
+static inline int rt_genid(struct net *net)
+{
+ return atomic_read(&net->rt_genid);
+}
+
+static inline void rt_genid_bump(struct net *net)
+{
+ atomic_inc(&net->rt_genid);
+}
#endif /* __NET_NET_NAMESPACE_H */
diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h
index 7d00583..2ae2b837 100644
--- a/include/net/netns/ipv4.h
+++ b/include/net/netns/ipv4.h
@@ -64,7 +64,6 @@ struct netns_ipv4 {
kgid_t sysctl_ping_group_range[2];
long sysctl_tcp_mem[3];
- atomic_t rt_genid;
atomic_t dev_addr_genid;
#ifdef CONFIG_IP_MROUTE
diff --git a/include/net/sock.h b/include/net/sock.h
index bc476a1..c917556 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -1339,7 +1339,7 @@ static inline bool sk_wmem_schedule(struct sock *sk, int size)
}
static inline bool
-sk_rmem_schedule(struct sock *sk, struct sk_buff *skb, unsigned int size)
+sk_rmem_schedule(struct sock *sk, struct sk_buff *skb, int size)
{
if (!sk_has_account(sk))
return true;
diff --git a/include/target/target_core_backend.h b/include/target/target_core_backend.h
index f1405d33..941c84bf 100644
--- a/include/target/target_core_backend.h
+++ b/include/target/target_core_backend.h
@@ -23,7 +23,9 @@ struct se_subsystem_api {
struct se_device *(*create_virtdevice)(struct se_hba *,
struct se_subsystem_dev *, void *);
void (*free_device)(void *);
- int (*transport_complete)(struct se_cmd *cmd, struct scatterlist *);
+ void (*transport_complete)(struct se_cmd *cmd,
+ struct scatterlist *,
+ unsigned char *);
int (*parse_cdb)(struct se_cmd *cmd);
ssize_t (*check_configfs_dev_params)(struct se_hba *,
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
index 015cea0..5be8937 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -121,6 +121,7 @@
#define SE_INQUIRY_BUF 512
#define SE_MODE_PAGE_BUF 512
+#define SE_SENSE_BUF 96
/* struct se_hba->hba_flags */
enum hba_flags_table {
diff --git a/include/trace/events/kmem.h b/include/trace/events/kmem.h
index 5f889f1..08fa272 100644
--- a/include/trace/events/kmem.h
+++ b/include/trace/events/kmem.h
@@ -214,7 +214,7 @@ TRACE_EVENT(mm_page_alloc,
TP_printk("page=%p pfn=%lu order=%d migratetype=%d gfp_flags=%s",
__entry->page,
- page_to_pfn(__entry->page),
+ __entry->page ? page_to_pfn(__entry->page) : 0,
__entry->order,
__entry->migratetype,
show_gfp_flags(__entry->gfp_flags))
@@ -240,7 +240,7 @@ DECLARE_EVENT_CLASS(mm_page,
TP_printk("page=%p pfn=%lu order=%u migratetype=%d percpu_refill=%d",
__entry->page,
- page_to_pfn(__entry->page),
+ __entry->page ? page_to_pfn(__entry->page) : 0,
__entry->order,
__entry->migratetype,
__entry->order == 0)
diff --git a/include/xen/grant_table.h b/include/xen/grant_table.h
index 11e27c3..f19fff8 100644
--- a/include/xen/grant_table.h
+++ b/include/xen/grant_table.h
@@ -187,6 +187,7 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
struct gnttab_map_grant_ref *kmap_ops,
struct page **pages, unsigned int count);
int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
- struct page **pages, unsigned int count, bool clear_pte);
+ struct gnttab_map_grant_ref *kunmap_ops,
+ struct page **pages, unsigned int count);
#endif /* __ASM_GNTTAB_H__ */
diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c
index baa528d..478bad2 100644
--- a/kernel/pid_namespace.c
+++ b/kernel/pid_namespace.c
@@ -234,15 +234,19 @@ static int pid_ns_ctl_handler(struct ctl_table *table, int write,
*/
tmp.data = &current->nsproxy->pid_ns->last_pid;
- return proc_dointvec(&tmp, write, buffer, lenp, ppos);
+ return proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
}
+extern int pid_max;
+static int zero = 0;
static struct ctl_table pid_ns_ctl_table[] = {
{
.procname = "ns_last_pid",
.maxlen = sizeof(int),
.mode = 0666, /* permissions are checked in the handler */
.proc_handler = pid_ns_ctl_handler,
+ .extra1 = &zero,
+ .extra2 = &pid_max,
},
{ }
};
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index a4ea245..649c9f8 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -6014,11 +6014,6 @@ static void destroy_sched_domains(struct sched_domain *sd, int cpu)
* SD_SHARE_PKG_RESOURCE set (Last Level Cache Domain) for this
* allows us to avoid some pointer chasing select_idle_sibling().
*
- * Iterate domains and sched_groups downward, assigning CPUs to be
- * select_idle_sibling() hw buddy. Cross-wiring hw makes bouncing
- * due to random perturbation self canceling, ie sw buddies pull
- * their counterpart to their CPU's hw counterpart.
- *
* Also keep a unique ID per domain (we use the first cpu number in
* the cpumask of the domain), this allows us to quickly tell if
* two cpus are in the same cache domain, see cpus_share_cache().
@@ -6032,40 +6027,8 @@ static void update_top_cache_domain(int cpu)
int id = cpu;
sd = highest_flag_domain(cpu, SD_SHARE_PKG_RESOURCES);
- if (sd) {
- struct sched_domain *tmp = sd;
- struct sched_group *sg, *prev;
- bool right;
-
- /*
- * Traverse to first CPU in group, and count hops
- * to cpu from there, switching direction on each
- * hop, never ever pointing the last CPU rightward.
- */
- do {
- id = cpumask_first(sched_domain_span(tmp));
- prev = sg = tmp->groups;
- right = 1;
-
- while (cpumask_first(sched_group_cpus(sg)) != id)
- sg = sg->next;
-
- while (!cpumask_test_cpu(cpu, sched_group_cpus(sg))) {
- prev = sg;
- sg = sg->next;
- right = !right;
- }
-
- /* A CPU went down, never point back to domain start. */
- if (right && cpumask_first(sched_group_cpus(sg->next)) == id)
- right = false;
-
- sg = right ? sg->next : prev;
- tmp->idle_buddy = cpumask_first(sched_group_cpus(sg));
- } while ((tmp = tmp->child));
-
+ if (sd)
id = cpumask_first(sched_domain_span(sd));
- }
rcu_assign_pointer(per_cpu(sd_llc, cpu), sd);
per_cpu(sd_llc_id, cpu) = id;
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 42d9df6..96e2b18 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -2637,6 +2637,8 @@ static int select_idle_sibling(struct task_struct *p, int target)
int cpu = smp_processor_id();
int prev_cpu = task_cpu(p);
struct sched_domain *sd;
+ struct sched_group *sg;
+ int i;
/*
* If the task is going to be woken-up on this cpu and if it is
@@ -2653,17 +2655,29 @@ static int select_idle_sibling(struct task_struct *p, int target)
return prev_cpu;
/*
- * Otherwise, check assigned siblings to find an elegible idle cpu.
+ * Otherwise, iterate the domains and find an elegible idle cpu.
*/
sd = rcu_dereference(per_cpu(sd_llc, target));
-
for_each_lower_domain(sd) {
- if (!cpumask_test_cpu(sd->idle_buddy, tsk_cpus_allowed(p)))
- continue;
- if (idle_cpu(sd->idle_buddy))
- return sd->idle_buddy;
- }
+ sg = sd->groups;
+ do {
+ if (!cpumask_intersects(sched_group_cpus(sg),
+ tsk_cpus_allowed(p)))
+ goto next;
+ for_each_cpu(i, sched_group_cpus(sg)) {
+ if (!idle_cpu(i))
+ goto next;
+ }
+
+ target = cpumask_first_and(sched_group_cpus(sg),
+ tsk_cpus_allowed(p));
+ goto done;
+next:
+ sg = sg->next;
+ } while (sg != sd->groups);
+ }
+done:
return target;
}
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index 34e5eac..d3b91e7 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -303,10 +303,11 @@ void getnstimeofday(struct timespec *ts)
seq = read_seqbegin(&tk->lock);
ts->tv_sec = tk->xtime_sec;
- ts->tv_nsec = timekeeping_get_ns(tk);
+ nsecs = timekeeping_get_ns(tk);
} while (read_seqretry(&tk->lock, seq));
+ ts->tv_nsec = 0;
timespec_add_ns(ts, nsecs);
}
EXPORT_SYMBOL(getnstimeofday);
@@ -345,6 +346,7 @@ void ktime_get_ts(struct timespec *ts)
{
struct timekeeper *tk = &timekeeper;
struct timespec tomono;
+ s64 nsec;
unsigned int seq;
WARN_ON(timekeeping_suspended);
@@ -352,13 +354,14 @@ void ktime_get_ts(struct timespec *ts)
do {
seq = read_seqbegin(&tk->lock);
ts->tv_sec = tk->xtime_sec;
- ts->tv_nsec = timekeeping_get_ns(tk);
+ nsec = timekeeping_get_ns(tk);
tomono = tk->wall_to_monotonic;
} while (read_seqretry(&tk->lock, seq));
- set_normalized_timespec(ts, ts->tv_sec + tomono.tv_sec,
- ts->tv_nsec + tomono.tv_nsec);
+ ts->tv_sec += tomono.tv_sec;
+ ts->tv_nsec = 0;
+ timespec_add_ns(ts, nsec + tomono.tv_nsec);
}
EXPORT_SYMBOL_GPL(ktime_get_ts);
@@ -1244,6 +1247,7 @@ void get_monotonic_boottime(struct timespec *ts)
{
struct timekeeper *tk = &timekeeper;
struct timespec tomono, sleep;
+ s64 nsec;
unsigned int seq;
WARN_ON(timekeeping_suspended);
@@ -1251,14 +1255,15 @@ void get_monotonic_boottime(struct timespec *ts)
do {
seq = read_seqbegin(&tk->lock);
ts->tv_sec = tk->xtime_sec;
- ts->tv_nsec = timekeeping_get_ns(tk);
+ nsec = timekeeping_get_ns(tk);
tomono = tk->wall_to_monotonic;
sleep = tk->total_sleep_time;
} while (read_seqretry(&tk->lock, seq));
- set_normalized_timespec(ts, ts->tv_sec + tomono.tv_sec + sleep.tv_sec,
- ts->tv_nsec + tomono.tv_nsec + sleep.tv_nsec);
+ ts->tv_sec += tomono.tv_sec + sleep.tv_sec;
+ ts->tv_nsec = 0;
+ timespec_add_ns(ts, nsec + tomono.tv_nsec + sleep.tv_nsec);
}
EXPORT_SYMBOL_GPL(get_monotonic_boottime);
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 1e1373b..3c5a79e 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -1349,8 +1349,16 @@ static void busy_worker_rebind_fn(struct work_struct *work)
struct worker *worker = container_of(work, struct worker, rebind_work);
struct global_cwq *gcwq = worker->pool->gcwq;
- if (worker_maybe_bind_and_lock(worker))
- worker_clr_flags(worker, WORKER_REBIND);
+ worker_maybe_bind_and_lock(worker);
+
+ /*
+ * %WORKER_REBIND must be cleared even if the above binding failed;
+ * otherwise, we may confuse the next CPU_UP cycle or oops / get
+ * stuck by calling idle_worker_rebind() prematurely. If CPU went
+ * down again inbetween, %WORKER_UNBOUND would be set, so clearing
+ * %WORKER_REBIND is always safe.
+ */
+ worker_clr_flags(worker, WORKER_REBIND);
spin_unlock_irq(&gcwq->lock);
}
@@ -3568,18 +3576,17 @@ static int __devinit workqueue_cpu_down_callback(struct notifier_block *nfb,
#ifdef CONFIG_SMP
struct work_for_cpu {
- struct completion completion;
+ struct work_struct work;
long (*fn)(void *);
void *arg;
long ret;
};
-static int do_work_for_cpu(void *_wfc)
+static void work_for_cpu_fn(struct work_struct *work)
{
- struct work_for_cpu *wfc = _wfc;
+ struct work_for_cpu *wfc = container_of(work, struct work_for_cpu, work);
+
wfc->ret = wfc->fn(wfc->arg);
- complete(&wfc->completion);
- return 0;
}
/**
@@ -3594,19 +3601,11 @@ static int do_work_for_cpu(void *_wfc)
*/
long work_on_cpu(unsigned int cpu, long (*fn)(void *), void *arg)
{
- struct task_struct *sub_thread;
- struct work_for_cpu wfc = {
- .completion = COMPLETION_INITIALIZER_ONSTACK(wfc.completion),
- .fn = fn,
- .arg = arg,
- };
+ struct work_for_cpu wfc = { .fn = fn, .arg = arg };
- sub_thread = kthread_create(do_work_for_cpu, &wfc, "work_for_cpu");
- if (IS_ERR(sub_thread))
- return PTR_ERR(sub_thread);
- kthread_bind(sub_thread, cpu);
- wake_up_process(sub_thread);
- wait_for_completion(&wfc.completion);
+ INIT_WORK_ONSTACK(&wfc.work, work_for_cpu_fn);
+ schedule_work_on(cpu, &wfc.work);
+ flush_work(&wfc.work);
return wfc.ret;
}
EXPORT_SYMBOL_GPL(work_on_cpu);
diff --git a/lib/flex_proportions.c b/lib/flex_proportions.c
index c785554..ebf3bac 100644
--- a/lib/flex_proportions.c
+++ b/lib/flex_proportions.c
@@ -62,7 +62,7 @@ void fprop_global_destroy(struct fprop_global *p)
*/
bool fprop_new_period(struct fprop_global *p, int periods)
{
- u64 events;
+ s64 events;
unsigned long flags;
local_irq_save(flags);
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 57c4b93..141dbb6 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -1811,7 +1811,6 @@ static void __collapse_huge_page_copy(pte_t *pte, struct page *page,
src_page = pte_page(pteval);
copy_user_highpage(page, src_page, address, vma);
VM_BUG_ON(page_mapcount(src_page) != 1);
- VM_BUG_ON(page_count(src_page) != 2);
release_pte_page(src_page);
/*
* ptl mostly unnecessary, but preempt has to
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 3ad25f9..6a5b90d 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -126,9 +126,6 @@ static void register_page_bootmem_info_section(unsigned long start_pfn)
struct mem_section *ms;
struct page *page, *memmap;
- if (!pfn_valid(start_pfn))
- return;
-
section_nr = pfn_to_section_nr(start_pfn);
ms = __nr_to_section(section_nr);
@@ -187,9 +184,16 @@ void register_page_bootmem_info_node(struct pglist_data *pgdat)
end_pfn = pfn + pgdat->node_spanned_pages;
/* register_section info */
- for (; pfn < end_pfn; pfn += PAGES_PER_SECTION)
- register_page_bootmem_info_section(pfn);
-
+ for (; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
+ /*
+ * Some platforms can assign the same pfn to multiple nodes - on
+ * node0 as well as nodeN. To avoid registering a pfn against
+ * multiple nodes we check that this pfn does not already
+ * reside in some other node.
+ */
+ if (pfn_valid(pfn) && (pfn_to_nid(pfn) == node))
+ register_page_bootmem_info_section(pfn);
+ }
}
#endif /* !CONFIG_SPARSEMEM_VMEMMAP */
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index c66fb87..c13ea75 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -584,7 +584,7 @@ static inline void __free_one_page(struct page *page,
combined_idx = buddy_idx & page_idx;
higher_page = page + (combined_idx - page_idx);
buddy_idx = __find_buddy_index(combined_idx, order + 1);
- higher_buddy = page + (buddy_idx - combined_idx);
+ higher_buddy = higher_page + (buddy_idx - combined_idx);
if (page_is_buddy(higher_page, higher_buddy, order + 1)) {
list_add_tail(&page->lru,
&zone->free_area[order].free_list[migratetype]);
diff --git a/mm/slab.c b/mm/slab.c
index 811af03..c685475 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -983,7 +983,7 @@ static void *__ac_get_obj(struct kmem_cache *cachep, struct array_cache *ac,
}
/* The caller cannot use PFMEMALLOC objects, find another one */
- for (i = 1; i < ac->avail; i++) {
+ for (i = 0; i < ac->avail; i++) {
/* If a !PFMEMALLOC object is found, swap them */
if (!is_obj_pfmemalloc(ac->entry[i])) {
objp = ac->entry[i];
@@ -1000,7 +1000,7 @@ static void *__ac_get_obj(struct kmem_cache *cachep, struct array_cache *ac,
l3 = cachep->nodelists[numa_mem_id()];
if (!list_empty(&l3->slabs_free) && force_refill) {
struct slab *slabp = virt_to_slab(objp);
- ClearPageSlabPfmemalloc(virt_to_page(slabp->s_mem));
+ ClearPageSlabPfmemalloc(virt_to_head_page(slabp->s_mem));
clear_obj_pfmemalloc(&objp);
recheck_pfmemalloc_active(cachep, ac);
return objp;
@@ -1032,7 +1032,7 @@ static void *__ac_put_obj(struct kmem_cache *cachep, struct array_cache *ac,
{
if (unlikely(pfmemalloc_active)) {
/* Some pfmemalloc slabs exist, check if this is one */
- struct page *page = virt_to_page(objp);
+ struct page *page = virt_to_head_page(objp);
if (PageSlabPfmemalloc(page))
set_obj_pfmemalloc(&objp);
}
diff --git a/mm/slub.c b/mm/slub.c
index 8f78e25..2fdd96f 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -1524,12 +1524,13 @@ static inline void *acquire_slab(struct kmem_cache *s,
}
static int put_cpu_partial(struct kmem_cache *s, struct page *page, int drain);
+static inline bool pfmemalloc_match(struct page *page, gfp_t gfpflags);
/*
* Try to allocate a partial slab from a specific node.
*/
-static void *get_partial_node(struct kmem_cache *s,
- struct kmem_cache_node *n, struct kmem_cache_cpu *c)
+static void *get_partial_node(struct kmem_cache *s, struct kmem_cache_node *n,
+ struct kmem_cache_cpu *c, gfp_t flags)
{
struct page *page, *page2;
void *object = NULL;
@@ -1545,9 +1546,13 @@ static void *get_partial_node(struct kmem_cache *s,
spin_lock(&n->list_lock);
list_for_each_entry_safe(page, page2, &n->partial, lru) {
- void *t = acquire_slab(s, n, page, object == NULL);
+ void *t;
int available;
+ if (!pfmemalloc_match(page, flags))
+ continue;
+
+ t = acquire_slab(s, n, page, object == NULL);
if (!t)
break;
@@ -1614,7 +1619,7 @@ static void *get_any_partial(struct kmem_cache *s, gfp_t flags,
if (n && cpuset_zone_allowed_hardwall(zone, flags) &&
n->nr_partial > s->min_partial) {
- object = get_partial_node(s, n, c);
+ object = get_partial_node(s, n, c, flags);
if (object) {
/*
* Return the object even if
@@ -1643,7 +1648,7 @@ static void *get_partial(struct kmem_cache *s, gfp_t flags, int node,
void *object;
int searchnode = (node == NUMA_NO_NODE) ? numa_node_id() : node;
- object = get_partial_node(s, get_node(s, searchnode), c);
+ object = get_partial_node(s, get_node(s, searchnode), c, flags);
if (object || node != NUMA_NO_NODE)
return object;
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 8d01243..99b434b 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -3102,6 +3102,7 @@ int kswapd_run(int nid)
/* failure at boot is fatal */
BUG_ON(system_state == SYSTEM_BOOTING);
printk("Failed to start kswapd on node %d\n",nid);
+ pgdat->kswapd = NULL;
ret = -1;
}
return ret;
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
index df79300..b02b75d 100644
--- a/net/batman-adv/bat_iv_ogm.c
+++ b/net/batman-adv/bat_iv_ogm.c
@@ -652,6 +652,7 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
struct batadv_neigh_node *router = NULL;
struct batadv_orig_node *orig_node_tmp;
struct hlist_node *node;
+ int if_num;
uint8_t sum_orig, sum_neigh;
uint8_t *neigh_addr;
uint8_t tq_avg;
@@ -738,12 +739,14 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
if (router && (neigh_node->tq_avg == router->tq_avg)) {
orig_node_tmp = router->orig_node;
spin_lock_bh(&orig_node_tmp->ogm_cnt_lock);
- sum_orig = orig_node_tmp->bcast_own_sum[if_incoming->if_num];
+ if_num = router->if_incoming->if_num;
+ sum_orig = orig_node_tmp->bcast_own_sum[if_num];
spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock);
orig_node_tmp = neigh_node->orig_node;
spin_lock_bh(&orig_node_tmp->ogm_cnt_lock);
- sum_neigh = orig_node_tmp->bcast_own_sum[if_incoming->if_num];
+ if_num = neigh_node->if_incoming->if_num;
+ sum_neigh = orig_node_tmp->bcast_own_sum[if_num];
spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock);
if (sum_orig >= sum_neigh)
diff --git a/net/batman-adv/bitarray.h b/net/batman-adv/bitarray.h
index a081ce1..cebaae7 100644
--- a/net/batman-adv/bitarray.h
+++ b/net/batman-adv/bitarray.h
@@ -20,8 +20,8 @@
#ifndef _NET_BATMAN_ADV_BITARRAY_H_
#define _NET_BATMAN_ADV_BITARRAY_H_
-/* returns true if the corresponding bit in the given seq_bits indicates true
- * and curr_seqno is within range of last_seqno
+/* Returns 1 if the corresponding bit in the given seq_bits indicates true
+ * and curr_seqno is within range of last_seqno. Otherwise returns 0.
*/
static inline int batadv_test_bit(const unsigned long *seq_bits,
uint32_t last_seqno, uint32_t curr_seqno)
@@ -32,7 +32,7 @@ static inline int batadv_test_bit(const unsigned long *seq_bits,
if (diff < 0 || diff >= BATADV_TQ_LOCAL_WINDOW_SIZE)
return 0;
else
- return test_bit(diff, seq_bits);
+ return test_bit(diff, seq_bits) != 0;
}
/* turn corresponding bit on, so we can remember that we got the packet */
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
index 7b683e0..b9a28d2 100644
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@ -107,18 +107,21 @@ static int batadv_interface_set_mac_addr(struct net_device *dev, void *p)
{
struct batadv_priv *bat_priv = netdev_priv(dev);
struct sockaddr *addr = p;
+ uint8_t old_addr[ETH_ALEN];
if (!is_valid_ether_addr(addr->sa_data))
return -EADDRNOTAVAIL;
+ memcpy(old_addr, dev->dev_addr, ETH_ALEN);
+ memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
+
/* only modify transtable if it has been initialized before */
if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_ACTIVE) {
- batadv_tt_local_remove(bat_priv, dev->dev_addr,
+ batadv_tt_local_remove(bat_priv, old_addr,
"mac address changed", false);
batadv_tt_local_add(dev, addr->sa_data, BATADV_NULL_IFINDEX);
}
- memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
dev->addr_assign_type &= ~NET_ADDR_RANDOM;
return 0;
}
diff --git a/net/bluetooth/bnep/sock.c b/net/bluetooth/bnep/sock.c
index 5b6cc0b..e7154a5 100644
--- a/net/bluetooth/bnep/sock.c
+++ b/net/bluetooth/bnep/sock.c
@@ -64,7 +64,7 @@ static int bnep_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long
switch (cmd) {
case BNEPCONNADD:
if (!capable(CAP_NET_ADMIN))
- return -EACCES;
+ return -EPERM;
if (copy_from_user(&ca, argp, sizeof(ca)))
return -EFAULT;
@@ -90,7 +90,7 @@ static int bnep_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long
case BNEPCONNDEL:
if (!capable(CAP_NET_ADMIN))
- return -EACCES;
+ return -EPERM;
if (copy_from_user(&cd, argp, sizeof(cd)))
return -EFAULT;
diff --git a/net/bluetooth/cmtp/sock.c b/net/bluetooth/cmtp/sock.c
index d5cacef..aacb802 100644
--- a/net/bluetooth/cmtp/sock.c
+++ b/net/bluetooth/cmtp/sock.c
@@ -78,7 +78,7 @@ static int cmtp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long
switch (cmd) {
case CMTPCONNADD:
if (!capable(CAP_NET_ADMIN))
- return -EACCES;
+ return -EPERM;
if (copy_from_user(&ca, argp, sizeof(ca)))
return -EFAULT;
@@ -103,7 +103,7 @@ static int cmtp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long
case CMTPCONNDEL:
if (!capable(CAP_NET_ADMIN))
- return -EACCES;
+ return -EPERM;
if (copy_from_user(&cd, argp, sizeof(cd)))
return -EFAULT;
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index e407051..8a0ce70 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -737,6 +737,8 @@ static int hci_dev_do_close(struct hci_dev *hdev)
cancel_work_sync(&hdev->le_scan);
+ cancel_delayed_work(&hdev->power_off);
+
hci_req_cancel(hdev, ENODEV);
hci_req_lock(hdev);
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index bb64331..07f0739 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -490,7 +490,7 @@ static int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd,
switch (cmd) {
case HCISETRAW:
if (!capable(CAP_NET_ADMIN))
- return -EACCES;
+ return -EPERM;
if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
return -EPERM;
@@ -510,12 +510,12 @@ static int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd,
case HCIBLOCKADDR:
if (!capable(CAP_NET_ADMIN))
- return -EACCES;
+ return -EPERM;
return hci_sock_blacklist_add(hdev, (void __user *) arg);
case HCIUNBLOCKADDR:
if (!capable(CAP_NET_ADMIN))
- return -EACCES;
+ return -EPERM;
return hci_sock_blacklist_del(hdev, (void __user *) arg);
default:
@@ -546,22 +546,22 @@ static int hci_sock_ioctl(struct socket *sock, unsigned int cmd,
case HCIDEVUP:
if (!capable(CAP_NET_ADMIN))
- return -EACCES;
+ return -EPERM;
return hci_dev_open(arg);
case HCIDEVDOWN:
if (!capable(CAP_NET_ADMIN))
- return -EACCES;
+ return -EPERM;
return hci_dev_close(arg);
case HCIDEVRESET:
if (!capable(CAP_NET_ADMIN))
- return -EACCES;
+ return -EPERM;
return hci_dev_reset(arg);
case HCIDEVRESTAT:
if (!capable(CAP_NET_ADMIN))
- return -EACCES;
+ return -EPERM;
return hci_dev_reset_stat(arg);
case HCISETSCAN:
@@ -573,7 +573,7 @@ static int hci_sock_ioctl(struct socket *sock, unsigned int cmd,
case HCISETACLMTU:
case HCISETSCOMTU:
if (!capable(CAP_NET_ADMIN))
- return -EACCES;
+ return -EPERM;
return hci_dev_cmd(cmd, argp);
case HCIINQUIRY:
diff --git a/net/bluetooth/hidp/sock.c b/net/bluetooth/hidp/sock.c
index eca3889..82a829d 100644
--- a/net/bluetooth/hidp/sock.c
+++ b/net/bluetooth/hidp/sock.c
@@ -62,7 +62,7 @@ static int hidp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long
switch (cmd) {
case HIDPCONNADD:
if (!capable(CAP_NET_ADMIN))
- return -EACCES;
+ return -EPERM;
if (copy_from_user(&ca, argp, sizeof(ca)))
return -EFAULT;
@@ -97,7 +97,7 @@ static int hidp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long
case HIDPCONNDEL:
if (!capable(CAP_NET_ADMIN))
- return -EACCES;
+ return -EPERM;
if (copy_from_user(&cd, argp, sizeof(cd)))
return -EFAULT;
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 7a59e92..a91239dc 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -1026,7 +1026,7 @@ static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *c
if (!conn)
return;
- if (chan->mode == L2CAP_MODE_ERTM) {
+ if (chan->mode == L2CAP_MODE_ERTM && chan->state == BT_CONNECTED) {
__clear_retrans_timer(chan);
__clear_monitor_timer(chan);
__clear_ack_timer(chan);
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 8934343..aa2ea0a 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2892,6 +2892,22 @@ int mgmt_powered(struct hci_dev *hdev, u8 powered)
if (scan)
hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
+ if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
+ u8 ssp = 1;
+
+ hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
+ }
+
+ if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
+ struct hci_cp_write_le_host_supported cp;
+
+ cp.le = 1;
+ cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR);
+
+ hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED,
+ sizeof(cp), &cp);
+ }
+
update_class(hdev);
update_name(hdev, hdev->dev_name);
update_eir(hdev);
diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c
index 24c5eea..159aa8b 100644
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -1073,16 +1073,13 @@ static int write_partial_msg_pages(struct ceph_connection *con)
BUG_ON(kaddr == NULL);
base = kaddr + con->out_msg_pos.page_pos + bio_offset;
crc = crc32c(crc, base, len);
+ kunmap(page);
msg->footer.data_crc = cpu_to_le32(crc);
con->out_msg_pos.did_page_crc = true;
}
ret = ceph_tcp_sendpage(con->sock, page,
con->out_msg_pos.page_pos + bio_offset,
len, 1);
-
- if (do_datacrc)
- kunmap(page);
-
if (ret <= 0)
goto out;
diff --git a/net/core/dev.c b/net/core/dev.c
index 707b124..3e645f3 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2156,7 +2156,8 @@ static bool can_checksum_protocol(netdev_features_t features, __be16 protocol)
static netdev_features_t harmonize_features(struct sk_buff *skb,
__be16 protocol, netdev_features_t features)
{
- if (!can_checksum_protocol(features, protocol)) {
+ if (skb->ip_summed != CHECKSUM_NONE &&
+ !can_checksum_protocol(features, protocol)) {
features &= ~NETIF_F_ALL_CSUM;
features &= ~NETIF_F_SG;
} else if (illegal_highdma(skb->dev, skb)) {
@@ -3345,7 +3346,7 @@ ncls:
if (pt_prev) {
if (unlikely(skb_orphan_frags(skb, GFP_ATOMIC)))
- ret = -ENOMEM;
+ goto drop;
else
ret = pt_prev->func(skb, skb->dev, pt_prev, orig_dev);
} else {
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 607a70f..d607bae 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -3497,7 +3497,9 @@ bool skb_try_coalesce(struct sk_buff *to, struct sk_buff *from,
if (!skb_cloned(from))
skb_shinfo(from)->nr_frags = 0;
- /* if the skb is cloned this does nothing since we set nr_frags to 0 */
+ /* if the skb is not cloned this does nothing
+ * since we set nr_frags to 0.
+ */
for (i = 0; i < skb_shinfo(from)->nr_frags; i++)
skb_frag_ref(from, i);
diff --git a/net/core/sock.c b/net/core/sock.c
index f5a4260..7eac864 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -691,7 +691,8 @@ set_rcvbuf:
case SO_KEEPALIVE:
#ifdef CONFIG_INET
- if (sk->sk_protocol == IPPROTO_TCP)
+ if (sk->sk_protocol == IPPROTO_TCP &&
+ sk->sk_type == SOCK_STREAM)
tcp_set_keepalive(sk, valbool);
#endif
sock_valbool_flag(sk, SOCK_KEEPOPEN, valbool);
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 7b00556..2a6abc1 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -722,7 +722,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
break;
case SIOCSIFFLAGS:
- ret = -EACCES;
+ ret = -EPERM;
if (!capable(CAP_NET_ADMIN))
goto out;
break;
@@ -730,7 +730,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
case SIOCSIFBRDADDR: /* Set the broadcast address */
case SIOCSIFDSTADDR: /* Set the destination address */
case SIOCSIFNETMASK: /* Set the netmask for the interface */
- ret = -EACCES;
+ ret = -EPERM;
if (!capable(CAP_NET_ADMIN))
goto out;
ret = -EINVAL;
diff --git a/net/ipv4/inetpeer.c b/net/ipv4/inetpeer.c
index e1e0a4e..c7527f6 100644
--- a/net/ipv4/inetpeer.c
+++ b/net/ipv4/inetpeer.c
@@ -510,7 +510,10 @@ relookup:
secure_ipv6_id(daddr->addr.a6));
p->metrics[RTAX_LOCK-1] = INETPEER_METRICS_NEW;
p->rate_tokens = 0;
- p->rate_last = 0;
+ /* 60*HZ is arbitrary, but chosen enough high so that the first
+ * calculation of tokens is at its maximum.
+ */
+ p->rate_last = jiffies - 60*HZ;
INIT_LIST_HEAD(&p->gc_list);
/* Link the node. */
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index f242578..73d1e4d 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -131,18 +131,20 @@ found:
* 0 - deliver
* 1 - block
*/
-static __inline__ int icmp_filter(struct sock *sk, struct sk_buff *skb)
+static int icmp_filter(const struct sock *sk, const struct sk_buff *skb)
{
- int type;
+ struct icmphdr _hdr;
+ const struct icmphdr *hdr;
- if (!pskb_may_pull(skb, sizeof(struct icmphdr)))
+ hdr = skb_header_pointer(skb, skb_transport_offset(skb),
+ sizeof(_hdr), &_hdr);
+ if (!hdr)
return 1;
- type = icmp_hdr(skb)->type;
- if (type < 32) {
+ if (hdr->type < 32) {
__u32 data = raw_sk(sk)->filter.data;
- return ((1 << type) & data) != 0;
+ return ((1U << hdr->type) & data) != 0;
}
/* Do not block unknown ICMP types */
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 940f4f4..ff62206 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -202,11 +202,6 @@ EXPORT_SYMBOL(ip_tos2prio);
static DEFINE_PER_CPU(struct rt_cache_stat, rt_cache_stat);
#define RT_CACHE_STAT_INC(field) __this_cpu_inc(rt_cache_stat.field)
-static inline int rt_genid(struct net *net)
-{
- return atomic_read(&net->ipv4.rt_genid);
-}
-
#ifdef CONFIG_PROC_FS
static void *rt_cache_seq_start(struct seq_file *seq, loff_t *pos)
{
@@ -449,7 +444,7 @@ static inline bool rt_is_expired(const struct rtable *rth)
void rt_cache_flush(struct net *net)
{
- atomic_inc(&net->ipv4.rt_genid);
+ rt_genid_bump(net);
}
static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst,
@@ -2506,7 +2501,7 @@ static __net_initdata struct pernet_operations sysctl_route_ops = {
static __net_init int rt_genid_init(struct net *net)
{
- atomic_set(&net->ipv4.rt_genid, 0);
+ atomic_set(&net->rt_genid, 0);
get_random_bytes(&net->ipv4.dev_addr_genid,
sizeof(net->ipv4.dev_addr_genid));
return 0;
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 72ea475..f32c02e 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -1738,8 +1738,14 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
}
#ifdef CONFIG_NET_DMA
- if (tp->ucopy.dma_chan)
- dma_async_memcpy_issue_pending(tp->ucopy.dma_chan);
+ if (tp->ucopy.dma_chan) {
+ if (tp->rcv_wnd == 0 &&
+ !skb_queue_empty(&sk->sk_async_wait_queue)) {
+ tcp_service_net_dma(sk, true);
+ tcp_cleanup_rbuf(sk, copied);
+ } else
+ dma_async_memcpy_issue_pending(tp->ucopy.dma_chan);
+ }
#endif
if (copied >= target) {
/* Do not sleep, just process backlog. */
@@ -2320,10 +2326,17 @@ static int tcp_repair_options_est(struct tcp_sock *tp,
tp->rx_opt.mss_clamp = opt.opt_val;
break;
case TCPOPT_WINDOW:
- if (opt.opt_val > 14)
- return -EFBIG;
+ {
+ u16 snd_wscale = opt.opt_val & 0xFFFF;
+ u16 rcv_wscale = opt.opt_val >> 16;
+
+ if (snd_wscale > 14 || rcv_wscale > 14)
+ return -EFBIG;
- tp->rx_opt.snd_wscale = opt.opt_val;
+ tp->rx_opt.snd_wscale = snd_wscale;
+ tp->rx_opt.rcv_wscale = rcv_wscale;
+ tp->rx_opt.wscale_ok = 1;
+ }
break;
case TCPOPT_SACK_PERM:
if (opt.opt_val != 0)
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index e037697..432c366 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -4634,7 +4634,7 @@ queue_and_out:
if (eaten > 0)
kfree_skb_partial(skb, fragstolen);
- else if (!sock_flag(sk, SOCK_DEAD))
+ if (!sock_flag(sk, SOCK_DEAD))
sk->sk_data_ready(sk, 0);
return;
}
@@ -5529,8 +5529,7 @@ no_ack:
#endif
if (eaten)
kfree_skb_partial(skb, fragstolen);
- else
- sk->sk_data_ready(sk, 0);
+ sk->sk_data_ready(sk, 0);
return 0;
}
}
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c
index 0251a60..c4f9341 100644
--- a/net/ipv6/inet6_connection_sock.c
+++ b/net/ipv6/inet6_connection_sock.c
@@ -175,33 +175,12 @@ void __inet6_csk_dst_store(struct sock *sk, struct dst_entry *dst,
const struct in6_addr *saddr)
{
__ip6_dst_store(sk, dst, daddr, saddr);
-
-#ifdef CONFIG_XFRM
- {
- struct rt6_info *rt = (struct rt6_info *)dst;
- rt->rt6i_flow_cache_genid = atomic_read(&flow_cache_genid);
- }
-#endif
}
static inline
struct dst_entry *__inet6_csk_dst_check(struct sock *sk, u32 cookie)
{
- struct dst_entry *dst;
-
- dst = __sk_dst_check(sk, cookie);
-
-#ifdef CONFIG_XFRM
- if (dst) {
- struct rt6_info *rt = (struct rt6_info *)dst;
- if (rt->rt6i_flow_cache_genid != atomic_read(&flow_cache_genid)) {
- __sk_dst_reset(sk);
- dst = NULL;
- }
- }
-#endif
-
- return dst;
+ return __sk_dst_check(sk, cookie);
}
static struct dst_entry *inet6_csk_route_socket(struct sock *sk,
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 13690d6..24995a9 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -514,7 +514,7 @@ static struct fib6_node * fib6_add_1(struct fib6_node *root, void *addr,
ln = node_alloc();
if (!ln)
- return NULL;
+ return ERR_PTR(-ENOMEM);
ln->fn_bit = plen;
ln->parent = pn;
@@ -561,7 +561,7 @@ insert_above:
node_free(in);
if (ln)
node_free(ln);
- return NULL;
+ return ERR_PTR(-ENOMEM);
}
/*
@@ -611,7 +611,7 @@ insert_above:
ln = node_alloc();
if (!ln)
- return NULL;
+ return ERR_PTR(-ENOMEM);
ln->fn_bit = plen;
@@ -777,11 +777,8 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info)
if (IS_ERR(fn)) {
err = PTR_ERR(fn);
- fn = NULL;
- }
-
- if (!fn)
goto out;
+ }
pn = fn;
@@ -819,12 +816,13 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info)
offsetof(struct rt6_info, rt6i_src),
allow_create, replace_required);
- if (!sn) {
+ if (IS_ERR(sn)) {
/* If it is failed, discard just allocated
root, and then (in st_failure) stale node
in main tree.
*/
node_free(sfn);
+ err = PTR_ERR(sn);
goto st_failure;
}
@@ -839,10 +837,8 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info)
if (IS_ERR(sn)) {
err = PTR_ERR(sn);
- sn = NULL;
- }
- if (!sn)
goto st_failure;
+ }
}
if (!fn->leaf) {
diff --git a/net/ipv6/mip6.c b/net/ipv6/mip6.c
index 5b087c3..0f9bdc5 100644
--- a/net/ipv6/mip6.c
+++ b/net/ipv6/mip6.c
@@ -86,28 +86,30 @@ static int mip6_mh_len(int type)
static int mip6_mh_filter(struct sock *sk, struct sk_buff *skb)
{
- struct ip6_mh *mh;
+ struct ip6_mh _hdr;
+ const struct ip6_mh *mh;
- if (!pskb_may_pull(skb, (skb_transport_offset(skb)) + 8) ||
- !pskb_may_pull(skb, (skb_transport_offset(skb) +
- ((skb_transport_header(skb)[1] + 1) << 3))))
+ mh = skb_header_pointer(skb, skb_transport_offset(skb),
+ sizeof(_hdr), &_hdr);
+ if (!mh)
return -1;
- mh = (struct ip6_mh *)skb_transport_header(skb);
+ if (((mh->ip6mh_hdrlen + 1) << 3) > skb->len)
+ return -1;
if (mh->ip6mh_hdrlen < mip6_mh_len(mh->ip6mh_type)) {
LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH message too short: %d vs >=%d\n",
mh->ip6mh_hdrlen, mip6_mh_len(mh->ip6mh_type));
- mip6_param_prob(skb, 0, ((&mh->ip6mh_hdrlen) -
- skb_network_header(skb)));
+ mip6_param_prob(skb, 0, offsetof(struct ip6_mh, ip6mh_hdrlen) +
+ skb_network_header_len(skb));
return -1;
}
if (mh->ip6mh_proto != IPPROTO_NONE) {
LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH invalid payload proto = %d\n",
mh->ip6mh_proto);
- mip6_param_prob(skb, 0, ((&mh->ip6mh_proto) -
- skb_network_header(skb)));
+ mip6_param_prob(skb, 0, offsetof(struct ip6_mh, ip6mh_proto) +
+ skb_network_header_len(skb));
return -1;
}
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 7af88ef..d8e95c7 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -107,21 +107,20 @@ found:
* 0 - deliver
* 1 - block
*/
-static __inline__ int icmpv6_filter(struct sock *sk, struct sk_buff *skb)
+static int icmpv6_filter(const struct sock *sk, const struct sk_buff *skb)
{
- struct icmp6hdr *icmph;
- struct raw6_sock *rp = raw6_sk(sk);
-
- if (pskb_may_pull(skb, sizeof(struct icmp6hdr))) {
- __u32 *data = &rp->filter.data[0];
- int bit_nr;
+ struct icmp6hdr *_hdr;
+ const struct icmp6hdr *hdr;
- icmph = (struct icmp6hdr *) skb->data;
- bit_nr = icmph->icmp6_type;
+ hdr = skb_header_pointer(skb, skb_transport_offset(skb),
+ sizeof(_hdr), &_hdr);
+ if (hdr) {
+ const __u32 *data = &raw6_sk(sk)->filter.data[0];
+ unsigned int type = hdr->icmp6_type;
- return (data[bit_nr >> 5] & (1 << (bit_nr & 31))) != 0;
+ return (data[type >> 5] & (1U << (type & 31))) != 0;
}
- return 0;
+ return 1;
}
#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 0607ee3..d1ddbc6 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -226,7 +226,7 @@ static const struct rt6_info ip6_null_entry_template = {
.dst = {
.__refcnt = ATOMIC_INIT(1),
.__use = 1,
- .obsolete = -1,
+ .obsolete = DST_OBSOLETE_FORCE_CHK,
.error = -ENETUNREACH,
.input = ip6_pkt_discard,
.output = ip6_pkt_discard_out,
@@ -246,7 +246,7 @@ static const struct rt6_info ip6_prohibit_entry_template = {
.dst = {
.__refcnt = ATOMIC_INIT(1),
.__use = 1,
- .obsolete = -1,
+ .obsolete = DST_OBSOLETE_FORCE_CHK,
.error = -EACCES,
.input = ip6_pkt_prohibit,
.output = ip6_pkt_prohibit_out,
@@ -261,7 +261,7 @@ static const struct rt6_info ip6_blk_hole_entry_template = {
.dst = {
.__refcnt = ATOMIC_INIT(1),
.__use = 1,
- .obsolete = -1,
+ .obsolete = DST_OBSOLETE_FORCE_CHK,
.error = -EINVAL,
.input = dst_discard,
.output = dst_discard,
@@ -281,13 +281,14 @@ static inline struct rt6_info *ip6_dst_alloc(struct net *net,
struct fib6_table *table)
{
struct rt6_info *rt = dst_alloc(&net->ipv6.ip6_dst_ops, dev,
- 0, DST_OBSOLETE_NONE, flags);
+ 0, DST_OBSOLETE_FORCE_CHK, flags);
if (rt) {
struct dst_entry *dst = &rt->dst;
memset(dst + 1, 0, sizeof(*rt) - sizeof(*dst));
rt6_init_peer(rt, table ? &table->tb6_peers : net->ipv6.peers);
+ rt->rt6i_genid = rt_genid(net);
}
return rt;
}
@@ -1022,6 +1023,13 @@ static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie)
rt = (struct rt6_info *) dst;
+ /* All IPV6 dsts are created with ->obsolete set to the value
+ * DST_OBSOLETE_FORCE_CHK which forces validation calls down
+ * into this function always.
+ */
+ if (rt->rt6i_genid != rt_genid(dev_net(rt->dst.dev)))
+ return NULL;
+
if (rt->rt6i_node && (rt->rt6i_node->fn_sernum == cookie)) {
if (rt->rt6i_peer_genid != rt6_peer_genid()) {
if (!rt6_has_peer(rt))
@@ -1388,8 +1396,6 @@ int ip6_route_add(struct fib6_config *cfg)
goto out;
}
- rt->dst.obsolete = -1;
-
if (cfg->fc_flags & RTF_EXPIRES)
rt6_set_expires(rt, jiffies +
clock_t_to_jiffies(cfg->fc_expires));
@@ -2084,7 +2090,6 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
rt->dst.input = ip6_input;
rt->dst.output = ip6_output;
rt->rt6i_idev = idev;
- rt->dst.obsolete = -1;
rt->rt6i_flags = RTF_UP | RTF_NONEXTHOP;
if (anycast)
diff --git a/net/l2tp/l2tp_netlink.c b/net/l2tp/l2tp_netlink.c
index 6ec3f67..6c4cc12 100644
--- a/net/l2tp/l2tp_netlink.c
+++ b/net/l2tp/l2tp_netlink.c
@@ -80,8 +80,8 @@ static int l2tp_nl_cmd_noop(struct sk_buff *skb, struct genl_info *info)
hdr = genlmsg_put(msg, info->snd_portid, info->snd_seq,
&l2tp_nl_family, 0, L2TP_CMD_NOOP);
- if (IS_ERR(hdr)) {
- ret = PTR_ERR(hdr);
+ if (!hdr) {
+ ret = -EMSGSIZE;
goto err_out;
}
@@ -250,8 +250,8 @@ static int l2tp_nl_tunnel_send(struct sk_buff *skb, u32 portid, u32 seq, int fla
hdr = genlmsg_put(skb, portid, seq, &l2tp_nl_family, flags,
L2TP_CMD_TUNNEL_GET);
- if (IS_ERR(hdr))
- return PTR_ERR(hdr);
+ if (!hdr)
+ return -EMSGSIZE;
if (nla_put_u8(skb, L2TP_ATTR_PROTO_VERSION, tunnel->version) ||
nla_put_u32(skb, L2TP_ATTR_CONN_ID, tunnel->tunnel_id) ||
@@ -617,8 +617,8 @@ static int l2tp_nl_session_send(struct sk_buff *skb, u32 portid, u32 seq, int fl
sk = tunnel->sock;
hdr = genlmsg_put(skb, portid, seq, &l2tp_nl_family, flags, L2TP_CMD_SESSION_GET);
- if (IS_ERR(hdr))
- return PTR_ERR(hdr);
+ if (!hdr)
+ return -EMSGSIZE;
if (nla_put_u32(skb, L2TP_ATTR_CONN_ID, tunnel->tunnel_id) ||
nla_put_u32(skb, L2TP_ATTR_SESSION_ID, session->session_id) ||
diff --git a/net/netfilter/xt_limit.c b/net/netfilter/xt_limit.c
index 5c22ce8..a4c1e45 100644
--- a/net/netfilter/xt_limit.c
+++ b/net/netfilter/xt_limit.c
@@ -117,11 +117,11 @@ static int limit_mt_check(const struct xt_mtchk_param *par)
/* For SMP, we only want to use one set of state. */
r->master = priv;
+ /* User avg in seconds * XT_LIMIT_SCALE: convert to jiffies *
+ 128. */
+ priv->prev = jiffies;
+ priv->credit = user2credits(r->avg * r->burst); /* Credits full. */
if (r->cost == 0) {
- /* User avg in seconds * XT_LIMIT_SCALE: convert to jiffies *
- 128. */
- priv->prev = jiffies;
- priv->credit = user2credits(r->avg * r->burst); /* Credits full. */
r->credit_cap = priv->credit; /* Credits full. */
r->cost = user2credits(r->avg);
}
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
index 1b9024e..7261eb8 100644
--- a/net/netrom/af_netrom.c
+++ b/net/netrom/af_netrom.c
@@ -601,7 +601,7 @@ static int nr_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
if (!capable(CAP_NET_BIND_SERVICE)) {
dev_put(dev);
release_sock(sk);
- return -EACCES;
+ return -EPERM;
}
nr->user_addr = addr->fsa_digipeater[0];
nr->source_addr = addr->fsa_ax25.sax25_call;
diff --git a/net/sched/sch_qfq.c b/net/sched/sch_qfq.c
index 2556620..f0dd83c 100644
--- a/net/sched/sch_qfq.c
+++ b/net/sched/sch_qfq.c
@@ -865,7 +865,10 @@ static void qfq_update_start(struct qfq_sched *q, struct qfq_class *cl)
if (mask) {
struct qfq_group *next = qfq_ffs(q, mask);
if (qfq_gt(roundedF, next->F)) {
- cl->S = next->F;
+ if (qfq_gt(limit, next->F))
+ cl->S = next->F;
+ else /* preserve timestamp correctness */
+ cl->S = limit;
return;
}
}
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 8448239..3b8cbbc 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -350,6 +350,9 @@ static void reg_regdb_search(struct work_struct *work)
struct reg_regdb_search_request *request;
const struct ieee80211_regdomain *curdom, *regdom;
int i, r;
+ bool set_reg = false;
+
+ mutex_lock(&cfg80211_mutex);
mutex_lock(&reg_regdb_search_mutex);
while (!list_empty(&reg_regdb_search_list)) {
@@ -365,9 +368,7 @@ static void reg_regdb_search(struct work_struct *work)
r = reg_copy_regd(&regdom, curdom);
if (r)
break;
- mutex_lock(&cfg80211_mutex);
- set_regdom(regdom);
- mutex_unlock(&cfg80211_mutex);
+ set_reg = true;
break;
}
}
@@ -375,6 +376,11 @@ static void reg_regdb_search(struct work_struct *work)
kfree(request);
}
mutex_unlock(&reg_regdb_search_mutex);
+
+ if (set_reg)
+ set_regdom(regdom);
+
+ mutex_unlock(&cfg80211_mutex);
}
static DECLARE_WORK(reg_regdb_work, reg_regdb_search);
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 741a32a..f4e0a6a 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -602,6 +602,7 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
xfrm_pol_hold(policy);
net->xfrm.policy_count[dir]++;
atomic_inc(&flow_cache_genid);
+ rt_genid_bump(net);
if (delpol)
__xfrm_policy_unlink(delpol, dir);
policy->index = delpol ? delpol->index : xfrm_gen_index(net, dir);
@@ -1780,7 +1781,7 @@ static struct dst_entry *make_blackhole(struct net *net, u16 family,
if (!afinfo) {
dst_release(dst_orig);
- ret = ERR_PTR(-EINVAL);
+ return ERR_PTR(-EINVAL);
} else {
ret = afinfo->blackhole_route(net, dst_orig);
}
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 5d6eb4b..94a2a1f 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -123,9 +123,21 @@ static inline int verify_replay(struct xfrm_usersa_info *p,
struct nlattr **attrs)
{
struct nlattr *rt = attrs[XFRMA_REPLAY_ESN_VAL];
+ struct xfrm_replay_state_esn *rs;
- if ((p->flags & XFRM_STATE_ESN) && !rt)
- return -EINVAL;
+ if (p->flags & XFRM_STATE_ESN) {
+ if (!rt)
+ return -EINVAL;
+
+ rs = nla_data(rt);
+
+ if (rs->bmp_len > XFRMA_REPLAY_ESN_MAX / sizeof(rs->bmp[0]) / 8)
+ return -EINVAL;
+
+ if (nla_len(rt) < xfrm_replay_state_esn_len(rs) &&
+ nla_len(rt) != sizeof(*rs))
+ return -EINVAL;
+ }
if (!rt)
return 0;
@@ -370,14 +382,15 @@ static inline int xfrm_replay_verify_len(struct xfrm_replay_state_esn *replay_es
struct nlattr *rp)
{
struct xfrm_replay_state_esn *up;
+ int ulen;
if (!replay_esn || !rp)
return 0;
up = nla_data(rp);
+ ulen = xfrm_replay_state_esn_len(up);
- if (xfrm_replay_state_esn_len(replay_esn) !=
- xfrm_replay_state_esn_len(up))
+ if (nla_len(rp) < ulen || xfrm_replay_state_esn_len(replay_esn) != ulen)
return -EINVAL;
return 0;
@@ -388,22 +401,28 @@ static int xfrm_alloc_replay_state_esn(struct xfrm_replay_state_esn **replay_esn
struct nlattr *rta)
{
struct xfrm_replay_state_esn *p, *pp, *up;
+ int klen, ulen;
if (!rta)
return 0;
up = nla_data(rta);
+ klen = xfrm_replay_state_esn_len(up);
+ ulen = nla_len(rta) >= klen ? klen : sizeof(*up);
- p = kmemdup(up, xfrm_replay_state_esn_len(up), GFP_KERNEL);
+ p = kzalloc(klen, GFP_KERNEL);
if (!p)
return -ENOMEM;
- pp = kmemdup(up, xfrm_replay_state_esn_len(up), GFP_KERNEL);
+ pp = kzalloc(klen, GFP_KERNEL);
if (!pp) {
kfree(p);
return -ENOMEM;
}
+ memcpy(p, up, ulen);
+ memcpy(pp, up, ulen);
+
*replay_esn = p;
*preplay_esn = pp;
@@ -442,10 +461,11 @@ static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info *
* somehow made shareable and move it to xfrm_state.c - JHS
*
*/
-static void xfrm_update_ae_params(struct xfrm_state *x, struct nlattr **attrs)
+static void xfrm_update_ae_params(struct xfrm_state *x, struct nlattr **attrs,
+ int update_esn)
{
struct nlattr *rp = attrs[XFRMA_REPLAY_VAL];
- struct nlattr *re = attrs[XFRMA_REPLAY_ESN_VAL];
+ struct nlattr *re = update_esn ? attrs[XFRMA_REPLAY_ESN_VAL] : NULL;
struct nlattr *lt = attrs[XFRMA_LTIME_VAL];
struct nlattr *et = attrs[XFRMA_ETIMER_THRESH];
struct nlattr *rt = attrs[XFRMA_REPLAY_THRESH];
@@ -555,7 +575,7 @@ static struct xfrm_state *xfrm_state_construct(struct net *net,
goto error;
/* override default values from above */
- xfrm_update_ae_params(x, attrs);
+ xfrm_update_ae_params(x, attrs, 0);
return x;
@@ -689,6 +709,7 @@ out:
static void copy_to_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p)
{
+ memset(p, 0, sizeof(*p));
memcpy(&p->id, &x->id, sizeof(p->id));
memcpy(&p->sel, &x->sel, sizeof(p->sel));
memcpy(&p->lft, &x->lft, sizeof(p->lft));
@@ -742,7 +763,7 @@ static int copy_to_user_auth(struct xfrm_algo_auth *auth, struct sk_buff *skb)
return -EMSGSIZE;
algo = nla_data(nla);
- strcpy(algo->alg_name, auth->alg_name);
+ strncpy(algo->alg_name, auth->alg_name, sizeof(algo->alg_name));
memcpy(algo->alg_key, auth->alg_key, (auth->alg_key_len + 7) / 8);
algo->alg_key_len = auth->alg_key_len;
@@ -878,6 +899,7 @@ static struct sk_buff *xfrm_state_netlink(struct sk_buff *in_skb,
{
struct xfrm_dump_info info;
struct sk_buff *skb;
+ int err;
skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
if (!skb)
@@ -888,9 +910,10 @@ static struct sk_buff *xfrm_state_netlink(struct sk_buff *in_skb,
info.nlmsg_seq = seq;
info.nlmsg_flags = 0;
- if (dump_one_state(x, 0, &info)) {
+ err = dump_one_state(x, 0, &info);
+ if (err) {
kfree_skb(skb);
- return NULL;
+ return ERR_PTR(err);
}
return skb;
@@ -1317,6 +1340,7 @@ static void copy_from_user_policy(struct xfrm_policy *xp, struct xfrm_userpolicy
static void copy_to_user_policy(struct xfrm_policy *xp, struct xfrm_userpolicy_info *p, int dir)
{
+ memset(p, 0, sizeof(*p));
memcpy(&p->sel, &xp->selector, sizeof(p->sel));
memcpy(&p->lft, &xp->lft, sizeof(p->lft));
memcpy(&p->curlft, &xp->curlft, sizeof(p->curlft));
@@ -1421,6 +1445,7 @@ static int copy_to_user_tmpl(struct xfrm_policy *xp, struct sk_buff *skb)
struct xfrm_user_tmpl *up = &vec[i];
struct xfrm_tmpl *kp = &xp->xfrm_vec[i];
+ memset(up, 0, sizeof(*up));
memcpy(&up->id, &kp->id, sizeof(up->id));
up->family = kp->encap_family;
memcpy(&up->saddr, &kp->saddr, sizeof(up->saddr));
@@ -1546,6 +1571,7 @@ static struct sk_buff *xfrm_policy_netlink(struct sk_buff *in_skb,
{
struct xfrm_dump_info info;
struct sk_buff *skb;
+ int err;
skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
if (!skb)
@@ -1556,9 +1582,10 @@ static struct sk_buff *xfrm_policy_netlink(struct sk_buff *in_skb,
info.nlmsg_seq = seq;
info.nlmsg_flags = 0;
- if (dump_one_policy(xp, dir, 0, &info) < 0) {
+ err = dump_one_policy(xp, dir, 0, &info);
+ if (err) {
kfree_skb(skb);
- return NULL;
+ return ERR_PTR(err);
}
return skb;
@@ -1822,7 +1849,7 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
goto out;
spin_lock_bh(&x->lock);
- xfrm_update_ae_params(x, attrs);
+ xfrm_update_ae_params(x, attrs, 1);
spin_unlock_bh(&x->lock);
c.event = nlh->nlmsg_type;
diff --git a/scripts/Makefile.fwinst b/scripts/Makefile.fwinst
index c3f69ae2..4d908d1 100644
--- a/scripts/Makefile.fwinst
+++ b/scripts/Makefile.fwinst
@@ -27,7 +27,7 @@ endif
installed-mod-fw := $(addprefix $(INSTALL_FW_PATH)/,$(mod-fw))
installed-fw := $(addprefix $(INSTALL_FW_PATH)/,$(fw-shipped-all))
-installed-fw-dirs := $(sort $(dir $(installed-fw))) $(INSTALL_FW_PATH)/.
+installed-fw-dirs := $(sort $(dir $(installed-fw))) $(INSTALL_FW_PATH)/./
# Workaround for make < 3.81, where .SECONDEXPANSION doesn't work.
PHONY += $(INSTALL_FW_PATH)/$$(%) install-all-dirs
@@ -42,7 +42,7 @@ quiet_cmd_install = INSTALL $(subst $(srctree)/,,$@)
$(installed-fw-dirs):
$(call cmd,mkdir)
-$(installed-fw): $(INSTALL_FW_PATH)/%: $(obj)/% | $$(dir $(INSTALL_FW_PATH)/%)
+$(installed-fw): $(INSTALL_FW_PATH)/%: $(obj)/% | $(INSTALL_FW_PATH)/$$(dir %)
$(call cmd,install)
PHONY += __fw_install __fw_modinst FORCE
diff --git a/scripts/checksyscalls.sh b/scripts/checksyscalls.sh
index d24810f..fd8fa9a 100755
--- a/scripts/checksyscalls.sh
+++ b/scripts/checksyscalls.sh
@@ -200,7 +200,7 @@ EOF
syscall_list() {
grep '^[0-9]' "$1" | sort -n | (
while read nr abi name entry ; do
- echo <<EOF
+ cat <<EOF
#if !defined(__NR_${name}) && !defined(__IGNORE_${name})
#warning syscall ${name} not implemented
#endif
diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h
index c220f31..65f67cb 100644
--- a/security/selinux/include/xfrm.h
+++ b/security/selinux/include/xfrm.h
@@ -51,6 +51,7 @@ int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall);
static inline void selinux_xfrm_notify_policyload(void)
{
atomic_inc(&flow_cache_genid);
+ rt_genid_bump(&init_net);
}
#else
static inline int selinux_xfrm_enabled(void)
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 228cdf9..c4763c5 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -2701,6 +2701,7 @@ static struct snd_pci_quirk position_fix_list[] __devinitdata = {
SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS M2V", POS_FIX_LPIB),
+ SND_PCI_QUIRK(0x1043, 0x1ac3, "ASUS X53S", POS_FIX_POSBUF),
SND_PCI_QUIRK(0x1043, 0x1b43, "ASUS K53E", POS_FIX_POSBUF),
SND_PCI_QUIRK(0x104d, 0x9069, "Sony VPCS11V9E", POS_FIX_LPIB),
SND_PCI_QUIRK(0x10de, 0xcb89, "Macbook Pro 7,1", POS_FIX_LPIB),
diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c
index 5c9caca..1cf7a32 100644
--- a/sound/soc/codecs/arizona.c
+++ b/sound/soc/codecs/arizona.c
@@ -426,7 +426,7 @@ static const int arizona_44k1_bclk_rates[] = {
940800,
1411200,
1881600,
- 2882400,
+ 2822400,
3763200,
5644800,
7526400,
diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c
index 8f726c0..115a403 100644
--- a/sound/soc/codecs/mc13783.c
+++ b/sound/soc/codecs/mc13783.c
@@ -659,7 +659,7 @@ static struct snd_soc_dai_driver mc13783_dai_async[] = {
.id = MC13783_ID_STEREO_DAC,
.playback = {
.stream_name = "Playback",
- .channels_min = 1,
+ .channels_min = 2,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_96000,
.formats = MC13783_FORMATS,
@@ -670,7 +670,7 @@ static struct snd_soc_dai_driver mc13783_dai_async[] = {
.id = MC13783_ID_STEREO_CODEC,
.capture = {
.stream_name = "Capture",
- .channels_min = 1,
+ .channels_min = 2,
.channels_max = 2,
.rates = MC13783_RATES_RECORD,
.formats = MC13783_FORMATS,
@@ -692,14 +692,14 @@ static struct snd_soc_dai_driver mc13783_dai_sync[] = {
.id = MC13783_ID_SYNC,
.playback = {
.stream_name = "Playback",
- .channels_min = 1,
+ .channels_min = 2,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_96000,
.formats = MC13783_FORMATS,
},
.capture = {
.stream_name = "Capture",
- .channels_min = 1,
+ .channels_min = 2,
.channels_max = 2,
.rates = MC13783_RATES_RECORD,
.formats = MC13783_FORMATS,
diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c
index 3fd5b29..a3acb7a 100644
--- a/sound/soc/codecs/wm2000.c
+++ b/sound/soc/codecs/wm2000.c
@@ -702,7 +702,7 @@ static bool wm2000_readable_reg(struct device *dev, unsigned int reg)
}
static const struct regmap_config wm2000_regmap = {
- .reg_bits = 8,
+ .reg_bits = 16,
.val_bits = 8,
.max_register = WM2000_REG_IF_CTL,
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c
index 0013afe..dc4262e 100644
--- a/sound/soc/codecs/wm8904.c
+++ b/sound/soc/codecs/wm8904.c
@@ -100,7 +100,7 @@ static const struct reg_default wm8904_reg_defaults[] = {
{ 14, 0x0000 }, /* R14 - Power Management 2 */
{ 15, 0x0000 }, /* R15 - Power Management 3 */
{ 18, 0x0000 }, /* R18 - Power Management 6 */
- { 19, 0x945E }, /* R20 - Clock Rates 0 */
+ { 20, 0x945E }, /* R20 - Clock Rates 0 */
{ 21, 0x0C05 }, /* R21 - Clock Rates 1 */
{ 22, 0x0006 }, /* R22 - Clock Rates 2 */
{ 24, 0x0050 }, /* R24 - Audio Interface 0 */
diff --git a/sound/soc/fsl/imx-sgtl5000.c b/sound/soc/fsl/imx-sgtl5000.c
index fb21b17..199408e 100644
--- a/sound/soc/fsl/imx-sgtl5000.c
+++ b/sound/soc/fsl/imx-sgtl5000.c
@@ -94,7 +94,7 @@ static int __devinit imx_sgtl5000_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "audmux internal port setup failed\n");
return ret;
}
- imx_audmux_v2_configure_port(ext_port,
+ ret = imx_audmux_v2_configure_port(ext_port,
IMX_AUDMUX_V2_PTCR_SYN,
IMX_AUDMUX_V2_PDCR_RXDSEL(int_port));
if (ret) {
diff --git a/sound/soc/omap/am3517evm.c b/sound/soc/omap/am3517evm.c
index 009533a..df65f98 100644
--- a/sound/soc/omap/am3517evm.c
+++ b/sound/soc/omap/am3517evm.c
@@ -59,7 +59,7 @@ static int am3517evm_hw_params(struct snd_pcm_substream *substream,
return ret;
}
- snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_FSR_SRC_FSX, 0,
+ ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_FSR_SRC_FSX, 0,
SND_SOC_CLOCK_IN);
if (ret < 0) {
printk(KERN_ERR "can't set CPU system clock OMAP_MCBSP_FSR_SRC_FSX\n");
diff --git a/sound/soc/samsung/dma.c b/sound/soc/samsung/dma.c
index f3ebc38..b70964e 100644
--- a/sound/soc/samsung/dma.c
+++ b/sound/soc/samsung/dma.c
@@ -34,9 +34,7 @@ static const struct snd_pcm_hardware dma_hardware = {
.info = SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_MMAP |
- SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_PAUSE |
- SNDRV_PCM_INFO_RESUME,
+ SNDRV_PCM_INFO_MMAP_VALID,
.formats = SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_U16_LE |
SNDRV_PCM_FMTBIT_U8 |
@@ -248,15 +246,11 @@ static int dma_trigger(struct snd_pcm_substream *substream, int cmd)
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
- case SNDRV_PCM_TRIGGER_RESUME:
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
prtd->state |= ST_RUNNING;
prtd->params->ops->trigger(prtd->params->ch);
break;
case SNDRV_PCM_TRIGGER_STOP:
- case SNDRV_PCM_TRIGGER_SUSPEND:
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
prtd->state &= ~ST_RUNNING;
prtd->params->ops->stop(prtd->params->ch);
break;
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index dd7c49f..f90139b 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -291,8 +291,11 @@ static int snd_soc_dapm_set_bias_level(struct snd_soc_dapm_context *dapm,
if (dapm->codec->driver->set_bias_level)
ret = dapm->codec->driver->set_bias_level(dapm->codec,
level);
- } else
+ else
+ dapm->bias_level = level;
+ } else if (!card || dapm != &card->dapm) {
dapm->bias_level = level;
+ }
if (ret != 0)
goto out;
diff --git a/sound/soc/spear/spear_pcm.c b/sound/soc/spear/spear_pcm.c
index 97c2cac..8c7f237 100644
--- a/sound/soc/spear/spear_pcm.c
+++ b/sound/soc/spear/spear_pcm.c
@@ -138,7 +138,7 @@ static void spear_pcm_free(struct snd_pcm *pcm)
continue;
buf = &substream->dma_buffer;
- if (!buf && !buf->area)
+ if (!buf || !buf->area)
continue;
dma_free_writecombine(pcm->card->dev, buf->bytes,
diff --git a/sound/soc/tegra/tegra_alc5632.c b/sound/soc/tegra/tegra_alc5632.c
index e463529..76cb1b3 100644
--- a/sound/soc/tegra/tegra_alc5632.c
+++ b/sound/soc/tegra/tegra_alc5632.c
@@ -89,7 +89,6 @@ static struct snd_soc_jack_gpio tegra_alc5632_hp_jack_gpio = {
.name = "Headset detection",
.report = SND_JACK_HEADSET,
.debounce_time = 150,
- .invert = 1,
};
static const struct snd_soc_dapm_widget tegra_alc5632_dapm_widgets[] = {
diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c
index 5658bce..8d6900c 100644
--- a/sound/soc/tegra/tegra_pcm.c
+++ b/sound/soc/tegra/tegra_pcm.c
@@ -334,11 +334,11 @@ static int tegra_pcm_hw_params(struct snd_pcm_substream *substream,
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
slave_config.dst_addr = dmap->addr;
- slave_config.src_maxburst = 0;
+ slave_config.dst_maxburst = 4;
} else {
slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
slave_config.src_addr = dmap->addr;
- slave_config.dst_maxburst = 0;
+ slave_config.src_maxburst = 4;
}
slave_config.slave_id = dmap->req_sel;
diff --git a/sound/soc/ux500/ux500_msp_i2s.c b/sound/soc/ux500/ux500_msp_i2s.c
index 5c472f3..eb85113 100644
--- a/sound/soc/ux500/ux500_msp_i2s.c
+++ b/sound/soc/ux500/ux500_msp_i2s.c
@@ -663,7 +663,6 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev,
struct ux500_msp **msp_p,
struct msp_i2s_platform_data *platform_data)
{
- int ret = 0;
struct resource *res = NULL;
struct i2s_controller *i2s_cont;
struct ux500_msp *msp;
@@ -685,15 +684,14 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev,
if (res == NULL) {
dev_err(&pdev->dev, "%s: ERROR: Unable to get resource!\n",
__func__);
- ret = -ENOMEM;
- goto err_res;
+ return -ENOMEM;
}
- msp->registers = ioremap(res->start, (res->end - res->start + 1));
+ msp->registers = devm_ioremap(&pdev->dev, res->start,
+ resource_size(res));
if (msp->registers == NULL) {
dev_err(&pdev->dev, "%s: ERROR: ioremap failed!\n", __func__);
- ret = -ENOMEM;
- goto err_res;
+ return -ENOMEM;
}
msp->msp_state = MSP_STATE_IDLE;
@@ -705,7 +703,7 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev,
dev_err(&pdev->dev,
"%s: ERROR: Failed to allocate I2S-controller!\n",
__func__);
- goto err_i2s_cont;
+ return -ENOMEM;
}
i2s_cont->dev.parent = &pdev->dev;
i2s_cont->data = (void *)msp;
@@ -716,14 +714,6 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev,
msp->i2s_cont = i2s_cont;
return 0;
-
-err_i2s_cont:
- iounmap(msp->registers);
-
-err_res:
- devm_kfree(&pdev->dev, msp);
-
- return ret;
}
void ux500_msp_i2s_cleanup_msp(struct platform_device *pdev,
@@ -732,11 +722,6 @@ void ux500_msp_i2s_cleanup_msp(struct platform_device *pdev,
dev_dbg(msp->dev, "%s: Enter (id = %d).\n", __func__, msp->id);
device_unregister(&msp->i2s_cont->dev);
- devm_kfree(&pdev->dev, msp->i2s_cont);
-
- iounmap(msp->registers);
-
- devm_kfree(&pdev->dev, msp);
}
MODULE_LICENSE("GPL v2");
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index d6e2bb4..060dccb 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -197,7 +197,13 @@ static void prepare_outbound_urb(struct snd_usb_endpoint *ep,
/* no data provider, so send silence */
unsigned int offs = 0;
for (i = 0; i < ctx->packets; ++i) {
- int counts = ctx->packet_size[i];
+ int counts;
+
+ if (ctx->packet_size[i])
+ counts = ctx->packet_size[i];
+ else
+ counts = snd_usb_endpoint_next_packet_size(ep);
+
urb->iso_frame_desc[i].offset = offs * ep->stride;
urb->iso_frame_desc[i].length = counts * ep->stride;
offs += counts;
OpenPOWER on IntegriCloud