Merge branch 'modsign-keys-devel' into security-next-keys
authorDavid Howells <dhowells@redhat.com>
Tue, 2 Oct 2012 18:30:19 +0000 (19:30 +0100)
committerDavid Howells <dhowells@redhat.com>
Tue, 2 Oct 2012 18:30:19 +0000 (19:30 +0100)
Signed-off-by: David Howells <dhowells@redhat.com>
619 files changed:
Documentation/ABI/testing/ima_policy
Documentation/ABI/testing/sysfs-bus-pci
Documentation/ABI/testing/sysfs-driver-ppi [new file with mode: 0644]
Documentation/i2c/busses/i2c-i801
Documentation/kernel-parameters.txt
Documentation/security/Smack.txt
Documentation/security/keys.txt
MAINTAINERS
Makefile
arch/arm/Kconfig
arch/arm/Kconfig.debug
arch/arm/Makefile
arch/arm/boot/compressed/head.S
arch/arm/boot/dts/at91sam9260.dtsi
arch/arm/boot/dts/at91sam9263.dtsi
arch/arm/boot/dts/at91sam9g45.dtsi
arch/arm/boot/dts/at91sam9n12.dtsi
arch/arm/boot/dts/at91sam9x5.dtsi
arch/arm/include/asm/assembler.h
arch/arm/include/asm/dma-mapping.h
arch/arm/include/asm/memory.h
arch/arm/include/asm/tlb.h
arch/arm/include/asm/uaccess.h
arch/arm/include/asm/unistd.h
arch/arm/kernel/calls.S
arch/arm/kernel/hw_breakpoint.c
arch/arm/kernel/smp_twd.c
arch/arm/kernel/traps.c
arch/arm/lib/delay.c
arch/arm/lib/getuser.S
arch/arm/lib/putuser.S
arch/arm/mach-imx/clk-imx25.c
arch/arm/mach-imx/clk-imx35.c
arch/arm/mach-imx/mach-armadillo5x0.c
arch/arm/mach-kirkwood/common.c
arch/arm/mach-omap2/Kconfig
arch/arm/mach-omap2/Makefile
arch/arm/mach-omap2/clock33xx_data.c
arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
arch/arm/mach-omap2/cm-regbits-34xx.h
arch/arm/mach-omap2/omap-wakeupgen.c
arch/arm/mach-omap2/omap_hwmod.c
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
arch/arm/mach-omap2/omap_hwmod_44xx_data.c
arch/arm/mach-omap2/timer.c
arch/arm/mach-shmobile/board-kzm9g.c
arch/arm/mm/context.c
arch/arm/mm/dma-mapping.c
arch/arm/mm/mm.h
arch/arm/mm/mmu.c
arch/arm/plat-mxc/include/mach/mx25.h
arch/arm/plat-omap/sram.c
arch/arm/plat-samsung/clock.c
arch/blackfin/Kconfig
arch/blackfin/Makefile
arch/blackfin/include/asm/smp.h
arch/blackfin/mach-common/smp.c
arch/m68k/platform/coldfire/clk.c
arch/mips/kernel/smp-cmp.c
arch/mips/mm/gup.c
arch/mips/mti-malta/malta-int.c
arch/mips/mti-malta/malta-platform.c
arch/powerpc/kernel/prom_init.c
arch/s390/include/asm/hugetlb.h
arch/s390/include/asm/tlbflush.h
arch/s390/kernel/setup.c
arch/s390/lib/uaccess_pt.c
arch/s390/oprofile/init.c
arch/sh/kernel/cpu/sh5/entry.S
arch/sh/kernel/entry-common.S
arch/sparc/kernel/module.c
arch/x86/Kconfig
arch/x86/Makefile
arch/x86/include/asm/xen/page.h
arch/x86/kernel/cpu/perf_event.h
arch/x86/kernel/cpu/perf_event_amd_ibs.c
arch/x86/kernel/cpu/perf_event_intel.c
arch/x86/kernel/cpu/perf_event_intel_ds.c
arch/x86/kernel/cpu/perf_event_intel_lbr.c
arch/x86/kernel/cpu/perf_event_intel_uncore.c
arch/x86/kernel/microcode_core.c
arch/x86/kvm/i8259.c
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c
arch/x86/mm/init.c
arch/x86/xen/enlighten.c
arch/x86/xen/mmu.c
arch/x86/xen/p2m.c
block/blk-core.c
block/ioctl.c
crypto/authenc.c
drivers/acpi/bus.c
drivers/acpi/power.c
drivers/ata/ahci.c
drivers/base/dma-contiguous.c
drivers/block/aoe/aoecmd.c
drivers/block/cciss_scsi.c
drivers/block/mtip32xx/mtip32xx.c
drivers/block/mtip32xx/mtip32xx.h
drivers/block/nbd.c
drivers/block/xen-blkback/blkback.c
drivers/bluetooth/ath3k.c
drivers/bluetooth/btusb.c
drivers/char/hw_random/Kconfig
drivers/char/hw_random/Makefile
drivers/char/hw_random/tpm-rng.c [new file with mode: 0644]
drivers/char/tpm/Kconfig
drivers/char/tpm/Makefile
drivers/char/tpm/tpm.c
drivers/char/tpm/tpm.h
drivers/char/tpm/tpm_acpi.c [new file with mode: 0644]
drivers/char/tpm/tpm_bios.c [deleted file]
drivers/char/tpm/tpm_eventlog.c [new file with mode: 0644]
drivers/char/tpm/tpm_eventlog.h [new file with mode: 0644]
drivers/char/tpm/tpm_i2c_infineon.c [new file with mode: 0644]
drivers/char/tpm/tpm_ibmvtpm.c [new file with mode: 0644]
drivers/char/tpm/tpm_ibmvtpm.h [new file with mode: 0644]
drivers/char/tpm/tpm_of.c [new file with mode: 0644]
drivers/char/tpm/tpm_ppi.c [new file with mode: 0644]
drivers/char/tpm/tpm_tis.c
drivers/clk/Makefile
drivers/clk/clk-devres.c [new file with mode: 0644]
drivers/clk/clkdev.c
drivers/cpufreq/powernow-k8.c
drivers/crypto/caam/key_gen.c
drivers/dma/at_hdmac.c
drivers/dma/pl330.c
drivers/edac/edac_mc.c
drivers/extcon/extcon-max77693.c
drivers/gpu/drm/ast/ast_drv.c
drivers/gpu/drm/ast/ast_mode.c
drivers/gpu/drm/cirrus/cirrus_drv.c
drivers/gpu/drm/exynos/Kconfig
drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
drivers/gpu/drm/exynos/exynos_drm_drv.c
drivers/gpu/drm/exynos/exynos_drm_fimd.c
drivers/gpu/drm/exynos/exynos_drm_g2d.c
drivers/gpu/drm/exynos/exynos_drm_gem.c
drivers/gpu/drm/exynos/exynos_drm_hdmi.c
drivers/gpu/drm/exynos/exynos_drm_plane.c
drivers/gpu/drm/exynos/exynos_drm_vidi.c
drivers/gpu/drm/exynos/exynos_hdmi.c
drivers/gpu/drm/exynos/exynos_mixer.c
drivers/gpu/drm/gma500/oaktrail_device.c
drivers/gpu/drm/i810/i810_dma.c
drivers/gpu/drm/i810/i810_drv.c
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_hdmi.c
drivers/gpu/drm/i915/intel_panel.c
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/i915/intel_sdvo.c
drivers/gpu/drm/mgag200/mgag200_drv.c
drivers/gpu/drm/nouveau/nouveau_display.c
drivers/gpu/drm/nouveau/nv50_gpio.c
drivers/gpu/drm/nouveau/nvd0_display.c
drivers/gpu/drm/radeon/r100.c
drivers/gpu/drm/radeon/radeon_fence.c
drivers/gpu/drm/savage/savage_drv.c
drivers/gpu/drm/sis/sis_drv.c
drivers/gpu/drm/tdfx/tdfx_drv.c
drivers/gpu/drm/udl/udl_drv.c
drivers/gpu/drm/via/via_drv.c
drivers/gpu/drm/vmwgfx/Kconfig
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
drivers/hid/hid-core.c
drivers/hid/hid-lenovo-tpkbd.c
drivers/hid/hid-logitech-dj.c
drivers/hid/hid-logitech-dj.h
drivers/hid/usbhid/hid-quirks.c
drivers/hwmon/ad7314.c
drivers/hwmon/ads7871.c
drivers/hwmon/applesmc.c
drivers/hwmon/coretemp.c
drivers/hwmon/fam15h_power.c
drivers/hwmon/ina2xx.c
drivers/hwmon/twl4030-madc-hwmon.c
drivers/hwmon/via-cputemp.c
drivers/hwspinlock/hwspinlock_core.c
drivers/i2c/algos/i2c-algo-pca.c
drivers/i2c/busses/Kconfig
drivers/i2c/busses/Makefile
drivers/i2c/busses/i2c-designware-core.c
drivers/i2c/busses/i2c-i801.c
drivers/i2c/busses/i2c-mxs.c
drivers/i2c/busses/i2c-pnx.c
drivers/i2c/i2c-core.c
drivers/iio/adc/at91_adc.c
drivers/infiniband/hw/cxgb4/cm.c
drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
drivers/infiniband/hw/qib/qib_mad.c
drivers/infiniband/ulp/ipoib/ipoib.h
drivers/infiniband/ulp/ipoib/ipoib_main.c
drivers/infiniband/ulp/ipoib/ipoib_multicast.c
drivers/input/keyboard/imx_keypad.c
drivers/input/misc/ab8500-ponkey.c
drivers/input/mouse/sentelic.c
drivers/input/serio/ambakmi.c
drivers/input/serio/i8042-x86ia64io.h
drivers/input/tablet/wacom_wac.c
drivers/input/touchscreen/edt-ft5x06.c
drivers/input/touchscreen/usbtouchscreen.c
drivers/isdn/hardware/mISDN/avmfritz.c
drivers/isdn/hardware/mISDN/hfcmulti.c
drivers/isdn/hardware/mISDN/mISDNipac.c
drivers/isdn/hardware/mISDN/mISDNisar.c
drivers/isdn/hardware/mISDN/netjet.c
drivers/isdn/hardware/mISDN/w6692.c
drivers/isdn/mISDN/hwchannel.c
drivers/md/md.c
drivers/md/raid5.c
drivers/mfd/88pm800.c
drivers/mfd/88pm805.c
drivers/mfd/88pm860x-core.c
drivers/mfd/aat2870-core.c
drivers/mfd/ab3100-core.c
drivers/mfd/ab8500-core.c
drivers/mfd/arizona-core.c
drivers/mfd/asic3.c
drivers/mfd/cs5535-mfd.c
drivers/mfd/da9052-core.c
drivers/mfd/davinci_voicecodec.c
drivers/mfd/db8500-prcmu.c
drivers/mfd/htc-pasic3.c
drivers/mfd/intel_msic.c
drivers/mfd/janz-cmodio.c
drivers/mfd/jz4740-adc.c
drivers/mfd/lm3533-core.c
drivers/mfd/lpc_ich.c
drivers/mfd/lpc_sch.c
drivers/mfd/max77686.c
drivers/mfd/max77693-irq.c
drivers/mfd/max77693.c
drivers/mfd/max8925-core.c
drivers/mfd/max8997.c
drivers/mfd/max8998.c
drivers/mfd/mc13xxx-core.c
drivers/mfd/mfd-core.c
drivers/mfd/palmas.c
drivers/mfd/rc5t583.c
drivers/mfd/rdc321x-southbridge.c
drivers/mfd/sec-core.c
drivers/mfd/sta2x11-mfd.c
drivers/mfd/stmpe.c
drivers/mfd/t7l66xb.c
drivers/mfd/tc3589x.c
drivers/mfd/tc6387xb.c
drivers/mfd/tc6393xb.c
drivers/mfd/ti-ssp.c
drivers/mfd/timberdale.c
drivers/mfd/tps6105x.c
drivers/mfd/tps6507x.c
drivers/mfd/tps65090.c
drivers/mfd/tps65217.c
drivers/mfd/tps6586x.c
drivers/mfd/tps65910.c
drivers/mfd/tps65912-core.c
drivers/mfd/twl4030-audio.c
drivers/mfd/twl6040-core.c
drivers/mfd/vx855.c
drivers/mfd/wl1273-core.c
drivers/mfd/wm831x-core.c
drivers/mfd/wm8400-core.c
drivers/mfd/wm8994-core.c
drivers/net/can/janz-ican3.c
drivers/net/can/mcp251x.c
drivers/net/can/ti_hecc.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_dump.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c
drivers/net/ethernet/cadence/at91_ether.c
drivers/net/ethernet/freescale/gianfar_ethtool.c
drivers/net/ethernet/freescale/gianfar_ptp.c
drivers/net/ethernet/i825xx/znet.c
drivers/net/ethernet/ibm/ibmveth.c
drivers/net/ethernet/intel/e1000/e1000_main.c
drivers/net/ethernet/mellanox/mlx4/icm.c
drivers/net/ethernet/mellanox/mlx4/icm.h
drivers/net/ethernet/mellanox/mlx4/main.c
drivers/net/ethernet/mellanox/mlx4/mcg.c
drivers/net/ethernet/mellanox/mlx4/mlx4.h
drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
drivers/net/ethernet/seeq/sgiseeq.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/stmicro/stmmac/stmmac_timer.c
drivers/net/irda/sh_sir.c
drivers/net/usb/asix_devices.c
drivers/net/usb/qmi_wwan.c
drivers/net/usb/sierra_net.c
drivers/net/usb/usbnet.c
drivers/net/wan/ixp4xx_hss.c
drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
drivers/net/wireless/ath/ath9k/ar9003_paprd.c
drivers/net/wireless/ath/ath9k/ar9003_phy.h
drivers/net/wireless/ath/ath9k/debug.c
drivers/net/wireless/ath/ath9k/gpio.c
drivers/net/wireless/ath/ath9k/hw.c
drivers/net/wireless/ath/ath9k/hw.h
drivers/net/wireless/ath/ath9k/link.c
drivers/net/wireless/ath/ath9k/xmit.c
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
drivers/net/wireless/brcm80211/brcmfmac/usb.c
drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
drivers/net/wireless/brcm80211/brcmsmac/channel.c
drivers/net/wireless/libertas/if_sdio.c
drivers/net/wireless/mwifiex/cmdevt.c
drivers/net/wireless/rt2x00/rt2400pci.c
drivers/net/wireless/rt2x00/rt2400pci.h
drivers/net/wireless/rt2x00/rt2500pci.c
drivers/net/wireless/rt2x00/rt2500usb.c
drivers/net/wireless/rt2x00/rt2500usb.h
drivers/net/wireless/rt2x00/rt2800lib.c
drivers/net/wireless/rt2x00/rt2800pci.c
drivers/net/wireless/rt2x00/rt2800usb.c
drivers/net/wireless/rt2x00/rt2x00dev.c
drivers/net/wireless/rt2x00/rt61pci.c
drivers/net/wireless/rt2x00/rt61pci.h
drivers/net/wireless/rt2x00/rt73usb.c
drivers/net/wireless/rt2x00/rt73usb.h
drivers/net/wireless/rtlwifi/rtl8192ce/def.h
drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
drivers/pci/pci-driver.c
drivers/pci/pci-sysfs.c
drivers/pci/pci.c
drivers/pci/pcie/portdrv_pci.c
drivers/pci/probe.c
drivers/platform/x86/acer-wmi.c
drivers/platform/x86/apple-gmux.c
drivers/platform/x86/asus-laptop.c
drivers/platform/x86/asus-wmi.c
drivers/platform/x86/eeepc-laptop.c
drivers/platform/x86/samsung-laptop.c
drivers/platform/x86/thinkpad_acpi.c
drivers/pwm/pwm-tiecap.c
drivers/pwm/pwm-tiehrpwm.c
drivers/regulator/tps65217-regulator.c
drivers/rpmsg/virtio_rpmsg_bus.c
drivers/rtc/rtc-twl.c
drivers/s390/block/dasd.c
drivers/s390/block/dasd_alias.c
drivers/s390/block/dasd_eckd.c
drivers/s390/cio/device.c
drivers/scsi/bnx2i/bnx2i_hwi.c
drivers/scsi/hpsa.c
drivers/scsi/megaraid/megaraid_sas_base.c
drivers/scsi/mpt2sas/mpt2sas_base.c
drivers/scsi/scsi_error.c
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_scan.c
drivers/scsi/virtio_scsi.c
drivers/sh/intc/core.c
drivers/sh/pfc/pinctrl.c
drivers/staging/android/android_alarm.h
drivers/staging/comedi/drivers/amplc_dio200.c
drivers/staging/comedi/drivers/amplc_pc236.c
drivers/staging/comedi/drivers/amplc_pc263.c
drivers/staging/comedi/drivers/amplc_pci224.c
drivers/staging/comedi/drivers/amplc_pci230.c
drivers/staging/comedi/drivers/das08.c
drivers/staging/iio/accel/lis3l02dq_ring.c
drivers/staging/iio/adc/ad7192.c
drivers/staging/iio/gyro/adis16260_core.c
drivers/staging/iio/imu/adis16400_core.c
drivers/staging/iio/meter/ade7753.c
drivers/staging/iio/meter/ade7754.c
drivers/staging/iio/meter/ade7759.c
drivers/staging/nvec/nvec.c
drivers/staging/omapdrm/omap_connector.c
drivers/staging/ozwpan/ozcdev.c
drivers/staging/rtl8712/recv_linux.c
drivers/staging/vt6656/dpc.c
drivers/staging/vt6656/rxtx.c
drivers/staging/wlan-ng/cfg80211.c
drivers/staging/zcache/zcache-main.c
drivers/target/iscsi/iscsi_target_login.c
drivers/target/target_core_alua.c
drivers/target/target_core_device.c
drivers/target/target_core_iblock.c
drivers/target/target_core_pr.c
drivers/target/target_core_pscsi.c
drivers/target/target_core_spc.c
drivers/target/target_core_transport.c
drivers/tty/serial/imx.c
drivers/usb/chipidea/udc.c
drivers/usb/class/cdc-wdm.c
drivers/usb/core/quirks.c
drivers/usb/dwc3/core.c
drivers/usb/dwc3/ep0.c
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/at91_udc.c
drivers/usb/gadget/dummy_hcd.c
drivers/usb/gadget/f_fs.c
drivers/usb/gadget/s3c-hsotg.c
drivers/usb/gadget/u_serial.c
drivers/usb/host/ehci-q.c
drivers/usb/host/ohci-at91.c
drivers/usb/host/pci-quirks.c
drivers/usb/host/pci-quirks.h
drivers/usb/host/xhci-hub.c
drivers/usb/host/xhci-plat.c
drivers/usb/host/xhci.c
drivers/usb/host/xhci.h
drivers/usb/musb/musb_host.c
drivers/usb/musb/musbhsdma.c
drivers/usb/musb/tusb6010.c
drivers/usb/renesas_usbhs/fifo.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio_ids.h
drivers/usb/serial/option.c
drivers/watchdog/hpwdt.c
drivers/watchdog/watchdog_core.c
drivers/xen/gntdev.c
drivers/xen/grant-table.c
drivers/xen/swiotlb-xen.c
drivers/xen/xen-pciback/pci_stub.c
fs/attr.c
fs/btrfs/qgroup.c
fs/cifs/cifs_unicode.c
fs/cifs/cifsacl.c
fs/cifs/file.c
fs/cifs/smb2pdu.h
fs/dcache.c
fs/debugfs/file.c
fs/ecryptfs/file.c
fs/ecryptfs/inode.c
fs/ecryptfs/main.c
fs/ext3/inode.c
fs/file_table.c
fs/fuse/control.c
fs/fuse/cuse.c
fs/fuse/dev.c
fs/fuse/inode.c
fs/gfs2/file.c
fs/gfs2/inode.c
fs/gfs2/rgrp.c
fs/nfs/file.c
fs/nfs/idmap.c
fs/nfs/inode.c
fs/nfs/nfs3proc.c
fs/nfs/nfs4file.c
fs/nfs/nfs4proc.c
fs/nfs/nfs4xdr.c
fs/nfs/super.c
fs/proc/proc_sysctl.c
fs/stat.c
fs/udf/file.c
fs/xattr.c
fs/xfs/xfs_buf.c
fs/xfs/xfs_buf.h
fs/xfs/xfs_super.c
include/drm/drm_fourcc.h
include/linux/atmel-ssc.h
include/linux/audit.h
include/linux/compiler-gcc4.h
include/linux/compiler.h
include/linux/cred.h
include/linux/dcache.h
include/linux/i2c-pnx.h
include/linux/ima.h
include/linux/integrity.h
include/linux/kernel.h
include/linux/key.h
include/linux/kobject.h
include/linux/mISDNhw.h
include/linux/memory.h
include/linux/mfd/core.h
include/linux/mfd/tps65217.h
include/linux/mlx4/device.h
include/linux/nfs_fs.h
include/linux/nfs_xdr.h
include/linux/perf_event.h
include/linux/ptrace.h
include/linux/sched.h
include/linux/security.h
include/linux/sunrpc/xprt.h
include/linux/tpm.h
include/linux/xattr.h
include/linux/xfrm.h
include/net/bluetooth/smp.h
include/net/ip6_fib.h
include/net/net_namespace.h
include/net/netns/ipv4.h
include/net/route.h
include/net/sock.h
include/net/xfrm.h
include/target/target_core_backend.h
include/target/target_core_base.h
include/trace/events/kmem.h
include/xen/grant_table.h
kernel/auditsc.c
kernel/cred.c
kernel/events/core.c
kernel/events/hw_breakpoint.c
kernel/pid_namespace.c
kernel/ptrace.c
kernel/sched/core.c
kernel/sched/fair.c
kernel/sched/rt.c
kernel/sched/sched.h
kernel/time/tick-sched.c
kernel/time/timekeeping.c
kernel/workqueue.c
lib/digsig.c
mm/memblock.c
mm/memory_hotplug.c
mm/page_alloc.c
mm/slab.c
mm/slub.c
mm/vmscan.c
net/batman-adv/bitarray.h
net/bluetooth/bnep/sock.c
net/bluetooth/cmtp/sock.c
net/bluetooth/hci_conn.c
net/bluetooth/hci_sock.c
net/bluetooth/hidp/sock.c
net/bluetooth/l2cap_core.c
net/bluetooth/l2cap_sock.c
net/bluetooth/smp.c
net/bridge/netfilter/ebt_log.c
net/caif/cfsrvl.c
net/core/dev.c
net/core/pktgen.c
net/core/skbuff.c
net/core/sock.c
net/dns_resolver/dns_key.c
net/ipv4/arp.c
net/ipv4/devinet.c
net/ipv4/fib_frontend.c
net/ipv4/fib_rules.c
net/ipv4/fib_trie.c
net/ipv4/route.c
net/ipv4/tcp.c
net/ipv4/tcp_input.c
net/ipv4/udp.c
net/ipv6/inet6_connection_sock.c
net/ipv6/ip6_fib.c
net/ipv6/route.c
net/ipv6/tcp_ipv6.c
net/ipv6/udp.c
net/l2tp/l2tp_core.c
net/l2tp/l2tp_eth.c
net/mac80211/cfg.c
net/mac80211/mlme.c
net/netfilter/nf_conntrack_proto_tcp.c
net/netfilter/nfnetlink_log.c
net/netfilter/xt_LOG.c
net/netrom/af_netrom.c
net/openvswitch/actions.c
net/openvswitch/datapath.c
net/openvswitch/flow.h
net/sched/sch_cbq.c
net/sched/sch_fq_codel.c
net/sched/sch_gred.c
net/sched/sch_qfq.c
net/sctp/output.c
net/sunrpc/xprt.c
net/sunrpc/xprtrdma/transport.c
net/sunrpc/xprtsock.c
net/wireless/nl80211.c
net/xfrm/xfrm_input.c
net/xfrm/xfrm_policy.c
net/xfrm/xfrm_replay.c
net/xfrm/xfrm_user.c
samples/seccomp/Makefile
samples/seccomp/bpf-helper.h
scripts/Makefile.fwinst
scripts/link-vmlinux.sh
security/integrity/evm/evm_main.c
security/integrity/iint.c
security/integrity/ima/Kconfig
security/integrity/ima/Makefile
security/integrity/ima/ima.h
security/integrity/ima/ima_api.c
security/integrity/ima/ima_appraise.c [new file with mode: 0644]
security/integrity/ima/ima_crypto.c
security/integrity/ima/ima_main.c
security/integrity/ima/ima_policy.c
security/integrity/integrity.h
security/keys/key.c
security/keys/keyctl.c
security/keys/keyring.c
security/keys/process_keys.c
security/keys/request_key.c
security/keys/trusted.c
security/security.c
security/selinux/include/xfrm.h
security/smack/smack_lsm.c
security/smack/smackfs.c
security/yama/Kconfig
security/yama/yama_lsm.c
sound/core/compress_offload.c
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_sigmatel.c
sound/pci/ice1712/prodigy_hifi.c
sound/soc/codecs/arizona.c
sound/soc/codecs/mc13783.c
sound/soc/codecs/wm8904.c
sound/soc/fsl/imx-sgtl5000.c
sound/soc/omap/am3517evm.c
sound/soc/samsung/dma.c
sound/soc/soc-dapm.c
sound/soc/spear/spear_pcm.c
sound/soc/tegra/tegra_alc5632.c
sound/soc/tegra/tegra_pcm.c
sound/soc/ux500/ux500_msp_i2s.c
sound/usb/pcm.c

index 6cd6daefaaedeb160a6f1ac1d616de7871b38965..986946613542b4bc1852aaf671e62059d3295cea 100644 (file)
@@ -12,11 +12,14 @@ Description:
                then closing the file.  The new policy takes effect after
                the file ima/policy is closed.
 
+               IMA appraisal, if configured, uses these file measurements
+               for local measurement appraisal.
+
                rule format: action [condition ...]
 
-               action: measure | dont_measure
+               action: measure | dont_measure | appraise | dont_appraise | audit
                condition:= base | lsm
-                       base:   [[func=] [mask=] [fsmagic=] [uid=]]
+                       base:   [[func=] [mask=] [fsmagic=] [uid=] [fowner]]
                        lsm:    [[subj_user=] [subj_role=] [subj_type=]
                                 [obj_user=] [obj_role=] [obj_type=]]
 
@@ -24,36 +27,50 @@ Description:
                        mask:= [MAY_READ] [MAY_WRITE] [MAY_APPEND] [MAY_EXEC]
                        fsmagic:= hex value
                        uid:= decimal value
+                       fowner:=decimal value
                lsm:    are LSM specific
 
                default policy:
                        # PROC_SUPER_MAGIC
                        dont_measure fsmagic=0x9fa0
+                       dont_appraise fsmagic=0x9fa0
                        # SYSFS_MAGIC
                        dont_measure fsmagic=0x62656572
+                       dont_appraise fsmagic=0x62656572
                        # DEBUGFS_MAGIC
                        dont_measure fsmagic=0x64626720
+                       dont_appraise fsmagic=0x64626720
                        # TMPFS_MAGIC
                        dont_measure fsmagic=0x01021994
+                       dont_appraise fsmagic=0x01021994
+                       # RAMFS_MAGIC
+                       dont_measure fsmagic=0x858458f6
+                       dont_appraise fsmagic=0x858458f6
                        # SECURITYFS_MAGIC
                        dont_measure fsmagic=0x73636673
+                       dont_appraise fsmagic=0x73636673
 
                        measure func=BPRM_CHECK
                        measure func=FILE_MMAP mask=MAY_EXEC
                        measure func=FILE_CHECK mask=MAY_READ uid=0
+                       appraise fowner=0
 
                The default policy measures all executables in bprm_check,
                all files mmapped executable in file_mmap, and all files
-               open for read by root in do_filp_open.
+               open for read by root in do_filp_open.  The default appraisal
+               policy appraises all files owned by root.
 
                Examples of LSM specific definitions:
 
                SELinux:
                        # SELINUX_MAGIC
-                       dont_measure fsmagic=0xF97CFF8C
+                       dont_measure fsmagic=0xf97cff8c
+                       dont_appraise fsmagic=0xf97cff8c
 
                        dont_measure obj_type=var_log_t
+                       dont_appraise obj_type=var_log_t
                        dont_measure obj_type=auditd_log_t
+                       dont_appraise obj_type=auditd_log_t
                        measure subj_user=system_u func=FILE_CHECK mask=MAY_READ
                        measure subj_role=system_r func=FILE_CHECK mask=MAY_READ
 
index 34f51100f0299cb5a96a77984def99dbfdd9367d..dff1f48d252d8f0d36aa31cccf6514cb02b3d333 100644 (file)
@@ -210,3 +210,15 @@ Users:
                firmware assigned instance number of the PCI
                device that can help in understanding the firmware
                intended order of the PCI device.
+
+What:          /sys/bus/pci/devices/.../d3cold_allowed
+Date:          July 2012
+Contact:       Huang Ying <ying.huang@intel.com>
+Description:
+               d3cold_allowed is bit to control whether the corresponding PCI
+               device can be put into D3Cold state.  If it is cleared, the
+               device will never be put into D3Cold state.  If it is set, the
+               device may be put into D3Cold state if other requirements are
+               satisfied too.  Reading this attribute will show the current
+               value of d3cold_allowed bit.  Writing this attribute will set
+               the value of d3cold_allowed bit.
diff --git a/Documentation/ABI/testing/sysfs-driver-ppi b/Documentation/ABI/testing/sysfs-driver-ppi
new file mode 100644 (file)
index 0000000..97a003e
--- /dev/null
@@ -0,0 +1,70 @@
+What:          /sys/devices/pnp0/<bus-num>/ppi/
+Date:          August 2012
+Kernel Version:        3.6
+Contact:       xiaoyan.zhang@intel.com
+Description:
+               This folder includes the attributes related with PPI (Physical
+               Presence Interface). Only if TPM is supported by BIOS, this
+               folder makes sence. The folder path can be got by command
+               'find /sys/ -name 'pcrs''. For the detail information of PPI,
+               please refer to the PPI specification from
+               http://www.trustedcomputinggroup.org/
+
+What:          /sys/devices/pnp0/<bus-num>/ppi/version
+Date:          August 2012
+Contact:       xiaoyan.zhang@intel.com
+Description:
+               This attribute shows the version of the PPI supported by the
+               platform.
+               This file is readonly.
+
+What:          /sys/devices/pnp0/<bus-num>/ppi/request
+Date:          August 2012
+Contact:       xiaoyan.zhang@intel.com
+Description:
+               This attribute shows the request for an operation to be
+               executed in the pre-OS environment. It is the only input from
+               the OS to the pre-OS environment. The request should be an
+               integer value range from 1 to 160, and 0 means no request.
+               This file can be read and written.
+
+What:          /sys/devices/pnp0/00:<bus-num>/ppi/response
+Date:          August 2012
+Contact:       xiaoyan.zhang@intel.com
+Description:
+               This attribute shows the response to the most recent operation
+               request it acted upon. The format is "<request> <response num>
+               : <response description>".
+               This file is readonly.
+
+What:          /sys/devices/pnp0/<bus-num>/ppi/transition_action
+Date:          August 2012
+Contact:       xiaoyan.zhang@intel.com
+Description:
+               This attribute shows the platform-specific action that should
+               take place in order to transition to the BIOS for execution of
+               a requested operation. The format is "<action num>: <action
+               description>".
+               This file is readonly.
+
+What:          /sys/devices/pnp0/<bus-num>/ppi/tcg_operations
+Date:          August 2012
+Contact:       xiaoyan.zhang@intel.com
+Description:
+               This attribute shows whether it is allowed to request an
+               operation to be executed in the pre-OS environment by the BIOS
+               for the requests defined by TCG, i.e. requests from 1 to 22.
+               The format is "<request> <status num>: <status description>".
+               This attribute is only supported by PPI version 1.2+.
+               This file is readonly.
+
+What:          /sys/devices/pnp0/<bus-num>/ppi/vs_operations
+Date:          August 2012
+Contact:       xiaoyan.zhang@intel.com
+Description:
+               This attribute shows whether it is allowed to request an
+               operation to be executed in the pre-OS environment by the BIOS
+               for the verdor specific requests, i.e. requests from 128 to
+               255. The format is same with tcg_operations. This attribute
+               is also only supported by PPI version 1.2+.
+               This file is readonly.
index 615142da4ef64c6ec8ae87893425046a1564e786..157416e78cc4168859c89c88b13bcfeb71c4848f 100644 (file)
@@ -21,6 +21,7 @@ Supported adapters:
   * Intel DH89xxCC (PCH)
   * Intel Panther Point (PCH)
   * Intel Lynx Point (PCH)
+  * Intel Lynx Point-LP (PCH)
    Datasheets: Publicly available at the Intel website
 
 On Intel Patsburg and later chipsets, both the normal host SMBus controller
index ad7e2e5088c126ce48e0362d1f3296f3e8b55d2b..949dddcfd17784724c6c6ce59afd8cd697e998de 100644 (file)
@@ -1051,6 +1051,14 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
        ihash_entries=  [KNL]
                        Set number of hash buckets for inode cache.
 
+       ima_appraise=   [IMA] appraise integrity measurements
+                       Format: { "off" | "enforce" | "fix" }
+                       default: "enforce"
+
+       ima_appraise_tcb [IMA]
+                       The builtin appraise policy appraises all files
+                       owned by uid=0.
+
        ima_audit=      [IMA]
                        Format: { "0" | "1" }
                        0 -- integrity auditing messages. (Default)
index a416479b8a1c23d6755cd5354027159af832a4dc..8a177e4b6e21237e0e03f0410acb70d9282ce014 100644 (file)
@@ -28,12 +28,11 @@ Smack kernels use the CIPSO IP option. Some network
 configurations are intolerant of IP options and can impede
 access to systems that use them as Smack does.
 
-The current git repositories for Smack user space are:
+The current git repository for Smack user space is:
 
-       git@gitorious.org:meego-platform-security/smackutil.git
-       git@gitorious.org:meego-platform-security/libsmack.git
+       git://github.com/smack-team/smack.git
 
-These should make and install on most modern distributions.
+This should make and install on most modern distributions.
 There are three commands included in smackutil:
 
 smackload  - properly formats data for writing to /smack/load
@@ -194,6 +193,9 @@ onlycap
        these capabilities are effective at for processes with any
        label. The value is set by writing the desired label to the
        file or cleared by writing "-" to the file.
+revoke-subject
+       Writing a Smack label here sets the access to '-' for all access
+       rules with that subject label.
 
 You can add access rules in /etc/smack/accesses. They take the form:
 
index 7d9ca92022d8c97b2f9db88c66713211c9c8cc2a..7b4145d00452f259fe79eff4f400ecfc949a6fd1 100644 (file)
@@ -994,6 +994,23 @@ payload contents" for more information.
     reference pointer if successful.
 
 
+(*) A keyring can be created by:
+
+       struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid,
+                                 const struct cred *cred,
+                                 key_perm_t perm,
+                                 unsigned long flags,
+                                 struct key *dest);
+
+    This creates a keyring with the given attributes and returns it.  If dest
+    is not NULL, the new keyring will be linked into the keyring to which it
+    points.  No permission checks are made upon the destination keyring.
+
+    Error EDQUOT can be returned if the keyring would overload the quota (pass
+    KEY_ALLOC_NOT_IN_QUOTA in flags if the keyring shouldn't be accounted
+    towards the user's quota).  Error ENOMEM can also be returned.
+
+
 (*) To check the validity of a key, this function can be called:
 
        int validate_key(struct key *key);
index fdc0119963e70f12c4f9e1eae3a613447e7d8781..b17587d9412f04318dab5e7368f6e5306ca57b91 100644 (file)
@@ -3388,7 +3388,7 @@ M:        "Wolfram Sang (embedded platforms)" <w.sang@pengutronix.de>
 L:     linux-i2c@vger.kernel.org
 W:     http://i2c.wiki.kernel.org/
 T:     quilt kernel.org/pub/linux/kernel/people/jdelvare/linux-2.6/jdelvare-i2c/
-T:     git git://git.fluff.org/bjdooks/linux.git
+T:     git git://git.pengutronix.de/git/wsa/linux.git
 S:     Maintained
 F:     Documentation/i2c/
 F:     drivers/i2c/
@@ -3666,11 +3666,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
index 371ce8899f5c758633ed25ffdacef01b45fa6e99..a3c11d589681d9a53db5cf31ca8a4e1c1b9246a5 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,8 @@
 VERSION = 3
 PATCHLEVEL = 6
 SUBLEVEL = 0
-EXTRAVERSION = -rc4
-NAME = Saber-toothed Squirrel
+EXTRAVERSION = -rc7
+NAME = Terrified Chipmunk
 
 # *DOCUMENTATION*
 # To see a list of typical targets execute "make help"
index c5f9ae5dbd1ad04da804d68e475d3b4b230832f6..2f88d8d9770116014f7ff55e80d98c65fbb191ed 100644 (file)
@@ -6,7 +6,7 @@ config ARM
        select HAVE_DMA_API_DEBUG
        select HAVE_IDE if PCI || ISA || PCMCIA
        select HAVE_DMA_ATTRS
-       select HAVE_DMA_CONTIGUOUS if (CPU_V6 || CPU_V6K || CPU_V7)
+       select HAVE_DMA_CONTIGUOUS if MMU
        select HAVE_MEMBLOCK
        select RTC_LIB
        select SYS_SUPPORTS_APM_EMULATION
index f15f82bf3a50f808005af479ff9c334f100c1044..e968a52e4881967a01f8aa68fc586aafe61edf38 100644 (file)
@@ -356,15 +356,15 @@ choice
                  is nothing connected to read from the DCC.
 
        config DEBUG_SEMIHOSTING
-               bool "Kernel low-level debug output via semihosting I"
+               bool "Kernel low-level debug output via semihosting I/O"
                help
                  Semihosting enables code running on an ARM target to use
                  the I/O facilities on a host debugger/emulator through a
-                 simple SVC calls. The host debugger or emulator must have
+                 simple SVC call. The host debugger or emulator must have
                  semihosting enabled for the special svc call to be trapped
                  otherwise the kernel will crash.
 
-                 This is known to work with OpenOCD, as wellas
+                 This is known to work with OpenOCD, as well as
                  ARM's Fast Models, or any other controlling environment
                  that implements semihosting.
 
index 30eae87ead6d4b245bc6707040645f5182464e90..a051dfbdd7db07fb12db913d85050a5bb0ea7167 100644 (file)
@@ -284,10 +284,10 @@ zImage Image xipImage bootpImage uImage: vmlinux
 zinstall uinstall install: vmlinux
        $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $@
 
-%.dtb:
+%.dtb: scripts
        $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
 
-dtbs:
+dtbs: scripts
        $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
 
 # We use MRPROPER_FILES and CLEAN_FILES now
index b8c64b80bafc848032dfff366a9ac4428a7f82b5..bc67cbff39448ff84a3f0c14cd22876975ee1965 100644 (file)
@@ -653,16 +653,21 @@ __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
 #ifdef CONFIG_CPU_ENDIAN_BE8
                orr     r0, r0, #1 << 25        @ big-endian page tables
 #endif
+               mrcne   p15, 0, r6, c2, c0, 2   @ read ttb control reg
                orrne   r0, r0, #1              @ MMU enabled
                movne   r1, #0xfffffffd         @ domain 0 = client
+               bic     r6, r6, #1 << 31        @ 32-bit translation system
+               bic     r6, r6, #3 << 0         @ use only ttbr0
                mcrne   p15, 0, r3, c2, c0, 0   @ load page table pointer
                mcrne   p15, 0, r1, c3, c0, 0   @ load domain access control
+               mcrne   p15, 0, r6, c2, c0, 2   @ load ttb control
 #endif
                mcr     p15, 0, r0, c7, c5, 4   @ ISB
                mcr     p15, 0, r0, c1, c0, 0   @ load control register
index 66389c1c6f6297e50c8ae3b944d7311dcbb26b6c..7c95f76398de401ac166af8f32d4a34a6b918e79 100644 (file)
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
+                               #interrupt-cells = <2>;
                        };
 
                        pioB: gpio@fffff600 {
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
+                               #interrupt-cells = <2>;
                        };
 
                        pioC: gpio@fffff800 {
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
+                               #interrupt-cells = <2>;
                        };
 
                        dbgu: serial@fffff200 {
index b460d6ce9eb592da5191871b40b2d3433156bcef..195019b7ca0e046073361a587862c885c8fbfb7e 100644 (file)
@@ -95,6 +95,7 @@
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
+                               #interrupt-cells = <2>;
                        };
 
                        pioB: gpio@fffff400 {
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
+                               #interrupt-cells = <2>;
                        };
 
                        pioC: gpio@fffff600 {
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
+                               #interrupt-cells = <2>;
                        };
 
                        pioD: gpio@fffff800 {
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
+                               #interrupt-cells = <2>;
                        };
 
                        pioE: gpio@fffffa00 {
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
+                               #interrupt-cells = <2>;
                        };
 
                        dbgu: serial@ffffee00 {
index bafa8806fc17293e3bddc28aff5b4829f677c178..63751b1e744b42611f8e74d17738ccd69dd1efe1 100644 (file)
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
+                               #interrupt-cells = <2>;
                        };
 
                        pioB: gpio@fffff400 {
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
+                               #interrupt-cells = <2>;
                        };
 
                        pioC: gpio@fffff600 {
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
+                               #interrupt-cells = <2>;
                        };
 
                        pioD: gpio@fffff800 {
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
+                               #interrupt-cells = <2>;
                        };
 
                        pioE: gpio@fffffa00 {
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
+                               #interrupt-cells = <2>;
                        };
 
                        dbgu: serial@ffffee00 {
index bfac0dfc332c7d10bc3fe2f87458ec728c48b885..ef9336ae9614f85ffb0ce2348b69fc06b0f756e5 100644 (file)
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
+                               #interrupt-cells = <2>;
                        };
 
                        pioB: gpio@fffff600 {
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
+                               #interrupt-cells = <2>;
                        };
 
                        pioC: gpio@fffff800 {
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
+                               #interrupt-cells = <2>;
                        };
 
                        pioD: gpio@fffffa00 {
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
+                               #interrupt-cells = <2>;
                        };
 
                        dbgu: serial@fffff200 {
index 4a18c393b1360f490c9796f3c598d349338ed2f5..8a387a8d61b745fc763c9e13f015896bc3e2bff7 100644 (file)
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
+                               #interrupt-cells = <2>;
                        };
 
                        pioB: gpio@fffff600 {
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
+                               #interrupt-cells = <2>;
                        };
 
                        pioC: gpio@fffff800 {
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
+                               #interrupt-cells = <2>;
                        };
 
                        pioD: gpio@fffffa00 {
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
+                               #interrupt-cells = <2>;
                        };
 
                        dbgu: serial@fffff200 {
index 03fb93621d0d6046b7b416c9c4328437380fd843..5c8b3bf4d8252f1013af6fea25848ce9c41dcfeb 100644 (file)
        .size \name , . - \name
        .endm
 
+       .macro check_uaccess, addr:req, size:req, limit:req, tmp:req, bad:req
+#ifndef CONFIG_CPU_USE_DOMAINS
+       adds    \tmp, \addr, #\size - 1
+       sbcccs  \tmp, \tmp, \limit
+       bcs     \bad
+#endif
+       .endm
+
 #endif /* __ASM_ASSEMBLER_H__ */
index 2ae842df455180d3bcd445d339ecd332d3b36c4e..5c44dcb0987bd31418298f7932baaa5a82320477 100644 (file)
@@ -202,6 +202,13 @@ static inline void dma_free_writecombine(struct device *dev, size_t size,
        return dma_free_attrs(dev, size, cpu_addr, dma_handle, &attrs);
 }
 
+/*
+ * This can be called during early boot to increase the size of the atomic
+ * coherent DMA pool above the default value of 256KiB. It must be called
+ * before postcore_initcall.
+ */
+extern void __init init_dma_coherent_pool_size(unsigned long size);
+
 /*
  * This can be called during boot to increase the size of the consistent
  * DMA region above it's default value of 2MB. It must be called before the
index e965f1b560f11e3a504814183c98f8f1b11bbf25..5f6ddcc56452998f40b1c16d7e20a0ff1ec010bd 100644 (file)
@@ -187,6 +187,7 @@ static inline unsigned long __phys_to_virt(unsigned long x)
 #define __phys_to_virt(x)      ((x) - PHYS_OFFSET + PAGE_OFFSET)
 #endif
 #endif
+#endif /* __ASSEMBLY__ */
 
 #ifndef PHYS_OFFSET
 #ifdef PLAT_PHYS_OFFSET
@@ -196,6 +197,8 @@ static inline unsigned long __phys_to_virt(unsigned long x)
 #endif
 #endif
 
+#ifndef __ASSEMBLY__
+
 /*
  * PFNs are used to describe any physical page; this means
  * PFN 0 == physical address 0.
index 314d4664eae7d9976a5fe656f74918cb8d15ab8b..99a19512ee26e2e5d99135d21f10d8b99e606226 100644 (file)
@@ -199,6 +199,9 @@ static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte,
 {
        pgtable_page_dtor(pte);
 
+#ifdef CONFIG_ARM_LPAE
+       tlb_add_flush(tlb, addr);
+#else
        /*
         * With the classic ARM MMU, a pte page has two corresponding pmd
         * entries, each covering 1MB.
@@ -206,6 +209,7 @@ static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte,
        addr &= PMD_MASK;
        tlb_add_flush(tlb, addr + SZ_1M - PAGE_SIZE);
        tlb_add_flush(tlb, addr + SZ_1M);
+#endif
 
        tlb_remove_page(tlb, pte);
 }
index 479a6352e0b5075911e91a4e0b60b7e9443fd4fd..77bd79f2ffdbd0344d096ca7fb2db809fb52d387 100644 (file)
@@ -101,28 +101,39 @@ extern int __get_user_1(void *);
 extern int __get_user_2(void *);
 extern int __get_user_4(void *);
 
-#define __get_user_x(__r2,__p,__e,__s,__i...)                          \
+#define __GUP_CLOBBER_1        "lr", "cc"
+#ifdef CONFIG_CPU_USE_DOMAINS
+#define __GUP_CLOBBER_2        "ip", "lr", "cc"
+#else
+#define __GUP_CLOBBER_2 "lr", "cc"
+#endif
+#define __GUP_CLOBBER_4        "lr", "cc"
+
+#define __get_user_x(__r2,__p,__e,__l,__s)                             \
           __asm__ __volatile__ (                                       \
                __asmeq("%0", "r0") __asmeq("%1", "r2")                 \
+               __asmeq("%3", "r1")                                     \
                "bl     __get_user_" #__s                               \
                : "=&r" (__e), "=r" (__r2)                              \
-               : "0" (__p)                                             \
-               : __i, "cc")
+               : "0" (__p), "r" (__l)                                  \
+               : __GUP_CLOBBER_##__s)
 
-#define get_user(x,p)                                                  \
+#define __get_user_check(x,p)                                                  \
        ({                                                              \
+               unsigned long __limit = current_thread_info()->addr_limit - 1; \
                register const typeof(*(p)) __user *__p asm("r0") = (p);\
                register unsigned long __r2 asm("r2");                  \
+               register unsigned long __l asm("r1") = __limit;         \
                register int __e asm("r0");                             \
                switch (sizeof(*(__p))) {                               \
                case 1:                                                 \
-                       __get_user_x(__r2, __p, __e, 1, "lr");          \
-                       break;                                          \
+                       __get_user_x(__r2, __p, __e, __l, 1);           \
+                       break;                                          \
                case 2:                                                 \
-                       __get_user_x(__r2, __p, __e, 2, "r3", "lr");    \
+                       __get_user_x(__r2, __p, __e, __l, 2);           \
                        break;                                          \
                case 4:                                                 \
-                       __get_user_x(__r2, __p, __e, 4, "lr");          \
+                       __get_user_x(__r2, __p, __e, __l, 4);           \
                        break;                                          \
                default: __e = __get_user_bad(); break;                 \
                }                                                       \
@@ -130,42 +141,57 @@ extern int __get_user_4(void *);
                __e;                                                    \
        })
 
+#define get_user(x,p)                                                  \
+       ({                                                              \
+               might_fault();                                          \
+               __get_user_check(x,p);                                  \
+        })
+
 extern int __put_user_1(void *, unsigned int);
 extern int __put_user_2(void *, unsigned int);
 extern int __put_user_4(void *, unsigned int);
 extern int __put_user_8(void *, unsigned long long);
 
-#define __put_user_x(__r2,__p,__e,__s)                                 \
+#define __put_user_x(__r2,__p,__e,__l,__s)                             \
           __asm__ __volatile__ (                                       \
                __asmeq("%0", "r0") __asmeq("%2", "r2")                 \
+               __asmeq("%3", "r1")                                     \
                "bl     __put_user_" #__s                               \
                : "=&r" (__e)                                           \
-               : "0" (__p), "r" (__r2)                                 \
+               : "0" (__p), "r" (__r2), "r" (__l)                      \
                : "ip", "lr", "cc")
 
-#define put_user(x,p)                                                  \
+#define __put_user_check(x,p)                                                  \
        ({                                                              \
+               unsigned long __limit = current_thread_info()->addr_limit - 1; \
                register const typeof(*(p)) __r2 asm("r2") = (x);       \
                register const typeof(*(p)) __user *__p asm("r0") = (p);\
+               register unsigned long __l asm("r1") = __limit;         \
                register int __e asm("r0");                             \
                switch (sizeof(*(__p))) {                               \
                case 1:                                                 \
-                       __put_user_x(__r2, __p, __e, 1);                \
+                       __put_user_x(__r2, __p, __e, __l, 1);           \
                        break;                                          \
                case 2:                                                 \
-                       __put_user_x(__r2, __p, __e, 2);                \
+                       __put_user_x(__r2, __p, __e, __l, 2);           \
                        break;                                          \
                case 4:                                                 \
-                       __put_user_x(__r2, __p, __e, 4);                \
+                       __put_user_x(__r2, __p, __e, __l, 4);           \
                        break;                                          \
                case 8:                                                 \
-                       __put_user_x(__r2, __p, __e, 8);                \
+                       __put_user_x(__r2, __p, __e, __l, 8);           \
                        break;                                          \
                default: __e = __put_user_bad(); break;                 \
                }                                                       \
                __e;                                                    \
        })
 
+#define put_user(x,p)                                                  \
+       ({                                                              \
+               might_fault();                                          \
+               __put_user_check(x,p);                                  \
+        })
+
 #else /* CONFIG_MMU */
 
 /*
@@ -219,6 +245,7 @@ do {                                                                        \
        unsigned long __gu_addr = (unsigned long)(ptr);                 \
        unsigned long __gu_val;                                         \
        __chk_user_ptr(ptr);                                            \
+       might_fault();                                                  \
        switch (sizeof(*(ptr))) {                                       \
        case 1: __get_user_asm_byte(__gu_val,__gu_addr,err);    break;  \
        case 2: __get_user_asm_half(__gu_val,__gu_addr,err);    break;  \
@@ -300,6 +327,7 @@ do {                                                                        \
        unsigned long __pu_addr = (unsigned long)(ptr);                 \
        __typeof__(*(ptr)) __pu_val = (x);                              \
        __chk_user_ptr(ptr);                                            \
+       might_fault();                                                  \
        switch (sizeof(*(ptr))) {                                       \
        case 1: __put_user_asm_byte(__pu_val,__pu_addr,err);    break;  \
        case 2: __put_user_asm_half(__pu_val,__pu_addr,err);    break;  \
index 0cab47d4a83ff97a23c7a9d2975cfb855a687e3e..2fde5fd1accedda5a00accac967e1985be9c7f08 100644 (file)
 #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.
  */
 #define __IGNORE_fadvise64_64
 #define __IGNORE_migrate_pages
+#define __IGNORE_kcmp
 
 #endif /* __KERNEL__ */
 #endif /* __ASM_ARM_UNISTD_H */
index 463ff4a0ec8acaa69372b8abd40a39260ee91736..e337879595e565e5666cbd8ac0c40a4a72908c0e 100644 (file)
 /* 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
index ba386bd94107642d9819a7d8bafb7ba04e92b83f..281bf3301241fba2a1ce1baafeaf3020b7cd57ff 100644 (file)
@@ -159,6 +159,12 @@ static int debug_arch_supported(void)
                arch >= ARM_DEBUG_ARCH_V7_1;
 }
 
+/* Can we determine the watchpoint access type from the fsr? */
+static int debug_exception_updates_fsr(void)
+{
+       return 0;
+}
+
 /* Determine number of WRP registers available. */
 static int get_num_wrp_resources(void)
 {
@@ -604,13 +610,14 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp)
                /* Aligned */
                break;
        case 1:
-               /* Allow single byte watchpoint. */
-               if (info->ctrl.len == ARM_BREAKPOINT_LEN_1)
-                       break;
        case 2:
                /* Allow halfword watchpoints and breakpoints. */
                if (info->ctrl.len == ARM_BREAKPOINT_LEN_2)
                        break;
+       case 3:
+               /* Allow single byte watchpoint. */
+               if (info->ctrl.len == ARM_BREAKPOINT_LEN_1)
+                       break;
        default:
                ret = -EINVAL;
                goto out;
@@ -619,18 +626,35 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp)
        info->address &= ~alignment_mask;
        info->ctrl.len <<= offset;
 
-       /*
-        * Currently we rely on an overflow handler to take
-        * care of single-stepping the breakpoint when it fires.
-        * In the case of userspace breakpoints on a core with V7 debug,
-        * we can use the mismatch feature as a poor-man's hardware
-        * single-step, but this only works for per-task breakpoints.
-        */
-       if (!bp->overflow_handler && (arch_check_bp_in_kernelspace(bp) ||
-           !core_has_mismatch_brps() || !bp->hw.bp_target)) {
-               pr_warning("overflow handler required but none found\n");
-               ret = -EINVAL;
+       if (!bp->overflow_handler) {
+               /*
+                * Mismatch breakpoints are required for single-stepping
+                * breakpoints.
+                */
+               if (!core_has_mismatch_brps())
+                       return -EINVAL;
+
+               /* We don't allow mismatch breakpoints in kernel space. */
+               if (arch_check_bp_in_kernelspace(bp))
+                       return -EPERM;
+
+               /*
+                * Per-cpu breakpoints are not supported by our stepping
+                * mechanism.
+                */
+               if (!bp->hw.bp_target)
+                       return -EINVAL;
+
+               /*
+                * We only support specific access types if the fsr
+                * reports them.
+                */
+               if (!debug_exception_updates_fsr() &&
+                   (info->ctrl.type == ARM_BREAKPOINT_LOAD ||
+                    info->ctrl.type == ARM_BREAKPOINT_STORE))
+                       return -EINVAL;
        }
+
 out:
        return ret;
 }
@@ -706,10 +730,12 @@ static void watchpoint_handler(unsigned long addr, unsigned int fsr,
                                goto unlock;
 
                        /* Check that the access type matches. */
-                       access = (fsr & ARM_FSR_ACCESS_MASK) ? HW_BREAKPOINT_W :
-                                HW_BREAKPOINT_R;
-                       if (!(access & hw_breakpoint_type(wp)))
-                               goto unlock;
+                       if (debug_exception_updates_fsr()) {
+                               access = (fsr & ARM_FSR_ACCESS_MASK) ?
+                                         HW_BREAKPOINT_W : HW_BREAKPOINT_R;
+                               if (!(access & hw_breakpoint_type(wp)))
+                                       goto unlock;
+                       }
 
                        /* We have a winner. */
                        info->trigger = addr;
index fef42b21cecba517e67e8ed74ef8c88d3cfd2afd..e1f906989bb8161963d8a714073a8d84a8e2c2e6 100644 (file)
@@ -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.
index f7945218b8c63a722cf08badc229345d7083b052..b0179b89a04ce26062184aaf23f86c521fb3009c 100644 (file)
@@ -420,20 +420,23 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
 #endif
                        instr = *(u32 *) pc;
        } else if (thumb_mode(regs)) {
-               get_user(instr, (u16 __user *)pc);
+               if (get_user(instr, (u16 __user *)pc))
+                       goto die_sig;
                if (is_wide_instruction(instr)) {
                        unsigned int instr2;
-                       get_user(instr2, (u16 __user *)pc+1);
+                       if (get_user(instr2, (u16 __user *)pc+1))
+                               goto die_sig;
                        instr <<= 16;
                        instr |= instr2;
                }
-       } else {
-               get_user(instr, (u32 __user *)pc);
+       } else if (get_user(instr, (u32 __user *)pc)) {
+               goto die_sig;
        }
 
        if (call_undef_hook(regs, instr) == 0)
                return;
 
+die_sig:
 #ifdef CONFIG_DEBUG_USER
        if (user_debug & UDBG_UNDEFINED) {
                printk(KERN_INFO "%s (%d): undefined instruction: pc=%p\n",
index d6dacc69254e47ddca3f399cc6f37eef12b073d8..395d5fbb8fa20c01c8b71d37dce42df700820c91 100644 (file)
@@ -59,6 +59,7 @@ void __init init_current_timer_delay(unsigned long freq)
 {
        pr_info("Switching to timer-based delay loop\n");
        lpj_fine                        = freq / HZ;
+       loops_per_jiffy                 = lpj_fine;
        arm_delay_ops.delay             = __timer_delay;
        arm_delay_ops.const_udelay      = __timer_const_udelay;
        arm_delay_ops.udelay            = __timer_udelay;
index 11093a7c3e32289e95a8c100cc01ef2bbb8d7101..9b06bb41fca659b9bbfc2f996e703ce2b8c315aa 100644 (file)
@@ -16,8 +16,9 @@
  * __get_user_X
  *
  * Inputs:     r0 contains the address
+ *             r1 contains the address limit, which must be preserved
  * Outputs:    r0 is the error code
- *             r2, r3 contains the zero-extended value
+ *             r2 contains the zero-extended value
  *             lr corrupted
  *
  * No other registers must be altered.  (see <asm/uaccess.h>
  * Note also that it is intended that __get_user_bad is not global.
  */
 #include <linux/linkage.h>
+#include <asm/assembler.h>
 #include <asm/errno.h>
 #include <asm/domain.h>
 
 ENTRY(__get_user_1)
+       check_uaccess r0, 1, r1, r2, __get_user_bad
 1: TUSER(ldrb) r2, [r0]
        mov     r0, #0
        mov     pc, lr
 ENDPROC(__get_user_1)
 
 ENTRY(__get_user_2)
-#ifdef CONFIG_THUMB2_KERNEL
-2: TUSER(ldrb) r2, [r0]
-3: TUSER(ldrb) r3, [r0, #1]
+       check_uaccess r0, 2, r1, r2, __get_user_bad
+#ifdef CONFIG_CPU_USE_DOMAINS
+rb     .req    ip
+2:     ldrbt   r2, [r0], #1
+3:     ldrbt   rb, [r0], #0
 #else
-2: TUSER(ldrb) r2, [r0], #1
-3: TUSER(ldrb) r3, [r0]
+rb     .req    r0
+2:     ldrb    r2, [r0]
+3:     ldrb    rb, [r0, #1]
 #endif
 #ifndef __ARMEB__
-       orr     r2, r2, r3, lsl #8
+       orr     r2, r2, rb, lsl #8
 #else
-       orr     r2, r3, r2, lsl #8
+       orr     r2, rb, r2, lsl #8
 #endif
        mov     r0, #0
        mov     pc, lr
 ENDPROC(__get_user_2)
 
 ENTRY(__get_user_4)
+       check_uaccess r0, 4, r1, r2, __get_user_bad
 4: TUSER(ldr)  r2, [r0]
        mov     r0, #0
        mov     pc, lr
index 7db25990c589f3d98554d9aee47cf7b5c3c486fd..3d73dcb959b0da83bc8affe3a781b7fcbdb17752 100644 (file)
@@ -16,6 +16,7 @@
  * __put_user_X
  *
  * Inputs:     r0 contains the address
+ *             r1 contains the address limit, which must be preserved
  *             r2, r3 contains the value
  * Outputs:    r0 is the error code
  *             lr corrupted
  * Note also that it is intended that __put_user_bad is not global.
  */
 #include <linux/linkage.h>
+#include <asm/assembler.h>
 #include <asm/errno.h>
 #include <asm/domain.h>
 
 ENTRY(__put_user_1)
+       check_uaccess r0, 1, r1, ip, __put_user_bad
 1: TUSER(strb) r2, [r0]
        mov     r0, #0
        mov     pc, lr
 ENDPROC(__put_user_1)
 
 ENTRY(__put_user_2)
+       check_uaccess r0, 2, r1, ip, __put_user_bad
        mov     ip, r2, lsr #8
 #ifdef CONFIG_THUMB2_KERNEL
 #ifndef __ARMEB__
@@ -60,12 +64,14 @@ ENTRY(__put_user_2)
 ENDPROC(__put_user_2)
 
 ENTRY(__put_user_4)
+       check_uaccess r0, 4, r1, ip, __put_user_bad
 4: TUSER(str)  r2, [r0]
        mov     r0, #0
        mov     pc, lr
 ENDPROC(__put_user_4)
 
 ENTRY(__put_user_8)
+       check_uaccess r0, 8, r1, ip, __put_user_bad
 #ifdef CONFIG_THUMB2_KERNEL
 5: TUSER(str)  r2, [r0]
 6: TUSER(str)  r3, [r0, #4]
index fdd8cc87c9feee388ca8a94b0fb46fa20305f33a..d20d4795f4eaebeb633c73ec441c36a661949a47 100644 (file)
@@ -222,10 +222,8 @@ int __init mx25_clocks_init(void)
        clk_register_clkdev(clk[lcdc_ipg], "ipg", "imx-fb.0");
        clk_register_clkdev(clk[lcdc_ahb], "ahb", "imx-fb.0");
        clk_register_clkdev(clk[wdt_ipg], NULL, "imx2-wdt.0");
-       clk_register_clkdev(clk[ssi1_ipg_per], "per", "imx-ssi.0");
-       clk_register_clkdev(clk[ssi1_ipg], "ipg", "imx-ssi.0");
-       clk_register_clkdev(clk[ssi2_ipg_per], "per", "imx-ssi.1");
-       clk_register_clkdev(clk[ssi2_ipg], "ipg", "imx-ssi.1");
+       clk_register_clkdev(clk[ssi1_ipg], NULL, "imx-ssi.0");
+       clk_register_clkdev(clk[ssi2_ipg], NULL, "imx-ssi.1");
        clk_register_clkdev(clk[esdhc1_ipg_per], "per", "sdhci-esdhc-imx25.0");
        clk_register_clkdev(clk[esdhc1_ipg], "ipg", "sdhci-esdhc-imx25.0");
        clk_register_clkdev(clk[esdhc1_ahb], "ahb", "sdhci-esdhc-imx25.0");
@@ -243,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;
 }
index c6422fb10bae37756693f3323f79df62e4fc932e..65fb8bcd86cb1652385ee0320679d04a427f8295 100644 (file)
@@ -230,10 +230,8 @@ int __init mx35_clocks_init()
        clk_register_clkdev(clk[ipu_gate], NULL, "mx3_sdc_fb");
        clk_register_clkdev(clk[owire_gate], NULL, "mxc_w1");
        clk_register_clkdev(clk[sdma_gate], NULL, "imx35-sdma");
-       clk_register_clkdev(clk[ipg], "ipg", "imx-ssi.0");
-       clk_register_clkdev(clk[ssi1_div_post], "per", "imx-ssi.0");
-       clk_register_clkdev(clk[ipg], "ipg", "imx-ssi.1");
-       clk_register_clkdev(clk[ssi2_div_post], "per", "imx-ssi.1");
+       clk_register_clkdev(clk[ssi1_gate], NULL, "imx-ssi.0");
+       clk_register_clkdev(clk[ssi2_gate], NULL, "imx-ssi.1");
        /* i.mx35 has the i.mx21 type uart */
        clk_register_clkdev(clk[uart1_gate], "per", "imx21-uart.0");
        clk_register_clkdev(clk[ipg], "ipg", "imx21-uart.0");
index 2c6ab3273f9e4d4a419e54a4f7cde417fdb213a6..5985ed1b8c9875cffc99ab74233147912ae01eca 100644 (file)
@@ -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 */
index 3226077735b1d7104627f8f40307e84c97d4ca5b..1201191d7f1bb24c386df88f5fe4de14e172b006 100644 (file)
@@ -517,6 +517,13 @@ void __init kirkwood_wdt_init(void)
 void __init kirkwood_init_early(void)
 {
        orion_time_set_base(TIMER_VIRT_BASE);
+
+       /*
+        * Some Kirkwood 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 kirkwood_tclk;
index fcd4e85c4ddcce66921a83b29e45669c50704918..346fd26f3aa62bcbe29757ddaa1c98fb9929c53b 100644 (file)
@@ -232,10 +232,11 @@ config MACH_OMAP3_PANDORA
        select OMAP_PACKAGE_CBB
        select REGULATOR_FIXED_VOLTAGE if REGULATOR
 
-config MACH_OMAP3_TOUCHBOOK
+config MACH_TOUCHBOOK
        bool "OMAP3 Touch Book"
        depends on ARCH_OMAP3
        default y
+       select OMAP_PACKAGE_CBB
 
 config MACH_OMAP_3430SDP
        bool "OMAP 3430 SDP board"
index f6a24b3f9c4f7b4dd3e381eb3ff7823444d99e70..34c2c7f59f0a855b2be4ddcd5f2ad2a8995995b1 100644 (file)
@@ -255,7 +255,7 @@ obj-$(CONFIG_MACH_OMAP_3630SDP)             += board-zoom-display.o
 obj-$(CONFIG_MACH_CM_T35)              += board-cm-t35.o
 obj-$(CONFIG_MACH_CM_T3517)            += board-cm-t3517.o
 obj-$(CONFIG_MACH_IGEP0020)            += board-igep0020.o
-obj-$(CONFIG_MACH_OMAP3_TOUCHBOOK)     += board-omap3touchbook.o
+obj-$(CONFIG_MACH_TOUCHBOOK)           += board-omap3touchbook.o
 obj-$(CONFIG_MACH_OMAP_4430SDP)                += board-4430sdp.o
 obj-$(CONFIG_MACH_OMAP4_PANDA)         += board-omap4panda.o
 
index 25bbcc7ca4dce9794676001167a23f36474fbd86..ae27de8899a69207ac90aca52164bb7ccf37a582 100644 (file)
@@ -1036,13 +1036,13 @@ static struct omap_clk am33xx_clks[] = {
        CLK(NULL,       "mmu_fck",              &mmu_fck,       CK_AM33XX),
        CLK(NULL,       "smartreflex0_fck",     &smartreflex0_fck,      CK_AM33XX),
        CLK(NULL,       "smartreflex1_fck",     &smartreflex1_fck,      CK_AM33XX),
-       CLK(NULL,       "gpt1_fck",             &timer1_fck,    CK_AM33XX),
-       CLK(NULL,       "gpt2_fck",             &timer2_fck,    CK_AM33XX),
-       CLK(NULL,       "gpt3_fck",             &timer3_fck,    CK_AM33XX),
-       CLK(NULL,       "gpt4_fck",             &timer4_fck,    CK_AM33XX),
-       CLK(NULL,       "gpt5_fck",             &timer5_fck,    CK_AM33XX),
-       CLK(NULL,       "gpt6_fck",             &timer6_fck,    CK_AM33XX),
-       CLK(NULL,       "gpt7_fck",             &timer7_fck,    CK_AM33XX),
+       CLK(NULL,       "timer1_fck",           &timer1_fck,    CK_AM33XX),
+       CLK(NULL,       "timer2_fck",           &timer2_fck,    CK_AM33XX),
+       CLK(NULL,       "timer3_fck",           &timer3_fck,    CK_AM33XX),
+       CLK(NULL,       "timer4_fck",           &timer4_fck,    CK_AM33XX),
+       CLK(NULL,       "timer5_fck",           &timer5_fck,    CK_AM33XX),
+       CLK(NULL,       "timer6_fck",           &timer6_fck,    CK_AM33XX),
+       CLK(NULL,       "timer7_fck",           &timer7_fck,    CK_AM33XX),
        CLK(NULL,       "usbotg_fck",           &usbotg_fck,    CK_AM33XX),
        CLK(NULL,       "ieee5000_fck",         &ieee5000_fck,  CK_AM33XX),
        CLK(NULL,       "wdt1_fck",             &wdt1_fck,      CK_AM33XX),
index a0d68dbecfa3bb96cd52226b0f8d7965379d1252..f99e65cfb86223c77ed544d1a8fbe6a0c4ad4b51 100644 (file)
@@ -241,6 +241,52 @@ static void omap3_clkdm_deny_idle(struct clockdomain *clkdm)
                _clkdm_del_autodeps(clkdm);
 }
 
+static int omap3xxx_clkdm_clk_enable(struct clockdomain *clkdm)
+{
+       bool hwsup = false;
+
+       if (!clkdm->clktrctrl_mask)
+               return 0;
+
+       hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+                               clkdm->clktrctrl_mask);
+
+       if (hwsup) {
+               /* Disable HW transitions when we are changing deps */
+               _disable_hwsup(clkdm);
+               _clkdm_add_autodeps(clkdm);
+               _enable_hwsup(clkdm);
+       } else {
+               if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
+                       omap3_clkdm_wakeup(clkdm);
+       }
+
+       return 0;
+}
+
+static int omap3xxx_clkdm_clk_disable(struct clockdomain *clkdm)
+{
+       bool hwsup = false;
+
+       if (!clkdm->clktrctrl_mask)
+               return 0;
+
+       hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+                               clkdm->clktrctrl_mask);
+
+       if (hwsup) {
+               /* Disable HW transitions when we are changing deps */
+               _disable_hwsup(clkdm);
+               _clkdm_del_autodeps(clkdm);
+               _enable_hwsup(clkdm);
+       } else {
+               if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP)
+                       omap3_clkdm_sleep(clkdm);
+       }
+
+       return 0;
+}
+
 struct clkdm_ops omap2_clkdm_operations = {
        .clkdm_add_wkdep        = omap2_clkdm_add_wkdep,
        .clkdm_del_wkdep        = omap2_clkdm_del_wkdep,
@@ -267,6 +313,6 @@ struct clkdm_ops omap3_clkdm_operations = {
        .clkdm_wakeup           = omap3_clkdm_wakeup,
        .clkdm_allow_idle       = omap3_clkdm_allow_idle,
        .clkdm_deny_idle        = omap3_clkdm_deny_idle,
-       .clkdm_clk_enable       = omap2_clkdm_clk_enable,
-       .clkdm_clk_disable      = omap2_clkdm_clk_disable,
+       .clkdm_clk_enable       = omap3xxx_clkdm_clk_enable,
+       .clkdm_clk_disable      = omap3xxx_clkdm_clk_disable,
 };
index 766338fe4d347746ee04eb3961452a7b3f8f6aa9..975f6bda0e0b7a84855a2e6c90f8051df747f6a2 100644 (file)
@@ -67,6 +67,7 @@
 #define OMAP3430_EN_IVA2_DPLL_MASK                     (0x7 << 0)
 
 /* CM_IDLEST_IVA2 */
+#define OMAP3430_ST_IVA2_SHIFT                         0
 #define OMAP3430_ST_IVA2_MASK                          (1 << 0)
 
 /* CM_IDLEST_PLL_IVA2 */
index 05fdebfaa195b0e5fc87e33217f24ce1b5c09822..330d4c6e746b703819f95ba41d733a88523b555a 100644 (file)
@@ -46,7 +46,7 @@
 static void __iomem *wakeupgen_base;
 static void __iomem *sar_base;
 static DEFINE_SPINLOCK(wakeupgen_lock);
-static unsigned int irq_target_cpu[NR_IRQS];
+static unsigned int irq_target_cpu[MAX_IRQS];
 static unsigned int irq_banks = MAX_NR_REG_BANKS;
 static unsigned int max_irqs = MAX_IRQS;
 static unsigned int omap_secure_apis;
index 6ca8e519968d0c4e82e94fb384ab84da90a892b1..37afbd173c2c27969e81f37917d70a767e8fbc2d 100644 (file)
@@ -1889,6 +1889,7 @@ static int _enable(struct omap_hwmod *oh)
                        _enable_sysc(oh);
                }
        } else {
+               _omap4_disable_module(oh);
                _disable_clocks(oh);
                pr_debug("omap_hwmod: %s: _wait_target_ready: %d\n",
                         oh->name, r);
index c9e38200216b2985cb3ef997e530891b8e3b19dd..ce7e6068768f3cebbb4bb8e32ea94e4ae6aca3a3 100644 (file)
@@ -100,9 +100,9 @@ static struct omap_hwmod omap3xxx_mpu_hwmod = {
 
 /* IVA2 (IVA2) */
 static struct omap_hwmod_rst_info omap3xxx_iva_resets[] = {
-       { .name = "logic", .rst_shift = 0 },
-       { .name = "seq0", .rst_shift = 1 },
-       { .name = "seq1", .rst_shift = 2 },
+       { .name = "logic", .rst_shift = 0, .st_shift = 8 },
+       { .name = "seq0", .rst_shift = 1, .st_shift = 9 },
+       { .name = "seq1", .rst_shift = 2, .st_shift = 10 },
 };
 
 static struct omap_hwmod omap3xxx_iva_hwmod = {
@@ -112,6 +112,15 @@ static struct omap_hwmod omap3xxx_iva_hwmod = {
        .rst_lines      = omap3xxx_iva_resets,
        .rst_lines_cnt  = ARRAY_SIZE(omap3xxx_iva_resets),
        .main_clk       = "iva2_ck",
+       .prcm = {
+               .omap2 = {
+                       .module_offs = OMAP3430_IVA2_MOD,
+                       .prcm_reg_id = 1,
+                       .module_bit = OMAP3430_CM_FCLKEN_IVA2_EN_IVA2_SHIFT,
+                       .idlest_reg_id = 1,
+                       .idlest_idle_bit = OMAP3430_ST_IVA2_SHIFT,
+               }
+       },
 };
 
 /* timer class */
index 242aee498ceb21466e33ee04035ed63147e4a615..afb60917a948b64bb3b0ed9b90924facc27fc7f6 100644 (file)
@@ -4210,7 +4210,7 @@ static struct omap_hwmod_ocp_if omap44xx_dsp__iva = {
 };
 
 /* dsp -> sl2if */
-static struct omap_hwmod_ocp_if omap44xx_dsp__sl2if = {
+static struct omap_hwmod_ocp_if __maybe_unused omap44xx_dsp__sl2if = {
        .master         = &omap44xx_dsp_hwmod,
        .slave          = &omap44xx_sl2if_hwmod,
        .clk            = "dpll_iva_m5x2_ck",
@@ -4828,7 +4828,7 @@ static struct omap_hwmod_ocp_if omap44xx_l3_main_2__iss = {
 };
 
 /* iva -> sl2if */
-static struct omap_hwmod_ocp_if omap44xx_iva__sl2if = {
+static struct omap_hwmod_ocp_if __maybe_unused omap44xx_iva__sl2if = {
        .master         = &omap44xx_iva_hwmod,
        .slave          = &omap44xx_sl2if_hwmod,
        .clk            = "dpll_iva_m5x2_ck",
@@ -5362,7 +5362,7 @@ static struct omap_hwmod_ocp_if omap44xx_l4_wkup__scrm = {
 };
 
 /* l3_main_2 -> sl2if */
-static struct omap_hwmod_ocp_if omap44xx_l3_main_2__sl2if = {
+static struct omap_hwmod_ocp_if __maybe_unused omap44xx_l3_main_2__sl2if = {
        .master         = &omap44xx_l3_main_2_hwmod,
        .slave          = &omap44xx_sl2if_hwmod,
        .clk            = "l3_div_ck",
@@ -6032,7 +6032,7 @@ static struct omap_hwmod_ocp_if *omap44xx_hwmod_ocp_ifs[] __initdata = {
        &omap44xx_l4_abe__dmic,
        &omap44xx_l4_abe__dmic_dma,
        &omap44xx_dsp__iva,
-       &omap44xx_dsp__sl2if,
+       /* &omap44xx_dsp__sl2if, */
        &omap44xx_l4_cfg__dsp,
        &omap44xx_l3_main_2__dss,
        &omap44xx_l4_per__dss,
@@ -6068,7 +6068,7 @@ static struct omap_hwmod_ocp_if *omap44xx_hwmod_ocp_ifs[] __initdata = {
        &omap44xx_l4_per__i2c4,
        &omap44xx_l3_main_2__ipu,
        &omap44xx_l3_main_2__iss,
-       &omap44xx_iva__sl2if,
+       /* &omap44xx_iva__sl2if, */
        &omap44xx_l3_main_2__iva,
        &omap44xx_l4_wkup__kbd,
        &omap44xx_l4_cfg__mailbox,
@@ -6099,7 +6099,7 @@ static struct omap_hwmod_ocp_if *omap44xx_hwmod_ocp_ifs[] __initdata = {
        &omap44xx_l4_cfg__cm_core,
        &omap44xx_l4_wkup__prm,
        &omap44xx_l4_wkup__scrm,
-       &omap44xx_l3_main_2__sl2if,
+       /* &omap44xx_l3_main_2__sl2if, */
        &omap44xx_l4_abe__slimbus1,
        &omap44xx_l4_abe__slimbus1_dma,
        &omap44xx_l4_per__slimbus2,
index 2ff6d41ec6c6c004ace041b525ec1821d6389653..2ba4f57dda866df44689834370916395ab9a4c3c 100644 (file)
@@ -260,6 +260,7 @@ static u32 notrace dmtimer_read_sched_clock(void)
        return 0;
 }
 
+#ifdef CONFIG_OMAP_32K_TIMER
 /* Setup free-running counter for clocksource */
 static int __init omap2_sync32k_clocksource_init(void)
 {
@@ -299,6 +300,12 @@ static int __init omap2_sync32k_clocksource_init(void)
 
        return ret;
 }
+#else
+static inline int omap2_sync32k_clocksource_init(void)
+{
+       return -ENODEV;
+}
+#endif
 
 static void __init omap2_gptimer_clocksource_init(int gptimer_id,
                                                const char *fck_source)
index 53b7ea92c32c119bcfc6d44a96b92fac915363da..3b8a0171c3cb3e30aa7242afcdc65f13cd5c11de 100644 (file)
@@ -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,
        },
 };
index 119bc52ab93ed7675d4528a779e97270d308c70e..4e07eec1270dd3b3fa51860fbc735a5d1fb9e18b 100644 (file)
@@ -63,10 +63,11 @@ static int contextidr_notifier(struct notifier_block *unused, unsigned long cmd,
        pid = task_pid_nr(thread->task) << ASID_BITS;
        asm volatile(
        "       mrc     p15, 0, %0, c13, c0, 1\n"
-       "       bfi     %1, %0, #0, %2\n"
-       "       mcr     p15, 0, %1, c13, c0, 1\n"
+       "       and     %0, %0, %2\n"
+       "       orr     %0, %0, %1\n"
+       "       mcr     p15, 0, %0, c13, c0, 1\n"
        : "=r" (contextidr), "+r" (pid)
-       : "I" (ASID_BITS));
+       : "I" (~ASID_MASK));
        isb();
 
        return NOTIFY_OK;
index 4e7d1182e8a3a59270073b5cb3b348e0bd690ef8..e59c4ab71bcb78282f968cebbda09c43b49809ff 100644 (file)
@@ -267,17 +267,19 @@ static void __dma_free_remap(void *cpu_addr, size_t size)
        vunmap(cpu_addr);
 }
 
+#define DEFAULT_DMA_COHERENT_POOL_SIZE SZ_256K
+
 struct dma_pool {
        size_t size;
        spinlock_t lock;
        unsigned long *bitmap;
        unsigned long nr_pages;
        void *vaddr;
-       struct page *page;
+       struct page **pages;
 };
 
 static struct dma_pool atomic_pool = {
-       .size = SZ_256K,
+       .size = DEFAULT_DMA_COHERENT_POOL_SIZE,
 };
 
 static int __init early_coherent_pool(char *p)
@@ -287,6 +289,21 @@ static int __init early_coherent_pool(char *p)
 }
 early_param("coherent_pool", early_coherent_pool);
 
+void __init init_dma_coherent_pool_size(unsigned long size)
+{
+       /*
+        * Catch any attempt to set the pool size too late.
+        */
+       BUG_ON(atomic_pool.vaddr);
+
+       /*
+        * Set architecture specific coherent pool size only if
+        * it has not been changed by kernel command line parameter.
+        */
+       if (atomic_pool.size == DEFAULT_DMA_COHERENT_POOL_SIZE)
+               atomic_pool.size = size;
+}
+
 /*
  * Initialise the coherent pool for atomic allocations.
  */
@@ -297,6 +314,7 @@ static int __init atomic_pool_init(void)
        unsigned long nr_pages = pool->size >> PAGE_SHIFT;
        unsigned long *bitmap;
        struct page *page;
+       struct page **pages;
        void *ptr;
        int bitmap_size = BITS_TO_LONGS(nr_pages) * sizeof(long);
 
@@ -304,21 +322,31 @@ static int __init atomic_pool_init(void)
        if (!bitmap)
                goto no_bitmap;
 
+       pages = kzalloc(nr_pages * sizeof(struct page *), GFP_KERNEL);
+       if (!pages)
+               goto no_pages;
+
        if (IS_ENABLED(CONFIG_CMA))
                ptr = __alloc_from_contiguous(NULL, pool->size, prot, &page);
        else
                ptr = __alloc_remap_buffer(NULL, pool->size, GFP_KERNEL, prot,
                                           &page, NULL);
        if (ptr) {
+               int i;
+
+               for (i = 0; i < nr_pages; i++)
+                       pages[i] = page + i;
+
                spin_lock_init(&pool->lock);
                pool->vaddr = ptr;
-               pool->page = page;
+               pool->pages = pages;
                pool->bitmap = bitmap;
                pool->nr_pages = nr_pages;
                pr_info("DMA: preallocated %u KiB pool for atomic coherent allocations\n",
                       (unsigned)pool->size / 1024);
                return 0;
        }
+no_pages:
        kfree(bitmap);
 no_bitmap:
        pr_err("DMA: failed to allocate %u KiB pool for atomic coherent allocation\n",
@@ -443,27 +471,45 @@ static void *__alloc_from_pool(size_t size, struct page **ret_page)
        if (pageno < pool->nr_pages) {
                bitmap_set(pool->bitmap, pageno, count);
                ptr = pool->vaddr + PAGE_SIZE * pageno;
-               *ret_page = pool->page + pageno;
+               *ret_page = pool->pages[pageno];
+       } else {
+               pr_err_once("ERROR: %u KiB atomic DMA coherent pool is too small!\n"
+                           "Please increase it with coherent_pool= kernel parameter!\n",
+                           (unsigned)pool->size / 1024);
        }
        spin_unlock_irqrestore(&pool->lock, flags);
 
        return ptr;
 }
 
+static bool __in_atomic_pool(void *start, size_t size)
+{
+       struct dma_pool *pool = &atomic_pool;
+       void *end = start + size;
+       void *pool_start = pool->vaddr;
+       void *pool_end = pool->vaddr + pool->size;
+
+       if (start < pool_start || start >= pool_end)
+               return false;
+
+       if (end <= pool_end)
+               return true;
+
+       WARN(1, "Wrong coherent size(%p-%p) from atomic pool(%p-%p)\n",
+            start, end - 1, pool_start, pool_end - 1);
+
+       return false;
+}
+
 static int __free_from_pool(void *start, size_t size)
 {
        struct dma_pool *pool = &atomic_pool;
        unsigned long pageno, count;
        unsigned long flags;
 
-       if (start < pool->vaddr || start > pool->vaddr + pool->size)
+       if (!__in_atomic_pool(start, size))
                return 0;
 
-       if (start + size > pool->vaddr + pool->size) {
-               WARN(1, "freeing wrong coherent size from pool\n");
-               return 0;
-       }
-
        pageno = (start - pool->vaddr) >> PAGE_SHIFT;
        count = size >> PAGE_SHIFT;
 
@@ -1090,10 +1136,22 @@ static int __iommu_remove_mapping(struct device *dev, dma_addr_t iova, size_t si
        return 0;
 }
 
+static struct page **__atomic_get_pages(void *addr)
+{
+       struct dma_pool *pool = &atomic_pool;
+       struct page **pages = pool->pages;
+       int offs = (addr - pool->vaddr) >> PAGE_SHIFT;
+
+       return pages + offs;
+}
+
 static struct page **__iommu_get_pages(void *cpu_addr, struct dma_attrs *attrs)
 {
        struct vm_struct *area;
 
+       if (__in_atomic_pool(cpu_addr, PAGE_SIZE))
+               return __atomic_get_pages(cpu_addr);
+
        if (dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING, attrs))
                return cpu_addr;
 
@@ -1103,6 +1161,34 @@ static struct page **__iommu_get_pages(void *cpu_addr, struct dma_attrs *attrs)
        return NULL;
 }
 
+static void *__iommu_alloc_atomic(struct device *dev, size_t size,
+                                 dma_addr_t *handle)
+{
+       struct page *page;
+       void *addr;
+
+       addr = __alloc_from_pool(size, &page);
+       if (!addr)
+               return NULL;
+
+       *handle = __iommu_create_mapping(dev, &page, size);
+       if (*handle == DMA_ERROR_CODE)
+               goto err_mapping;
+
+       return addr;
+
+err_mapping:
+       __free_from_pool(addr, size);
+       return NULL;
+}
+
+static void __iommu_free_atomic(struct device *dev, struct page **pages,
+                               dma_addr_t handle, size_t size)
+{
+       __iommu_remove_mapping(dev, handle, size);
+       __free_from_pool(page_address(pages[0]), size);
+}
+
 static void *arm_iommu_alloc_attrs(struct device *dev, size_t size,
            dma_addr_t *handle, gfp_t gfp, struct dma_attrs *attrs)
 {
@@ -1113,6 +1199,9 @@ static void *arm_iommu_alloc_attrs(struct device *dev, size_t size,
        *handle = DMA_ERROR_CODE;
        size = PAGE_ALIGN(size);
 
+       if (gfp & GFP_ATOMIC)
+               return __iommu_alloc_atomic(dev, size, handle);
+
        pages = __iommu_alloc_buffer(dev, size, gfp);
        if (!pages)
                return NULL;
@@ -1179,6 +1268,11 @@ void arm_iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr,
                return;
        }
 
+       if (__in_atomic_pool(cpu_addr, size)) {
+               __iommu_free_atomic(dev, pages, handle, size);
+               return;
+       }
+
        if (!dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING, attrs)) {
                unmap_kernel_range((unsigned long)cpu_addr, size);
                vunmap(cpu_addr);
index 6776160618ef0ede79d07b4f6a0873c30df2a1d0..a8ee92da3544926138f68116fbddbc2c55b64dbf 100644 (file)
@@ -55,6 +55,9 @@ extern void __flush_dcache_page(struct address_space *mapping, struct page *page
 /* permanent static mappings from iotable_init() */
 #define VM_ARM_STATIC_MAPPING  0x40000000
 
+/* empty mapping */
+#define VM_ARM_EMPTY_MAPPING   0x20000000
+
 /* mapping type (attributes) for permanent static mappings */
 #define VM_ARM_MTYPE(mt)               ((mt) << 20)
 #define VM_ARM_MTYPE_MASK      (0x1f << 20)
index 4c2d0451e84af1c2a0347a6fe462dd2e3306db3e..c2fa21d0103e0348f2b1f48c886aa11d63809dad 100644 (file)
@@ -807,7 +807,7 @@ static void __init pmd_empty_section_gap(unsigned long addr)
        vm = early_alloc_aligned(sizeof(*vm), __alignof__(*vm));
        vm->addr = (void *)addr;
        vm->size = SECTION_SIZE;
-       vm->flags = VM_IOREMAP | VM_ARM_STATIC_MAPPING;
+       vm->flags = VM_IOREMAP | VM_ARM_EMPTY_MAPPING;
        vm->caller = pmd_empty_section_gap;
        vm_area_add_early(vm);
 }
@@ -820,7 +820,7 @@ static void __init fill_pmd_gaps(void)
 
        /* we're still single threaded hence no lock needed here */
        for (vm = vmlist; vm; vm = vm->next) {
-               if (!(vm->flags & VM_ARM_STATIC_MAPPING))
+               if (!(vm->flags & (VM_ARM_STATIC_MAPPING | VM_ARM_EMPTY_MAPPING)))
                        continue;
                addr = (unsigned long)vm->addr;
                if (addr < next)
@@ -961,8 +961,8 @@ void __init sanity_check_meminfo(void)
                 * Check whether this memory bank would partially overlap
                 * the vmalloc area.
                 */
-               if (__va(bank->start + bank->size) > vmalloc_min ||
-                   __va(bank->start + bank->size) < __va(bank->start)) {
+               if (__va(bank->start + bank->size - 1) >= vmalloc_min ||
+                   __va(bank->start + bank->size - 1) <= __va(bank->start)) {
                        unsigned long newsize = vmalloc_min - __va(bank->start);
                        printk(KERN_NOTICE "Truncating RAM at %.8llx-%.8llx "
                               "to -%.8llx (vmalloc region overlap).\n",
index 627d94f1b010d32d09091bf4f025fabb617bde03..ec466400a2002943de0ccaf840f25266db6149e0 100644 (file)
@@ -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
index 766181cb5c95c277b8495966835571059a36dda5..024f3b08db29b0046a58457120259e7b5366a1ca 100644 (file)
@@ -68,6 +68,7 @@
 
 static unsigned long omap_sram_start;
 static void __iomem *omap_sram_base;
+static unsigned long omap_sram_skip;
 static unsigned long omap_sram_size;
 static void __iomem *omap_sram_ceil;
 
@@ -106,6 +107,7 @@ static int is_sram_locked(void)
  */
 static void __init omap_detect_sram(void)
 {
+       omap_sram_skip = SRAM_BOOTLOADER_SZ;
        if (cpu_class_is_omap2()) {
                if (is_sram_locked()) {
                        if (cpu_is_omap34xx()) {
@@ -113,6 +115,7 @@ static void __init omap_detect_sram(void)
                                if ((omap_type() == OMAP2_DEVICE_TYPE_EMU) ||
                                    (omap_type() == OMAP2_DEVICE_TYPE_SEC)) {
                                        omap_sram_size = 0x7000; /* 28K */
+                                       omap_sram_skip += SZ_16K;
                                } else {
                                        omap_sram_size = 0x8000; /* 32K */
                                }
@@ -175,8 +178,10 @@ static void __init omap_map_sram(void)
                return;
 
 #ifdef CONFIG_OMAP4_ERRATA_I688
+       if (cpu_is_omap44xx()) {
                omap_sram_start += PAGE_SIZE;
                omap_sram_size -= SZ_16K;
+       }
 #endif
        if (cpu_is_omap34xx()) {
                /*
@@ -203,8 +208,8 @@ static void __init omap_map_sram(void)
         * Looks like we need to preserve some bootloader code at the
         * beginning of SRAM for jumping to flash for reboot to work...
         */
-       memset_io(omap_sram_base + SRAM_BOOTLOADER_SZ, 0,
-                 omap_sram_size - SRAM_BOOTLOADER_SZ);
+       memset_io(omap_sram_base + omap_sram_skip, 0,
+                 omap_sram_size - omap_sram_skip);
 }
 
 /*
@@ -218,7 +223,7 @@ void *omap_sram_push_address(unsigned long size)
 {
        unsigned long available, new_ceil = (unsigned long)omap_sram_ceil;
 
-       available = omap_sram_ceil - (omap_sram_base + SRAM_BOOTLOADER_SZ);
+       available = omap_sram_ceil - (omap_sram_base + omap_sram_skip);
 
        if (size > available) {
                pr_err("Not enough space in SRAM\n");
index 65c5eca475e76ef839a16aaef568173a2dc0ee1c..d1116e2dfbeaf57ccd0c2a1aff9ce413d9b57f2a 100644 (file)
@@ -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;
 }
index f34861920634d15c9de2b1149aa8562a767e64f1..c7092e6057c56e4fa856362263ed4ac49a95d32e 100644 (file)
@@ -38,6 +38,7 @@ config BLACKFIN
        select GENERIC_ATOMIC64
        select GENERIC_IRQ_PROBE
        select IRQ_PER_CPU if SMP
+       select USE_GENERIC_SMP_HELPERS if SMP
        select HAVE_NMI_WATCHDOG if NMI_WATCHDOG
        select GENERIC_SMP_IDLE_THREAD
        select ARCH_USES_GETTIMEOFFSET if !GENERIC_CLOCKEVENTS
index d3d7e64ca96dacfa41bc298733ef3ed2076c7d3e..66cf00095b8487210b3187cbf41072bc3d80406b 100644 (file)
@@ -20,7 +20,6 @@ endif
 KBUILD_AFLAGS           += $(call cc-option,-mno-fdpic)
 KBUILD_CFLAGS_MODULE    += -mlong-calls
 LDFLAGS                 += -m elf32bfin
-KALLSYMS         += --symbol-prefix=_
 
 KBUILD_DEFCONFIG := BF537-STAMP_defconfig
 
index dc3d144b4bb5930a396f73d9bce48f67ca1c6365..9631598dcc5d120321febba77a85b6309bbdea7b 100644 (file)
@@ -18,6 +18,8 @@
 #define raw_smp_processor_id()  blackfin_core_id()
 
 extern void bfin_relocate_coreb_l1_mem(void);
+extern void arch_send_call_function_single_ipi(int cpu);
+extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
 
 #if defined(CONFIG_SMP) && defined(CONFIG_ICACHE_FLUSH_L1)
 asmlinkage void blackfin_icache_flush_range_l1(unsigned long *ptr);
index 00bbe672b3b308433445d39461637f3a0d396573..a40151306b77ff301b9b152b205795a6fece4b9c 100644 (file)
@@ -48,10 +48,13 @@ unsigned long blackfin_iflush_l1_entry[NR_CPUS];
 
 struct blackfin_initial_pda __cpuinitdata initial_pda_coreb;
 
-#define BFIN_IPI_TIMER       0
-#define BFIN_IPI_RESCHEDULE   1
-#define BFIN_IPI_CALL_FUNC    2
-#define BFIN_IPI_CPU_STOP     3
+enum ipi_message_type {
+       BFIN_IPI_TIMER,
+       BFIN_IPI_RESCHEDULE,
+       BFIN_IPI_CALL_FUNC,
+       BFIN_IPI_CALL_FUNC_SINGLE,
+       BFIN_IPI_CPU_STOP,
+};
 
 struct blackfin_flush_data {
        unsigned long start;
@@ -60,35 +63,20 @@ struct blackfin_flush_data {
 
 void *secondary_stack;
 
-
-struct smp_call_struct {
-       void (*func)(void *info);
-       void *info;
-       int wait;
-       cpumask_t *waitmask;
-};
-
 static struct blackfin_flush_data smp_flush_data;
 
 static DEFINE_SPINLOCK(stop_lock);
 
-struct ipi_message {
-       unsigned long type;
-       struct smp_call_struct call_struct;
-};
-
 /* A magic number - stress test shows this is safe for common cases */
 #define BFIN_IPI_MSGQ_LEN 5
 
 /* Simple FIFO buffer, overflow leads to panic */
-struct ipi_message_queue {
-       spinlock_t lock;
+struct ipi_data {
        unsigned long count;
-       unsigned long head; /* head of the queue */
-       struct ipi_message ipi_message[BFIN_IPI_MSGQ_LEN];
+       unsigned long bits;
 };
 
-static DEFINE_PER_CPU(struct ipi_message_queue, ipi_msg_queue);
+static DEFINE_PER_CPU(struct ipi_data, bfin_ipi);
 
 static void ipi_cpu_stop(unsigned int cpu)
 {
@@ -129,28 +117,6 @@ static void ipi_flush_icache(void *info)
        blackfin_icache_flush_range(fdata->start, fdata->end);
 }
 
-static void ipi_call_function(unsigned int cpu, struct ipi_message *msg)
-{
-       int wait;
-       void (*func)(void *info);
-       void *info;
-       func = msg->call_struct.func;
-       info = msg->call_struct.info;
-       wait = msg->call_struct.wait;
-       func(info);
-       if (wait) {
-#ifdef __ARCH_SYNC_CORE_DCACHE
-               /*
-                * 'wait' usually means synchronization between CPUs.
-                * Invalidate D cache in case shared data was changed
-                * by func() to ensure cache coherence.
-                */
-               resync_core_dcache();
-#endif
-               cpumask_clear_cpu(cpu, msg->call_struct.waitmask);
-       }
-}
-
 /* Use IRQ_SUPPLE_0 to request reschedule.
  * When returning from interrupt to user space,
  * there is chance to reschedule */
@@ -172,152 +138,95 @@ void ipi_timer(void)
 
 static irqreturn_t ipi_handler_int1(int irq, void *dev_instance)
 {
-       struct ipi_message *msg;
-       struct ipi_message_queue *msg_queue;
+       struct ipi_data *bfin_ipi_data;
        unsigned int cpu = smp_processor_id();
-       unsigned long flags;
+       unsigned long pending;
+       unsigned long msg;
 
        platform_clear_ipi(cpu, IRQ_SUPPLE_1);
 
-       msg_queue = &__get_cpu_var(ipi_msg_queue);
-
-       spin_lock_irqsave(&msg_queue->lock, flags);
-
-       while (msg_queue->count) {
-               msg = &msg_queue->ipi_message[msg_queue->head];
-               switch (msg->type) {
-               case BFIN_IPI_TIMER:
-                       ipi_timer();
-                       break;
-               case BFIN_IPI_RESCHEDULE:
-                       scheduler_ipi();
-                       break;
-               case BFIN_IPI_CALL_FUNC:
-                       ipi_call_function(cpu, msg);
-                       break;
-               case BFIN_IPI_CPU_STOP:
-                       ipi_cpu_stop(cpu);
-                       break;
-               default:
-                       printk(KERN_CRIT "CPU%u: Unknown IPI message 0x%lx\n",
-                              cpu, msg->type);
-                       break;
-               }
-               msg_queue->head++;
-               msg_queue->head %= BFIN_IPI_MSGQ_LEN;
-               msg_queue->count--;
+       bfin_ipi_data = &__get_cpu_var(bfin_ipi);
+
+       while ((pending = xchg(&bfin_ipi_data->bits, 0)) != 0) {
+               msg = 0;
+               do {
+                       msg = find_next_bit(&pending, BITS_PER_LONG, msg + 1);
+                       switch (msg) {
+                       case BFIN_IPI_TIMER:
+                               ipi_timer();
+                               break;
+                       case BFIN_IPI_RESCHEDULE:
+                               scheduler_ipi();
+                               break;
+                       case BFIN_IPI_CALL_FUNC:
+                               generic_smp_call_function_interrupt();
+                               break;
+
+                       case BFIN_IPI_CALL_FUNC_SINGLE:
+                               generic_smp_call_function_single_interrupt();
+                               break;
+
+                       case BFIN_IPI_CPU_STOP:
+                               ipi_cpu_stop(cpu);
+                               break;
+                       }
+               } while (msg < BITS_PER_LONG);
+
+               smp_mb();
        }
-       spin_unlock_irqrestore(&msg_queue->lock, flags);
        return IRQ_HANDLED;
 }
 
-static void ipi_queue_init(void)
+static void bfin_ipi_init(void)
 {
        unsigned int cpu;
-       struct ipi_message_queue *msg_queue;
+       struct ipi_data *bfin_ipi_data;
        for_each_possible_cpu(cpu) {
-               msg_queue = &per_cpu(ipi_msg_queue, cpu);
-               spin_lock_init(&msg_queue->lock);
-               msg_queue->count = 0;
-               msg_queue->head = 0;
+               bfin_ipi_data = &per_cpu(bfin_ipi, cpu);
+               bfin_ipi_data->bits = 0;
+               bfin_ipi_data->count = 0;
        }
 }
 
-static inline void smp_send_message(cpumask_t callmap, unsigned long type,
-                                       void (*func) (void *info), void *info, int wait)
+void send_ipi(const struct cpumask *cpumask, enum ipi_message_type msg)
 {
        unsigned int cpu;
-       struct ipi_message_queue *msg_queue;
-       struct ipi_message *msg;
-       unsigned long flags, next_msg;
-       cpumask_t waitmask; /* waitmask is shared by all cpus */
-
-       cpumask_copy(&waitmask, &callmap);
-       for_each_cpu(cpu, &callmap) {
-               msg_queue = &per_cpu(ipi_msg_queue, cpu);
-               spin_lock_irqsave(&msg_queue->lock, flags);
-               if (msg_queue->count < BFIN_IPI_MSGQ_LEN) {
-                       next_msg = (msg_queue->head + msg_queue->count)
-                                       % BFIN_IPI_MSGQ_LEN;
-                       msg = &msg_queue->ipi_message[next_msg];
-                       msg->type = type;
-                       if (type == BFIN_IPI_CALL_FUNC) {
-                               msg->call_struct.func = func;
-                               msg->call_struct.info = info;
-                               msg->call_struct.wait = wait;
-                               msg->call_struct.waitmask = &waitmask;
-                       }
-                       msg_queue->count++;
-               } else
-                       panic("IPI message queue overflow\n");
-               spin_unlock_irqrestore(&msg_queue->lock, flags);
+       struct ipi_data *bfin_ipi_data;
+       unsigned long flags;
+
+       local_irq_save(flags);
+
+       for_each_cpu(cpu, cpumask) {
+               bfin_ipi_data = &per_cpu(bfin_ipi, cpu);
+               smp_mb();
+               set_bit(msg, &bfin_ipi_data->bits);
+               bfin_ipi_data->count++;
                platform_send_ipi_cpu(cpu, IRQ_SUPPLE_1);
        }
 
-       if (wait) {
-               while (!cpumask_empty(&waitmask))
-                       blackfin_dcache_invalidate_range(
-                               (unsigned long)(&waitmask),
-                               (unsigned long)(&waitmask));
-#ifdef __ARCH_SYNC_CORE_DCACHE
-               /*
-                * Invalidate D cache in case shared data was changed by
-                * other processors to ensure cache coherence.
-                */
-               resync_core_dcache();
-#endif
-       }
+       local_irq_restore(flags);
 }
 
-int smp_call_function(void (*func)(void *info), void *info, int wait)
+void arch_send_call_function_single_ipi(int cpu)
 {
-       cpumask_t callmap;
-
-       preempt_disable();
-       cpumask_copy(&callmap, cpu_online_mask);
-       cpumask_clear_cpu(smp_processor_id(), &callmap);
-       if (!cpumask_empty(&callmap))
-               smp_send_message(callmap, BFIN_IPI_CALL_FUNC, func, info, wait);
-
-       preempt_enable();
-
-       return 0;
+       send_ipi(cpumask_of(cpu), BFIN_IPI_CALL_FUNC_SINGLE);
 }
-EXPORT_SYMBOL_GPL(smp_call_function);
 
-int smp_call_function_single(int cpuid, void (*func) (void *info), void *info,
-                               int wait)
+void arch_send_call_function_ipi_mask(const struct cpumask *mask)
 {
-       unsigned int cpu = cpuid;
-       cpumask_t callmap;
-
-       if (cpu_is_offline(cpu))
-               return 0;
-       cpumask_clear(&callmap);
-       cpumask_set_cpu(cpu, &callmap);
-
-       smp_send_message(callmap, BFIN_IPI_CALL_FUNC, func, info, wait);
-
-       return 0;
+       send_ipi(mask, BFIN_IPI_CALL_FUNC);
 }
-EXPORT_SYMBOL_GPL(smp_call_function_single);
 
 void smp_send_reschedule(int cpu)
 {
-       cpumask_t callmap;
-       /* simply trigger an ipi */
-
-       cpumask_clear(&callmap);
-       cpumask_set_cpu(cpu, &callmap);
-
-       smp_send_message(callmap, BFIN_IPI_RESCHEDULE, NULL, NULL, 0);
+       send_ipi(cpumask_of(cpu), BFIN_IPI_RESCHEDULE);
 
        return;
 }
 
 void smp_send_msg(const struct cpumask *mask, unsigned long type)
 {
-       smp_send_message(*mask, type, NULL, NULL, 0);
+       send_ipi(mask, type);
 }
 
 void smp_timer_broadcast(const struct cpumask *mask)
@@ -333,7 +242,7 @@ void smp_send_stop(void)
        cpumask_copy(&callmap, cpu_online_mask);
        cpumask_clear_cpu(smp_processor_id(), &callmap);
        if (!cpumask_empty(&callmap))
-               smp_send_message(callmap, BFIN_IPI_CPU_STOP, NULL, NULL, 0);
+               send_ipi(&callmap, BFIN_IPI_CPU_STOP);
 
        preempt_enable();
 
@@ -436,7 +345,7 @@ void __init smp_prepare_boot_cpu(void)
 void __init smp_prepare_cpus(unsigned int max_cpus)
 {
        platform_prepare_cpus(max_cpus);
-       ipi_queue_init();
+       bfin_ipi_init();
        platform_request_ipi(IRQ_SUPPLE_0, ipi_handler_int0);
        platform_request_ipi(IRQ_SUPPLE_1, ipi_handler_int1);
 }
index 75f9ee967ea71cc696c3ed9cc5efb390b4ed209a..9cd13b4ce42ba9eb4367be63010802a632577629 100644 (file)
@@ -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);
index e7e03ecf54959988e029e81783422fa0c5b78554..afc379ca375301f7e916a4fd46447239ad478a38 100644 (file)
@@ -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
 }
 
index 33aadbcf170bb4428020ddb87a17383180719400..dcfd573871c142348c4fa790bfcbd3dcc0c50879 100644 (file)
@@ -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++;
index 7b13a4caeea41b6377fb9410fe1397f2dce6aef2..fea823f184794a8a9003ce79afd90cb762a4ed52 100644 (file)
@@ -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
index 4c35301720e76c04aad4eade1d88310c107ba6fd..80562b81f0f2a2036fbf0a28781601b420c5d872 100644 (file)
@@ -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;
 }
 
index 0794a3017b1b53e65e4d1aa325b79711a9fb04b1..e144498bcddda0471c96ca52e412f476aba7dd07 100644 (file)
@@ -1623,6 +1623,63 @@ static void __init prom_instantiate_rtas(void)
 }
 
 #ifdef CONFIG_PPC64
+/*
+ * Allocate room for and instantiate Stored Measurement Log (SML)
+ */
+static void __init prom_instantiate_sml(void)
+{
+       phandle ibmvtpm_node;
+       ihandle ibmvtpm_inst;
+       u32 entry = 0, size = 0;
+       u64 base;
+
+       prom_debug("prom_instantiate_sml: start...\n");
+
+       ibmvtpm_node = call_prom("finddevice", 1, 1, ADDR("/ibm,vtpm"));
+       prom_debug("ibmvtpm_node: %x\n", ibmvtpm_node);
+       if (!PHANDLE_VALID(ibmvtpm_node))
+               return;
+
+       ibmvtpm_inst = call_prom("open", 1, 1, ADDR("/ibm,vtpm"));
+       if (!IHANDLE_VALID(ibmvtpm_inst)) {
+               prom_printf("opening vtpm package failed (%x)\n", ibmvtpm_inst);
+               return;
+       }
+
+       if (call_prom_ret("call-method", 2, 2, &size,
+                         ADDR("sml-get-handover-size"),
+                         ibmvtpm_inst) != 0 || size == 0) {
+               prom_printf("SML get handover size failed\n");
+               return;
+       }
+
+       base = alloc_down(size, PAGE_SIZE, 0);
+       if (base == 0)
+               prom_panic("Could not allocate memory for sml\n");
+
+       prom_printf("instantiating sml at 0x%x...", base);
+
+       if (call_prom_ret("call-method", 4, 2, &entry,
+                         ADDR("sml-handover"),
+                         ibmvtpm_inst, size, base) != 0 || entry == 0) {
+               prom_printf("SML handover failed\n");
+               return;
+       }
+       prom_printf(" done\n");
+
+       reserve_mem(base, size);
+
+       prom_setprop(ibmvtpm_node, "/ibm,vtpm", "linux,sml-base",
+                    &base, sizeof(base));
+       prom_setprop(ibmvtpm_node, "/ibm,vtpm", "linux,sml-size",
+                    &size, sizeof(size));
+
+       prom_debug("sml base     = 0x%x\n", base);
+       prom_debug("sml size     = 0x%x\n", (long)size);
+
+       prom_debug("prom_instantiate_sml: end...\n");
+}
+
 /*
  * Allocate room for and initialize TCE tables
  */
@@ -2916,6 +2973,11 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
                prom_instantiate_opal();
 #endif
 
+#ifdef CONFIG_PPC64
+       /* instantiate sml */
+       prom_instantiate_sml();
+#endif
+
        /*
         * On non-powermacs, put all CPUs in spin-loops.
         *
index 799ed0f1643d135c843f3a1cdc41204063289f0f..2d6e6e3805641bbc79ce1ee11aa639f48f5e2933 100644 (file)
@@ -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));             \
        }                                                               \
index 9fde315f3a7cd42184a54f2174584258076e6a60..1d8fe2b17ef6f1d0069c0e3cc8ff70c7d9cc402a 100644 (file)
@@ -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);
 }
 
 /*
index f86c81e13c374be484f591faead417a7fb3ee572..40b57693de389b24a5b08decae1dbb1fedd47e6c 100644 (file)
@@ -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) {
index 60ee2b8837972c27d8bfb3d95dd9fc3b0b4d0091..2d37bb861faf69cf43e30971881fae771322158a 100644 (file)
@@ -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;
index a1e9d69a9c90e579c2f68cea8869ae6ec26d05c4..584b93674ea43bceea2259142081ef81a02ad9aa 100644 (file)
@@ -169,7 +169,7 @@ static ssize_t hw_interval_write(struct file *file, char const __user *buf,
        if (*offset)
                return -EINVAL;
        retval = oprofilefs_ulong_from_user(&val, buf, count);
-       if (retval)
+       if (retval <= 0)
                return retval;
        if (val < oprofile_min_interval)
                oprofile_hw_interval = oprofile_min_interval;
@@ -212,7 +212,7 @@ static ssize_t hwsampler_zero_write(struct file *file, char const __user *buf,
                return -EINVAL;
 
        retval = oprofilefs_ulong_from_user(&val, buf, count);
-       if (retval)
+       if (retval <= 0)
                return retval;
        if (val != 0)
                return -EINVAL;
@@ -243,7 +243,7 @@ static ssize_t hwsampler_kernel_write(struct file *file, char const __user *buf,
                return -EINVAL;
 
        retval = oprofilefs_ulong_from_user(&val, buf, count);
-       if (retval)
+       if (retval <= 0)
                return retval;
 
        if (val != 0 && val != 1)
@@ -278,7 +278,7 @@ static ssize_t hwsampler_user_write(struct file *file, char const __user *buf,
                return -EINVAL;
 
        retval = oprofilefs_ulong_from_user(&val, buf, count);
-       if (retval)
+       if (retval <= 0)
                return retval;
 
        if (val != 0 && val != 1)
@@ -317,7 +317,7 @@ static ssize_t timer_enabled_write(struct file *file, char const __user *buf,
                return -EINVAL;
 
        retval = oprofilefs_ulong_from_user(&val, buf, count);
-       if (retval)
+       if (retval <= 0)
                return retval;
 
        if (val != 0 && val != 1)
index b7cf6a547f117c5eeae4b69f6b1ccbcdb41b37c8..7e605b95592aea7ac767b817df3a7a61af8d4f20 100644 (file)
@@ -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
index f67601cb3f1f47da13a49ae4948021800b9a2f4d..b96489d8b27dde9e38630d51de4e9d7f04115c08 100644 (file)
@@ -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
index 15e0a16939765148efd633663c131390daaa9893..f1ddc0d2367947d850e863aa4d0a897705074574 100644 (file)
@@ -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) |
index 8ec3a1aa4abd3f612df4a5da31f30c67554d5182..50a1d1f9b6d3ac28c6b2294cd579d71cda2e75c1 100644 (file)
@@ -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)
index 682e9c210baacb99b86817adbd45ebbd17a30955..474ca35b1bce342356b27ac4118f133135d8c249 100644 (file)
@@ -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
 
 ###
index 93971e841dd5e7eaa032f5f4a8d5542040900a6d..472b9b783019a2e2f7c7b273ab7b13b96ec257b9 100644 (file)
@@ -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);
 
index 6605a81ba3399fb8c1c9044b0e7aa8c2e22ff882..8b6defe7eefc5e6de1538984622f109c4223528d 100644 (file)
@@ -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);
index 7bfb5bec8630ada6580dd446e8a62de847d12288..eebd5ffe1bba0b922f9ef8481fd141f2ba9668da 100644 (file)
@@ -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;
 
index 7f2739e03e79a80fc1baaf203cf3a22eccec54dc..6bca492b85475bc8eab5577447ce1fa9a5133223 100644 (file)
@@ -2008,6 +2008,7 @@ __init int intel_pmu_init(void)
                break;
 
        case 28: /* Atom */
+       case 54: /* Cedariew */
                memcpy(hw_cache_event_ids, atom_hw_cache_event_ids,
                       sizeof(hw_cache_event_ids));
 
@@ -2047,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,
@@ -2072,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) {
index e38d97bf4259fc579f2b070fef85980ae7aaab7a..826054a4f2ee4c54ea4cfb9d29ab117db35e7fc5 100644 (file)
@@ -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;
index 520b4265fcd215ee5afe240fe11c944dd6bc06aa..da02e9cc3754b4a2c1a37c1edb44865143f7f723 100644 (file)
@@ -686,7 +686,8 @@ void intel_pmu_lbr_init_atom(void)
         * to have an operational LBR which can freeze
         * on PMU interrupt
         */
-       if (boot_cpu_data.x86_mask < 10) {
+       if (boot_cpu_data.x86_model == 28
+           && boot_cpu_data.x86_mask < 10) {
                pr_cont("LBR disabled due to erratum");
                return;
        }
index 0a5571080e7453bc9d602061ffbe2c6ad81647a2..38e4894165b9cdc096e038de65fc4ee04bdb0690 100644 (file)
@@ -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[] = {
index 4873e62db6a18468b23736c5f4adfd2de8b3b85b..9e5bcf1e2376e9713adc8841df162293c859c97c 100644 (file)
@@ -225,6 +225,9 @@ static ssize_t microcode_write(struct file *file, const char __user *buf,
        if (do_microcode_update(buf, len) == 0)
                ret = (ssize_t)len;
 
+       if (ret > 0)
+               perf_check_microcode();
+
        mutex_unlock(&microcode_mutex);
        put_online_cpus();
 
index e498b18f010c7b97480ccf1f1018c87a5f07daa1..9fc9aa7ac7034c64dc8cdb59f27f5ac80e1d77ab 100644 (file)
@@ -318,7 +318,7 @@ static void pic_ioport_write(void *opaque, u32 addr, u32 val)
                if (val & 0x10) {
                        u8 edge_irr = s->irr & ~s->elcr;
                        int i;
-                       bool found;
+                       bool found = false;
                        struct kvm_vcpu *vcpu;
 
                        s->init4 = val & 1;
index c00f03de1b794af8fe65387747813d57ed2885a2..b1eb202ee76a9265d920ca1b02d57aa1ff803d9a 100644 (file)
@@ -3619,6 +3619,7 @@ static void seg_setup(int seg)
 
 static int alloc_apic_access_page(struct kvm *kvm)
 {
+       struct page *page;
        struct kvm_userspace_memory_region kvm_userspace_mem;
        int r = 0;
 
@@ -3633,7 +3634,13 @@ static int alloc_apic_access_page(struct kvm *kvm)
        if (r)
                goto out;
 
-       kvm->arch.apic_access_page = gfn_to_page(kvm, 0xfee00);
+       page = gfn_to_page(kvm, 0xfee00);
+       if (is_error_page(page)) {
+               r = -EFAULT;
+               goto out;
+       }
+
+       kvm->arch.apic_access_page = page;
 out:
        mutex_unlock(&kvm->slots_lock);
        return r;
@@ -3641,6 +3648,7 @@ out:
 
 static int alloc_identity_pagetable(struct kvm *kvm)
 {
+       struct page *page;
        struct kvm_userspace_memory_region kvm_userspace_mem;
        int r = 0;
 
@@ -3656,8 +3664,13 @@ static int alloc_identity_pagetable(struct kvm *kvm)
        if (r)
                goto out;
 
-       kvm->arch.ept_identity_pagetable = gfn_to_page(kvm,
-                       kvm->arch.ept_identity_map_addr >> PAGE_SHIFT);
+       page = gfn_to_page(kvm, kvm->arch.ept_identity_map_addr >> PAGE_SHIFT);
+       if (is_error_page(page)) {
+               r = -EFAULT;
+               goto out;
+       }
+
+       kvm->arch.ept_identity_pagetable = page;
 out:
        mutex_unlock(&kvm->slots_lock);
        return r;
@@ -6575,7 +6588,7 @@ static void vmx_cpuid_update(struct kvm_vcpu *vcpu)
        /* Exposing INVPCID only when PCID is exposed */
        best = kvm_find_cpuid_entry(vcpu, 0x7, 0);
        if (vmx_invpcid_supported() &&
-           best && (best->ecx & bit(X86_FEATURE_INVPCID)) &&
+           best && (best->ebx & bit(X86_FEATURE_INVPCID)) &&
            guest_cpuid_has_pcid(vcpu)) {
                exec_control |= SECONDARY_EXEC_ENABLE_INVPCID;
                vmcs_write32(SECONDARY_VM_EXEC_CONTROL,
@@ -6585,7 +6598,7 @@ static void vmx_cpuid_update(struct kvm_vcpu *vcpu)
                vmcs_write32(SECONDARY_VM_EXEC_CONTROL,
                             exec_control);
                if (best)
-                       best->ecx &= ~bit(X86_FEATURE_INVPCID);
+                       best->ebx &= ~bit(X86_FEATURE_INVPCID);
        }
 }
 
index 148ed666e311fda2979887d6c9e9a2d440f75ffc..2966c847d489d84f1f2b3cb8450daf4bcce1d568 100644 (file)
@@ -5113,17 +5113,20 @@ static void post_kvm_run_save(struct kvm_vcpu *vcpu)
                        !kvm_event_needs_reinjection(vcpu);
 }
 
-static void vapic_enter(struct kvm_vcpu *vcpu)
+static int vapic_enter(struct kvm_vcpu *vcpu)
 {
        struct kvm_lapic *apic = vcpu->arch.apic;
        struct page *page;
 
        if (!apic || !apic->vapic_addr)
-               return;
+               return 0;
 
        page = gfn_to_page(vcpu->kvm, apic->vapic_addr >> PAGE_SHIFT);
+       if (is_error_page(page))
+               return -EFAULT;
 
        vcpu->arch.apic->vapic_page = page;
+       return 0;
 }
 
 static void vapic_exit(struct kvm_vcpu *vcpu)
@@ -5430,7 +5433,11 @@ static int __vcpu_run(struct kvm_vcpu *vcpu)
        }
 
        vcpu->srcu_idx = srcu_read_lock(&kvm->srcu);
-       vapic_enter(vcpu);
+       r = vapic_enter(vcpu);
+       if (r) {
+               srcu_read_unlock(&kvm->srcu, vcpu->srcu_idx);
+               return r;
+       }
 
        r = 1;
        while (r > 0) {
index e0e6990723e982e12f425f2fdd26113725f2d52a..ab1f6a93b527c9bd50acc12a52e9ce157f2cc48b 100644 (file)
@@ -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;
index 9642d4a3860239f3203a2ff12dba5543a26ccf4f..1fbe75a95f15953d3d0ed6cd0dd7c911a88eac0b 100644 (file)
@@ -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. */
index b65a76133f4f9b4f51dc426021975d7a5427191e..5141d808e7519d8f38ca8c001e4e5c6c7b318956 100644 (file)
@@ -1283,7 +1283,7 @@ static void xen_flush_tlb_others(const struct cpumask *cpus,
        cpumask_clear_cpu(smp_processor_id(), to_cpumask(args->mask));
 
        args->op.cmd = MMUEXT_TLB_FLUSH_MULTI;
-       if (start != TLB_FLUSH_ALL && (end - start) <= PAGE_SIZE) {
+       if (end != TLB_FLUSH_ALL && (end - start) <= PAGE_SIZE) {
                args->op.cmd = MMUEXT_INVLPG_MULTI;
                args->op.arg1.linear_addr = start;
        }
index d4b255463253c8b3bb824a915f5764cc2992e202..72213da605f50c07f3684ca07d351a8bbd7435ef 100644 (file)
@@ -599,7 +599,7 @@ bool __init early_can_reuse_p2m_middle(unsigned long set_pfn, unsigned long set_
        if (p2m_index(set_pfn))
                return false;
 
-       for (pfn = 0; pfn <= MAX_DOMAIN_PAGES; pfn += P2M_PER_PAGE) {
+       for (pfn = 0; pfn < MAX_DOMAIN_PAGES; pfn += P2M_PER_PAGE) {
                topidx = p2m_top_index(pfn);
 
                if (!p2m_top[topidx])
@@ -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
index 4b4dbdfbca89fe5769fd4b2f6826f305fca18e26..ee3cb3a5e2782292bba4807c0d9cc887de48a31e 100644 (file)
@@ -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);
index 4476e0e85d1687c08b31f81e7f633ae802b14814..4a85096f5410adde92d01cd58ecba30373c808f1 100644 (file)
@@ -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;
                        }
 
index 5ef7ba6b6a76a3251956329ffd9ebcfe85ce66b9..d0583a4489e60ee59a6cc0950d7342594a4d5780 100644 (file)
@@ -336,7 +336,7 @@ static int crypto_authenc_genicv(struct aead_request *req, u8 *iv,
                cryptlen += ivsize;
        }
 
-       if (sg_is_last(assoc)) {
+       if (req->assoclen && sg_is_last(assoc)) {
                authenc_ahash_fn = crypto_authenc_ahash;
                sg_init_table(asg, 2);
                sg_set_page(asg, sg_page(assoc), assoc->length, assoc->offset);
@@ -490,7 +490,7 @@ static int crypto_authenc_iverify(struct aead_request *req, u8 *iv,
                cryptlen += ivsize;
        }
 
-       if (sg_is_last(assoc)) {
+       if (req->assoclen && sg_is_last(assoc)) {
                authenc_ahash_fn = crypto_authenc_ahash;
                sg_init_table(asg, 2);
                sg_set_page(asg, sg_page(assoc), assoc->length, assoc->offset);
index 9628652e080c590fb3f6e01dedc655584c12737b..e0596954290b8e33e20791effc0227b80fb4a0c9 100644 (file)
@@ -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:
index fc1803414629d8233b0d6f11819efd166838952e..40e38a06ba854fc04751ec2386ca334d01998eb8 100644 (file)
@@ -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);
index 50d5dea0ff599feb19626ff80b8143dff1ae4f6e..7862d17976b7532f48204cbf4210ffb6d4984f97 100644 (file)
@@ -268,6 +268,9 @@ static const struct pci_device_id ahci_pci_tbl[] = {
        /* JMicron 360/1/3/5/6, match class to avoid IDE function */
        { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
          PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci_ign_iferr },
+       /* JMicron 362B and 362C have an AHCI function with IDE class code */
+       { PCI_VDEVICE(JMICRON, 0x2362), board_ahci_ign_iferr },
+       { PCI_VDEVICE(JMICRON, 0x236f), board_ahci_ign_iferr },
 
        /* ATI */
        { PCI_VDEVICE(ATI, 0x4380), board_ahci_sb600 }, /* ATI SB600 */
@@ -393,6 +396,8 @@ static const struct pci_device_id ahci_pci_tbl[] = {
          .driver_data = board_ahci_yes_fbs },                  /* 88se9125 */
        { PCI_DEVICE(0x1b4b, 0x917a),
          .driver_data = board_ahci_yes_fbs },                  /* 88se9172 */
+       { PCI_DEVICE(0x1b4b, 0x9192),
+         .driver_data = board_ahci_yes_fbs },                  /* 88se9172 on some Gigabyte */
        { PCI_DEVICE(0x1b4b, 0x91a3),
          .driver_data = board_ahci_yes_fbs },
 
@@ -400,7 +405,10 @@ static const struct pci_device_id ahci_pci_tbl[] = {
        { PCI_VDEVICE(PROMISE, 0x3f20), board_ahci },   /* PDC42819 */
 
        /* Asmedia */
-       { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci },   /* ASM1061 */
+       { PCI_VDEVICE(ASMEDIA, 0x0601), board_ahci },   /* ASM1060 */
+       { PCI_VDEVICE(ASMEDIA, 0x0602), board_ahci },   /* ASM1060 */
+       { PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci },   /* ASM1061 */
+       { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci },   /* ASM1062 */
 
        /* Generic, PCI class code for AHCI */
        { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
index 78efb0306a446027f7fce1019572902f5aaa805b..34d94c762a1e79415fc00b0fc59caf034a3e186a 100644 (file)
@@ -250,7 +250,7 @@ int __init dma_declare_contiguous(struct device *dev, unsigned long size,
                return -EINVAL;
 
        /* Sanitise input arguments */
-       alignment = PAGE_SIZE << max(MAX_ORDER, pageblock_order);
+       alignment = PAGE_SIZE << max(MAX_ORDER - 1, pageblock_order);
        base = ALIGN(base, alignment);
        size = ALIGN(size, alignment);
        limit &= ~(alignment - 1);
index de0435e63b02cbd349c5dcc282682359f6f85934..887f68f6d79a9e615beba7525cb9d0e671917c4e 100644 (file)
@@ -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;
 }
index 38aa6dda6b81d0deeb355956ead087324f41f3d1..da3311129a0c5b87b8cc8b3718cc63b5bdfd3928 100644 (file)
@@ -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;
index a8fddeb3d638ebcdf9a0191beda816d8f1338ccd..f946d31d6917e00aa0637df5d21cef35ebf82845 100644 (file)
@@ -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;
                }
        }
index f51fc23d17bb0e0025c74ac9f495007dcbc8b784..18627a1d04c59eff34f7cdd2313555b10a75b283 100644 (file)
 
 /* 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)),
 
index d07c9f7fded600d76192330ef37c35c2135c0fb5..0c03411c59eb8cba0f744e72aed93342dc9cace8 100644 (file)
@@ -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;
index 73f196ca713f20e037e22adccba64d0e00c936b1..c6decb901e5e16f4ba09ccef7db33675aeecb189 100644 (file)
@@ -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);
 }
 
index 11f36e5021367d7dd7c2b0794241154a0544ad0a..fc2de5528dcc94eb65537baa17b78048a5002827 100644 (file)
@@ -86,6 +86,7 @@ static struct usb_device_id ath3k_table[] = {
 
        /* Atheros AR5BBU22 with sflash firmware */
        { USB_DEVICE(0x0489, 0xE03C) },
+       { USB_DEVICE(0x0489, 0xE036) },
 
        { }     /* Terminating entry */
 };
@@ -109,6 +110,7 @@ static struct usb_device_id ath3k_blist_tbl[] = {
 
        /* Atheros AR5BBU22 with sflash firmware */
        { USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0489, 0xE036), .driver_info = BTUSB_ATH3012 },
 
        { }     /* Terminating entry */
 };
index cef3bac1a543d83113b54939585f807748accaf7..654e248763efb98024bd81b57118cd2ad1d77cdf 100644 (file)
@@ -52,6 +52,9 @@ static struct usb_device_id btusb_table[] = {
        /* Generic Bluetooth USB device */
        { USB_DEVICE_INFO(0xe0, 0x01, 0x01) },
 
+       /* Apple-specific (Broadcom) devices */
+       { USB_VENDOR_AND_INTERFACE_INFO(0x05ac, 0xff, 0x01, 0x01) },
+
        /* Broadcom SoftSailing reporting vendor specific */
        { USB_DEVICE(0x0a5c, 0x21e1) },
 
@@ -94,16 +97,14 @@ static struct usb_device_id btusb_table[] = {
 
        /* Broadcom BCM20702A0 */
        { USB_DEVICE(0x0489, 0xe042) },
-       { USB_DEVICE(0x0a5c, 0x21e3) },
-       { USB_DEVICE(0x0a5c, 0x21e6) },
-       { USB_DEVICE(0x0a5c, 0x21e8) },
-       { USB_DEVICE(0x0a5c, 0x21f3) },
-       { USB_DEVICE(0x0a5c, 0x21f4) },
        { USB_DEVICE(0x413c, 0x8197) },
 
        /* Foxconn - Hon Hai */
        { USB_DEVICE(0x0489, 0xe033) },
 
+       /*Broadcom devices with vendor specific id */
+       { USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01) },
+
        { }     /* Terminating entry */
 };
 
@@ -141,6 +142,7 @@ static struct usb_device_id blacklist_table[] = {
 
        /* Atheros AR5BBU12 with sflash firmware */
        { USB_DEVICE(0x0489, 0xe03c), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0489, 0xe036), .driver_info = BTUSB_ATH3012 },
 
        /* Broadcom BCM2035 */
        { USB_DEVICE(0x0a5c, 0x2035), .driver_info = BTUSB_WRONG_SCO_MTU },
index 7c0d391996b5b4e82432b9b3418d427f7a42894a..fbd9b2b850ef1de0a84a57182ff79bdd38064896 100644 (file)
@@ -289,3 +289,16 @@ config HW_RANDOM_EXYNOS
          module will be called exynos-rng.
 
          If unsure, say Y.
+
+config HW_RANDOM_TPM
+       tristate "TPM HW Random Number Generator support"
+       depends on HW_RANDOM && TCG_TPM
+       default HW_RANDOM
+       ---help---
+         This driver provides kernel-side support for the Random Number
+         Generator in the Trusted Platform Module
+
+         To compile this driver as a module, choose M here: the
+         module will be called tpm-rng.
+
+         If unsure, say Y.
index 39a757ca15b65c59b188d0489b12488e4b4c6ac3..1fd7eec9fbf6421ace05971f95671095917bf4fa 100644 (file)
@@ -25,3 +25,4 @@ obj-$(CONFIG_HW_RANDOM_PICOXCELL) += picoxcell-rng.o
 obj-$(CONFIG_HW_RANDOM_PPC4XX) += ppc4xx-rng.o
 obj-$(CONFIG_HW_RANDOM_PSERIES) += pseries-rng.o
 obj-$(CONFIG_HW_RANDOM_EXYNOS) += exynos-rng.o
+obj-$(CONFIG_HW_RANDOM_TPM) += tpm-rng.o
diff --git a/drivers/char/hw_random/tpm-rng.c b/drivers/char/hw_random/tpm-rng.c
new file mode 100644 (file)
index 0000000..d6d4482
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2012 Kent Yoder IBM Corporation
+ *
+ * HWRNG interfaces to pull RNG data from a TPM
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#include <linux/module.h>
+#include <linux/hw_random.h>
+#include <linux/tpm.h>
+
+#define MODULE_NAME "tpm-rng"
+
+static int tpm_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
+{
+       return tpm_get_random(TPM_ANY_NUM, data, max);
+}
+
+static struct hwrng tpm_rng = {
+       .name = MODULE_NAME,
+       .read = tpm_rng_read,
+};
+
+static int __init rng_init(void)
+{
+       return hwrng_register(&tpm_rng);
+}
+module_init(rng_init);
+
+static void __exit rng_exit(void)
+{
+       hwrng_unregister(&tpm_rng);
+}
+module_exit(rng_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Kent Yoder <key@linux.vnet.ibm.com>");
+MODULE_DESCRIPTION("RNG driver for TPM devices");
index a048199ce866555f19b98fcd93ff10f3890c1eb3..915875e431d2151f48d9f793da67d0b2817d5e45 100644 (file)
@@ -33,6 +33,17 @@ config TCG_TIS
          from within Linux.  To compile this driver as a module, choose
          M here; the module will be called tpm_tis.
 
+config TCG_TIS_I2C_INFINEON
+       tristate "TPM Interface Specification 1.2 Interface (I2C - Infineon)"
+       depends on I2C
+       ---help---
+         If you have a TPM security chip that is compliant with the
+         TCG TIS 1.2 TPM specification and Infineon's I2C Protocol Stack
+         Specification 0.20 say Yes and it will be accessible from within
+         Linux.
+         To compile this driver as a module, choose M here; the module
+         will be called tpm_tis_i2c_infineon.
+
 config TCG_NSC
        tristate "National Semiconductor TPM Interface"
        depends on X86
@@ -62,4 +73,12 @@ config TCG_INFINEON
          Further information on this driver and the supported hardware
          can be found at http://www.trust.rub.de/projects/linux-device-driver-infineon-tpm/ 
 
+config TCG_IBMVTPM
+       tristate "IBM VTPM Interface"
+       depends on PPC64
+       ---help---
+         If you have IBM virtual TPM (VTPM) support say Yes and it
+         will be accessible from within Linux.  To compile this driver
+         as a module, choose M here; the module will be called tpm_ibmvtpm.
+
 endif # TCG_TPM
index ea3a1e02a824de2b1a80feaa5ebc0e0125162c1c..5b3fc8bc6c132fa76f1e6ec8723c9bf096670271 100644 (file)
@@ -4,8 +4,16 @@
 obj-$(CONFIG_TCG_TPM) += tpm.o
 ifdef CONFIG_ACPI
        obj-$(CONFIG_TCG_TPM) += tpm_bios.o
+       tpm_bios-objs += tpm_eventlog.o tpm_acpi.o tpm_ppi.o
+else
+ifdef CONFIG_TCG_IBMVTPM
+       obj-$(CONFIG_TCG_TPM) += tpm_bios.o
+       tpm_bios-objs += tpm_eventlog.o tpm_of.o
+endif
 endif
 obj-$(CONFIG_TCG_TIS) += tpm_tis.o
+obj-$(CONFIG_TCG_TIS_I2C_INFINEON) += tpm_i2c_infineon.o
 obj-$(CONFIG_TCG_NSC) += tpm_nsc.o
 obj-$(CONFIG_TCG_ATMEL) += tpm_atmel.o
 obj-$(CONFIG_TCG_INFINEON) += tpm_infineon.o
+obj-$(CONFIG_TCG_IBMVTPM) += tpm_ibmvtpm.o
index 817f0ee202b6861e87e146e2cc8864bc2de33ede..6724615a4fdd1827028a24fff16b91a5f29d16d7 100644 (file)
 #include <linux/freezer.h>
 
 #include "tpm.h"
-
-enum tpm_const {
-       TPM_MINOR = 224,        /* officially assigned */
-       TPM_BUFSIZE = 4096,
-       TPM_NUM_DEVICES = 256,
-};
+#include "tpm_eventlog.h"
 
 enum tpm_duration {
        TPM_SHORT = 0,
@@ -482,6 +477,7 @@ static ssize_t transmit_cmd(struct tpm_chip *chip, struct tpm_cmd_t *cmd,
 #define TPM_INTERNAL_RESULT_SIZE 200
 #define TPM_TAG_RQU_COMMAND cpu_to_be16(193)
 #define TPM_ORD_GET_CAP cpu_to_be32(101)
+#define TPM_ORD_GET_RANDOM cpu_to_be32(70)
 
 static const struct tpm_input_header tpm_getcap_header = {
        .tag = TPM_TAG_RQU_COMMAND,
@@ -919,7 +915,7 @@ EXPORT_SYMBOL_GPL(tpm_show_pcrs);
 
 #define  READ_PUBEK_RESULT_SIZE 314
 #define TPM_ORD_READPUBEK cpu_to_be32(124)
-struct tpm_input_header tpm_readpubek_header = {
+static struct tpm_input_header tpm_readpubek_header = {
        .tag = TPM_TAG_RQU_COMMAND,
        .length = cpu_to_be32(30),
        .ordinal = TPM_ORD_READPUBEK
@@ -1175,7 +1171,7 @@ int tpm_release(struct inode *inode, struct file *file)
        flush_work_sync(&chip->work);
        file->private_data = NULL;
        atomic_set(&chip->data_pending, 0);
-       kfree(chip->data_buffer);
+       kzfree(chip->data_buffer);
        clear_bit(0, &chip->is_open);
        put_device(chip->dev);
        return 0;
@@ -1227,7 +1223,6 @@ ssize_t tpm_read(struct file *file, char __user *buf,
        del_singleshot_timer_sync(&chip->user_read_timer);
        flush_work_sync(&chip->work);
        ret_size = atomic_read(&chip->data_pending);
-       atomic_set(&chip->data_pending, 0);
        if (ret_size > 0) {     /* relay data */
                ssize_t orig_ret_size = ret_size;
                if (size < ret_size)
@@ -1242,6 +1237,8 @@ ssize_t tpm_read(struct file *file, char __user *buf,
                mutex_unlock(&chip->buffer_mutex);
        }
 
+       atomic_set(&chip->data_pending, 0);
+
        return ret_size;
 }
 EXPORT_SYMBOL_GPL(tpm_read);
@@ -1326,6 +1323,58 @@ int tpm_pm_resume(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(tpm_pm_resume);
 
+#define TPM_GETRANDOM_RESULT_SIZE      18
+static struct tpm_input_header tpm_getrandom_header = {
+       .tag = TPM_TAG_RQU_COMMAND,
+       .length = cpu_to_be32(14),
+       .ordinal = TPM_ORD_GET_RANDOM
+};
+
+/**
+ * tpm_get_random() - Get random bytes from the tpm's RNG
+ * @chip_num: A specific chip number for the request or TPM_ANY_NUM
+ * @out: destination buffer for the random bytes
+ * @max: the max number of bytes to write to @out
+ *
+ * Returns < 0 on error and the number of bytes read on success
+ */
+int tpm_get_random(u32 chip_num, u8 *out, size_t max)
+{
+       struct tpm_chip *chip;
+       struct tpm_cmd_t tpm_cmd;
+       u32 recd, num_bytes = min_t(u32, max, TPM_MAX_RNG_DATA);
+       int err, total = 0, retries = 5;
+       u8 *dest = out;
+
+       chip = tpm_chip_find_get(chip_num);
+       if (chip == NULL)
+               return -ENODEV;
+
+       if (!out || !num_bytes || max > TPM_MAX_RNG_DATA)
+               return -EINVAL;
+
+       do {
+               tpm_cmd.header.in = tpm_getrandom_header;
+               tpm_cmd.params.getrandom_in.num_bytes = cpu_to_be32(num_bytes);
+
+               err = transmit_cmd(chip, &tpm_cmd,
+                                  TPM_GETRANDOM_RESULT_SIZE + num_bytes,
+                                  "attempting get random");
+               if (err)
+                       break;
+
+               recd = be32_to_cpu(tpm_cmd.params.getrandom_out.rng_data_len);
+               memcpy(dest, tpm_cmd.params.getrandom_out.rng_data, recd);
+
+               dest += recd;
+               total += recd;
+               num_bytes -= recd;
+       } while (retries-- && total < max);
+
+       return total ? total : -EIO;
+}
+EXPORT_SYMBOL_GPL(tpm_get_random);
+
 /* In case vendor provided release function, call it too.*/
 
 void tpm_dev_vendor_release(struct tpm_chip *chip)
@@ -1346,7 +1395,7 @@ EXPORT_SYMBOL_GPL(tpm_dev_vendor_release);
  * Once all references to platform device are down to 0,
  * release all allocated structures.
  */
-void tpm_dev_release(struct device *dev)
+static void tpm_dev_release(struct device *dev)
 {
        struct tpm_chip *chip = dev_get_drvdata(dev);
 
@@ -1427,6 +1476,11 @@ struct tpm_chip *tpm_register_hardware(struct device *dev,
                goto put_device;
        }
 
+       if (sys_add_ppi(&dev->kobj)) {
+               misc_deregister(&chip->vendor.miscdev);
+               goto put_device;
+       }
+
        chip->bios_dir = tpm_bios_log_setup(devname);
 
        /* Make chip available */
index 917f727e674059b7e7daa2fc36a9920a306deef6..02c266aa2bf712657d3507071c1b266a4215e3c2 100644 (file)
 #include <linux/io.h>
 #include <linux/tpm.h>
 
+enum tpm_const {
+       TPM_MINOR = 224,        /* officially assigned */
+       TPM_BUFSIZE = 4096,
+       TPM_NUM_DEVICES = 256,
+};
+
 enum tpm_timeout {
        TPM_TIMEOUT = 5,        /* msecs */
 };
@@ -94,6 +100,7 @@ struct tpm_vendor_specific {
        bool timeout_adjusted;
        unsigned long duration[3]; /* jiffies */
        bool duration_adjusted;
+       void *data;
 
        wait_queue_head_t read_queue;
        wait_queue_head_t int_queue;
@@ -269,6 +276,21 @@ struct tpm_pcrextend_in {
        u8      hash[TPM_DIGEST_SIZE];
 }__attribute__((packed));
 
+/* 128 bytes is an arbitrary cap. This could be as large as TPM_BUFSIZE - 18
+ * bytes, but 128 is still a relatively large number of random bytes and
+ * anything much bigger causes users of struct tpm_cmd_t to start getting
+ * compiler warnings about stack frame size. */
+#define TPM_MAX_RNG_DATA       128
+
+struct tpm_getrandom_out {
+       __be32 rng_data_len;
+       u8     rng_data[TPM_MAX_RNG_DATA];
+}__attribute__((packed));
+
+struct tpm_getrandom_in {
+       __be32 num_bytes;
+}__attribute__((packed));
+
 typedef union {
        struct  tpm_getcap_params_out getcap_out;
        struct  tpm_readpubek_params_out readpubek_out;
@@ -277,6 +299,8 @@ typedef union {
        struct  tpm_pcrread_in  pcrread_in;
        struct  tpm_pcrread_out pcrread_out;
        struct  tpm_pcrextend_in pcrextend_in;
+       struct  tpm_getrandom_in getrandom_in;
+       struct  tpm_getrandom_out getrandom_out;
 } tpm_cmd_params;
 
 struct tpm_cmd_t {
@@ -303,15 +327,12 @@ extern int tpm_pm_suspend(struct device *);
 extern int tpm_pm_resume(struct device *);
 extern int wait_for_tpm_stat(struct tpm_chip *, u8, unsigned long,
                             wait_queue_head_t *);
+
 #ifdef CONFIG_ACPI
-extern struct dentry ** tpm_bios_log_setup(char *);
-extern void tpm_bios_log_teardown(struct dentry **);
+extern ssize_t sys_add_ppi(struct kobject *parent);
 #else
-static inline struct dentry ** tpm_bios_log_setup(char *name)
-{
-       return NULL;
-}
-static inline void tpm_bios_log_teardown(struct dentry **dir)
+static inline ssize_t sys_add_ppi(struct kobject *parent)
 {
+       return 0;
 }
 #endif
diff --git a/drivers/char/tpm/tpm_acpi.c b/drivers/char/tpm/tpm_acpi.c
new file mode 100644 (file)
index 0000000..56051d0
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2005 IBM Corporation
+ *
+ * Authors:
+ *     Seiji Munetoh <munetoh@jp.ibm.com>
+ *     Stefan Berger <stefanb@us.ibm.com>
+ *     Reiner Sailer <sailer@watson.ibm.com>
+ *     Kylene Hall <kjhall@us.ibm.com>
+ *
+ * Maintained by: <tpmdd-devel@lists.sourceforge.net>
+ *
+ * Access to the eventlog extended by the TCG BIOS of PC platform
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ */
+
+#include <linux/seq_file.h>
+#include <linux/fs.h>
+#include <linux/security.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <acpi/acpi.h>
+
+#include "tpm.h"
+#include "tpm_eventlog.h"
+
+struct acpi_tcpa {
+       struct acpi_table_header hdr;
+       u16 platform_class;
+       union {
+               struct client_hdr {
+                       u32 log_max_len __attribute__ ((packed));
+                       u64 log_start_addr __attribute__ ((packed));
+               } client;
+               struct server_hdr {
+                       u16 reserved;
+                       u64 log_max_len __attribute__ ((packed));
+                       u64 log_start_addr __attribute__ ((packed));
+               } server;
+       };
+};
+
+/* read binary bios log */
+int read_log(struct tpm_bios_log *log)
+{
+       struct acpi_tcpa *buff;
+       acpi_status status;
+       void __iomem *virt;
+       u64 len, start;
+
+       if (log->bios_event_log != NULL) {
+               printk(KERN_ERR
+                      "%s: ERROR - Eventlog already initialized\n",
+                      __func__);
+               return -EFAULT;
+       }
+
+       /* Find TCPA entry in RSDT (ACPI_LOGICAL_ADDRESSING) */
+       status = acpi_get_table(ACPI_SIG_TCPA, 1,
+                               (struct acpi_table_header **)&buff);
+
+       if (ACPI_FAILURE(status)) {
+               printk(KERN_ERR "%s: ERROR - Could not get TCPA table\n",
+                      __func__);
+               return -EIO;
+       }
+
+       switch(buff->platform_class) {
+       case BIOS_SERVER:
+               len = buff->server.log_max_len;
+               start = buff->server.log_start_addr;
+               break;
+       case BIOS_CLIENT:
+       default:
+               len = buff->client.log_max_len;
+               start = buff->client.log_start_addr;
+               break;
+       }
+       if (!len) {
+               printk(KERN_ERR "%s: ERROR - TCPA log area empty\n", __func__);
+               return -EIO;
+       }
+
+       /* malloc EventLog space */
+       log->bios_event_log = kmalloc(len, GFP_KERNEL);
+       if (!log->bios_event_log) {
+               printk("%s: ERROR - Not enough  Memory for BIOS measurements\n",
+                       __func__);
+               return -ENOMEM;
+       }
+
+       log->bios_event_log_end = log->bios_event_log + len;
+
+       virt = acpi_os_map_memory(start, len);
+       if (!virt) {
+               kfree(log->bios_event_log);
+               printk("%s: ERROR - Unable to map memory\n", __func__);
+               return -EIO;
+       }
+
+       memcpy_fromio(log->bios_event_log, virt, len);
+
+       acpi_os_unmap_memory(virt, len);
+       return 0;
+}
diff --git a/drivers/char/tpm/tpm_bios.c b/drivers/char/tpm/tpm_bios.c
deleted file mode 100644 (file)
index 0636520..0000000
+++ /dev/null
@@ -1,556 +0,0 @@
-/*
- * Copyright (C) 2005 IBM Corporation
- *
- * Authors:
- *     Seiji Munetoh <munetoh@jp.ibm.com>
- *     Stefan Berger <stefanb@us.ibm.com>
- *     Reiner Sailer <sailer@watson.ibm.com>
- *     Kylene Hall <kjhall@us.ibm.com>
- *
- * Maintained by: <tpmdd-devel@lists.sourceforge.net>
- *
- * Access to the eventlog extended by the TCG BIOS of PC platform
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- *
- */
-
-#include <linux/seq_file.h>
-#include <linux/fs.h>
-#include <linux/security.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <acpi/acpi.h>
-#include "tpm.h"
-
-#define TCG_EVENT_NAME_LEN_MAX 255
-#define MAX_TEXT_EVENT         1000    /* Max event string length */
-#define ACPI_TCPA_SIG          "TCPA"  /* 0x41504354 /'TCPA' */
-
-enum bios_platform_class {
-       BIOS_CLIENT = 0x00,
-       BIOS_SERVER = 0x01,
-};
-
-struct tpm_bios_log {
-       void *bios_event_log;
-       void *bios_event_log_end;
-};
-
-struct acpi_tcpa {
-       struct acpi_table_header hdr;
-       u16 platform_class;
-       union {
-               struct client_hdr {
-                       u32 log_max_len __attribute__ ((packed));
-                       u64 log_start_addr __attribute__ ((packed));
-               } client;
-               struct server_hdr {
-                       u16 reserved;
-                       u64 log_max_len __attribute__ ((packed));
-                       u64 log_start_addr __attribute__ ((packed));
-               } server;
-       };
-};
-
-struct tcpa_event {
-       u32 pcr_index;
-       u32 event_type;
-       u8 pcr_value[20];       /* SHA1 */
-       u32 event_size;
-       u8 event_data[0];
-};
-
-enum tcpa_event_types {
-       PREBOOT = 0,
-       POST_CODE,
-       UNUSED,
-       NO_ACTION,
-       SEPARATOR,
-       ACTION,
-       EVENT_TAG,
-       SCRTM_CONTENTS,
-       SCRTM_VERSION,
-       CPU_MICROCODE,
-       PLATFORM_CONFIG_FLAGS,
-       TABLE_OF_DEVICES,
-       COMPACT_HASH,
-       IPL,
-       IPL_PARTITION_DATA,
-       NONHOST_CODE,
-       NONHOST_CONFIG,
-       NONHOST_INFO,
-};
-
-static const char* tcpa_event_type_strings[] = {
-       "PREBOOT",
-       "POST CODE",
-       "",
-       "NO ACTION",
-       "SEPARATOR",
-       "ACTION",
-       "EVENT TAG",
-       "S-CRTM Contents",
-       "S-CRTM Version",
-       "CPU Microcode",
-       "Platform Config Flags",
-       "Table of Devices",
-       "Compact Hash",
-       "IPL",
-       "IPL Partition Data",
-       "Non-Host Code",
-       "Non-Host Config",
-       "Non-Host Info"
-};
-
-struct tcpa_pc_event {
-       u32 event_id;
-       u32 event_size;
-       u8 event_data[0];
-};
-
-enum tcpa_pc_event_ids {
-       SMBIOS = 1,
-       BIS_CERT,
-       POST_BIOS_ROM,
-       ESCD,
-       CMOS,
-       NVRAM,
-       OPTION_ROM_EXEC,
-       OPTION_ROM_CONFIG,
-       OPTION_ROM_MICROCODE = 10,
-       S_CRTM_VERSION,
-       S_CRTM_CONTENTS,
-       POST_CONTENTS,
-       HOST_TABLE_OF_DEVICES,
-};
-
-static const char* tcpa_pc_event_id_strings[] = {
-       "",
-       "SMBIOS",
-       "BIS Certificate",
-       "POST BIOS ",
-       "ESCD ",
-       "CMOS",
-       "NVRAM",
-       "Option ROM",
-       "Option ROM config",
-       "",
-       "Option ROM microcode ",
-       "S-CRTM Version",
-       "S-CRTM Contents ",
-       "POST Contents ",
-       "Table of Devices",
-};
-
-/* returns pointer to start of pos. entry of tcg log */
-static void *tpm_bios_measurements_start(struct seq_file *m, loff_t *pos)
-{
-       loff_t i;
-       struct tpm_bios_log *log = m->private;
-       void *addr = log->bios_event_log;
-       void *limit = log->bios_event_log_end;
-       struct tcpa_event *event;
-
-       /* read over *pos measurements */
-       for (i = 0; i < *pos; i++) {
-               event = addr;
-
-               if ((addr + sizeof(struct tcpa_event)) < limit) {
-                       if (event->event_type == 0 && event->event_size == 0)
-                               return NULL;
-                       addr += sizeof(struct tcpa_event) + event->event_size;
-               }
-       }
-
-       /* now check if current entry is valid */
-       if ((addr + sizeof(struct tcpa_event)) >= limit)
-               return NULL;
-
-       event = addr;
-
-       if ((event->event_type == 0 && event->event_size == 0) ||
-           ((addr + sizeof(struct tcpa_event) + event->event_size) >= limit))
-               return NULL;
-
-       return addr;
-}
-
-static void *tpm_bios_measurements_next(struct seq_file *m, void *v,
-                                       loff_t *pos)
-{
-       struct tcpa_event *event = v;
-       struct tpm_bios_log *log = m->private;
-       void *limit = log->bios_event_log_end;
-
-       v += sizeof(struct tcpa_event) + event->event_size;
-
-       /* now check if current entry is valid */
-       if ((v + sizeof(struct tcpa_event)) >= limit)
-               return NULL;
-
-       event = v;
-
-       if (event->event_type == 0 && event->event_size == 0)
-               return NULL;
-
-       if ((event->event_type == 0 && event->event_size == 0) ||
-           ((v + sizeof(struct tcpa_event) + event->event_size) >= limit))
-               return NULL;
-
-       (*pos)++;
-       return v;
-}
-
-static void tpm_bios_measurements_stop(struct seq_file *m, void *v)
-{
-}
-
-static int get_event_name(char *dest, struct tcpa_event *event,
-                       unsigned char * event_entry)
-{
-       const char *name = "";
-       /* 41 so there is room for 40 data and 1 nul */
-       char data[41] = "";
-       int i, n_len = 0, d_len = 0;
-       struct tcpa_pc_event *pc_event;
-
-       switch(event->event_type) {
-       case PREBOOT:
-       case POST_CODE:
-       case UNUSED:
-       case NO_ACTION:
-       case SCRTM_CONTENTS:
-       case SCRTM_VERSION:
-       case CPU_MICROCODE:
-       case PLATFORM_CONFIG_FLAGS:
-       case TABLE_OF_DEVICES:
-       case COMPACT_HASH:
-       case IPL:
-       case IPL_PARTITION_DATA:
-       case NONHOST_CODE:
-       case NONHOST_CONFIG:
-       case NONHOST_INFO:
-               name = tcpa_event_type_strings[event->event_type];
-               n_len = strlen(name);
-               break;
-       case SEPARATOR:
-       case ACTION:
-               if (MAX_TEXT_EVENT > event->event_size) {
-                       name = event_entry;
-                       n_len = event->event_size;
-               }
-               break;
-       case EVENT_TAG:
-               pc_event = (struct tcpa_pc_event *)event_entry;
-
-               /* ToDo Row data -> Base64 */
-
-               switch (pc_event->event_id) {
-               case SMBIOS:
-               case BIS_CERT:
-               case CMOS:
-               case NVRAM:
-               case OPTION_ROM_EXEC:
-               case OPTION_ROM_CONFIG:
-               case S_CRTM_VERSION:
-                       name = tcpa_pc_event_id_strings[pc_event->event_id];
-                       n_len = strlen(name);
-                       break;
-               /* hash data */
-               case POST_BIOS_ROM:
-               case ESCD:
-               case OPTION_ROM_MICROCODE:
-               case S_CRTM_CONTENTS:
-               case POST_CONTENTS:
-                       name = tcpa_pc_event_id_strings[pc_event->event_id];
-                       n_len = strlen(name);
-                       for (i = 0; i < 20; i++)
-                               d_len += sprintf(&data[2*i], "%02x",
-                                               pc_event->event_data[i]);
-                       break;
-               default:
-                       break;
-               }
-       default:
-               break;
-       }
-
-       return snprintf(dest, MAX_TEXT_EVENT, "[%.*s%.*s]",
-                       n_len, name, d_len, data);
-
-}
-
-static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v)
-{
-       struct tcpa_event *event = v;
-       char *data = v;
-       int i;
-
-       for (i = 0; i < sizeof(struct tcpa_event) + event->event_size; i++)
-               seq_putc(m, data[i]);
-
-       return 0;
-}
-
-static int tpm_bios_measurements_release(struct inode *inode,
-                                        struct file *file)
-{
-       struct seq_file *seq = file->private_data;
-       struct tpm_bios_log *log = seq->private;
-
-       if (log) {
-               kfree(log->bios_event_log);
-               kfree(log);
-       }
-
-       return seq_release(inode, file);
-}
-
-static int tpm_ascii_bios_measurements_show(struct seq_file *m, void *v)
-{
-       int len = 0;
-       int i;
-       char *eventname;
-       struct tcpa_event *event = v;
-       unsigned char *event_entry =
-           (unsigned char *) (v + sizeof(struct tcpa_event));
-
-       eventname = kmalloc(MAX_TEXT_EVENT, GFP_KERNEL);
-       if (!eventname) {
-               printk(KERN_ERR "%s: ERROR - No Memory for event name\n ",
-                      __func__);
-               return -EFAULT;
-       }
-
-       seq_printf(m, "%2d ", event->pcr_index);
-
-       /* 2nd: SHA1 */
-       for (i = 0; i < 20; i++)
-               seq_printf(m, "%02x", event->pcr_value[i]);
-
-       /* 3rd: event type identifier */
-       seq_printf(m, " %02x", event->event_type);
-
-       len += get_event_name(eventname, event, event_entry);
-
-       /* 4th: eventname <= max + \'0' delimiter */
-       seq_printf(m, " %s\n", eventname);
-
-       kfree(eventname);
-       return 0;
-}
-
-static const struct seq_operations tpm_ascii_b_measurments_seqops = {
-       .start = tpm_bios_measurements_start,
-       .next = tpm_bios_measurements_next,
-       .stop = tpm_bios_measurements_stop,
-       .show = tpm_ascii_bios_measurements_show,
-};
-
-static const struct seq_operations tpm_binary_b_measurments_seqops = {
-       .start = tpm_bios_measurements_start,
-       .next = tpm_bios_measurements_next,
-       .stop = tpm_bios_measurements_stop,
-       .show = tpm_binary_bios_measurements_show,
-};
-
-/* read binary bios log */
-static int read_log(struct tpm_bios_log *log)
-{
-       struct acpi_tcpa *buff;
-       acpi_status status;
-       struct acpi_table_header *virt;
-       u64 len, start;
-
-       if (log->bios_event_log != NULL) {
-               printk(KERN_ERR
-                      "%s: ERROR - Eventlog already initialized\n",
-                      __func__);
-               return -EFAULT;
-       }
-
-       /* Find TCPA entry in RSDT (ACPI_LOGICAL_ADDRESSING) */
-       status = acpi_get_table(ACPI_SIG_TCPA, 1,
-                               (struct acpi_table_header **)&buff);
-
-       if (ACPI_FAILURE(status)) {
-               printk(KERN_ERR "%s: ERROR - Could not get TCPA table\n",
-                      __func__);
-               return -EIO;
-       }
-
-       switch(buff->platform_class) {
-       case BIOS_SERVER:
-               len = buff->server.log_max_len;
-               start = buff->server.log_start_addr;
-               break;
-       case BIOS_CLIENT:
-       default:
-               len = buff->client.log_max_len;
-               start = buff->client.log_start_addr;
-               break;
-       }
-       if (!len) {
-               printk(KERN_ERR "%s: ERROR - TCPA log area empty\n", __func__);
-               return -EIO;
-       }
-
-       /* malloc EventLog space */
-       log->bios_event_log = kmalloc(len, GFP_KERNEL);
-       if (!log->bios_event_log) {
-               printk("%s: ERROR - Not enough  Memory for BIOS measurements\n",
-                       __func__);
-               return -ENOMEM;
-       }
-
-       log->bios_event_log_end = log->bios_event_log + len;
-
-       virt = acpi_os_map_memory(start, len);
-
-       memcpy(log->bios_event_log, virt, len);
-
-       acpi_os_unmap_memory(virt, len);
-       return 0;
-}
-
-static int tpm_ascii_bios_measurements_open(struct inode *inode,
-                                           struct file *file)
-{
-       int err;
-       struct tpm_bios_log *log;
-       struct seq_file *seq;
-
-       log = kzalloc(sizeof(struct tpm_bios_log), GFP_KERNEL);
-       if (!log)
-               return -ENOMEM;
-
-       if ((err = read_log(log)))
-               goto out_free;
-
-       /* now register seq file */
-       err = seq_open(file, &tpm_ascii_b_measurments_seqops);
-       if (!err) {
-               seq = file->private_data;
-               seq->private = log;
-       } else {
-               goto out_free;
-       }
-
-out:
-       return err;
-out_free:
-       kfree(log->bios_event_log);
-       kfree(log);
-       goto out;
-}
-
-static const struct file_operations tpm_ascii_bios_measurements_ops = {
-       .open = tpm_ascii_bios_measurements_open,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = tpm_bios_measurements_release,
-};
-
-static int tpm_binary_bios_measurements_open(struct inode *inode,
-                                            struct file *file)
-{
-       int err;
-       struct tpm_bios_log *log;
-       struct seq_file *seq;
-
-       log = kzalloc(sizeof(struct tpm_bios_log), GFP_KERNEL);
-       if (!log)
-               return -ENOMEM;
-
-       if ((err = read_log(log)))
-               goto out_free;
-
-       /* now register seq file */
-       err = seq_open(file, &tpm_binary_b_measurments_seqops);
-       if (!err) {
-               seq = file->private_data;
-               seq->private = log;
-       } else {
-               goto out_free;
-       }
-
-out:
-       return err;
-out_free:
-       kfree(log->bios_event_log);
-       kfree(log);
-       goto out;
-}
-
-static const struct file_operations tpm_binary_bios_measurements_ops = {
-       .open = tpm_binary_bios_measurements_open,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = tpm_bios_measurements_release,
-};
-
-static int is_bad(void *p)
-{
-       if (!p)
-               return 1;
-       if (IS_ERR(p) && (PTR_ERR(p) != -ENODEV))
-               return 1;
-       return 0;
-}
-
-struct dentry **tpm_bios_log_setup(char *name)
-{
-       struct dentry **ret = NULL, *tpm_dir, *bin_file, *ascii_file;
-
-       tpm_dir = securityfs_create_dir(name, NULL);
-       if (is_bad(tpm_dir))
-               goto out;
-
-       bin_file =
-           securityfs_create_file("binary_bios_measurements",
-                                  S_IRUSR | S_IRGRP, tpm_dir, NULL,
-                                  &tpm_binary_bios_measurements_ops);
-       if (is_bad(bin_file))
-               goto out_tpm;
-
-       ascii_file =
-           securityfs_create_file("ascii_bios_measurements",
-                                  S_IRUSR | S_IRGRP, tpm_dir, NULL,
-                                  &tpm_ascii_bios_measurements_ops);
-       if (is_bad(ascii_file))
-               goto out_bin;
-
-       ret = kmalloc(3 * sizeof(struct dentry *), GFP_KERNEL);
-       if (!ret)
-               goto out_ascii;
-
-       ret[0] = ascii_file;
-       ret[1] = bin_file;
-       ret[2] = tpm_dir;
-
-       return ret;
-
-out_ascii:
-       securityfs_remove(ascii_file);
-out_bin:
-       securityfs_remove(bin_file);
-out_tpm:
-       securityfs_remove(tpm_dir);
-out:
-       return NULL;
-}
-EXPORT_SYMBOL_GPL(tpm_bios_log_setup);
-
-void tpm_bios_log_teardown(struct dentry **lst)
-{
-       int i;
-
-       for (i = 0; i < 3; i++)
-               securityfs_remove(lst[i]);
-}
-EXPORT_SYMBOL_GPL(tpm_bios_log_teardown);
-MODULE_LICENSE("GPL");
diff --git a/drivers/char/tpm/tpm_eventlog.c b/drivers/char/tpm/tpm_eventlog.c
new file mode 100644 (file)
index 0000000..84ddc55
--- /dev/null
@@ -0,0 +1,419 @@
+/*
+ * Copyright (C) 2005, 2012 IBM Corporation
+ *
+ * Authors:
+ *     Kent Yoder <key@linux.vnet.ibm.com>
+ *     Seiji Munetoh <munetoh@jp.ibm.com>
+ *     Stefan Berger <stefanb@us.ibm.com>
+ *     Reiner Sailer <sailer@watson.ibm.com>
+ *     Kylene Hall <kjhall@us.ibm.com>
+ *
+ * Maintained by: <tpmdd-devel@lists.sourceforge.net>
+ *
+ * Access to the eventlog created by a system's firmware / BIOS
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ */
+
+#include <linux/seq_file.h>
+#include <linux/fs.h>
+#include <linux/security.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include "tpm.h"
+#include "tpm_eventlog.h"
+
+
+static const char* tcpa_event_type_strings[] = {
+       "PREBOOT",
+       "POST CODE",
+       "",
+       "NO ACTION",
+       "SEPARATOR",
+       "ACTION",
+       "EVENT TAG",
+       "S-CRTM Contents",
+       "S-CRTM Version",
+       "CPU Microcode",
+       "Platform Config Flags",
+       "Table of Devices",
+       "Compact Hash",
+       "IPL",
+       "IPL Partition Data",
+       "Non-Host Code",
+       "Non-Host Config",
+       "Non-Host Info"
+};
+
+static const char* tcpa_pc_event_id_strings[] = {
+       "",
+       "SMBIOS",
+       "BIS Certificate",
+       "POST BIOS ",
+       "ESCD ",
+       "CMOS",
+       "NVRAM",
+       "Option ROM",
+       "Option ROM config",
+       "",
+       "Option ROM microcode ",
+       "S-CRTM Version",
+       "S-CRTM Contents ",
+       "POST Contents ",
+       "Table of Devices",
+};
+
+/* returns pointer to start of pos. entry of tcg log */
+static void *tpm_bios_measurements_start(struct seq_file *m, loff_t *pos)
+{
+       loff_t i;
+       struct tpm_bios_log *log = m->private;
+       void *addr = log->bios_event_log;
+       void *limit = log->bios_event_log_end;
+       struct tcpa_event *event;
+
+       /* read over *pos measurements */
+       for (i = 0; i < *pos; i++) {
+               event = addr;
+
+               if ((addr + sizeof(struct tcpa_event)) < limit) {
+                       if (event->event_type == 0 && event->event_size == 0)
+                               return NULL;
+                       addr += sizeof(struct tcpa_event) + event->event_size;
+               }
+       }
+
+       /* now check if current entry is valid */
+       if ((addr + sizeof(struct tcpa_event)) >= limit)
+               return NULL;
+
+       event = addr;
+
+       if ((event->event_type == 0 && event->event_size == 0) ||
+           ((addr + sizeof(struct tcpa_event) + event->event_size) >= limit))
+               return NULL;
+
+       return addr;
+}
+
+static void *tpm_bios_measurements_next(struct seq_file *m, void *v,
+                                       loff_t *pos)
+{
+       struct tcpa_event *event = v;
+       struct tpm_bios_log *log = m->private;
+       void *limit = log->bios_event_log_end;
+
+       v += sizeof(struct tcpa_event) + event->event_size;
+
+       /* now check if current entry is valid */
+       if ((v + sizeof(struct tcpa_event)) >= limit)
+               return NULL;
+
+       event = v;
+
+       if (event->event_type == 0 && event->event_size == 0)
+               return NULL;
+
+       if ((event->event_type == 0 && event->event_size == 0) ||
+           ((v + sizeof(struct tcpa_event) + event->event_size) >= limit))
+               return NULL;
+
+       (*pos)++;
+       return v;
+}
+
+static void tpm_bios_measurements_stop(struct seq_file *m, void *v)
+{
+}
+
+static int get_event_name(char *dest, struct tcpa_event *event,
+                       unsigned char * event_entry)
+{
+       const char *name = "";
+       /* 41 so there is room for 40 data and 1 nul */
+       char data[41] = "";
+       int i, n_len = 0, d_len = 0;
+       struct tcpa_pc_event *pc_event;
+
+       switch(event->event_type) {
+       case PREBOOT:
+       case POST_CODE:
+       case UNUSED:
+       case NO_ACTION:
+       case SCRTM_CONTENTS:
+       case SCRTM_VERSION:
+       case CPU_MICROCODE:
+       case PLATFORM_CONFIG_FLAGS:
+       case TABLE_OF_DEVICES:
+       case COMPACT_HASH:
+       case IPL:
+       case IPL_PARTITION_DATA:
+       case NONHOST_CODE:
+       case NONHOST_CONFIG:
+       case NONHOST_INFO:
+               name = tcpa_event_type_strings[event->event_type];
+               n_len = strlen(name);
+               break;
+       case SEPARATOR:
+       case ACTION:
+               if (MAX_TEXT_EVENT > event->event_size) {
+                       name = event_entry;
+                       n_len = event->event_size;
+               }
+               break;
+       case EVENT_TAG:
+               pc_event = (struct tcpa_pc_event *)event_entry;
+
+               /* ToDo Row data -> Base64 */
+
+               switch (pc_event->event_id) {
+               case SMBIOS:
+               case BIS_CERT:
+               case CMOS:
+               case NVRAM:
+               case OPTION_ROM_EXEC:
+               case OPTION_ROM_CONFIG:
+               case S_CRTM_VERSION:
+                       name = tcpa_pc_event_id_strings[pc_event->event_id];
+                       n_len = strlen(name);
+                       break;
+               /* hash data */
+               case POST_BIOS_ROM:
+               case ESCD:
+               case OPTION_ROM_MICROCODE:
+               case S_CRTM_CONTENTS:
+               case POST_CONTENTS:
+                       name = tcpa_pc_event_id_strings[pc_event->event_id];
+                       n_len = strlen(name);
+                       for (i = 0; i < 20; i++)
+                               d_len += sprintf(&data[2*i], "%02x",
+                                               pc_event->event_data[i]);
+                       break;
+               default:
+                       break;
+               }
+       default:
+               break;
+       }
+
+       return snprintf(dest, MAX_TEXT_EVENT, "[%.*s%.*s]",
+                       n_len, name, d_len, data);
+
+}
+
+static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v)
+{
+       struct tcpa_event *event = v;
+       char *data = v;
+       int i;
+
+       for (i = 0; i < sizeof(struct tcpa_event) + event->event_size; i++)
+               seq_putc(m, data[i]);
+
+       return 0;
+}
+
+static int tpm_bios_measurements_release(struct inode *inode,
+                                        struct file *file)
+{
+       struct seq_file *seq = file->private_data;
+       struct tpm_bios_log *log = seq->private;
+
+       if (log) {
+               kfree(log->bios_event_log);
+               kfree(log);
+       }
+
+       return seq_release(inode, file);
+}
+
+static int tpm_ascii_bios_measurements_show(struct seq_file *m, void *v)
+{
+       int len = 0;
+       int i;
+       char *eventname;
+       struct tcpa_event *event = v;
+       unsigned char *event_entry =
+           (unsigned char *) (v + sizeof(struct tcpa_event));
+
+       eventname = kmalloc(MAX_TEXT_EVENT, GFP_KERNEL);
+       if (!eventname) {
+               printk(KERN_ERR "%s: ERROR - No Memory for event name\n ",
+                      __func__);
+               return -EFAULT;
+       }
+
+       seq_printf(m, "%2d ", event->pcr_index);
+
+       /* 2nd: SHA1 */
+       for (i = 0; i < 20; i++)
+               seq_printf(m, "%02x", event->pcr_value[i]);
+
+       /* 3rd: event type identifier */
+       seq_printf(m, " %02x", event->event_type);
+
+       len += get_event_name(eventname, event, event_entry);
+
+       /* 4th: eventname <= max + \'0' delimiter */
+       seq_printf(m, " %s\n", eventname);
+
+       kfree(eventname);
+       return 0;
+}
+
+static const struct seq_operations tpm_ascii_b_measurments_seqops = {
+       .start = tpm_bios_measurements_start,
+       .next = tpm_bios_measurements_next,
+       .stop = tpm_bios_measurements_stop,
+       .show = tpm_ascii_bios_measurements_show,
+};
+
+static const struct seq_operations tpm_binary_b_measurments_seqops = {
+       .start = tpm_bios_measurements_start,
+       .next = tpm_bios_measurements_next,
+       .stop = tpm_bios_measurements_stop,
+       .show = tpm_binary_bios_measurements_show,
+};
+
+static int tpm_ascii_bios_measurements_open(struct inode *inode,
+                                           struct file *file)
+{
+       int err;
+       struct tpm_bios_log *log;
+       struct seq_file *seq;
+
+       log = kzalloc(sizeof(struct tpm_bios_log), GFP_KERNEL);
+       if (!log)
+               return -ENOMEM;
+
+       if ((err = read_log(log)))
+               goto out_free;
+
+       /* now register seq file */
+       err = seq_open(file, &tpm_ascii_b_measurments_seqops);
+       if (!err) {
+               seq = file->private_data;
+               seq->private = log;
+       } else {
+               goto out_free;
+       }
+
+out:
+       return err;
+out_free:
+       kfree(log->bios_event_log);
+       kfree(log);
+       goto out;
+}
+
+static const struct file_operations tpm_ascii_bios_measurements_ops = {
+       .open = tpm_ascii_bios_measurements_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = tpm_bios_measurements_release,
+};
+
+static int tpm_binary_bios_measurements_open(struct inode *inode,
+                                            struct file *file)
+{
+       int err;
+       struct tpm_bios_log *log;
+       struct seq_file *seq;
+
+       log = kzalloc(sizeof(struct tpm_bios_log), GFP_KERNEL);
+       if (!log)
+               return -ENOMEM;
+
+       if ((err = read_log(log)))
+               goto out_free;
+
+       /* now register seq file */
+       err = seq_open(file, &tpm_binary_b_measurments_seqops);
+       if (!err) {
+               seq = file->private_data;
+               seq->private = log;
+       } else {
+               goto out_free;
+       }
+
+out:
+       return err;
+out_free:
+       kfree(log->bios_event_log);
+       kfree(log);
+       goto out;
+}
+
+static const struct file_operations tpm_binary_bios_measurements_ops = {
+       .open = tpm_binary_bios_measurements_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = tpm_bios_measurements_release,
+};
+
+static int is_bad(void *p)
+{
+       if (!p)
+               return 1;
+       if (IS_ERR(p) && (PTR_ERR(p) != -ENODEV))
+               return 1;
+       return 0;
+}
+
+struct dentry **tpm_bios_log_setup(char *name)
+{
+       struct dentry **ret = NULL, *tpm_dir, *bin_file, *ascii_file;
+
+       tpm_dir = securityfs_create_dir(name, NULL);
+       if (is_bad(tpm_dir))
+               goto out;
+
+       bin_file =
+           securityfs_create_file("binary_bios_measurements",
+                                  S_IRUSR | S_IRGRP, tpm_dir, NULL,
+                                  &tpm_binary_bios_measurements_ops);
+       if (is_bad(bin_file))
+               goto out_tpm;
+
+       ascii_file =
+           securityfs_create_file("ascii_bios_measurements",
+                                  S_IRUSR | S_IRGRP, tpm_dir, NULL,
+                                  &tpm_ascii_bios_measurements_ops);
+       if (is_bad(ascii_file))
+               goto out_bin;
+
+       ret = kmalloc(3 * sizeof(struct dentry *), GFP_KERNEL);
+       if (!ret)
+               goto out_ascii;
+
+       ret[0] = ascii_file;
+       ret[1] = bin_file;
+       ret[2] = tpm_dir;
+
+       return ret;
+
+out_ascii:
+       securityfs_remove(ascii_file);
+out_bin:
+       securityfs_remove(bin_file);
+out_tpm:
+       securityfs_remove(tpm_dir);
+out:
+       return NULL;
+}
+EXPORT_SYMBOL_GPL(tpm_bios_log_setup);
+
+void tpm_bios_log_teardown(struct dentry **lst)
+{
+       int i;
+
+       for (i = 0; i < 3; i++)
+               securityfs_remove(lst[i]);
+}
+EXPORT_SYMBOL_GPL(tpm_bios_log_teardown);
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/tpm/tpm_eventlog.h b/drivers/char/tpm/tpm_eventlog.h
new file mode 100644 (file)
index 0000000..e7da086
--- /dev/null
@@ -0,0 +1,86 @@
+
+#ifndef __TPM_EVENTLOG_H__
+#define __TPM_EVENTLOG_H__
+
+#define TCG_EVENT_NAME_LEN_MAX 255
+#define MAX_TEXT_EVENT         1000    /* Max event string length */
+#define ACPI_TCPA_SIG          "TCPA"  /* 0x41504354 /'TCPA' */
+
+enum bios_platform_class {
+       BIOS_CLIENT = 0x00,
+       BIOS_SERVER = 0x01,
+};
+
+struct tpm_bios_log {
+       void *bios_event_log;
+       void *bios_event_log_end;
+};
+
+struct tcpa_event {
+       u32 pcr_index;
+       u32 event_type;
+       u8 pcr_value[20];       /* SHA1 */
+       u32 event_size;
+       u8 event_data[0];
+};
+
+enum tcpa_event_types {
+       PREBOOT = 0,
+       POST_CODE,
+       UNUSED,
+       NO_ACTION,
+       SEPARATOR,
+       ACTION,
+       EVENT_TAG,
+       SCRTM_CONTENTS,
+       SCRTM_VERSION,
+       CPU_MICROCODE,
+       PLATFORM_CONFIG_FLAGS,
+       TABLE_OF_DEVICES,
+       COMPACT_HASH,
+       IPL,
+       IPL_PARTITION_DATA,
+       NONHOST_CODE,
+       NONHOST_CONFIG,
+       NONHOST_INFO,
+};
+
+struct tcpa_pc_event {
+       u32 event_id;
+       u32 event_size;
+       u8 event_data[0];
+};
+
+enum tcpa_pc_event_ids {
+       SMBIOS = 1,
+       BIS_CERT,
+       POST_BIOS_ROM,
+       ESCD,
+       CMOS,
+       NVRAM,
+       OPTION_ROM_EXEC,
+       OPTION_ROM_CONFIG,
+       OPTION_ROM_MICROCODE = 10,
+       S_CRTM_VERSION,
+       S_CRTM_CONTENTS,
+       POST_CONTENTS,
+       HOST_TABLE_OF_DEVICES,
+};
+
+int read_log(struct tpm_bios_log *log);
+
+#if defined(CONFIG_TCG_IBMVTPM) || defined(CONFIG_TCG_IBMVTPM_MODULE) || \
+       defined(CONFIG_ACPI)
+extern struct dentry **tpm_bios_log_setup(char *);
+extern void tpm_bios_log_teardown(struct dentry **);
+#else
+static inline struct dentry **tpm_bios_log_setup(char *name)
+{
+       return NULL;
+}
+static inline void tpm_bios_log_teardown(struct dentry **dir)
+{
+}
+#endif
+
+#endif
diff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c_infineon.c
new file mode 100644 (file)
index 0000000..5a831ae
--- /dev/null
@@ -0,0 +1,695 @@
+/*
+ * Copyright (C) 2012 Infineon Technologies
+ *
+ * Authors:
+ * Peter Huewe <peter.huewe@infineon.com>
+ *
+ * Device driver for TCG/TCPA TPM (trusted platform module).
+ * Specifications at www.trustedcomputinggroup.org
+ *
+ * This device driver implements the TPM interface as defined in
+ * the TCG TPM Interface Spec version 1.2, revision 1.0 and the
+ * Infineon I2C Protocol Stack Specification v0.20.
+ *
+ * It is based on the original tpm_tis device driver from Leendert van
+ * Dorn and Kyleen Hall.
+ *
+ * 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, version 2 of the
+ * License.
+ *
+ *
+ */
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/wait.h>
+#include "tpm.h"
+
+/* max. buffer size supported by our TPM */
+#define TPM_BUFSIZE 1260
+
+/* max. number of iterations after I2C NAK */
+#define MAX_COUNT 3
+
+#define SLEEP_DURATION_LOW 55
+#define SLEEP_DURATION_HI 65
+
+/* max. number of iterations after I2C NAK for 'long' commands
+ * we need this especially for sending TPM_READY, since the cleanup after the
+ * transtion to the ready state may take some time, but it is unpredictable
+ * how long it will take.
+ */
+#define MAX_COUNT_LONG 50
+
+#define SLEEP_DURATION_LONG_LOW 200
+#define SLEEP_DURATION_LONG_HI 220
+
+/* After sending TPM_READY to 'reset' the TPM we have to sleep even longer */
+#define SLEEP_DURATION_RESET_LOW 2400
+#define SLEEP_DURATION_RESET_HI 2600
+
+/* we want to use usleep_range instead of msleep for the 5ms TPM_TIMEOUT */
+#define TPM_TIMEOUT_US_LOW (TPM_TIMEOUT * 1000)
+#define TPM_TIMEOUT_US_HI  (TPM_TIMEOUT_US_LOW + 2000)
+
+/* expected value for DIDVID register */
+#define TPM_TIS_I2C_DID_VID 0x000b15d1L
+
+/* Structure to store I2C TPM specific stuff */
+struct tpm_inf_dev {
+       struct i2c_client *client;
+       u8 buf[TPM_BUFSIZE + sizeof(u8)]; /* max. buffer size + addr */
+       struct tpm_chip *chip;
+};
+
+static struct tpm_inf_dev tpm_dev;
+static struct i2c_driver tpm_tis_i2c_driver;
+
+/*
+ * iic_tpm_read() - read from TPM register
+ * @addr: register address to read from
+ * @buffer: provided by caller
+ * @len: number of bytes to read
+ *
+ * Read len bytes from TPM register and put them into
+ * buffer (little-endian format, i.e. first byte is put into buffer[0]).
+ *
+ * NOTE: TPM is big-endian for multi-byte values. Multi-byte
+ * values have to be swapped.
+ *
+ * NOTE: We can't unfortunately use the combined read/write functions
+ * provided by the i2c core as the TPM currently does not support the
+ * repeated start condition and due to it's special requirements.
+ * The i2c_smbus* functions do not work for this chip.
+ *
+ * Return -EIO on error, 0 on success.
+ */
+static int iic_tpm_read(u8 addr, u8 *buffer, size_t len)
+{
+
+       struct i2c_msg msg1 = { tpm_dev.client->addr, 0, 1, &addr };
+       struct i2c_msg msg2 = { tpm_dev.client->addr, I2C_M_RD, len, buffer };
+
+       int rc;
+       int count;
+
+       /* Lock the adapter for the duration of the whole sequence. */
+       if (!tpm_dev.client->adapter->algo->master_xfer)
+               return -EOPNOTSUPP;
+       i2c_lock_adapter(tpm_dev.client->adapter);
+
+       for (count = 0; count < MAX_COUNT; count++) {
+               rc = __i2c_transfer(tpm_dev.client->adapter, &msg1, 1);
+               if (rc > 0)
+                       break;  /* break here to skip sleep */
+
+               usleep_range(SLEEP_DURATION_LOW, SLEEP_DURATION_HI);
+       }
+
+       if (rc <= 0)
+               goto out;
+
+       /* After the TPM has successfully received the register address it needs
+        * some time, thus we're sleeping here again, before retrieving the data
+        */
+       for (count = 0; count < MAX_COUNT; count++) {
+               usleep_range(SLEEP_DURATION_LOW, SLEEP_DURATION_HI);
+               rc = __i2c_transfer(tpm_dev.client->adapter, &msg2, 1);
+               if (rc > 0)
+                       break;
+
+       }
+
+out:
+       i2c_unlock_adapter(tpm_dev.client->adapter);
+       if (rc <= 0)
+               return -EIO;
+
+       return 0;
+}
+
+static int iic_tpm_write_generic(u8 addr, u8 *buffer, size_t len,
+                                unsigned int sleep_low,
+                                unsigned int sleep_hi, u8 max_count)
+{
+       int rc = -EIO;
+       int count;
+
+       struct i2c_msg msg1 = { tpm_dev.client->addr, 0, len + 1, tpm_dev.buf };
+
+       if (len > TPM_BUFSIZE)
+               return -EINVAL;
+
+       if (!tpm_dev.client->adapter->algo->master_xfer)
+               return -EOPNOTSUPP;
+       i2c_lock_adapter(tpm_dev.client->adapter);
+
+       /* prepend the 'register address' to the buffer */
+       tpm_dev.buf[0] = addr;
+       memcpy(&(tpm_dev.buf[1]), buffer, len);
+
+       /*
+        * NOTE: We have to use these special mechanisms here and unfortunately
+        * cannot rely on the standard behavior of i2c_transfer.
+        */
+       for (count = 0; count < max_count; count++) {
+               rc = __i2c_transfer(tpm_dev.client->adapter, &msg1, 1);
+               if (rc > 0)
+                       break;
+
+               usleep_range(sleep_low, sleep_hi);
+       }
+
+       i2c_unlock_adapter(tpm_dev.client->adapter);
+       if (rc <= 0)
+               return -EIO;
+
+       return 0;
+}
+
+/*
+ * iic_tpm_write() - write to TPM register
+ * @addr: register address to write to
+ * @buffer: containing data to be written
+ * @len: number of bytes to write
+ *
+ * Write len bytes from provided buffer to TPM register (little
+ * endian format, i.e. buffer[0] is written as first byte).
+ *
+ * NOTE: TPM is big-endian for multi-byte values. Multi-byte
+ * values have to be swapped.
+ *
+ * NOTE: use this function instead of the iic_tpm_write_generic function.
+ *
+ * Return -EIO on error, 0 on success
+ */
+static int iic_tpm_write(u8 addr, u8 *buffer, size_t len)
+{
+       return iic_tpm_write_generic(addr, buffer, len, SLEEP_DURATION_LOW,
+                                    SLEEP_DURATION_HI, MAX_COUNT);
+}
+
+/*
+ * This function is needed especially for the cleanup situation after
+ * sending TPM_READY
+ * */
+static int iic_tpm_write_long(u8 addr, u8 *buffer, size_t len)
+{
+       return iic_tpm_write_generic(addr, buffer, len, SLEEP_DURATION_LONG_LOW,
+                                    SLEEP_DURATION_LONG_HI, MAX_COUNT_LONG);
+}
+
+enum tis_access {
+       TPM_ACCESS_VALID = 0x80,
+       TPM_ACCESS_ACTIVE_LOCALITY = 0x20,
+       TPM_ACCESS_REQUEST_PENDING = 0x04,
+       TPM_ACCESS_REQUEST_USE = 0x02,
+};
+
+enum tis_status {
+       TPM_STS_VALID = 0x80,
+       TPM_STS_COMMAND_READY = 0x40,
+       TPM_STS_GO = 0x20,
+       TPM_STS_DATA_AVAIL = 0x10,
+       TPM_STS_DATA_EXPECT = 0x08,
+};
+
+enum tis_defaults {
+       TIS_SHORT_TIMEOUT = 750,        /* ms */
+       TIS_LONG_TIMEOUT = 2000,        /* 2 sec */
+};
+
+#define        TPM_ACCESS(l)                   (0x0000 | ((l) << 4))
+#define        TPM_STS(l)                      (0x0001 | ((l) << 4))
+#define        TPM_DATA_FIFO(l)                (0x0005 | ((l) << 4))
+#define        TPM_DID_VID(l)                  (0x0006 | ((l) << 4))
+
+static int check_locality(struct tpm_chip *chip, int loc)
+{
+       u8 buf;
+       int rc;
+
+       rc = iic_tpm_read(TPM_ACCESS(loc), &buf, 1);
+       if (rc < 0)
+               return rc;
+
+       if ((buf & (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) ==
+           (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) {
+               chip->vendor.locality = loc;
+               return loc;
+       }
+
+       return -EIO;
+}
+
+/* implementation similar to tpm_tis */
+static void release_locality(struct tpm_chip *chip, int loc, int force)
+{
+       u8 buf;
+       if (iic_tpm_read(TPM_ACCESS(loc), &buf, 1) < 0)
+               return;
+
+       if (force || (buf & (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) ==
+           (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) {
+               buf = TPM_ACCESS_ACTIVE_LOCALITY;
+               iic_tpm_write(TPM_ACCESS(loc), &buf, 1);
+       }
+}
+
+static int request_locality(struct tpm_chip *chip, int loc)
+{
+       unsigned long stop;
+       u8 buf = TPM_ACCESS_REQUEST_USE;
+
+       if (check_locality(chip, loc) >= 0)
+               return loc;
+
+       iic_tpm_write(TPM_ACCESS(loc), &buf, 1);
+
+       /* wait for burstcount */
+       stop = jiffies + chip->vendor.timeout_a;
+       do {
+               if (check_locality(chip, loc) >= 0)
+                       return loc;
+               usleep_range(TPM_TIMEOUT_US_LOW, TPM_TIMEOUT_US_HI);
+       } while (time_before(jiffies, stop));
+
+       return -ETIME;
+}
+
+static u8 tpm_tis_i2c_status(struct tpm_chip *chip)
+{
+       /* NOTE: since I2C read may fail, return 0 in this case --> time-out */
+       u8 buf;
+       if (iic_tpm_read(TPM_STS(chip->vendor.locality), &buf, 1) < 0)
+               return 0;
+       else
+               return buf;
+}
+
+static void tpm_tis_i2c_ready(struct tpm_chip *chip)
+{
+       /* this causes the current command to be aborted */
+       u8 buf = TPM_STS_COMMAND_READY;
+       iic_tpm_write_long(TPM_STS(chip->vendor.locality), &buf, 1);
+}
+
+static ssize_t get_burstcount(struct tpm_chip *chip)
+{
+       unsigned long stop;
+       ssize_t burstcnt;
+       u8 buf[3];
+
+       /* wait for burstcount */
+       /* which timeout value, spec has 2 answers (c & d) */
+       stop = jiffies + chip->vendor.timeout_d;
+       do {
+               /* Note: STS is little endian */
+               if (iic_tpm_read(TPM_STS(chip->vendor.locality)+1, buf, 3) < 0)
+                       burstcnt = 0;
+               else
+                       burstcnt = (buf[2] << 16) + (buf[1] << 8) + buf[0];
+
+               if (burstcnt)
+                       return burstcnt;
+
+               usleep_range(TPM_TIMEOUT_US_LOW, TPM_TIMEOUT_US_HI);
+       } while (time_before(jiffies, stop));
+       return -EBUSY;
+}
+
+static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
+                        int *status)
+{
+       unsigned long stop;
+
+       /* check current status */
+       *status = tpm_tis_i2c_status(chip);
+       if ((*status & mask) == mask)
+               return 0;
+
+       stop = jiffies + timeout;
+       do {
+               /* since we just checked the status, give the TPM some time */
+               usleep_range(TPM_TIMEOUT_US_LOW, TPM_TIMEOUT_US_HI);
+               *status = tpm_tis_i2c_status(chip);
+               if ((*status & mask) == mask)
+                       return 0;
+
+       } while (time_before(jiffies, stop));
+
+       return -ETIME;
+}
+
+static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count)
+{
+       size_t size = 0;
+       ssize_t burstcnt;
+       u8 retries = 0;
+       int rc;
+
+       while (size < count) {
+               burstcnt = get_burstcount(chip);
+
+               /* burstcnt < 0 = TPM is busy */
+               if (burstcnt < 0)
+                       return burstcnt;
+
+               /* limit received data to max. left */
+               if (burstcnt > (count - size))
+                       burstcnt = count - size;
+
+               rc = iic_tpm_read(TPM_DATA_FIFO(chip->vendor.locality),
+                                 &(buf[size]), burstcnt);
+               if (rc == 0)
+                       size += burstcnt;
+               else if (rc < 0)
+                       retries++;
+
+               /* avoid endless loop in case of broken HW */
+               if (retries > MAX_COUNT_LONG)
+                       return -EIO;
+
+       }
+       return size;
+}
+
+static int tpm_tis_i2c_recv(struct tpm_chip *chip, u8 *buf, size_t count)
+{
+       int size = 0;
+       int expected, status;
+
+       if (count < TPM_HEADER_SIZE) {
+               size = -EIO;
+               goto out;
+       }
+
+       /* read first 10 bytes, including tag, paramsize, and result */
+       size = recv_data(chip, buf, TPM_HEADER_SIZE);
+       if (size < TPM_HEADER_SIZE) {
+               dev_err(chip->dev, "Unable to read header\n");
+               goto out;
+       }
+
+       expected = be32_to_cpu(*(__be32 *)(buf + 2));
+       if ((size_t) expected > count) {
+               size = -EIO;
+               goto out;
+       }
+
+       size += recv_data(chip, &buf[TPM_HEADER_SIZE],
+                         expected - TPM_HEADER_SIZE);
+       if (size < expected) {
+               dev_err(chip->dev, "Unable to read remainder of result\n");
+               size = -ETIME;
+               goto out;
+       }
+
+       wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, &status);
+       if (status & TPM_STS_DATA_AVAIL) {      /* retry? */
+               dev_err(chip->dev, "Error left over data\n");
+               size = -EIO;
+               goto out;
+       }
+
+out:
+       tpm_tis_i2c_ready(chip);
+       /* The TPM needs some time to clean up here,
+        * so we sleep rather than keeping the bus busy
+        */
+       usleep_range(SLEEP_DURATION_RESET_LOW, SLEEP_DURATION_RESET_HI);
+       release_locality(chip, chip->vendor.locality, 0);
+       return size;
+}
+
+static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len)
+{
+       int rc, status;
+       ssize_t burstcnt;
+       size_t count = 0;
+       u8 retries = 0;
+       u8 sts = TPM_STS_GO;
+
+       if (len > TPM_BUFSIZE)
+               return -E2BIG;  /* command is too long for our tpm, sorry */
+
+       if (request_locality(chip, 0) < 0)
+               return -EBUSY;
+
+       status = tpm_tis_i2c_status(chip);
+       if ((status & TPM_STS_COMMAND_READY) == 0) {
+               tpm_tis_i2c_ready(chip);
+               if (wait_for_stat
+                   (chip, TPM_STS_COMMAND_READY,
+                    chip->vendor.timeout_b, &status) < 0) {
+                       rc = -ETIME;
+                       goto out_err;
+               }
+       }
+
+       while (count < len - 1) {
+               burstcnt = get_burstcount(chip);
+
+               /* burstcnt < 0 = TPM is busy */
+               if (burstcnt < 0)
+                       return burstcnt;
+
+               if (burstcnt > (len - 1 - count))
+                       burstcnt = len - 1 - count;
+
+               rc = iic_tpm_write(TPM_DATA_FIFO(chip->vendor.locality),
+                                  &(buf[count]), burstcnt);
+               if (rc == 0)
+                       count += burstcnt;
+               else if (rc < 0)
+                       retries++;
+
+               /* avoid endless loop in case of broken HW */
+               if (retries > MAX_COUNT_LONG) {
+                       rc = -EIO;
+                       goto out_err;
+               }
+
+               wait_for_stat(chip, TPM_STS_VALID,
+                             chip->vendor.timeout_c, &status);
+
+               if ((status & TPM_STS_DATA_EXPECT) == 0) {
+                       rc = -EIO;
+                       goto out_err;
+               }
+
+       }
+
+       /* write last byte */
+       iic_tpm_write(TPM_DATA_FIFO(chip->vendor.locality), &(buf[count]), 1);
+       wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, &status);
+       if ((status & TPM_STS_DATA_EXPECT) != 0) {
+               rc = -EIO;
+               goto out_err;
+       }
+
+       /* go and do it */
+       iic_tpm_write(TPM_STS(chip->vendor.locality), &sts, 1);
+
+       return len;
+out_err:
+       tpm_tis_i2c_ready(chip);
+       /* The TPM needs some time to clean up here,
+        * so we sleep rather than keeping the bus busy
+        */
+       usleep_range(SLEEP_DURATION_RESET_LOW, SLEEP_DURATION_RESET_HI);
+       release_locality(chip, chip->vendor.locality, 0);
+       return rc;
+}
+
+static const struct file_operations tis_ops = {
+       .owner = THIS_MODULE,
+       .llseek = no_llseek,
+       .open = tpm_open,
+       .read = tpm_read,
+       .write = tpm_write,
+       .release = tpm_release,
+};
+
+static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
+static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL);
+static DEVICE_ATTR(enabled, S_IRUGO, tpm_show_enabled, NULL);
+static DEVICE_ATTR(active, S_IRUGO, tpm_show_active, NULL);
+static DEVICE_ATTR(owned, S_IRUGO, tpm_show_owned, NULL);
+static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated, NULL);
+static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps_1_2, NULL);
+static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel);
+static DEVICE_ATTR(durations, S_IRUGO, tpm_show_durations, NULL);
+static DEVICE_ATTR(timeouts, S_IRUGO, tpm_show_timeouts, NULL);
+
+static struct attribute *tis_attrs[] = {
+       &dev_attr_pubek.attr,
+       &dev_attr_pcrs.attr,
+       &dev_attr_enabled.attr,
+       &dev_attr_active.attr,
+       &dev_attr_owned.attr,
+       &dev_attr_temp_deactivated.attr,
+       &dev_attr_caps.attr,
+       &dev_attr_cancel.attr,
+       &dev_attr_durations.attr,
+       &dev_attr_timeouts.attr,
+       NULL,
+};
+
+static struct attribute_group tis_attr_grp = {
+       .attrs = tis_attrs
+};
+
+static struct tpm_vendor_specific tpm_tis_i2c = {
+       .status = tpm_tis_i2c_status,
+       .recv = tpm_tis_i2c_recv,
+       .send = tpm_tis_i2c_send,
+       .cancel = tpm_tis_i2c_ready,
+       .req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
+       .req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
+       .req_canceled = TPM_STS_COMMAND_READY,
+       .attr_group = &tis_attr_grp,
+       .miscdev.fops = &tis_ops,
+};
+
+static int __devinit tpm_tis_i2c_init(struct device *dev)
+{
+       u32 vendor;
+       int rc = 0;
+       struct tpm_chip *chip;
+
+       chip = tpm_register_hardware(dev, &tpm_tis_i2c);
+       if (!chip) {
+               rc = -ENODEV;
+               goto out_err;
+       }
+
+       /* Disable interrupts */
+       chip->vendor.irq = 0;
+
+       /* Default timeouts */
+       chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
+       chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT);
+       chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
+       chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
+
+       if (request_locality(chip, 0) != 0) {
+               rc = -ENODEV;
+               goto out_vendor;
+       }
+
+       /* read four bytes from DID_VID register */
+       if (iic_tpm_read(TPM_DID_VID(0), (u8 *)&vendor, 4) < 0) {
+               rc = -EIO;
+               goto out_release;
+       }
+
+       /* create DID_VID register value, after swapping to little-endian */
+       vendor = be32_to_cpu((__be32) vendor);
+
+       if (vendor != TPM_TIS_I2C_DID_VID) {
+               rc = -ENODEV;
+               goto out_release;
+       }
+
+       dev_info(dev, "1.2 TPM (device-id 0x%X)\n", vendor >> 16);
+
+       INIT_LIST_HEAD(&chip->vendor.list);
+       tpm_dev.chip = chip;
+
+       tpm_get_timeouts(chip);
+       tpm_do_selftest(chip);
+
+       return 0;
+
+out_release:
+       release_locality(chip, chip->vendor.locality, 1);
+
+out_vendor:
+       /* close file handles */
+       tpm_dev_vendor_release(chip);
+
+       /* remove hardware */
+       tpm_remove_hardware(chip->dev);
+
+       /* reset these pointers, otherwise we oops */
+       chip->dev->release = NULL;
+       chip->release = NULL;
+       tpm_dev.client = NULL;
+       dev_set_drvdata(chip->dev, chip);
+out_err:
+       return rc;
+}
+
+static const struct i2c_device_id tpm_tis_i2c_table[] = {
+       {"tpm_i2c_infineon", 0},
+       {},
+};
+
+MODULE_DEVICE_TABLE(i2c, tpm_tis_i2c_table);
+static SIMPLE_DEV_PM_OPS(tpm_tis_i2c_ops, tpm_pm_suspend, tpm_pm_resume);
+
+static int __devinit tpm_tis_i2c_probe(struct i2c_client *client,
+                            const struct i2c_device_id *id)
+{
+       int rc;
+       if (tpm_dev.client != NULL)
+               return -EBUSY;  /* We only support one client */
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+               dev_err(&client->dev,
+                       "no algorithms associated to the i2c bus\n");
+               return -ENODEV;
+       }
+
+       client->driver = &tpm_tis_i2c_driver;
+       tpm_dev.client = client;
+       rc = tpm_tis_i2c_init(&client->dev);
+       if (rc != 0) {
+               client->driver = NULL;
+               tpm_dev.client = NULL;
+               rc = -ENODEV;
+       }
+       return rc;
+}
+
+static int __devexit tpm_tis_i2c_remove(struct i2c_client *client)
+{
+       struct tpm_chip *chip = tpm_dev.chip;
+       release_locality(chip, chip->vendor.locality, 1);
+
+       /* close file handles */
+       tpm_dev_vendor_release(chip);
+
+       /* remove hardware */
+       tpm_remove_hardware(chip->dev);
+
+       /* reset these pointers, otherwise we oops */
+       chip->dev->release = NULL;
+       chip->release = NULL;
+       tpm_dev.client = NULL;
+       dev_set_drvdata(chip->dev, chip);
+
+       return 0;
+}
+
+static struct i2c_driver tpm_tis_i2c_driver = {
+
+       .id_table = tpm_tis_i2c_table,
+       .probe = tpm_tis_i2c_probe,
+       .remove = tpm_tis_i2c_remove,
+       .driver = {
+                  .name = "tpm_i2c_infineon",
+                  .owner = THIS_MODULE,
+                  .pm = &tpm_tis_i2c_ops,
+                  },
+};
+
+module_i2c_driver(tpm_tis_i2c_driver);
+MODULE_AUTHOR("Peter Huewe <peter.huewe@infineon.com>");
+MODULE_DESCRIPTION("TPM TIS I2C Infineon Driver");
+MODULE_VERSION("2.1.5");
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/tpm/tpm_ibmvtpm.c b/drivers/char/tpm/tpm_ibmvtpm.c
new file mode 100644 (file)
index 0000000..efc4ab3
--- /dev/null
@@ -0,0 +1,749 @@
+/*
+ * Copyright (C) 2012 IBM Corporation
+ *
+ * Author: Ashley Lai <adlai@us.ibm.com>
+ *
+ * Maintained by: <tpmdd-devel@lists.sourceforge.net>
+ *
+ * Device driver for TCG/TCPA TPM (trusted platform module).
+ * Specifications at www.trustedcomputinggroup.org
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/dmapool.h>
+#include <linux/slab.h>
+#include <asm/vio.h>
+#include <asm/irq.h>
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/wait.h>
+#include <asm/prom.h>
+
+#include "tpm.h"
+#include "tpm_ibmvtpm.h"
+
+static const char tpm_ibmvtpm_driver_name[] = "tpm_ibmvtpm";
+
+static struct vio_device_id tpm_ibmvtpm_device_table[] __devinitdata = {
+       { "IBM,vtpm", "IBM,vtpm"},
+       { "", "" }
+};
+MODULE_DEVICE_TABLE(vio, tpm_ibmvtpm_device_table);
+
+DECLARE_WAIT_QUEUE_HEAD(wq);
+
+/**
+ * ibmvtpm_send_crq - Send a CRQ request
+ * @vdev:      vio device struct
+ * @w1:                first word
+ * @w2:                second word
+ *
+ * Return value:
+ *     0 -Sucess
+ *     Non-zero - Failure
+ */
+static int ibmvtpm_send_crq(struct vio_dev *vdev, u64 w1, u64 w2)
+{
+       return plpar_hcall_norets(H_SEND_CRQ, vdev->unit_address, w1, w2);
+}
+
+/**
+ * ibmvtpm_get_data - Retrieve ibm vtpm data
+ * @dev:       device struct
+ *
+ * Return value:
+ *     vtpm device struct
+ */
+static struct ibmvtpm_dev *ibmvtpm_get_data(const struct device *dev)
+{
+       struct tpm_chip *chip = dev_get_drvdata(dev);
+       if (chip)
+               return (struct ibmvtpm_dev *)chip->vendor.data;
+       return NULL;
+}
+
+/**
+ * tpm_ibmvtpm_recv - Receive data after send
+ * @chip:      tpm chip struct
+ * @buf:       buffer to read
+ * count:      size of buffer
+ *
+ * Return value:
+ *     Number of bytes read
+ */
+static int tpm_ibmvtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count)
+{
+       struct ibmvtpm_dev *ibmvtpm;
+       u16 len;
+
+       ibmvtpm = (struct ibmvtpm_dev *)chip->vendor.data;
+
+       if (!ibmvtpm->rtce_buf) {
+               dev_err(ibmvtpm->dev, "ibmvtpm device is not ready\n");
+               return 0;
+       }
+
+       wait_event_interruptible(wq, ibmvtpm->crq_res.len != 0);
+
+       if (count < ibmvtpm->crq_res.len) {
+               dev_err(ibmvtpm->dev,
+                       "Invalid size in recv: count=%ld, crq_size=%d\n",
+                       count, ibmvtpm->crq_res.len);
+               return -EIO;
+       }
+
+       spin_lock(&ibmvtpm->rtce_lock);
+       memcpy((void *)buf, (void *)ibmvtpm->rtce_buf, ibmvtpm->crq_res.len);
+       memset(ibmvtpm->rtce_buf, 0, ibmvtpm->crq_res.len);
+       ibmvtpm->crq_res.valid = 0;
+       ibmvtpm->crq_res.msg = 0;
+       len = ibmvtpm->crq_res.len;
+       ibmvtpm->crq_res.len = 0;
+       spin_unlock(&ibmvtpm->rtce_lock);
+       return len;
+}
+
+/**
+ * tpm_ibmvtpm_send - Send tpm request
+ * @chip:      tpm chip struct
+ * @buf:       buffer contains data to send
+ * count:      size of buffer
+ *
+ * Return value:
+ *     Number of bytes sent
+ */
+static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
+{
+       struct ibmvtpm_dev *ibmvtpm;
+       struct ibmvtpm_crq crq;
+       u64 *word = (u64 *) &crq;
+       int rc;
+
+       ibmvtpm = (struct ibmvtpm_dev *)chip->vendor.data;
+
+       if (!ibmvtpm->rtce_buf) {
+               dev_err(ibmvtpm->dev, "ibmvtpm device is not ready\n");
+               return 0;
+       }
+
+       if (count > ibmvtpm->rtce_size) {
+               dev_err(ibmvtpm->dev,
+                       "Invalid size in send: count=%ld, rtce_size=%d\n",
+                       count, ibmvtpm->rtce_size);
+               return -EIO;
+       }
+
+       spin_lock(&ibmvtpm->rtce_lock);
+       memcpy((void *)ibmvtpm->rtce_buf, (void *)buf, count);
+       crq.valid = (u8)IBMVTPM_VALID_CMD;
+       crq.msg = (u8)VTPM_TPM_COMMAND;
+       crq.len = (u16)count;
+       crq.data = ibmvtpm->rtce_dma_handle;
+
+       rc = ibmvtpm_send_crq(ibmvtpm->vdev, word[0], word[1]);
+       if (rc != H_SUCCESS) {
+               dev_err(ibmvtpm->dev, "tpm_ibmvtpm_send failed rc=%d\n", rc);
+               rc = 0;
+       } else
+               rc = count;
+
+       spin_unlock(&ibmvtpm->rtce_lock);
+       return rc;
+}
+
+static void tpm_ibmvtpm_cancel(struct tpm_chip *chip)
+{
+       return;
+}
+
+static u8 tpm_ibmvtpm_status(struct tpm_chip *chip)
+{
+       return 0;
+}
+
+/**
+ * ibmvtpm_crq_get_rtce_size - Send a CRQ request to get rtce size
+ * @ibmvtpm:   vtpm device struct
+ *
+ * Return value:
+ *     0 - Success
+ *     Non-zero - Failure
+ */
+static int ibmvtpm_crq_get_rtce_size(struct ibmvtpm_dev *ibmvtpm)
+{
+       struct ibmvtpm_crq crq;
+       u64 *buf = (u64 *) &crq;
+       int rc;
+
+       crq.valid = (u8)IBMVTPM_VALID_CMD;
+       crq.msg = (u8)VTPM_GET_RTCE_BUFFER_SIZE;
+
+       rc = ibmvtpm_send_crq(ibmvtpm->vdev, buf[0], buf[1]);
+       if (rc != H_SUCCESS)
+               dev_err(ibmvtpm->dev,
+                       "ibmvtpm_crq_get_rtce_size failed rc=%d\n", rc);
+
+       return rc;
+}
+
+/**
+ * ibmvtpm_crq_get_version - Send a CRQ request to get vtpm version
+ *                        - Note that this is vtpm version and not tpm version
+ * @ibmvtpm:   vtpm device struct
+ *
+ * Return value:
+ *     0 - Success
+ *     Non-zero - Failure
+ */
+static int ibmvtpm_crq_get_version(struct ibmvtpm_dev *ibmvtpm)
+{
+       struct ibmvtpm_crq crq;
+       u64 *buf = (u64 *) &crq;
+       int rc;
+
+       crq.valid = (u8)IBMVTPM_VALID_CMD;
+       crq.msg = (u8)VTPM_GET_VERSION;
+
+       rc = ibmvtpm_send_crq(ibmvtpm->vdev, buf[0], buf[1]);
+       if (rc != H_SUCCESS)
+               dev_err(ibmvtpm->dev,
+                       "ibmvtpm_crq_get_version failed rc=%d\n", rc);
+
+       return rc;
+}
+
+/**
+ * ibmvtpm_crq_send_init_complete - Send a CRQ initialize complete message
+ * @ibmvtpm:   vtpm device struct
+ *
+ * Return value:
+ *     0 - Success
+ *     Non-zero - Failure
+ */
+static int ibmvtpm_crq_send_init_complete(struct ibmvtpm_dev *ibmvtpm)
+{
+       int rc;
+
+       rc = ibmvtpm_send_crq(ibmvtpm->vdev, INIT_CRQ_COMP_CMD, 0);
+       if (rc != H_SUCCESS)
+               dev_err(ibmvtpm->dev,
+                       "ibmvtpm_crq_send_init_complete failed rc=%d\n", rc);
+
+       return rc;
+}
+
+/**
+ * ibmvtpm_crq_send_init - Send a CRQ initialize message
+ * @ibmvtpm:   vtpm device struct
+ *
+ * Return value:
+ *     0 - Success
+ *     Non-zero - Failure
+ */
+static int ibmvtpm_crq_send_init(struct ibmvtpm_dev *ibmvtpm)
+{
+       int rc;
+
+       rc = ibmvtpm_send_crq(ibmvtpm->vdev, INIT_CRQ_CMD, 0);
+       if (rc != H_SUCCESS)
+               dev_err(ibmvtpm->dev,
+                       "ibmvtpm_crq_send_init failed rc=%d\n", rc);
+
+       return rc;
+}
+
+/**
+ * tpm_ibmvtpm_remove - ibm vtpm remove entry point
+ * @vdev:      vio device struct
+ *
+ * Return value:
+ *     0
+ */
+static int __devexit tpm_ibmvtpm_remove(struct vio_dev *vdev)
+{
+       struct ibmvtpm_dev *ibmvtpm = ibmvtpm_get_data(&vdev->dev);
+       int rc = 0;
+
+       free_irq(vdev->irq, ibmvtpm);
+       tasklet_kill(&ibmvtpm->tasklet);
+
+       do {
+               if (rc)
+                       msleep(100);
+               rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address);
+       } while (rc == H_BUSY || H_IS_LONG_BUSY(rc));
+
+       dma_unmap_single(ibmvtpm->dev, ibmvtpm->crq_dma_handle,
+                        CRQ_RES_BUF_SIZE, DMA_BIDIRECTIONAL);
+       free_page((unsigned long)ibmvtpm->crq_queue.crq_addr);
+
+       if (ibmvtpm->rtce_buf) {
+               dma_unmap_single(ibmvtpm->dev, ibmvtpm->rtce_dma_handle,
+                                ibmvtpm->rtce_size, DMA_BIDIRECTIONAL);
+               kfree(ibmvtpm->rtce_buf);
+       }
+
+       tpm_remove_hardware(ibmvtpm->dev);
+
+       kfree(ibmvtpm);
+
+       return 0;
+}
+
+/**
+ * tpm_ibmvtpm_get_desired_dma - Get DMA size needed by this driver
+ * @vdev:      vio device struct
+ *
+ * Return value:
+ *     Number of bytes the driver needs to DMA map
+ */
+static unsigned long tpm_ibmvtpm_get_desired_dma(struct vio_dev *vdev)
+{
+       struct ibmvtpm_dev *ibmvtpm = ibmvtpm_get_data(&vdev->dev);
+       return CRQ_RES_BUF_SIZE + ibmvtpm->rtce_size;
+}
+
+/**
+ * tpm_ibmvtpm_suspend - Suspend
+ * @dev:       device struct
+ *
+ * Return value:
+ *     0
+ */
+static int tpm_ibmvtpm_suspend(struct device *dev)
+{
+       struct ibmvtpm_dev *ibmvtpm = ibmvtpm_get_data(dev);
+       struct ibmvtpm_crq crq;
+       u64 *buf = (u64 *) &crq;
+       int rc = 0;
+
+       crq.valid = (u8)IBMVTPM_VALID_CMD;
+       crq.msg = (u8)VTPM_PREPARE_TO_SUSPEND;
+
+       rc = ibmvtpm_send_crq(ibmvtpm->vdev, buf[0], buf[1]);
+       if (rc != H_SUCCESS)
+               dev_err(ibmvtpm->dev,
+                       "tpm_ibmvtpm_suspend failed rc=%d\n", rc);
+
+       return rc;
+}
+
+/**
+ * ibmvtpm_reset_crq - Reset CRQ
+ * @ibmvtpm:   ibm vtpm struct
+ *
+ * Return value:
+ *     0 - Success
+ *     Non-zero - Failure
+ */
+static int ibmvtpm_reset_crq(struct ibmvtpm_dev *ibmvtpm)
+{
+       int rc = 0;
+
+       do {
+               if (rc)
+                       msleep(100);
+               rc = plpar_hcall_norets(H_FREE_CRQ,
+                                       ibmvtpm->vdev->unit_address);
+       } while (rc == H_BUSY || H_IS_LONG_BUSY(rc));
+
+       memset(ibmvtpm->crq_queue.crq_addr, 0, CRQ_RES_BUF_SIZE);
+       ibmvtpm->crq_queue.index = 0;
+
+       return plpar_hcall_norets(H_REG_CRQ, ibmvtpm->vdev->unit_address,
+                                 ibmvtpm->crq_dma_handle, CRQ_RES_BUF_SIZE);
+}
+
+/**
+ * tpm_ibmvtpm_resume - Resume from suspend
+ * @dev:       device struct
+ *
+ * Return value:
+ *     0
+ */
+static int tpm_ibmvtpm_resume(struct device *dev)
+{
+       struct ibmvtpm_dev *ibmvtpm = ibmvtpm_get_data(dev);
+       unsigned long flags;
+       int rc = 0;
+
+       do {
+               if (rc)
+                       msleep(100);
+               rc = plpar_hcall_norets(H_ENABLE_CRQ,
+                                       ibmvtpm->vdev->unit_address);
+       } while (rc == H_IN_PROGRESS || rc == H_BUSY || H_IS_LONG_BUSY(rc));
+
+       if (rc) {
+               dev_err(dev, "Error enabling ibmvtpm rc=%d\n", rc);
+               return rc;
+       }
+
+       spin_lock_irqsave(&ibmvtpm->lock, flags);
+       vio_disable_interrupts(ibmvtpm->vdev);
+       tasklet_schedule(&ibmvtpm->tasklet);
+       spin_unlock_irqrestore(&ibmvtpm->lock, flags);
+
+       rc = ibmvtpm_crq_send_init(ibmvtpm);
+       if (rc)
+               dev_err(dev, "Error send_init rc=%d\n", rc);
+
+       return rc;
+}
+
+static const struct file_operations ibmvtpm_ops = {
+       .owner = THIS_MODULE,
+       .llseek = no_llseek,
+       .open = tpm_open,
+       .read = tpm_read,
+       .write = tpm_write,
+       .release = tpm_release,
+};
+
+static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
+static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL);
+static DEVICE_ATTR(enabled, S_IRUGO, tpm_show_enabled, NULL);
+static DEVICE_ATTR(active, S_IRUGO, tpm_show_active, NULL);
+static DEVICE_ATTR(owned, S_IRUGO, tpm_show_owned, NULL);
+static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated,
+                  NULL);
+static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps_1_2, NULL);
+static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel);
+static DEVICE_ATTR(durations, S_IRUGO, tpm_show_durations, NULL);
+static DEVICE_ATTR(timeouts, S_IRUGO, tpm_show_timeouts, NULL);
+
+static struct attribute *ibmvtpm_attrs[] = {
+       &dev_attr_pubek.attr,
+       &dev_attr_pcrs.attr,
+       &dev_attr_enabled.attr,
+       &dev_attr_active.attr,
+       &dev_attr_owned.attr,
+       &dev_attr_temp_deactivated.attr,
+       &dev_attr_caps.attr,
+       &dev_attr_cancel.attr,
+       &dev_attr_durations.attr,
+       &dev_attr_timeouts.attr, NULL,
+};
+
+static struct attribute_group ibmvtpm_attr_grp = { .attrs = ibmvtpm_attrs };
+
+static const struct tpm_vendor_specific tpm_ibmvtpm = {
+       .recv = tpm_ibmvtpm_recv,
+       .send = tpm_ibmvtpm_send,
+       .cancel = tpm_ibmvtpm_cancel,
+       .status = tpm_ibmvtpm_status,
+       .req_complete_mask = 0,
+       .req_complete_val = 0,
+       .req_canceled = 0,
+       .attr_group = &ibmvtpm_attr_grp,
+       .miscdev = { .fops = &ibmvtpm_ops, },
+};
+
+static const struct dev_pm_ops tpm_ibmvtpm_pm_ops = {
+       .suspend = tpm_ibmvtpm_suspend,
+       .resume = tpm_ibmvtpm_resume,
+};
+
+/**
+ * ibmvtpm_crq_get_next - Get next responded crq
+ * @ibmvtpm    vtpm device struct
+ *
+ * Return value:
+ *     vtpm crq pointer
+ */
+static struct ibmvtpm_crq *ibmvtpm_crq_get_next(struct ibmvtpm_dev *ibmvtpm)
+{
+       struct ibmvtpm_crq_queue *crq_q = &ibmvtpm->crq_queue;
+       struct ibmvtpm_crq *crq = &crq_q->crq_addr[crq_q->index];
+
+       if (crq->valid & VTPM_MSG_RES) {
+               if (++crq_q->index == crq_q->num_entry)
+                       crq_q->index = 0;
+               rmb();
+       } else
+               crq = NULL;
+       return crq;
+}
+
+/**
+ * ibmvtpm_crq_process - Process responded crq
+ * @crq                crq to be processed
+ * @ibmvtpm    vtpm device struct
+ *
+ * Return value:
+ *     Nothing
+ */
+static void ibmvtpm_crq_process(struct ibmvtpm_crq *crq,
+                               struct ibmvtpm_dev *ibmvtpm)
+{
+       int rc = 0;
+
+       switch (crq->valid) {
+       case VALID_INIT_CRQ:
+               switch (crq->msg) {
+               case INIT_CRQ_RES:
+                       dev_info(ibmvtpm->dev, "CRQ initialized\n");
+                       rc = ibmvtpm_crq_send_init_complete(ibmvtpm);
+                       if (rc)
+                               dev_err(ibmvtpm->dev, "Unable to send CRQ init complete rc=%d\n", rc);
+                       return;
+               case INIT_CRQ_COMP_RES:
+                       dev_info(ibmvtpm->dev,
+                                "CRQ initialization completed\n");
+                       return;
+               default:
+                       dev_err(ibmvtpm->dev, "Unknown crq message type: %d\n", crq->msg);
+                       return;
+               }
+               return;
+       case IBMVTPM_VALID_CMD:
+               switch (crq->msg) {
+               case VTPM_GET_RTCE_BUFFER_SIZE_RES:
+                       if (crq->len <= 0) {
+                               dev_err(ibmvtpm->dev, "Invalid rtce size\n");
+                               return;
+                       }
+                       ibmvtpm->rtce_size = crq->len;
+                       ibmvtpm->rtce_buf = kmalloc(ibmvtpm->rtce_size,
+                                                   GFP_KERNEL);
+                       if (!ibmvtpm->rtce_buf) {
+                               dev_err(ibmvtpm->dev, "Failed to allocate memory for rtce buffer\n");
+                               return;
+                       }
+
+                       ibmvtpm->rtce_dma_handle = dma_map_single(ibmvtpm->dev,
+                               ibmvtpm->rtce_buf, ibmvtpm->rtce_size,
+                               DMA_BIDIRECTIONAL);
+
+                       if (dma_mapping_error(ibmvtpm->dev,
+                                             ibmvtpm->rtce_dma_handle)) {
+                               kfree(ibmvtpm->rtce_buf);
+                               ibmvtpm->rtce_buf = NULL;
+                               dev_err(ibmvtpm->dev, "Failed to dma map rtce buffer\n");
+                       }
+
+                       return;
+               case VTPM_GET_VERSION_RES:
+                       ibmvtpm->vtpm_version = crq->data;
+                       return;
+               case VTPM_TPM_COMMAND_RES:
+                       ibmvtpm->crq_res.valid = crq->valid;
+                       ibmvtpm->crq_res.msg = crq->msg;
+                       ibmvtpm->crq_res.len = crq->len;
+                       ibmvtpm->crq_res.data = crq->data;
+                       wake_up_interruptible(&wq);
+                       return;
+               default:
+                       return;
+               }
+       }
+       return;
+}
+
+/**
+ * ibmvtpm_interrupt - Interrupt handler
+ * @irq:               irq number to handle
+ * @vtpm_instance:     vtpm that received interrupt
+ *
+ * Returns:
+ *     IRQ_HANDLED
+ **/
+static irqreturn_t ibmvtpm_interrupt(int irq, void *vtpm_instance)
+{
+       struct ibmvtpm_dev *ibmvtpm = (struct ibmvtpm_dev *) vtpm_instance;
+       unsigned long flags;
+
+       spin_lock_irqsave(&ibmvtpm->lock, flags);
+       vio_disable_interrupts(ibmvtpm->vdev);
+       tasklet_schedule(&ibmvtpm->tasklet);
+       spin_unlock_irqrestore(&ibmvtpm->lock, flags);
+
+       return IRQ_HANDLED;
+}
+
+/**
+ * ibmvtpm_tasklet - Interrupt handler tasklet
+ * @data:      ibm vtpm device struct
+ *
+ * Returns:
+ *     Nothing
+ **/
+static void ibmvtpm_tasklet(void *data)
+{
+       struct ibmvtpm_dev *ibmvtpm = data;
+       struct ibmvtpm_crq *crq;
+       unsigned long flags;
+
+       spin_lock_irqsave(&ibmvtpm->lock, flags);
+       while ((crq = ibmvtpm_crq_get_next(ibmvtpm)) != NULL) {
+               ibmvtpm_crq_process(crq, ibmvtpm);
+               crq->valid = 0;
+               wmb();
+       }
+
+       vio_enable_interrupts(ibmvtpm->vdev);
+       spin_unlock_irqrestore(&ibmvtpm->lock, flags);
+}
+
+/**
+ * tpm_ibmvtpm_probe - ibm vtpm initialize entry point
+ * @vio_dev:   vio device struct
+ * @id:                vio device id struct
+ *
+ * Return value:
+ *     0 - Success
+ *     Non-zero - Failure
+ */
+static int __devinit tpm_ibmvtpm_probe(struct vio_dev *vio_dev,
+                                  const struct vio_device_id *id)
+{
+       struct ibmvtpm_dev *ibmvtpm;
+       struct device *dev = &vio_dev->dev;
+       struct ibmvtpm_crq_queue *crq_q;
+       struct tpm_chip *chip;
+       int rc = -ENOMEM, rc1;
+
+       chip = tpm_register_hardware(dev, &tpm_ibmvtpm);
+       if (!chip) {
+               dev_err(dev, "tpm_register_hardware failed\n");
+               return -ENODEV;
+       }
+
+       ibmvtpm = kzalloc(sizeof(struct ibmvtpm_dev), GFP_KERNEL);
+       if (!ibmvtpm) {
+               dev_err(dev, "kzalloc for ibmvtpm failed\n");
+               goto cleanup;
+       }
+
+       crq_q = &ibmvtpm->crq_queue;
+       crq_q->crq_addr = (struct ibmvtpm_crq *)get_zeroed_page(GFP_KERNEL);
+       if (!crq_q->crq_addr) {
+               dev_err(dev, "Unable to allocate memory for crq_addr\n");
+               goto cleanup;
+       }
+
+       crq_q->num_entry = CRQ_RES_BUF_SIZE / sizeof(*crq_q->crq_addr);
+       ibmvtpm->crq_dma_handle = dma_map_single(dev, crq_q->crq_addr,
+                                                CRQ_RES_BUF_SIZE,
+                                                DMA_BIDIRECTIONAL);
+
+       if (dma_mapping_error(dev, ibmvtpm->crq_dma_handle)) {
+               dev_err(dev, "dma mapping failed\n");
+               goto cleanup;
+       }
+
+       rc = plpar_hcall_norets(H_REG_CRQ, vio_dev->unit_address,
+                               ibmvtpm->crq_dma_handle, CRQ_RES_BUF_SIZE);
+       if (rc == H_RESOURCE)
+               rc = ibmvtpm_reset_crq(ibmvtpm);
+
+       if (rc) {
+               dev_err(dev, "Unable to register CRQ rc=%d\n", rc);
+               goto reg_crq_cleanup;
+       }
+
+       tasklet_init(&ibmvtpm->tasklet, (void *)ibmvtpm_tasklet,
+                    (unsigned long)ibmvtpm);
+
+       rc = request_irq(vio_dev->irq, ibmvtpm_interrupt, 0,
+                        tpm_ibmvtpm_driver_name, ibmvtpm);
+       if (rc) {
+               dev_err(dev, "Error %d register irq 0x%x\n", rc, vio_dev->irq);
+               goto init_irq_cleanup;
+       }
+
+       rc = vio_enable_interrupts(vio_dev);
+       if (rc) {
+               dev_err(dev, "Error %d enabling interrupts\n", rc);
+               goto init_irq_cleanup;
+       }
+
+       crq_q->index = 0;
+
+       ibmvtpm->dev = dev;
+       ibmvtpm->vdev = vio_dev;
+       chip->vendor.data = (void *)ibmvtpm;
+
+       spin_lock_init(&ibmvtpm->lock);
+       spin_lock_init(&ibmvtpm->rtce_lock);
+
+       rc = ibmvtpm_crq_send_init(ibmvtpm);
+       if (rc)
+               goto init_irq_cleanup;
+
+       rc = ibmvtpm_crq_get_version(ibmvtpm);
+       if (rc)
+               goto init_irq_cleanup;
+
+       rc = ibmvtpm_crq_get_rtce_size(ibmvtpm);
+       if (rc)
+               goto init_irq_cleanup;
+
+       return rc;
+init_irq_cleanup:
+       tasklet_kill(&ibmvtpm->tasklet);
+       do {
+               rc1 = plpar_hcall_norets(H_FREE_CRQ, vio_dev->unit_address);
+       } while (rc1 == H_BUSY || H_IS_LONG_BUSY(rc1));
+reg_crq_cleanup:
+       dma_unmap_single(dev, ibmvtpm->crq_dma_handle, CRQ_RES_BUF_SIZE,
+                        DMA_BIDIRECTIONAL);
+cleanup:
+       if (ibmvtpm) {
+               if (crq_q->crq_addr)
+                       free_page((unsigned long)crq_q->crq_addr);
+               kfree(ibmvtpm);
+       }
+
+       tpm_remove_hardware(dev);
+
+       return rc;
+}
+
+static struct vio_driver ibmvtpm_driver = {
+       .id_table        = tpm_ibmvtpm_device_table,
+       .probe           = tpm_ibmvtpm_probe,
+       .remove          = tpm_ibmvtpm_remove,
+       .get_desired_dma = tpm_ibmvtpm_get_desired_dma,
+       .name            = tpm_ibmvtpm_driver_name,
+       .pm              = &tpm_ibmvtpm_pm_ops,
+};
+
+/**
+ * ibmvtpm_module_init - Initialize ibm vtpm module
+ *
+ * Return value:
+ *     0 -Success
+ *     Non-zero - Failure
+ */
+static int __init ibmvtpm_module_init(void)
+{
+       return vio_register_driver(&ibmvtpm_driver);
+}
+
+/**
+ * ibmvtpm_module_exit - Teardown ibm vtpm module
+ *
+ * Return value:
+ *     Nothing
+ */
+static void __exit ibmvtpm_module_exit(void)
+{
+       vio_unregister_driver(&ibmvtpm_driver);
+}
+
+module_init(ibmvtpm_module_init);
+module_exit(ibmvtpm_module_exit);
+
+MODULE_AUTHOR("adlai@us.ibm.com");
+MODULE_DESCRIPTION("IBM vTPM Driver");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/tpm/tpm_ibmvtpm.h b/drivers/char/tpm/tpm_ibmvtpm.h
new file mode 100644 (file)
index 0000000..4296eb4
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2012 IBM Corporation
+ *
+ * Author: Ashley Lai <adlai@us.ibm.com>
+ *
+ * Maintained by: <tpmdd-devel@lists.sourceforge.net>
+ *
+ * Device driver for TCG/TCPA TPM (trusted platform module).
+ * Specifications at www.trustedcomputinggroup.org
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ */
+
+#ifndef __TPM_IBMVTPM_H__
+#define __TPM_IBMVTPM_H__
+
+/* vTPM Message Format 1 */
+struct ibmvtpm_crq {
+       u8 valid;
+       u8 msg;
+       u16 len;
+       u32 data;
+       u64 reserved;
+} __attribute__((packed, aligned(8)));
+
+struct ibmvtpm_crq_queue {
+       struct ibmvtpm_crq *crq_addr;
+       u32 index;
+       u32 num_entry;
+};
+
+struct ibmvtpm_dev {
+       struct device *dev;
+       struct vio_dev *vdev;
+       struct ibmvtpm_crq_queue crq_queue;
+       dma_addr_t crq_dma_handle;
+       spinlock_t lock;
+       struct tasklet_struct tasklet;
+       u32 rtce_size;
+       void __iomem *rtce_buf;
+       dma_addr_t rtce_dma_handle;
+       spinlock_t rtce_lock;
+       struct ibmvtpm_crq crq_res;
+       u32 vtpm_version;
+};
+
+#define CRQ_RES_BUF_SIZE       PAGE_SIZE
+
+/* Initialize CRQ */
+#define INIT_CRQ_CMD           0xC001000000000000LL /* Init cmd */
+#define INIT_CRQ_COMP_CMD      0xC002000000000000LL /* Init complete cmd */
+#define INIT_CRQ_RES           0x01    /* Init respond */
+#define INIT_CRQ_COMP_RES      0x02    /* Init complete respond */
+#define VALID_INIT_CRQ         0xC0    /* Valid command for init crq */
+
+/* vTPM CRQ response is the message type | 0x80 */
+#define VTPM_MSG_RES           0x80
+#define IBMVTPM_VALID_CMD      0x80
+
+/* vTPM CRQ message types */
+#define VTPM_GET_VERSION                       0x01
+#define VTPM_GET_VERSION_RES                   (0x01 | VTPM_MSG_RES)
+
+#define VTPM_TPM_COMMAND                       0x02
+#define VTPM_TPM_COMMAND_RES                   (0x02 | VTPM_MSG_RES)
+
+#define VTPM_GET_RTCE_BUFFER_SIZE              0x03
+#define VTPM_GET_RTCE_BUFFER_SIZE_RES          (0x03 | VTPM_MSG_RES)
+
+#define VTPM_PREPARE_TO_SUSPEND                        0x04
+#define VTPM_PREPARE_TO_SUSPEND_RES            (0x04 | VTPM_MSG_RES)
+
+#endif
diff --git a/drivers/char/tpm/tpm_of.c b/drivers/char/tpm/tpm_of.c
new file mode 100644 (file)
index 0000000..98ba2bd
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2012 IBM Corporation
+ *
+ * Author: Ashley Lai <adlai@us.ibm.com>
+ *
+ * Maintained by: <tpmdd-devel@lists.sourceforge.net>
+ *
+ * Read the event log created by the firmware on PPC64
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ */
+
+#include <linux/slab.h>
+#include <linux/of.h>
+
+#include "tpm.h"
+#include "tpm_eventlog.h"
+
+int read_log(struct tpm_bios_log *log)
+{
+       struct device_node *np;
+       const u32 *sizep;
+       const __be64 *basep;
+
+       if (log->bios_event_log != NULL) {
+               pr_err("%s: ERROR - Eventlog already initialized\n", __func__);
+               return -EFAULT;
+       }
+
+       np = of_find_node_by_name(NULL, "ibm,vtpm");
+       if (!np) {
+               pr_err("%s: ERROR - IBMVTPM not supported\n", __func__);
+               return -ENODEV;
+       }
+
+       sizep = of_get_property(np, "linux,sml-size", NULL);
+       if (sizep == NULL) {
+               pr_err("%s: ERROR - SML size not found\n", __func__);
+               goto cleanup_eio;
+       }
+       if (*sizep == 0) {
+               pr_err("%s: ERROR - event log area empty\n", __func__);
+               goto cleanup_eio;
+       }
+
+       basep = of_get_property(np, "linux,sml-base", NULL);
+       if (basep == NULL) {
+               pr_err(KERN_ERR "%s: ERROR - SML not found\n", __func__);
+               goto cleanup_eio;
+       }
+
+       of_node_put(np);
+       log->bios_event_log = kmalloc(*sizep, GFP_KERNEL);
+       if (!log->bios_event_log) {
+               pr_err("%s: ERROR - Not enough memory for BIOS measurements\n",
+                      __func__);
+               return -ENOMEM;
+       }
+
+       log->bios_event_log_end = log->bios_event_log + *sizep;
+
+       memcpy(log->bios_event_log, __va(be64_to_cpup(basep)), *sizep);
+
+       return 0;
+
+cleanup_eio:
+       of_node_put(np);
+       return -EIO;
+}
diff --git a/drivers/char/tpm/tpm_ppi.c b/drivers/char/tpm/tpm_ppi.c
new file mode 100644 (file)
index 0000000..f27b58c
--- /dev/null
@@ -0,0 +1,461 @@
+#include <linux/acpi.h>
+#include <acpi/acpi_drivers.h>
+#include "tpm.h"
+
+static const u8 tpm_ppi_uuid[] = {
+       0xA6, 0xFA, 0xDD, 0x3D,
+       0x1B, 0x36,
+       0xB4, 0x4E,
+       0xA4, 0x24,
+       0x8D, 0x10, 0x08, 0x9D, 0x16, 0x53
+};
+static char *tpm_device_name = "TPM";
+
+#define TPM_PPI_REVISION_ID    1
+#define TPM_PPI_FN_VERSION     1
+#define TPM_PPI_FN_SUBREQ      2
+#define TPM_PPI_FN_GETREQ      3
+#define TPM_PPI_FN_GETACT      4
+#define TPM_PPI_FN_GETRSP      5
+#define TPM_PPI_FN_SUBREQ2     7
+#define TPM_PPI_FN_GETOPR      8
+#define PPI_TPM_REQ_MAX                22
+#define PPI_VS_REQ_START       128
+#define PPI_VS_REQ_END         255
+#define PPI_VERSION_LEN                3
+
+static acpi_status ppi_callback(acpi_handle handle, u32 level, void *context,
+                               void **return_value)
+{
+       acpi_status status;
+       struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+       status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
+       if (strstr(buffer.pointer, context) != NULL) {
+               *return_value = handle;
+               kfree(buffer.pointer);
+               return AE_CTRL_TERMINATE;
+       }
+       return AE_OK;
+}
+
+static inline void ppi_assign_params(union acpi_object params[4],
+                                    u64 function_num)
+{
+       params[0].type = ACPI_TYPE_BUFFER;
+       params[0].buffer.length = sizeof(tpm_ppi_uuid);
+       params[0].buffer.pointer = (char *)tpm_ppi_uuid;
+       params[1].type = ACPI_TYPE_INTEGER;
+       params[1].integer.value = TPM_PPI_REVISION_ID;
+       params[2].type = ACPI_TYPE_INTEGER;
+       params[2].integer.value = function_num;
+       params[3].type = ACPI_TYPE_PACKAGE;
+       params[3].package.count = 0;
+       params[3].package.elements = NULL;
+}
+
+static ssize_t tpm_show_ppi_version(struct device *dev,
+                                   struct device_attribute *attr, char *buf)
+{
+       acpi_handle handle;
+       acpi_status status;
+       struct acpi_object_list input;
+       struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
+       union acpi_object params[4];
+       union acpi_object *obj;
+
+       input.count = 4;
+       ppi_assign_params(params, TPM_PPI_FN_VERSION);
+       input.pointer = params;
+       status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+                                    ACPI_UINT32_MAX, ppi_callback, NULL,
+                                    tpm_device_name, &handle);
+       if (ACPI_FAILURE(status))
+               return -ENXIO;
+
+       status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output,
+                                        ACPI_TYPE_STRING);
+       if (ACPI_FAILURE(status))
+               return -ENOMEM;
+       obj = (union acpi_object *)output.pointer;
+       status = scnprintf(buf, PAGE_SIZE, "%s\n", obj->string.pointer);
+       kfree(output.pointer);
+       return status;
+}
+
+static ssize_t tpm_show_ppi_request(struct device *dev,
+                                   struct device_attribute *attr, char *buf)
+{
+       acpi_handle handle;
+       acpi_status status;
+       struct acpi_object_list input;
+       struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
+       union acpi_object params[4];
+       union acpi_object *ret_obj;
+
+       input.count = 4;
+       ppi_assign_params(params, TPM_PPI_FN_GETREQ);
+       input.pointer = params;
+       status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+                                    ACPI_UINT32_MAX, ppi_callback, NULL,
+                                    tpm_device_name, &handle);
+       if (ACPI_FAILURE(status))
+               return -ENXIO;
+
+       status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output,
+                                           ACPI_TYPE_PACKAGE);
+       if (ACPI_FAILURE(status))
+               return -ENOMEM;
+       /*
+        * output.pointer should be of package type, including two integers.
+        * The first is function return code, 0 means success and 1 means
+        * error. The second is pending TPM operation requested by the OS, 0
+        * means none and >0 means operation value.
+        */
+       ret_obj = ((union acpi_object *)output.pointer)->package.elements;
+       if (ret_obj->type == ACPI_TYPE_INTEGER) {
+               if (ret_obj->integer.value) {
+                       status = -EFAULT;
+                       goto cleanup;
+               }
+               ret_obj++;
+               if (ret_obj->type == ACPI_TYPE_INTEGER)
+                       status = scnprintf(buf, PAGE_SIZE, "%llu\n",
+                                          ret_obj->integer.value);
+               else
+                       status = -EINVAL;
+       } else {
+               status = -EINVAL;
+       }
+cleanup:
+       kfree(output.pointer);
+       return status;
+}
+
+static ssize_t tpm_store_ppi_request(struct device *dev,
+                                    struct device_attribute *attr,
+                                    const char *buf, size_t count)
+{
+       char version[PPI_VERSION_LEN + 1];
+       acpi_handle handle;
+       acpi_status status;
+       struct acpi_object_list input;
+       struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
+       union acpi_object params[4];
+       union acpi_object obj;
+       u32 req;
+       u64 ret;
+
+       input.count = 4;
+       ppi_assign_params(params, TPM_PPI_FN_VERSION);
+       input.pointer = params;
+       status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+                                    ACPI_UINT32_MAX, ppi_callback, NULL,
+                                    tpm_device_name, &handle);
+       if (ACPI_FAILURE(status))
+               return -ENXIO;
+
+       status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output,
+                                           ACPI_TYPE_STRING);
+       if (ACPI_FAILURE(status))
+               return -ENOMEM;
+       strncpy(version,
+               ((union acpi_object *)output.pointer)->string.pointer,
+               PPI_VERSION_LEN);
+       kfree(output.pointer);
+       output.length = ACPI_ALLOCATE_BUFFER;
+       output.pointer = NULL;
+       /*
+        * the function to submit TPM operation request to pre-os environment
+        * is updated with function index from SUBREQ to SUBREQ2 since PPI
+        * version 1.1
+        */
+       if (strcmp(version, "1.1") == -1)
+               params[2].integer.value = TPM_PPI_FN_SUBREQ;
+       else
+               params[2].integer.value = TPM_PPI_FN_SUBREQ2;
+       /*
+        * PPI spec defines params[3].type as ACPI_TYPE_PACKAGE. Some BIOS
+        * accept buffer/string/integer type, but some BIOS accept buffer/
+        * string/package type. For PPI version 1.0 and 1.1, use buffer type
+        * for compatibility, and use package type since 1.2 according to spec.
+        */
+       if (strcmp(version, "1.2") == -1) {
+               params[3].type = ACPI_TYPE_BUFFER;
+               params[3].buffer.length = sizeof(req);
+               sscanf(buf, "%d", &req);
+               params[3].buffer.pointer = (char *)&req;
+       } else {
+               params[3].package.count = 1;
+               obj.type = ACPI_TYPE_INTEGER;
+               sscanf(buf, "%llu", &obj.integer.value);
+               params[3].package.elements = &obj;
+       }
+
+       status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output,
+                                           ACPI_TYPE_INTEGER);
+       if (ACPI_FAILURE(status))
+               return -ENOMEM;
+       ret = ((union acpi_object *)output.pointer)->integer.value;
+       if (ret == 0)
+               status = (acpi_status)count;
+       else if (ret == 1)
+               status = -EPERM;
+       else
+               status = -EFAULT;
+       kfree(output.pointer);
+       return status;
+}
+
+static ssize_t tpm_show_ppi_transition_action(struct device *dev,
+                                             struct device_attribute *attr,
+                                             char *buf)
+{
+       char version[PPI_VERSION_LEN + 1];
+       acpi_handle handle;
+       acpi_status status;
+       struct acpi_object_list input;
+       struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
+       union acpi_object params[4];
+       u32 ret;
+       char *info[] = {
+               "None",
+               "Shutdown",
+               "Reboot",
+               "OS Vendor-specific",
+               "Error",
+       };
+       input.count = 4;
+       ppi_assign_params(params, TPM_PPI_FN_VERSION);
+       input.pointer = params;
+       status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+                                    ACPI_UINT32_MAX, ppi_callback, NULL,
+                                    tpm_device_name, &handle);
+       if (ACPI_FAILURE(status))
+               return -ENXIO;
+
+       status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output,
+                                           ACPI_TYPE_STRING);
+       if (ACPI_FAILURE(status))
+               return -ENOMEM;
+       strncpy(version,
+               ((union acpi_object *)output.pointer)->string.pointer,
+               PPI_VERSION_LEN);
+       /*
+        * PPI spec defines params[3].type as empty package, but some platforms
+        * (e.g. Capella with PPI 1.0) need integer/string/buffer type, so for
+        * compatibility, define params[3].type as buffer, if PPI version < 1.2
+        */
+       if (strcmp(version, "1.2") == -1) {
+               params[3].type = ACPI_TYPE_BUFFER;
+               params[3].buffer.length =  0;
+               params[3].buffer.pointer = NULL;
+       }
+       params[2].integer.value = TPM_PPI_FN_GETACT;
+       kfree(output.pointer);
+       output.length = ACPI_ALLOCATE_BUFFER;
+       output.pointer = NULL;
+       status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output,
+                                           ACPI_TYPE_INTEGER);
+       if (ACPI_FAILURE(status))
+               return -ENOMEM;
+       ret = ((union acpi_object *)output.pointer)->integer.value;
+       if (ret < ARRAY_SIZE(info) - 1)
+               status = scnprintf(buf, PAGE_SIZE, "%d: %s\n", ret, info[ret]);
+       else
+               status = scnprintf(buf, PAGE_SIZE, "%d: %s\n", ret,
+                                  info[ARRAY_SIZE(info)-1]);
+       kfree(output.pointer);
+       return status;
+}
+
+static ssize_t tpm_show_ppi_response(struct device *dev,
+                                    struct device_attribute *attr,
+                                    char *buf)
+{
+       acpi_handle handle;
+       acpi_status status;
+       struct acpi_object_list input;
+       struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
+       union acpi_object params[4];
+       union acpi_object *ret_obj;
+       u64 req;
+
+       input.count = 4;
+       ppi_assign_params(params, TPM_PPI_FN_GETRSP);
+       input.pointer = params;
+       status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+                                    ACPI_UINT32_MAX, ppi_callback, NULL,
+                                    tpm_device_name, &handle);
+       if (ACPI_FAILURE(status))
+               return -ENXIO;
+
+       status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output,
+                                           ACPI_TYPE_PACKAGE);
+       if (ACPI_FAILURE(status))
+               return -ENOMEM;
+       /*
+        * parameter output.pointer should be of package type, including
+        * 3 integers. The first means function return code, the second means
+        * most recent TPM operation request, and the last means response to
+        * the most recent TPM operation request. Only if the first is 0, and
+        * the second integer is not 0, the response makes sense.
+        */
+       ret_obj = ((union acpi_object *)output.pointer)->package.elements;
+       if (ret_obj->type != ACPI_TYPE_INTEGER) {
+               status = -EINVAL;
+               goto cleanup;
+       }
+       if (ret_obj->integer.value) {
+               status = -EFAULT;
+               goto cleanup;
+       }
+       ret_obj++;
+       if (ret_obj->type != ACPI_TYPE_INTEGER) {
+               status = -EINVAL;
+               goto cleanup;
+       }
+       if (ret_obj->integer.value) {
+               req = ret_obj->integer.value;
+               ret_obj++;
+               if (ret_obj->type != ACPI_TYPE_INTEGER) {
+                       status = -EINVAL;
+                       goto cleanup;
+               }
+               if (ret_obj->integer.value == 0)
+                       status = scnprintf(buf, PAGE_SIZE, "%llu %s\n", req,
+                                          "0: Success");
+               else if (ret_obj->integer.value == 0xFFFFFFF0)
+                       status = scnprintf(buf, PAGE_SIZE, "%llu %s\n", req,
+                                          "0xFFFFFFF0: User Abort");
+               else if (ret_obj->integer.value == 0xFFFFFFF1)
+                       status = scnprintf(buf, PAGE_SIZE, "%llu %s\n", req,
+                                          "0xFFFFFFF1: BIOS Failure");
+               else if (ret_obj->integer.value >= 1 &&
+                        ret_obj->integer.value <= 0x00000FFF)
+                       status = scnprintf(buf, PAGE_SIZE, "%llu %llu: %s\n",
+                                          req, ret_obj->integer.value,
+                                          "Corresponding TPM error");
+               else
+                       status = scnprintf(buf, PAGE_SIZE, "%llu %llu: %s\n",
+                                          req, ret_obj->integer.value,
+                                          "Error");
+       } else {
+               status = scnprintf(buf, PAGE_SIZE, "%llu: %s\n",
+                                  ret_obj->integer.value, "No Recent Request");
+       }
+cleanup:
+       kfree(output.pointer);
+       return status;
+}
+
+static ssize_t show_ppi_operations(char *buf, u32 start, u32 end)
+{
+       char *str = buf;
+       char version[PPI_VERSION_LEN];
+       acpi_handle handle;
+       acpi_status status;
+       struct acpi_object_list input;
+       struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
+       union acpi_object params[4];
+       union acpi_object obj;
+       int i;
+       u32 ret;
+       char *info[] = {
+               "Not implemented",
+               "BIOS only",
+               "Blocked for OS by BIOS",
+               "User required",
+               "User not required",
+       };
+       input.count = 4;
+       ppi_assign_params(params, TPM_PPI_FN_VERSION);
+       input.pointer = params;
+       status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+                                    ACPI_UINT32_MAX, ppi_callback, NULL,
+                                    tpm_device_name, &handle);
+       if (ACPI_FAILURE(status))
+               return -ENXIO;
+
+       status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output,
+                                        ACPI_TYPE_STRING);
+       if (ACPI_FAILURE(status))
+               return -ENOMEM;
+
+       strncpy(version,
+               ((union acpi_object *)output.pointer)->string.pointer,
+               PPI_VERSION_LEN);
+       kfree(output.pointer);
+       output.length = ACPI_ALLOCATE_BUFFER;
+       output.pointer = NULL;
+       if (strcmp(version, "1.2") == -1)
+               return -EPERM;
+
+       params[2].integer.value = TPM_PPI_FN_GETOPR;
+       params[3].package.count = 1;
+       obj.type = ACPI_TYPE_INTEGER;
+       params[3].package.elements = &obj;
+       for (i = start; i <= end; i++) {
+               obj.integer.value = i;
+               status = acpi_evaluate_object_typed(handle, "_DSM",
+                        &input, &output, ACPI_TYPE_INTEGER);
+               if (ACPI_FAILURE(status))
+                       return -ENOMEM;
+
+               ret = ((union acpi_object *)output.pointer)->integer.value;
+               if (ret > 0 && ret < ARRAY_SIZE(info))
+                       str += scnprintf(str, PAGE_SIZE, "%d %d: %s\n",
+                                        i, ret, info[ret]);
+               kfree(output.pointer);
+               output.length = ACPI_ALLOCATE_BUFFER;
+               output.pointer = NULL;
+       }
+       return str - buf;
+}
+
+static ssize_t tpm_show_ppi_tcg_operations(struct device *dev,
+                                          struct device_attribute *attr,
+                                          char *buf)
+{
+       return show_ppi_operations(buf, 0, PPI_TPM_REQ_MAX);
+}
+
+static ssize_t tpm_show_ppi_vs_operations(struct device *dev,
+                                         struct device_attribute *attr,
+                                         char *buf)
+{
+       return show_ppi_operations(buf, PPI_VS_REQ_START, PPI_VS_REQ_END);
+}
+
+static DEVICE_ATTR(version, S_IRUGO, tpm_show_ppi_version, NULL);
+static DEVICE_ATTR(request, S_IRUGO | S_IWUSR | S_IWGRP,
+                  tpm_show_ppi_request, tpm_store_ppi_request);
+static DEVICE_ATTR(transition_action, S_IRUGO,
+                  tpm_show_ppi_transition_action, NULL);
+static DEVICE_ATTR(response, S_IRUGO, tpm_show_ppi_response, NULL);
+static DEVICE_ATTR(tcg_operations, S_IRUGO, tpm_show_ppi_tcg_operations, NULL);
+static DEVICE_ATTR(vs_operations, S_IRUGO, tpm_show_ppi_vs_operations, NULL);
+
+static struct attribute *ppi_attrs[] = {
+       &dev_attr_version.attr,
+       &dev_attr_request.attr,
+       &dev_attr_transition_action.attr,
+       &dev_attr_response.attr,
+       &dev_attr_tcg_operations.attr,
+       &dev_attr_vs_operations.attr, NULL,
+};
+static struct attribute_group ppi_attr_grp = {
+       .attrs = ppi_attrs
+};
+
+ssize_t sys_add_ppi(struct kobject *parent)
+{
+       struct kobject *ppi;
+       ppi = kobject_create_and_add("ppi", parent);
+       if (sysfs_create_group(ppi, &ppi_attr_grp))
+               return -EFAULT;
+       else
+               return 0;
+}
+EXPORT_SYMBOL_GPL(sys_add_ppi);
+
+MODULE_LICENSE("GPL");
index c4be3519a587c4fe33c3a14be17ba72e6067d9a0..6bdf2671254f405e03bfcca83cebba4cbae2e50c 100644 (file)
@@ -705,6 +705,7 @@ out_err:
        return rc;
 }
 
+#if defined(CONFIG_PNP) || defined(CONFIG_PM_SLEEP)
 static void tpm_tis_reenable_interrupts(struct tpm_chip *chip)
 {
        u32 intmask;
@@ -725,7 +726,7 @@ static void tpm_tis_reenable_interrupts(struct tpm_chip *chip)
        iowrite32(intmask,
                  chip->vendor.iobase + TPM_INT_ENABLE(chip->vendor.locality));
 }
-
+#endif
 
 #ifdef CONFIG_PNP
 static int __devinit tpm_tis_pnp_init(struct pnp_dev *pnp_dev,
index 5869ea3870545f0f7c3ab64a185e1c486243b4e1..72ce247a0e8d5c08395fe92c9163a8c376c555bc 100644 (file)
@@ -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 (file)
index 0000000..8f57154
--- /dev/null
@@ -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);
index d423c9bdd71a9d4670c340c94f7f1eb08152ed41..442a31363873d35f319e0d5ee5b6b250084c02fc 100644 (file)
@@ -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);
index c0e816468e300f242735f4825d09b9d291a9b522..1a40935c85fdcc1f21e976ad8dbd5298a87d6060 100644 (file)
@@ -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 */
index 002888185f170e92fa798233a40c64ef2258d42c..d216cd3cc569ecdbf195f45b055a5489470f0b70 100644 (file)
@@ -120,3 +120,4 @@ u32 gen_split_key(struct device *jrdev, u8 *key_out, int split_key_len,
 
        return ret;
 }
+EXPORT_SYMBOL(gen_split_key);
index 3934fcc4e00b1b02778bb02866fb86073f9b1f0a..7ab6e26664a77a1ab2b375148488d1209e2e21ba 100644 (file)
@@ -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;
 }
index e4feba6b03c00e6f2ae412a9a1104eef21fb94f4..f5843bc80baa9b8168f6034ad167ce46a0d537bb 100644 (file)
@@ -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];
index 616d90bcb3a4106929523c4a98fe32fb27f6a9a6..d5dc9da7f99f95fc9dd3a6edb5d4bc302e69c2c3 100644 (file)
@@ -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);
 }
index 920a609b2c35857c2fa64c8341ad6561fe6f7d65..38f9e52f358b17596b8b41177d6af493d509f84b 100644 (file)
@@ -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);
index d0c4574ef49c1d60b074643b278580a72ff8dc69..36164806b9d475aabff5165f47d481c8a93ce644 100644 (file)
@@ -193,6 +193,9 @@ static const struct file_operations ast_fops = {
        .mmap = ast_mmap,
        .poll = drm_poll,
        .fasync = drm_fasync,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl = drm_compat_ioctl,
+#endif
        .read = drm_read,
 };
 
index 7282c081fb53000397346d6c34879c06f940a4bd..a712cafcfa1dfde6f76e5c94a77307b7c1f1041a 100644 (file)
@@ -841,7 +841,7 @@ int ast_cursor_init(struct drm_device *dev)
 
        ast->cursor_cache = obj;
        ast->cursor_cache_gpu_addr = gpu_addr;
-       DRM_ERROR("pinned cursor cache at %llx\n", ast->cursor_cache_gpu_addr);
+       DRM_DEBUG_KMS("pinned cursor cache at %llx\n", ast->cursor_cache_gpu_addr);
        return 0;
 fail:
        return ret;
index 7053140c65969758f9f22ded7cea130fe0ab7bd5..b83a2d7ddd1ae8ec04ae0df1b1e647fbc1e327af 100644 (file)
@@ -74,6 +74,9 @@ static const struct file_operations cirrus_driver_fops = {
        .unlocked_ioctl = drm_ioctl,
        .mmap = cirrus_mmap,
        .poll = drm_poll,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl = drm_compat_ioctl,
+#endif
        .fasync = drm_fasync,
 };
 static struct drm_driver driver = {
index 7f5096763b7d387c25713d7e9ee95e17ce90f7d6..59a26e577b57f423077d5a2c86d75364f14b6838 100644 (file)
@@ -36,6 +36,6 @@ config DRM_EXYNOS_VIDI
 
 config DRM_EXYNOS_G2D
        bool "Exynos DRM G2D"
-       depends on DRM_EXYNOS
+       depends on DRM_EXYNOS && !VIDEO_SAMSUNG_S5P_G2D
        help
          Choose this option if you want to use Exynos G2D for DRM.
index 613bf8a5d9b268331779b0f60f43f52a047269de..ae13febe0eaa64e821adf2f5db306e5ebdd07186 100644 (file)
@@ -163,6 +163,12 @@ static void exynos_gem_dmabuf_kunmap(struct dma_buf *dma_buf,
        /* TODO */
 }
 
+static int exynos_gem_dmabuf_mmap(struct dma_buf *dma_buf,
+       struct vm_area_struct *vma)
+{
+       return -ENOTTY;
+}
+
 static struct dma_buf_ops exynos_dmabuf_ops = {
        .map_dma_buf            = exynos_gem_map_dma_buf,
        .unmap_dma_buf          = exynos_gem_unmap_dma_buf,
@@ -170,6 +176,7 @@ static struct dma_buf_ops exynos_dmabuf_ops = {
        .kmap_atomic            = exynos_gem_dmabuf_kmap_atomic,
        .kunmap                 = exynos_gem_dmabuf_kunmap,
        .kunmap_atomic          = exynos_gem_dmabuf_kunmap_atomic,
+       .mmap                   = exynos_gem_dmabuf_mmap,
        .release                = exynos_dmabuf_release,
 };
 
index ebacec6f1e48efef646700c630f02813007eaac0..d07071937453302fc74793c4aecb48a086b8069f 100644 (file)
@@ -160,7 +160,6 @@ static int exynos_drm_open(struct drm_device *dev, struct drm_file *file)
        if (!file_priv)
                return -ENOMEM;
 
-       drm_prime_init_file_private(&file->prime);
        file->driver_priv = file_priv;
 
        return exynos_drm_subdrv_open(dev, file);
@@ -184,7 +183,6 @@ static void exynos_drm_preclose(struct drm_device *dev,
                        e->base.destroy(&e->base);
                }
        }
-       drm_prime_destroy_file_private(&file->prime);
        spin_unlock_irqrestore(&dev->event_lock, flags);
 
        exynos_drm_subdrv_close(dev, file);
@@ -241,6 +239,9 @@ static const struct file_operations exynos_drm_driver_fops = {
        .poll           = drm_poll,
        .read           = drm_read,
        .unlocked_ioctl = drm_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl = drm_compat_ioctl,
+#endif
        .release        = drm_release,
 };
 
index a68d2b313f03cab1d42fae0d362159f6a4f1ba26..b19cd93e70472b325224611d5725614c33f72f83 100644 (file)
@@ -831,11 +831,6 @@ static int __devinit fimd_probe(struct platform_device *pdev)
        }
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(dev, "failed to find registers\n");
-               ret = -ENOENT;
-               goto err_clk;
-       }
 
        ctx->regs = devm_request_and_ioremap(&pdev->dev, res);
        if (!ctx->regs) {
index d2d88f22a037a8ace36fae877fd45dbf60357b6c..1065e90d09199414585adca93e2e586b9fe215f0 100644 (file)
@@ -129,7 +129,6 @@ struct g2d_runqueue_node {
 struct g2d_data {
        struct device                   *dev;
        struct clk                      *gate_clk;
-       struct resource                 *regs_res;
        void __iomem                    *regs;
        int                             irq;
        struct workqueue_struct         *g2d_workq;
@@ -751,7 +750,7 @@ static int __devinit g2d_probe(struct platform_device *pdev)
        struct exynos_drm_subdrv *subdrv;
        int ret;
 
-       g2d = kzalloc(sizeof(*g2d), GFP_KERNEL);
+       g2d = devm_kzalloc(&pdev->dev, sizeof(*g2d), GFP_KERNEL);
        if (!g2d) {
                dev_err(dev, "failed to allocate driver data\n");
                return -ENOMEM;
@@ -759,10 +758,8 @@ static int __devinit g2d_probe(struct platform_device *pdev)
 
        g2d->runqueue_slab = kmem_cache_create("g2d_runqueue_slab",
                        sizeof(struct g2d_runqueue_node), 0, 0, NULL);
-       if (!g2d->runqueue_slab) {
-               ret = -ENOMEM;
-               goto err_free_mem;
-       }
+       if (!g2d->runqueue_slab)
+               return -ENOMEM;
 
        g2d->dev = dev;
 
@@ -794,38 +791,26 @@ static int __devinit g2d_probe(struct platform_device *pdev)
        pm_runtime_enable(dev);
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(dev, "failed to get I/O memory\n");
-               ret = -ENOENT;
-               goto err_put_clk;
-       }
 
-       g2d->regs_res = request_mem_region(res->start, resource_size(res),
-                                          dev_name(dev));
-       if (!g2d->regs_res) {
-               dev_err(dev, "failed to request I/O memory\n");
-               ret = -ENOENT;
-               goto err_put_clk;
-       }
-
-       g2d->regs = ioremap(res->start, resource_size(res));
+       g2d->regs = devm_request_and_ioremap(&pdev->dev, res);
        if (!g2d->regs) {
                dev_err(dev, "failed to remap I/O memory\n");
                ret = -ENXIO;
-               goto err_release_res;
+               goto err_put_clk;
        }
 
        g2d->irq = platform_get_irq(pdev, 0);
        if (g2d->irq < 0) {
                dev_err(dev, "failed to get irq\n");
                ret = g2d->irq;
-               goto err_unmap_base;
+               goto err_put_clk;
        }
 
-       ret = request_irq(g2d->irq, g2d_irq_handler, 0, "drm_g2d", g2d);
+       ret = devm_request_irq(&pdev->dev, g2d->irq, g2d_irq_handler, 0,
+                                                               "drm_g2d", g2d);
        if (ret < 0) {
                dev_err(dev, "irq request failed\n");
-               goto err_unmap_base;
+               goto err_put_clk;
        }
 
        platform_set_drvdata(pdev, g2d);
@@ -838,7 +823,7 @@ static int __devinit g2d_probe(struct platform_device *pdev)
        ret = exynos_drm_subdrv_register(subdrv);
        if (ret < 0) {
                dev_err(dev, "failed to register drm g2d device\n");
-               goto err_free_irq;
+               goto err_put_clk;
        }
 
        dev_info(dev, "The exynos g2d(ver %d.%d) successfully probed\n",
@@ -846,13 +831,6 @@ static int __devinit g2d_probe(struct platform_device *pdev)
 
        return 0;
 
-err_free_irq:
-       free_irq(g2d->irq, g2d);
-err_unmap_base:
-       iounmap(g2d->regs);
-err_release_res:
-       release_resource(g2d->regs_res);
-       kfree(g2d->regs_res);
 err_put_clk:
        pm_runtime_disable(dev);
        clk_put(g2d->gate_clk);
@@ -862,8 +840,6 @@ err_destroy_workqueue:
        destroy_workqueue(g2d->g2d_workq);
 err_destroy_slab:
        kmem_cache_destroy(g2d->runqueue_slab);
-err_free_mem:
-       kfree(g2d);
        return ret;
 }
 
@@ -873,24 +849,18 @@ static int __devexit g2d_remove(struct platform_device *pdev)
 
        cancel_work_sync(&g2d->runqueue_work);
        exynos_drm_subdrv_unregister(&g2d->subdrv);
-       free_irq(g2d->irq, g2d);
 
        while (g2d->runqueue_node) {
                g2d_free_runqueue_node(g2d, g2d->runqueue_node);
                g2d->runqueue_node = g2d_get_runqueue_node(g2d);
        }
 
-       iounmap(g2d->regs);
-       release_resource(g2d->regs_res);
-       kfree(g2d->regs_res);
-
        pm_runtime_disable(&pdev->dev);
        clk_put(g2d->gate_clk);
 
        g2d_fini_cmdlist(g2d);
        destroy_workqueue(g2d->g2d_workq);
        kmem_cache_destroy(g2d->runqueue_slab);
-       kfree(g2d);
 
        return 0;
 }
@@ -924,7 +894,7 @@ static int g2d_resume(struct device *dev)
 }
 #endif
 
-SIMPLE_DEV_PM_OPS(g2d_pm_ops, g2d_suspend, g2d_resume);
+static SIMPLE_DEV_PM_OPS(g2d_pm_ops, g2d_suspend, g2d_resume);
 
 struct platform_driver g2d_driver = {
        .probe          = g2d_probe,
index f9efde40c097b819af24d41ff32162f3191ea632..a38051c95ec4384176ddc5f8bd8937e4270c3fb6 100644 (file)
@@ -122,7 +122,7 @@ fail:
                __free_page(pages[i]);
 
        drm_free_large(pages);
-       return ERR_PTR(PTR_ERR(p));
+       return ERR_CAST(p);
 }
 
 static void exynos_gem_put_pages(struct drm_gem_object *obj,
@@ -662,7 +662,7 @@ int exynos_drm_gem_dumb_create(struct drm_file *file_priv,
         */
 
        args->pitch = args->width * ((args->bpp + 7) / 8);
-       args->size = PAGE_ALIGN(args->pitch * args->height);
+       args->size = args->pitch * args->height;
 
        exynos_gem_obj = exynos_drm_gem_create(dev, args->flags, args->size);
        if (IS_ERR(exynos_gem_obj))
index 8ffcdf8b9e223ffdfe7552aa1d57b4334cba19cc..3fdf0b65f47e6659b820d1fa343005b682e354b1 100644 (file)
@@ -345,7 +345,7 @@ static int __devinit exynos_drm_hdmi_probe(struct platform_device *pdev)
 
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
-       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+       ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
        if (!ctx) {
                DRM_LOG_KMS("failed to alloc common hdmi context.\n");
                return -ENOMEM;
@@ -371,7 +371,6 @@ static int __devexit exynos_drm_hdmi_remove(struct platform_device *pdev)
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
        exynos_drm_subdrv_unregister(&ctx->subdrv);
-       kfree(ctx);
 
        return 0;
 }
index b89829e5043a59a67152c5cafc241265f0183f12..e1f94b746bd7e0a9419e40ce694bf55e1bff36ab 100644 (file)
@@ -29,7 +29,6 @@ static const uint32_t formats[] = {
        DRM_FORMAT_XRGB8888,
        DRM_FORMAT_ARGB8888,
        DRM_FORMAT_NV12,
-       DRM_FORMAT_NV12M,
        DRM_FORMAT_NV12MT,
 };
 
index bb1550c4dd57db37554954537ef19c61d4e513ce..537027a74fd54f06b49c1387c1650bf90abc11f1 100644 (file)
@@ -633,7 +633,7 @@ static int __devinit vidi_probe(struct platform_device *pdev)
 
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
-       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+       ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
        if (!ctx)
                return -ENOMEM;
 
@@ -673,8 +673,6 @@ static int __devexit vidi_remove(struct platform_device *pdev)
                ctx->raw_edid = NULL;
        }
 
-       kfree(ctx);
-
        return 0;
 }
 
index 409e2ec1207c3ddbe4ecae65f9fae1498fcd6410..a6aea6f3ea1ab842d8c6d26a5ecb7e606c335f0d 100644 (file)
@@ -2172,7 +2172,7 @@ static int __devinit hdmi_resources_init(struct hdmi_context *hdata)
 
        DRM_DEBUG_KMS("HDMI resource init\n");
 
-       memset(res, 0, sizeof *res);
+       memset(res, 0, sizeof(*res));
 
        /* get clocks, power */
        res->hdmi = clk_get(dev, "hdmi");
@@ -2204,7 +2204,7 @@ static int __devinit hdmi_resources_init(struct hdmi_context *hdata)
        clk_set_parent(res->sclk_hdmi, res->sclk_pixel);
 
        res->regul_bulk = kzalloc(ARRAY_SIZE(supply) *
-               sizeof res->regul_bulk[0], GFP_KERNEL);
+               sizeof(res->regul_bulk[0]), GFP_KERNEL);
        if (!res->regul_bulk) {
                DRM_ERROR("failed to get memory for regulators\n");
                goto fail;
@@ -2243,7 +2243,7 @@ static int hdmi_resources_cleanup(struct hdmi_context *hdata)
                clk_put(res->sclk_hdmi);
        if (!IS_ERR_OR_NULL(res->hdmi))
                clk_put(res->hdmi);
-       memset(res, 0, sizeof *res);
+       memset(res, 0, sizeof(*res));
 
        return 0;
 }
@@ -2312,11 +2312,6 @@ static int __devinit hdmi_probe(struct platform_device *pdev)
        }
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               DRM_ERROR("failed to find registers\n");
-               ret = -ENOENT;
-               goto err_resource;
-       }
 
        hdata->regs = devm_request_and_ioremap(&pdev->dev, res);
        if (!hdata->regs) {
index 30fcc12f81dd943802031936dcfc9ea81b8f1548..25b97d5e5fcb44679a331b8e8e5b1a9da7d7d3ca 100644 (file)
@@ -236,11 +236,11 @@ static inline void vp_filter_set(struct mixer_resources *res,
 static void vp_default_filter(struct mixer_resources *res)
 {
        vp_filter_set(res, VP_POLY8_Y0_LL,
-               filter_y_horiz_tap8, sizeof filter_y_horiz_tap8);
+               filter_y_horiz_tap8, sizeof(filter_y_horiz_tap8));
        vp_filter_set(res, VP_POLY4_Y0_LL,
-               filter_y_vert_tap4, sizeof filter_y_vert_tap4);
+               filter_y_vert_tap4, sizeof(filter_y_vert_tap4));
        vp_filter_set(res, VP_POLY4_C0_LL,
-               filter_cr_horiz_tap4, sizeof filter_cr_horiz_tap4);
+               filter_cr_horiz_tap4, sizeof(filter_cr_horiz_tap4));
 }
 
 static void mixer_vsync_set_update(struct mixer_context *ctx, bool enable)
index 0f9b7db80f6bdc91193ef7bd914a580e2b5eec26..cf49ba5a54bf3a351b4bda14c8fd3d4daf26df73 100644 (file)
@@ -476,6 +476,7 @@ static const struct psb_offset oaktrail_regmap[2] = {
                .pos = DSPAPOS,
                .surf = DSPASURF,
                .addr = MRST_DSPABASE,
+               .base = MRST_DSPABASE,
                .status = PIPEASTAT,
                .linoff = DSPALINOFF,
                .tileoff = DSPATILEOFF,
@@ -499,6 +500,7 @@ static const struct psb_offset oaktrail_regmap[2] = {
                .pos = DSPBPOS,
                .surf = DSPBSURF,
                .addr = DSPBBASE,
+               .base = DSPBBASE,
                .status = PIPEBSTAT,
                .linoff = DSPBLINOFF,
                .tileoff = DSPBTILEOFF,
index 57d892eaaa6effc66defdbb890bb9f1b68208515..463ec6871fe998229659eaa82fb8237a57109543 100644 (file)
@@ -115,6 +115,9 @@ static const struct file_operations i810_buffer_fops = {
        .unlocked_ioctl = drm_ioctl,
        .mmap = i810_mmap_buffers,
        .fasync = drm_fasync,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl = drm_compat_ioctl,
+#endif
        .llseek = noop_llseek,
 };
 
index f9924ad04d0993d5d6157918082b9d4d5d3ed604..48cfcca2b350122f0b3ed5fdb7e78dee78af8dd6 100644 (file)
@@ -51,6 +51,9 @@ static const struct file_operations i810_driver_fops = {
        .mmap = drm_mmap,
        .poll = drm_poll,
        .fasync = drm_fasync,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl = drm_compat_ioctl,
+#endif
        .llseek = noop_llseek,
 };
 
index 9cf7dfe022b989a23e02cb8ad45cd2177f956605..914c0dfabe6048113abc150b38e06a107eb33c5b 100644 (file)
@@ -1587,6 +1587,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
        spin_lock_init(&dev_priv->irq_lock);
        spin_lock_init(&dev_priv->error_lock);
        spin_lock_init(&dev_priv->rps_lock);
+       spin_lock_init(&dev_priv->dpio_lock);
 
        if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev))
                dev_priv->num_pipe = 3;
index 489e2b162b2736b4fc3d43e171ebddb25c66b12e..274d25de521e78c577d5a62456fc812024bbae79 100644 (file)
@@ -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)) ||
index 8a3828528b9ddfa9678e7bfbf015bd7acdfdc29d..5249640cce1381c912c76ec73c6658cde12ae95f 100644 (file)
@@ -2700,9 +2700,6 @@ void intel_irq_init(struct drm_device *dev)
                        dev->driver->irq_handler = i8xx_irq_handler;
                        dev->driver->irq_uninstall = i8xx_irq_uninstall;
                } else if (INTEL_INFO(dev)->gen == 3) {
-                       /* IIR "flip pending" means done if this bit is set */
-                       I915_WRITE(ECOSKPD, _MASKED_BIT_DISABLE(ECO_FLIP_DONE));
-
                        dev->driver->irq_preinstall = i915_irq_preinstall;
                        dev->driver->irq_postinstall = i915_irq_postinstall;
                        dev->driver->irq_uninstall = i915_irq_uninstall;
index 2dfa6cf4886b6a2a3b31b90d1df489634a30df3f..c040aee1341cf2065f1ea91eb1b54fbdf54d96b8 100644 (file)
@@ -1376,7 +1376,8 @@ static void assert_pch_dp_disabled(struct drm_i915_private *dev_priv,
             "PCH DP (0x%08x) enabled on transcoder %c, should be disabled\n",
             reg, pipe_name(pipe));
 
-       WARN(HAS_PCH_IBX(dev_priv->dev) && (val & SDVO_PIPE_B_SELECT),
+       WARN(HAS_PCH_IBX(dev_priv->dev) && (val & DP_PORT_EN) == 0
+            && (val & DP_PIPEB_SELECT),
             "IBX PCH dp port still using transcoder B\n");
 }
 
@@ -1388,7 +1389,8 @@ static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv,
             "PCH HDMI (0x%08x) enabled on transcoder %c, should be disabled\n",
             reg, pipe_name(pipe));
 
-       WARN(HAS_PCH_IBX(dev_priv->dev) && (val & SDVO_PIPE_B_SELECT),
+       WARN(HAS_PCH_IBX(dev_priv->dev) && (val & PORT_ENABLE) == 0
+            && (val & SDVO_PIPE_B_SELECT),
             "IBX PCH hdmi port still using transcoder B\n");
 }
 
@@ -4189,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.
@@ -4202,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.
         *
index a6c426afaa7aca46144f5a3710c0ea6f10a46b83..ace757af913366db3e7cff4e670fa9c804c84d08 100644 (file)
@@ -2533,14 +2533,10 @@ intel_dp_init(struct drm_device *dev, int output_reg)
                        break;
        }
 
-       intel_dp_i2c_init(intel_dp, intel_connector, name);
-
        /* Cache some DPCD data in the eDP case */
        if (is_edp(intel_dp)) {
-               bool ret;
                struct edp_power_seq    cur, vbt;
                u32 pp_on, pp_off, pp_div;
-               struct edid *edid;
 
                pp_on = I915_READ(PCH_PP_ON_DELAYS);
                pp_off = I915_READ(PCH_PP_OFF_DELAYS);
@@ -2591,6 +2587,13 @@ intel_dp_init(struct drm_device *dev, int output_reg)
 
                DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n",
                              intel_dp->backlight_on_delay, intel_dp->backlight_off_delay);
+       }
+
+       intel_dp_i2c_init(intel_dp, intel_connector, name);
+
+       if (is_edp(intel_dp)) {
+               bool ret;
+               struct edid *edid;
 
                ironlake_edp_panel_vdd_on(intel_dp);
                ret = intel_dp_get_dpcd(intel_dp);
index 98f602427eb8cb8fe9a8cc975ff1b4128ce68ae6..12dc3308ab8c982f063a4b5b0e7dcc8dd2b3519b 100644 (file)
@@ -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);
index 3df4f5fa892ad847b394c2050e8956779473afd8..e019b236986128bae46c61bf49180f7ec2502a0d 100644 (file)
@@ -162,19 +162,12 @@ static u32 i915_read_blc_pwm_ctl(struct drm_i915_private *dev_priv)
        return val;
 }
 
-u32 intel_panel_get_max_backlight(struct drm_device *dev)
+static u32 _intel_panel_get_max_backlight(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        u32 max;
 
        max = i915_read_blc_pwm_ctl(dev_priv);
-       if (max == 0) {
-               /* XXX add code here to query mode clock or hardware clock
-                * and program max PWM appropriately.
-                */
-               pr_warn_once("fixme: max PWM is zero\n");
-               return 1;
-       }
 
        if (HAS_PCH_SPLIT(dev)) {
                max >>= 16;
@@ -188,6 +181,22 @@ u32 intel_panel_get_max_backlight(struct drm_device *dev)
                        max *= 0xff;
        }
 
+       return max;
+}
+
+u32 intel_panel_get_max_backlight(struct drm_device *dev)
+{
+       u32 max;
+
+       max = _intel_panel_get_max_backlight(dev);
+       if (max == 0) {
+               /* XXX add code here to query mode clock or hardware clock
+                * and program max PWM appropriately.
+                */
+               pr_warn_once("fixme: max PWM is zero\n");
+               return 1;
+       }
+
        DRM_DEBUG_DRIVER("max backlight PWM = %d\n", max);
        return max;
 }
@@ -424,7 +433,11 @@ int intel_panel_setup_backlight(struct drm_device *dev)
 
        memset(&props, 0, sizeof(props));
        props.type = BACKLIGHT_RAW;
-       props.max_brightness = intel_panel_get_max_backlight(dev);
+       props.max_brightness = _intel_panel_get_max_backlight(dev);
+       if (props.max_brightness == 0) {
+               DRM_ERROR("Failed to get maximum backlight value\n");
+               return -ENODEV;
+       }
        dev_priv->backlight =
                backlight_device_register("intel_backlight",
                                          &connector->kdev, dev,
index 1881c8c83f0e0c44ab009dfed7049235c4074d97..ba8a27b1757ad97e774fe8266432161477a3561a 100644 (file)
@@ -3672,6 +3672,9 @@ static void gen3_init_clock_gating(struct drm_device *dev)
 
        if (IS_PINEVIEW(dev))
                I915_WRITE(ECOSKPD, _MASKED_BIT_ENABLE(ECO_GATING_CX_ONLY));
+
+       /* IIR "flip pending" means done if this bit is set */
+       I915_WRITE(ECOSKPD, _MASKED_BIT_DISABLE(ECO_FLIP_DONE));
 }
 
 static void i85x_init_clock_gating(struct drm_device *dev)
index d81bb0bf28850f4ea734dedabec44d8478b12d44..123afd357611a6fbbd4c235aa7449afd6ac15dff 100644 (file)
@@ -2573,7 +2573,6 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)
                hotplug_mask = intel_sdvo->is_sdvob ?
                        SDVOB_HOTPLUG_INT_STATUS_I915 : SDVOC_HOTPLUG_INT_STATUS_I915;
        }
-       dev_priv->hotplug_supported_mask |= hotplug_mask;
 
        drm_encoder_helper_add(&intel_encoder->base, &intel_sdvo_helper_funcs);
 
@@ -2581,14 +2580,6 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)
        if (!intel_sdvo_get_capabilities(intel_sdvo, &intel_sdvo->caps))
                goto err;
 
-       /* Set up hotplug command - note paranoia about contents of reply.
-        * We assume that the hardware is in a sane state, and only touch
-        * the bits we think we understand.
-        */
-       intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_ACTIVE_HOT_PLUG,
-                            &intel_sdvo->hotplug_active, 2);
-       intel_sdvo->hotplug_active[0] &= ~0x3;
-
        if (intel_sdvo_output_setup(intel_sdvo,
                                    intel_sdvo->caps.output_flags) != true) {
                DRM_DEBUG_KMS("SDVO output failed to setup on %s\n",
@@ -2596,6 +2587,12 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)
                goto err;
        }
 
+       /* Only enable the hotplug irq if we need it, to work around noisy
+        * hotplug lines.
+        */
+       if (intel_sdvo->hotplug_active[0])
+               dev_priv->hotplug_supported_mask |= hotplug_mask;
+
        intel_sdvo_select_ddc_bus(dev_priv, intel_sdvo, sdvo_reg);
 
        /* Set the input timing to the screen. Assume always input 0. */
index ea1024d79974a0f05b91c0e763ca6929266f5a72..e5f145d2cb3bac2565051a65cfbb07a8cf206c36 100644 (file)
@@ -84,6 +84,9 @@ static const struct file_operations mgag200_driver_fops = {
        .mmap = mgag200_mmap,
        .poll = drm_poll,
        .fasync = drm_fasync,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl = drm_compat_ioctl,
+#endif
        .read = drm_read,
 };
 
index 69688ef5cf46802d82922046577ada8d27f3a82c..7e16dc5e64672929e80a2aecf4b6e6e2446641b8 100644 (file)
@@ -598,7 +598,7 @@ nouveau_display_dumb_create(struct drm_file *file_priv, struct drm_device *dev,
        args->size = args->pitch * args->height;
        args->size = roundup(args->size, PAGE_SIZE);
 
-       ret = nouveau_gem_new(dev, args->size, 0, TTM_PL_FLAG_VRAM, 0, 0, &bo);
+       ret = nouveau_gem_new(dev, args->size, 0, NOUVEAU_GEM_DOMAIN_VRAM, 0, 0, &bo);
        if (ret)
                return ret;
 
index f429e6a8ca7aeba09b3f8ef852376ea8d360c4ee..c399d510b27a8611aa4524b3cffa582f9f033da7 100644 (file)
@@ -22,6 +22,7 @@
  * Authors: Ben Skeggs
  */
 
+#include <linux/dmi.h>
 #include "drmP.h"
 #include "nouveau_drv.h"
 #include "nouveau_hw.h"
@@ -110,11 +111,26 @@ 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 */
+       if (dmi_check_system(gpio_reset_ids))
+               nouveau_gpio_reset(dev);
+
        /* disable, and ack any pending gpio interrupts */
        nv_wr32(dev, 0xe050, 0x00000000);
        nv_wr32(dev, 0xe054, 0xffffffff);
index dac525b2994ee4bd28ff862625e7a6fe7649d2cd..8a2fc89b7763cc278c65a2ba20382165cde4a203 100644 (file)
@@ -1510,10 +1510,10 @@ nvd0_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode,
        case OUTPUT_DP:
                if (nv_connector->base.display_info.bpc == 6) {
                        nv_encoder->dp.datarate = mode->clock * 18 / 8;
-                       syncs |= 0x00000140;
+                       syncs |= 0x00000002 << 6;
                } else {
                        nv_encoder->dp.datarate = mode->clock * 24 / 8;
-                       syncs |= 0x00000180;
+                       syncs |= 0x00000005 << 6;
                }
 
                if (nv_encoder->dcb->sorconf.link & 1)
index 8acb34fd3fd548aa6e34d999682d0f8fafac95fd..8d7e33a0b243585100839905205a5f11ccab5f06 100644 (file)
@@ -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);
index 7b737b9339ad41e136a96237817ef099bfae3c10..2a59375dbe5205f64764771de6abfe7184a90be9 100644 (file)
@@ -131,7 +131,7 @@ int radeon_fence_emit(struct radeon_device *rdev,
  */
 void radeon_fence_process(struct radeon_device *rdev, int ring)
 {
-       uint64_t seq, last_seq;
+       uint64_t seq, last_seq, last_emitted;
        unsigned count_loop = 0;
        bool wake = false;
 
@@ -158,13 +158,15 @@ void radeon_fence_process(struct radeon_device *rdev, int ring)
         */
        last_seq = atomic64_read(&rdev->fence_drv[ring].last_seq);
        do {
+               last_emitted = rdev->fence_drv[ring].sync_seq[ring];
                seq = radeon_fence_read(rdev, ring);
                seq |= last_seq & 0xffffffff00000000LL;
                if (seq < last_seq) {
-                       seq += 0x100000000LL;
+                       seq &= 0xffffffff;
+                       seq |= last_emitted & 0xffffffff00000000LL;
                }
 
-               if (seq == last_seq) {
+               if (seq <= last_seq || seq > last_emitted) {
                        break;
                }
                /* If we loop over we don't want to return without
index d31d4cca9a4c7425609cf92d9e8fcb5a512cc4f0..c5a164337bd5deaf7fd85f15b94f0f8b21fbba88 100644 (file)
@@ -43,6 +43,9 @@ static const struct file_operations savage_driver_fops = {
        .mmap = drm_mmap,
        .poll = drm_poll,
        .fasync = drm_fasync,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl = drm_compat_ioctl,
+#endif
        .llseek = noop_llseek,
 };
 
index 7f119870147c04cee307eaded5e6bf1abfba2bff..867dc03000e62007f470fc963706369d7411b90c 100644 (file)
@@ -74,6 +74,9 @@ static const struct file_operations sis_driver_fops = {
        .mmap = drm_mmap,
        .poll = drm_poll,
        .fasync = drm_fasync,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl = drm_compat_ioctl,
+#endif
        .llseek = noop_llseek,
 };
 
index 90f6b13acfac416270ac5abb70fa919cf66b611a..a7f4d6bd1330de6ad9e5878be70019d3e6ebf2df 100644 (file)
@@ -49,6 +49,9 @@ static const struct file_operations tdfx_driver_fops = {
        .mmap = drm_mmap,
        .poll = drm_poll,
        .fasync = drm_fasync,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl = drm_compat_ioctl,
+#endif
        .llseek = noop_llseek,
 };
 
index 6e52069894b35d91037474521e5ebf6e2f157e98..9f84128505bb420703745d426f0cdba4c8a46ab6 100644 (file)
@@ -66,6 +66,9 @@ static const struct file_operations udl_driver_fops = {
        .unlocked_ioctl = drm_ioctl,
        .release = drm_release,
        .fasync = drm_fasync,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl = drm_compat_ioctl,
+#endif
        .llseek = noop_llseek,
 };
 
index e927b4c052f52a4ed2e73a296354a0e84c849f20..af1b914b17e399a8de2265bd8cbdff32ed553a06 100644 (file)
@@ -65,6 +65,9 @@ static const struct file_operations via_driver_fops = {
        .mmap = drm_mmap,
        .poll = drm_poll,
        .fasync = drm_fasync,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl = drm_compat_ioctl,
+#endif
        .llseek = noop_llseek,
 };
 
index 794ff67c5701386ce781abe5c0f91e42de150e26..b71bcd0bfbbf65a60dea1ea47beef41daddb7d8c 100644 (file)
@@ -12,3 +12,11 @@ config DRM_VMWGFX
          This is a KMS enabled DRM driver for the VMware SVGA2
          virtual hardware.
          The compiled module will be called "vmwgfx.ko".
+
+config DRM_VMWGFX_FBCON
+       depends on DRM_VMWGFX
+       bool "Enable framebuffer console under vmwgfx by default"
+       help
+          Choose this option if you are shipping a new vmwgfx
+          userspace driver that supports using the kernel driver.
+
index 4d9edead01acdbcb900a3fdca87d5ed08cdab682..ba2c35dbf10e3a7c90095d3fce4265dd3cfd14ff 100644 (file)
@@ -182,8 +182,9 @@ static struct pci_device_id vmw_pci_id_list[] = {
        {0x15ad, 0x0405, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VMWGFX_CHIP_SVGAII},
        {0, 0, 0}
 };
+MODULE_DEVICE_TABLE(pci, vmw_pci_id_list);
 
-static int enable_fbdev;
+static int enable_fbdev = IS_ENABLED(CONFIG_DRM_VMWGFX_FBCON);
 
 static int vmw_probe(struct pci_dev *, const struct pci_device_id *);
 static void vmw_master_init(struct vmw_master *);
@@ -1154,6 +1155,11 @@ static struct drm_driver driver = {
        .open = vmw_driver_open,
        .preclose = vmw_preclose,
        .postclose = vmw_postclose,
+
+       .dumb_create = vmw_dumb_create,
+       .dumb_map_offset = vmw_dumb_map_offset,
+       .dumb_destroy = vmw_dumb_destroy,
+
        .fops = &vmwgfx_driver_fops,
        .name = VMWGFX_DRIVER_NAME,
        .desc = VMWGFX_DRIVER_DESC,
index d0f2c079ee2732d62f064b2667747412b5b6fb1c..29c984ff7f23aed1012e70d7e3e0744c1d1fa026 100644 (file)
@@ -645,6 +645,16 @@ int vmw_kms_readback(struct vmw_private *dev_priv,
 int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
                                struct drm_file *file_priv);
 
+int vmw_dumb_create(struct drm_file *file_priv,
+                   struct drm_device *dev,
+                   struct drm_mode_create_dumb *args);
+
+int vmw_dumb_map_offset(struct drm_file *file_priv,
+                       struct drm_device *dev, uint32_t handle,
+                       uint64_t *offset);
+int vmw_dumb_destroy(struct drm_file *file_priv,
+                    struct drm_device *dev,
+                    uint32_t handle);
 /**
  * Overlay control - vmwgfx_overlay.c
  */
index 22bf9a21ec7137a38735feea3c131ce72f156516..2c6ffe0e2c07828bc7b07e3a9bf55b71e7d438f6 100644 (file)
@@ -1917,3 +1917,76 @@ err_ref:
        vmw_resource_unreference(&res);
        return ret;
 }
+
+
+int vmw_dumb_create(struct drm_file *file_priv,
+                   struct drm_device *dev,
+                   struct drm_mode_create_dumb *args)
+{
+       struct vmw_private *dev_priv = vmw_priv(dev);
+       struct vmw_master *vmaster = vmw_master(file_priv->master);
+       struct vmw_user_dma_buffer *vmw_user_bo;
+       struct ttm_buffer_object *tmp;
+       int ret;
+
+       args->pitch = args->width * ((args->bpp + 7) / 8);
+       args->size = args->pitch * args->height;
+
+       vmw_user_bo = kzalloc(sizeof(*vmw_user_bo), GFP_KERNEL);
+       if (vmw_user_bo == NULL)
+               return -ENOMEM;
+
+       ret = ttm_read_lock(&vmaster->lock, true);
+       if (ret != 0) {
+               kfree(vmw_user_bo);
+               return ret;
+       }
+
+       ret = vmw_dmabuf_init(dev_priv, &vmw_user_bo->dma, args->size,
+                             &vmw_vram_sys_placement, true,
+                             &vmw_user_dmabuf_destroy);
+       if (ret != 0)
+               goto out_no_dmabuf;
+
+       tmp = ttm_bo_reference(&vmw_user_bo->dma.base);
+       ret = ttm_base_object_init(vmw_fpriv(file_priv)->tfile,
+                                  &vmw_user_bo->base,
+                                  false,
+                                  ttm_buffer_type,
+                                  &vmw_user_dmabuf_release, NULL);
+       if (unlikely(ret != 0))
+               goto out_no_base_object;
+
+       args->handle = vmw_user_bo->base.hash.key;
+
+out_no_base_object:
+       ttm_bo_unref(&tmp);
+out_no_dmabuf:
+       ttm_read_unlock(&vmaster->lock);
+       return ret;
+}
+
+int vmw_dumb_map_offset(struct drm_file *file_priv,
+                       struct drm_device *dev, uint32_t handle,
+                       uint64_t *offset)
+{
+       struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+       struct vmw_dma_buffer *out_buf;
+       int ret;
+
+       ret = vmw_user_dmabuf_lookup(tfile, handle, &out_buf);
+       if (ret != 0)
+               return -EINVAL;
+
+       *offset = out_buf->base.addr_space_offset;
+       vmw_dmabuf_unreference(&out_buf);
+       return 0;
+}
+
+int vmw_dumb_destroy(struct drm_file *file_priv,
+                    struct drm_device *dev,
+                    uint32_t handle)
+{
+       return ttm_ref_object_base_unref(vmw_fpriv(file_priv)->tfile,
+                                        handle, TTM_REF_USAGE);
+}
index 8bf8a64e511543989c41624338304d0f11f0c59b..8bcd168fffaebbf80808fa9ee9c02e42384eb1f5 100644 (file)
@@ -996,7 +996,8 @@ static void hid_process_event(struct hid_device *hid, struct hid_field *field,
        struct hid_driver *hdrv = hid->driver;
        int ret;
 
-       hid_dump_input(hid, usage, value);
+       if (!list_empty(&hid->debug_list))
+               hid_dump_input(hid, usage, value);
 
        if (hdrv && hdrv->event && hid_match_usage(hid, usage)) {
                ret = hdrv->event(hid, field, usage, value);
@@ -1558,7 +1559,9 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LCPOWER, USB_DEVICE_ID_LCPOWER_LC1000 ) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) },
+#if IS_ENABLED(CONFIG_HID_LENOVO_TPKBD)
+       { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) },
+#endif
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2) },
index 77d2df04c97b0dbe6c34eb11b9e566ae07d5ae28..60c4e1e85913fd435ba7c3fe977db50e4fb00f6c 100644 (file)
@@ -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);
 }
 
index 4d524b5f52f5631179e9092d6ee471522d3735a3..9500f2f3f8fea702432e683a56dc0eea53dbf3fe 100644 (file)
@@ -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)
 {
index fd28a5e0ca3b84b8407791421b25f8b17bf7815a..4a4000340ce1ed8cf6be1f81ee8e0f21d8ba5f5a 100644 (file)
@@ -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 {
index 903eef3d3e10034f8e36974ba4e95ee746438702..991e85c7325c849d4e7c287afe28364a8e3351e6 100644 (file)
@@ -70,6 +70,7 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_AXIS_295, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET },
+       { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2, HID_QUIRK_NO_INIT_REPORTS },
index cfec802cf9ca949b705d24a1d862a702af223193..f915eb1c29f7030e0612c80812e2b32ba25334b4 100644 (file)
@@ -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,
 };
index e65c6e45d36b05a24241680558fd2012be3f3c85..7bf4ce3d405e4903e26c010cc9040ce87e7067ba 100644 (file)
@@ -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
 };
 
index 282708860517e8de41e2f86c3aeb55a118aaca17..8f3f6f2c45fd1a5ba95664a4ba92a6ffe7e6323c 100644 (file)
 
 #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
index 0fa356fe82ccc00fc6a70704627da99bb66fc49a..984a3f13923b615b7c6849cd59b396689680ed20 100644 (file)
@@ -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);
 }
 
index 2764b78a784b9be83f9df1fd48f558452d9b8d61..af69073b3fe87a323e8986f76268c3ec1aa78522 100644 (file)
@@ -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);
index 7f3f4a385729375c002409387d157f3565b30e04..602148299f68db03a81683ab95c14e39614e5d8d 100644 (file)
@@ -69,22 +69,6 @@ struct ina2xx_data {
        u16 regs[INA2XX_MAX_REGISTERS];
 };
 
-int ina2xx_read_word(struct i2c_client *client, int reg)
-{
-       int val = i2c_smbus_read_word_data(client, reg);
-       if (unlikely(val < 0)) {
-               dev_dbg(&client->dev,
-                       "Failed to read register: %d\n", reg);
-               return val;
-       }
-       return be16_to_cpu(val);
-}
-
-void ina2xx_write_word(struct i2c_client *client, int reg, int data)
-{
-       i2c_smbus_write_word_data(client, reg, cpu_to_be16(data));
-}
-
 static struct ina2xx_data *ina2xx_update_device(struct device *dev)
 {
        struct i2c_client *client = to_i2c_client(dev);
@@ -102,7 +86,7 @@ static struct ina2xx_data *ina2xx_update_device(struct device *dev)
 
                /* Read all registers */
                for (i = 0; i < data->registers; i++) {
-                       int rv = ina2xx_read_word(client, i);
+                       int rv = i2c_smbus_read_word_swapped(client, i);
                        if (rv < 0) {
                                ret = ERR_PTR(rv);
                                goto abort;
@@ -279,22 +263,26 @@ static int ina2xx_probe(struct i2c_client *client,
        switch (data->kind) {
        case ina219:
                /* device configuration */
-               ina2xx_write_word(client, INA2XX_CONFIG, INA219_CONFIG_DEFAULT);
+               i2c_smbus_write_word_swapped(client, INA2XX_CONFIG,
+                                            INA219_CONFIG_DEFAULT);
 
                /* set current LSB to 1mA, shunt is in uOhms */
                /* (equation 13 in datasheet) */
-               ina2xx_write_word(client, INA2XX_CALIBRATION, 40960000 / shunt);
+               i2c_smbus_write_word_swapped(client, INA2XX_CALIBRATION,
+                                            40960000 / shunt);
                dev_info(&client->dev,
                         "power monitor INA219 (Rshunt = %li uOhm)\n", shunt);
                data->registers = INA219_REGISTERS;
                break;
        case ina226:
                /* device configuration */
-               ina2xx_write_word(client, INA2XX_CONFIG, INA226_CONFIG_DEFAULT);
+               i2c_smbus_write_word_swapped(client, INA2XX_CONFIG,
+                                            INA226_CONFIG_DEFAULT);
 
                /* set current LSB to 1mA, shunt is in uOhms */
                /* (equation 1 in datasheet)*/
-               ina2xx_write_word(client, INA2XX_CALIBRATION, 5120000 / shunt);
+               i2c_smbus_write_word_swapped(client, INA2XX_CALIBRATION,
+                                            5120000 / shunt);
                dev_info(&client->dev,
                         "power monitor INA226 (Rshunt = %li uOhm)\n", shunt);
                data->registers = INA226_REGISTERS;
index 0018c7dd0097de5045f646d98e715713ea7edba4..1a174f0a3cdeb9bd854d13fa61171a63c33e41d7 100644 (file)
@@ -44,12 +44,13 @@ static ssize_t madc_read(struct device *dev,
                         struct device_attribute *devattr, char *buf)
 {
        struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-       struct twl4030_madc_request req;
+       struct twl4030_madc_request req = {
+               .channels = 1 << attr->index,
+               .method = TWL4030_MADC_SW2,
+               .type = TWL4030_MADC_WAIT,
+       };
        long val;
 
-       req.channels = (1 << attr->index);
-       req.method = TWL4030_MADC_SW2;
-       req.func_cb = NULL;
        val = twl4030_madc_conversion(&req);
        if (val < 0)
                return val;
index ee4ebc198a9448e868f45af079e8f3d5f51968ae..2e56c6ce9fb654cb0532f4cbef756fd99f618e9d 100644 (file)
@@ -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);
 }
 
index 1201a15784c3a0eec329affa6f6edf1546df0b51..db713c0dfba4d6c6272ac19c79b793595a9cdad7 100644 (file)
@@ -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 */
index 73133b1063f012416d2a957f3fc2432ace395439..6f5f98d69af7c26b2fd7b895106e11745ce7d155 100644 (file)
@@ -476,17 +476,17 @@ static int pca_init(struct i2c_adapter *adap)
                /* To avoid integer overflow, use clock/100 for calculations */
                clock = pca_clock(pca_data) / 100;
 
-               if (pca_data->i2c_clock > 10000) {
+               if (pca_data->i2c_clock > 1000000) {
                        mode = I2C_PCA_MODE_TURBO;
                        min_tlow = 14;
                        min_thi  = 5;
                        raise_fall_time = 22; /* Raise 11e-8s, Fall 11e-8s */
-               } else if (pca_data->i2c_clock > 4000) {
+               } else if (pca_data->i2c_clock > 400000) {
                        mode = I2C_PCA_MODE_FASTP;
                        min_tlow = 17;
                        min_thi  = 9;
                        raise_fall_time = 22; /* Raise 11e-8s, Fall 11e-8s */
-               } else if (pca_data->i2c_clock > 1000) {
+               } else if (pca_data->i2c_clock > 100000) {
                        mode = I2C_PCA_MODE_FAST;
                        min_tlow = 44;
                        min_thi  = 20;
index b4aaa1bd6728503b629acea078f3021fc148115a..970a1612e795566f007ccebe2b6ae811131694c9 100644 (file)
@@ -104,6 +104,7 @@ config I2C_I801
            DH89xxCC (PCH)
            Panther Point (PCH)
            Lynx Point (PCH)
+           Lynx Point-LP (PCH)
 
          This driver can also be built as a module.  If so, the module
          will be called i2c-i801.
@@ -354,9 +355,13 @@ config I2C_DAVINCI
          devices such as DaVinci NIC.
          For details please see http://www.ti.com/davinci
 
+config I2C_DESIGNWARE_CORE
+       tristate
+
 config I2C_DESIGNWARE_PLATFORM
        tristate "Synopsys DesignWare Platform"
        depends on HAVE_CLK
+       select I2C_DESIGNWARE_CORE
        help
          If you say yes to this option, support will be included for the
          Synopsys DesignWare I2C adapter. Only master mode is supported.
@@ -367,6 +372,7 @@ config I2C_DESIGNWARE_PLATFORM
 config I2C_DESIGNWARE_PCI
        tristate "Synopsys DesignWare PCI"
        depends on PCI
+       select I2C_DESIGNWARE_CORE
        help
          If you say yes to this option, support will be included for the
          Synopsys DesignWare I2C adapter. Only master mode is supported.
index ce3c2be7fb40a6cb453a92a9cc1eb89da510383f..37c4182cc98bb28520eeb1ce579bb3b601cffc01 100644 (file)
@@ -33,10 +33,11 @@ obj-$(CONFIG_I2C_AU1550)    += i2c-au1550.o
 obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o
 obj-$(CONFIG_I2C_CPM)          += i2c-cpm.o
 obj-$(CONFIG_I2C_DAVINCI)      += i2c-davinci.o
+obj-$(CONFIG_I2C_DESIGNWARE_CORE)      += i2c-designware-core.o
 obj-$(CONFIG_I2C_DESIGNWARE_PLATFORM)  += i2c-designware-platform.o
-i2c-designware-platform-objs := i2c-designware-platdrv.o i2c-designware-core.o
+i2c-designware-platform-objs := i2c-designware-platdrv.o
 obj-$(CONFIG_I2C_DESIGNWARE_PCI)       += i2c-designware-pci.o
-i2c-designware-pci-objs := i2c-designware-pcidrv.o i2c-designware-core.o
+i2c-designware-pci-objs := i2c-designware-pcidrv.o
 obj-$(CONFIG_I2C_EG20T)                += i2c-eg20t.o
 obj-$(CONFIG_I2C_GPIO)         += i2c-gpio.o
 obj-$(CONFIG_I2C_HIGHLANDER)   += i2c-highlander.o
index 1e48bec80edfb08a0628cc816004c1955075fc42..7b8ebbefb581156ee8dd795cd6c4d458e37367f7 100644 (file)
@@ -25,6 +25,7 @@
  * ----------------------------------------------------------------------------
  *
  */
+#include <linux/export.h>
 #include <linux/clk.h>
 #include <linux/errno.h>
 #include <linux/err.h>
@@ -316,6 +317,7 @@ int i2c_dw_init(struct dw_i2c_dev *dev)
        dw_writel(dev, dev->master_cfg , DW_IC_CON);
        return 0;
 }
+EXPORT_SYMBOL_GPL(i2c_dw_init);
 
 /*
  * Waiting for bus not busy
@@ -568,12 +570,14 @@ done:
 
        return ret;
 }
+EXPORT_SYMBOL_GPL(i2c_dw_xfer);
 
 u32 i2c_dw_func(struct i2c_adapter *adap)
 {
        struct dw_i2c_dev *dev = i2c_get_adapdata(adap);
        return dev->functionality;
 }
+EXPORT_SYMBOL_GPL(i2c_dw_func);
 
 static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev)
 {
@@ -678,17 +682,20 @@ tx_aborted:
 
        return IRQ_HANDLED;
 }
+EXPORT_SYMBOL_GPL(i2c_dw_isr);
 
 void i2c_dw_enable(struct dw_i2c_dev *dev)
 {
        /* Enable the adapter */
        dw_writel(dev, 1, DW_IC_ENABLE);
 }
+EXPORT_SYMBOL_GPL(i2c_dw_enable);
 
 u32 i2c_dw_is_enabled(struct dw_i2c_dev *dev)
 {
        return dw_readl(dev, DW_IC_ENABLE);
 }
+EXPORT_SYMBOL_GPL(i2c_dw_is_enabled);
 
 void i2c_dw_disable(struct dw_i2c_dev *dev)
 {
@@ -699,18 +706,22 @@ void i2c_dw_disable(struct dw_i2c_dev *dev)
        dw_writel(dev, 0, DW_IC_INTR_MASK);
        dw_readl(dev, DW_IC_CLR_INTR);
 }
+EXPORT_SYMBOL_GPL(i2c_dw_disable);
 
 void i2c_dw_clear_int(struct dw_i2c_dev *dev)
 {
        dw_readl(dev, DW_IC_CLR_INTR);
 }
+EXPORT_SYMBOL_GPL(i2c_dw_clear_int);
 
 void i2c_dw_disable_int(struct dw_i2c_dev *dev)
 {
        dw_writel(dev, 0, DW_IC_INTR_MASK);
 }
+EXPORT_SYMBOL_GPL(i2c_dw_disable_int);
 
 u32 i2c_dw_read_comp_param(struct dw_i2c_dev *dev)
 {
        return dw_readl(dev, DW_IC_COMP_PARAM_1);
 }
+EXPORT_SYMBOL_GPL(i2c_dw_read_comp_param);
index 898dcf9c7adeaac26d932b6e8c6a6e8d90e9be66..33e9b0c09af208762f7f8f58b4c3895798618233 100644 (file)
@@ -52,6 +52,7 @@
   DH89xxCC (PCH)        0x2330     32     hard     yes     yes     yes
   Panther Point (PCH)   0x1e22     32     hard     yes     yes     yes
   Lynx Point (PCH)      0x8c22     32     hard     yes     yes     yes
+  Lynx Point-LP (PCH)   0x9c22     32     hard     yes     yes     yes
 
   Features supported by this driver:
   Software PEC                     no
 #define PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS     0x2330
 #define PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS        0x3b30
 #define PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS    0x8c22
+#define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_SMBUS 0x9c22
 
 struct i801_priv {
        struct i2c_adapter adapter;
@@ -771,6 +773,7 @@ static DEFINE_PCI_DEVICE_TABLE(i801_ids) = {
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS) },
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PANTHERPOINT_SMBUS) },
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_SMBUS) },
        { 0, }
 };
 
index 088c5c1ed17dfe831c4345ee8f02dd0ef4e1c82d..51f05b8520edb3f95b983d5002859afd386586e4 100644 (file)
@@ -365,10 +365,6 @@ static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c)
        struct device_node *node = dev->of_node;
        int ret;
 
-       if (!node)
-               return -EINVAL;
-
-       i2c->speed = &mxs_i2c_95kHz_config;
        ret = of_property_read_u32(node, "clock-frequency", &speed);
        if (ret)
                dev_warn(dev, "No I2C speed selected, using 100kHz\n");
@@ -419,10 +415,13 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev)
                return err;
 
        i2c->dev = dev;
+       i2c->speed = &mxs_i2c_95kHz_config;
 
-       err = mxs_i2c_get_ofdata(i2c);
-       if (err)
-               return err;
+       if (dev->of_node) {
+               err = mxs_i2c_get_ofdata(i2c);
+               if (err)
+                       return err;
+       }
 
        platform_set_drvdata(pdev, i2c);
 
index 5d54416770b01e7816cc85cd7dcbf403bf407442..8488bddfe46596109249edd242a3ad0ebc7cfe8b 100644 (file)
@@ -48,8 +48,9 @@ enum {
        mcntrl_afie = 0x00000002,
        mcntrl_naie = 0x00000004,
        mcntrl_drmie = 0x00000008,
-       mcntrl_daie = 0x00000020,
-       mcntrl_rffie = 0x00000040,
+       mcntrl_drsie = 0x00000010,
+       mcntrl_rffie = 0x00000020,
+       mcntrl_daie = 0x00000040,
        mcntrl_tffie = 0x00000080,
        mcntrl_reset = 0x00000100,
        mcntrl_cdbmode = 0x00000400,
@@ -290,31 +291,37 @@ static int i2c_pnx_master_rcv(struct i2c_pnx_algo_data *alg_data)
         * or we didn't 'ask' for it yet.
         */
        if (ioread32(I2C_REG_STS(alg_data)) & mstatus_rfe) {
-               dev_dbg(&alg_data->adapter.dev,
-                       "%s(): Write dummy data to fill Rx-fifo...\n",
-                       __func__);
+               /* 'Asking' is done asynchronously, e.g. dummy TX of several
+                * bytes is done before the first actual RX arrives in FIFO.
+                * Therefore, ordered bytes (via TX) are counted separately.
+                */
+               if (alg_data->mif.order) {
+                       dev_dbg(&alg_data->adapter.dev,
+                               "%s(): Write dummy data to fill Rx-fifo...\n",
+                               __func__);
 
-               if (alg_data->mif.len == 1) {
-                       /* Last byte, do not acknowledge next rcv. */
-                       val |= stop_bit;
+                       if (alg_data->mif.order == 1) {
+                               /* Last byte, do not acknowledge next rcv. */
+                               val |= stop_bit;
+
+                               /*
+                                * Enable interrupt RFDAIE (data in Rx fifo),
+                                * and disable DRMIE (need data for Tx)
+                                */
+                               ctl = ioread32(I2C_REG_CTL(alg_data));
+                               ctl |= mcntrl_rffie | mcntrl_daie;
+                               ctl &= ~mcntrl_drmie;
+                               iowrite32(ctl, I2C_REG_CTL(alg_data));
+                       }
 
                        /*
-                        * Enable interrupt RFDAIE (data in Rx fifo),
-                        * and disable DRMIE (need data for Tx)
+                        * Now we'll 'ask' for data:
+                        * For each byte we want to receive, we must
+                        * write a (dummy) byte to the Tx-FIFO.
                         */
-                       ctl = ioread32(I2C_REG_CTL(alg_data));
-                       ctl |= mcntrl_rffie | mcntrl_daie;
-                       ctl &= ~mcntrl_drmie;
-                       iowrite32(ctl, I2C_REG_CTL(alg_data));
+                       iowrite32(val, I2C_REG_TX(alg_data));
+                       alg_data->mif.order--;
                }
-
-               /*
-                * Now we'll 'ask' for data:
-                * For each byte we want to receive, we must
-                * write a (dummy) byte to the Tx-FIFO.
-                */
-               iowrite32(val, I2C_REG_TX(alg_data));
-
                return 0;
        }
 
@@ -514,6 +521,7 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
 
                alg_data->mif.buf = pmsg->buf;
                alg_data->mif.len = pmsg->len;
+               alg_data->mif.order = pmsg->len;
                alg_data->mif.mode = (pmsg->flags & I2C_M_RD) ?
                        I2C_SMBUS_READ : I2C_SMBUS_WRITE;
                alg_data->mif.ret = 0;
@@ -566,6 +574,7 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
        /* Cleanup to be sure... */
        alg_data->mif.buf = NULL;
        alg_data->mif.len = 0;
+       alg_data->mif.order = 0;
 
        dev_dbg(&alg_data->adapter.dev, "%s(): exiting, stat = %x\n",
                __func__, ioread32(I2C_REG_STS(alg_data)));
index 2efa56c5ff2c32d10ff3018def5bc077b8492e4e..2091ae8f539a5e78ee59338cd29876109b22883d 100644 (file)
@@ -636,6 +636,22 @@ static void i2c_adapter_dev_release(struct device *dev)
        complete(&adap->dev_released);
 }
 
+/*
+ * This function is only needed for mutex_lock_nested, so it is never
+ * called unless locking correctness checking is enabled. Thus we
+ * make it inline to avoid a compiler warning. That's what gcc ends up
+ * doing anyway.
+ */
+static inline unsigned int i2c_adapter_depth(struct i2c_adapter *adapter)
+{
+       unsigned int depth = 0;
+
+       while ((adapter = i2c_parent_is_i2c_adapter(adapter)))
+               depth++;
+
+       return depth;
+}
+
 /*
  * Let users instantiate I2C devices through sysfs. This can be used when
  * platform initialization code doesn't contain the proper data for
@@ -726,7 +742,8 @@ i2c_sysfs_delete_device(struct device *dev, struct device_attribute *attr,
 
        /* Make sure the device was added through sysfs */
        res = -ENOENT;
-       mutex_lock(&adap->userspace_clients_lock);
+       mutex_lock_nested(&adap->userspace_clients_lock,
+                         i2c_adapter_depth(adap));
        list_for_each_entry_safe(client, next, &adap->userspace_clients,
                                 detected) {
                if (client->addr == addr) {
@@ -1073,7 +1090,8 @@ int i2c_del_adapter(struct i2c_adapter *adap)
                return res;
 
        /* Remove devices instantiated from sysfs */
-       mutex_lock(&adap->userspace_clients_lock);
+       mutex_lock_nested(&adap->userspace_clients_lock,
+                         i2c_adapter_depth(adap));
        list_for_each_entry_safe(client, next, &adap->userspace_clients,
                                 detected) {
                dev_dbg(&adap->dev, "Removing %s at 0x%x\n", client->name,
index f61780a02374d1f855af861092c3ebae5b35cd80..3bd5540238a7e6d683fd903cfacc14c8b05b92d5 100644 (file)
@@ -617,7 +617,7 @@ static int __devinit at91_adc_probe(struct platform_device *pdev)
        st->adc_clk = clk_get(&pdev->dev, "adc_op_clk");
        if (IS_ERR(st->adc_clk)) {
                dev_err(&pdev->dev, "Failed to get the ADC clock.\n");
-               ret = PTR_ERR(st->clk);
+               ret = PTR_ERR(st->adc_clk);
                goto error_disable_clk;
        }
 
index 51f42061dae9de4d375795e89e5a95b28bbc0405..6cfd4d8fd0bd8e240dd1311698a2cf603fcfed15 100644 (file)
@@ -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:
index cb5b7f7d4d3876904bb6b515273747c37787465d..b29a4246ef41ef6068372398ed23134cceae3384 100644 (file)
@@ -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;
 }
index 19f1e6c45fb6847caaac2a45af4e69d4df981ca4..ccb119143d20568eb0570ab5b1360a78ca888e08 100644 (file)
@@ -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;
+                       }
                }
        }
 
index ca43901ed861b8d2bc31c70a9e570d9db3d2f8c1..0af216d21f8790c31af507022bbc722627f41671 100644 (file)
@@ -262,7 +262,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;
@@ -271,9 +274,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;
 };
 
 /*
index 3e2085a3ee474fc0111c7034ca013bfda7d63d7e..1e19b5ae7c479a5865837ffa4b08f7f5c89bdcdc 100644 (file)
@@ -546,15 +546,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);
@@ -863,10 +863,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;
@@ -883,16 +883,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;
@@ -902,7 +900,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)
@@ -947,10 +945,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;
@@ -961,10 +957,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)) {
@@ -987,12 +983,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;
 }
@@ -1040,35 +1035,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)
@@ -1080,7 +1069,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;
@@ -1095,6 +1083,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 */
@@ -1111,9 +1100,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)
@@ -1125,10 +1116,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;
@@ -1138,16 +1129,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;
@@ -1156,7 +1145,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)
@@ -1164,37 +1153,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)
@@ -1203,7 +1199,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 */
@@ -1211,10 +1207,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);
 }
 
 
index 13f4aa7593c834f2ee1475c6471cad8e0bcd12f8..75367249f447f497851e76a0a4312b6000989ff2 100644 (file)
@@ -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;
index ff4c0a87a25f9804441ac90561e7c97e24610e85..cdc252612c0b35c453b976355c13b26f6d6767e1 100644 (file)
@@ -358,6 +358,7 @@ static void imx_keypad_inhibit(struct imx_keypad *keypad)
        /* Inhibit KDI and KRI interrupts. */
        reg_val = readw(keypad->mmio_base + KPSR);
        reg_val &= ~(KBD_STAT_KRIE | KBD_STAT_KDIE);
+       reg_val |= KBD_STAT_KPKR | KBD_STAT_KPKD;
        writew(reg_val, keypad->mmio_base + KPSR);
 
        /* Colums as open drain and disable all rows */
@@ -515,7 +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_prepare_enable(keypad->clk);
        imx_keypad_inhibit(keypad);
+       clk_disable_unprepare(keypad->clk);
 
        error = request_irq(irq, imx_keypad_irq_handler, 0,
                            pdev->name, keypad);
index f06231b7cab1ef762d7ad5db073b3a6b64d39987..84ec691c05aa983751492a8dff29c5ca87b27ad2 100644 (file)
@@ -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;
index 3f5649f190824408a25c495bdfd4da88b8febe9a..a261d857691957a98e732124f6370c6f8280451a 100644 (file)
@@ -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);
 
index 2ffd110bd5bc756e461051d39ba31238202a0fa7..2e77246c2e5ac8293569ecd19fe1df673c394c75 100644 (file)
@@ -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,
index 5ec774d6c82b4be13f06c97efffe7cc42860ebab..d6cc77a53c7e2bdbe94ee3c138ab8c86f0d90135 100644 (file)
@@ -176,6 +176,20 @@ static const struct dmi_system_id __initconst i8042_dmi_noloop_table[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "Spring Peak"),
                },
        },
+       {
+               /* Gigabyte T1005 - defines wrong chassis type ("Other") */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "T1005"),
+               },
+       },
+       {
+               /* Gigabyte T1005M/P - defines wrong chassis type ("Other") */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "T1005M/P"),
+               },
+       },
        {
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
@@ -319,6 +333,12 @@ static const struct dmi_system_id __initconst i8042_dmi_nomux_table[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "EQUIUM A110"),
                },
        },
+       {
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE C850D"),
+               },
+       },
        {
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "ALIENWARE"),
index 002041975de9c902f193f2448865d051f0ce98dc..532d067a9e07a0745188eb3dab8e4025ef7b664f 100644 (file)
@@ -1848,7 +1848,10 @@ static const struct wacom_features wacom_features_0x2A =
        { "Wacom Intuos5 M", WACOM_PKGLEN_INTUOS,  44704, 27940, 2047,
          63, INTUOS5, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
 static const struct wacom_features wacom_features_0xF4 =
-       { "Wacom Cintiq 24HD",    WACOM_PKGLEN_INTUOS,   104480, 65600, 2047,
+       { "Wacom Cintiq 24HD",       WACOM_PKGLEN_INTUOS,   104480, 65600, 2047,
+         63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+static const struct wacom_features wacom_features_0xF8 =
+       { "Wacom Cintiq 24HD touch", WACOM_PKGLEN_INTUOS,   104480, 65600, 2047,
          63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
 static const struct wacom_features wacom_features_0x3F =
        { "Wacom Cintiq 21UX",    WACOM_PKGLEN_INTUOS,    87200, 65600, 1023,
@@ -2091,6 +2094,7 @@ const struct usb_device_id wacom_ids[] = {
        { USB_DEVICE_WACOM(0xEF) },
        { USB_DEVICE_WACOM(0x47) },
        { USB_DEVICE_WACOM(0xF4) },
+       { USB_DEVICE_WACOM(0xF8) },
        { USB_DEVICE_WACOM(0xFA) },
        { USB_DEVICE_LENOVO(0x6004) },
        { }
index 9afc777a40a7077a5bbd667944f1c1ee3bac38d7..64957770b52209fcc527e3f015e21816b3165bc7 100644 (file)
@@ -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;
@@ -602,6 +605,7 @@ edt_ft5x06_ts_teardown_debugfs(struct edt_ft5x06_ts_data *tsdata)
 {
        if (tsdata->debug_dir)
                debugfs_remove_recursive(tsdata->debug_dir);
+       kfree(tsdata->raw_buffer);
 }
 
 #else
@@ -843,7 +847,6 @@ static int __devexit edt_ft5x06_ts_remove(struct i2c_client *client)
        if (gpio_is_valid(pdata->reset_pin))
                gpio_free(pdata->reset_pin);
 
-       kfree(tsdata->raw_buffer);
        kfree(tsdata);
 
        return 0;
index e32709e0dd65193286bccc2e81bd4e86d717c643..721fdb3597ca9d9ecb3f971f389f6852395ff39c 100644 (file)
@@ -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
 
index fa6ca473372539fda128a7a1ec46d9c4d13c3c4a..dceaec821b0e5324cbfa2d92bdb7334845bf9262 100644 (file)
@@ -857,8 +857,9 @@ avm_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
        switch (cmd) {
        case CLOSE_CHANNEL:
                test_and_clear_bit(FLG_OPEN, &bch->Flags);
+               cancel_work_sync(&bch->workq);
                spin_lock_irqsave(&fc->lock, flags);
-               mISDN_freebchannel(bch);
+               mISDN_clear_bchannel(bch);
                modehdlc(bch, ISDN_P_NONE);
                spin_unlock_irqrestore(&fc->lock, flags);
                ch->protocol = ISDN_P_NONE;
index 5e402cf2e79506b82288140334da60eb4e923e6d..f02794203bb193b41291efc3bc6d8457b2043883 100644 (file)
@@ -5059,6 +5059,7 @@ hfcmulti_init(struct hm_map *m, struct pci_dev *pdev,
                                printk(KERN_INFO
                                       "HFC-E1 #%d has overlapping B-channels on fragment #%d\n",
                                       E1_cnt + 1, pt);
+                               kfree(hc);
                                return -EINVAL;
                        }
                        maskcheck |= hc->bmask[pt];
@@ -5086,6 +5087,7 @@ hfcmulti_init(struct hm_map *m, struct pci_dev *pdev,
        if ((poll >> 1) > sizeof(hc->silence_data)) {
                printk(KERN_ERR "HFCMULTI error: silence_data too small, "
                       "please fix\n");
+               kfree(hc);
                return -EINVAL;
        }
        for (i = 0; i < (poll >> 1); i++)
index 752e0825591fbed9e820044495d42b9a80842320..ccd7d851be26d27913a26656cdef1fc838c90870 100644 (file)
@@ -1406,8 +1406,9 @@ hscx_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
        switch (cmd) {
        case CLOSE_CHANNEL:
                test_and_clear_bit(FLG_OPEN, &bch->Flags);
+               cancel_work_sync(&bch->workq);
                spin_lock_irqsave(hx->ip->hwlock, flags);
-               mISDN_freebchannel(bch);
+               mISDN_clear_bchannel(bch);
                hscx_mode(hx, ISDN_P_NONE);
                spin_unlock_irqrestore(hx->ip->hwlock, flags);
                ch->protocol = ISDN_P_NONE;
index be5973ded6d6e4288fe8fdebd0967150228ff937..182ecf0626c2098e3c38c4da0eeea54a1197ce7d 100644 (file)
@@ -1588,8 +1588,9 @@ isar_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
        switch (cmd) {
        case CLOSE_CHANNEL:
                test_and_clear_bit(FLG_OPEN, &bch->Flags);
+               cancel_work_sync(&bch->workq);
                spin_lock_irqsave(ich->is->hwlock, flags);
-               mISDN_freebchannel(bch);
+               mISDN_clear_bchannel(bch);
                modeisar(ich, ISDN_P_NONE);
                spin_unlock_irqrestore(ich->is->hwlock, flags);
                ch->protocol = ISDN_P_NONE;
index c3e3e76862731496b6bea5d35b3ca8ef5662e486..9bcade59eb73bdf24f72e8fa5a6e08e4be641f1c 100644 (file)
@@ -812,8 +812,9 @@ nj_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
        switch (cmd) {
        case CLOSE_CHANNEL:
                test_and_clear_bit(FLG_OPEN, &bch->Flags);
+               cancel_work_sync(&bch->workq);
                spin_lock_irqsave(&card->lock, flags);
-               mISDN_freebchannel(bch);
+               mISDN_clear_bchannel(bch);
                mode_tiger(bc, ISDN_P_NONE);
                spin_unlock_irqrestore(&card->lock, flags);
                ch->protocol = ISDN_P_NONE;
index 26a86b8460992e5e98c722f8b6487fb8ff1fe932..335fe6455002c708cfb0be66318b2473f4cdfcc7 100644 (file)
@@ -1054,8 +1054,9 @@ w6692_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
        switch (cmd) {
        case CLOSE_CHANNEL:
                test_and_clear_bit(FLG_OPEN, &bch->Flags);
+               cancel_work_sync(&bch->workq);
                spin_lock_irqsave(&card->lock, flags);
-               mISDN_freebchannel(bch);
+               mISDN_clear_bchannel(bch);
                w6692_mode(bc, ISDN_P_NONE);
                spin_unlock_irqrestore(&card->lock, flags);
                ch->protocol = ISDN_P_NONE;
index ef34fd40867cb6b7f5b767542c4da2e173d6b9cc..2602be23f341287468524c9fbd79e33a18e21aa6 100644 (file)
@@ -148,17 +148,16 @@ mISDN_clear_bchannel(struct bchannel *ch)
        ch->next_minlen = ch->init_minlen;
        ch->maxlen = ch->init_maxlen;
        ch->next_maxlen = ch->init_maxlen;
+       skb_queue_purge(&ch->rqueue);
+       ch->rcount = 0;
 }
 EXPORT_SYMBOL(mISDN_clear_bchannel);
 
-int
+void
 mISDN_freebchannel(struct bchannel *ch)
 {
+       cancel_work_sync(&ch->workq);
        mISDN_clear_bchannel(ch);
-       skb_queue_purge(&ch->rqueue);
-       ch->rcount = 0;
-       flush_work_sync(&ch->workq);
-       return 0;
 }
 EXPORT_SYMBOL(mISDN_freebchannel);
 
index 3f6203a4c7ea0dd730b80a6b441b99e8a4da3216..308e87b417e05a74e4429bac63e1eb2e7af43885 100644 (file)
@@ -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)
index adda94df5eb2352775e64fb7fae4e88c6e89a98b..7031b865b3a030488614764528295d509c663ba5 100644 (file)
@@ -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))
@@ -4192,7 +4196,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);
index b67a3018b13645f2e15f9c773f92d6f9e5acba06..ce229ea933d1388467aed017b9f65d4a2f9ef3a1 100644 (file)
@@ -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;
index 6146583589f61b53af6918db338861f116596a5b..c20a31136f045ccd57c0c19ec62ceb6b229bc861 100644 (file)
@@ -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;
index d09918cf1b1556a74edb622e0174d3ceffdf7ca6..b73f033b2c602fadce09dd97d0c7623581962e12 100644 (file)
@@ -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");
 }
index 44a3fdbadef40df1e09b12884f44caa46b76f0ac..f1beb4971f87f580090df39b38dbdc5e9937140e 100644 (file)
@@ -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;
index 78fca2902c8da38fd07660e381e8ed55c0d78c2d..01781ae5d0d7f3de38c811dad727ecc179c94be7 100644 (file)
@@ -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);
 
index 626b4ecaf64761fdd3cd43ac3f02986d6830e467..47adf800024e01f8cdf05856eb3b356226c527f3 100644 (file)
@@ -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");
        }
index c7983e862549a0b79775cae3e76c7cf0c867ad83..1b48f2094806c75fa8914657978f1b7bf814ae93 100644 (file)
@@ -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;
        }
 
index 683e18a23329802875d03f92d53e354a6474ad9d..62f0883a7630c360ab9e52f9fa11f306d1a3efee 100644 (file)
@@ -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:
index 3419e726de478cb330801d1dfb1db42d2a5d1748..2b282133c725b1b6fbb9c0f10442760640bfcd47 100644 (file)
@@ -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;
index 2544910e1fd604f5f6184009a1a208fa5f838cf2..a0a62b24621b831cb0c7c43e62692bd061eb7163 100644 (file)
@@ -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;
 
index 4e2af2cb2d26a76534c884c3cc57fe97f3c30d52..45e83a68641b81d0a5f7605b19027e2cd5b1aec0 100644 (file)
@@ -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;
index 7040a0081130c93ce6b73145355abec0a8c571b8..0e63cdd9b52abc44666c57994623e120f11644b2 100644 (file)
@@ -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;
index 04c7093d6499cb88f330b2f768713e49e58c9ffc..9e5453d21a6806263d17bc6ada0c07a3a2a7013a 100644 (file)
@@ -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");
        }
index 59df5584cb58f54a25a424ca2551417a231fcb4d..266bdc5bd96d17ea1bc05967d911aa4b9b7fc8bb 100644 (file)
@@ -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;
 
index 2ea99989551af85a4796c69e5fc2b65ba7a951e9..965c4801df8a1765e069ecb8707df451984b080a 100644 (file)
@@ -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);
 }
 
 /*
index 87662a17dec62d527a3af1b8b7fb8c782c85dd92..c6b6d7dda517528081a9e3f7e96d96458846ef67 100644 (file)
@@ -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;
 
index 0b2879b87fd999f537bbfc652da9a29c90eb1042..24212f45b201458961373df48c08d9a1f7f9536d 100644 (file)
@@ -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;
index 027cc8f861324de8f10bc7e9a1aa66af9e6ef093..092ad4b44b6d67b9b4ee039fccc73da1748d3a2c 100644 (file)
@@ -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;
 }
 
index 9f20abc5e3937065238ff1f3240c27cde9cbb4f6..f6b9c5c96b24f7d68e80b9ca2db8f202c2e3dd91 100644 (file)
@@ -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;
index c03e12b51924060704641c0152ad6e629d167a72..d9e24c849a00a3f21aad864442293aa2db0ca64d 100644 (file)
@@ -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;
index 2b403569e0a6411a92c0e7cb66c7d703d60cc0cf..1029d018c73921828f34740b4034c0cd7df5c3bd 100644 (file)
@@ -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)
index a1811cb50ec75fc7c1dffd02aca98f132d7e4810..cc5155e20494726c2ae6954e64128f61973ebafd 100644 (file)
@@ -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;
 
index 825a7f06d9ba5ade6281810bec19c209187561b2..ee53757beca7e8344c15a66bbe5d51bcce7b9da1 100644 (file)
@@ -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;
index 10b629c245b6770d304dde9bf978891c2a5ac800..f123517065ec911ff6e4154aa25a3f8e1dd0bd98 100644 (file)
@@ -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
index 6ef56d28c05686bf298f589cebf91c43fcc707b8..d7218cc90945a643ee03cc670852d42078131503 100644 (file)
@@ -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;
index b801dc72f041a125fcf9a52e25e6d594ee052d92..1ec79b54bd2f12f304c57f92633cc8c125a0d389 100644 (file)
@@ -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)
index 0c3a01cde2f7615960fb2c9cc20ba7489bf00fbd..f8b77711ad2da4c26acade369d0bc6443631427b 100644 (file)
@@ -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]);
        }
index c4a69f193a1df1985abfbaeeffb8e39cda933493..a345f9bb7b4758765725cf2c056303950ecc1c02 100644 (file)
@@ -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)
index cdc1df7fa0e94d10a26059c18dd347c045dcf2cd..3a8fa88567b18385461fbed0bbc9ff30e8d0fffc 100644 (file)
@@ -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;
index 685d61e431adfa4f8b733a13bd5c93cfb71c9a44..0f70dce611605fb5e92419c5ac393c2079b74833 100644 (file)
@@ -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)
index 2988efde11ebc60b6a714044f79d6a7cd9a44dba..49d361a618d06f5f26d17c49a8c9d48e20547caf 100644 (file)
@@ -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 */
index d31fed07aefbc51bfb620c492a2f05197886eb36..d35da6820beae8ee2c7e01e1faf51cc48c96972b 100644 (file)
@@ -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;
index 2dd8d49cb30bc7d63d14250e673b2c12eb4cef3f..c94f521f392cb0b5214385ff57ac6e18e8762907 100644 (file)
@@ -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)
index 2d9e8799e733c6644c18aa9335e9796ef0c0709f..b32940ec903425d37010b79eed9a16e4b3c20761 100644 (file)
@@ -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;
index 048bf0532a095014e03358b01af1f4cd58585b97..b56ba6b43294b77e536b12247c0e8b1d18085701 100644 (file)
@@ -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;
index d20a284ad4baca528c36eb351200ff16fdd5282e..413c891102f867d32b3bd62b25bb02120fe0159e 100644 (file)
@@ -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;
index 9612264f0e6dcf7832ebf2f4736815b4eabc6a4b..dcab026fcbb25070a7c79c8e2601b3b911079367 100644 (file)
@@ -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;
index 4fb0e6c8e8fe0fbfee94299b7c0de45920621a25..7c3675a74f93414c806543f4c50bc44cbb8ad46f 100644 (file)
@@ -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;
index a447f4ec11fb757ee38755aa44da467f83229d1f..cccc626c83c80c2bf79cf03c89936d5249a44714 100644 (file)
@@ -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;
index a293b978e27ce19b116025e3ab4e87be6ae0dd74..14051bdc714b80197f258c14afd9cf629667e765 100644 (file)
@@ -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;
 
index 33ba7723c967435b67c49a6f3f78212a63204b4e..1b203499c74402c59c19bf29a8ce6aa7b51a058b 100644 (file)
@@ -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;
index 80e24f4b47bffce67679b7e637627e9e7c769466..50fd87c87a1cca64e21104401c1adbff1b4cf45c 100644 (file)
@@ -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);
index 61c097a98f5de7eb45fd0ccb8fdc44dd53c869fa..a95e9421b73580df95402f718a4166898a1c41dd 100644 (file)
 #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);
 
index 353c34812120fc46e37140c0b6a04babdd5cb080..5f58370ccf5502b1d6a729f2daa0db411a6e3e1d 100644 (file)
@@ -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;
index 1c563792c777ba8f04c194a2a99c39159d8871f7..d3ce4d569deb57c2b707dc73d6cb7cf600962cab 100644 (file)
@@ -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;
index 74fd8cb5f37224e576f58398c20fda9f4884d9e7..4658b5bdcd84488d3379a2ef4f33e334eb96ea2f 100644 (file)
@@ -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;
 
index 838ce4eb444e24ce44bd3b120fe21a9f977d6e75..77c9acb145831c5b03fd04cbc08d0f6e0bfd47ec 100644 (file)
@@ -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;
index b0fad0ffca560b0714a9574b42d4c87c89ea3e4d..3dca5c195a200505c3796c488b34b65f8a32b7e6 100644 (file)
@@ -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;
 
index 872aff21e4be6fa682eb01aad72b04492efd622e..b9a636d44c7f95979adcd17172e9d7803fa5d5fe 100644 (file)
@@ -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 */
index f39b756df561dcfd5fee7fa310222bb27748d708..86e0e4309fc274e41ec73a20dc1fb675e06fb0fc 100644 (file)
@@ -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;
 
index 946698fd2dc6a4dc9b3a7868bc7f44c920a46201..3017310359403248719495fe39692698271ba7ed 100644 (file)
@@ -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);
index 4b7d378551d58daf515532dbcaea2c6f35c17f1e..639ca359242f849cebfe407333e6107c0bca4bbb 100644 (file)
@@ -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);
 }
 
 /*
index eec74aa55fdfe28c46476c3360e1632bfd51cf7f..2febf88cfce8847383be5a4fe8ab80ae89fe48e2 100644 (file)
@@ -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;
index 98ee4381991189d8814600967acac3b170525b1d..7edadee487bab16c0cbcf514ab59540f35cc2a41 100644 (file)
@@ -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;
index a580db29e50360f8be44403e5893764261562549..26e7129332abc7e18bd7b27cd3f49d67976c3a16 100644 (file)
 #define INSTRUCTION_LOAD_TXB(n)        (0x40 + 2 * (n))
 #define INSTRUCTION_READ_RXB(n)        (((n) == 0) ? 0x90 : 0x94)
 #define INSTRUCTION_RESET      0xC0
+#define RTS_TXB0               0x01
+#define RTS_TXB1               0x02
+#define RTS_TXB2               0x04
+#define INSTRUCTION_RTS(n)     (0x80 | ((n) & 0x07))
+
 
 /* MPC251x registers */
 #define CANSTAT              0x0e
@@ -397,6 +402,7 @@ static void mcp251x_hw_tx_frame(struct spi_device *spi, u8 *buf,
 static void mcp251x_hw_tx(struct spi_device *spi, struct can_frame *frame,
                          int tx_buf_idx)
 {
+       struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
        u32 sid, eid, exide, rtr;
        u8 buf[SPI_TRANSFER_BUF_LEN];
 
@@ -418,7 +424,10 @@ static void mcp251x_hw_tx(struct spi_device *spi, struct can_frame *frame,
        buf[TXBDLC_OFF] = (rtr << DLC_RTR_SHIFT) | frame->can_dlc;
        memcpy(buf + TXBDAT_OFF, frame->data, frame->can_dlc);
        mcp251x_hw_tx_frame(spi, buf, frame->can_dlc, tx_buf_idx);
-       mcp251x_write_reg(spi, TXBCTRL(tx_buf_idx), TXBCTRL_TXREQ);
+
+       /* use INSTRUCTION_RTS, to avoid "repeated frame problem" */
+       priv->spi_tx_buf[0] = INSTRUCTION_RTS(1 << tx_buf_idx);
+       mcp251x_spi_trans(priv->spi, 1);
 }
 
 static void mcp251x_hw_rx_frame(struct spi_device *spi, u8 *buf,
index 527dbcf9533561489bb33332f03462ac5f405f43..9ded21e79db5866602706ca568dea6613bc0a727 100644 (file)
@@ -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);
 
index af20c6ee2cd9292dfa41c8693e6d8253dfe667e4..e8e97a7d1d06df9a209c741406af32c19a1313e2 100644 (file)
@@ -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 |
index 21b553229ea4c176dfe6c53c60ddde9df3f3f977..dfd86a55f1dcab583ad08342a21eaae9a97be53f 100644 (file)
@@ -710,17 +710,15 @@ static inline u16 bnx2x_tx_avail(struct bnx2x *bp,
        prod = txdata->tx_bd_prod;
        cons = txdata->tx_bd_cons;
 
-       /* NUM_TX_RINGS = number of "next-page" entries
-          It will be used as a threshold */
-       used = SUB_S16(prod, cons) + (s16)NUM_TX_RINGS;
+       used = SUB_S16(prod, cons);
 
 #ifdef BNX2X_STOP_ON_ERROR
        WARN_ON(used < 0);
-       WARN_ON(used > bp->tx_ring_size);
-       WARN_ON((bp->tx_ring_size - used) > MAX_TX_AVAIL);
+       WARN_ON(used > txdata->tx_ring_size);
+       WARN_ON((txdata->tx_ring_size - used) > MAX_TX_AVAIL);
 #endif
 
-       return (s16)(bp->tx_ring_size) - used;
+       return (s16)(txdata->tx_ring_size) - used;
 }
 
 static inline int bnx2x_tx_queue_has_work(struct bnx2x_fp_txdata *txdata)
@@ -1088,6 +1086,7 @@ static inline void bnx2x_init_txdata(struct bnx2x *bp,
        txdata->txq_index = txq_index;
        txdata->tx_cons_sb = tx_cons_sb;
        txdata->parent_fp = fp;
+       txdata->tx_ring_size = IS_FCOE_FP(fp) ? MAX_TX_AVAIL : bp->tx_ring_size;
 
        DP(NETIF_MSG_IFUP, "created tx data cid %d, txq %d\n",
           txdata->cid, txdata->txq_index);
index 3e4cff9b1ebee60a4fa4cedbb90fdeaecc73b580..b926f58e983bbfe083e004c362df6203efb17a3e 100644 (file)
@@ -401,11 +401,11 @@ static const struct reg_addr reg_addrs[] = {
        { 0x70000, 8, RI_ALL_ONLINE },
        { 0x70020, 8184, RI_ALL_OFFLINE },
        { 0x78000, 8192, RI_E3E3B0_OFFLINE },
-       { 0x85000, 3, RI_ALL_ONLINE },
-       { 0x8501c, 7, RI_ALL_ONLINE },
-       { 0x85048, 1, RI_ALL_ONLINE },
-       { 0x85200, 32, RI_ALL_ONLINE },
-       { 0xb0000, 16384, RI_E1H_ONLINE },
+       { 0x85000, 3, RI_ALL_OFFLINE },
+       { 0x8501c, 7, RI_ALL_OFFLINE },
+       { 0x85048, 1, RI_ALL_OFFLINE },
+       { 0x85200, 32, RI_ALL_OFFLINE },
+       { 0xb0000, 16384, RI_E1H_OFFLINE },
        { 0xc1000, 7, RI_ALL_ONLINE },
        { 0xc103c, 2, RI_E2E3E3B0_ONLINE },
        { 0xc1800, 2, RI_ALL_ONLINE },
@@ -581,17 +581,12 @@ static const struct reg_addr reg_addrs[] = {
        { 0x140188, 3, RI_E1E1HE2E3_ONLINE },
        { 0x140194, 13, RI_ALL_ONLINE },
        { 0x140200, 6, RI_E1E1HE2E3_ONLINE },
-       { 0x140220, 4, RI_E2E3_ONLINE },
-       { 0x140240, 4, RI_E2E3_ONLINE },
        { 0x140260, 4, RI_E2E3_ONLINE },
        { 0x140280, 4, RI_E2E3_ONLINE },
-       { 0x1402a0, 4, RI_E2E3_ONLINE },
-       { 0x1402c0, 4, RI_E2E3_ONLINE },
        { 0x1402e0, 2, RI_E2E3_ONLINE },
        { 0x1402e8, 2, RI_E2E3E3B0_ONLINE },
        { 0x1402f0, 9, RI_E2E3_ONLINE },
        { 0x140314, 44, RI_E3B0_ONLINE },
-       { 0x1403d0, 70, RI_E3B0_ONLINE },
        { 0x144000, 4, RI_E1E1H_ONLINE },
        { 0x148000, 4, RI_E1E1H_ONLINE },
        { 0x14c000, 4, RI_E1E1H_ONLINE },
@@ -704,7 +699,6 @@ static const struct reg_addr reg_addrs[] = {
        { 0x180398, 1, RI_E2E3E3B0_ONLINE },
        { 0x1803a0, 5, RI_E2E3E3B0_ONLINE },
        { 0x1803b4, 2, RI_E3E3B0_ONLINE },
-       { 0x180400, 1, RI_ALL_ONLINE },
        { 0x180404, 255, RI_E1E1H_OFFLINE },
        { 0x181000, 4, RI_ALL_ONLINE },
        { 0x181010, 1020, RI_ALL_OFFLINE },
@@ -800,9 +794,9 @@ static const struct reg_addr reg_addrs[] = {
        { 0x1b905c, 1, RI_E3E3B0_ONLINE },
        { 0x1b9064, 1, RI_E3B0_ONLINE },
        { 0x1b9080, 10, RI_E3B0_ONLINE },
-       { 0x1b9400, 14, RI_E2E3E3B0_ONLINE },
-       { 0x1b943c, 19, RI_E2E3E3B0_ONLINE },
-       { 0x1b9490, 10, RI_E2E3E3B0_ONLINE },
+       { 0x1b9400, 14, RI_E2E3E3B0_OFFLINE },
+       { 0x1b943c, 19, RI_E2E3E3B0_OFFLINE },
+       { 0x1b9490, 10, RI_E2E3E3B0_OFFLINE },
        { 0x1c0000, 2, RI_ALL_ONLINE },
        { 0x200000, 65, RI_ALL_ONLINE },
        { 0x20014c, 2, RI_E1HE2E3E3B0_ONLINE },
@@ -814,7 +808,6 @@ static const struct reg_addr reg_addrs[] = {
        { 0x200398, 1, RI_E2E3E3B0_ONLINE },
        { 0x2003a0, 1, RI_E2E3E3B0_ONLINE },
        { 0x2003a8, 2, RI_E2E3E3B0_ONLINE },
-       { 0x200400, 1, RI_ALL_ONLINE },
        { 0x200404, 255, RI_E1E1H_OFFLINE },
        { 0x202000, 4, RI_ALL_ONLINE },
        { 0x202010, 2044, RI_ALL_OFFLINE },
@@ -921,7 +914,6 @@ static const struct reg_addr reg_addrs[] = {
        { 0x280398, 1, RI_E2E3E3B0_ONLINE },
        { 0x2803a0, 1, RI_E2E3E3B0_ONLINE },
        { 0x2803a8, 2, RI_E2E3E3B0_ONLINE },
-       { 0x280400, 1, RI_ALL_ONLINE },
        { 0x280404, 255, RI_E1E1H_OFFLINE },
        { 0x282000, 4, RI_ALL_ONLINE },
        { 0x282010, 2044, RI_ALL_OFFLINE },
@@ -1031,7 +1023,6 @@ static const struct reg_addr reg_addrs[] = {
        { 0x300398, 1, RI_E2E3E3B0_ONLINE },
        { 0x3003a0, 1, RI_E2E3E3B0_ONLINE },
        { 0x3003a8, 2, RI_E2E3E3B0_ONLINE },
-       { 0x300400, 1, RI_ALL_ONLINE },
        { 0x300404, 255, RI_E1E1H_OFFLINE },
        { 0x302000, 4, RI_ALL_ONLINE },
        { 0x302010, 2044, RI_ALL_OFFLINE },
index c37a68d68090e1326b6f491c9f4e28f26a78f87b..ebf40cd7aa1050d716683e806eda505050bf1e40 100644 (file)
@@ -775,7 +775,7 @@ static void bnx2x_get_regs(struct net_device *dev,
        struct bnx2x *bp = netdev_priv(dev);
        struct dump_hdr dump_hdr = {0};
 
-       regs->version = 0;
+       regs->version = 1;
        memset(p, 0, regs->len);
 
        if (!netif_running(bp->dev))
@@ -1587,6 +1587,12 @@ static int bnx2x_set_pauseparam(struct net_device *dev,
                        bp->link_params.req_flow_ctrl[cfg_idx] =
                                BNX2X_FLOW_CTRL_AUTO;
                }
+               bp->link_params.req_fc_auto_adv = BNX2X_FLOW_CTRL_NONE;
+               if (epause->rx_pause)
+                       bp->link_params.req_fc_auto_adv |= BNX2X_FLOW_CTRL_RX;
+
+               if (epause->tx_pause)
+                       bp->link_params.req_fc_auto_adv |= BNX2X_FLOW_CTRL_TX;
        }
 
        DP(BNX2X_MSG_ETHTOOL,
index f4beb46c4709af8291ed7aecc373d7a72a366f59..b046beb435b2c490f70ef3bc2f67bf3af16bfcb5 100644 (file)
@@ -2667,9 +2667,11 @@ int bnx2x_update_pfc(struct link_params *params,
                return bnx2x_status;
 
        DP(NETIF_MSG_LINK, "About to update PFC in BMAC\n");
-       if (CHIP_IS_E3(bp))
-               bnx2x_update_pfc_xmac(params, vars, 0);
-       else {
+
+       if (CHIP_IS_E3(bp)) {
+               if (vars->mac_type == MAC_TYPE_XMAC)
+                       bnx2x_update_pfc_xmac(params, vars, 0);
+       } else {
                val = REG_RD(bp, MISC_REG_RESET_REG_2);
                if ((val &
                     (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << params->port))
@@ -5432,7 +5434,7 @@ static int bnx2x_get_link_speed_duplex(struct bnx2x_phy *phy,
                switch (speed_mask) {
                case GP_STATUS_10M:
                        vars->line_speed = SPEED_10;
-                       if (vars->duplex == DUPLEX_FULL)
+                       if (is_duplex == DUPLEX_FULL)
                                vars->link_status |= LINK_10TFD;
                        else
                                vars->link_status |= LINK_10THD;
@@ -5440,7 +5442,7 @@ static int bnx2x_get_link_speed_duplex(struct bnx2x_phy *phy,
 
                case GP_STATUS_100M:
                        vars->line_speed = SPEED_100;
-                       if (vars->duplex == DUPLEX_FULL)
+                       if (is_duplex == DUPLEX_FULL)
                                vars->link_status |= LINK_100TXFD;
                        else
                                vars->link_status |= LINK_100TXHD;
@@ -5449,7 +5451,7 @@ static int bnx2x_get_link_speed_duplex(struct bnx2x_phy *phy,
                case GP_STATUS_1G:
                case GP_STATUS_1G_KX:
                        vars->line_speed = SPEED_1000;
-                       if (vars->duplex == DUPLEX_FULL)
+                       if (is_duplex == DUPLEX_FULL)
                                vars->link_status |= LINK_1000TFD;
                        else
                                vars->link_status |= LINK_1000THD;
@@ -5457,7 +5459,7 @@ static int bnx2x_get_link_speed_duplex(struct bnx2x_phy *phy,
 
                case GP_STATUS_2_5G:
                        vars->line_speed = SPEED_2500;
-                       if (vars->duplex == DUPLEX_FULL)
+                       if (is_duplex == DUPLEX_FULL)
                                vars->link_status |= LINK_2500TFD;
                        else
                                vars->link_status |= LINK_2500THD;
@@ -5531,6 +5533,7 @@ static int bnx2x_link_settings_status(struct bnx2x_phy *phy,
 
        if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) {
                if (SINGLE_MEDIA_DIRECT(params)) {
+                       vars->duplex = duplex;
                        bnx2x_flow_ctrl_resolve(phy, params, vars, gp_status);
                        if (phy->req_line_speed == SPEED_AUTO_NEG)
                                bnx2x_xgxs_an_resolve(phy, params, vars,
@@ -5625,6 +5628,7 @@ static int bnx2x_warpcore_read_status(struct bnx2x_phy *phy,
                                        LINK_STATUS_PARALLEL_DETECTION_USED;
                        }
                        bnx2x_ext_phy_resolve_fc(phy, params, vars);
+                       vars->duplex = duplex;
                }
        }
 
index 21054987257a12960b859594db72830c42e21059..0875ecfe33729e2c2860dd5149e62042ddcbc6d7 100644 (file)
@@ -7561,8 +7561,14 @@ int bnx2x_set_mac_one(struct bnx2x *bp, u8 *mac,
        }
 
        rc = bnx2x_config_vlan_mac(bp, &ramrod_param);
-       if (rc < 0)
+
+       if (rc == -EEXIST) {
+               DP(BNX2X_MSG_SP, "Failed to schedule ADD operations: %d\n", rc);
+               /* do not treat adding same MAC as error */
+               rc = 0;
+       } else if (rc < 0)
                BNX2X_ERR("%s MAC failed\n", (set ? "Set" : "Del"));
+
        return rc;
 }
 
@@ -9825,12 +9831,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)
@@ -10294,13 +10301,11 @@ static void __devinit bnx2x_get_fcoe_info(struct bnx2x *bp)
                                dev_info.port_hw_config[port].
                                 fcoe_wwn_node_name_lower);
        } else if (!IS_MF_SD(bp)) {
-               u32 cfg = MF_CFG_RD(bp, func_ext_config[func].func_cfg);
-
                /*
                 * Read the WWN info only if the FCoE feature is enabled for
                 * this function.
                 */
-               if (cfg & MACP_FUNC_CFG_FLAGS_FCOE_OFFLOAD)
+               if (BNX2X_MF_EXT_PROTOCOL_FCOE(bp) && !CHIP_IS_E1x(bp))
                        bnx2x_get_ext_wwn_info(bp, func);
 
        } else if (IS_MF_FCOE_SD(bp))
@@ -11073,7 +11078,14 @@ static int bnx2x_set_uc_list(struct bnx2x *bp)
        netdev_for_each_uc_addr(ha, dev) {
                rc = bnx2x_set_mac_one(bp, bnx2x_uc_addr(ha), mac_obj, true,
                                       BNX2X_UC_LIST_MAC, &ramrod_flags);
-               if (rc < 0) {
+               if (rc == -EEXIST) {
+                       DP(BNX2X_MSG_SP,
+                          "Failed to schedule ADD operations: %d\n", rc);
+                       /* do not treat adding same MAC as error */
+                       rc = 0;
+
+               } else if (rc < 0) {
+
                        BNX2X_ERR("Failed to schedule ADD operations: %d\n",
                                  rc);
                        return rc;
index 332db64dd5bea11eed0cf878565c5c2e573f5c3e..a1d0446b39b356dd69e0b77e69f6285ba37edb63 100644 (file)
@@ -101,6 +101,11 @@ static void bnx2x_hw_stats_post(struct bnx2x *bp)
        if (CHIP_REV_IS_SLOW(bp))
                return;
 
+       /* Update MCP's statistics if possible */
+       if (bp->func_stx)
+               memcpy(bnx2x_sp(bp, func_stats), &bp->func_stats,
+                      sizeof(bp->func_stats));
+
        /* loader */
        if (bp->executer_idx) {
                int loader_idx = PMF_DMAE_C(bp);
@@ -128,8 +133,6 @@ static void bnx2x_hw_stats_post(struct bnx2x *bp)
 
        } else if (bp->func_stx) {
                *stats_comp = 0;
-               memcpy(bnx2x_sp(bp, func_stats), &bp->func_stats,
-                      sizeof(bp->func_stats));
                bnx2x_post_dmae(bp, dmae, INIT_DMAE_C(bp));
        }
 }
@@ -1151,9 +1154,11 @@ static void bnx2x_stats_update(struct bnx2x *bp)
        if (bp->port.pmf)
                bnx2x_hw_stats_update(bp);
 
-       if (bnx2x_storm_stats_update(bp) && (bp->stats_pending++ == 3)) {
-               BNX2X_ERR("storm stats were not updated for 3 times\n");
-               bnx2x_panic();
+       if (bnx2x_storm_stats_update(bp)) {
+               if (bp->stats_pending++ == 3) {
+                       BNX2X_ERR("storm stats were not updated for 3 times\n");
+                       bnx2x_panic();
+               }
                return;
        }
 
index 77884191a8c6448a7eea54c94b8ba8d9ce0fef83..4e980a7886fb58758fa84071b2494f56364da1f2 100644 (file)
@@ -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);
index 8971921cc1c84966170b7f7a6350732f93b416e9..ab6762caa95702f492bbb457deae8986257bdcc4 100644 (file)
@@ -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)
index c08e5d40fecb425c7f6c26b8de269d270bac727f..0daa66b8eca088735974f7ee45595d22c6be4c56 100644 (file)
@@ -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);
index bd1f1ef91e1910f81f454a7332337870fa031331..ba4e0cea3506f80da5cc36a69f22994a7a3e470e 100644 (file)
@@ -139,8 +139,11 @@ struct znet_private {
 /* Only one can be built-in;-> */
 static struct net_device *znet_dev;
 
+#define NETIDBLK_MAGIC         "NETIDBLK"
+#define NETIDBLK_MAGIC_SIZE    8
+
 struct netidblk {
-       char magic[8];          /* The magic number (string) "NETIDBLK" */
+       char magic[NETIDBLK_MAGIC_SIZE];        /* The magic number (string) "NETIDBLK" */
        unsigned char netid[8]; /* The physical station address */
        char nettype, globalopt;
        char vendor[8];         /* The machine vendor and product name. */
@@ -373,14 +376,16 @@ static int __init znet_probe (void)
        struct znet_private *znet;
        struct net_device *dev;
        char *p;
+       char *plast = phys_to_virt(0x100000 - NETIDBLK_MAGIC_SIZE);
        int err = -ENOMEM;
 
        /* This code scans the region 0xf0000 to 0xfffff for a "NETIDBLK". */
-       for(p = (char *)phys_to_virt(0xf0000); p < (char *)phys_to_virt(0x100000); p++)
-               if (*p == 'N'  &&  strncmp(p, "NETIDBLK", 8) == 0)
+       for(p = (char *)phys_to_virt(0xf0000); p <= plast; p++)
+               if (*p == 'N' &&
+                   strncmp(p, NETIDBLK_MAGIC, NETIDBLK_MAGIC_SIZE) == 0)
                        break;
 
-       if (p >= (char *)phys_to_virt(0x100000)) {
+       if (p > plast) {
                if (znet_debug > 1)
                        printk(KERN_INFO "No Z-Note ethernet adaptor found.\n");
                return -ENODEV;
index 9010cea68bc3094a4b9b18b06cae1aa7d9796cd7..b68d28a130e664e2042bbb9a4335710964f861a7 100644 (file)
@@ -472,14 +472,9 @@ static void ibmveth_cleanup(struct ibmveth_adapter *adapter)
        }
 
        if (adapter->rx_queue.queue_addr != NULL) {
-               if (!dma_mapping_error(dev, adapter->rx_queue.queue_dma)) {
-                       dma_unmap_single(dev,
-                                       adapter->rx_queue.queue_dma,
-                                       adapter->rx_queue.queue_len,
-                                       DMA_BIDIRECTIONAL);
-                       adapter->rx_queue.queue_dma = DMA_ERROR_CODE;
-               }
-               kfree(adapter->rx_queue.queue_addr);
+               dma_free_coherent(dev, adapter->rx_queue.queue_len,
+                                 adapter->rx_queue.queue_addr,
+                                 adapter->rx_queue.queue_dma);
                adapter->rx_queue.queue_addr = NULL;
        }
 
@@ -556,10 +551,13 @@ static int ibmveth_open(struct net_device *netdev)
                goto err_out;
        }
 
+       dev = &adapter->vdev->dev;
+
        adapter->rx_queue.queue_len = sizeof(struct ibmveth_rx_q_entry) *
                                                rxq_entries;
-       adapter->rx_queue.queue_addr = kmalloc(adapter->rx_queue.queue_len,
-                                               GFP_KERNEL);
+       adapter->rx_queue.queue_addr =
+           dma_alloc_coherent(dev, adapter->rx_queue.queue_len,
+                              &adapter->rx_queue.queue_dma, GFP_KERNEL);
 
        if (!adapter->rx_queue.queue_addr) {
                netdev_err(netdev, "unable to allocate rx queue pages\n");
@@ -567,19 +565,13 @@ static int ibmveth_open(struct net_device *netdev)
                goto err_out;
        }
 
-       dev = &adapter->vdev->dev;
-
        adapter->buffer_list_dma = dma_map_single(dev,
                        adapter->buffer_list_addr, 4096, DMA_BIDIRECTIONAL);
        adapter->filter_list_dma = dma_map_single(dev,
                        adapter->filter_list_addr, 4096, DMA_BIDIRECTIONAL);
-       adapter->rx_queue.queue_dma = dma_map_single(dev,
-                       adapter->rx_queue.queue_addr,
-                       adapter->rx_queue.queue_len, DMA_BIDIRECTIONAL);
 
        if ((dma_mapping_error(dev, adapter->buffer_list_dma)) ||
-           (dma_mapping_error(dev, adapter->filter_list_dma)) ||
-           (dma_mapping_error(dev, adapter->rx_queue.queue_dma))) {
+           (dma_mapping_error(dev, adapter->filter_list_dma))) {
                netdev_err(netdev, "unable to map filter or buffer list "
                           "pages\n");
                rc = -ENOMEM;
index 3bfbb8df898935f4acf47a52ebb8be3f0f683a67..bde337ee1a34f954e90c583711f155eec87b633e 100644 (file)
@@ -3149,6 +3149,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
index daf41792366147c7381e9f8f7f1017489c55a57e..31d02649be41f2317d16f178f88bc1f19153352a 100644 (file)
@@ -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);
index a67744f53506af7f86c0de581445e1e67568de7f..dee67fa39107f890508e158e56b680af6496d74a 100644 (file)
@@ -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)
index 827b72dfce99690093f0fe81ee3ccf804d59db85..2f816c6aed72da16bc6afc22c957f0b6c7a5eac0 100644 (file)
@@ -1234,13 +1234,13 @@ static int mlx4_init_hca(struct mlx4_dev *dev)
                                mlx4_info(dev, "non-primary physical function, skipping.\n");
                        else
                                mlx4_err(dev, "QUERY_FW command failed, aborting.\n");
-                       goto unmap_bf;
+                       return err;
                }
 
                err = mlx4_load_fw(dev);
                if (err) {
                        mlx4_err(dev, "Failed to start FW, aborting.\n");
-                       goto unmap_bf;
+                       return err;
                }
 
                mlx4_cfg.log_pg_sz_m = 1;
@@ -1304,7 +1304,7 @@ static int mlx4_init_hca(struct mlx4_dev *dev)
                err = mlx4_init_slave(dev);
                if (err) {
                        mlx4_err(dev, "Failed to initialize slave\n");
-                       goto unmap_bf;
+                       return err;
                }
 
                err = mlx4_slave_cap(dev);
@@ -1324,7 +1324,7 @@ static int mlx4_init_hca(struct mlx4_dev *dev)
        err = mlx4_QUERY_ADAPTER(dev, &adapter);
        if (err) {
                mlx4_err(dev, "QUERY_ADAPTER command failed, aborting.\n");
-               goto err_close;
+               goto unmap_bf;
        }
 
        priv->eq_table.inta_pin = adapter.inta_pin;
@@ -1332,6 +1332,9 @@ static int mlx4_init_hca(struct mlx4_dev *dev)
 
        return 0;
 
+unmap_bf:
+       unmap_bf_area(dev);
+
 err_close:
        mlx4_close_hca(dev);
 
@@ -1344,8 +1347,6 @@ err_stop_fw:
                mlx4_UNMAP_FA(dev);
                mlx4_free_icm(dev, priv->fw.fw_icm, 0);
        }
-unmap_bf:
-       unmap_bf_area(dev);
        return err;
 }
 
@@ -1996,7 +1997,8 @@ static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
        }
 
 slave_start:
-       if (mlx4_cmd_init(dev)) {
+       err = mlx4_cmd_init(dev);
+       if (err) {
                mlx4_err(dev, "Failed to init command interface, aborting.\n");
                goto err_sriov;
        }
index a018ea2a43deb9c67e773032e62d8a83f54bb3d9..e151c21baf2baf5970c9c232c79d0c8650c0eb4e 100644 (file)
@@ -137,11 +137,11 @@ static int mlx4_GID_HASH(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
        return err;
 }
 
-static struct mlx4_promisc_qp *get_promisc_qp(struct mlx4_dev *dev, u8 pf_num,
+static struct mlx4_promisc_qp *get_promisc_qp(struct mlx4_dev *dev, u8 port,
                                              enum mlx4_steer_type steer,
                                              u32 qpn)
 {
-       struct mlx4_steer *s_steer = &mlx4_priv(dev)->steer[pf_num];
+       struct mlx4_steer *s_steer = &mlx4_priv(dev)->steer[port - 1];
        struct mlx4_promisc_qp *pqp;
 
        list_for_each_entry(pqp, &s_steer->promisc_qps[steer], list) {
@@ -182,7 +182,7 @@ static int new_steering_entry(struct mlx4_dev *dev, u8 port,
        /* If the given qpn is also a promisc qp,
         * it should be inserted to duplicates list
         */
-       pqp = get_promisc_qp(dev, 0, steer, qpn);
+       pqp = get_promisc_qp(dev, port, steer, qpn);
        if (pqp) {
                dqp = kmalloc(sizeof *dqp, GFP_KERNEL);
                if (!dqp) {
@@ -256,7 +256,7 @@ static int existing_steering_entry(struct mlx4_dev *dev, u8 port,
 
        s_steer = &mlx4_priv(dev)->steer[port - 1];
 
-       pqp = get_promisc_qp(dev, 0, steer, qpn);
+       pqp = get_promisc_qp(dev, port, steer, qpn);
        if (!pqp)
                return 0; /* nothing to do */
 
@@ -302,7 +302,7 @@ static bool check_duplicate_entry(struct mlx4_dev *dev, u8 port,
        s_steer = &mlx4_priv(dev)->steer[port - 1];
 
        /* if qp is not promisc, it cannot be duplicated */
-       if (!get_promisc_qp(dev, 0, steer, qpn))
+       if (!get_promisc_qp(dev, port, steer, qpn))
                return false;
 
        /* The qp is promisc qp so it is a duplicate on this index
@@ -352,7 +352,7 @@ static bool can_remove_steering_entry(struct mlx4_dev *dev, u8 port,
        members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
        for (i = 0;  i < members_count; i++) {
                qpn = be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK;
-               if (!get_promisc_qp(dev, 0, steer, qpn) && qpn != tqpn) {
+               if (!get_promisc_qp(dev, port, steer, qpn) && qpn != tqpn) {
                        /* the qp is not promisc, the entry can't be removed */
                        goto out;
                }
@@ -398,7 +398,7 @@ static int add_promisc_qp(struct mlx4_dev *dev, u8 port,
 
        mutex_lock(&priv->mcg_table.mutex);
 
-       if (get_promisc_qp(dev, 0, steer, qpn)) {
+       if (get_promisc_qp(dev, port, steer, qpn)) {
                err = 0;  /* Noting to do, already exists */
                goto out_mutex;
        }
@@ -503,7 +503,7 @@ static int remove_promisc_qp(struct mlx4_dev *dev, u8 port,
        s_steer = &mlx4_priv(dev)->steer[port - 1];
        mutex_lock(&priv->mcg_table.mutex);
 
-       pqp = get_promisc_qp(dev, 0, steer, qpn);
+       pqp = get_promisc_qp(dev, port, steer, qpn);
        if (unlikely(!pqp)) {
                mlx4_warn(dev, "QP %x is not promiscuous QP\n", qpn);
                /* nothing to do */
@@ -650,13 +650,6 @@ static int find_entry(struct mlx4_dev *dev, u8 port,
        return err;
 }
 
-struct mlx4_net_trans_rule_hw_ctrl {
-       __be32 ctrl;
-       __be32 vf_vep_port;
-       __be32 qpn;
-       __be32 reserved;
-};
-
 static void trans_rule_ctrl_to_hw(struct mlx4_net_trans_rule *ctrl,
                                  struct mlx4_net_trans_rule_hw_ctrl *hw)
 {
@@ -680,87 +673,18 @@ static void trans_rule_ctrl_to_hw(struct mlx4_net_trans_rule *ctrl,
        hw->qpn = cpu_to_be32(ctrl->qpn);
 }
 
-struct mlx4_net_trans_rule_hw_ib {
-       u8      size;
-       u8      rsvd1;
-       __be16  id;
-       u32     rsvd2;
-       __be32  qpn;
-       __be32  qpn_mask;
-       u8      dst_gid[16];
-       u8      dst_gid_msk[16];
-} __packed;
-
-struct mlx4_net_trans_rule_hw_eth {
-       u8      size;
-       u8      rsvd;
-       __be16  id;
-       u8      rsvd1[6];
-       u8      dst_mac[6];
-       u16     rsvd2;
-       u8      dst_mac_msk[6];
-       u16     rsvd3;
-       u8      src_mac[6];
-       u16     rsvd4;
-       u8      src_mac_msk[6];
-       u8      rsvd5;
-       u8      ether_type_enable;
-       __be16  ether_type;
-       __be16  vlan_id_msk;
-       __be16  vlan_id;
-} __packed;
-
-struct mlx4_net_trans_rule_hw_tcp_udp {
-       u8      size;
-       u8      rsvd;
-       __be16  id;
-       __be16  rsvd1[3];
-       __be16  dst_port;
-       __be16  rsvd2;
-       __be16  dst_port_msk;
-       __be16  rsvd3;
-       __be16  src_port;
-       __be16  rsvd4;
-       __be16  src_port_msk;
-} __packed;
-
-struct mlx4_net_trans_rule_hw_ipv4 {
-       u8      size;
-       u8      rsvd;
-       __be16  id;
-       __be32  rsvd1;
-       __be32  dst_ip;
-       __be32  dst_ip_msk;
-       __be32  src_ip;
-       __be32  src_ip_msk;
-} __packed;
-
-struct _rule_hw {
-       union {
-               struct {
-                       u8 size;
-                       u8 rsvd;
-                       __be16 id;
-               };
-               struct mlx4_net_trans_rule_hw_eth eth;
-               struct mlx4_net_trans_rule_hw_ib ib;
-               struct mlx4_net_trans_rule_hw_ipv4 ipv4;
-               struct mlx4_net_trans_rule_hw_tcp_udp tcp_udp;
-       };
+const u16 __sw_id_hw[] = {
+       [MLX4_NET_TRANS_RULE_ID_ETH]     = 0xE001,
+       [MLX4_NET_TRANS_RULE_ID_IB]      = 0xE005,
+       [MLX4_NET_TRANS_RULE_ID_IPV6]    = 0xE003,
+       [MLX4_NET_TRANS_RULE_ID_IPV4]    = 0xE002,
+       [MLX4_NET_TRANS_RULE_ID_TCP]     = 0xE004,
+       [MLX4_NET_TRANS_RULE_ID_UDP]     = 0xE006
 };
 
 static int parse_trans_rule(struct mlx4_dev *dev, struct mlx4_spec_list *spec,
                            struct _rule_hw *rule_hw)
 {
-       static const u16 __sw_id_hw[] = {
-               [MLX4_NET_TRANS_RULE_ID_ETH]     = 0xE001,
-               [MLX4_NET_TRANS_RULE_ID_IB]      = 0xE005,
-               [MLX4_NET_TRANS_RULE_ID_IPV6]    = 0xE003,
-               [MLX4_NET_TRANS_RULE_ID_IPV4]    = 0xE002,
-               [MLX4_NET_TRANS_RULE_ID_TCP]     = 0xE004,
-               [MLX4_NET_TRANS_RULE_ID_UDP]     = 0xE006
-       };
-
        static const size_t __rule_hw_sz[] = {
                [MLX4_NET_TRANS_RULE_ID_ETH] =
                        sizeof(struct mlx4_net_trans_rule_hw_eth),
index 4d9df8f2a12617047355fc9988d5187af80a95f5..dba69d98734a29b9a10038e22eff8e93714147ed 100644 (file)
@@ -690,6 +690,82 @@ struct mlx4_steer {
        struct list_head steer_entries[MLX4_NUM_STEERS];
 };
 
+struct mlx4_net_trans_rule_hw_ctrl {
+       __be32 ctrl;
+       __be32 vf_vep_port;
+       __be32 qpn;
+       __be32 reserved;
+};
+
+struct mlx4_net_trans_rule_hw_ib {
+       u8 size;
+       u8 rsvd1;
+       __be16 id;
+       u32 rsvd2;
+       __be32 qpn;
+       __be32 qpn_mask;
+       u8 dst_gid[16];
+       u8 dst_gid_msk[16];
+} __packed;
+
+struct mlx4_net_trans_rule_hw_eth {
+       u8      size;
+       u8      rsvd;
+       __be16  id;
+       u8      rsvd1[6];
+       u8      dst_mac[6];
+       u16     rsvd2;
+       u8      dst_mac_msk[6];
+       u16     rsvd3;
+       u8      src_mac[6];
+       u16     rsvd4;
+       u8      src_mac_msk[6];
+       u8      rsvd5;
+       u8      ether_type_enable;
+       __be16  ether_type;
+       __be16  vlan_id_msk;
+       __be16  vlan_id;
+} __packed;
+
+struct mlx4_net_trans_rule_hw_tcp_udp {
+       u8      size;
+       u8      rsvd;
+       __be16  id;
+       __be16  rsvd1[3];
+       __be16  dst_port;
+       __be16  rsvd2;
+       __be16  dst_port_msk;
+       __be16  rsvd3;
+       __be16  src_port;
+       __be16  rsvd4;
+       __be16  src_port_msk;
+} __packed;
+
+struct mlx4_net_trans_rule_hw_ipv4 {
+       u8      size;
+       u8      rsvd;
+       __be16  id;
+       __be32  rsvd1;
+       __be32  dst_ip;
+       __be32  dst_ip_msk;
+       __be32  src_ip;
+       __be32  src_ip_msk;
+} __packed;
+
+struct _rule_hw {
+       union {
+               struct {
+                       u8 size;
+                       u8 rsvd;
+                       __be16 id;
+               };
+               struct mlx4_net_trans_rule_hw_eth eth;
+               struct mlx4_net_trans_rule_hw_ib ib;
+               struct mlx4_net_trans_rule_hw_ipv4 ipv4;
+               struct mlx4_net_trans_rule_hw_tcp_udp tcp_udp;
+       };
+};
+
 struct mlx4_priv {
        struct mlx4_dev         dev;
 
index 94ceddd17ab28a3ea13a15ea4c7ec1211042278f..293c9e820c49b5d470dce7eda95f2252b94d4251 100644 (file)
@@ -42,6 +42,7 @@
 #include <linux/mlx4/cmd.h>
 #include <linux/mlx4/qp.h>
 #include <linux/if_ether.h>
+#include <linux/etherdevice.h>
 
 #include "mlx4.h"
 #include "fw.h"
@@ -2776,18 +2777,133 @@ ex_put:
        return err;
 }
 
+/*
+ * MAC validation for Flow Steering rules.
+ * VF can attach rules only with a mac address which is assigned to it.
+ */
+static int validate_eth_header_mac(int slave, struct _rule_hw *eth_header,
+                                  struct list_head *rlist)
+{
+       struct mac_res *res, *tmp;
+       __be64 be_mac;
+
+       /* make sure it isn't multicast or broadcast mac*/
+       if (!is_multicast_ether_addr(eth_header->eth.dst_mac) &&
+           !is_broadcast_ether_addr(eth_header->eth.dst_mac)) {
+               list_for_each_entry_safe(res, tmp, rlist, list) {
+                       be_mac = cpu_to_be64(res->mac << 16);
+                       if (!memcmp(&be_mac, eth_header->eth.dst_mac, ETH_ALEN))
+                               return 0;
+               }
+               pr_err("MAC %pM doesn't belong to VF %d, Steering rule rejected\n",
+                      eth_header->eth.dst_mac, slave);
+               return -EINVAL;
+       }
+       return 0;
+}
+
+/*
+ * In case of missing eth header, append eth header with a MAC address
+ * assigned to the VF.
+ */
+static int add_eth_header(struct mlx4_dev *dev, int slave,
+                         struct mlx4_cmd_mailbox *inbox,
+                         struct list_head *rlist, int header_id)
+{
+       struct mac_res *res, *tmp;
+       u8 port;
+       struct mlx4_net_trans_rule_hw_ctrl *ctrl;
+       struct mlx4_net_trans_rule_hw_eth *eth_header;
+       struct mlx4_net_trans_rule_hw_ipv4 *ip_header;
+       struct mlx4_net_trans_rule_hw_tcp_udp *l4_header;
+       __be64 be_mac = 0;
+       __be64 mac_msk = cpu_to_be64(MLX4_MAC_MASK << 16);
+
+       ctrl = (struct mlx4_net_trans_rule_hw_ctrl *)inbox->buf;
+       port = be32_to_cpu(ctrl->vf_vep_port) & 0xff;
+       eth_header = (struct mlx4_net_trans_rule_hw_eth *)(ctrl + 1);
+
+       /* Clear a space in the inbox for eth header */
+       switch (header_id) {
+       case MLX4_NET_TRANS_RULE_ID_IPV4:
+               ip_header =
+                       (struct mlx4_net_trans_rule_hw_ipv4 *)(eth_header + 1);
+               memmove(ip_header, eth_header,
+                       sizeof(*ip_header) + sizeof(*l4_header));
+               break;
+       case MLX4_NET_TRANS_RULE_ID_TCP:
+       case MLX4_NET_TRANS_RULE_ID_UDP:
+               l4_header = (struct mlx4_net_trans_rule_hw_tcp_udp *)
+                           (eth_header + 1);
+               memmove(l4_header, eth_header, sizeof(*l4_header));
+               break;
+       default:
+               return -EINVAL;
+       }
+       list_for_each_entry_safe(res, tmp, rlist, list) {
+               if (port == res->port) {
+                       be_mac = cpu_to_be64(res->mac << 16);
+                       break;
+               }
+       }
+       if (!be_mac) {
+               pr_err("Failed adding eth header to FS rule, Can't find matching MAC for port %d .\n",
+                      port);
+               return -EINVAL;
+       }
+
+       memset(eth_header, 0, sizeof(*eth_header));
+       eth_header->size = sizeof(*eth_header) >> 2;
+       eth_header->id = cpu_to_be16(__sw_id_hw[MLX4_NET_TRANS_RULE_ID_ETH]);
+       memcpy(eth_header->dst_mac, &be_mac, ETH_ALEN);
+       memcpy(eth_header->dst_mac_msk, &mac_msk, ETH_ALEN);
+
+       return 0;
+
+}
+
 int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
                                         struct mlx4_vhcr *vhcr,
                                         struct mlx4_cmd_mailbox *inbox,
                                         struct mlx4_cmd_mailbox *outbox,
                                         struct mlx4_cmd_info *cmd)
 {
+
+       struct mlx4_priv *priv = mlx4_priv(dev);
+       struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
+       struct list_head *rlist = &tracker->slave_list[slave].res_list[RES_MAC];
        int err;
+       struct mlx4_net_trans_rule_hw_ctrl *ctrl;
+       struct _rule_hw  *rule_header;
+       int header_id;
 
        if (dev->caps.steering_mode !=
            MLX4_STEERING_MODE_DEVICE_MANAGED)
                return -EOPNOTSUPP;
 
+       ctrl = (struct mlx4_net_trans_rule_hw_ctrl *)inbox->buf;
+       rule_header = (struct _rule_hw *)(ctrl + 1);
+       header_id = map_hw_to_sw_id(be16_to_cpu(rule_header->id));
+
+       switch (header_id) {
+       case MLX4_NET_TRANS_RULE_ID_ETH:
+               if (validate_eth_header_mac(slave, rule_header, rlist))
+                       return -EINVAL;
+               break;
+       case MLX4_NET_TRANS_RULE_ID_IPV4:
+       case MLX4_NET_TRANS_RULE_ID_TCP:
+       case MLX4_NET_TRANS_RULE_ID_UDP:
+               pr_warn("Can't attach FS rule without L2 headers, adding L2 header.\n");
+               if (add_eth_header(dev, slave, inbox, rlist, header_id))
+                       return -EINVAL;
+               vhcr->in_modifier +=
+                       sizeof(struct mlx4_net_trans_rule_hw_eth) >> 2;
+               break;
+       default:
+               pr_err("Corrupted mailbox.\n");
+               return -EINVAL;
+       }
+
        err = mlx4_cmd_imm(dev, inbox->dma, &vhcr->out_param,
                           vhcr->in_modifier, 0,
                           MLX4_QP_FLOW_STEERING_ATTACH, MLX4_CMD_TIME_CLASS_A,
index 342b3a79bd0fd7a6a6bde8860446c20c78595ef2..a77c558d8f4078e7cc4747a5308dc315e34d99c1 100644 (file)
@@ -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;
index bb8c8222122b920511f729463a04b97395724c7d..4d15bf413bdc89f060964c8114d4486be337ce46 100644 (file)
@@ -751,6 +751,7 @@ static int __devinit sgiseeq_probe(struct platform_device *pdev)
        sp->srings = sr;
        sp->rx_desc = sp->srings->rxvector;
        sp->tx_desc = sp->srings->txvector;
+       spin_lock_init(&sp->tx_lock);
 
        /* A couple calculations now, saves many cycles later. */
        setup_rx_ring(dev, sp->rx_desc, SEEQ_RX_BUFFERS);
index c136162e6473e1746b48f50a0c7cc0adc57986d6..3be88331d17ab0e690b71f06b2ac30f50d7a7f77 100644 (file)
@@ -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);
 
index 2a0e1abde7e73eeea25c9c457999765b5315a01f..4ccd4e2977b73a0d441f6f0dbb99ea0636c8dae0 100644 (file)
@@ -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;
index 256eddf1f75a1913576067742f8fc1cb3dce3e7a..795109425568623977428b1a62bffc7d11c6fa14 100644 (file)
@@ -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;
        }
index 4fd48df6b989eee8aff62ee1d5edb5014bae5e1d..32e31c5c5dc6bfe95b4d38e377a508448d85c890 100644 (file)
@@ -961,6 +961,10 @@ static const struct usb_device_id  products [] = {
        // DLink DUB-E100 H/W Ver B1 Alternate
        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),
index adfab3fc5478cb6815129e3b966dbe904141bad3..3543c9e578247e6ee550ef7f18f680b680be3587 100644 (file)
@@ -297,7 +297,7 @@ static int qmi_wwan_suspend(struct usb_interface *intf, pm_message_t message)
        if (ret < 0)
                goto err;
 
-       if (info->subdriver && info->subdriver->suspend)
+       if (intf == info->control && info->subdriver && info->subdriver->suspend)
                ret = info->subdriver->suspend(intf, message);
        if (ret < 0)
                usbnet_resume(intf);
@@ -310,13 +310,14 @@ static int qmi_wwan_resume(struct usb_interface *intf)
        struct usbnet *dev = usb_get_intfdata(intf);
        struct qmi_wwan_state *info = (void *)&dev->data;
        int ret = 0;
+       bool callsub = (intf == info->control && info->subdriver && info->subdriver->resume);
 
-       if (info->subdriver && info->subdriver->resume)
+       if (callsub)
                ret = info->subdriver->resume(intf);
        if (ret < 0)
                goto err;
        ret = usbnet_resume(intf);
-       if (ret < 0 && info->subdriver && info->subdriver->resume && info->subdriver->suspend)
+       if (ret < 0 && callsub && info->subdriver->suspend)
                info->subdriver->suspend(intf, PMSG_SUSPEND);
 err:
        return ret;
@@ -365,16 +366,20 @@ static const struct usb_device_id products[] = {
        },
 
        /* 2. Combined interface devices matching on class+protocol */
+       {       /* 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,
+       },
        {       /* Huawei E392, E398 and possibly others in "Windows mode" */
                USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 1, 17),
                .driver_info        = (unsigned long)&qmi_wwan_shared,
        },
-       {       /* Pantech UML290 */
-               USB_DEVICE_AND_INTERFACE_INFO(0x106c, 0x3718, USB_CLASS_VENDOR_SPEC, 0xf0, 0xff),
+       {       /* Pantech UML290, P4200 and more */
+               USB_VENDOR_AND_INTERFACE_INFO(0x106c, USB_CLASS_VENDOR_SPEC, 0xf0, 0xff),
                .driver_info        = (unsigned long)&qmi_wwan_shared,
        },
        {       /* Pantech UML290 - newer firmware */
-               USB_DEVICE_AND_INTERFACE_INFO(0x106c, 0x3718, USB_CLASS_VENDOR_SPEC, 0xf1, 0xff),
+               USB_VENDOR_AND_INTERFACE_INFO(0x106c, USB_CLASS_VENDOR_SPEC, 0xf1, 0xff),
                .driver_info        = (unsigned long)&qmi_wwan_shared,
        },
 
@@ -382,6 +387,7 @@ static const struct usb_device_id products[] = {
        {QMI_FIXED_INTF(0x19d2, 0x0055, 1)},    /* ZTE (Vodafone) K3520-Z */
        {QMI_FIXED_INTF(0x19d2, 0x0063, 4)},    /* ZTE (Vodafone) K3565-Z */
        {QMI_FIXED_INTF(0x19d2, 0x0104, 4)},    /* ZTE (Vodafone) K4505-Z */
+       {QMI_FIXED_INTF(0x19d2, 0x0157, 5)},    /* ZTE MF683 */
        {QMI_FIXED_INTF(0x19d2, 0x0167, 4)},    /* ZTE MF820D */
        {QMI_FIXED_INTF(0x19d2, 0x0326, 4)},    /* ZTE MF821D */
        {QMI_FIXED_INTF(0x19d2, 0x1008, 4)},    /* ZTE (Vodafone) K3570-Z */
@@ -398,7 +404,6 @@ static const struct usb_device_id products[] = {
        /* 4. Gobi 1000 devices */
        {QMI_GOBI1K_DEVICE(0x05c6, 0x9212)},    /* Acer Gobi Modem Device */
        {QMI_GOBI1K_DEVICE(0x03f0, 0x1f1d)},    /* HP un2400 Gobi Modem Device */
-       {QMI_GOBI1K_DEVICE(0x03f0, 0x371d)},    /* HP un2430 Mobile Broadband Module */
        {QMI_GOBI1K_DEVICE(0x04da, 0x250d)},    /* Panasonic Gobi Modem device */
        {QMI_GOBI1K_DEVICE(0x413c, 0x8172)},    /* Dell Gobi Modem device */
        {QMI_GOBI1K_DEVICE(0x1410, 0xa001)},    /* Novatel Gobi Modem device */
@@ -440,6 +445,7 @@ static const struct usb_device_id products[] = {
        {QMI_GOBI_DEVICE(0x16d8, 0x8002)},      /* CMDTech Gobi 2000 Modem device (VU922) */
        {QMI_GOBI_DEVICE(0x05c6, 0x9205)},      /* Gobi 2000 Modem device */
        {QMI_GOBI_DEVICE(0x1199, 0x9013)},      /* Sierra Wireless Gobi 3000 Modem device (MC8355) */
+       {QMI_GOBI_DEVICE(0x03f0, 0x371d)},      /* HP un2430 Mobile Broadband Module */
        {QMI_GOBI_DEVICE(0x1199, 0x9015)},      /* Sierra Wireless Gobi 3000 Modem device */
        {QMI_GOBI_DEVICE(0x1199, 0x9019)},      /* Sierra Wireless Gobi 3000 Modem device */
        {QMI_GOBI_DEVICE(0x1199, 0x901b)},      /* Sierra Wireless MC7770 */
index 7be49ea60b6d8f9353720d757f47c2c61b16fc60..8e22417fa6c11b5d41845bda1ff4c84e9d369cda 100644 (file)
@@ -656,7 +656,7 @@ static int sierra_net_get_fw_attr(struct usbnet *dev, u16 *datap)
                return -EIO;
        }
 
-       *datap = *attrdata;
+       *datap = le16_to_cpu(*attrdata);
 
        kfree(attrdata);
        return result;
index fd4b26d46fd5d2f2c8ccb68cd55844a3a5c9d336..fc9f578a1e253a781b9406b1e4a43ed2de2688d1 100644 (file)
@@ -1201,19 +1201,26 @@ deferred:
 }
 EXPORT_SYMBOL_GPL(usbnet_start_xmit);
 
-static void rx_alloc_submit(struct usbnet *dev, gfp_t flags)
+static int rx_alloc_submit(struct usbnet *dev, gfp_t flags)
 {
        struct urb      *urb;
        int             i;
+       int             ret = 0;
 
        /* don't refill the queue all at once */
        for (i = 0; i < 10 && dev->rxq.qlen < RX_QLEN(dev); i++) {
                urb = usb_alloc_urb(0, flags);
                if (urb != NULL) {
-                       if (rx_submit(dev, urb, flags) == -ENOLINK)
-                               return;
+                       ret = rx_submit(dev, urb, flags);
+                       if (ret)
+                               goto err;
+               } else {
+                       ret = -ENOMEM;
+                       goto err;
                }
        }
+err:
+       return ret;
 }
 
 /*-------------------------------------------------------------------------*/
@@ -1257,7 +1264,8 @@ static void usbnet_bh (unsigned long param)
                int     temp = dev->rxq.qlen;
 
                if (temp < RX_QLEN(dev)) {
-                       rx_alloc_submit(dev, GFP_ATOMIC);
+                       if (rx_alloc_submit(dev, GFP_ATOMIC) == -ENOLINK)
+                               return;
                        if (temp != dev->rxq.qlen)
                                netif_dbg(dev, link, dev->net,
                                          "rxqlen %d --> %d\n",
index aaaca9aa2293dcf4fc991cb1645056ebfa3d0da1..3f575afd8cfcb03f283df0932f6fb33bb1495cca 100644 (file)
@@ -10,6 +10,7 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <linux/module.h>
 #include <linux/bitops.h>
 #include <linux/cdev.h>
 #include <linux/dma-mapping.h>
index 2588848f4a822a1bf879ce447f9f146c5e186873..d066f2516e4753617aa55f1522427eb96f4a1115 100644 (file)
@@ -2982,6 +2982,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;
index 2c9f7d7ed4cc2557a86cb5256afc213a4c16f5c5..0ed3846f9cbb36e8aa1f67eab09dc9e5f219b0c8 100644 (file)
@@ -142,6 +142,7 @@ static int ar9003_paprd_setup_single_table(struct ath_hw *ah)
        };
        int training_power;
        int i, val;
+       u32 am2pm_mask = ah->paprd_ratemask;
 
        if (IS_CHAN_2GHZ(ah->curchan))
                training_power = ar9003_get_training_power_2g(ah);
@@ -158,10 +159,13 @@ static int ar9003_paprd_setup_single_table(struct ath_hw *ah)
        }
        ah->paprd_training_power = training_power;
 
+       if (AR_SREV_9330(ah))
+               am2pm_mask = 0;
+
        REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2AM, AR_PHY_PAPRD_AM2AM_MASK,
                      ah->paprd_ratemask);
        REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2PM, AR_PHY_PAPRD_AM2PM_MASK,
-                     ah->paprd_ratemask);
+                     am2pm_mask);
        REG_RMW_FIELD(ah, AR_PHY_PAPRD_HT40, AR_PHY_PAPRD_HT40_MASK,
                      ah->paprd_ratemask_ht40);
 
@@ -782,6 +786,102 @@ int ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain)
 }
 EXPORT_SYMBOL(ar9003_paprd_setup_gain_table);
 
+static bool ar9003_paprd_retrain_pa_in(struct ath_hw *ah,
+                                      struct ath9k_hw_cal_data *caldata,
+                                      int chain)
+{
+       u32 *pa_in = caldata->pa_table[chain];
+       int capdiv_offset, quick_drop_offset;
+       int capdiv2g, quick_drop;
+       int count = 0;
+       int i;
+
+       if (!AR_SREV_9485(ah) && !AR_SREV_9330(ah))
+               return false;
+
+       capdiv2g = REG_READ_FIELD(ah, AR_PHY_65NM_CH0_TXRF3,
+                                 AR_PHY_65NM_CH0_TXRF3_CAPDIV2G);
+
+       quick_drop = REG_READ_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
+                                   AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP);
+
+       if (quick_drop)
+               quick_drop -= 0x40;
+
+       for (i = 0; i < NUM_BIN + 1; i++) {
+               if (pa_in[i] == 1400)
+                       count++;
+       }
+
+       if (AR_SREV_9485(ah)) {
+               if (pa_in[23] < 800) {
+                       capdiv_offset = (int)((1000 - pa_in[23] + 75) / 150);
+                       capdiv2g += capdiv_offset;
+                       if (capdiv2g > 7) {
+                               capdiv2g = 7;
+                               if (pa_in[23] < 600) {
+                                       quick_drop++;
+                                       if (quick_drop > 0)
+                                               quick_drop = 0;
+                               }
+                       }
+               } else if (pa_in[23] == 1400) {
+                       quick_drop_offset = min_t(int, count / 3, 2);
+                       quick_drop += quick_drop_offset;
+                       capdiv2g += quick_drop_offset / 2;
+
+                       if (capdiv2g > 7)
+                               capdiv2g = 7;
+
+                       if (quick_drop > 0) {
+                               quick_drop = 0;
+                               capdiv2g -= quick_drop_offset;
+                               if (capdiv2g < 0)
+                                       capdiv2g = 0;
+                       }
+               } else {
+                       return false;
+               }
+       } else if (AR_SREV_9330(ah)) {
+               if (pa_in[23] < 1000) {
+                       capdiv_offset = (1000 - pa_in[23]) / 100;
+                       capdiv2g += capdiv_offset;
+                       if (capdiv_offset > 3) {
+                               capdiv_offset = 1;
+                               quick_drop--;
+                       }
+
+                       capdiv2g += capdiv_offset;
+                       if (capdiv2g > 6)
+                               capdiv2g = 6;
+                       if (quick_drop < -4)
+                               quick_drop = -4;
+               } else if (pa_in[23] == 1400) {
+                       if (count > 3) {
+                               quick_drop++;
+                               capdiv2g -= count / 4;
+                               if (quick_drop > -2)
+                                       quick_drop = -2;
+                       } else {
+                               capdiv2g--;
+                       }
+
+                       if (capdiv2g < 0)
+                               capdiv2g = 0;
+               } else {
+                       return false;
+               }
+       }
+
+       REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_TXRF3,
+                     AR_PHY_65NM_CH0_TXRF3_CAPDIV2G, capdiv2g);
+       REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
+                     AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP,
+                     quick_drop);
+
+       return true;
+}
+
 int ar9003_paprd_create_curve(struct ath_hw *ah,
                              struct ath9k_hw_cal_data *caldata, int chain)
 {
@@ -817,6 +917,9 @@ int ar9003_paprd_create_curve(struct ath_hw *ah,
        if (!create_pa_curve(data_L, data_U, pa_table, small_signal_gain))
                status = -2;
 
+       if (ar9003_paprd_retrain_pa_in(ah, caldata, chain))
+               status = -EINPROGRESS;
+
        REG_CLR_BIT(ah, AR_PHY_PAPRD_TRAINER_STAT1,
                    AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE);
 
index 7bfbaf065a4332c89ac5568c0cde81ed42d9313e..84d3d49568616c5452692b1660253f6ae70468cf 100644 (file)
 #define AR_PHY_AIC_CTRL_4_B0   (AR_SM_BASE + 0x4c0)
 #define AR_PHY_AIC_STAT_2_B0   (AR_SM_BASE + 0x4cc)
 
+#define AR_PHY_65NM_CH0_TXRF3       0x16048
+#define AR_PHY_65NM_CH0_TXRF3_CAPDIV2G         0x0000001e
+#define AR_PHY_65NM_CH0_TXRF3_CAPDIV2G_S       1
+
 #define AR_PHY_65NM_CH0_SYNTH4      0x1608c
 #define AR_PHY_SYNTH4_LONG_SHIFT_SELECT   (AR_SREV_9462(ah) ? 0x00000001 : 0x00000002)
 #define AR_PHY_SYNTH4_LONG_SHIFT_SELECT_S (AR_SREV_9462(ah) ? 0 : 1)
index 68b643c8943c4c2db074e4ada4eeb2fda397eccc..c8ef30127adb53da590bf4d6350798fa261dffa6 100644 (file)
@@ -1577,6 +1577,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,
index bacdb8fb4ef453dda48d5a9394c0030cb7866596..9f83f71742a5ecb774f95c3d563f2e0dc7d37ab7 100644 (file)
@@ -341,7 +341,8 @@ void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc)
 {
        struct ath_btcoex *btcoex = &sc->btcoex;
 
-       ath9k_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer);
+       if (btcoex->hw_timer_enabled)
+               ath9k_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer);
 }
 
 u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, u32 max_4ms_framelen)
index 60b6a9daff7e21cde68fb6eda800e4ca065c62aa..4faf0a3958765bd07ae683fdd6dceb879a5adbfd 100644 (file)
@@ -463,9 +463,6 @@ static void ath9k_hw_init_config(struct ath_hw *ah)
                ah->config.spurchans[i][1] = AR_NO_SPUR;
        }
 
-       /* PAPRD needs some more work to be enabled */
-       ah->config.paprd_disable = 1;
-
        ah->config.rx_intr_mitigation = true;
        ah->config.pcieSerDesWrite = true;
 
@@ -978,9 +975,6 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah,
        else
                imr_reg |= AR_IMR_TXOK;
 
-       if (opmode == NL80211_IFTYPE_AP)
-               imr_reg |= AR_IMR_MIB;
-
        ENABLE_REGWRITE_BUFFER(ah);
 
        REG_WRITE(ah, AR_IMR, imr_reg);
@@ -1778,6 +1772,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
                /* Operating channel changed, reset channel calibration data */
                memset(caldata, 0, sizeof(*caldata));
                ath9k_init_nfcal_hist_buffer(ah, chan);
+       } else if (caldata) {
+               caldata->paprd_packet_sent = false;
        }
        ah->noise = ath9k_hw_getchan_noise(ah, chan);
 
@@ -2501,9 +2497,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))
-                       pCap->hw_caps |= ATH9K_HW_CAP_PAPRD;
        } else {
                pCap->tx_desc_len = sizeof(struct ath_desc);
                if (AR_SREV_9280_20(ah))
index ce7332c64efb2c5b417cd40fec2428522186142a..de6968fc64f42920304fe52dd93a493c3ce679c6 100644 (file)
@@ -236,7 +236,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),
@@ -287,12 +286,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;
@@ -405,6 +404,7 @@ struct ath9k_hw_cal_data {
        int8_t iCoff;
        int8_t qCoff;
        bool rtt_done;
+       bool paprd_packet_sent;
        bool paprd_done;
        bool nfcal_pending;
        bool nfcal_interference;
index d4549e9aac5c5f1f30ace855d6c94dafe98f4d38..7b88b9c39ccddc4ef4e3aeafb53e437d0f35a0ce 100644 (file)
@@ -254,8 +254,9 @@ void ath_paprd_calibrate(struct work_struct *work)
        int chain_ok = 0;
        int chain;
        int len = 1800;
+       int ret;
 
-       if (!caldata)
+       if (!caldata || !caldata->paprd_packet_sent || caldata->paprd_done)
                return;
 
        ath9k_ps_wakeup(sc);
@@ -282,13 +283,6 @@ void ath_paprd_calibrate(struct work_struct *work)
                        continue;
 
                chain_ok = 0;
-
-               ath_dbg(common, CALIBRATE,
-                       "Sending PAPRD frame for thermal measurement on chain %d\n",
-                       chain);
-               if (!ath_paprd_send_frame(sc, skb, chain))
-                       goto fail_paprd;
-
                ar9003_paprd_setup_gain_table(ah, chain);
 
                ath_dbg(common, CALIBRATE,
@@ -302,7 +296,13 @@ void ath_paprd_calibrate(struct work_struct *work)
                        break;
                }
 
-               if (ar9003_paprd_create_curve(ah, caldata, chain)) {
+               ret = ar9003_paprd_create_curve(ah, caldata, chain);
+               if (ret == -EINPROGRESS) {
+                       ath_dbg(common, CALIBRATE,
+                               "PAPRD curve on chain %d needs to be re-trained\n",
+                               chain);
+                       break;
+               } else if (ret) {
                        ath_dbg(common, CALIBRATE,
                                "PAPRD create curve failed on chain %d\n",
                                chain);
@@ -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)
index 2c9da6b2ecb1b7b1141770f1240188bf2af50277..0d4155aec48d72196d5c64eee5c2517766760632 100644 (file)
@@ -2018,6 +2018,9 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
 
        ath_dbg(common, XMIT, "TX complete: skb: %p\n", skb);
 
+       if (sc->sc_ah->caldata)
+               sc->sc_ah->caldata->paprd_packet_sent = true;
+
        if (!(tx_flags & ATH_TX_ERROR))
                /* Frame was ACKed */
                tx_info->flags |= IEEE80211_TX_STAT_ACK;
index 49765d34b4e0b43ac947aa360fb58d1fff88aa90..7c4ee72f9d56006cb7e069a9472a0524bbebb9c9 100644 (file)
@@ -638,6 +638,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);
index 2621dd3d7dcd9d3b6ac5ca05db587cdd94454011..6f70953f0bade06ef046a845829a887611c0a8b8 100644 (file)
@@ -764,8 +764,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;
@@ -781,8 +784,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));
@@ -800,10 +806,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;
@@ -829,14 +835,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));
@@ -848,9 +854,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);
index a299d42da8e74a358939b8fa5da8a32a01fd312b..58f89fa9c9f8a218ed29cfb93ad253c41471c648 100644 (file)
@@ -519,7 +519,7 @@ static void brcmf_usb_tx_complete(struct urb *urb)
        else
                devinfo->bus_pub.bus->dstats.tx_errors++;
 
-       dev_kfree_skb(req->skb);
+       brcmu_pkt_buf_free_skb(req->skb);
        req->skb = NULL;
        brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req);
 
@@ -540,7 +540,7 @@ static void brcmf_usb_rx_complete(struct urb *urb)
                devinfo->bus_pub.bus->dstats.rx_packets++;
        } else {
                devinfo->bus_pub.bus->dstats.rx_errors++;
-               dev_kfree_skb(skb);
+               brcmu_pkt_buf_free_skb(skb);
                brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req);
                return;
        }
@@ -550,13 +550,15 @@ static void brcmf_usb_rx_complete(struct urb *urb)
                if (brcmf_proto_hdrpull(devinfo->dev, &ifidx, skb) != 0) {
                        brcmf_dbg(ERROR, "rx protocol error\n");
                        brcmu_pkt_buf_free_skb(skb);
+                       brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req);
                        devinfo->bus_pub.bus->dstats.rx_errors++;
                } else {
                        brcmf_rx_packet(devinfo->dev, ifidx, skb);
                        brcmf_usb_rx_refill(devinfo, req);
                }
        } else {
-               dev_kfree_skb(skb);
+               brcmu_pkt_buf_free_skb(skb);
+               brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req);
        }
        return;
 
@@ -581,14 +583,13 @@ static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo,
        usb_fill_bulk_urb(req->urb, devinfo->usbdev, devinfo->rx_pipe,
                          skb->data, skb_tailroom(skb), brcmf_usb_rx_complete,
                          req);
-       req->urb->transfer_flags |= URB_ZERO_PACKET;
        req->devinfo = devinfo;
+       brcmf_usb_enq(devinfo, &devinfo->rx_postq, req);
 
        ret = usb_submit_urb(req->urb, GFP_ATOMIC);
-       if (ret == 0) {
-               brcmf_usb_enq(devinfo, &devinfo->rx_postq, req);
-       } else {
-               dev_kfree_skb(req->skb);
+       if (ret) {
+               brcmf_usb_del_fromq(devinfo, req);
+               brcmu_pkt_buf_free_skb(req->skb);
                req->skb = NULL;
                brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req);
        }
@@ -683,23 +684,22 @@ static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb)
 
        req = brcmf_usb_deq(devinfo, &devinfo->tx_freeq);
        if (!req) {
+               brcmu_pkt_buf_free_skb(skb);
                brcmf_dbg(ERROR, "no req to send\n");
                return -ENOMEM;
        }
-       if (!req->urb) {
-               brcmf_dbg(ERROR, "no urb for req %p\n", req);
-               return -ENOBUFS;
-       }
 
        req->skb = skb;
        req->devinfo = devinfo;
        usb_fill_bulk_urb(req->urb, devinfo->usbdev, devinfo->tx_pipe,
                          skb->data, skb->len, brcmf_usb_tx_complete, req);
        req->urb->transfer_flags |= URB_ZERO_PACKET;
+       brcmf_usb_enq(devinfo, &devinfo->tx_postq, req);
        ret = usb_submit_urb(req->urb, GFP_ATOMIC);
-       if (!ret) {
-               brcmf_usb_enq(devinfo, &devinfo->tx_postq, req);
-       } else {
+       if (ret) {
+               brcmf_dbg(ERROR, "brcmf_usb_tx usb_submit_urb FAILED\n");
+               brcmf_usb_del_fromq(devinfo, req);
+               brcmu_pkt_buf_free_skb(req->skb);
                req->skb = NULL;
                brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req);
        }
index 28c5fbb4af267b59ef1c8bab67f2d4ac2d7e9485..50b5553b6964b95dffecf40f4d28fdb91796efc8 100644 (file)
@@ -500,8 +500,10 @@ static void wl_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
@@ -1876,16 +1878,17 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
        }
 
        if (test_bit(WL_STATUS_CONNECTED, &cfg_priv->status)) {
-               scb_val.val = cpu_to_le32(0);
+               memset(&scb_val, 0, sizeof(scb_val));
                err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_RSSI, &scb_val,
                                      sizeof(struct brcmf_scb_val_le));
-               if (err)
+               if (err) {
                        WL_ERR("Could not get rssi (%d)\n", err);
-
-               rssi = le32_to_cpu(scb_val.val);
-               sinfo->filled |= STATION_INFO_SIGNAL;
-               sinfo->signal = rssi;
-               WL_CONN("RSSI %d dBm\n", rssi);
+               } else {
+                       rssi = le32_to_cpu(scb_val.val);
+                       sinfo->filled |= STATION_INFO_SIGNAL;
+                       sinfo->signal = rssi;
+                       WL_CONN("RSSI %d dBm\n", rssi);
+               }
        }
 
 done:
index 7ed7d7577024628d228a78f6e94433c810295bc2..64a48f06d68bfa124c1687bc1fa81a799fb5be82 100644 (file)
@@ -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,
index e970897f6ab52370a632a64a62cc10bb3c39a3c6..4cb234349fbfacc305b1565ed5f1a30ba16aa108 100644 (file)
@@ -1326,6 +1326,11 @@ static int if_sdio_suspend(struct device *dev)
 
        mmc_pm_flag_t flags = sdio_get_host_pm_caps(func);
 
+       /* If we're powered off anyway, just let the mmc layer remove the
+        * card. */
+       if (!lbs_iface_active(card->priv))
+               return -ENOSYS;
+
        dev_info(dev, "%s: suspend: PM flags = 0x%x\n",
                 sdio_func_id(func), flags);
 
index c68adec3cc8b6522678c98582c7781b885193849..565527aee0ea3f73caa832f336c0ded06a3b22d9 100644 (file)
@@ -170,7 +170,20 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv,
        cmd_code = le16_to_cpu(host_cmd->command);
        cmd_size = le16_to_cpu(host_cmd->size);
 
-       skb_trim(cmd_node->cmd_skb, cmd_size);
+       /* Adjust skb length */
+       if (cmd_node->cmd_skb->len > cmd_size)
+               /*
+                * cmd_size is less than sizeof(struct host_cmd_ds_command).
+                * Trim off the unused portion.
+                */
+               skb_trim(cmd_node->cmd_skb, cmd_size);
+       else if (cmd_node->cmd_skb->len < cmd_size)
+               /*
+                * cmd_size is larger than sizeof(struct host_cmd_ds_command)
+                * because we have appended custom IE TLV. Increase skb length
+                * accordingly.
+                */
+               skb_put(cmd_node->cmd_skb, cmd_size - cmd_node->cmd_skb->len);
 
        do_gettimeofday(&tstamp);
        dev_dbg(adapter->dev, "cmd: DNLD_CMD: (%lu.%lu): %#x, act %#x, len %d,"
index 8b9dbd76a25255634ad79338223739c939429d26..64328af496f598bb3280784b6d2adfd25ec5cc70 100644 (file)
@@ -1611,6 +1611,7 @@ static int rt2400pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
 static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev)
 {
        int retval;
+       u32 reg;
 
        /*
         * Allocate eeprom data.
@@ -1623,6 +1624,14 @@ static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev)
        if (retval)
                return retval;
 
+       /*
+        * Enable rfkill polling by setting GPIO direction of the
+        * rfkill switch GPIO pin correctly.
+        */
+       rt2x00pci_register_read(rt2x00dev, GPIOCSR, &reg);
+       rt2x00_set_field32(&reg, GPIOCSR_BIT8, 1);
+       rt2x00pci_register_write(rt2x00dev, GPIOCSR, reg);
+
        /*
         * Initialize hw specifications.
         */
index d3a4a68cc439b22faea7f6e9d4899e9313e5a7e2..7564ae992b735179b15e24a3d616c5a71acb1aeb 100644 (file)
 #define GPIOCSR_BIT5                   FIELD32(0x00000020)
 #define GPIOCSR_BIT6                   FIELD32(0x00000040)
 #define GPIOCSR_BIT7                   FIELD32(0x00000080)
+#define GPIOCSR_BIT8                   FIELD32(0x00000100)
 
 /*
  * BBPPCSR: BBP Pin control register.
index d2cf8a4bc8b52fd985f4720df6bc20a9269069c3..3de0406735f6b7347b46cdf2305e413aaa17256d 100644 (file)
@@ -1929,6 +1929,7 @@ static int rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
 static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev)
 {
        int retval;
+       u32 reg;
 
        /*
         * Allocate eeprom data.
@@ -1941,6 +1942,14 @@ static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev)
        if (retval)
                return retval;
 
+       /*
+        * Enable rfkill polling by setting GPIO direction of the
+        * rfkill switch GPIO pin correctly.
+        */
+       rt2x00pci_register_read(rt2x00dev, GPIOCSR, &reg);
+       rt2x00_set_field32(&reg, GPIOCSR_DIR0, 1);
+       rt2x00pci_register_write(rt2x00dev, GPIOCSR, reg);
+
        /*
         * Initialize hw specifications.
         */
index 3aae36bb0a9e9f99cf89705bc2dca5022109824a..89fee311d8fda5ad07ae5ecd50fae567232aa35d 100644 (file)
@@ -283,7 +283,7 @@ static int rt2500usb_rfkill_poll(struct rt2x00_dev *rt2x00dev)
        u16 reg;
 
        rt2500usb_register_read(rt2x00dev, MAC_CSR19, &reg);
-       return rt2x00_get_field32(reg, MAC_CSR19_BIT7);
+       return rt2x00_get_field16(reg, MAC_CSR19_BIT7);
 }
 
 #ifdef CONFIG_RT2X00_LIB_LEDS
@@ -1768,6 +1768,7 @@ static int rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
 static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)
 {
        int retval;
+       u16 reg;
 
        /*
         * Allocate eeprom data.
@@ -1780,6 +1781,14 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)
        if (retval)
                return retval;
 
+       /*
+        * Enable rfkill polling by setting GPIO direction of the
+        * rfkill switch GPIO pin correctly.
+        */
+       rt2500usb_register_read(rt2x00dev, MAC_CSR19, &reg);
+       rt2x00_set_field16(&reg, MAC_CSR19_BIT8, 0);
+       rt2500usb_register_write(rt2x00dev, MAC_CSR19, reg);
+
        /*
         * Initialize hw specifications.
         */
index b493306a7eede0888af2cccef613c6612b579514..196bd5103e4f5450483ce1e60449021bf6eafd2c 100644 (file)
  * MAC_CSR19: GPIO control register.
  */
 #define MAC_CSR19                      0x0426
-#define MAC_CSR19_BIT0                 FIELD32(0x0001)
-#define MAC_CSR19_BIT1                 FIELD32(0x0002)
-#define MAC_CSR19_BIT2                 FIELD32(0x0004)
-#define MAC_CSR19_BIT3                 FIELD32(0x0008)
-#define MAC_CSR19_BIT4                 FIELD32(0x0010)
-#define MAC_CSR19_BIT5                 FIELD32(0x0020)
-#define MAC_CSR19_BIT6                 FIELD32(0x0040)
-#define MAC_CSR19_BIT7                 FIELD32(0x0080)
+#define MAC_CSR19_BIT0                 FIELD16(0x0001)
+#define MAC_CSR19_BIT1                 FIELD16(0x0002)
+#define MAC_CSR19_BIT2                 FIELD16(0x0004)
+#define MAC_CSR19_BIT3                 FIELD16(0x0008)
+#define MAC_CSR19_BIT4                 FIELD16(0x0010)
+#define MAC_CSR19_BIT5                 FIELD16(0x0020)
+#define MAC_CSR19_BIT6                 FIELD16(0x0040)
+#define MAC_CSR19_BIT7                 FIELD16(0x0080)
+#define MAC_CSR19_BIT8                 FIELD16(0x0100)
 
 /*
  * MAC_CSR20: LED control register.
index cb8c2aca54e4dfdac4a7e223a8070f4e4543399e..b93516d832fb5603e4bb3d287a4770c0c8de06ad 100644 (file)
@@ -4089,6 +4089,7 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
                rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
                msleep(1);
                rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
+               rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 0);
                rt2x00_set_field32(&reg, LDO_CFG0_BGSEL, 1);
                rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
        }
index 98aa426a35649828e3c70c0f2bab0acf24e49381..4765bbd654cdcfeea617c84f9c755db05409600d 100644 (file)
@@ -983,6 +983,7 @@ static int rt2800pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
 static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)
 {
        int retval;
+       u32 reg;
 
        /*
         * Allocate eeprom data.
@@ -995,6 +996,14 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)
        if (retval)
                return retval;
 
+       /*
+        * Enable rfkill polling by setting GPIO direction of the
+        * rfkill switch GPIO pin correctly.
+        */
+       rt2x00pci_register_read(rt2x00dev, GPIO_CTRL_CFG, &reg);
+       rt2x00_set_field32(&reg, GPIO_CTRL_CFG_GPIOD_BIT2, 1);
+       rt2x00pci_register_write(rt2x00dev, GPIO_CTRL_CFG, reg);
+
        /*
         * Initialize hw specifications.
         */
index 6cf336595e2544a5703612e5156af0559b5cc8ab..6b4226b716187ea037d2a1c84e012806649e8816 100644 (file)
@@ -667,8 +667,16 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,
        skb_pull(entry->skb, RXINFO_DESC_SIZE);
 
        /*
-        * FIXME: we need to check for rx_pkt_len validity
+        * Check for rx_pkt_len validity. Return if invalid, leaving
+        * rxdesc->size zeroed out by the upper level.
         */
+       if (unlikely(rx_pkt_len == 0 ||
+                       rx_pkt_len > entry->queue->data_size)) {
+               ERROR(entry->queue->rt2x00dev,
+                       "Bad frame size %d, forcing to 0\n", rx_pkt_len);
+               return;
+       }
+
        rxd = (__le32 *)(entry->skb->data + rx_pkt_len);
 
        /*
@@ -736,6 +744,7 @@ static int rt2800usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
 static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)
 {
        int retval;
+       u32 reg;
 
        /*
         * Allocate eeprom data.
@@ -748,6 +757,14 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)
        if (retval)
                return retval;
 
+       /*
+        * Enable rfkill polling by setting GPIO direction of the
+        * rfkill switch GPIO pin correctly.
+        */
+       rt2x00usb_register_read(rt2x00dev, GPIO_CTRL_CFG, &reg);
+       rt2x00_set_field32(&reg, GPIO_CTRL_CFG_GPIOD_BIT2, 1);
+       rt2x00usb_register_write(rt2x00dev, GPIO_CTRL_CFG, reg);
+
        /*
         * Initialize hw specifications.
         */
@@ -1157,6 +1174,8 @@ static struct usb_device_id rt2800usb_device_table[] = {
        { USB_DEVICE(0x1690, 0x0744) },
        { USB_DEVICE(0x1690, 0x0761) },
        { USB_DEVICE(0x1690, 0x0764) },
+       /* ASUS */
+       { USB_DEVICE(0x0b05, 0x179d) },
        /* Cisco */
        { USB_DEVICE(0x167b, 0x4001) },
        /* EnGenius */
@@ -1222,7 +1241,6 @@ static struct usb_device_id rt2800usb_device_table[] = {
        { USB_DEVICE(0x0b05, 0x1760) },
        { USB_DEVICE(0x0b05, 0x1761) },
        { USB_DEVICE(0x0b05, 0x1790) },
-       { USB_DEVICE(0x0b05, 0x179d) },
        /* AzureWave */
        { USB_DEVICE(0x13d3, 0x3262) },
        { USB_DEVICE(0x13d3, 0x3284) },
index a6b88bd4a1a57d7f904c75faa62c95ea219be029..3f07e36f462b384565884580170faf7c3be2f25f 100644 (file)
@@ -629,7 +629,7 @@ void rt2x00lib_rxdone(struct queue_entry *entry, gfp_t gfp)
         */
        if (unlikely(rxdesc.size == 0 ||
                     rxdesc.size > entry->queue->data_size)) {
-               WARNING(rt2x00dev, "Wrong frame size %d max %d.\n",
+               ERROR(rt2x00dev, "Wrong frame size %d max %d.\n",
                        rxdesc.size, entry->queue->data_size);
                dev_kfree_skb(entry->skb);
                goto renew_skb;
index 3f7bc5cadf9a8a7a433688e8d480d76de3c1ab82..b8ec96163922a11711a3d6800b9556052c1386fc 100644 (file)
@@ -2832,6 +2832,7 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
 static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev)
 {
        int retval;
+       u32 reg;
 
        /*
         * Disable power saving.
@@ -2849,6 +2850,14 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev)
        if (retval)
                return retval;
 
+       /*
+        * Enable rfkill polling by setting GPIO direction of the
+        * rfkill switch GPIO pin correctly.
+        */
+       rt2x00pci_register_read(rt2x00dev, MAC_CSR13, &reg);
+       rt2x00_set_field32(&reg, MAC_CSR13_BIT13, 1);
+       rt2x00pci_register_write(rt2x00dev, MAC_CSR13, reg);
+
        /*
         * Initialize hw specifications.
         */
index e3cd6db76b0e561d481873d22c5637d3d1732446..8f3da5a56766f4c3293825c2d649078f4cb5455f 100644 (file)
@@ -372,6 +372,7 @@ struct hw_pairwise_ta_entry {
 #define MAC_CSR13_BIT10                        FIELD32(0x00000400)
 #define MAC_CSR13_BIT11                        FIELD32(0x00000800)
 #define MAC_CSR13_BIT12                        FIELD32(0x00001000)
+#define MAC_CSR13_BIT13                        FIELD32(0x00002000)
 
 /*
  * MAC_CSR14: LED control register.
index ba6e434b859d66506c26c5f05b7d5a569403c9d9..248436c13ce04ae1f79312c6cbb1e16d8a4b5fc9 100644 (file)
@@ -2177,6 +2177,7 @@ static int rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
 static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)
 {
        int retval;
+       u32 reg;
 
        /*
         * Allocate eeprom data.
@@ -2189,6 +2190,14 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)
        if (retval)
                return retval;
 
+       /*
+        * Enable rfkill polling by setting GPIO direction of the
+        * rfkill switch GPIO pin correctly.
+        */
+       rt2x00usb_register_read(rt2x00dev, MAC_CSR13, &reg);
+       rt2x00_set_field32(&reg, MAC_CSR13_BIT15, 0);
+       rt2x00usb_register_write(rt2x00dev, MAC_CSR13, reg);
+
        /*
         * Initialize hw specifications.
         */
index 9f6b470414d33a687c8795b380add18cd8efaeb4..df1cc116b83be891ee2ff20702260f5949d3d983 100644 (file)
@@ -282,6 +282,9 @@ struct hw_pairwise_ta_entry {
 #define MAC_CSR13_BIT10                        FIELD32(0x00000400)
 #define MAC_CSR13_BIT11                        FIELD32(0x00000800)
 #define MAC_CSR13_BIT12                        FIELD32(0x00001000)
+#define MAC_CSR13_BIT13                        FIELD32(0x00002000)
+#define MAC_CSR13_BIT14                        FIELD32(0x00004000)
+#define MAC_CSR13_BIT15                        FIELD32(0x00008000)
 
 /*
  * MAC_CSR14: LED control register.
index 04c3aef8a4f62e178fbac155a956c64c529b97c8..2925094b2d912529fb32dc5202487d1def6d9910 100644 (file)
 
 #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
index bd0da7ef290b3cf5cafafe4d56ec4c3d7cf33611..dd4bb0950a575ddd37c31489f10d2bacdaaab940 100644 (file)
@@ -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) {
index 3aa927f8b9b93bfbf0b12d9d0194966cd24900c8..7d8f96405f42068bafa9c08d7ec6a382f2e2c7f0 100644 (file)
@@ -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);
index 5270f1a99328d678396739781c7b0d4a87a586ef..d6fd6b6d9d4b575c26eb0041e503ddb10ddb9d64 100644 (file)
@@ -280,8 +280,12 @@ static long local_pci_probe(void *_ddi)
 {
        struct drv_dev_and_id *ddi = _ddi;
        struct device *dev = &ddi->dev->dev;
+       struct device *parent = dev->parent;
        int rc;
 
+       /* The parent bridge must be in active state when probing */
+       if (parent)
+               pm_runtime_get_sync(parent);
        /* Unbound PCI devices are always set to disabled and suspended.
         * During probe, the device is set to enabled and active and the
         * usage count is incremented.  If the driver supports runtime PM,
@@ -298,6 +302,8 @@ static long local_pci_probe(void *_ddi)
                pm_runtime_set_suspended(dev);
                pm_runtime_put_noidle(dev);
        }
+       if (parent)
+               pm_runtime_put(parent);
        return rc;
 }
 
index 6869009c7393f7081497c51901f11f31e62957bf..02d107b152818e948cc3e561d276bf24126ac997 100644 (file)
@@ -458,6 +458,40 @@ boot_vga_show(struct device *dev, struct device_attribute *attr, char *buf)
 }
 struct device_attribute vga_attr = __ATTR_RO(boot_vga);
 
+static void
+pci_config_pm_runtime_get(struct pci_dev *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct device *parent = dev->parent;
+
+       if (parent)
+               pm_runtime_get_sync(parent);
+       pm_runtime_get_noresume(dev);
+       /*
+        * pdev->current_state is set to PCI_D3cold during suspending,
+        * so wait until suspending completes
+        */
+       pm_runtime_barrier(dev);
+       /*
+        * Only need to resume devices in D3cold, because config
+        * registers are still accessible for devices suspended but
+        * not in D3cold.
+        */
+       if (pdev->current_state == PCI_D3cold)
+               pm_runtime_resume(dev);
+}
+
+static void
+pci_config_pm_runtime_put(struct pci_dev *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct device *parent = dev->parent;
+
+       pm_runtime_put(dev);
+       if (parent)
+               pm_runtime_put_sync(parent);
+}
+
 static ssize_t
 pci_read_config(struct file *filp, struct kobject *kobj,
                struct bin_attribute *bin_attr,
@@ -484,6 +518,8 @@ pci_read_config(struct file *filp, struct kobject *kobj,
                size = count;
        }
 
+       pci_config_pm_runtime_get(dev);
+
        if ((off & 1) && size) {
                u8 val;
                pci_user_read_config_byte(dev, off, &val);
@@ -529,6 +565,8 @@ pci_read_config(struct file *filp, struct kobject *kobj,
                --size;
        }
 
+       pci_config_pm_runtime_put(dev);
+
        return count;
 }
 
@@ -549,6 +587,8 @@ pci_write_config(struct file* filp, struct kobject *kobj,
                count = size;
        }
        
+       pci_config_pm_runtime_get(dev);
+
        if ((off & 1) && size) {
                pci_user_write_config_byte(dev, off, data[off - init_off]);
                off++;
@@ -587,6 +627,8 @@ pci_write_config(struct file* filp, struct kobject *kobj,
                --size;
        }
 
+       pci_config_pm_runtime_put(dev);
+
        return count;
 }
 
index f3ea977a5b1bf6f458c8ed0757cd8e02cc1d3ff2..ab4bf5a4c2f12ee6dc90a83666d03387fc618fca 100644 (file)
@@ -1941,6 +1941,7 @@ void pci_pm_init(struct pci_dev *dev)
        dev->pm_cap = pm;
        dev->d3_delay = PCI_PM_D3_WAIT;
        dev->d3cold_delay = PCI_PM_D3COLD_WAIT;
+       dev->d3cold_allowed = true;
 
        dev->d1_support = false;
        dev->d2_support = false;
index 3a7eefcb270a5dda9a2dcbcead63086da4433c3e..e76b44777dbf7f2893ecdcde08997cad1d904eb4 100644 (file)
@@ -140,9 +140,17 @@ static int pcie_port_runtime_resume(struct device *dev)
 {
        return 0;
 }
+
+static int pcie_port_runtime_idle(struct device *dev)
+{
+       /* Delay for a short while to prevent too frequent suspend/resume */
+       pm_schedule_suspend(dev, 10);
+       return -EBUSY;
+}
 #else
 #define pcie_port_runtime_suspend      NULL
 #define pcie_port_runtime_resume       NULL
+#define pcie_port_runtime_idle         NULL
 #endif
 
 static const struct dev_pm_ops pcie_portdrv_pm_ops = {
@@ -155,6 +163,7 @@ static const struct dev_pm_ops pcie_portdrv_pm_ops = {
        .resume_noirq   = pcie_port_resume_noirq,
        .runtime_suspend = pcie_port_runtime_suspend,
        .runtime_resume = pcie_port_runtime_resume,
+       .runtime_idle   = pcie_port_runtime_idle,
 };
 
 #define PCIE_PORTDRV_PM_OPS    (&pcie_portdrv_pm_ops)
@@ -200,6 +209,11 @@ static int __devinit pcie_portdrv_probe(struct pci_dev *dev,
                return status;
 
        pci_save_state(dev);
+       /*
+        * D3cold may not work properly on some PCIe port, so disable
+        * it by default.
+        */
+       dev->d3cold_allowed = false;
        if (!pci_match_id(port_runtime_pm_black_list, dev))
                pm_runtime_put_noidle(&dev->dev);
 
index 6c143b4497ca4381677dcc34459ecf269e5cdc88..9f8a6b79a8ecf22d604056a902e7ca7adee8520a 100644 (file)
@@ -144,15 +144,13 @@ static inline unsigned long decode_bar(struct pci_dev *dev, u32 bar)
        case PCI_BASE_ADDRESS_MEM_TYPE_32:
                break;
        case PCI_BASE_ADDRESS_MEM_TYPE_1M:
-               dev_info(&dev->dev, "1M mem BAR treated as 32-bit BAR\n");
+               /* 1M mem BAR treated as 32-bit BAR */
                break;
        case PCI_BASE_ADDRESS_MEM_TYPE_64:
                flags |= IORESOURCE_MEM_64;
                break;
        default:
-               dev_warn(&dev->dev,
-                        "mem unknown type %x treated as 32-bit BAR\n",
-                        mem_type);
+               /* mem unknown type treated as 32-bit BAR */
                break;
        }
        return flags;
@@ -173,9 +171,11 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
        u32 l, sz, mask;
        u16 orig_cmd;
        struct pci_bus_region region;
+       bool bar_too_big = false, bar_disabled = false;
 
        mask = type ? PCI_ROM_ADDRESS_MASK : ~0;
 
+       /* No printks while decoding is disabled! */
        if (!dev->mmio_always_on) {
                pci_read_config_word(dev, PCI_COMMAND, &orig_cmd);
                pci_write_config_word(dev, PCI_COMMAND,
@@ -240,8 +240,7 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
                        goto fail;
 
                if ((sizeof(resource_size_t) < 8) && (sz64 > 0x100000000ULL)) {
-                       dev_err(&dev->dev, "reg %x: can't handle 64-bit BAR\n",
-                               pos);
+                       bar_too_big = true;
                        goto fail;
                }
 
@@ -252,12 +251,11 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
                        region.start = 0;
                        region.end = sz64;
                        pcibios_bus_to_resource(dev, res, &region);
+                       bar_disabled = true;
                } else {
                        region.start = l64;
                        region.end = l64 + sz64;
                        pcibios_bus_to_resource(dev, res, &region);
-                       dev_printk(KERN_DEBUG, &dev->dev, "reg %x: %pR\n",
-                                  pos, res);
                }
        } else {
                sz = pci_size(l, sz, mask);
@@ -268,18 +266,23 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
                region.start = l;
                region.end = l + sz;
                pcibios_bus_to_resource(dev, res, &region);
-
-               dev_printk(KERN_DEBUG, &dev->dev, "reg %x: %pR\n", pos, res);
        }
 
- out:
+       goto out;
+
+
+fail:
+       res->flags = 0;
+out:
        if (!dev->mmio_always_on)
                pci_write_config_word(dev, PCI_COMMAND, orig_cmd);
 
+       if (bar_too_big)
+               dev_err(&dev->dev, "reg %x: can't handle 64-bit BAR\n", pos);
+       if (res->flags && !bar_disabled)
+               dev_printk(KERN_DEBUG, &dev->dev, "reg %x: %pR\n", pos, res);
+
        return (res->flags & IORESOURCE_MEM_64) ? 1 : 0;
- fail:
-       res->flags = 0;
-       goto out;
 }
 
 static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom)
index 3782e1cd3697020219d34b81aa039a8c767be486..934d861a32359bb553ce17966d152f089b31c04d 100644 (file)
@@ -2196,10 +2196,8 @@ static int __init acer_wmi_init(void)
                interface->capability &= ~ACER_CAP_BRIGHTNESS;
                pr_info("Brightness must be controlled by acpi video driver\n");
        } else {
-#ifdef CONFIG_ACPI_VIDEO
                pr_info("Disabling ACPI video driver\n");
                acpi_video_unregister();
-#endif
        }
 
        if (wmi_has_guid(WMID_GUID3)) {
index dfb1a92ce9497cb49e913fa23d8f8819300243e9..db8f63841b4265922b5a630c020e00cb4f490ad3 100644 (file)
@@ -101,7 +101,7 @@ static void gmux_pio_write32(struct apple_gmux_data *gmux_data, int port,
 
        for (i = 0; i < 4; i++) {
                tmpval = (val >> (i * 8)) & 0xff;
-               outb(tmpval, port + i);
+               outb(tmpval, gmux_data->iostart + port + i);
        }
 }
 
@@ -142,8 +142,9 @@ static u8 gmux_index_read8(struct apple_gmux_data *gmux_data, int port)
        u8 val;
 
        mutex_lock(&gmux_data->index_lock);
-       outb((port & 0xff), gmux_data->iostart + GMUX_PORT_READ);
        gmux_index_wait_ready(gmux_data);
+       outb((port & 0xff), gmux_data->iostart + GMUX_PORT_READ);
+       gmux_index_wait_complete(gmux_data);
        val = inb(gmux_data->iostart + GMUX_PORT_VALUE);
        mutex_unlock(&gmux_data->index_lock);
 
@@ -166,8 +167,9 @@ static u32 gmux_index_read32(struct apple_gmux_data *gmux_data, int port)
        u32 val;
 
        mutex_lock(&gmux_data->index_lock);
-       outb((port & 0xff), gmux_data->iostart + GMUX_PORT_READ);
        gmux_index_wait_ready(gmux_data);
+       outb((port & 0xff), gmux_data->iostart + GMUX_PORT_READ);
+       gmux_index_wait_complete(gmux_data);
        val = inl(gmux_data->iostart + GMUX_PORT_VALUE);
        mutex_unlock(&gmux_data->index_lock);
 
@@ -461,18 +463,22 @@ static int __devinit gmux_probe(struct pnp_dev *pnp,
        ver_release = gmux_read8(gmux_data, GMUX_PORT_VERSION_RELEASE);
        if (ver_major == 0xff && ver_minor == 0xff && ver_release == 0xff) {
                if (gmux_is_indexed(gmux_data)) {
+                       u32 version;
                        mutex_init(&gmux_data->index_lock);
                        gmux_data->indexed = true;
+                       version = gmux_read32(gmux_data,
+                               GMUX_PORT_VERSION_MAJOR);
+                       ver_major = (version >> 24) & 0xff;
+                       ver_minor = (version >> 16) & 0xff;
+                       ver_release = (version >> 8) & 0xff;
                } else {
                        pr_info("gmux device not present\n");
                        ret = -ENODEV;
                        goto err_release;
                }
-               pr_info("Found indexed gmux\n");
-       } else {
-               pr_info("Found gmux version %d.%d.%d\n", ver_major, ver_minor,
-                       ver_release);
        }
+       pr_info("Found gmux version %d.%d.%d [%s]\n", ver_major, ver_minor,
+               ver_release, (gmux_data->indexed ? "indexed" : "classic"));
 
        memset(&props, 0, sizeof(props));
        props.type = BACKLIGHT_PLATFORM;
@@ -505,9 +511,7 @@ static int __devinit gmux_probe(struct pnp_dev *pnp,
         * Disable the other backlight choices.
         */
        acpi_video_dmi_promote_vendor();
-#if defined (CONFIG_ACPI_VIDEO) || defined (CONFIG_ACPI_VIDEO_MODULE)
        acpi_video_unregister();
-#endif
        apple_bl_unregister();
 
        gmux_data->power_state = VGA_SWITCHEROO_ON;
@@ -593,9 +597,7 @@ static void __devexit gmux_remove(struct pnp_dev *pnp)
        kfree(gmux_data);
 
        acpi_video_dmi_demote_vendor();
-#if defined (CONFIG_ACPI_VIDEO) || defined (CONFIG_ACPI_VIDEO_MODULE)
        acpi_video_register();
-#endif
        apple_bl_register();
 }
 
index e38f91be0b10964c12f6a9b8eb4347908fc54d94..4b568df56643f846de78a3228582342fb3a89c67 100644 (file)
@@ -85,7 +85,7 @@ static char *wled_type = "unknown";
 static char *bled_type = "unknown";
 
 module_param(wled_type, charp, 0444);
-MODULE_PARM_DESC(wlan_status, "Set the wled type on boot "
+MODULE_PARM_DESC(wled_type, "Set the wled type on boot "
                 "(unknown, led or rfkill). "
                 "default is unknown");
 
@@ -863,9 +863,9 @@ static ssize_t show_infos(struct device *dev,
         * The significance of others is yet to be found.
         * If we don't find the method, we assume the device are present.
         */
-       rv = acpi_evaluate_integer(asus->handle, "HRWS", NULL, &temp);
+       rv = acpi_evaluate_integer(asus->handle, "HWRS", NULL, &temp);
        if (!ACPI_FAILURE(rv))
-               len += sprintf(page + len, "HRWS value         : %#x\n",
+               len += sprintf(page + len, "HWRS value         : %#x\n",
                               (uint) temp);
        /*
         * Another value for userspace: the ASYM method returns 0x02 for
@@ -1751,9 +1751,9 @@ static int asus_laptop_get_info(struct asus_laptop *asus)
         * The significance of others is yet to be found.
         */
        status =
-           acpi_evaluate_integer(asus->handle, "HRWS", NULL, &hwrs_result);
+           acpi_evaluate_integer(asus->handle, "HWRS", NULL, &hwrs_result);
        if (!ACPI_FAILURE(status))
-               pr_notice("  HRWS returned %x", (int)hwrs_result);
+               pr_notice("  HWRS returned %x", (int)hwrs_result);
 
        if (!acpi_check_handle(asus->handle, METHOD_WL_STATUS, NULL))
                asus->have_rsts = true;
index 2eb9fe8e8efd038c7bb1d25ad4fbde2961ca8e1a..c0e9ff489b2417f2469e7abc7d2289e4b971c8a2 100644 (file)
@@ -47,9 +47,7 @@
 #include <linux/thermal.h>
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
-#ifdef CONFIG_ACPI_VIDEO
 #include <acpi/video.h>
-#endif
 
 #include "asus-wmi.h"
 
@@ -1704,10 +1702,8 @@ static int asus_wmi_add(struct platform_device *pdev)
        if (asus->driver->quirks->wmi_backlight_power)
                acpi_video_dmi_promote_vendor();
        if (!acpi_video_backlight_support()) {
-#ifdef CONFIG_ACPI_VIDEO
                pr_info("Disabling ACPI video driver\n");
                acpi_video_unregister();
-#endif
                err = asus_wmi_backlight_init(asus);
                if (err && err != -ENODEV)
                        goto fail_backlight;
index dab91b48d22cf5fbb955efd7ecb5fc0f6fa318c1..5ca264179f4e32a758102b0a05f865164250534b 100644 (file)
@@ -610,12 +610,12 @@ static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc, acpi_handle handle)
 
                if (!bus) {
                        pr_warn("Unable to find PCI bus 1?\n");
-                       goto out_unlock;
+                       goto out_put_dev;
                }
 
                if (pci_bus_read_config_dword(bus, 0, PCI_VENDOR_ID, &l)) {
                        pr_err("Unable to read PCI config space?\n");
-                       goto out_unlock;
+                       goto out_put_dev;
                }
 
                absent = (l == 0xffffffff);
@@ -627,7 +627,7 @@ static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc, acpi_handle handle)
                                absent ? "absent" : "present");
                        pr_warn("skipped wireless hotplug as probably "
                                "inappropriate for this model\n");
-                       goto out_unlock;
+                       goto out_put_dev;
                }
 
                if (!blocked) {
@@ -635,7 +635,7 @@ static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc, acpi_handle handle)
                        if (dev) {
                                /* Device already present */
                                pci_dev_put(dev);
-                               goto out_unlock;
+                               goto out_put_dev;
                        }
                        dev = pci_scan_single_device(bus, 0);
                        if (dev) {
@@ -650,6 +650,8 @@ static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc, acpi_handle handle)
                                pci_dev_put(dev);
                        }
                }
+out_put_dev:
+               pci_dev_put(port);
        }
 
 out_unlock:
index c1ca7bcebb66b52bfb033fc24cc0bc2856bd313d..dd90d15f52101e24296b30523d68056e01bac7df 100644 (file)
@@ -26,9 +26,7 @@
 #include <linux/seq_file.h>
 #include <linux/debugfs.h>
 #include <linux/ctype.h>
-#ifdef CONFIG_ACPI_VIDEO
 #include <acpi/video.h>
-#endif
 
 /*
  * This driver is needed because a number of Samsung laptops do not hook
@@ -1558,9 +1556,7 @@ static int __init samsung_init(void)
                samsung->handle_backlight = false;
        } else if (samsung->quirks->broken_acpi_video) {
                pr_info("Disabling ACPI video driver\n");
-#ifdef CONFIG_ACPI_VIDEO
                acpi_video_unregister();
-#endif
        }
 #endif
 
index 80e377949314ba37b3f00f09655290ed062349ed..52daaa816e53691792b6071955dbe680c4721b91 100644 (file)
@@ -545,7 +545,7 @@ TPACPI_HANDLE(hkey, ec, "\\_SB.HKEY",       /* 600e/x, 770e, 770x */
  */
 
 static int acpi_evalf(acpi_handle handle,
-                     void *res, char *method, char *fmt, ...)
+                     int *res, char *method, char *fmt, ...)
 {
        char *fmt0 = fmt;
        struct acpi_object_list params;
@@ -606,7 +606,7 @@ static int acpi_evalf(acpi_handle handle,
                success = (status == AE_OK &&
                           out_obj.type == ACPI_TYPE_INTEGER);
                if (success && res)
-                       *(int *)res = out_obj.integer.value;
+                       *res = out_obj.integer.value;
                break;
        case 'v':               /* void */
                success = status == AE_OK;
@@ -7386,17 +7386,18 @@ static int fan_get_status(u8 *status)
         * Add TPACPI_FAN_RD_ACPI_FANS ? */
 
        switch (fan_status_access_mode) {
-       case TPACPI_FAN_RD_ACPI_GFAN:
+       case TPACPI_FAN_RD_ACPI_GFAN: {
                /* 570, 600e/x, 770e, 770x */
+               int res;
 
-               if (unlikely(!acpi_evalf(gfan_handle, &s, NULL, "d")))
+               if (unlikely(!acpi_evalf(gfan_handle, &res, NULL, "d")))
                        return -EIO;
 
                if (likely(status))
-                       *status = s & 0x07;
+                       *status = res & 0x07;
 
                break;
-
+       }
        case TPACPI_FAN_RD_TPEC:
                /* all except 570, 600e/x, 770e, 770x */
                if (unlikely(!acpi_ec_read(fan_status_offset, &s)))
index 0b66d0f259224f9e7ca679a2759a473708cd3be6..4b6688909fee076c5573e086b972b7b3cf5ebffc 100644 (file)
@@ -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;
 }
index c3756d1be19496fdf3dd163787b7e289e9ad70bd..b1996bcd5b788fd8923ef646b828d71dbc769265 100644 (file)
@@ -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 = {
index 6caa222af77a284f09f1e8a5f634da794dd84838..ab00cab905b730459c6e752907f1139aaec9ee57 100644 (file)
@@ -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;
 }
index 590cfafc7c172ce8a2d3230de12057a85dfaa7d0..1859f71372e24912203dca245f3d60c71c80a35d 100644 (file)
@@ -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);
index c5d06fe83bba6274f2e6b944a43489395e04e01c..9277d945bf4853d136ec483036be8cd0cf6f06b3 100644 (file)
@@ -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)
index 15370a2c5ff0b29e5286a9ffb2660beefd045f2e..0595c763dafd687ac3938f803618eed679549d76 100644 (file)
@@ -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)
index 157defe5e0693c06c6432ddfbd65d0f6632a6f90..6b556995bb33e9baf98663175973bbb69805522d 100644 (file)
@@ -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);
index 2fb2b9ea97ecc11d7e60af84d756b9eaad8dfbed..c48c72abbefc640671af73090536bd206b1c95dc 100644 (file)
@@ -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);
index ed25c8740a9ce4b0bb8e8334a32b72abc08655ae..fc916f5d731412c7146465d3ff29277979b69189 100644 (file)
@@ -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;
index 33d6630529ded9b8db625a1ca4545c6fdb2472b3..91eec60252ee1c973198ae5c230762af37607073 100644 (file)
@@ -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 =
index 796482badf13acfe91f4391822d90cd6339d9ffc..2b4261cb77424b52046d6e4c255f32f3359bbf2a 100644 (file)
@@ -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;
index dc27598785e5d781ff9790697f8b3a5960921d85..ed38454228c626bdabbea4d4265b22dfbc637864 100644 (file)
@@ -4066,7 +4066,6 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
        spin_lock_init(&instance->cmd_pool_lock);
        spin_lock_init(&instance->hba_lock);
        spin_lock_init(&instance->completion_lock);
-       spin_lock_init(&poll_aen_lock);
 
        mutex_init(&instance->aen_mutex);
        mutex_init(&instance->reset_mutex);
@@ -5392,6 +5391,8 @@ static int __init megasas_init(void)
        printk(KERN_INFO "megasas: %s %s\n", MEGASAS_VERSION,
               MEGASAS_EXT_VERSION);
 
+       spin_lock_init(&poll_aen_lock);
+
        support_poll_for_event = 2;
        support_device_change = 1;
 
index 9d46fcbe7755fd2aa258e3de91c5a8cd76e3079c..9d5a56c4b3321deea9b9001468755d222fa13b51 100644 (file)
@@ -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 "
@@ -2424,10 +2431,13 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc,  int sleep_flag)
        }
 
        /* command line tunables  for max controller queue depth */
-       if (max_queue_depth != -1)
-               max_request_credit = (max_queue_depth < facts->RequestCredit)
-                   ? max_queue_depth : facts->RequestCredit;
-       else
+       if (max_queue_depth != -1 && max_queue_depth != 0) {
+               max_request_credit = min_t(u16, max_queue_depth +
+                       ioc->hi_priority_depth + ioc->internal_depth,
+                       facts->RequestCredit);
+               if (max_request_credit > MAX_HBA_QUEUE_DEPTH)
+                       max_request_credit =  MAX_HBA_QUEUE_DEPTH;
+       } else
                max_request_credit = min_t(u16, facts->RequestCredit,
                    MAX_HBA_QUEUE_DEPTH);
 
@@ -2502,7 +2512,7 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc,  int sleep_flag)
        /* set the scsi host can_queue depth
         * with some internal commands that could be outstanding
         */
-       ioc->shost->can_queue = ioc->scsiio_depth - (2);
+       ioc->shost->can_queue = ioc->scsiio_depth;
        dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "scsi host: "
            "can_queue depth (%d)\n", ioc->name, ioc->shost->can_queue));
 
index 4a6381c87253ec4be307eb47dc8d1ff6ebad4dc3..de2337f255a74ff02888f67e1d202766f257930a 100644 (file)
@@ -42,6 +42,8 @@
 
 #include <trace/events/scsi.h>
 
+static void scsi_eh_done(struct scsi_cmnd *scmd);
+
 #define SENSE_TIMEOUT          (10*HZ)
 
 /*
@@ -241,6 +243,14 @@ static int scsi_check_sense(struct scsi_cmnd *scmd)
        if (! scsi_command_normalize_sense(scmd, &sshdr))
                return FAILED;  /* no valid sense data */
 
+       if (scmd->cmnd[0] == TEST_UNIT_READY && scmd->scsi_done != scsi_eh_done)
+               /*
+                * nasty: for mid-layer issued TURs, we need to return the
+                * actual sense data without any recovery attempt.  For eh
+                * issued ones, we need to try to recover and interpret
+                */
+               return SUCCESS;
+
        if (scsi_sense_is_deferred(&sshdr))
                return NEEDS_RETRY;
 
index ffd77739ae3e2bc4bf793fe7b4bb0ed37c3ca8f4..faa790fba1347fc61b0869015e2a28bad4f113f2 100644 (file)
@@ -776,7 +776,6 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
        }
 
        if (req->cmd_type == REQ_TYPE_BLOCK_PC) { /* SG_IO ioctl from block level */
-               req->errors = result;
                if (result) {
                        if (sense_valid && req->sense) {
                                /*
@@ -792,6 +791,10 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
                        if (!sense_deferred)
                                error = __scsi_error_from_host_byte(cmd, result);
                }
+               /*
+                * __scsi_error_from_host_byte may have reset the host_byte
+                */
+               req->errors = cmd->result;
 
                req->resid_len = scsi_get_resid(cmd);
 
index 56a93794c470ae99d603426f15eaccb1dd3ae727..d947ffc20ceba301eaaf45973fee97dfba7fb7f7 100644 (file)
@@ -764,6 +764,16 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result,
        sdev->model = (char *) (sdev->inquiry + 16);
        sdev->rev = (char *) (sdev->inquiry + 32);
 
+       if (strncmp(sdev->vendor, "ATA     ", 8) == 0) {
+               /*
+                * sata emulation layer device.  This is a hack to work around
+                * the SATL power management specifications which state that
+                * when the SATL detects the device has gone into standby
+                * mode, it shall respond with NOT READY.
+                */
+               sdev->allow_restart = 1;
+       }
+
        if (*bflags & BLIST_ISROM) {
                sdev->type = TYPE_ROM;
                sdev->removable = 1;
index c7030fbee79c254ace6a41eed0a88e6b968e6bfb..3e79a2f0004279d0b2b1175281d003a664d5aeee 100644 (file)
@@ -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;
 }
index 32c26d795ed06d3a58c43bf3d295d8f75dcf676f..8f32a1323a79dd40e6e91433fa38e15709a3ca02 100644 (file)
@@ -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");
index 2804eaae804e7279aedb64f52066e380212a2176..a3ac39b79192a4c8f2de0d063054f5477a1f257a 100644 (file)
@@ -211,7 +211,8 @@ static int sh_pfc_gpio_request_enable(struct pinctrl_dev *pctldev,
                break;
        default:
                pr_err("Unsupported mux type (%d), bailing...\n", pinmux_type);
-               return -ENOTSUPP;
+               ret = -ENOTSUPP;
+               goto err;
        }
 
        ret = 0;
index d0cafd6371996c75e3ee094b2be3168ad14d38b7..f2ffd963f1c348e3986f761b1d2d2b7b75b361e2 100644 (file)
@@ -51,10 +51,12 @@ enum android_alarm_return_flags {
 #define ANDROID_ALARM_WAIT                  _IO('a', 1)
 
 #define ALARM_IOW(c, type, size)            _IOW('a', (c) | ((type) << 4), size)
+#define ALARM_IOR(c, type, size)            _IOR('a', (c) | ((type) << 4), size)
+
 /* Set alarm */
 #define ANDROID_ALARM_SET(type)             ALARM_IOW(2, type, struct timespec)
 #define ANDROID_ALARM_SET_AND_WAIT(type)    ALARM_IOW(3, type, struct timespec)
-#define ANDROID_ALARM_GET_TIME(type)        ALARM_IOW(4, type, struct timespec)
+#define ANDROID_ALARM_GET_TIME(type)        ALARM_IOR(4, type, struct timespec)
 #define ANDROID_ALARM_SET_RTC               _IOW('a', 5, struct timespec)
 #define ANDROID_ALARM_BASE_CMD(cmd)         (cmd & ~(_IOC(0, 0, 0xf0, 0)))
 #define ANDROID_ALARM_IOCTL_TO_TYPE(cmd)    (_IOC_NR(cmd) >> 4)
index 6c81e377262c204ca8a9354743f344ff824267d5..cc8931fde839c491455ed10beaa56529480fbe2d 100644 (file)
@@ -1412,6 +1412,13 @@ static int __devinit dio200_attach_pci(struct comedi_device *dev,
                dev_err(dev->class_dev, "BUG! cannot determine board type!\n");
                return -EINVAL;
        }
+       /*
+        * Need to 'get' the PCI device to match the 'put' in dio200_detach().
+        * TODO: Remove the pci_dev_get() and matching pci_dev_put() once
+        * support for manual attachment of PCI devices via dio200_attach()
+        * has been removed.
+        */
+       pci_dev_get(pci_dev);
        return dio200_pci_common_attach(dev, pci_dev);
 }
 
index aabba9886b7d9276eb1c4233c89ce894685fbd58..f50287903038bb22772c1c99522c69078fc638c0 100644 (file)
@@ -565,6 +565,13 @@ static int __devinit pc236_attach_pci(struct comedi_device *dev,
                dev_err(dev->class_dev, "BUG! cannot determine board type!\n");
                return -EINVAL;
        }
+       /*
+        * Need to 'get' the PCI device to match the 'put' in pc236_detach().
+        * TODO: Remove the pci_dev_get() and matching pci_dev_put() once
+        * support for manual attachment of PCI devices via pc236_attach()
+        * has been removed.
+        */
+       pci_dev_get(pci_dev);
        return pc236_pci_common_attach(dev, pci_dev);
 }
 
index 40ec1ffebba651fda62f23af21ff7b0e3ef097a4..8191c4e28e0a6849fb53e7def7b4fc1639c79c09 100644 (file)
@@ -298,6 +298,13 @@ static int __devinit pc263_attach_pci(struct comedi_device *dev,
                dev_err(dev->class_dev, "BUG! cannot determine board type!\n");
                return -EINVAL;
        }
+       /*
+        * Need to 'get' the PCI device to match the 'put' in pc263_detach().
+        * TODO: Remove the pci_dev_get() and matching pci_dev_put() once
+        * support for manual attachment of PCI devices via pc263_attach()
+        * has been removed.
+        */
+       pci_dev_get(pci_dev);
        return pc263_pci_common_attach(dev, pci_dev);
 }
 
index 4e17f13e57f6530b2bc3cfd1afc4485d0940d880..8bf109e7bb05cef4c9c50669314289cde734c47c 100644 (file)
@@ -1503,6 +1503,13 @@ pci224_attach_pci(struct comedi_device *dev, struct pci_dev *pci_dev)
                        DRIVER_NAME ": BUG! cannot determine board type!\n");
                return -EINVAL;
        }
+       /*
+        * Need to 'get' the PCI device to match the 'put' in pci224_detach().
+        * TODO: Remove the pci_dev_get() and matching pci_dev_put() once
+        * support for manual attachment of PCI devices via pci224_attach()
+        * has been removed.
+        */
+       pci_dev_get(pci_dev);
        return pci224_attach_common(dev, pci_dev, NULL);
 }
 
index 1b67d0c61fa72ff782e02a09dc63b2c14ec5982c..66e74bd12267a565263556f8e6f3389b2c6c41b9 100644 (file)
@@ -2925,6 +2925,13 @@ static int __devinit pci230_attach_pci(struct comedi_device *dev,
                        "amplc_pci230: BUG! cannot determine board type!\n");
                return -EINVAL;
        }
+       /*
+        * Need to 'get' the PCI device to match the 'put' in pci230_detach().
+        * TODO: Remove the pci_dev_get() and matching pci_dev_put() once
+        * support for manual attachment of PCI devices via pci230_attach()
+        * has been removed.
+        */
+       pci_dev_get(pci_dev);
        return pci230_attach_common(dev, pci_dev);
 }
 
index 874e02e47668e60a024b350a72822894be801f1a..67a914a10b55fb2333c9ec747ccd907084fc7b6d 100644 (file)
@@ -378,7 +378,7 @@ das08jr_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
        int chan;
 
        lsb = data[0] & 0xff;
-       msb = (data[0] >> 8) & 0xf;
+       msb = (data[0] >> 8) & 0xff;
 
        chan = CR_CHAN(insn->chanspec);
 
@@ -623,7 +623,7 @@ static const struct das08_board_struct das08_boards[] = {
                .ai = das08_ai_rinsn,
                .ai_nbits = 16,
                .ai_pg = das08_pg_none,
-               .ai_encoding = das08_encode12,
+               .ai_encoding = das08_encode16,
                .ao = das08jr_ao_winsn,
                .ao_nbits = 16,
                .di = das08jr_di_rbits,
@@ -922,6 +922,13 @@ das08_attach_pci(struct comedi_device *dev, struct pci_dev *pdev)
                dev_err(dev->class_dev, "BUG! cannot determine board type!\n");
                return -EINVAL;
        }
+       /*
+        * Need to 'get' the PCI device to match the 'put' in das08_detach().
+        * TODO: Remove the pci_dev_get() and matching pci_dev_put() once
+        * support for manual attachment of PCI devices via das08_attach()
+        * has been removed.
+        */
+       pci_dev_get(pdev);
        return das08_pci_attach_common(dev, pdev);
 }
 
index 18d108fd967a908817efa70d1056fcba35d00458..f3da59063ed2e5a8c934ed201f1add435810028a 100644 (file)
@@ -121,8 +121,10 @@ static int lis3l02dq_get_buffer_element(struct iio_dev *indio_dev,
        if (rx_array == NULL)
                return -ENOMEM;
        ret = lis3l02dq_read_all(indio_dev, rx_array);
-       if (ret < 0)
+       if (ret < 0) {
+               kfree(rx_array);
                return ret;
+       }
        for (i = 0; i < scan_count; i++)
                data[i] = combine_8_to_16(rx_array[i*4+1],
                                        rx_array[i*4+3]);
index 095837285f4fb25732b8986f3d6d25458a9a11a2..19a064d649e3f72a783dd2b2ffc2e6a385175216 100644 (file)
@@ -647,6 +647,8 @@ static ssize_t ad7192_write_frequency(struct device *dev,
        ret = strict_strtoul(buf, 10, &lval);
        if (ret)
                return ret;
+       if (lval == 0)
+               return -EINVAL;
 
        mutex_lock(&indio_dev->mlock);
        if (iio_buffer_enabled(indio_dev)) {
index 93aa431287ac6efb17d9b5172c337f67be30365a..eb8e9d69efd3f39ab42a788f70c8eb1d4b105bf2 100644 (file)
@@ -195,6 +195,8 @@ static ssize_t adis16260_write_frequency(struct device *dev,
        ret = strict_strtol(buf, 10, &val);
        if (ret)
                return ret;
+       if (val == 0)
+               return -EINVAL;
 
        mutex_lock(&indio_dev->mlock);
        if (spi_get_device_id(st->us)) {
index 1f4c17779b5a64e18f48865aa6ecb0e6d49387f4..a618327e06edf2c3374b38b425771b4a823517f2 100644 (file)
@@ -234,6 +234,8 @@ static ssize_t adis16400_write_frequency(struct device *dev,
        ret = strict_strtol(buf, 10, &val);
        if (ret)
                return ret;
+       if (val == 0)
+               return -EINVAL;
 
        mutex_lock(&indio_dev->mlock);
 
index f04ece7fbc2fbe3d33b61dd3387e1cb0b53b23c5..3ccff189f258232cd4704acc2d8674029cf190b1 100644 (file)
@@ -425,6 +425,8 @@ static ssize_t ade7753_write_frequency(struct device *dev,
        ret = strict_strtol(buf, 10, &val);
        if (ret)
                return ret;
+       if (val == 0)
+               return -EINVAL;
 
        mutex_lock(&indio_dev->mlock);
 
index 6cee28a5e87731bee476ab4efc7c0501c89cff45..abb1e9c8d0947adcd1bc6d5567b9620496207c5e 100644 (file)
@@ -445,6 +445,8 @@ static ssize_t ade7754_write_frequency(struct device *dev,
        ret = strict_strtol(buf, 10, &val);
        if (ret)
                return ret;
+       if (val == 0)
+               return -EINVAL;
 
        mutex_lock(&indio_dev->mlock);
 
index b3f7e0fa96124b6ce8d719d63fce6e45df210d0f..eb0a2a98f3886afe1948b284c2ede98094a95754 100644 (file)
@@ -385,6 +385,8 @@ static ssize_t ade7759_write_frequency(struct device *dev,
        ret = strict_strtol(buf, 10, &val);
        if (ret)
                return ret;
+       if (val == 0)
+               return -EINVAL;
 
        mutex_lock(&indio_dev->mlock);
 
index 695ea35f75b0831cc8e2d28369d9ef124f8c2da9..d0a7e408efe93847606d1db21397fab44aba1ae6 100644 (file)
@@ -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");
 
index 5e2856c0e0bbf3ead714ca105d06e54e1dff1545..55e9c865585058e9195e3eeef9aa8c554b57c886 100644 (file)
@@ -48,13 +48,20 @@ static inline void copy_timings_omap_to_drm(struct drm_display_mode *mode,
        mode->vsync_end = mode->vsync_start + timings->vsw;
        mode->vtotal = mode->vsync_end + timings->vbp;
 
-       /* note: whether or not it is interlaced, +/- h/vsync, etc,
-        * which should be set in the mode flags, is not exposed in
-        * the omap_video_timings struct.. but hdmi driver tracks
-        * those separately so all we have to have to set the mode
-        * is the way to recover these timings values, and the
-        * omap_dss_driver would do the rest.
-        */
+       mode->flags = 0;
+
+       if (timings->interlace)
+               mode->flags |= DRM_MODE_FLAG_INTERLACE;
+
+       if (timings->hsync_level == OMAPDSS_SIG_ACTIVE_HIGH)
+               mode->flags |= DRM_MODE_FLAG_PHSYNC;
+       else
+               mode->flags |= DRM_MODE_FLAG_NHSYNC;
+
+       if (timings->vsync_level == OMAPDSS_SIG_ACTIVE_HIGH)
+               mode->flags |= DRM_MODE_FLAG_PVSYNC;
+       else
+               mode->flags |= DRM_MODE_FLAG_NVSYNC;
 }
 
 static inline void copy_timings_drm_to_omap(struct omap_video_timings *timings,
@@ -71,6 +78,22 @@ static inline void copy_timings_drm_to_omap(struct omap_video_timings *timings,
        timings->vfp = mode->vsync_start - mode->vdisplay;
        timings->vsw = mode->vsync_end - mode->vsync_start;
        timings->vbp = mode->vtotal - mode->vsync_end;
+
+       timings->interlace = !!(mode->flags & DRM_MODE_FLAG_INTERLACE);
+
+       if (mode->flags & DRM_MODE_FLAG_PHSYNC)
+               timings->hsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
+       else
+               timings->hsync_level = OMAPDSS_SIG_ACTIVE_LOW;
+
+       if (mode->flags & DRM_MODE_FLAG_PVSYNC)
+               timings->vsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
+       else
+               timings->vsync_level = OMAPDSS_SIG_ACTIVE_LOW;
+
+       timings->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
+       timings->de_level = OMAPDSS_SIG_ACTIVE_HIGH;
+       timings->sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES;
 }
 
 static void omap_connector_dpms(struct drm_connector *connector, int mode)
@@ -187,7 +210,7 @@ static int omap_connector_get_modes(struct drm_connector *connector)
                }
        } else {
                struct drm_display_mode *mode = drm_mode_create(dev);
-               struct omap_video_timings timings;
+               struct omap_video_timings timings = {0};
 
                dssdrv->get_timings(dssdev, &timings);
 
@@ -291,7 +314,7 @@ void omap_connector_mode_set(struct drm_connector *connector,
        struct omap_connector *omap_connector = to_omap_connector(connector);
        struct omap_dss_device *dssdev = omap_connector->dssdev;
        struct omap_dss_driver *dssdrv = dssdev->driver;
-       struct omap_video_timings timings;
+       struct omap_video_timings timings = {0};
 
        copy_timings_drm_to_omap(&timings, mode);
 
index d98321945802c8daf8ec71cc3908ec0c44133c7a..758ce0a8d82e03c59d326b5ce0f6b8bdda425b25 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/cdev.h>
 #include <linux/uaccess.h>
 #include <linux/netdevice.h>
+#include <linux/etherdevice.h>
 #include <linux/poll.h>
 #include <linux/sched.h>
 #include "ozconfig.h"
@@ -213,7 +214,7 @@ static int oz_set_active_pd(u8 *addr)
                if (old_pd)
                        oz_pd_put(old_pd);
        } else {
-               if (!memcmp(addr, "\0\0\0\0\0\0", sizeof(addr))) {
+               if (is_zero_ether_addr(addr)) {
                        spin_lock_bh(&g_cdev.lock);
                        pd = g_cdev.active_pd;
                        g_cdev.active_pd = 0;
index 0e26d5f6cf2d57d64eca7d5440af7da0f77443cd..495ee1205e02a9c77aa59a1e7ec5da1cf255d534 100644 (file)
@@ -117,13 +117,8 @@ void r8712_recv_indicatepkt(struct _adapter *padapter,
        if (skb == NULL)
                goto _recv_indicatepkt_drop;
        skb->data = precv_frame->u.hdr.rx_data;
-#ifdef NET_SKBUFF_DATA_USES_OFFSET
-       skb->tail = (sk_buff_data_t)(precv_frame->u.hdr.rx_tail -
-                    precv_frame->u.hdr.rx_head);
-#else
-       skb->tail = (sk_buff_data_t)precv_frame->u.hdr.rx_tail;
-#endif
        skb->len = precv_frame->u.hdr.len;
+       skb_set_tail_pointer(skb, skb->len);
        if ((pattrib->tcpchk_valid == 1) && (pattrib->tcp_chkrpt == 1))
                skb->ip_summed = CHECKSUM_UNNECESSARY;
        else
index e4bdf2a2b5829292e23d8f4675fab023249e16d3..3aa895ec6507f7dde81f1440b4af349e792dc1cd 100644 (file)
@@ -200,7 +200,7 @@ s_vProcessRxMACHeader (
     } else if (!compare_ether_addr(pbyRxBuffer, &pDevice->abySNAP_RFC1042[0])) {
         cbHeaderSize += 6;
         pwType = (PWORD) (pbyRxBufferAddr + cbHeaderSize);
-       if ((*pwType == cpu_to_le16(ETH_P_IPX)) ||
+       if ((*pwType == cpu_to_be16(ETH_P_IPX)) ||
            (*pwType == cpu_to_le16(0xF380))) {
                cbHeaderSize -= 8;
             pwType = (PWORD) (pbyRxBufferAddr + cbHeaderSize);
index bb464527fc1b06e8814b05c23c97e89208cda92e..b6e04e7b629bdc0a63a04ac4f47698abed3cece8 100644 (file)
@@ -1699,7 +1699,7 @@ s_bPacketToWirelessUsb(
     // 802.1H
     if (ntohs(psEthHeader->wType) > ETH_DATA_LEN) {
        if (pDevice->dwDiagRefCount == 0) {
-               if ((psEthHeader->wType == cpu_to_le16(ETH_P_IPX)) ||
+               if ((psEthHeader->wType == cpu_to_be16(ETH_P_IPX)) ||
                    (psEthHeader->wType == cpu_to_le16(0xF380))) {
                        memcpy((PBYTE) (pbyPayloadHead),
                               abySNAP_Bridgetunnel, 6);
@@ -2838,10 +2838,10 @@ int nsDMA_tx_packet(PSDevice pDevice, unsigned int uDMAIdx, struct sk_buff *skb)
     Packet_Type = skb->data[ETH_HLEN+1];
     Descriptor_type = skb->data[ETH_HLEN+1+1+2];
     Key_info = (skb->data[ETH_HLEN+1+1+2+1] << 8)|(skb->data[ETH_HLEN+1+1+2+2]);
-    if (pDevice->sTxEthHeader.wType == cpu_to_le16(ETH_P_PAE)) {
-       /* 802.1x OR eapol-key challenge frame transfer */
-       if (((Protocol_Version == 1) || (Protocol_Version == 2)) &&
-               (Packet_Type == 3)) {
+       if (pDevice->sTxEthHeader.wType == cpu_to_be16(ETH_P_PAE)) {
+               /* 802.1x OR eapol-key challenge frame transfer */
+               if (((Protocol_Version == 1) || (Protocol_Version == 2)) &&
+                       (Packet_Type == 3)) {
                         bTxeapol_key = TRUE;
                        if(!(Key_info & BIT3) &&  //WPA or RSN group-key challenge
                           (Key_info & BIT8) && (Key_info & BIT9)) {    //send 2/2 key
@@ -2987,19 +2987,19 @@ int nsDMA_tx_packet(PSDevice pDevice, unsigned int uDMAIdx, struct sk_buff *skb)
         }
     }
 
-    if (pDevice->sTxEthHeader.wType == cpu_to_le16(ETH_P_PAE)) {
-        if (pDevice->byBBType != BB_TYPE_11A) {
-            pDevice->wCurrentRate = RATE_1M;
-            pDevice->byACKRate = RATE_1M;
-            pDevice->byTopCCKBasicRate = RATE_1M;
-            pDevice->byTopOFDMBasicRate = RATE_6M;
-        } else {
-            pDevice->wCurrentRate = RATE_6M;
-            pDevice->byACKRate = RATE_6M;
-            pDevice->byTopCCKBasicRate = RATE_1M;
-            pDevice->byTopOFDMBasicRate = RATE_6M;
-        }
-    }
+       if (pDevice->sTxEthHeader.wType == cpu_to_be16(ETH_P_PAE)) {
+               if (pDevice->byBBType != BB_TYPE_11A) {
+                       pDevice->wCurrentRate = RATE_1M;
+                       pDevice->byACKRate = RATE_1M;
+                       pDevice->byTopCCKBasicRate = RATE_1M;
+                       pDevice->byTopOFDMBasicRate = RATE_6M;
+               } else {
+                       pDevice->wCurrentRate = RATE_6M;
+                       pDevice->byACKRate = RATE_6M;
+                       pDevice->byTopCCKBasicRate = RATE_1M;
+                       pDevice->byTopOFDMBasicRate = RATE_6M;
+               }
+       }
 
     DBG_PRT(MSG_LEVEL_DEBUG,
            KERN_INFO "dma_tx: pDevice->wCurrentRate = %d\n",
@@ -3015,7 +3015,7 @@ int nsDMA_tx_packet(PSDevice pDevice, unsigned int uDMAIdx, struct sk_buff *skb)
 
     if (bNeedEncryption == TRUE) {
         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ntohs Pkt Type=%04x\n", ntohs(pDevice->sTxEthHeader.wType));
-       if ((pDevice->sTxEthHeader.wType) == cpu_to_le16(ETH_P_PAE)) {
+       if ((pDevice->sTxEthHeader.wType) == cpu_to_be16(ETH_P_PAE)) {
                bNeedEncryption = FALSE;
             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Pkt Type=%04x\n", (pDevice->sTxEthHeader.wType));
             if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && (pMgmt->eCurrState == WMAC_STATE_ASSOC)) {
index fabff4d650ef8c5645ed26dfeb5a46e452d26c05..0970127344e60828e569e1ca87ee6c82cb3f11eb 100644 (file)
@@ -327,9 +327,9 @@ int prism2_get_station(struct wiphy *wiphy, struct net_device *dev,
        return result;
 }
 
-int prism2_scan(struct wiphy *wiphy, struct net_device *dev,
-               struct cfg80211_scan_request *request)
+int prism2_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
 {
+       struct net_device *dev = request->wdev->netdev;
        struct prism2_wiphy_private *priv = wiphy_priv(wiphy);
        wlandevice_t *wlandev = dev->ml_priv;
        struct p80211msg_dot11req_scan msg1;
index c214977b4ab48adec84fc260df0116b12b498aa7..52b43b7b83d7b3c9d7e3acfc853912afc64c2b61 100644 (file)
@@ -1251,13 +1251,12 @@ static int zcache_pampd_get_data_and_free(char *data, size_t *bufsize, bool raw,
                                        void *pampd, struct tmem_pool *pool,
                                        struct tmem_oid *oid, uint32_t index)
 {
-       int ret = 0;
-
        BUG_ON(!is_ephemeral(pool));
-       zbud_decompress((struct page *)(data), pampd);
+       if (zbud_decompress((struct page *)(data), pampd) < 0)
+               return -EINVAL;
        zbud_free_and_delist((struct zbud_hdr *)pampd);
        atomic_dec(&zcache_curr_eph_pampd_count);
-       return ret;
+       return 0;
 }
 
 /*
index 0694d9b1bce6a4e066a7bba1b1ef5f870b4b51d7..6aba4395e8d8ffd5aa950c4dfc745791c3f65fc2 100644 (file)
@@ -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);
        /*
index 91799973081a3d907cd260792df3f573d1dbec82..41641ba548286e9dbf33f45a02ece5b20eec0d14 100644 (file)
@@ -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);
 
        /*
index cf2c66f3c11690c81ca23e9fd2ce286e76b56e62..9fc9a6006ca082076a6d235dfad676e1e1a11ea9 100644 (file)
@@ -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;
index 76db75e836ede701c2aed6090a212fdf1a08ad10..9ba495477fd24f80bf6643cfae3707525b7c165e 100644 (file)
@@ -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;
index 1e946502c378886aa90bafc16239d2c34730b9fb..956c84c6b666498caabf7b60b7404413698c0b14 100644 (file)
@@ -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,
index 5552fa7426bc9b317da906dec2e395bbf854ae78..9d7ce3daa26275a7c08b831ae9b955382e0e9103 100644 (file)
@@ -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,
index 4c861de538c9ddb627356e8aa3ea992b164033cf..388a922c8f6de8f4f2a18f7bea85f5b3590b41a9 100644 (file)
@@ -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;
 }
index 4de3186dc44e99672d3666a24ec145e058183691..269f54488397bd2193bb80869bf9de8ac4c73bf2 100644 (file)
@@ -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;
@@ -1815,61 +1848,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;
index d5c689d6217e3a2eb46223fa1ffd01b77e15e0df..e309e8b0aaba0c10f0e45d72c57480000ed43d6b 100644 (file)
 #define  UCR4_OREN      (1<<1)  /* Receiver overrun interrupt enable */
 #define  UCR4_DREN      (1<<0)  /* Recv data ready interrupt enable */
 #define  UFCR_RXTL_SHF   0       /* Receiver trigger level shift */
+#define  UFCR_DCEDTE    (1<<6)  /* DCE/DTE mode select */
 #define  UFCR_RFDIV      (7<<7)  /* Reference freq divider mask */
 #define  UFCR_RFDIV_REG(x)     (((x) < 7 ? 6 - (x) : 6) << 7)
 #define  UFCR_TXTL_SHF   10      /* Transmitter trigger level shift */
@@ -667,22 +668,11 @@ static void imx_break_ctl(struct uart_port *port, int break_state)
 static int imx_setup_ufcr(struct imx_port *sport, unsigned int mode)
 {
        unsigned int val;
-       unsigned int ufcr_rfdiv;
-
-       /* set receiver / transmitter trigger level.
-        * RFDIV is set such way to satisfy requested uartclk value
-        */
-       val = TXTL << 10 | RXTL;
-       ufcr_rfdiv = (clk_get_rate(sport->clk_per) + sport->port.uartclk / 2)
-                       / sport->port.uartclk;
-
-       if(!ufcr_rfdiv)
-               ufcr_rfdiv = 1;
-
-       val |= UFCR_RFDIV_REG(ufcr_rfdiv);
 
+       /* set receiver / transmitter trigger level */
+       val = readl(sport->port.membase + UFCR) & (UFCR_RFDIV | UFCR_DCEDTE);
+       val |= TXTL << UFCR_TXTL_SHF | RXTL;
        writel(val, sport->port.membase + UFCR);
-
        return 0;
 }
 
@@ -754,6 +744,7 @@ static int imx_startup(struct uart_port *port)
                }
        }
 
+       spin_lock_irqsave(&sport->port.lock, flags);
        /*
         * Finally, clear and enable interrupts
         */
@@ -807,7 +798,6 @@ static int imx_startup(struct uart_port *port)
        /*
         * Enable modem status interrupts
         */
-       spin_lock_irqsave(&sport->port.lock,flags);
        imx_enable_ms(&sport->port);
        spin_unlock_irqrestore(&sport->port.lock,flags);
 
@@ -837,10 +827,13 @@ static void imx_shutdown(struct uart_port *port)
 {
        struct imx_port *sport = (struct imx_port *)port;
        unsigned long temp;
+       unsigned long flags;
 
+       spin_lock_irqsave(&sport->port.lock, flags);
        temp = readl(sport->port.membase + UCR2);
        temp &= ~(UCR2_TXEN);
        writel(temp, sport->port.membase + UCR2);
+       spin_unlock_irqrestore(&sport->port.lock, flags);
 
        if (USE_IRDA(sport)) {
                struct imxuart_platform_data *pdata;
@@ -869,12 +862,14 @@ static void imx_shutdown(struct uart_port *port)
         * Disable all interrupts, port and break condition.
         */
 
+       spin_lock_irqsave(&sport->port.lock, flags);
        temp = readl(sport->port.membase + UCR1);
        temp &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN);
        if (USE_IRDA(sport))
                temp &= ~(UCR1_IREN);
 
        writel(temp, sport->port.membase + UCR1);
+       spin_unlock_irqrestore(&sport->port.lock, flags);
 }
 
 static void
@@ -1217,6 +1212,9 @@ imx_console_write(struct console *co, const char *s, unsigned int count)
        struct imx_port *sport = imx_ports[co->index];
        struct imx_port_ucrs old_ucr;
        unsigned int ucr1;
+       unsigned long flags;
+
+       spin_lock_irqsave(&sport->port.lock, flags);
 
        /*
         *      First, save UCR1/2/3 and then disable interrupts
@@ -1242,6 +1240,8 @@ imx_console_write(struct console *co, const char *s, unsigned int count)
        while (!(readl(sport->port.membase + USR2) & USR2_TXDC));
 
        imx_port_ucrs_restore(&sport->port, &old_ucr);
+
+       spin_unlock_irqrestore(&sport->port.lock, flags);
 }
 
 /*
index c7a032a4f0c54b4aa975e4dbc3dba9ba43cabfc9..d214448b677e68d1eeff7847fea48bb46942f31f 100644 (file)
@@ -78,8 +78,7 @@ static inline int ep_to_bit(struct ci13xxx *ci, int n)
 }
 
 /**
- * hw_device_state: enables/disables interrupts & starts/stops device (execute
- *                  without interruption)
+ * hw_device_state: enables/disables interrupts (execute without interruption)
  * @dma: 0 => disable, !0 => enable and set dma engine
  *
  * This function returns an error code
@@ -91,9 +90,7 @@ static int hw_device_state(struct ci13xxx *ci, u32 dma)
                /* interrupt, error, port change, reset, sleep/suspend */
                hw_write(ci, OP_USBINTR, ~0,
                             USBi_UI|USBi_UEI|USBi_PCI|USBi_URI|USBi_SLI);
-               hw_write(ci, OP_USBCMD, USBCMD_RS, USBCMD_RS);
        } else {
-               hw_write(ci, OP_USBCMD, USBCMD_RS, 0);
                hw_write(ci, OP_USBINTR, ~0, 0);
        }
        return 0;
@@ -774,10 +771,7 @@ __acquires(mEp->lock)
 {
        struct ci13xxx_req *mReq, *mReqTemp;
        struct ci13xxx_ep *mEpTemp = mEp;
-       int uninitialized_var(retval);
-
-       if (list_empty(&mEp->qh.queue))
-               return -EINVAL;
+       int retval = 0;
 
        list_for_each_entry_safe(mReq, mReqTemp, &mEp->qh.queue,
                        queue) {
@@ -1420,6 +1414,21 @@ static int ci13xxx_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
        return -ENOTSUPP;
 }
 
+/* Change Data+ pullup status
+ * this func is used by usb_gadget_connect/disconnet
+ */
+static int ci13xxx_pullup(struct usb_gadget *_gadget, int is_on)
+{
+       struct ci13xxx *ci = container_of(_gadget, struct ci13xxx, gadget);
+
+       if (is_on)
+               hw_write(ci, OP_USBCMD, USBCMD_RS, USBCMD_RS);
+       else
+               hw_write(ci, OP_USBCMD, USBCMD_RS, 0);
+
+       return 0;
+}
+
 static int ci13xxx_start(struct usb_gadget *gadget,
                         struct usb_gadget_driver *driver);
 static int ci13xxx_stop(struct usb_gadget *gadget,
@@ -1432,6 +1441,7 @@ static int ci13xxx_stop(struct usb_gadget *gadget,
 static const struct usb_gadget_ops usb_gadget_ops = {
        .vbus_session   = ci13xxx_vbus_session,
        .wakeup         = ci13xxx_wakeup,
+       .pullup         = ci13xxx_pullup,
        .vbus_draw      = ci13xxx_vbus_draw,
        .udc_start      = ci13xxx_start,
        .udc_stop       = ci13xxx_stop,
@@ -1455,7 +1465,12 @@ static int init_eps(struct ci13xxx *ci)
 
                        mEp->ep.name      = mEp->name;
                        mEp->ep.ops       = &usb_ep_ops;
-                       mEp->ep.maxpacket = CTRL_PAYLOAD_MAX;
+                       /*
+                        * for ep0: maxP defined in desc, for other
+                        * eps, maxP is set by epautoconfig() called
+                        * by gadget layer
+                        */
+                       mEp->ep.maxpacket = (unsigned short)~0;
 
                        INIT_LIST_HEAD(&mEp->qh.queue);
                        mEp->qh.ptr = dma_pool_alloc(ci->qh_pool, GFP_KERNEL,
@@ -1475,6 +1490,7 @@ static int init_eps(struct ci13xxx *ci)
                                else
                                        ci->ep0in = mEp;
 
+                               mEp->ep.maxpacket = CTRL_PAYLOAD_MAX;
                                continue;
                        }
 
@@ -1484,6 +1500,17 @@ static int init_eps(struct ci13xxx *ci)
        return retval;
 }
 
+static void destroy_eps(struct ci13xxx *ci)
+{
+       int i;
+
+       for (i = 0; i < ci->hw_ep_max; i++) {
+               struct ci13xxx_ep *mEp = &ci->ci13xxx_ep[i];
+
+               dma_pool_free(ci->qh_pool, mEp->qh.ptr, mEp->qh.dma);
+       }
+}
+
 /**
  * ci13xxx_start: register a gadget driver
  * @gadget: our gadget
@@ -1691,7 +1718,7 @@ static int udc_start(struct ci13xxx *ci)
        if (ci->platdata->flags & CI13XXX_REQUIRE_TRANSCEIVER) {
                if (ci->transceiver == NULL) {
                        retval = -ENODEV;
-                       goto free_pools;
+                       goto destroy_eps;
                }
        }
 
@@ -1729,7 +1756,7 @@ static int udc_start(struct ci13xxx *ci)
 
 remove_trans:
        if (!IS_ERR_OR_NULL(ci->transceiver)) {
-               otg_set_peripheral(ci->transceiver->otg, &ci->gadget);
+               otg_set_peripheral(ci->transceiver->otg, NULL);
                if (ci->global_phy)
                        usb_put_phy(ci->transceiver);
        }
@@ -1742,6 +1769,8 @@ unreg_device:
 put_transceiver:
        if (!IS_ERR_OR_NULL(ci->transceiver) && ci->global_phy)
                usb_put_phy(ci->transceiver);
+destroy_eps:
+       destroy_eps(ci);
 free_pools:
        dma_pool_destroy(ci->td_pool);
 free_qh_pool:
@@ -1756,18 +1785,12 @@ free_qh_pool:
  */
 static void udc_stop(struct ci13xxx *ci)
 {
-       int i;
-
        if (ci == NULL)
                return;
 
        usb_del_gadget_udc(&ci->gadget);
 
-       for (i = 0; i < ci->hw_ep_max; i++) {
-               struct ci13xxx_ep *mEp = &ci->ci13xxx_ep[i];
-
-               dma_pool_free(ci->qh_pool, mEp->qh.ptr, mEp->qh.dma);
-       }
+       destroy_eps(ci);
 
        dma_pool_destroy(ci->td_pool);
        dma_pool_destroy(ci->qh_pool);
index 65a55abb791f53dd458f0b23c77af5497142ec6d..5f0cb417b736bb4b61c73afc52672029af59cbda 100644 (file)
@@ -109,12 +109,14 @@ static struct usb_driver wdm_driver;
 /* return intfdata if we own the interface, else look up intf in the list */
 static struct wdm_device *wdm_find_device(struct usb_interface *intf)
 {
-       struct wdm_device *desc = NULL;
+       struct wdm_device *desc;
 
        spin_lock(&wdm_device_list_lock);
        list_for_each_entry(desc, &wdm_device_list, device_list)
                if (desc->intf == intf)
-                       break;
+                       goto found;
+       desc = NULL;
+found:
        spin_unlock(&wdm_device_list_lock);
 
        return desc;
@@ -122,12 +124,14 @@ static struct wdm_device *wdm_find_device(struct usb_interface *intf)
 
 static struct wdm_device *wdm_find_device_by_minor(int minor)
 {
-       struct wdm_device *desc = NULL;
+       struct wdm_device *desc;
 
        spin_lock(&wdm_device_list_lock);
        list_for_each_entry(desc, &wdm_device_list, device_list)
                if (desc->intf->minor == minor)
-                       break;
+                       goto found;
+       desc = NULL;
+found:
        spin_unlock(&wdm_device_list_lock);
 
        return desc;
index f15501f4c585694c0c513eac78f692558ae8720f..e77a8e8eaa233b9b4febd38ef8c01ace8ac832a5 100644 (file)
@@ -71,6 +71,10 @@ static const struct usb_device_id usb_quirk_list[] = {
        { USB_DEVICE(0x04b4, 0x0526), .driver_info =
                        USB_QUIRK_CONFIG_INTF_STRINGS },
 
+       /* Microchip Joss Optical infrared touchboard device */
+       { USB_DEVICE(0x04d8, 0x000c), .driver_info =
+                       USB_QUIRK_CONFIG_INTF_STRINGS },
+
        /* Samsung Android phone modem - ID conflict with SPH-I500 */
        { USB_DEVICE(0x04e8, 0x6601), .driver_info =
                        USB_QUIRK_CONFIG_INTF_STRINGS },
index c34452a7304f9dec269ba64706ab999559e67eff..a68ff53124dc15e88ab3ceaa35e3fbf7e97cc978 100644 (file)
@@ -436,16 +436,21 @@ static int __devinit dwc3_probe(struct platform_device *pdev)
                dev_err(dev, "missing IRQ\n");
                return -ENODEV;
        }
-       dwc->xhci_resources[1] = *res;
+       dwc->xhci_resources[1].start = res->start;
+       dwc->xhci_resources[1].end = res->end;
+       dwc->xhci_resources[1].flags = res->flags;
+       dwc->xhci_resources[1].name = res->name;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res) {
                dev_err(dev, "missing memory resource\n");
                return -ENODEV;
        }
-       dwc->xhci_resources[0] = *res;
+       dwc->xhci_resources[0].start = res->start;
        dwc->xhci_resources[0].end = dwc->xhci_resources[0].start +
                                        DWC3_XHCI_REGS_END;
+       dwc->xhci_resources[0].flags = res->flags;
+       dwc->xhci_resources[0].name = res->name;
 
         /*
          * Request memory region but exclude xHCI regs,
index 9b94886b66e589ee3040556bf284985a01a64bc6..e4d5ca86b9da5413d1c3c52079b4a2abcd9481ad 100644 (file)
@@ -720,7 +720,6 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
                transferred = min_t(u32, ur->length,
                                transfer_size - length);
                memcpy(ur->buf, dwc->ep0_bounce, transferred);
-               dwc->ep0_bounced = false;
        } else {
                transferred = ur->length - length;
        }
index 58fdfad96b4d61b2cc86de9763a135dc81fcd908..c2813c2b005a8e223f93ff50a3215e24172904c2 100644 (file)
@@ -263,8 +263,11 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,
        if (req->request.status == -EINPROGRESS)
                req->request.status = status;
 
-       usb_gadget_unmap_request(&dwc->gadget, &req->request,
-                       req->direction);
+       if (dwc->ep0_bounced && dep->number == 0)
+               dwc->ep0_bounced = false;
+       else
+               usb_gadget_unmap_request(&dwc->gadget, &req->request,
+                               req->direction);
 
        dev_dbg(dwc->dev, "request %p from %s completed %d/%d ===> %d\n",
                        req, dep->name, req->request.actual,
@@ -1026,6 +1029,7 @@ static void __dwc3_gadget_start_isoc(struct dwc3 *dwc,
        if (list_empty(&dep->request_list)) {
                dev_vdbg(dwc->dev, "ISOC ep %s run out for requests.\n",
                        dep->name);
+               dep->flags |= DWC3_EP_PENDING_REQUEST;
                return;
        }
 
@@ -1089,6 +1093,17 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
        if (dep->flags & DWC3_EP_PENDING_REQUEST) {
                int     ret;
 
+               /*
+                * If xfernotready is already elapsed and it is a case
+                * of isoc transfer, then issue END TRANSFER, so that
+                * you can receive xfernotready again and can have
+                * notion of current microframe.
+                */
+               if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
+                       dwc3_stop_active_transfer(dwc, dep->number);
+                       return 0;
+               }
+
                ret = __dwc3_gadget_kick_transfer(dep, 0, true);
                if (ret && ret != -EBUSY) {
                        struct dwc3     *dwc = dep->dwc;
index c9e66dfb02e6642c1e88149884857948b44869e8..1e35963bd4edc29f735319a76e0a4eb7052b27f5 100644 (file)
@@ -475,8 +475,7 @@ static int at91_ep_enable(struct usb_ep *_ep,
        unsigned long   flags;
 
        if (!_ep || !ep
-                       || !desc || ep->ep.desc
-                       || _ep->name == ep0name
+                       || !desc || _ep->name == ep0name
                        || desc->bDescriptorType != USB_DT_ENDPOINT
                        || (maxpacket = usb_endpoint_maxp(desc)) == 0
                        || maxpacket > ep->maxpacket) {
@@ -530,7 +529,6 @@ ok:
        tmp |= AT91_UDP_EPEDS;
        __raw_writel(tmp, ep->creg);
 
-       ep->ep.desc = desc;
        ep->ep.maxpacket = maxpacket;
 
        /*
@@ -1635,7 +1633,6 @@ static int at91_start(struct usb_gadget *gadget,
        udc->driver = driver;
        udc->gadget.dev.driver = &driver->driver;
        udc->gadget.dev.of_node = udc->pdev->dev.of_node;
-       dev_set_drvdata(&udc->gadget.dev, &driver->driver);
        udc->enabled = 1;
        udc->selfpowered = 1;
 
@@ -1656,7 +1653,6 @@ static int at91_stop(struct usb_gadget *gadget,
        spin_unlock_irqrestore(&udc->lock, flags);
 
        udc->gadget.dev.driver = NULL;
-       dev_set_drvdata(&udc->gadget.dev, NULL);
        udc->driver = NULL;
 
        DBG("unbound from %s\n", driver->driver.name);
index b799106027adfc5d75a45244a47fbd015bedfd20..afdbb1cbf5d94d972c52f57f4099a1bb0202bef5 100644 (file)
@@ -1916,6 +1916,27 @@ done:
        return retval;
 }
 
+/* usb 3.0 root hub device descriptor */
+struct {
+       struct usb_bos_descriptor bos;
+       struct usb_ss_cap_descriptor ss_cap;
+} __packed usb3_bos_desc = {
+
+       .bos = {
+               .bLength                = USB_DT_BOS_SIZE,
+               .bDescriptorType        = USB_DT_BOS,
+               .wTotalLength           = cpu_to_le16(sizeof(usb3_bos_desc)),
+               .bNumDeviceCaps         = 1,
+       },
+       .ss_cap = {
+               .bLength                = USB_DT_USB_SS_CAP_SIZE,
+               .bDescriptorType        = USB_DT_DEVICE_CAPABILITY,
+               .bDevCapabilityType     = USB_SS_CAP_TYPE,
+               .wSpeedSupported        = cpu_to_le16(USB_5GBPS_OPERATION),
+               .bFunctionalitySupport  = ilog2(USB_5GBPS_OPERATION),
+       },
+};
+
 static inline void
 ss_hub_descriptor(struct usb_hub_descriptor *desc)
 {
@@ -2006,6 +2027,18 @@ static int dummy_hub_control(
                else
                        hub_descriptor((struct usb_hub_descriptor *) buf);
                break;
+
+       case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
+               if (hcd->speed != HCD_USB3)
+                       goto error;
+
+               if ((wValue >> 8) != USB_DT_BOS)
+                       goto error;
+
+               memcpy(buf, &usb3_bos_desc, sizeof(usb3_bos_desc));
+               retval = sizeof(usb3_bos_desc);
+               break;
+
        case GetHubStatus:
                *(__le32 *) buf = cpu_to_le32(0);
                break;
@@ -2503,10 +2536,8 @@ static int dummy_hcd_probe(struct platform_device *pdev)
        hs_hcd->has_tt = 1;
 
        retval = usb_add_hcd(hs_hcd, 0, 0);
-       if (retval != 0) {
-               usb_put_hcd(hs_hcd);
-               return retval;
-       }
+       if (retval)
+               goto put_usb2_hcd;
 
        if (mod_data.is_super_speed) {
                ss_hcd = usb_create_shared_hcd(&dummy_hcd, &pdev->dev,
@@ -2525,6 +2556,8 @@ static int dummy_hcd_probe(struct platform_device *pdev)
 put_usb3_hcd:
        usb_put_hcd(ss_hcd);
 dealloc_usb2_hcd:
+       usb_remove_hcd(hs_hcd);
+put_usb2_hcd:
        usb_put_hcd(hs_hcd);
        the_controller.hs_hcd = the_controller.ss_hcd = NULL;
        return retval;
index 8adc79d1b40277ac15092a53bac28749627c60cf..829aba75a6dfef28f1ce79055f5b73d6df883c68 100644 (file)
 /* Debugging ****************************************************************/
 
 #ifdef VERBOSE_DEBUG
+#ifndef pr_vdebug
 #  define pr_vdebug pr_debug
+#endif /* pr_vdebug */
 #  define ffs_dump_mem(prefix, ptr, len) \
        print_hex_dump_bytes(pr_fmt(prefix ": "), DUMP_PREFIX_NONE, ptr, len)
 #else
+#ifndef pr_vdebug
 #  define pr_vdebug(...)                 do { } while (0)
+#endif /* pr_vdebug */
 #  define ffs_dump_mem(prefix, ptr, len) do { } while (0)
 #endif /* VERBOSE_DEBUG */
 
index b13e0bb5f5b8131de7cc26a928449215f2e0334c..0bb617e1dda2e0ecf2a440b6494761338f15004c 100644 (file)
@@ -3599,6 +3599,7 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev)
 
        if (hsotg->num_of_eps == 0) {
                dev_err(dev, "wrong number of EPs (zero)\n");
+               ret = -EINVAL;
                goto err_supplies;
        }
 
@@ -3606,6 +3607,7 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev)
                      GFP_KERNEL);
        if (!eps) {
                dev_err(dev, "cannot get memory\n");
+               ret = -ENOMEM;
                goto err_supplies;
        }
 
@@ -3622,6 +3624,7 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev)
                                                     GFP_KERNEL);
        if (!hsotg->ctrl_req) {
                dev_err(dev, "failed to allocate ctrl req\n");
+               ret = -ENOMEM;
                goto err_ep_mem;
        }
 
index 5b3f5fffea92d241b50587b885c24bf69f83e878..da6d479ff9a61e5f57950be3b78e052a029eaa32 100644 (file)
@@ -132,11 +132,15 @@ static unsigned   n_ports;
 
 
 #ifdef VERBOSE_DEBUG
+#ifndef pr_vdebug
 #define pr_vdebug(fmt, arg...) \
        pr_debug(fmt, ##arg)
+#endif /* pr_vdebug */
 #else
+#ifndef pr_vdebig
 #define pr_vdebug(fmt, arg...) \
        ({ if (0) pr_debug(fmt, ##arg); })
+#endif /* pr_vdebug */
 #endif
 
 /*-------------------------------------------------------------------------*/
index 9bc39ca460c80bdfe275b313a47f4683a81e4f3c..4b66374bdc8e33f74e20ff7bc30b7894ab24698e 100644 (file)
@@ -128,9 +128,17 @@ qh_refresh (struct ehci_hcd *ehci, struct ehci_qh *qh)
        else {
                qtd = list_entry (qh->qtd_list.next,
                                struct ehci_qtd, qtd_list);
-               /* first qtd may already be partially processed */
-               if (cpu_to_hc32(ehci, qtd->qtd_dma) == qh->hw->hw_current)
+               /*
+                * first qtd may already be partially processed.
+                * If we come here during unlink, the QH overlay region
+                * might have reference to the just unlinked qtd. The
+                * qtd is updated in qh_completions(). Update the QH
+                * overlay here.
+                */
+               if (cpu_to_hc32(ehci, qtd->qtd_dma) == qh->hw->hw_current) {
+                       qh->hw->hw_qtd_next = qtd->hw_next;
                        qtd = NULL;
+               }
        }
 
        if (qtd)
index a665b3eaa74672f28e7d011b1ea4da265667187f..aaa8d2bce21702aa8d7844bb343de68bd30f0a3d 100644 (file)
@@ -570,6 +570,16 @@ static int __devinit ohci_hcd_at91_drv_probe(struct platform_device *pdev)
 
        if (pdata) {
                at91_for_each_port(i) {
+                       /*
+                        * do not configure PIO if not in relation with
+                        * real USB port on board
+                        */
+                       if (i >= pdata->ports) {
+                               pdata->vbus_pin[i] = -EINVAL;
+                               pdata->overcurrent_pin[i] = -EINVAL;
+                               break;
+                       }
+
                        if (!gpio_is_valid(pdata->vbus_pin[i]))
                                continue;
                        gpio = pdata->vbus_pin[i];
index c5e9e4a76f148d4eed0c4785cf46fb38d143a074..966d1484ee79a2db8c5e78e135c5e0760814d183 100644 (file)
@@ -75,7 +75,9 @@
 #define        NB_PIF0_PWRDOWN_1       0x01100013
 
 #define USB_INTEL_XUSB2PR      0xD0
+#define USB_INTEL_USB2PRM      0xD4
 #define USB_INTEL_USB3_PSSEN   0xD8
+#define USB_INTEL_USB3PRM      0xDC
 
 static struct amd_chipset_info {
        struct pci_dev  *nb_dev;
@@ -772,10 +774,18 @@ void usb_enable_xhci_ports(struct pci_dev *xhci_pdev)
                return;
        }
 
-       ports_available = 0xffffffff;
+       /* Read USB3PRM, the USB 3.0 Port Routing Mask Register
+        * Indicate the ports that can be changed from OS.
+        */
+       pci_read_config_dword(xhci_pdev, USB_INTEL_USB3PRM,
+                       &ports_available);
+
+       dev_dbg(&xhci_pdev->dev, "Configurable ports to enable SuperSpeed: 0x%x\n",
+                       ports_available);
+
        /* Write USB3_PSSEN, the USB 3.0 Port SuperSpeed Enable
-        * Register, to turn on SuperSpeed terminations for all
-        * available ports.
+        * Register, to turn on SuperSpeed terminations for the
+        * switchable ports.
         */
        pci_write_config_dword(xhci_pdev, USB_INTEL_USB3_PSSEN,
                        cpu_to_le32(ports_available));
@@ -785,7 +795,16 @@ void usb_enable_xhci_ports(struct pci_dev *xhci_pdev)
        dev_dbg(&xhci_pdev->dev, "USB 3.0 ports that are now enabled "
                        "under xHCI: 0x%x\n", ports_available);
 
-       ports_available = 0xffffffff;
+       /* Read XUSB2PRM, xHCI USB 2.0 Port Routing Mask Register
+        * Indicate the USB 2.0 ports to be controlled by the xHCI host.
+        */
+
+       pci_read_config_dword(xhci_pdev, USB_INTEL_USB2PRM,
+                       &ports_available);
+
+       dev_dbg(&xhci_pdev->dev, "Configurable USB 2.0 ports to hand over to xCHI: 0x%x\n",
+                       ports_available);
+
        /* Write XUSB2PR, the xHC USB 2.0 Port Routing Register, to
         * switch the USB 2.0 power and data lines over to the xHCI
         * host.
@@ -822,12 +841,12 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev)
        void __iomem *op_reg_base;
        u32 val;
        int timeout;
+       int len = pci_resource_len(pdev, 0);
 
        if (!mmio_resource_enabled(pdev, 0))
                return;
 
-       base = ioremap_nocache(pci_resource_start(pdev, 0),
-                               pci_resource_len(pdev, 0));
+       base = ioremap_nocache(pci_resource_start(pdev, 0), len);
        if (base == NULL)
                return;
 
@@ -837,9 +856,17 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev)
         */
        ext_cap_offset = xhci_find_next_cap_offset(base, XHCI_HCC_PARAMS_OFFSET);
        do {
+               if ((ext_cap_offset + sizeof(val)) > len) {
+                       /* We're reading garbage from the controller */
+                       dev_warn(&pdev->dev,
+                                "xHCI controller failing to respond");
+                       return;
+               }
+
                if (!ext_cap_offset)
                        /* We've reached the end of the extended capabilities */
                        goto hc_init;
+
                val = readl(base + ext_cap_offset);
                if (XHCI_EXT_CAPS_ID(val) == XHCI_EXT_CAPS_LEGACY)
                        break;
@@ -870,9 +897,10 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev)
        /* Disable any BIOS SMIs and clear all SMI events*/
        writel(val, base + ext_cap_offset + XHCI_LEGACY_CONTROL_OFFSET);
 
+hc_init:
        if (usb_is_intel_switchable_xhci(pdev))
                usb_enable_xhci_ports(pdev);
-hc_init:
+
        op_reg_base = base + XHCI_HC_LENGTH(readl(base));
 
        /* Wait for the host controller to be ready before writing any
index ef004a5de20f176c27801f83bd9ae2456570e6b1..7f69a39163ce3b5560f9e0e24a0a9d86e7f77cef 100644 (file)
@@ -15,6 +15,7 @@ void usb_disable_xhci_ports(struct pci_dev *xhci_pdev);
 static inline void usb_amd_quirk_pll_disable(void) {}
 static inline void usb_amd_quirk_pll_enable(void) {}
 static inline void usb_amd_dev_put(void) {}
+static inline void usb_disable_xhci_ports(struct pci_dev *xhci_pdev) {}
 #endif  /* CONFIG_PCI */
 
 #endif  /*  __LINUX_USB_PCI_QUIRKS_H  */
index 74bfc868b7ade609dc67cea66195bd499f92b067..d5eb357aa5c42cff5575bdf1297f3ebbafa49d85 100644 (file)
@@ -493,11 +493,48 @@ static void xhci_hub_report_link_state(u32 *status, u32 status_reg)
                 * when this bit is set.
                 */
                pls |= USB_PORT_STAT_CONNECTION;
+       } else {
+               /*
+                * If CAS bit isn't set but the Port is already at
+                * Compliance Mode, fake a connection so the USB core
+                * notices the Compliance state and resets the port.
+                * This resolves an issue generated by the SN65LVPE502CP
+                * in which sometimes the port enters compliance mode
+                * caused by a delay on the host-device negotiation.
+                */
+               if (pls == USB_SS_PORT_LS_COMP_MOD)
+                       pls |= USB_PORT_STAT_CONNECTION;
        }
+
        /* update status field */
        *status |= pls;
 }
 
+/*
+ * Function for Compliance Mode Quirk.
+ *
+ * This Function verifies if all xhc USB3 ports have entered U0, if so,
+ * the compliance mode timer is deleted. A port won't enter
+ * compliance mode if it has previously entered U0.
+ */
+void xhci_del_comp_mod_timer(struct xhci_hcd *xhci, u32 status, u16 wIndex)
+{
+       u32 all_ports_seen_u0 = ((1 << xhci->num_usb3_ports)-1);
+       bool port_in_u0 = ((status & PORT_PLS_MASK) == XDEV_U0);
+
+       if (!(xhci->quirks & XHCI_COMP_MODE_QUIRK))
+               return;
+
+       if ((xhci->port_status_u0 != all_ports_seen_u0) && port_in_u0) {
+               xhci->port_status_u0 |= 1 << wIndex;
+               if (xhci->port_status_u0 == all_ports_seen_u0) {
+                       del_timer_sync(&xhci->comp_mode_recovery_timer);
+                       xhci_dbg(xhci, "All USB3 ports have entered U0 already!\n");
+                       xhci_dbg(xhci, "Compliance Mode Recovery Timer Deleted.\n");
+               }
+       }
+}
+
 int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                u16 wIndex, char *buf, u16 wLength)
 {
@@ -651,6 +688,11 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                /* Update Port Link State for super speed ports*/
                if (hcd->speed == HCD_USB3) {
                        xhci_hub_report_link_state(&status, temp);
+                       /*
+                        * Verify if all USB3 Ports Have entered U0 already.
+                        * Delete Compliance Mode Timer if so.
+                        */
+                       xhci_del_comp_mod_timer(xhci, temp, wIndex);
                }
                if (bus_state->port_c_suspend & (1 << wIndex))
                        status |= 1 << USB_PORT_FEAT_C_SUSPEND;
index 689bc18b051d6c1d1ae8e381e887a01edbdfc9e9..df90fe51b4aa2d406b8b2f8bfa591c410df89a35 100644 (file)
@@ -118,7 +118,7 @@ static int xhci_plat_probe(struct platform_device *pdev)
                goto put_hcd;
        }
 
-       hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+       hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
        if (!hcd->regs) {
                dev_dbg(&pdev->dev, "error mapping memory\n");
                ret = -EFAULT;
index c59d5b5b6c7d227a8005ca520e8b9badad5207b1..6ece0ed288d4da9398bb96ecc8223f31b6ce8e0c 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/slab.h>
+#include <linux/dmi.h>
 
 #include "xhci.h"
 
@@ -398,6 +399,95 @@ static void xhci_msix_sync_irqs(struct xhci_hcd *xhci)
 
 #endif
 
+static void compliance_mode_recovery(unsigned long arg)
+{
+       struct xhci_hcd *xhci;
+       struct usb_hcd *hcd;
+       u32 temp;
+       int i;
+
+       xhci = (struct xhci_hcd *)arg;
+
+       for (i = 0; i < xhci->num_usb3_ports; i++) {
+               temp = xhci_readl(xhci, xhci->usb3_ports[i]);
+               if ((temp & PORT_PLS_MASK) == USB_SS_PORT_LS_COMP_MOD) {
+                       /*
+                        * Compliance Mode Detected. Letting USB Core
+                        * handle the Warm Reset
+                        */
+                       xhci_dbg(xhci, "Compliance Mode Detected->Port %d!\n",
+                                       i + 1);
+                       xhci_dbg(xhci, "Attempting Recovery routine!\n");
+                       hcd = xhci->shared_hcd;
+
+                       if (hcd->state == HC_STATE_SUSPENDED)
+                               usb_hcd_resume_root_hub(hcd);
+
+                       usb_hcd_poll_rh_status(hcd);
+               }
+       }
+
+       if (xhci->port_status_u0 != ((1 << xhci->num_usb3_ports)-1))
+               mod_timer(&xhci->comp_mode_recovery_timer,
+                       jiffies + msecs_to_jiffies(COMP_MODE_RCVRY_MSECS));
+}
+
+/*
+ * Quirk to work around issue generated by the SN65LVPE502CP USB3.0 re-driver
+ * that causes ports behind that hardware to enter compliance mode sometimes.
+ * The quirk creates a timer that polls every 2 seconds the link state of
+ * each host controller's port and recovers it by issuing a Warm reset
+ * if Compliance mode is detected, otherwise the port will become "dead" (no
+ * device connections or disconnections will be detected anymore). Becasue no
+ * status event is generated when entering compliance mode (per xhci spec),
+ * this quirk is needed on systems that have the failing hardware installed.
+ */
+static void compliance_mode_recovery_timer_init(struct xhci_hcd *xhci)
+{
+       xhci->port_status_u0 = 0;
+       init_timer(&xhci->comp_mode_recovery_timer);
+
+       xhci->comp_mode_recovery_timer.data = (unsigned long) xhci;
+       xhci->comp_mode_recovery_timer.function = compliance_mode_recovery;
+       xhci->comp_mode_recovery_timer.expires = jiffies +
+                       msecs_to_jiffies(COMP_MODE_RCVRY_MSECS);
+
+       set_timer_slack(&xhci->comp_mode_recovery_timer,
+                       msecs_to_jiffies(COMP_MODE_RCVRY_MSECS));
+       add_timer(&xhci->comp_mode_recovery_timer);
+       xhci_dbg(xhci, "Compliance Mode Recovery Timer Initialized.\n");
+}
+
+/*
+ * This function identifies the systems that have installed the SN65LVPE502CP
+ * USB3.0 re-driver and that need the Compliance Mode Quirk.
+ * Systems:
+ * Vendor: Hewlett-Packard -> System Models: Z420, Z620 and Z820
+ */
+static bool compliance_mode_recovery_timer_quirk_check(void)
+{
+       const char *dmi_product_name, *dmi_sys_vendor;
+
+       dmi_product_name = dmi_get_system_info(DMI_PRODUCT_NAME);
+       dmi_sys_vendor = dmi_get_system_info(DMI_SYS_VENDOR);
+
+       if (!(strstr(dmi_sys_vendor, "Hewlett-Packard")))
+               return false;
+
+       if (strstr(dmi_product_name, "Z420") ||
+                       strstr(dmi_product_name, "Z620") ||
+                       strstr(dmi_product_name, "Z820"))
+               return true;
+
+       return false;
+}
+
+static int xhci_all_ports_seen_u0(struct xhci_hcd *xhci)
+{
+       return (xhci->port_status_u0 == ((1 << xhci->num_usb3_ports)-1));
+}
+
+
 /*
  * Initialize memory for HCD and xHC (one-time init).
  *
@@ -421,6 +511,12 @@ int xhci_init(struct usb_hcd *hcd)
        retval = xhci_mem_init(xhci, GFP_KERNEL);
        xhci_dbg(xhci, "Finished xhci_init\n");
 
+       /* Initializing Compliance Mode Recovery Data If Needed */
+       if (compliance_mode_recovery_timer_quirk_check()) {
+               xhci->quirks |= XHCI_COMP_MODE_QUIRK;
+               compliance_mode_recovery_timer_init(xhci);
+       }
+
        return retval;
 }
 
@@ -629,6 +725,11 @@ void xhci_stop(struct usb_hcd *hcd)
        del_timer_sync(&xhci->event_ring_timer);
 #endif
 
+       /* Deleting Compliance Mode Recovery Timer */
+       if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) &&
+                       (!(xhci_all_ports_seen_u0(xhci))))
+               del_timer_sync(&xhci->comp_mode_recovery_timer);
+
        if (xhci->quirks & XHCI_AMD_PLL_FIX)
                usb_amd_dev_put();
 
@@ -659,7 +760,7 @@ void xhci_shutdown(struct usb_hcd *hcd)
 {
        struct xhci_hcd *xhci = hcd_to_xhci(hcd);
 
-       if (xhci->quirks && XHCI_SPURIOUS_REBOOT)
+       if (xhci->quirks & XHCI_SPURIOUS_REBOOT)
                usb_disable_xhci_ports(to_pci_dev(hcd->self.controller));
 
        spin_lock_irq(&xhci->lock);
@@ -806,6 +907,16 @@ int xhci_suspend(struct xhci_hcd *xhci)
        }
        spin_unlock_irq(&xhci->lock);
 
+       /*
+        * Deleting Compliance Mode Recovery Timer because the xHCI Host
+        * is about to be suspended.
+        */
+       if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) &&
+                       (!(xhci_all_ports_seen_u0(xhci)))) {
+               del_timer_sync(&xhci->comp_mode_recovery_timer);
+               xhci_dbg(xhci, "Compliance Mode Recovery Timer Deleted!\n");
+       }
+
        /* step 5: remove core well power */
        /* synchronize irq when using MSI-X */
        xhci_msix_sync_irqs(xhci);
@@ -938,6 +1049,16 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
                usb_hcd_resume_root_hub(hcd);
                usb_hcd_resume_root_hub(xhci->shared_hcd);
        }
+
+       /*
+        * If system is subject to the Quirk, Compliance Mode Timer needs to
+        * be re-initialized Always after a system resume. Ports are subject
+        * to suffer the Compliance Mode issue again. It doesn't matter if
+        * ports have entered previously to U0 before system's suspension.
+        */
+       if (xhci->quirks & XHCI_COMP_MODE_QUIRK)
+               compliance_mode_recovery_timer_init(xhci);
+
        return retval;
 }
 #endif /* CONFIG_PM */
index c713256297acd073e7589f2fdfd936390fb8bbd0..1a05908c66737ce94a77f880d1bc14cb7e40134a 100644 (file)
@@ -1495,6 +1495,7 @@ struct xhci_hcd {
 #define XHCI_LPM_SUPPORT       (1 << 11)
 #define XHCI_INTEL_HOST                (1 << 12)
 #define XHCI_SPURIOUS_REBOOT   (1 << 13)
+#define XHCI_COMP_MODE_QUIRK   (1 << 14)
        unsigned int            num_active_eps;
        unsigned int            limit_active_eps;
        /* There are two roothubs to keep track of bus suspend info for */
@@ -1511,6 +1512,11 @@ struct xhci_hcd {
        unsigned                sw_lpm_support:1;
        /* support xHCI 1.0 spec USB2 hardware LPM */
        unsigned                hw_lpm_support:1;
+       /* Compliance Mode Recovery Data */
+       struct timer_list       comp_mode_recovery_timer;
+       u32                     port_status_u0;
+/* Compliance Mode Timer Triggered every 2 seconds */
+#define COMP_MODE_RCVRY_MSECS 2000
 };
 
 /* convert between an HCD pointer and the corresponding EHCI_HCD */
index 4bb717d0bd41b12a8b0f6fd879c987286a8059b5..1ae378d5fc6f25b5861eb2e3ef79b32a76a4885f 100644 (file)
@@ -2049,7 +2049,7 @@ static int musb_urb_enqueue(
         * we only have work to do in the former case.
         */
        spin_lock_irqsave(&musb->lock, flags);
-       if (hep->hcpriv) {
+       if (hep->hcpriv || !next_urb(qh)) {
                /* some concurrent activity submitted another urb to hep...
                 * odd, rare, error prone, but legal.
                 */
index 57a608584e160248708aca39570a7e30bf55d7a5..c1be687e00ec722524f8807ff8d628ec7a5d0798 100644 (file)
@@ -388,7 +388,7 @@ dma_controller_create(struct musb *musb, void __iomem *base)
        struct platform_device *pdev = to_platform_device(dev);
        int irq = platform_get_irq_byname(pdev, "dma");
 
-       if (irq == 0) {
+       if (irq <= 0) {
                dev_err(dev, "No DMA interrupt line!\n");
                return NULL;
        }
index 1a1bd9cf40c5ce7c1d6f7ef1ac46360d0b6884a4..341625442377ec6f1daac69450269c95f4148eb5 100644 (file)
@@ -1215,7 +1215,7 @@ static int __devinit tusb_probe(struct platform_device *pdev)
        ret = platform_device_add(musb);
        if (ret) {
                dev_err(&pdev->dev, "failed to register musb device\n");
-               goto err1;
+               goto err2;
        }
 
        return 0;
index ecd173032fd480cc5954c48f03aa61e7b5c439e8..143c4e9e1be45cc24c0a612d38e590a5ad136be9 100644 (file)
@@ -818,7 +818,7 @@ static int usbhsf_dma_prepare_push(struct usbhs_pkt *pkt, int *is_done)
            usbhs_pipe_is_dcp(pipe))
                goto usbhsf_pio_prepare_push;
 
-       if (len % 4) /* 32bit alignment */
+       if (len & 0x7) /* 8byte alignment */
                goto usbhsf_pio_prepare_push;
 
        if ((uintptr_t)(pkt->buf + pkt->actual) & 0x7) /* 8byte alignment */
@@ -905,7 +905,7 @@ static int usbhsf_dma_try_pop(struct usbhs_pkt *pkt, int *is_done)
        /* use PIO if packet is less than pio_dma_border */
        len = usbhsf_fifo_rcv_len(priv, fifo);
        len = min(pkt->length - pkt->actual, len);
-       if (len % 4) /* 32bit alignment */
+       if (len & 0x7) /* 8byte alignment */
                goto usbhsf_pio_prepare_pop_unselect;
 
        if (len < usbhs_get_dparam(priv, pio_dma_border))
index 5620db6469e586f85ea8eacfa79798b1b4a676d8..f906b3aec2179ceb708c9cce772cd85a4e1a1724 100644 (file)
@@ -704,6 +704,7 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(FTDI_VID, FTDI_PCDJ_DAC2_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_RRCIRKITS_LOCOBUFFER_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_ASK_RDR400_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_NZR_SEM_USB_PID) },
        { USB_DEVICE(ICOM_VID, ICOM_ID_1_PID) },
        { USB_DEVICE(ICOM_VID, ICOM_OPC_U_UC_PID) },
        { USB_DEVICE(ICOM_VID, ICOM_ID_RP2C1_PID) },
@@ -804,13 +805,32 @@ static struct usb_device_id id_table_combined [] = {
                .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
        { USB_DEVICE(ADI_VID, ADI_GNICEPLUS_PID),
                .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
-       { USB_DEVICE(MICROCHIP_VID, MICROCHIP_USB_BOARD_PID) },
+       { USB_DEVICE_AND_INTERFACE_INFO(MICROCHIP_VID, MICROCHIP_USB_BOARD_PID,
+                                       USB_CLASS_VENDOR_SPEC,
+                                       USB_SUBCLASS_VENDOR_SPEC, 0x00) },
        { USB_DEVICE(JETI_VID, JETI_SPC1201_PID) },
        { USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID),
                .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
        { USB_DEVICE(LARSENBRUSGAARD_VID, LB_ALTITRACK_PID) },
        { USB_DEVICE(GN_OTOMETRICS_VID, AURICAL_USB_PID) },
+       { USB_DEVICE(FTDI_VID, PI_C865_PID) },
+       { USB_DEVICE(FTDI_VID, PI_C857_PID) },
+       { USB_DEVICE(PI_VID, PI_C866_PID) },
+       { USB_DEVICE(PI_VID, PI_C663_PID) },
+       { USB_DEVICE(PI_VID, PI_C725_PID) },
+       { USB_DEVICE(PI_VID, PI_E517_PID) },
+       { USB_DEVICE(PI_VID, PI_C863_PID) },
        { USB_DEVICE(PI_VID, PI_E861_PID) },
+       { USB_DEVICE(PI_VID, PI_C867_PID) },
+       { USB_DEVICE(PI_VID, PI_E609_PID) },
+       { USB_DEVICE(PI_VID, PI_E709_PID) },
+       { USB_DEVICE(PI_VID, PI_100F_PID) },
+       { USB_DEVICE(PI_VID, PI_1011_PID) },
+       { USB_DEVICE(PI_VID, PI_1012_PID) },
+       { USB_DEVICE(PI_VID, PI_1013_PID) },
+       { USB_DEVICE(PI_VID, PI_1014_PID) },
+       { USB_DEVICE(PI_VID, PI_1015_PID) },
+       { USB_DEVICE(PI_VID, PI_1016_PID) },
        { USB_DEVICE(KONDO_VID, KONDO_USB_SERIAL_PID) },
        { USB_DEVICE(BAYER_VID, BAYER_CONTOUR_CABLE_PID) },
        { USB_DEVICE(FTDI_VID, MARVELL_OPENRD_PID),
index 5dd96ca6c380a0971921d198e12399e1902663db..41fe5826100c0ad27a62d21d16e8d5845dfa25cc 100644 (file)
@@ -75,6 +75,9 @@
 #define FTDI_OPENDCC_GATEWAY_PID       0xBFDB
 #define FTDI_OPENDCC_GBM_PID   0xBFDC
 
+/* NZR SEM 16+ USB (http://www.nzr.de) */
+#define FTDI_NZR_SEM_USB_PID   0xC1E0  /* NZR SEM-LOG16+ */
+
 /*
  * RR-CirKits LocoBuffer USB (http://www.rr-cirkits.com)
  */
 /*
  * Microchip Technology, Inc.
  *
- * MICROCHIP_VID (0x04D8) and MICROCHIP_USB_BOARD_PID (0x000A) are also used by:
+ * MICROCHIP_VID (0x04D8) and MICROCHIP_USB_BOARD_PID (0x000A) are
+ * used by single function CDC ACM class based firmware demo
+ * applications.  The VID/PID has also been used in firmware
+ * emulating FTDI serial chips by:
  * Hornby Elite - Digital Command Control Console
  * http://www.hornby.com/hornby-dcc/controllers/
  */
  * Physik Instrumente
  * http://www.physikinstrumente.com/en/products/
  */
+/* These two devices use the VID of FTDI */
+#define PI_C865_PID    0xe0a0  /* PI C-865 Piezomotor Controller */
+#define PI_C857_PID    0xe0a1  /* PI Encoder Trigger Box */
+
 #define PI_VID              0x1a72  /* Vendor ID */
-#define PI_E861_PID         0x1008  /* E-861 piezo controller USB connection */
+#define PI_C866_PID    0x1000  /* PI C-866 Piezomotor Controller */
+#define PI_C663_PID    0x1001  /* PI C-663 Mercury-Step */
+#define PI_C725_PID    0x1002  /* PI C-725 Piezomotor Controller */
+#define PI_E517_PID    0x1005  /* PI E-517 Digital Piezo Controller Operation Module */
+#define PI_C863_PID    0x1007  /* PI C-863 */
+#define PI_E861_PID    0x1008  /* PI E-861 Piezomotor Controller */
+#define PI_C867_PID    0x1009  /* PI C-867 Piezomotor Controller */
+#define PI_E609_PID    0x100D  /* PI E-609 Digital Piezo Controller */
+#define PI_E709_PID    0x100E  /* PI E-709 Digital Piezo Controller */
+#define PI_100F_PID    0x100F  /* PI Digital Piezo Controller */
+#define PI_1011_PID    0x1011  /* PI Digital Piezo Controller */
+#define PI_1012_PID    0x1012  /* PI Motion Controller */
+#define PI_1013_PID    0x1013  /* PI Motion Controller */
+#define PI_1014_PID    0x1014  /* PI Device */
+#define PI_1015_PID    0x1015  /* PI Device */
+#define PI_1016_PID    0x1016  /* PI Digital Servo Module */
 
 /*
  * Kondo Kagaku Co.Ltd.
index cc40f47ecea13ff2041389d5aa7d5526159e58d8..5ce88d1bc6f1e3ac15ac91290ad8cb2fd5935361 100644 (file)
@@ -886,8 +886,6 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1010, 0xff, 0xff, 0xff),
          .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1018, 0xff, 0xff, 0xff),
-         .driver_info = (kernel_ulong_t)&net_intf3_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1057, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1058, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1059, 0xff, 0xff, 0xff) },
@@ -1092,6 +1090,10 @@ static const struct usb_device_id option_ids[] = {
         .driver_info = (kernel_ulong_t)&zte_ad3812_z_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MC2716, 0xff, 0xff, 0xff),
         .driver_info = (kernel_ulong_t)&zte_mc2716_z_blacklist },
+       { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x01) },
+       { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x05) },
+       { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x86, 0x10) },
+
        { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) },
        { USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) },
        { USB_DEVICE(ALINK_VENDOR_ID, DLINK_PRODUCT_DWM_652_U5) }, /* Yes, ALINK_VENDOR_ID */
index 1eff743ec4970071f8451704fb51d4b06de70950..ae60406ea8a1878cefd03d29868eda31b955578f 100644 (file)
@@ -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);
index 6aa46a90ff028691f97627765f593d864bc885a1..3796434991faa83466c85c8779a072db1278ef33 100644 (file)
@@ -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);
index 1ffd03bf8e10dcb6b015e3e0b94a2a460f0d0dcd..7f1241608489de05a33e957a77145f4faa605f0e 100644 (file)
@@ -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;
 
index 0bfc1ef11259eccaa937eb8d0913e4e14e04832e..006726688baf4f0a535896dd38c9a3ea2198c617 100644 (file)
@@ -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;
        }
index 1afb4fba11b430b5b7cf0f0b16cd2afa8fb61f08..4d519488d3045355672b8f48e3c1e2eb4ac64864 100644 (file)
@@ -232,7 +232,7 @@ xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size,
                return ret;
 
        if (hwdev && hwdev->coherent_dma_mask)
-               dma_mask = hwdev->coherent_dma_mask;
+               dma_mask = dma_alloc_coherent_mask(hwdev, flags);
 
        phys = virt_to_phys(ret);
        dev_addr = xen_phys_to_bus(phys);
index 097e536e8672d68ff32da41406156a75ed05a996..03342728bf2352ff751f21c333b58bd5cb8756b6 100644 (file)
@@ -353,16 +353,16 @@ static int __devinit pcistub_init_device(struct pci_dev *dev)
        if (err)
                goto config_release;
 
-       dev_dbg(&dev->dev, "reseting (FLR, D3, etc) the device\n");
-       __pci_reset_function_locked(dev);
-
        /* We need the device active to save the state. */
        dev_dbg(&dev->dev, "save state of device\n");
        pci_save_state(dev);
        dev_data->pci_saved_state = pci_store_saved_state(dev);
        if (!dev_data->pci_saved_state)
                dev_err(&dev->dev, "Could not store PCI conf saved state!\n");
-
+       else {
+               dev_dbg(&dev->dev, "reseting (FLR, D3, etc) the device\n");
+               __pci_reset_function_locked(dev);
+       }
        /* Now disable the device (this also ensures some private device
         * data is setup before we export)
         */
index 29e38a1f7f77a15100f1d20b3e51507470273633..cce7df53b694373b6288795f14b07eb91c0894fc 100644 (file)
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -14,6 +14,7 @@
 #include <linux/fcntl.h>
 #include <linux/security.h>
 #include <linux/evm.h>
+#include <linux/ima.h>
 
 /**
  * inode_change_ok - check if attribute changes to an inode are allowed
@@ -247,6 +248,7 @@ int notify_change(struct dentry * dentry, struct iattr * attr)
 
        if (!error) {
                fsnotify_change(dentry, ia_valid);
+               ima_inode_post_setattr(dentry);
                evm_inode_post_setattr(dentry, ia_valid);
        }
 
index 38b42e7bc91d0e258a7fd086d793aae3d43ac4c1..b65015581744a6eefb9b3ed720478673b888d336 100644 (file)
@@ -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) {
index 7dab9c04ad524117a386c08fb21d7a886e9ca82d..53cf2aabce877ce2a8e15844ab667cf6f26a2d63 100644 (file)
@@ -328,7 +328,7 @@ cifsConvertToUTF16(__le16 *target, const char *source, int srclen,
        }
 
 ctoUTF16_out:
-       return i;
+       return j;
 }
 
 #ifdef CONFIG_CIFS_SMB2
index f3c60e264ca83b99d4f40d8969e40c0da38583ad..3151a264988ec1a98cc03d45e3d30f95fccf17bd 100644 (file)
@@ -537,19 +537,15 @@ init_cifs_idmap(void)
        if (!cred)
                return -ENOMEM;
 
-       keyring = key_alloc(&key_type_keyring, ".cifs_idmap", 0, 0, cred,
-                           (KEY_POS_ALL & ~KEY_POS_SETATTR) |
-                           KEY_USR_VIEW | KEY_USR_READ,
-                           KEY_ALLOC_NOT_IN_QUOTA);
+       keyring = keyring_alloc(".cifs_idmap", 0, 0, cred,
+                               (KEY_POS_ALL & ~KEY_POS_SETATTR) |
+                               KEY_USR_VIEW | KEY_USR_READ,
+                               KEY_ALLOC_NOT_IN_QUOTA, NULL);
        if (IS_ERR(keyring)) {
                ret = PTR_ERR(keyring);
                goto failed_put_cred;
        }
 
-       ret = key_instantiate_and_link(keyring, NULL, 0, NULL, NULL);
-       if (ret < 0)
-               goto failed_put_key;
-
        ret = register_key_type(&cifs_idmap_key_type);
        if (ret < 0)
                goto failed_put_key;
index 9154192b0683e368a521ddf118961e1cdd592355..71e9ad9f59610aedef820784e558e1652973a553 100644 (file)
@@ -917,7 +917,7 @@ cifs_push_mandatory_locks(struct cifsFileInfo *cfile)
        if (!buf) {
                mutex_unlock(&cinode->lock_mutex);
                free_xid(xid);
-               return rc;
+               return -ENOMEM;
        }
 
        for (i = 0; i < 2; i++) {
index c5fbfac5d576ef917f8cf8e484dbb801523fd35c..15dc8eea82731fb8c00485d67493ab30d3a39318 100644 (file)
@@ -96,7 +96,7 @@
  *
  */
 
-#define SMB2_HEADER_STRUCTURE_SIZE __constant_le16_to_cpu(64)
+#define SMB2_HEADER_STRUCTURE_SIZE __constant_cpu_to_le16(64)
 
 struct smb2_hdr {
        __be32 smb2_buf_length; /* big endian on wire */
@@ -140,7 +140,7 @@ struct smb2_pdu {
  *
  */
 
-#define SMB2_ERROR_STRUCTURE_SIZE2 __constant_le16_to_cpu(9)
+#define SMB2_ERROR_STRUCTURE_SIZE2 __constant_cpu_to_le16(9)
 
 struct smb2_err_rsp {
        struct smb2_hdr hdr;
index 8086636bf796ab328219d4a898608af1be2fdb2b..16521a9f203859a28a8804d3fb2f5f4cb894ed7f 100644 (file)
@@ -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;
index 2340f6978d6e29e01c9b90ddaa9abd33beb0ee11..c5ca6ae5a30cc750e5a33b42ce746da6cf2f4591 100644 (file)
@@ -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);
index 44ce5c6a541d65b7ceae1e7d67655a2e3f0f109a..d45ba4568128eb17baf60535d6dc00e663196afa 100644 (file)
@@ -275,8 +275,14 @@ out:
 
 static int ecryptfs_flush(struct file *file, fl_owner_t td)
 {
-       return file->f_mode & FMODE_WRITE
-              ? filemap_write_and_wait(file->f_mapping) : 0;
+       struct file *lower_file = ecryptfs_file_to_lower(file);
+
+       if (lower_file->f_op && lower_file->f_op->flush) {
+               filemap_write_and_wait(file->f_mapping);
+               return lower_file->f_op->flush(lower_file, td);
+       }
+
+       return 0;
 }
 
 static int ecryptfs_release(struct inode *inode, struct file *file)
index 534b129ea676500c4df149d95cb9bd5be517dc54..cc7709e7c508d81a1429ffa25bace9c7a101a832 100644 (file)
@@ -619,6 +619,7 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,
        struct dentry *lower_old_dir_dentry;
        struct dentry *lower_new_dir_dentry;
        struct dentry *trap = NULL;
+       struct inode *target_inode;
 
        lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry);
        lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry);
@@ -626,6 +627,7 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,
        dget(lower_new_dentry);
        lower_old_dir_dentry = dget_parent(lower_old_dentry);
        lower_new_dir_dentry = dget_parent(lower_new_dentry);
+       target_inode = new_dentry->d_inode;
        trap = lock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
        /* source should not be ancestor of target */
        if (trap == lower_old_dentry) {
@@ -641,6 +643,9 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                        lower_new_dir_dentry->d_inode, lower_new_dentry);
        if (rc)
                goto out_lock;
+       if (target_inode)
+               fsstack_copy_attr_all(target_inode,
+                                     ecryptfs_inode_to_lower(target_inode));
        fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode);
        if (new_dir != old_dir)
                fsstack_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode);
index 2768138eefeef85707f9ee29652532b25d50dfcb..9b627c15010a3af35e1f2ec85ccafc2b18d97d44 100644 (file)
@@ -162,6 +162,7 @@ void ecryptfs_put_lower_file(struct inode *inode)
        inode_info = ecryptfs_inode_to_private(inode);
        if (atomic_dec_and_mutex_lock(&inode_info->lower_file_count,
                                      &inode_info->lower_file_mutex)) {
+               filemap_write_and_wait(inode->i_mapping);
                fput(inode_info->lower_file);
                inode_info->lower_file = NULL;
                mutex_unlock(&inode_info->lower_file_mutex);
index a07597307fd1cd221b20997d9e0268caa6bc9138..ff574b4e345efd09a7c2e6f2511213210fbcc92d 100644 (file)
@@ -3072,6 +3072,8 @@ static int ext3_do_update_inode(handle_t *handle,
        struct ext3_inode_info *ei = EXT3_I(inode);
        struct buffer_head *bh = iloc->bh;
        int err = 0, rc, block;
+       int need_datasync = 0;
+       __le32 disksize;
        uid_t i_uid;
        gid_t i_gid;
 
@@ -3113,7 +3115,11 @@ again:
                raw_inode->i_gid_high = 0;
        }
        raw_inode->i_links_count = cpu_to_le16(inode->i_nlink);
-       raw_inode->i_size = cpu_to_le32(ei->i_disksize);
+       disksize = cpu_to_le32(ei->i_disksize);
+       if (disksize != raw_inode->i_size) {
+               need_datasync = 1;
+               raw_inode->i_size = disksize;
+       }
        raw_inode->i_atime = cpu_to_le32(inode->i_atime.tv_sec);
        raw_inode->i_ctime = cpu_to_le32(inode->i_ctime.tv_sec);
        raw_inode->i_mtime = cpu_to_le32(inode->i_mtime.tv_sec);
@@ -3129,8 +3135,11 @@ again:
        if (!S_ISREG(inode->i_mode)) {
                raw_inode->i_dir_acl = cpu_to_le32(ei->i_dir_acl);
        } else {
-               raw_inode->i_size_high =
-                       cpu_to_le32(ei->i_disksize >> 32);
+               disksize = cpu_to_le32(ei->i_disksize >> 32);
+               if (disksize != raw_inode->i_size_high) {
+                       raw_inode->i_size_high = disksize;
+                       need_datasync = 1;
+               }
                if (ei->i_disksize > 0x7fffffffULL) {
                        struct super_block *sb = inode->i_sb;
                        if (!EXT3_HAS_RO_COMPAT_FEATURE(sb,
@@ -3183,6 +3192,8 @@ again:
        ext3_clear_inode_state(inode, EXT3_STATE_NEW);
 
        atomic_set(&ei->i_sync_tid, handle->h_transaction->t_tid);
+       if (need_datasync)
+               atomic_set(&ei->i_datasync_tid, handle->h_transaction->t_tid);
 out_brelse:
        brelse (bh);
        ext3_std_error(inode->i_sb, err);
index 701985e4ccda4fc5afc05977f511bd6ca11ba3af..a41f23f90b17d932a7da824ed6a3f48053e03fc7 100644 (file)
@@ -243,10 +243,10 @@ static void __fput(struct file *file)
                if (file->f_op && file->f_op->fasync)
                        file->f_op->fasync(-1, file, 0);
        }
+       ima_file_free(file);
        if (file->f_op && file->f_op->release)
                file->f_op->release(inode, file);
        security_file_free(file);
-       ima_file_free(file);
        if (unlikely(S_ISCHR(inode->i_mode) && inode->i_cdev != NULL &&
                     !(file->f_mode & FMODE_PATH))) {
                cdev_put(inode->i_cdev);
index 03ff5b1eba93ec21e11d9ca31f9c8b3f22e65d36..75a20c092dd43b573c4f24788d067b3e6b1bfef0 100644 (file)
@@ -117,7 +117,7 @@ static ssize_t fuse_conn_max_background_write(struct file *file,
                                              const char __user *buf,
                                              size_t count, loff_t *ppos)
 {
-       unsigned val;
+       unsigned uninitialized_var(val);
        ssize_t ret;
 
        ret = fuse_conn_limit_write(file, buf, count, ppos, &val,
@@ -154,7 +154,7 @@ static ssize_t fuse_conn_congestion_threshold_write(struct file *file,
                                                    const char __user *buf,
                                                    size_t count, loff_t *ppos)
 {
-       unsigned val;
+       unsigned uninitialized_var(val);
        ssize_t ret;
 
        ret = fuse_conn_limit_write(file, buf, count, ppos, &val,
index 3426521f3205cce09a98b8a1bd01ffe9e44f84c0..ee8d55042298272f6ac6c76982f4ecd5efb745ca 100644 (file)
@@ -396,7 +396,7 @@ err_device:
 err_region:
        unregister_chrdev_region(devt, 1);
 err:
-       fc->conn_error = 1;
+       fuse_conn_kill(fc);
        goto out;
 }
 
@@ -532,8 +532,6 @@ static int cuse_channel_release(struct inode *inode, struct file *file)
                cdev_del(cc->cdev);
        }
 
-       /* kill connection and shutdown channel */
-       fuse_conn_kill(&cc->fc);
        rc = fuse_dev_release(inode, file);     /* puts the base reference */
 
        return rc;
index 7df2b5e8fbe187af6599504f935d1ed463a40c64..f4246cfc8d876db6ac39a6ef058b144c73d503af 100644 (file)
@@ -1576,6 +1576,7 @@ static int fuse_retrieve(struct fuse_conn *fc, struct inode *inode,
                req->pages[req->num_pages] = page;
                req->num_pages++;
 
+               offset = 0;
                num -= this_num;
                total_len += this_num;
                index++;
index ce0a2838ccd097a5392d469fc0650d2e7b0d7e8d..fca222dabe3ccc4a791e894d325bdc4e4f78b7f3 100644 (file)
@@ -367,11 +367,6 @@ void fuse_conn_kill(struct fuse_conn *fc)
        wake_up_all(&fc->waitq);
        wake_up_all(&fc->blocked_waitq);
        wake_up_all(&fc->reserved_req_waitq);
-       mutex_lock(&fuse_mutex);
-       list_del(&fc->entry);
-       fuse_ctl_remove_conn(fc);
-       mutex_unlock(&fuse_mutex);
-       fuse_bdi_destroy(fc);
 }
 EXPORT_SYMBOL_GPL(fuse_conn_kill);
 
@@ -380,7 +375,14 @@ static void fuse_put_super(struct super_block *sb)
        struct fuse_conn *fc = get_fuse_conn_super(sb);
 
        fuse_send_destroy(fc);
+
        fuse_conn_kill(fc);
+       mutex_lock(&fuse_mutex);
+       list_del(&fc->entry);
+       fuse_ctl_remove_conn(fc);
+       mutex_unlock(&fuse_mutex);
+       fuse_bdi_destroy(fc);
+
        fuse_conn_put(fc);
 }
 
index d1d791ef38de2188852551254a63f974a605feff..382000ffac1f7e892163665a27982e587b9d83e7 100644 (file)
@@ -322,6 +322,29 @@ static long gfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
        return -ENOTTY;
 }
 
+/**
+ * gfs2_size_hint - Give a hint to the size of a write request
+ * @file: The struct file
+ * @offset: The file offset of the write
+ * @size: The length of the write
+ *
+ * When we are about to do a write, this function records the total
+ * write size in order to provide a suitable hint to the lower layers
+ * about how many blocks will be required.
+ *
+ */
+
+static void gfs2_size_hint(struct file *filep, loff_t offset, size_t size)
+{
+       struct inode *inode = filep->f_dentry->d_inode;
+       struct gfs2_sbd *sdp = GFS2_SB(inode);
+       struct gfs2_inode *ip = GFS2_I(inode);
+       size_t blks = (size + sdp->sd_sb.sb_bsize - 1) >> sdp->sd_sb.sb_bsize_shift;
+       int hint = min_t(size_t, INT_MAX, blks);
+
+       atomic_set(&ip->i_res->rs_sizehint, hint);
+}
+
 /**
  * gfs2_allocate_page_backing - Use bmap to allocate blocks
  * @page: The (locked) page to allocate backing for
@@ -382,8 +405,7 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
        if (ret)
                return ret;
 
-       atomic_set(&ip->i_res->rs_sizehint,
-                  PAGE_CACHE_SIZE >> sdp->sd_sb.sb_bsize_shift);
+       gfs2_size_hint(vma->vm_file, pos, PAGE_CACHE_SIZE);
 
        gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
        ret = gfs2_glock_nq(&gh);
@@ -663,7 +685,8 @@ static ssize_t gfs2_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
        if (ret)
                return ret;
 
-       atomic_set(&ip->i_res->rs_sizehint, writesize >> sdp->sd_sb.sb_bsize_shift);
+       gfs2_size_hint(file, pos, writesize);
+
        if (file->f_flags & O_APPEND) {
                struct gfs2_holder gh;
 
@@ -789,7 +812,7 @@ static long gfs2_fallocate(struct file *file, int mode, loff_t offset,
        if (unlikely(error))
                goto out_uninit;
 
-       atomic_set(&ip->i_res->rs_sizehint, len >> sdp->sd_sb.sb_bsize_shift);
+       gfs2_size_hint(file, offset, len);
 
        while (len > 0) {
                if (len < bytes)
index 4ce22e54730806e02ed0ba70f7e7fc847d513142..753af3d86bbcecaa76f5c01cb54d81b0006c4fac 100644 (file)
@@ -1722,7 +1722,9 @@ static int gfs2_setxattr(struct dentry *dentry, const char *name,
        gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
        ret = gfs2_glock_nq(&gh);
        if (ret == 0) {
-               ret = generic_setxattr(dentry, name, data, size, flags);
+               ret = gfs2_rs_alloc(ip);
+               if (ret == 0)
+                       ret = generic_setxattr(dentry, name, data, size, flags);
                gfs2_glock_dq(&gh);
        }
        gfs2_holder_uninit(&gh);
@@ -1757,7 +1759,9 @@ static int gfs2_removexattr(struct dentry *dentry, const char *name)
        gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
        ret = gfs2_glock_nq(&gh);
        if (ret == 0) {
-               ret = generic_removexattr(dentry, name);
+               ret = gfs2_rs_alloc(ip);
+               if (ret == 0)
+                       ret = generic_removexattr(dentry, name);
                gfs2_glock_dq(&gh);
        }
        gfs2_holder_uninit(&gh);
index 4d34887a601d966660549b0d0a27517353c1ed5e..c9ed814eeb6f9652eaa927e2ab13fc42c906da14 100644 (file)
@@ -1961,7 +1961,7 @@ static void gfs2_rgrp_error(struct gfs2_rgrpd *rgd)
  * @dinode: 1 if this block is a dinode block, otherwise data block
  * @nblocks: desired extent length
  *
- * Lay claim to previously allocated block reservation blocks.
+ * Lay claim to previously reserved blocks.
  * Returns: Starting block number of the blocks claimed.
  * Sets *nblocks to the actual extent length allocated.
  */
@@ -1970,19 +1970,17 @@ static u64 claim_reserved_blks(struct gfs2_inode *ip, bool dinode,
 {
        struct gfs2_blkreserv *rs = ip->i_res;
        struct gfs2_rgrpd *rgd = rs->rs_rgd;
-       struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
        struct gfs2_bitmap *bi;
        u64 start_block = gfs2_rs_startblk(rs);
        const unsigned int elen = *nblocks;
 
-       /*BUG_ON(!gfs2_glock_is_locked_by_me(ip->i_gl));*/
-       gfs2_assert_withdraw(sdp, rgd);
-       /*BUG_ON(!gfs2_glock_is_locked_by_me(rgd->rd_gl));*/
        bi = rs->rs_bi;
        gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1);
 
        for (*nblocks = 0; *nblocks < elen && rs->rs_free; (*nblocks)++) {
-               /* Make sure the bitmap hasn't changed */
+               if (gfs2_testbit(rgd, bi->bi_bh->b_data + bi->bi_offset,
+                                bi->bi_len, rs->rs_biblk) != GFS2_BLKST_FREE)
+                       break;
                gfs2_setbit(rgd, bi->bi_clone, bi, rs->rs_biblk,
                            dinode ? GFS2_BLKST_DINODE : GFS2_BLKST_USED);
                rs->rs_biblk++;
@@ -1991,20 +1989,12 @@ static u64 claim_reserved_blks(struct gfs2_inode *ip, bool dinode,
                BUG_ON(!rgd->rd_reserved);
                rgd->rd_reserved--;
                dinode = false;
-               trace_gfs2_rs(ip, rs, TRACE_RS_CLAIM);
        }
 
-       if (!rs->rs_free) {
-               struct gfs2_rgrpd *rgd = ip->i_res->rs_rgd;
-
+       trace_gfs2_rs(ip, rs, TRACE_RS_CLAIM);
+       if (!rs->rs_free || *nblocks != elen)
                gfs2_rs_deltree(rs);
-               /* -nblocks because we haven't returned to do the math yet.
-                  I'm doing the math backwards to prevent negative numbers,
-                  but think of it as:
-                  if (unclaimed_blocks(rgd) - *nblocks >= RGRP_RSRV_MINBLKS */
-               if (unclaimed_blocks(rgd) >= RGRP_RSRV_MINBLKS + *nblocks)
-                       rg_mblk_search(rgd, ip);
-       }
+
        return start_block;
 }
 
@@ -2037,34 +2027,34 @@ int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *nblocks,
        if (ip->i_res->rs_requested == 0)
                return -ECANCELED;
 
-       /* Check if we have a multi-block reservation, and if so, claim the
-          next free block from it. */
+       /* If we have a reservation, claim blocks from it. */
        if (gfs2_rs_active(ip->i_res)) {
                BUG_ON(!ip->i_res->rs_free);
                rgd = ip->i_res->rs_rgd;
                block = claim_reserved_blks(ip, dinode, nblocks);
-       } else {
-               rgd = ip->i_rgd;
+               if (*nblocks)
+                       goto found_blocks;
+       }
 
-               if (!dinode && rgrp_contains_block(rgd, ip->i_goal))
-                       goal = ip->i_goal - rgd->rd_data0;
-               else
-                       goal = rgd->rd_last_alloc;
-
-               blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, &bi);
-
-               /* Since all blocks are reserved in advance, this shouldn't
-                  happen */
-               if (blk == BFITNOENT) {
-                       printk(KERN_WARNING "BFITNOENT, nblocks=%u\n",
-                              *nblocks);
-                       printk(KERN_WARNING "FULL=%d\n",
-                              test_bit(GBF_FULL, &rgd->rd_bits->bi_flags));
-                       goto rgrp_error;
-               }
+       rgd = ip->i_rgd;
 
-               block = gfs2_alloc_extent(rgd, bi, blk, dinode, nblocks);
+       if (!dinode && rgrp_contains_block(rgd, ip->i_goal))
+               goal = ip->i_goal - rgd->rd_data0;
+       else
+               goal = rgd->rd_last_alloc;
+
+       blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, &bi);
+
+       /* Since all blocks are reserved in advance, this shouldn't happen */
+       if (blk == BFITNOENT) {
+               printk(KERN_WARNING "BFITNOENT, nblocks=%u\n", *nblocks);
+               printk(KERN_WARNING "FULL=%d\n",
+                      test_bit(GBF_FULL, &rgd->rd_bits->bi_flags));
+               goto rgrp_error;
        }
+
+       block = gfs2_alloc_extent(rgd, bi, blk, dinode, nblocks);
+found_blocks:
        ndata = *nblocks;
        if (dinode)
                ndata--;
index 75d6d0a3d32e2685bbd43f791b1f32775c87ce59..6a7fcab7ecb3115c7630573c17f4d8285a418591 100644 (file)
@@ -287,10 +287,12 @@ nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
        struct inode *inode = file->f_path.dentry->d_inode;
 
        ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
+       if (ret != 0)
+               goto out;
        mutex_lock(&inode->i_mutex);
        ret = nfs_file_fsync_commit(file, start, end, datasync);
        mutex_unlock(&inode->i_mutex);
-
+out:
        return ret;
 }
 
index a850079467d85f149d997b9c96176c9a0829be0d..957134b4c0fd47c59977607aa27b05d096bd0e0c 100644 (file)
@@ -192,19 +192,15 @@ static int nfs_idmap_init_keyring(void)
        if (!cred)
                return -ENOMEM;
 
-       keyring = key_alloc(&key_type_keyring, ".id_resolver", 0, 0, cred,
-                            (KEY_POS_ALL & ~KEY_POS_SETATTR) |
-                            KEY_USR_VIEW | KEY_USR_READ,
-                            KEY_ALLOC_NOT_IN_QUOTA);
+       keyring = keyring_alloc(".id_resolver", 0, 0, cred,
+                               (KEY_POS_ALL & ~KEY_POS_SETATTR) |
+                               KEY_USR_VIEW | KEY_USR_READ,
+                               KEY_ALLOC_NOT_IN_QUOTA, NULL);
        if (IS_ERR(keyring)) {
                ret = PTR_ERR(keyring);
                goto failed_put_cred;
        }
 
-       ret = key_instantiate_and_link(keyring, NULL, 0, NULL, NULL);
-       if (ret < 0)
-               goto failed_put_key;
-
        ret = register_key_type(&key_type_id_resolver);
        if (ret < 0)
                goto failed_put_key;
index c6e895f0fbf36eee681a5cb5d8e4a92bfd8c0d35..9b47610338f59f03f6b4fdc0280d6aa61c266d4f 100644 (file)
@@ -154,7 +154,7 @@ static void nfs_zap_caches_locked(struct inode *inode)
        nfsi->attrtimeo = NFS_MINATTRTIMEO(inode);
        nfsi->attrtimeo_timestamp = jiffies;
 
-       memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode)));
+       memset(NFS_I(inode)->cookieverf, 0, sizeof(NFS_I(inode)->cookieverf));
        if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))
                nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE;
        else
index d6b3b5f2d779acd1ce7e0324e8c52e388c7a273a..69322096c32569d4674517f7121e4fc272206ba8 100644 (file)
@@ -643,7 +643,7 @@ nfs3_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
                  u64 cookie, struct page **pages, unsigned int count, int plus)
 {
        struct inode            *dir = dentry->d_inode;
-       __be32                  *verf = NFS_COOKIEVERF(dir);
+       __be32                  *verf = NFS_I(dir)->cookieverf;
        struct nfs3_readdirargs arg = {
                .fh             = NFS_FH(dir),
                .cookie         = cookie,
index acb65e7887f8437b8aac391255f4be1218524a27..eb5eb8eef4d34db3c7bafe3c84c1db0bf43e8974 100644 (file)
@@ -96,13 +96,15 @@ nfs4_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
        struct inode *inode = file->f_path.dentry->d_inode;
 
        ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
+       if (ret != 0)
+               goto out;
        mutex_lock(&inode->i_mutex);
        ret = nfs_file_fsync_commit(file, start, end, datasync);
        if (!ret && !datasync)
                /* application has asked for meta-data sync */
                ret = pnfs_layoutcommit_inode(inode, true);
        mutex_unlock(&inode->i_mutex);
-
+out:
        return ret;
 }
 
index 635274140b180287668dbaa7540bd84852051181..1e50326d00ddd1f7ef8931470bc1cd0ad32b4015 100644 (file)
@@ -3215,11 +3215,11 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
                        dentry->d_parent->d_name.name,
                        dentry->d_name.name,
                        (unsigned long long)cookie);
-       nfs4_setup_readdir(cookie, NFS_COOKIEVERF(dir), dentry, &args);
+       nfs4_setup_readdir(cookie, NFS_I(dir)->cookieverf, dentry, &args);
        res.pgbase = args.pgbase;
        status = nfs4_call_sync(NFS_SERVER(dir)->client, NFS_SERVER(dir), &msg, &args.seq_args, &res.seq_res, 0);
        if (status >= 0) {
-               memcpy(NFS_COOKIEVERF(dir), res.verifier.data, NFS4_VERIFIER_SIZE);
+               memcpy(NFS_I(dir)->cookieverf, res.verifier.data, NFS4_VERIFIER_SIZE);
                status += args.pgbase;
        }
 
@@ -3653,11 +3653,11 @@ static inline int nfs4_server_supports_acls(struct nfs_server *server)
                && (server->acl_bitmask & ACL4_SUPPORT_DENY_ACL);
 }
 
-/* Assuming that XATTR_SIZE_MAX is a multiple of PAGE_CACHE_SIZE, and that
- * it's OK to put sizeof(void) * (XATTR_SIZE_MAX/PAGE_CACHE_SIZE) bytes on
+/* Assuming that XATTR_SIZE_MAX is a multiple of PAGE_SIZE, and that
+ * it's OK to put sizeof(void) * (XATTR_SIZE_MAX/PAGE_SIZE) bytes on
  * the stack.
  */
-#define NFS4ACL_MAXPAGES (XATTR_SIZE_MAX >> PAGE_CACHE_SHIFT)
+#define NFS4ACL_MAXPAGES DIV_ROUND_UP(XATTR_SIZE_MAX, PAGE_SIZE)
 
 static int buf_to_pages_noslab(const void *buf, size_t buflen,
                struct page **pages, unsigned int *pgbase)
@@ -3668,7 +3668,7 @@ static int buf_to_pages_noslab(const void *buf, size_t buflen,
        spages = pages;
 
        do {
-               len = min_t(size_t, PAGE_CACHE_SIZE, buflen);
+               len = min_t(size_t, PAGE_SIZE, buflen);
                newpage = alloc_page(GFP_KERNEL);
 
                if (newpage == NULL)
@@ -3739,7 +3739,7 @@ static void nfs4_write_cached_acl(struct inode *inode, struct page **pages, size
        struct nfs4_cached_acl *acl;
        size_t buflen = sizeof(*acl) + acl_len;
 
-       if (pages && buflen <= PAGE_SIZE) {
+       if (buflen <= PAGE_SIZE) {
                acl = kmalloc(buflen, GFP_KERNEL);
                if (acl == NULL)
                        goto out;
@@ -3782,17 +3782,15 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu
                .rpc_argp = &args,
                .rpc_resp = &res,
        };
-       int ret = -ENOMEM, npages, i;
-       size_t acl_len = 0;
+       unsigned int npages = DIV_ROUND_UP(buflen, PAGE_SIZE);
+       int ret = -ENOMEM, i;
 
-       npages = (buflen + PAGE_SIZE - 1) >> PAGE_SHIFT;
        /* As long as we're doing a round trip to the server anyway,
         * let's be prepared for a page of acl data. */
        if (npages == 0)
                npages = 1;
-
-       /* Add an extra page to handle the bitmap returned */
-       npages++;
+       if (npages > ARRAY_SIZE(pages))
+               return -ERANGE;
 
        for (i = 0; i < npages; i++) {
                pages[i] = alloc_page(GFP_KERNEL);
@@ -3808,11 +3806,6 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu
        args.acl_len = npages * PAGE_SIZE;
        args.acl_pgbase = 0;
 
-       /* Let decode_getfacl know not to fail if the ACL data is larger than
-        * the page we send as a guess */
-       if (buf == NULL)
-               res.acl_flags |= NFS4_ACL_LEN_REQUEST;
-
        dprintk("%s  buf %p buflen %zu npages %d args.acl_len %zu\n",
                __func__, buf, buflen, npages, args.acl_len);
        ret = nfs4_call_sync(NFS_SERVER(inode)->client, NFS_SERVER(inode),
@@ -3820,20 +3813,19 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu
        if (ret)
                goto out_free;
 
-       acl_len = res.acl_len;
-       if (acl_len > args.acl_len)
-               nfs4_write_cached_acl(inode, NULL, 0, acl_len);
-       else
-               nfs4_write_cached_acl(inode, pages, res.acl_data_offset,
-                                     acl_len);
-       if (buf) {
+       /* Handle the case where the passed-in buffer is too short */
+       if (res.acl_flags & NFS4_ACL_TRUNC) {
+               /* Did the user only issue a request for the acl length? */
+               if (buf == NULL)
+                       goto out_ok;
                ret = -ERANGE;
-               if (acl_len > buflen)
-                       goto out_free;
-               _copy_from_pages(buf, pages, res.acl_data_offset,
-                               acl_len);
+               goto out_free;
        }
-       ret = acl_len;
+       nfs4_write_cached_acl(inode, pages, res.acl_data_offset, res.acl_len);
+       if (buf)
+               _copy_from_pages(buf, pages, res.acl_data_offset, res.acl_len);
+out_ok:
+       ret = res.acl_len;
 out_free:
        for (i = 0; i < npages; i++)
                if (pages[i])
@@ -3891,10 +3883,13 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl
                .rpc_argp       = &arg,
                .rpc_resp       = &res,
        };
+       unsigned int npages = DIV_ROUND_UP(buflen, PAGE_SIZE);
        int ret, i;
 
        if (!nfs4_server_supports_acls(server))
                return -EOPNOTSUPP;
+       if (npages > ARRAY_SIZE(pages))
+               return -ERANGE;
        i = buf_to_pages_noslab(buf, buflen, arg.acl_pages, &arg.acl_pgbase);
        if (i < 0)
                return i;
index 1bfbd67c556d753a21f046c87edc3c9b07b0b8f0..8dba6bd485578695fb791f8aa548bc8ac99b4391 100644 (file)
@@ -5072,18 +5072,14 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req,
                 * are stored with the acl data to handle the problem of
                 * variable length bitmaps.*/
                res->acl_data_offset = xdr_stream_pos(xdr) - pg_offset;
-
-               /* We ignore &savep and don't do consistency checks on
-                * the attr length.  Let userspace figure it out.... */
                res->acl_len = attrlen;
-               if (attrlen > (xdr->nwords << 2)) {
-                       if (res->acl_flags & NFS4_ACL_LEN_REQUEST) {
-                               /* getxattr interface called with a NULL buf */
-                               goto out;
-                       }
+
+               /* Check for receive buffer overflow */
+               if (res->acl_len > (xdr->nwords << 2) ||
+                   res->acl_len + res->acl_data_offset > xdr->buf->page_len) {
+                       res->acl_flags |= NFS4_ACL_TRUNC;
                        dprintk("NFS: acl reply: attrlen %u > page_len %u\n",
                                        attrlen, xdr->nwords << 2);
-                       return -EINVAL;
                }
        } else
                status = -EOPNOTSUPP;
@@ -6229,7 +6225,8 @@ static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
        status = decode_open(xdr, res);
        if (status)
                goto out;
-       if (decode_getfh(xdr, &res->fh) != 0)
+       status = decode_getfh(xdr, &res->fh);
+       if (status)
                goto out;
        decode_getfattr(xdr, res->f_attr, res->server);
 out:
index 239aff7338eb89ee8c0d4080694178317d84929e..b8eda700584bfbd25086d898a21b3fd03959030d 100644 (file)
@@ -1867,6 +1867,7 @@ static int nfs23_validate_mount_data(void *options,
 
                memcpy(sap, &data->addr, sizeof(data->addr));
                args->nfs_server.addrlen = sizeof(data->addr);
+               args->nfs_server.port = ntohs(data->addr.sin_port);
                if (!nfs_verify_server_address(sap))
                        goto out_no_address;
 
@@ -2564,6 +2565,7 @@ static int nfs4_validate_mount_data(void *options,
                        return -EFAULT;
                if (!nfs_verify_server_address(sap))
                        goto out_no_address;
+               args->nfs_server.port = ntohs(((struct sockaddr_in *)sap)->sin_port);
 
                if (data->auth_flavourlen) {
                        if (data->auth_flavourlen > 1)
index dfafeb2b05a0e2ddc5481b2b2a4f445ec8086a0e..eb7cc91b7258870f89b77a60de4172dd6f1502b6 100644 (file)
@@ -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;
 }
index b6ff11825fc8a9c37f8d45ccf01e1fbdc1115868..40780229a03281376d4d449e896745f3f169a0d3 100644 (file)
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -58,7 +58,7 @@ EXPORT_SYMBOL(vfs_getattr);
 int vfs_fstat(unsigned int fd, struct kstat *stat)
 {
        int fput_needed;
-       struct file *f = fget_light(fd, &fput_needed);
+       struct file *f = fget_raw_light(fd, &fput_needed);
        int error = -EBADF;
 
        if (f) {
index 7f3f7ba3df6e7526b78699dd17a7439380611461..d1c6093fd3d3c8a204b6cca9dfc8ced300da075f 100644 (file)
 #include "udf_i.h"
 #include "udf_sb.h"
 
-static int udf_adinicb_readpage(struct file *file, struct page *page)
+static void __udf_adinicb_readpage(struct page *page)
 {
        struct inode *inode = page->mapping->host;
        char *kaddr;
        struct udf_inode_info *iinfo = UDF_I(inode);
 
-       BUG_ON(!PageLocked(page));
-
        kaddr = kmap(page);
-       memset(kaddr, 0, PAGE_CACHE_SIZE);
        memcpy(kaddr, iinfo->i_ext.i_data + iinfo->i_lenEAttr, inode->i_size);
+       memset(kaddr + inode->i_size, 0, PAGE_CACHE_SIZE - inode->i_size);
        flush_dcache_page(page);
        SetPageUptodate(page);
        kunmap(page);
+}
+
+static int udf_adinicb_readpage(struct file *file, struct page *page)
+{
+       BUG_ON(!PageLocked(page));
+       __udf_adinicb_readpage(page);
        unlock_page(page);
 
        return 0;
@@ -77,6 +81,25 @@ static int udf_adinicb_writepage(struct page *page,
        return 0;
 }
 
+static int udf_adinicb_write_begin(struct file *file,
+                       struct address_space *mapping, loff_t pos,
+                       unsigned len, unsigned flags, struct page **pagep,
+                       void **fsdata)
+{
+       struct page *page;
+
+       if (WARN_ON_ONCE(pos >= PAGE_CACHE_SIZE))
+               return -EIO;
+       page = grab_cache_page_write_begin(mapping, 0, flags);
+       if (!page)
+               return -ENOMEM;
+       *pagep = page;
+
+       if (!PageUptodate(page) && len != PAGE_CACHE_SIZE)
+               __udf_adinicb_readpage(page);
+       return 0;
+}
+
 static int udf_adinicb_write_end(struct file *file,
                        struct address_space *mapping,
                        loff_t pos, unsigned len, unsigned copied,
@@ -98,8 +121,8 @@ static int udf_adinicb_write_end(struct file *file,
 const struct address_space_operations udf_adinicb_aops = {
        .readpage       = udf_adinicb_readpage,
        .writepage      = udf_adinicb_writepage,
-       .write_begin = simple_write_begin,
-       .write_end = udf_adinicb_write_end,
+       .write_begin    = udf_adinicb_write_begin,
+       .write_end      = udf_adinicb_write_end,
 };
 
 static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
index 4d45b7189e7eaa352da0567b8fe4a2d1b738c999..107f457143c35ffbcb9ad39ae52815a81332fcec 100644 (file)
@@ -295,11 +295,13 @@ vfs_removexattr(struct dentry *dentry, const char *name)
        if (error)
                return error;
 
+       mutex_lock(&inode->i_mutex);
        error = security_inode_removexattr(dentry, name);
-       if (error)
+       if (error) {
+               mutex_unlock(&inode->i_mutex);
                return error;
+       }
 
-       mutex_lock(&inode->i_mutex);
        error = inode->i_op->removexattr(dentry, name);
        mutex_unlock(&inode->i_mutex);
 
index d7a9dd735e1e429a1787d8b0e8e1c9ddde5eff10..933b7930b8636da970a627d571388b11e8dabde7 100644 (file)
@@ -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);
 
index d03b73b9604e3d55d93f1fdc08201512b01449dd..7c0b6a0a1557c0d30db4b94e4bc27879d2614537 100644 (file)
@@ -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 */
index bdaf4cb9f4a2d19fc8b781f232f61d88c529ac2a..19e2380fb8679d2e8641e691eaeb0b200456bfb4 100644 (file)
@@ -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);
index bdf0152cbbe95b2747f0736366f520eabb193ea9..f4621184a9b404f8f7a81dfb130258def67cbd58 100644 (file)
 #define DRM_FORMAT_NV16                fourcc_code('N', 'V', '1', '6') /* 2x1 subsampled Cr:Cb plane */
 #define DRM_FORMAT_NV61                fourcc_code('N', 'V', '6', '1') /* 2x1 subsampled Cb:Cr plane */
 
-/* 2 non contiguous plane YCbCr */
-#define DRM_FORMAT_NV12M       fourcc_code('N', 'M', '1', '2') /* 2x2 subsampled Cr:Cb plane */
+/* special NV12 tiled format */
 #define DRM_FORMAT_NV12MT      fourcc_code('T', 'M', '1', '2') /* 2x2 subsampled Cr:Cb plane 64x32 macroblocks */
 
 /*
 #define DRM_FORMAT_YUV444      fourcc_code('Y', 'U', '2', '4') /* non-subsampled Cb (1) and Cr (2) planes */
 #define DRM_FORMAT_YVU444      fourcc_code('Y', 'V', '2', '4') /* non-subsampled Cr (1) and Cb (2) planes */
 
-/* 3 non contiguous plane YCbCr */
-#define DRM_FORMAT_YUV420M     fourcc_code('Y', 'M', '1', '2') /* 2x2 subsampled Cb (1) and Cr (2) planes */
-
 #endif /* DRM_FOURCC_H */
index 06023393fba97cfc069ae119f66d84b1bdb0b256..4eb31752e2b77592e8a2fdbf3fde779d4851504d 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <linux/platform_device.h>
 #include <linux/list.h>
+#include <linux/io.h>
 
 struct ssc_device {
        struct list_head        list;
index 36abf2aa7e680e24afe8c52b87ccf8f88707ee17..2a5073cf548a0d848f99c7810a124bded3313eb9 100644 (file)
@@ -529,6 +529,7 @@ extern int  audit_set_loginuid(uid_t loginuid);
 #define audit_get_loginuid(t) ((t)->loginuid)
 #define audit_get_sessionid(t) ((t)->sessionid)
 extern void audit_log_task_context(struct audit_buffer *ab);
+extern void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk);
 extern void __audit_ipc_obj(struct kern_ipc_perm *ipcp);
 extern void __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, umode_t mode);
 extern int __audit_bprm(struct linux_binprm *bprm);
@@ -640,6 +641,7 @@ extern int audit_signals;
 #define audit_get_loginuid(t) (-1)
 #define audit_get_sessionid(t) (-1)
 #define audit_log_task_context(b) do { ; } while (0)
+#define audit_log_task_info(b, t) do { ; } while (0)
 #define audit_ipc_obj(i) ((void)0)
 #define audit_ipc_set_perm(q,u,g,m) ((void)0)
 #define audit_bprm(p) ({ 0; })
index 2f4079175afb81f80f641e28da9b1145b5415bae..934bc34d5f993892f75c3b803d412b43e62dc072 100644 (file)
 #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
index 923d093c9ceac685f199868a8b49fa58349aa554..f430e4162f41ea188fdb5168df28b4304b7c14c3 100644 (file)
@@ -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))
index ebbed2ce66379bd986fbf83f11e7ae8c32bf6070..0142aacb70b7049583a1618c735c7410a6827d65 100644 (file)
@@ -76,21 +76,6 @@ extern int groups_search(const struct group_info *, kgid_t);
 extern int in_group_p(kgid_t);
 extern int in_egroup_p(kgid_t);
 
-/*
- * The common credentials for a thread group
- * - shared by CLONE_THREAD
- */
-#ifdef CONFIG_KEYS
-struct thread_group_cred {
-       atomic_t        usage;
-       pid_t           tgid;                   /* thread group process ID */
-       spinlock_t      lock;
-       struct key __rcu *session_keyring;      /* keyring inherited over fork */
-       struct key      *process_keyring;       /* keyring private to this process */
-       struct rcu_head rcu;                    /* RCU deletion hook */
-};
-#endif
-
 /*
  * The security context of a task
  *
@@ -139,6 +124,8 @@ struct cred {
 #ifdef CONFIG_KEYS
        unsigned char   jit_keyring;    /* default keyring to attach requested
                                         * keys to */
+       struct key __rcu *session_keyring; /* keyring inherited over fork */
+       struct key      *process_keyring; /* keyring private to this process */
        struct key      *thread_keyring; /* keyring private to this thread */
        struct key      *request_key_auth; /* assumed request_key authority */
        struct thread_group_cred *tgcred; /* thread-group shared credentials */
index caa34e50537e895a7a4b5149148f03157e253129..59200795482eebccde8497372c82d1aca0cadd40 100644 (file)
@@ -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)
index 1bc74afe7a35c7ea248510874910525d0206c9c3..49ed17fdf0556436cd626e52e0a9cd9809bc610a 100644 (file)
@@ -22,6 +22,7 @@ struct i2c_pnx_mif {
        struct timer_list       timer;          /* Timeout */
        u8 *                    buf;            /* Data buffer */
        int                     len;            /* Length of data buffer */
+       int                     order;          /* RX Bytes to order via TX */
 };
 
 struct i2c_pnx_algo_data {
index 6ac8e50c6cf5453e338fec108f9dd1418046e3e9..2c7223d7e73b720de899756e3a0433a813c2640e 100644 (file)
@@ -39,5 +39,32 @@ static inline int ima_file_mmap(struct file *file, unsigned long prot)
 {
        return 0;
 }
+
 #endif /* CONFIG_IMA_H */
+
+#ifdef CONFIG_IMA_APPRAISE
+extern void ima_inode_post_setattr(struct dentry *dentry);
+extern int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name,
+                      const void *xattr_value, size_t xattr_value_len);
+extern int ima_inode_removexattr(struct dentry *dentry, const char *xattr_name);
+#else
+static inline void ima_inode_post_setattr(struct dentry *dentry)
+{
+       return;
+}
+
+static inline int ima_inode_setxattr(struct dentry *dentry,
+                                    const char *xattr_name,
+                                    const void *xattr_value,
+                                    size_t xattr_value_len)
+{
+       return 0;
+}
+
+static inline int ima_inode_removexattr(struct dentry *dentry,
+                                       const char *xattr_name)
+{
+       return 0;
+}
+#endif /* CONFIG_IMA_APPRAISE_H */
 #endif /* _LINUX_IMA_H */
index a0c41256cb923d5ffb21d9f4acd20680d3fc54a0..66c5fe9550a5e47bfc2a32c67e1339eb7d4f92ae 100644 (file)
@@ -22,13 +22,14 @@ enum integrity_status {
 
 /* List of EVM protected security xattrs */
 #ifdef CONFIG_INTEGRITY
-extern int integrity_inode_alloc(struct inode *inode);
+extern struct integrity_iint_cache *integrity_inode_get(struct inode *inode);
 extern void integrity_inode_free(struct inode *inode);
 
 #else
-static inline int integrity_inode_alloc(struct inode *inode)
+static inline struct integrity_iint_cache *
+                               integrity_inode_get(struct inode *inode)
 {
-       return 0;
+       return NULL;
 }
 
 static inline void integrity_inode_free(struct inode *inode)
index 594b419b7d20229cf79715b1250124491abe4ca6..2451f1f7a1d969f29bb2a3137c846566bfaf614a 100644 (file)
@@ -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));        \
 }                                                      \
index cef3b315ba7c2e0786e78940cc476c8e12bc89ce..890699815212009a4ba7bf08cdb86f7128477408 100644 (file)
@@ -264,6 +264,7 @@ extern int key_unlink(struct key *keyring,
 
 extern struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid,
                                 const struct cred *cred,
+                                key_perm_t perm,
                                 unsigned long flags,
                                 struct key *dest);
 
index fc615a97e2d363df686f6111988cf686d8e03dfa..1e57449395b16db43ecfb638b71acc533e9ec73b 100644 (file)
@@ -224,7 +224,7 @@ static inline int kobject_uevent_env(struct kobject *kobj,
 
 static inline __printf(2, 3)
 int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...)
-{ return 0; }
+{ return -ENOMEM; }
 
 static inline int kobject_action_type(const char *buf, size_t count,
                                      enum kobject_action *type)
index d0752eca9b4495011f6f82b20ba4e487b06ad6da..9d96d5d4dfed30f19c5ddeb04bacacd44f08bd45 100644 (file)
@@ -183,7 +183,7 @@ extern int  mISDN_initbchannel(struct bchannel *, unsigned short,
                                   unsigned short);
 extern int     mISDN_freedchannel(struct dchannel *);
 extern void    mISDN_clear_bchannel(struct bchannel *);
-extern int     mISDN_freebchannel(struct bchannel *);
+extern void    mISDN_freebchannel(struct bchannel *);
 extern int     mISDN_ctrl_bchannel(struct bchannel *, struct mISDN_ctrl_req *);
 extern void    queue_ch_frame(struct mISDNchannel *, u_int,
                        int, struct sk_buff *);
index 1ac7f6e405f9e2fe3556cb02135393b9b818af24..ff9a9f8e0ed9deb1573c087475511b269b7e17e2 100644 (file)
@@ -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;
index 3a8435a8058f1cec9357b3f980efb0eae18f5569..cebe97ee98b86e1d6f6ef478ddf84693d8486d6b 100644 (file)
@@ -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);
 
index 12c06870829af2add4caed14a9ea57f069b7479f..7cd83d826ed82285099c55cc7008dc558feddcb2 100644 (file)
@@ -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,
index bd6c9fcdf2dd30c29b582a38e5f5c3f1eb320b62..6e1b0f973a03511b398154a5d42f3a9174b9268a 100644 (file)
@@ -796,6 +796,19 @@ enum mlx4_net_trans_rule_id {
        MLX4_NET_TRANS_RULE_NUM, /* should be last */
 };
 
+extern const u16 __sw_id_hw[];
+
+static inline int map_hw_to_sw_id(u16 header_id)
+{
+
+       int i;
+       for (i = 0; i < MLX4_NET_TRANS_RULE_NUM; i++) {
+               if (header_id == __sw_id_hw[i])
+                       return i;
+       }
+       return -EINVAL;
+}
+
 enum mlx4_net_trans_promisc_mode {
        MLX4_FS_PROMISC_NONE = 0,
        MLX4_FS_PROMISC_UPLINK,
index 1f8fc7f9bcd8b8eb0d07588ba671b9327e53fe90..4b03f56e280eb9e59f236806ce24ce36e435c9c7 100644 (file)
@@ -265,11 +265,6 @@ static inline const struct nfs_rpc_ops *NFS_PROTO(const struct inode *inode)
        return NFS_SERVER(inode)->nfs_client->rpc_ops;
 }
 
-static inline __be32 *NFS_COOKIEVERF(const struct inode *inode)
-{
-       return NFS_I(inode)->cookieverf;
-}
-
 static inline unsigned NFS_MINATTRTIMEO(const struct inode *inode)
 {
        struct nfs_server *nfss = NFS_SERVER(inode);
index ac7c8ae254f251933e48f04d5c877eaaa3ec6e09..be9cf3c7e79ec0afcc0e024f6b95da5ab2bbd97e 100644 (file)
@@ -652,7 +652,7 @@ struct nfs_getaclargs {
 };
 
 /* getxattr ACL interface flags */
-#define NFS4_ACL_LEN_REQUEST   0x0001  /* zero length getxattr buffer */
+#define NFS4_ACL_TRUNC         0x0001  /* ACL was truncated */
 struct nfs_getaclres {
        size_t                          acl_len;
        size_t                          acl_data_offset;
index 7602ccb3f40ec672001be2eae9be3395604493f2..bdb41612bfec621e1aaba5e2468c5b01c6131770 100644 (file)
@@ -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:
  */
@@ -926,7 +928,7 @@ struct perf_event {
        struct hw_perf_event            hw;
 
        struct perf_event_context       *ctx;
-       struct file                     *filp;
+       atomic_long_t                   refcount;
 
        /*
         * These accumulate total time (in nanoseconds) that children
@@ -1296,6 +1298,7 @@ extern int perf_swevent_get_recursion_context(void);
 extern void perf_swevent_put_recursion_context(int rctx);
 extern void perf_event_enable(struct perf_event *event);
 extern void perf_event_disable(struct perf_event *event);
+extern int __perf_event_disable(void *info);
 extern void perf_event_task_tick(void);
 #else
 static inline void
@@ -1334,6 +1337,7 @@ static inline int  perf_swevent_get_recursion_context(void)               { return -1; }
 static inline void perf_swevent_put_recursion_context(int rctx)                { }
 static inline void perf_event_enable(struct perf_event *event)         { }
 static inline void perf_event_disable(struct perf_event *event)                { }
+static inline int __perf_event_disable(void *info)                     { return -1; }
 static inline void perf_event_task_tick(void)                          { }
 #endif
 
index 597e4fdb97fe4d676b5fa0b717ae53f023893e5e..3db698aee34cd9437f8f42823f17825796597f09 100644 (file)
@@ -130,8 +130,6 @@ extern void exit_ptrace(struct task_struct *tracer);
 #define PTRACE_MODE_READ       0x01
 #define PTRACE_MODE_ATTACH     0x02
 #define PTRACE_MODE_NOAUDIT    0x04
-/* Returns 0 on success, -errno on denial. */
-extern int __ptrace_may_access(struct task_struct *task, unsigned int mode);
 /* Returns true on success, false on denial. */
 extern bool ptrace_may_access(struct task_struct *task, unsigned int mode);
 
index b8c86648a2f95dc6f83aab668fd9a7e07f277b4e..23bddac4bad8d08f3781d1e8a453aa41edb28632 100644 (file)
@@ -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 */
index 3dea6a9d568f416ccd1b704eec1d4bff9dea6d90..01ef030b94099edab9e884de3ebc3cf2d3749fae 100644 (file)
@@ -3021,5 +3021,36 @@ static inline void free_secdata(void *secdata)
 { }
 #endif /* CONFIG_SECURITY */
 
+#ifdef CONFIG_SECURITY_YAMA
+extern int yama_ptrace_access_check(struct task_struct *child,
+                                   unsigned int mode);
+extern int yama_ptrace_traceme(struct task_struct *parent);
+extern void yama_task_free(struct task_struct *task);
+extern int yama_task_prctl(int option, unsigned long arg2, unsigned long arg3,
+                          unsigned long arg4, unsigned long arg5);
+#else
+static inline int yama_ptrace_access_check(struct task_struct *child,
+                                          unsigned int mode)
+{
+       return 0;
+}
+
+static inline int yama_ptrace_traceme(struct task_struct *parent)
+{
+       return 0;
+}
+
+static inline void yama_task_free(struct task_struct *task)
+{
+}
+
+static inline int yama_task_prctl(int option, unsigned long arg2,
+                                 unsigned long arg3, unsigned long arg4,
+                                 unsigned long arg5)
+{
+       return -ENOSYS;
+}
+#endif /* CONFIG_SECURITY_YAMA */
+
 #endif /* ! __LINUX_SECURITY_H */
 
index cff40aa7db625bbb9dafd6b5842d3dc70276c682..bf8c49ff7530c7ee8b85d4a8b3ccef5de86ff308 100644 (file)
@@ -114,6 +114,7 @@ struct rpc_xprt_ops {
        void            (*set_buffer_size)(struct rpc_xprt *xprt, size_t sndsize, size_t rcvsize);
        int             (*reserve_xprt)(struct rpc_xprt *xprt, struct rpc_task *task);
        void            (*release_xprt)(struct rpc_xprt *xprt, struct rpc_task *task);
+       void            (*alloc_slot)(struct rpc_xprt *xprt, struct rpc_task *task);
        void            (*rpcbind)(struct rpc_task *task);
        void            (*set_port)(struct rpc_xprt *xprt, unsigned short port);
        void            (*connect)(struct rpc_task *task);
@@ -281,6 +282,8 @@ void                        xprt_connect(struct rpc_task *task);
 void                   xprt_reserve(struct rpc_task *task);
 int                    xprt_reserve_xprt(struct rpc_xprt *xprt, struct rpc_task *task);
 int                    xprt_reserve_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task);
+void                   xprt_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task);
+void                   xprt_lock_and_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task);
 int                    xprt_prepare_transmit(struct rpc_task *task);
 void                   xprt_transmit(struct rpc_task *task);
 void                   xprt_end_transmit(struct rpc_task *task);
index fdc718abf83becac29f7dd3a01cabd8b6ad7f068..fcb627ff8d3eb71ad49ced6763a0ff061b83f62e 100644 (file)
@@ -32,6 +32,7 @@
 extern int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf);
 extern int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash);
 extern int tpm_send(u32 chip_num, void *cmd, size_t buflen);
+extern int tpm_get_random(u32 chip_num, u8 *data, size_t max);
 #else
 static inline int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf) {
        return -ENODEV;
@@ -42,5 +43,8 @@ static inline int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash) {
 static inline int tpm_send(u32 chip_num, void *cmd, size_t buflen) {
        return -ENODEV;
 }
+static inline int tpm_get_random(u32 chip_num, u8 *data, size_t max) {
+       return -ENODEV;
+}
 #endif
 #endif
index e5d122031542f5e3628d5a3bbbd044f0f36f51a3..77a3e686d56627cba522616bd9425ae551b0ce35 100644 (file)
@@ -33,6 +33,9 @@
 #define XATTR_EVM_SUFFIX "evm"
 #define XATTR_NAME_EVM XATTR_SECURITY_PREFIX XATTR_EVM_SUFFIX
 
+#define XATTR_IMA_SUFFIX "ima"
+#define XATTR_NAME_IMA XATTR_SECURITY_PREFIX XATTR_IMA_SUFFIX
+
 #define XATTR_SELINUX_SUFFIX "selinux"
 #define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIX
 
index 22e61fdf75a2bd46a656e164e046a006acd43343..28e493b5b94c9ba6d946d728a0908c84e34294db 100644 (file)
@@ -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;
index ca356a7349202272236b9d7db421f6d8804d89a5..8b27927b2a55de3dfd5f94c5a40ef3c3b886eb06 100644 (file)
@@ -136,7 +136,7 @@ struct smp_chan {
 };
 
 /* SMP Commands */
-int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level);
+int smp_conn_security(struct hci_conn *hcon, __u8 sec_level);
 int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb);
 int smp_distribute_keys(struct l2cap_conn *conn, __u8 force);
 int smp_user_confirm_reply(struct hci_conn *conn, u16 mgmt_op, __le32 passkey);
index 0fedbd8d747a049db1810fdc325b032d62782b1b..9fc7114159e885031550abedebf67c74f08bde76 100644 (file)
@@ -111,9 +111,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;
 
index ae1cd6c9ba521bb6ca9a57706b4ca77180bdcc7a..fd87963a0ea5878cecae892541b9fc9f79e64814 100644 (file)
@@ -102,6 +102,7 @@ struct net {
 #endif
        struct netns_ipvs       *ipvs;
        struct sock             *diag_nlsk;
+       atomic_t                rt_genid;
 };
 
 
@@ -300,5 +301,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 */
index 1474dd65c66f558999a70f38c081dea247fbee5a..eb24dbccd81e81aff5fac76c8792e93df66e7bb6 100644 (file)
@@ -65,7 +65,6 @@ struct netns_ipv4 {
        unsigned int sysctl_ping_group_range[2];
        long sysctl_tcp_mem[3];
 
-       atomic_t rt_genid;
        atomic_t dev_addr_genid;
 
 #ifdef CONFIG_IP_MROUTE
index 776a27f1ab78ef5a385ef8b8d2f21b9e0101e115..da22243d27600cd66b5fb70da61f5cadc05d5468 100644 (file)
@@ -108,7 +108,7 @@ extern struct ip_rt_acct __percpu *ip_rt_acct;
 
 struct in_device;
 extern int             ip_rt_init(void);
-extern void            rt_cache_flush(struct net *net, int how);
+extern void            rt_cache_flush(struct net *net);
 extern void            rt_flush_dev(struct net_device *dev);
 extern struct rtable *__ip_route_output_key(struct net *, struct flowi4 *flp);
 extern struct rtable *ip_route_output_flow(struct net *, struct flowi4 *flp,
index 72132aef53fc61a721ce23c8fbc4fe17cb7a9699..adb7da20b5a10b2679d59734f6f46b971acf0094 100644 (file)
@@ -1332,7 +1332,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;
index 976a81abe1a231de348085a92c8f3110a21fc3fa..639dd1316d375aeb2802c73032cc4cae6dcb8b0c 100644 (file)
@@ -273,6 +273,9 @@ struct xfrm_replay {
        int     (*check)(struct xfrm_state *x,
                         struct sk_buff *skb,
                         __be32 net_seq);
+       int     (*recheck)(struct xfrm_state *x,
+                          struct sk_buff *skb,
+                          __be32 net_seq);
        void    (*notify)(struct xfrm_state *x, int event);
        int     (*overflow)(struct xfrm_state *x, struct sk_buff *skb);
 };
index f1405d335a968d093aadafee06ab4be105970f88..941c84bf1065f406cfbc3eeb5f4b09e4fdcd58ec 100644 (file)
@@ -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 *,
index 015cea01ae39bedd1a1bf796e23a8f90f061e5e2..5be89373ceac659c92e671a463c80f146656c416 100644 (file)
 
 #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 {
index 5f889f16b0c891dbedafd65686c48688aa7110da..08fa27244da740787539bd391ef3d61dc8060158 100644 (file)
@@ -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)
index 11e27c3af3cb45c63d9c689442096b4afd66c55f..f19fff8650e93075aae1717034f29898f1199646 100644 (file)
@@ -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__ */
index 4b96415527b8664753e18cb169f0de9f391f9314..37f52f27828df4890a4dce17c2a8402f013b74f8 100644 (file)
@@ -1154,13 +1154,38 @@ error_path:
 
 EXPORT_SYMBOL(audit_log_task_context);
 
-static void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk)
+void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk)
 {
+       const struct cred *cred;
        char name[sizeof(tsk->comm)];
        struct mm_struct *mm = tsk->mm;
        struct vm_area_struct *vma;
+       char *tty;
+
+       if (!ab)
+               return;
 
        /* tsk == current */
+       cred = current_cred();
+
+       spin_lock_irq(&tsk->sighand->siglock);
+       if (tsk->signal && tsk->signal->tty && tsk->signal->tty->name)
+               tty = tsk->signal->tty->name;
+       else
+               tty = "(none)";
+       spin_unlock_irq(&tsk->sighand->siglock);
+
+
+       audit_log_format(ab,
+                        " ppid=%ld pid=%d auid=%u uid=%u gid=%u"
+                        " euid=%u suid=%u fsuid=%u"
+                        " egid=%u sgid=%u fsgid=%u ses=%u tty=%s",
+                        sys_getppid(),
+                        tsk->pid,
+                        tsk->loginuid, cred->uid, cred->gid,
+                        cred->euid, cred->suid, cred->fsuid,
+                        cred->egid, cred->sgid, cred->fsgid,
+                        tsk->sessionid, tty);
 
        get_task_comm(name, tsk);
        audit_log_format(ab, " comm=");
@@ -1183,6 +1208,8 @@ static void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk
        audit_log_task_context(ab);
 }
 
+EXPORT_SYMBOL(audit_log_task_info);
+
 static int audit_log_pid_context(struct audit_context *context, pid_t pid,
                                 uid_t auid, uid_t uid, unsigned int sessionid,
                                 u32 sid, char *comm)
@@ -1585,26 +1612,12 @@ static void audit_log_name(struct audit_context *context, struct audit_names *n,
 
 static void audit_log_exit(struct audit_context *context, struct task_struct *tsk)
 {
-       const struct cred *cred;
        int i, call_panic = 0;
        struct audit_buffer *ab;
        struct audit_aux_data *aux;
-       const char *tty;
        struct audit_names *n;
 
        /* tsk == current */
-       context->pid = tsk->pid;
-       if (!context->ppid)
-               context->ppid = sys_getppid();
-       cred = current_cred();
-       context->uid   = cred->uid;
-       context->gid   = cred->gid;
-       context->euid  = cred->euid;
-       context->suid  = cred->suid;
-       context->fsuid = cred->fsuid;
-       context->egid  = cred->egid;
-       context->sgid  = cred->sgid;
-       context->fsgid = cred->fsgid;
        context->personality = tsk->personality;
 
        ab = audit_log_start(context, GFP_KERNEL, AUDIT_SYSCALL);
@@ -1619,32 +1632,13 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
                                 (context->return_valid==AUDITSC_SUCCESS)?"yes":"no",
                                 context->return_code);
 
-       spin_lock_irq(&tsk->sighand->siglock);
-       if (tsk->signal && tsk->signal->tty && tsk->signal->tty->name)
-               tty = tsk->signal->tty->name;
-       else
-               tty = "(none)";
-       spin_unlock_irq(&tsk->sighand->siglock);
-
        audit_log_format(ab,
-                 " a0=%lx a1=%lx a2=%lx a3=%lx items=%d"
-                 " ppid=%d pid=%d auid=%u uid=%u gid=%u"
-                 " euid=%u suid=%u fsuid=%u"
-                 " egid=%u sgid=%u fsgid=%u tty=%s ses=%u",
-                 context->argv[0],
-                 context->argv[1],
-                 context->argv[2],
-                 context->argv[3],
-                 context->name_count,
-                 context->ppid,
-                 context->pid,
-                 tsk->loginuid,
-                 context->uid,
-                 context->gid,
-                 context->euid, context->suid, context->fsuid,
-                 context->egid, context->sgid, context->fsgid, tty,
-                 tsk->sessionid);
-
+                        " a0=%lx a1=%lx a2=%lx a3=%lx items=%d",
+                        context->argv[0],
+                        context->argv[1],
+                        context->argv[2],
+                        context->argv[3],
+                        context->name_count);
 
        audit_log_task_info(ab, tsk);
        audit_log_key(ab, context->filterkey);
index de728ac50d821b9f38340534a4ba6202137d55a2..3f7ad1ec2ae43b20c8e952feab4003d9b7b50535 100644 (file)
 
 static struct kmem_cache *cred_jar;
 
-/*
- * The common credentials for the initial task's thread group
- */
-#ifdef CONFIG_KEYS
-static struct thread_group_cred init_tgcred = {
-       .usage  = ATOMIC_INIT(2),
-       .tgid   = 0,
-       .lock   = __SPIN_LOCK_UNLOCKED(init_cred.tgcred.lock),
-};
-#endif
-
 /*
  * The initial credentials for the initial task
  */
@@ -65,9 +54,6 @@ struct cred init_cred = {
        .user                   = INIT_USER,
        .user_ns                = &init_user_ns,
        .group_info             = &init_groups,
-#ifdef CONFIG_KEYS
-       .tgcred                 = &init_tgcred,
-#endif
 };
 
 static inline void set_cred_subscribers(struct cred *cred, int n)
@@ -95,36 +81,6 @@ static inline void alter_cred_subscribers(const struct cred *_cred, int n)
 #endif
 }
 
-/*
- * Dispose of the shared task group credentials
- */
-#ifdef CONFIG_KEYS
-static void release_tgcred_rcu(struct rcu_head *rcu)
-{
-       struct thread_group_cred *tgcred =
-               container_of(rcu, struct thread_group_cred, rcu);
-
-       BUG_ON(atomic_read(&tgcred->usage) != 0);
-
-       key_put(tgcred->session_keyring);
-       key_put(tgcred->process_keyring);
-       kfree(tgcred);
-}
-#endif
-
-/*
- * Release a set of thread group credentials.
- */
-static void release_tgcred(struct cred *cred)
-{
-#ifdef CONFIG_KEYS
-       struct thread_group_cred *tgcred = cred->tgcred;
-
-       if (atomic_dec_and_test(&tgcred->usage))
-               call_rcu(&tgcred->rcu, release_tgcred_rcu);
-#endif
-}
-
 /*
  * The RCU callback to actually dispose of a set of credentials
  */
@@ -150,9 +106,10 @@ static void put_cred_rcu(struct rcu_head *rcu)
 #endif
 
        security_cred_free(cred);
+       key_put(cred->session_keyring);
+       key_put(cred->process_keyring);
        key_put(cred->thread_keyring);
        key_put(cred->request_key_auth);
-       release_tgcred(cred);
        if (cred->group_info)
                put_group_info(cred->group_info);
        free_uid(cred->user);
@@ -246,15 +203,6 @@ struct cred *cred_alloc_blank(void)
        if (!new)
                return NULL;
 
-#ifdef CONFIG_KEYS
-       new->tgcred = kzalloc(sizeof(*new->tgcred), GFP_KERNEL);
-       if (!new->tgcred) {
-               kmem_cache_free(cred_jar, new);
-               return NULL;
-       }
-       atomic_set(&new->tgcred->usage, 1);
-#endif
-
        atomic_set(&new->usage, 1);
 #ifdef CONFIG_DEBUG_CREDENTIALS
        new->magic = CRED_MAGIC;
@@ -308,9 +256,10 @@ struct cred *prepare_creds(void)
        get_user_ns(new->user_ns);
 
 #ifdef CONFIG_KEYS
+       key_get(new->session_keyring);
+       key_get(new->process_keyring);
        key_get(new->thread_keyring);
        key_get(new->request_key_auth);
-       atomic_inc(&new->tgcred->usage);
 #endif
 
 #ifdef CONFIG_SECURITY
@@ -334,39 +283,20 @@ EXPORT_SYMBOL(prepare_creds);
  */
 struct cred *prepare_exec_creds(void)
 {
-       struct thread_group_cred *tgcred = NULL;
        struct cred *new;
 
-#ifdef CONFIG_KEYS
-       tgcred = kmalloc(sizeof(*tgcred), GFP_KERNEL);
-       if (!tgcred)
-               return NULL;
-#endif
-
        new = prepare_creds();
-       if (!new) {
-               kfree(tgcred);
+       if (!new)
                return new;
-       }
 
 #ifdef CONFIG_KEYS
        /* newly exec'd tasks don't get a thread keyring */
        key_put(new->thread_keyring);
        new->thread_keyring = NULL;
 
-       /* create a new per-thread-group creds for all this set of threads to
-        * share */
-       memcpy(tgcred, new->tgcred, sizeof(struct thread_group_cred));
-
-       atomic_set(&tgcred->usage, 1);
-       spin_lock_init(&tgcred->lock);
-
        /* inherit the session keyring; new process keyring */
-       key_get(tgcred->session_keyring);
-       tgcred->process_keyring = NULL;
-
-       release_tgcred(new);
-       new->tgcred = tgcred;
+       key_put(new->process_keyring);
+       new->process_keyring = NULL;
 #endif
 
        return new;
@@ -383,9 +313,6 @@ struct cred *prepare_exec_creds(void)
  */
 int copy_creds(struct task_struct *p, unsigned long clone_flags)
 {
-#ifdef CONFIG_KEYS
-       struct thread_group_cred *tgcred;
-#endif
        struct cred *new;
        int ret;
 
@@ -425,22 +352,12 @@ int copy_creds(struct task_struct *p, unsigned long clone_flags)
                        install_thread_keyring_to_cred(new);
        }
 
-       /* we share the process and session keyrings between all the threads in
-        * a process - this is slightly icky as we violate COW credentials a
-        * bit */
+       /* The process keyring is only shared between the threads in a process;
+        * anything outside of those threads doesn't inherit.
+        */
        if (!(clone_flags & CLONE_THREAD)) {
-               tgcred = kmalloc(sizeof(*tgcred), GFP_KERNEL);
-               if (!tgcred) {
-                       ret = -ENOMEM;
-                       goto error_put;
-               }
-               atomic_set(&tgcred->usage, 1);
-               spin_lock_init(&tgcred->lock);
-               tgcred->process_keyring = NULL;
-               tgcred->session_keyring = key_get(new->tgcred->session_keyring);
-
-               release_tgcred(new);
-               new->tgcred = tgcred;
+               key_put(new->process_keyring);
+               new->process_keyring = NULL;
        }
 #endif
 
@@ -643,9 +560,6 @@ void __init cred_init(void)
  */
 struct cred *prepare_kernel_cred(struct task_struct *daemon)
 {
-#ifdef CONFIG_KEYS
-       struct thread_group_cred *tgcred;
-#endif
        const struct cred *old;
        struct cred *new;
 
@@ -653,14 +567,6 @@ struct cred *prepare_kernel_cred(struct task_struct *daemon)
        if (!new)
                return NULL;
 
-#ifdef CONFIG_KEYS
-       tgcred = kmalloc(sizeof(*tgcred), GFP_KERNEL);
-       if (!tgcred) {
-               kmem_cache_free(cred_jar, new);
-               return NULL;
-       }
-#endif
-
        kdebug("prepare_kernel_cred() alloc %p", new);
 
        if (daemon)
@@ -678,13 +584,10 @@ struct cred *prepare_kernel_cred(struct task_struct *daemon)
        get_group_info(new->group_info);
 
 #ifdef CONFIG_KEYS
-       atomic_set(&tgcred->usage, 1);
-       spin_lock_init(&tgcred->lock);
-       tgcred->process_keyring = NULL;
-       tgcred->session_keyring = NULL;
-       new->tgcred = tgcred;
-       new->request_key_auth = NULL;
+       new->session_keyring = NULL;
+       new->process_keyring = NULL;
        new->thread_keyring = NULL;
+       new->request_key_auth = NULL;
        new->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
 #endif
 
index b7935fcec7d923b0b0b89fe0fe7dfdf61967b447..7fee567153f022cc2a097135a524bf393887e1a2 100644 (file)
@@ -1253,7 +1253,7 @@ retry:
 /*
  * Cross CPU call to disable a performance event
  */
-static int __perf_event_disable(void *info)
+int __perf_event_disable(void *info)
 {
        struct perf_event *event = info;
        struct perf_event_context *ctx = event->ctx;
@@ -2935,12 +2935,12 @@ EXPORT_SYMBOL_GPL(perf_event_release_kernel);
 /*
  * Called when the last reference to the file is gone.
  */
-static int perf_release(struct inode *inode, struct file *file)
+static void put_event(struct perf_event *event)
 {
-       struct perf_event *event = file->private_data;
        struct task_struct *owner;
 
-       file->private_data = NULL;
+       if (!atomic_long_dec_and_test(&event->refcount))
+               return;
 
        rcu_read_lock();
        owner = ACCESS_ONCE(event->owner);
@@ -2975,7 +2975,13 @@ static int perf_release(struct inode *inode, struct file *file)
                put_task_struct(owner);
        }
 
-       return perf_event_release_kernel(event);
+       perf_event_release_kernel(event);
+}
+
+static int perf_release(struct inode *inode, struct file *file)
+{
+       put_event(file->private_data);
+       return 0;
 }
 
 u64 perf_event_read_value(struct perf_event *event, u64 *enabled, u64 *running)
@@ -3227,7 +3233,7 @@ unlock:
 
 static const struct file_operations perf_fops;
 
-static struct perf_event *perf_fget_light(int fd, int *fput_needed)
+static struct file *perf_fget_light(int fd, int *fput_needed)
 {
        struct file *file;
 
@@ -3241,7 +3247,7 @@ static struct perf_event *perf_fget_light(int fd, int *fput_needed)
                return ERR_PTR(-EBADF);
        }
 
-       return file->private_data;
+       return file;
 }
 
 static int perf_event_set_output(struct perf_event *event,
@@ -3273,19 +3279,21 @@ static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 
        case PERF_EVENT_IOC_SET_OUTPUT:
        {
+               struct file *output_file = NULL;
                struct perf_event *output_event = NULL;
                int fput_needed = 0;
                int ret;
 
                if (arg != -1) {
-                       output_event = perf_fget_light(arg, &fput_needed);
-                       if (IS_ERR(output_event))
-                               return PTR_ERR(output_event);
+                       output_file = perf_fget_light(arg, &fput_needed);
+                       if (IS_ERR(output_file))
+                               return PTR_ERR(output_file);
+                       output_event = output_file->private_data;
                }
 
                ret = perf_event_set_output(event, output_event);
                if (output_event)
-                       fput_light(output_event->filp, fput_needed);
+                       fput_light(output_file, fput_needed);
 
                return ret;
        }
@@ -5950,6 +5958,7 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
 
        mutex_init(&event->mmap_mutex);
 
+       atomic_long_set(&event->refcount, 1);
        event->cpu              = cpu;
        event->attr             = *attr;
        event->group_leader     = group_leader;
@@ -6260,12 +6269,12 @@ SYSCALL_DEFINE5(perf_event_open,
                return event_fd;
 
        if (group_fd != -1) {
-               group_leader = perf_fget_light(group_fd, &fput_needed);
-               if (IS_ERR(group_leader)) {
-                       err = PTR_ERR(group_leader);
+               group_file = perf_fget_light(group_fd, &fput_needed);
+               if (IS_ERR(group_file)) {
+                       err = PTR_ERR(group_file);
                        goto err_fd;
                }
-               group_file = group_leader->filp;
+               group_leader = group_file->private_data;
                if (flags & PERF_FLAG_FD_OUTPUT)
                        output_event = group_leader;
                if (flags & PERF_FLAG_FD_NO_GROUP)
@@ -6402,7 +6411,6 @@ SYSCALL_DEFINE5(perf_event_open,
                put_ctx(gctx);
        }
 
-       event->filp = event_file;
        WARN_ON_ONCE(ctx->parent_ctx);
        mutex_lock(&ctx->mutex);
 
@@ -6496,7 +6504,6 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu,
                goto err_free;
        }
 
-       event->filp = NULL;
        WARN_ON_ONCE(ctx->parent_ctx);
        mutex_lock(&ctx->mutex);
        perf_install_in_context(ctx, event, cpu);
@@ -6578,7 +6585,7 @@ static void sync_child_event(struct perf_event *child_event,
         * Release the parent event, if this was the last
         * reference to it.
         */
-       fput(parent_event->filp);
+       put_event(parent_event);
 }
 
 static void
@@ -6654,9 +6661,8 @@ static void perf_event_exit_task_context(struct task_struct *child, int ctxn)
         *
         *   __perf_event_exit_task()
         *     sync_child_event()
-        *       fput(parent_event->filp)
-        *         perf_release()
-        *           mutex_lock(&ctx->mutex)
+        *       put_event()
+        *         mutex_lock(&ctx->mutex)
         *
         * But since its the parent context it won't be the same instance.
         */
@@ -6724,7 +6730,7 @@ static void perf_free_event(struct perf_event *event,
        list_del_init(&event->child_list);
        mutex_unlock(&parent->child_mutex);
 
-       fput(parent->filp);
+       put_event(parent);
 
        perf_group_detach(event);
        list_del_event(event, ctx);
@@ -6804,6 +6810,12 @@ inherit_event(struct perf_event *parent_event,
                                           NULL, NULL);
        if (IS_ERR(child_event))
                return child_event;
+
+       if (!atomic_long_inc_not_zero(&parent_event->refcount)) {
+               free_event(child_event);
+               return NULL;
+       }
+
        get_ctx(child_ctx);
 
        /*
@@ -6844,14 +6856,6 @@ inherit_event(struct perf_event *parent_event,
        add_event_to_ctx(child_event, child_ctx);
        raw_spin_unlock_irqrestore(&child_ctx->lock, flags);
 
-       /*
-        * Get a reference to the parent filp - we will fput it
-        * when the child event exits. This is safe to do because
-        * we are in the parent and we know that the filp still
-        * exists and has a nonzero count:
-        */
-       atomic_long_inc(&parent_event->filp->f_count);
-
        /*
         * Link this into the parent event's child list
         */
index bb38c4d3ee129ab06c1b46dc295ca6864c39c416..9a7b487c6fe240c1a2e4f5c70ef68da6370ebf78 100644 (file)
@@ -453,7 +453,16 @@ int modify_user_hw_breakpoint(struct perf_event *bp, struct perf_event_attr *att
        int old_type = bp->attr.bp_type;
        int err = 0;
 
-       perf_event_disable(bp);
+       /*
+        * modify_user_hw_breakpoint can be invoked with IRQs disabled and hence it
+        * will not be possible to raise IPIs that invoke __perf_event_disable.
+        * So call the function directly after making sure we are targeting the
+        * current task.
+        */
+       if (irqs_disabled() && bp->ctx && bp->ctx->task == current)
+               __perf_event_disable(bp);
+       else
+               perf_event_disable(bp);
 
        bp->attr.bp_addr = attr->bp_addr;
        bp->attr.bp_type = attr->bp_type;
index b3c7fd5542500ab13940814211692bbe3b7ef8d3..6144bab8fd8eeed14327c116bea39ba0061cbdb5 100644 (file)
@@ -232,15 +232,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,
        },
        { }
 };
index a232bb59d93fa220e3720ce3d068b44d96ca24f3..1f5e55dda955544ca4a3f1f944e967f6b561bea2 100644 (file)
@@ -180,7 +180,8 @@ static int ptrace_has_cap(struct user_namespace *ns, unsigned int mode)
                return has_ns_capability(current, ns, CAP_SYS_PTRACE);
 }
 
-int __ptrace_may_access(struct task_struct *task, unsigned int mode)
+/* Returns 0 on success, -errno on denial. */
+static int __ptrace_may_access(struct task_struct *task, unsigned int mode)
 {
        const struct cred *cred = current_cred(), *tcred;
 
index fbf1fd098dc6cca687f0e9296a931aa0425c6fee..649c9f876cb164b0e16683479b59bf4d4f3b794b 100644 (file)
@@ -5304,27 +5304,17 @@ void idle_task_exit(void)
 }
 
 /*
- * While a dead CPU has no uninterruptible tasks queued at this point,
- * it might still have a nonzero ->nr_uninterruptible counter, because
- * for performance reasons the counter is not stricly tracking tasks to
- * their home CPUs. So we just add the counter to another CPU's counter,
- * to keep the global sum constant after CPU-down:
- */
-static void migrate_nr_uninterruptible(struct rq *rq_src)
-{
-       struct rq *rq_dest = cpu_rq(cpumask_any(cpu_active_mask));
-
-       rq_dest->nr_uninterruptible += rq_src->nr_uninterruptible;
-       rq_src->nr_uninterruptible = 0;
-}
-
-/*
- * remove the tasks which were accounted by rq from calc_load_tasks.
+ * Since this CPU is going 'away' for a while, fold any nr_active delta
+ * we might have. Assumes we're called after migrate_tasks() so that the
+ * nr_active count is stable.
+ *
+ * Also see the comment "Global load-average calculations".
  */
-static void calc_global_load_remove(struct rq *rq)
+static void calc_load_migrate(struct rq *rq)
 {
-       atomic_long_sub(rq->calc_load_active, &calc_load_tasks);
-       rq->calc_load_active = 0;
+       long delta = calc_load_fold_active(rq);
+       if (delta)
+               atomic_long_add(delta, &calc_load_tasks);
 }
 
 /*
@@ -5352,9 +5342,6 @@ static void migrate_tasks(unsigned int dead_cpu)
         */
        rq->stop = NULL;
 
-       /* Ensure any throttled groups are reachable by pick_next_task */
-       unthrottle_offline_cfs_rqs(rq);
-
        for ( ; ; ) {
                /*
                 * There's this thread running, bail when that's the only
@@ -5618,8 +5605,7 @@ migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu)
                BUG_ON(rq->nr_running != 1); /* the migration thread */
                raw_spin_unlock_irqrestore(&rq->lock, flags);
 
-               migrate_nr_uninterruptible(rq);
-               calc_global_load_remove(rq);
+               calc_load_migrate(rq);
                break;
 #endif
        }
@@ -6028,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().
@@ -6046,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;
index c219bf8d704c5460291abee8416264ee32d36e22..96e2b18b628312dd69e8ad2ee6e3a6e08f33cce7 100644 (file)
@@ -2052,7 +2052,7 @@ static void destroy_cfs_bandwidth(struct cfs_bandwidth *cfs_b)
        hrtimer_cancel(&cfs_b->slack_timer);
 }
 
-void unthrottle_offline_cfs_rqs(struct rq *rq)
+static void unthrottle_offline_cfs_rqs(struct rq *rq)
 {
        struct cfs_rq *cfs_rq;
 
@@ -2106,7 +2106,7 @@ static inline struct cfs_bandwidth *tg_cfs_bandwidth(struct task_group *tg)
        return NULL;
 }
 static inline void destroy_cfs_bandwidth(struct cfs_bandwidth *cfs_b) {}
-void unthrottle_offline_cfs_rqs(struct rq *rq) {}
+static inline void unthrottle_offline_cfs_rqs(struct rq *rq) {}
 
 #endif /* CONFIG_CFS_BANDWIDTH */
 
@@ -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;
 }
 
@@ -3658,7 +3672,6 @@ fix_small_capacity(struct sched_domain *sd, struct sched_group *group)
  * @group: sched_group whose statistics are to be updated.
  * @load_idx: Load index of sched_domain of this_cpu for load calc.
  * @local_group: Does group contain this_cpu.
- * @cpus: Set of cpus considered for load balancing.
  * @balance: Should we balance.
  * @sgs: variable to hold the statistics for this group.
  */
@@ -3805,7 +3818,6 @@ static bool update_sd_pick_busiest(struct lb_env *env,
 /**
  * update_sd_lb_stats - Update sched_domain's statistics for load balancing.
  * @env: The load balancing environment.
- * @cpus: Set of cpus considered for load balancing.
  * @balance: Should we balance.
  * @sds: variable to hold the statistics for this sched_domain.
  */
@@ -4956,6 +4968,9 @@ static void rq_online_fair(struct rq *rq)
 static void rq_offline_fair(struct rq *rq)
 {
        update_sysctl();
+
+       /* Ensure any throttled groups are reachable by pick_next_task */
+       unthrottle_offline_cfs_rqs(rq);
 }
 
 #endif /* CONFIG_SMP */
index 944cb68420e957cbde71f9cacaaa4e81c4b1de20..e0b7ba9c040f74b22bb63e0d957b672dac4adce0 100644 (file)
@@ -691,6 +691,7 @@ balanced:
                 * runtime - in which case borrowing doesn't make sense.
                 */
                rt_rq->rt_runtime = RUNTIME_INF;
+               rt_rq->rt_throttled = 0;
                raw_spin_unlock(&rt_rq->rt_runtime_lock);
                raw_spin_unlock(&rt_b->rt_runtime_lock);
        }
index f6714d009e779a225ef295d33ceff7f2f8573be8..0848fa36c383e940a1e4245c611312dbdb7459d3 100644 (file)
@@ -1144,7 +1144,6 @@ extern void print_rt_stats(struct seq_file *m, int cpu);
 
 extern void init_cfs_rq(struct cfs_rq *cfs_rq);
 extern void init_rt_rq(struct rt_rq *rt_rq, struct rq *rq);
-extern void unthrottle_offline_cfs_rqs(struct rq *rq);
 
 extern void account_cfs_bandwidth_used(int enabled, int was_enabled);
 
index 024540f97f74c3e94205826f33d3968ea765f626..3a9e5d5c10916a7e67c131df489617a485a39bfc 100644 (file)
@@ -573,6 +573,7 @@ static void tick_nohz_restart_sched_tick(struct tick_sched *ts, ktime_t now)
        tick_do_update_jiffies64(now);
        update_cpu_load_nohz();
 
+       calc_load_exit_idle();
        touch_softlockup_watchdog();
        /*
         * Cancel the scheduled timer and restore the tick
index 34e5eac81424d98738246415a85d1a98a042bef1..d3b91e75cecd0df7895033aff87f588c6ba2d4df 100644 (file)
@@ -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);
 
index 692d97628a106360683dfef46797952cdf1861e1..3c5a79e2134cac6f404673093a84df5c8b371d80 100644 (file)
@@ -66,6 +66,7 @@ enum {
 
        /* pool flags */
        POOL_MANAGE_WORKERS     = 1 << 0,       /* need to manage workers */
+       POOL_MANAGING_WORKERS   = 1 << 1,       /* managing workers */
 
        /* worker flags */
        WORKER_STARTED          = 1 << 0,       /* started */
@@ -652,7 +653,7 @@ static bool need_to_manage_workers(struct worker_pool *pool)
 /* Do we have too many workers and should some go away? */
 static bool too_many_workers(struct worker_pool *pool)
 {
-       bool managing = mutex_is_locked(&pool->manager_mutex);
+       bool managing = pool->flags & POOL_MANAGING_WORKERS;
        int nr_idle = pool->nr_idle + managing; /* manager is considered idle */
        int nr_busy = pool->nr_workers - nr_idle;
 
@@ -1326,6 +1327,15 @@ static void idle_worker_rebind(struct worker *worker)
 
        /* we did our part, wait for rebind_workers() to finish up */
        wait_event(gcwq->rebind_hold, !(worker->flags & WORKER_REBIND));
+
+       /*
+        * rebind_workers() shouldn't finish until all workers passed the
+        * above WORKER_REBIND wait.  Tell it when done.
+        */
+       spin_lock_irq(&worker->pool->gcwq->lock);
+       if (!--worker->idle_rebind->cnt)
+               complete(&worker->idle_rebind->done);
+       spin_unlock_irq(&worker->pool->gcwq->lock);
 }
 
 /*
@@ -1339,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);
 }
@@ -1396,12 +1414,15 @@ retry:
        /* set REBIND and kick idle ones, we'll wait for these later */
        for_each_worker_pool(pool, gcwq) {
                list_for_each_entry(worker, &pool->idle_list, entry) {
+                       unsigned long worker_flags = worker->flags;
+
                        if (worker->flags & WORKER_REBIND)
                                continue;
 
-                       /* morph UNBOUND to REBIND */
-                       worker->flags &= ~WORKER_UNBOUND;
-                       worker->flags |= WORKER_REBIND;
+                       /* morph UNBOUND to REBIND atomically */
+                       worker_flags &= ~WORKER_UNBOUND;
+                       worker_flags |= WORKER_REBIND;
+                       ACCESS_ONCE(worker->flags) = worker_flags;
 
                        idle_rebind.cnt++;
                        worker->idle_rebind = &idle_rebind;
@@ -1419,25 +1440,15 @@ retry:
                goto retry;
        }
 
-       /*
-        * All idle workers are rebound and waiting for %WORKER_REBIND to
-        * be cleared inside idle_worker_rebind().  Clear and release.
-        * Clearing %WORKER_REBIND from this foreign context is safe
-        * because these workers are still guaranteed to be idle.
-        */
-       for_each_worker_pool(pool, gcwq)
-               list_for_each_entry(worker, &pool->idle_list, entry)
-                       worker->flags &= ~WORKER_REBIND;
-
-       wake_up_all(&gcwq->rebind_hold);
-
-       /* rebind busy workers */
+       /* all idle workers are rebound, rebind busy workers */
        for_each_busy_worker(worker, i, pos, gcwq) {
                struct work_struct *rebind_work = &worker->rebind_work;
+               unsigned long worker_flags = worker->flags;
 
-               /* morph UNBOUND to REBIND */
-               worker->flags &= ~WORKER_UNBOUND;
-               worker->flags |= WORKER_REBIND;
+               /* morph UNBOUND to REBIND atomically */
+               worker_flags &= ~WORKER_UNBOUND;
+               worker_flags |= WORKER_REBIND;
+               ACCESS_ONCE(worker->flags) = worker_flags;
 
                if (test_and_set_bit(WORK_STRUCT_PENDING_BIT,
                                     work_data_bits(rebind_work)))
@@ -1449,6 +1460,34 @@ retry:
                            worker->scheduled.next,
                            work_color_to_flags(WORK_NO_COLOR));
        }
+
+       /*
+        * All idle workers are rebound and waiting for %WORKER_REBIND to
+        * be cleared inside idle_worker_rebind().  Clear and release.
+        * Clearing %WORKER_REBIND from this foreign context is safe
+        * because these workers are still guaranteed to be idle.
+        *
+        * We need to make sure all idle workers passed WORKER_REBIND wait
+        * in idle_worker_rebind() before returning; otherwise, workers can
+        * get stuck at the wait if hotplug cycle repeats.
+        */
+       idle_rebind.cnt = 1;
+       INIT_COMPLETION(idle_rebind.done);
+
+       for_each_worker_pool(pool, gcwq) {
+               list_for_each_entry(worker, &pool->idle_list, entry) {
+                       worker->flags &= ~WORKER_REBIND;
+                       idle_rebind.cnt++;
+               }
+       }
+
+       wake_up_all(&gcwq->rebind_hold);
+
+       if (--idle_rebind.cnt) {
+               spin_unlock_irq(&gcwq->lock);
+               wait_for_completion(&idle_rebind.done);
+               spin_lock_irq(&gcwq->lock);
+       }
 }
 
 static struct worker *alloc_worker(void)
@@ -1794,9 +1833,45 @@ static bool manage_workers(struct worker *worker)
        struct worker_pool *pool = worker->pool;
        bool ret = false;
 
-       if (!mutex_trylock(&pool->manager_mutex))
+       if (pool->flags & POOL_MANAGING_WORKERS)
                return ret;
 
+       pool->flags |= POOL_MANAGING_WORKERS;
+
+       /*
+        * To simplify both worker management and CPU hotplug, hold off
+        * management while hotplug is in progress.  CPU hotplug path can't
+        * grab %POOL_MANAGING_WORKERS to achieve this because that can
+        * lead to idle worker depletion (all become busy thinking someone
+        * else is managing) which in turn can result in deadlock under
+        * extreme circumstances.  Use @pool->manager_mutex to synchronize
+        * manager against CPU hotplug.
+        *
+        * manager_mutex would always be free unless CPU hotplug is in
+        * progress.  trylock first without dropping @gcwq->lock.
+        */
+       if (unlikely(!mutex_trylock(&pool->manager_mutex))) {
+               spin_unlock_irq(&pool->gcwq->lock);
+               mutex_lock(&pool->manager_mutex);
+               /*
+                * CPU hotplug could have happened while we were waiting
+                * for manager_mutex.  Hotplug itself can't handle us
+                * because manager isn't either on idle or busy list, and
+                * @gcwq's state and ours could have deviated.
+                *
+                * As hotplug is now excluded via manager_mutex, we can
+                * simply try to bind.  It will succeed or fail depending
+                * on @gcwq's current state.  Try it and adjust
+                * %WORKER_UNBOUND accordingly.
+                */
+               if (worker_maybe_bind_and_lock(worker))
+                       worker->flags &= ~WORKER_UNBOUND;
+               else
+                       worker->flags |= WORKER_UNBOUND;
+
+               ret = true;
+       }
+
        pool->flags &= ~POOL_MANAGE_WORKERS;
 
        /*
@@ -1806,6 +1881,7 @@ static bool manage_workers(struct worker *worker)
        ret |= maybe_destroy_workers(pool);
        ret |= maybe_create_worker(pool);
 
+       pool->flags &= ~POOL_MANAGING_WORKERS;
        mutex_unlock(&pool->manager_mutex);
        return ret;
 }
@@ -3500,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;
 }
 
 /**
@@ -3526,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);
index 286d558033e270524ff3fdeac9c96393b81170a6..8c0e62975c88d49a09c9c29ab9e7a2b1334a6587 100644 (file)
@@ -163,9 +163,11 @@ static int digsig_verify_rsa(struct key *key,
        memcpy(out1 + head, p, l);
 
        err = pkcs_1_v1_5_decode_emsa(out1, len, mblen, out2, &len);
+       if (err)
+               goto err;
 
-       if (!err && len == hlen)
-               err = memcmp(out2, h, hlen);
+       if (len != hlen || memcmp(out2, h, hlen))
+               err = -EINVAL;
 
 err:
        mpi_free(in);
index 4d9393c7edc9072ff929175eec6e611788da124b..82aa349d2f7a040b489bee441bf848b61119f788 100644 (file)
@@ -246,7 +246,7 @@ static int __init_memblock memblock_double_array(struct memblock_type *type,
                                min(new_area_start, memblock.current_limit),
                                new_alloc_size, PAGE_SIZE);
 
-               new_array = addr ? __va(addr) : 0;
+               new_array = addr ? __va(addr) : NULL;
        }
        if (!addr) {
                pr_err("memblock: Failed to double %s array from %ld to %ld entries !\n",
index 3ad25f9d1fc134dc09e9672fad40f508e12e9502..6a5b90d0cfd7cbd61f4bc679bb4313e7a374ac0d 100644 (file)
@@ -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 */
 
index c66fb875104ab99feccb0e116b48b9d54a6011e4..c13ea7538891d85988b029236f11e233632b58ec 100644 (file)
@@ -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]);
index 811af03a14ef168ca8e6ba90ec0af60b2dffa305..c6854759bcf1e041d7a21781921ac45cfd2f5484 100644 (file)
--- 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);
        }
index 8f78e25770317e63a37c741d66c2761f71afa2e9..2fdd96f9e9986b4c1244c13fde954d586afa7952 100644 (file)
--- 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;
 
index 8d01243d9560e0ea8d8a04cf51cd4087ed8b280d..99b434b674c02b4099bcfe58632ad56e183801fd 100644 (file)
@@ -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;
index a081ce1c05140d43473dbc02518bfc51f913f6eb..cebaae7e148b7f8a88f8b265bb625256363cde5a 100644 (file)
@@ -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 */
index 5e5f5b410e0b24f751eb158ad235fe16bfa3ee6f..1eaacf10d19d9ea078f49f225423dff96ebee8a2 100644 (file)
@@ -58,7 +58,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;
@@ -84,7 +84,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;
index 311668d14571626dac778201a65ed21f05c72cbe..32dc83dcb6b2edd669d7a9ce2fc00480d249b4be 100644 (file)
@@ -72,7 +72,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;
@@ -97,7 +97,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;
index 5ad7da21747413f50ba0106041c6e73d6ce727d4..3c094e78dde98cafed3ac893abd3b2fa86b76a92 100644 (file)
@@ -29,6 +29,7 @@
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
 #include <net/bluetooth/a2mp.h>
+#include <net/bluetooth/smp.h>
 
 static void hci_le_connect(struct hci_conn *conn)
 {
@@ -619,6 +620,9 @@ int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
 {
        BT_DBG("hcon %p", conn);
 
+       if (conn->type == LE_LINK)
+               return smp_conn_security(conn, sec_level);
+
        /* For sdp we don't need the link key. */
        if (sec_level == BT_SECURITY_SDP)
                return 1;
index 19fdac78e555b97c44dd6826bc60ef89a888395b..d5ace1eda3ed8c3fd06f422bb7cbf340d3187c6c 100644 (file)
@@ -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:
index 18b3f6892a36847de621954cbae7358ae719c0be..b24fb3bd862555c81746fe664e7f90270cc6a2df 100644 (file)
@@ -56,7 +56,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;
@@ -91,7 +91,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;
index daa149b7003cdd659120e79225a50c6216a6dce4..4ea1710a478329a5d4219ce686a2ef4450ca30b8 100644 (file)
@@ -1199,14 +1199,15 @@ clean:
 static void l2cap_conn_ready(struct l2cap_conn *conn)
 {
        struct l2cap_chan *chan;
+       struct hci_conn *hcon = conn->hcon;
 
        BT_DBG("conn %p", conn);
 
-       if (!conn->hcon->out && conn->hcon->type == LE_LINK)
+       if (!hcon->out && hcon->type == LE_LINK)
                l2cap_le_conn_ready(conn);
 
-       if (conn->hcon->out && conn->hcon->type == LE_LINK)
-               smp_conn_security(conn, conn->hcon->pending_sec_level);
+       if (hcon->out && hcon->type == LE_LINK)
+               smp_conn_security(hcon, hcon->pending_sec_level);
 
        mutex_lock(&conn->chan_lock);
 
@@ -1219,8 +1220,8 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)
                        continue;
                }
 
-               if (conn->hcon->type == LE_LINK) {
-                       if (smp_conn_security(conn, chan->sec_level))
+               if (hcon->type == LE_LINK) {
+                       if (smp_conn_security(hcon, chan->sec_level))
                                l2cap_chan_ready(chan);
 
                } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
index 1497edd191a2e04ee3121624db92547059f24369..34bbe1c5e389500f080e15b30c194e95ea36f189 100644 (file)
@@ -616,7 +616,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
                                break;
                        }
 
-                       if (smp_conn_security(conn, sec.level))
+                       if (smp_conn_security(conn->hcon, sec.level))
                                break;
                        sk->sk_state = BT_CONFIG;
                        chan->state = BT_CONFIG;
index 901a616c8083e22f5163f8bbd1613b1529c63519..8c225ef349cd733614dfeaca0f2f1bceccdae064 100644 (file)
@@ -267,10 +267,10 @@ static void smp_failure(struct l2cap_conn *conn, u8 reason, u8 send)
        mgmt_auth_failed(conn->hcon->hdev, conn->dst, hcon->type,
                         hcon->dst_type, reason);
 
-       if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) {
-               cancel_delayed_work_sync(&conn->security_timer);
+       cancel_delayed_work_sync(&conn->security_timer);
+
+       if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags))
                smp_chan_destroy(conn);
-       }
 }
 
 #define JUST_WORKS     0x00
@@ -760,9 +760,9 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
        return 0;
 }
 
-int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
+int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
 {
-       struct hci_conn *hcon = conn->hcon;
+       struct l2cap_conn *conn = hcon->l2cap_data;
        struct smp_chan *smp = conn->smp_chan;
        __u8 authreq;
 
index f88ee537fb2b811347c109cfa19dbdd34c2923c0..92de5e5f9db211fb004a5b8f095c2bd215276682 100644 (file)
@@ -80,7 +80,7 @@ ebt_log_packet(u_int8_t pf, unsigned int hooknum,
        unsigned int bitmask;
 
        spin_lock_bh(&ebt_log_lock);
-       printk("<%c>%s IN=%s OUT=%s MAC source = %pM MAC dest = %pM proto = 0x%04x",
+       printk(KERN_SOH "%c%s IN=%s OUT=%s MAC source = %pM MAC dest = %pM proto = 0x%04x",
               '0' + loginfo->u.log.level, prefix,
               in ? in->name : "", out ? out->name : "",
               eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest,
index dd485f6128e81df5f8b1b454f57dac3b3871158a..ba217e90765e11024251feae5bbcb46450101ea7 100644 (file)
@@ -211,9 +211,10 @@ void caif_client_register_refcnt(struct cflayer *adapt_layer,
                                        void (*put)(struct cflayer *lyr))
 {
        struct cfsrvl *service;
-       service = container_of(adapt_layer->dn, struct cfsrvl, layer);
 
-       WARN_ON(adapt_layer == NULL || adapt_layer->dn == NULL);
+       if (WARN_ON(adapt_layer == NULL || adapt_layer->dn == NULL))
+               return;
+       service = container_of(adapt_layer->dn, struct cfsrvl, layer);
        service->hold = hold;
        service->put = put;
 }
index 83988362805ef1453efb37bfcb3692f59f4edd21..89e33a5d4d932c54af74a08cb080809affc7dd67 100644 (file)
@@ -2134,7 +2134,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)) {
@@ -2647,15 +2648,16 @@ void __skb_get_rxhash(struct sk_buff *skb)
        if (!skb_flow_dissect(skb, &keys))
                return;
 
-       if (keys.ports) {
-               if ((__force u16)keys.port16[1] < (__force u16)keys.port16[0])
-                       swap(keys.port16[0], keys.port16[1]);
+       if (keys.ports)
                skb->l4_rxhash = 1;
-       }
 
        /* get a consistent hash (same value on both flow directions) */
-       if ((__force u32)keys.dst < (__force u32)keys.src)
+       if (((__force u32)keys.dst < (__force u32)keys.src) ||
+           (((__force u32)keys.dst == (__force u32)keys.src) &&
+            ((__force u16)keys.port16[1] < (__force u16)keys.port16[0]))) {
                swap(keys.dst, keys.src);
+               swap(keys.port16[0], keys.port16[1]);
+       }
 
        hash = jhash_3words((__force u32)keys.dst,
                            (__force u32)keys.src,
@@ -3321,7 +3323,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 {
index cce9e53528b169a67a8b5cd8bf0e568460587e24..148e73d2c4515d777d577733f32205c38d03932e 100644 (file)
@@ -2721,7 +2721,7 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
        /* Eth + IPh + UDPh + mpls */
        datalen = pkt_dev->cur_pkt_size - 14 - 20 - 8 -
                  pkt_dev->pkt_overhead;
-       if (datalen < sizeof(struct pktgen_hdr))
+       if (datalen < 0 || datalen < sizeof(struct pktgen_hdr))
                datalen = sizeof(struct pktgen_hdr);
 
        udph->source = htons(pkt_dev->cur_udp_src);
index fe00d12081671a22c65d05d290069d7358dda1d6..e33ebae519c8c3283dadde917cdf46d413229a54 100644 (file)
@@ -3502,7 +3502,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);
 
index 8f67ced8d6a808689255435dd412df132138af65..30579207612175f0a65b19310368079c54ce4bc9 100644 (file)
@@ -1523,7 +1523,14 @@ EXPORT_SYMBOL(sock_rfree);
 
 void sock_edemux(struct sk_buff *skb)
 {
-       sock_put(skb->sk);
+       struct sock *sk = skb->sk;
+
+#ifdef CONFIG_INET
+       if (sk->sk_state == TCP_TIME_WAIT)
+               inet_twsk_put(inet_twsk(sk));
+       else
+#endif
+               sock_put(sk);
 }
 EXPORT_SYMBOL(sock_edemux);
 
index 859ab8b6ec343880f74cc749136518525d6b8a8d..b53bb4a41daa6cf0b05dedfb5df9c1979af46bf8 100644 (file)
@@ -259,19 +259,15 @@ static int __init init_dns_resolver(void)
        if (!cred)
                return -ENOMEM;
 
-       keyring = key_alloc(&key_type_keyring, ".dns_resolver", 0, 0, cred,
-                           (KEY_POS_ALL & ~KEY_POS_SETATTR) |
-                           KEY_USR_VIEW | KEY_USR_READ,
-                           KEY_ALLOC_NOT_IN_QUOTA);
+       keyring = keyring_alloc(".dns_resolver", 0, 0, cred,
+                               (KEY_POS_ALL & ~KEY_POS_SETATTR) |
+                               KEY_USR_VIEW | KEY_USR_READ,
+                               KEY_ALLOC_NOT_IN_QUOTA, NULL);
        if (IS_ERR(keyring)) {
                ret = PTR_ERR(keyring);
                goto failed_put_cred;
        }
 
-       ret = key_instantiate_and_link(keyring, NULL, 0, NULL, NULL);
-       if (ret < 0)
-               goto failed_put_key;
-
        ret = register_key_type(&key_type_dns_resolver);
        if (ret < 0)
                goto failed_put_key;
@@ -303,3 +299,4 @@ static void __exit exit_dns_resolver(void)
 module_init(init_dns_resolver)
 module_exit(exit_dns_resolver)
 MODULE_LICENSE("GPL");
+
index 77e87aff419ab105ef3ad3b5f852ef676b18a827..47800459e4cb341c395f54f2d161c300a112c1cf 100644 (file)
@@ -1225,7 +1225,7 @@ static int arp_netdev_event(struct notifier_block *this, unsigned long event,
        switch (event) {
        case NETDEV_CHANGEADDR:
                neigh_changeaddr(&arp_tbl, dev);
-               rt_cache_flush(dev_net(dev), 0);
+               rt_cache_flush(dev_net(dev));
                break;
        default:
                break;
index 44bf82e3aef7d6d4b5afc39a357b7da6d85a44e7..e12fad773852b5271afafa414ffc1f2706ff4428 100644 (file)
@@ -725,7 +725,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;
@@ -733,7 +733,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;
@@ -1503,7 +1503,7 @@ static int devinet_conf_proc(ctl_table *ctl, int write,
                if (i == IPV4_DEVCONF_ACCEPT_LOCAL - 1 ||
                    i == IPV4_DEVCONF_ROUTE_LOCALNET - 1)
                        if ((new_value == 0) && (old_value != 0))
-                               rt_cache_flush(net, 0);
+                               rt_cache_flush(net);
        }
 
        return ret;
@@ -1537,7 +1537,7 @@ static int devinet_sysctl_forward(ctl_table *ctl, int write,
                                dev_disable_lro(idev->dev);
                        }
                        rtnl_unlock();
-                       rt_cache_flush(net, 0);
+                       rt_cache_flush(net);
                }
        }
 
@@ -1554,7 +1554,7 @@ static int ipv4_doint_and_flush(ctl_table *ctl, int write,
        struct net *net = ctl->extra2;
 
        if (write && *valp != val)
-               rt_cache_flush(net, 0);
+               rt_cache_flush(net);
 
        return ret;
 }
index c43ae3fba7921e590859cea407ba9b9e030b16be..8e2b475da9faca9f7e27482f7e416908e7cf66fa 100644 (file)
@@ -148,7 +148,7 @@ static void fib_flush(struct net *net)
        }
 
        if (flushed)
-               rt_cache_flush(net, -1);
+               rt_cache_flush(net);
 }
 
 /*
@@ -999,11 +999,11 @@ static void nl_fib_lookup_exit(struct net *net)
        net->ipv4.fibnl = NULL;
 }
 
-static void fib_disable_ip(struct net_device *dev, int force, int delay)
+static void fib_disable_ip(struct net_device *dev, int force)
 {
        if (fib_sync_down_dev(dev, force))
                fib_flush(dev_net(dev));
-       rt_cache_flush(dev_net(dev), delay);
+       rt_cache_flush(dev_net(dev));
        arp_ifdown(dev);
 }
 
@@ -1020,7 +1020,7 @@ static int fib_inetaddr_event(struct notifier_block *this, unsigned long event,
                fib_sync_up(dev);
 #endif
                atomic_inc(&net->ipv4.dev_addr_genid);
-               rt_cache_flush(dev_net(dev), -1);
+               rt_cache_flush(dev_net(dev));
                break;
        case NETDEV_DOWN:
                fib_del_ifaddr(ifa, NULL);
@@ -1029,9 +1029,9 @@ static int fib_inetaddr_event(struct notifier_block *this, unsigned long event,
                        /* Last address was deleted from this interface.
                         * Disable IP.
                         */
-                       fib_disable_ip(dev, 1, 0);
+                       fib_disable_ip(dev, 1);
                } else {
-                       rt_cache_flush(dev_net(dev), -1);
+                       rt_cache_flush(dev_net(dev));
                }
                break;
        }
@@ -1045,7 +1045,7 @@ static int fib_netdev_event(struct notifier_block *this, unsigned long event, vo
        struct net *net = dev_net(dev);
 
        if (event == NETDEV_UNREGISTER) {
-               fib_disable_ip(dev, 2, -1);
+               fib_disable_ip(dev, 2);
                rt_flush_dev(dev);
                return NOTIFY_DONE;
        }
@@ -1062,14 +1062,14 @@ static int fib_netdev_event(struct notifier_block *this, unsigned long event, vo
                fib_sync_up(dev);
 #endif
                atomic_inc(&net->ipv4.dev_addr_genid);
-               rt_cache_flush(dev_net(dev), -1);
+               rt_cache_flush(dev_net(dev));
                break;
        case NETDEV_DOWN:
-               fib_disable_ip(dev, 0, 0);
+               fib_disable_ip(dev, 0);
                break;
        case NETDEV_CHANGEMTU:
        case NETDEV_CHANGE:
-               rt_cache_flush(dev_net(dev), 0);
+               rt_cache_flush(dev_net(dev));
                break;
        case NETDEV_UNREGISTER_BATCH:
                break;
index a83d74e498d23af8c104bc3d68eca5ca4a8ac228..274309d3aded0ffbf351dbf5f4ad128d87ff5a0b 100644 (file)
@@ -259,7 +259,7 @@ static size_t fib4_rule_nlmsg_payload(struct fib_rule *rule)
 
 static void fib4_rule_flush_cache(struct fib_rules_ops *ops)
 {
-       rt_cache_flush(ops->fro_net, -1);
+       rt_cache_flush(ops->fro_net);
 }
 
 static const struct fib_rules_ops __net_initdata fib4_rules_ops_template = {
index 57bd978483e1fe47a96c964f356432e51e62d6b7..d1b93595b4a7dce1e7701bb713bd5f0bc5adf1f6 100644 (file)
@@ -1286,7 +1286,7 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg)
 
                        fib_release_info(fi_drop);
                        if (state & FA_S_ACCESSED)
-                               rt_cache_flush(cfg->fc_nlinfo.nl_net, -1);
+                               rt_cache_flush(cfg->fc_nlinfo.nl_net);
                        rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen,
                                tb->tb_id, &cfg->fc_nlinfo, NLM_F_REPLACE);
 
@@ -1333,7 +1333,7 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg)
        list_add_tail_rcu(&new_fa->fa_list,
                          (fa ? &fa->fa_list : fa_head));
 
-       rt_cache_flush(cfg->fc_nlinfo.nl_net, -1);
+       rt_cache_flush(cfg->fc_nlinfo.nl_net);
        rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen, tb->tb_id,
                  &cfg->fc_nlinfo, 0);
 succeeded:
@@ -1708,7 +1708,7 @@ int fib_table_delete(struct fib_table *tb, struct fib_config *cfg)
                trie_leaf_remove(t, l);
 
        if (fa->fa_state & FA_S_ACCESSED)
-               rt_cache_flush(cfg->fc_nlinfo.nl_net, -1);
+               rt_cache_flush(cfg->fc_nlinfo.nl_net);
 
        fib_release_info(fa->fa_info);
        alias_free_mem_rcu(fa);
index 82cf2a722b2310803ec603f60d59cdf819481a4a..fd9af60397b590dd817e02a52a33fdf99bb24c8e 100644 (file)
@@ -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)
 {
@@ -447,27 +442,9 @@ static inline bool rt_is_expired(const struct rtable *rth)
        return rth->rt_genid != rt_genid(dev_net(rth->dst.dev));
 }
 
-/*
- * Perturbation of rt_genid by a small quantity [1..256]
- * Using 8 bits of shuffling ensure we can call rt_cache_invalidate()
- * many times (2^24) without giving recent rt_genid.
- * Jenkins hash is strong enough that litle changes of rt_genid are OK.
- */
-static void rt_cache_invalidate(struct net *net)
+void rt_cache_flush(struct net *net)
 {
-       unsigned char shuffle;
-
-       get_random_bytes(&shuffle, sizeof(shuffle));
-       atomic_add(shuffle + 1U, &net->ipv4.rt_genid);
-}
-
-/*
- * delay < 0  : invalidate cache (fast : entries will be deleted later)
- * delay >= 0 : invalidate & flush cache (can be long)
- */
-void rt_cache_flush(struct net *net, int delay)
-{
-       rt_cache_invalidate(net);
+       rt_genid_bump(net);
 }
 
 static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst,
@@ -2345,7 +2322,7 @@ int ip_rt_dump(struct sk_buff *skb,  struct netlink_callback *cb)
 
 void ip_rt_multicast_event(struct in_device *in_dev)
 {
-       rt_cache_flush(dev_net(in_dev->dev), 0);
+       rt_cache_flush(dev_net(in_dev->dev));
 }
 
 #ifdef CONFIG_SYSCTL
@@ -2354,16 +2331,7 @@ static int ipv4_sysctl_rtcache_flush(ctl_table *__ctl, int write,
                                        size_t *lenp, loff_t *ppos)
 {
        if (write) {
-               int flush_delay;
-               ctl_table ctl;
-               struct net *net;
-
-               memcpy(&ctl, __ctl, sizeof(ctl));
-               ctl.data = &flush_delay;
-               proc_dointvec(&ctl, write, buffer, lenp, ppos);
-
-               net = (struct net *)__ctl->extra1;
-               rt_cache_flush(net, flush_delay);
+               rt_cache_flush((struct net *)__ctl->extra1);
                return 0;
        }
 
@@ -2533,8 +2501,7 @@ static __net_initdata struct pernet_operations sysctl_route_ops = {
 
 static __net_init int rt_genid_init(struct net *net)
 {
-       get_random_bytes(&net->ipv4.rt_genid,
-                        sizeof(net->ipv4.rt_genid));
+       atomic_set(&net->rt_genid, 0);
        get_random_bytes(&net->ipv4.dev_addr_genid,
                         sizeof(net->ipv4.dev_addr_genid));
        return 0;
index 2109ff4a1dafd489fbe0e2240075432df4517374..5f64193418216393448ec9d8e839f83e85636716 100644 (file)
@@ -1762,8 +1762,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. */
@@ -2325,10 +2331,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)
index 6e38c6c23caa69601216e193507460663c1926ec..d377f4854cb853c454541062fb6f8438608d470c 100644 (file)
@@ -4661,7 +4661,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;
        }
@@ -5556,8 +5556,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;
                }
        }
index 6f6d1aca3c3de0e21036c075c0a13c429ef4f8ae..2814f66dac64cf5775806138c91903c7a02eeae3 100644 (file)
@@ -1226,6 +1226,11 @@ try_again:
 
        if (unlikely(err)) {
                trace_kfree_skb(skb, udp_recvmsg);
+               if (!peeked) {
+                       atomic_inc(&sk->sk_drops);
+                       UDP_INC_STATS_USER(sock_net(sk),
+                                          UDP_MIB_INERRORS, is_udplite);
+               }
                goto out_free;
        }
 
index 0251a6005be8ff8d35cffe7fb0e2611b43296158..c4f934176cabd92ebfb4bba774335427b9f8932a 100644 (file)
@@ -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,
index 13690d650c3e227de6579ed6ee489fbff1cbddef..286acfc21250cd760565b182cbc2d3d4490463dd 100644 (file)
@@ -819,6 +819,10 @@ 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 (IS_ERR(sn)) {
+                               err = PTR_ERR(sn);
+                               sn = NULL;
+                       }
                        if (!sn) {
                                /* If it is failed, discard just allocated
                                   root, and then (in st_failure) stale node
index 8e80fd279100d7d18d111eff1be73f10fdd6eeaf..854e4018d205c826032633ce2641cbc1af2c057a 100644 (file)
@@ -226,7 +226,7 @@ static 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 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 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;
 }
@@ -1031,6 +1032,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))
@@ -1397,8 +1405,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));
@@ -2080,7 +2086,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)
index a3e60cc04a8a17e229afb44f38643ed86ac0c63e..acd32e3f1b68e7c11fd211383e05b50dfd07ee6a 100644 (file)
@@ -403,8 +403,9 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                tp->mtu_info = ntohl(info);
                if (!sock_owned_by_user(sk))
                        tcp_v6_mtu_reduced(sk);
-               else
-                       set_bit(TCP_MTU_REDUCED_DEFERRED, &tp->tsq_flags);
+               else if (!test_and_set_bit(TCP_MTU_REDUCED_DEFERRED,
+                                          &tp->tsq_flags))
+                       sock_hold(sk);
                goto out;
        }
 
index 99d0077b56b86f088a4a2fd2819a7b03e0eabd49..07e2bfef6845429ee7e359a6c21141db0a0219de 100644 (file)
@@ -394,6 +394,17 @@ try_again:
        }
        if (unlikely(err)) {
                trace_kfree_skb(skb, udpv6_recvmsg);
+               if (!peeked) {
+                       atomic_inc(&sk->sk_drops);
+                       if (is_udp4)
+                               UDP_INC_STATS_USER(sock_net(sk),
+                                                  UDP_MIB_INERRORS,
+                                                  is_udplite);
+                       else
+                               UDP6_INC_STATS_USER(sock_net(sk),
+                                                   UDP_MIB_INERRORS,
+                                                   is_udplite);
+               }
                goto out_free;
        }
        if (!peeked) {
index 513cab08a9863c0080d510ae5a2a4d927ad2ccdd..1a9f3723c13cb45b608bbc07fe4a9803df926523 100644 (file)
@@ -1501,6 +1501,8 @@ out:
        return err;
 }
 
+static struct lock_class_key l2tp_socket_class;
+
 int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32 peer_tunnel_id, struct l2tp_tunnel_cfg *cfg, struct l2tp_tunnel **tunnelp)
 {
        struct l2tp_tunnel *tunnel = NULL;
@@ -1605,6 +1607,8 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32
        tunnel->old_sk_destruct = sk->sk_destruct;
        sk->sk_destruct = &l2tp_tunnel_destruct;
        tunnel->sock = sk;
+       lockdep_set_class_and_name(&sk->sk_lock.slock, &l2tp_socket_class, "l2tp_sock");
+
        sk->sk_allocation = GFP_ATOMIC;
 
        /* Add tunnel to our list */
index f9ee74deeac26f5469271a0800669cc82ffddc63..3bfb34aaee293cb697f36ae88a060f3329571214 100644 (file)
@@ -153,7 +153,7 @@ static void l2tp_eth_dev_recv(struct l2tp_session *session, struct sk_buff *skb,
                print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, skb->data, length);
        }
 
-       if (!pskb_may_pull(skb, sizeof(ETH_HLEN)))
+       if (!pskb_may_pull(skb, ETH_HLEN))
                goto error;
 
        secpath_reset(skb);
index d41974aacf5168597fd559f1c976252f9e36ffd9..a58c0b649ba137b09214c031bf3508b5fe2974eb 100644 (file)
@@ -1378,6 +1378,8 @@ static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop,
        else
                memset(next_hop, 0, ETH_ALEN);
 
+       memset(pinfo, 0, sizeof(*pinfo));
+
        pinfo->generation = mesh_paths_generation;
 
        pinfo->filled = MPATH_INFO_FRAME_QLEN |
@@ -1396,7 +1398,6 @@ static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop,
        pinfo->discovery_timeout =
                        jiffies_to_msecs(mpath->discovery_timeout);
        pinfo->discovery_retries = mpath->discovery_retries;
-       pinfo->flags = 0;
        if (mpath->flags & MESH_PATH_ACTIVE)
                pinfo->flags |= NL80211_MPATH_FLAG_ACTIVE;
        if (mpath->flags & MESH_PATH_RESOLVING)
@@ -1405,10 +1406,8 @@ static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop,
                pinfo->flags |= NL80211_MPATH_FLAG_SN_VALID;
        if (mpath->flags & MESH_PATH_FIXED)
                pinfo->flags |= NL80211_MPATH_FLAG_FIXED;
-       if (mpath->flags & MESH_PATH_RESOLVING)
-               pinfo->flags |= NL80211_MPATH_FLAG_RESOLVING;
-
-       pinfo->flags = mpath->flags;
+       if (mpath->flags & MESH_PATH_RESOLVED)
+               pinfo->flags |= NL80211_MPATH_FLAG_RESOLVED;
 }
 
 static int ieee80211_get_mpath(struct wiphy *wiphy, struct net_device *dev,
index a4a5acdbaa4dd3ac5e2fb8c5f0ff1d1b97553d6a..f76b83341cf9a39db0e14092a85f2e576245a306 100644 (file)
@@ -3248,6 +3248,8 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
        goto out_unlock;
 
  err_clear:
+       memset(ifmgd->bssid, 0, ETH_ALEN);
+       ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
        ifmgd->auth_data = NULL;
  err_free:
        kfree(auth_data);
@@ -3439,6 +3441,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
        err = 0;
        goto out;
  err_clear:
+       memset(ifmgd->bssid, 0, ETH_ALEN);
+       ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
        ifmgd->assoc_data = NULL;
  err_free:
        kfree(assoc_data);
index a5ac11ebef331895f39af5e86ca4406e56562ceb..e046b3756aab755080d3edced132c459b7c8d4c4 100644 (file)
@@ -158,21 +158,18 @@ static const u8 tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = {
  *     sCL -> sSS
  */
 /*          sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2   */
-/*synack*/ { sIV, sIV, sIG, sIG, sIG, sIG, sIG, sIG, sIG, sSR },
+/*synack*/ { sIV, sIV, sSR, sIV, sIV, sIV, sIV, sIV, sIV, sSR },
 /*
  *     sNO -> sIV      Too late and no reason to do anything
  *     sSS -> sIV      Client can't send SYN and then SYN/ACK
  *     sS2 -> sSR      SYN/ACK sent to SYN2 in simultaneous open
- *     sSR -> sIG
- *     sES -> sIG      Error: SYNs in window outside the SYN_SENT state
- *                     are errors. Receiver will reply with RST
- *                     and close the connection.
- *                     Or we are not in sync and hold a dead connection.
- *     sFW -> sIG
- *     sCW -> sIG
- *     sLA -> sIG
- *     sTW -> sIG
- *     sCL -> sIG
+ *     sSR -> sSR      Late retransmitted SYN/ACK in simultaneous open
+ *     sES -> sIV      Invalid SYN/ACK packets sent by the client
+ *     sFW -> sIV
+ *     sCW -> sIV
+ *     sLA -> sIV
+ *     sTW -> sIV
+ *     sCL -> sIV
  */
 /*          sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2   */
 /*fin*/    { sIV, sIV, sFW, sFW, sLA, sLA, sLA, sTW, sCL, sIV },
@@ -633,15 +630,9 @@ static bool tcp_in_window(const struct nf_conn *ct,
                ack = sack = receiver->td_end;
        }
 
-       if (seq == end
-           && (!tcph->rst
-               || (seq == 0 && state->state == TCP_CONNTRACK_SYN_SENT)))
+       if (tcph->rst && seq == 0 && state->state == TCP_CONNTRACK_SYN_SENT)
                /*
-                * Packets contains no data: we assume it is valid
-                * and check the ack value only.
-                * However RST segments are always validated by their
-                * SEQ number, except when seq == 0 (reset sent answering
-                * SYN.
+                * RST sent answering SYN.
                 */
                seq = end = sender->td_end;
 
index 14e2f3903142e322d1ce72a3eba13441004eef16..5cfb5bedb2b8e8f2fa44ed936a7cab265b5878e6 100644 (file)
@@ -381,6 +381,7 @@ __build_packet_message(struct nfulnl_instance *inst,
        struct nlmsghdr *nlh;
        struct nfgenmsg *nfmsg;
        sk_buff_data_t old_tail = inst->skb->tail;
+       struct sock *sk;
 
        nlh = nlmsg_put(inst->skb, 0, 0,
                        NFNL_SUBSYS_ULOG << 8 | NFULNL_MSG_PACKET,
@@ -499,18 +500,19 @@ __build_packet_message(struct nfulnl_instance *inst,
        }
 
        /* UID */
-       if (skb->sk) {
-               read_lock_bh(&skb->sk->sk_callback_lock);
-               if (skb->sk->sk_socket && skb->sk->sk_socket->file) {
-                       struct file *file = skb->sk->sk_socket->file;
+       sk = skb->sk;
+       if (sk && sk->sk_state != TCP_TIME_WAIT) {
+               read_lock_bh(&sk->sk_callback_lock);
+               if (sk->sk_socket && sk->sk_socket->file) {
+                       struct file *file = sk->sk_socket->file;
                        __be32 uid = htonl(file->f_cred->fsuid);
                        __be32 gid = htonl(file->f_cred->fsgid);
-                       read_unlock_bh(&skb->sk->sk_callback_lock);
+                       read_unlock_bh(&sk->sk_callback_lock);
                        if (nla_put_be32(inst->skb, NFULA_UID, uid) ||
                            nla_put_be32(inst->skb, NFULA_GID, gid))
                                goto nla_put_failure;
                } else
-                       read_unlock_bh(&skb->sk->sk_callback_lock);
+                       read_unlock_bh(&sk->sk_callback_lock);
        }
 
        /* local sequence number */
index ff5f75fddb15175c408a1e0a1cf8a656453aff80..91e9af4d1f42c3baef9af1261c9464c70cd1bac0 100644 (file)
@@ -145,6 +145,19 @@ static int dump_tcp_header(struct sbuff *m, const struct sk_buff *skb,
        return 0;
 }
 
+static void dump_sk_uid_gid(struct sbuff *m, struct sock *sk)
+{
+       if (!sk || sk->sk_state == TCP_TIME_WAIT)
+               return;
+
+       read_lock_bh(&sk->sk_callback_lock);
+       if (sk->sk_socket && sk->sk_socket->file)
+               sb_add(m, "UID=%u GID=%u ",
+                       sk->sk_socket->file->f_cred->fsuid,
+                       sk->sk_socket->file->f_cred->fsgid);
+       read_unlock_bh(&sk->sk_callback_lock);
+}
+
 /* One level of recursion won't kill us */
 static void dump_ipv4_packet(struct sbuff *m,
                        const struct nf_loginfo *info,
@@ -361,14 +374,8 @@ static void dump_ipv4_packet(struct sbuff *m,
        }
 
        /* Max length: 15 "UID=4294967295 " */
-       if ((logflags & XT_LOG_UID) && !iphoff && skb->sk) {
-               read_lock_bh(&skb->sk->sk_callback_lock);
-               if (skb->sk->sk_socket && skb->sk->sk_socket->file)
-                       sb_add(m, "UID=%u GID=%u ",
-                               skb->sk->sk_socket->file->f_cred->fsuid,
-                               skb->sk->sk_socket->file->f_cred->fsgid);
-               read_unlock_bh(&skb->sk->sk_callback_lock);
-       }
+       if ((logflags & XT_LOG_UID) && !iphoff)
+               dump_sk_uid_gid(m, skb->sk);
 
        /* Max length: 16 "MARK=0xFFFFFFFF " */
        if (!iphoff && skb->mark)
@@ -436,8 +443,8 @@ log_packet_common(struct sbuff *m,
                  const struct nf_loginfo *loginfo,
                  const char *prefix)
 {
-       sb_add(m, "<%d>%sIN=%s OUT=%s ", loginfo->u.log.level,
-              prefix,
+       sb_add(m, KERN_SOH "%c%sIN=%s OUT=%s ",
+              '0' + loginfo->u.log.level, prefix,
               in ? in->name : "",
               out ? out->name : "");
 #ifdef CONFIG_BRIDGE_NETFILTER
@@ -717,14 +724,8 @@ static void dump_ipv6_packet(struct sbuff *m,
        }
 
        /* Max length: 15 "UID=4294967295 " */
-       if ((logflags & XT_LOG_UID) && recurse && skb->sk) {
-               read_lock_bh(&skb->sk->sk_callback_lock);
-               if (skb->sk->sk_socket && skb->sk->sk_socket->file)
-                       sb_add(m, "UID=%u GID=%u ",
-                               skb->sk->sk_socket->file->f_cred->fsuid,
-                               skb->sk->sk_socket->file->f_cred->fsgid);
-               read_unlock_bh(&skb->sk->sk_callback_lock);
-       }
+       if ((logflags & XT_LOG_UID) && recurse)
+               dump_sk_uid_gid(m, skb->sk);
 
        /* Max length: 16 "MARK=0xFFFFFFFF " */
        if (!recurse && skb->mark)
index 06592d8b4a2b4eba33d9e71e44fc75ca206b38a8..7261eb81974ff9f3761976372c9272db04a62abd 100644 (file)
@@ -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;
@@ -1169,7 +1169,12 @@ static int nr_recvmsg(struct kiocb *iocb, struct socket *sock,
                msg->msg_flags |= MSG_TRUNC;
        }
 
-       skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
+       er = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
+       if (er < 0) {
+               skb_free_datagram(sk, skb);
+               release_sock(sk);
+               return er;
+       }
 
        if (sax != NULL) {
                sax->sax25_family = AF_NETROM;
index f3f96badf5aac0202a2bd54155d595b0373a18df..954405ceae9ed5141293d3f47ce7c784aeee3c31 100644 (file)
@@ -45,7 +45,7 @@ static int make_writable(struct sk_buff *skb, int write_len)
        return pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
 }
 
-/* remove VLAN header from packet and update csum accrodingly. */
+/* remove VLAN header from packet and update csum accordingly. */
 static int __pop_vlan_tci(struct sk_buff *skb, __be16 *current_tci)
 {
        struct vlan_hdr *vhdr;
index d8277d29e7102caf343d78b802f3371283c40de1..cf58cedad0833f9e9e704401fdecb5480c121caf 100644 (file)
@@ -425,10 +425,10 @@ static int validate_sample(const struct nlattr *attr,
 static int validate_tp_port(const struct sw_flow_key *flow_key)
 {
        if (flow_key->eth.type == htons(ETH_P_IP)) {
-               if (flow_key->ipv4.tp.src && flow_key->ipv4.tp.dst)
+               if (flow_key->ipv4.tp.src || flow_key->ipv4.tp.dst)
                        return 0;
        } else if (flow_key->eth.type == htons(ETH_P_IPV6)) {
-               if (flow_key->ipv6.tp.src && flow_key->ipv6.tp.dst)
+               if (flow_key->ipv6.tp.src || flow_key->ipv6.tp.dst)
                        return 0;
        }
 
@@ -460,7 +460,7 @@ static int validate_set(const struct nlattr *a,
                if (flow_key->eth.type != htons(ETH_P_IP))
                        return -EINVAL;
 
-               if (!flow_key->ipv4.addr.src || !flow_key->ipv4.addr.dst)
+               if (!flow_key->ip.proto)
                        return -EINVAL;
 
                ipv4_key = nla_data(ovs_key);
index 9b75617ca4e031db60ddbeb609bb658af7f8de0c..c30df1a10c670ad01b7b8b88c49434c95c0c659e 100644 (file)
@@ -145,15 +145,17 @@ u64 ovs_flow_used_time(unsigned long flow_jiffies);
  *  OVS_KEY_ATTR_PRIORITY      4    --     4      8
  *  OVS_KEY_ATTR_IN_PORT       4    --     4      8
  *  OVS_KEY_ATTR_ETHERNET     12    --     4     16
+ *  OVS_KEY_ATTR_ETHERTYPE     2     2     4      8  (outer VLAN ethertype)
  *  OVS_KEY_ATTR_8021Q         4    --     4      8
- *  OVS_KEY_ATTR_ETHERTYPE     2     2     4      8
+ *  OVS_KEY_ATTR_ENCAP         0    --     4      4  (VLAN encapsulation)
+ *  OVS_KEY_ATTR_ETHERTYPE     2     2     4      8  (inner VLAN ethertype)
  *  OVS_KEY_ATTR_IPV6         40    --     4     44
  *  OVS_KEY_ATTR_ICMPV6        2     2     4      8
  *  OVS_KEY_ATTR_ND           28    --     4     32
  *  -------------------------------------------------
- *  total                                       132
+ *  total                                       144
  */
-#define FLOW_BUFSIZE 132
+#define FLOW_BUFSIZE 144
 
 int ovs_flow_to_nlattrs(const struct sw_flow_key *, struct sk_buff *);
 int ovs_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp,
index 6aabd77d1cfdd5cddd34b55dc69699cae9956e57..564b9fc8efd3c8778ef8ba155cf17f79d92a9a80 100644 (file)
@@ -250,10 +250,11 @@ cbq_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr)
                        else if ((cl = defmap[res.classid & TC_PRIO_MAX]) == NULL)
                                cl = defmap[TC_PRIO_BESTEFFORT];
 
-                       if (cl == NULL || cl->level >= head->level)
+                       if (cl == NULL)
                                goto fallback;
                }
-
+               if (cl->level >= head->level)
+                       goto fallback;
 #ifdef CONFIG_NET_CLS_ACT
                switch (result) {
                case TC_ACT_QUEUED:
index 9fc1c62ec80e1ad56b760b2820c0c4f2e495d4a0..4e606fcb2534929a2470e807816ac1089d81b7b2 100644 (file)
@@ -191,7 +191,6 @@ static int fq_codel_enqueue(struct sk_buff *skb, struct Qdisc *sch)
 
        if (list_empty(&flow->flowchain)) {
                list_add_tail(&flow->flowchain, &q->new_flows);
-               codel_vars_init(&flow->cvars);
                q->new_flow_count++;
                flow->deficit = q->quantum;
                flow->dropped = 0;
@@ -418,6 +417,7 @@ static int fq_codel_init(struct Qdisc *sch, struct nlattr *opt)
                        struct fq_codel_flow *flow = q->flows + i;
 
                        INIT_LIST_HEAD(&flow->flowchain);
+                       codel_vars_init(&flow->cvars);
                }
        }
        if (sch->limit >= 1)
index e901583e4ea533581f13e0fb39599f72e57b3e4c..d42234c0f13bf4d4829930e0f6bcb30681ad4782 100644 (file)
@@ -102,9 +102,8 @@ static inline int gred_wred_mode_check(struct Qdisc *sch)
                if (q == NULL)
                        continue;
 
-               for (n = 0; n < table->DPs; n++)
-                       if (table->tab[n] && table->tab[n] != q &&
-                           table->tab[n]->prio == q->prio)
+               for (n = i + 1; n < table->DPs; n++)
+                       if (table->tab[n] && table->tab[n]->prio == q->prio)
                                return 1;
        }
 
@@ -137,6 +136,7 @@ static inline void gred_store_wred_set(struct gred_sched *table,
                                       struct gred_sched_data *q)
 {
        table->wred_set.qavg = q->vars.qavg;
+       table->wred_set.qidlestart = q->vars.qidlestart;
 }
 
 static inline int gred_use_ecn(struct gred_sched *t)
@@ -176,7 +176,7 @@ static int gred_enqueue(struct sk_buff *skb, struct Qdisc *sch)
                skb->tc_index = (skb->tc_index & ~GRED_VQ_MASK) | dp;
        }
 
-       /* sum up all the qaves of prios <= to ours to get the new qave */
+       /* sum up all the qaves of prios < ours to get the new qave */
        if (!gred_wred_mode(t) && gred_rio_mode(t)) {
                int i;
 
@@ -260,16 +260,18 @@ static struct sk_buff *gred_dequeue(struct Qdisc *sch)
                } else {
                        q->backlog -= qdisc_pkt_len(skb);
 
-                       if (!q->backlog && !gred_wred_mode(t))
-                               red_start_of_idle_period(&q->vars);
+                       if (gred_wred_mode(t)) {
+                               if (!sch->qstats.backlog)
+                                       red_start_of_idle_period(&t->wred_set);
+                       } else {
+                               if (!q->backlog)
+                                       red_start_of_idle_period(&q->vars);
+                       }
                }
 
                return skb;
        }
 
-       if (gred_wred_mode(t) && !red_is_idling(&t->wred_set))
-               red_start_of_idle_period(&t->wred_set);
-
        return NULL;
 }
 
@@ -291,19 +293,20 @@ static unsigned int gred_drop(struct Qdisc *sch)
                        q->backlog -= len;
                        q->stats.other++;
 
-                       if (!q->backlog && !gred_wred_mode(t))
-                               red_start_of_idle_period(&q->vars);
+                       if (gred_wred_mode(t)) {
+                               if (!sch->qstats.backlog)
+                                       red_start_of_idle_period(&t->wred_set);
+                       } else {
+                               if (!q->backlog)
+                                       red_start_of_idle_period(&q->vars);
+                       }
                }
 
                qdisc_drop(skb, sch);
                return len;
        }
 
-       if (gred_wred_mode(t) && !red_is_idling(&t->wred_set))
-               red_start_of_idle_period(&t->wred_set);
-
        return 0;
-
 }
 
 static void gred_reset(struct Qdisc *sch)
@@ -535,6 +538,7 @@ static int gred_dump(struct Qdisc *sch, struct sk_buff *skb)
        for (i = 0; i < MAX_DPs; i++) {
                struct gred_sched_data *q = table->tab[i];
                struct tc_gred_qopt opt;
+               unsigned long qavg;
 
                memset(&opt, 0, sizeof(opt));
 
@@ -566,7 +570,9 @@ static int gred_dump(struct Qdisc *sch, struct sk_buff *skb)
                if (gred_wred_mode(table))
                        gred_load_wred_set(table, q);
 
-               opt.qave = red_calc_qavg(&q->parms, &q->vars, q->vars.qavg);
+               qavg = red_calc_qavg(&q->parms, &q->vars,
+                                    q->vars.qavg >> q->parms.Wlog);
+               opt.qave = qavg >> q->parms.Wlog;
 
 append_opt:
                if (nla_append(skb, sizeof(opt), &opt) < 0)
index e4723d31fdd56d6a46b2519afd19d612c7336749..211a212170451c41f352f087dc9e0b3af9e8ae2c 100644 (file)
@@ -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;
                        }
                }
index 838e18b4d7ea62cfd4d57e9d64a86630a0100f67..be50aa234dcdea30a5c7986eaeaae3570f64a6e3 100644 (file)
@@ -364,6 +364,25 @@ finish:
        return retval;
 }
 
+static void sctp_packet_release_owner(struct sk_buff *skb)
+{
+       sk_free(skb->sk);
+}
+
+static void sctp_packet_set_owner_w(struct sk_buff *skb, struct sock *sk)
+{
+       skb_orphan(skb);
+       skb->sk = sk;
+       skb->destructor = sctp_packet_release_owner;
+
+       /*
+        * The data chunks have already been accounted for in sctp_sendmsg(),
+        * therefore only reserve a single byte to keep socket around until
+        * the packet has been transmitted.
+        */
+       atomic_inc(&sk->sk_wmem_alloc);
+}
+
 /* All packets are sent to the network through this function from
  * sctp_outq_tail().
  *
@@ -405,7 +424,7 @@ int sctp_packet_transmit(struct sctp_packet *packet)
        /* Set the owning socket so that we know where to get the
         * destination IP address.
         */
-       skb_set_owner_w(nskb, sk);
+       sctp_packet_set_owner_w(nskb, sk);
 
        if (!sctp_transport_dst_check(tp)) {
                sctp_transport_route(tp, NULL, sctp_sk(sk));
index a5a402a7d21f9e888b1c3f45b3bed09e8baf57e8..5d7f61d7559c9753c9bff0f29b371b5e62b5f0d9 100644 (file)
@@ -969,11 +969,11 @@ static bool xprt_dynamic_free_slot(struct rpc_xprt *xprt, struct rpc_rqst *req)
        return false;
 }
 
-static void xprt_alloc_slot(struct rpc_task *task)
+void xprt_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task)
 {
-       struct rpc_xprt *xprt = task->tk_xprt;
        struct rpc_rqst *req;
 
+       spin_lock(&xprt->reserve_lock);
        if (!list_empty(&xprt->free)) {
                req = list_entry(xprt->free.next, struct rpc_rqst, rq_list);
                list_del(&req->rq_list);
@@ -994,12 +994,29 @@ static void xprt_alloc_slot(struct rpc_task *task)
        default:
                task->tk_status = -EAGAIN;
        }
+       spin_unlock(&xprt->reserve_lock);
        return;
 out_init_req:
        task->tk_status = 0;
        task->tk_rqstp = req;
        xprt_request_init(task, xprt);
+       spin_unlock(&xprt->reserve_lock);
+}
+EXPORT_SYMBOL_GPL(xprt_alloc_slot);
+
+void xprt_lock_and_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task)
+{
+       /* Note: grabbing the xprt_lock_write() ensures that we throttle
+        * new slot allocation if the transport is congested (i.e. when
+        * reconnecting a stream transport or when out of socket write
+        * buffer space).
+        */
+       if (xprt_lock_write(xprt, task)) {
+               xprt_alloc_slot(xprt, task);
+               xprt_release_write(xprt, task);
+       }
 }
+EXPORT_SYMBOL_GPL(xprt_lock_and_alloc_slot);
 
 static void xprt_free_slot(struct rpc_xprt *xprt, struct rpc_rqst *req)
 {
@@ -1083,20 +1100,9 @@ void xprt_reserve(struct rpc_task *task)
        if (task->tk_rqstp != NULL)
                return;
 
-       /* Note: grabbing the xprt_lock_write() here is not strictly needed,
-        * but ensures that we throttle new slot allocation if the transport
-        * is congested (e.g. if reconnecting or if we're out of socket
-        * write buffer space).
-        */
        task->tk_timeout = 0;
        task->tk_status = -EAGAIN;
-       if (!xprt_lock_write(xprt, task))
-               return;
-
-       spin_lock(&xprt->reserve_lock);
-       xprt_alloc_slot(task);
-       spin_unlock(&xprt->reserve_lock);
-       xprt_release_write(xprt, task);
+       xprt->ops->alloc_slot(xprt, task);
 }
 
 static inline __be32 xprt_alloc_xid(struct rpc_xprt *xprt)
index 06cdbff79e4af433d5a4ea3a2766d6d09a9b5a01..5d9202dc7cb127f5158a2a6e275fa0656c18f0a6 100644 (file)
@@ -713,6 +713,7 @@ static void xprt_rdma_print_stats(struct rpc_xprt *xprt, struct seq_file *seq)
 static struct rpc_xprt_ops xprt_rdma_procs = {
        .reserve_xprt           = xprt_rdma_reserve_xprt,
        .release_xprt           = xprt_release_xprt_cong, /* sunrpc/xprt.c */
+       .alloc_slot             = xprt_alloc_slot,
        .release_request        = xprt_release_rqst_cong,       /* ditto */
        .set_retrans_timeout    = xprt_set_retrans_timeout_def, /* ditto */
        .rpcbind                = rpcb_getport_async,   /* sunrpc/rpcb_clnt.c */
index 400567243f84ba95e8f04d8a631a3b74539c53ea..a35b8e52e551d4b931110a78727604c8d6af8283 100644 (file)
@@ -2473,6 +2473,7 @@ static void bc_destroy(struct rpc_xprt *xprt)
 static struct rpc_xprt_ops xs_local_ops = {
        .reserve_xprt           = xprt_reserve_xprt,
        .release_xprt           = xs_tcp_release_xprt,
+       .alloc_slot             = xprt_alloc_slot,
        .rpcbind                = xs_local_rpcbind,
        .set_port               = xs_local_set_port,
        .connect                = xs_connect,
@@ -2489,6 +2490,7 @@ static struct rpc_xprt_ops xs_udp_ops = {
        .set_buffer_size        = xs_udp_set_buffer_size,
        .reserve_xprt           = xprt_reserve_xprt_cong,
        .release_xprt           = xprt_release_xprt_cong,
+       .alloc_slot             = xprt_alloc_slot,
        .rpcbind                = rpcb_getport_async,
        .set_port               = xs_set_port,
        .connect                = xs_connect,
@@ -2506,6 +2508,7 @@ static struct rpc_xprt_ops xs_udp_ops = {
 static struct rpc_xprt_ops xs_tcp_ops = {
        .reserve_xprt           = xprt_reserve_xprt,
        .release_xprt           = xs_tcp_release_xprt,
+       .alloc_slot             = xprt_lock_and_alloc_slot,
        .rpcbind                = rpcb_getport_async,
        .set_port               = xs_set_port,
        .connect                = xs_connect,
index 97026f3b215a1c85b3ddf0f0f6cf71636e76a586..1e37dbf00cb3f3850d3785827f896ca09339873b 100644 (file)
@@ -5633,8 +5633,10 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
                       sizeof(connect.ht_capa_mask));
 
        if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) {
-               if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
+               if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]) {
+                       kfree(connkeys);
                        return -EINVAL;
+               }
                memcpy(&connect.ht_capa,
                       nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]),
                       sizeof(connect.ht_capa));
index 54a0dc2e2f8d45d7a842be98882969f696c07ec2..ab2bb42fe094b7390d5135ec6e37b9113ea8219b 100644 (file)
@@ -212,7 +212,7 @@ resume:
                /* only the first xfrm gets the encap type */
                encap_type = 0;
 
-               if (async && x->repl->check(x, skb, seq)) {
+               if (async && x->repl->recheck(x, skb, seq)) {
                        XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATESEQERROR);
                        goto drop_unlock;
                }
index 5a2aa17e4d3c4a3667783266ddbb8992a3eff6bd..387848e900783f6e6862c6d2c0b52ab45bbcfe50 100644 (file)
@@ -585,6 +585,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);
@@ -1763,7 +1764,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);
        }
index 2f6d11d04a2b29910a1f284d3e3af8b0db1bfcce..3efb07d3eb27425c8b9b5114c925eb9e7f402c9e 100644 (file)
@@ -420,6 +420,18 @@ err:
        return -EINVAL;
 }
 
+static int xfrm_replay_recheck_esn(struct xfrm_state *x,
+                                  struct sk_buff *skb, __be32 net_seq)
+{
+       if (unlikely(XFRM_SKB_CB(skb)->seq.input.hi !=
+                    htonl(xfrm_replay_seqhi(x, net_seq)))) {
+                       x->stats.replay_window++;
+                       return -EINVAL;
+       }
+
+       return xfrm_replay_check_esn(x, skb, net_seq);
+}
+
 static void xfrm_replay_advance_esn(struct xfrm_state *x, __be32 net_seq)
 {
        unsigned int bitnr, nr, i;
@@ -479,6 +491,7 @@ static void xfrm_replay_advance_esn(struct xfrm_state *x, __be32 net_seq)
 static struct xfrm_replay xfrm_replay_legacy = {
        .advance        = xfrm_replay_advance,
        .check          = xfrm_replay_check,
+       .recheck        = xfrm_replay_check,
        .notify         = xfrm_replay_notify,
        .overflow       = xfrm_replay_overflow,
 };
@@ -486,6 +499,7 @@ static struct xfrm_replay xfrm_replay_legacy = {
 static struct xfrm_replay xfrm_replay_bmp = {
        .advance        = xfrm_replay_advance_bmp,
        .check          = xfrm_replay_check_bmp,
+       .recheck        = xfrm_replay_check_bmp,
        .notify         = xfrm_replay_notify_bmp,
        .overflow       = xfrm_replay_overflow_bmp,
 };
@@ -493,6 +507,7 @@ static struct xfrm_replay xfrm_replay_bmp = {
 static struct xfrm_replay xfrm_replay_esn = {
        .advance        = xfrm_replay_advance_esn,
        .check          = xfrm_replay_check_esn,
+       .recheck        = xfrm_replay_recheck_esn,
        .notify         = xfrm_replay_notify_bmp,
        .overflow       = xfrm_replay_overflow_esn,
 };
index e75d8e47f35cab2bdddd1051e6da556ef20eb26c..289f4bf18ff05751c5938c8722b098f6a560ee00 100644 (file)
@@ -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;
index 16aa2d424985fa524e4eb8a60122be8d7ad817b0..bbbd276659ba5edad0e01b915d03639c7980803f 100644 (file)
@@ -18,14 +18,22 @@ HOSTCFLAGS_bpf-direct.o += -idirafter $(objtree)/include
 bpf-direct-objs := bpf-direct.o
 
 # Try to match the kernel target.
-ifeq ($(CONFIG_64BIT),)
-HOSTCFLAGS_bpf-direct.o += -m32
-HOSTCFLAGS_dropper.o += -m32
-HOSTCFLAGS_bpf-helper.o += -m32
-HOSTCFLAGS_bpf-fancy.o += -m32
-HOSTLOADLIBES_bpf-direct += -m32
-HOSTLOADLIBES_bpf-fancy += -m32
-HOSTLOADLIBES_dropper += -m32
+ifndef CONFIG_64BIT
+
+# s390 has -m31 flag to build 31 bit binaries
+ifndef CONFIG_S390
+MFLAG = -m32
+else
+MFLAG = -m31
+endif
+
+HOSTCFLAGS_bpf-direct.o += $(MFLAG)
+HOSTCFLAGS_dropper.o += $(MFLAG)
+HOSTCFLAGS_bpf-helper.o += $(MFLAG)
+HOSTCFLAGS_bpf-fancy.o += $(MFLAG)
+HOSTLOADLIBES_bpf-direct += $(MFLAG)
+HOSTLOADLIBES_bpf-fancy += $(MFLAG)
+HOSTLOADLIBES_dropper += $(MFLAG)
 endif
 
 # Tell kbuild to always build the programs
index 643279dd30fbbe6151578e328be864745cc03216..38ee70f3cd5b970101edd6d2edb52b4df8d73d14 100644 (file)
@@ -59,6 +59,16 @@ void seccomp_bpf_print(struct sock_filter *filter, size_t count);
 #define FIND_LABEL(labels, label) seccomp_bpf_label((labels), #label)
 
 #define EXPAND(...) __VA_ARGS__
+
+/* Ensure that we load the logically correct offset. */
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define LO_ARG(idx) offsetof(struct seccomp_data, args[(idx)])
+#elif __BYTE_ORDER == __BIG_ENDIAN
+#define LO_ARG(idx) offsetof(struct seccomp_data, args[(idx)]) + sizeof(__u32)
+#else
+#error "Unknown endianness"
+#endif
+
 /* Map all width-sensitive operations */
 #if __BITS_PER_LONG == 32
 
@@ -70,21 +80,16 @@ void seccomp_bpf_print(struct sock_filter *filter, size_t count);
 #define JLE(x, jt) JLE32(x, EXPAND(jt))
 #define JA(x, jt) JA32(x, EXPAND(jt))
 #define ARG(i) ARG_32(i)
-#define LO_ARG(idx) offsetof(struct seccomp_data, args[(idx)])
 
 #elif __BITS_PER_LONG == 64
 
 /* Ensure that we load the logically correct offset. */
 #if __BYTE_ORDER == __LITTLE_ENDIAN
 #define ENDIAN(_lo, _hi) _lo, _hi
-#define LO_ARG(idx) offsetof(struct seccomp_data, args[(idx)])
 #define HI_ARG(idx) offsetof(struct seccomp_data, args[(idx)]) + sizeof(__u32)
 #elif __BYTE_ORDER == __BIG_ENDIAN
 #define ENDIAN(_lo, _hi) _hi, _lo
-#define LO_ARG(idx) offsetof(struct seccomp_data, args[(idx)]) + sizeof(__u32)
 #define HI_ARG(idx) offsetof(struct seccomp_data, args[(idx)])
-#else
-#error "Unknown endianness"
 #endif
 
 union arg64 {
index c3f69ae275d1f7710b5f38c02e9daf6b45b947a4..4d908d16c035c4e6c582e254e531998e7f6156ae 100644 (file)
@@ -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
index 4235a6361fec8076de79166cdf78f37260be30dc..b3d907eb93a91e7437ec8be8dac4248990eaf1e0 100644 (file)
@@ -74,8 +74,13 @@ kallsyms()
        info KSYM ${2}
        local kallsymopt;
 
+       if [ -n "${CONFIG_SYMBOL_PREFIX}" ]; then
+               kallsymopt="${kallsymopt} \
+                           --symbol-prefix=${CONFIG_SYMBOL_PREFIX}"
+       fi
+
        if [ -n "${CONFIG_KALLSYMS_ALL}" ]; then
-               kallsymopt=--all-symbols
+               kallsymopt="${kallsymopt} --all-symbols"
        fi
 
        local aflags="${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL}               \
index 8901501425f42beb8a0e23dade6b4e4200019bf1..eb5484504f506490eb7c4f90a81cba92b7020c40 100644 (file)
@@ -33,6 +33,9 @@ char *evm_config_xattrnames[] = {
 #endif
 #ifdef CONFIG_SECURITY_SMACK
        XATTR_NAME_SMACK,
+#endif
+#ifdef CONFIG_IMA_APPRAISE
+       XATTR_NAME_IMA,
 #endif
        XATTR_NAME_CAPS,
        NULL
index 399641c3e84644821e711c0ade263a2ee89cdc49..d82a5a13d8551ca1b857a13c401f706340b88850 100644 (file)
@@ -22,7 +22,7 @@
 #include "integrity.h"
 
 static struct rb_root integrity_iint_tree = RB_ROOT;
-static DEFINE_SPINLOCK(integrity_iint_lock);
+static DEFINE_RWLOCK(integrity_iint_lock);
 static struct kmem_cache *iint_cache __read_mostly;
 
 int iint_initialized;
@@ -35,8 +35,6 @@ static struct integrity_iint_cache *__integrity_iint_find(struct inode *inode)
        struct integrity_iint_cache *iint;
        struct rb_node *n = integrity_iint_tree.rb_node;
 
-       assert_spin_locked(&integrity_iint_lock);
-
        while (n) {
                iint = rb_entry(n, struct integrity_iint_cache, rb_node);
 
@@ -63,9 +61,9 @@ struct integrity_iint_cache *integrity_iint_find(struct inode *inode)
        if (!IS_IMA(inode))
                return NULL;
 
-       spin_lock(&integrity_iint_lock);
+       read_lock(&integrity_iint_lock);
        iint = __integrity_iint_find(inode);
-       spin_unlock(&integrity_iint_lock);
+       read_unlock(&integrity_iint_lock);
 
        return iint;
 }
@@ -74,59 +72,53 @@ static void iint_free(struct integrity_iint_cache *iint)
 {
        iint->version = 0;
        iint->flags = 0UL;
+       iint->ima_status = INTEGRITY_UNKNOWN;
        iint->evm_status = INTEGRITY_UNKNOWN;
        kmem_cache_free(iint_cache, iint);
 }
 
 /**
- * integrity_inode_alloc - allocate an iint associated with an inode
+ * integrity_inode_get - find or allocate an iint associated with an inode
  * @inode: pointer to the inode
+ * @return: allocated iint
+ *
+ * Caller must lock i_mutex
  */
-int integrity_inode_alloc(struct inode *inode)
+struct integrity_iint_cache *integrity_inode_get(struct inode *inode)
 {
        struct rb_node **p;
-       struct rb_node *new_node, *parent = NULL;
-       struct integrity_iint_cache *new_iint, *test_iint;
-       int rc;
+       struct rb_node *node, *parent = NULL;
+       struct integrity_iint_cache *iint, *test_iint;
 
-       new_iint = kmem_cache_alloc(iint_cache, GFP_NOFS);
-       if (!new_iint)
-               return -ENOMEM;
+       iint = integrity_iint_find(inode);
+       if (iint)
+               return iint;
 
-       new_iint->inode = inode;
-       new_node = &new_iint->rb_node;
+       iint = kmem_cache_alloc(iint_cache, GFP_NOFS);
+       if (!iint)
+               return NULL;
 
-       mutex_lock(&inode->i_mutex);    /* i_flags */
-       spin_lock(&integrity_iint_lock);
+       write_lock(&integrity_iint_lock);
 
        p = &integrity_iint_tree.rb_node;
        while (*p) {
                parent = *p;
                test_iint = rb_entry(parent, struct integrity_iint_cache,
                                     rb_node);
-               rc = -EEXIST;
                if (inode < test_iint->inode)
                        p = &(*p)->rb_left;
-               else if (inode > test_iint->inode)
-                       p = &(*p)->rb_right;
                else
-                       goto out_err;
+                       p = &(*p)->rb_right;
        }
 
+       iint->inode = inode;
+       node = &iint->rb_node;
        inode->i_flags |= S_IMA;
-       rb_link_node(new_node, parent, p);
-       rb_insert_color(new_node, &integrity_iint_tree);
+       rb_link_node(node, parent, p);
+       rb_insert_color(node, &integrity_iint_tree);
 
-       spin_unlock(&integrity_iint_lock);
-       mutex_unlock(&inode->i_mutex);  /* i_flags */
-
-       return 0;
-out_err:
-       spin_unlock(&integrity_iint_lock);
-       mutex_unlock(&inode->i_mutex);  /* i_flags */
-       iint_free(new_iint);
-
-       return rc;
+       write_unlock(&integrity_iint_lock);
+       return iint;
 }
 
 /**
@@ -142,10 +134,10 @@ void integrity_inode_free(struct inode *inode)
        if (!IS_IMA(inode))
                return;
 
-       spin_lock(&integrity_iint_lock);
+       write_lock(&integrity_iint_lock);
        iint = __integrity_iint_find(inode);
        rb_erase(&iint->rb_node, &integrity_iint_tree);
-       spin_unlock(&integrity_iint_lock);
+       write_unlock(&integrity_iint_lock);
 
        iint_free(iint);
 }
@@ -157,7 +149,7 @@ static void init_once(void *foo)
        memset(iint, 0, sizeof *iint);
        iint->version = 0;
        iint->flags = 0UL;
-       mutex_init(&iint->mutex);
+       iint->ima_status = INTEGRITY_UNKNOWN;
        iint->evm_status = INTEGRITY_UNKNOWN;
 }
 
index b9c1219924f197b7195650ea99cc0c28b79aaa56..d232c73647ae46ee0f8295a4965419f5b044ca99 100644 (file)
@@ -11,6 +11,7 @@ config IMA
        select CRYPTO_SHA1
        select TCG_TPM if HAS_IOMEM && !UML
        select TCG_TIS if TCG_TPM && X86
+       select TCG_IBMVTPM if TCG_TPM && PPC64
        help
          The Trusted Computing Group(TCG) runtime Integrity
          Measurement Architecture(IMA) maintains a list of hash
@@ -55,3 +56,18 @@ config IMA_LSM_RULES
        default y
        help
          Disabling this option will disregard LSM based policy rules.
+
+config IMA_APPRAISE
+       bool "Appraise integrity measurements"
+       depends on IMA
+       default n
+       help
+         This option enables local measurement integrity appraisal.
+         It requires the system to be labeled with a security extended
+         attribute containing the file hash measurement.  To protect
+         the security extended attributes from offline attack, enable
+         and configure EVM.
+
+         For more information on integrity appraisal refer to:
+         <http://linux-ima.sourceforge.net>
+         If unsure, say N.
index 5f740f6971e1f59c6d3e7bfb6254d6350f3f55fa..3f2ca6bdc384ecbb5b3de4dc53d32c9a802d5958 100644 (file)
@@ -8,3 +8,4 @@ obj-$(CONFIG_IMA) += ima.o
 ima-y := ima_fs.o ima_queue.o ima_init.o ima_main.o ima_crypto.o ima_api.o \
         ima_policy.o
 ima-$(CONFIG_IMA_AUDIT) += ima_audit.o
+ima-$(CONFIG_IMA_APPRAISE) += ima_appraise.o
index e7c99fd0d2236e7d3a923733bdf7e622f8cd993a..8180adde10b72486644ba9eb1902c02b855a06c2 100644 (file)
@@ -40,6 +40,7 @@ enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8 };
 extern int ima_initialized;
 extern int ima_used_chip;
 extern char *ima_hash;
+extern int ima_appraise;
 
 /* IMA inode template definition */
 struct ima_template_data {
@@ -107,11 +108,14 @@ static inline unsigned long ima_hash_key(u8 *digest)
 }
 
 /* LIM API function definitions */
+int ima_get_action(struct inode *inode, int mask, int function);
 int ima_must_measure(struct inode *inode, int mask, int function);
 int ima_collect_measurement(struct integrity_iint_cache *iint,
                            struct file *file);
 void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file,
                           const unsigned char *filename);
+void ima_audit_measurement(struct integrity_iint_cache *iint,
+                          const unsigned char *filename);
 int ima_store_template(struct ima_template_entry *entry, int violation,
                       struct inode *inode);
 void ima_template_show(struct seq_file *m, void *e, enum ima_show_type show);
@@ -123,14 +127,45 @@ struct integrity_iint_cache *integrity_iint_insert(struct inode *inode);
 struct integrity_iint_cache *integrity_iint_find(struct inode *inode);
 
 /* IMA policy related functions */
-enum ima_hooks { FILE_CHECK = 1, FILE_MMAP, BPRM_CHECK };
+enum ima_hooks { FILE_CHECK = 1, FILE_MMAP, BPRM_CHECK, POST_SETATTR };
 
-int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask);
+int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask,
+                    int flags);
 void ima_init_policy(void);
 void ima_update_policy(void);
 ssize_t ima_parse_add_rule(char *);
 void ima_delete_rules(void);
 
+/* Appraise integrity measurements */
+#define IMA_APPRAISE_ENFORCE   0x01
+#define IMA_APPRAISE_FIX       0x02
+
+#ifdef CONFIG_IMA_APPRAISE
+int ima_appraise_measurement(struct integrity_iint_cache *iint,
+                            struct file *file, const unsigned char *filename);
+int ima_must_appraise(struct inode *inode, enum ima_hooks func, int mask);
+void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file);
+
+#else
+static inline int ima_appraise_measurement(struct integrity_iint_cache *iint,
+                                          struct file *file,
+                                          const unsigned char *filename)
+{
+       return INTEGRITY_UNKNOWN;
+}
+
+static inline int ima_must_appraise(struct inode *inode,
+                                   enum ima_hooks func, int mask)
+{
+       return 0;
+}
+
+static inline void ima_update_xattr(struct integrity_iint_cache *iint,
+                                   struct file *file)
+{
+}
+#endif
+
 /* LSM based policy rules require audit */
 #ifdef CONFIG_IMA_LSM_RULES
 
index 032ff03ad9078bc956faa6c6e6d6759b6e2a0420..b356884fb3ef9c17dbc3d71396ac01c98e20a400 100644 (file)
@@ -9,13 +9,17 @@
  * License.
  *
  * File: ima_api.c
- *     Implements must_measure, collect_measurement, store_measurement,
- *     and store_template.
+ *     Implements must_appraise_or_measure, collect_measurement,
+ *     appraise_measurement, store_measurement and store_template.
  */
 #include <linux/module.h>
 #include <linux/slab.h>
-
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/xattr.h>
+#include <linux/evm.h>
 #include "ima.h"
+
 static const char *IMA_TEMPLATE_NAME = "ima";
 
 /*
@@ -93,7 +97,7 @@ err_out:
 }
 
 /**
- * ima_must_measure - measure decision based on policy.
+ * ima_get_action - appraise & measure decision based on policy.
  * @inode: pointer to inode to measure
  * @mask: contains the permission mask (MAY_READ, MAY_WRITE, MAY_EXECUTE)
  * @function: calling function (FILE_CHECK, BPRM_CHECK, FILE_MMAP)
@@ -105,15 +109,22 @@ err_out:
  *     mask: contains the permission mask
  *     fsmagic: hex value
  *
- * Return 0 to measure. For matching a DONT_MEASURE policy, no policy,
- * or other error, return an error code.
-*/
-int ima_must_measure(struct inode *inode, int mask, int function)
+ * Returns IMA_MEASURE, IMA_APPRAISE mask.
+ *
+ */
+int ima_get_action(struct inode *inode, int mask, int function)
 {
-       int must_measure;
+       int flags = IMA_MEASURE | IMA_AUDIT | IMA_APPRAISE;
+
+       if (!ima_appraise)
+               flags &= ~IMA_APPRAISE;
 
-       must_measure = ima_match_policy(inode, function, mask);
-       return must_measure ? 0 : -EACCES;
+       return ima_match_policy(inode, function, mask, flags);
+}
+
+int ima_must_measure(struct inode *inode, int mask, int function)
+{
+       return ima_match_policy(inode, function, mask, IMA_MEASURE);
 }
 
 /*
@@ -129,16 +140,24 @@ int ima_must_measure(struct inode *inode, int mask, int function)
 int ima_collect_measurement(struct integrity_iint_cache *iint,
                            struct file *file)
 {
-       int result = -EEXIST;
+       struct inode *inode = file->f_dentry->d_inode;
+       const char *filename = file->f_dentry->d_name.name;
+       int result = 0;
 
-       if (!(iint->flags & IMA_MEASURED)) {
+       if (!(iint->flags & IMA_COLLECTED)) {
                u64 i_version = file->f_dentry->d_inode->i_version;
 
-               memset(iint->digest, 0, IMA_DIGEST_SIZE);
-               result = ima_calc_hash(file, iint->digest);
-               if (!result)
+               iint->ima_xattr.type = IMA_XATTR_DIGEST;
+               result = ima_calc_hash(file, iint->ima_xattr.digest);
+               if (!result) {
                        iint->version = i_version;
+                       iint->flags |= IMA_COLLECTED;
+               }
        }
+       if (result)
+               integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode,
+                                   filename, "collect_data", "failed",
+                                   result, 0);
        return result;
 }
 
@@ -167,6 +186,9 @@ void ima_store_measurement(struct integrity_iint_cache *iint,
        struct ima_template_entry *entry;
        int violation = 0;
 
+       if (iint->flags & IMA_MEASURED)
+               return;
+
        entry = kmalloc(sizeof(*entry), GFP_KERNEL);
        if (!entry) {
                integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, filename,
@@ -174,7 +196,7 @@ void ima_store_measurement(struct integrity_iint_cache *iint,
                return;
        }
        memset(&entry->template, 0, sizeof(entry->template));
-       memcpy(entry->template.digest, iint->digest, IMA_DIGEST_SIZE);
+       memcpy(entry->template.digest, iint->ima_xattr.digest, IMA_DIGEST_SIZE);
        strcpy(entry->template.file_name,
               (strlen(filename) > IMA_EVENT_NAME_LEN_MAX) ?
               file->f_dentry->d_name.name : filename);
@@ -185,3 +207,33 @@ void ima_store_measurement(struct integrity_iint_cache *iint,
        if (result < 0)
                kfree(entry);
 }
+
+void ima_audit_measurement(struct integrity_iint_cache *iint,
+                          const unsigned char *filename)
+{
+       struct audit_buffer *ab;
+       char hash[(IMA_DIGEST_SIZE * 2) + 1];
+       int i;
+
+       if (iint->flags & IMA_AUDITED)
+               return;
+
+       for (i = 0; i < IMA_DIGEST_SIZE; i++)
+               hex_byte_pack(hash + (i * 2), iint->ima_xattr.digest[i]);
+       hash[i * 2] = '\0';
+
+       ab = audit_log_start(current->audit_context, GFP_KERNEL,
+                            AUDIT_INTEGRITY_RULE);
+       if (!ab)
+               return;
+
+       audit_log_format(ab, "file=");
+       audit_log_untrustedstring(ab, filename);
+       audit_log_format(ab, " hash=");
+       audit_log_untrustedstring(ab, hash);
+
+       audit_log_task_info(ab, current);
+       audit_log_end(ab);
+
+       iint->flags |= IMA_AUDITED;
+}
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
new file mode 100644 (file)
index 0000000..0aa43bd
--- /dev/null
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) 2011 IBM Corporation
+ *
+ * Author:
+ * Mimi Zohar <zohar@us.ibm.com>
+ *
+ * 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, version 2 of the License.
+ */
+#include <linux/module.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/xattr.h>
+#include <linux/magic.h>
+#include <linux/ima.h>
+#include <linux/evm.h>
+
+#include "ima.h"
+
+static int __init default_appraise_setup(char *str)
+{
+       if (strncmp(str, "off", 3) == 0)
+               ima_appraise = 0;
+       else if (strncmp(str, "fix", 3) == 0)
+               ima_appraise = IMA_APPRAISE_FIX;
+       return 1;
+}
+
+__setup("ima_appraise=", default_appraise_setup);
+
+/*
+ * ima_must_appraise - set appraise flag
+ *
+ * Return 1 to appraise
+ */
+int ima_must_appraise(struct inode *inode, enum ima_hooks func, int mask)
+{
+       if (!ima_appraise)
+               return 0;
+
+       return ima_match_policy(inode, func, mask, IMA_APPRAISE);
+}
+
+static void ima_fix_xattr(struct dentry *dentry,
+                         struct integrity_iint_cache *iint)
+{
+       iint->ima_xattr.type = IMA_XATTR_DIGEST;
+       __vfs_setxattr_noperm(dentry, XATTR_NAME_IMA, (u8 *)&iint->ima_xattr,
+                             sizeof iint->ima_xattr, 0);
+}
+
+/*
+ * ima_appraise_measurement - appraise file measurement
+ *
+ * Call evm_verifyxattr() to verify the integrity of 'security.ima'.
+ * Assuming success, compare the xattr hash with the collected measurement.
+ *
+ * Return 0 on success, error code otherwise
+ */
+int ima_appraise_measurement(struct integrity_iint_cache *iint,
+                            struct file *file, const unsigned char *filename)
+{
+       struct dentry *dentry = file->f_dentry;
+       struct inode *inode = dentry->d_inode;
+       struct evm_ima_xattr_data *xattr_value = NULL;
+       enum integrity_status status = INTEGRITY_UNKNOWN;
+       const char *op = "appraise_data";
+       char *cause = "unknown";
+       int rc;
+
+       if (!ima_appraise)
+               return 0;
+       if (!inode->i_op->getxattr)
+               return INTEGRITY_UNKNOWN;
+
+       if (iint->flags & IMA_APPRAISED)
+               return iint->ima_status;
+
+       rc = vfs_getxattr_alloc(dentry, XATTR_NAME_IMA, (char **)&xattr_value,
+                               0, GFP_NOFS);
+       if (rc <= 0) {
+               if (rc && rc != -ENODATA)
+                       goto out;
+
+               cause = "missing-hash";
+               status =
+                   (inode->i_size == 0) ? INTEGRITY_PASS : INTEGRITY_NOLABEL;
+               goto out;
+       }
+
+       status = evm_verifyxattr(dentry, XATTR_NAME_IMA, xattr_value, rc, iint);
+       if ((status != INTEGRITY_PASS) && (status != INTEGRITY_UNKNOWN)) {
+               if ((status == INTEGRITY_NOLABEL)
+                   || (status == INTEGRITY_NOXATTRS))
+                       cause = "missing-HMAC";
+               else if (status == INTEGRITY_FAIL)
+                       cause = "invalid-HMAC";
+               goto out;
+       }
+
+       switch (xattr_value->type) {
+       case IMA_XATTR_DIGEST:
+               rc = memcmp(xattr_value->digest, iint->ima_xattr.digest,
+                           IMA_DIGEST_SIZE);
+               if (rc) {
+                       cause = "invalid-hash";
+                       status = INTEGRITY_FAIL;
+                       print_hex_dump_bytes("security.ima: ", DUMP_PREFIX_NONE,
+                                            xattr_value, sizeof(*xattr_value));
+                       print_hex_dump_bytes("collected: ", DUMP_PREFIX_NONE,
+                                            (u8 *)&iint->ima_xattr,
+                                            sizeof iint->ima_xattr);
+                       break;
+               }
+               status = INTEGRITY_PASS;
+               break;
+       case EVM_IMA_XATTR_DIGSIG:
+               iint->flags |= IMA_DIGSIG;
+               rc = integrity_digsig_verify(INTEGRITY_KEYRING_IMA,
+                                            xattr_value->digest, rc - 1,
+                                            iint->ima_xattr.digest,
+                                            IMA_DIGEST_SIZE);
+               if (rc == -EOPNOTSUPP) {
+                       status = INTEGRITY_UNKNOWN;
+               } else if (rc) {
+                       cause = "invalid-signature";
+                       status = INTEGRITY_FAIL;
+               } else {
+                       status = INTEGRITY_PASS;
+               }
+               break;
+       default:
+               status = INTEGRITY_UNKNOWN;
+               cause = "unknown-ima-data";
+               break;
+       }
+
+out:
+       if (status != INTEGRITY_PASS) {
+               if ((ima_appraise & IMA_APPRAISE_FIX) &&
+                   (!xattr_value ||
+                    xattr_value->type != EVM_IMA_XATTR_DIGSIG)) {
+                       ima_fix_xattr(dentry, iint);
+                       status = INTEGRITY_PASS;
+               }
+               integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, filename,
+                                   op, cause, rc, 0);
+       } else {
+               iint->flags |= IMA_APPRAISED;
+       }
+       iint->ima_status = status;
+       kfree(xattr_value);
+       return status;
+}
+
+/*
+ * ima_update_xattr - update 'security.ima' hash value
+ */
+void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file)
+{
+       struct dentry *dentry = file->f_dentry;
+       int rc = 0;
+
+       /* do not collect and update hash for digital signatures */
+       if (iint->flags & IMA_DIGSIG)
+               return;
+
+       rc = ima_collect_measurement(iint, file);
+       if (rc < 0)
+               return;
+
+       ima_fix_xattr(dentry, iint);
+}
+
+/**
+ * ima_inode_post_setattr - reflect file metadata changes
+ * @dentry: pointer to the affected dentry
+ *
+ * Changes to a dentry's metadata might result in needing to appraise.
+ *
+ * This function is called from notify_change(), which expects the caller
+ * to lock the inode's i_mutex.
+ */
+void ima_inode_post_setattr(struct dentry *dentry)
+{
+       struct inode *inode = dentry->d_inode;
+       struct integrity_iint_cache *iint;
+       int must_appraise, rc;
+
+       if (!ima_initialized || !ima_appraise || !S_ISREG(inode->i_mode)
+           || !inode->i_op->removexattr)
+               return;
+
+       must_appraise = ima_must_appraise(inode, MAY_ACCESS, POST_SETATTR);
+       iint = integrity_iint_find(inode);
+       if (iint) {
+               if (must_appraise)
+                       iint->flags |= IMA_APPRAISE;
+               else
+                       iint->flags &= ~(IMA_APPRAISE | IMA_APPRAISED);
+       }
+       if (!must_appraise)
+               rc = inode->i_op->removexattr(dentry, XATTR_NAME_IMA);
+       return;
+}
+
+/*
+ * ima_protect_xattr - protect 'security.ima'
+ *
+ * Ensure that not just anyone can modify or remove 'security.ima'.
+ */
+static int ima_protect_xattr(struct dentry *dentry, const char *xattr_name,
+                            const void *xattr_value, size_t xattr_value_len)
+{
+       if (strcmp(xattr_name, XATTR_NAME_IMA) == 0) {
+               if (!capable(CAP_SYS_ADMIN))
+                       return -EPERM;
+               return 1;
+       }
+       return 0;
+}
+
+static void ima_reset_appraise_flags(struct inode *inode)
+{
+       struct integrity_iint_cache *iint;
+
+       if (!ima_initialized || !ima_appraise || !S_ISREG(inode->i_mode))
+               return;
+
+       iint = integrity_iint_find(inode);
+       if (!iint)
+               return;
+
+       iint->flags &= ~IMA_DONE_MASK;
+       return;
+}
+
+int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name,
+                      const void *xattr_value, size_t xattr_value_len)
+{
+       int result;
+
+       result = ima_protect_xattr(dentry, xattr_name, xattr_value,
+                                  xattr_value_len);
+       if (result == 1) {
+               ima_reset_appraise_flags(dentry->d_inode);
+               result = 0;
+       }
+       return result;
+}
+
+int ima_inode_removexattr(struct dentry *dentry, const char *xattr_name)
+{
+       int result;
+
+       result = ima_protect_xattr(dentry, xattr_name, NULL, 0);
+       if (result == 1) {
+               ima_reset_appraise_flags(dentry->d_inode);
+               result = 0;
+       }
+       return result;
+}
index 9b3ade7468b283412fa962fa291f0c3f6413812f..b21ee5b5495a8a4a3bf3e5626cd367d16158757f 100644 (file)
@@ -48,7 +48,7 @@ int ima_calc_hash(struct file *file, char *digest)
        struct scatterlist sg[1];
        loff_t i_size, offset = 0;
        char *rbuf;
-       int rc;
+       int rc, read = 0;
 
        rc = init_desc(&desc);
        if (rc != 0)
@@ -59,6 +59,10 @@ int ima_calc_hash(struct file *file, char *digest)
                rc = -ENOMEM;
                goto out;
        }
+       if (!(file->f_mode & FMODE_READ)) {
+               file->f_mode |= FMODE_READ;
+               read = 1;
+       }
        i_size = i_size_read(file->f_dentry->d_inode);
        while (offset < i_size) {
                int rbuf_len;
@@ -80,6 +84,8 @@ int ima_calc_hash(struct file *file, char *digest)
        kfree(rbuf);
        if (!rc)
                rc = crypto_hash_final(&desc, digest);
+       if (read)
+               file->f_mode &= ~FMODE_READ;
 out:
        crypto_free_hash(desc.tfm);
        return rc;
index be8294915cf7f65524a21ab2dd3101ecb0a6edd9..73c9a268253e44718c1f02395f2ffb1f905511ca 100644 (file)
 #include <linux/mount.h>
 #include <linux/mman.h>
 #include <linux/slab.h>
+#include <linux/xattr.h>
 #include <linux/ima.h>
 
 #include "ima.h"
 
 int ima_initialized;
 
+#ifdef CONFIG_IMA_APPRAISE
+int ima_appraise = IMA_APPRAISE_ENFORCE;
+#else
+int ima_appraise;
+#endif
+
 char *ima_hash = "sha1";
 static int __init hash_setup(char *str)
 {
@@ -52,7 +59,7 @@ static void ima_rdwr_violation_check(struct file *file)
        struct dentry *dentry = file->f_path.dentry;
        struct inode *inode = dentry->d_inode;
        fmode_t mode = file->f_mode;
-       int rc;
+       int must_measure;
        bool send_tomtou = false, send_writers = false;
        unsigned char *pathname = NULL, *pathbuf = NULL;
 
@@ -67,8 +74,8 @@ static void ima_rdwr_violation_check(struct file *file)
                goto out;
        }
 
-       rc = ima_must_measure(inode, MAY_READ, FILE_CHECK);
-       if (rc < 0)
+       must_measure = ima_must_measure(inode, MAY_READ, FILE_CHECK);
+       if (!must_measure)
                goto out;
 
        if (atomic_read(&inode->i_writecount) > 0)
@@ -100,17 +107,21 @@ out:
 }
 
 static void ima_check_last_writer(struct integrity_iint_cache *iint,
-                                 struct inode *inode,
-                                 struct file *file)
+                                 struct inode *inode, struct file *file)
 {
        fmode_t mode = file->f_mode;
 
-       mutex_lock(&iint->mutex);
-       if (mode & FMODE_WRITE &&
-           atomic_read(&inode->i_writecount) == 1 &&
-           iint->version != inode->i_version)
-               iint->flags &= ~IMA_MEASURED;
-       mutex_unlock(&iint->mutex);
+       if (!(mode & FMODE_WRITE))
+               return;
+
+       mutex_lock(&inode->i_mutex);
+       if (atomic_read(&inode->i_writecount) == 1 &&
+           iint->version != inode->i_version) {
+               iint->flags &= ~IMA_DONE_MASK;
+               if (iint->flags & IMA_APPRAISE)
+                       ima_update_xattr(iint, file);
+       }
+       mutex_unlock(&inode->i_mutex);
 }
 
 /**
@@ -140,28 +151,37 @@ static int process_measurement(struct file *file, const unsigned char *filename,
        struct inode *inode = file->f_dentry->d_inode;
        struct integrity_iint_cache *iint;
        unsigned char *pathname = NULL, *pathbuf = NULL;
-       int rc = 0;
+       int rc = -ENOMEM, action, must_appraise;
 
        if (!ima_initialized || !S_ISREG(inode->i_mode))
                return 0;
 
-       rc = ima_must_measure(inode, mask, function);
-       if (rc != 0)
-               return rc;
-retry:
-       iint = integrity_iint_find(inode);
-       if (!iint) {
-               rc = integrity_inode_alloc(inode);
-               if (!rc || rc == -EEXIST)
-                       goto retry;
-               return rc;
-       }
+       /* Determine if in appraise/audit/measurement policy,
+        * returns IMA_MEASURE, IMA_APPRAISE, IMA_AUDIT bitmask.  */
+       action = ima_get_action(inode, mask, function);
+       if (!action)
+               return 0;
 
-       mutex_lock(&iint->mutex);
+       must_appraise = action & IMA_APPRAISE;
 
-       rc = iint->flags & IMA_MEASURED ? 1 : 0;
-       if (rc != 0)
+       mutex_lock(&inode->i_mutex);
+
+       iint = integrity_inode_get(inode);
+       if (!iint)
+               goto out;
+
+       /* Determine if already appraised/measured based on bitmask
+        * (IMA_MEASURE, IMA_MEASURED, IMA_APPRAISE, IMA_APPRAISED,
+        *  IMA_AUDIT, IMA_AUDITED) */
+       iint->flags |= action;
+       action &= ~((iint->flags & IMA_DONE_MASK) >> 1);
+
+       /* Nothing to do, just return existing appraised status */
+       if (!action) {
+               if (iint->flags & IMA_APPRAISED)
+                       rc = iint->ima_status;
                goto out;
+       }
 
        rc = ima_collect_measurement(iint, file);
        if (rc != 0)
@@ -177,11 +197,18 @@ retry:
                                pathname = NULL;
                }
        }
-       ima_store_measurement(iint, file, !pathname ? filename : pathname);
+       if (action & IMA_MEASURE)
+               ima_store_measurement(iint, file,
+                                     !pathname ? filename : pathname);
+       if (action & IMA_APPRAISE)
+               rc = ima_appraise_measurement(iint, file,
+                                             !pathname ? filename : pathname);
+       if (action & IMA_AUDIT)
+               ima_audit_measurement(iint, !pathname ? filename : pathname);
        kfree(pathbuf);
 out:
-       mutex_unlock(&iint->mutex);
-       return rc;
+       mutex_unlock(&inode->i_mutex);
+       return (rc && must_appraise) ? -EACCES : 0;
 }
 
 /**
@@ -197,14 +224,14 @@ out:
  */
 int ima_file_mmap(struct file *file, unsigned long prot)
 {
-       int rc;
+       int rc = 0;
 
        if (!file)
                return 0;
        if (prot & PROT_EXEC)
                rc = process_measurement(file, file->f_dentry->d_name.name,
                                         MAY_EXEC, FILE_MMAP);
-       return 0;
+       return (ima_appraise & IMA_APPRAISE_ENFORCE) ? rc : 0;
 }
 
 /**
@@ -228,7 +255,7 @@ int ima_bprm_check(struct linux_binprm *bprm)
                                 (strcmp(bprm->filename, bprm->interp) == 0) ?
                                 bprm->filename : bprm->interp,
                                 MAY_EXEC, BPRM_CHECK);
-       return 0;
+       return (ima_appraise & IMA_APPRAISE_ENFORCE) ? rc : 0;
 }
 
 /**
@@ -249,7 +276,7 @@ int ima_file_check(struct file *file, int mask)
        rc = process_measurement(file, file->f_dentry->d_name.name,
                                 mask & (MAY_READ | MAY_WRITE | MAY_EXEC),
                                 FILE_CHECK);
-       return 0;
+       return (ima_appraise & IMA_APPRAISE_ENFORCE) ? rc : 0;
 }
 EXPORT_SYMBOL_GPL(ima_file_check);
 
index 1a9583008aaef1bf1fe6868f921408ac83d06a63..cda903131dbfb2122abb027261db38ed09e83a17 100644 (file)
 #define IMA_MASK       0x0002
 #define IMA_FSMAGIC    0x0004
 #define IMA_UID                0x0008
+#define IMA_FOWNER     0x0010
 
-enum ima_action { UNKNOWN = -1, DONT_MEASURE = 0, MEASURE };
+#define UNKNOWN                0
+#define MEASURE                0x0001  /* same as IMA_MEASURE */
+#define DONT_MEASURE   0x0002
+#define APPRAISE       0x0004  /* same as IMA_APPRAISE */
+#define DONT_APPRAISE  0x0008
+#define AUDIT          0x0040
 
 #define MAX_LSM_RULES 6
 enum lsm_rule_types { LSM_OBJ_USER, LSM_OBJ_ROLE, LSM_OBJ_TYPE,
        LSM_SUBJ_USER, LSM_SUBJ_ROLE, LSM_SUBJ_TYPE
 };
 
-struct ima_measure_rule_entry {
+struct ima_rule_entry {
        struct list_head list;
-       enum ima_action action;
+       int action;
        unsigned int flags;
        enum ima_hooks func;
        int mask;
        unsigned long fsmagic;
        uid_t uid;
+       uid_t fowner;
        struct {
                void *rule;     /* LSM file metadata specific */
                int type;       /* audit type */
@@ -48,7 +55,7 @@ struct ima_measure_rule_entry {
 
 /*
  * Without LSM specific knowledge, the default policy can only be
- * written in terms of .action, .func, .mask, .fsmagic, and .uid
+ * written in terms of .action, .func, .mask, .fsmagic, .uid, and .fowner
  */
 
 /*
@@ -57,7 +64,7 @@ struct ima_measure_rule_entry {
  * normal users can easily run the machine out of memory simply building
  * and running executables.
  */
-static struct ima_measure_rule_entry default_rules[] = {
+static struct ima_rule_entry default_rules[] = {
        {.action = DONT_MEASURE,.fsmagic = PROC_SUPER_MAGIC,.flags = IMA_FSMAGIC},
        {.action = DONT_MEASURE,.fsmagic = SYSFS_MAGIC,.flags = IMA_FSMAGIC},
        {.action = DONT_MEASURE,.fsmagic = DEBUGFS_MAGIC,.flags = IMA_FSMAGIC},
@@ -75,19 +82,41 @@ static struct ima_measure_rule_entry default_rules[] = {
         .flags = IMA_FUNC | IMA_MASK | IMA_UID},
 };
 
-static LIST_HEAD(measure_default_rules);
-static LIST_HEAD(measure_policy_rules);
-static struct list_head *ima_measure;
+static struct ima_rule_entry default_appraise_rules[] = {
+       {.action = DONT_APPRAISE,.fsmagic = PROC_SUPER_MAGIC,.flags = IMA_FSMAGIC},
+       {.action = DONT_APPRAISE,.fsmagic = SYSFS_MAGIC,.flags = IMA_FSMAGIC},
+       {.action = DONT_APPRAISE,.fsmagic = DEBUGFS_MAGIC,.flags = IMA_FSMAGIC},
+       {.action = DONT_APPRAISE,.fsmagic = TMPFS_MAGIC,.flags = IMA_FSMAGIC},
+       {.action = DONT_APPRAISE,.fsmagic = RAMFS_MAGIC,.flags = IMA_FSMAGIC},
+       {.action = DONT_APPRAISE,.fsmagic = DEVPTS_SUPER_MAGIC,.flags = IMA_FSMAGIC},
+       {.action = DONT_APPRAISE,.fsmagic = BINFMTFS_MAGIC,.flags = IMA_FSMAGIC},
+       {.action = DONT_APPRAISE,.fsmagic = SECURITYFS_MAGIC,.flags = IMA_FSMAGIC},
+       {.action = DONT_APPRAISE,.fsmagic = SELINUX_MAGIC,.flags = IMA_FSMAGIC},
+       {.action = DONT_APPRAISE,.fsmagic = CGROUP_SUPER_MAGIC,.flags = IMA_FSMAGIC},
+       {.action = APPRAISE,.fowner = 0,.flags = IMA_FOWNER},
+};
+
+static LIST_HEAD(ima_default_rules);
+static LIST_HEAD(ima_policy_rules);
+static struct list_head *ima_rules;
 
-static DEFINE_MUTEX(ima_measure_mutex);
+static DEFINE_MUTEX(ima_rules_mutex);
 
 static bool ima_use_tcb __initdata;
-static int __init default_policy_setup(char *str)
+static int __init default_measure_policy_setup(char *str)
 {
        ima_use_tcb = 1;
        return 1;
 }
-__setup("ima_tcb", default_policy_setup);
+__setup("ima_tcb", default_measure_policy_setup);
+
+static bool ima_use_appraise_tcb __initdata;
+static int __init default_appraise_policy_setup(char *str)
+{
+       ima_use_appraise_tcb = 1;
+       return 1;
+}
+__setup("ima_appraise_tcb", default_appraise_policy_setup);
 
 /**
  * ima_match_rules - determine whether an inode matches the measure rule.
@@ -98,7 +127,7 @@ __setup("ima_tcb", default_policy_setup);
  *
  * Returns true on rule match, false on failure.
  */
-static bool ima_match_rules(struct ima_measure_rule_entry *rule,
+static bool ima_match_rules(struct ima_rule_entry *rule,
                            struct inode *inode, enum ima_hooks func, int mask)
 {
        struct task_struct *tsk = current;
@@ -114,6 +143,8 @@ static bool ima_match_rules(struct ima_measure_rule_entry *rule,
                return false;
        if ((rule->flags & IMA_UID) && rule->uid != cred->uid)
                return false;
+       if ((rule->flags & IMA_FOWNER) && rule->fowner != inode->i_uid)
+               return false;
        for (i = 0; i < MAX_LSM_RULES; i++) {
                int rc = 0;
                u32 osid, sid;
@@ -163,39 +194,61 @@ static bool ima_match_rules(struct ima_measure_rule_entry *rule,
  * as elements in the list are never deleted, nor does the list
  * change.)
  */
-int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask)
+int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask,
+                    int flags)
 {
-       struct ima_measure_rule_entry *entry;
+       struct ima_rule_entry *entry;
+       int action = 0, actmask = flags | (flags << 1);
+
+       list_for_each_entry(entry, ima_rules, list) {
+
+               if (!(entry->action & actmask))
+                       continue;
+
+               if (!ima_match_rules(entry, inode, func, mask))
+                       continue;
 
-       list_for_each_entry(entry, ima_measure, list) {
-               bool rc;
+               action |= entry->action & IMA_DO_MASK;
+               if (entry->action & IMA_DO_MASK)
+                       actmask &= ~(entry->action | entry->action << 1);
+               else
+                       actmask &= ~(entry->action | entry->action >> 1);
 
-               rc = ima_match_rules(entry, inode, func, mask);
-               if (rc)
-                       return entry->action;
+               if (!actmask)
+                       break;
        }
-       return 0;
+
+       return action;
 }
 
 /**
  * ima_init_policy - initialize the default measure rules.
  *
- * ima_measure points to either the measure_default_rules or the
- * the new measure_policy_rules.
+ * ima_rules points to either the ima_default_rules or the
+ * the new ima_policy_rules.
  */
 void __init ima_init_policy(void)
 {
-       int i, entries;
+       int i, measure_entries, appraise_entries;
 
        /* if !ima_use_tcb set entries = 0 so we load NO default rules */
-       if (ima_use_tcb)
-               entries = ARRAY_SIZE(default_rules);
-       else
-               entries = 0;
-
-       for (i = 0; i < entries; i++)
-               list_add_tail(&default_rules[i].list, &measure_default_rules);
-       ima_measure = &measure_default_rules;
+       measure_entries = ima_use_tcb ? ARRAY_SIZE(default_rules) : 0;
+       appraise_entries = ima_use_appraise_tcb ?
+                        ARRAY_SIZE(default_appraise_rules) : 0;
+       
+       for (i = 0; i < measure_entries + appraise_entries; i++) {
+               if (i < measure_entries)
+                       list_add_tail(&default_rules[i].list,
+                                     &ima_default_rules);
+               else {
+                       int j = i - measure_entries;
+
+                       list_add_tail(&default_appraise_rules[j].list,
+                                     &ima_default_rules);
+               }
+       }
+
+       ima_rules = &ima_default_rules;
 }
 
 /**
@@ -212,8 +265,8 @@ void ima_update_policy(void)
        int result = 1;
        int audit_info = 0;
 
-       if (ima_measure == &measure_default_rules) {
-               ima_measure = &measure_policy_rules;
+       if (ima_rules == &ima_default_rules) {
+               ima_rules = &ima_policy_rules;
                cause = "complete";
                result = 0;
        }
@@ -224,14 +277,19 @@ void ima_update_policy(void)
 enum {
        Opt_err = -1,
        Opt_measure = 1, Opt_dont_measure,
+       Opt_appraise, Opt_dont_appraise,
+       Opt_audit,
        Opt_obj_user, Opt_obj_role, Opt_obj_type,
        Opt_subj_user, Opt_subj_role, Opt_subj_type,
-       Opt_func, Opt_mask, Opt_fsmagic, Opt_uid
+       Opt_func, Opt_mask, Opt_fsmagic, Opt_uid, Opt_fowner
 };
 
 static match_table_t policy_tokens = {
        {Opt_measure, "measure"},
        {Opt_dont_measure, "dont_measure"},
+       {Opt_appraise, "appraise"},
+       {Opt_dont_appraise, "dont_appraise"},
+       {Opt_audit, "audit"},
        {Opt_obj_user, "obj_user=%s"},
        {Opt_obj_role, "obj_role=%s"},
        {Opt_obj_type, "obj_type=%s"},
@@ -242,10 +300,11 @@ static match_table_t policy_tokens = {
        {Opt_mask, "mask=%s"},
        {Opt_fsmagic, "fsmagic=%s"},
        {Opt_uid, "uid=%s"},
+       {Opt_fowner, "fowner=%s"},
        {Opt_err, NULL}
 };
 
-static int ima_lsm_rule_init(struct ima_measure_rule_entry *entry,
+static int ima_lsm_rule_init(struct ima_rule_entry *entry,
                             char *args, int lsm_rule, int audit_type)
 {
        int result;
@@ -269,7 +328,7 @@ static void ima_log_string(struct audit_buffer *ab, char *key, char *value)
        audit_log_format(ab, " ");
 }
 
-static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry)
+static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
 {
        struct audit_buffer *ab;
        char *p;
@@ -278,6 +337,7 @@ static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry)
        ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_INTEGRITY_RULE);
 
        entry->uid = -1;
+       entry->fowner = -1;
        entry->action = UNKNOWN;
        while ((p = strsep(&rule, " \t")) != NULL) {
                substring_t args[MAX_OPT_ARGS];
@@ -306,11 +366,35 @@ static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry)
 
                        entry->action = DONT_MEASURE;
                        break;
+               case Opt_appraise:
+                       ima_log_string(ab, "action", "appraise");
+
+                       if (entry->action != UNKNOWN)
+                               result = -EINVAL;
+
+                       entry->action = APPRAISE;
+                       break;
+               case Opt_dont_appraise:
+                       ima_log_string(ab, "action", "dont_appraise");
+
+                       if (entry->action != UNKNOWN)
+                               result = -EINVAL;
+
+                       entry->action = DONT_APPRAISE;
+                       break;
+               case Opt_audit:
+                       ima_log_string(ab, "action", "audit");
+
+                       if (entry->action != UNKNOWN)
+                               result = -EINVAL;
+
+                       entry->action = AUDIT;
+                       break;
                case Opt_func:
                        ima_log_string(ab, "func", args[0].from);
 
                        if (entry->func)
-                               result  = -EINVAL;
+                               result = -EINVAL;
 
                        if (strcmp(args[0].from, "FILE_CHECK") == 0)
                                entry->func = FILE_CHECK;
@@ -375,6 +459,23 @@ static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry)
                                        entry->flags |= IMA_UID;
                        }
                        break;
+               case Opt_fowner:
+                       ima_log_string(ab, "fowner", args[0].from);
+
+                       if (entry->fowner != -1) {
+                               result = -EINVAL;
+                               break;
+                       }
+
+                       result = strict_strtoul(args[0].from, 10, &lnum);
+                       if (!result) {
+                               entry->fowner = (uid_t) lnum;
+                               if (entry->fowner != lnum)
+                                       result = -EINVAL;
+                               else
+                                       entry->flags |= IMA_FOWNER;
+                       }
+                       break;
                case Opt_obj_user:
                        ima_log_string(ab, "obj_user", args[0].from);
                        result = ima_lsm_rule_init(entry, args[0].from,
@@ -426,7 +527,7 @@ static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry)
 }
 
 /**
- * ima_parse_add_rule - add a rule to measure_policy_rules
+ * ima_parse_add_rule - add a rule to ima_policy_rules
  * @rule - ima measurement policy rule
  *
  * Uses a mutex to protect the policy list from multiple concurrent writers.
@@ -436,12 +537,12 @@ ssize_t ima_parse_add_rule(char *rule)
 {
        const char *op = "update_policy";
        char *p;
-       struct ima_measure_rule_entry *entry;
+       struct ima_rule_entry *entry;
        ssize_t result, len;
        int audit_info = 0;
 
        /* Prevent installed policy from changing */
-       if (ima_measure != &measure_default_rules) {
+       if (ima_rules != &ima_default_rules) {
                integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL,
                                    NULL, op, "already exists",
                                    -EACCES, audit_info);
@@ -474,9 +575,9 @@ ssize_t ima_parse_add_rule(char *rule)
                return result;
        }
 
-       mutex_lock(&ima_measure_mutex);
-       list_add_tail(&entry->list, &measure_policy_rules);
-       mutex_unlock(&ima_measure_mutex);
+       mutex_lock(&ima_rules_mutex);
+       list_add_tail(&entry->list, &ima_policy_rules);
+       mutex_unlock(&ima_rules_mutex);
 
        return len;
 }
@@ -484,12 +585,12 @@ ssize_t ima_parse_add_rule(char *rule)
 /* ima_delete_rules called to cleanup invalid policy */
 void ima_delete_rules(void)
 {
-       struct ima_measure_rule_entry *entry, *tmp;
+       struct ima_rule_entry *entry, *tmp;
 
-       mutex_lock(&ima_measure_mutex);
-       list_for_each_entry_safe(entry, tmp, &measure_policy_rules, list) {
+       mutex_lock(&ima_rules_mutex);
+       list_for_each_entry_safe(entry, tmp, &ima_policy_rules, list) {
                list_del(&entry->list);
                kfree(entry);
        }
-       mutex_unlock(&ima_measure_mutex);
+       mutex_unlock(&ima_rules_mutex);
 }
index 7a25ecec5aaac6b8d00c2bf0f926deaeea561163..e9db763a875e80f8fc4bd528974922d7e98ae97e 100644 (file)
 #include <linux/integrity.h>
 #include <crypto/sha.h>
 
+/* iint action cache flags */
+#define IMA_MEASURE            0x0001
+#define IMA_MEASURED           0x0002
+#define IMA_APPRAISE           0x0004
+#define IMA_APPRAISED          0x0008
+/*#define IMA_COLLECT          0x0010  do not use this flag */
+#define IMA_COLLECTED          0x0020
+#define IMA_AUDIT              0x0040
+#define IMA_AUDITED            0x0080
+
 /* iint cache flags */
-#define IMA_MEASURED           0x01
+#define IMA_DIGSIG             0x0100
+
+#define IMA_DO_MASK            (IMA_MEASURE | IMA_APPRAISE | IMA_AUDIT)
+#define IMA_DONE_MASK          (IMA_MEASURED | IMA_APPRAISED | IMA_AUDITED \
+                                | IMA_COLLECTED)
 
 enum evm_ima_xattr_type {
        IMA_XATTR_DIGEST = 0x01,
@@ -34,9 +48,9 @@ struct integrity_iint_cache {
        struct rb_node rb_node; /* rooted in integrity_iint_tree */
        struct inode *inode;    /* back pointer to inode in question */
        u64 version;            /* track inode changes */
-       unsigned char flags;
-       u8 digest[SHA1_DIGEST_SIZE];
-       struct mutex mutex;     /* protects: version, flags, digest */
+       unsigned short flags;
+       struct evm_ima_xattr_data ima_xattr;
+       enum integrity_status ima_status;
        enum integrity_status evm_status;
 };
 
index 1d039af99f50552c3c34b850ad22c020e04b9495..da63a659db75866694e6b5909668ea6e06a6c360 100644 (file)
@@ -861,13 +861,13 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
        /* if the client doesn't provide, decide on the permissions we want */
        if (perm == KEY_PERM_UNDEF) {
                perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK | KEY_POS_SETATTR;
-               perm |= KEY_USR_VIEW | KEY_USR_SEARCH | KEY_USR_LINK | KEY_USR_SETATTR;
+               perm |= KEY_USR_VIEW;
 
                if (ktype->read)
-                       perm |= KEY_POS_READ | KEY_USR_READ;
+                       perm |= KEY_POS_READ;
 
                if (ktype == &key_type_keyring || ktype->update)
-                       perm |= KEY_USR_WRITE;
+                       perm |= KEY_POS_WRITE;
        }
 
        /* allocate a new key */
index 505d40be196c0e4803442c6ff2228ccc5e07bcf8..6d9d0c747525fe3dee3458d2f20c235d5126d623 100644 (file)
@@ -1122,12 +1122,12 @@ long keyctl_instantiate_key_iov(key_serial_t id,
        ret = rw_copy_check_uvector(WRITE, _payload_iov, ioc,
                                    ARRAY_SIZE(iovstack), iovstack, &iov);
        if (ret < 0)
-               return ret;
+               goto err;
        if (ret == 0)
                goto no_payload_free;
 
        ret = keyctl_instantiate_key_common(id, iov, ioc, ret, ringid);
-
+err:
        if (iov != iovstack)
                kfree(iov);
        return ret;
@@ -1485,7 +1485,8 @@ long keyctl_session_to_parent(void)
                goto error_keyring;
        newwork = &cred->rcu;
 
-       cred->tgcred->session_keyring = key_ref_to_ptr(keyring_r);
+       cred->session_keyring = key_ref_to_ptr(keyring_r);
+       keyring_r = NULL;
        init_task_work(newwork, key_change_session_keyring);
 
        me = current;
@@ -1510,7 +1511,7 @@ long keyctl_session_to_parent(void)
        mycred = current_cred();
        pcred = __task_cred(parent);
        if (mycred == pcred ||
-           mycred->tgcred->session_keyring == pcred->tgcred->session_keyring) {
+           mycred->session_keyring == pcred->session_keyring) {
                ret = 0;
                goto unlock;
        }
@@ -1526,9 +1527,9 @@ long keyctl_session_to_parent(void)
                goto unlock;
 
        /* the keyrings must have the same UID */
-       if ((pcred->tgcred->session_keyring &&
-            pcred->tgcred->session_keyring->uid != mycred->euid) ||
-           mycred->tgcred->session_keyring->uid != mycred->euid)
+       if ((pcred->session_keyring &&
+            pcred->session_keyring->uid != mycred->euid) ||
+           mycred->session_keyring->uid != mycred->euid)
                goto unlock;
 
        /* cancel an already pending keyring replacement */
index f04d8cf81f3c77cc17f2646059986735740d754c..9270ba054a1ea57096e7bce87e766704377bf825 100644 (file)
@@ -257,17 +257,14 @@ error:
  * Allocate a keyring and link into the destination keyring.
  */
 struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid,
-                         const struct cred *cred, unsigned long flags,
-                         struct key *dest)
+                         const struct cred *cred, key_perm_t perm,
+                         unsigned long flags, struct key *dest)
 {
        struct key *keyring;
        int ret;
 
        keyring = key_alloc(&key_type_keyring, description,
-                           uid, gid, cred,
-                           (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL,
-                           flags);
-
+                           uid, gid, cred, perm, flags);
        if (!IS_ERR(keyring)) {
                ret = key_instantiate_and_link(keyring, NULL, 0, dest, NULL);
                if (ret < 0) {
@@ -278,6 +275,7 @@ struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid,
 
        return keyring;
 }
+EXPORT_SYMBOL(keyring_alloc);
 
 /**
  * keyring_search_aux - Search a keyring tree for a key matching some criteria
index 54339cfd6734d46927e8e9228019891e7130c272..b58d93892740476ed115568167d3dac8a5b2db34 100644 (file)
@@ -46,9 +46,11 @@ int install_user_keyrings(void)
        struct user_struct *user;
        const struct cred *cred;
        struct key *uid_keyring, *session_keyring;
+       key_perm_t user_keyring_perm;
        char buf[20];
        int ret;
 
+       user_keyring_perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL;
        cred = current_cred();
        user = cred->user;
 
@@ -72,8 +74,8 @@ int install_user_keyrings(void)
                uid_keyring = find_keyring_by_name(buf, true);
                if (IS_ERR(uid_keyring)) {
                        uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1,
-                                                   cred, KEY_ALLOC_IN_QUOTA,
-                                                   NULL);
+                                                   cred, user_keyring_perm,
+                                                   KEY_ALLOC_IN_QUOTA, NULL);
                        if (IS_ERR(uid_keyring)) {
                                ret = PTR_ERR(uid_keyring);
                                goto error;
@@ -88,7 +90,8 @@ int install_user_keyrings(void)
                if (IS_ERR(session_keyring)) {
                        session_keyring =
                                keyring_alloc(buf, user->uid, (gid_t) -1,
-                                             cred, KEY_ALLOC_IN_QUOTA, NULL);
+                                             cred, user_keyring_perm,
+                                             KEY_ALLOC_IN_QUOTA, NULL);
                        if (IS_ERR(session_keyring)) {
                                ret = PTR_ERR(session_keyring);
                                goto error_release;
@@ -129,6 +132,7 @@ int install_thread_keyring_to_cred(struct cred *new)
        struct key *keyring;
 
        keyring = keyring_alloc("_tid", new->uid, new->gid, new,
+                               KEY_POS_ALL | KEY_USR_VIEW,
                                KEY_ALLOC_QUOTA_OVERRUN, NULL);
        if (IS_ERR(keyring))
                return PTR_ERR(keyring);
@@ -169,27 +173,18 @@ static int install_thread_keyring(void)
 int install_process_keyring_to_cred(struct cred *new)
 {
        struct key *keyring;
-       int ret;
 
-       if (new->tgcred->process_keyring)
+       if (new->process_keyring)
                return -EEXIST;
 
-       keyring = keyring_alloc("_pid", new->uid, new->gid,
-                               new, KEY_ALLOC_QUOTA_OVERRUN, NULL);
+       keyring = keyring_alloc("_pid", new->uid, new->gid, new,
+                               KEY_POS_ALL | KEY_USR_VIEW,
+                               KEY_ALLOC_QUOTA_OVERRUN, NULL);
        if (IS_ERR(keyring))
                return PTR_ERR(keyring);
 
-       spin_lock_irq(&new->tgcred->lock);
-       if (!new->tgcred->process_keyring) {
-               new->tgcred->process_keyring = keyring;
-               keyring = NULL;
-               ret = 0;
-       } else {
-               ret = -EEXIST;
-       }
-       spin_unlock_irq(&new->tgcred->lock);
-       key_put(keyring);
-       return ret;
+       new->process_keyring = keyring;
+       return 0;
 }
 
 /*
@@ -230,11 +225,12 @@ int install_session_keyring_to_cred(struct cred *cred, struct key *keyring)
        /* create an empty session keyring */
        if (!keyring) {
                flags = KEY_ALLOC_QUOTA_OVERRUN;
-               if (cred->tgcred->session_keyring)
+               if (cred->session_keyring)
                        flags = KEY_ALLOC_IN_QUOTA;
 
-               keyring = keyring_alloc("_ses", cred->uid, cred->gid,
-                                       cred, flags, NULL);
+               keyring = keyring_alloc("_ses", cred->uid, cred->gid, cred,
+                                       KEY_POS_ALL | KEY_USR_VIEW | KEY_USR_READ,
+                                       flags, NULL);
                if (IS_ERR(keyring))
                        return PTR_ERR(keyring);
        } else {
@@ -242,17 +238,11 @@ int install_session_keyring_to_cred(struct cred *cred, struct key *keyring)
        }
 
        /* install the keyring */
-       spin_lock_irq(&cred->tgcred->lock);
-       old = cred->tgcred->session_keyring;
-       rcu_assign_pointer(cred->tgcred->session_keyring, keyring);
-       spin_unlock_irq(&cred->tgcred->lock);
-
-       /* we're using RCU on the pointer, but there's no point synchronising
-        * on it if it didn't previously point to anything */
-       if (old) {
-               synchronize_rcu();
+       old = cred->session_keyring;
+       rcu_assign_pointer(cred->session_keyring, keyring);
+
+       if (old)
                key_put(old);
-       }
 
        return 0;
 }
@@ -357,8 +347,6 @@ key_ref_t search_my_process_keyrings(struct key_type *type,
 
                switch (PTR_ERR(key_ref)) {
                case -EAGAIN: /* no key */
-                       if (ret)
-                               break;
                case -ENOKEY: /* negative key */
                        ret = key_ref;
                        break;
@@ -369,9 +357,9 @@ key_ref_t search_my_process_keyrings(struct key_type *type,
        }
 
        /* search the process keyring second */
-       if (cred->tgcred->process_keyring) {
+       if (cred->process_keyring) {
                key_ref = keyring_search_aux(
-                       make_key_ref(cred->tgcred->process_keyring, 1),
+                       make_key_ref(cred->process_keyring, 1),
                        cred, type, description, match, no_state_check);
                if (!IS_ERR(key_ref))
                        goto found;
@@ -390,12 +378,10 @@ key_ref_t search_my_process_keyrings(struct key_type *type,
        }
 
        /* search the session keyring */
-       if (cred->tgcred->session_keyring) {
+       if (cred->session_keyring) {
                rcu_read_lock();
                key_ref = keyring_search_aux(
-                       make_key_ref(rcu_dereference(
-                                            cred->tgcred->session_keyring),
-                                    1),
+                       make_key_ref(rcu_dereference(cred->session_keyring), 1),
                        cred, type, description, match, no_state_check);
                rcu_read_unlock();
 
@@ -565,7 +551,7 @@ try_again:
                break;
 
        case KEY_SPEC_PROCESS_KEYRING:
-               if (!cred->tgcred->process_keyring) {
+               if (!cred->process_keyring) {
                        if (!(lflags & KEY_LOOKUP_CREATE))
                                goto error;
 
@@ -577,13 +563,13 @@ try_again:
                        goto reget_creds;
                }
 
-               key = cred->tgcred->process_keyring;
+               key = cred->process_keyring;
                atomic_inc(&key->usage);
                key_ref = make_key_ref(key, 1);
                break;
 
        case KEY_SPEC_SESSION_KEYRING:
-               if (!cred->tgcred->session_keyring) {
+               if (!cred->session_keyring) {
                        /* always install a session keyring upon access if one
                         * doesn't exist yet */
                        ret = install_user_keyrings();
@@ -598,7 +584,7 @@ try_again:
                        if (ret < 0)
                                goto error;
                        goto reget_creds;
-               } else if (cred->tgcred->session_keyring ==
+               } else if (cred->session_keyring ==
                           cred->user->session_keyring &&
                           lflags & KEY_LOOKUP_CREATE) {
                        ret = join_session_keyring(NULL);
@@ -608,7 +594,7 @@ try_again:
                }
 
                rcu_read_lock();
-               key = rcu_dereference(cred->tgcred->session_keyring);
+               key = rcu_dereference(cred->session_keyring);
                atomic_inc(&key->usage);
                rcu_read_unlock();
                key_ref = make_key_ref(key, 1);
@@ -768,12 +754,6 @@ long join_session_keyring(const char *name)
        struct key *keyring;
        long ret, serial;
 
-       /* only permit this if there's a single thread in the thread group -
-        * this avoids us having to adjust the creds on all threads and risking
-        * ENOMEM */
-       if (!current_is_single_threaded())
-               return -EMLINK;
-
        new = prepare_creds();
        if (!new)
                return -ENOMEM;
@@ -785,7 +765,7 @@ long join_session_keyring(const char *name)
                if (ret < 0)
                        goto error;
 
-               serial = new->tgcred->session_keyring->serial;
+               serial = new->session_keyring->serial;
                ret = commit_creds(new);
                if (ret == 0)
                        ret = serial;
@@ -799,8 +779,10 @@ long join_session_keyring(const char *name)
        keyring = find_keyring_by_name(name, false);
        if (PTR_ERR(keyring) == -ENOKEY) {
                /* not found - try and create a new one */
-               keyring = keyring_alloc(name, old->uid, old->gid, old,
-                                       KEY_ALLOC_IN_QUOTA, NULL);
+               keyring = keyring_alloc(
+                       name, old->uid, old->gid, old,
+                       KEY_POS_ALL | KEY_USR_VIEW | KEY_USR_READ | KEY_USR_LINK,
+                       KEY_ALLOC_IN_QUOTA, NULL);
                if (IS_ERR(keyring)) {
                        ret = PTR_ERR(keyring);
                        goto error2;
@@ -808,6 +790,9 @@ long join_session_keyring(const char *name)
        } else if (IS_ERR(keyring)) {
                ret = PTR_ERR(keyring);
                goto error2;
+       } else if (keyring == new->session_keyring) {
+               ret = 0;
+               goto error2;
        }
 
        /* we've got a keyring - now to install it */
@@ -864,8 +849,7 @@ void key_change_session_keyring(struct callback_head *twork)
 
        new->jit_keyring        = old->jit_keyring;
        new->thread_keyring     = key_get(old->thread_keyring);
-       new->tgcred->tgid       = old->tgcred->tgid;
-       new->tgcred->process_keyring = key_get(old->tgcred->process_keyring);
+       new->process_keyring    = key_get(old->process_keyring);
 
        security_transfer_creds(new, old);
 
index 000e7501752022089b82efeb153115498e55da60..0ae3a2202771a0b58730b2aee01e4b1f573c2f75 100644 (file)
@@ -126,6 +126,7 @@ static int call_sbin_request_key(struct key_construction *cons,
 
        cred = get_current_cred();
        keyring = keyring_alloc(desc, cred->fsuid, cred->fsgid, cred,
+                               KEY_POS_ALL | KEY_USR_VIEW | KEY_USR_READ,
                                KEY_ALLOC_QUOTA_OVERRUN, NULL);
        put_cred(cred);
        if (IS_ERR(keyring)) {
@@ -150,12 +151,12 @@ static int call_sbin_request_key(struct key_construction *cons,
                cred->thread_keyring ? cred->thread_keyring->serial : 0);
 
        prkey = 0;
-       if (cred->tgcred->process_keyring)
-               prkey = cred->tgcred->process_keyring->serial;
+       if (cred->process_keyring)
+               prkey = cred->process_keyring->serial;
        sprintf(keyring_str[1], "%d", prkey);
 
        rcu_read_lock();
-       session = rcu_dereference(cred->tgcred->session_keyring);
+       session = rcu_dereference(cred->session_keyring);
        if (!session)
                session = cred->user->session_keyring;
        sskey = session->serial;
@@ -297,14 +298,14 @@ static void construct_get_dest_keyring(struct key **_dest_keyring)
                                break;
 
                case KEY_REQKEY_DEFL_PROCESS_KEYRING:
-                       dest_keyring = key_get(cred->tgcred->process_keyring);
+                       dest_keyring = key_get(cred->process_keyring);
                        if (dest_keyring)
                                break;
 
                case KEY_REQKEY_DEFL_SESSION_KEYRING:
                        rcu_read_lock();
                        dest_keyring = key_get(
-                               rcu_dereference(cred->tgcred->session_keyring));
+                               rcu_dereference(cred->session_keyring));
                        rcu_read_unlock();
 
                        if (dest_keyring)
@@ -347,6 +348,7 @@ static int construct_alloc_key(struct key_type *type,
        const struct cred *cred = current_cred();
        unsigned long prealloc;
        struct key *key;
+       key_perm_t perm;
        key_ref_t key_ref;
        int ret;
 
@@ -355,8 +357,15 @@ static int construct_alloc_key(struct key_type *type,
        *_key = NULL;
        mutex_lock(&user->cons_lock);
 
+       perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK | KEY_POS_SETATTR;
+       perm |= KEY_USR_VIEW;
+       if (type->read)
+               perm |= KEY_POS_READ;
+       if (type == &key_type_keyring || type->update)
+               perm |= KEY_POS_WRITE;
+
        key = key_alloc(type, description, cred->fsuid, cred->fsgid, cred,
-                       KEY_POS_ALL, flags);
+                       perm, flags);
        if (IS_ERR(key))
                goto alloc_failed;
 
index 42036c7a08560d7f2b9d2cdf7197784a1cd1ec9f..e13fcf7636f7ffa0ff40d7cd60408645621dab1f 100644 (file)
@@ -368,38 +368,6 @@ static int trusted_tpm_send(const u32 chip_num, unsigned char *cmd,
        return rc;
 }
 
-/*
- * get a random value from TPM
- */
-static int tpm_get_random(struct tpm_buf *tb, unsigned char *buf, uint32_t len)
-{
-       int ret;
-
-       INIT_BUF(tb);
-       store16(tb, TPM_TAG_RQU_COMMAND);
-       store32(tb, TPM_GETRANDOM_SIZE);
-       store32(tb, TPM_ORD_GETRANDOM);
-       store32(tb, len);
-       ret = trusted_tpm_send(TPM_ANY_NUM, tb->data, sizeof tb->data);
-       if (!ret)
-               memcpy(buf, tb->data + TPM_GETRANDOM_SIZE, len);
-       return ret;
-}
-
-static int my_get_random(unsigned char *buf, int len)
-{
-       struct tpm_buf *tb;
-       int ret;
-
-       tb = kmalloc(sizeof *tb, GFP_KERNEL);
-       if (!tb)
-               return -ENOMEM;
-       ret = tpm_get_random(tb, buf, len);
-
-       kfree(tb);
-       return ret;
-}
-
 /*
  * Lock a trusted key, by extending a selected PCR.
  *
@@ -413,8 +381,8 @@ static int pcrlock(const int pcrnum)
 
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
-       ret = my_get_random(hash, SHA1_DIGEST_SIZE);
-       if (ret < 0)
+       ret = tpm_get_random(TPM_ANY_NUM, hash, SHA1_DIGEST_SIZE);
+       if (ret != SHA1_DIGEST_SIZE)
                return ret;
        return tpm_pcr_extend(TPM_ANY_NUM, pcrnum, hash) ? -EINVAL : 0;
 }
@@ -429,8 +397,8 @@ static int osap(struct tpm_buf *tb, struct osapsess *s,
        unsigned char ononce[TPM_NONCE_SIZE];
        int ret;
 
-       ret = tpm_get_random(tb, ononce, TPM_NONCE_SIZE);
-       if (ret < 0)
+       ret = tpm_get_random(TPM_ANY_NUM, ononce, TPM_NONCE_SIZE);
+       if (ret != TPM_NONCE_SIZE)
                return ret;
 
        INIT_BUF(tb);
@@ -524,8 +492,8 @@ static int tpm_seal(struct tpm_buf *tb, uint16_t keytype,
        if (ret < 0)
                goto out;
 
-       ret = tpm_get_random(tb, td->nonceodd, TPM_NONCE_SIZE);
-       if (ret < 0)
+       ret = tpm_get_random(TPM_ANY_NUM, td->nonceodd, TPM_NONCE_SIZE);
+       if (ret != TPM_NONCE_SIZE)
                goto out;
        ordinal = htonl(TPM_ORD_SEAL);
        datsize = htonl(datalen);
@@ -634,8 +602,8 @@ static int tpm_unseal(struct tpm_buf *tb,
 
        ordinal = htonl(TPM_ORD_UNSEAL);
        keyhndl = htonl(SRKHANDLE);
-       ret = tpm_get_random(tb, nonceodd, TPM_NONCE_SIZE);
-       if (ret < 0) {
+       ret = tpm_get_random(TPM_ANY_NUM, nonceodd, TPM_NONCE_SIZE);
+       if (ret != TPM_NONCE_SIZE) {
                pr_info("trusted_key: tpm_get_random failed (%d)\n", ret);
                return ret;
        }
@@ -936,6 +904,7 @@ static int trusted_instantiate(struct key *key,
        char *datablob;
        int ret = 0;
        int key_cmd;
+       size_t key_len;
 
        if (datalen <= 0 || datalen > 32767 || !prep->data)
                return -EINVAL;
@@ -975,8 +944,9 @@ static int trusted_instantiate(struct key *key,
                        pr_info("trusted_key: key_unseal failed (%d)\n", ret);
                break;
        case Opt_new:
-               ret = my_get_random(payload->key, payload->key_len);
-               if (ret < 0) {
+               key_len = payload->key_len;
+               ret = tpm_get_random(TPM_ANY_NUM, payload->key, key_len);
+               if (ret != key_len) {
                        pr_info("trusted_key: key_create failed (%d)\n", ret);
                        goto out;
                }
index 860aeb349cb337bbccf4346d99120d4d1fd51c90..d23b43522a5a3206d87a663175550b9acea7e777 100644 (file)
@@ -136,11 +136,23 @@ int __init register_security(struct security_operations *ops)
 
 int security_ptrace_access_check(struct task_struct *child, unsigned int mode)
 {
+#ifdef CONFIG_SECURITY_YAMA_STACKED
+       int rc;
+       rc = yama_ptrace_access_check(child, mode);
+       if (rc)
+               return rc;
+#endif
        return security_ops->ptrace_access_check(child, mode);
 }
 
 int security_ptrace_traceme(struct task_struct *parent)
 {
+#ifdef CONFIG_SECURITY_YAMA_STACKED
+       int rc;
+       rc = yama_ptrace_traceme(parent);
+       if (rc)
+               return rc;
+#endif
        return security_ops->ptrace_traceme(parent);
 }
 
@@ -559,6 +571,9 @@ int security_inode_setxattr(struct dentry *dentry, const char *name,
        if (unlikely(IS_PRIVATE(dentry->d_inode)))
                return 0;
        ret = security_ops->inode_setxattr(dentry, name, value, size, flags);
+       if (ret)
+               return ret;
+       ret = ima_inode_setxattr(dentry, name, value, size);
        if (ret)
                return ret;
        return evm_inode_setxattr(dentry, name, value, size);
@@ -594,6 +609,9 @@ int security_inode_removexattr(struct dentry *dentry, const char *name)
        if (unlikely(IS_PRIVATE(dentry->d_inode)))
                return 0;
        ret = security_ops->inode_removexattr(dentry, name);
+       if (ret)
+               return ret;
+       ret = ima_inode_removexattr(dentry, name);
        if (ret)
                return ret;
        return evm_inode_removexattr(dentry, name);
@@ -761,6 +779,9 @@ int security_task_create(unsigned long clone_flags)
 
 void security_task_free(struct task_struct *task)
 {
+#ifdef CONFIG_SECURITY_YAMA_STACKED
+       yama_task_free(task);
+#endif
        security_ops->task_free(task);
 }
 
@@ -876,6 +897,12 @@ int security_task_wait(struct task_struct *p)
 int security_task_prctl(int option, unsigned long arg2, unsigned long arg3,
                         unsigned long arg4, unsigned long arg5)
 {
+#ifdef CONFIG_SECURITY_YAMA_STACKED
+       int rc;
+       rc = yama_task_prctl(option, arg2, arg3, arg4, arg5);
+       if (rc != -ENOSYS)
+               return rc;
+#endif
        return security_ops->task_prctl(option, arg2, arg3, arg4, arg5);
 }
 
index c220f314709cc1345792e4a4ddab28cd63a23177..65f67cb0aefb22f323d8048c140417555c273c9d 100644 (file)
@@ -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)
index 8221514cc997303f5d5d8844198c233fe79b64ac..2874c73167831f6f72cdb8aefffbf29c3aa0f7a2 100644 (file)
@@ -1691,40 +1691,19 @@ static int smack_task_kill(struct task_struct *p, struct siginfo *info,
  * smack_task_wait - Smack access check for waiting
  * @p: task to wait for
  *
- * Returns 0 if current can wait for p, error code otherwise
+ * Returns 0
  */
 static int smack_task_wait(struct task_struct *p)
 {
-       struct smk_audit_info ad;
-       char *sp = smk_of_current();
-       char *tsp = smk_of_forked(task_security(p));
-       int rc;
-
-       /* we don't log here, we can be overriden */
-       rc = smk_access(tsp, sp, MAY_WRITE, NULL);
-       if (rc == 0)
-               goto out_log;
-
        /*
-        * Allow the operation to succeed if either task
-        * has privilege to perform operations that might
-        * account for the smack labels having gotten to
-        * be different in the first place.
-        *
-        * This breaks the strict subject/object access
-        * control ideal, taking the object's privilege
-        * state into account in the decision as well as
-        * the smack value.
+        * Allow the operation to succeed.
+        * Zombies are bad.
+        * In userless environments (e.g. phones) programs
+        * get marked with SMACK64EXEC and even if the parent
+        * and child shouldn't be talking the parent still
+        * may expect to know when the child exits.
         */
-       if (smack_privileged(CAP_MAC_OVERRIDE) ||
-           has_capability(p, CAP_MAC_OVERRIDE))
-               rc = 0;
-       /* we log only if we didn't get overriden */
- out_log:
-       smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK);
-       smk_ad_setfield_u_tsk(&ad, p);
-       smack_log(tsp, sp, MAY_WRITE, rc, &ad);
-       return rc;
+       return 0;
 }
 
 /**
@@ -2705,9 +2684,7 @@ static int smack_getprocattr(struct task_struct *p, char *name, char **value)
 static int smack_setprocattr(struct task_struct *p, char *name,
                             void *value, size_t size)
 {
-       int rc;
        struct task_smack *tsp;
-       struct task_smack *oldtsp;
        struct cred *new;
        char *newsmack;
 
@@ -2737,21 +2714,13 @@ static int smack_setprocattr(struct task_struct *p, char *name,
        if (newsmack == smack_known_web.smk_known)
                return -EPERM;
 
-       oldtsp = p->cred->security;
        new = prepare_creds();
        if (new == NULL)
                return -ENOMEM;
 
-       tsp = new_task_smack(newsmack, oldtsp->smk_forked, GFP_KERNEL);
-       if (tsp == NULL) {
-               kfree(new);
-               return -ENOMEM;
-       }
-       rc = smk_copy_rules(&tsp->smk_rules, &oldtsp->smk_rules, GFP_KERNEL);
-       if (rc != 0)
-               return rc;
+       tsp = new->security;
+       tsp->smk_task = newsmack;
 
-       new->security = tsp;
        commit_creds(new);
        return size;
 }
index b1b768e4049af3304d457451f06c8fa834909b89..99929a50093aa38fdd2917974f68df9c267b9933 100644 (file)
@@ -49,6 +49,7 @@ enum smk_inos {
        SMK_LOAD_SELF2  = 15,   /* load task specific rules with long labels */
        SMK_ACCESS2     = 16,   /* make an access check with long labels */
        SMK_CIPSO2      = 17,   /* load long label -> CIPSO mapping */
+       SMK_REVOKE_SUBJ = 18,   /* set rules with subject label to '-' */
 };
 
 /*
@@ -1991,6 +1992,77 @@ static const struct file_operations smk_access2_ops = {
        .llseek         = generic_file_llseek,
 };
 
+/**
+ * smk_write_revoke_subj - write() for /smack/revoke-subject
+ * @file: file pointer
+ * @buf: data from user space
+ * @count: bytes sent
+ * @ppos: where to start - must be 0
+ */
+static ssize_t smk_write_revoke_subj(struct file *file, const char __user *buf,
+                               size_t count, loff_t *ppos)
+{
+       char *data = NULL;
+       const char *cp = NULL;
+       struct smack_known *skp;
+       struct smack_rule *sp;
+       struct list_head *rule_list;
+       struct mutex *rule_lock;
+       int rc = count;
+
+       if (*ppos != 0)
+               return -EINVAL;
+
+       if (!smack_privileged(CAP_MAC_ADMIN))
+               return -EPERM;
+
+       if (count == 0 || count > SMK_LONGLABEL)
+               return -EINVAL;
+
+       data = kzalloc(count, GFP_KERNEL);
+       if (data == NULL)
+               return -ENOMEM;
+
+       if (copy_from_user(data, buf, count) != 0) {
+               rc = -EFAULT;
+               goto free_out;
+       }
+
+       cp = smk_parse_smack(data, count);
+       if (cp == NULL) {
+               rc = -EINVAL;
+               goto free_out;
+       }
+
+       skp = smk_find_entry(cp);
+       if (skp == NULL) {
+               rc = -EINVAL;
+               goto free_out;
+       }
+
+       rule_list = &skp->smk_rules;
+       rule_lock = &skp->smk_rules_lock;
+
+       mutex_lock(rule_lock);
+
+       list_for_each_entry_rcu(sp, rule_list, list)
+               sp->smk_access = 0;
+
+       mutex_unlock(rule_lock);
+
+free_out:
+       kfree(data);
+       kfree(cp);
+       return rc;
+}
+
+static const struct file_operations smk_revoke_subj_ops = {
+       .write          = smk_write_revoke_subj,
+       .read           = simple_transaction_read,
+       .release        = simple_transaction_release,
+       .llseek         = generic_file_llseek,
+};
+
 /**
  * smk_fill_super - fill the /smackfs superblock
  * @sb: the empty superblock
@@ -2037,6 +2109,9 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent)
                        "access2", &smk_access2_ops, S_IRUGO|S_IWUGO},
                [SMK_CIPSO2] = {
                        "cipso2", &smk_cipso2_ops, S_IRUGO|S_IWUSR},
+               [SMK_REVOKE_SUBJ] = {
+                       "revoke-subject", &smk_revoke_subj_ops,
+                       S_IRUGO|S_IWUSR},
                /* last one */
                        {""}
        };
index 51d6709d8bbd3fdd065ae119c3608149ee94d1cd..20ef5143c0c06bbedbfaf4114bf08c4579d75011 100644 (file)
@@ -11,3 +11,11 @@ config SECURITY_YAMA
          Further information can be found in Documentation/security/Yama.txt.
 
          If you are unsure how to answer this question, answer N.
+
+config SECURITY_YAMA_STACKED
+       bool "Yama stacked with other LSMs"
+       depends on SECURITY_YAMA
+       default n
+       help
+         When Yama is built into the kernel, force it to stack with the
+         selected primary LSM.
index 0cc99a3ea42d65c81188c302626681fae6044473..b4c29848b49d2ab2741ade9f1aece147ac02e6a3 100644 (file)
@@ -100,7 +100,7 @@ static void yama_ptracer_del(struct task_struct *tracer,
  * yama_task_free - check for task_pid to remove from exception list
  * @task: task being removed
  */
-static void yama_task_free(struct task_struct *task)
+void yama_task_free(struct task_struct *task)
 {
        yama_ptracer_del(task, task);
 }
@@ -116,7 +116,7 @@ static void yama_task_free(struct task_struct *task)
  * Return 0 on success, -ve on error.  -ENOSYS is returned when Yama
  * does not handle the given option.
  */
-static int yama_task_prctl(int option, unsigned long arg2, unsigned long arg3,
+int yama_task_prctl(int option, unsigned long arg2, unsigned long arg3,
                           unsigned long arg4, unsigned long arg5)
 {
        int rc;
@@ -143,7 +143,7 @@ static int yama_task_prctl(int option, unsigned long arg2, unsigned long arg3,
                if (arg2 == 0) {
                        yama_ptracer_del(NULL, myself);
                        rc = 0;
-               } else if (arg2 == PR_SET_PTRACER_ANY) {
+               } else if (arg2 == PR_SET_PTRACER_ANY || (int)arg2 == -1) {
                        rc = yama_ptracer_add(NULL, myself);
                } else {
                        struct task_struct *tracer;
@@ -243,7 +243,7 @@ static int ptracer_exception_found(struct task_struct *tracer,
  *
  * Returns 0 if following the ptrace is allowed, -ve on error.
  */
-static int yama_ptrace_access_check(struct task_struct *child,
+int yama_ptrace_access_check(struct task_struct *child,
                                    unsigned int mode)
 {
        int rc;
@@ -293,7 +293,7 @@ static int yama_ptrace_access_check(struct task_struct *child,
  *
  * Returns 0 if following the ptrace is allowed, -ve on error.
  */
-static int yama_ptrace_traceme(struct task_struct *parent)
+int yama_ptrace_traceme(struct task_struct *parent)
 {
        int rc;
 
@@ -324,6 +324,7 @@ static int yama_ptrace_traceme(struct task_struct *parent)
        return rc;
 }
 
+#ifndef CONFIG_SECURITY_YAMA_STACKED
 static struct security_operations yama_ops = {
        .name =                 "yama",
 
@@ -332,6 +333,7 @@ static struct security_operations yama_ops = {
        .task_prctl =           yama_task_prctl,
        .task_free =            yama_task_free,
 };
+#endif
 
 #ifdef CONFIG_SYSCTL
 static int yama_dointvec_minmax(struct ctl_table *table, int write,
@@ -378,13 +380,17 @@ static struct ctl_table yama_sysctl_table[] = {
 
 static __init int yama_init(void)
 {
+#ifndef CONFIG_SECURITY_YAMA_STACKED
        if (!security_module_enable(&yama_ops))
                return 0;
+#endif
 
        printk(KERN_INFO "Yama: becoming mindful.\n");
 
+#ifndef CONFIG_SECURITY_YAMA_STACKED
        if (register_security(&yama_ops))
                panic("Yama: kernel registration failed.\n");
+#endif
 
 #ifdef CONFIG_SYSCTL
        if (!register_sysctl_paths(yama_sysctl_path, yama_sysctl_table))
index ec2118d0e27aca3f5fef6c2ddd72f8b166ce98ca..eb60cb8dbb8a6f12d965912e923197cdd2f4e8b5 100644 (file)
@@ -80,14 +80,12 @@ static int snd_compr_open(struct inode *inode, struct file *f)
        int maj = imajor(inode);
        int ret;
 
-       if (f->f_flags & O_WRONLY)
+       if ((f->f_flags & O_ACCMODE) == O_WRONLY)
                dirn = SND_COMPRESS_PLAYBACK;
-       else if (f->f_flags & O_RDONLY)
+       else if ((f->f_flags & O_ACCMODE) == O_RDONLY)
                dirn = SND_COMPRESS_CAPTURE;
-       else {
-               pr_err("invalid direction\n");
+       else
                return -EINVAL;
-       }
 
        if (maj == snd_major)
                compr = snd_lookup_minor_data(iminor(inode),
index f25c24c743f9d7dedd551d2196c2f1e441076a07..1c65cc5e3a31101d098d6cdb48a2772d1adc38f9 100644 (file)
@@ -2353,6 +2353,7 @@ int snd_hda_codec_reset(struct hda_codec *codec)
        }
        if (codec->patch_ops.free)
                codec->patch_ops.free(codec);
+       memset(&codec->patch_ops, 0, sizeof(codec->patch_ops));
        snd_hda_jack_tbl_clear(codec);
        codec->proc_widget_hook = NULL;
        codec->spec = NULL;
@@ -2368,7 +2369,6 @@ int snd_hda_codec_reset(struct hda_codec *codec)
        codec->num_pcms = 0;
        codec->pcm_info = NULL;
        codec->preset = NULL;
-       memset(&codec->patch_ops, 0, sizeof(codec->patch_ops));
        codec->slave_dig_outs = NULL;
        codec->spdif_status_reset = 0;
        module_put(codec->owner);
index 60882c62f18006a3b2339d354b58550fdcd30718..c4763c52eaf64ced9e1d520f80fd8b245507dbd6 100644 (file)
@@ -2701,6 +2701,8 @@ 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),
        SND_PCI_QUIRK(0x1297, 0x3166, "Shuttle", POS_FIX_LPIB),
index 6f806d3e56bbf878d27f08cdd8ce3f805c9e9f1e..3d4722f0a1cacba8fc9a923f22dbf767433dbd6c 100644 (file)
@@ -1075,7 +1075,7 @@ static struct snd_kcontrol_new stac_smux_mixer = {
 
 static const char * const slave_pfxs[] = {
        "Front", "Surround", "Center", "LFE", "Side",
-       "Headphone", "Speaker", "IEC958",
+       "Headphone", "Speaker", "IEC958", "PCM",
        NULL
 };
 
index 764cc93dbca402f6372b6f73a0854470f3046f73..075d5aa1fee003bef0dfaa4177ac21d010247277 100644 (file)
@@ -297,6 +297,7 @@ static int ak4396_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem
 }
 
 static const DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1);
+static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0);
 
 static struct snd_kcontrol_new prodigy_hd2_controls[] __devinitdata = {
     {
@@ -307,7 +308,7 @@ static struct snd_kcontrol_new prodigy_hd2_controls[] __devinitdata = {
        .info = ak4396_dac_vol_info,
        .get = ak4396_dac_vol_get,
        .put = ak4396_dac_vol_put,
-       .tlv = { .p = db_scale_wm_dac },
+       .tlv = { .p = ak4396_db_scale },
     },
 };
 
index 5c9cacaf2d525cddabffd0b416c0695dfadaab99..1cf7a32d1b211e779cb7705746c32b07c11afa82 100644 (file)
@@ -426,7 +426,7 @@ static const int arizona_44k1_bclk_rates[] = {
        940800,
        1411200,
        1881600,
-       2882400,
+       2822400,
        3763200,
        5644800,
        7526400,
index 8f726c063f42badc9c598de4af670fb78f8937e1..115a403018105b0eaa2fb64abee56a47b5d32cc4 100644 (file)
@@ -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,
index 0013afe48e66a83171b93691b46593cb2e64d7ea..dc4262eea4b711990c71e602fe1a0fba7928250b 100644 (file)
@@ -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 */
index fb21b17f17f54ae342b552e05b42df6a0afcaeca..199408ec42612dfe57f63e3933457e901cf7bcfa 100644 (file)
@@ -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) {
index 009533ab8d1894054ed07c05ae140362d6738582..df65f98211ec2bdc3c664f7a87443f8477dc5476 100644 (file)
@@ -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");
index f3ebc38c10fe7633ea5ec260562b64bfdb7e402f..b70964ea448cef264bf540597850558e7c9fd23c 100644 (file)
@@ -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;
index dd7c49fafd754f949014f88b9a2ad0b80d59cc20..f90139b5f50d74089dc98fd0d19de42cb3732a84 100644 (file)
@@ -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;
index 97c2cac8e92c726712746d5db4658d7f0898e441..8c7f23729446b1582f6d7625d5933aad905e45d7 100644 (file)
@@ -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,
index e463529b38bbfbfd35cc745bf430f68399bfee91..76cb1b363b71c2ce2d1be75c27113c3cf2154127 100644 (file)
@@ -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[] = {
index 5658bcec1931ce5a76a75a32b020730f41da8c13..8d6900c1ee47e8d1a263584bf470e5c2eec56af4 100644 (file)
@@ -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;
 
index 5c472f335a64d6e5c11a5ee82e755153312ee40b..eb85113d472a22503aceb1939d5191d9d2c856de 100644 (file)
@@ -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");
index fd5e982fc98c2af6b01f84d00450b1262b76f218..f782ce19bf5aa14be92a43df553d66b177cb9429 100644 (file)
@@ -1140,6 +1140,12 @@ static void retire_playback_urb(struct snd_usb_substream *subs,
        int processed = urb->transfer_buffer_length / stride;
        int est_delay;
 
+       /* ignore the delay accounting when procssed=0 is given, i.e.
+        * silent payloads are procssed before handling the actual data
+        */
+       if (!processed)
+               return;
+
        spin_lock_irqsave(&subs->lock, flags);
        est_delay = snd_usb_pcm_delay(subs, runtime->rate);
        /* update delay with exact number of samples played */