Merge branch 'nfs-for-next' of git://linux-nfs.org/~trondmy/nfs-2.6 into for-3.10
authorJ. Bruce Fields <bfields@redhat.com>
Mon, 29 Apr 2013 18:03:30 +0000 (14:03 -0400)
committerJ. Bruce Fields <bfields@redhat.com>
Mon, 29 Apr 2013 20:23:34 +0000 (16:23 -0400)
Note conflict: Chuck's patches modified (and made static)
gss_mech_get_by_OID, which is still needed by gss-proxy patches.

The conflict resolution is a bit minimal; we may want some more cleanup.

663 files changed:
CREDITS
Documentation/SubmittingPatches
Documentation/device-mapper/dm-raid.txt
Documentation/devicetree/bindings/mfd/ab8500.txt
Documentation/devicetree/bindings/tty/serial/of-serial.txt
Documentation/filesystems/nfs/00-INDEX
Documentation/filesystems/nfs/rpc-server-gss.txt [new file with mode: 0644]
Documentation/hwmon/adm1275
Documentation/hwmon/adt7410
Documentation/hwmon/jc42
Documentation/hwmon/lineage-pem
Documentation/hwmon/lm25066
Documentation/hwmon/ltc2978
Documentation/hwmon/ltc4261
Documentation/hwmon/max16064
Documentation/hwmon/max16065
Documentation/hwmon/max34440
Documentation/hwmon/max8688
Documentation/hwmon/pmbus
Documentation/hwmon/smm665
Documentation/hwmon/ucd9000
Documentation/hwmon/ucd9200
Documentation/hwmon/zl6100
Documentation/input/alps.txt
Documentation/networking/tuntap.txt
Documentation/power/opp.txt
Documentation/printk-formats.txt
Documentation/trace/ftrace.txt
MAINTAINERS
Makefile
arch/Kconfig
arch/alpha/Kconfig
arch/alpha/boot/head.S
arch/arm/Kconfig
arch/arm/Kconfig.debug
arch/arm/boot/Makefile
arch/arm/boot/compressed/Makefile
arch/arm/boot/dts/armada-370-rd.dts
arch/arm/boot/dts/armada-370-xp.dtsi
arch/arm/boot/dts/armada-xp.dtsi
arch/arm/boot/dts/bcm2835.dtsi
arch/arm/boot/dts/dbx5x0.dtsi
arch/arm/boot/dts/dove.dtsi
arch/arm/boot/dts/href.dtsi
arch/arm/boot/dts/hrefv60plus.dts
arch/arm/boot/dts/imx53-mba53.dts
arch/arm/boot/dts/kirkwood-dns320.dts
arch/arm/boot/dts/kirkwood-dns325.dts
arch/arm/boot/dts/kirkwood-dockstar.dts
arch/arm/boot/dts/kirkwood-dreamplug.dts
arch/arm/boot/dts/kirkwood-goflexnet.dts
arch/arm/boot/dts/kirkwood-ib62x0.dts
arch/arm/boot/dts/kirkwood-iconnect.dts
arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts
arch/arm/boot/dts/kirkwood-km_kirkwood.dts
arch/arm/boot/dts/kirkwood-lschlv2.dts
arch/arm/boot/dts/kirkwood-lsxhl.dts
arch/arm/boot/dts/kirkwood-mplcec4.dts
arch/arm/boot/dts/kirkwood-ns2-common.dtsi
arch/arm/boot/dts/kirkwood-nsa310.dts
arch/arm/boot/dts/kirkwood-openblocks_a6.dts
arch/arm/boot/dts/kirkwood-topkick.dts
arch/arm/boot/dts/kirkwood.dtsi
arch/arm/boot/dts/orion5x-lacie-ethernet-disk-mini-v2.dts
arch/arm/boot/dts/snowball.dts
arch/arm/boot/dts/socfpga.dtsi
arch/arm/boot/dts/tegra20.dtsi
arch/arm/boot/dts/tegra30.dtsi
arch/arm/configs/mxs_defconfig
arch/arm/configs/omap2plus_defconfig
arch/arm/include/asm/mmu.h
arch/arm/include/asm/mmu_context.h
arch/arm/include/asm/tlbflush.h
arch/arm/include/asm/xen/events.h
arch/arm/include/uapi/asm/unistd.h
arch/arm/kernel/asm-offsets.c
arch/arm/kernel/calls.S
arch/arm/kernel/head.S
arch/arm/kernel/hw_breakpoint.c
arch/arm/kernel/perf_event.c
arch/arm/kernel/perf_event_v7.c
arch/arm/kernel/smp.c
arch/arm/kernel/smp_tlb.c
arch/arm/kernel/smp_twd.c
arch/arm/kernel/suspend.c
arch/arm/lib/memset.S
arch/arm/mach-at91/board-foxg20.c
arch/arm/mach-at91/board-stamp9g20.c
arch/arm/mach-imx/clk-imx6q.c
arch/arm/mach-imx/headsmp.S
arch/arm/mach-imx/pm-imx6q.c
arch/arm/mach-ixp4xx/vulcan-setup.c
arch/arm/mach-kirkwood/board-dt.c
arch/arm/mach-mxs/icoll.c
arch/arm/mach-mxs/mach-mxs.c
arch/arm/mach-mxs/mm.c
arch/arm/mach-mxs/ocotp.c
arch/arm/mach-netx/generic.c
arch/arm/mach-netx/include/mach/irqs.h
arch/arm/mach-omap1/common.h
arch/arm/mach-omap2/Kconfig
arch/arm/mach-omap2/board-generic.c
arch/arm/mach-omap2/board-rx51.c
arch/arm/mach-omap2/common.h
arch/arm/mach-omap2/gpmc.c
arch/arm/mach-omap2/mux.c
arch/arm/mach-pxa/raumfeld.c
arch/arm/mach-spear3xx/spear3xx.c
arch/arm/mm/context.c
arch/arm/mm/dma-mapping.c
arch/arm/mm/idmap.c
arch/arm/mm/proc-v7-3level.S
arch/arm/plat-orion/addr-map.c
arch/arm/plat-spear/Kconfig
arch/avr32/Kconfig
arch/blackfin/Kconfig
arch/cris/Kconfig
arch/frv/Kconfig
arch/h8300/Kconfig
arch/ia64/Kconfig
arch/ia64/kernel/perfmon.c
arch/m32r/Kconfig
arch/m32r/include/uapi/asm/stat.h
arch/m68k/Kconfig
arch/m68k/Kconfig.machine
arch/m68k/include/asm/MC68328.h
arch/m68k/kernel/setup_no.c
arch/m68k/mm/init.c
arch/m68k/platform/coldfire/m528x.c
arch/metag/include/asm/elf.h
arch/metag/mm/Kconfig
arch/microblaze/Kconfig
arch/mips/Kconfig
arch/mn10300/Kconfig
arch/openrisc/Kconfig
arch/parisc/Kconfig
arch/powerpc/Kconfig
arch/powerpc/crypto/sha1-powerpc-asm.S
arch/powerpc/include/asm/bitops.h
arch/powerpc/include/asm/reg.h
arch/powerpc/include/asm/systbl.h
arch/powerpc/include/asm/unistd.h
arch/powerpc/include/uapi/asm/unistd.h
arch/powerpc/kernel/cpu_setup_power.S
arch/powerpc/kernel/exceptions-64s.S
arch/powerpc/platforms/cell/spufs/inode.c
arch/powerpc/platforms/pseries/hvcserver.c
arch/s390/Kconfig
arch/s390/hypfs/inode.c
arch/s390/include/asm/cpu_mf.h
arch/score/Kconfig
arch/tile/Kconfig
arch/tile/include/asm/compat.h
arch/tile/kernel/compat.c
arch/um/drivers/chan.h
arch/um/drivers/chan_kern.c
arch/um/drivers/chan_user.c
arch/um/drivers/chan_user.h
arch/um/drivers/line.c
arch/um/drivers/net_kern.c
arch/um/drivers/ssl.c
arch/um/drivers/stdio_console.c
arch/um/os-Linux/signal.c
arch/um/os-Linux/start_up.c
arch/unicore32/Kconfig
arch/x86/Kconfig
arch/x86/include/asm/bootparam_utils.h
arch/x86/kernel/cpu/perf_event_intel_ds.c
arch/x86/kernel/setup.c
arch/x86/kernel/smpboot.c
arch/x86/mm/init.c
arch/x86/mm/pat.c
arch/x86/power/cpu.c
arch/xtensa/Kconfig
drivers/acpi/glue.c
drivers/acpi/processor_core.c
drivers/acpi/processor_driver.c
drivers/acpi/processor_perflib.c
drivers/acpi/sleep.c
drivers/ata/libata-acpi.c
drivers/base/power/main.c
drivers/base/power/power.h
drivers/base/power/qos.c
drivers/base/power/sysfs.c
drivers/base/regmap/regmap-irq.c
drivers/bcma/driver_pci_host.c
drivers/char/hw_random/core.c
drivers/char/hw_random/virtio-rng.c
drivers/char/random.c
drivers/clk/tegra/clk-tegra20.c
drivers/clk/tegra/clk-tegra30.c
drivers/connector/cn_proc.c
drivers/cpufreq/cpufreq_governor.h
drivers/cpufreq/highbank-cpufreq.c
drivers/cpufreq/intel_pstate.c
drivers/firmware/dmi_scan.c
drivers/firmware/efivars.c
drivers/gpio/gpio-ich.c
drivers/gpio/gpio-mvebu.c
drivers/gpio/gpiolib.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_crt.c
drivers/gpu/drm/i915/intel_ddi.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/mgag200/mgag200_drv.h
drivers/gpu/drm/mgag200/mgag200_i2c.c
drivers/gpu/drm/mgag200/mgag200_mode.c
drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
drivers/gpu/drm/nouveau/core/engine/graph/nve0.c
drivers/gpu/drm/nouveau/core/subdev/bios/init.c
drivers/gpu/drm/nouveau/core/subdev/i2c/base.c
drivers/gpu/drm/nouveau/nouveau_abi16.c
drivers/gpu/drm/nouveau/nouveau_agp.c
drivers/gpu/drm/nouveau/nouveau_bo.c
drivers/gpu/drm/nouveau/nv50_display.c
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/evergreen_cs.c
drivers/gpu/drm/radeon/ni.c
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/radeon_combios.c
drivers/gpu/drm/radeon/radeon_drv.c
drivers/gpu/drm/radeon/radeon_irq_kms.c
drivers/gpu/drm/radeon/si.c
drivers/gpu/drm/tegra/Kconfig
drivers/hid/hid-logitech-dj.c
drivers/hwmon/lineage-pem.c
drivers/hwmon/pmbus/ltc2978.c
drivers/hwmon/pmbus/pmbus_core.c
drivers/hwmon/sht15.c
drivers/iio/common/st_sensors/st_sensors_core.c
drivers/iio/dac/ad5064.c
drivers/iio/imu/inv_mpu6050/Kconfig
drivers/infiniband/hw/ipath/ipath_fs.c
drivers/infiniband/hw/mlx4/cm.c
drivers/infiniband/hw/qib/qib_fs.c
drivers/input/keyboard/tc3589x-keypad.c
drivers/input/mouse/alps.c
drivers/input/mouse/alps.h
drivers/input/mouse/cypress_ps2.c
drivers/input/tablet/wacom_wac.c
drivers/input/touchscreen/ads7846.c
drivers/input/touchscreen/atmel_mxt_ts.c
drivers/input/touchscreen/mms114.c
drivers/iommu/dmar.c
drivers/irqchip/irq-gic.c
drivers/isdn/hisax/st5481_usb.c
drivers/isdn/i4l/isdn_tty.c
drivers/mailbox/pl320-ipc.c
drivers/md/Kconfig
drivers/md/dm-raid.c
drivers/md/md.c
drivers/md/raid0.c
drivers/md/raid1.c
drivers/md/raid10.c
drivers/md/raid10.h
drivers/md/raid5.c
drivers/mfd/Kconfig
drivers/mfd/ab8500-gpadc.c
drivers/mfd/omap-usb-host.c
drivers/mfd/palmas.c
drivers/mfd/tps65912-core.c
drivers/mfd/twl4030-audio.c
drivers/mfd/twl4030-madc.c
drivers/misc/ibmasm/ibmasmfs.c
drivers/mtd/mtdchar.c
drivers/net/bonding/bond_main.c
drivers/net/ethernet/broadcom/bgmac.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h
drivers/net/ethernet/broadcom/tg3.c
drivers/net/ethernet/emulex/benet/be.h
drivers/net/ethernet/emulex/benet/be_cmds.c
drivers/net/ethernet/emulex/benet/be_hw.h
drivers/net/ethernet/emulex/benet/be_main.c
drivers/net/ethernet/freescale/fec.c
drivers/net/ethernet/freescale/fec.h
drivers/net/ethernet/intel/e1000e/ethtool.c
drivers/net/ethernet/intel/e1000e/ich8lan.c
drivers/net/ethernet/intel/e1000e/ich8lan.h
drivers/net/ethernet/intel/e1000e/netdev.c
drivers/net/ethernet/intel/e1000e/regs.h
drivers/net/ethernet/intel/igb/e1000_82575.c
drivers/net/ethernet/intel/igb/igb.h
drivers/net/ethernet/intel/igb/igb_hwmon.c
drivers/net/ethernet/intel/igb/igb_main.c
drivers/net/ethernet/marvell/mv643xx_eth.c
drivers/net/ethernet/mellanox/mlx4/cq.c
drivers/net/ethernet/mellanox/mlx4/en_netdev.c
drivers/net/ethernet/mellanox/mlx4/fw.c
drivers/net/ethernet/mellanox/mlx4/main.c
drivers/net/ethernet/mellanox/mlx4/mlx4.h
drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
drivers/net/ethernet/mellanox/mlx4/mr.c
drivers/net/ethernet/mellanox/mlx4/pd.c
drivers/net/ethernet/mellanox/mlx4/port.c
drivers/net/ethernet/mellanox/mlx4/qp.c
drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
drivers/net/ethernet/mellanox/mlx4/srq.c
drivers/net/ethernet/realtek/r8169.c
drivers/net/ethernet/sfc/efx.c
drivers/net/ethernet/sfc/efx.h
drivers/net/ethernet/sfc/net_driver.h
drivers/net/ethernet/sfc/rx.c
drivers/net/ethernet/ti/cpsw.c
drivers/net/hippi/rrunner.c
drivers/net/macvlan.c
drivers/net/phy/micrel.c
drivers/net/phy/phy_device.c
drivers/net/team/team.c
drivers/net/tun.c
drivers/net/usb/Kconfig
drivers/net/usb/Makefile
drivers/net/usb/asix_devices.c
drivers/net/usb/ax88179_178a.c [new file with mode: 0644]
drivers/net/usb/cdc_ncm.c
drivers/net/vmxnet3/vmxnet3_drv.c
drivers/net/vmxnet3/vmxnet3_ethtool.c
drivers/net/vmxnet3/vmxnet3_int.h
drivers/net/vxlan.c
drivers/net/wireless/ath/ath9k/common.h
drivers/net/wireless/ath/ath9k/htc.h
drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
drivers/net/wireless/ath/ath9k/hw.c
drivers/net/wireless/iwlwifi/dvm/sta.c
drivers/net/wireless/iwlwifi/iwl-devtrace.h
drivers/net/wireless/iwlwifi/iwl-drv.c
drivers/net/wireless/iwlwifi/iwl-modparams.h
drivers/net/wireless/iwlwifi/iwl-phy-db.c
drivers/net/wireless/iwlwifi/iwl-trans.h
drivers/net/wireless/iwlwifi/mvm/d3.c
drivers/net/wireless/iwlwifi/mvm/fw-api.h
drivers/net/wireless/iwlwifi/mvm/fw.c
drivers/net/wireless/iwlwifi/mvm/mac80211.c
drivers/net/wireless/iwlwifi/mvm/mvm.h
drivers/net/wireless/iwlwifi/mvm/ops.c
drivers/net/wireless/iwlwifi/mvm/rx.c
drivers/net/wireless/iwlwifi/mvm/sta.c
drivers/net/wireless/iwlwifi/mvm/tx.c
drivers/net/wireless/iwlwifi/pcie/internal.h
drivers/net/wireless/iwlwifi/pcie/rx.c
drivers/net/wireless/iwlwifi/pcie/tx.c
drivers/net/wireless/libertas/if_sdio.c
drivers/net/wireless/mwifiex/pcie.c
drivers/net/wireless/rt2x00/rt2x00dev.c
drivers/oprofile/oprofilefs.c
drivers/pci/pci-acpi.c
drivers/platform/x86/chromeos_laptop.c
drivers/pnp/pnpacpi/core.c
drivers/regulator/core.c
drivers/regulator/db8500-prcmu.c
drivers/regulator/palmas-regulator.c
drivers/regulator/twl-regulator.c
drivers/rtc/rtc-mv.c
drivers/scsi/scsi_lib.c
drivers/staging/ccg/f_fs.c
drivers/staging/comedi/drivers/dt9812.c
drivers/staging/comedi/drivers/usbdux.c
drivers/staging/comedi/drivers/usbduxfast.c
drivers/staging/comedi/drivers/usbduxsigma.c
drivers/staging/imx-drm/ipuv3-crtc.c
drivers/staging/tidspbridge/rmgr/drv.c
drivers/staging/vt6656/card.c
drivers/staging/vt6656/main_usb.c
drivers/staging/zcache/ramster/tcp.c
drivers/tty/hvc/hvcs.c
drivers/tty/serial/8250/8250.c
drivers/tty/serial/8250/8250_pci.c
drivers/tty/serial/8250/8250_pnp.c
drivers/tty/serial/Kconfig
drivers/tty/serial/bcm63xx_uart.c
drivers/tty/serial/mpc52xx_uart.c
drivers/tty/serial/of_serial.c
drivers/tty/serial/vt8500_serial.c
drivers/tty/tty_buffer.c
drivers/usb/Makefile
drivers/usb/c67x00/c67x00-sched.c
drivers/usb/chipidea/udc.c
drivers/usb/class/cdc-wdm.c
drivers/usb/core/usb-acpi.c
drivers/usb/dwc3/core.c
drivers/usb/dwc3/dwc3-exynos.c
drivers/usb/dwc3/dwc3-omap.c
drivers/usb/dwc3/dwc3-pci.c
drivers/usb/dwc3/ep0.c
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/Makefile
drivers/usb/gadget/composite.c
drivers/usb/gadget/f_fs.c
drivers/usb/gadget/f_uac1.c
drivers/usb/gadget/imx_udc.c
drivers/usb/gadget/inode.c
drivers/usb/gadget/omap_udc.c
drivers/usb/gadget/pxa25x_udc.c
drivers/usb/gadget/pxa27x_udc.c
drivers/usb/gadget/s3c2410_udc.c
drivers/usb/gadget/u_uac1.c
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ehci-q.c
drivers/usb/musb/Kconfig
drivers/usb/musb/musb_core.c
drivers/usb/musb/omap2430.c
drivers/usb/otg/otg.c
drivers/usb/phy/omap-control-usb.c
drivers/usb/phy/omap-usb3.c
drivers/usb/phy/samsung-usbphy.c
drivers/usb/serial/cp210x.c
drivers/usb/serial/option.c
drivers/usb/serial/qcaux.c
drivers/usb/serial/qcserial.c
drivers/usb/serial/quatech2.c
drivers/usb/storage/initializers.c
drivers/usb/storage/initializers.h
drivers/usb/storage/unusual_devs.h
drivers/video/omap/lcd_ams_delta.c
drivers/video/omap/lcd_osk.c
drivers/w1/masters/w1-gpio.c
drivers/w1/w1.c
drivers/xen/xen-acpi-processor.c
drivers/xen/xen-pciback/pciback_ops.c
drivers/xen/xen-stub.c
drivers/xen/xenfs/super.c
fs/9p/vfs_super.c
fs/adfs/super.c
fs/affs/super.c
fs/afs/super.c
fs/autofs4/init.c
fs/befs/linuxvfs.c
fs/bfs/inode.c
fs/binfmt_misc.c
fs/btrfs/delayed-inode.c
fs/btrfs/delayed-inode.h
fs/btrfs/disk-io.c
fs/btrfs/extent-tree.c
fs/btrfs/file.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/locking.h
fs/btrfs/qgroup.c
fs/btrfs/relocation.c
fs/btrfs/super.c
fs/btrfs/transaction.c
fs/btrfs/tree-log.c
fs/btrfs/volumes.c
fs/ceph/super.c
fs/cifs/cifsfs.c
fs/cifs/cifssmb.c
fs/cifs/connect.c
fs/cifs/inode.c
fs/cifs/smb2ops.c
fs/coda/inode.c
fs/compat.c
fs/configfs/mount.c
fs/cramfs/inode.c
fs/debugfs/inode.c
fs/ecryptfs/Kconfig
fs/ecryptfs/Makefile
fs/ecryptfs/crypto.c
fs/ecryptfs/dentry.c
fs/ecryptfs/ecryptfs_kernel.h
fs/ecryptfs/file.c
fs/ecryptfs/inode.c
fs/ecryptfs/keystore.c
fs/ecryptfs/main.c
fs/ecryptfs/messaging.c
fs/efs/super.c
fs/exofs/super.c
fs/ext2/ialloc.c
fs/ext2/inode.c
fs/ext2/super.c
fs/ext3/super.c
fs/ext4/super.c
fs/f2fs/super.c
fs/fat/namei_msdos.c
fs/fat/namei_vfat.c
fs/filesystems.c
fs/freevxfs/vxfs_super.c
fs/fuse/control.c
fs/fuse/inode.c
fs/gfs2/ops_fstype.c
fs/hfs/super.c
fs/hfsplus/super.c
fs/hostfs/hostfs_kern.c
fs/hpfs/super.c
fs/hppfs/hppfs.c
fs/hugetlbfs/inode.c
fs/isofs/inode.c
fs/jffs2/super.c
fs/jfs/super.c
fs/logfs/super.c
fs/minix/inode.c
fs/namei.c
fs/ncpfs/inode.c
fs/nfs/super.c
fs/nfsd/cache.h
fs/nfsd/netns.h
fs/nfsd/nfs4callback.c
fs/nfsd/nfs4proc.c
fs/nfsd/nfs4state.c
fs/nfsd/nfs4xdr.c
fs/nfsd/nfscache.c
fs/nfsd/nfsctl.c
fs/nfsd/state.h
fs/nfsd/vfs.c
fs/nfsd/xdr4.h
fs/nfsd/xdr4cb.h [new file with mode: 0644]
fs/nilfs2/super.c
fs/ntfs/super.c
fs/ocfs2/dlmfs/dlmfs.c
fs/ocfs2/super.c
fs/omfs/inode.c
fs/openpromfs/inode.c
fs/pipe.c
fs/proc/namespaces.c
fs/qnx4/inode.c
fs/qnx6/inode.c
fs/quota/dquot.c
fs/reiserfs/super.c
fs/romfs/super.c
fs/squashfs/super.c
fs/sysv/super.c
fs/ubifs/super.c
fs/udf/super.c
fs/ufs/super.c
fs/xfs/xfs_super.c
include/acpi/acpi_bus.h
include/acpi/processor.h
include/asm-generic/atomic.h
include/asm-generic/cmpxchg.h
include/drm/drm_crtc.h
include/linux/ecryptfs.h
include/linux/fs.h
include/linux/hardirq.h
include/linux/i2c/atmel_mxt_ts.h
include/linux/idr.h
include/linux/iio/common/st_sensors.h
include/linux/list.h
include/linux/mfd/palmas.h
include/linux/mfd/tps65912.h
include/linux/mfd/wm831x/auxadc.h
include/linux/mfd/wm831x/core.h
include/linux/netfilter/ipset/ip_set_ahash.h
include/linux/perf_event.h
include/linux/regulator/driver.h
include/linux/res_counter.h
include/linux/smpboot.h
include/linux/sunrpc/clnt.h
include/linux/sunrpc/gss_api.h
include/linux/sunrpc/msg_prot.h
include/linux/sunrpc/xprt.h
include/linux/usb/composite.h
include/net/tcp.h
include/uapi/linux/acct.h
include/uapi/linux/aio_abi.h
include/uapi/linux/raid/md_p.h
include/uapi/linux/serial_core.h
init/Kconfig
ipc/msg.c
ipc/msgutil.c
kernel/fork.c
kernel/futex.c
kernel/signal.c
kernel/smpboot.c
kernel/softirq.c
kernel/stop_machine.c
kernel/trace/Kconfig
kernel/trace/trace.c
kernel/user_namespace.c
kernel/workqueue.c
lib/idr.c
lib/xz/Kconfig
mm/Kconfig
mm/fremap.c
mm/ksm.c
mm/memcontrol.c
mm/memory_hotplug.c
mm/mempolicy.c
mm/process_vm_access.c
net/9p/trans_virtio.c
net/bridge/br_device.c
net/bridge/br_input.c
net/bridge/br_mdb.c
net/bridge/br_multicast.c
net/bridge/br_private.h
net/caif/caif_dev.c
net/caif/caif_usb.c
net/ceph/osdmap.c
net/core/dev.c
net/core/rtnetlink.c
net/dcb/dcbnl.c
net/ieee802154/6lowpan.h
net/ipv4/inet_connection_sock.c
net/ipv4/ip_input.c
net/ipv4/ip_options.c
net/ipv4/tcp_input.c
net/ipv6/ip6_input.c
net/ipv6/route.c
net/irda/ircomm/ircomm_tty.c
net/irda/iriap.c
net/key/af_key.c
net/l2tp/l2tp_ppp.c
net/mac80211/cfg.c
net/mac80211/iface.c
net/mac80211/mlme.c
net/mac80211/tx.c
net/netfilter/ipset/ip_set_core.c
net/netfilter/nf_conntrack_helper.c
net/netfilter/nfnetlink.c
net/netfilter/xt_AUDIT.c
net/netlabel/netlabel_unlabeled.c
net/rds/message.c
net/rds/stats.c
net/sched/sch_qfq.c
net/sctp/endpointola.c
net/sctp/socket.c
net/sctp/ssnmap.c
net/sctp/tsnmap.c
net/sctp/ulpqueue.c
net/sunrpc/auth_gss/Makefile
net/sunrpc/auth_gss/auth_gss.c
net/sunrpc/auth_gss/gss_krb5_mech.c
net/sunrpc/auth_gss/gss_mech_switch.c
net/sunrpc/auth_gss/gss_rpc_upcall.c [new file with mode: 0644]
net/sunrpc/auth_gss/gss_rpc_upcall.h [new file with mode: 0644]
net/sunrpc/auth_gss/gss_rpc_xdr.c [new file with mode: 0644]
net/sunrpc/auth_gss/gss_rpc_xdr.h [new file with mode: 0644]
net/sunrpc/auth_gss/svcauth_gss.c
net/sunrpc/cache.c
net/sunrpc/clnt.c
net/sunrpc/netns.h
net/sunrpc/rpc_pipe.c
net/sunrpc/xprt.c
net/sunrpc/xprtsock.c
net/wireless/core.c
net/wireless/nl80211.c
scripts/Makefile.headersinst
security/keys/compat.c
security/keys/process_keys.c
sound/core/seq/oss/seq_oss_event.c
sound/core/seq/seq_timer.c
sound/core/vmaster.c
sound/oss/sequencer.c
sound/pci/asihpi/asihpi.c
sound/pci/hda/hda_codec.c
sound/pci/hda/patch_ca0132.c
sound/pci/hda/patch_cirrus.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c
sound/pci/ice1712/ice1712.c
sound/soc/codecs/wm5102.c
sound/soc/codecs/wm5110.c
sound/soc/codecs/wm8350.c
sound/soc/codecs/wm8960.c
sound/soc/tegra/tegra20_i2s.h
sound/soc/tegra/tegra30_i2s.h
sound/usb/card.c
tools/testing/selftests/efivarfs/efivarfs.sh
tools/usb/ffs-test.c

diff --git a/CREDITS b/CREDITS
index 948e0fb..78163cb 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -953,11 +953,11 @@ S: Blacksburg, Virginia 24061
 S: USA
 
 N: Randy Dunlap
-E: rdunlap@xenotime.net
-W: http://www.xenotime.net/linux/linux.html
-W: http://www.linux-usb.org
+E: rdunlap@infradead.org
+W: http://www.infradead.org/~rdunlap/
 D: Linux-USB subsystem, USB core/UHCI/printer/storage drivers
 D: x86 SMP, ACPI, bootflag hacking
+D: documentation, builds
 S: (ask for current address)
 S: USA
 
index c379a2a..aa0c1e6 100644 (file)
@@ -60,8 +60,7 @@ own source tree.  For example:
 "dontdiff" is a list of files which are generated by the kernel during
 the build process, and should be ignored in any diff(1)-generated
 patch.  The "dontdiff" file is included in the kernel tree in
-2.6.12 and later.  For earlier kernel versions, you can get it
-from <http://www.xenotime.net/linux/doc/dontdiff>.
+2.6.12 and later.
 
 Make sure your patch does not include any extra files which do not
 belong in a patch submission.  Make sure to review your patch -after-
index 56fb62b..b428556 100644 (file)
@@ -30,6 +30,7 @@ The target is named "raid" and it accepts the following parameters:
   raid10        Various RAID10 inspired algorithms chosen by additional params
                - RAID10: Striped Mirrors (aka 'Striping on top of mirrors')
                - RAID1E: Integrated Adjacent Stripe Mirroring
+               - RAID1E: Integrated Offset Stripe Mirroring
                -  and other similar RAID10 variants
 
   Reference: Chapter 4 of
@@ -64,15 +65,15 @@ The target is named "raid" and it accepts the following parameters:
                synchronisation state for each region.
 
         [raid10_copies   <# copies>]
-        [raid10_format   near]
+        [raid10_format   <near|far|offset>]
                These two options are used to alter the default layout of
                a RAID10 configuration.  The number of copies is can be
-               specified, but the default is 2.  There are other variations
-               to how the copies are laid down - the default and only current
-               option is "near".  Near copies are what most people think of
-               with respect to mirroring.  If these options are left
-               unspecified, or 'raid10_copies 2' and/or 'raid10_format near'
-               are given, then the layouts for 2, 3 and 4 devices are:
+               specified, but the default is 2.  There are also three
+               variations to how the copies are laid down - the default
+               is "near".  Near copies are what most people think of with
+               respect to mirroring.  If these options are left unspecified,
+               or 'raid10_copies 2' and/or 'raid10_format near' are given,
+               then the layouts for 2, 3 and 4 devices are:
                2 drives         3 drives          4 drives
                --------         ----------        --------------
                A1  A1           A1  A1  A2        A1  A1  A2  A2
@@ -85,6 +86,33 @@ The target is named "raid" and it accepts the following parameters:
                3-device layout is what might be called a 'RAID1E - Integrated
                Adjacent Stripe Mirroring'.
 
+               If 'raid10_copies 2' and 'raid10_format far', then the layouts
+               for 2, 3 and 4 devices are:
+               2 drives             3 drives             4 drives
+               --------             --------------       --------------------
+               A1  A2               A1   A2   A3         A1   A2   A3   A4
+               A3  A4               A4   A5   A6         A5   A6   A7   A8
+               A5  A6               A7   A8   A9         A9   A10  A11  A12
+               ..  ..               ..   ..   ..         ..   ..   ..   ..
+               A2  A1               A3   A1   A2         A2   A1   A4   A3
+               A4  A3               A6   A4   A5         A6   A5   A8   A7
+               A6  A5               A9   A7   A8         A10  A9   A12  A11
+               ..  ..               ..   ..   ..         ..   ..   ..   ..
+
+               If 'raid10_copies 2' and 'raid10_format offset', then the
+               layouts for 2, 3 and 4 devices are:
+               2 drives       3 drives           4 drives
+               --------       ------------       -----------------
+               A1  A2         A1  A2  A3         A1  A2  A3  A4
+               A2  A1         A3  A1  A2         A2  A1  A4  A3
+               A3  A4         A4  A5  A6         A5  A6  A7  A8
+               A4  A3         A6  A4  A5         A6  A5  A8  A7
+               A5  A6         A7  A8  A9         A9  A10 A11 A12
+               A6  A5         A9  A7  A8         A10 A9  A12 A11
+               ..  ..         ..  ..  ..         ..  ..  ..  ..
+               Here we see layouts closely akin to 'RAID1E - Integrated
+               Offset Stripe Mirroring'.
+
 <#raid_devs>: The number of devices composing the array.
        Each device consists of two entries.  The first is the device
        containing the metadata (if any); the second is the one containing the
@@ -142,3 +170,5 @@ Version History
 1.3.0  Added support for RAID 10
 1.3.1  Allow device replacement/rebuild for RAID 10
 1.3.2   Fix/improve redundancy checking for RAID10
+1.4.0  Non-functional change.  Removes arg from mapping function.
+1.4.1   Add RAID10 "far" and "offset" algorithm support.
index 13b707b..c3a14e0 100644 (file)
@@ -13,9 +13,6 @@ Required parent device properties:
                                   4 = active high level-sensitive
                                   8 = active low level-sensitive
 
-Optional parent device properties:
-- reg                    : contains the PRCMU mailbox address for the AB8500 i2c port
-
 The AB8500 consists of a large and varied group of sub-devices:
 
 Device                     IRQ Names              Supply Names   Description
@@ -86,9 +83,8 @@ Non-standard child device properties:
    - stericsson,amic2-bias-vamic1           : Analoge Mic wishes to use a non-standard Vamic
    - stericsson,earpeice-cmv                : Earpeice voltage (only: 950 | 1100 | 1270 | 1580)
 
-ab8500@5 {
+ab8500 {
          compatible = "stericsson,ab8500";
-         reg = <5>; /* mailbox 5 is i2c */
          interrupts = <0 40 0x4>;
          interrupt-controller;
          #interrupt-cells = <2>;
index 1e1145c..8f01cb1 100644 (file)
@@ -11,6 +11,9 @@ Required properties:
        - "nvidia,tegra20-uart"
        - "nxp,lpc3220-uart"
        - "ibm,qpace-nwp-serial"
+       - "altr,16550-FIFO32"
+       - "altr,16550-FIFO64"
+       - "altr,16550-FIFO128"
        - "serial" if the port type is unknown.
 - reg : offset and length of the register set for the device.
 - interrupts : should contain uart interrupt.
index 1716874..66eb6c8 100644 (file)
@@ -20,3 +20,5 @@ rpc-cache.txt
        - introduction to the caching mechanisms in the sunrpc layer.
 idmapper.txt
        - information for configuring request-keys to be used by idmapper
+knfsd-rpcgss.txt
+       - Information on GSS authentication support in the NFS Server
diff --git a/Documentation/filesystems/nfs/rpc-server-gss.txt b/Documentation/filesystems/nfs/rpc-server-gss.txt
new file mode 100644 (file)
index 0000000..716f4be
--- /dev/null
@@ -0,0 +1,91 @@
+
+rpcsec_gss support for kernel RPC servers
+=========================================
+
+This document gives references to the standards and protocols used to
+implement RPCGSS authentication in kernel RPC servers such as the NFS
+server and the NFS client's NFSv4.0 callback server.  (But note that
+NFSv4.1 and higher don't require the client to act as a server for the
+purposes of authentication.)
+
+RPCGSS is specified in a few IETF documents:
+ - RFC2203 v1: http://tools.ietf.org/rfc/rfc2203.txt
+ - RFC5403 v2: http://tools.ietf.org/rfc/rfc5403.txt
+and there is a 3rd version  being proposed:
+ - http://tools.ietf.org/id/draft-williams-rpcsecgssv3.txt
+   (At draft n. 02 at the time of writing)
+
+Background
+----------
+
+The RPCGSS Authentication method describes a way to perform GSSAPI
+Authentication for NFS.  Although GSSAPI is itself completely mechanism
+agnostic, in many cases only the KRB5 mechanism is supported by NFS
+implementations.
+
+The Linux kernel, at the moment, supports only the KRB5 mechanism, and
+depends on GSSAPI extensions that are KRB5 specific.
+
+GSSAPI is a complex library, and implementing it completely in kernel is
+unwarranted. However GSSAPI operations are fundementally separable in 2
+parts:
+- initial context establishment
+- integrity/privacy protection (signing and encrypting of individual
+  packets)
+
+The former is more complex and policy-independent, but less
+performance-sensitive.  The latter is simpler and needs to be very fast.
+
+Therefore, we perform per-packet integrity and privacy protection in the
+kernel, but leave the initial context establishment to userspace.  We
+need upcalls to request userspace to perform context establishment.
+
+NFS Server Legacy Upcall Mechanism
+----------------------------------
+
+The classic upcall mechanism uses a custom text based upcall mechanism
+to talk to a custom daemon called rpc.svcgssd that is provide by the
+nfs-utils package.
+
+This upcall mechanism has 2 limitations:
+
+A) It can handle tokens that are no bigger than 2KiB
+
+In some Kerberos deployment GSSAPI tokens can be quite big, up and
+beyond 64KiB in size due to various authorization extensions attacked to
+the Kerberos tickets, that needs to be sent through the GSS layer in
+order to perform context establishment.
+
+B) It does not properly handle creds where the user is member of more
+than a few housand groups (the current hard limit in the kernel is 65K
+groups) due to limitation on the size of the buffer that can be send
+back to the kernel (4KiB).
+
+NFS Server New RPC Upcall Mechanism
+-----------------------------------
+
+The newer upcall mechanism uses RPC over a unix socket to a daemon
+called gss-proxy, implemented by a userspace program called Gssproxy.
+
+The gss_proxy RPC protocol is currently documented here:
+
+       https://fedorahosted.org/gss-proxy/wiki/ProtocolDocumentation
+
+This upcall mechanism uses the kernel rpc client and connects to the gssproxy
+userspace program over a regular unix socket. The gssproxy protocol does not
+suffer from the size limitations of the legacy protocol.
+
+Negotiating Upcall Mechanisms
+-----------------------------
+
+To provide backward compatibility, the kernel defaults to using the
+legacy mechanism.  To switch to the new mechanism, gss-proxy must bind
+to /var/run/gssproxy.sock and then write "1" to
+/proc/net/rpc/use-gss-proxy.  If gss-proxy dies, it must repeat both
+steps.
+
+Once the upcall mechanism is chosen, it cannot be changed.  To prevent
+locking into the legacy mechanisms, the above steps must be performed
+before starting nfsd.  Whoever starts nfsd can guarantee this by reading
+from /proc/net/rpc/use-gss-proxy and checking that it contains a
+"1"--the read will block until gss-proxy has done its write to the file.
index 2cfa256..15b4a20 100644 (file)
@@ -15,7 +15,7 @@ Supported chips:
     Addresses scanned: -
     Datasheet: www.analog.com/static/imported-files/data_sheets/ADM1276.pdf
 
-Author: Guenter Roeck <guenter.roeck@ericsson.com>
+Author: Guenter Roeck <linux@roeck-us.net>
 
 
 Description
index 9600400..58150c4 100644 (file)
@@ -4,9 +4,14 @@ Kernel driver adt7410
 Supported chips:
   * Analog Devices ADT7410
     Prefix: 'adt7410'
-    Addresses scanned: I2C 0x48 - 0x4B
+    Addresses scanned: None
     Datasheet: Publicly available at the Analog Devices website
                http://www.analog.com/static/imported-files/data_sheets/ADT7410.pdf
+  * Analog Devices ADT7420
+    Prefix: 'adt7420'
+    Addresses scanned: None
+    Datasheet: Publicly available at the Analog Devices website
+               http://www.analog.com/static/imported-files/data_sheets/ADT7420.pdf
 
 Author: Hartmut Knaack <knaack.h@gmx.de>
 
@@ -27,6 +32,10 @@ value per second or even justget one sample on demand for power saving.
 Besides, it can completely power down its ADC, if power management is
 required.
 
+The ADT7420 is register compatible, the only differences being the package,
+a slightly narrower operating temperature range (-40°C to +150°C), and a
+better accuracy (0.25°C instead of 0.50°C.)
+
 Configuration Notes
 -------------------
 
index 1650771..868d74d 100644 (file)
@@ -49,7 +49,7 @@ Supported chips:
     Addresses scanned: I2C 0x18 - 0x1f
 
 Author:
-       Guenter Roeck <guenter.roeck@ericsson.com>
+       Guenter Roeck <linux@roeck-us.net>
 
 
 Description
index 2ba5ed1..83b2ddc 100644 (file)
@@ -8,7 +8,7 @@ Supported devices:
     Documentation:
         http://www.lineagepower.com/oem/pdf/CPLI2C.pdf
 
-Author: Guenter Roeck <guenter.roeck@ericsson.com>
+Author: Guenter Roeck <linux@roeck-us.net>
 
 
 Description
index a21db81..26025e4 100644 (file)
@@ -19,7 +19,7 @@ Supported chips:
     Datasheet:
        http://www.national.com/pf/LM/LM5066.html
 
-Author: Guenter Roeck <guenter.roeck@ericsson.com>
+Author: Guenter Roeck <linux@roeck-us.net>
 
 
 Description
index c365f9b..e4d75c6 100644 (file)
@@ -5,13 +5,13 @@ Supported chips:
   * Linear Technology LTC2978
     Prefix: 'ltc2978'
     Addresses scanned: -
-    Datasheet: http://cds.linear.com/docs/Datasheet/2978fa.pdf
+    Datasheet: http://www.linear.com/product/ltc2978
   * Linear Technology LTC3880
     Prefix: 'ltc3880'
     Addresses scanned: -
-    Datasheet: http://cds.linear.com/docs/Datasheet/3880f.pdf
+    Datasheet: http://www.linear.com/product/ltc3880
 
-Author: Guenter Roeck <guenter.roeck@ericsson.com>
+Author: Guenter Roeck <linux@roeck-us.net>
 
 
 Description
index eba2e2c..9378a75 100644 (file)
@@ -8,7 +8,7 @@ Supported chips:
     Datasheet:
         http://cds.linear.com/docs/Datasheet/42612fb.pdf
 
-Author: Guenter Roeck <guenter.roeck@ericsson.com>
+Author: Guenter Roeck <linux@roeck-us.net>
 
 
 Description
index f8b4780..d59cc78 100644 (file)
@@ -7,7 +7,7 @@ Supported chips:
     Addresses scanned: -
     Datasheet: http://datasheets.maxim-ic.com/en/ds/MAX16064.pdf
 
-Author: Guenter Roeck <guenter.roeck@ericsson.com>
+Author: Guenter Roeck <linux@roeck-us.net>
 
 
 Description
index c11f64a..208a29e 100644 (file)
@@ -24,7 +24,7 @@ Supported chips:
        http://datasheets.maxim-ic.com/en/ds/MAX16070-MAX16071.pdf
 
 
-Author: Guenter Roeck <guenter.roeck@ericsson.com>
+Author: Guenter Roeck <linux@roeck-us.net>
 
 
 Description
index 47651ff..37cbf47 100644 (file)
@@ -27,7 +27,7 @@ Supported chips:
     Addresses scanned: -
     Datasheet: http://datasheets.maximintegrated.com/en/ds/MAX34461.pdf
 
-Author: Guenter Roeck <guenter.roeck@ericsson.com>
+Author: Guenter Roeck <linux@roeck-us.net>
 
 
 Description
index fe84987..e780786 100644 (file)
@@ -7,7 +7,7 @@ Supported chips:
     Addresses scanned: -
     Datasheet: http://datasheets.maxim-ic.com/en/ds/MAX8688.pdf
 
-Author: Guenter Roeck <guenter.roeck@ericsson.com>
+Author: Guenter Roeck <linux@roeck-us.net>
 
 
 Description
index 3d3a0f9..cf756ed 100644 (file)
@@ -34,7 +34,7 @@ Supported chips:
     Addresses scanned: -
     Datasheet: n.a.
 
-Author: Guenter Roeck <guenter.roeck@ericsson.com>
+Author: Guenter Roeck <linux@roeck-us.net>
 
 
 Description
index 59e3161..a341eee 100644 (file)
@@ -29,7 +29,7 @@ Supported chips:
       http://www.summitmicro.com/prod_select/summary/SMM766/SMM766_2086.pdf
       http://www.summitmicro.com/prod_select/summary/SMM766B/SMM766B_2122.pdf
 
-Author: Guenter Roeck <guenter.roeck@ericsson.com>
+Author: Guenter Roeck <linux@roeck-us.net>
 
 
 Module Parameters
index 0df5f27..805e33e 100644 (file)
@@ -11,7 +11,7 @@ Supported chips:
        http://focus.ti.com/lit/ds/symlink/ucd9090.pdf
        http://focus.ti.com/lit/ds/symlink/ucd90910.pdf
 
-Author: Guenter Roeck <guenter.roeck@ericsson.com>
+Author: Guenter Roeck <linux@roeck-us.net>
 
 
 Description
index fd7d07b..1e8060e 100644 (file)
@@ -15,7 +15,7 @@ Supported chips:
        http://focus.ti.com/lit/ds/symlink/ucd9246.pdf
        http://focus.ti.com/lit/ds/symlink/ucd9248.pdf
 
-Author: Guenter Roeck <guenter.roeck@ericsson.com>
+Author: Guenter Roeck <linux@roeck-us.net>
 
 
 Description
index 3d924b6..756b57c 100644 (file)
@@ -54,7 +54,7 @@ http://archive.ericsson.net/service/internet/picov/get?DocNo=28701-EN/LZT146401
 http://archive.ericsson.net/service/internet/picov/get?DocNo=28701-EN/LZT146256
 
 
-Author: Guenter Roeck <guenter.roeck@ericsson.com>
+Author: Guenter Roeck <linux@roeck-us.net>
 
 
 Description
index 3262b6e..e544c7f 100644 (file)
@@ -3,10 +3,26 @@ ALPS Touchpad Protocol
 
 Introduction
 ------------
-
-Currently the ALPS touchpad driver supports four protocol versions in use by
-ALPS touchpads, called versions 1, 2, 3, and 4. Information about the various
-protocol versions is contained in the following sections.
+Currently the ALPS touchpad driver supports five protocol versions in use by
+ALPS touchpads, called versions 1, 2, 3, 4 and 5.
+
+Since roughly mid-2010 several new ALPS touchpads have been released and
+integrated into a variety of laptops and netbooks.  These new touchpads
+have enough behavior differences that the alps_model_data definition
+table, describing the properties of the different versions, is no longer
+adequate.  The design choices were to re-define the alps_model_data
+table, with the risk of regression testing existing devices, or isolate
+the new devices outside of the alps_model_data table.  The latter design
+choice was made.  The new touchpad signatures are named: "Rushmore",
+"Pinnacle", and "Dolphin", which you will see in the alps.c code.
+For the purposes of this document, this group of ALPS touchpads will
+generically be called "new ALPS touchpads".
+
+We experimented with probing the ACPI interface _HID (Hardware ID)/_CID
+(Compatibility ID) definition as a way to uniquely identify the
+different ALPS variants but there did not appear to be a 1:1 mapping.
+In fact, it appeared to be an m:n mapping between the _HID and actual
+hardware type.
 
 Detection
 ---------
@@ -20,9 +36,13 @@ If the E6 report is successful, the touchpad model is identified using the "E7
 report" sequence: E8-E7-E7-E7-E9. The response is the model signature and is
 matched against known models in the alps_model_data_array.
 
-With protocol versions 3 and 4, the E7 report model signature is always
-73-02-64. To differentiate between these versions, the response from the
-"Enter Command Mode" sequence must be inspected as described below.
+For older touchpads supporting protocol versions 3 and 4, the E7 report
+model signature is always 73-02-64. To differentiate between these
+versions, the response from the "Enter Command Mode" sequence must be
+inspected as described below.
+
+The new ALPS touchpads have an E7 signature of 73-03-50 or 73-03-0A but
+seem to be better differentiated by the EC Command Mode response.
 
 Command Mode
 ------------
@@ -47,6 +67,14 @@ address of the register being read, and the third contains the value of the
 register. Registers are written by writing the value one nibble at a time
 using the same encoding used for addresses.
 
+For the new ALPS touchpads, the EC command is used to enter command
+mode. The response in the new ALPS touchpads is significantly different,
+and more important in determining the behavior.  This code has been
+separated from the original alps_model_data table and put in the
+alps_identify function.  For example, there seem to be two hardware init
+sequences for the "Dolphin" touchpads as determined by the second byte
+of the EC response.
+
 Packet Format
 -------------
 
@@ -187,3 +215,28 @@ There are several things worth noting here.
     well.
 
 So far no v4 devices with tracksticks have been encountered.
+
+ALPS Absolute Mode - Protocol Version 5
+---------------------------------------
+This is basically Protocol Version 3 but with different logic for packet
+decode.  It uses the same alps_process_touchpad_packet_v3 call with a
+specialized decode_fields function pointer to correctly interpret the
+packets.  This appears to only be used by the Dolphin devices.
+
+For single-touch, the 6-byte packet format is:
+
+ byte 0:    1    1    0    0    1    0    0    0
+ byte 1:    0   x6   x5   x4   x3   x2   x1   x0
+ byte 2:    0   y6   y5   y4   y3   y2   y1   y0
+ byte 3:    0    M    R    L    1    m    r    l
+ byte 4:   y10  y9   y8   y7  x10   x9   x8   x7
+ byte 5:    0   z6   z5   z4   z3   z2   z1   z0
+
+For mt, the format is:
+
+ byte 0:    1    1    1    n3   1   n2   n1   x24
+ byte 1:    1   y7   y6    y5  y4   y3   y2    y1
+ byte 2:    ?   x2   x1   y12 y11  y10   y9    y8
+ byte 3:    0  x23  x22   x21 x20  x19  x18   x17
+ byte 4:    0   x9   x8    x7  x6   x5   x4    x3
+ byte 5:    0  x16  x15   x14 x13  x12  x11   x10
index c0aab98..949d5dc 100644 (file)
@@ -105,6 +105,83 @@ Copyright (C) 1999-2000 Maxim Krasnyansky <max_mk@yahoo.com>
      Proto [2 bytes]
      Raw protocol(IP, IPv6, etc) frame.
 
+  3.3 Multiqueue tuntap interface:
+
+  From version 3.8, Linux supports multiqueue tuntap which can uses multiple
+  file descriptors (queues) to parallelize packets sending or receiving. The
+  device allocation is the same as before, and if user wants to create multiple
+  queues, TUNSETIFF with the same device name must be called many times with
+  IFF_MULTI_QUEUE flag.
+
+  char *dev should be the name of the device, queues is the number of queues to
+  be created, fds is used to store and return the file descriptors (queues)
+  created to the caller. Each file descriptor were served as the interface of a
+  queue which could be accessed by userspace.
+
+  #include <linux/if.h>
+  #include <linux/if_tun.h>
+
+  int tun_alloc_mq(char *dev, int queues, int *fds)
+  {
+      struct ifreq ifr;
+      int fd, err, i;
+
+      if (!dev)
+          return -1;
+
+      memset(&ifr, 0, sizeof(ifr));
+      /* Flags: IFF_TUN   - TUN device (no Ethernet headers)
+       *        IFF_TAP   - TAP device
+       *
+       *        IFF_NO_PI - Do not provide packet information
+       *        IFF_MULTI_QUEUE - Create a queue of multiqueue device
+       */
+      ifr.ifr_flags = IFF_TAP | IFF_NO_PI | IFF_MULTI_QUEUE;
+      strcpy(ifr.ifr_name, dev);
+
+      for (i = 0; i < queues; i++) {
+          if ((fd = open("/dev/net/tun", O_RDWR)) < 0)
+             goto err;
+          err = ioctl(fd, TUNSETIFF, (void *)&ifr);
+          if (err) {
+             close(fd);
+             goto err;
+          }
+          fds[i] = fd;
+      }
+
+      return 0;
+  err:
+      for (--i; i >= 0; i--)
+          close(fds[i]);
+      return err;
+  }
+
+  A new ioctl(TUNSETQUEUE) were introduced to enable or disable a queue. When
+  calling it with IFF_DETACH_QUEUE flag, the queue were disabled. And when
+  calling it with IFF_ATTACH_QUEUE flag, the queue were enabled. The queue were
+  enabled by default after it was created through TUNSETIFF.
+
+  fd is the file descriptor (queue) that we want to enable or disable, when
+  enable is true we enable it, otherwise we disable it
+
+  #include <linux/if.h>
+  #include <linux/if_tun.h>
+
+  int tun_set_queue(int fd, int enable)
+  {
+      struct ifreq ifr;
+
+      memset(&ifr, 0, sizeof(ifr));
+
+      if (enable)
+         ifr.ifr_flags = IFF_ATTACH_QUEUE;
+      else
+         ifr.ifr_flags = IFF_DETACH_QUEUE;
+
+      return ioctl(fd, TUNSETQUEUE, (void *)&ifr);
+  }
+
 Universal TUN/TAP device driver Frequently Asked Question.
    
 1. What platforms are supported by TUN/TAP driver ?
index 3035d00..425c51d 100644 (file)
@@ -1,6 +1,5 @@
-*=============*
-* OPP Library *
-*=============*
+Operating Performance Points (OPP) Library
+==========================================
 
 (C) 2009-2010 Nishanth Menon <nm@ti.com>, Texas Instruments Incorporated
 
@@ -16,15 +15,31 @@ Contents
 
 1. Introduction
 ===============
+1.1 What is an Operating Performance Point (OPP)?
+
 Complex SoCs of today consists of a multiple sub-modules working in conjunction.
 In an operational system executing varied use cases, not all modules in the SoC
 need to function at their highest performing frequency all the time. To
 facilitate this, sub-modules in a SoC are grouped into domains, allowing some
-domains to run at lower voltage and frequency while other domains are loaded
-more. The set of discrete tuples consisting of frequency and voltage pairs that
+domains to run at lower voltage and frequency while other domains run at
+voltage/frequency pairs that are higher.
+
+The set of discrete tuples consisting of frequency and voltage pairs that
 the device will support per domain are called Operating Performance Points or
 OPPs.
 
+As an example:
+Let us consider an MPU device which supports the following:
+{300MHz at minimum voltage of 1V}, {800MHz at minimum voltage of 1.2V},
+{1GHz at minimum voltage of 1.3V}
+
+We can represent these as three OPPs as the following {Hz, uV} tuples:
+{300000000, 1000000}
+{800000000, 1200000}
+{1000000000, 1300000}
+
+1.2 Operating Performance Points Library
+
 OPP library provides a set of helper functions to organize and query the OPP
 information. The library is located in drivers/base/power/opp.c and the header
 is located in include/linux/opp.h. OPP library can be enabled by enabling
index e8a6aa4..6e95356 100644 (file)
@@ -170,5 +170,5 @@ Reminder: sizeof() result is of type size_t.
 Thank you for your cooperation and attention.
 
 
-By Randy Dunlap <rdunlap@xenotime.net> and
+By Randy Dunlap <rdunlap@infradead.org> and
 Andrew Murray <amurray@mpc-data.co.uk>
index 53d6a3c..a372304 100644 (file)
@@ -1873,7 +1873,7 @@ feature:
 
        status\input  |     0      |     1      |    else    |
        --------------+------------+------------+------------+
-       not allocated |(do nothing)| alloc+swap |   EINVAL   |
+       not allocated |(do nothing)| alloc+swap |(do nothing)|
        --------------+------------+------------+------------+
        allocated     |    free    |    swap    |   clear    |
        --------------+------------+------------+------------+
index e95b1e9..50b4d73 100644 (file)
@@ -114,12 +114,6 @@ Maintainers List (try to look for most precise areas first)
 
                -----------------------------------
 
-3C505 NETWORK DRIVER
-M:     Philip Blundell <philb@gnu.org>
-L:     netdev@vger.kernel.org
-S:     Maintained
-F:     drivers/net/ethernet/i825xx/3c505*
-
 3C59X NETWORK DRIVER
 M:     Steffen Klassert <klassert@mathematik.tu-chemnitz.de>
 L:     netdev@vger.kernel.org
@@ -2361,12 +2355,6 @@ W:       http://www.arm.linux.org.uk/
 S:     Maintained
 F:     drivers/video/cyber2000fb.*
 
-CYCLADES 2X SYNC CARD DRIVER
-M:     Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
-W:     http://oops.ghostprotocols.net:81/blog
-S:     Maintained
-F:     drivers/net/wan/cycx*
-
 CYCLADES ASYNC MUX DRIVER
 W:     http://www.cyclades.com/
 S:     Orphan
@@ -3067,12 +3055,6 @@ T:       git git://git.kernel.org/pub/scm/linux/kernel/git/kristoffer/linux-hpc.git
 F:     drivers/video/s1d13xxxfb.c
 F:     include/video/s1d13xxxfb.h
 
-ETHEREXPRESS-16 NETWORK DRIVER
-M:     Philip Blundell <philb@gnu.org>
-L:     netdev@vger.kernel.org
-S:     Maintained
-F:     drivers/net/ethernet/i825xx/eexpress.*
-
 ETHERNET BRIDGE
 M:     Stephen Hemminger <stephen@networkplumber.org>
 L:     bridge@lists.linux-foundation.org
@@ -4023,6 +4005,22 @@ M:       Stanislaw Gruszka <stf_xl@wp.pl>
 S:     Maintained
 F:     drivers/usb/atm/ueagle-atm.c
 
+INA209 HARDWARE MONITOR DRIVER
+M:     Guenter Roeck <linux@roeck-us.net>
+L:     lm-sensors@lm-sensors.org
+S:     Maintained
+F:     Documentation/hwmon/ina209
+F:     Documentation/devicetree/bindings/i2c/ina209.txt
+F:     drivers/hwmon/ina209.c
+
+INA2XX HARDWARE MONITOR DRIVER
+M:     Guenter Roeck <linux@roeck-us.net>
+L:     lm-sensors@lm-sensors.org
+S:     Maintained
+F:     Documentation/hwmon/ina2xx
+F:     drivers/hwmon/ina2xx.c
+F:     include/linux/platform_data/ina2xx.h
+
 INDUSTRY PACK SUBSYSTEM (IPACK)
 M:     Samuel Iglesias Gonsalvez <siglesias@igalia.com>
 M:     Jens Taprogge <jens.taprogge@taprogge.org>
@@ -5116,6 +5114,15 @@ S:       Maintained
 F:     Documentation/hwmon/max6650
 F:     drivers/hwmon/max6650.c
 
+MAX6697 HARDWARE MONITOR DRIVER
+M:     Guenter Roeck <linux@roeck-us.net>
+L:     lm-sensors@lm-sensors.org
+S:     Maintained
+F:     Documentation/hwmon/max6697
+F:     Documentation/devicetree/bindings/i2c/max6697.txt
+F:     drivers/hwmon/max6697.c
+F:     include/linux/platform_data/max6697.h
+
 MAXIRADIO FM RADIO RECEIVER DRIVER
 M:     Hans Verkuil <hverkuil@xs4all.nl>
 L:     linux-media@vger.kernel.org
@@ -6430,6 +6437,8 @@ F:        Documentation/networking/LICENSE.qla3xxx
 F:     drivers/net/ethernet/qlogic/qla3xxx.*
 
 QLOGIC QLCNIC (1/10)Gb ETHERNET DRIVER
+M:     Rajesh Borundia <rajesh.borundia@qlogic.com>
+M:     Shahed Shaikh <shahed.shaikh@qlogic.com>
 M:     Jitendra Kalsaria <jitendra.kalsaria@qlogic.com>
 M:     Sony Chacko <sony.chacko@qlogic.com>
 M:     linux-driver@qlogic.com
index 5bd9f77..22113a7 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 3
 PATCHLEVEL = 9
 SUBLEVEL = 0
-EXTRAVERSION = -rc1
+EXTRAVERSION = -rc3
 NAME = Unicycling Gorilla
 
 # *DOCUMENTATION*
index 5a1779c..1455579 100644 (file)
@@ -319,13 +319,6 @@ config ARCH_WANT_OLD_COMPAT_IPC
        select ARCH_WANT_COMPAT_IPC_PARSE_VERSION
        bool
 
-config HAVE_VIRT_TO_BUS
-       bool
-       help
-         An architecture should select this if it implements the
-         deprecated interface virt_to_bus().  All new architectures
-         should probably not select this.
-
 config HAVE_ARCH_SECCOMP_FILTER
        bool
        help
index 5833aa4..8a33ba0 100644 (file)
@@ -9,7 +9,7 @@ config ALPHA
        select HAVE_PERF_EVENTS
        select HAVE_DMA_ATTRS
        select HAVE_GENERIC_HARDIRQS
-       select HAVE_VIRT_TO_BUS
+       select VIRT_TO_BUS
        select GENERIC_IRQ_PROBE
        select AUTO_IRQ_AFFINITY if SMP
        select GENERIC_IRQ_SHOW
index b06812b..8efb266 100644 (file)
@@ -4,6 +4,7 @@
  * initial bootloader stuff..
  */
 
+#include <asm/pal.h>
 
        .set noreorder
        .globl  __start
index 5b71469..2c3bdce 100644 (file)
@@ -49,7 +49,7 @@ config ARM
        select HAVE_REGS_AND_STACK_ACCESS_API
        select HAVE_SYSCALL_TRACEPOINTS
        select HAVE_UID16
-       select HAVE_VIRT_TO_BUS
+       select VIRT_TO_BUS
        select KTIME_SCALAR
        select PERF_USE_VMALLOC
        select RTC_LIB
@@ -556,7 +556,6 @@ config ARCH_IXP4XX
 config ARCH_DOVE
        bool "Marvell Dove"
        select ARCH_REQUIRE_GPIOLIB
-       select COMMON_CLK_DOVE
        select CPU_V7
        select GENERIC_CLOCKEVENTS
        select MIGHT_HAVE_PCI
@@ -1657,13 +1656,16 @@ config LOCAL_TIMERS
          accounting to be spread across the timer interval, preventing a
          "thundering herd" at every timer tick.
 
+# The GPIO number here must be sorted by descending number. In case of
+# a multiplatform kernel, we just want the highest value required by the
+# selected platforms.
 config ARCH_NR_GPIO
        int
        default 1024 if ARCH_SHMOBILE || ARCH_TEGRA
-       default 355 if ARCH_U8500
-       default 264 if MACH_H4700
        default 512 if SOC_OMAP5
+       default 355 if ARCH_U8500
        default 288 if ARCH_VT8500 || ARCH_SUNXI
+       default 264 if MACH_H4700
        default 0
        help
          Maximum number of GPIOs in the system.
@@ -1887,8 +1889,9 @@ config XEN_DOM0
 
 config XEN
        bool "Xen guest support on ARM (EXPERIMENTAL)"
-       depends on ARM && OF
+       depends on ARM && AEABI && OF
        depends on CPU_V7 && !CPU_V6
+       depends on !GENERIC_ATOMIC64
        help
          Say Y if you want to run Linux in a Virtual Machine on Xen on ARM.
 
index acdddda..ecfcdba 100644 (file)
@@ -492,7 +492,7 @@ config DEBUG_IMX_UART_PORT
                                                DEBUG_IMX31_UART || \
                                                DEBUG_IMX35_UART || \
                                                DEBUG_IMX51_UART || \
-                                               DEBUG_IMX50_IMX53_UART || \
+                                               DEBUG_IMX53_UART || \
                                                DEBUG_IMX6Q_UART
        default 1
        help
index 71768b8..84aa2ca 100644 (file)
@@ -115,4 +115,4 @@ i:
        $(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \
        $(obj)/Image System.map "$(INSTALL_PATH)"
 
-subdir-            := bootp compressed
+subdir-            := bootp compressed dts
index 5cad8a6..afed28e 100644 (file)
@@ -120,7 +120,7 @@ ORIG_CFLAGS := $(KBUILD_CFLAGS)
 KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CFLAGS))
 endif
 
-ccflags-y := -fpic -fno-builtin -I$(obj)
+ccflags-y := -fpic -mno-single-pic-base -fno-builtin -I$(obj)
 asflags-y := -Wa,-march=all -DZIMAGE
 
 # Supply kernel BSS size to the decompressor via a linker symbol.
index f8e4855..070bba4 100644 (file)
                        status = "okay";
                        /* No CD or WP GPIOs */
                };
+
+               usb@d0050000 {
+                       status = "okay";
+               };
+
+               usb@d0051000 {
+                       status = "okay";
+               };
        };
 };
index 6f1acc7..5b70820 100644 (file)
@@ -31,7 +31,6 @@
        mpic: interrupt-controller@d0020000 {
              compatible = "marvell,mpic";
              #interrupt-cells = <1>;
-             #address-cells = <1>;
              #size-cells = <1>;
              interrupt-controller;
        };
@@ -54,7 +53,7 @@
                                reg = <0xd0012000 0x100>;
                                reg-shift = <2>;
                                interrupts = <41>;
-                               reg-io-width = <4>;
+                               reg-io-width = <1>;
                                status = "disabled";
                };
                serial@d0012100 {
@@ -62,7 +61,7 @@
                                reg = <0xd0012100 0x100>;
                                reg-shift = <2>;
                                interrupts = <42>;
-                               reg-io-width = <4>;
+                               reg-io-width = <1>;
                                status = "disabled";
                };
 
index 1443949..ca00d83 100644 (file)
@@ -46,7 +46,7 @@
                                reg = <0xd0012200 0x100>;
                                reg-shift = <2>;
                                interrupts = <43>;
-                               reg-io-width = <4>;
+                               reg-io-width = <1>;
                                status = "disabled";
                };
                serial@d0012300 {
@@ -54,7 +54,7 @@
                                reg = <0xd0012300 0x100>;
                                reg-shift = <2>;
                                interrupts = <44>;
-                               reg-io-width = <4>;
+                               reg-io-width = <1>;
                                status = "disabled";
                };
 
index 4bf2a87..7e0481e 100644 (file)
                        compatible = "fixed-clock";
                        reg = <1>;
                        #clock-cells = <0>;
-                       clock-frequency = <150000000>;
+                       clock-frequency = <250000000>;
                };
        };
 };
index 69140ba..9de9309 100644 (file)
                                };
                        };
 
-                       ab8500@5 {
+                       ab8500 {
                                compatible = "stericsson,ab8500";
-                               reg = <5>; /* mailbox 5 is i2c */
                                interrupt-parent = <&intc>;
                                interrupts = <0 40 0x4>;
                                interrupt-controller;
index 67dbe20..f7509ca 100644 (file)
                        status = "disabled";
                };
 
+               rtc@d8500 {
+                       compatible = "marvell,orion-rtc";
+                       reg = <0xd8500 0x20>;
+               };
+
                crypto: crypto@30000 {
                        compatible = "marvell,orion-crypto";
                        reg = <0x30000 0x10000>,
index 592fb9d..379128e 100644 (file)
                                };
                        };
 
-                       ab8500@5 {
+                       ab8500 {
                                ab8500-regulators {
                                        ab8500_ldo_aux1_reg: ab8500_ldo_aux1 {
                                                regulator-name = "V-DISPLAY";
index 55f4191..2b587a7 100644 (file)
                                };
                        };
 
-                       ab8500@5 {
+                       ab8500 {
                                ab8500-regulators {
                                        ab8500_ldo_aux1_reg: ab8500_ldo_aux1 {
                                                regulator-name = "V-DISPLAY";
index e54fffd..468c0a1 100644 (file)
                        fsl,pins = <689 0x10000         /* DISP1_DRDY   */
                                    482 0x10000         /* DISP1_HSYNC  */
                                    489 0x10000         /* DISP1_VSYNC  */
-                                   684 0x10000         /* DISP1_DAT_0  */
                                    515 0x10000         /* DISP1_DAT_22 */
                                    523 0x10000         /* DISP1_DAT_23 */
-                                   543 0x10000         /* DISP1_DAT_21 */
+                                   545 0x10000         /* DISP1_DAT_21 */
                                    553 0x10000         /* DISP1_DAT_20 */
                                    558 0x10000         /* DISP1_DAT_19 */
                                    564 0x10000         /* DISP1_DAT_18 */
index 5bb0bf3..c9c44b2 100644 (file)
 
        ocp@f1000000 {
                serial@12000 {
-                       clock-frequency = <166666667>;
                        status = "okay";
                };
 
                serial@12100 {
-                       clock-frequency = <166666667>;
                        status = "okay";
                };
        };
index d430713..e4e4930 100644 (file)
@@ -50,7 +50,6 @@
                        };
                };
                serial@12000 {
-                       clock-frequency = <200000000>;
                        status = "okay";
                };
        };
index 2e3dd34..0196cf6 100644 (file)
@@ -37,7 +37,6 @@
                        };
                };
                serial@12000 {
-                       clock-frequency = <200000000>;
                        status = "ok";
                };
 
index ef2d8c7..289e51d 100644 (file)
@@ -38,7 +38,6 @@
                        };
                };
                serial@12000 {
-                       clock-frequency = <200000000>;
                        status = "ok";
                };
 
index 1b133e0..bd83b8f 100644 (file)
@@ -73,7 +73,6 @@
                        };
                };
                serial@12000 {
-                       clock-frequency = <200000000>;
                        status = "ok";
                };
 
index 71902da..5335b1a 100644 (file)
@@ -51,7 +51,6 @@
                        };
                };
                serial@12000 {
-                       clock-frequency = <200000000>;
                        status = "okay";
                };
 
index 504f16b..12ccf74 100644 (file)
@@ -78,7 +78,6 @@
                        };
                };
                serial@12000 {
-                       clock-frequency = <200000000>;
                        status = "ok";
                };
 
index 6cae459..93c3afb 100644 (file)
                };
 
                serial@12000 {
-                       clock-frequency = <200000000>;
                        status = "ok";
                };
 
index 8db3123..5bbd054 100644 (file)
@@ -34,7 +34,6 @@
                };
 
                serial@12000 {
-                       clock-frequency = <200000000>;
                        status = "ok";
                };
 
index 9510c9e..9f55d95 100644 (file)
@@ -13,7 +13,6 @@
 
        ocp@f1000000 {
                serial@12000 {
-                       clock-frequency = <166666667>;
                        status = "okay";
                };
        };
index 739019c..5c84c11 100644 (file)
@@ -13,7 +13,6 @@
 
        ocp@f1000000 {
                serial@12000 {
-                       clock-frequency = <200000000>;
                        status = "okay";
                };
        };
index 662dfd8..7588241 100644 (file)
@@ -90,7 +90,6 @@
                 };
 
                 serial@12000 {
-                        clock-frequency = <200000000>;
                         status = "ok";
                 };
 
index e8e7ece..6affd92 100644 (file)
@@ -23,7 +23,6 @@
                };
 
                serial@12000 {
-                       clock-frequency = <166666667>;
                        status = "okay";
                };
 
index 3a178cf..a7412b9 100644 (file)
                };
 
                serial@12000 {
-                       clock-frequency = <200000000>;
                        status = "ok";
                };
 
index ede7fe0..d27f724 100644 (file)
 
        ocp@f1000000 {
                serial@12000 {
-                       clock-frequency = <200000000>;
                        status = "ok";
                };
 
                serial@12100 {
-                       clock-frequency = <200000000>;
                        status = "ok";
                };
 
index 842ff95..66eb45b 100644 (file)
                };
 
                serial@12000 {
-                       clock-frequency = <200000000>;
                        status = "ok";
                };
 
index 2c738d9..fada7e6 100644 (file)
@@ -38,6 +38,7 @@
                        interrupt-controller;
                        #interrupt-cells = <2>;
                        interrupts = <35>, <36>, <37>, <38>;
+                       clocks = <&gate_clk 7>;
                };
 
                gpio1: gpio@10140 {
@@ -49,6 +50,7 @@
                        interrupt-controller;
                        #interrupt-cells = <2>;
                        interrupts = <39>, <40>, <41>;
+                       clocks = <&gate_clk 7>;
                };
 
                serial@12000 {
@@ -57,7 +59,6 @@
                        reg-shift = <2>;
                        interrupts = <33>;
                        clocks = <&gate_clk 7>;
-                       /* set clock-frequency in board dts */
                        status = "disabled";
                };
 
@@ -67,7 +68,6 @@
                        reg-shift = <2>;
                        interrupts = <34>;
                        clocks = <&gate_clk 7>;
-                       /* set clock-frequency in board dts */
                        status = "disabled";
                };
 
@@ -75,6 +75,7 @@
                        compatible = "marvell,kirkwood-rtc", "marvell,orion-rtc";
                        reg = <0x10300 0x20>;
                        interrupts = <53>;
+                       clocks = <&gate_clk 7>;
                };
 
                spi@10600 {
index 5a3a58b..0077fc8 100644 (file)
@@ -11,7 +11,7 @@
 
 / {
        model = "LaCie Ethernet Disk mini V2";
-       compatible = "lacie,ethernet-disk-mini-v2", "marvell-orion5x-88f5182", "marvell,orion5x";
+       compatible = "lacie,ethernet-disk-mini-v2", "marvell,orion5x-88f5182", "marvell,orion5x";
 
        memory {
                reg = <0x00000000 0x4000000>; /* 64 MB */
index 27f31a5..d3ec32f 100644 (file)
                                };
                        };
 
-                       ab8500@5 {
+                       ab8500 {
                                ab8500-regulators {
                                        ab8500_ldo_aux1_reg: ab8500_ldo_aux1 {
                                                regulator-name = "V-DISPLAY";
index 936d230..7e8769b 100644 (file)
@@ -75,6 +75,9 @@
                                compatible = "arm,pl330", "arm,primecell";
                                reg = <0xffe01000 0x1000>;
                                interrupts = <0 180 4>;
+                               #dma-cells = <1>;
+                               #dma-channels = <8>;
+                               #dma-requests = <32>;
                        };
                };
 
index 9a42893..48d00a0 100644 (file)
                compatible = "arm,cortex-a9-twd-timer";
                reg = <0x50040600 0x20>;
                interrupts = <1 13 0x304>;
+               clocks = <&tegra_car 132>;
        };
 
        intc: interrupt-controller {
index 767803e..9d87a3f 100644 (file)
                compatible = "arm,cortex-a9-twd-timer";
                reg = <0x50040600 0x20>;
                interrupts = <1 13 0xf04>;
+               clocks = <&tegra_car 214>;
        };
 
        intc: interrupt-controller {
index fbbc5bb..6a99e30 100644 (file)
@@ -116,6 +116,7 @@ CONFIG_SND_SOC=y
 CONFIG_SND_MXS_SOC=y
 CONFIG_SND_SOC_MXS_SGTL5000=y
 CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_CHIPIDEA=y
 CONFIG_USB_CHIPIDEA_HOST=y
 CONFIG_USB_STORAGE=y
index b16bae2..bd07864 100644 (file)
@@ -126,6 +126,8 @@ CONFIG_INPUT_MISC=y
 CONFIG_INPUT_TWL4030_PWRBUTTON=y
 CONFIG_VT_HW_CONSOLE_BINDING=y
 # CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_NR_UARTS=32
 CONFIG_SERIAL_8250_EXTENDED=y
 CONFIG_SERIAL_8250_MANY_PORTS=y
index 9f77e78..e3d5554 100644 (file)
@@ -5,15 +5,15 @@
 
 typedef struct {
 #ifdef CONFIG_CPU_HAS_ASID
-       u64 id;
+       atomic64_t      id;
 #endif
-       unsigned int vmalloc_seq;
+       unsigned int    vmalloc_seq;
 } mm_context_t;
 
 #ifdef CONFIG_CPU_HAS_ASID
 #define ASID_BITS      8
 #define ASID_MASK      ((~0ULL) << ASID_BITS)
-#define ASID(mm)       ((mm)->context.id & ~ASID_MASK)
+#define ASID(mm)       ((mm)->context.id.counter & ~ASID_MASK)
 #else
 #define ASID(mm)       (0)
 #endif
@@ -26,7 +26,7 @@ typedef struct {
  *  modified for 2.6 by Hyok S. Choi <hyok.choi@samsung.com>
  */
 typedef struct {
-       unsigned long           end_brk;
+       unsigned long   end_brk;
 } mm_context_t;
 
 #endif
index e1f644b..863a661 100644 (file)
@@ -25,7 +25,7 @@ void __check_vmalloc_seq(struct mm_struct *mm);
 #ifdef CONFIG_CPU_HAS_ASID
 
 void check_and_switch_context(struct mm_struct *mm, struct task_struct *tsk);
-#define init_new_context(tsk,mm)       ({ mm->context.id = 0; })
+#define init_new_context(tsk,mm)       ({ atomic64_set(&mm->context.id, 0); 0; })
 
 #else  /* !CONFIG_CPU_HAS_ASID */
 
index 6e924d3..4db8c88 100644 (file)
 #define TLB_V6_D_ASID  (1 << 17)
 #define TLB_V6_I_ASID  (1 << 18)
 
+#define TLB_V6_BP      (1 << 19)
+
 /* Unified Inner Shareable TLB operations (ARMv7 MP extensions) */
-#define TLB_V7_UIS_PAGE        (1 << 19)
-#define TLB_V7_UIS_FULL (1 << 20)
-#define TLB_V7_UIS_ASID (1 << 21)
+#define TLB_V7_UIS_PAGE        (1 << 20)
+#define TLB_V7_UIS_FULL (1 << 21)
+#define TLB_V7_UIS_ASID (1 << 22)
+#define TLB_V7_UIS_BP  (1 << 23)
 
 #define TLB_BARRIER    (1 << 28)
 #define TLB_L2CLEAN_FR (1 << 29)               /* Feroceon */
 #define v6wbi_tlb_flags (TLB_WB | TLB_DCLEAN | TLB_BARRIER | \
                         TLB_V6_I_FULL | TLB_V6_D_FULL | \
                         TLB_V6_I_PAGE | TLB_V6_D_PAGE | \
-                        TLB_V6_I_ASID | TLB_V6_D_ASID)
+                        TLB_V6_I_ASID | TLB_V6_D_ASID | \
+                        TLB_V6_BP)
 
 #ifdef CONFIG_CPU_TLB_V6
 # define v6wbi_possible_flags  v6wbi_tlb_flags
 #endif
 
 #define v7wbi_tlb_flags_smp    (TLB_WB | TLB_DCLEAN | TLB_BARRIER | \
-                        TLB_V7_UIS_FULL | TLB_V7_UIS_PAGE | TLB_V7_UIS_ASID)
+                                TLB_V7_UIS_FULL | TLB_V7_UIS_PAGE | \
+                                TLB_V7_UIS_ASID | TLB_V7_UIS_BP)
 #define v7wbi_tlb_flags_up     (TLB_WB | TLB_DCLEAN | TLB_BARRIER | \
-                        TLB_V6_U_FULL | TLB_V6_U_PAGE | TLB_V6_U_ASID)
+                                TLB_V6_U_FULL | TLB_V6_U_PAGE | \
+                                TLB_V6_U_ASID | TLB_V6_BP)
 
 #ifdef CONFIG_CPU_TLB_V7
 
@@ -430,6 +436,20 @@ static inline void local_flush_tlb_kernel_page(unsigned long kaddr)
        }
 }
 
+static inline void local_flush_bp_all(void)
+{
+       const int zero = 0;
+       const unsigned int __tlb_flag = __cpu_tlb_flags;
+
+       if (tlb_flag(TLB_V7_UIS_BP))
+               asm("mcr p15, 0, %0, c7, c1, 6" : : "r" (zero));
+       else if (tlb_flag(TLB_V6_BP))
+               asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero));
+
+       if (tlb_flag(TLB_BARRIER))
+               isb();
+}
+
 /*
  *     flush_pmd_entry
  *
@@ -480,6 +500,7 @@ static inline void clean_pmd_entry(void *pmd)
 #define flush_tlb_kernel_page  local_flush_tlb_kernel_page
 #define flush_tlb_range                local_flush_tlb_range
 #define flush_tlb_kernel_range local_flush_tlb_kernel_range
+#define flush_bp_all           local_flush_bp_all
 #else
 extern void flush_tlb_all(void);
 extern void flush_tlb_mm(struct mm_struct *mm);
@@ -487,6 +508,7 @@ extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr);
 extern void flush_tlb_kernel_page(unsigned long kaddr);
 extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned long end);
 extern void flush_tlb_kernel_range(unsigned long start, unsigned long end);
+extern void flush_bp_all(void);
 #endif
 
 /*
index 5c27696..8b1f37b 100644 (file)
@@ -2,6 +2,7 @@
 #define _ASM_ARM_XEN_EVENTS_H
 
 #include <asm/ptrace.h>
+#include <asm/atomic.h>
 
 enum ipi_vector {
        XEN_PLACEHOLDER_VECTOR,
@@ -15,26 +16,8 @@ static inline int xen_irqs_disabled(struct pt_regs *regs)
        return raw_irqs_disabled_flags(regs->ARM_cpsr);
 }
 
-/*
- * We cannot use xchg because it does not support 8-byte
- * values. However it is safe to use {ldr,dtd}exd directly because all
- * platforms which Xen can run on support those instructions.
- */
-static inline xen_ulong_t xchg_xen_ulong(xen_ulong_t *ptr, xen_ulong_t val)
-{
-       xen_ulong_t oldval;
-       unsigned int tmp;
-
-       wmb();
-       asm volatile("@ xchg_xen_ulong\n"
-               "1:     ldrexd  %0, %H0, [%3]\n"
-               "       strexd  %1, %2, %H2, [%3]\n"
-               "       teq     %1, #0\n"
-               "       bne     1b"
-               : "=&r" (oldval), "=&r" (tmp)
-               : "r" (val), "r" (ptr)
-               : "memory", "cc");
-       return oldval;
-}
+#define xchg_xen_ulong(ptr, val) atomic64_xchg(container_of((ptr),     \
+                                                           atomic64_t, \
+                                                           counter), (val))
 
 #endif /* _ASM_ARM_XEN_EVENTS_H */
index 4da7cde..af33b44 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 */
+#define __NR_kcmp                      (__NR_SYSCALL_BASE+378)
 #define __NR_finit_module              (__NR_SYSCALL_BASE+379)
 
 /*
index 5ce738b..923eec7 100644 (file)
@@ -110,7 +110,7 @@ int main(void)
   BLANK();
 #endif
 #ifdef CONFIG_CPU_HAS_ASID
-  DEFINE(MM_CONTEXT_ID,                offsetof(struct mm_struct, context.id));
+  DEFINE(MM_CONTEXT_ID,                offsetof(struct mm_struct, context.id.counter));
   BLANK();
 #endif
   DEFINE(VMA_VM_MM,            offsetof(struct vm_area_struct, vm_mm));
index 0cc5761..c6ca7e3 100644 (file)
 /* 375 */      CALL(sys_setns)
                CALL(sys_process_vm_readv)
                CALL(sys_process_vm_writev)
-               CALL(sys_ni_syscall)    /* reserved for sys_kcmp */
+               CALL(sys_kcmp)
                CALL(sys_finit_module)
 #ifndef syscalls_counted
 .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
index 486a15a..e0eb9a1 100644 (file)
@@ -184,13 +184,22 @@ __create_page_tables:
        orr     r3, r3, #3                      @ PGD block type
        mov     r6, #4                          @ PTRS_PER_PGD
        mov     r7, #1 << (55 - 32)             @ L_PGD_SWAPPER
-1:     str     r3, [r0], #4                    @ set bottom PGD entry bits
+1:
+#ifdef CONFIG_CPU_ENDIAN_BE8
        str     r7, [r0], #4                    @ set top PGD entry bits
+       str     r3, [r0], #4                    @ set bottom PGD entry bits
+#else
+       str     r3, [r0], #4                    @ set bottom PGD entry bits
+       str     r7, [r0], #4                    @ set top PGD entry bits
+#endif
        add     r3, r3, #0x1000                 @ next PMD table
        subs    r6, r6, #1
        bne     1b
 
        add     r4, r4, #0x1000                 @ point to the PMD tables
+#ifdef CONFIG_CPU_ENDIAN_BE8
+       add     r4, r4, #4                      @ we only write the bottom word
+#endif
 #endif
 
        ldr     r7, [r10, #PROCINFO_MM_MMUFLAGS] @ mm_mmuflags
@@ -258,6 +267,11 @@ __create_page_tables:
        addne   r6, r6, #1 << SECTION_SHIFT
        strne   r6, [r3]
 
+#if defined(CONFIG_LPAE) && defined(CONFIG_CPU_ENDIAN_BE8)
+       sub     r4, r4, #4                      @ Fixup page table pointer
+                                               @ for 64-bit descriptors
+#endif
+
 #ifdef CONFIG_DEBUG_LL
 #if !defined(CONFIG_DEBUG_ICEDCC) && !defined(CONFIG_DEBUG_SEMIHOSTING)
        /*
@@ -276,13 +290,17 @@ __create_page_tables:
        orr     r3, r7, r3, lsl #SECTION_SHIFT
 #ifdef CONFIG_ARM_LPAE
        mov     r7, #1 << (54 - 32)             @ XN
+#ifdef CONFIG_CPU_ENDIAN_BE8
+       str     r7, [r0], #4
+       str     r3, [r0], #4
 #else
-       orr     r3, r3, #PMD_SECT_XN
-#endif
        str     r3, [r0], #4
-#ifdef CONFIG_ARM_LPAE
        str     r7, [r0], #4
 #endif
+#else
+       orr     r3, r3, #PMD_SECT_XN
+       str     r3, [r0], #4
+#endif
 
 #else /* CONFIG_DEBUG_ICEDCC || CONFIG_DEBUG_SEMIHOSTING */
        /* we don't need any serial debugging mappings */
index 5eae53e..96093b7 100644 (file)
@@ -1023,7 +1023,7 @@ out_mdbgen:
 static int __cpuinit dbg_reset_notify(struct notifier_block *self,
                                      unsigned long action, void *cpu)
 {
-       if (action == CPU_ONLINE)
+       if ((action & ~CPU_TASKS_FROZEN) == CPU_ONLINE)
                smp_call_function_single((int)cpu, reset_ctrl_regs, NULL, 1);
 
        return NOTIFY_OK;
index 31e0eb3..146157d 100644 (file)
@@ -400,7 +400,7 @@ __hw_perf_event_init(struct perf_event *event)
        }
 
        if (event->group_leader != event) {
-               if (validate_group(event) != 0);
+               if (validate_group(event) != 0)
                        return -EINVAL;
        }
 
@@ -484,7 +484,7 @@ const struct dev_pm_ops armpmu_dev_pm_ops = {
        SET_RUNTIME_PM_OPS(armpmu_runtime_suspend, armpmu_runtime_resume, NULL)
 };
 
-static void __init armpmu_init(struct arm_pmu *armpmu)
+static void armpmu_init(struct arm_pmu *armpmu)
 {
        atomic_set(&armpmu->active_events, 0);
        mutex_init(&armpmu->reserve_mutex);
index 8c79a9e..039cffb 100644 (file)
@@ -774,7 +774,7 @@ static const unsigned armv7_a7_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
 /*
  * PMXEVTYPER: Event selection reg
  */
-#define        ARMV7_EVTYPE_MASK       0xc00000ff      /* Mask for writable bits */
+#define        ARMV7_EVTYPE_MASK       0xc80000ff      /* Mask for writable bits */
 #define        ARMV7_EVTYPE_EVENT      0xff            /* Mask for EVENT bits */
 
 /*
index 1bdfd87..31644f1 100644 (file)
@@ -285,6 +285,7 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
         * switch away from it before attempting any exclusive accesses.
         */
        cpu_switch_mm(mm->pgd, mm);
+       local_flush_bp_all();
        enter_lazy_tlb(mm, current);
        local_flush_tlb_all();
 
index 02c5d2c..bd03005 100644 (file)
@@ -64,6 +64,11 @@ static inline void ipi_flush_tlb_kernel_range(void *arg)
        local_flush_tlb_kernel_range(ta->ta_start, ta->ta_end);
 }
 
+static inline void ipi_flush_bp_all(void *ignored)
+{
+       local_flush_bp_all();
+}
+
 void flush_tlb_all(void)
 {
        if (tlb_ops_need_broadcast())
@@ -127,3 +132,10 @@ void flush_tlb_kernel_range(unsigned long start, unsigned long end)
                local_flush_tlb_kernel_range(start, end);
 }
 
+void flush_bp_all(void)
+{
+       if (tlb_ops_need_broadcast())
+               on_each_cpu(ipi_flush_bp_all, NULL, 1);
+       else
+               local_flush_bp_all();
+}
index c092115..3f25650 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/of_irq.h>
 #include <linux/of_address.h>
 
+#include <asm/smp_plat.h>
 #include <asm/smp_twd.h>
 #include <asm/localtimer.h>
 
@@ -373,6 +374,9 @@ void __init twd_local_timer_of_register(void)
        struct device_node *np;
        int err;
 
+       if (!is_smp() || !setup_max_cpus)
+               return;
+
        np = of_find_matching_node(NULL, twd_of_match);
        if (!np)
                return;
index 358bca3..c59c97e 100644 (file)
@@ -68,6 +68,7 @@ int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
        ret = __cpu_suspend(arg, fn);
        if (ret == 0) {
                cpu_switch_mm(mm->pgd, mm);
+               local_flush_bp_all();
                local_flush_tlb_all();
        }
 
index 650d592..d912e73 100644 (file)
@@ -19,9 +19,9 @@
 1:     subs    r2, r2, #4              @ 1 do we have enough
        blt     5f                      @ 1 bytes to align with?
        cmp     r3, #2                  @ 1
-       strltb  r1, [r0], #1            @ 1
-       strleb  r1, [r0], #1            @ 1
-       strb    r1, [r0], #1            @ 1
+       strltb  r1, [ip], #1            @ 1
+       strleb  r1, [ip], #1            @ 1
+       strb    r1, [ip], #1            @ 1
        add     r2, r2, r3              @ 1 (r2 = r2 - (4 - r3))
 /*
  * The pointer is now aligned and the length is adjusted.  Try doing the
  */
 
 ENTRY(memset)
-       ands    r3, r0, #3              @ 1 unaligned?
+/*
+ * Preserve the contents of r0 for the return value.
+ */
+       mov     ip, r0
+       ands    r3, ip, #3              @ 1 unaligned?
        bne     1b                      @ 1
 /*
- * we know that the pointer in r0 is aligned to a word boundary.
+ * we know that the pointer in ip is aligned to a word boundary.
  */
        orr     r1, r1, r1, lsl #8
        orr     r1, r1, r1, lsl #16
@@ -43,29 +47,28 @@ ENTRY(memset)
 #if ! CALGN(1)+0
 
 /*
- * We need an extra register for this loop - save the return address and
- * use the LR
+ * We need 2 extra registers for this loop - use r8 and the LR
  */
-       str     lr, [sp, #-4]!
-       mov     ip, r1
+       stmfd   sp!, {r8, lr}
+       mov     r8, r1
        mov     lr, r1
 
 2:     subs    r2, r2, #64
-       stmgeia r0!, {r1, r3, ip, lr}   @ 64 bytes at a time.
-       stmgeia r0!, {r1, r3, ip, lr}
-       stmgeia r0!, {r1, r3, ip, lr}
-       stmgeia r0!, {r1, r3, ip, lr}
+       stmgeia ip!, {r1, r3, r8, lr}   @ 64 bytes at a time.
+       stmgeia ip!, {r1, r3, r8, lr}
+       stmgeia ip!, {r1, r3, r8, lr}
+       stmgeia ip!, {r1, r3, r8, lr}
        bgt     2b
-       ldmeqfd sp!, {pc}               @ Now <64 bytes to go.
+       ldmeqfd sp!, {r8, pc}           @ Now <64 bytes to go.
 /*
  * No need to correct the count; we're only testing bits from now on
  */
        tst     r2, #32
-       stmneia r0!, {r1, r3, ip, lr}
-       stmneia r0!, {r1, r3, ip, lr}
+       stmneia ip!, {r1, r3, r8, lr}
+       stmneia ip!, {r1, r3, r8, lr}
        tst     r2, #16
-       stmneia r0!, {r1, r3, ip, lr}
-       ldr     lr, [sp], #4
+       stmneia ip!, {r1, r3, r8, lr}
+       ldmfd   sp!, {r8, lr}
 
 #else
 
@@ -74,54 +77,54 @@ ENTRY(memset)
  * whole cache lines at once.
  */
 
-       stmfd   sp!, {r4-r7, lr}
+       stmfd   sp!, {r4-r8, lr}
        mov     r4, r1
        mov     r5, r1
        mov     r6, r1
        mov     r7, r1
-       mov     ip, r1
+       mov     r8, r1
        mov     lr, r1
 
        cmp     r2, #96
-       tstgt   r0, #31
+       tstgt   ip, #31
        ble     3f
 
-       and     ip, r0, #31
-       rsb     ip, ip, #32
-       sub     r2, r2, ip
-       movs    ip, ip, lsl #(32 - 4)
-       stmcsia r0!, {r4, r5, r6, r7}
-       stmmiia r0!, {r4, r5}
-       tst     ip, #(1 << 30)
-       mov     ip, r1
-       strne   r1, [r0], #4
+       and     r8, ip, #31
+       rsb     r8, r8, #32
+       sub     r2, r2, r8
+       movs    r8, r8, lsl #(32 - 4)
+       stmcsia ip!, {r4, r5, r6, r7}
+       stmmiia ip!, {r4, r5}
+       tst     r8, #(1 << 30)
+       mov     r8, r1
+       strne   r1, [ip], #4
 
 3:     subs    r2, r2, #64
-       stmgeia r0!, {r1, r3-r7, ip, lr}
-       stmgeia r0!, {r1, r3-r7, ip, lr}
+       stmgeia ip!, {r1, r3-r8, lr}
+       stmgeia ip!, {r1, r3-r8, lr}
        bgt     3b
-       ldmeqfd sp!, {r4-r7, pc}
+       ldmeqfd sp!, {r4-r8, pc}
 
        tst     r2, #32
-       stmneia r0!, {r1, r3-r7, ip, lr}
+       stmneia ip!, {r1, r3-r8, lr}
        tst     r2, #16
-       stmneia r0!, {r4-r7}
-       ldmfd   sp!, {r4-r7, lr}
+       stmneia ip!, {r4-r7}
+       ldmfd   sp!, {r4-r8, lr}
 
 #endif
 
 4:     tst     r2, #8
-       stmneia r0!, {r1, r3}
+       stmneia ip!, {r1, r3}
        tst     r2, #4
-       strne   r1, [r0], #4
+       strne   r1, [ip], #4
 /*
  * When we get here, we've got less than 4 bytes to zero.  We
  * may have an unaligned pointer as well.
  */
 5:     tst     r2, #2
-       strneb  r1, [r0], #1
-       strneb  r1, [r0], #1
+       strneb  r1, [ip], #1
+       strneb  r1, [ip], #1
        tst     r2, #1
-       strneb  r1, [r0], #1
+       strneb  r1, [ip], #1
        mov     pc, lr
 ENDPROC(memset)
index 2ea7059..c20a870 100644 (file)
@@ -176,6 +176,7 @@ static struct w1_gpio_platform_data w1_gpio_pdata = {
        /* If you choose to use a pin other than PB16 it needs to be 3.3V */
        .pin            = AT91_PIN_PB16,
        .is_open_drain  = 1,
+       .ext_pullup_enable_pin  = -EINVAL,
 };
 
 static struct platform_device w1_device = {
index a033b8d..869cbec 100644 (file)
@@ -188,6 +188,7 @@ static struct spi_board_info portuxg20_spi_devices[] = {
 static struct w1_gpio_platform_data w1_gpio_pdata = {
        .pin            = AT91_PIN_PA29,
        .is_open_drain  = 1,
+       .ext_pullup_enable_pin  = -EINVAL,
 };
 
 static struct platform_device w1_device = {
index 7b025ee..2f9ff93 100644 (file)
@@ -172,7 +172,7 @@ static struct clk *clk[clk_max];
 static struct clk_onecell_data clk_data;
 
 static enum mx6q_clks const clks_init_on[] __initconst = {
-       mmdc_ch0_axi, rom,
+       mmdc_ch0_axi, rom, pll1_sys,
 };
 
 static struct clk_div_table clk_enet_ref_table[] = {
index 921fc15..a58c8b0 100644 (file)
@@ -26,16 +26,16 @@ ENDPROC(v7_secondary_startup)
 
 #ifdef CONFIG_PM
 /*
- * The following code is located into the .data section.  This is to
- * allow phys_l2x0_saved_regs to be accessed with a relative load
- * as we are running on physical address here.
+ * The following code must assume it is running from physical address
+ * where absolute virtual addresses to the data section have to be
+ * turned into relative ones.
  */
-       .data
-       .align
 
 #ifdef CONFIG_CACHE_L2X0
        .macro  pl310_resume
-       ldr     r2, phys_l2x0_saved_regs
+       adr     r0, l2x0_saved_regs_offset
+       ldr     r2, [r0]
+       add     r2, r2, r0
        ldr     r0, [r2, #L2X0_R_PHY_BASE]      @ get physical base of l2x0
        ldr     r1, [r2, #L2X0_R_AUX_CTRL]      @ get aux_ctrl value
        str     r1, [r0, #L2X0_AUX_CTRL]        @ restore aux_ctrl
@@ -43,9 +43,9 @@ ENDPROC(v7_secondary_startup)
        str     r1, [r0, #L2X0_CTRL]            @ re-enable L2
        .endm
 
-       .globl  phys_l2x0_saved_regs
-phys_l2x0_saved_regs:
-        .long   0
+l2x0_saved_regs_offset:
+       .word   l2x0_saved_regs - .
+
 #else
        .macro  pl310_resume
        .endm
index ee42d20..5faba7a 100644 (file)
@@ -22,8 +22,6 @@
 #include "common.h"
 #include "hardware.h"
 
-extern unsigned long phys_l2x0_saved_regs;
-
 static int imx6q_suspend_finish(unsigned long val)
 {
        cpu_do_idle();
@@ -57,18 +55,5 @@ static const struct platform_suspend_ops imx6q_pm_ops = {
 
 void __init imx6q_pm_init(void)
 {
-       /*
-        * The l2x0 core code provides an infrastucture to save and restore
-        * l2x0 registers across suspend/resume cycle.  But because imx6q
-        * retains L2 content during suspend and needs to resume L2 before
-        * MMU is enabled, it can only utilize register saving support and
-        * have to take care of restoring on its own.  So we save physical
-        * address of the data structure used by l2x0 core to save registers,
-        * and later restore the necessary ones in imx6q resume entry.
-        */
-#ifdef CONFIG_CACHE_L2X0
-       phys_l2x0_saved_regs = __pa(&l2x0_saved_regs);
-#endif
-
        suspend_set_ops(&imx6q_pm_ops);
 }
index d42730a..d599e35 100644 (file)
@@ -163,6 +163,7 @@ static struct platform_device vulcan_max6369 = {
 
 static struct w1_gpio_platform_data vulcan_w1_gpio_pdata = {
        .pin                    = 14,
+       .ext_pullup_enable_pin  = -EINVAL,
 };
 
 static struct platform_device vulcan_w1_gpio = {
index 2e73e9d..d367aa6 100644 (file)
@@ -41,16 +41,12 @@ static void __init kirkwood_legacy_clk_init(void)
 
        struct device_node *np = of_find_compatible_node(
                NULL, NULL, "marvell,kirkwood-gating-clock");
-
        struct of_phandle_args clkspec;
+       struct clk *clk;
 
        clkspec.np = np;
        clkspec.args_count = 1;
 
-       clkspec.args[0] = CGC_BIT_GE0;
-       orion_clkdev_add(NULL, "mv643xx_eth_port.0",
-                        of_clk_get_from_provider(&clkspec));
-
        clkspec.args[0] = CGC_BIT_PEX0;
        orion_clkdev_add("0", "pcie",
                         of_clk_get_from_provider(&clkspec));
@@ -59,9 +55,24 @@ static void __init kirkwood_legacy_clk_init(void)
        orion_clkdev_add("1", "pcie",
                         of_clk_get_from_provider(&clkspec));
 
-       clkspec.args[0] = CGC_BIT_GE1;
-       orion_clkdev_add(NULL, "mv643xx_eth_port.1",
+       clkspec.args[0] = CGC_BIT_SDIO;
+       orion_clkdev_add(NULL, "mvsdio",
                         of_clk_get_from_provider(&clkspec));
+
+       /*
+        * The ethernet interfaces forget the MAC address assigned by
+        * u-boot if the clocks are turned off. Until proper DT support
+        * is available we always enable them for now.
+        */
+       clkspec.args[0] = CGC_BIT_GE0;
+       clk = of_clk_get_from_provider(&clkspec);
+       orion_clkdev_add(NULL, "mv643xx_eth_port.0", clk);
+       clk_prepare_enable(clk);
+
+       clkspec.args[0] = CGC_BIT_GE1;
+       clk = of_clk_get_from_provider(&clkspec);
+       orion_clkdev_add(NULL, "mv643xx_eth_port.1", clk);
+       clk_prepare_enable(clk);
 }
 
 static void __init kirkwood_of_clk_init(void)
index 8fb23af..e26eeba 100644 (file)
@@ -100,7 +100,7 @@ static struct irq_domain_ops icoll_irq_domain_ops = {
        .xlate = irq_domain_xlate_onecell,
 };
 
-void __init icoll_of_init(struct device_node *np,
+static void __init icoll_of_init(struct device_node *np,
                          struct device_node *interrupt_parent)
 {
        /*
index 0521867..3218f1f 100644 (file)
@@ -402,17 +402,17 @@ static void __init cfa10049_init(void)
 {
        enable_clk_enet_out();
        update_fec_mac_prop(OUI_CRYSTALFONTZ);
+
+       mxsfb_pdata.mode_list = cfa10049_video_modes;
+       mxsfb_pdata.mode_count = ARRAY_SIZE(cfa10049_video_modes);
+       mxsfb_pdata.default_bpp = 32;
+       mxsfb_pdata.ld_intf_width = STMLCDIF_18BIT;
 }
 
 static void __init cfa10037_init(void)
 {
        enable_clk_enet_out();
        update_fec_mac_prop(OUI_CRYSTALFONTZ);
-
-       mxsfb_pdata.mode_list = cfa10049_video_modes;
-       mxsfb_pdata.mode_count = ARRAY_SIZE(cfa10049_video_modes);
-       mxsfb_pdata.default_bpp = 32;
-       mxsfb_pdata.ld_intf_width = STMLCDIF_18BIT;
 }
 
 static void __init apf28_init(void)
index a4294aa..e63b7d8 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <mach/mx23.h>
 #include <mach/mx28.h>
+#include <mach/common.h>
 
 /*
  * Define the MX23 memory map.
index 54add60..1dff467 100644 (file)
@@ -19,6 +19,7 @@
 #include <asm/processor.h>     /* for cpu_relax() */
 
 #include <mach/mxs.h>
+#include <mach/common.h>
 
 #define OCOTP_WORD_OFFSET              0x20
 #define OCOTP_WORD_COUNT               0x20
index 27c2cb7..1504b68 100644 (file)
@@ -168,7 +168,7 @@ void __init netx_init_irq(void)
 {
        int irq;
 
-       vic_init(io_p2v(NETX_PA_VIC), 0, ~0, 0);
+       vic_init(io_p2v(NETX_PA_VIC), NETX_IRQ_VIC_START, ~0, 0);
 
        for (irq = NETX_IRQ_HIF_CHAINED(0); irq <= NETX_IRQ_HIF_LAST; irq++) {
                irq_set_chip_and_handler(irq, &netx_hif_chip,
index 6ce914d..8f74a84 100644 (file)
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#define NETX_IRQ_VIC_START   0
-#define NETX_IRQ_SOFTINT     0
-#define NETX_IRQ_TIMER0      1
-#define NETX_IRQ_TIMER1      2
-#define NETX_IRQ_TIMER2      3
-#define NETX_IRQ_SYSTIME_NS  4
-#define NETX_IRQ_SYSTIME_S   5
-#define NETX_IRQ_GPIO_15     6
-#define NETX_IRQ_WATCHDOG    7
-#define NETX_IRQ_UART0       8
-#define NETX_IRQ_UART1       9
-#define NETX_IRQ_UART2      10
-#define NETX_IRQ_USB        11
-#define NETX_IRQ_SPI        12
-#define NETX_IRQ_I2C        13
-#define NETX_IRQ_LCD        14
-#define NETX_IRQ_HIF        15
-#define NETX_IRQ_GPIO_0_14  16
-#define NETX_IRQ_XPEC0      17
-#define NETX_IRQ_XPEC1      18
-#define NETX_IRQ_XPEC2      19
-#define NETX_IRQ_XPEC3      20
-#define NETX_IRQ_XPEC(no)   (17 + (no))
-#define NETX_IRQ_MSYNC0     21
-#define NETX_IRQ_MSYNC1     22
-#define NETX_IRQ_MSYNC2     23
-#define NETX_IRQ_MSYNC3     24
-#define NETX_IRQ_IRQ_PHY    25
-#define NETX_IRQ_ISO_AREA   26
+#define NETX_IRQ_VIC_START     64
+#define NETX_IRQ_SOFTINT       (NETX_IRQ_VIC_START + 0)
+#define NETX_IRQ_TIMER0                (NETX_IRQ_VIC_START + 1)
+#define NETX_IRQ_TIMER1                (NETX_IRQ_VIC_START + 2)
+#define NETX_IRQ_TIMER2                (NETX_IRQ_VIC_START + 3)
+#define NETX_IRQ_SYSTIME_NS    (NETX_IRQ_VIC_START + 4)
+#define NETX_IRQ_SYSTIME_S     (NETX_IRQ_VIC_START + 5)
+#define NETX_IRQ_GPIO_15       (NETX_IRQ_VIC_START + 6)
+#define NETX_IRQ_WATCHDOG      (NETX_IRQ_VIC_START + 7)
+#define NETX_IRQ_UART0         (NETX_IRQ_VIC_START + 8)
+#define NETX_IRQ_UART1         (NETX_IRQ_VIC_START + 9)
+#define NETX_IRQ_UART2         (NETX_IRQ_VIC_START + 10)
+#define NETX_IRQ_USB           (NETX_IRQ_VIC_START + 11)
+#define NETX_IRQ_SPI           (NETX_IRQ_VIC_START + 12)
+#define NETX_IRQ_I2C           (NETX_IRQ_VIC_START + 13)
+#define NETX_IRQ_LCD           (NETX_IRQ_VIC_START + 14)
+#define NETX_IRQ_HIF           (NETX_IRQ_VIC_START + 15)
+#define NETX_IRQ_GPIO_0_14     (NETX_IRQ_VIC_START + 16)
+#define NETX_IRQ_XPEC0         (NETX_IRQ_VIC_START + 17)
+#define NETX_IRQ_XPEC1         (NETX_IRQ_VIC_START + 18)
+#define NETX_IRQ_XPEC2         (NETX_IRQ_VIC_START + 19)
+#define NETX_IRQ_XPEC3         (NETX_IRQ_VIC_START + 20)
+#define NETX_IRQ_XPEC(no)      (NETX_IRQ_VIC_START + 17 + (no))
+#define NETX_IRQ_MSYNC0                (NETX_IRQ_VIC_START + 21)
+#define NETX_IRQ_MSYNC1                (NETX_IRQ_VIC_START + 22)
+#define NETX_IRQ_MSYNC2                (NETX_IRQ_VIC_START + 23)
+#define NETX_IRQ_MSYNC3                (NETX_IRQ_VIC_START + 24)
+#define NETX_IRQ_IRQ_PHY       (NETX_IRQ_VIC_START + 25)
+#define NETX_IRQ_ISO_AREA      (NETX_IRQ_VIC_START + 26)
 /* int 27 is reserved */
 /* int 28 is reserved */
-#define NETX_IRQ_TIMER3     29
-#define NETX_IRQ_TIMER4     30
+#define NETX_IRQ_TIMER3                (NETX_IRQ_VIC_START + 29)
+#define NETX_IRQ_TIMER4                (NETX_IRQ_VIC_START + 30)
 /* int 31 is reserved */
 
-#define NETX_IRQS 32
+#define NETX_IRQS              (NETX_IRQ_VIC_START + 32)
 
 /* for multiplexed irqs on gpio 0..14 */
 #define NETX_IRQ_GPIO(x) (NETX_IRQS + (x))
index fb18831..14f7e99 100644 (file)
@@ -31,6 +31,8 @@
 
 #include <plat/i2c.h>
 
+#include <mach/irqs.h>
+
 #if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
 void omap7xx_map_io(void);
 #else
index 49ac3df..8111cd9 100644 (file)
@@ -311,9 +311,6 @@ config MACH_OMAP_ZOOM2
        default y
        select OMAP_PACKAGE_CBB
        select REGULATOR_FIXED_VOLTAGE if REGULATOR
-       select SERIAL_8250
-       select SERIAL_8250_CONSOLE
-       select SERIAL_CORE_CONSOLE
 
 config MACH_OMAP_ZOOM3
        bool "OMAP3630 Zoom3 board"
@@ -321,9 +318,6 @@ config MACH_OMAP_ZOOM3
        default y
        select OMAP_PACKAGE_CBP
        select REGULATOR_FIXED_VOLTAGE if REGULATOR
-       select SERIAL_8250
-       select SERIAL_8250_CONSOLE
-       select SERIAL_CORE_CONSOLE
 
 config MACH_CM_T35
        bool "CompuLab CM-T35/CM-T3730 modules"
index 0274ff7..e54a480 100644 (file)
@@ -102,6 +102,7 @@ DT_MACHINE_START(OMAP3_DT, "Generic OMAP3 (Flattened Device Tree)")
        .init_irq       = omap_intc_of_init,
        .handle_irq     = omap3_intc_handle_irq,
        .init_machine   = omap_generic_init,
+       .init_late      = omap3_init_late,
        .init_time      = omap3_sync32k_timer_init,
        .dt_compat      = omap3_boards_compat,
        .restart        = omap3xxx_restart,
@@ -119,6 +120,7 @@ DT_MACHINE_START(OMAP3_GP_DT, "Generic OMAP3-GP (Flattened Device Tree)")
        .init_irq       = omap_intc_of_init,
        .handle_irq     = omap3_intc_handle_irq,
        .init_machine   = omap_generic_init,
+       .init_late      = omap3_init_late,
        .init_time      = omap3_secure_sync32k_timer_init,
        .dt_compat      = omap3_gp_boards_compat,
        .restart        = omap3xxx_restart,
index f7c4616..d2ea68e 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/io.h>
 #include <linux/gpio.h>
 #include <linux/leds.h>
+#include <linux/usb/phy.h>
 #include <linux/usb/musb.h>
 #include <linux/platform_data/spi-omap2-mcspi.h>
 
@@ -98,6 +99,7 @@ static void __init rx51_init(void)
        sdrc_params = nokia_get_sdram_timings();
        omap_sdrc_init(sdrc_params, sdrc_params);
 
+       usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
        usb_musb_init(&musb_board_data);
        rx51_peripherals_init();
 
index 0a6b9c7..40f4a03 100644 (file)
@@ -108,7 +108,6 @@ void omap35xx_init_late(void);
 void omap3630_init_late(void);
 void am35xx_init_late(void);
 void ti81xx_init_late(void);
-void omap4430_init_late(void);
 int omap2_common_pm_late_init(void);
 
 #if defined(CONFIG_SOC_OMAP2420) || defined(CONFIG_SOC_OMAP2430)
index e4b16c8..410e1ba 100644 (file)
@@ -1122,9 +1122,6 @@ int gpmc_calc_timings(struct gpmc_timings *gpmc_t,
        /* TODO: remove, see function definition */
        gpmc_convert_ps_to_ns(gpmc_t);
 
-       /* Now the GPMC is initialised, unreserve the chip-selects */
-       gpmc_cs_map = 0;
-
        return 0;
 }
 
@@ -1383,6 +1380,9 @@ static int gpmc_probe(struct platform_device *pdev)
        if (IS_ERR_VALUE(gpmc_setup_irq()))
                dev_warn(gpmc_dev, "gpmc_setup_irq failed\n");
 
+       /* Now the GPMC is initialised, unreserve the chip-selects */
+       gpmc_cs_map = 0;
+
        rc = gpmc_probe_dt(pdev);
        if (rc < 0) {
                clk_disable_unprepare(gpmc_l3_clk);
index 6a217c9..f82cf87 100644 (file)
@@ -211,8 +211,6 @@ static int __init _omap_mux_get_by_name(struct omap_mux_partition *partition,
                return -EINVAL;
        }
 
-       pr_err("%s: Could not find signal %s\n", __func__, muxname);
-
        return -ENODEV;
 }
 
@@ -234,6 +232,8 @@ int __init omap_mux_get_by_name(const char *muxname,
                return mux_mode;
        }
 
+       pr_err("%s: Could not find signal %s\n", __func__, muxname);
+
        return -ENODEV;
 }
 
@@ -739,8 +739,9 @@ static void __init omap_mux_dbg_create_entry(
        list_for_each_entry(e, &partition->muxmodes, node) {
                struct omap_mux *m = &e->mux;
 
-               (void)debugfs_create_file(m->muxnames[0], S_IWUSR, mux_dbg_dir,
-                                         m, &omap_mux_dbg_signal_fops);
+               (void)debugfs_create_file(m->muxnames[0], S_IWUSR | S_IRUGO,
+                                         mux_dbg_dir, m,
+                                         &omap_mux_dbg_signal_fops);
        }
 }
 
index af41888..969b0ba 100644 (file)
@@ -505,6 +505,7 @@ static struct w1_gpio_platform_data w1_gpio_platform_data = {
        .pin                    = GPIO_ONE_WIRE,
        .is_open_drain          = 0,
        .enable_external_pullup = w1_enable_external_pullup,
+       .ext_pullup_enable_pin  = -EINVAL,
 };
 
 struct platform_device raumfeld_w1_gpio_device = {
index f9d754f..d2b3937 100644 (file)
@@ -14,7 +14,7 @@
 #define pr_fmt(fmt) "SPEAr3xx: " fmt
 
 #include <linux/amba/pl022.h>
-#include <linux/amba/pl08x.h>
+#include <linux/amba/pl080.h>
 #include <linux/io.h>
 #include <plat/pl080.h>
 #include <mach/generic.h>
index 7a05111..a5a4b2b 100644 (file)
@@ -152,9 +152,9 @@ static int is_reserved_asid(u64 asid)
        return 0;
 }
 
-static void new_context(struct mm_struct *mm, unsigned int cpu)
+static u64 new_context(struct mm_struct *mm, unsigned int cpu)
 {
-       u64 asid = mm->context.id;
+       u64 asid = atomic64_read(&mm->context.id);
        u64 generation = atomic64_read(&asid_generation);
 
        if (asid != 0 && is_reserved_asid(asid)) {
@@ -181,13 +181,14 @@ static void new_context(struct mm_struct *mm, unsigned int cpu)
                cpumask_clear(mm_cpumask(mm));
        }
 
-       mm->context.id = asid;
+       return asid;
 }
 
 void check_and_switch_context(struct mm_struct *mm, struct task_struct *tsk)
 {
        unsigned long flags;
        unsigned int cpu = smp_processor_id();
+       u64 asid;
 
        if (unlikely(mm->context.vmalloc_seq != init_mm.context.vmalloc_seq))
                __check_vmalloc_seq(mm);
@@ -198,20 +199,26 @@ void check_and_switch_context(struct mm_struct *mm, struct task_struct *tsk)
         */
        cpu_set_reserved_ttbr0();
 
-       if (!((mm->context.id ^ atomic64_read(&asid_generation)) >> ASID_BITS)
-           && atomic64_xchg(&per_cpu(active_asids, cpu), mm->context.id))
+       asid = atomic64_read(&mm->context.id);
+       if (!((asid ^ atomic64_read(&asid_generation)) >> ASID_BITS)
+           && atomic64_xchg(&per_cpu(active_asids, cpu), asid))
                goto switch_mm_fastpath;
 
        raw_spin_lock_irqsave(&cpu_asid_lock, flags);
        /* Check that our ASID belongs to the current generation. */
-       if ((mm->context.id ^ atomic64_read(&asid_generation)) >> ASID_BITS)
-               new_context(mm, cpu);
-
-       atomic64_set(&per_cpu(active_asids, cpu), mm->context.id);
-       cpumask_set_cpu(cpu, mm_cpumask(mm));
+       asid = atomic64_read(&mm->context.id);
+       if ((asid ^ atomic64_read(&asid_generation)) >> ASID_BITS) {
+               asid = new_context(mm, cpu);
+               atomic64_set(&mm->context.id, asid);
+       }
 
-       if (cpumask_test_and_clear_cpu(cpu, &tlb_flush_pending))
+       if (cpumask_test_and_clear_cpu(cpu, &tlb_flush_pending)) {
+               local_flush_bp_all();
                local_flush_tlb_all();
+       }
+
+       atomic64_set(&per_cpu(active_asids, cpu), asid);
+       cpumask_set_cpu(cpu, mm_cpumask(mm));
        raw_spin_unlock_irqrestore(&cpu_asid_lock, flags);
 
 switch_mm_fastpath:
index c7e3759..e9db6b4 100644 (file)
@@ -342,6 +342,7 @@ static int __init atomic_pool_init(void)
 {
        struct dma_pool *pool = &atomic_pool;
        pgprot_t prot = pgprot_dmacoherent(pgprot_kernel);
+       gfp_t gfp = GFP_KERNEL | GFP_DMA;
        unsigned long nr_pages = pool->size >> PAGE_SHIFT;
        unsigned long *bitmap;
        struct page *page;
@@ -361,8 +362,8 @@ static int __init atomic_pool_init(void)
                ptr = __alloc_from_contiguous(NULL, pool->size, prot, &page,
                                              atomic_pool_init);
        else
-               ptr = __alloc_remap_buffer(NULL, pool->size, GFP_KERNEL, prot,
-                                          &page, atomic_pool_init);
+               ptr = __alloc_remap_buffer(NULL, pool->size, gfp, prot, &page,
+                                          atomic_pool_init);
        if (ptr) {
                int i;
 
index 2dffc01..5ee505c 100644 (file)
@@ -141,6 +141,7 @@ void setup_mm_for_reboot(void)
 {
        /* Switch to the identity mapping. */
        cpu_switch_mm(idmap_pgd, &init_mm);
+       local_flush_bp_all();
 
 #ifdef CONFIG_CPU_HAS_ASID
        /*
index 50bf1da..6ffd78c 100644 (file)
@@ -48,7 +48,7 @@
 ENTRY(cpu_v7_switch_mm)
 #ifdef CONFIG_MMU
        mmid    r1, r1                          @ get mm->context.id
-       and     r3, r1, #0xff
+       asid    r3, r1
        mov     r3, r3, lsl #(48 - 32)          @ ASID
        mcrr    p15, 0, r0, r3, c2              @ set TTB 0
        isb
index febe386..807ac8e 100644 (file)
@@ -157,9 +157,12 @@ void __init orion_setup_cpu_mbus_target(const struct orion_addr_map_cfg *cfg,
                u32 size = readl(ddr_window_cpu_base + DDR_SIZE_CS_OFF(i));
 
                /*
-                * Chip select enabled?
+                * We only take care of entries for which the chip
+                * select is enabled, and that don't have high base
+                * address bits set (devices can only access the first
+                * 32 bits of the memory).
                 */
-               if (size & 1) {
+               if ((size & 1) && !(base & 0xF)) {
                        struct mbus_dram_window *w;
 
                        w = &orion_mbus_dram_info.cs[cs++];
index 739d016..8a08c31 100644 (file)
@@ -10,7 +10,7 @@ choice
 
 config ARCH_SPEAR13XX
        bool "ST SPEAr13xx with Device Tree"
-       select ARCH_HAVE_CPUFREQ
+       select ARCH_HAS_CPUFREQ
        select ARM_GIC
        select CPU_V7
        select GPIO_SPEAR_SPICS
index 9b89257..c1a868d 100644 (file)
@@ -7,7 +7,7 @@ config AVR32
        select HAVE_OPROFILE
        select HAVE_KPROBES
        select HAVE_GENERIC_HARDIRQS
-       select HAVE_VIRT_TO_BUS
+       select VIRT_TO_BUS
        select GENERIC_IRQ_PROBE
        select GENERIC_ATOMIC64
        select HARDIRQS_SW_RESEND
index 600494c..c3f2e0b 100644 (file)
@@ -33,7 +33,7 @@ config BLACKFIN
        select ARCH_HAVE_CUSTOM_GPIO_H
        select ARCH_WANT_OPTIONAL_GPIOLIB
        select HAVE_UID16
-       select HAVE_VIRT_TO_BUS
+       select VIRT_TO_BUS
        select ARCH_WANT_IPC_PARSE_VERSION
        select HAVE_GENERIC_HARDIRQS
        select GENERIC_ATOMIC64
index bb0ac66..06dd026 100644 (file)
@@ -43,7 +43,7 @@ config CRIS
        select GENERIC_ATOMIC64
        select HAVE_GENERIC_HARDIRQS
        select HAVE_UID16
-       select HAVE_VIRT_TO_BUS
+       select VIRT_TO_BUS
        select ARCH_WANT_IPC_PARSE_VERSION
        select GENERIC_IRQ_SHOW
        select GENERIC_IOMAP
index 12369b1..2ce731f 100644 (file)
@@ -6,7 +6,7 @@ config FRV
        select HAVE_PERF_EVENTS
        select HAVE_UID16
        select HAVE_GENERIC_HARDIRQS
-       select HAVE_VIRT_TO_BUS
+       select VIRT_TO_BUS
        select GENERIC_IRQ_SHOW
        select HAVE_DEBUG_BUGVERBOSE
        select ARCH_HAVE_NMI_SAFE_CMPXCHG
index ae8551e..79250de 100644 (file)
@@ -5,7 +5,7 @@ config H8300
        select HAVE_GENERIC_HARDIRQS
        select GENERIC_ATOMIC64
        select HAVE_UID16
-       select HAVE_VIRT_TO_BUS
+       select VIRT_TO_BUS
        select ARCH_WANT_IPC_PARSE_VERSION
        select GENERIC_IRQ_SHOW
        select GENERIC_CPU_DEVICES
index 33f3fdc..9a02f71 100644 (file)
@@ -26,7 +26,7 @@ config IA64
        select HAVE_MEMBLOCK
        select HAVE_MEMBLOCK_NODE_MAP
        select HAVE_VIRT_CPU_ACCOUNTING
-       select HAVE_VIRT_TO_BUS
+       select VIRT_TO_BUS
        select ARCH_DISCARD_MEMBLOCK
        select GENERIC_IRQ_PROBE
        select GENERIC_PENDING_IRQ if SMP
index 433f5e8..2eda284 100644 (file)
@@ -619,6 +619,7 @@ static struct file_system_type pfm_fs_type = {
        .mount    = pfmfs_mount,
        .kill_sb  = kill_anon_super,
 };
+MODULE_ALIAS_FS("pfmfs");
 
 DEFINE_PER_CPU(unsigned long, pfm_syst_info);
 DEFINE_PER_CPU(struct task_struct *, pmu_owner);
index 9262381..bcd17b2 100644 (file)
@@ -10,7 +10,7 @@ config M32R
        select ARCH_WANT_IPC_PARSE_VERSION
        select HAVE_DEBUG_BUGVERBOSE
        select HAVE_GENERIC_HARDIRQS
-       select HAVE_VIRT_TO_BUS
+       select VIRT_TO_BUS
        select GENERIC_IRQ_PROBE
        select GENERIC_IRQ_SHOW
        select GENERIC_ATOMIC64
index da4518f..98470fe 100644 (file)
@@ -63,10 +63,10 @@ struct stat64 {
        long long       st_size;
        unsigned long   st_blksize;
 
-#if defined(__BIG_ENDIAN)
+#if defined(__BYTE_ORDER) ? __BYTE_ORDER == __BIG_ENDIAN : defined(__BIG_ENDIAN)
        unsigned long   __pad4;         /* future possible st_blocks high bits */
        unsigned long   st_blocks;      /* Number 512-byte blocks allocated. */
-#elif defined(__LITTLE_ENDIAN)
+#elif defined(__BYTE_ORDER) ? __BYTE_ORDER == __LITTLE_ENDIAN : defined(__LITTLE_ENDIAN)
        unsigned long   st_blocks;      /* Number 512-byte blocks allocated. */
        unsigned long   __pad4;         /* future possible st_blocks high bits */
 #else
index 0e708c7..6de8133 100644 (file)
@@ -8,7 +8,7 @@ config M68K
        select GENERIC_IRQ_SHOW
        select GENERIC_ATOMIC64
        select HAVE_UID16
-       select HAVE_VIRT_TO_BUS
+       select VIRT_TO_BUS
        select ARCH_HAVE_NMI_SAFE_CMPXCHG if RMW_INSNS
        select GENERIC_CPU_DEVICES
        select GENERIC_STRNCPY_FROM_USER if MMU
index 7cdf6b0..7240584 100644 (file)
@@ -310,7 +310,6 @@ config COBRA5282
 config SOM5282EM
        bool "EMAC.Inc SOM5282EM board support"
        depends on M528x
-       select EMAC_INC
        help
          Support for the EMAC.Inc SOM5282EM module.
 
index a337e56..4ebf098 100644 (file)
 /*
  * Here go the bitmasks themselves
  */
-#define IMR_MSPIM      (1 << SPIM _IRQ_NUM)    /* Mask SPI Master interrupt */
+#define IMR_MSPIM      (1 << SPIM_IRQ_NUM)     /* Mask SPI Master interrupt */
 #define        IMR_MTMR2       (1 << TMR2_IRQ_NUM)     /* Mask Timer 2 interrupt */
 #define IMR_MUART      (1 << UART_IRQ_NUM)     /* Mask UART interrupt */       
 #define        IMR_MWDT        (1 << WDT_IRQ_NUM)      /* Mask Watchdog Timer interrupt */
 #define IWR_ADDR       0xfffff308
 #define IWR            LONG_REF(IWR_ADDR)
 
-#define IWR_SPIM       (1 << SPIM _IRQ_NUM)    /* SPI Master interrupt */
+#define IWR_SPIM       (1 << SPIM_IRQ_NUM)     /* SPI Master interrupt */
 #define        IWR_TMR2        (1 << TMR2_IRQ_NUM)     /* Timer 2 interrupt */
 #define IWR_UART       (1 << UART_IRQ_NUM)     /* UART interrupt */    
 #define        IWR_WDT         (1 << WDT_IRQ_NUM)      /* Watchdog Timer interrupt */
 #define ISR_ADDR       0xfffff30c
 #define ISR            LONG_REF(ISR_ADDR)
 
-#define ISR_SPIM       (1 << SPIM _IRQ_NUM)    /* SPI Master interrupt */
+#define ISR_SPIM       (1 << SPIM_IRQ_NUM)     /* SPI Master interrupt */
 #define        ISR_TMR2        (1 << TMR2_IRQ_NUM)     /* Timer 2 interrupt */
 #define ISR_UART       (1 << UART_IRQ_NUM)     /* UART interrupt */    
 #define        ISR_WDT         (1 << WDT_IRQ_NUM)      /* Watchdog Timer interrupt */
 #define IPR_ADDR       0xfffff310
 #define IPR            LONG_REF(IPR_ADDR)
 
-#define IPR_SPIM       (1 << SPIM _IRQ_NUM)    /* SPI Master interrupt */
+#define IPR_SPIM       (1 << SPIM_IRQ_NUM)     /* SPI Master interrupt */
 #define        IPR_TMR2        (1 << TMR2_IRQ_NUM)     /* Timer 2 interrupt */
 #define IPR_UART       (1 << UART_IRQ_NUM)     /* UART interrupt */    
 #define        IPR_WDT         (1 << WDT_IRQ_NUM)      /* Watchdog Timer interrupt */
 
 /* 'EZ328-compatible definitions */
 #define TCN_ADDR       TCN1_ADDR
-#define TCN            TCN
+#define TCN            TCN1
 
 /*
  * Timer Unit 1 and 2 Status Registers
index 71fb299..911ba47 100644 (file)
@@ -57,6 +57,9 @@ void (*mach_reset)(void);
 void (*mach_halt)(void);
 void (*mach_power_off)(void);
 
+#ifdef CONFIG_M68000
+#define CPU_NAME       "MC68000"
+#endif
 #ifdef CONFIG_M68328
 #define CPU_NAME       "MC68328"
 #endif
index afd8106..519aad8 100644 (file)
@@ -188,7 +188,7 @@ void __init mem_init(void)
                }
        }
 
-#if !defined(CONFIG_SUN3) && !defined(CONFIG_COLDFIRE)
+#if defined(CONFIG_MMU) && !defined(CONFIG_SUN3) && !defined(CONFIG_COLDFIRE)
        /* insert pointer tables allocated so far into the tablelist */
        init_pointer_table((unsigned long)kernel_pg_dir);
        for (i = 0; i < PTRS_PER_PGD; i++) {
index 83b7dad..b03a9d2 100644 (file)
@@ -69,7 +69,7 @@ static void __init m528x_uarts_init(void)
        u8 port;
 
        /* make sure PUAPAR is set for UART0 and UART1 */
-       port = readb(MCF5282_GPIO_PUAPAR);
+       port = readb(MCFGPIO_PUAPAR);
        port |= 0x03 | (0x03 << 2);
        writeb(port, MCFGPIO_PUAPAR);
 }
index d63b9d0..d2baf69 100644 (file)
@@ -100,9 +100,6 @@ typedef unsigned long elf_fpregset_t;
 
 #define ELF_PLATFORM  (NULL)
 
-#define SET_PERSONALITY(ex) \
-       set_personality(PER_LINUX | (current->personality & (~PER_MASK)))
-
 #define STACK_RND_MASK (0)
 
 #ifdef CONFIG_METAG_USER_TCM
index cd7f2f2..975f2f4 100644 (file)
@@ -40,6 +40,7 @@ endchoice
 
 config NUMA
        bool "Non Uniform Memory Access (NUMA) Support"
+       select ARCH_WANT_NUMA_VARIABLE_LOCALITY
        help
          Some Meta systems have MMU-mappable on-chip memories with
          lower latencies than main memory. This enables support for
index 7843d11..1323fa2 100644 (file)
@@ -19,7 +19,7 @@ config MICROBLAZE
        select HAVE_DEBUG_KMEMLEAK
        select IRQ_DOMAIN
        select HAVE_GENERIC_HARDIRQS
-       select HAVE_VIRT_TO_BUS
+       select VIRT_TO_BUS
        select GENERIC_IRQ_PROBE
        select GENERIC_IRQ_SHOW
        select GENERIC_PCI_IOMAP
index ae9c716..cd2e21f 100644 (file)
@@ -38,7 +38,7 @@ config MIPS
        select GENERIC_CLOCKEVENTS
        select GENERIC_CMOS_UPDATE
        select HAVE_MOD_ARCH_SPECIFIC
-       select HAVE_VIRT_TO_BUS
+       select VIRT_TO_BUS
        select MODULES_USE_ELF_REL if MODULES
        select MODULES_USE_ELF_RELA if MODULES && 64BIT
        select CLONE_BACKWARDS
index b06c736..428da17 100644 (file)
@@ -8,7 +8,7 @@ config MN10300
        select HAVE_ARCH_KGDB
        select GENERIC_ATOMIC64
        select HAVE_NMI_WATCHDOG if MN10300_WD_TIMER
-       select HAVE_VIRT_TO_BUS
+       select VIRT_TO_BUS
        select GENERIC_CLOCKEVENTS
        select MODULES_USE_ELF_RELA
        select OLD_SIGSUSPEND3
index 014a648..9ab3bf2 100644 (file)
@@ -9,10 +9,9 @@ config OPENRISC
        select OF_EARLY_FLATTREE
        select IRQ_DOMAIN
        select HAVE_MEMBLOCK
-       select ARCH_WANT_OPTIONAL_GPIOLIB
+       select ARCH_REQUIRE_GPIOLIB
         select HAVE_ARCH_TRACEHOOK
        select HAVE_GENERIC_HARDIRQS
-       select HAVE_VIRT_TO_BUS
        select GENERIC_IRQ_CHIP
        select GENERIC_IRQ_PROBE
        select GENERIC_IRQ_SHOW
index a9ff712..0339181 100644 (file)
@@ -21,7 +21,7 @@ config PARISC
        select GENERIC_STRNCPY_FROM_USER
        select SYSCTL_ARCH_UNALIGN_ALLOW
        select HAVE_MOD_ARCH_SPECIFIC
-       select HAVE_VIRT_TO_BUS
+       select VIRT_TO_BUS
        select MODULES_USE_ELF_RELA
        select CLONE_BACKWARDS
        select TTY # Needed for pdc_cons.c
index b89d7eb..8082151 100644 (file)
@@ -98,7 +98,7 @@ config PPC
        select HAVE_FUNCTION_GRAPH_TRACER
        select SYSCTL_EXCEPTION_TRACE
        select ARCH_WANT_OPTIONAL_GPIOLIB
-       select HAVE_VIRT_TO_BUS if !PPC64
+       select VIRT_TO_BUS if !PPC64
        select HAVE_IDE
        select HAVE_IOREMAP_PROT
        select HAVE_EFFICIENT_UNALIGNED_ACCESS
index a5f8264..125e165 100644 (file)
        STEPUP4((t)+16, fn)
 
 _GLOBAL(powerpc_sha_transform)
-       PPC_STLU r1,-STACKFRAMESIZE(r1)
+       PPC_STLU r1,-INT_FRAME_SIZE(r1)
        SAVE_8GPRS(14, r1)
        SAVE_10GPRS(22, r1)
 
@@ -175,5 +175,5 @@ _GLOBAL(powerpc_sha_transform)
 
        REST_8GPRS(14, r1)
        REST_10GPRS(22, r1)
-       addi    r1,r1,STACKFRAMESIZE
+       addi    r1,r1,INT_FRAME_SIZE
        blr
index ef918a2..08bd299 100644 (file)
@@ -52,8 +52,6 @@
 #define smp_mb__before_clear_bit()     smp_mb()
 #define smp_mb__after_clear_bit()      smp_mb()
 
-#define BITOP_LE_SWIZZLE       ((BITS_PER_LONG-1) & ~0x7)
-
 /* Macro for generating the ***_bits() functions */
 #define DEFINE_BITOP(fn, op, prefix, postfix)  \
 static __inline__ void fn(unsigned long mask,  \
index e665861..c9c67fc 100644 (file)
 #define SPRN_HSRR0     0x13A   /* Hypervisor Save/Restore 0 */
 #define SPRN_HSRR1     0x13B   /* Hypervisor Save/Restore 1 */
 #define SPRN_FSCR      0x099   /* Facility Status & Control Register */
-#define FSCR_TAR       (1<<8)  /* Enable Target Adress Register */
+#define   FSCR_TAR     (1 << (63-55)) /* Enable Target Address Register */
+#define   FSCR_DSCR    (1 << (63-61)) /* Enable Data Stream Control Register */
 #define SPRN_TAR       0x32f   /* Target Address Register */
 #define SPRN_LPCR      0x13E   /* LPAR Control Register */
 #define   LPCR_VPM0    (1ul << (63-0))
index 535b6d8..ebbec52 100644 (file)
@@ -358,3 +358,4 @@ SYSCALL_SPU(setns)
 COMPAT_SYS(process_vm_readv)
 COMPAT_SYS(process_vm_writev)
 SYSCALL(finit_module)
+SYSCALL(ni_syscall) /* sys_kcmp */
index f25b5c4..1487f0f 100644 (file)
@@ -12,7 +12,7 @@
 #include <uapi/asm/unistd.h>
 
 
-#define __NR_syscalls          354
+#define __NR_syscalls          355
 
 #define __NR__exit __NR_exit
 #define NR_syscalls    __NR_syscalls
index 8c478c6..74cb4d7 100644 (file)
 #define __NR_process_vm_readv  351
 #define __NR_process_vm_writev 352
 #define __NR_finit_module      353
+#define __NR_kcmp              354
 
 
 #endif /* _UAPI_ASM_POWERPC_UNISTD_H_ */
index d29facb..ea847ab 100644 (file)
@@ -48,6 +48,7 @@ _GLOBAL(__restore_cpu_power7)
 
 _GLOBAL(__setup_cpu_power8)
        mflr    r11
+       bl      __init_FSCR
        bl      __init_hvmode_206
        mtlr    r11
        beqlr
@@ -56,13 +57,13 @@ _GLOBAL(__setup_cpu_power8)
        mfspr   r3,SPRN_LPCR
        oris    r3, r3, LPCR_AIL_3@h
        bl      __init_LPCR
-       bl      __init_FSCR
        bl      __init_TLB
        mtlr    r11
        blr
 
 _GLOBAL(__restore_cpu_power8)
        mflr    r11
+       bl      __init_FSCR
        mfmsr   r3
        rldicl. r0,r3,4,63
        beqlr
@@ -115,7 +116,7 @@ __init_LPCR:
 
 __init_FSCR:
        mfspr   r3,SPRN_FSCR
-       ori     r3,r3,FSCR_TAR
+       ori     r3,r3,FSCR_TAR|FSCR_DSCR
        mtspr   SPRN_FSCR,r3
        blr
 
index a8a5361..87ef8f5 100644 (file)
@@ -74,13 +74,13 @@ END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE)                              \
        mflr    r10 ;                                           \
        ld      r12,PACAKBASE(r13) ;                            \
        LOAD_HANDLER(r12, system_call_entry_direct) ;           \
-       mtlr    r12 ;                                           \
+       mtctr   r12 ;                                           \
        mfspr   r12,SPRN_SRR1 ;                                 \
        /* Re-use of r13... No spare regs to do this */ \
        li      r13,MSR_RI ;                                    \
        mtmsrd  r13,1 ;                                         \
        GET_PACA(r13) ; /* get r13 back */                      \
-       blr ;
+       bctr ;
 #else
        /* We can branch directly */
 #define SYSCALL_PSERIES_2_DIRECT                               \
index 863184b..3f3bb4c 100644 (file)
@@ -749,6 +749,7 @@ static struct file_system_type spufs_type = {
        .mount = spufs_mount,
        .kill_sb = kill_litter_super,
 };
+MODULE_ALIAS_FS("spufs");
 
 static int __init spufs_init(void)
 {
index fcf4b4c..4557e91 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/list.h>
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <linux/string.h>
 
 #include <asm/hvcall.h>
 #include <asm/hvcserver.h>
@@ -188,9 +189,9 @@ int hvcs_get_partner_info(uint32_t unit_address, struct list_head *head,
                        = (unsigned int)last_p_partition_ID;
 
                /* copy the Null-term char too */
-               strncpy(&next_partner_info->location_code[0],
+               strlcpy(&next_partner_info->location_code[0],
                        (char *)&pi_buff[2],
-                       strlen((char *)&pi_buff[2]) + 1);
+                       sizeof(next_partner_info->location_code));
 
                list_add_tail(&(next_partner_info->node), head);
                next_partner_info = NULL;
index 4b50537..eb8fb62 100644 (file)
@@ -134,7 +134,7 @@ config S390
        select HAVE_SYSCALL_WRAPPERS
        select HAVE_UID16 if 32BIT
        select HAVE_VIRT_CPU_ACCOUNTING
-       select HAVE_VIRT_TO_BUS
+       select VIRT_TO_BUS
        select INIT_ALL_POSSIBLE
        select KTIME_SCALAR if 32BIT
        select MODULES_USE_ELF_RELA
index 8538015..5f7d7ba 100644 (file)
@@ -456,6 +456,7 @@ static struct file_system_type hypfs_type = {
        .mount          = hypfs_mount,
        .kill_sb        = hypfs_kill_super
 };
+MODULE_ALIAS_FS("s390_hypfs");
 
 static const struct super_operations hypfs_s_ops = {
        .statfs         = simple_statfs,
index f1eddd1..c879fad 100644 (file)
@@ -12,6 +12,7 @@
 #ifndef _ASM_S390_CPU_MF_H
 #define _ASM_S390_CPU_MF_H
 
+#include <linux/errno.h>
 #include <asm/facility.h>
 
 #define CPU_MF_INT_SF_IAE      (1 << 31)       /* invalid entry address */
index e569aa1..c8def8b 100644 (file)
@@ -12,7 +12,7 @@ config SCORE
        select GENERIC_CPU_DEVICES
        select GENERIC_CLOCKEVENTS
        select HAVE_MOD_ARCH_SPECIFIC
-       select HAVE_VIRT_TO_BUS
+       select VIRT_TO_BUS
        select MODULES_USE_ELF_REL
        select CLONE_BACKWARDS
 
index ff496ab..25877ae 100644 (file)
@@ -17,7 +17,7 @@ config TILE
        select GENERIC_IRQ_SHOW
        select HAVE_DEBUG_BUGVERBOSE
        select HAVE_SYSCALL_WRAPPERS if TILEGX
-       select HAVE_VIRT_TO_BUS
+       select VIRT_TO_BUS
        select SYS_HYPERVISOR
        select ARCH_HAVE_NMI_SAFE_CMPXCHG
        select GENERIC_CLOCKEVENTS
index 001d418..78f1f2d 100644 (file)
@@ -288,6 +288,9 @@ long compat_sys_sync_file_range2(int fd, unsigned int flags,
 long compat_sys_fallocate(int fd, int mode,
                          u32 offset_lo, u32 offset_hi,
                          u32 len_lo, u32 len_hi);
+long compat_sys_llseek(unsigned int fd, unsigned int offset_high,
+                      unsigned int offset_low, loff_t __user * result,
+                      unsigned int origin);
 
 /* Assembly trampoline to avoid clobbering r0. */
 long _compat_sys_rt_sigreturn(void);
index 7f72401..6ea4cdb 100644 (file)
  * adapt the usual convention.
  */
 
-long compat_sys_truncate64(char __user *filename, u32 dummy, u32 low, u32 high)
+COMPAT_SYSCALL_DEFINE4(truncate64, char __user *, filename, u32, dummy,
+                       u32, low, u32, high)
 {
        return sys_truncate(filename, ((loff_t)high << 32) | low);
 }
 
-long compat_sys_ftruncate64(unsigned int fd, u32 dummy, u32 low, u32 high)
+COMPAT_SYSCALL_DEFINE4(ftruncate64, unsigned int, fd, u32, dummy,
+                       u32, low, u32, high)
 {
        return sys_ftruncate(fd, ((loff_t)high << 32) | low);
 }
 
-long compat_sys_pread64(unsigned int fd, char __user *ubuf, size_t count,
-                       u32 dummy, u32 low, u32 high)
+COMPAT_SYSCALL_DEFINE6(pread64, unsigned int, fd, char __user *, ubuf,
+                       size_t, count, u32, dummy, u32, low, u32, high)
 {
        return sys_pread64(fd, ubuf, count, ((loff_t)high << 32) | low);
 }
 
-long compat_sys_pwrite64(unsigned int fd, char __user *ubuf, size_t count,
-                        u32 dummy, u32 low, u32 high)
+COMPAT_SYSCALL_DEFINE6(pwrite64, unsigned int, fd, char __user *, ubuf,
+                       size_t, count, u32, dummy, u32, low, u32, high)
 {
        return sys_pwrite64(fd, ubuf, count, ((loff_t)high << 32) | low);
 }
 
-long compat_sys_lookup_dcookie(u32 low, u32 high, char __user *buf, size_t len)
+COMPAT_SYSCALL_DEFINE4(lookup_dcookie, u32, low, u32, high,
+                       char __user *, buf, size_t, len)
 {
        return sys_lookup_dcookie(((loff_t)high << 32) | low, buf, len);
 }
 
-long compat_sys_sync_file_range2(int fd, unsigned int flags,
-                                u32 offset_lo, u32 offset_hi,
-                                u32 nbytes_lo, u32 nbytes_hi)
+COMPAT_SYSCALL_DEFINE6(sync_file_range2, int, fd, unsigned int, flags,
+                       u32, offset_lo, u32, offset_hi,
+                       u32, nbytes_lo, u32, nbytes_hi)
 {
        return sys_sync_file_range(fd, ((loff_t)offset_hi << 32) | offset_lo,
                                   ((loff_t)nbytes_hi << 32) | nbytes_lo,
                                   flags);
 }
 
-long compat_sys_fallocate(int fd, int mode,
-                         u32 offset_lo, u32 offset_hi,
-                         u32 len_lo, u32 len_hi)
+COMPAT_SYSCALL_DEFINE6(fallocate, int, fd, int, mode,
+                       u32, offset_lo, u32, offset_hi,
+                       u32, len_lo, u32, len_hi)
 {
        return sys_fallocate(fd, mode, ((loff_t)offset_hi << 32) | offset_lo,
                             ((loff_t)len_hi << 32) | len_lo);
 }
 
+/*
+ * Avoid bug in generic sys_llseek() that specifies offset_high and
+ * offset_low as "unsigned long", thus making it possible to pass
+ * a sign-extended high 32 bits in offset_low.
+ */
+COMPAT_SYSCALL_DEFINE5(llseek, unsigned int, fd, unsigned int, offset_high,
+                      unsigned int, offset_low, loff_t __user *, result,
+                      unsigned int, origin)
+{
+       return sys_llseek(fd, offset_high, offset_low, result, origin);
+}
 /* Provide the compat syscall number to call mapping. */
 #undef __SYSCALL
 #define __SYSCALL(nr, call) [nr] = (call),
@@ -83,6 +98,7 @@ long compat_sys_fallocate(int fd, int mode,
 /* See comments in sys.c */
 #define compat_sys_fadvise64_64 sys32_fadvise64_64
 #define compat_sys_readahead sys32_readahead
+#define sys_llseek compat_sys_llseek
 
 /* Call the assembly trampolines where necessary. */
 #define compat_sys_rt_sigreturn _compat_sys_rt_sigreturn
index 78f1b89..c512b03 100644 (file)
@@ -37,7 +37,7 @@ extern int console_write_chan(struct chan *chan, const char *buf,
 extern int console_open_chan(struct line *line, struct console *co);
 extern void deactivate_chan(struct chan *chan, int irq);
 extern void reactivate_chan(struct chan *chan, int irq);
-extern void chan_enable_winch(struct chan *chan, struct tty_struct *tty);
+extern void chan_enable_winch(struct chan *chan, struct tty_port *port);
 extern int enable_chan(struct line *line);
 extern void close_chan(struct line *line);
 extern int chan_window_size(struct line *line, 
index 15c553c..80b47cb 100644 (file)
@@ -122,10 +122,10 @@ static int open_chan(struct list_head *chans)
        return err;
 }
 
-void chan_enable_winch(struct chan *chan, struct tty_struct *tty)
+void chan_enable_winch(struct chan *chan, struct tty_port *port)
 {
        if (chan && chan->primary && chan->ops->winch)
-               register_winch(chan->fd, tty);
+               register_winch(chan->fd, port);
 }
 
 static void line_timer_cb(struct work_struct *work)
index 9be670a..3fd7c3e 100644 (file)
@@ -216,7 +216,7 @@ static int winch_thread(void *arg)
        }
 }
 
-static int winch_tramp(int fd, struct tty_struct *tty, int *fd_out,
+static int winch_tramp(int fd, struct tty_port *port, int *fd_out,
                       unsigned long *stack_out)
 {
        struct winch_data data;
@@ -271,7 +271,7 @@ static int winch_tramp(int fd, struct tty_struct *tty, int *fd_out,
        return err;
 }
 
-void register_winch(int fd, struct tty_struct *tty)
+void register_winch(int fd, struct tty_port *port)
 {
        unsigned long stack;
        int pid, thread, count, thread_fd = -1;
@@ -281,17 +281,17 @@ void register_winch(int fd, struct tty_struct *tty)
                return;
 
        pid = tcgetpgrp(fd);
-       if (is_skas_winch(pid, fd, tty)) {
-               register_winch_irq(-1, fd, -1, tty, 0);
+       if (is_skas_winch(pid, fd, port)) {
+               register_winch_irq(-1, fd, -1, port, 0);
                return;
        }
 
        if (pid == -1) {
-               thread = winch_tramp(fd, tty, &thread_fd, &stack);
+               thread = winch_tramp(fd, port, &thread_fd, &stack);
                if (thread < 0)
                        return;
 
-               register_winch_irq(thread_fd, fd, thread, tty, stack);
+               register_winch_irq(thread_fd, fd, thread, port, stack);
 
                count = write(thread_fd, &c, sizeof(c));
                if (count != sizeof(c))
index dc69329..03f1b56 100644 (file)
@@ -38,10 +38,10 @@ extern int generic_window_size(int fd, void *unused, unsigned short *rows_out,
                               unsigned short *cols_out);
 extern void generic_free(void *data);
 
-struct tty_struct;
-extern void register_winch(int fd,  struct tty_struct *tty);
+struct tty_port;
+extern void register_winch(int fd,  struct tty_port *port);
 extern void register_winch_irq(int fd, int tty_fd, int pid,
-                              struct tty_struct *tty, unsigned long stack);
+                              struct tty_port *port, unsigned long stack);
 
 #define __channel_help(fn, prefix) \
 __uml_help(fn, prefix "[0-9]*=<channel description>\n" \
index f1b3857..be541cf 100644 (file)
@@ -305,7 +305,7 @@ static int line_activate(struct tty_port *port, struct tty_struct *tty)
                return ret;
 
        if (!line->sigio) {
-               chan_enable_winch(line->chan_out, tty);
+               chan_enable_winch(line->chan_out, port);
                line->sigio = 1;
        }
 
@@ -315,8 +315,22 @@ static int line_activate(struct tty_port *port, struct tty_struct *tty)
        return 0;
 }
 
+static void unregister_winch(struct tty_struct *tty);
+
+static void line_destruct(struct tty_port *port)
+{
+       struct tty_struct *tty = tty_port_tty_get(port);
+       struct line *line = tty->driver_data;
+
+       if (line->sigio) {
+               unregister_winch(tty);
+               line->sigio = 0;
+       }
+}
+
 static const struct tty_port_operations line_port_ops = {
        .activate = line_activate,
+       .destruct = line_destruct,
 };
 
 int line_open(struct tty_struct *tty, struct file *filp)
@@ -340,18 +354,6 @@ int line_install(struct tty_driver *driver, struct tty_struct *tty,
        return 0;
 }
 
-static void unregister_winch(struct tty_struct *tty);
-
-void line_cleanup(struct tty_struct *tty)
-{
-       struct line *line = tty->driver_data;
-
-       if (line->sigio) {
-               unregister_winch(tty);
-               line->sigio = 0;
-       }
-}
-
 void line_close(struct tty_struct *tty, struct file * filp)
 {
        struct line *line = tty->driver_data;
@@ -601,7 +603,7 @@ struct winch {
        int fd;
        int tty_fd;
        int pid;
-       struct tty_struct *tty;
+       struct tty_port *port;
        unsigned long stack;
        struct work_struct work;
 };
@@ -655,7 +657,7 @@ static irqreturn_t winch_interrupt(int irq, void *data)
                        goto out;
                }
        }
-       tty = winch->tty;
+       tty = tty_port_tty_get(winch->port);
        if (tty != NULL) {
                line = tty->driver_data;
                if (line != NULL) {
@@ -663,6 +665,7 @@ static irqreturn_t winch_interrupt(int irq, void *data)
                                         &tty->winsize.ws_col);
                        kill_pgrp(tty->pgrp, SIGWINCH, 1);
                }
+               tty_kref_put(tty);
        }
  out:
        if (winch->fd != -1)
@@ -670,7 +673,7 @@ static irqreturn_t winch_interrupt(int irq, void *data)
        return IRQ_HANDLED;
 }
 
-void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty,
+void register_winch_irq(int fd, int tty_fd, int pid, struct tty_port *port,
                        unsigned long stack)
 {
        struct winch *winch;
@@ -685,7 +688,7 @@ void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty,
                                   .fd          = fd,
                                   .tty_fd      = tty_fd,
                                   .pid         = pid,
-                                  .tty         = tty,
+                                  .port        = port,
                                   .stack       = stack });
 
        if (um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt,
@@ -714,15 +717,18 @@ static void unregister_winch(struct tty_struct *tty)
 {
        struct list_head *ele, *next;
        struct winch *winch;
+       struct tty_struct *wtty;
 
        spin_lock(&winch_handler_lock);
 
        list_for_each_safe(ele, next, &winch_handlers) {
                winch = list_entry(ele, struct winch, list);
-               if (winch->tty == tty) {
+               wtty = tty_port_tty_get(winch->port);
+               if (wtty == tty) {
                        free_winch(winch);
                        break;
                }
+               tty_kref_put(wtty);
        }
        spin_unlock(&winch_handler_lock);
 }
index d8926c3..39f1862 100644 (file)
@@ -218,6 +218,7 @@ static int uml_net_start_xmit(struct sk_buff *skb, struct net_device *dev)
        spin_lock_irqsave(&lp->lock, flags);
 
        len = (*lp->write)(lp->fd, skb, lp);
+       skb_tx_timestamp(skb);
 
        if (len == skb->len) {
                dev->stats.tx_packets++;
@@ -281,6 +282,7 @@ static void uml_net_get_drvinfo(struct net_device *dev,
 static const struct ethtool_ops uml_net_ethtool_ops = {
        .get_drvinfo    = uml_net_get_drvinfo,
        .get_link       = ethtool_op_get_link,
+       .get_ts_info    = ethtool_op_get_ts_info,
 };
 
 static void uml_net_user_timer_expire(unsigned long _conn)
index 16fdd0a..b8d14fa 100644 (file)
@@ -105,7 +105,6 @@ static const struct tty_operations ssl_ops = {
        .throttle               = line_throttle,
        .unthrottle             = line_unthrottle,
        .install                = ssl_install,
-       .cleanup                = line_cleanup,
        .hangup                 = line_hangup,
 };
 
index 827777a..7b361f3 100644 (file)
@@ -110,7 +110,6 @@ static const struct tty_operations console_ops = {
        .set_termios            = line_set_termios,
        .throttle               = line_throttle,
        .unthrottle             = line_unthrottle,
-       .cleanup                = line_cleanup,
        .hangup                 = line_hangup,
 };
 
index b1469fe..9d9f1b4 100644 (file)
@@ -15,7 +15,7 @@
 #include <sysdep/mcontext.h>
 #include "internal.h"
 
-void (*sig_info[NSIG])(int, siginfo_t *, struct uml_pt_regs *) = {
+void (*sig_info[NSIG])(int, struct siginfo *, struct uml_pt_regs *) = {
        [SIGTRAP]       = relay_signal,
        [SIGFPE]        = relay_signal,
        [SIGILL]        = relay_signal,
index da4b9e9..337518c 100644 (file)
@@ -15,6 +15,8 @@
 #include <sys/mman.h>
 #include <sys/stat.h>
 #include <sys/wait.h>
+#include <sys/time.h>
+#include <sys/resource.h>
 #include <asm/unistd.h>
 #include <init.h>
 #include <os.h>
index dc50b15..2943e3a 100644 (file)
@@ -9,7 +9,7 @@ config UNICORE32
        select GENERIC_ATOMIC64
        select HAVE_KERNEL_LZO
        select HAVE_KERNEL_LZMA
-       select HAVE_VIRT_TO_BUS
+       select VIRT_TO_BUS
        select ARCH_HAVE_CUSTOM_GPIO_H
        select GENERIC_FIND_FIRST_BIT
        select GENERIC_IRQ_PROBE
index a4f24f5..70c0f3d 100644 (file)
@@ -112,7 +112,7 @@ config X86
        select GENERIC_STRNLEN_USER
        select HAVE_CONTEXT_TRACKING if X86_64
        select HAVE_IRQ_TIME_ACCOUNTING
-       select HAVE_VIRT_TO_BUS
+       select VIRT_TO_BUS
        select MODULES_USE_ELF_REL if X86_32
        select MODULES_USE_ELF_RELA if X86_64
        select CLONE_BACKWARDS if X86_32
index 5b5e9cb..653668d 100644 (file)
  * analysis of kexec-tools; if other broken bootloaders initialize a
  * different set of fields we will need to figure out how to disambiguate.
  *
+ * Note: efi_info is commonly left uninitialized, but that field has a
+ * private magic, so it is better to leave it unchanged.
  */
 static void sanitize_boot_params(struct boot_params *boot_params)
 {
+       /* 
+        * IMPORTANT NOTE TO BOOTLOADER AUTHORS: do not simply clear
+        * this field.  The purpose of this field is to guarantee
+        * compliance with the x86 boot spec located in
+        * Documentation/x86/boot.txt .  That spec says that the
+        * *whole* structure should be cleared, after which only the
+        * portion defined by struct setup_header (boot_params->hdr)
+        * should be copied in.
+        *
+        * If you're having an issue because the sentinel is set, you
+        * need to change the whole structure to be cleared, not this
+        * (or any other) individual field, or you will soon have
+        * problems again.
+        */
        if (boot_params->sentinel) {
-               /*fields in boot_params are not valid, clear them */
+               /* fields in boot_params are left uninitialized, clear them */
                memset(&boot_params->olpc_ofw_header, 0,
-                      (char *)&boot_params->alt_mem_k -
+                      (char *)&boot_params->efi_info -
                        (char *)&boot_params->olpc_ofw_header);
                memset(&boot_params->kbd_status, 0,
                       (char *)&boot_params->hdr -
index 826054a..b05a575 100644 (file)
@@ -729,3 +729,13 @@ void intel_ds_init(void)
                }
        }
 }
+
+void perf_restore_debug_store(void)
+{
+       struct debug_store *ds = __this_cpu_read(cpu_hw_events.ds);
+
+       if (!x86_pmu.bts && !x86_pmu.pebs)
+               return;
+
+       wrmsrl(MSR_IA32_DS_AREA, (unsigned long)ds);
+}
index 84d3285..90d8cc9 100644 (file)
@@ -171,9 +171,15 @@ static struct resource bss_resource = {
 
 #ifdef CONFIG_X86_32
 /* cpu data as detected by the assembly code in head.S */
-struct cpuinfo_x86 new_cpu_data __cpuinitdata = {0, 0, 0, 0, -1, 1, 0, 0, -1};
+struct cpuinfo_x86 new_cpu_data __cpuinitdata = {
+       .wp_works_ok = -1,
+       .fdiv_bug = -1,
+};
 /* common cpu data for all cpus */
-struct cpuinfo_x86 boot_cpu_data __read_mostly = {0, 0, 0, 0, -1, 1, 0, 0, -1};
+struct cpuinfo_x86 boot_cpu_data __read_mostly = {
+       .wp_works_ok = -1,
+       .fdiv_bug = -1,
+};
 EXPORT_SYMBOL(boot_cpu_data);
 
 unsigned int def_to_bigsmp;
index a6ceaed..9f190a2 100644 (file)
@@ -1365,9 +1365,8 @@ static inline void mwait_play_dead(void)
        unsigned int eax, ebx, ecx, edx;
        unsigned int highest_cstate = 0;
        unsigned int highest_subcstate = 0;
-       int i;
        void *mwait_ptr;
-       struct cpuinfo_x86 *c = __this_cpu_ptr(&cpu_info);
+       int i;
 
        if (!this_cpu_has(X86_FEATURE_MWAIT))
                return;
index 4903a03..59b7fc4 100644 (file)
@@ -410,9 +410,8 @@ void __init init_mem_mapping(void)
        /* the ISA range is always mapped regardless of memory holes */
        init_memory_mapping(0, ISA_END_ADDRESS);
 
-       /* xen has big range in reserved near end of ram, skip it at first */
-       addr = memblock_find_in_range(ISA_END_ADDRESS, end, PMD_SIZE,
-                        PAGE_SIZE);
+       /* xen has big range in reserved near end of ram, skip it at first.*/
+       addr = memblock_find_in_range(ISA_END_ADDRESS, end, PMD_SIZE, PMD_SIZE);
        real_end = addr + PMD_SIZE;
 
        /* step_size need to be small so pgt_buf from BRK could cover it */
index 2610bd9..6574388 100644 (file)
@@ -563,6 +563,13 @@ int kernel_map_sync_memtype(u64 base, unsigned long size, unsigned long flags)
        if (base > __pa(high_memory-1))
                return 0;
 
+       /*
+        * some areas in the middle of the kernel identity range
+        * are not mapped, like the PCI space.
+        */
+       if (!page_is_ram(base >> PAGE_SHIFT))
+               return 0;
+
        id_sz = (__pa(high_memory-1) <= base + size) ?
                                __pa(high_memory) - base :
                                size;
index 120cee1..3c68768 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/suspend.h>
 #include <linux/export.h>
 #include <linux/smp.h>
+#include <linux/perf_event.h>
 
 #include <asm/pgtable.h>
 #include <asm/proto.h>
@@ -228,6 +229,7 @@ static void __restore_processor_state(struct saved_context *ctxt)
        do_fpu_end();
        x86_platform.restore_sched_clock_state();
        mtrr_bp_restore();
+       perf_restore_debug_store();
 }
 
 /* Needed by apm.c */
index 35876ff..b09de49 100644 (file)
@@ -9,7 +9,7 @@ config XTENSA
        select HAVE_IDE
        select GENERIC_ATOMIC64
        select HAVE_GENERIC_HARDIRQS
-       select HAVE_VIRT_TO_BUS
+       select VIRT_TO_BUS
        select GENERIC_IRQ_SHOW
        select GENERIC_CPU_DEVICES
        select MODULES_USE_ELF_RELA
index ef6f155..40a84cc 100644 (file)
@@ -36,12 +36,11 @@ int register_acpi_bus_type(struct acpi_bus_type *type)
 {
        if (acpi_disabled)
                return -ENODEV;
-       if (type && type->bus && type->find_device) {
+       if (type && type->match && type->find_device) {
                down_write(&bus_type_sem);
                list_add_tail(&type->list, &bus_type_list);
                up_write(&bus_type_sem);
-               printk(KERN_INFO PREFIX "bus type %s registered\n",
-                      type->bus->name);
+               printk(KERN_INFO PREFIX "bus type %s registered\n", type->name);
                return 0;
        }
        return -ENODEV;
@@ -56,24 +55,21 @@ int unregister_acpi_bus_type(struct acpi_bus_type *type)
                down_write(&bus_type_sem);
                list_del_init(&type->list);
                up_write(&bus_type_sem);
-               printk(KERN_INFO PREFIX "ACPI bus type %s unregistered\n",
-                      type->bus->name);
+               printk(KERN_INFO PREFIX "bus type %s unregistered\n",
+                      type->name);
                return 0;
        }
        return -ENODEV;
 }
 EXPORT_SYMBOL_GPL(unregister_acpi_bus_type);
 
-static struct acpi_bus_type *acpi_get_bus_type(struct bus_type *type)
+static struct acpi_bus_type *acpi_get_bus_type(struct device *dev)
 {
        struct acpi_bus_type *tmp, *ret = NULL;
 
-       if (!type)
-               return NULL;
-
        down_read(&bus_type_sem);
        list_for_each_entry(tmp, &bus_type_list, list) {
-               if (tmp->bus == type) {
+               if (tmp->match(dev)) {
                        ret = tmp;
                        break;
                }
@@ -82,22 +78,6 @@ static struct acpi_bus_type *acpi_get_bus_type(struct bus_type *type)
        return ret;
 }
 
-static int acpi_find_bridge_device(struct device *dev, acpi_handle * handle)
-{
-       struct acpi_bus_type *tmp;
-       int ret = -ENODEV;
-
-       down_read(&bus_type_sem);
-       list_for_each_entry(tmp, &bus_type_list, list) {
-               if (tmp->find_bridge && !tmp->find_bridge(dev, handle)) {
-                       ret = 0;
-                       break;
-               }
-       }
-       up_read(&bus_type_sem);
-       return ret;
-}
-
 static acpi_status do_acpi_find_child(acpi_handle handle, u32 lvl_not_used,
                                      void *addr_p, void **ret_p)
 {
@@ -261,29 +241,12 @@ err:
 
 static int acpi_platform_notify(struct device *dev)
 {
-       struct acpi_bus_type *type;
+       struct acpi_bus_type *type = acpi_get_bus_type(dev);
        acpi_handle handle;
        int ret;
 
        ret = acpi_bind_one(dev, NULL);
-       if (ret && (!dev->bus || !dev->parent)) {
-               /* bridge devices genernally haven't bus or parent */
-               ret = acpi_find_bridge_device(dev, &handle);
-               if (!ret) {
-                       ret = acpi_bind_one(dev, handle);
-                       if (ret)
-                               goto out;
-               }
-       }
-
-       type = acpi_get_bus_type(dev->bus);
-       if (ret) {
-               if (!type || !type->find_device) {
-                       DBG("No ACPI bus support for %s\n", dev_name(dev));
-                       ret = -EINVAL;
-                       goto out;
-               }
-
+       if (ret && type) {
                ret = type->find_device(dev, &handle);
                if (ret) {
                        DBG("Unable to get handle for %s\n", dev_name(dev));
@@ -316,7 +279,7 @@ static int acpi_platform_notify_remove(struct device *dev)
 {
        struct acpi_bus_type *type;
 
-       type = acpi_get_bus_type(dev->bus);
+       type = acpi_get_bus_type(dev);
        if (type && type->cleanup)
                type->cleanup(dev);
 
index eff7222..164d495 100644 (file)
@@ -158,8 +158,7 @@ static int map_mat_entry(acpi_handle handle, int type, u32 acpi_id)
        }
 
 exit:
-       if (buffer.pointer)
-               kfree(buffer.pointer);
+       kfree(buffer.pointer);
        return apic_id;
 }
 
index df34bd0..bec717f 100644 (file)
@@ -559,7 +559,7 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device)
                return 0;
 #endif
 
-       BUG_ON((pr->id >= nr_cpu_ids) || (pr->id < 0));
+       BUG_ON(pr->id >= nr_cpu_ids);
 
        /*
         * Buggy BIOS check
index 53e7ac9..e854582 100644 (file)
@@ -465,7 +465,7 @@ static int acpi_processor_get_performance_states(struct acpi_processor *pr)
        return result;
 }
 
-static int acpi_processor_get_performance_info(struct acpi_processor *pr)
+int acpi_processor_get_performance_info(struct acpi_processor *pr)
 {
        int result = 0;
        acpi_status status = AE_OK;
@@ -509,7 +509,7 @@ static int acpi_processor_get_performance_info(struct acpi_processor *pr)
 #endif
        return result;
 }
-
+EXPORT_SYMBOL_GPL(acpi_processor_get_performance_info);
 int acpi_processor_notify_smm(struct module *calling_module)
 {
        acpi_status status;
index 6d3a06a..2421303 100644 (file)
@@ -599,7 +599,6 @@ static void acpi_sleep_suspend_setup(void)
                status = acpi_get_sleep_type_data(i, &type_a, &type_b);
                if (ACPI_SUCCESS(status)) {
                        sleep_states[i] = 1;
-                       pr_cont(" S%d", i);
                }
        }
 
@@ -742,7 +741,6 @@ static void acpi_sleep_hibernate_setup(void)
        hibernation_set_ops(old_suspend_ordering ?
                        &acpi_hibernation_ops_old : &acpi_hibernation_ops);
        sleep_states[ACPI_STATE_S4] = 1;
-       pr_cont(KERN_CONT " S4");
        if (nosigcheck)
                return;
 
@@ -788,6 +786,9 @@ int __init acpi_sleep_init(void)
 {
        acpi_status status;
        u8 type_a, type_b;
+       char supported[ACPI_S_STATE_COUNT * 3 + 1];
+       char *pos = supported;
+       int i;
 
        if (acpi_disabled)
                return 0;
@@ -795,7 +796,6 @@ int __init acpi_sleep_init(void)
        acpi_sleep_dmi_check();
 
        sleep_states[ACPI_STATE_S0] = 1;
-       pr_info(PREFIX "(supports S0");
 
        acpi_sleep_suspend_setup();
        acpi_sleep_hibernate_setup();
@@ -803,11 +803,17 @@ int __init acpi_sleep_init(void)
        status = acpi_get_sleep_type_data(ACPI_STATE_S5, &type_a, &type_b);
        if (ACPI_SUCCESS(status)) {
                sleep_states[ACPI_STATE_S5] = 1;
-               pr_cont(" S5");
                pm_power_off_prepare = acpi_power_off_prepare;
                pm_power_off = acpi_power_off;
        }
-       pr_cont(")\n");
+
+       supported[0] = 0;
+       for (i = 0; i < ACPI_S_STATE_COUNT; i++) {
+               if (sleep_states[i])
+                       pos += sprintf(pos, " S%d", i);
+       }
+       pr_info(PREFIX "(supports%s)\n", supported);
+
        /*
         * Register the tts_notifier to reboot notifier list so that the _TTS
         * object can also be evaluated when the system enters S5.
index 0ea1018..beea311 100644 (file)
@@ -1144,13 +1144,8 @@ static int ata_acpi_find_device(struct device *dev, acpi_handle *handle)
                return -ENODEV;
 }
 
-static int ata_acpi_find_dummy(struct device *dev, acpi_handle *handle)
-{
-       return -ENODEV;
-}
-
 static struct acpi_bus_type ata_acpi_bus = {
-       .find_bridge = ata_acpi_find_dummy,
+       .name = "ATA",
        .find_device = ata_acpi_find_device,
 };
 
index 2b7f77d..15beb50 100644 (file)
@@ -99,7 +99,6 @@ void device_pm_add(struct device *dev)
                dev_warn(dev, "parent %s should not be sleeping\n",
                        dev_name(dev->parent));
        list_add_tail(&dev->power.entry, &dpm_list);
-       dev_pm_qos_constraints_init(dev);
        mutex_unlock(&dpm_list_mtx);
 }
 
@@ -113,7 +112,6 @@ void device_pm_remove(struct device *dev)
                 dev->bus ? dev->bus->name : "No Bus", dev_name(dev));
        complete_all(&dev->power.completion);
        mutex_lock(&dpm_list_mtx);
-       dev_pm_qos_constraints_destroy(dev);
        list_del_init(&dev->power.entry);
        mutex_unlock(&dpm_list_mtx);
        device_wakeup_disable(dev);
index b16686a..cfc3226 100644 (file)
@@ -4,7 +4,7 @@ static inline void device_pm_init_common(struct device *dev)
 {
        if (!dev->power.early_init) {
                spin_lock_init(&dev->power.lock);
-               dev->power.power_state = PMSG_INVALID;
+               dev->power.qos = NULL;
                dev->power.early_init = true;
        }
 }
@@ -56,14 +56,10 @@ extern void device_pm_move_last(struct device *);
 
 static inline void device_pm_sleep_init(struct device *dev) {}
 
-static inline void device_pm_add(struct device *dev)
-{
-       dev_pm_qos_constraints_init(dev);
-}
+static inline void device_pm_add(struct device *dev) {}
 
 static inline void device_pm_remove(struct device *dev)
 {
-       dev_pm_qos_constraints_destroy(dev);
        pm_runtime_remove(dev);
 }
 
index 3d4d1f8..5f74587 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/mutex.h>
 #include <linux/export.h>
 #include <linux/pm_runtime.h>
+#include <linux/err.h>
 
 #include "power.h"
 
@@ -61,7 +62,7 @@ enum pm_qos_flags_status __dev_pm_qos_flags(struct device *dev, s32 mask)
        struct pm_qos_flags *pqf;
        s32 val;
 
-       if (!qos)
+       if (IS_ERR_OR_NULL(qos))
                return PM_QOS_FLAGS_UNDEFINED;
 
        pqf = &qos->flags;
@@ -101,7 +102,8 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_flags);
  */
 s32 __dev_pm_qos_read_value(struct device *dev)
 {
-       return dev->power.qos ? pm_qos_read_value(&dev->power.qos->latency) : 0;
+       return IS_ERR_OR_NULL(dev->power.qos) ?
+               0 : pm_qos_read_value(&dev->power.qos->latency);
 }
 
 /**
@@ -198,20 +200,8 @@ static int dev_pm_qos_constraints_allocate(struct device *dev)
        return 0;
 }
 
-/**
- * dev_pm_qos_constraints_init - Initalize device's PM QoS constraints pointer.
- * @dev: target device
- *
- * Called from the device PM subsystem during device insertion under
- * device_pm_lock().
- */
-void dev_pm_qos_constraints_init(struct device *dev)
-{
-       mutex_lock(&dev_pm_qos_mtx);
-       dev->power.qos = NULL;
-       dev->power.power_state = PMSG_ON;
-       mutex_unlock(&dev_pm_qos_mtx);
-}
+static void __dev_pm_qos_hide_latency_limit(struct device *dev);
+static void __dev_pm_qos_hide_flags(struct device *dev);
 
 /**
  * dev_pm_qos_constraints_destroy
@@ -226,16 +216,15 @@ void dev_pm_qos_constraints_destroy(struct device *dev)
        struct pm_qos_constraints *c;
        struct pm_qos_flags *f;
 
+       mutex_lock(&dev_pm_qos_mtx);
+
        /*
         * If the device's PM QoS resume latency limit or PM QoS flags have been
         * exposed to user space, they have to be hidden at this point.
         */
-       dev_pm_qos_hide_latency_limit(dev);
-       dev_pm_qos_hide_flags(dev);
+       __dev_pm_qos_hide_latency_limit(dev);
+       __dev_pm_qos_hide_flags(dev);
 
-       mutex_lock(&dev_pm_qos_mtx);
-
-       dev->power.power_state = PMSG_INVALID;
        qos = dev->power.qos;
        if (!qos)
                goto out;
@@ -257,7 +246,7 @@ void dev_pm_qos_constraints_destroy(struct device *dev)
        }
 
        spin_lock_irq(&dev->power.lock);
-       dev->power.qos = NULL;
+       dev->power.qos = ERR_PTR(-ENODEV);
        spin_unlock_irq(&dev->power.lock);
 
        kfree(c->notifiers);
@@ -301,32 +290,19 @@ int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req,
                 "%s() called for already added request\n", __func__))
                return -EINVAL;
 
-       req->dev = dev;
-
        mutex_lock(&dev_pm_qos_mtx);
 
-       if (!dev->power.qos) {
-               if (dev->power.power_state.event == PM_EVENT_INVALID) {
-                       /* The device has been removed from the system. */
-                       req->dev = NULL;
-                       ret = -ENODEV;
-                       goto out;
-               } else {
-                       /*
-                        * Allocate the constraints data on the first call to
-                        * add_request, i.e. only if the data is not already
-                        * allocated and if the device has not been removed.
-                        */
-                       ret = dev_pm_qos_constraints_allocate(dev);
-               }
-       }
+       if (IS_ERR(dev->power.qos))
+               ret = -ENODEV;
+       else if (!dev->power.qos)
+               ret = dev_pm_qos_constraints_allocate(dev);
 
        if (!ret) {
+               req->dev = dev;
                req->type = type;
                ret = apply_constraint(req, PM_QOS_ADD_REQ, value);
        }
 
- out:
        mutex_unlock(&dev_pm_qos_mtx);
 
        return ret;
@@ -344,7 +320,14 @@ static int __dev_pm_qos_update_request(struct dev_pm_qos_request *req,
        s32 curr_value;
        int ret = 0;
 
-       if (!req->dev->power.qos)
+       if (!req) /*guard against callers passing in null */
+               return -EINVAL;
+
+       if (WARN(!dev_pm_qos_request_active(req),
+                "%s() called for unknown object\n", __func__))
+               return -EINVAL;
+
+       if (IS_ERR_OR_NULL(req->dev->power.qos))
                return -ENODEV;
 
        switch(req->type) {
@@ -386,6 +369,17 @@ int dev_pm_qos_update_request(struct dev_pm_qos_request *req, s32 new_value)
 {
        int ret;
 
+       mutex_lock(&dev_pm_qos_mtx);
+       ret = __dev_pm_qos_update_request(req, new_value);
+       mutex_unlock(&dev_pm_qos_mtx);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(dev_pm_qos_update_request);
+
+static int __dev_pm_qos_remove_request(struct dev_pm_qos_request *req)
+{
+       int ret;
+
        if (!req) /*guard against callers passing in null */
                return -EINVAL;
 
@@ -393,13 +387,13 @@ int dev_pm_qos_update_request(struct dev_pm_qos_request *req, s32 new_value)
                 "%s() called for unknown object\n", __func__))
                return -EINVAL;
 
-       mutex_lock(&dev_pm_qos_mtx);
-       ret = __dev_pm_qos_update_request(req, new_value);
-       mutex_unlock(&dev_pm_qos_mtx);
+       if (IS_ERR_OR_NULL(req->dev->power.qos))
+               return -ENODEV;
 
+       ret = apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE);
+       memset(req, 0, sizeof(*req));
        return ret;
 }
-EXPORT_SYMBOL_GPL(dev_pm_qos_update_request);
 
 /**
  * dev_pm_qos_remove_request - modifies an existing qos request
@@ -418,26 +412,10 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_update_request);
  */
 int dev_pm_qos_remove_request(struct dev_pm_qos_request *req)
 {
-       int ret = 0;
-
-       if (!req) /*guard against callers passing in null */
-               return -EINVAL;
-
-       if (WARN(!dev_pm_qos_request_active(req),
-                "%s() called for unknown object\n", __func__))
-               return -EINVAL;
+       int ret;
 
        mutex_lock(&dev_pm_qos_mtx);
-
-       if (req->dev->power.qos) {
-               ret = apply_constraint(req, PM_QOS_REMOVE_REQ,
-                                      PM_QOS_DEFAULT_VALUE);
-               memset(req, 0, sizeof(*req));
-       } else {
-               /* Return if the device has been removed */
-               ret = -ENODEV;
-       }
-
+       ret = __dev_pm_qos_remove_request(req);
        mutex_unlock(&dev_pm_qos_mtx);
        return ret;
 }
@@ -462,9 +440,10 @@ int dev_pm_qos_add_notifier(struct device *dev, struct notifier_block *notifier)
 
        mutex_lock(&dev_pm_qos_mtx);
 
-       if (!dev->power.qos)
-               ret = dev->power.power_state.event != PM_EVENT_INVALID ?
-                       dev_pm_qos_constraints_allocate(dev) : -ENODEV;
+       if (IS_ERR(dev->power.qos))
+               ret = -ENODEV;
+       else if (!dev->power.qos)
+               ret = dev_pm_qos_constraints_allocate(dev);
 
        if (!ret)
                ret = blocking_notifier_chain_register(
@@ -493,7 +472,7 @@ int dev_pm_qos_remove_notifier(struct device *dev,
        mutex_lock(&dev_pm_qos_mtx);
 
        /* Silently return if the constraints object is not present. */
-       if (dev->power.qos)
+       if (!IS_ERR_OR_NULL(dev->power.qos))
                retval = blocking_notifier_chain_unregister(
                                dev->power.qos->latency.notifiers,
                                notifier);
@@ -563,16 +542,20 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_add_ancestor_request);
 static void __dev_pm_qos_drop_user_request(struct device *dev,
                                           enum dev_pm_qos_req_type type)
 {
+       struct dev_pm_qos_request *req = NULL;
+
        switch(type) {
        case DEV_PM_QOS_LATENCY:
-               dev_pm_qos_remove_request(dev->power.qos->latency_req);
+               req = dev->power.qos->latency_req;
                dev->power.qos->latency_req = NULL;
                break;
        case DEV_PM_QOS_FLAGS:
-               dev_pm_qos_remove_request(dev->power.qos->flags_req);
+               req = dev->power.qos->flags_req;
                dev->power.qos->flags_req = NULL;
                break;
        }
+       __dev_pm_qos_remove_request(req);
+       kfree(req);
 }
 
 /**
@@ -588,36 +571,57 @@ int dev_pm_qos_expose_latency_limit(struct device *dev, s32 value)
        if (!device_is_registered(dev) || value < 0)
                return -EINVAL;
 
-       if (dev->power.qos && dev->power.qos->latency_req)
-               return -EEXIST;
-
        req = kzalloc(sizeof(*req), GFP_KERNEL);
        if (!req)
                return -ENOMEM;
 
        ret = dev_pm_qos_add_request(dev, req, DEV_PM_QOS_LATENCY, value);
-       if (ret < 0)
+       if (ret < 0) {
+               kfree(req);
                return ret;
+       }
+
+       mutex_lock(&dev_pm_qos_mtx);
+
+       if (IS_ERR_OR_NULL(dev->power.qos))
+               ret = -ENODEV;
+       else if (dev->power.qos->latency_req)
+               ret = -EEXIST;
+
+       if (ret < 0) {
+               __dev_pm_qos_remove_request(req);
+               kfree(req);
+               goto out;
+       }
 
        dev->power.qos->latency_req = req;
        ret = pm_qos_sysfs_add_latency(dev);
        if (ret)
                __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY);
 
+ out:
+       mutex_unlock(&dev_pm_qos_mtx);
        return ret;
 }
 EXPORT_SYMBOL_GPL(dev_pm_qos_expose_latency_limit);
 
+static void __dev_pm_qos_hide_latency_limit(struct device *dev)
+{
+       if (!IS_ERR_OR_NULL(dev->power.qos) && dev->power.qos->latency_req) {
+               pm_qos_sysfs_remove_latency(dev);
+               __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY);
+       }
+}
+
 /**
  * dev_pm_qos_hide_latency_limit - Hide PM QoS latency limit from user space.
  * @dev: Device whose PM QoS latency limit is to be hidden from user space.
  */
 void dev_pm_qos_hide_latency_limit(struct device *dev)
 {
-       if (dev->power.qos && dev->power.qos->latency_req) {
-               pm_qos_sysfs_remove_latency(dev);
-               __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY);
-       }
+       mutex_lock(&dev_pm_qos_mtx);
+       __dev_pm_qos_hide_latency_limit(dev);
+       mutex_unlock(&dev_pm_qos_mtx);
 }
 EXPORT_SYMBOL_GPL(dev_pm_qos_hide_latency_limit);
 
@@ -634,41 +638,61 @@ int dev_pm_qos_expose_flags(struct device *dev, s32 val)
        if (!device_is_registered(dev))
                return -EINVAL;
 
-       if (dev->power.qos && dev->power.qos->flags_req)
-               return -EEXIST;
-
        req = kzalloc(sizeof(*req), GFP_KERNEL);
        if (!req)
                return -ENOMEM;
 
-       pm_runtime_get_sync(dev);
        ret = dev_pm_qos_add_request(dev, req, DEV_PM_QOS_FLAGS, val);
-       if (ret < 0)
-               goto fail;
+       if (ret < 0) {
+               kfree(req);
+               return ret;
+       }
+
+       pm_runtime_get_sync(dev);
+       mutex_lock(&dev_pm_qos_mtx);
+
+       if (IS_ERR_OR_NULL(dev->power.qos))
+               ret = -ENODEV;
+       else if (dev->power.qos->flags_req)
+               ret = -EEXIST;
+
+       if (ret < 0) {
+               __dev_pm_qos_remove_request(req);
+               kfree(req);
+               goto out;
+       }
 
        dev->power.qos->flags_req = req;
        ret = pm_qos_sysfs_add_flags(dev);
        if (ret)
                __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_FLAGS);
 
-fail:
+ out:
+       mutex_unlock(&dev_pm_qos_mtx);
        pm_runtime_put(dev);
        return ret;
 }
 EXPORT_SYMBOL_GPL(dev_pm_qos_expose_flags);
 
+static void __dev_pm_qos_hide_flags(struct device *dev)
+{
+       if (!IS_ERR_OR_NULL(dev->power.qos) && dev->power.qos->flags_req) {
+               pm_qos_sysfs_remove_flags(dev);
+               __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_FLAGS);
+       }
+}
+
 /**
  * dev_pm_qos_hide_flags - Hide PM QoS flags of a device from user space.
  * @dev: Device whose PM QoS flags are to be hidden from user space.
  */
 void dev_pm_qos_hide_flags(struct device *dev)
 {
-       if (dev->power.qos && dev->power.qos->flags_req) {
-               pm_qos_sysfs_remove_flags(dev);
-               pm_runtime_get_sync(dev);
-               __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_FLAGS);
-               pm_runtime_put(dev);
-       }
+       pm_runtime_get_sync(dev);
+       mutex_lock(&dev_pm_qos_mtx);
+       __dev_pm_qos_hide_flags(dev);
+       mutex_unlock(&dev_pm_qos_mtx);
+       pm_runtime_put(dev);
 }
 EXPORT_SYMBOL_GPL(dev_pm_qos_hide_flags);
 
@@ -683,12 +707,14 @@ int dev_pm_qos_update_flags(struct device *dev, s32 mask, bool set)
        s32 value;
        int ret;
 
-       if (!dev->power.qos || !dev->power.qos->flags_req)
-               return -EINVAL;
-
        pm_runtime_get_sync(dev);
        mutex_lock(&dev_pm_qos_mtx);
 
+       if (IS_ERR_OR_NULL(dev->power.qos) || !dev->power.qos->flags_req) {
+               ret = -EINVAL;
+               goto out;
+       }
+
        value = dev_pm_qos_requested_flags(dev);
        if (set)
                value |= mask;
@@ -697,9 +723,12 @@ int dev_pm_qos_update_flags(struct device *dev, s32 mask, bool set)
 
        ret = __dev_pm_qos_update_request(dev->power.qos->flags_req, value);
 
+ out:
        mutex_unlock(&dev_pm_qos_mtx);
        pm_runtime_put(dev);
-
        return ret;
 }
+#else /* !CONFIG_PM_RUNTIME */
+static void __dev_pm_qos_hide_latency_limit(struct device *dev) {}
+static void __dev_pm_qos_hide_flags(struct device *dev) {}
 #endif /* CONFIG_PM_RUNTIME */
index 50d16e3..a53ebd2 100644 (file)
@@ -708,6 +708,7 @@ void rpm_sysfs_remove(struct device *dev)
 
 void dpm_sysfs_remove(struct device *dev)
 {
+       dev_pm_qos_constraints_destroy(dev);
        rpm_sysfs_remove(dev);
        sysfs_unmerge_group(&dev->kobj, &pm_wakeup_attr_group);
        sysfs_remove_group(&dev->kobj, &pm_attr_group);
index 4706c63..020ea2b 100644 (file)
@@ -184,6 +184,7 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
                if (ret < 0) {
                        dev_err(map->dev, "IRQ thread failed to resume: %d\n",
                                ret);
+                       pm_runtime_put(map->dev);
                        return IRQ_NONE;
                }
        }
index d3bde6c..30629a3 100644 (file)
@@ -404,6 +404,8 @@ void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc)
                return;
        }
 
+       spin_lock_init(&pc_host->cfgspace_lock);
+
        pc->host_controller = pc_host;
        pc_host->pci_controller.io_resource = &pc_host->io_resource;
        pc_host->pci_controller.mem_resource = &pc_host->mem_resource;
index 1bafb40..69ae597 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/init.h>
 #include <linux/miscdevice.h>
 #include <linux/delay.h>
+#include <linux/slab.h>
 #include <asm/uaccess.h>
 
 
@@ -52,8 +53,12 @@ static struct hwrng *current_rng;
 static LIST_HEAD(rng_list);
 static DEFINE_MUTEX(rng_mutex);
 static int data_avail;
-static u8 rng_buffer[SMP_CACHE_BYTES < 32 ? 32 : SMP_CACHE_BYTES]
-       __cacheline_aligned;
+static u8 *rng_buffer;
+
+static size_t rng_buffer_size(void)
+{
+       return SMP_CACHE_BYTES < 32 ? 32 : SMP_CACHE_BYTES;
+}
 
 static inline int hwrng_init(struct hwrng *rng)
 {
@@ -116,7 +121,7 @@ static ssize_t rng_dev_read(struct file *filp, char __user *buf,
 
                if (!data_avail) {
                        bytes_read = rng_get_data(current_rng, rng_buffer,
-                               sizeof(rng_buffer),
+                               rng_buffer_size(),
                                !(filp->f_flags & O_NONBLOCK));
                        if (bytes_read < 0) {
                                err = bytes_read;
@@ -307,6 +312,14 @@ int hwrng_register(struct hwrng *rng)
 
        mutex_lock(&rng_mutex);
 
+       /* kmalloc makes this safe for virt_to_page() in virtio_rng.c */
+       err = -ENOMEM;
+       if (!rng_buffer) {
+               rng_buffer = kmalloc(rng_buffer_size(), GFP_KERNEL);
+               if (!rng_buffer)
+                       goto out_unlock;
+       }
+
        /* Must not register two RNGs with the same name. */
        err = -EEXIST;
        list_for_each_entry(tmp, &rng_list, list) {
index 10fd71c..6bf4d47 100644 (file)
@@ -92,14 +92,22 @@ static int probe_common(struct virtio_device *vdev)
 {
        int err;
 
+       if (vq) {
+               /* We only support one device for now */
+               return -EBUSY;
+       }
        /* We expect a single virtqueue. */
        vq = virtio_find_single_vq(vdev, random_recv_done, "input");
-       if (IS_ERR(vq))
-               return PTR_ERR(vq);
+       if (IS_ERR(vq)) {
+               err = PTR_ERR(vq);
+               vq = NULL;
+               return err;
+       }
 
        err = hwrng_register(&virtio_hwrng);
        if (err) {
                vdev->config->del_vqs(vdev);
+               vq = NULL;
                return err;
        }
 
@@ -112,6 +120,7 @@ static void remove_common(struct virtio_device *vdev)
        busy = false;
        hwrng_unregister(&virtio_hwrng);
        vdev->config->del_vqs(vdev);
+       vq = NULL;
 }
 
 static int virtrng_probe(struct virtio_device *vdev)
index 594bda9..32a6c57 100644 (file)
@@ -852,6 +852,7 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min,
                      int reserved)
 {
        unsigned long flags;
+       int wakeup_write = 0;
 
        /* Hold lock while accounting */
        spin_lock_irqsave(&r->lock, flags);
@@ -873,10 +874,8 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min,
                else
                        r->entropy_count = reserved;
 
-               if (r->entropy_count < random_write_wakeup_thresh) {
-                       wake_up_interruptible(&random_write_wait);
-                       kill_fasync(&fasync, SIGIO, POLL_OUT);
-               }
+               if (r->entropy_count < random_write_wakeup_thresh)
+                       wakeup_write = 1;
        }
 
        DEBUG_ENT("debiting %zu entropy credits from %s%s\n",
@@ -884,6 +883,11 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min,
 
        spin_unlock_irqrestore(&r->lock, flags);
 
+       if (wakeup_write) {
+               wake_up_interruptible(&random_write_wait);
+               kill_fasync(&fasync, SIGIO, POLL_OUT);
+       }
+
        return nbytes;
 }
 
index 143ce1f..1e2de73 100644 (file)
@@ -1292,7 +1292,6 @@ static struct tegra_clk_duplicate tegra_clk_duplicates[] = {
        TEGRA_CLK_DUPLICATE(usbd,   "tegra-ehci.0", NULL),
        TEGRA_CLK_DUPLICATE(usbd,   "tegra-otg",    NULL),
        TEGRA_CLK_DUPLICATE(cclk,   NULL,           "cpu"),
-       TEGRA_CLK_DUPLICATE(twd,    "smp_twd",      NULL),
        TEGRA_CLK_DUPLICATE(clk_max, NULL, NULL), /* Must be the last entry */
 };
 
index 32c61cb..ba6f51b 100644 (file)
@@ -1931,7 +1931,6 @@ static struct tegra_clk_duplicate tegra_clk_duplicates[] = {
        TEGRA_CLK_DUPLICATE(cml1, "tegra_sata_cml", NULL),
        TEGRA_CLK_DUPLICATE(cml0, "tegra_pcie", "cml"),
        TEGRA_CLK_DUPLICATE(pciex, "tegra_pcie", "pciex"),
-       TEGRA_CLK_DUPLICATE(twd, "smp_twd", NULL),
        TEGRA_CLK_DUPLICATE(vcp, "nvavp", "vcp"),
        TEGRA_CLK_DUPLICATE(clk_max, NULL, NULL), /* MUST be the last entry */
 };
index fce2000..1110478 100644 (file)
@@ -313,6 +313,12 @@ static void cn_proc_mcast_ctl(struct cn_msg *msg,
            (task_active_pid_ns(current) != &init_pid_ns))
                return;
 
+       /* Can only change if privileged. */
+       if (!capable(CAP_NET_ADMIN)) {
+               err = EPERM;
+               goto out;
+       }
+
        mc_op = (enum proc_cn_mcast_op *)msg->data;
        switch (*mc_op) {
        case PROC_CN_MCAST_LISTEN:
@@ -325,6 +331,8 @@ static void cn_proc_mcast_ctl(struct cn_msg *msg,
                err = EINVAL;
                break;
        }
+
+out:
        cn_proc_ack(err, msg->seq, msg->ack);
 }
 
index d2ac911..46bde01 100644 (file)
@@ -64,7 +64,7 @@ static void *get_cpu_dbs_info_s(int cpu)                              \
  * dbs: used as a shortform for demand based switching It helps to keep variable
  *     names smaller, simpler
  * cdbs: common dbs
- * on_*: On-demand governor
+ * od_*: On-demand governor
  * cs_*: Conservative governor
  */
 
index 66e3a71..b61b5a3 100644 (file)
 
 static int hb_voltage_change(unsigned int freq)
 {
-       int i;
-       u32 msg[HB_CPUFREQ_IPC_LEN];
-
-       msg[0] = HB_CPUFREQ_CHANGE_NOTE;
-       msg[1] = freq / 1000000;
-       for (i = 2; i < HB_CPUFREQ_IPC_LEN; i++)
-               msg[i] = 0;
+       u32 msg[HB_CPUFREQ_IPC_LEN] = {HB_CPUFREQ_CHANGE_NOTE, freq / 1000000};
 
        return pl320_ipc_transmit(msg);
 }
index 096fde0..f6dd1e7 100644 (file)
@@ -662,6 +662,9 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy)
 
        cpu = all_cpu_data[policy->cpu];
 
+       if (!policy->cpuinfo.max_freq)
+               return -ENODEV;
+
        intel_pstate_get_min_max(cpu, &min, &max);
 
        limits.min_perf_pct = (policy->min * 100) / policy->cpuinfo.max_freq;
@@ -747,37 +750,11 @@ static struct cpufreq_driver intel_pstate_driver = {
        .owner          = THIS_MODULE,
 };
 
-static void intel_pstate_exit(void)
-{
-       int cpu;
-
-       sysfs_remove_group(intel_pstate_kobject,
-                               &intel_pstate_attr_group);
-       debugfs_remove_recursive(debugfs_parent);
-
-       cpufreq_unregister_driver(&intel_pstate_driver);
-
-       if (!all_cpu_data)
-               return;
-
-       get_online_cpus();
-       for_each_online_cpu(cpu) {
-               if (all_cpu_data[cpu]) {
-                       del_timer_sync(&all_cpu_data[cpu]->timer);
-                       kfree(all_cpu_data[cpu]);
-               }
-       }
-
-       put_online_cpus();
-       vfree(all_cpu_data);
-}
-module_exit(intel_pstate_exit);
-
 static int __initdata no_load;
 
 static int __init intel_pstate_init(void)
 {
-       int rc = 0;
+       int cpu, rc = 0;
        const struct x86_cpu_id *id;
 
        if (no_load)
@@ -802,7 +779,16 @@ static int __init intel_pstate_init(void)
        intel_pstate_sysfs_expose_params();
        return rc;
 out:
-       intel_pstate_exit();
+       get_online_cpus();
+       for_each_online_cpu(cpu) {
+               if (all_cpu_data[cpu]) {
+                       del_timer_sync(&all_cpu_data[cpu]->timer);
+                       kfree(all_cpu_data[cpu]);
+               }
+       }
+
+       put_online_cpus();
+       vfree(all_cpu_data);
        return -ENODEV;
 }
 device_initcall(intel_pstate_init);
index 982f1f5..4cd392d 100644 (file)
@@ -442,7 +442,6 @@ static int __init dmi_present(const char __iomem *p)
 static int __init smbios_present(const char __iomem *p)
 {
        u8 buf[32];
-       int offset = 0;
 
        memcpy_fromio(buf, p, 32);
        if ((buf[5] < 32) && dmi_checksum(buf, buf[5])) {
@@ -461,9 +460,9 @@ static int __init smbios_present(const char __iomem *p)
                        dmi_ver = 0x0206;
                        break;
                }
-               offset = 16;
+               return memcmp(p + 16, "_DMI_", 5) || dmi_present(p + 16);
        }
-       return dmi_present(buf + offset);
+       return 1;
 }
 
 void __init dmi_scan_machine(void)
index 7320bf8..fe62aa3 100644 (file)
@@ -426,6 +426,44 @@ get_var_data(struct efivars *efivars, struct efi_variable *var)
        return status;
 }
 
+static efi_status_t
+check_var_size_locked(struct efivars *efivars, u32 attributes,
+                       unsigned long size)
+{
+       u64 storage_size, remaining_size, max_size;
+       efi_status_t status;
+       const struct efivar_operations *fops = efivars->ops;
+
+       if (!efivars->ops->query_variable_info)
+               return EFI_UNSUPPORTED;
+
+       status = fops->query_variable_info(attributes, &storage_size,
+                                          &remaining_size, &max_size);
+
+       if (status != EFI_SUCCESS)
+               return status;
+
+       if (!storage_size || size > remaining_size || size > max_size ||
+           (remaining_size - size) < (storage_size / 2))
+               return EFI_OUT_OF_RESOURCES;
+
+       return status;
+}
+
+
+static efi_status_t
+check_var_size(struct efivars *efivars, u32 attributes, unsigned long size)
+{
+       efi_status_t status;
+       unsigned long flags;
+
+       spin_lock_irqsave(&efivars->lock, flags);
+       status = check_var_size_locked(efivars, attributes, size);
+       spin_unlock_irqrestore(&efivars->lock, flags);
+
+       return status;
+}
+
 static ssize_t
 efivar_guid_read(struct efivar_entry *entry, char *buf)
 {
@@ -547,11 +585,16 @@ efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count)
        }
 
        spin_lock_irq(&efivars->lock);
-       status = efivars->ops->set_variable(new_var->VariableName,
-                                           &new_var->VendorGuid,
-                                           new_var->Attributes,
-                                           new_var->DataSize,
-                                           new_var->Data);
+
+       status = check_var_size_locked(efivars, new_var->Attributes,
+              new_var->DataSize + utf16_strsize(new_var->VariableName, 1024));
+
+       if (status == EFI_SUCCESS || status == EFI_UNSUPPORTED)
+               status = efivars->ops->set_variable(new_var->VariableName,
+                                                   &new_var->VendorGuid,
+                                                   new_var->Attributes,
+                                                   new_var->DataSize,
+                                                   new_var->Data);
 
        spin_unlock_irq(&efivars->lock);
 
@@ -702,8 +745,7 @@ static ssize_t efivarfs_file_write(struct file *file,
        u32 attributes;
        struct inode *inode = file->f_mapping->host;
        unsigned long datasize = count - sizeof(attributes);
-       unsigned long newdatasize;
-       u64 storage_size, remaining_size, max_size;
+       unsigned long newdatasize, varsize;
        ssize_t bytes = 0;
 
        if (count < sizeof(attributes))
@@ -722,28 +764,18 @@ static ssize_t efivarfs_file_write(struct file *file,
         * amounts of memory. Pick a default size of 64K if
         * QueryVariableInfo() isn't supported by the firmware.
         */
-       spin_lock_irq(&efivars->lock);
-
-       if (!efivars->ops->query_variable_info)
-               status = EFI_UNSUPPORTED;
-       else {
-               const struct efivar_operations *fops = efivars->ops;
-               status = fops->query_variable_info(attributes, &storage_size,
-                                                  &remaining_size, &max_size);
-       }
 
-       spin_unlock_irq(&efivars->lock);
+       varsize = datasize + utf16_strsize(var->var.VariableName, 1024);
+       status = check_var_size(efivars, attributes, varsize);
 
        if (status != EFI_SUCCESS) {
                if (status != EFI_UNSUPPORTED)
                        return efi_status_to_err(status);
 
-               remaining_size = 65536;
+               if (datasize > 65536)
+                       return -ENOSPC;
        }
 
-       if (datasize > remaining_size)
-               return -ENOSPC;
-
        data = kmalloc(datasize, GFP_KERNEL);
        if (!data)
                return -ENOMEM;
@@ -765,6 +797,19 @@ static ssize_t efivarfs_file_write(struct file *file,
         */
        spin_lock_irq(&efivars->lock);
 
+       /*
+        * Ensure that the available space hasn't shrunk below the safe level
+        */
+
+       status = check_var_size_locked(efivars, attributes, varsize);
+
+       if (status != EFI_SUCCESS && status != EFI_UNSUPPORTED) {
+               spin_unlock_irq(&efivars->lock);
+               kfree(data);
+
+               return efi_status_to_err(status);
+       }
+
        status = efivars->ops->set_variable(var->var.VariableName,
                                            &var->var.VendorGuid,
                                            attributes, datasize,
@@ -929,8 +974,8 @@ static bool efivarfs_valid_name(const char *str, int len)
        if (len < GUID_LEN + 2)
                return false;
 
-       /* GUID should be right after the first '-' */
-       if (s - 1 != strchr(str, '-'))
+       /* GUID must be preceded by a '-' */
+       if (*(s - 1) != '-')
                return false;
 
        /*
@@ -1118,15 +1163,22 @@ static struct dentry_operations efivarfs_d_ops = {
 
 static struct dentry *efivarfs_alloc_dentry(struct dentry *parent, char *name)
 {
+       struct dentry *d;
        struct qstr q;
+       int err;
 
        q.name = name;
        q.len = strlen(name);
 
-       if (efivarfs_d_hash(NULL, NULL, &q))
-               return NULL;
+       err = efivarfs_d_hash(NULL, NULL, &q);
+       if (err)
+               return ERR_PTR(err);
+
+       d = d_alloc(parent, &q);
+       if (d)
+               return d;
 
-       return d_alloc(parent, &q);
+       return ERR_PTR(-ENOMEM);
 }
 
 static int efivarfs_fill_super(struct super_block *sb, void *data, int silent)
@@ -1136,6 +1188,7 @@ static int efivarfs_fill_super(struct super_block *sb, void *data, int silent)
        struct efivar_entry *entry, *n;
        struct efivars *efivars = &__efivars;
        char *name;
+       int err = -ENOMEM;
 
        efivarfs_sb = sb;
 
@@ -1186,8 +1239,10 @@ static int efivarfs_fill_super(struct super_block *sb, void *data, int silent)
                        goto fail_name;
 
                dentry = efivarfs_alloc_dentry(root, name);
-               if (!dentry)
+               if (IS_ERR(dentry)) {
+                       err = PTR_ERR(dentry);
                        goto fail_inode;
+               }
 
                /* copied by the above to local storage in the dentry. */
                kfree(name);
@@ -1214,7 +1269,7 @@ fail_inode:
 fail_name:
        kfree(name);
 fail:
-       return -ENOMEM;
+       return err;
 }
 
 static struct dentry *efivarfs_mount(struct file_system_type *fs_type,
@@ -1234,6 +1289,7 @@ static struct file_system_type efivarfs_type = {
        .mount   = efivarfs_mount,
        .kill_sb = efivarfs_kill_sb,
 };
+MODULE_ALIAS_FS("efivarfs");
 
 /*
  * Handle negative dentry.
@@ -1345,7 +1401,6 @@ static int efi_pstore_write(enum pstore_type_id type,
        efi_guid_t vendor = LINUX_EFI_CRASH_GUID;
        struct efivars *efivars = psi->data;
        int i, ret = 0;
-       u64 storage_space, remaining_space, max_variable_size;
        efi_status_t status = EFI_NOT_FOUND;
        unsigned long flags;
 
@@ -1365,11 +1420,11 @@ static int efi_pstore_write(enum pstore_type_id type,
         * size: a size of logging data
         * DUMP_NAME_LEN * 2: a maximum size of variable name
         */
-       status = efivars->ops->query_variable_info(PSTORE_EFI_ATTRIBUTES,
-                                                  &storage_space,
-                                                  &remaining_space,
-                                                  &max_variable_size);
-       if (status || remaining_space < size + DUMP_NAME_LEN * 2) {
+
+       status = check_var_size_locked(efivars, PSTORE_EFI_ATTRIBUTES,
+                                        size + DUMP_NAME_LEN * 2);
+
+       if (status) {
                spin_unlock_irqrestore(&efivars->lock, flags);
                *id = part;
                return -ENOSPC;
@@ -1544,6 +1599,14 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj,
                return -EINVAL;
        }
 
+       status = check_var_size_locked(efivars, new_var->Attributes,
+              new_var->DataSize + utf16_strsize(new_var->VariableName, 1024));
+
+       if (status && status != EFI_UNSUPPORTED) {
+               spin_unlock_irq(&efivars->lock);
+               return efi_status_to_err(status);
+       }
+
        /* now *really* create the variable via EFI */
        status = efivars->ops->set_variable(new_var->VariableName,
                                            &new_var->VendorGuid,
index 6f2306d..f9dbd50 100644 (file)
@@ -128,9 +128,9 @@ static int ichx_read_bit(int reg, unsigned nr)
        return data & (1 << bit) ? 1 : 0;
 }
 
-static int ichx_gpio_check_available(struct gpio_chip *gpio, unsigned nr)
+static bool ichx_gpio_check_available(struct gpio_chip *gpio, unsigned nr)
 {
-       return (ichx_priv.use_gpio & (1 << (nr / 32))) ? 0 : -ENXIO;
+       return ichx_priv.use_gpio & (1 << (nr / 32));
 }
 
 static int ichx_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
index 7472182..61a6fde 100644 (file)
@@ -42,6 +42,7 @@
 #include <linux/io.h>
 #include <linux/of_irq.h>
 #include <linux/of_device.h>
+#include <linux/clk.h>
 #include <linux/pinctrl/consumer.h>
 
 /*
@@ -496,6 +497,7 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
        struct resource *res;
        struct irq_chip_generic *gc;
        struct irq_chip_type *ct;
+       struct clk *clk;
        unsigned int ngpios;
        int soc_variant;
        int i, cpu, id;
@@ -529,6 +531,11 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
                return id;
        }
 
+       clk = devm_clk_get(&pdev->dev, NULL);
+       /* Not all SoCs require a clock.*/
+       if (!IS_ERR(clk))
+               clk_prepare_enable(clk);
+
        mvchip->soc_variant = soc_variant;
        mvchip->chip.label = dev_name(&pdev->dev);
        mvchip->chip.dev = &pdev->dev;
index fff9786..c2534d6 100644 (file)
@@ -88,13 +88,14 @@ static int gpiod_request(struct gpio_desc *desc, const char *label);
 static void gpiod_free(struct gpio_desc *desc);
 static int gpiod_direction_input(struct gpio_desc *desc);
 static int gpiod_direction_output(struct gpio_desc *desc, int value);
+static int gpiod_get_direction(const struct gpio_desc *desc);
 static int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce);
-static int gpiod_get_value_cansleep(struct gpio_desc *desc);
+static int gpiod_get_value_cansleep(const struct gpio_desc *desc);
 static void gpiod_set_value_cansleep(struct gpio_desc *desc, int value);
-static int gpiod_get_value(struct gpio_desc *desc);
+static int gpiod_get_value(const struct gpio_desc *desc);
 static void gpiod_set_value(struct gpio_desc *desc, int value);
-static int gpiod_cansleep(struct gpio_desc *desc);
-static int gpiod_to_irq(struct gpio_desc *desc);
+static int gpiod_cansleep(const struct gpio_desc *desc);
+static int gpiod_to_irq(const struct gpio_desc *desc);
 static int gpiod_export(struct gpio_desc *desc, bool direction_may_change);
 static int gpiod_export_link(struct device *dev, const char *name,
                             struct gpio_desc *desc);
@@ -171,12 +172,12 @@ static int gpio_ensure_requested(struct gpio_desc *desc)
        return 0;
 }
 
-/* caller holds gpio_lock *OR* gpio is marked as requested */
-static struct gpio_chip *gpiod_to_chip(struct gpio_desc *desc)
+static struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc)
 {
-       return desc->chip;
+       return desc ? desc->chip : NULL;
 }
 
+/* caller holds gpio_lock *OR* gpio is marked as requested */
 struct gpio_chip *gpio_to_chip(unsigned gpio)
 {
        return gpiod_to_chip(gpio_to_desc(gpio));
@@ -207,7 +208,7 @@ static int gpiochip_find_base(int ngpio)
 }
 
 /* caller ensures gpio is valid and requested, chip->get_direction may sleep  */
-static int gpiod_get_direction(struct gpio_desc *desc)
+static int gpiod_get_direction(const struct gpio_desc *desc)
 {
        struct gpio_chip        *chip;
        unsigned                offset;
@@ -223,11 +224,13 @@ static int gpiod_get_direction(struct gpio_desc *desc)
        if (status > 0) {
                /* GPIOF_DIR_IN, or other positive */
                status = 1;
-               clear_bit(FLAG_IS_OUT, &desc->flags);
+               /* FLAG_IS_OUT is just a cache of the result of get_direction(),
+                * so it does not affect constness per se */
+               clear_bit(FLAG_IS_OUT, &((struct gpio_desc *)desc)->flags);
        }
        if (status == 0) {
                /* GPIOF_DIR_OUT */
-               set_bit(FLAG_IS_OUT, &desc->flags);
+               set_bit(FLAG_IS_OUT, &((struct gpio_desc *)desc)->flags);
        }
        return status;
 }
@@ -263,7 +266,7 @@ static DEFINE_MUTEX(sysfs_lock);
 static ssize_t gpio_direction_show(struct device *dev,
                struct device_attribute *attr, char *buf)
 {
-       struct gpio_desc        *desc = dev_get_drvdata(dev);
+       const struct gpio_desc  *desc = dev_get_drvdata(dev);
        ssize_t                 status;
 
        mutex_lock(&sysfs_lock);
@@ -654,6 +657,11 @@ static ssize_t export_store(struct class *class,
                goto done;
 
        desc = gpio_to_desc(gpio);
+       /* reject invalid GPIOs */
+       if (!desc) {
+               pr_warn("%s: invalid GPIO %ld\n", __func__, gpio);
+               return -EINVAL;
+       }
 
        /* No extra locking here; FLAG_SYSFS just signifies that the
         * request and export were done by on behalf of userspace, so
@@ -690,12 +698,14 @@ static ssize_t unexport_store(struct class *class,
        if (status < 0)
                goto done;
 
-       status = -EINVAL;
-
        desc = gpio_to_desc(gpio);
        /* reject bogus commands (gpio_unexport ignores them) */
-       if (!desc)
-               goto done;
+       if (!desc) {
+               pr_warn("%s: invalid GPIO %ld\n", __func__, gpio);
+               return -EINVAL;
+       }
+
+       status = -EINVAL;
 
        /* No extra locking here; FLAG_SYSFS just signifies that the
         * request and export were done by on behalf of userspace, so
@@ -846,8 +856,10 @@ static int gpiod_export_link(struct device *dev, const char *name,
 {
        int                     status = -EINVAL;
 
-       if (!desc)
-               goto done;
+       if (!desc) {
+               pr_warn("%s: invalid GPIO\n", __func__);
+               return -EINVAL;
+       }
 
        mutex_lock(&sysfs_lock);
 
@@ -865,7 +877,6 @@ static int gpiod_export_link(struct device *dev, const char *name,
 
        mutex_unlock(&sysfs_lock);
 
-done:
        if (status)
                pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc),
                         status);
@@ -896,8 +907,10 @@ static int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value)
        struct device           *dev = NULL;
        int                     status = -EINVAL;
 
-       if (!desc)
-               goto done;
+       if (!desc) {
+               pr_warn("%s: invalid GPIO\n", __func__);
+               return -EINVAL;
+       }
 
        mutex_lock(&sysfs_lock);
 
@@ -914,7 +927,6 @@ static int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value)
 unlock:
        mutex_unlock(&sysfs_lock);
 
-done:
        if (status)
                pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc),
                         status);
@@ -940,8 +952,8 @@ static void gpiod_unexport(struct gpio_desc *desc)
        struct device           *dev = NULL;
 
        if (!desc) {
-               status = -EINVAL;
-               goto done;
+               pr_warn("%s: invalid GPIO\n", __func__);
+               return;
        }
 
        mutex_lock(&sysfs_lock);
@@ -962,7 +974,7 @@ static void gpiod_unexport(struct gpio_desc *desc)
                device_unregister(dev);
                put_device(dev);
        }
-done:
+
        if (status)
                pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc),
                         status);
@@ -1384,12 +1396,13 @@ static int gpiod_request(struct gpio_desc *desc, const char *label)
        int                     status = -EPROBE_DEFER;
        unsigned long           flags;
 
-       spin_lock_irqsave(&gpio_lock, flags);
-
        if (!desc) {
-               status = -EINVAL;
-               goto done;
+               pr_warn("%s: invalid GPIO\n", __func__);
+               return -EINVAL;
        }
+
+       spin_lock_irqsave(&gpio_lock, flags);
+
        chip = desc->chip;
        if (chip == NULL)
                goto done;
@@ -1432,8 +1445,7 @@ static int gpiod_request(struct gpio_desc *desc, const char *label)
 done:
        if (status)
                pr_debug("_gpio_request: gpio-%d (%s) status %d\n",
-                        desc ? desc_to_gpio(desc) : -1,
-                        label ? : "?", status);
+                        desc_to_gpio(desc), label ? : "?", status);
        spin_unlock_irqrestore(&gpio_lock, flags);
        return status;
 }
@@ -1616,10 +1628,13 @@ static int gpiod_direction_input(struct gpio_desc *desc)
        int                     status = -EINVAL;
        int                     offset;
 
+       if (!desc) {
+               pr_warn("%s: invalid GPIO\n", __func__);
+               return -EINVAL;
+       }
+
        spin_lock_irqsave(&gpio_lock, flags);
 
-       if (!desc)
-               goto fail;
        chip = desc->chip;
        if (!chip || !chip->get || !chip->direction_input)
                goto fail;
@@ -1655,13 +1670,9 @@ lose:
        return status;
 fail:
        spin_unlock_irqrestore(&gpio_lock, flags);
-       if (status) {
-               int gpio = -1;
-               if (desc)
-                       gpio = desc_to_gpio(desc);
-               pr_debug("%s: gpio-%d status %d\n",
-                       __func__, gpio, status);
-       }
+       if (status)
+               pr_debug("%s: gpio-%d status %d\n", __func__,
+                        desc_to_gpio(desc), status);
        return status;
 }
 
@@ -1678,6 +1689,11 @@ static int gpiod_direction_output(struct gpio_desc *desc, int value)
        int                     status = -EINVAL;
        int offset;
 
+       if (!desc) {
+               pr_warn("%s: invalid GPIO\n", __func__);
+               return -EINVAL;
+       }
+
        /* Open drain pin should not be driven to 1 */
        if (value && test_bit(FLAG_OPEN_DRAIN,  &desc->flags))
                return gpiod_direction_input(desc);
@@ -1688,8 +1704,6 @@ static int gpiod_direction_output(struct gpio_desc *desc, int value)
 
        spin_lock_irqsave(&gpio_lock, flags);
 
-       if (!desc)
-               goto fail;
        chip = desc->chip;
        if (!chip || !chip->set || !chip->direction_output)
                goto fail;
@@ -1725,13 +1739,9 @@ lose:
        return status;
 fail:
        spin_unlock_irqrestore(&gpio_lock, flags);
-       if (status) {
-               int gpio = -1;
-               if (desc)
-                       gpio = desc_to_gpio(desc);
-               pr_debug("%s: gpio-%d status %d\n",
-                       __func__, gpio, status);
-       }
+       if (status)
+               pr_debug("%s: gpio-%d status %d\n", __func__,
+                        desc_to_gpio(desc), status);
        return status;
 }
 
@@ -1753,10 +1763,13 @@ static int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce)
        int                     status = -EINVAL;
        int                     offset;
 
+       if (!desc) {
+               pr_warn("%s: invalid GPIO\n", __func__);
+               return -EINVAL;
+       }
+
        spin_lock_irqsave(&gpio_lock, flags);
 
-       if (!desc)
-               goto fail;
        chip = desc->chip;
        if (!chip || !chip->set || !chip->set_debounce)
                goto fail;
@@ -1776,13 +1789,9 @@ static int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce)
 
 fail:
        spin_unlock_irqrestore(&gpio_lock, flags);
-       if (status) {
-               int gpio = -1;
-               if (desc)
-                       gpio = desc_to_gpio(desc);
-               pr_debug("%s: gpio-%d status %d\n",
-                       __func__, gpio, status);
-       }
+       if (status)
+               pr_debug("%s: gpio-%d status %d\n", __func__,
+                        desc_to_gpio(desc), status);
 
        return status;
 }
@@ -1824,12 +1833,14 @@ EXPORT_SYMBOL_GPL(gpio_set_debounce);
  * It returns the zero or nonzero value provided by the associated
  * gpio_chip.get() method; or zero if no such method is provided.
  */
-static int gpiod_get_value(struct gpio_desc *desc)
+static int gpiod_get_value(const struct gpio_desc *desc)
 {
        struct gpio_chip        *chip;
        int value;
        int offset;
 
+       if (!desc)
+               return 0;
        chip = desc->chip;
        offset = gpio_chip_hwgpio(desc);
        /* Should be using gpio_get_value_cansleep() */
@@ -1912,6 +1923,8 @@ static void gpiod_set_value(struct gpio_desc *desc, int value)
 {
        struct gpio_chip        *chip;
 
+       if (!desc)
+               return;
        chip = desc->chip;
        /* Should be using gpio_set_value_cansleep() */
        WARN_ON(chip->can_sleep);
@@ -1938,8 +1951,10 @@ EXPORT_SYMBOL_GPL(__gpio_set_value);
  * This is used directly or indirectly to implement gpio_cansleep().  It
  * returns nonzero if access reading or writing the GPIO value can sleep.
  */
-static int gpiod_cansleep(struct gpio_desc *desc)
+static int gpiod_cansleep(const struct gpio_desc *desc)
 {
+       if (!desc)
+               return 0;
        /* only call this on GPIOs that are valid! */
        return desc->chip->can_sleep;
 }
@@ -1959,11 +1974,13 @@ EXPORT_SYMBOL_GPL(__gpio_cansleep);
  * It returns the number of the IRQ signaled by this (input) GPIO,
  * or a negative errno.
  */
-static int gpiod_to_irq(struct gpio_desc *desc)
+static int gpiod_to_irq(const struct gpio_desc *desc)
 {
        struct gpio_chip        *chip;
        int                     offset;
 
+       if (!desc)
+               return -EINVAL;
        chip = desc->chip;
        offset = gpio_chip_hwgpio(desc);
        return chip->to_irq ? chip->to_irq(chip, offset) : -ENXIO;
@@ -1980,13 +1997,15 @@ EXPORT_SYMBOL_GPL(__gpio_to_irq);
  * Common examples include ones connected to I2C or SPI chips.
  */
 
-static int gpiod_get_value_cansleep(struct gpio_desc *desc)
+static int gpiod_get_value_cansleep(const struct gpio_desc *desc)
 {
        struct gpio_chip        *chip;
        int value;
        int offset;
 
        might_sleep_if(extra_checks);
+       if (!desc)
+               return 0;
        chip = desc->chip;
        offset = gpio_chip_hwgpio(desc);
        value = chip->get ? chip->get(chip, offset) : 0;
@@ -2005,6 +2024,8 @@ static void gpiod_set_value_cansleep(struct gpio_desc *desc, int value)
        struct gpio_chip        *chip;
 
        might_sleep_if(extra_checks);
+       if (!desc)
+               return;
        chip = desc->chip;
        trace_gpio_value(desc_to_gpio(desc), 0, value);
        if (test_bit(FLAG_OPEN_DRAIN,  &desc->flags))
index c5b8c81..0a8eceb 100644 (file)
@@ -379,15 +379,15 @@ static const struct pci_device_id pciidlist[] = {         /* aka */
        INTEL_VGA_DEVICE(0x0A06, &intel_haswell_m_info), /* ULT GT1 mobile */
        INTEL_VGA_DEVICE(0x0A16, &intel_haswell_m_info), /* ULT GT2 mobile */
        INTEL_VGA_DEVICE(0x0A26, &intel_haswell_m_info), /* ULT GT2 mobile */
-       INTEL_VGA_DEVICE(0x0D12, &intel_haswell_d_info), /* CRW GT1 desktop */
+       INTEL_VGA_DEVICE(0x0D02, &intel_haswell_d_info), /* CRW GT1 desktop */
+       INTEL_VGA_DEVICE(0x0D12, &intel_haswell_d_info), /* CRW GT2 desktop */
        INTEL_VGA_DEVICE(0x0D22, &intel_haswell_d_info), /* CRW GT2 desktop */
-       INTEL_VGA_DEVICE(0x0D32, &intel_haswell_d_info), /* CRW GT2 desktop */
-       INTEL_VGA_DEVICE(0x0D1A, &intel_haswell_d_info), /* CRW GT1 server */
+       INTEL_VGA_DEVICE(0x0D0A, &intel_haswell_d_info), /* CRW GT1 server */
+       INTEL_VGA_DEVICE(0x0D1A, &intel_haswell_d_info), /* CRW GT2 server */
        INTEL_VGA_DEVICE(0x0D2A, &intel_haswell_d_info), /* CRW GT2 server */
-       INTEL_VGA_DEVICE(0x0D3A, &intel_haswell_d_info), /* CRW GT2 server */
-       INTEL_VGA_DEVICE(0x0D16, &intel_haswell_m_info), /* CRW GT1 mobile */
+       INTEL_VGA_DEVICE(0x0D06, &intel_haswell_m_info), /* CRW GT1 mobile */
+       INTEL_VGA_DEVICE(0x0D16, &intel_haswell_m_info), /* CRW GT2 mobile */
        INTEL_VGA_DEVICE(0x0D26, &intel_haswell_m_info), /* CRW GT2 mobile */
-       INTEL_VGA_DEVICE(0x0D36, &intel_haswell_m_info), /* CRW GT2 mobile */
        INTEL_VGA_DEVICE(0x0f30, &intel_valleyview_m_info),
        INTEL_VGA_DEVICE(0x0157, &intel_valleyview_m_info),
        INTEL_VGA_DEVICE(0x0155, &intel_valleyview_d_info),
@@ -495,6 +495,7 @@ static int i915_drm_freeze(struct drm_device *dev)
                intel_modeset_disable(dev);
 
                drm_irq_uninstall(dev);
+               dev_priv->enable_hotplug_processing = false;
        }
 
        i915_save_state(dev);
@@ -568,10 +569,20 @@ static int __i915_drm_thaw(struct drm_device *dev)
                error = i915_gem_init_hw(dev);
                mutex_unlock(&dev->struct_mutex);
 
+               /* We need working interrupts for modeset enabling ... */
+               drm_irq_install(dev);
+
                intel_modeset_init_hw(dev);
                intel_modeset_setup_hw_state(dev, false);
-               drm_irq_install(dev);
+
+               /*
+                * ... but also need to make sure that hotplug processing
+                * doesn't cause havoc. Like in the driver load code we don't
+                * bother with the tiny race here where we might loose hotplug
+                * notifications.
+                * */
                intel_hpd_init(dev);
+               dev_priv->enable_hotplug_processing = true;
        }
 
        intel_opregion_init(dev);
index 2cd97d1..3c7bb04 100644 (file)
@@ -701,7 +701,7 @@ static irqreturn_t ivybridge_irq_handler(int irq, void *arg)
 {
        struct drm_device *dev = (struct drm_device *) arg;
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-       u32 de_iir, gt_iir, de_ier, pm_iir;
+       u32 de_iir, gt_iir, de_ier, pm_iir, sde_ier;
        irqreturn_t ret = IRQ_NONE;
        int i;
 
@@ -711,6 +711,15 @@ static irqreturn_t ivybridge_irq_handler(int irq, void *arg)
        de_ier = I915_READ(DEIER);
        I915_WRITE(DEIER, de_ier & ~DE_MASTER_IRQ_CONTROL);
 
+       /* Disable south interrupts. We'll only write to SDEIIR once, so further
+        * interrupts will will be stored on its back queue, and then we'll be
+        * able to process them after we restore SDEIER (as soon as we restore
+        * it, we'll get an interrupt if SDEIIR still has something to process
+        * due to its back queue). */
+       sde_ier = I915_READ(SDEIER);
+       I915_WRITE(SDEIER, 0);
+       POSTING_READ(SDEIER);
+
        gt_iir = I915_READ(GTIIR);
        if (gt_iir) {
                snb_gt_irq_handler(dev, dev_priv, gt_iir);
@@ -759,6 +768,8 @@ static irqreturn_t ivybridge_irq_handler(int irq, void *arg)
 
        I915_WRITE(DEIER, de_ier);
        POSTING_READ(DEIER);
+       I915_WRITE(SDEIER, sde_ier);
+       POSTING_READ(SDEIER);
 
        return ret;
 }
@@ -778,7 +789,7 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg)
        struct drm_device *dev = (struct drm_device *) arg;
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
        int ret = IRQ_NONE;
-       u32 de_iir, gt_iir, de_ier, pm_iir;
+       u32 de_iir, gt_iir, de_ier, pm_iir, sde_ier;
 
        atomic_inc(&dev_priv->irq_received);
 
@@ -787,6 +798,15 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg)
        I915_WRITE(DEIER, de_ier & ~DE_MASTER_IRQ_CONTROL);
        POSTING_READ(DEIER);
 
+       /* Disable south interrupts. We'll only write to SDEIIR once, so further
+        * interrupts will will be stored on its back queue, and then we'll be
+        * able to process them after we restore SDEIER (as soon as we restore
+        * it, we'll get an interrupt if SDEIIR still has something to process
+        * due to its back queue). */
+       sde_ier = I915_READ(SDEIER);
+       I915_WRITE(SDEIER, 0);
+       POSTING_READ(SDEIER);
+
        de_iir = I915_READ(DEIIR);
        gt_iir = I915_READ(GTIIR);
        pm_iir = I915_READ(GEN6_PMIIR);
@@ -849,6 +869,8 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg)
 done:
        I915_WRITE(DEIER, de_ier);
        POSTING_READ(DEIER);
+       I915_WRITE(SDEIER, sde_ier);
+       POSTING_READ(SDEIER);
 
        return ret;
 }
index 527b664..848992f 100644 (file)
 #define   ADPA_CRT_HOTPLUG_FORCE_TRIGGER (1<<16)
 #define   ADPA_USE_VGA_HVPOLARITY (1<<15)
 #define   ADPA_SETS_HVPOLARITY 0
-#define   ADPA_VSYNC_CNTL_DISABLE (1<<11)
+#define   ADPA_VSYNC_CNTL_DISABLE (1<<10)
 #define   ADPA_VSYNC_CNTL_ENABLE 0
-#define   ADPA_HSYNC_CNTL_DISABLE (1<<10)
+#define   ADPA_HSYNC_CNTL_DISABLE (1<<11)
 #define   ADPA_HSYNC_CNTL_ENABLE 0
 #define   ADPA_VSYNC_ACTIVE_HIGH (1<<4)
 #define   ADPA_VSYNC_ACTIVE_LOW        0
index 969d08c..32a3693 100644 (file)
@@ -88,7 +88,7 @@ static void intel_disable_crt(struct intel_encoder *encoder)
        u32 temp;
 
        temp = I915_READ(crt->adpa_reg);
-       temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE);
+       temp |= ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE;
        temp &= ~ADPA_DAC_ENABLE;
        I915_WRITE(crt->adpa_reg, temp);
 }
index d64af5a..8d0bac3 100644 (file)
@@ -1391,8 +1391,8 @@ void intel_ddi_prepare_link_retrain(struct drm_encoder *encoder)
        struct intel_dp *intel_dp = &intel_dig_port->dp;
        struct drm_i915_private *dev_priv = encoder->dev->dev_private;
        enum port port = intel_dig_port->port;
-       bool wait;
        uint32_t val;
+       bool wait = false;
 
        if (I915_READ(DP_TP_CTL(port)) & DP_TP_CTL_ENABLE) {
                val = I915_READ(DDI_BUF_CTL(port));
index a05ac2c..287b42c 100644 (file)
@@ -3604,6 +3604,30 @@ static void intel_crtc_dpms_overlay(struct intel_crtc *intel_crtc, bool enable)
         */
 }
 
+/**
+ * i9xx_fixup_plane - ugly workaround for G45 to fire up the hardware
+ * cursor plane briefly if not already running after enabling the display
+ * plane.
+ * This workaround avoids occasional blank screens when self refresh is
+ * enabled.
+ */
+static void
+g4x_fixup_plane(struct drm_i915_private *dev_priv, enum pipe pipe)
+{
+       u32 cntl = I915_READ(CURCNTR(pipe));
+
+       if ((cntl & CURSOR_MODE) == 0) {
+               u32 fw_bcl_self = I915_READ(FW_BLC_SELF);
+
+               I915_WRITE(FW_BLC_SELF, fw_bcl_self & ~FW_BLC_SELF_EN);
+               I915_WRITE(CURCNTR(pipe), CURSOR_MODE_64_ARGB_AX);
+               intel_wait_for_vblank(dev_priv->dev, pipe);
+               I915_WRITE(CURCNTR(pipe), cntl);
+               I915_WRITE(CURBASE(pipe), I915_READ(CURBASE(pipe)));
+               I915_WRITE(FW_BLC_SELF, fw_bcl_self);
+       }
+}
+
 static void i9xx_crtc_enable(struct drm_crtc *crtc)
 {
        struct drm_device *dev = crtc->dev;
@@ -3629,6 +3653,8 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
 
        intel_enable_pipe(dev_priv, pipe, false);
        intel_enable_plane(dev_priv, plane, pipe);
+       if (IS_G4X(dev))
+               g4x_fixup_plane(dev_priv, pipe);
 
        intel_crtc_load_lut(crtc);
        intel_update_fbc(dev);
@@ -7256,8 +7282,8 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
 {
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_framebuffer *intel_fb;
-       struct drm_i915_gem_object *obj;
+       struct drm_framebuffer *old_fb = crtc->fb;
+       struct drm_i915_gem_object *obj = to_intel_framebuffer(fb)->obj;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        struct intel_unpin_work *work;
        unsigned long flags;
@@ -7282,8 +7308,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
 
        work->event = event;
        work->crtc = crtc;
-       intel_fb = to_intel_framebuffer(crtc->fb);
-       work->old_fb_obj = intel_fb->obj;
+       work->old_fb_obj = to_intel_framebuffer(old_fb)->obj;
        INIT_WORK(&work->work, intel_unpin_work_fn);
 
        ret = drm_vblank_get(dev, intel_crtc->pipe);
@@ -7303,9 +7328,6 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
        intel_crtc->unpin_work = work;
        spin_unlock_irqrestore(&dev->event_lock, flags);
 
-       intel_fb = to_intel_framebuffer(fb);
-       obj = intel_fb->obj;
-
        if (atomic_read(&intel_crtc->unpin_work_count) >= 2)
                flush_workqueue(dev_priv->wq);
 
@@ -7340,6 +7362,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
 
 cleanup_pending:
        atomic_dec(&intel_crtc->unpin_work_count);
+       crtc->fb = old_fb;
        drm_gem_object_unreference(&work->old_fb_obj->base);
        drm_gem_object_unreference(&obj->base);
        mutex_unlock(&dev->struct_mutex);
index f61cb79..6f728e5 100644 (file)
@@ -353,7 +353,8 @@ intel_dp_aux_wait_done(struct intel_dp *intel_dp, bool has_aux_irq)
 
 #define C (((status = I915_READ_NOTRACE(ch_ctl)) & DP_AUX_CH_CTL_SEND_BUSY) == 0)
        if (has_aux_irq)
-               done = wait_event_timeout(dev_priv->gmbus_wait_queue, C, 10);
+               done = wait_event_timeout(dev_priv->gmbus_wait_queue, C,
+                                         msecs_to_jiffies(10));
        else
                done = wait_for_atomic(C, 10) == 0;
        if (!done)
index 61fee7f..a1794c6 100644 (file)
@@ -2574,7 +2574,7 @@ static void gen6_enable_rps(struct drm_device *dev)
        I915_WRITE(GEN6_RC_SLEEP, 0);
        I915_WRITE(GEN6_RC1e_THRESHOLD, 1000);
        I915_WRITE(GEN6_RC6_THRESHOLD, 50000);
-       I915_WRITE(GEN6_RC6p_THRESHOLD, 100000);
+       I915_WRITE(GEN6_RC6p_THRESHOLD, 150000);
        I915_WRITE(GEN6_RC6pp_THRESHOLD, 64000); /* unused */
 
        /* Check if we are enabling RC6 */
index 5ea5033..4d932c4 100644 (file)
@@ -112,7 +112,6 @@ struct mga_framebuffer {
 struct mga_fbdev {
        struct drm_fb_helper helper;
        struct mga_framebuffer mfb;
-       struct list_head fbdev_list;
        void *sysram;
        int size;
        struct ttm_bo_kmap_obj mapping;
index 5a88ec5..d3dcf54 100644 (file)
@@ -92,6 +92,7 @@ struct mga_i2c_chan *mgag200_i2c_create(struct drm_device *dev)
        int ret;
        int data, clock;
 
+       WREG_DAC(MGA1064_GEN_IO_CTL2, 1);
        WREG_DAC(MGA1064_GEN_IO_DATA, 0xff);
        WREG_DAC(MGA1064_GEN_IO_CTL, 0);
 
index d3d99a2..a274b99 100644 (file)
@@ -1406,6 +1406,14 @@ static int mga_vga_get_modes(struct drm_connector *connector)
 static int mga_vga_mode_valid(struct drm_connector *connector,
                                 struct drm_display_mode *mode)
 {
+       struct drm_device *dev = connector->dev;
+       struct mga_device *mdev = (struct mga_device*)dev->dev_private;
+       struct mga_fbdev *mfbdev = mdev->mfbdev;
+       struct drm_fb_helper *fb_helper = &mfbdev->helper;
+       struct drm_fb_helper_connector *fb_helper_conn = NULL;
+       int bpp = 32;
+       int i = 0;
+
        /* FIXME: Add bandwidth and g200se limitations */
 
        if (mode->crtc_hdisplay > 2048 || mode->crtc_hsync_start > 4096 ||
@@ -1415,6 +1423,25 @@ static int mga_vga_mode_valid(struct drm_connector *connector,
                return MODE_BAD;
        }
 
+       /* Validate the mode input by the user */
+       for (i = 0; i < fb_helper->connector_count; i++) {
+               if (fb_helper->connector_info[i]->connector == connector) {
+                       /* Found the helper for this connector */
+                       fb_helper_conn = fb_helper->connector_info[i];
+                       if (fb_helper_conn->cmdline_mode.specified) {
+                               if (fb_helper_conn->cmdline_mode.bpp_specified) {
+                                       bpp = fb_helper_conn->cmdline_mode.bpp;
+                               }
+                       }
+               }
+       }
+
+       if ((mode->hdisplay * mode->vdisplay * (bpp/8)) > mdev->mc.vram_size) {
+               if (fb_helper_conn)
+                       fb_helper_conn->cmdline_mode.specified = false;
+               return MODE_BAD;
+       }
+
        return MODE_OK;
 }
 
index 5fa1326..02e369f 100644 (file)
@@ -544,13 +544,13 @@ nv50_disp_curs_ofuncs = {
 static void
 nv50_disp_base_vblank_enable(struct nouveau_event *event, int head)
 {
-       nv_mask(event->priv, 0x61002c, (1 << head), (1 << head));
+       nv_mask(event->priv, 0x61002c, (4 << head), (4 << head));
 }
 
 static void
 nv50_disp_base_vblank_disable(struct nouveau_event *event, int head)
 {
-       nv_mask(event->priv, 0x61002c, (1 << head), (0 << head));
+       nv_mask(event->priv, 0x61002c, (4 << head), 0);
 }
 
 static int
index 61cec0f..4857f91 100644 (file)
@@ -350,7 +350,7 @@ nve0_graph_init_gpc_0(struct nvc0_graph_priv *priv)
                nv_wr32(priv, GPC_UNIT(gpc, 0x0918), magicgpc918);
        }
 
-       nv_wr32(priv, GPC_BCAST(0x1bd4), magicgpc918);
+       nv_wr32(priv, GPC_BCAST(0x3fd4), magicgpc918);
        nv_wr32(priv, GPC_BCAST(0x08ac), nv_rd32(priv, 0x100800));
 }
 
index 2cc1e6a..9c41b58 100644 (file)
@@ -869,7 +869,7 @@ init_idx_addr_latched(struct nvbios_init *init)
                init->offset += 2;
 
                init_wr32(init, dreg, idata);
-               init_mask(init, creg, ~mask, data | idata);
+               init_mask(init, creg, ~mask, data | iaddr);
        }
 }
 
index a114a0e..2e98e8a 100644 (file)
@@ -142,6 +142,7 @@ nouveau_i2c_port_create_(struct nouveau_object *parent,
        /* drop port's i2c subdev refcount, i2c handles this itself */
        if (ret == 0) {
                list_add_tail(&port->head, &i2c->ports);
+               atomic_dec(&parent->refcount);
                atomic_dec(&engine->refcount);
        }
 
index 4124192..3b6dc88 100644 (file)
@@ -116,6 +116,11 @@ nouveau_abi16_chan_fini(struct nouveau_abi16 *abi16,
 {
        struct nouveau_abi16_ntfy *ntfy, *temp;
 
+       /* wait for all activity to stop before releasing notify object, which
+        * may be still in use */
+       if (chan->chan && chan->ntfy)
+               nouveau_channel_idle(chan->chan);
+
        /* cleanup notifier state */
        list_for_each_entry_safe(ntfy, temp, &chan->notifiers, head) {
                nouveau_abi16_ntfy_fini(chan, ntfy);
index d28430c..6e7a55f 100644 (file)
@@ -47,6 +47,18 @@ nouveau_agp_enabled(struct nouveau_drm *drm)
        if (drm->agp.stat == UNKNOWN) {
                if (!nouveau_agpmode)
                        return false;
+#ifdef __powerpc__
+               /* Disable AGP by default on all PowerPC machines for
+                * now -- At least some UniNorth-2 AGP bridges are
+                * known to be broken: DMA from the host to the card
+                * works just fine, but writeback from the card to the
+                * host goes straight to memory untranslated bypassing
+                * the GATT somehow, making them quite painful to deal
+                * with...
+                */
+               if (nouveau_agpmode == -1)
+                       return false;
+#endif
                return true;
        }
 
index 11ca821..7ff1071 100644 (file)
@@ -801,7 +801,7 @@ nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
                stride  = 16 * 4;
                height  = amount / stride;
 
-               if (new_mem->mem_type == TTM_PL_VRAM &&
+               if (old_mem->mem_type == TTM_PL_VRAM &&
                    nouveau_bo_tile_layout(nvbo)) {
                        ret = RING_SPACE(chan, 8);
                        if (ret)
@@ -823,7 +823,7 @@ nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
                        BEGIN_NV04(chan, NvSubCopy, 0x0200, 1);
                        OUT_RING  (chan, 1);
                }
-               if (old_mem->mem_type == TTM_PL_VRAM &&
+               if (new_mem->mem_type == TTM_PL_VRAM &&
                    nouveau_bo_tile_layout(nvbo)) {
                        ret = RING_SPACE(chan, 8);
                        if (ret)
index a6237c9..2db5799 100644 (file)
@@ -55,9 +55,9 @@
 
 /* offsets in shared sync bo of various structures */
 #define EVO_SYNC(c, o) ((c) * 0x0100 + (o))
-#define EVO_MAST_NTFY     EVO_SYNC(  0, 0x00)
-#define EVO_FLIP_SEM0(c)  EVO_SYNC((c), 0x00)
-#define EVO_FLIP_SEM1(c)  EVO_SYNC((c), 0x10)
+#define EVO_MAST_NTFY     EVO_SYNC(      0, 0x00)
+#define EVO_FLIP_SEM0(c)  EVO_SYNC((c) + 1, 0x00)
+#define EVO_FLIP_SEM1(c)  EVO_SYNC((c) + 1, 0x10)
 
 #define EVO_CORE_HANDLE      (0xd1500000)
 #define EVO_CHAN_HANDLE(t,i) (0xd15c0000 | (((t) & 0x00ff) << 8) | (i))
@@ -341,10 +341,8 @@ struct nv50_curs {
 
 struct nv50_sync {
        struct nv50_dmac base;
-       struct {
-               u32 offset;
-               u16 value;
-       } sem;
+       u32 addr;
+       u32 data;
 };
 
 struct nv50_ovly {
@@ -471,13 +469,33 @@ nv50_display_crtc_sema(struct drm_device *dev, int crtc)
        return nv50_disp(dev)->sync;
 }
 
+struct nv50_display_flip {
+       struct nv50_disp *disp;
+       struct nv50_sync *chan;
+};
+
+static bool
+nv50_display_flip_wait(void *data)
+{
+       struct nv50_display_flip *flip = data;
+       if (nouveau_bo_rd32(flip->disp->sync, flip->chan->addr / 4) ==
+                                             flip->chan->data);
+               return true;
+       usleep_range(1, 2);
+       return false;
+}
+
 void
 nv50_display_flip_stop(struct drm_crtc *crtc)
 {
-       struct nv50_sync *sync = nv50_sync(crtc);
+       struct nouveau_device *device = nouveau_dev(crtc->dev);
+       struct nv50_display_flip flip = {
+               .disp = nv50_disp(crtc->dev),
+               .chan = nv50_sync(crtc),
+       };
        u32 *push;
 
-       push = evo_wait(sync, 8);
+       push = evo_wait(flip.chan, 8);
        if (push) {
                evo_mthd(push, 0x0084, 1);
                evo_data(push, 0x00000000);
@@ -487,8 +505,10 @@ nv50_display_flip_stop(struct drm_crtc *crtc)
                evo_data(push, 0x00000000);
                evo_mthd(push, 0x0080, 1);
                evo_data(push, 0x00000000);
-               evo_kick(push, sync);
+               evo_kick(push, flip.chan);
        }
+
+       nv_wait_cb(device, nv50_display_flip_wait, &flip);
 }
 
 int
@@ -496,11 +516,10 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,
                       struct nouveau_channel *chan, u32 swap_interval)
 {
        struct nouveau_framebuffer *nv_fb = nouveau_framebuffer(fb);
-       struct nv50_disp *disp = nv50_disp(crtc->dev);
        struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
        struct nv50_sync *sync = nv50_sync(crtc);
+       int head = nv_crtc->index, ret;
        u32 *push;
-       int ret;
 
        swap_interval <<= 4;
        if (swap_interval == 0)
@@ -510,58 +529,64 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,
        if (unlikely(push == NULL))
                return -EBUSY;
 
-       /* synchronise with the rendering channel, if necessary */
-       if (likely(chan)) {
+       if (chan && nv_mclass(chan->object) < NV84_CHANNEL_IND_CLASS) {
+               ret = RING_SPACE(chan, 8);
+               if (ret)
+                       return ret;
+
+               BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 2);
+               OUT_RING  (chan, NvEvoSema0 + head);
+               OUT_RING  (chan, sync->addr ^ 0x10);
+               BEGIN_NV04(chan, 0, NV11_SUBCHAN_SEMAPHORE_RELEASE, 1);
+               OUT_RING  (chan, sync->data + 1);
+               BEGIN_NV04(chan, 0, NV11_SUBCHAN_SEMAPHORE_OFFSET, 2);
+               OUT_RING  (chan, sync->addr);
+               OUT_RING  (chan, sync->data);
+       } else
+       if (chan && nv_mclass(chan->object) < NVC0_CHANNEL_IND_CLASS) {
+               u64 addr = nv84_fence_crtc(chan, head) + sync->addr;
+               ret = RING_SPACE(chan, 12);
+               if (ret)
+                       return ret;
+
+               BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 1);
+               OUT_RING  (chan, chan->vram);
+               BEGIN_NV04(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4);
+               OUT_RING  (chan, upper_32_bits(addr ^ 0x10));
+               OUT_RING  (chan, lower_32_bits(addr ^ 0x10));
+               OUT_RING  (chan, sync->data + 1);
+               OUT_RING  (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_WRITE_LONG);
+               BEGIN_NV04(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4);
+               OUT_RING  (chan, upper_32_bits(addr));
+               OUT_RING  (chan, lower_32_bits(addr));
+               OUT_RING  (chan, sync->data);
+               OUT_RING  (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_ACQUIRE_EQUAL);
+       } else
+       if (chan) {
+               u64 addr = nv84_fence_crtc(chan, head) + sync->addr;
                ret = RING_SPACE(chan, 10);
                if (ret)
                        return ret;
 
-               if (nv_mclass(chan->object) < NV84_CHANNEL_IND_CLASS) {
-                       BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 2);
-                       OUT_RING  (chan, NvEvoSema0 + nv_crtc->index);
-                       OUT_RING  (chan, sync->sem.offset);
-                       BEGIN_NV04(chan, 0, NV11_SUBCHAN_SEMAPHORE_RELEASE, 1);
-                       OUT_RING  (chan, 0xf00d0000 | sync->sem.value);
-                       BEGIN_NV04(chan, 0, NV11_SUBCHAN_SEMAPHORE_OFFSET, 2);
-                       OUT_RING  (chan, sync->sem.offset ^ 0x10);
-                       OUT_RING  (chan, 0x74b1e000);
-                       BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 1);
-                       OUT_RING  (chan, NvSema);
-               } else
-               if (nv_mclass(chan->object) < NVC0_CHANNEL_IND_CLASS) {
-                       u64 offset = nv84_fence_crtc(chan, nv_crtc->index);
-                       offset += sync->sem.offset;
-
-                       BEGIN_NV04(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4);
-                       OUT_RING  (chan, upper_32_bits(offset));
-                       OUT_RING  (chan, lower_32_bits(offset));
-                       OUT_RING  (chan, 0xf00d0000 | sync->sem.value);
-                       OUT_RING  (chan, 0x00000002);
-                       BEGIN_NV04(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4);
-                       OUT_RING  (chan, upper_32_bits(offset));
-                       OUT_RING  (chan, lower_32_bits(offset ^ 0x10));
-                       OUT_RING  (chan, 0x74b1e000);
-                       OUT_RING  (chan, 0x00000001);
-               } else {
-                       u64 offset = nv84_fence_crtc(chan, nv_crtc->index);
-                       offset += sync->sem.offset;
-
-                       BEGIN_NVC0(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4);
-                       OUT_RING  (chan, upper_32_bits(offset));
-                       OUT_RING  (chan, lower_32_bits(offset));
-                       OUT_RING  (chan, 0xf00d0000 | sync->sem.value);
-                       OUT_RING  (chan, 0x00001002);
-                       BEGIN_NVC0(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4);
-                       OUT_RING  (chan, upper_32_bits(offset));
-                       OUT_RING  (chan, lower_32_bits(offset ^ 0x10));
-                       OUT_RING  (chan, 0x74b1e000);
-                       OUT_RING  (chan, 0x00001001);
-               }
+               BEGIN_NVC0(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4);
+               OUT_RING  (chan, upper_32_bits(addr ^ 0x10));
+               OUT_RING  (chan, lower_32_bits(addr ^ 0x10));
+               OUT_RING  (chan, sync->data + 1);
+               OUT_RING  (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_WRITE_LONG |
+                                NVC0_SUBCHAN_SEMAPHORE_TRIGGER_YIELD);
+               BEGIN_NVC0(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4);
+               OUT_RING  (chan, upper_32_bits(addr));
+               OUT_RING  (chan, lower_32_bits(addr));
+               OUT_RING  (chan, sync->data);
+               OUT_RING  (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_ACQUIRE_EQUAL |
+                                NVC0_SUBCHAN_SEMAPHORE_TRIGGER_YIELD);
+       }
 
+       if (chan) {
+               sync->addr ^= 0x10;
+               sync->data++;
                FIRE_RING (chan);
        } else {
-               nouveau_bo_wr32(disp->sync, sync->sem.offset / 4,
-                               0xf00d0000 | sync->sem.value);
                evo_sync(crtc->dev);
        }
 
@@ -575,9 +600,9 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,
                evo_data(push, 0x40000000);
        }
        evo_mthd(push, 0x0088, 4);
-       evo_data(push, sync->sem.offset);
-       evo_data(push, 0xf00d0000 | sync->sem.value);
-       evo_data(push, 0x74b1e000);
+       evo_data(push, sync->addr);
+       evo_data(push, sync->data++);
+       evo_data(push, sync->data);
        evo_data(push, NvEvoSync);
        evo_mthd(push, 0x00a0, 2);
        evo_data(push, 0x00000000);
@@ -605,9 +630,6 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,
        evo_mthd(push, 0x0080, 1);
        evo_data(push, 0x00000000);
        evo_kick(push, sync);
-
-       sync->sem.offset ^= 0x10;
-       sync->sem.value++;
        return 0;
 }
 
@@ -1379,7 +1401,8 @@ nv50_crtc_create(struct drm_device *dev, struct nouveau_object *core, int index)
        if (ret)
                goto out;
 
-       head->sync.sem.offset = EVO_SYNC(1 + index, 0x00);
+       head->sync.addr = EVO_FLIP_SEM0(index);
+       head->sync.data = 0x00000000;
 
        /* allocate overlay resources */
        ret = nv50_pioc_create(disp->core, NV50_DISP_OIMM_CLASS, index,
@@ -2112,15 +2135,23 @@ nv50_display_fini(struct drm_device *dev)
 int
 nv50_display_init(struct drm_device *dev)
 {
-       u32 *push = evo_wait(nv50_mast(dev), 32);
-       if (push) {
-               evo_mthd(push, 0x0088, 1);
-               evo_data(push, NvEvoSync);
-               evo_kick(push, nv50_mast(dev));
-               return 0;
+       struct nv50_disp *disp = nv50_disp(dev);
+       struct drm_crtc *crtc;
+       u32 *push;
+
+       push = evo_wait(nv50_mast(dev), 32);
+       if (!push)
+               return -EBUSY;
+
+       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+               struct nv50_sync *sync = nv50_sync(crtc);
+               nouveau_bo_wr32(disp->sync, sync->addr / 4, sync->data);
        }
 
-       return -EBUSY;
+       evo_mthd(push, 0x0088, 1);
+       evo_data(push, NvEvoSync);
+       evo_kick(push, nv50_mast(dev));
+       return 0;
 }
 
 void
@@ -2245,6 +2276,7 @@ nv50_display_create(struct drm_device *dev)
                        NV_WARN(drm, "failed to create encoder %d/%d/%d: %d\n",
                                     dcbe->location, dcbe->type,
                                     ffs(dcbe->or) - 1, ret);
+                       ret = 0;
                }
        }
 
index 3c38ea4..305a657 100644 (file)
@@ -2438,6 +2438,12 @@ static u32 evergreen_gpu_check_soft_reset(struct radeon_device *rdev)
        if (tmp & L2_BUSY)
                reset_mask |= RADEON_RESET_VMC;
 
+       /* Skip MC reset as it's mostly likely not hung, just busy */
+       if (reset_mask & RADEON_RESET_MC) {
+               DRM_DEBUG("MC busy: 0x%08X, clearing.\n", reset_mask);
+               reset_mask &= ~RADEON_RESET_MC;
+       }
+
        return reset_mask;
 }
 
index 99fb132..eb8ac31 100644 (file)
@@ -834,7 +834,7 @@ static int evergreen_cs_track_validate_texture(struct radeon_cs_parser *p,
                         __func__, __LINE__, toffset, surf.base_align);
                return -EINVAL;
        }
-       if (moffset & (surf.base_align - 1)) {
+       if (surf.nsamples <= 1 && moffset & (surf.base_align - 1)) {
                dev_warn(p->dev, "%s:%d mipmap bo base %ld not aligned with %ld\n",
                         __func__, __LINE__, moffset, surf.base_align);
                return -EINVAL;
index 7cead76..d4c633e 100644 (file)
@@ -1381,6 +1381,12 @@ static u32 cayman_gpu_check_soft_reset(struct radeon_device *rdev)
        if (tmp & L2_BUSY)
                reset_mask |= RADEON_RESET_VMC;
 
+       /* Skip MC reset as it's mostly likely not hung, just busy */
+       if (reset_mask & RADEON_RESET_MC) {
+               DRM_DEBUG("MC busy: 0x%08X, clearing.\n", reset_mask);
+               reset_mask &= ~RADEON_RESET_MC;
+       }
+
        return reset_mask;
 }
 
index 6d4b561..0740db3 100644 (file)
@@ -1394,6 +1394,12 @@ static u32 r600_gpu_check_soft_reset(struct radeon_device *rdev)
        if (r600_is_display_hung(rdev))
                reset_mask |= RADEON_RESET_DISPLAY;
 
+       /* Skip MC reset as it's mostly likely not hung, just busy */
+       if (reset_mask & RADEON_RESET_MC) {
+               DRM_DEBUG("MC busy: 0x%08X, clearing.\n", reset_mask);
+               reset_mask &= ~RADEON_RESET_MC;
+       }
+
        return reset_mask;
 }
 
index 3e403bd..78edadc 100644 (file)
@@ -970,6 +970,15 @@ struct radeon_encoder_primary_dac *radeon_combios_get_primary_dac_info(struct
                        found = 1;
        }
 
+       /* quirks */
+       /* Radeon 9100 (R200) */
+       if ((dev->pdev->device == 0x514D) &&
+           (dev->pdev->subsystem_vendor == 0x174B) &&
+           (dev->pdev->subsystem_device == 0x7149)) {
+               /* vbios value is bad, use the default */
+               found = 0;
+       }
+
        if (!found) /* fallback to defaults */
                radeon_legacy_get_primary_dac_info_from_table(rdev, p_dac);
 
index 1677584..66a7f0f 100644 (file)
  *   2.27.0 - r600-SI: Add CS ioctl support for async DMA
  *   2.28.0 - r600-eg: Add MEM_WRITE packet support
  *   2.29.0 - R500 FP16 color clear registers
+ *   2.30.0 - fix for FMASK texturing
  */
 #define KMS_DRIVER_MAJOR       2
-#define KMS_DRIVER_MINOR       29
+#define KMS_DRIVER_MINOR       30
 #define KMS_DRIVER_PATCHLEVEL  0
 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
 int radeon_driver_unload_kms(struct drm_device *dev);
index 90374dd..48f80cd 100644 (file)
@@ -400,6 +400,9 @@ void radeon_irq_kms_enable_afmt(struct radeon_device *rdev, int block)
 {
        unsigned long irqflags;
 
+       if (!rdev->ddev->irq_enabled)
+               return;
+
        spin_lock_irqsave(&rdev->irq.lock, irqflags);
        rdev->irq.afmt[block] = true;
        radeon_irq_set(rdev);
@@ -419,6 +422,9 @@ void radeon_irq_kms_disable_afmt(struct radeon_device *rdev, int block)
 {
        unsigned long irqflags;
 
+       if (!rdev->ddev->irq_enabled)
+               return;
+
        spin_lock_irqsave(&rdev->irq.lock, irqflags);
        rdev->irq.afmt[block] = false;
        radeon_irq_set(rdev);
@@ -438,6 +444,9 @@ void radeon_irq_kms_enable_hpd(struct radeon_device *rdev, unsigned hpd_mask)
        unsigned long irqflags;
        int i;
 
+       if (!rdev->ddev->irq_enabled)
+               return;
+
        spin_lock_irqsave(&rdev->irq.lock, irqflags);
        for (i = 0; i < RADEON_MAX_HPD_PINS; ++i)
                rdev->irq.hpd[i] |= !!(hpd_mask & (1 << i));
@@ -458,6 +467,9 @@ void radeon_irq_kms_disable_hpd(struct radeon_device *rdev, unsigned hpd_mask)
        unsigned long irqflags;
        int i;
 
+       if (!rdev->ddev->irq_enabled)
+               return;
+
        spin_lock_irqsave(&rdev->irq.lock, irqflags);
        for (i = 0; i < RADEON_MAX_HPD_PINS; ++i)
                rdev->irq.hpd[i] &= !(hpd_mask & (1 << i));
index 80979ed..9128120 100644 (file)
@@ -2284,6 +2284,12 @@ static u32 si_gpu_check_soft_reset(struct radeon_device *rdev)
        if (tmp & L2_BUSY)
                reset_mask |= RADEON_RESET_VMC;
 
+       /* Skip MC reset as it's mostly likely not hung, just busy */
+       if (reset_mask & RADEON_RESET_MC) {
+               DRM_DEBUG("MC busy: 0x%08X, clearing.\n", reset_mask);
+               reset_mask &= ~RADEON_RESET_MC;
+       }
+
        return reset_mask;
 }
 
index c92955d..be1daf7 100644 (file)
@@ -4,7 +4,6 @@ config DRM_TEGRA
        select DRM_KMS_HELPER
        select DRM_GEM_CMA_HELPER
        select DRM_KMS_CMA_HELPER
-       select DRM_HDMI
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
index 9500f2f..8758f38 100644 (file)
@@ -459,19 +459,25 @@ static int logi_dj_recv_send_report(struct dj_receiver_dev *djrcv_dev,
                                    struct dj_report *dj_report)
 {
        struct hid_device *hdev = djrcv_dev->hdev;
-       int sent_bytes;
+       struct hid_report *report;
+       struct hid_report_enum *output_report_enum;
+       u8 *data = (u8 *)(&dj_report->device_index);
+       int i;
 
-       if (!hdev->hid_output_raw_report) {
-               dev_err(&hdev->dev, "%s:"
-                       "hid_output_raw_report is null\n", __func__);
+       output_report_enum = &hdev->report_enum[HID_OUTPUT_REPORT];
+       report = output_report_enum->report_id_hash[REPORT_ID_DJ_SHORT];
+
+       if (!report) {
+               dev_err(&hdev->dev, "%s: unable to find dj report\n", __func__);
                return -ENODEV;
        }
 
-       sent_bytes = hdev->hid_output_raw_report(hdev, (u8 *) dj_report,
-                                                sizeof(struct dj_report),
-                                                HID_OUTPUT_REPORT);
+       for (i = 0; i < report->field[0]->report_count; i++)
+               report->field[0]->value[i] = data[i];
+
+       usbhid_submit_report(hdev, report, USB_DIR_OUT);
 
-       return (sent_bytes < 0) ? sent_bytes : 0;
+       return 0;
 }
 
 static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev)
index 41df29f..ebbb9f4 100644 (file)
@@ -422,6 +422,7 @@ static struct attribute *pem_input_attributes[] = {
        &sensor_dev_attr_in2_input.dev_attr.attr,
        &sensor_dev_attr_curr1_input.dev_attr.attr,
        &sensor_dev_attr_power1_input.dev_attr.attr,
+       NULL
 };
 
 static const struct attribute_group pem_input_group = {
@@ -432,6 +433,7 @@ static struct attribute *pem_fan_attributes[] = {
        &sensor_dev_attr_fan1_input.dev_attr.attr,
        &sensor_dev_attr_fan2_input.dev_attr.attr,
        &sensor_dev_attr_fan3_input.dev_attr.attr,
+       NULL
 };
 
 static const struct attribute_group pem_fan_group = {
index 9652a2c..6d61307 100644 (file)
@@ -59,10 +59,10 @@ enum chips { ltc2978, ltc3880 };
 struct ltc2978_data {
        enum chips id;
        int vin_min, vin_max;
-       int temp_min, temp_max;
+       int temp_min, temp_max[2];
        int vout_min[8], vout_max[8];
        int iout_max[2];
-       int temp2_max[2];
+       int temp2_max;
        struct pmbus_driver_info info;
 };
 
@@ -113,9 +113,10 @@ static int ltc2978_read_word_data_common(struct i2c_client *client, int page,
                ret = pmbus_read_word_data(client, page,
                                           LTC2978_MFR_TEMPERATURE_PEAK);
                if (ret >= 0) {
-                       if (lin11_to_val(ret) > lin11_to_val(data->temp_max))
-                               data->temp_max = ret;
-                       ret = data->temp_max;
+                       if (lin11_to_val(ret)
+                           > lin11_to_val(data->temp_max[page]))
+                               data->temp_max[page] = ret;
+                       ret = data->temp_max[page];
                }
                break;
        case PMBUS_VIRT_RESET_VOUT_HISTORY:
@@ -204,10 +205,9 @@ static int ltc3880_read_word_data(struct i2c_client *client, int page, int reg)
                ret = pmbus_read_word_data(client, page,
                                           LTC3880_MFR_TEMPERATURE2_PEAK);
                if (ret >= 0) {
-                       if (lin11_to_val(ret)
-                           > lin11_to_val(data->temp2_max[page]))
-                               data->temp2_max[page] = ret;
-                       ret = data->temp2_max[page];
+                       if (lin11_to_val(ret) > lin11_to_val(data->temp2_max))
+                               data->temp2_max = ret;
+                       ret = data->temp2_max;
                }
                break;
        case PMBUS_VIRT_READ_VIN_MIN:
@@ -248,11 +248,11 @@ static int ltc2978_write_word_data(struct i2c_client *client, int page,
 
        switch (reg) {
        case PMBUS_VIRT_RESET_IOUT_HISTORY:
-               data->iout_max[page] = 0x7fff;
+               data->iout_max[page] = 0x7c00;
                ret = ltc2978_clear_peaks(client, page, data->id);
                break;
        case PMBUS_VIRT_RESET_TEMP2_HISTORY:
-               data->temp2_max[page] = 0x7fff;
+               data->temp2_max = 0x7c00;
                ret = ltc2978_clear_peaks(client, page, data->id);
                break;
        case PMBUS_VIRT_RESET_VOUT_HISTORY:
@@ -262,12 +262,12 @@ static int ltc2978_write_word_data(struct i2c_client *client, int page,
                break;
        case PMBUS_VIRT_RESET_VIN_HISTORY:
                data->vin_min = 0x7bff;
-               data->vin_max = 0;
+               data->vin_max = 0x7c00;
                ret = ltc2978_clear_peaks(client, page, data->id);
                break;
        case PMBUS_VIRT_RESET_TEMP_HISTORY:
                data->temp_min = 0x7bff;
-               data->temp_max = 0x7fff;
+               data->temp_max[page] = 0x7c00;
                ret = ltc2978_clear_peaks(client, page, data->id);
                break;
        default:
@@ -321,12 +321,14 @@ static int ltc2978_probe(struct i2c_client *client,
        info = &data->info;
        info->write_word_data = ltc2978_write_word_data;
 
-       data->vout_min[0] = 0xffff;
        data->vin_min = 0x7bff;
+       data->vin_max = 0x7c00;
        data->temp_min = 0x7bff;
-       data->temp_max = 0x7fff;
+       for (i = 0; i < ARRAY_SIZE(data->temp_max); i++)
+               data->temp_max[i] = 0x7c00;
+       data->temp2_max = 0x7c00;
 
-       switch (id->driver_data) {
+       switch (data->id) {
        case ltc2978:
                info->read_word_data = ltc2978_read_word_data;
                info->pages = 8;
@@ -336,7 +338,6 @@ static int ltc2978_probe(struct i2c_client *client,
                for (i = 1; i < 8; i++) {
                        info->func[i] = PMBUS_HAVE_VOUT
                          | PMBUS_HAVE_STATUS_VOUT;
-                       data->vout_min[i] = 0xffff;
                }
                break;
        case ltc3880:
@@ -352,11 +353,14 @@ static int ltc2978_probe(struct i2c_client *client,
                  | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
                  | PMBUS_HAVE_POUT
                  | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
-               data->vout_min[1] = 0xffff;
+               data->iout_max[0] = 0x7c00;
+               data->iout_max[1] = 0x7c00;
                break;
        default:
                return -ENODEV;
        }
+       for (i = 0; i < info->pages; i++)
+               data->vout_min[i] = 0xffff;
 
        return pmbus_do_probe(client, id, info);
 }
index 80eef50..9add609 100644 (file)
@@ -766,12 +766,14 @@ static ssize_t pmbus_show_label(struct device *dev,
 static int pmbus_add_attribute(struct pmbus_data *data, struct attribute *attr)
 {
        if (data->num_attributes >= data->max_attributes - 1) {
-               data->max_attributes += PMBUS_ATTR_ALLOC_SIZE;
-               data->group.attrs = krealloc(data->group.attrs,
-                                            sizeof(struct attribute *) *
-                                            data->max_attributes, GFP_KERNEL);
-               if (data->group.attrs == NULL)
+               int new_max_attrs = data->max_attributes + PMBUS_ATTR_ALLOC_SIZE;
+               void *new_attrs = krealloc(data->group.attrs,
+                                          new_max_attrs * sizeof(void *),
+                                          GFP_KERNEL);
+               if (!new_attrs)
                        return -ENOMEM;
+               data->group.attrs = new_attrs;
+               data->max_attributes = new_max_attrs;
        }
 
        data->group.attrs[data->num_attributes++] = attr;
index bfe326e..2507f90 100644 (file)
@@ -965,7 +965,13 @@ static int sht15_probe(struct platform_device *pdev)
                if (voltage)
                        data->supply_uv = voltage;
 
-               regulator_enable(data->reg);
+               ret = regulator_enable(data->reg);
+               if (ret != 0) {
+                       dev_err(&pdev->dev,
+                               "failed to enable regulator: %d\n", ret);
+                       return ret;
+               }
+
                /*
                 * Setup a notifier block to update this if another device
                 * causes the voltage to change
index 0198324..bd33473 100644 (file)
@@ -62,7 +62,7 @@ st_sensors_match_odr_error:
 int st_sensors_set_odr(struct iio_dev *indio_dev, unsigned int odr)
 {
        int err;
-       struct st_sensor_odr_avl odr_out;
+       struct st_sensor_odr_avl odr_out = {0, 0};
        struct st_sensor_data *sdata = iio_priv(indio_dev);
 
        err = st_sensors_match_odr(sdata->sensor, odr, &odr_out);
@@ -114,7 +114,7 @@ st_sensors_match_odr_error:
 
 static int st_sensors_set_fullscale(struct iio_dev *indio_dev, unsigned int fs)
 {
-       int err, i;
+       int err, i = 0;
        struct st_sensor_data *sdata = iio_priv(indio_dev);
 
        err = st_sensors_match_fs(sdata->sensor, fs, &i);
@@ -139,14 +139,13 @@ st_accel_set_fullscale_error:
 
 int st_sensors_set_enable(struct iio_dev *indio_dev, bool enable)
 {
-       bool found;
        u8 tmp_value;
        int err = -EINVAL;
-       struct st_sensor_odr_avl odr_out;
+       bool found = false;
+       struct st_sensor_odr_avl odr_out = {0, 0};
        struct st_sensor_data *sdata = iio_priv(indio_dev);
 
        if (enable) {
-               found = false;
                tmp_value = sdata->sensor->pw.value_on;
                if ((sdata->sensor->odr.addr == sdata->sensor->pw.addr) &&
                        (sdata->sensor->odr.mask == sdata->sensor->pw.mask)) {
index 2fe1d4e..74f2d52 100644 (file)
@@ -27,7 +27,6 @@
 #define AD5064_ADDR(x)                         ((x) << 20)
 #define AD5064_CMD(x)                          ((x) << 24)
 
-#define AD5064_ADDR_DAC(chan)                  (chan)
 #define AD5064_ADDR_ALL_DAC                    0xF
 
 #define AD5064_CMD_WRITE_INPUT_N               0x0
@@ -131,15 +130,15 @@ static int ad5064_write(struct ad5064_state *st, unsigned int cmd,
 }
 
 static int ad5064_sync_powerdown_mode(struct ad5064_state *st,
-       unsigned int channel)
+       const struct iio_chan_spec *chan)
 {
        unsigned int val;
        int ret;
 
-       val = (0x1 << channel);
+       val = (0x1 << chan->address);
 
-       if (st->pwr_down[channel])
-               val |= st->pwr_down_mode[channel] << 8;
+       if (st->pwr_down[chan->channel])
+               val |= st->pwr_down_mode[chan->channel] << 8;
 
        ret = ad5064_write(st, AD5064_CMD_POWERDOWN_DAC, 0, val, 0);
 
@@ -169,7 +168,7 @@ static int ad5064_set_powerdown_mode(struct iio_dev *indio_dev,
        mutex_lock(&indio_dev->mlock);
        st->pwr_down_mode[chan->channel] = mode + 1;
 
-       ret = ad5064_sync_powerdown_mode(st, chan->channel);
+       ret = ad5064_sync_powerdown_mode(st, chan);
        mutex_unlock(&indio_dev->mlock);
 
        return ret;
@@ -205,7 +204,7 @@ static ssize_t ad5064_write_dac_powerdown(struct iio_dev *indio_dev,
        mutex_lock(&indio_dev->mlock);
        st->pwr_down[chan->channel] = pwr_down;
 
-       ret = ad5064_sync_powerdown_mode(st, chan->channel);
+       ret = ad5064_sync_powerdown_mode(st, chan);
        mutex_unlock(&indio_dev->mlock);
        return ret ? ret : len;
 }
@@ -258,7 +257,7 @@ static int ad5064_write_raw(struct iio_dev *indio_dev,
 
        switch (mask) {
        case IIO_CHAN_INFO_RAW:
-               if (val > (1 << chan->scan_type.realbits) || val < 0)
+               if (val >= (1 << chan->scan_type.realbits) || val < 0)
                        return -EINVAL;
 
                mutex_lock(&indio_dev->mlock);
@@ -292,34 +291,44 @@ static const struct iio_chan_spec_ext_info ad5064_ext_info[] = {
        { },
 };
 
-#define AD5064_CHANNEL(chan, bits) {                           \
+#define AD5064_CHANNEL(chan, addr, bits) {                     \
        .type = IIO_VOLTAGE,                                    \
        .indexed = 1,                                           \
        .output = 1,                                            \
        .channel = (chan),                                      \
        .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |           \
        IIO_CHAN_INFO_SCALE_SEPARATE_BIT,                       \
-       .address = AD5064_ADDR_DAC(chan),                       \
+       .address = addr,                                        \
        .scan_type = IIO_ST('u', (bits), 16, 20 - (bits)),      \
        .ext_info = ad5064_ext_info,                            \
 }
 
 #define DECLARE_AD5064_CHANNELS(name, bits) \
 const struct iio_chan_spec name[] = { \
-       AD5064_CHANNEL(0, bits), \
-       AD5064_CHANNEL(1, bits), \
-       AD5064_CHANNEL(2, bits), \
-       AD5064_CHANNEL(3, bits), \
-       AD5064_CHANNEL(4, bits), \
-       AD5064_CHANNEL(5, bits), \
-       AD5064_CHANNEL(6, bits), \
-       AD5064_CHANNEL(7, bits), \
+       AD5064_CHANNEL(0, 0, bits), \
+       AD5064_CHANNEL(1, 1, bits), \
+       AD5064_CHANNEL(2, 2, bits), \
+       AD5064_CHANNEL(3, 3, bits), \
+       AD5064_CHANNEL(4, 4, bits), \
+       AD5064_CHANNEL(5, 5, bits), \
+       AD5064_CHANNEL(6, 6, bits), \
+       AD5064_CHANNEL(7, 7, bits), \
+}
+
+#define DECLARE_AD5065_CHANNELS(name, bits) \
+const struct iio_chan_spec name[] = { \
+       AD5064_CHANNEL(0, 0, bits), \
+       AD5064_CHANNEL(1, 3, bits), \
 }
 
 static DECLARE_AD5064_CHANNELS(ad5024_channels, 12);
 static DECLARE_AD5064_CHANNELS(ad5044_channels, 14);
 static DECLARE_AD5064_CHANNELS(ad5064_channels, 16);
 
+static DECLARE_AD5065_CHANNELS(ad5025_channels, 12);
+static DECLARE_AD5065_CHANNELS(ad5045_channels, 14);
+static DECLARE_AD5065_CHANNELS(ad5065_channels, 16);
+
 static const struct ad5064_chip_info ad5064_chip_info_tbl[] = {
        [ID_AD5024] = {
                .shared_vref = false,
@@ -328,7 +337,7 @@ static const struct ad5064_chip_info ad5064_chip_info_tbl[] = {
        },
        [ID_AD5025] = {
                .shared_vref = false,
-               .channels = ad5024_channels,
+               .channels = ad5025_channels,
                .num_channels = 2,
        },
        [ID_AD5044] = {
@@ -338,7 +347,7 @@ static const struct ad5064_chip_info ad5064_chip_info_tbl[] = {
        },
        [ID_AD5045] = {
                .shared_vref = false,
-               .channels = ad5044_channels,
+               .channels = ad5045_channels,
                .num_channels = 2,
        },
        [ID_AD5064] = {
@@ -353,7 +362,7 @@ static const struct ad5064_chip_info ad5064_chip_info_tbl[] = {
        },
        [ID_AD5065] = {
                .shared_vref = false,
-               .channels = ad5064_channels,
+               .channels = ad5065_channels,
                .num_channels = 2,
        },
        [ID_AD5628_1] = {
@@ -429,6 +438,7 @@ static int ad5064_probe(struct device *dev, enum ad5064_type type,
 {
        struct iio_dev *indio_dev;
        struct ad5064_state *st;
+       unsigned int midscale;
        unsigned int i;
        int ret;
 
@@ -465,11 +475,6 @@ static int ad5064_probe(struct device *dev, enum ad5064_type type,
                        goto error_free_reg;
        }
 
-       for (i = 0; i < st->chip_info->num_channels; ++i) {
-               st->pwr_down_mode[i] = AD5064_LDAC_PWRDN_1K;
-               st->dac_cache[i] = 0x8000;
-       }
-
        indio_dev->dev.parent = dev;
        indio_dev->name = name;
        indio_dev->info = &ad5064_info;
@@ -477,6 +482,13 @@ static int ad5064_probe(struct device *dev, enum ad5064_type type,
        indio_dev->channels = st->chip_info->channels;
        indio_dev->num_channels = st->chip_info->num_channels;
 
+       midscale = (1 << indio_dev->channels[0].scan_type.realbits) /  2;
+
+       for (i = 0; i < st->chip_info->num_channels; ++i) {
+               st->pwr_down_mode[i] = AD5064_LDAC_PWRDN_1K;
+               st->dac_cache[i] = midscale;
+       }
+
        ret = iio_device_register(indio_dev);
        if (ret)
                goto error_disable_reg;
index b5cfa3a..361b232 100644 (file)
@@ -5,6 +5,7 @@
 config INV_MPU6050_IIO
        tristate "Invensense MPU6050 devices"
        depends on I2C && SYSFS
+       select IIO_BUFFER
        select IIO_TRIGGERED_BUFFER
        help
          This driver supports the Invensense MPU6050 devices.
index a479375..e0c404b 100644 (file)
@@ -410,6 +410,7 @@ static struct file_system_type ipathfs_fs_type = {
        .mount =        ipathfs_mount,
        .kill_sb =      ipathfs_kill_super,
 };
+MODULE_ALIAS_FS("ipathfs");
 
 int __init ipath_init_ipathfs(void)
 {
index e0d79b2..add98d0 100644 (file)
@@ -362,7 +362,6 @@ void mlx4_ib_cm_paravirt_init(struct mlx4_ib_dev *dev)
        INIT_LIST_HEAD(&dev->sriov.cm_list);
        dev->sriov.sl_id_map = RB_ROOT;
        idr_init(&dev->sriov.pv_id_table);
-       idr_pre_get(&dev->sriov.pv_id_table, GFP_KERNEL);
 }
 
 /* slave = -1 ==> all slaves */
index 644bd6f..f247fc6 100644 (file)
@@ -604,6 +604,7 @@ static struct file_system_type qibfs_fs_type = {
        .mount =        qibfs_mount,
        .kill_sb =      qibfs_kill_super,
 };
+MODULE_ALIAS_FS("ipathfs");
 
 int __init qib_init_qibfs(void)
 {
index 2fb0d76..208de7c 100644 (file)
@@ -70,8 +70,6 @@
 #define TC3589x_EVT_INT_CLR    0x2
 #define TC3589x_KBD_INT_CLR    0x1
 
-#define TC3589x_KBD_KEYMAP_SIZE     64
-
 /**
  * struct tc_keypad - data structure used by keypad driver
  * @tc3589x:    pointer to tc35893
@@ -88,7 +86,7 @@ struct tc_keypad {
        const struct tc3589x_keypad_platform_data *board;
        unsigned int krow;
        unsigned int kcol;
-       unsigned short keymap[TC3589x_KBD_KEYMAP_SIZE];
+       unsigned short *keymap;
        bool keypad_stopped;
 };
 
@@ -338,12 +336,14 @@ static int tc3589x_keypad_probe(struct platform_device *pdev)
 
        error = matrix_keypad_build_keymap(plat->keymap_data, NULL,
                                           TC3589x_MAX_KPROW, TC3589x_MAX_KPCOL,
-                                          keypad->keymap, input);
+                                          NULL, input);
        if (error) {
                dev_err(&pdev->dev, "Failed to build keymap\n");
                goto err_free_mem;
        }
 
+       keypad->keymap = input->keycode;
+
        input_set_capability(input, EV_MSC, MSC_SCAN);
        if (!plat->no_autorepeat)
                __set_bit(EV_REP, input->evbit);
index 7b99fc7..0238e0e 100644 (file)
@@ -490,6 +490,29 @@ static void alps_decode_rushmore(struct alps_fields *f, unsigned char *p)
        f->y_map |= (p[5] & 0x20) << 6;
 }
 
+static void alps_decode_dolphin(struct alps_fields *f, unsigned char *p)
+{
+       f->first_mp = !!(p[0] & 0x02);
+       f->is_mp = !!(p[0] & 0x20);
+
+       f->fingers = ((p[0] & 0x6) >> 1 |
+                    (p[0] & 0x10) >> 2);
+       f->x_map = ((p[2] & 0x60) >> 5) |
+                  ((p[4] & 0x7f) << 2) |
+                  ((p[5] & 0x7f) << 9) |
+                  ((p[3] & 0x07) << 16) |
+                  ((p[3] & 0x70) << 15) |
+                  ((p[0] & 0x01) << 22);
+       f->y_map = (p[1] & 0x7f) |
+                  ((p[2] & 0x1f) << 7);
+
+       f->x = ((p[1] & 0x7f) | ((p[4] & 0x0f) << 7));
+       f->y = ((p[2] & 0x7f) | ((p[4] & 0xf0) << 3));
+       f->z = (p[0] & 4) ? 0 : p[5] & 0x7f;
+
+       alps_decode_buttons_v3(f, p);
+}
+
 static void alps_process_touchpad_packet_v3(struct psmouse *psmouse)
 {
        struct alps_data *priv = psmouse->private;
@@ -874,7 +897,8 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse)
        }
 
        /* Bytes 2 - pktsize should have 0 in the highest bit */
-       if (psmouse->pktcnt >= 2 && psmouse->pktcnt <= psmouse->pktsize &&
+       if (priv->proto_version != ALPS_PROTO_V5 &&
+           psmouse->pktcnt >= 2 && psmouse->pktcnt <= psmouse->pktsize &&
            (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) {
                psmouse_dbg(psmouse, "refusing packet[%i] = %x\n",
                            psmouse->pktcnt - 1,
@@ -994,8 +1018,7 @@ static int alps_rpt_cmd(struct psmouse *psmouse, int init_command,
        return 0;
 }
 
-static int alps_enter_command_mode(struct psmouse *psmouse,
-                                  unsigned char *resp)
+static int alps_enter_command_mode(struct psmouse *psmouse)
 {
        unsigned char param[4];
 
@@ -1004,14 +1027,12 @@ static int alps_enter_command_mode(struct psmouse *psmouse,
                return -1;
        }
 
-       if (param[0] != 0x88 || (param[1] != 0x07 && param[1] != 0x08)) {
+       if ((param[0] != 0x88 || (param[1] != 0x07 && param[1] != 0x08)) &&
+           param[0] != 0x73) {
                psmouse_dbg(psmouse,
                            "unknown response while entering command mode\n");
                return -1;
        }
-
-       if (resp)
-               *resp = param[2];
        return 0;
 }
 
@@ -1176,7 +1197,7 @@ static int alps_passthrough_mode_v3(struct psmouse *psmouse,
 {
        int reg_val, ret = -1;
 
-       if (alps_enter_command_mode(psmouse, NULL))
+       if (alps_enter_command_mode(psmouse))
                return -1;
 
        reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x0008);
@@ -1216,7 +1237,7 @@ static int alps_probe_trackstick_v3(struct psmouse *psmouse, int reg_base)
 {
        int ret = -EIO, reg_val;
 
-       if (alps_enter_command_mode(psmouse, NULL))
+       if (alps_enter_command_mode(psmouse))
                goto error;
 
        reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x08);
@@ -1279,7 +1300,7 @@ static int alps_setup_trackstick_v3(struct psmouse *psmouse, int reg_base)
                 * supported by this driver. If bit 1 isn't set the packet
                 * format is different.
                 */
-               if (alps_enter_command_mode(psmouse, NULL) ||
+               if (alps_enter_command_mode(psmouse) ||
                    alps_command_mode_write_reg(psmouse,
                                                reg_base + 0x08, 0x82) ||
                    alps_exit_command_mode(psmouse))
@@ -1306,7 +1327,7 @@ static int alps_hw_init_v3(struct psmouse *psmouse)
            alps_setup_trackstick_v3(psmouse, ALPS_REG_BASE_PINNACLE) == -EIO)
                goto error;
 
-       if (alps_enter_command_mode(psmouse, NULL) ||
+       if (alps_enter_command_mode(psmouse) ||
            alps_absolute_mode_v3(psmouse)) {
                psmouse_err(psmouse, "Failed to enter absolute mode\n");
                goto error;
@@ -1381,7 +1402,7 @@ static int alps_hw_init_rushmore_v3(struct psmouse *psmouse)
                        priv->flags &= ~ALPS_DUALPOINT;
        }
 
-       if (alps_enter_command_mode(psmouse, NULL) ||
+       if (alps_enter_command_mode(psmouse) ||
            alps_command_mode_read_reg(psmouse, 0xc2d9) == -1 ||
            alps_command_mode_write_reg(psmouse, 0xc2cb, 0x00))
                goto error;
@@ -1431,7 +1452,7 @@ static int alps_hw_init_v4(struct psmouse *psmouse)
        struct ps2dev *ps2dev = &psmouse->ps2dev;
        unsigned char param[4];
 
-       if (alps_enter_command_mode(psmouse, NULL))
+       if (alps_enter_command_mode(psmouse))
                goto error;
 
        if (alps_absolute_mode_v4(psmouse)) {
@@ -1499,6 +1520,23 @@ error:
        return -1;
 }
 
+static int alps_hw_init_dolphin_v1(struct psmouse *psmouse)
+{
+       struct ps2dev *ps2dev = &psmouse->ps2dev;
+       unsigned char param[2];
+
+       /* This is dolphin "v1" as empirically defined by florin9doi */
+       param[0] = 0x64;
+       param[1] = 0x28;
+
+       if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM) ||
+           ps2_command(ps2dev, &param[0], PSMOUSE_CMD_SETRATE) ||
+           ps2_command(ps2dev, &param[1], PSMOUSE_CMD_SETRATE))
+               return -1;
+
+       return 0;
+}
+
 static void alps_set_defaults(struct alps_data *priv)
 {
        priv->byte0 = 0x8f;
@@ -1532,6 +1570,21 @@ static void alps_set_defaults(struct alps_data *priv)
                priv->nibble_commands = alps_v4_nibble_commands;
                priv->addr_command = PSMOUSE_CMD_DISABLE;
                break;
+       case ALPS_PROTO_V5:
+               priv->hw_init = alps_hw_init_dolphin_v1;
+               priv->process_packet = alps_process_packet_v3;
+               priv->decode_fields = alps_decode_dolphin;
+               priv->set_abs_params = alps_set_abs_params_mt;
+               priv->nibble_commands = alps_v3_nibble_commands;
+               priv->addr_command = PSMOUSE_CMD_RESET_WRAP;
+               priv->byte0 = 0xc8;
+               priv->mask0 = 0xc8;
+               priv->flags = 0;
+               priv->x_max = 1360;
+               priv->y_max = 660;
+               priv->x_bits = 23;
+               priv->y_bits = 12;
+               break;
        }
 }
 
@@ -1592,6 +1645,12 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv)
 
        if (alps_match_table(psmouse, priv, e7, ec) == 0) {
                return 0;
+       } else if (e7[0] == 0x73 && e7[1] == 0x03 && e7[2] == 0x50 &&
+                  ec[0] == 0x73 && ec[1] == 0x01) {
+               priv->proto_version = ALPS_PROTO_V5;
+               alps_set_defaults(priv);
+
+               return 0;
        } else if (ec[0] == 0x88 && ec[1] == 0x08) {
                priv->proto_version = ALPS_PROTO_V3;
                alps_set_defaults(priv);
index 9704805..eee5985 100644 (file)
@@ -16,6 +16,7 @@
 #define ALPS_PROTO_V2  2
 #define ALPS_PROTO_V3  3
 #define ALPS_PROTO_V4  4
+#define ALPS_PROTO_V5  5
 
 /**
  * struct alps_model_info - touchpad ID table
index 1673dc6..f51765f 100644 (file)
@@ -236,6 +236,13 @@ static int cypress_read_fw_version(struct psmouse *psmouse)
        cytp->fw_version = param[2] & FW_VERSION_MASX;
        cytp->tp_metrics_supported = (param[2] & TP_METRICS_MASK) ? 1 : 0;
 
+       /*
+        * Trackpad fw_version 11 (in Dell XPS12) yields a bogus response to
+        * CYTP_CMD_READ_TP_METRICS so do not try to use it. LP: #1103594.
+        */
+       if (cytp->fw_version >= 11)
+               cytp->tp_metrics_supported = 0;
+
        psmouse_dbg(psmouse, "cytp->fw_version = %d\n", cytp->fw_version);
        psmouse_dbg(psmouse, "cytp->tp_metrics_supported = %d\n",
                 cytp->tp_metrics_supported);
@@ -258,6 +265,9 @@ static int cypress_read_tp_metrics(struct psmouse *psmouse)
        cytp->tp_res_x = cytp->tp_max_abs_x / cytp->tp_width;
        cytp->tp_res_y = cytp->tp_max_abs_y / cytp->tp_high;
 
+       if (!cytp->tp_metrics_supported)
+               return 0;
+
        memset(param, 0, sizeof(param));
        if (cypress_send_ext_cmd(psmouse, CYTP_CMD_READ_TP_METRICS, param) == 0) {
                /* Update trackpad parameters. */
@@ -315,18 +325,15 @@ static int cypress_read_tp_metrics(struct psmouse *psmouse)
 
 static int cypress_query_hardware(struct psmouse *psmouse)
 {
-       struct cytp_data *cytp = psmouse->private;
        int ret;
 
        ret = cypress_read_fw_version(psmouse);
        if (ret)
                return ret;
 
-       if (cytp->tp_metrics_supported) {
-               ret = cypress_read_tp_metrics(psmouse);
-               if (ret)
-                       return ret;
-       }
+       ret = cypress_read_tp_metrics(psmouse);
+       if (ret)
+               return ret;
 
        return 0;
 }
index 41b6fbf..1daa979 100644 (file)
@@ -2017,6 +2017,9 @@ static const struct wacom_features wacom_features_0x100 =
 static const struct wacom_features wacom_features_0x101 =
        { "Wacom ISDv4 101",      WACOM_PKGLEN_MTTPC,     26202, 16325,  255,
          0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x10D =
+       { "Wacom ISDv4 10D",      WACOM_PKGLEN_MTTPC,     26202, 16325,  255,
+         0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0x4001 =
        { "Wacom ISDv4 4001",      WACOM_PKGLEN_MTTPC,     26202, 16325,  255,
          0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
@@ -2201,6 +2204,7 @@ const struct usb_device_id wacom_ids[] = {
        { USB_DEVICE_WACOM(0xEF) },
        { USB_DEVICE_WACOM(0x100) },
        { USB_DEVICE_WACOM(0x101) },
+       { USB_DEVICE_WACOM(0x10D) },
        { USB_DEVICE_WACOM(0x4001) },
        { USB_DEVICE_WACOM(0x47) },
        { USB_DEVICE_WACOM(0xF4) },
index 4f702b3..434c3df 100644 (file)
@@ -236,7 +236,12 @@ static void __ads7846_disable(struct ads7846 *ts)
 /* Must be called with ts->lock held */
 static void __ads7846_enable(struct ads7846 *ts)
 {
-       regulator_enable(ts->reg);
+       int error;
+
+       error = regulator_enable(ts->reg);
+       if (error != 0)
+               dev_err(&ts->spi->dev, "Failed to enable supply: %d\n", error);
+
        ads7846_restart(ts);
 }
 
index d04f810..59aa240 100644 (file)
 /* Define for MXT_GEN_COMMAND_T6 */
 #define MXT_BOOT_VALUE         0xa5
 #define MXT_BACKUP_VALUE       0x55
-#define MXT_BACKUP_TIME                25      /* msec */
-#define MXT_RESET_TIME         65      /* msec */
+#define MXT_BACKUP_TIME                50      /* msec */
+#define MXT_RESET_TIME         200     /* msec */
 
 #define MXT_FWRESET_TIME       175     /* msec */
 
+/* MXT_SPT_GPIOPWM_T19 field */
+#define MXT_GPIO0_MASK         0x04
+#define MXT_GPIO1_MASK         0x08
+#define MXT_GPIO2_MASK         0x10
+#define MXT_GPIO3_MASK         0x20
+
 /* Command to unlock bootloader */
 #define MXT_UNLOCK_CMD_MSB     0xaa
 #define MXT_UNLOCK_CMD_LSB     0xdc
 /* Touchscreen absolute values */
 #define MXT_MAX_AREA           0xff
 
+#define MXT_PIXELS_PER_MM      20
+
 struct mxt_info {
        u8 family_id;
        u8 variant_id;
@@ -243,6 +251,8 @@ struct mxt_data {
        const struct mxt_platform_data *pdata;
        struct mxt_object *object_table;
        struct mxt_info info;
+       bool is_tp;
+
        unsigned int irq;
        unsigned int max_x;
        unsigned int max_y;
@@ -251,6 +261,7 @@ struct mxt_data {
        u8 T6_reportid;
        u8 T9_reportid_min;
        u8 T9_reportid_max;
+       u8 T19_reportid;
 };
 
 static bool mxt_object_readable(unsigned int type)
@@ -502,6 +513,21 @@ static int mxt_write_object(struct mxt_data *data,
        return mxt_write_reg(data->client, reg + offset, val);
 }
 
+static void mxt_input_button(struct mxt_data *data, struct mxt_message *message)
+{
+       struct input_dev *input = data->input_dev;
+       bool button;
+       int i;
+
+       /* Active-low switch */
+       for (i = 0; i < MXT_NUM_GPIO; i++) {
+               if (data->pdata->key_map[i] == KEY_RESERVED)
+                       continue;
+               button = !(message->message[0] & MXT_GPIO0_MASK << i);
+               input_report_key(input, data->pdata->key_map[i], button);
+       }
+}
+
 static void mxt_input_touchevent(struct mxt_data *data,
                                      struct mxt_message *message, int id)
 {
@@ -585,6 +611,9 @@ static irqreturn_t mxt_interrupt(int irq, void *dev_id)
                        int id = reportid - data->T9_reportid_min;
                        mxt_input_touchevent(data, &message, id);
                        update_input = true;
+               } else if (message.reportid == data->T19_reportid) {
+                       mxt_input_button(data, &message);
+                       update_input = true;
                } else {
                        mxt_dump_message(dev, &message);
                }
@@ -764,6 +793,9 @@ static int mxt_get_object_table(struct mxt_data *data)
                        data->T9_reportid_min = min_id;
                        data->T9_reportid_max = max_id;
                        break;
+               case MXT_SPT_GPIOPWM_T19:
+                       data->T19_reportid = min_id;
+                       break;
                }
        }
 
@@ -777,7 +809,7 @@ static void mxt_free_object_table(struct mxt_data *data)
        data->T6_reportid = 0;
        data->T9_reportid_min = 0;
        data->T9_reportid_max = 0;
-
+       data->T19_reportid = 0;
 }
 
 static int mxt_initialize(struct mxt_data *data)
@@ -1115,9 +1147,13 @@ static int mxt_probe(struct i2c_client *client,
                goto err_free_mem;
        }
 
-       input_dev->name = "Atmel maXTouch Touchscreen";
+       data->is_tp = pdata && pdata->is_tp;
+
+       input_dev->name = (data->is_tp) ? "Atmel maXTouch Touchpad" :
+                                         "Atmel maXTouch Touchscreen";
        snprintf(data->phys, sizeof(data->phys), "i2c-%u-%04x/input0",
                 client->adapter->nr, client->addr);
+
        input_dev->phys = data->phys;
 
        input_dev->id.bustype = BUS_I2C;
@@ -1140,6 +1176,29 @@ static int mxt_probe(struct i2c_client *client,
        __set_bit(EV_KEY, input_dev->evbit);
        __set_bit(BTN_TOUCH, input_dev->keybit);
 
+       if (data->is_tp) {
+               int i;
+               __set_bit(INPUT_PROP_POINTER, input_dev->propbit);
+               __set_bit(INPUT_PROP_BUTTONPAD, input_dev->propbit);
+
+               for (i = 0; i < MXT_NUM_GPIO; i++)
+                       if (pdata->key_map[i] != KEY_RESERVED)
+                               __set_bit(pdata->key_map[i], input_dev->keybit);
+
+               __set_bit(BTN_TOOL_FINGER, input_dev->keybit);
+               __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit);
+               __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit);
+               __set_bit(BTN_TOOL_QUADTAP, input_dev->keybit);
+               __set_bit(BTN_TOOL_QUINTTAP, input_dev->keybit);
+
+               input_abs_set_res(input_dev, ABS_X, MXT_PIXELS_PER_MM);
+               input_abs_set_res(input_dev, ABS_Y, MXT_PIXELS_PER_MM);
+               input_abs_set_res(input_dev, ABS_MT_POSITION_X,
+                                 MXT_PIXELS_PER_MM);
+               input_abs_set_res(input_dev, ABS_MT_POSITION_Y,
+                                 MXT_PIXELS_PER_MM);
+       }
+
        /* For single touch */
        input_set_abs_params(input_dev, ABS_X,
                             0, data->max_x, 0, 0);
@@ -1258,6 +1317,7 @@ static SIMPLE_DEV_PM_OPS(mxt_pm_ops, mxt_suspend, mxt_resume);
 static const struct i2c_device_id mxt_id[] = {
        { "qt602240_ts", 0 },
        { "atmel_mxt_ts", 0 },
+       { "atmel_mxt_tp", 0 },
        { "mXT224", 0 },
        { }
 };
index 4a29ddf..1443532 100644 (file)
@@ -314,15 +314,27 @@ static int mms114_start(struct mms114_data *data)
        struct i2c_client *client = data->client;
        int error;
 
-       if (data->core_reg)
-               regulator_enable(data->core_reg);
-       if (data->io_reg)
-               regulator_enable(data->io_reg);
+       error = regulator_enable(data->core_reg);
+       if (error) {
+               dev_err(&client->dev, "Failed to enable avdd: %d\n", error);
+               return error;
+       }
+
+       error = regulator_enable(data->io_reg);
+       if (error) {
+               dev_err(&client->dev, "Failed to enable vdd: %d\n", error);
+               regulator_disable(data->core_reg);
+               return error;
+       }
+
        mdelay(MMS114_POWERON_DELAY);
 
        error = mms114_setup_regs(data);
-       if (error < 0)
+       if (error < 0) {
+               regulator_disable(data->io_reg);
+               regulator_disable(data->core_reg);
                return error;
+       }
 
        if (data->pdata->cfg_pin)
                data->pdata->cfg_pin(true);
@@ -335,16 +347,20 @@ static int mms114_start(struct mms114_data *data)
 static void mms114_stop(struct mms114_data *data)
 {
        struct i2c_client *client = data->client;
+       int error;
 
        disable_irq(client->irq);
 
        if (data->pdata->cfg_pin)
                data->pdata->cfg_pin(false);
 
-       if (data->io_reg)
-               regulator_disable(data->io_reg);
-       if (data->core_reg)
-               regulator_disable(data->core_reg);
+       error = regulator_disable(data->io_reg);
+       if (error)
+               dev_warn(&client->dev, "Failed to disable vdd: %d\n", error);
+
+       error = regulator_disable(data->core_reg);
+       if (error)
+               dev_warn(&client->dev, "Failed to disable avdd: %d\n", error);
 }
 
 static int mms114_input_open(struct input_dev *dev)
index dc7e478..e5cdaf8 100644 (file)
@@ -1083,6 +1083,7 @@ static const char *dma_remap_fault_reasons[] =
        "non-zero reserved fields in RTP",
        "non-zero reserved fields in CTP",
        "non-zero reserved fields in PTE",
+       "PCE for translation request specifies blocking",
 };
 
 static const char *irq_remap_fault_reasons[] =
index 644d724..a32e0d5 100644 (file)
@@ -648,7 +648,7 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
 
        /* Convert our logical CPU mask into a physical one. */
        for_each_cpu(cpu, mask)
-               map |= 1 << cpu_logical_map(cpu);
+               map |= gic_cpu_map[cpu];
 
        /*
         * Ensure that stores to Normal memory are visible to the
index 017c67e..ead0a4f 100644 (file)
@@ -294,13 +294,13 @@ int st5481_setup_usb(struct st5481_adapter *adapter)
        // Allocate URBs and buffers for interrupt endpoint
        urb = usb_alloc_urb(0, GFP_KERNEL);
        if (!urb) {
-               return -ENOMEM;
+               goto err1;
        }
        intr->urb = urb;
 
        buf = kmalloc(INT_PKT_SIZE, GFP_KERNEL);
        if (!buf) {
-               return -ENOMEM;
+               goto err2;
        }
 
        endpoint = &altsetting->endpoint[EP_INT-1];
@@ -313,6 +313,14 @@ int st5481_setup_usb(struct st5481_adapter *adapter)
                         endpoint->desc.bInterval);
 
        return 0;
+err2:
+       usb_free_urb(intr->urb);
+       intr->urb = NULL;
+err1:
+       usb_free_urb(ctrl->urb);
+       ctrl->urb = NULL;
+
+       return -ENOMEM;
 }
 
 /*
index d8a7d83..ebaebdf 100644 (file)
@@ -902,7 +902,9 @@ isdn_tty_send_msg(modem_info *info, atemu *m, char *msg)
        int j;
        int l;
 
-       l = strlen(msg);
+       l = min(strlen(msg), sizeof(cmd.parm) - sizeof(cmd.parm.cmsg)
+               + sizeof(cmd.parm.cmsg.para) - 2);
+
        if (!l) {
                isdn_tty_modem_result(RESULT_ERROR, info);
                return;
index c45b3ae..d873cba 100644 (file)
@@ -138,8 +138,7 @@ int pl320_ipc_unregister_notifier(struct notifier_block *nb)
 }
 EXPORT_SYMBOL_GPL(pl320_ipc_unregister_notifier);
 
-static int __init pl320_probe(struct amba_device *adev,
-                               const struct amba_id *id)
+static int pl320_probe(struct amba_device *adev, const struct amba_id *id)
 {
        int ret;
 
index e30b490..4d8d90b 100644 (file)
@@ -154,17 +154,6 @@ config MD_RAID456
 
          If unsure, say Y.
 
-config MULTICORE_RAID456
-       bool "RAID-4/RAID-5/RAID-6 Multicore processing (EXPERIMENTAL)"
-       depends on MD_RAID456
-       depends on SMP
-       depends on EXPERIMENTAL
-       ---help---
-         Enable the raid456 module to dispatch per-stripe raid operations to a
-         thread pool.
-
-         If unsure, say N.
-
 config MD_MULTIPATH
        tristate "Multipath I/O support"
        depends on BLK_DEV_MD
index 9a01d1e..311e3d3 100644 (file)
@@ -91,15 +91,44 @@ static struct raid_type {
        {"raid6_nc", "RAID6 (N continue)",              2, 4, 6, ALGORITHM_ROTATING_N_CONTINUE}
 };
 
+static char *raid10_md_layout_to_format(int layout)
+{
+       /*
+        * Bit 16 and 17 stand for "offset" and "use_far_sets"
+        * Refer to MD's raid10.c for details
+        */
+       if ((layout & 0x10000) && (layout & 0x20000))
+               return "offset";
+
+       if ((layout & 0xFF) > 1)
+               return "near";
+
+       return "far";
+}
+
 static unsigned raid10_md_layout_to_copies(int layout)
 {
-       return layout & 0xFF;
+       if ((layout & 0xFF) > 1)
+               return layout & 0xFF;
+       return (layout >> 8) & 0xFF;
 }
 
 static int raid10_format_to_md_layout(char *format, unsigned copies)
 {
-       /* 1 "far" copy, and 'copies' "near" copies */
-       return (1 << 8) | (copies & 0xFF);
+       unsigned n = 1, f = 1;
+
+       if (!strcmp("near", format))
+               n = copies;
+       else
+               f = copies;
+
+       if (!strcmp("offset", format))
+               return 0x30000 | (f << 8) | n;
+
+       if (!strcmp("far", format))
+               return 0x20000 | (f << 8) | n;
+
+       return (f << 8) | n;
 }
 
 static struct raid_type *get_raid_type(char *name)
@@ -352,6 +381,7 @@ static int validate_raid_redundancy(struct raid_set *rs)
 {
        unsigned i, rebuild_cnt = 0;
        unsigned rebuilds_per_group, copies, d;
+       unsigned group_size, last_group_start;
 
        for (i = 0; i < rs->md.raid_disks; i++)
                if (!test_bit(In_sync, &rs->dev[i].rdev.flags) ||
@@ -379,9 +409,6 @@ static int validate_raid_redundancy(struct raid_set *rs)
                 * as long as the failed devices occur in different mirror
                 * groups (i.e. different stripes).
                 *
-                * Right now, we only allow for "near" copies.  When other
-                * formats are added, we will have to check those too.
-                *
                 * When checking "near" format, make sure no adjacent devices
                 * have failed beyond what can be handled.  In addition to the
                 * simple case where the number of devices is a multiple of the
@@ -391,14 +418,41 @@ static int validate_raid_redundancy(struct raid_set *rs)
                 *          A    A    B    B    C
                 *          C    D    D    E    E
                 */
-               for (i = 0; i < rs->md.raid_disks * copies; i++) {
-                       if (!(i % copies))
+               if (!strcmp("near", raid10_md_layout_to_format(rs->md.layout))) {
+                       for (i = 0; i < rs->md.raid_disks * copies; i++) {
+                               if (!(i % copies))
+                                       rebuilds_per_group = 0;
+                               d = i % rs->md.raid_disks;
+                               if ((!rs->dev[d].rdev.sb_page ||
+                                    !test_bit(In_sync, &rs->dev[d].rdev.flags)) &&
+                                   (++rebuilds_per_group >= copies))
+                                       goto too_many;
+                       }
+                       break;
+               }
+
+               /*
+                * When checking "far" and "offset" formats, we need to ensure
+                * that the device that holds its copy is not also dead or
+                * being rebuilt.  (Note that "far" and "offset" formats only
+                * support two copies right now.  These formats also only ever
+                * use the 'use_far_sets' variant.)
+                *
+                * This check is somewhat complicated by the need to account
+                * for arrays that are not a multiple of (far) copies.  This
+                * results in the need to treat the last (potentially larger)
+                * set differently.
+                */
+               group_size = (rs->md.raid_disks / copies);
+               last_group_start = (rs->md.raid_disks / group_size) - 1;
+               last_group_start *= group_size;
+               for (i = 0; i < rs->md.raid_disks; i++) {
+                       if (!(i % copies) && !(i > last_group_start))
                                rebuilds_per_group = 0;
-                       d = i % rs->md.raid_disks;
-                       if ((!rs->dev[d].rdev.sb_page ||
-                            !test_bit(In_sync, &rs->dev[d].rdev.flags)) &&
+                       if ((!rs->dev[i].rdev.sb_page ||
+                            !test_bit(In_sync, &rs->dev[i].rdev.flags)) &&
                            (++rebuilds_per_group >= copies))
-                               goto too_many;
+                                       goto too_many;
                }
                break;
        default:
@@ -433,7 +487,7 @@ too_many:
  *
  * RAID10-only options:
  *    [raid10_copies <# copies>]        Number of copies.  (Default: 2)
- *    [raid10_format <near>]            Layout algorithm.  (Default: near)
+ *    [raid10_format <near|far|offset>] Layout algorithm.  (Default: near)
  */
 static int parse_raid_params(struct raid_set *rs, char **argv,
                             unsigned num_raid_params)
@@ -520,7 +574,9 @@ static int parse_raid_params(struct raid_set *rs, char **argv,
                                rs->ti->error = "'raid10_format' is an invalid parameter for this RAID type";
                                return -EINVAL;
                        }
-                       if (strcmp("near", argv[i])) {
+                       if (strcmp("near", argv[i]) &&
+                           strcmp("far", argv[i]) &&
+                           strcmp("offset", argv[i])) {
                                rs->ti->error = "Invalid 'raid10_format' value given";
                                return -EINVAL;
                        }
@@ -644,6 +700,15 @@ static int parse_raid_params(struct raid_set *rs, char **argv,
                        return -EINVAL;
                }
 
+               /*
+                * If the format is not "near", we only support
+                * two copies at the moment.
+                */
+               if (strcmp("near", raid10_format) && (raid10_copies > 2)) {
+                       rs->ti->error = "Too many copies for given RAID10 format.";
+                       return -EINVAL;
+               }
+
                /* (Len * #mirrors) / #devices */
                sectors_per_dev = rs->ti->len * raid10_copies;
                sector_div(sectors_per_dev, rs->md.raid_disks);
@@ -854,17 +919,30 @@ static int super_init_validation(struct mddev *mddev, struct md_rdev *rdev)
        /*
         * Reshaping is not currently allowed
         */
-       if ((le32_to_cpu(sb->level) != mddev->level) ||
-           (le32_to_cpu(sb->layout) != mddev->layout) ||
-           (le32_to_cpu(sb->stripe_sectors) != mddev->chunk_sectors)) {
-               DMERR("Reshaping arrays not yet supported.");
+       if (le32_to_cpu(sb->level) != mddev->level) {
+               DMERR("Reshaping arrays not yet supported. (RAID level change)");
+               return -EINVAL;
+       }
+       if (le32_to_cpu(sb->layout) != mddev->layout) {
+               DMERR("Reshaping arrays not yet supported. (RAID layout change)");
+               DMERR("  0x%X vs 0x%X", le32_to_cpu(sb->layout), mddev->layout);
+               DMERR("  Old layout: %s w/ %d copies",
+                     raid10_md_layout_to_format(le32_to_cpu(sb->layout)),
+                     raid10_md_layout_to_copies(le32_to_cpu(sb->layout)));
+               DMERR("  New layout: %s w/ %d copies",
+                     raid10_md_layout_to_format(mddev->layout),
+                     raid10_md_layout_to_copies(mddev->layout));
+               return -EINVAL;
+       }
+       if (le32_to_cpu(sb->stripe_sectors) != mddev->chunk_sectors) {
+               DMERR("Reshaping arrays not yet supported. (stripe sectors change)");
                return -EINVAL;
        }
 
        /* We can only change the number of devices in RAID1 right now */
        if ((rs->raid_type->level != 1) &&
            (le32_to_cpu(sb->num_devices) != mddev->raid_disks)) {
-               DMERR("Reshaping arrays not yet supported.");
+               DMERR("Reshaping arrays not yet supported. (device count change)");
                return -EINVAL;
        }
 
@@ -1329,7 +1407,8 @@ static void raid_status(struct dm_target *ti, status_type_t type,
                               raid10_md_layout_to_copies(rs->md.layout));
 
                if (rs->print_flags & DMPF_RAID10_FORMAT)
-                       DMEMIT(" raid10_format near");
+                       DMEMIT(" raid10_format %s",
+                              raid10_md_layout_to_format(rs->md.layout));
 
                DMEMIT(" %d", rs->md.raid_disks);
                for (i = 0; i < rs->md.raid_disks; i++) {
@@ -1418,6 +1497,10 @@ static struct target_type raid_target = {
 
 static int __init dm_raid_init(void)
 {
+       DMINFO("Loading target version %u.%u.%u",
+              raid_target.version[0],
+              raid_target.version[1],
+              raid_target.version[2]);
        return dm_register_target(&raid_target);
 }
 
index 3db3d1b..fcb878f 100644 (file)
@@ -307,6 +307,10 @@ static void md_make_request(struct request_queue *q, struct bio *bio)
                bio_io_error(bio);
                return;
        }
+       if (mddev->ro == 1 && unlikely(rw == WRITE)) {
+               bio_endio(bio, bio_sectors(bio) == 0 ? 0 : -EROFS);
+               return;
+       }
        smp_rmb(); /* Ensure implications of  'active' are visible */
        rcu_read_lock();
        if (mddev->suspended) {
@@ -2994,6 +2998,9 @@ rdev_size_store(struct md_rdev *rdev, const char *buf, size_t len)
                } else if (!sectors)
                        sectors = (i_size_read(rdev->bdev->bd_inode) >> 9) -
                                rdev->data_offset;
+               if (!my_mddev->pers->resize)
+                       /* Cannot change size for RAID0 or Linear etc */
+                       return -EINVAL;
        }
        if (sectors < my_mddev->dev_sectors)
                return -EINVAL; /* component must fit device */
@@ -6525,7 +6532,17 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode,
                        mddev->ro = 0;
                        sysfs_notify_dirent_safe(mddev->sysfs_state);
                        set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
-                       md_wakeup_thread(mddev->thread);
+                       /* mddev_unlock will wake thread */
+                       /* If a device failed while we were read-only, we
+                        * need to make sure the metadata is updated now.
+                        */
+                       if (test_bit(MD_CHANGE_DEVS, &mddev->flags)) {
+                               mddev_unlock(mddev);
+                               wait_event(mddev->sb_wait,
+                                          !test_bit(MD_CHANGE_DEVS, &mddev->flags) &&
+                                          !test_bit(MD_CHANGE_PENDING, &mddev->flags));
+                               mddev_lock(mddev);
+                       }
                } else {
                        err = -EROFS;
                        goto abort_unlock;
index 24b3597..0505452 100644 (file)
@@ -175,7 +175,13 @@ static int create_strip_zones(struct mddev *mddev, struct r0conf **private_conf)
                        rdev1->new_raid_disk = j;
                }
 
-               if (j < 0 || j >= mddev->raid_disks) {
+               if (j < 0) {
+                       printk(KERN_ERR
+                              "md/raid0:%s: remove inactive devices before converting to RAID0\n",
+                              mdname(mddev));
+                       goto abort;
+               }
+               if (j >= mddev->raid_disks) {
                        printk(KERN_ERR "md/raid0:%s: bad disk number %d - "
                               "aborting!\n", mdname(mddev), j);
                        goto abort;
@@ -289,7 +295,7 @@ abort:
        kfree(conf->strip_zone);
        kfree(conf->devlist);
        kfree(conf);
-       *private_conf = NULL;
+       *private_conf = ERR_PTR(err);
        return err;
 }
 
@@ -411,7 +417,8 @@ static sector_t raid0_size(struct mddev *mddev, sector_t sectors, int raid_disks
                  "%s does not support generic reshape\n", __func__);
 
        rdev_for_each(rdev, mddev)
-               array_sectors += rdev->sectors;
+               array_sectors += (rdev->sectors &
+                                 ~(sector_t)(mddev->chunk_sectors-1));
 
        return array_sectors;
 }
index d5bddfc..fd86b37 100644 (file)
@@ -967,6 +967,7 @@ static void raid1_unplug(struct blk_plug_cb *cb, bool from_schedule)
                bio_list_merge(&conf->pending_bio_list, &plug->pending);
                conf->pending_count += plug->pending_cnt;
                spin_unlock_irq(&conf->device_lock);
+               wake_up(&conf->wait_barrier);
                md_wakeup_thread(mddev->thread);
                kfree(plug);
                return;
@@ -1000,6 +1001,7 @@ static void make_request(struct mddev *mddev, struct bio * bio)
        const unsigned long do_flush_fua = (bio->bi_rw & (REQ_FLUSH | REQ_FUA));
        const unsigned long do_discard = (bio->bi_rw
                                          & (REQ_DISCARD | REQ_SECURE));
+       const unsigned long do_same = (bio->bi_rw & REQ_WRITE_SAME);
        struct md_rdev *blocked_rdev;
        struct blk_plug_cb *cb;
        struct raid1_plug_cb *plug = NULL;
@@ -1301,7 +1303,8 @@ read_again:
                                   conf->mirrors[i].rdev->data_offset);
                mbio->bi_bdev = conf->mirrors[i].rdev->bdev;
                mbio->bi_end_io = raid1_end_write_request;
-               mbio->bi_rw = WRITE | do_flush_fua | do_sync | do_discard;
+               mbio->bi_rw =
+                       WRITE | do_flush_fua | do_sync | do_discard | do_same;
                mbio->bi_private = r1_bio;
 
                atomic_inc(&r1_bio->remaining);
@@ -2818,6 +2821,9 @@ static int run(struct mddev *mddev)
        if (IS_ERR(conf))
                return PTR_ERR(conf);
 
+       if (mddev->queue)
+               blk_queue_max_write_same_sectors(mddev->queue,
+                                                mddev->chunk_sectors);
        rdev_for_each(rdev, mddev) {
                if (!mddev->gendisk)
                        continue;
index 64d4824..77b562d 100644 (file)
  *    near_copies (stored in low byte of layout)
  *    far_copies (stored in second byte of layout)
  *    far_offset (stored in bit 16 of layout )
+ *    use_far_sets (stored in bit 17 of layout )
  *
- * The data to be stored is divided into chunks using chunksize.
- * Each device is divided into far_copies sections.
- * In each section, chunks are laid out in a style similar to raid0, but
- * near_copies copies of each chunk is stored (each on a different drive).
- * The starting device for each section is offset near_copies from the starting
- * device of the previous section.
- * Thus they are (near_copies*far_copies) of each chunk, and each is on a different
- * drive.
- * near_copies and far_copies must be at least one, and their product is at most
- * raid_disks.
+ * The data to be stored is divided into chunks using chunksize.  Each device
+ * is divided into far_copies sections.   In each section, chunks are laid out
+ * in a style similar to raid0, but near_copies copies of each chunk is stored
+ * (each on a different drive).  The starting device for each section is offset
+ * near_copies from the starting device of the previous section.  Thus there
+ * are (near_copies * far_copies) of each chunk, and each is on a different
+ * drive.  near_copies and far_copies must be at least one, and their product
+ * is at most raid_disks.
  *
  * If far_offset is true, then the far_copies are handled a bit differently.
- * The copies are still in different stripes, but instead of be very far apart
- * on disk, there are adjacent stripes.
+ * The copies are still in different stripes, but instead of being very far
+ * apart on disk, there are adjacent stripes.
+ *
+ * The far and offset algorithms are handled slightly differently if
+ * 'use_far_sets' is true.  In this case, the array's devices are grouped into
+ * sets that are (near_copies * far_copies) in size.  The far copied stripes
+ * are still shifted by 'near_copies' devices, but this shifting stays confined
+ * to the set rather than the entire array.  This is done to improve the number
+ * of device combinations that can fail without causing the array to fail.
+ * Example 'far' algorithm w/o 'use_far_sets' (each letter represents a chunk
+ * on a device):
+ *    A B C D    A B C D E
+ *      ...         ...
+ *    D A B C    E A B C D
+ * Example 'far' algorithm w/ 'use_far_sets' enabled (sets illustrated w/ []'s):
+ *    [A B] [C D]    [A B] [C D E]
+ *    |...| |...|    |...| | ... |
+ *    [B A] [D C]    [B A] [E C D]
  */
 
 /*
@@ -535,6 +550,13 @@ static void __raid10_find_phys(struct geom *geo, struct r10bio *r10bio)
        sector_t stripe;
        int dev;
        int slot = 0;
+       int last_far_set_start, last_far_set_size;
+
+       last_far_set_start = (geo->raid_disks / geo->far_set_size) - 1;
+       last_far_set_start *= geo->far_set_size;
+
+       last_far_set_size = geo->far_set_size;
+       last_far_set_size += (geo->raid_disks % geo->far_set_size);
 
        /* now calculate first sector/dev */
        chunk = r10bio->sector >> geo->chunk_shift;
@@ -551,15 +573,25 @@ static void __raid10_find_phys(struct geom *geo, struct r10bio *r10bio)
        /* and calculate all the others */
        for (n = 0; n < geo->near_copies; n++) {
                int d = dev;
+               int set;
                sector_t s = sector;
-               r10bio->devs[slot].addr = sector;
                r10bio->devs[slot].devnum = d;
+               r10bio->devs[slot].addr = s;
                slot++;
 
                for (f = 1; f < geo->far_copies; f++) {
+                       set = d / geo->far_set_size;
                        d += geo->near_copies;
-                       if (d >= geo->raid_disks)
-                               d -= geo->raid_disks;
+
+                       if ((geo->raid_disks % geo->far_set_size) &&
+                           (d > last_far_set_start)) {
+                               d -= last_far_set_start;
+                               d %= last_far_set_size;
+                               d += last_far_set_start;
+                       } else {
+                               d %= geo->far_set_size;
+                               d += geo->far_set_size * set;
+                       }
                        s += geo->stride;
                        r10bio->devs[slot].devnum = d;
                        r10bio->devs[slot].addr = s;
@@ -595,6 +627,20 @@ static sector_t raid10_find_virt(struct r10conf *conf, sector_t sector, int dev)
         * or recovery, so reshape isn't happening
         */
        struct geom *geo = &conf->geo;
+       int far_set_start = (dev / geo->far_set_size) * geo->far_set_size;
+       int far_set_size = geo->far_set_size;
+       int last_far_set_start;
+
+       if (geo->raid_disks % geo->far_set_size) {
+               last_far_set_start = (geo->raid_disks / geo->far_set_size) - 1;
+               last_far_set_start *= geo->far_set_size;
+
+               if (dev >= last_far_set_start) {
+                       far_set_size = geo->far_set_size;
+                       far_set_size += (geo->raid_disks % geo->far_set_size);
+                       far_set_start = last_far_set_start;
+               }
+       }
 
        offset = sector & geo->chunk_mask;
        if (geo->far_offset) {
@@ -602,13 +648,13 @@ static sector_t raid10_find_virt(struct r10conf *conf, sector_t sector, int dev)
                chunk = sector >> geo->chunk_shift;
                fc = sector_div(chunk, geo->far_copies);
                dev -= fc * geo->near_copies;
-               if (dev < 0)
-                       dev += geo->raid_disks;
+               if (dev < far_set_start)
+                       dev += far_set_size;
        } else {
                while (sector >= geo->stride) {
                        sector -= geo->stride;
-                       if (dev < geo->near_copies)
-                               dev += geo->raid_disks - geo->near_copies;
+                       if (dev < (geo->near_copies + far_set_start))
+                               dev += far_set_size - geo->near_copies;
                        else
                                dev -= geo->near_copies;
                }
@@ -1073,6 +1119,7 @@ static void raid10_unplug(struct blk_plug_cb *cb, bool from_schedule)
                bio_list_merge(&conf->pending_bio_list, &plug->pending);
                conf->pending_count += plug->pending_cnt;
                spin_unlock_irq(&conf->device_lock);
+               wake_up(&conf->wait_barrier);
                md_wakeup_thread(mddev->thread);
                kfree(plug);
                return;
@@ -1105,6 +1152,7 @@ static void make_request(struct mddev *mddev, struct bio * bio)
        const unsigned long do_fua = (bio->bi_rw & REQ_FUA);
        const unsigned long do_discard = (bio->bi_rw
                                          & (REQ_DISCARD | REQ_SECURE));
+       const unsigned long do_same = (bio->bi_rw & REQ_WRITE_SAME);
        unsigned long flags;
        struct md_rdev *blocked_rdev;
        struct blk_plug_cb *cb;
@@ -1460,7 +1508,8 @@ retry_write:
                                                              rdev));
                        mbio->bi_bdev = rdev->bdev;
                        mbio->bi_end_io = raid10_end_write_request;
-                       mbio->bi_rw = WRITE | do_sync | do_fua | do_discard;
+                       mbio->bi_rw =
+                               WRITE | do_sync | do_fua | do_discard | do_same;
                        mbio->bi_private = r10_bio;
 
                        atomic_inc(&r10_bio->remaining);
@@ -1502,7 +1551,8 @@ retry_write:
                                                   r10_bio, rdev));
                        mbio->bi_bdev = rdev->bdev;
                        mbio->bi_end_io = raid10_end_write_request;
-                       mbio->bi_rw = WRITE | do_sync | do_fua | do_discard;
+                       mbio->bi_rw =
+                               WRITE | do_sync | do_fua | do_discard | do_same;
                        mbio->bi_private = r10_bio;
 
                        atomic_inc(&r10_bio->remaining);
@@ -3436,7 +3486,7 @@ static int setup_geo(struct geom *geo, struct mddev *mddev, enum geo_type new)
                disks = mddev->raid_disks + mddev->delta_disks;
                break;
        }
-       if (layout >> 17)
+       if (layout >> 18)
                return -1;
        if (chunk < (PAGE_SIZE >> 9) ||
            !is_power_of_2(chunk))
@@ -3448,6 +3498,7 @@ static int setup_geo(struct geom *geo, struct mddev *mddev, enum geo_type new)
        geo->near_copies = nc;
        geo->far_copies = fc;
        geo->far_offset = fo;
+       geo->far_set_size = (layout & (1<<17)) ? disks / fc : disks;
        geo->chunk_mask = chunk - 1;
        geo->chunk_shift = ffz(~chunk);
        return nc*fc;
@@ -3569,6 +3620,8 @@ static int run(struct mddev *mddev)
        if (mddev->queue) {
                blk_queue_max_discard_sectors(mddev->queue,
                                              mddev->chunk_sectors);
+               blk_queue_max_write_same_sectors(mddev->queue,
+                                                mddev->chunk_sectors);
                blk_queue_io_min(mddev->queue, chunk_size);
                if (conf->geo.raid_disks % conf->geo.near_copies)
                        blk_queue_io_opt(mddev->queue, chunk_size * conf->geo.raid_disks);
index 1054cf6..157d69e 100644 (file)
@@ -33,6 +33,11 @@ struct r10conf {
                                               * far_offset, in which case it is
                                               * 1 stripe.
                                               */
+               int             far_set_size; /* The number of devices in a set,
+                                              * where a 'set' are devices that
+                                              * contain far/offset copies of
+                                              * each other.
+                                              */
                int             chunk_shift; /* shift from chunks to sectors */
                sector_t        chunk_mask;
        } prev, geo;
index 5af2d27..3ee2912 100644 (file)
@@ -1403,7 +1403,7 @@ static void ops_run_check_pq(struct stripe_head *sh, struct raid5_percpu *percpu
                           &sh->ops.zero_sum_result, percpu->spare_page, &submit);
 }
 
-static void __raid_run_ops(struct stripe_head *sh, unsigned long ops_request)
+static void raid_run_ops(struct stripe_head *sh, unsigned long ops_request)
 {
        int overlap_clear = 0, i, disks = sh->disks;
        struct dma_async_tx_descriptor *tx = NULL;
@@ -1468,36 +1468,6 @@ static void __raid_run_ops(struct stripe_head *sh, unsigned long ops_request)
        put_cpu();
 }
 
-#ifdef CONFIG_MULTICORE_RAID456
-static void async_run_ops(void *param, async_cookie_t cookie)
-{
-       struct stripe_head *sh = param;
-       unsigned long ops_request = sh->ops.request;
-
-       clear_bit_unlock(STRIPE_OPS_REQ_PENDING, &sh->state);
-       wake_up(&sh->ops.wait_for_ops);
-
-       __raid_run_ops(sh, ops_request);
-       release_stripe(sh);
-}
-
-static void raid_run_ops(struct stripe_head *sh, unsigned long ops_request)
-{
-       /* since handle_stripe can be called outside of raid5d context
-        * we need to ensure sh->ops.request is de-staged before another
-        * request arrives
-        */
-       wait_event(sh->ops.wait_for_ops,
-                  !test_and_set_bit_lock(STRIPE_OPS_REQ_PENDING, &sh->state));
-       sh->ops.request = ops_request;
-
-       atomic_inc(&sh->count);
-       async_schedule(async_run_ops, sh);
-}
-#else
-#define raid_run_ops __raid_run_ops
-#endif
-
 static int grow_one_stripe(struct r5conf *conf)
 {
        struct stripe_head *sh;
@@ -1506,9 +1476,6 @@ static int grow_one_stripe(struct r5conf *conf)
                return 0;
 
        sh->raid_conf = conf;
-       #ifdef CONFIG_MULTICORE_RAID456
-       init_waitqueue_head(&sh->ops.wait_for_ops);
-       #endif
 
        spin_lock_init(&sh->stripe_lock);
 
@@ -1627,9 +1594,6 @@ static int resize_stripes(struct r5conf *conf, int newsize)
                        break;
 
                nsh->raid_conf = conf;
-               #ifdef CONFIG_MULTICORE_RAID456
-               init_waitqueue_head(&nsh->ops.wait_for_ops);
-               #endif
                spin_lock_init(&nsh->stripe_lock);
 
                list_add(&nsh->lru, &newstripes);
index 671f5b1..c346941 100644 (file)
@@ -858,6 +858,7 @@ config EZX_PCAP
 config AB8500_CORE
        bool "ST-Ericsson AB8500 Mixed Signal Power Management chip"
        depends on GENERIC_HARDIRQS && ABX500_CORE && MFD_DB8500_PRCMU
+       select POWER_SUPPLY
        select MFD_CORE
        select IRQ_DOMAIN
        help
index b1f3561..5f341a5 100644 (file)
@@ -594,9 +594,12 @@ static int ab8500_gpadc_runtime_suspend(struct device *dev)
 static int ab8500_gpadc_runtime_resume(struct device *dev)
 {
        struct ab8500_gpadc *gpadc = dev_get_drvdata(dev);
+       int ret;
 
-       regulator_enable(gpadc->regu);
-       return 0;
+       ret = regulator_enable(gpadc->regu);
+       if (ret)
+               dev_err(dev, "Failed to enable vtvout LDO: %d\n", ret);
+       return ret;
 }
 
 static int ab8500_gpadc_runtime_idle(struct device *dev)
@@ -643,7 +646,7 @@ static int ab8500_gpadc_probe(struct platform_device *pdev)
        }
 
        /* VTVout LDO used to power up ab8500-GPADC */
-       gpadc->regu = regulator_get(&pdev->dev, "vddadc");
+       gpadc->regu = devm_regulator_get(&pdev->dev, "vddadc");
        if (IS_ERR(gpadc->regu)) {
                ret = PTR_ERR(gpadc->regu);
                dev_err(gpadc->dev, "failed to get vtvout LDO\n");
@@ -652,7 +655,11 @@ static int ab8500_gpadc_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, gpadc);
 
-       regulator_enable(gpadc->regu);
+       ret = regulator_enable(gpadc->regu);
+       if (ret) {
+               dev_err(gpadc->dev, "Failed to enable vtvout LDO: %d\n", ret);
+               goto fail_enable;
+       }
 
        pm_runtime_set_autosuspend_delay(gpadc->dev, GPADC_AUDOSUSPEND_DELAY);
        pm_runtime_use_autosuspend(gpadc->dev);
@@ -663,6 +670,8 @@ static int ab8500_gpadc_probe(struct platform_device *pdev)
        list_add_tail(&gpadc->node, &ab8500_gpadc_list);
        dev_dbg(gpadc->dev, "probe success\n");
        return 0;
+
+fail_enable:
 fail_irq:
        free_irq(gpadc->irq, gpadc);
 fail:
index 6b5edf6..4febc5c 100644 (file)
@@ -460,15 +460,15 @@ static void omap_usbhs_init(struct device *dev)
 
        switch (omap->usbhs_rev) {
        case OMAP_USBHS_REV1:
-               omap_usbhs_rev1_hostconfig(omap, reg);
+               reg = omap_usbhs_rev1_hostconfig(omap, reg);
                break;
 
        case OMAP_USBHS_REV2:
-               omap_usbhs_rev2_hostconfig(omap, reg);
+               reg = omap_usbhs_rev2_hostconfig(omap, reg);
                break;
 
        default:        /* newer revisions */
-               omap_usbhs_rev2_hostconfig(omap, reg);
+               reg = omap_usbhs_rev2_hostconfig(omap, reg);
                break;
        }
 
index bbdbc50..73bf76d 100644 (file)
@@ -257,9 +257,24 @@ static struct regmap_irq_chip palmas_irq_chip = {
                        PALMAS_INT1_MASK),
 };
 
-static void palmas_dt_to_pdata(struct device_node *node,
+static int palmas_set_pdata_irq_flag(struct i2c_client *i2c,
                struct palmas_platform_data *pdata)
 {
+       struct irq_data *irq_data = irq_get_irq_data(i2c->irq);
+       if (!irq_data) {
+               dev_err(&i2c->dev, "Invalid IRQ: %d\n", i2c->irq);
+               return -EINVAL;
+       }
+
+       pdata->irq_flags = irqd_get_trigger_type(irq_data);
+       dev_info(&i2c->dev, "Irq flag is 0x%08x\n", pdata->irq_flags);
+       return 0;
+}
+
+static void palmas_dt_to_pdata(struct i2c_client *i2c,
+               struct palmas_platform_data *pdata)
+{
+       struct device_node *node = i2c->dev.of_node;
        int ret;
        u32 prop;
 
@@ -283,6 +298,8 @@ static void palmas_dt_to_pdata(struct device_node *node,
                pdata->power_ctrl = PALMAS_POWER_CTRL_NSLEEP_MASK |
                                        PALMAS_POWER_CTRL_ENABLE1_MASK |
                                        PALMAS_POWER_CTRL_ENABLE2_MASK;
+       if (i2c->irq)
+               palmas_set_pdata_irq_flag(i2c, pdata);
 }
 
 static int palmas_i2c_probe(struct i2c_client *i2c,
@@ -304,7 +321,7 @@ static int palmas_i2c_probe(struct i2c_client *i2c,
                if (!pdata)
                        return -ENOMEM;
 
-               palmas_dt_to_pdata(node, pdata);
+               palmas_dt_to_pdata(i2c, pdata);
        }
 
        if (!pdata)
@@ -344,6 +361,19 @@ static int palmas_i2c_probe(struct i2c_client *i2c,
                }
        }
 
+       /* Change interrupt line output polarity */
+       if (pdata->irq_flags & IRQ_TYPE_LEVEL_HIGH)
+               reg = PALMAS_POLARITY_CTRL_INT_POLARITY;
+       else
+               reg = 0;
+       ret = palmas_update_bits(palmas, PALMAS_PU_PD_OD_BASE,
+                       PALMAS_POLARITY_CTRL, PALMAS_POLARITY_CTRL_INT_POLARITY,
+                       reg);
+       if (ret < 0) {
+               dev_err(palmas->dev, "POLARITY_CTRL updat failed: %d\n", ret);
+               goto err;
+       }
+
        /* Change IRQ into clear on read mode for efficiency */
        slave = PALMAS_BASE_TO_SLAVE(PALMAS_INTERRUPT_BASE);
        addr = PALMAS_BASE_TO_REG(PALMAS_INTERRUPT_BASE, PALMAS_INT_CTRL);
@@ -352,7 +382,7 @@ static int palmas_i2c_probe(struct i2c_client *i2c,
        regmap_write(palmas->regmap[slave], addr, reg);
 
        ret = regmap_add_irq_chip(palmas->regmap[slave], palmas->irq,
-                       IRQF_ONESHOT | IRQF_TRIGGER_LOW, 0, &palmas_irq_chip,
+                       IRQF_ONESHOT | pdata->irq_flags, 0, &palmas_irq_chip,
                        &palmas->irq_data);
        if (ret < 0)
                goto err;
index 4658b5b..aeb8e40 100644 (file)
@@ -169,6 +169,7 @@ err:
 void tps65912_device_exit(struct tps65912 *tps65912)
 {
        mfd_remove_devices(tps65912->dev);
+       tps65912_irq_exit(tps65912);
        kfree(tps65912);
 }
 
index e16edca..d2ab222 100644 (file)
@@ -118,7 +118,7 @@ EXPORT_SYMBOL_GPL(twl4030_audio_enable_resource);
  * Disable the resource.
  * The function returns with error or the content of the register
  */
-int twl4030_audio_disable_resource(unsigned id)
+int twl4030_audio_disable_resource(enum twl4030_audio_res id)
 {
        struct twl4030_audio *audio = platform_get_drvdata(twl4030_audio_dev);
        int val;
index 88ff9dc..942b666 100644 (file)
@@ -800,7 +800,7 @@ static int twl4030_madc_remove(struct platform_device *pdev)
 
 static struct platform_driver twl4030_madc_driver = {
        .probe = twl4030_madc_probe,
-       .remove = __exit_p(twl4030_madc_remove),
+       .remove = twl4030_madc_remove,
        .driver = {
                   .name = "twl4030_madc",
                   .owner = THIS_MODULE,
index 6673e57..ce5b756 100644 (file)
@@ -110,6 +110,7 @@ static struct file_system_type ibmasmfs_type = {
        .mount          = ibmasmfs_mount,
        .kill_sb        = kill_litter_super,
 };
+MODULE_ALIAS_FS("ibmasmfs");
 
 static int ibmasmfs_fill_super (struct super_block *sb, void *data, int silent)
 {
index 82c0616..92ab30a 100644 (file)
@@ -1238,6 +1238,7 @@ static struct file_system_type mtd_inodefs_type = {
        .mount = mtd_inodefs_mount,
        .kill_sb = kill_anon_super,
 };
+MODULE_ALIAS_FS("mtd_inodefs");
 
 static int __init init_mtdchar(void)
 {
index 11d01d6..8b4e96e 100644 (file)
@@ -1629,7 +1629,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 
        /* If this is the first slave, then we need to set the master's hardware
         * address to be the same as the slave's. */
-       if (bond->dev_addr_from_first)
+       if (bond->slave_cnt == 0 && bond->dev_addr_from_first)
                bond_set_dev_addr(bond->dev, slave_dev);
 
        new_slave = kzalloc(sizeof(struct slave), GFP_KERNEL);
@@ -1964,7 +1964,6 @@ static int __bond_release_one(struct net_device *bond_dev,
        }
 
        block_netpoll_tx();
-       call_netdevice_notifiers(NETDEV_RELEASE, bond_dev);
        write_lock_bh(&bond->lock);
 
        slave = bond_get_slave_by_dev(bond, slave_dev);
@@ -2066,8 +2065,10 @@ static int __bond_release_one(struct net_device *bond_dev,
        write_unlock_bh(&bond->lock);
        unblock_netpoll_tx();
 
-       if (bond->slave_cnt == 0)
+       if (bond->slave_cnt == 0) {
                call_netdevice_notifiers(NETDEV_CHANGEADDR, bond->dev);
+               call_netdevice_notifiers(NETDEV_RELEASE, bond->dev);
+       }
 
        bond_compute_features(bond);
        if (!(bond_dev->features & NETIF_F_VLAN_CHALLENGED) &&
index 639049d..da5f439 100644 (file)
@@ -301,12 +301,16 @@ static int bgmac_dma_rx_read(struct bgmac *bgmac, struct bgmac_dma_ring *ring,
                        bgmac_err(bgmac, "Found poisoned packet at slot %d, DMA issue!\n",
                                  ring->start);
                } else {
+                       /* Omit CRC. */
+                       len -= ETH_FCS_LEN;
+
                        new_skb = netdev_alloc_skb_ip_align(bgmac->net_dev, len);
                        if (new_skb) {
                                skb_put(new_skb, len);
                                skb_copy_from_linear_data_offset(skb, BGMAC_RX_FRAME_OFFSET,
                                                                 new_skb->data,
                                                                 len);
+                               skb_checksum_none_assert(skb);
                                new_skb->protocol =
                                        eth_type_trans(new_skb, bgmac->net_dev);
                                netif_receive_skb(new_skb);
index ecac04a..a923bc4 100644 (file)
@@ -3142,7 +3142,7 @@ static inline __le16 bnx2x_csum_fix(unsigned char *t_header, u16 csum, s8 fix)
                tsum = ~csum_fold(csum_add((__force __wsum) csum,
                                  csum_partial(t_header, -fix, 0)));
 
-       return bswab16(csum);
+       return bswab16(tsum);
 }
 
 static inline u32 bnx2x_xmit_type(struct bnx2x *bp, struct sk_buff *skb)
index 9a674b1..edfa67a 100644 (file)
@@ -281,6 +281,8 @@ static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
                        cmd->lp_advertising |= ADVERTISED_2500baseX_Full;
                if (status & LINK_STATUS_LINK_PARTNER_10GXFD_CAPABLE)
                        cmd->lp_advertising |= ADVERTISED_10000baseT_Full;
+               if (status & LINK_STATUS_LINK_PARTNER_20GXFD_CAPABLE)
+                       cmd->lp_advertising |= ADVERTISED_20000baseKR2_Full;
        }
 
        cmd->maxtxpkt = 0;
@@ -463,6 +465,10 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
                                                ADVERTISED_10000baseKR_Full))
                                bp->link_params.speed_cap_mask[cfg_idx] |=
                                        PORT_HW_CFG_SPEED_CAPABILITY_D0_10G;
+
+                       if (cmd->advertising & ADVERTISED_20000baseKR2_Full)
+                               bp->link_params.speed_cap_mask[cfg_idx] |=
+                                       PORT_HW_CFG_SPEED_CAPABILITY_D0_20G;
                }
        } else { /* forced speed */
                /* advertise the requested speed and duplex if supported */
index 1663e0b..77ebae0 100644 (file)
@@ -8647,7 +8647,9 @@ void bnx2x_handle_module_detect_int(struct link_params *params)
                                                MDIO_WC_DEVAD,
                                                MDIO_WC_REG_DIGITAL5_MISC6,
                                                &rx_tx_in_reset);
-                               if (!rx_tx_in_reset) {
+                               if ((!rx_tx_in_reset) &&
+                                   (params->link_flags &
+                                    PHY_INITIALIZED)) {
                                        bnx2x_warpcore_reset_lane(bp, phy, 1);
                                        bnx2x_warpcore_config_sfi(phy, params);
                                        bnx2x_warpcore_reset_lane(bp, phy, 0);
@@ -10422,6 +10424,28 @@ static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy,
                                         MDIO_PMA_DEVAD,
                                         MDIO_PMA_REG_8481_LED1_MASK,
                                         0x0);
+                       if (phy->type ==
+                           PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834) {
+                               /* Disable MI_INT interrupt before setting LED4
+                                * source to constant off.
+                                */
+                               if (REG_RD(bp, NIG_REG_MASK_INTERRUPT_PORT0 +
+                                          params->port*4) &
+                                   NIG_MASK_MI_INT) {
+                                       params->link_flags |=
+                                       LINK_FLAGS_INT_DISABLED;
+
+                                       bnx2x_bits_dis(
+                                               bp,
+                                               NIG_REG_MASK_INTERRUPT_PORT0 +
+                                               params->port*4,
+                                               NIG_MASK_MI_INT);
+                               }
+                               bnx2x_cl45_write(bp, phy,
+                                                MDIO_PMA_DEVAD,
+                                                MDIO_PMA_REG_8481_SIGNAL_MASK,
+                                                0x0);
+                       }
                }
                break;
        case LED_MODE_ON:
@@ -10468,6 +10492,28 @@ static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy,
                                         MDIO_PMA_DEVAD,
                                         MDIO_PMA_REG_8481_LED1_MASK,
                                         0x20);
+                       if (phy->type ==
+                           PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834) {
+                               /* Disable MI_INT interrupt before setting LED4
+                                * source to constant on.
+                                */
+                               if (REG_RD(bp, NIG_REG_MASK_INTERRUPT_PORT0 +
+                                          params->port*4) &
+                                   NIG_MASK_MI_INT) {
+                                       params->link_flags |=
+                                       LINK_FLAGS_INT_DISABLED;
+
+                                       bnx2x_bits_dis(
+                                               bp,
+                                               NIG_REG_MASK_INTERRUPT_PORT0 +
+                                               params->port*4,
+                                               NIG_MASK_MI_INT);
+                               }
+                               bnx2x_cl45_write(bp, phy,
+                                                MDIO_PMA_DEVAD,
+                                                MDIO_PMA_REG_8481_SIGNAL_MASK,
+                                                0x20);
+                       }
                }
                break;
 
@@ -10532,6 +10578,22 @@ static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy,
                                         MDIO_PMA_DEVAD,
                                         MDIO_PMA_REG_8481_LINK_SIGNAL,
                                         val);
+                       if (phy->type ==
+                           PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834) {
+                               /* Restore LED4 source to external link,
+                                * and re-enable interrupts.
+                                */
+                               bnx2x_cl45_write(bp, phy,
+                                                MDIO_PMA_DEVAD,
+                                                MDIO_PMA_REG_8481_SIGNAL_MASK,
+                                                0x40);
+                               if (params->link_flags &
+                                   LINK_FLAGS_INT_DISABLED) {
+                                       bnx2x_link_int_enable(params);
+                                       params->link_flags &=
+                                               ~LINK_FLAGS_INT_DISABLED;
+                               }
+                       }
                }
                break;
        }
@@ -11791,6 +11853,8 @@ static int bnx2x_populate_int_phy(struct bnx2x *bp, u32 shmem_base, u8 port,
                        phy->media_type = ETH_PHY_KR;
                        phy->flags |= FLAGS_WC_DUAL_MODE;
                        phy->supported &= (SUPPORTED_20000baseKR2_Full |
+                                          SUPPORTED_10000baseT_Full |
+                                          SUPPORTED_1000baseT_Full |
                                           SUPPORTED_Autoneg |
                                           SUPPORTED_FIBRE |
                                           SUPPORTED_Pause |
@@ -12465,6 +12529,8 @@ int bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
        vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
        vars->mac_type = MAC_TYPE_NONE;
        vars->phy_flags = 0;
+       vars->check_kr2_recovery_cnt = 0;
+       params->link_flags = PHY_INITIALIZED;
        /* Driver opens NIG-BRB filters */
        bnx2x_set_rx_filter(params, 1);
        /* Check if link flap can be avoided */
@@ -12629,6 +12695,7 @@ int bnx2x_lfa_reset(struct link_params *params,
        struct bnx2x *bp = params->bp;
        vars->link_up = 0;
        vars->phy_flags = 0;
+       params->link_flags &= ~PHY_INITIALIZED;
        if (!params->lfa_base)
                return bnx2x_link_reset(params, vars, 1);
        /*
@@ -13349,6 +13416,7 @@ static void bnx2x_disable_kr2(struct link_params *params,
        vars->link_attr_sync &= ~LINK_ATTR_SYNC_KR2_ENABLE;
        bnx2x_update_link_attr(params, vars->link_attr_sync);
 
+       vars->check_kr2_recovery_cnt = CHECK_KR2_RECOVERY_CNT;
        /* Restart AN on leading lane */
        bnx2x_warpcore_restart_AN_KR(phy, params);
 }
@@ -13377,6 +13445,15 @@ static void bnx2x_check_kr2_wa(struct link_params *params,
                return;
        }
 
+       /* Once KR2 was disabled, wait 5 seconds before checking KR2 recovery
+        * since some switches tend to reinit the AN process and clear the
+        * advertised BP/NP after ~2 seconds causing the KR2 to be disabled
+        * and recovered many times
+        */
+       if (vars->check_kr2_recovery_cnt > 0) {
+               vars->check_kr2_recovery_cnt--;
+               return;
+       }
        lane = bnx2x_get_warpcore_lane(phy, params);
        CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
                          MDIO_AER_BLOCK_AER_REG, lane);
@@ -13437,7 +13514,7 @@ void bnx2x_period_func(struct link_params *params, struct link_vars *vars)
                struct bnx2x_phy *phy = &params->phy[INT_PHY];
                bnx2x_set_aer_mmd(params, phy);
                if ((phy->supported & SUPPORTED_20000baseKR2_Full) &&
-                   (phy->speed_cap_mask & SPEED_20000))
+                   (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_20G))
                        bnx2x_check_kr2_wa(params, vars, phy);
                bnx2x_check_over_curr(params, vars);
                if (vars->rx_tx_asic_rst)
index d25c7d7..56c2aae 100644 (file)
@@ -307,7 +307,9 @@ struct link_params {
        struct bnx2x *bp;
        u16 req_fc_auto_adv; /* Should be set to TX / BOTH when
                                req_flow_ctrl is set to AUTO */
-       u16 rsrv1;
+       u16 link_flags;
+#define LINK_FLAGS_INT_DISABLED                (1<<0)
+#define PHY_INITIALIZED                (1<<1)
        u32 lfa_base;
 };
 
@@ -341,7 +343,8 @@ struct link_vars {
        u32 link_status;
        u32 eee_status;
        u8 fault_detected;
-       u8 rsrv1;
+       u8 check_kr2_recovery_cnt;
+#define CHECK_KR2_RECOVERY_CNT 5
        u16 periodic_flags;
 #define PERIODIC_FLAGS_LINK_EVENT      0x0001
 
index fdb9b56..93729f9 100644 (file)
@@ -1869,6 +1869,8 @@ static void tg3_link_report(struct tg3 *tp)
 
                tg3_ump_link_report(tp);
        }
+
+       tp->link_up = netif_carrier_ok(tp->dev);
 }
 
 static u16 tg3_advert_flowctrl_1000X(u8 flow_ctrl)
@@ -2522,12 +2524,6 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp)
        return err;
 }
 
-static void tg3_carrier_on(struct tg3 *tp)
-{
-       netif_carrier_on(tp->dev);
-       tp->link_up = true;
-}
-
 static void tg3_carrier_off(struct tg3 *tp)
 {
        netif_carrier_off(tp->dev);
@@ -2553,7 +2549,7 @@ static int tg3_phy_reset(struct tg3 *tp)
                return -EBUSY;
 
        if (netif_running(tp->dev) && tp->link_up) {
-               tg3_carrier_off(tp);
+               netif_carrier_off(tp->dev);
                tg3_link_report(tp);
        }
 
@@ -4262,9 +4258,9 @@ static bool tg3_test_and_report_link_chg(struct tg3 *tp, int curr_link_up)
 {
        if (curr_link_up != tp->link_up) {
                if (curr_link_up) {
-                       tg3_carrier_on(tp);
+                       netif_carrier_on(tp->dev);
                } else {
-                       tg3_carrier_off(tp);
+                       netif_carrier_off(tp->dev);
                        if (tp->phy_flags & TG3_PHYFLG_MII_SERDES)
                                tp->phy_flags &= ~TG3_PHYFLG_PARALLEL_DETECT;
                }
index 28ceb84..29aff55 100644 (file)
@@ -349,6 +349,7 @@ struct be_adapter {
        struct pci_dev *pdev;
        struct net_device *netdev;
 
+       u8 __iomem *csr;        /* CSR BAR used only for BE2/3 */
        u8 __iomem *db;         /* Door Bell */
 
        struct mutex mbox_lock; /* For serializing mbox cmds to BE card */
index 071aea7..3c9b4f1 100644 (file)
@@ -473,19 +473,17 @@ static int be_mbox_notify_wait(struct be_adapter *adapter)
        return 0;
 }
 
-static int be_POST_stage_get(struct be_adapter *adapter, u16 *stage)
+static u16 be_POST_stage_get(struct be_adapter *adapter)
 {
        u32 sem;
-       u32 reg = skyhawk_chip(adapter) ? SLIPORT_SEMAPHORE_OFFSET_SH :
-                                         SLIPORT_SEMAPHORE_OFFSET_BE;
 
-       pci_read_config_dword(adapter->pdev, reg, &sem);
-       *stage = sem & POST_STAGE_MASK;
-
-       if ((sem >> POST_ERR_SHIFT) & POST_ERR_MASK)
-               return -1;
+       if (BEx_chip(adapter))
+               sem  = ioread32(adapter->csr + SLIPORT_SEMAPHORE_OFFSET_BEx);
        else
-               return 0;
+               pci_read_config_dword(adapter->pdev,
+                                     SLIPORT_SEMAPHORE_OFFSET_SH, &sem);
+
+       return sem & POST_STAGE_MASK;
 }
 
 int lancer_wait_ready(struct be_adapter *adapter)
@@ -579,19 +577,17 @@ int be_fw_wait_ready(struct be_adapter *adapter)
        }
 
        do {
-               status = be_POST_stage_get(adapter, &stage);
-               if (status) {
-                       dev_err(dev, "POST error; stage=0x%x\n", stage);
-                       return -1;
-               } else if (stage != POST_STAGE_ARMFW_RDY) {
-                       if (msleep_interruptible(2000)) {
-                               dev_err(dev, "Waiting for POST aborted\n");
-                               return -EINTR;
-                       }
-                       timeout += 2;
-               } else {
+               stage = be_POST_stage_get(adapter);
+               if (stage == POST_STAGE_ARMFW_RDY)
                        return 0;
+
+               dev_info(dev, "Waiting for POST, %ds elapsed\n",
+                        timeout);
+               if (msleep_interruptible(2000)) {
+                       dev_err(dev, "Waiting for POST aborted\n");
+                       return -EINTR;
                }
+               timeout += 2;
        } while (timeout < 60);
 
        dev_err(dev, "POST timeout; stage=0x%x\n", stage);
index 541d453..62dc220 100644 (file)
@@ -32,8 +32,8 @@
 #define MPU_EP_CONTROL                 0
 
 /********** MPU semphore: used for SH & BE  *************/
-#define SLIPORT_SEMAPHORE_OFFSET_BE            0x7c
-#define SLIPORT_SEMAPHORE_OFFSET_SH            0x94
+#define SLIPORT_SEMAPHORE_OFFSET_BEx           0xac  /* CSR BAR offset */
+#define SLIPORT_SEMAPHORE_OFFSET_SH            0x94  /* PCI-CFG offset */
 #define POST_STAGE_MASK                                0x0000FFFF
 #define POST_ERR_MASK                          0x1
 #define POST_ERR_SHIFT                         31
index 3860888..08e54f3 100644 (file)
@@ -3688,6 +3688,8 @@ static void be_netdev_init(struct net_device *netdev)
 
 static void be_unmap_pci_bars(struct be_adapter *adapter)
 {
+       if (adapter->csr)
+               pci_iounmap(adapter->pdev, adapter->csr);
        if (adapter->db)
                pci_iounmap(adapter->pdev, adapter->db);
 }
@@ -3721,6 +3723,12 @@ static int be_map_pci_bars(struct be_adapter *adapter)
        adapter->if_type = (sli_intf & SLI_INTF_IF_TYPE_MASK) >>
                                SLI_INTF_IF_TYPE_SHIFT;
 
+       if (BEx_chip(adapter) && be_physfn(adapter)) {
+               adapter->csr = pci_iomap(adapter->pdev, 2, 0);
+               if (adapter->csr == NULL)
+                       return -ENOMEM;
+       }
+
        addr = pci_iomap(adapter->pdev, db_bar(adapter), 0);
        if (addr == NULL)
                goto pci_map_err;
@@ -4329,6 +4337,8 @@ static pci_ers_result_t be_eeh_reset(struct pci_dev *pdev)
        pci_restore_state(pdev);
 
        /* Check if card is ok and fw is ready */
+       dev_info(&adapter->pdev->dev,
+                "Waiting for FW to be ready after EEH reset\n");
        status = be_fw_wait_ready(adapter);
        if (status)
                return PCI_ERS_RESULT_DISCONNECT;
index fccc3bf..069a155 100644 (file)
@@ -246,14 +246,13 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
        struct bufdesc *bdp;
        void *bufaddr;
        unsigned short  status;
-       unsigned long flags;
+       unsigned int index;
 
        if (!fep->link) {
                /* Link is down or autonegotiation is in progress. */
                return NETDEV_TX_BUSY;
        }
 
-       spin_lock_irqsave(&fep->hw_lock, flags);
        /* Fill in a Tx ring entry */
        bdp = fep->cur_tx;
 
@@ -264,7 +263,6 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
                 * This should not happen, since ndev->tbusy should be set.
                 */
                printk("%s: tx queue full!.\n", ndev->name);
-               spin_unlock_irqrestore(&fep->hw_lock, flags);
                return NETDEV_TX_BUSY;
        }
 
@@ -280,13 +278,13 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
         * 4-byte boundaries. Use bounce buffers to copy data
         * and get it aligned. Ugh.
         */
+       if (fep->bufdesc_ex)
+               index = (struct bufdesc_ex *)bdp -
+                       (struct bufdesc_ex *)fep->tx_bd_base;
+       else
+               index = bdp - fep->tx_bd_base;
+
        if (((unsigned long) bufaddr) & FEC_ALIGNMENT) {
-               unsigned int index;
-               if (fep->bufdesc_ex)
-                       index = (struct bufdesc_ex *)bdp -
-                               (struct bufdesc_ex *)fep->tx_bd_base;
-               else
-                       index = bdp - fep->tx_bd_base;
                memcpy(fep->tx_bounce[index], skb->data, skb->len);
                bufaddr = fep->tx_bounce[index];
        }
@@ -300,10 +298,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
                swap_buffer(bufaddr, skb->len);
 
        /* Save skb pointer */
-       fep->tx_skbuff[fep->skb_cur] = skb;
-
-       ndev->stats.tx_bytes += skb->len;
-       fep->skb_cur = (fep->skb_cur+1) & TX_RING_MOD_MASK;
+       fep->tx_skbuff[index] = skb;
 
        /* Push the data cache so the CPM does not get stale memory
         * data.
@@ -331,26 +326,22 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
                        ebdp->cbd_esc = BD_ENET_TX_INT;
                }
        }
-       /* Trigger transmission start */
-       writel(0, fep->hwp + FEC_X_DES_ACTIVE);
-
        /* If this was the last BD in the ring, start at the beginning again. */
        if (status & BD_ENET_TX_WRAP)
                bdp = fep->tx_bd_base;
        else
                bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
 
-       if (bdp == fep->dirty_tx) {
-               fep->tx_full = 1;
+       fep->cur_tx = bdp;
+
+       if (fep->cur_tx == fep->dirty_tx)
                netif_stop_queue(ndev);
-       }
 
-       fep->cur_tx = bdp;
+       /* Trigger transmission start */
+       writel(0, fep->hwp + FEC_X_DES_ACTIVE);
 
        skb_tx_timestamp(skb);
 
-       spin_unlock_irqrestore(&fep->hw_lock, flags);
-
        return NETDEV_TX_OK;
 }
 
@@ -406,11 +397,8 @@ fec_restart(struct net_device *ndev, int duplex)
                writel((unsigned long)fep->bd_dma + sizeof(struct bufdesc)
                        * RX_RING_SIZE, fep->hwp + FEC_X_DES_START);
 
-       fep->dirty_tx = fep->cur_tx = fep->tx_bd_base;
        fep->cur_rx = fep->rx_bd_base;
 
-       /* Reset SKB transmit buffers. */
-       fep->skb_cur = fep->skb_dirty = 0;
        for (i = 0; i <= TX_RING_MOD_MASK; i++) {
                if (fep->tx_skbuff[i]) {
                        dev_kfree_skb_any(fep->tx_skbuff[i]);
@@ -573,20 +561,35 @@ fec_enet_tx(struct net_device *ndev)
        struct bufdesc *bdp;
        unsigned short status;
        struct  sk_buff *skb;
+       int     index = 0;
 
        fep = netdev_priv(ndev);
-       spin_lock(&fep->hw_lock);
        bdp = fep->dirty_tx;
 
+       /* get next bdp of dirty_tx */
+       if (bdp->cbd_sc & BD_ENET_TX_WRAP)
+               bdp = fep->tx_bd_base;
+       else
+               bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
+
        while (((status = bdp->cbd_sc) & BD_ENET_TX_READY) == 0) {
-               if (bdp == fep->cur_tx && fep->tx_full == 0)
+
+               /* current queue is empty */
+               if (bdp == fep->cur_tx)
                        break;
 
+               if (fep->bufdesc_ex)
+                       index = (struct bufdesc_ex *)bdp -
+                               (struct bufdesc_ex *)fep->tx_bd_base;
+               else
+                       index = bdp - fep->tx_bd_base;
+
                dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr,
                                FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE);
                bdp->cbd_bufaddr = 0;
 
-               skb = fep->tx_skbuff[fep->skb_dirty];
+               skb = fep->tx_skbuff[index];
+
                /* Check for errors. */
                if (status & (BD_ENET_TX_HB | BD_ENET_TX_LC |
                                   BD_ENET_TX_RL | BD_ENET_TX_UN |
@@ -631,8 +634,9 @@ fec_enet_tx(struct net_device *ndev)
 
                /* Free the sk buffer associated with this last transmit */
                dev_kfree_skb_any(skb);
-               fep->tx_skbuff[fep->skb_dirty] = NULL;
-               fep->skb_dirty = (fep->skb_dirty + 1) & TX_RING_MOD_MASK;
+               fep->tx_skbuff[index] = NULL;
+
+               fep->dirty_tx = bdp;
 
                /* Update pointer to next buffer descriptor to be transmitted */
                if (status & BD_ENET_TX_WRAP)
@@ -642,14 +646,12 @@ fec_enet_tx(struct net_device *ndev)
 
                /* Since we have freed up a buffer, the ring is no longer full
                 */
-               if (fep->tx_full) {
-                       fep->tx_full = 0;
+               if (fep->dirty_tx != fep->cur_tx) {
                        if (netif_queue_stopped(ndev))
                                netif_wake_queue(ndev);
                }
        }
-       fep->dirty_tx = bdp;
-       spin_unlock(&fep->hw_lock);
+       return;
 }
 
 
@@ -816,7 +818,7 @@ fec_enet_interrupt(int irq, void *dev_id)
                int_events = readl(fep->hwp + FEC_IEVENT);
                writel(int_events, fep->hwp + FEC_IEVENT);
 
-               if (int_events & FEC_ENET_RXF) {
+               if (int_events & (FEC_ENET_RXF | FEC_ENET_TXF)) {
                        ret = IRQ_HANDLED;
 
                        /* Disable the RX interrupt */
@@ -827,15 +829,6 @@ fec_enet_interrupt(int irq, void *dev_id)
                        }
                }
 
-               /* Transmit OK, or non-fatal error. Update the buffer
-                * descriptors. FEC handles all errors, we just discover
-                * them as part of the transmit process.
-                */
-               if (int_events & FEC_ENET_TXF) {
-                       ret = IRQ_HANDLED;
-                       fec_enet_tx(ndev);
-               }
-
                if (int_events & FEC_ENET_MII) {
                        ret = IRQ_HANDLED;
                        complete(&fep->mdio_done);
@@ -851,6 +844,8 @@ static int fec_enet_rx_napi(struct napi_struct *napi, int budget)
        int pkts = fec_enet_rx(ndev, budget);
        struct fec_enet_private *fep = netdev_priv(ndev);
 
+       fec_enet_tx(ndev);
+
        if (pkts < budget) {
                napi_complete(napi);
                writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
@@ -1646,6 +1641,7 @@ static int fec_enet_init(struct net_device *ndev)
 
        /* ...and the same for transmit */
        bdp = fep->tx_bd_base;
+       fep->cur_tx = bdp;
        for (i = 0; i < TX_RING_SIZE; i++) {
 
                /* Initialize the BD for every fragment in the page. */
@@ -1657,6 +1653,7 @@ static int fec_enet_init(struct net_device *ndev)
        /* Set the last buffer to wrap */
        bdp = fec_enet_get_prevdesc(bdp, fep->bufdesc_ex);
        bdp->cbd_sc |= BD_SC_WRAP;
+       fep->dirty_tx = bdp;
 
        fec_restart(ndev, 0);
 
index 01579b8..f539007 100644 (file)
@@ -97,6 +97,13 @@ struct bufdesc {
        unsigned short cbd_sc;  /* Control and status info */
        unsigned long cbd_bufaddr;      /* Buffer address */
 };
+#else
+struct bufdesc {
+       unsigned short  cbd_sc;                 /* Control and status info */
+       unsigned short  cbd_datlen;             /* Data length */
+       unsigned long   cbd_bufaddr;            /* Buffer address */
+};
+#endif
 
 struct bufdesc_ex {
        struct bufdesc desc;
@@ -107,14 +114,6 @@ struct bufdesc_ex {
        unsigned short res0[4];
 };
 
-#else
-struct bufdesc {
-       unsigned short  cbd_sc;                 /* Control and status info */
-       unsigned short  cbd_datlen;             /* Data length */
-       unsigned long   cbd_bufaddr;            /* Buffer address */
-};
-#endif
-
 /*
  *     The following definitions courtesy of commproc.h, which where
  *     Copyright (c) 1997 Dan Malek (dmalek@jlc.net).
@@ -214,8 +213,6 @@ struct fec_enet_private {
        unsigned char *tx_bounce[TX_RING_SIZE];
        struct  sk_buff *tx_skbuff[TX_RING_SIZE];
        struct  sk_buff *rx_skbuff[RX_RING_SIZE];
-       ushort  skb_cur;
-       ushort  skb_dirty;
 
        /* CPM dual port RAM relative addresses */
        dma_addr_t      bd_dma;
@@ -227,7 +224,6 @@ struct fec_enet_private {
        /* The ring entries to be free()ed */
        struct bufdesc  *dirty_tx;
 
-       uint    tx_full;
        /* hold while accessing the HW like ringbuffer for tx/rx but not MAC */
        spinlock_t hw_lock;
 
index 2c18137..f91a8f3 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/delay.h>
 #include <linux/vmalloc.h>
 #include <linux/mdio.h>
+#include <linux/pm_runtime.h>
 
 #include "e1000.h"
 
@@ -2229,7 +2230,19 @@ static int e1000e_get_ts_info(struct net_device *netdev,
        return 0;
 }
 
+static int e1000e_ethtool_begin(struct net_device *netdev)
+{
+       return pm_runtime_get_sync(netdev->dev.parent);
+}
+
+static void e1000e_ethtool_complete(struct net_device *netdev)
+{
+       pm_runtime_put_sync(netdev->dev.parent);
+}
+
 static const struct ethtool_ops e1000_ethtool_ops = {
+       .begin                  = e1000e_ethtool_begin,
+       .complete               = e1000e_ethtool_complete,
        .get_settings           = e1000_get_settings,
        .set_settings           = e1000_set_settings,
        .get_drvinfo            = e1000_get_drvinfo,
index dff7bff..121a865 100644 (file)
@@ -782,6 +782,59 @@ release:
 }
 
 /**
+ *  e1000_k1_workaround_lpt_lp - K1 workaround on Lynxpoint-LP
+ *  @hw:   pointer to the HW structure
+ *  @link: link up bool flag
+ *
+ *  When K1 is enabled for 1Gbps, the MAC can miss 2 DMA completion indications
+ *  preventing further DMA write requests.  Workaround the issue by disabling
+ *  the de-assertion of the clock request when in 1Gpbs mode.
+ **/
+static s32 e1000_k1_workaround_lpt_lp(struct e1000_hw *hw, bool link)
+{
+       u32 fextnvm6 = er32(FEXTNVM6);
+       s32 ret_val = 0;
+
+       if (link && (er32(STATUS) & E1000_STATUS_SPEED_1000)) {
+               u16 kmrn_reg;
+
+               ret_val = hw->phy.ops.acquire(hw);
+               if (ret_val)
+                       return ret_val;
+
+               ret_val =
+                   e1000e_read_kmrn_reg_locked(hw, E1000_KMRNCTRLSTA_K1_CONFIG,
+                                               &kmrn_reg);
+               if (ret_val)
+                       goto release;
+
+               ret_val =
+                   e1000e_write_kmrn_reg_locked(hw,
+                                                E1000_KMRNCTRLSTA_K1_CONFIG,
+                                                kmrn_reg &
+                                                ~E1000_KMRNCTRLSTA_K1_ENABLE);
+               if (ret_val)
+                       goto release;
+
+               usleep_range(10, 20);
+
+               ew32(FEXTNVM6, fextnvm6 | E1000_FEXTNVM6_REQ_PLL_CLK);
+
+               ret_val =
+                   e1000e_write_kmrn_reg_locked(hw,
+                                                E1000_KMRNCTRLSTA_K1_CONFIG,
+                                                kmrn_reg);
+release:
+               hw->phy.ops.release(hw);
+       } else {
+               /* clear FEXTNVM6 bit 8 on link down or 10/100 */
+               ew32(FEXTNVM6, fextnvm6 & ~E1000_FEXTNVM6_REQ_PLL_CLK);
+       }
+
+       return ret_val;
+}
+
+/**
  *  e1000_check_for_copper_link_ich8lan - Check for link (Copper)
  *  @hw: pointer to the HW structure
  *
@@ -818,6 +871,14 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
                        return ret_val;
        }
 
+       /* Work-around I218 hang issue */
+       if ((hw->adapter->pdev->device == E1000_DEV_ID_PCH_LPTLP_I218_LM) ||
+           (hw->adapter->pdev->device == E1000_DEV_ID_PCH_LPTLP_I218_V)) {
+               ret_val = e1000_k1_workaround_lpt_lp(hw, link);
+               if (ret_val)
+                       return ret_val;
+       }
+
        /* Clear link partner's EEE ability */
        hw->dev_spec.ich8lan.eee_lp_ability = 0;
 
@@ -3954,8 +4015,16 @@ void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw)
 
        phy_ctrl = er32(PHY_CTRL);
        phy_ctrl |= E1000_PHY_CTRL_GBE_DISABLE;
+
        if (hw->phy.type == e1000_phy_i217) {
-               u16 phy_reg;
+               u16 phy_reg, device_id = hw->adapter->pdev->device;
+
+               if ((device_id == E1000_DEV_ID_PCH_LPTLP_I218_LM) ||
+                   (device_id == E1000_DEV_ID_PCH_LPTLP_I218_V)) {
+                       u32 fextnvm6 = er32(FEXTNVM6);
+
+                       ew32(FEXTNVM6, fextnvm6 & ~E1000_FEXTNVM6_REQ_PLL_CLK);
+               }
 
                ret_val = hw->phy.ops.acquire(hw);
                if (ret_val)
index b6d3174..8bf4655 100644 (file)
@@ -92,6 +92,8 @@
 #define E1000_FEXTNVM4_BEACON_DURATION_8USEC   0x7
 #define E1000_FEXTNVM4_BEACON_DURATION_16USEC  0x3
 
+#define E1000_FEXTNVM6_REQ_PLL_CLK     0x00000100
+
 #define PCIE_ICH8_SNOOP_ALL    PCIE_NO_SNOOP_ALL
 
 #define E1000_ICH_RAR_ENTRIES  7
index a177b8b..948b86f 100644 (file)
@@ -4303,6 +4303,7 @@ static int e1000_open(struct net_device *netdev)
        netif_start_queue(netdev);
 
        adapter->idle_check = true;
+       hw->mac.get_link_status = true;
        pm_runtime_put(&pdev->dev);
 
        /* fire a link status change interrupt to start the watchdog */
@@ -4662,6 +4663,7 @@ static void e1000_phy_read_status(struct e1000_adapter *adapter)
            (adapter->hw.phy.media_type == e1000_media_type_copper)) {
                int ret_val;
 
+               pm_runtime_get_sync(&adapter->pdev->dev);
                ret_val = e1e_rphy(hw, MII_BMCR, &phy->bmcr);
                ret_val |= e1e_rphy(hw, MII_BMSR, &phy->bmsr);
                ret_val |= e1e_rphy(hw, MII_ADVERTISE, &phy->advertise);
@@ -4672,6 +4674,7 @@ static void e1000_phy_read_status(struct e1000_adapter *adapter)
                ret_val |= e1e_rphy(hw, MII_ESTATUS, &phy->estatus);
                if (ret_val)
                        e_warn("Error reading PHY register\n");
+               pm_runtime_put_sync(&adapter->pdev->dev);
        } else {
                /* Do not read PHY registers if link is not up
                 * Set values to typical power-on defaults
@@ -5887,8 +5890,7 @@ release:
        return retval;
 }
 
-static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake,
-                           bool runtime)
+static int __e1000_shutdown(struct pci_dev *pdev, bool runtime)
 {
        struct net_device *netdev = pci_get_drvdata(pdev);
        struct e1000_adapter *adapter = netdev_priv(netdev);
@@ -5912,10 +5914,6 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake,
        }
        e1000e_reset_interrupt_capability(adapter);
 
-       retval = pci_save_state(pdev);
-       if (retval)
-               return retval;
-
        status = er32(STATUS);
        if (status & E1000_STATUS_LU)
                wufc &= ~E1000_WUFC_LNKC;
@@ -5971,13 +5969,6 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake,
                ew32(WUFC, 0);
        }
 
-       *enable_wake = !!wufc;
-
-       /* make sure adapter isn't asleep if manageability is enabled */
-       if ((adapter->flags & FLAG_MNG_PT_ENABLED) ||
-           (hw->mac.ops.check_mng_mode(hw)))
-               *enable_wake = true;
-
        if (adapter->hw.phy.type == e1000_phy_igp_3)
                e1000e_igp3_phy_powerdown_workaround_ich8lan(&adapter->hw);
 
@@ -5986,27 +5977,7 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake,
         */
        e1000e_release_hw_control(adapter);
 
-       pci_disable_device(pdev);
-
-       return 0;
-}
-
-static void e1000_power_off(struct pci_dev *pdev, bool sleep, bool wake)
-{
-       if (sleep && wake) {
-               pci_prepare_to_sleep(pdev);
-               return;
-       }
-
-       pci_wake_from_d3(pdev, wake);
-       pci_set_power_state(pdev, PCI_D3hot);
-}
-
-static void e1000_complete_shutdown(struct pci_dev *pdev, bool sleep,
-                                    bool wake)
-{
-       struct net_device *netdev = pci_get_drvdata(pdev);
-       struct e1000_adapter *adapter = netdev_priv(netdev);
+       pci_clear_master(pdev);
 
        /* The pci-e switch on some quad port adapters will report a
         * correctable error when the MAC transitions from D0 to D3.  To
@@ -6021,12 +5992,13 @@ static void e1000_complete_shutdown(struct pci_dev *pdev, bool sleep,
                pcie_capability_write_word(us_dev, PCI_EXP_DEVCTL,
                                           (devctl & ~PCI_EXP_DEVCTL_CERE));
 
-               e1000_power_off(pdev, sleep, wake);
+               pci_save_state(pdev);
+               pci_prepare_to_sleep(pdev);
 
                pcie_capability_write_word(us_dev, PCI_EXP_DEVCTL, devctl);
-       } else {
-               e1000_power_off(pdev, sleep, wake);
        }
+
+       return 0;
 }
 
 #ifdef CONFIG_PCIEASPM
@@ -6084,9 +6056,7 @@ static int __e1000_resume(struct pci_dev *pdev)
        if (aspm_disable_flag)
                e1000e_disable_aspm(pdev, aspm_disable_flag);
 
-       pci_set_power_state(pdev, PCI_D0);
-       pci_restore_state(pdev);
-       pci_save_state(pdev);
+       pci_set_master(pdev);
 
        e1000e_set_interrupt_capability(adapter);
        if (netif_running(netdev)) {
@@ -6152,14 +6122,8 @@ static int __e1000_resume(struct pci_dev *pdev)
 static int e1000_suspend(struct device *dev)
 {
        struct pci_dev *pdev = to_pci_dev(dev);
-       int retval;
-       bool wake;
-
-       retval = __e1000_shutdown(pdev, &wake, false);
-       if (!retval)
-               e1000_complete_shutdown(pdev, true, wake);
 
-       return retval;
+       return __e1000_shutdown(pdev, false);
 }
 
 static int e1000_resume(struct device *dev)
@@ -6182,13 +6146,10 @@ static int e1000_runtime_suspend(struct device *dev)
        struct net_device *netdev = pci_get_drvdata(pdev);
        struct e1000_adapter *adapter = netdev_priv(netdev);
 
-       if (e1000e_pm_ready(adapter)) {
-               bool wake;
-
-               __e1000_shutdown(pdev, &wake, true);
-       }
+       if (!e1000e_pm_ready(adapter))
+               return 0;
 
-       return 0;
+       return __e1000_shutdown(pdev, true);
 }
 
 static int e1000_idle(struct device *dev)
@@ -6226,12 +6187,7 @@ static int e1000_runtime_resume(struct device *dev)
 
 static void e1000_shutdown(struct pci_dev *pdev)
 {
-       bool wake = false;
-
-       __e1000_shutdown(pdev, &wake, false);
-
-       if (system_state == SYSTEM_POWER_OFF)
-               e1000_complete_shutdown(pdev, false, wake);
+       __e1000_shutdown(pdev, false);
 }
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -6352,9 +6308,9 @@ static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev)
                        "Cannot re-enable PCI device after reset.\n");
                result = PCI_ERS_RESULT_DISCONNECT;
        } else {
-               pci_set_master(pdev);
                pdev->state_saved = true;
                pci_restore_state(pdev);
+               pci_set_master(pdev);
 
                pci_enable_wake(pdev, PCI_D3hot, 0);
                pci_enable_wake(pdev, PCI_D3cold, 0);
@@ -6783,7 +6739,11 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        /* initialize the wol settings based on the eeprom settings */
        adapter->wol = adapter->eeprom_wol;
-       device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
+
+       /* make sure adapter isn't asleep if manageability is enabled */
+       if (adapter->wol || (adapter->flags & FLAG_MNG_PT_ENABLED) ||
+           (hw->mac.ops.check_mng_mode(hw)))
+               device_wakeup_enable(&pdev->dev);
 
        /* save off EEPROM version number */
        e1000_read_nvm(&adapter->hw, 5, 1, &adapter->eeprom_vers);
index 794fe14..a7e6a3e 100644 (file)
@@ -42,6 +42,7 @@
 #define E1000_FEXTNVM  0x00028 /* Future Extended NVM - RW */
 #define E1000_FEXTNVM3 0x0003C /* Future Extended NVM 3 - RW */
 #define E1000_FEXTNVM4 0x00024 /* Future Extended NVM 4 - RW */
+#define E1000_FEXTNVM6 0x00010 /* Future Extended NVM 6 - RW */
 #define E1000_FEXTNVM7 0x000E4 /* Future Extended NVM 7 - RW */
 #define E1000_FCT      0x00030 /* Flow Control Type - RW */
 #define E1000_VET      0x00038 /* VLAN Ether Type - RW */
index 84e7e09..b64542a 100644 (file)
@@ -1361,11 +1361,16 @@ static s32 igb_setup_copper_link_82575(struct e1000_hw *hw)
        switch (hw->phy.type) {
        case e1000_phy_i210:
        case e1000_phy_m88:
-               if (hw->phy.id == I347AT4_E_PHY_ID ||
-                   hw->phy.id == M88E1112_E_PHY_ID)
+               switch (hw->phy.id) {
+               case I347AT4_E_PHY_ID:
+               case M88E1112_E_PHY_ID:
+               case I210_I_PHY_ID:
                        ret_val = igb_copper_link_setup_m88_gen2(hw);
-               else
+                       break;
+               default:
                        ret_val = igb_copper_link_setup_m88(hw);
+                       break;
+               }
                break;
        case e1000_phy_igp_3:
                ret_val = igb_copper_link_setup_igp(hw);
index d27edbc..2515140 100644 (file)
@@ -447,7 +447,7 @@ struct igb_adapter {
 #endif
        struct i2c_algo_bit_data i2c_algo;
        struct i2c_adapter i2c_adap;
-       struct igb_i2c_client_list *i2c_clients;
+       struct i2c_client *i2c_client;
 };
 
 #define IGB_FLAG_HAS_MSI               (1 << 0)
index 0a9b073..4623502 100644 (file)
 #include <linux/pci.h>
 
 #ifdef CONFIG_IGB_HWMON
+struct i2c_board_info i350_sensor_info = {
+       I2C_BOARD_INFO("i350bb", (0Xf8 >> 1)),
+};
+
 /* hwmon callback functions */
 static ssize_t igb_hwmon_show_location(struct device *dev,
                                         struct device_attribute *attr,
@@ -188,6 +192,7 @@ int igb_sysfs_init(struct igb_adapter *adapter)
        unsigned int i;
        int n_attrs;
        int rc = 0;
+       struct i2c_client *client = NULL;
 
        /* If this method isn't defined we don't support thermals */
        if (adapter->hw.mac.ops.init_thermal_sensor_thresh == NULL)
@@ -198,6 +203,15 @@ int igb_sysfs_init(struct igb_adapter *adapter)
                if (rc)
                        goto exit;
 
+       /* init i2c_client */
+       client = i2c_new_device(&adapter->i2c_adap, &i350_sensor_info);
+       if (client == NULL) {
+               dev_info(&adapter->pdev->dev,
+                       "Failed to create new i2c device..\n");
+               goto exit;
+       }
+       adapter->i2c_client = client;
+
        /* Allocation space for max attributes
         * max num sensors * values (loc, temp, max, caution)
         */
index ed79a1c..4dbd629 100644 (file)
@@ -1923,10 +1923,6 @@ void igb_set_fw_version(struct igb_adapter *adapter)
        return;
 }
 
-static const struct i2c_board_info i350_sensor_info = {
-       I2C_BOARD_INFO("i350bb", 0Xf8),
-};
-
 /*  igb_init_i2c - Init I2C interface
  *  @adapter: pointer to adapter structure
  *
@@ -6227,13 +6223,6 @@ static struct sk_buff *igb_build_rx_buffer(struct igb_ring *rx_ring,
        /* If we spanned a buffer we have a huge mess so test for it */
        BUG_ON(unlikely(!igb_test_staterr(rx_desc, E1000_RXD_STAT_EOP)));
 
-       /* Guarantee this function can be used by verifying buffer sizes */
-       BUILD_BUG_ON(SKB_WITH_OVERHEAD(IGB_RX_BUFSZ) < (NET_SKB_PAD +
-                                                       NET_IP_ALIGN +
-                                                       IGB_TS_HDR_LEN +
-                                                       ETH_FRAME_LEN +
-                                                       ETH_FCS_LEN));
-
        rx_buffer = &rx_ring->rx_buffer_info[rx_ring->next_to_clean];
        page = rx_buffer->page;
        prefetchw(page);
@@ -7724,67 +7713,6 @@ static void igb_init_dmac(struct igb_adapter *adapter, u32 pba)
        }
 }
 
-static DEFINE_SPINLOCK(i2c_clients_lock);
-
-/*  igb_get_i2c_client - returns matching client
- *  in adapters's client list.
- *  @adapter: adapter struct
- *  @dev_addr: device address of i2c needed.
- */
-static struct i2c_client *
-igb_get_i2c_client(struct igb_adapter *adapter, u8 dev_addr)
-{
-       ulong flags;
-       struct igb_i2c_client_list *client_list;
-       struct i2c_client *client = NULL;
-       struct i2c_board_info client_info = {
-               I2C_BOARD_INFO("igb", 0x00),
-       };
-
-       spin_lock_irqsave(&i2c_clients_lock, flags);
-       client_list = adapter->i2c_clients;
-
-       /* See if we already have an i2c_client */
-       while (client_list) {
-               if (client_list->client->addr == (dev_addr >> 1)) {
-                       client = client_list->client;
-                       goto exit;
-               } else {
-                       client_list = client_list->next;
-               }
-       }
-
-       /* no client_list found, create a new one */
-       client_list = kzalloc(sizeof(*client_list), GFP_ATOMIC);
-       if (client_list == NULL)
-               goto exit;
-
-       /* dev_addr passed to us is left-shifted by 1 bit
-        * i2c_new_device call expects it to be flush to the right.
-        */
-       client_info.addr = dev_addr >> 1;
-       client_info.platform_data = adapter;
-       client_list->client = i2c_new_device(&adapter->i2c_adap, &client_info);
-       if (client_list->client == NULL) {
-               dev_info(&adapter->pdev->dev,
-                       "Failed to create new i2c device..\n");
-               goto err_no_client;
-       }
-
-       /* insert new client at head of list */
-       client_list->next = adapter->i2c_clients;
-       adapter->i2c_clients = client_list;
-
-       client = client_list->client;
-       goto exit;
-
-err_no_client:
-       kfree(client_list);
-exit:
-       spin_unlock_irqrestore(&i2c_clients_lock, flags);
-       return client;
-}
-
 /*  igb_read_i2c_byte - Reads 8 bit word over I2C
  *  @hw: pointer to hardware structure
  *  @byte_offset: byte offset to read
@@ -7798,7 +7726,7 @@ s32 igb_read_i2c_byte(struct e1000_hw *hw, u8 byte_offset,
                                u8 dev_addr, u8 *data)
 {
        struct igb_adapter *adapter = container_of(hw, struct igb_adapter, hw);
-       struct i2c_client *this_client = igb_get_i2c_client(adapter, dev_addr);
+       struct i2c_client *this_client = adapter->i2c_client;
        s32 status;
        u16 swfw_mask = 0;
 
@@ -7835,7 +7763,7 @@ s32 igb_write_i2c_byte(struct e1000_hw *hw, u8 byte_offset,
                                 u8 dev_addr, u8 data)
 {
        struct igb_adapter *adapter = container_of(hw, struct igb_adapter, hw);
-       struct i2c_client *this_client = igb_get_i2c_client(adapter, dev_addr);
+       struct i2c_client *this_client = adapter->i2c_client;
        s32 status;
        u16 swfw_mask = E1000_SWFW_PHY0_SM;
 
index 2914050..6562c73 100644 (file)
@@ -1081,6 +1081,45 @@ static void txq_set_fixed_prio_mode(struct tx_queue *txq)
 
 
 /* mii management interface *************************************************/
+static void mv643xx_adjust_pscr(struct mv643xx_eth_private *mp)
+{
+       u32 pscr = rdlp(mp, PORT_SERIAL_CONTROL);
+       u32 autoneg_disable = FORCE_LINK_PASS |
+                    DISABLE_AUTO_NEG_SPEED_GMII |
+                    DISABLE_AUTO_NEG_FOR_FLOW_CTRL |
+                    DISABLE_AUTO_NEG_FOR_DUPLEX;
+
+       if (mp->phy->autoneg == AUTONEG_ENABLE) {
+               /* enable auto negotiation */
+               pscr &= ~autoneg_disable;
+               goto out_write;
+       }
+
+       pscr |= autoneg_disable;
+
+       if (mp->phy->speed == SPEED_1000) {
+               /* force gigabit, half duplex not supported */
+               pscr |= SET_GMII_SPEED_TO_1000;
+               pscr |= SET_FULL_DUPLEX_MODE;
+               goto out_write;
+       }
+
+       pscr &= ~SET_GMII_SPEED_TO_1000;
+
+       if (mp->phy->speed == SPEED_100)
+               pscr |= SET_MII_SPEED_TO_100;
+       else
+               pscr &= ~SET_MII_SPEED_TO_100;
+
+       if (mp->phy->duplex == DUPLEX_FULL)
+               pscr |= SET_FULL_DUPLEX_MODE;
+       else
+               pscr &= ~SET_FULL_DUPLEX_MODE;
+
+out_write:
+       wrlp(mp, PORT_SERIAL_CONTROL, pscr);
+}
+
 static irqreturn_t mv643xx_eth_err_irq(int irq, void *dev_id)
 {
        struct mv643xx_eth_shared_private *msp = dev_id;
@@ -1499,6 +1538,7 @@ static int
 mv643xx_eth_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
        struct mv643xx_eth_private *mp = netdev_priv(dev);
+       int ret;
 
        if (mp->phy == NULL)
                return -EINVAL;
@@ -1508,7 +1548,10 @@ mv643xx_eth_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
         */
        cmd->advertising &= ~ADVERTISED_1000baseT_Half;
 
-       return phy_ethtool_sset(mp->phy, cmd);
+       ret = phy_ethtool_sset(mp->phy, cmd);
+       if (!ret)
+               mv643xx_adjust_pscr(mp);
+       return ret;
 }
 
 static void mv643xx_eth_get_drvinfo(struct net_device *dev,
@@ -2442,11 +2485,15 @@ static int mv643xx_eth_stop(struct net_device *dev)
 static int mv643xx_eth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
        struct mv643xx_eth_private *mp = netdev_priv(dev);
+       int ret;
 
-       if (mp->phy != NULL)
-               return phy_mii_ioctl(mp->phy, ifr, cmd);
+       if (mp->phy == NULL)
+               return -ENOTSUPP;
 
-       return -EOPNOTSUPP;
+       ret = phy_mii_ioctl(mp->phy, ifr, cmd);
+       if (!ret)
+               mv643xx_adjust_pscr(mp);
+       return ret;
 }
 
 static int mv643xx_eth_change_mtu(struct net_device *dev, int new_mtu)
index 7e64033..0706623 100644 (file)
@@ -226,7 +226,7 @@ void __mlx4_cq_free_icm(struct mlx4_dev *dev, int cqn)
 
 static void mlx4_cq_free_icm(struct mlx4_dev *dev, int cqn)
 {
-       u64 in_param;
+       u64 in_param = 0;
        int err;
 
        if (mlx4_is_mfunc(dev)) {
index bb4d8d9..995d4b6 100644 (file)
@@ -565,34 +565,38 @@ static void mlx4_en_put_qp(struct mlx4_en_priv *priv)
        struct mlx4_en_dev *mdev = priv->mdev;
        struct mlx4_dev *dev = mdev->dev;
        int qpn = priv->base_qpn;
-       u64 mac = mlx4_en_mac_to_u64(priv->dev->dev_addr);
-
-       en_dbg(DRV, priv, "Registering MAC: %pM for deleting\n",
-              priv->dev->dev_addr);
-       mlx4_unregister_mac(dev, priv->port, mac);
+       u64 mac;
 
-       if (dev->caps.steering_mode != MLX4_STEERING_MODE_A0) {
+       if (dev->caps.steering_mode == MLX4_STEERING_MODE_A0) {
+               mac = mlx4_en_mac_to_u64(priv->dev->dev_addr);
+               en_dbg(DRV, priv, "Registering MAC: %pM for deleting\n",
+                      priv->dev->dev_addr);
+               mlx4_unregister_mac(dev, priv->port, mac);
+       } else {
                struct mlx4_mac_entry *entry;
                struct hlist_node *tmp;
                struct hlist_head *bucket;
-               unsigned int mac_hash;
+               unsigned int i;
 
-               mac_hash = priv->dev->dev_addr[MLX4_EN_MAC_HASH_IDX];
-               bucket = &priv->mac_hash[mac_hash];
-               hlist_for_each_entry_safe(entry, tmp, bucket, hlist) {
-                       if (ether_addr_equal_64bits(entry->mac,
-                                                   priv->dev->dev_addr)) {
-                               en_dbg(DRV, priv, "Releasing qp: port %d, MAC %pM, qpn %d\n",
-                                      priv->port, priv->dev->dev_addr, qpn);
+               for (i = 0; i < MLX4_EN_MAC_HASH_SIZE; ++i) {
+                       bucket = &priv->mac_hash[i];
+                       hlist_for_each_entry_safe(entry, tmp, bucket, hlist) {
+                               mac = mlx4_en_mac_to_u64(entry->mac);
+                               en_dbg(DRV, priv, "Registering MAC: %pM for deleting\n",
+                                      entry->mac);
                                mlx4_en_uc_steer_release(priv, entry->mac,
                                                         qpn, entry->reg_id);
-                               mlx4_qp_release_range(dev, qpn, 1);
 
+                               mlx4_unregister_mac(dev, priv->port, mac);
                                hlist_del_rcu(&entry->hlist);
                                kfree_rcu(entry, rcu);
-                               break;
                        }
                }
+
+               en_dbg(DRV, priv, "Releasing qp: port %d, qpn %d\n",
+                      priv->port, qpn);
+               mlx4_qp_release_range(dev, qpn, 1);
+               priv->flags &= ~MLX4_EN_FLAG_FORCE_PROMISC;
        }
 }
 
@@ -650,28 +654,10 @@ u64 mlx4_en_mac_to_u64(u8 *addr)
        return mac;
 }
 
-static int mlx4_en_set_mac(struct net_device *dev, void *addr)
-{
-       struct mlx4_en_priv *priv = netdev_priv(dev);
-       struct mlx4_en_dev *mdev = priv->mdev;
-       struct sockaddr *saddr = addr;
-
-       if (!is_valid_ether_addr(saddr->sa_data))
-               return -EADDRNOTAVAIL;
-
-       memcpy(dev->dev_addr, saddr->sa_data, ETH_ALEN);
-       queue_work(mdev->workqueue, &priv->mac_task);
-       return 0;
-}
-
-static void mlx4_en_do_set_mac(struct work_struct *work)
+static int mlx4_en_do_set_mac(struct mlx4_en_priv *priv)
 {
-       struct mlx4_en_priv *priv = container_of(work, struct mlx4_en_priv,
-                                                mac_task);
-       struct mlx4_en_dev *mdev = priv->mdev;
        int err = 0;
 
-       mutex_lock(&mdev->state_lock);
        if (priv->port_up) {
                /* Remove old MAC and insert the new one */
                err = mlx4_en_replace_mac(priv, priv->base_qpn,
@@ -683,7 +669,26 @@ static void mlx4_en_do_set_mac(struct work_struct *work)
        } else
                en_dbg(HW, priv, "Port is down while registering mac, exiting...\n");
 
+       return err;
+}
+
+static int mlx4_en_set_mac(struct net_device *dev, void *addr)
+{
+       struct mlx4_en_priv *priv = netdev_priv(dev);
+       struct mlx4_en_dev *mdev = priv->mdev;
+       struct sockaddr *saddr = addr;
+       int err;
+
+       if (!is_valid_ether_addr(saddr->sa_data))
+               return -EADDRNOTAVAIL;
+
+       memcpy(dev->dev_addr, saddr->sa_data, ETH_ALEN);
+
+       mutex_lock(&mdev->state_lock);
+       err = mlx4_en_do_set_mac(priv);
        mutex_unlock(&mdev->state_lock);
+
+       return err;
 }
 
 static void mlx4_en_clear_list(struct net_device *dev)
@@ -1348,7 +1353,7 @@ static void mlx4_en_do_get_stats(struct work_struct *work)
                queue_delayed_work(mdev->workqueue, &priv->stats_task, STATS_DELAY);
        }
        if (mdev->mac_removed[MLX4_MAX_PORTS + 1 - priv->port]) {
-               queue_work(mdev->workqueue, &priv->mac_task);
+               mlx4_en_do_set_mac(priv);
                mdev->mac_removed[MLX4_MAX_PORTS + 1 - priv->port] = 0;
        }
        mutex_unlock(&mdev->state_lock);
@@ -1828,9 +1833,11 @@ int mlx4_en_alloc_resources(struct mlx4_en_priv *priv)
        }
 
 #ifdef CONFIG_RFS_ACCEL
-       priv->dev->rx_cpu_rmap = alloc_irq_cpu_rmap(priv->mdev->dev->caps.comp_pool);
-       if (!priv->dev->rx_cpu_rmap)
-               goto err;
+       if (priv->mdev->dev->caps.comp_pool) {
+               priv->dev->rx_cpu_rmap = alloc_irq_cpu_rmap(priv->mdev->dev->caps.comp_pool);
+               if (!priv->dev->rx_cpu_rmap)
+                       goto err;
+       }
 #endif
 
        return 0;
@@ -2078,7 +2085,6 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
        priv->msg_enable = MLX4_EN_MSG_LEVEL;
        spin_lock_init(&priv->stats_lock);
        INIT_WORK(&priv->rx_mode_task, mlx4_en_do_set_rx_mode);
-       INIT_WORK(&priv->mac_task, mlx4_en_do_set_mac);
        INIT_WORK(&priv->watchdog_task, mlx4_en_restart);
        INIT_WORK(&priv->linkstate_task, mlx4_en_linkstate);
        INIT_DELAYED_WORK(&priv->stats_task, mlx4_en_do_get_stats);
index 50917eb..f624557 100644 (file)
@@ -787,6 +787,14 @@ int mlx4_QUERY_DEV_CAP_wrapper(struct mlx4_dev *dev, int slave,
        bmme_flags &= ~MLX4_BMME_FLAG_TYPE_2_WIN;
        MLX4_PUT(outbox->buf, bmme_flags, QUERY_DEV_CAP_BMME_FLAGS_OFFSET);
 
+       /* turn off device-managed steering capability if not enabled */
+       if (dev->caps.steering_mode != MLX4_STEERING_MODE_DEVICE_MANAGED) {
+               MLX4_GET(field, outbox->buf,
+                        QUERY_DEV_CAP_FLOW_STEERING_RANGE_EN_OFFSET);
+               field &= 0x7f;
+               MLX4_PUT(outbox->buf, field,
+                        QUERY_DEV_CAP_FLOW_STEERING_RANGE_EN_OFFSET);
+       }
        return 0;
 }
 
index d180bc4..16abde2 100644 (file)
@@ -1555,7 +1555,7 @@ void __mlx4_counter_free(struct mlx4_dev *dev, u32 idx)
 
 void mlx4_counter_free(struct mlx4_dev *dev, u32 idx)
 {
-       u64 in_param;
+       u64 in_param = 0;
 
        if (mlx4_is_mfunc(dev)) {
                set_param_l(&in_param, idx);
index cf88334..d738454 100644 (file)
@@ -1235,7 +1235,7 @@ int mlx4_get_qp_per_mgm(struct mlx4_dev *dev);
 
 static inline void set_param_l(u64 *arg, u32 val)
 {
-       *((u32 *)arg) = val;
+       *arg = (*arg & 0xffffffff00000000ULL) | (u64) val;
 }
 
 static inline void set_param_h(u64 *arg, u32 val)
index c313d7e..f710b7c 100644 (file)
@@ -509,7 +509,6 @@ struct mlx4_en_priv {
        struct mlx4_en_cq rx_cq[MAX_RX_RINGS];
        struct mlx4_qp drop_qp;
        struct work_struct rx_mode_task;
-       struct work_struct mac_task;
        struct work_struct watchdog_task;
        struct work_struct linkstate_task;
        struct delayed_work stats_task;
index 602ca9b..f91719a 100644 (file)
@@ -183,7 +183,7 @@ u32 __mlx4_alloc_mtt_range(struct mlx4_dev *dev, int order)
 
 static u32 mlx4_alloc_mtt_range(struct mlx4_dev *dev, int order)
 {
-       u64 in_param;
+       u64 in_param = 0;
        u64 out_param;
        int err;
 
@@ -240,7 +240,7 @@ void __mlx4_free_mtt_range(struct mlx4_dev *dev, u32 offset, int order)
 
 static void mlx4_free_mtt_range(struct mlx4_dev *dev, u32 offset, int order)
 {
-       u64 in_param;
+       u64 in_param = 0;
        int err;
 
        if (mlx4_is_mfunc(dev)) {
@@ -351,7 +351,7 @@ void __mlx4_mpt_release(struct mlx4_dev *dev, u32 index)
 
 static void mlx4_mpt_release(struct mlx4_dev *dev, u32 index)
 {
-       u64 in_param;
+       u64 in_param = 0;
 
        if (mlx4_is_mfunc(dev)) {
                set_param_l(&in_param, index);
@@ -374,7 +374,7 @@ int __mlx4_mpt_alloc_icm(struct mlx4_dev *dev, u32 index)
 
 static int mlx4_mpt_alloc_icm(struct mlx4_dev *dev, u32 index)
 {
-       u64 param;
+       u64 param = 0;
 
        if (mlx4_is_mfunc(dev)) {
                set_param_l(&param, index);
@@ -395,7 +395,7 @@ void __mlx4_mpt_free_icm(struct mlx4_dev *dev, u32 index)
 
 static void mlx4_mpt_free_icm(struct mlx4_dev *dev, u32 index)
 {
-       u64 in_param;
+       u64 in_param = 0;
 
        if (mlx4_is_mfunc(dev)) {
                set_param_l(&in_param, index);
index 1ac8863..00f223a 100644 (file)
@@ -101,7 +101,7 @@ void __mlx4_xrcd_free(struct mlx4_dev *dev, u32 xrcdn)
 
 void mlx4_xrcd_free(struct mlx4_dev *dev, u32 xrcdn)
 {
-       u64 in_param;
+       u64 in_param = 0;
        int err;
 
        if (mlx4_is_mfunc(dev)) {
index 719ead1..10c57c8 100644 (file)
@@ -175,7 +175,7 @@ EXPORT_SYMBOL_GPL(__mlx4_register_mac);
 
 int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac)
 {
-       u64 out_param;
+       u64 out_param = 0;
        int err;
 
        if (mlx4_is_mfunc(dev)) {
@@ -222,7 +222,7 @@ EXPORT_SYMBOL_GPL(__mlx4_unregister_mac);
 
 void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, u64 mac)
 {
-       u64 out_param;
+       u64 out_param = 0;
 
        if (mlx4_is_mfunc(dev)) {
                set_param_l(&out_param, port);
@@ -361,7 +361,7 @@ out:
 
 int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index)
 {
-       u64 out_param;
+       u64 out_param = 0;
        int err;
 
        if (mlx4_is_mfunc(dev)) {
@@ -406,7 +406,7 @@ out:
 
 void mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, int index)
 {
-       u64 in_param;
+       u64 in_param = 0;
        int err;
 
        if (mlx4_is_mfunc(dev)) {
index 81e2abe..e891b05 100644 (file)
@@ -222,7 +222,7 @@ int __mlx4_qp_reserve_range(struct mlx4_dev *dev, int cnt, int align,
 
 int mlx4_qp_reserve_range(struct mlx4_dev *dev, int cnt, int align, int *base)
 {
-       u64 in_param;
+       u64 in_param = 0;
        u64 out_param;
        int err;
 
@@ -255,7 +255,7 @@ void __mlx4_qp_release_range(struct mlx4_dev *dev, int base_qpn, int cnt)
 
 void mlx4_qp_release_range(struct mlx4_dev *dev, int base_qpn, int cnt)
 {
-       u64 in_param;
+       u64 in_param = 0;
        int err;
 
        if (mlx4_is_mfunc(dev)) {
@@ -319,7 +319,7 @@ err_out:
 
 static int mlx4_qp_alloc_icm(struct mlx4_dev *dev, int qpn)
 {
-       u64 param;
+       u64 param = 0;
 
        if (mlx4_is_mfunc(dev)) {
                set_param_l(&param, qpn);
@@ -344,7 +344,7 @@ void __mlx4_qp_free_icm(struct mlx4_dev *dev, int qpn)
 
 static void mlx4_qp_free_icm(struct mlx4_dev *dev, int qpn)
 {
-       u64 in_param;
+       u64 in_param = 0;
 
        if (mlx4_is_mfunc(dev)) {
                set_param_l(&in_param, qpn);
index 083fb48..2995687 100644 (file)
@@ -2990,6 +2990,9 @@ int mlx4_QP_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
        u8 steer_type_mask = 2;
        enum mlx4_steer_type type = (gid[7] & steer_type_mask) >> 1;
 
+       if (dev->caps.steering_mode != MLX4_STEERING_MODE_B0)
+               return -EINVAL;
+
        qpn = vhcr->in_modifier & 0xffffff;
        err = get_res(dev, slave, qpn, RES_QP, &rqp);
        if (err)
index feda6c0..e329fe1 100644 (file)
@@ -149,7 +149,7 @@ void __mlx4_srq_free_icm(struct mlx4_dev *dev, int srqn)
 
 static void mlx4_srq_free_icm(struct mlx4_dev *dev, int srqn)
 {
-       u64 in_param;
+       u64 in_param = 0;
 
        if (mlx4_is_mfunc(dev)) {
                set_param_l(&in_param, srqn);
index 8900398..28fb50a 100644 (file)
@@ -4765,8 +4765,10 @@ static void rtl_hw_start_8168bb(struct rtl8169_private *tp)
 
        RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
 
-       rtl_tx_performance_tweak(pdev,
-               (0x5 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN);
+       if (tp->dev->mtu <= ETH_DATA_LEN) {
+               rtl_tx_performance_tweak(pdev, (0x5 << MAX_READ_REQUEST_SHIFT) |
+                                        PCI_EXP_DEVCTL_NOSNOOP_EN);
+       }
 }
 
 static void rtl_hw_start_8168bef(struct rtl8169_private *tp)
@@ -4789,7 +4791,8 @@ static void __rtl_hw_start_8168cp(struct rtl8169_private *tp)
 
        RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
 
-       rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
+       if (tp->dev->mtu <= ETH_DATA_LEN)
+               rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
 
        rtl_disable_clock_request(pdev);
 
@@ -4822,7 +4825,8 @@ static void rtl_hw_start_8168cp_2(struct rtl8169_private *tp)
 
        RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
 
-       rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
+       if (tp->dev->mtu <= ETH_DATA_LEN)
+               rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
 
        RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
 }
@@ -4841,7 +4845,8 @@ static void rtl_hw_start_8168cp_3(struct rtl8169_private *tp)
 
        RTL_W8(MaxTxPacketSize, TxPacketMax);
 
-       rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
+       if (tp->dev->mtu <= ETH_DATA_LEN)
+               rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
 
        RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
 }
@@ -4901,7 +4906,8 @@ static void rtl_hw_start_8168d(struct rtl8169_private *tp)
 
        RTL_W8(MaxTxPacketSize, TxPacketMax);
 
-       rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
+       if (tp->dev->mtu <= ETH_DATA_LEN)
+               rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
 
        RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
 }
@@ -4913,7 +4919,8 @@ static void rtl_hw_start_8168dp(struct rtl8169_private *tp)
 
        rtl_csi_access_enable_1(tp);
 
-       rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
+       if (tp->dev->mtu <= ETH_DATA_LEN)
+               rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
 
        RTL_W8(MaxTxPacketSize, TxPacketMax);
 
@@ -4972,7 +4979,8 @@ static void rtl_hw_start_8168e_1(struct rtl8169_private *tp)
 
        rtl_ephy_init(tp, e_info_8168e_1, ARRAY_SIZE(e_info_8168e_1));
 
-       rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
+       if (tp->dev->mtu <= ETH_DATA_LEN)
+               rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
 
        RTL_W8(MaxTxPacketSize, TxPacketMax);
 
@@ -4998,7 +5006,8 @@ static void rtl_hw_start_8168e_2(struct rtl8169_private *tp)
 
        rtl_ephy_init(tp, e_info_8168e_2, ARRAY_SIZE(e_info_8168e_2));
 
-       rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
+       if (tp->dev->mtu <= ETH_DATA_LEN)
+               rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
 
        rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
        rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
index bf57b3c..0bc0099 100644 (file)
@@ -779,6 +779,7 @@ efx_realloc_channels(struct efx_nic *efx, u32 rxq_entries, u32 txq_entries)
                                                tx_queue->txd.entries);
        }
 
+       efx_device_detach_sync(efx);
        efx_stop_all(efx);
        efx_stop_interrupts(efx, true);
 
@@ -832,6 +833,7 @@ out:
 
        efx_start_interrupts(efx, true);
        efx_start_all(efx);
+       netif_device_attach(efx->net_dev);
        return rc;
 
 rollback:
@@ -1641,8 +1643,12 @@ static void efx_stop_all(struct efx_nic *efx)
        /* Flush efx_mac_work(), refill_workqueue, monitor_work */
        efx_flush_all(efx);
 
-       /* Stop the kernel transmit interface late, so the watchdog
-        * timer isn't ticking over the flush */
+       /* Stop the kernel transmit interface.  This is only valid if
+        * the device is stopped or detached; otherwise the watchdog
+        * may fire immediately.
+        */
+       WARN_ON(netif_running(efx->net_dev) &&
+               netif_device_present(efx->net_dev));
        netif_tx_disable(efx->net_dev);
 
        efx_stop_datapath(efx);
@@ -1963,16 +1969,18 @@ static int efx_change_mtu(struct net_device *net_dev, int new_mtu)
        if (new_mtu > EFX_MAX_MTU)
                return -EINVAL;
 
-       efx_stop_all(efx);
-
        netif_dbg(efx, drv, efx->net_dev, "changing MTU to %d\n", new_mtu);
 
+       efx_device_detach_sync(efx);
+       efx_stop_all(efx);
+
        mutex_lock(&efx->mac_lock);
        net_dev->mtu = new_mtu;
        efx->type->reconfigure_mac(efx);
        mutex_unlock(&efx->mac_lock);
 
        efx_start_all(efx);
+       netif_device_attach(efx->net_dev);
        return 0;
 }
 
index 50247df..d2f790d 100644 (file)
@@ -171,9 +171,9 @@ static inline void efx_device_detach_sync(struct efx_nic *efx)
         * TX scheduler is stopped when we're done and before
         * netif_device_present() becomes false.
         */
-       netif_tx_lock(dev);
+       netif_tx_lock_bh(dev);
        netif_device_detach(dev);
-       netif_tx_unlock(dev);
+       netif_tx_unlock_bh(dev);
 }
 
 #endif /* EFX_EFX_H */
index 2d756c1..0a90abd 100644 (file)
@@ -210,6 +210,7 @@ struct efx_tx_queue {
  *     Will be %NULL if the buffer slot is currently free.
  * @page: The associated page buffer. Valif iff @flags & %EFX_RX_BUF_PAGE.
  *     Will be %NULL if the buffer slot is currently free.
+ * @page_offset: Offset within page. Valid iff @flags & %EFX_RX_BUF_PAGE.
  * @len: Buffer length, in bytes.
  * @flags: Flags for buffer and packet state.
  */
@@ -219,7 +220,8 @@ struct efx_rx_buffer {
                struct sk_buff *skb;
                struct page *page;
        } u;
-       unsigned int len;
+       u16 page_offset;
+       u16 len;
        u16 flags;
 };
 #define EFX_RX_BUF_PAGE                0x0001
index d780a0d..bb579a6 100644 (file)
@@ -90,11 +90,7 @@ static unsigned int rx_refill_threshold;
 static inline unsigned int efx_rx_buf_offset(struct efx_nic *efx,
                                             struct efx_rx_buffer *buf)
 {
-       /* Offset is always within one page, so we don't need to consider
-        * the page order.
-        */
-       return ((unsigned int) buf->dma_addr & (PAGE_SIZE - 1)) +
-               efx->type->rx_buffer_hash_size;
+       return buf->page_offset + efx->type->rx_buffer_hash_size;
 }
 static inline unsigned int efx_rx_buf_size(struct efx_nic *efx)
 {
@@ -187,6 +183,7 @@ static int efx_init_rx_buffers_page(struct efx_rx_queue *rx_queue)
        struct efx_nic *efx = rx_queue->efx;
        struct efx_rx_buffer *rx_buf;
        struct page *page;
+       unsigned int page_offset;
        struct efx_rx_page_state *state;
        dma_addr_t dma_addr;
        unsigned index, count;
@@ -211,12 +208,14 @@ static int efx_init_rx_buffers_page(struct efx_rx_queue *rx_queue)
                state->dma_addr = dma_addr;
 
                dma_addr += sizeof(struct efx_rx_page_state);
+               page_offset = sizeof(struct efx_rx_page_state);
 
        split:
                index = rx_queue->added_count & rx_queue->ptr_mask;
                rx_buf = efx_rx_buffer(rx_queue, index);
                rx_buf->dma_addr = dma_addr + EFX_PAGE_IP_ALIGN;
                rx_buf->u.page = page;
+               rx_buf->page_offset = page_offset + EFX_PAGE_IP_ALIGN;
                rx_buf->len = efx->rx_buffer_len - EFX_PAGE_IP_ALIGN;
                rx_buf->flags = EFX_RX_BUF_PAGE;
                ++rx_queue->added_count;
@@ -227,6 +226,7 @@ static int efx_init_rx_buffers_page(struct efx_rx_queue *rx_queue)
                        /* Use the second half of the page */
                        get_page(page);
                        dma_addr += (PAGE_SIZE >> 1);
+                       page_offset += (PAGE_SIZE >> 1);
                        ++count;
                        goto split;
                }
@@ -236,7 +236,8 @@ static int efx_init_rx_buffers_page(struct efx_rx_queue *rx_queue)
 }
 
 static void efx_unmap_rx_buffer(struct efx_nic *efx,
-                               struct efx_rx_buffer *rx_buf)
+                               struct efx_rx_buffer *rx_buf,
+                               unsigned int used_len)
 {
        if ((rx_buf->flags & EFX_RX_BUF_PAGE) && rx_buf->u.page) {
                struct efx_rx_page_state *state;
@@ -247,6 +248,10 @@ static void efx_unmap_rx_buffer(struct efx_nic *efx,
                                       state->dma_addr,
                                       efx_rx_buf_size(efx),
                                       DMA_FROM_DEVICE);
+               } else if (used_len) {
+                       dma_sync_single_for_cpu(&efx->pci_dev->dev,
+                                               rx_buf->dma_addr, used_len,
+                                               DMA_FROM_DEVICE);
                }
        } else if (!(rx_buf->flags & EFX_RX_BUF_PAGE) && rx_buf->u.skb) {
                dma_unmap_single(&efx->pci_dev->dev, rx_buf->dma_addr,
@@ -269,7 +274,7 @@ static void efx_free_rx_buffer(struct efx_nic *efx,
 static void efx_fini_rx_buffer(struct efx_rx_queue *rx_queue,
                               struct efx_rx_buffer *rx_buf)
 {
-       efx_unmap_rx_buffer(rx_queue->efx, rx_buf);
+       efx_unmap_rx_buffer(rx_queue->efx, rx_buf, 0);
        efx_free_rx_buffer(rx_queue->efx, rx_buf);
 }
 
@@ -535,10 +540,10 @@ void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index,
                goto out;
        }
 
-       /* Release card resources - assumes all RX buffers consumed in-order
-        * per RX queue
+       /* Release and/or sync DMA mapping - assumes all RX buffers
+        * consumed in-order per RX queue
         */
-       efx_unmap_rx_buffer(efx, rx_buf);
+       efx_unmap_rx_buffer(efx, rx_buf, len);
 
        /* Prefetch nice and early so data will (hopefully) be in cache by
         * the time we look at it.
index 7e93df6..01ffbc4 100644 (file)
@@ -731,7 +731,7 @@ static inline void cpsw_add_default_vlan(struct cpsw_priv *priv)
 
        writel(vlan, &priv->host_port_regs->port_vlan);
 
-       for (i = 0; i < 2; i++)
+       for (i = 0; i < priv->data.slaves; i++)
                slave_write(priv->slaves + i, vlan, reg);
 
        cpsw_ale_add_vlan(priv->ale, vlan, ALE_ALL_PORTS << port,
index e5b19b0..3c4d627 100644 (file)
@@ -202,6 +202,9 @@ static int rr_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        return 0;
 
  out:
+       if (rrpriv->evt_ring)
+               pci_free_consistent(pdev, EVT_RING_SIZE, rrpriv->evt_ring,
+                                   rrpriv->evt_ring_dma);
        if (rrpriv->rx_ring)
                pci_free_consistent(pdev, RX_TOTAL_SIZE, rrpriv->rx_ring,
                                    rrpriv->rx_ring_dma);
index 417b2af..73abbc1 100644 (file)
@@ -660,6 +660,7 @@ void macvlan_common_setup(struct net_device *dev)
        ether_setup(dev);
 
        dev->priv_flags        &= ~(IFF_XMIT_DST_RELEASE | IFF_TX_SKB_SHARING);
+       dev->priv_flags        |= IFF_UNICAST_FLT;
        dev->netdev_ops         = &macvlan_netdev_ops;
        dev->destructor         = free_netdev;
        dev->header_ops         = &macvlan_hard_header_ops,
index 2993444..abf7b61 100644 (file)
@@ -257,8 +257,7 @@ static struct phy_driver ksphy_driver[] = {
        .phy_id         = PHY_ID_KSZ9021,
        .phy_id_mask    = 0x000ffffe,
        .name           = "Micrel KSZ9021 Gigabit PHY",
-       .features       = (PHY_GBIT_FEATURES | SUPPORTED_Pause
-                               | SUPPORTED_Asym_Pause),
+       .features       = (PHY_GBIT_FEATURES | SUPPORTED_Pause),
        .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
        .config_init    = kszphy_config_init,
        .config_aneg    = genphy_config_aneg,
index 9930f99..3657b4a 100644 (file)
@@ -44,13 +44,13 @@ MODULE_LICENSE("GPL");
 
 void phy_device_free(struct phy_device *phydev)
 {
-       kfree(phydev);
+       put_device(&phydev->dev);
 }
 EXPORT_SYMBOL(phy_device_free);
 
 static void phy_device_release(struct device *dev)
 {
-       phy_device_free(to_phy_device(dev));
+       kfree(to_phy_device(dev));
 }
 
 static struct phy_driver genphy_driver;
@@ -201,6 +201,8 @@ struct phy_device *phy_device_create(struct mii_bus *bus, int addr, int phy_id,
           there's no driver _already_ loaded. */
        request_module(MDIO_MODULE_PREFIX MDIO_ID_FMT, MDIO_ID_ARGS(phy_id));
 
+       device_initialize(&dev->dev);
+
        return dev;
 }
 EXPORT_SYMBOL(phy_device_create);
@@ -363,9 +365,9 @@ int phy_device_register(struct phy_device *phydev)
        /* Run all of the fixups for this PHY */
        phy_scan_fixups(phydev);
 
-       err = device_register(&phydev->dev);
+       err = device_add(&phydev->dev);
        if (err) {
-               pr_err("phy %d failed to register\n", phydev->addr);
+               pr_err("PHY %d failed to add\n", phydev->addr);
                goto out;
        }
 
index 05c5efe..bf34192 100644 (file)
@@ -1138,6 +1138,8 @@ static int team_port_del(struct team *team, struct net_device *port_dev)
        netdev_upper_dev_unlink(port_dev, dev);
        team_port_disable_netpoll(port);
        vlan_vids_del_by_dev(port_dev, dev);
+       dev_uc_unsync(port_dev, dev);
+       dev_mc_unsync(port_dev, dev);
        dev_close(port_dev);
        team_port_leave(team, port);
 
index 2c6a22e..b7c457a 100644 (file)
@@ -747,6 +747,8 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
                goto drop;
        skb_orphan(skb);
 
+       nf_reset(skb);
+
        /* Enqueue packet */
        skb_queue_tail(&tfile->socket.sk->sk_receive_queue, skb);
 
index da92ed3..3b6e9b8 100644 (file)
@@ -156,6 +156,24 @@ config USB_NET_AX8817X
          This driver creates an interface named "ethX", where X depends on
          what other networking devices you have in use.
 
+config USB_NET_AX88179_178A
+       tristate "ASIX AX88179/178A USB 3.0/2.0 to Gigabit Ethernet"
+       depends on USB_USBNET
+       select CRC32
+       select PHYLIB
+       default y
+       help
+         This option adds support for ASIX AX88179 based USB 3.0/2.0
+         to Gigabit Ethernet adapters.
+
+         This driver should work with at least the following devices:
+           * ASIX AX88179
+           * ASIX AX88178A
+           * Sitcomm LN-032
+
+         This driver creates an interface named "ethX", where X depends on
+         what other networking devices you have in use.
+
 config USB_NET_CDCETHER
        tristate "CDC Ethernet support (smart devices such as cable modems)"
        depends on USB_USBNET
index 4786913..119b06c 100644 (file)
@@ -9,6 +9,7 @@ obj-$(CONFIG_USB_RTL8150)       += rtl8150.o
 obj-$(CONFIG_USB_HSO)          += hso.o
 obj-$(CONFIG_USB_NET_AX8817X)  += asix.o
 asix-y := asix_devices.o asix_common.o ax88172a.o
+obj-$(CONFIG_USB_NET_AX88179_178A)      += ax88179_178a.o
 obj-$(CONFIG_USB_NET_CDCETHER) += cdc_ether.o
 obj-$(CONFIG_USB_NET_CDC_EEM)  += cdc_eem.o
 obj-$(CONFIG_USB_NET_DM9601)   += dm9601.o
index 2205dbc..7097534 100644 (file)
@@ -924,6 +924,29 @@ static const struct driver_info ax88178_info = {
        .tx_fixup = asix_tx_fixup,
 };
 
+/*
+ * USBLINK 20F9 "USB 2.0 LAN" USB ethernet adapter, typically found in
+ * no-name packaging.
+ * USB device strings are:
+ *   1: Manufacturer: USBLINK
+ *   2: Product: HG20F9 USB2.0
+ *   3: Serial: 000003
+ * Appears to be compatible with Asix 88772B.
+ */
+static const struct driver_info hg20f9_info = {
+       .description = "HG20F9 USB 2.0 Ethernet",
+       .bind = ax88772_bind,
+       .unbind = ax88772_unbind,
+       .status = asix_status,
+       .link_reset = ax88772_link_reset,
+       .reset = ax88772_reset,
+       .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR |
+                FLAG_MULTI_PACKET,
+       .rx_fixup = asix_rx_fixup_common,
+       .tx_fixup = asix_tx_fixup,
+       .data = FLAG_EEPROM_MAC,
+};
+
 extern const struct driver_info ax88172a_info;
 
 static const struct usb_device_id      products [] = {
@@ -1063,6 +1086,14 @@ static const struct usb_device_id        products [] = {
        /* ASIX 88172a demo board */
        USB_DEVICE(0x0b95, 0x172a),
        .driver_info = (unsigned long) &ax88172a_info,
+}, {
+       /*
+        * USBLINK HG20F9 "USB 2.0 LAN"
+        * Appears to have gazumped Linksys's manufacturer ID but
+        * doesn't (yet) conflict with any known Linksys product.
+        */
+       USB_DEVICE(0x066b, 0x20f9),
+       .driver_info = (unsigned long) &hg20f9_info,
 },
        { },            // END
 };
diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c
new file mode 100644 (file)
index 0000000..71c27d8
--- /dev/null
@@ -0,0 +1,1448 @@
+/*
+ * ASIX AX88179/178A USB 3.0/2.0 to Gigabit Ethernet Devices
+ *
+ * Copyright (C) 2011-2013 ASIX
+ *
+ * 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.
+ *
+ * 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/etherdevice.h>
+#include <linux/mii.h>
+#include <linux/usb.h>
+#include <linux/crc32.h>
+#include <linux/usb/usbnet.h>
+
+#define AX88179_PHY_ID                         0x03
+#define AX_EEPROM_LEN                          0x100
+#define AX88179_EEPROM_MAGIC                   0x17900b95
+#define AX_MCAST_FLTSIZE                       8
+#define AX_MAX_MCAST                           64
+#define AX_INT_PPLS_LINK                       ((u32)BIT(16))
+#define AX_RXHDR_L4_TYPE_MASK                  0x1c
+#define AX_RXHDR_L4_TYPE_UDP                   4
+#define AX_RXHDR_L4_TYPE_TCP                   16
+#define AX_RXHDR_L3CSUM_ERR                    2
+#define AX_RXHDR_L4CSUM_ERR                    1
+#define AX_RXHDR_CRC_ERR                       ((u32)BIT(31))
+#define AX_RXHDR_DROP_ERR                      ((u32)BIT(30))
+#define AX_ACCESS_MAC                          0x01
+#define AX_ACCESS_PHY                          0x02
+#define AX_ACCESS_EEPROM                       0x04
+#define AX_ACCESS_EFUS                         0x05
+#define AX_PAUSE_WATERLVL_HIGH                 0x54
+#define AX_PAUSE_WATERLVL_LOW                  0x55
+
+#define PHYSICAL_LINK_STATUS                   0x02
+       #define AX_USB_SS               0x04
+       #define AX_USB_HS               0x02
+
+#define GENERAL_STATUS                         0x03
+/* Check AX88179 version. UA1:Bit2 = 0,  UA2:Bit2 = 1 */
+       #define AX_SECLD                0x04
+
+#define AX_SROM_ADDR                           0x07
+#define AX_SROM_CMD                            0x0a
+       #define EEP_RD                  0x04
+       #define EEP_BUSY                0x10
+
+#define AX_SROM_DATA_LOW                       0x08
+#define AX_SROM_DATA_HIGH                      0x09
+
+#define AX_RX_CTL                              0x0b
+       #define AX_RX_CTL_DROPCRCERR    0x0100
+       #define AX_RX_CTL_IPE           0x0200
+       #define AX_RX_CTL_START         0x0080
+       #define AX_RX_CTL_AP            0x0020
+       #define AX_RX_CTL_AM            0x0010
+       #define AX_RX_CTL_AB            0x0008
+       #define AX_RX_CTL_AMALL         0x0002
+       #define AX_RX_CTL_PRO           0x0001
+       #define AX_RX_CTL_STOP          0x0000
+
+#define AX_NODE_ID                             0x10
+#define AX_MULFLTARY                           0x16
+
+#define AX_MEDIUM_STATUS_MODE                  0x22
+       #define AX_MEDIUM_GIGAMODE      0x01
+       #define AX_MEDIUM_FULL_DUPLEX   0x02
+       #define AX_MEDIUM_ALWAYS_ONE    0x04
+       #define AX_MEDIUM_EN_125MHZ     0x08
+       #define AX_MEDIUM_RXFLOW_CTRLEN 0x10
+       #define AX_MEDIUM_TXFLOW_CTRLEN 0x20
+       #define AX_MEDIUM_RECEIVE_EN    0x100
+       #define AX_MEDIUM_PS            0x200
+       #define AX_MEDIUM_JUMBO_EN      0x8040
+
+#define AX_MONITOR_MOD                         0x24
+       #define AX_MONITOR_MODE_RWLC    0x02
+       #define AX_MONITOR_MODE_RWMP    0x04
+       #define AX_MONITOR_MODE_PMEPOL  0x20
+       #define AX_MONITOR_MODE_PMETYPE 0x40
+
+#define AX_GPIO_CTRL                           0x25
+       #define AX_GPIO_CTRL_GPIO3EN    0x80
+       #define AX_GPIO_CTRL_GPIO2EN    0x40
+       #define AX_GPIO_CTRL_GPIO1EN    0x20
+
+#define AX_PHYPWR_RSTCTL                       0x26
+       #define AX_PHYPWR_RSTCTL_BZ     0x0010
+       #define AX_PHYPWR_RSTCTL_IPRL   0x0020
+       #define AX_PHYPWR_RSTCTL_AT     0x1000
+
+#define AX_RX_BULKIN_QCTRL                     0x2e
+#define AX_CLK_SELECT                          0x33
+       #define AX_CLK_SELECT_BCS       0x01
+       #define AX_CLK_SELECT_ACS       0x02
+       #define AX_CLK_SELECT_ULR       0x08
+
+#define AX_RXCOE_CTL                           0x34
+       #define AX_RXCOE_IP             0x01
+       #define AX_RXCOE_TCP            0x02
+       #define AX_RXCOE_UDP            0x04
+       #define AX_RXCOE_TCPV6          0x20
+       #define AX_RXCOE_UDPV6          0x40
+
+#define AX_TXCOE_CTL                           0x35
+       #define AX_TXCOE_IP             0x01
+       #define AX_TXCOE_TCP            0x02
+       #define AX_TXCOE_UDP            0x04
+       #define AX_TXCOE_TCPV6          0x20
+       #define AX_TXCOE_UDPV6          0x40
+
+#define AX_LEDCTRL                             0x73
+
+#define GMII_PHY_PHYSR                         0x11
+       #define GMII_PHY_PHYSR_SMASK    0xc000
+       #define GMII_PHY_PHYSR_GIGA     0x8000
+       #define GMII_PHY_PHYSR_100      0x4000
+       #define GMII_PHY_PHYSR_FULL     0x2000
+       #define GMII_PHY_PHYSR_LINK     0x400
+
+#define GMII_LED_ACT                           0x1a
+       #define GMII_LED_ACTIVE_MASK    0xff8f
+       #define GMII_LED0_ACTIVE        BIT(4)
+       #define GMII_LED1_ACTIVE        BIT(5)
+       #define GMII_LED2_ACTIVE        BIT(6)
+
+#define GMII_LED_LINK                          0x1c
+       #define GMII_LED_LINK_MASK      0xf888
+       #define GMII_LED0_LINK_10       BIT(0)
+       #define GMII_LED0_LINK_100      BIT(1)
+       #define GMII_LED0_LINK_1000     BIT(2)
+       #define GMII_LED1_LINK_10       BIT(4)
+       #define GMII_LED1_LINK_100      BIT(5)
+       #define GMII_LED1_LINK_1000     BIT(6)
+       #define GMII_LED2_LINK_10       BIT(8)
+       #define GMII_LED2_LINK_100      BIT(9)
+       #define GMII_LED2_LINK_1000     BIT(10)
+       #define LED0_ACTIVE             BIT(0)
+       #define LED0_LINK_10            BIT(1)
+       #define LED0_LINK_100           BIT(2)
+       #define LED0_LINK_1000          BIT(3)
+       #define LED0_FD                 BIT(4)
+       #define LED0_USB3_MASK          0x001f
+       #define LED1_ACTIVE             BIT(5)
+       #define LED1_LINK_10            BIT(6)
+       #define LED1_LINK_100           BIT(7)
+       #define LED1_LINK_1000          BIT(8)
+       #define LED1_FD                 BIT(9)
+       #define LED1_USB3_MASK          0x03e0
+       #define LED2_ACTIVE             BIT(10)
+       #define LED2_LINK_1000          BIT(13)
+       #define LED2_LINK_100           BIT(12)
+       #define LED2_LINK_10            BIT(11)
+       #define LED2_FD                 BIT(14)
+       #define LED_VALID               BIT(15)
+       #define LED2_USB3_MASK          0x7c00
+
+#define GMII_PHYPAGE                           0x1e
+#define GMII_PHY_PAGE_SELECT                   0x1f
+       #define GMII_PHY_PGSEL_EXT      0x0007
+       #define GMII_PHY_PGSEL_PAGE0    0x0000
+
+struct ax88179_data {
+       u16 rxctl;
+       u16 reserved;
+};
+
+struct ax88179_int_data {
+       __le32 intdata1;
+       __le32 intdata2;
+};
+
+static const struct {
+       unsigned char ctrl, timer_l, timer_h, size, ifg;
+} AX88179_BULKIN_SIZE[] =      {
+       {7, 0x4f, 0,    0x12, 0xff},
+       {7, 0x20, 3,    0x16, 0xff},
+       {7, 0xae, 7,    0x18, 0xff},
+       {7, 0xcc, 0x4c, 0x18, 8},
+};
+
+static int __ax88179_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
+                             u16 size, void *data, int in_pm)
+{
+       int ret;
+       int (*fn)(struct usbnet *, u8, u8, u16, u16, void *, u16);
+
+       BUG_ON(!dev);
+
+       if (!in_pm)
+               fn = usbnet_read_cmd;
+       else
+               fn = usbnet_read_cmd_nopm;
+
+       ret = fn(dev, cmd, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                value, index, data, size);
+
+       if (unlikely(ret < 0))
+               netdev_warn(dev->net, "Failed to read reg index 0x%04x: %d\n",
+                           index, ret);
+
+       return ret;
+}
+
+static int __ax88179_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
+                              u16 size, void *data, int in_pm)
+{
+       int ret;
+       int (*fn)(struct usbnet *, u8, u8, u16, u16, const void *, u16);
+
+       BUG_ON(!dev);
+
+       if (!in_pm)
+               fn = usbnet_write_cmd;
+       else
+               fn = usbnet_write_cmd_nopm;
+
+       ret = fn(dev, cmd, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                value, index, data, size);
+
+       if (unlikely(ret < 0))
+               netdev_warn(dev->net, "Failed to write reg index 0x%04x: %d\n",
+                           index, ret);
+
+       return ret;
+}
+
+static void ax88179_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value,
+                                   u16 index, u16 size, void *data)
+{
+       u16 buf;
+
+       if (2 == size) {
+               buf = *((u16 *)data);
+               cpu_to_le16s(&buf);
+               usbnet_write_cmd_async(dev, cmd, USB_DIR_OUT | USB_TYPE_VENDOR |
+                                      USB_RECIP_DEVICE, value, index, &buf,
+                                      size);
+       } else {
+               usbnet_write_cmd_async(dev, cmd, USB_DIR_OUT | USB_TYPE_VENDOR |
+                                      USB_RECIP_DEVICE, value, index, data,
+                                      size);
+       }
+}
+
+static int ax88179_read_cmd_nopm(struct usbnet *dev, u8 cmd, u16 value,
+                                u16 index, u16 size, void *data)
+{
+       int ret;
+
+       if (2 == size) {
+               u16 buf;
+               ret = __ax88179_read_cmd(dev, cmd, value, index, size, &buf, 1);
+               le16_to_cpus(&buf);
+               *((u16 *)data) = buf;
+       } else if (4 == size) {
+               u32 buf;
+               ret = __ax88179_read_cmd(dev, cmd, value, index, size, &buf, 1);
+               le32_to_cpus(&buf);
+               *((u32 *)data) = buf;
+       } else {
+               ret = __ax88179_read_cmd(dev, cmd, value, index, size, data, 1);
+       }
+
+       return ret;
+}
+
+static int ax88179_write_cmd_nopm(struct usbnet *dev, u8 cmd, u16 value,
+                                 u16 index, u16 size, void *data)
+{
+       int ret;
+
+       if (2 == size) {
+               u16 buf;
+               buf = *((u16 *)data);
+               cpu_to_le16s(&buf);
+               ret = __ax88179_write_cmd(dev, cmd, value, index,
+                                         size, &buf, 1);
+       } else {
+               ret = __ax88179_write_cmd(dev, cmd, value, index,
+                                         size, data, 1);
+       }
+
+       return ret;
+}
+
+static int ax88179_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
+                           u16 size, void *data)
+{
+       int ret;
+
+       if (2 == size) {
+               u16 buf;
+               ret = __ax88179_read_cmd(dev, cmd, value, index, size, &buf, 0);
+               le16_to_cpus(&buf);
+               *((u16 *)data) = buf;
+       } else if (4 == size) {
+               u32 buf;
+               ret = __ax88179_read_cmd(dev, cmd, value, index, size, &buf, 0);
+               le32_to_cpus(&buf);
+               *((u32 *)data) = buf;
+       } else {
+               ret = __ax88179_read_cmd(dev, cmd, value, index, size, data, 0);
+       }
+
+       return ret;
+}
+
+static int ax88179_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
+                            u16 size, void *data)
+{
+       int ret;
+
+       if (2 == size) {
+               u16 buf;
+               buf = *((u16 *)data);
+               cpu_to_le16s(&buf);
+               ret = __ax88179_write_cmd(dev, cmd, value, index,
+                                         size, &buf, 0);
+       } else {
+               ret = __ax88179_write_cmd(dev, cmd, value, index,
+                                         size, data, 0);
+       }
+
+       return ret;
+}
+
+static void ax88179_status(struct usbnet *dev, struct urb *urb)
+{
+       struct ax88179_int_data *event;
+       u32 link;
+
+       if (urb->actual_length < 8)
+               return;
+
+       event = urb->transfer_buffer;
+       le32_to_cpus((void *)&event->intdata1);
+
+       link = (((__force u32)event->intdata1) & AX_INT_PPLS_LINK) >> 16;
+
+       if (netif_carrier_ok(dev->net) != link) {
+               if (link)
+                       usbnet_defer_kevent(dev, EVENT_LINK_RESET);
+               else
+                       netif_carrier_off(dev->net);
+
+               netdev_info(dev->net, "ax88179 - Link status is: %d\n", link);
+       }
+}
+
+static int ax88179_mdio_read(struct net_device *netdev, int phy_id, int loc)
+{
+       struct usbnet *dev = netdev_priv(netdev);
+       u16 res;
+
+       ax88179_read_cmd(dev, AX_ACCESS_PHY, phy_id, (__u16)loc, 2, &res);
+       return res;
+}
+
+static void ax88179_mdio_write(struct net_device *netdev, int phy_id, int loc,
+                              int val)
+{
+       struct usbnet *dev = netdev_priv(netdev);
+       u16 res = (u16) val;
+
+       ax88179_write_cmd(dev, AX_ACCESS_PHY, phy_id, (__u16)loc, 2, &res);
+}
+
+static int ax88179_suspend(struct usb_interface *intf, pm_message_t message)
+{
+       struct usbnet *dev = usb_get_intfdata(intf);
+       u16 tmp16;
+       u8 tmp8;
+
+       usbnet_suspend(intf, message);
+
+       /* Disable RX path */
+       ax88179_read_cmd_nopm(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE,
+                             2, 2, &tmp16);
+       tmp16 &= ~AX_MEDIUM_RECEIVE_EN;
+       ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE,
+                              2, 2, &tmp16);
+
+       /* Force bulk-in zero length */
+       ax88179_read_cmd_nopm(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL,
+                             2, 2, &tmp16);
+
+       tmp16 |= AX_PHYPWR_RSTCTL_BZ | AX_PHYPWR_RSTCTL_IPRL;
+       ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL,
+                              2, 2, &tmp16);
+
+       /* change clock */
+       tmp8 = 0;
+       ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, &tmp8);
+
+       /* Configure RX control register => stop operation */
+       tmp16 = AX_RX_CTL_STOP;
+       ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, &tmp16);
+
+       return 0;
+}
+
+/* This function is used to enable the autodetach function. */
+/* This function is determined by offset 0x43 of EEPROM */
+static int ax88179_auto_detach(struct usbnet *dev, int in_pm)
+{
+       u16 tmp16;
+       u8 tmp8;
+       int (*fnr)(struct usbnet *, u8, u16, u16, u16, void *);
+       int (*fnw)(struct usbnet *, u8, u16, u16, u16, void *);
+
+       if (!in_pm) {
+               fnr = ax88179_read_cmd;
+               fnw = ax88179_write_cmd;
+       } else {
+               fnr = ax88179_read_cmd_nopm;
+               fnw = ax88179_write_cmd_nopm;
+       }
+
+       if (fnr(dev, AX_ACCESS_EEPROM, 0x43, 1, 2, &tmp16) < 0)
+               return 0;
+
+       if ((tmp16 == 0xFFFF) || (!(tmp16 & 0x0100)))
+               return 0;
+
+       /* Enable Auto Detach bit */
+       tmp8 = 0;
+       fnr(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, &tmp8);
+       tmp8 |= AX_CLK_SELECT_ULR;
+       fnw(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, &tmp8);
+
+       fnr(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, &tmp16);
+       tmp16 |= AX_PHYPWR_RSTCTL_AT;
+       fnw(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, &tmp16);
+
+       return 0;
+}
+
+static int ax88179_resume(struct usb_interface *intf)
+{
+       struct usbnet *dev = usb_get_intfdata(intf);
+       u16 tmp16;
+       u8 tmp8;
+
+       netif_carrier_off(dev->net);
+
+       /* Power up ethernet PHY */
+       tmp16 = 0;
+       ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL,
+                              2, 2, &tmp16);
+       udelay(1000);
+
+       tmp16 = AX_PHYPWR_RSTCTL_IPRL;
+       ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL,
+                              2, 2, &tmp16);
+       msleep(200);
+
+       /* Ethernet PHY Auto Detach*/
+       ax88179_auto_detach(dev, 1);
+
+       /* Enable clock */
+       ax88179_read_cmd_nopm(dev, AX_ACCESS_MAC,  AX_CLK_SELECT, 1, 1, &tmp8);
+       tmp8 |= AX_CLK_SELECT_ACS | AX_CLK_SELECT_BCS;
+       ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, &tmp8);
+       msleep(100);
+
+       /* Configure RX control register => start operation */
+       tmp16 = AX_RX_CTL_DROPCRCERR | AX_RX_CTL_IPE | AX_RX_CTL_START |
+               AX_RX_CTL_AP | AX_RX_CTL_AMALL | AX_RX_CTL_AB;
+       ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, &tmp16);
+
+       return usbnet_resume(intf);
+}
+
+static void
+ax88179_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
+{
+       struct usbnet *dev = netdev_priv(net);
+       u8 opt;
+
+       if (ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_MONITOR_MOD,
+                            1, 1, &opt) < 0) {
+               wolinfo->supported = 0;
+               wolinfo->wolopts = 0;
+               return;
+       }
+
+       wolinfo->supported = WAKE_PHY | WAKE_MAGIC;
+       wolinfo->wolopts = 0;
+       if (opt & AX_MONITOR_MODE_RWLC)
+               wolinfo->wolopts |= WAKE_PHY;
+       if (opt & AX_MONITOR_MODE_RWMP)
+               wolinfo->wolopts |= WAKE_MAGIC;
+}
+
+static int
+ax88179_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
+{
+       struct usbnet *dev = netdev_priv(net);
+       u8 opt = 0;
+
+       if (wolinfo->wolopts & WAKE_PHY)
+               opt |= AX_MONITOR_MODE_RWLC;
+       if (wolinfo->wolopts & WAKE_MAGIC)
+               opt |= AX_MONITOR_MODE_RWMP;
+
+       if (ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MONITOR_MOD,
+                             1, 1, &opt) < 0)
+               return -EINVAL;
+
+       return 0;
+}
+
+static int ax88179_get_eeprom_len(struct net_device *net)
+{
+       return AX_EEPROM_LEN;
+}
+
+static int
+ax88179_get_eeprom(struct net_device *net, struct ethtool_eeprom *eeprom,
+                  u8 *data)
+{
+       struct usbnet *dev = netdev_priv(net);
+       u16 *eeprom_buff;
+       int first_word, last_word;
+       int i, ret;
+
+       if (eeprom->len == 0)
+               return -EINVAL;
+
+       eeprom->magic = AX88179_EEPROM_MAGIC;
+
+       first_word = eeprom->offset >> 1;
+       last_word = (eeprom->offset + eeprom->len - 1) >> 1;
+       eeprom_buff = kmalloc(sizeof(u16) * (last_word - first_word + 1),
+                             GFP_KERNEL);
+       if (!eeprom_buff)
+               return -ENOMEM;
+
+       /* ax88179/178A returns 2 bytes from eeprom on read */
+       for (i = first_word; i <= last_word; i++) {
+               ret = __ax88179_read_cmd(dev, AX_ACCESS_EEPROM, i, 1, 2,
+                                        &eeprom_buff[i - first_word],
+                                        0);
+               if (ret < 0) {
+                       kfree(eeprom_buff);
+                       return -EIO;
+               }
+       }
+
+       memcpy(data, (u8 *)eeprom_buff + (eeprom->offset & 1), eeprom->len);
+       kfree(eeprom_buff);
+       return 0;
+}
+
+static int ax88179_get_settings(struct net_device *net, struct ethtool_cmd *cmd)
+{
+       struct usbnet *dev = netdev_priv(net);
+       return mii_ethtool_gset(&dev->mii, cmd);
+}
+
+static int ax88179_set_settings(struct net_device *net, struct ethtool_cmd *cmd)
+{
+       struct usbnet *dev = netdev_priv(net);
+       return mii_ethtool_sset(&dev->mii, cmd);
+}
+
+
+static int ax88179_ioctl(struct net_device *net, struct ifreq *rq, int cmd)
+{
+       struct usbnet *dev = netdev_priv(net);
+       return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL);
+}
+
+static const struct ethtool_ops ax88179_ethtool_ops = {
+       .get_link               = ethtool_op_get_link,
+       .get_msglevel           = usbnet_get_msglevel,
+       .set_msglevel           = usbnet_set_msglevel,
+       .get_wol                = ax88179_get_wol,
+       .set_wol                = ax88179_set_wol,
+       .get_eeprom_len         = ax88179_get_eeprom_len,
+       .get_eeprom             = ax88179_get_eeprom,
+       .get_settings           = ax88179_get_settings,
+       .set_settings           = ax88179_set_settings,
+       .nway_reset             = usbnet_nway_reset,
+};
+
+static void ax88179_set_multicast(struct net_device *net)
+{
+       struct usbnet *dev = netdev_priv(net);
+       struct ax88179_data *data = (struct ax88179_data *)dev->data;
+       u8 *m_filter = ((u8 *)dev->data) + 12;
+
+       data->rxctl = (AX_RX_CTL_START | AX_RX_CTL_AB | AX_RX_CTL_IPE);
+
+       if (net->flags & IFF_PROMISC) {
+               data->rxctl |= AX_RX_CTL_PRO;
+       } else if (net->flags & IFF_ALLMULTI ||
+                  netdev_mc_count(net) > AX_MAX_MCAST) {
+               data->rxctl |= AX_RX_CTL_AMALL;
+       } else if (netdev_mc_empty(net)) {
+               /* just broadcast and directed */
+       } else {
+               /* We use the 20 byte dev->data for our 8 byte filter buffer
+                * to avoid allocating memory that is tricky to free later
+                */
+               u32 crc_bits;
+               struct netdev_hw_addr *ha;
+
+               memset(m_filter, 0, AX_MCAST_FLTSIZE);
+
+               netdev_for_each_mc_addr(ha, net) {
+                       crc_bits = ether_crc(ETH_ALEN, ha->addr) >> 26;
+                       *(m_filter + (crc_bits >> 3)) |= (1 << (crc_bits & 7));
+               }
+
+               ax88179_write_cmd_async(dev, AX_ACCESS_MAC, AX_MULFLTARY,
+                                       AX_MCAST_FLTSIZE, AX_MCAST_FLTSIZE,
+                                       m_filter);
+
+               data->rxctl |= AX_RX_CTL_AM;
+       }
+
+       ax88179_write_cmd_async(dev, AX_ACCESS_MAC, AX_RX_CTL,
+                               2, 2, &data->rxctl);
+}
+
+static int
+ax88179_set_features(struct net_device *net, netdev_features_t features)
+{
+       u8 tmp;
+       struct usbnet *dev = netdev_priv(net);
+       netdev_features_t changed = net->features ^ features;
+
+       if (changed & NETIF_F_IP_CSUM) {
+               ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, &tmp);
+               tmp ^= AX_TXCOE_TCP | AX_TXCOE_UDP;
+               ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, &tmp);
+       }
+
+       if (changed & NETIF_F_IPV6_CSUM) {
+               ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, &tmp);
+               tmp ^= AX_TXCOE_TCPV6 | AX_TXCOE_UDPV6;
+               ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, &tmp);
+       }
+
+       if (changed & NETIF_F_RXCSUM) {
+               ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_RXCOE_CTL, 1, 1, &tmp);
+               tmp ^= AX_RXCOE_IP | AX_RXCOE_TCP | AX_RXCOE_UDP |
+                      AX_RXCOE_TCPV6 | AX_RXCOE_UDPV6;
+               ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RXCOE_CTL, 1, 1, &tmp);
+       }
+
+       return 0;
+}
+
+static int ax88179_change_mtu(struct net_device *net, int new_mtu)
+{
+       struct usbnet *dev = netdev_priv(net);
+       u16 tmp16;
+
+       if (new_mtu <= 0 || new_mtu > 4088)
+               return -EINVAL;
+
+       net->mtu = new_mtu;
+       dev->hard_mtu = net->mtu + net->hard_header_len;
+
+       if (net->mtu > 1500) {
+               ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE,
+                                2, 2, &tmp16);
+               tmp16 |= AX_MEDIUM_JUMBO_EN;
+               ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE,
+                                 2, 2, &tmp16);
+       } else {
+               ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE,
+                                2, 2, &tmp16);
+               tmp16 &= ~AX_MEDIUM_JUMBO_EN;
+               ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE,
+                                 2, 2, &tmp16);
+       }
+
+       return 0;
+}
+
+static int ax88179_set_mac_addr(struct net_device *net, void *p)
+{
+       struct usbnet *dev = netdev_priv(net);
+       struct sockaddr *addr = p;
+
+       if (netif_running(net))
+               return -EBUSY;
+       if (!is_valid_ether_addr(addr->sa_data))
+               return -EADDRNOTAVAIL;
+
+       memcpy(net->dev_addr, addr->sa_data, ETH_ALEN);
+
+       /* Set the MAC address */
+       return ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_NODE_ID, ETH_ALEN,
+                                ETH_ALEN, net->dev_addr);
+}
+
+static const struct net_device_ops ax88179_netdev_ops = {
+       .ndo_open               = usbnet_open,
+       .ndo_stop               = usbnet_stop,
+       .ndo_start_xmit         = usbnet_start_xmit,
+       .ndo_tx_timeout         = usbnet_tx_timeout,
+       .ndo_change_mtu         = ax88179_change_mtu,
+       .ndo_set_mac_address    = ax88179_set_mac_addr,
+       .ndo_validate_addr      = eth_validate_addr,
+       .ndo_do_ioctl           = ax88179_ioctl,
+       .ndo_set_rx_mode        = ax88179_set_multicast,
+       .ndo_set_features       = ax88179_set_features,
+};
+
+static int ax88179_check_eeprom(struct usbnet *dev)
+{
+       u8 i, buf, eeprom[20];
+       u16 csum, delay = HZ / 10;
+       unsigned long jtimeout;
+
+       /* Read EEPROM content */
+       for (i = 0; i < 6; i++) {
+               buf = i;
+               if (ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_SROM_ADDR,
+                                     1, 1, &buf) < 0)
+                       return -EINVAL;
+
+               buf = EEP_RD;
+               if (ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_SROM_CMD,
+                                     1, 1, &buf) < 0)
+                       return -EINVAL;
+
+               jtimeout = jiffies + delay;
+               do {
+                       ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_SROM_CMD,
+                                        1, 1, &buf);
+
+                       if (time_after(jiffies, jtimeout))
+                               return -EINVAL;
+
+               } while (buf & EEP_BUSY);
+
+               __ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_SROM_DATA_LOW,
+                                  2, 2, &eeprom[i * 2], 0);
+
+               if ((i == 0) && (eeprom[0] == 0xFF))
+                       return -EINVAL;
+       }
+
+       csum = eeprom[6] + eeprom[7] + eeprom[8] + eeprom[9];
+       csum = (csum >> 8) + (csum & 0xff);
+       if ((csum + eeprom[10]) != 0xff)
+               return -EINVAL;
+
+       return 0;
+}
+
+static int ax88179_check_efuse(struct usbnet *dev, u16 *ledmode)
+{
+       u8      i;
+       u8      efuse[64];
+       u16     csum = 0;
+
+       if (ax88179_read_cmd(dev, AX_ACCESS_EFUS, 0, 64, 64, efuse) < 0)
+               return -EINVAL;
+
+       if (*efuse == 0xFF)
+               return -EINVAL;
+
+       for (i = 0; i < 64; i++)
+               csum = csum + efuse[i];
+
+       while (csum > 255)
+               csum = (csum & 0x00FF) + ((csum >> 8) & 0x00FF);
+
+       if (csum != 0xFF)
+               return -EINVAL;
+
+       *ledmode = (efuse[51] << 8) | efuse[52];
+
+       return 0;
+}
+
+static int ax88179_convert_old_led(struct usbnet *dev, u16 *ledvalue)
+{
+       u16 led;
+
+       /* Loaded the old eFuse LED Mode */
+       if (ax88179_read_cmd(dev, AX_ACCESS_EEPROM, 0x3C, 1, 2, &led) < 0)
+               return -EINVAL;
+
+       led >>= 8;
+       switch (led) {
+       case 0xFF:
+               led = LED0_ACTIVE | LED1_LINK_10 | LED1_LINK_100 |
+                     LED1_LINK_1000 | LED2_ACTIVE | LED2_LINK_10 |
+                     LED2_LINK_100 | LED2_LINK_1000 | LED_VALID;
+               break;
+       case 0xFE:
+               led = LED0_ACTIVE | LED1_LINK_1000 | LED2_LINK_100 | LED_VALID;
+               break;
+       case 0xFD:
+               led = LED0_ACTIVE | LED1_LINK_1000 | LED2_LINK_100 |
+                     LED2_LINK_10 | LED_VALID;
+               break;
+       case 0xFC:
+               led = LED0_ACTIVE | LED1_ACTIVE | LED1_LINK_1000 | LED2_ACTIVE |
+                     LED2_LINK_100 | LED2_LINK_10 | LED_VALID;
+               break;
+       default:
+               led = LED0_ACTIVE | LED1_LINK_10 | LED1_LINK_100 |
+                     LED1_LINK_1000 | LED2_ACTIVE | LED2_LINK_10 |
+                     LED2_LINK_100 | LED2_LINK_1000 | LED_VALID;
+               break;
+       }
+
+       *ledvalue = led;
+
+       return 0;
+}
+
+static int ax88179_led_setting(struct usbnet *dev)
+{
+       u8 ledfd, value = 0;
+       u16 tmp, ledact, ledlink, ledvalue = 0, delay = HZ / 10;
+       unsigned long jtimeout;
+
+       /* Check AX88179 version. UA1 or UA2*/
+       ax88179_read_cmd(dev, AX_ACCESS_MAC, GENERAL_STATUS, 1, 1, &value);
+
+       if (!(value & AX_SECLD)) {      /* UA1 */
+               value = AX_GPIO_CTRL_GPIO3EN | AX_GPIO_CTRL_GPIO2EN |
+                       AX_GPIO_CTRL_GPIO1EN;
+               if (ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_GPIO_CTRL,
+                                     1, 1, &value) < 0)
+                       return -EINVAL;
+       }
+
+       /* Check EEPROM */
+       if (!ax88179_check_eeprom(dev)) {
+               value = 0x42;
+               if (ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_SROM_ADDR,
+                                     1, 1, &value) < 0)
+                       return -EINVAL;
+
+               value = EEP_RD;
+               if (ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_SROM_CMD,
+                                     1, 1, &value) < 0)
+                       return -EINVAL;
+
+               jtimeout = jiffies + delay;
+               do {
+                       ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_SROM_CMD,
+                                        1, 1, &value);
+
+                       if (time_after(jiffies, jtimeout))
+                               return -EINVAL;
+
+               } while (value & EEP_BUSY);
+
+               ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_SROM_DATA_HIGH,
+                                1, 1, &value);
+               ledvalue = (value << 8);
+
+               ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_SROM_DATA_LOW,
+                                1, 1, &value);
+               ledvalue |= value;
+
+               /* load internal ROM for defaule setting */
+               if ((ledvalue == 0xFFFF) || ((ledvalue & LED_VALID) == 0))
+                       ax88179_convert_old_led(dev, &ledvalue);
+
+       } else if (!ax88179_check_efuse(dev, &ledvalue)) {
+               if ((ledvalue == 0xFFFF) || ((ledvalue & LED_VALID) == 0))
+                       ax88179_convert_old_led(dev, &ledvalue);
+       } else {
+               ax88179_convert_old_led(dev, &ledvalue);
+       }
+
+       tmp = GMII_PHY_PGSEL_EXT;
+       ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
+                         GMII_PHY_PAGE_SELECT, 2, &tmp);
+
+       tmp = 0x2c;
+       ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
+                         GMII_PHYPAGE, 2, &tmp);
+
+       ax88179_read_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
+                        GMII_LED_ACT, 2, &ledact);
+
+       ax88179_read_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
+                        GMII_LED_LINK, 2, &ledlink);
+
+       ledact &= GMII_LED_ACTIVE_MASK;
+       ledlink &= GMII_LED_LINK_MASK;
+
+       if (ledvalue & LED0_ACTIVE)
+               ledact |= GMII_LED0_ACTIVE;
+
+       if (ledvalue & LED1_ACTIVE)
+               ledact |= GMII_LED1_ACTIVE;
+
+       if (ledvalue & LED2_ACTIVE)
+               ledact |= GMII_LED2_ACTIVE;
+
+       if (ledvalue & LED0_LINK_10)
+               ledlink |= GMII_LED0_LINK_10;
+
+       if (ledvalue & LED1_LINK_10)
+               ledlink |= GMII_LED1_LINK_10;
+
+       if (ledvalue & LED2_LINK_10)
+               ledlink |= GMII_LED2_LINK_10;
+
+       if (ledvalue & LED0_LINK_100)
+               ledlink |= GMII_LED0_LINK_100;
+
+       if (ledvalue & LED1_LINK_100)
+               ledlink |= GMII_LED1_LINK_100;
+
+       if (ledvalue & LED2_LINK_100)
+               ledlink |= GMII_LED2_LINK_100;
+
+       if (ledvalue & LED0_LINK_1000)
+               ledlink |= GMII_LED0_LINK_1000;
+
+       if (ledvalue & LED1_LINK_1000)
+               ledlink |= GMII_LED1_LINK_1000;
+
+       if (ledvalue & LED2_LINK_1000)
+               ledlink |= GMII_LED2_LINK_1000;
+
+       tmp = ledact;
+       ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
+                         GMII_LED_ACT, 2, &tmp);
+
+       tmp = ledlink;
+       ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
+                         GMII_LED_LINK, 2, &tmp);
+
+       tmp = GMII_PHY_PGSEL_PAGE0;
+       ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
+                         GMII_PHY_PAGE_SELECT, 2, &tmp);
+
+       /* LED full duplex setting */
+       ledfd = 0;
+       if (ledvalue & LED0_FD)
+               ledfd |= 0x01;
+       else if ((ledvalue & LED0_USB3_MASK) == 0)
+               ledfd |= 0x02;
+
+       if (ledvalue & LED1_FD)
+               ledfd |= 0x04;
+       else if ((ledvalue & LED1_USB3_MASK) == 0)
+               ledfd |= 0x08;
+
+       if (ledvalue & LED2_FD)
+               ledfd |= 0x10;
+       else if ((ledvalue & LED2_USB3_MASK) == 0)
+               ledfd |= 0x20;
+
+       ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_LEDCTRL, 1, 1, &ledfd);
+
+       return 0;
+}
+
+static int ax88179_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+       u8 buf[5];
+       u16 *tmp16;
+       u8 *tmp;
+       struct ax88179_data *ax179_data = (struct ax88179_data *)dev->data;
+
+       usbnet_get_endpoints(dev, intf);
+
+       tmp16 = (u16 *)buf;
+       tmp = (u8 *)buf;
+
+       memset(ax179_data, 0, sizeof(*ax179_data));
+
+       /* Power up ethernet PHY */
+       *tmp16 = 0;
+       ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, tmp16);
+       *tmp16 = AX_PHYPWR_RSTCTL_IPRL;
+       ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, tmp16);
+       msleep(200);
+
+       *tmp = AX_CLK_SELECT_ACS | AX_CLK_SELECT_BCS;
+       ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, tmp);
+       msleep(100);
+
+       ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_NODE_ID, ETH_ALEN,
+                        ETH_ALEN, dev->net->dev_addr);
+       memcpy(dev->net->perm_addr, dev->net->dev_addr, ETH_ALEN);
+
+       /* RX bulk configuration */
+       memcpy(tmp, &AX88179_BULKIN_SIZE[0], 5);
+       ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_BULKIN_QCTRL, 5, 5, tmp);
+
+       dev->rx_urb_size = 1024 * 20;
+
+       *tmp = 0x34;
+       ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PAUSE_WATERLVL_LOW, 1, 1, tmp);
+
+       *tmp = 0x52;
+       ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PAUSE_WATERLVL_HIGH,
+                         1, 1, tmp);
+
+       dev->net->netdev_ops = &ax88179_netdev_ops;
+       dev->net->ethtool_ops = &ax88179_ethtool_ops;
+       dev->net->needed_headroom = 8;
+
+       /* Initialize MII structure */
+       dev->mii.dev = dev->net;
+       dev->mii.mdio_read = ax88179_mdio_read;
+       dev->mii.mdio_write = ax88179_mdio_write;
+       dev->mii.phy_id_mask = 0xff;
+       dev->mii.reg_num_mask = 0xff;
+       dev->mii.phy_id = 0x03;
+       dev->mii.supports_gmii = 1;
+
+       dev->net->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
+                             NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_TSO;
+
+       dev->net->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
+                                NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_TSO;
+
+       /* Enable checksum offload */
+       *tmp = AX_RXCOE_IP | AX_RXCOE_TCP | AX_RXCOE_UDP |
+              AX_RXCOE_TCPV6 | AX_RXCOE_UDPV6;
+       ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RXCOE_CTL, 1, 1, tmp);
+
+       *tmp = AX_TXCOE_IP | AX_TXCOE_TCP | AX_TXCOE_UDP |
+              AX_TXCOE_TCPV6 | AX_TXCOE_UDPV6;
+       ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, tmp);
+
+       /* Configure RX control register => start operation */
+       *tmp16 = AX_RX_CTL_DROPCRCERR | AX_RX_CTL_IPE | AX_RX_CTL_START |
+                AX_RX_CTL_AP | AX_RX_CTL_AMALL | AX_RX_CTL_AB;
+       ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, tmp16);
+
+       *tmp = AX_MONITOR_MODE_PMETYPE | AX_MONITOR_MODE_PMEPOL |
+              AX_MONITOR_MODE_RWMP;
+       ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MONITOR_MOD, 1, 1, tmp);
+
+       /* Configure default medium type => giga */
+       *tmp16 = AX_MEDIUM_RECEIVE_EN | AX_MEDIUM_TXFLOW_CTRLEN |
+                AX_MEDIUM_RXFLOW_CTRLEN | AX_MEDIUM_ALWAYS_ONE |
+                AX_MEDIUM_FULL_DUPLEX | AX_MEDIUM_GIGAMODE;
+       ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE,
+                         2, 2, tmp16);
+
+       ax88179_led_setting(dev);
+
+       /* Restart autoneg */
+       mii_nway_restart(&dev->mii);
+
+       netif_carrier_off(dev->net);
+
+       return 0;
+}
+
+static void ax88179_unbind(struct usbnet *dev, struct usb_interface *intf)
+{
+       u16 tmp16;
+
+       /* Configure RX control register => stop operation */
+       tmp16 = AX_RX_CTL_STOP;
+       ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, &tmp16);
+
+       tmp16 = 0;
+       ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, &tmp16);
+
+       /* Power down ethernet PHY */
+       tmp16 = 0;
+       ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, &tmp16);
+}
+
+static void
+ax88179_rx_checksum(struct sk_buff *skb, u32 *pkt_hdr)
+{
+       skb->ip_summed = CHECKSUM_NONE;
+
+       /* checksum error bit is set */
+       if ((*pkt_hdr & AX_RXHDR_L3CSUM_ERR) ||
+           (*pkt_hdr & AX_RXHDR_L4CSUM_ERR))
+               return;
+
+       /* It must be a TCP or UDP packet with a valid checksum */
+       if (((*pkt_hdr & AX_RXHDR_L4_TYPE_MASK) == AX_RXHDR_L4_TYPE_TCP) ||
+           ((*pkt_hdr & AX_RXHDR_L4_TYPE_MASK) == AX_RXHDR_L4_TYPE_UDP))
+               skb->ip_summed = CHECKSUM_UNNECESSARY;
+}
+
+static int ax88179_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+{
+       struct sk_buff *ax_skb;
+       int pkt_cnt;
+       u32 rx_hdr;
+       u16 hdr_off;
+       u32 *pkt_hdr;
+
+       skb_trim(skb, skb->len - 4);
+       memcpy(&rx_hdr, skb_tail_pointer(skb), 4);
+       le32_to_cpus(&rx_hdr);
+
+       pkt_cnt = (u16)rx_hdr;
+       hdr_off = (u16)(rx_hdr >> 16);
+       pkt_hdr = (u32 *)(skb->data + hdr_off);
+
+       while (pkt_cnt--) {
+               u16 pkt_len;
+
+               le32_to_cpus(pkt_hdr);
+               pkt_len = (*pkt_hdr >> 16) & 0x1fff;
+
+               /* Check CRC or runt packet */
+               if ((*pkt_hdr & AX_RXHDR_CRC_ERR) ||
+                   (*pkt_hdr & AX_RXHDR_DROP_ERR)) {
+                       skb_pull(skb, (pkt_len + 7) & 0xFFF8);
+                       pkt_hdr++;
+                       continue;
+               }
+
+               if (pkt_cnt == 0) {
+                       /* Skip IP alignment psudo header */
+                       skb_pull(skb, 2);
+                       skb->len = pkt_len;
+                       skb_set_tail_pointer(skb, pkt_len);
+                       skb->truesize = pkt_len + sizeof(struct sk_buff);
+                       ax88179_rx_checksum(skb, pkt_hdr);
+                       return 1;
+               }
+
+               ax_skb = skb_clone(skb, GFP_ATOMIC);
+               if (ax_skb) {
+                       ax_skb->len = pkt_len;
+                       ax_skb->data = skb->data + 2;
+                       skb_set_tail_pointer(ax_skb, pkt_len);
+                       ax_skb->truesize = pkt_len + sizeof(struct sk_buff);
+                       ax88179_rx_checksum(ax_skb, pkt_hdr);
+                       usbnet_skb_return(dev, ax_skb);
+               } else {
+                       return 0;
+               }
+
+               skb_pull(skb, (pkt_len + 7) & 0xFFF8);
+               pkt_hdr++;
+       }
+       return 1;
+}
+
+static struct sk_buff *
+ax88179_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
+{
+       u32 tx_hdr1, tx_hdr2;
+       int frame_size = dev->maxpacket;
+       int mss = skb_shinfo(skb)->gso_size;
+       int headroom;
+       int tailroom;
+
+       tx_hdr1 = skb->len;
+       tx_hdr2 = mss;
+       if (((skb->len + 8) % frame_size) == 0)
+               tx_hdr2 |= 0x80008000;  /* Enable padding */
+
+       skb_linearize(skb);
+       headroom = skb_headroom(skb);
+       tailroom = skb_tailroom(skb);
+
+       if (!skb_header_cloned(skb) &&
+           !skb_cloned(skb) &&
+           (headroom + tailroom) >= 8) {
+               if (headroom < 8) {
+                       skb->data = memmove(skb->head + 8, skb->data, skb->len);
+                       skb_set_tail_pointer(skb, skb->len);
+               }
+       } else {
+               struct sk_buff *skb2;
+
+               skb2 = skb_copy_expand(skb, 8, 0, flags);
+               dev_kfree_skb_any(skb);
+               skb = skb2;
+               if (!skb)
+                       return NULL;
+       }
+
+       skb_push(skb, 4);
+       cpu_to_le32s(&tx_hdr2);
+       skb_copy_to_linear_data(skb, &tx_hdr2, 4);
+
+       skb_push(skb, 4);
+       cpu_to_le32s(&tx_hdr1);
+       skb_copy_to_linear_data(skb, &tx_hdr1, 4);
+
+       return skb;
+}
+
+static int ax88179_link_reset(struct usbnet *dev)
+{
+       struct ax88179_data *ax179_data = (struct ax88179_data *)dev->data;
+       u8 tmp[5], link_sts;
+       u16 mode, tmp16, delay = HZ / 10;
+       u32 tmp32 = 0x40000000;
+       unsigned long jtimeout;
+
+       jtimeout = jiffies + delay;
+       while (tmp32 & 0x40000000) {
+               mode = 0;
+               ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, &mode);
+               ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2,
+                                 &ax179_data->rxctl);
+
+               /*link up, check the usb device control TX FIFO full or empty*/
+               ax88179_read_cmd(dev, 0x81, 0x8c, 0, 4, &tmp32);
+
+               if (time_after(jiffies, jtimeout))
+                       return 0;
+       }
+
+       mode = AX_MEDIUM_RECEIVE_EN | AX_MEDIUM_TXFLOW_CTRLEN |
+              AX_MEDIUM_RXFLOW_CTRLEN | AX_MEDIUM_ALWAYS_ONE;
+
+       ax88179_read_cmd(dev, AX_ACCESS_MAC, PHYSICAL_LINK_STATUS,
+                        1, 1, &link_sts);
+
+       ax88179_read_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
+                        GMII_PHY_PHYSR, 2, &tmp16);
+
+       if (!(tmp16 & GMII_PHY_PHYSR_LINK)) {
+               return 0;
+       } else if (GMII_PHY_PHYSR_GIGA == (tmp16 & GMII_PHY_PHYSR_SMASK)) {
+               mode |= AX_MEDIUM_GIGAMODE | AX_MEDIUM_EN_125MHZ;
+               if (dev->net->mtu > 1500)
+                       mode |= AX_MEDIUM_JUMBO_EN;
+
+               if (link_sts & AX_USB_SS)
+                       memcpy(tmp, &AX88179_BULKIN_SIZE[0], 5);
+               else if (link_sts & AX_USB_HS)
+                       memcpy(tmp, &AX88179_BULKIN_SIZE[1], 5);
+               else
+                       memcpy(tmp, &AX88179_BULKIN_SIZE[3], 5);
+       } else if (GMII_PHY_PHYSR_100 == (tmp16 & GMII_PHY_PHYSR_SMASK)) {
+               mode |= AX_MEDIUM_PS;
+
+               if (link_sts & (AX_USB_SS | AX_USB_HS))
+                       memcpy(tmp, &AX88179_BULKIN_SIZE[2], 5);
+               else
+                       memcpy(tmp, &AX88179_BULKIN_SIZE[3], 5);
+       } else {
+               memcpy(tmp, &AX88179_BULKIN_SIZE[3], 5);
+       }
+
+       /* RX bulk configuration */
+       ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_BULKIN_QCTRL, 5, 5, tmp);
+
+       dev->rx_urb_size = (1024 * (tmp[3] + 2));
+
+       if (tmp16 & GMII_PHY_PHYSR_FULL)
+               mode |= AX_MEDIUM_FULL_DUPLEX;
+       ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE,
+                         2, 2, &mode);
+
+       netif_carrier_on(dev->net);
+
+       return 0;
+}
+
+static int ax88179_reset(struct usbnet *dev)
+{
+       u8 buf[5];
+       u16 *tmp16;
+       u8 *tmp;
+
+       tmp16 = (u16 *)buf;
+       tmp = (u8 *)buf;
+
+       /* Power up ethernet PHY */
+       *tmp16 = 0;
+       ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, tmp16);
+
+       *tmp16 = AX_PHYPWR_RSTCTL_IPRL;
+       ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, tmp16);
+       msleep(200);
+
+       *tmp = AX_CLK_SELECT_ACS | AX_CLK_SELECT_BCS;
+       ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, tmp);
+       msleep(100);
+
+       /* Ethernet PHY Auto Detach*/
+       ax88179_auto_detach(dev, 0);
+
+       ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_NODE_ID, ETH_ALEN, ETH_ALEN,
+                        dev->net->dev_addr);
+       memcpy(dev->net->perm_addr, dev->net->dev_addr, ETH_ALEN);
+
+       /* RX bulk configuration */
+       memcpy(tmp, &AX88179_BULKIN_SIZE[0], 5);
+       ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_BULKIN_QCTRL, 5, 5, tmp);
+
+       dev->rx_urb_size = 1024 * 20;
+
+       *tmp = 0x34;
+       ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PAUSE_WATERLVL_LOW, 1, 1, tmp);
+
+       *tmp = 0x52;
+       ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PAUSE_WATERLVL_HIGH,
+                         1, 1, tmp);
+
+       dev->net->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
+                             NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_TSO;
+
+       dev->net->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
+                                NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_TSO;
+
+       /* Enable checksum offload */
+       *tmp = AX_RXCOE_IP | AX_RXCOE_TCP | AX_RXCOE_UDP |
+              AX_RXCOE_TCPV6 | AX_RXCOE_UDPV6;
+       ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RXCOE_CTL, 1, 1, tmp);
+
+       *tmp = AX_TXCOE_IP | AX_TXCOE_TCP | AX_TXCOE_UDP |
+              AX_TXCOE_TCPV6 | AX_TXCOE_UDPV6;
+       ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, tmp);
+
+       /* Configure RX control register => start operation */
+       *tmp16 = AX_RX_CTL_DROPCRCERR | AX_RX_CTL_IPE | AX_RX_CTL_START |
+                AX_RX_CTL_AP | AX_RX_CTL_AMALL | AX_RX_CTL_AB;
+       ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, tmp16);
+
+       *tmp = AX_MONITOR_MODE_PMETYPE | AX_MONITOR_MODE_PMEPOL |
+              AX_MONITOR_MODE_RWMP;
+       ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MONITOR_MOD, 1, 1, tmp);
+
+       /* Configure default medium type => giga */
+       *tmp16 = AX_MEDIUM_RECEIVE_EN | AX_MEDIUM_TXFLOW_CTRLEN |
+                AX_MEDIUM_RXFLOW_CTRLEN | AX_MEDIUM_ALWAYS_ONE |
+                AX_MEDIUM_FULL_DUPLEX | AX_MEDIUM_GIGAMODE;
+       ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE,
+                         2, 2, tmp16);
+
+       ax88179_led_setting(dev);
+
+       /* Restart autoneg */
+       mii_nway_restart(&dev->mii);
+
+       netif_carrier_off(dev->net);
+
+       return 0;
+}
+
+static int ax88179_stop(struct usbnet *dev)
+{
+       u16 tmp16;
+
+       ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE,
+                        2, 2, &tmp16);
+       tmp16 &= ~AX_MEDIUM_RECEIVE_EN;
+       ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE,
+                         2, 2, &tmp16);
+
+       return 0;
+}
+
+static const struct driver_info ax88179_info = {
+       .description = "ASIX AX88179 USB 3.0 Gigibit Ethernet",
+       .bind = ax88179_bind,
+       .unbind = ax88179_unbind,
+       .status = ax88179_status,
+       .link_reset = ax88179_link_reset,
+       .reset = ax88179_reset,
+       .stop = ax88179_stop,
+       .flags = FLAG_ETHER | FLAG_FRAMING_AX,
+       .rx_fixup = ax88179_rx_fixup,
+       .tx_fixup = ax88179_tx_fixup,
+};
+
+static const struct driver_info ax88178a_info = {
+       .description = "ASIX AX88178A USB 2.0 Gigibit Ethernet",
+       .bind = ax88179_bind,
+       .unbind = ax88179_unbind,
+       .status = ax88179_status,
+       .link_reset = ax88179_link_reset,
+       .reset = ax88179_reset,
+       .stop = ax88179_stop,
+       .flags = FLAG_ETHER | FLAG_FRAMING_AX,
+       .rx_fixup = ax88179_rx_fixup,
+       .tx_fixup = ax88179_tx_fixup,
+};
+
+static const struct driver_info sitecom_info = {
+       .description = "Sitecom USB 3.0 to Gigabit Adapter",
+       .bind = ax88179_bind,
+       .unbind = ax88179_unbind,
+       .status = ax88179_status,
+       .link_reset = ax88179_link_reset,
+       .reset = ax88179_reset,
+       .stop = ax88179_stop,
+       .flags = FLAG_ETHER | FLAG_FRAMING_AX,
+       .rx_fixup = ax88179_rx_fixup,
+       .tx_fixup = ax88179_tx_fixup,
+};
+
+static const struct usb_device_id products[] = {
+{
+       /* ASIX AX88179 10/100/1000 */
+       USB_DEVICE(0x0b95, 0x1790),
+       .driver_info = (unsigned long)&ax88179_info,
+}, {
+       /* ASIX AX88178A 10/100/1000 */
+       USB_DEVICE(0x0b95, 0x178a),
+       .driver_info = (unsigned long)&ax88178a_info,
+}, {
+       /* Sitecom USB 3.0 to Gigabit Adapter */
+       USB_DEVICE(0x0df6, 0x0072),
+       .driver_info = (unsigned long) &sitecom_info,
+},
+       { },
+};
+MODULE_DEVICE_TABLE(usb, products);
+
+static struct usb_driver ax88179_178a_driver = {
+       .name =         "ax88179_178a",
+       .id_table =     products,
+       .probe =        usbnet_probe,
+       .suspend =      ax88179_suspend,
+       .resume =       ax88179_resume,
+       .disconnect =   usbnet_disconnect,
+       .supports_autosuspend = 1,
+       .disable_hub_initiated_lpm = 1,
+};
+
+module_usb_driver(ax88179_178a_driver);
+
+MODULE_DESCRIPTION("ASIX AX88179/178A based USB 3.0/2.0 Gigabit Ethernet Devices");
+MODULE_LICENSE("GPL");
index 4a8c25a..61b74a2 100644 (file)
@@ -1213,6 +1213,14 @@ static const struct usb_device_id cdc_devs[] = {
          .driver_info = (unsigned long) &wwan_info,
        },
 
+       /* tag Huawei devices as wwan */
+       { USB_VENDOR_AND_INTERFACE_INFO(0x12d1,
+                                       USB_CLASS_COMM,
+                                       USB_CDC_SUBCLASS_NCM,
+                                       USB_CDC_PROTO_NONE),
+         .driver_info = (unsigned long)&wwan_info,
+       },
+
        /* Huawei NCM devices disguised as vendor specific */
        { USB_VENDOR_AND_INTERFACE_INFO(0x12d1, 0xff, 0x02, 0x16),
          .driver_info = (unsigned long)&wwan_info,
index 4aad350..eae7a03 100644 (file)
@@ -2958,6 +2958,7 @@ vmxnet3_probe_device(struct pci_dev *pdev,
 
        adapter->num_rx_queues = num_rx_queues;
        adapter->num_tx_queues = num_tx_queues;
+       adapter->rx_buf_per_pkt = 1;
 
        size = sizeof(struct Vmxnet3_TxQueueDesc) * adapter->num_tx_queues;
        size += sizeof(struct Vmxnet3_RxQueueDesc) * adapter->num_rx_queues;
index a0feb17..63a1243 100644 (file)
@@ -472,6 +472,12 @@ vmxnet3_set_ringparam(struct net_device *netdev,
                                                VMXNET3_RX_RING_MAX_SIZE)
                return -EINVAL;
 
+       /* if adapter not yet initialized, do nothing */
+       if (adapter->rx_buf_per_pkt == 0) {
+               netdev_err(netdev, "adapter not completely initialized, "
+                          "ring size cannot be changed yet\n");
+               return -EOPNOTSUPP;
+       }
 
        /* round it up to a multiple of VMXNET3_RING_SIZE_ALIGN */
        new_tx_ring_size = (param->tx_pending + VMXNET3_RING_SIZE_MASK) &
index 3198384..3541814 100644 (file)
 /*
  * Version numbers
  */
-#define VMXNET3_DRIVER_VERSION_STRING   "1.1.29.0-k"
+#define VMXNET3_DRIVER_VERSION_STRING   "1.1.30.0-k"
 
 /* a 32-bit int, each byte encode a verion number in VMXNET3_DRIVER_VERSION */
-#define VMXNET3_DRIVER_VERSION_NUM      0x01011D00
+#define VMXNET3_DRIVER_VERSION_NUM      0x01011E00
 
 #if defined(CONFIG_PCI_MSI)
        /* RSS only makes sense if MSI-X is supported. */
index f10e58a..7cee7a3 100644 (file)
@@ -961,6 +961,8 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
        iph->ttl        = ttl ? : ip4_dst_hoplimit(&rt->dst);
        tunnel_ip_select_ident(skb, old_iph, &rt->dst);
 
+       nf_reset(skb);
+
        vxlan_set_owner(dev, skb);
 
        /* See iptunnel_xmit() */
@@ -1504,6 +1506,14 @@ static __net_init int vxlan_init_net(struct net *net)
 static __net_exit void vxlan_exit_net(struct net *net)
 {
        struct vxlan_net *vn = net_generic(net, vxlan_net_id);
+       struct vxlan_dev *vxlan;
+       unsigned h;
+
+       rtnl_lock();
+       for (h = 0; h < VNI_HASH_SIZE; ++h)
+               hlist_for_each_entry(vxlan, &vn->vni_list[h], hlist)
+                       dev_close(vxlan->dev);
+       rtnl_unlock();
 
        if (vn->sock) {
                sk_release_kernel(vn->sock->sk);
index 5f845be..050ca4a 100644 (file)
@@ -27,7 +27,7 @@
 #define WME_MAX_BA              WME_BA_BMP_SIZE
 #define ATH_TID_MAX_BUFS        (2 * WME_MAX_BA)
 
-#define ATH_RSSI_DUMMY_MARKER   0x127
+#define ATH_RSSI_DUMMY_MARKER   127
 #define ATH_RSSI_LPF_LEN               10
 #define RSSI_LPF_THRESHOLD             -20
 #define ATH_RSSI_EP_MULTIPLIER     (1<<7)
index 96bfb18..d3b099d 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/firmware.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
+#include <linux/etherdevice.h>
 #include <linux/leds.h>
 #include <linux/slab.h>
 #include <net/mac80211.h>
index 3ad1fd0..bd8251c 100644 (file)
@@ -1067,15 +1067,19 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
 
        last_rssi = priv->rx.last_rssi;
 
-       if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
-               rxbuf->rxstatus.rs_rssi = ATH_EP_RND(last_rssi,
-                                                    ATH_RSSI_EP_MULTIPLIER);
+       if (ieee80211_is_beacon(hdr->frame_control) &&
+           !is_zero_ether_addr(common->curbssid) &&
+           ether_addr_equal(hdr->addr3, common->curbssid)) {
+               s8 rssi = rxbuf->rxstatus.rs_rssi;
 
-       if (rxbuf->rxstatus.rs_rssi < 0)
-               rxbuf->rxstatus.rs_rssi = 0;
+               if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
+                       rssi = ATH_EP_RND(last_rssi, ATH_RSSI_EP_MULTIPLIER);
 
-       if (ieee80211_is_beacon(fc))
-               priv->ah->stats.avgbrssi = rxbuf->rxstatus.rs_rssi;
+               if (rssi < 0)
+                       rssi = 0;
+
+               priv->ah->stats.avgbrssi = rssi;
+       }
 
        rx_status->mactime = be64_to_cpu(rxbuf->rxstatus.rs_tstamp);
        rx_status->band = hw->conf.channel->band;
index 2a2ae40..07e2526 100644 (file)
@@ -1463,7 +1463,9 @@ static bool ath9k_hw_chip_reset(struct ath_hw *ah,
                        reset_type = ATH9K_RESET_POWER_ON;
                else
                        reset_type = ATH9K_RESET_COLD;
-       }
+       } else if (ah->chip_fullsleep || REG_READ(ah, AR_Q_TXE) ||
+                  (REG_READ(ah, AR_CR) & AR_CR_RXE))
+               reset_type = ATH9K_RESET_COLD;
 
        if (!ath9k_hw_set_reset_reg(ah, reset_type))
                return false;
index 94ef338..b775769 100644 (file)
@@ -151,7 +151,7 @@ int iwl_send_add_sta(struct iwl_priv *priv,
                       sta_id, sta->sta.addr, flags & CMD_ASYNC ?  "a" : "");
 
        if (!(flags & CMD_ASYNC)) {
-               cmd.flags |= CMD_WANT_SKB | CMD_WANT_HCMD;
+               cmd.flags |= CMD_WANT_SKB;
                might_sleep();
        }
 
index 9a0f45e..81aa91f 100644 (file)
@@ -349,25 +349,23 @@ TRACE_EVENT(iwlwifi_dev_rx_data,
 TRACE_EVENT(iwlwifi_dev_hcmd,
        TP_PROTO(const struct device *dev,
                 struct iwl_host_cmd *cmd, u16 total_size,
-                const void *hdr, size_t hdr_len),
-       TP_ARGS(dev, cmd, total_size, hdr, hdr_len),
+                struct iwl_cmd_header *hdr),
+       TP_ARGS(dev, cmd, total_size, hdr),
        TP_STRUCT__entry(
                DEV_ENTRY
                __dynamic_array(u8, hcmd, total_size)
                __field(u32, flags)
        ),
        TP_fast_assign(
-               int i, offset = hdr_len;
+               int i, offset = sizeof(*hdr);
 
                DEV_ASSIGN;
                __entry->flags = cmd->flags;
-               memcpy(__get_dynamic_array(hcmd), hdr, hdr_len);
+               memcpy(__get_dynamic_array(hcmd), hdr, sizeof(*hdr));
 
-               for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
+               for (i = 0; i < IWL_MAX_CMD_TBS_PER_TFD; i++) {
                        if (!cmd->len[i])
                                continue;
-                       if (!(cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY))
-                               continue;
                        memcpy((u8 *)__get_dynamic_array(hcmd) + offset,
                               cmd->data[i], cmd->len[i]);
                        offset += cmd->len[i];
index 6f228bb..fbfd2d1 100644 (file)
@@ -1102,7 +1102,6 @@ void iwl_drv_stop(struct iwl_drv *drv)
 
 /* shared module parameters */
 struct iwl_mod_params iwlwifi_mod_params = {
-       .amsdu_size_8K = 1,
        .restart_fw = 1,
        .plcp_check = true,
        .bt_coex_active = true,
@@ -1207,7 +1206,7 @@ MODULE_PARM_DESC(11n_disable,
        "disable 11n functionality, bitmap: 1: full, 2: agg TX, 4: agg RX");
 module_param_named(amsdu_size_8K, iwlwifi_mod_params.amsdu_size_8K,
                   int, S_IRUGO);
-MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size");
+MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size (default 0)");
 module_param_named(fw_restart, iwlwifi_mod_params.restart_fw, int, S_IRUGO);
 MODULE_PARM_DESC(fw_restart, "restart firmware in case of error");
 
index e5e3a79..2c2a729 100644 (file)
@@ -91,7 +91,7 @@ enum iwl_power_level {
  * @sw_crypto: using hardware encryption, default = 0
  * @disable_11n: disable 11n capabilities, default = 0,
  *     use IWL_DISABLE_HT_* constants
- * @amsdu_size_8K: enable 8K amsdu size, default = 1
+ * @amsdu_size_8K: enable 8K amsdu size, default = 0
  * @restart_fw: restart firmware, default = 1
  * @plcp_check: enable plcp health check, default = true
  * @wd_disable: enable stuck queue check, default = 0
index 14fc8d3..3392011 100644 (file)
@@ -136,12 +136,6 @@ struct iwl_calib_res_notif_phy_db {
        u8 data[];
 } __packed;
 
-#define IWL_PHY_DB_STATIC_PIC cpu_to_le32(0x21436587)
-static inline void iwl_phy_db_test_pic(__le32 pic)
-{
-       WARN_ON(IWL_PHY_DB_STATIC_PIC != pic);
-}
-
 struct iwl_phy_db *iwl_phy_db_init(struct iwl_trans *trans)
 {
        struct iwl_phy_db *phy_db = kzalloc(sizeof(struct iwl_phy_db),
@@ -260,11 +254,6 @@ int iwl_phy_db_set_section(struct iwl_phy_db *phy_db, struct iwl_rx_packet *pkt,
                        (size - CHANNEL_NUM_SIZE) / phy_db->channel_num;
        }
 
-       /* Test PIC */
-       if (type != IWL_PHY_DB_CFG)
-               iwl_phy_db_test_pic(*(((__le32 *)phy_db_notif->data) +
-                                     (size / sizeof(__le32)) - 1));
-
        IWL_DEBUG_INFO(phy_db->trans,
                       "%s(%d): [PHYDB]SET: Type %d , Size: %d\n",
                       __func__, __LINE__, type, size);
@@ -372,11 +361,6 @@ int iwl_phy_db_get_section_data(struct iwl_phy_db *phy_db,
                *size = entry->size;
        }
 
-       /* Test PIC */
-       if (type != IWL_PHY_DB_CFG)
-               iwl_phy_db_test_pic(*(((__le32 *)*data) +
-                                     (*size / sizeof(__le32)) - 1));
-
        IWL_DEBUG_INFO(phy_db->trans,
                       "%s(%d): [PHYDB] GET: Type %d , Size: %d\n",
                       __func__, __LINE__, type, *size);
index 8c7bec6..0cac2b7 100644 (file)
@@ -186,19 +186,13 @@ struct iwl_rx_packet {
  * @CMD_ASYNC: Return right away and don't want for the response
  * @CMD_WANT_SKB: valid only with CMD_SYNC. The caller needs the buffer of the
  *     response. The caller needs to call iwl_free_resp when done.
- * @CMD_WANT_HCMD: The caller needs to get the HCMD that was sent in the
- *     response handler. Chunks flagged by %IWL_HCMD_DFL_NOCOPY won't be
- *     copied. The pointer passed to the response handler is in the transport
- *     ownership and don't need to be freed by the op_mode. This also means
- *     that the pointer is invalidated after the op_mode's handler returns.
  * @CMD_ON_DEMAND: This command is sent by the test mode pipe.
  */
 enum CMD_MODE {
        CMD_SYNC                = 0,
        CMD_ASYNC               = BIT(0),
        CMD_WANT_SKB            = BIT(1),
-       CMD_WANT_HCMD           = BIT(2),
-       CMD_ON_DEMAND           = BIT(3),
+       CMD_ON_DEMAND           = BIT(2),
 };
 
 #define DEF_CMD_PAYLOAD_SIZE 320
@@ -217,7 +211,11 @@ struct iwl_device_cmd {
 
 #define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl_device_cmd))
 
-#define IWL_MAX_CMD_TFDS       2
+/*
+ * number of transfer buffers (fragments) per transmit frame descriptor;
+ * this is just the driver's idea, the hardware supports 20
+ */
+#define IWL_MAX_CMD_TBS_PER_TFD        2
 
 /**
  * struct iwl_hcmd_dataflag - flag for each one of the chunks of the command
@@ -254,15 +252,15 @@ enum iwl_hcmd_dataflag {
  * @id: id of the host command
  */
 struct iwl_host_cmd {
-       const void *data[IWL_MAX_CMD_TFDS];
+       const void *data[IWL_MAX_CMD_TBS_PER_TFD];
        struct iwl_rx_packet *resp_pkt;
        unsigned long _rx_page_addr;
        u32 _rx_page_order;
        int handler_status;
 
        u32 flags;
-       u16 len[IWL_MAX_CMD_TFDS];
-       u8 dataflags[IWL_MAX_CMD_TFDS];
+       u16 len[IWL_MAX_CMD_TBS_PER_TFD];
+       u8 dataflags[IWL_MAX_CMD_TBS_PER_TFD];
        u8 id;
 };
 
index c64d864..994c8c2 100644 (file)
@@ -61,6 +61,7 @@
  *
  *****************************************************************************/
 
+#include <linux/etherdevice.h>
 #include <net/cfg80211.h>
 #include <net/ipv6.h>
 #include "iwl-modparams.h"
@@ -192,6 +193,11 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw,
                                           sizeof(wkc), &wkc);
                data->error = ret != 0;
 
+               mvm->ptk_ivlen = key->iv_len;
+               mvm->ptk_icvlen = key->icv_len;
+               mvm->gtk_ivlen = key->iv_len;
+               mvm->gtk_icvlen = key->icv_len;
+
                /* don't upload key again */
                goto out_unlock;
        }
@@ -304,9 +310,13 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw,
         */
        if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) {
                key->hw_key_idx = 0;
+               mvm->ptk_ivlen = key->iv_len;
+               mvm->ptk_icvlen = key->icv_len;
        } else {
                data->gtk_key_idx++;
                key->hw_key_idx = data->gtk_key_idx;
+               mvm->gtk_ivlen = key->iv_len;
+               mvm->gtk_icvlen = key->icv_len;
        }
 
        ret = iwl_mvm_set_sta_key(mvm, vif, sta, key, true);
@@ -649,6 +659,11 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
        /* We reprogram keys and shouldn't allocate new key indices */
        memset(mvm->fw_key_table, 0, sizeof(mvm->fw_key_table));
 
+       mvm->ptk_ivlen = 0;
+       mvm->ptk_icvlen = 0;
+       mvm->ptk_ivlen = 0;
+       mvm->ptk_icvlen = 0;
+
        /*
         * The D3 firmware still hardcodes the AP station ID for the
         * BSS we're associated with as 0. As a result, we have to move
@@ -783,7 +798,6 @@ static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm,
        struct iwl_wowlan_status *status;
        u32 reasons;
        int ret, len;
-       bool pkt8023 = false;
        struct sk_buff *pkt = NULL;
 
        iwl_trans_read_mem_bytes(mvm->trans, base,
@@ -824,7 +838,8 @@ static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm,
        status = (void *)cmd.resp_pkt->data;
 
        if (len - sizeof(struct iwl_cmd_header) !=
-           sizeof(*status) + le32_to_cpu(status->wake_packet_bufsize)) {
+           sizeof(*status) +
+           ALIGN(le32_to_cpu(status->wake_packet_bufsize), 4)) {
                IWL_ERR(mvm, "Invalid WoWLAN status response!\n");
                goto out;
        }
@@ -836,61 +851,96 @@ static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm,
                goto report;
        }
 
-       if (reasons & IWL_WOWLAN_WAKEUP_BY_MAGIC_PACKET) {
+       if (reasons & IWL_WOWLAN_WAKEUP_BY_MAGIC_PACKET)
                wakeup.magic_pkt = true;
-               pkt8023 = true;
-       }
 
-       if (reasons & IWL_WOWLAN_WAKEUP_BY_PATTERN) {
+       if (reasons & IWL_WOWLAN_WAKEUP_BY_PATTERN)
                wakeup.pattern_idx =
                        le16_to_cpu(status->pattern_number);
-               pkt8023 = true;
-       }
 
        if (reasons & (IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_MISSED_BEACON |
                       IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_DEAUTH))
                wakeup.disconnect = true;
 
-       if (reasons & IWL_WOWLAN_WAKEUP_BY_GTK_REKEY_FAILURE) {
+       if (reasons & IWL_WOWLAN_WAKEUP_BY_GTK_REKEY_FAILURE)
                wakeup.gtk_rekey_failure = true;
-               pkt8023 = true;
-       }
 
-       if (reasons & IWL_WOWLAN_WAKEUP_BY_RFKILL_DEASSERTED) {
+       if (reasons & IWL_WOWLAN_WAKEUP_BY_RFKILL_DEASSERTED)
                wakeup.rfkill_release = true;
-               pkt8023 = true;
-       }
 
-       if (reasons & IWL_WOWLAN_WAKEUP_BY_EAPOL_REQUEST) {
+       if (reasons & IWL_WOWLAN_WAKEUP_BY_EAPOL_REQUEST)
                wakeup.eap_identity_req = true;
-               pkt8023 = true;
-       }
 
-       if (reasons & IWL_WOWLAN_WAKEUP_BY_FOUR_WAY_HANDSHAKE) {
+       if (reasons & IWL_WOWLAN_WAKEUP_BY_FOUR_WAY_HANDSHAKE)
                wakeup.four_way_handshake = true;
-               pkt8023 = true;
-       }
 
        if (status->wake_packet_bufsize) {
-               u32 pktsize = le32_to_cpu(status->wake_packet_bufsize);
-               u32 pktlen = le32_to_cpu(status->wake_packet_length);
+               int pktsize = le32_to_cpu(status->wake_packet_bufsize);
+               int pktlen = le32_to_cpu(status->wake_packet_length);
+               const u8 *pktdata = status->wake_packet;
+               struct ieee80211_hdr *hdr = (void *)pktdata;
+               int truncated = pktlen - pktsize;
+
+               /* this would be a firmware bug */
+               if (WARN_ON_ONCE(truncated < 0))
+                       truncated = 0;
+
+               if (ieee80211_is_data(hdr->frame_control)) {
+                       int hdrlen = ieee80211_hdrlen(hdr->frame_control);
+                       int ivlen = 0, icvlen = 4; /* also FCS */
 
-               if (pkt8023) {
                        pkt = alloc_skb(pktsize, GFP_KERNEL);
                        if (!pkt)
                                goto report;
-                       memcpy(skb_put(pkt, pktsize), status->wake_packet,
-                              pktsize);
+
+                       memcpy(skb_put(pkt, hdrlen), pktdata, hdrlen);
+                       pktdata += hdrlen;
+                       pktsize -= hdrlen;
+
+                       if (ieee80211_has_protected(hdr->frame_control)) {
+                               if (is_multicast_ether_addr(hdr->addr1)) {
+                                       ivlen = mvm->gtk_ivlen;
+                                       icvlen += mvm->gtk_icvlen;
+                               } else {
+                                       ivlen = mvm->ptk_ivlen;
+                                       icvlen += mvm->ptk_icvlen;
+                               }
+                       }
+
+                       /* if truncated, FCS/ICV is (partially) gone */
+                       if (truncated >= icvlen) {
+                               icvlen = 0;
+                               truncated -= icvlen;
+                       } else {
+                               icvlen -= truncated;
+                               truncated = 0;
+                       }
+
+                       pktsize -= ivlen + icvlen;
+                       pktdata += ivlen;
+
+                       memcpy(skb_put(pkt, pktsize), pktdata, pktsize);
+
                        if (ieee80211_data_to_8023(pkt, vif->addr, vif->type))
                                goto report;
                        wakeup.packet = pkt->data;
                        wakeup.packet_present_len = pkt->len;
-                       wakeup.packet_len = pkt->len - (pktlen - pktsize);
+                       wakeup.packet_len = pkt->len - truncated;
                        wakeup.packet_80211 = false;
                } else {
+                       int fcslen = 4;
+
+                       if (truncated >= 4) {
+                               truncated -= 4;
+                               fcslen = 0;
+                       } else {
+                               fcslen -= truncated;
+                               truncated = 0;
+                       }
+                       pktsize -= fcslen;
                        wakeup.packet = status->wake_packet;
                        wakeup.packet_present_len = pktsize;
-                       wakeup.packet_len = pktlen;
+                       wakeup.packet_len = pktlen - truncated;
                        wakeup.packet_80211 = true;
                }
        }
index 23eebda..2adb61f 100644 (file)
@@ -762,18 +762,20 @@ struct iwl_phy_context_cmd {
 #define IWL_RX_INFO_PHY_CNT 8
 #define IWL_RX_INFO_AGC_IDX 1
 #define IWL_RX_INFO_RSSI_AB_IDX 2
-#define IWL_RX_INFO_RSSI_C_IDX 3
-#define IWL_OFDM_AGC_DB_MSK 0xfe00
-#define IWL_OFDM_AGC_DB_POS 9
+#define IWL_OFDM_AGC_A_MSK 0x0000007f
+#define IWL_OFDM_AGC_A_POS 0
+#define IWL_OFDM_AGC_B_MSK 0x00003f80
+#define IWL_OFDM_AGC_B_POS 7
+#define IWL_OFDM_AGC_CODE_MSK 0x3fe00000
+#define IWL_OFDM_AGC_CODE_POS 20
 #define IWL_OFDM_RSSI_INBAND_A_MSK 0x00ff
-#define IWL_OFDM_RSSI_ALLBAND_A_MSK 0xff00
 #define IWL_OFDM_RSSI_A_POS 0
+#define IWL_OFDM_RSSI_ALLBAND_A_MSK 0xff00
+#define IWL_OFDM_RSSI_ALLBAND_A_POS 8
 #define IWL_OFDM_RSSI_INBAND_B_MSK 0xff0000
-#define IWL_OFDM_RSSI_ALLBAND_B_MSK 0xff000000
 #define IWL_OFDM_RSSI_B_POS 16
-#define IWL_OFDM_RSSI_INBAND_C_MSK 0x00ff
-#define IWL_OFDM_RSSI_ALLBAND_C_MSK 0xff00
-#define IWL_OFDM_RSSI_C_POS 0
+#define IWL_OFDM_RSSI_ALLBAND_B_MSK 0xff000000
+#define IWL_OFDM_RSSI_ALLBAND_B_POS 24
 
 /**
  * struct iwl_rx_phy_info - phy info
index d3d959d..500f818 100644 (file)
 #define UCODE_VALID_OK cpu_to_le32(0x1)
 
 /* Default calibration values for WkP - set to INIT image w/o running */
-static const u8 wkp_calib_values_bb_filter[] = { 0xbf, 0x00, 0x5f, 0x00, 0x2f,
-                                                0x00, 0x18, 0x00 };
-static const u8 wkp_calib_values_rx_dc[] = { 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
-                                            0x7f, 0x7f, 0x7f };
-static const u8 wkp_calib_values_tx_lo[] = { 0x00, 0x00, 0x00, 0x00 };
-static const u8 wkp_calib_values_tx_iq[] = { 0xff, 0x00, 0xff, 0x00, 0x00,
-                                            0x00 };
-static const u8 wkp_calib_values_rx_iq[] = { 0xff, 0x00, 0x00, 0x00 };
 static const u8 wkp_calib_values_rx_iq_skew[] = { 0x00, 0x00, 0x01, 0x00 };
 static const u8 wkp_calib_values_tx_iq_skew[] = { 0x01, 0x00, 0x00, 0x00 };
-static const u8 wkp_calib_values_xtal[] = { 0xd2, 0xd2 };
 
 struct iwl_calib_default_data {
        u16 size;
@@ -99,12 +90,7 @@ struct iwl_calib_default_data {
 #define CALIB_SIZE_N_DATA(_buf) {.size = sizeof(_buf), .data = &_buf}
 
 static const struct iwl_calib_default_data wkp_calib_default_data[12] = {
-       [5] = CALIB_SIZE_N_DATA(wkp_calib_values_rx_dc),
-       [6] = CALIB_SIZE_N_DATA(wkp_calib_values_bb_filter),
-       [7] = CALIB_SIZE_N_DATA(wkp_calib_values_tx_lo),
-       [8] = CALIB_SIZE_N_DATA(wkp_calib_values_tx_iq),
        [9] = CALIB_SIZE_N_DATA(wkp_calib_values_tx_iq_skew),
-       [10] = CALIB_SIZE_N_DATA(wkp_calib_values_rx_iq),
        [11] = CALIB_SIZE_N_DATA(wkp_calib_values_rx_iq_skew),
 };
 
@@ -241,20 +227,6 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
 
        return 0;
 }
-#define IWL_HW_REV_ID_RAINBOW  0x2
-#define IWL_PROJ_TYPE_LHP      0x5
-
-static u32 iwl_mvm_build_phy_cfg(struct iwl_mvm *mvm)
-{
-       struct iwl_nvm_data *data = mvm->nvm_data;
-       /* Temp calls to static definitions, will be changed to CSR calls */
-       u8 hw_rev_id = IWL_HW_REV_ID_RAINBOW;
-       u8 project_type = IWL_PROJ_TYPE_LHP;
-
-       return data->radio_cfg_dash | (data->radio_cfg_step << 2) |
-               (hw_rev_id << 4) | ((project_type & 0x7f) << 6) |
-               (data->valid_tx_ant << 16) | (data->valid_rx_ant << 20);
-}
 
 static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm)
 {
@@ -262,7 +234,7 @@ static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm)
        enum iwl_ucode_type ucode_type = mvm->cur_ucode;
 
        /* Set parameters */
-       phy_cfg_cmd.phy_cfg = cpu_to_le32(iwl_mvm_build_phy_cfg(mvm));
+       phy_cfg_cmd.phy_cfg = cpu_to_le32(mvm->fw->phy_config);
        phy_cfg_cmd.calib_control.event_trigger =
                mvm->fw->default_calib[ucode_type].event_trigger;
        phy_cfg_cmd.calib_control.flow_trigger =
@@ -275,103 +247,6 @@ static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm)
                                    sizeof(phy_cfg_cmd), &phy_cfg_cmd);
 }
 
-/* Starting with the new PHY DB implementation - New calibs are enabled */
-/* Value - 0x405e7 */
-#define IWL_CALIB_DEFAULT_FLOW_INIT    (IWL_CALIB_CFG_XTAL_IDX         |\
-                                        IWL_CALIB_CFG_TEMPERATURE_IDX  |\
-                                        IWL_CALIB_CFG_VOLTAGE_READ_IDX |\
-                                        IWL_CALIB_CFG_DC_IDX           |\
-                                        IWL_CALIB_CFG_BB_FILTER_IDX    |\
-                                        IWL_CALIB_CFG_LO_LEAKAGE_IDX   |\
-                                        IWL_CALIB_CFG_TX_IQ_IDX        |\
-                                        IWL_CALIB_CFG_RX_IQ_IDX        |\
-                                        IWL_CALIB_CFG_AGC_IDX)
-
-#define IWL_CALIB_DEFAULT_EVENT_INIT   0x0
-
-/* Value 0x41567 */
-#define IWL_CALIB_DEFAULT_FLOW_RUN     (IWL_CALIB_CFG_XTAL_IDX         |\
-                                        IWL_CALIB_CFG_TEMPERATURE_IDX  |\
-                                        IWL_CALIB_CFG_VOLTAGE_READ_IDX |\
-                                        IWL_CALIB_CFG_BB_FILTER_IDX    |\
-                                        IWL_CALIB_CFG_DC_IDX           |\
-                                        IWL_CALIB_CFG_TX_IQ_IDX        |\
-                                        IWL_CALIB_CFG_RX_IQ_IDX        |\
-                                        IWL_CALIB_CFG_SENSITIVITY_IDX  |\
-                                        IWL_CALIB_CFG_AGC_IDX)
-
-#define IWL_CALIB_DEFAULT_EVENT_RUN    (IWL_CALIB_CFG_XTAL_IDX         |\
-                                        IWL_CALIB_CFG_TEMPERATURE_IDX  |\
-                                        IWL_CALIB_CFG_VOLTAGE_READ_IDX |\
-                                        IWL_CALIB_CFG_TX_PWR_IDX       |\
-                                        IWL_CALIB_CFG_DC_IDX           |\
-                                        IWL_CALIB_CFG_TX_IQ_IDX        |\
-                                        IWL_CALIB_CFG_SENSITIVITY_IDX)
-
-/*
- * Sets the calibrations trigger values that will be sent to the FW for runtime
- * and init calibrations.
- * The ones given in the FW TLV are not correct.
- */
-static void iwl_set_default_calib_trigger(struct iwl_mvm *mvm)
-{
-       struct iwl_tlv_calib_ctrl default_calib;
-
-       /*
-        * WkP FW TLV calib bits are wrong, overwrite them.
-        * This defines the dynamic calibrations which are implemented in the
-        * uCode both for init(flow) calculation and event driven calibs.
-        */
-
-       /* Init Image */
-       default_calib.event_trigger = cpu_to_le32(IWL_CALIB_DEFAULT_EVENT_INIT);
-       default_calib.flow_trigger = cpu_to_le32(IWL_CALIB_DEFAULT_FLOW_INIT);
-
-       if (default_calib.event_trigger !=
-           mvm->fw->default_calib[IWL_UCODE_INIT].event_trigger)
-               IWL_ERR(mvm,
-                       "Updating the event calib for INIT image: 0x%x -> 0x%x\n",
-                       mvm->fw->default_calib[IWL_UCODE_INIT].event_trigger,
-                       default_calib.event_trigger);
-       if (default_calib.flow_trigger !=
-           mvm->fw->default_calib[IWL_UCODE_INIT].flow_trigger)
-               IWL_ERR(mvm,
-                       "Updating the flow calib for INIT image: 0x%x -> 0x%x\n",
-                       mvm->fw->default_calib[IWL_UCODE_INIT].flow_trigger,
-                       default_calib.flow_trigger);
-
-       memcpy((void *)&mvm->fw->default_calib[IWL_UCODE_INIT],
-              &default_calib, sizeof(struct iwl_tlv_calib_ctrl));
-       IWL_ERR(mvm,
-               "Setting uCode init calibrations event 0x%x, trigger 0x%x\n",
-               default_calib.event_trigger,
-               default_calib.flow_trigger);
-
-       /* Run time image */
-       default_calib.event_trigger = cpu_to_le32(IWL_CALIB_DEFAULT_EVENT_RUN);
-       default_calib.flow_trigger = cpu_to_le32(IWL_CALIB_DEFAULT_FLOW_RUN);
-
-       if (default_calib.event_trigger !=
-           mvm->fw->default_calib[IWL_UCODE_REGULAR].event_trigger)
-               IWL_ERR(mvm,
-                       "Updating the event calib for RT image: 0x%x -> 0x%x\n",
-                       mvm->fw->default_calib[IWL_UCODE_REGULAR].event_trigger,
-                       default_calib.event_trigger);
-       if (default_calib.flow_trigger !=
-           mvm->fw->default_calib[IWL_UCODE_REGULAR].flow_trigger)
-               IWL_ERR(mvm,
-                       "Updating the flow calib for RT image: 0x%x -> 0x%x\n",
-                       mvm->fw->default_calib[IWL_UCODE_REGULAR].flow_trigger,
-                       default_calib.flow_trigger);
-
-       memcpy((void *)&mvm->fw->default_calib[IWL_UCODE_REGULAR],
-              &default_calib, sizeof(struct iwl_tlv_calib_ctrl));
-       IWL_ERR(mvm,
-               "Setting uCode runtime calibs event 0x%x, trigger 0x%x\n",
-               default_calib.event_trigger,
-               default_calib.flow_trigger);
-}
-
 static int iwl_set_default_calibrations(struct iwl_mvm *mvm)
 {
        u8 cmd_raw[16]; /* holds the variable size commands */
@@ -446,8 +321,10 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
        ret = iwl_nvm_check_version(mvm->nvm_data, mvm->trans);
        WARN_ON(ret);
 
-       /* Override the calibrations from TLV and the const of fw */
-       iwl_set_default_calib_trigger(mvm);
+       /* Send TX valid antennas before triggering calibrations */
+       ret = iwl_send_tx_ant_cfg(mvm, mvm->nvm_data->valid_tx_ant);
+       if (ret)
+               goto error;
 
        /* WkP doesn't have all calibrations, need to set default values */
        if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) {
index e8264e1..7e169b0 100644 (file)
@@ -557,11 +557,9 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
        return ret;
 }
 
-static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw,
-                                        struct ieee80211_vif *vif)
+static void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm,
+                                       struct ieee80211_vif *vif)
 {
-       struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
-       struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
        u32 tfd_msk = 0, ac;
 
        for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
@@ -594,12 +592,21 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw,
                 */
                flush_work(&mvm->sta_drained_wk);
        }
+}
+
+static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw,
+                                        struct ieee80211_vif *vif)
+{
+       struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+       struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+
+       iwl_mvm_prepare_mac_removal(mvm, vif);
 
        mutex_lock(&mvm->mutex);
 
        /*
         * For AP/GO interface, the tear down of the resources allocated to the
-        * interface should be handled as part of the bss_info_changed flow.
+        * interface is be handled as part of the stop_ap flow.
         */
        if (vif->type == NL80211_IFTYPE_AP) {
                iwl_mvm_dealloc_int_sta(mvm, &mvmvif->bcast_sta);
@@ -763,6 +770,8 @@ static void iwl_mvm_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
        struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
        struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 
+       iwl_mvm_prepare_mac_removal(mvm, vif);
+
        mutex_lock(&mvm->mutex);
 
        mvmvif->ap_active = false;
index 4e339cc..bdae700 100644 (file)
@@ -80,7 +80,8 @@
 
 #define IWL_INVALID_MAC80211_QUEUE     0xff
 #define IWL_MVM_MAX_ADDRESSES          2
-#define IWL_RSSI_OFFSET 44
+/* RSSI offset for WkP */
+#define IWL_RSSI_OFFSET 50
 
 enum iwl_mvm_tx_fifo {
        IWL_MVM_TX_FIFO_BK = 0,
@@ -327,6 +328,10 @@ struct iwl_mvm {
        struct led_classdev led;
 
        struct ieee80211_vif *p2p_device_vif;
+
+#ifdef CONFIG_PM_SLEEP
+       int gtk_ivlen, gtk_icvlen, ptk_ivlen, ptk_icvlen;
+#endif
 };
 
 /* Extract MVM priv from op_mode and _hw */
index aa59adf..d0f9c1e 100644 (file)
@@ -624,12 +624,8 @@ static void iwl_mvm_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb)
        ieee80211_free_txskb(mvm->hw, skb);
 }
 
-static void iwl_mvm_nic_error(struct iwl_op_mode *op_mode)
+static void iwl_mvm_nic_restart(struct iwl_mvm *mvm)
 {
-       struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
-
-       iwl_mvm_dump_nic_error_log(mvm);
-
        iwl_abort_notification_waits(&mvm->notif_wait);
 
        /*
@@ -663,9 +659,21 @@ static void iwl_mvm_nic_error(struct iwl_op_mode *op_mode)
        }
 }
 
+static void iwl_mvm_nic_error(struct iwl_op_mode *op_mode)
+{
+       struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
+
+       iwl_mvm_dump_nic_error_log(mvm);
+
+       iwl_mvm_nic_restart(mvm);
+}
+
 static void iwl_mvm_cmd_queue_full(struct iwl_op_mode *op_mode)
 {
+       struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
+
        WARN_ON(1);
+       iwl_mvm_nic_restart(mvm);
 }
 
 static const struct iwl_op_mode_ops iwl_mvm_ops = {
index 3f40ab0..b0b190d 100644 (file)
@@ -131,33 +131,42 @@ static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm,
 static int iwl_mvm_calc_rssi(struct iwl_mvm *mvm,
                             struct iwl_rx_phy_info *phy_info)
 {
-       u32 rssi_a, rssi_b, rssi_c, max_rssi, agc_db;
+       int rssi_a, rssi_b, rssi_a_dbm, rssi_b_dbm, max_rssi_dbm;
+       int rssi_all_band_a, rssi_all_band_b;
+       u32 agc_a, agc_b, max_agc;
        u32 val;
 
-       /* Find max rssi among 3 possible receivers.
+       /* Find max rssi among 2 possible receivers.
         * These values are measured by the Digital Signal Processor (DSP).
         * They should stay fairly constant even as the signal strength varies,
         * if the radio's Automatic Gain Control (AGC) is working right.
         * AGC value (see below) will provide the "interesting" info.
         */
+       val = le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_AGC_IDX]);
+       agc_a = (val & IWL_OFDM_AGC_A_MSK) >> IWL_OFDM_AGC_A_POS;
+       agc_b = (val & IWL_OFDM_AGC_B_MSK) >> IWL_OFDM_AGC_B_POS;
+       max_agc = max_t(u32, agc_a, agc_b);
+
        val = le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_RSSI_AB_IDX]);
        rssi_a = (val & IWL_OFDM_RSSI_INBAND_A_MSK) >> IWL_OFDM_RSSI_A_POS;
        rssi_b = (val & IWL_OFDM_RSSI_INBAND_B_MSK) >> IWL_OFDM_RSSI_B_POS;
-       val = le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_RSSI_C_IDX]);
-       rssi_c = (val & IWL_OFDM_RSSI_INBAND_C_MSK) >> IWL_OFDM_RSSI_C_POS;
-
-       val = le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_AGC_IDX]);
-       agc_db = (val & IWL_OFDM_AGC_DB_MSK) >> IWL_OFDM_AGC_DB_POS;
+       rssi_all_band_a = (val & IWL_OFDM_RSSI_ALLBAND_A_MSK) >>
+                               IWL_OFDM_RSSI_ALLBAND_A_POS;
+       rssi_all_band_b = (val & IWL_OFDM_RSSI_ALLBAND_B_MSK) >>
+                               IWL_OFDM_RSSI_ALLBAND_B_POS;
 
-       max_rssi = max_t(u32, rssi_a, rssi_b);
-       max_rssi = max_t(u32, max_rssi, rssi_c);
+       /*
+        * dBm = rssi dB - agc dB - constant.
+        * Higher AGC (higher radio gain) means lower signal.
+        */
+       rssi_a_dbm = rssi_a - IWL_RSSI_OFFSET - agc_a;
+       rssi_b_dbm = rssi_b - IWL_RSSI_OFFSET - agc_b;
+       max_rssi_dbm = max_t(int, rssi_a_dbm, rssi_b_dbm);
 
-       IWL_DEBUG_STATS(mvm, "Rssi In A %d B %d C %d Max %d AGC dB %d\n",
-                       rssi_a, rssi_b, rssi_c, max_rssi, agc_db);
+       IWL_DEBUG_STATS(mvm, "Rssi In A %d B %d Max %d AGCA %d AGCB %d\n",
+                       rssi_a_dbm, rssi_b_dbm, max_rssi_dbm, agc_a, agc_b);
 
-       /* dBm = max_rssi dB - agc dB - constant.
-        * Higher AGC (higher radio gain) means lower signal. */
-       return max_rssi - agc_db - IWL_RSSI_OFFSET;
+       return max_rssi_dbm;
 }
 
 /*
index 861a7f9..274f44e 100644 (file)
@@ -770,6 +770,16 @@ int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
        u16 txq_id;
        int err;
 
+
+       /*
+        * If mac80211 is cleaning its state, then say that we finished since
+        * our state has been cleared anyway.
+        */
+       if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
+               ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+               return 0;
+       }
+
        spin_lock_bh(&mvmsta->lock);
 
        txq_id = tid_data->txq_id;
index 6b67ce3..6645efe 100644 (file)
@@ -607,12 +607,8 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
 
                /* Single frame failure in an AMPDU queue => send BAR */
                if (txq_id >= IWL_FIRST_AMPDU_QUEUE &&
-                   !(info->flags & IEEE80211_TX_STAT_ACK)) {
-                       /* there must be only one skb in the skb_list */
-                       WARN_ON_ONCE(skb_freed > 1 ||
-                                    !skb_queue_empty(&skbs));
+                   !(info->flags & IEEE80211_TX_STAT_ACK))
                        info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
-               }
 
                /* W/A FW bug: seq_ctl is wrong when the queue is flushed */
                if (status == TX_STATUS_FAIL_FIFO_FLUSHED) {
index aa2a39a..148843e 100644 (file)
@@ -137,10 +137,6 @@ static inline int iwl_queue_dec_wrap(int index, int n_bd)
 struct iwl_cmd_meta {
        /* only for SYNC commands, iff the reply skb is wanted */
        struct iwl_host_cmd *source;
-
-       DEFINE_DMA_UNMAP_ADDR(mapping);
-       DEFINE_DMA_UNMAP_LEN(len);
-
        u32 flags;
 };
 
@@ -182,19 +178,39 @@ struct iwl_queue {
 #define TFD_TX_CMD_SLOTS 256
 #define TFD_CMD_SLOTS 32
 
+/*
+ * The FH will write back to the first TB only, so we need
+ * to copy some data into the buffer regardless of whether
+ * it should be mapped or not. This indicates how big the
+ * first TB must be to include the scratch buffer. Since
+ * the scratch is 4 bytes at offset 12, it's 16 now. If we
+ * make it bigger then allocations will be bigger and copy
+ * slower, so that's probably not useful.
+ */
+#define IWL_HCMD_SCRATCHBUF_SIZE       16
+
 struct iwl_pcie_txq_entry {
        struct iwl_device_cmd *cmd;
-       struct iwl_device_cmd *copy_cmd;
        struct sk_buff *skb;
        /* buffer to free after command completes */
        const void *free_buf;
        struct iwl_cmd_meta meta;
 };
 
+struct iwl_pcie_txq_scratch_buf {
+       struct iwl_cmd_header hdr;
+       u8 buf[8];
+       __le32 scratch;
+};
+
 /**
  * struct iwl_txq - Tx Queue for DMA
  * @q: generic Rx/Tx queue descriptor
  * @tfds: transmit frame descriptors (DMA memory)
+ * @scratchbufs: start of command headers, including scratch buffers, for
+ *     the writeback -- this is DMA memory and an array holding one buffer
+ *     for each command on the queue
+ * @scratchbufs_dma: DMA address for the scratchbufs start
  * @entries: transmit entries (driver state)
  * @lock: queue lock
  * @stuck_timer: timer that fires if queue gets stuck
@@ -208,6 +224,8 @@ struct iwl_pcie_txq_entry {
 struct iwl_txq {
        struct iwl_queue q;
        struct iwl_tfd *tfds;
+       struct iwl_pcie_txq_scratch_buf *scratchbufs;
+       dma_addr_t scratchbufs_dma;
        struct iwl_pcie_txq_entry *entries;
        spinlock_t lock;
        struct timer_list stuck_timer;
@@ -216,6 +234,13 @@ struct iwl_txq {
        u8 active;
 };
 
+static inline dma_addr_t
+iwl_pcie_get_scratchbuf_dma(struct iwl_txq *txq, int idx)
+{
+       return txq->scratchbufs_dma +
+              sizeof(struct iwl_pcie_txq_scratch_buf) * idx;
+}
+
 /**
  * struct iwl_trans_pcie - PCIe transport specific data
  * @rxq: all the RX queue data
index b0ae06d..567e67a 100644 (file)
@@ -637,22 +637,14 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans,
                index = SEQ_TO_INDEX(sequence);
                cmd_index = get_cmd_index(&txq->q, index);
 
-               if (reclaim) {
-                       struct iwl_pcie_txq_entry *ent;
-                       ent = &txq->entries[cmd_index];
-                       cmd = ent->copy_cmd;
-                       WARN_ON_ONCE(!cmd && ent->meta.flags & CMD_WANT_HCMD);
-               } else {
+               if (reclaim)
+                       cmd = txq->entries[cmd_index].cmd;
+               else
                        cmd = NULL;
-               }
 
                err = iwl_op_mode_rx(trans->op_mode, &rxcb, cmd);
 
                if (reclaim) {
-                       /* The original command isn't needed any more */
-                       kfree(txq->entries[cmd_index].copy_cmd);
-                       txq->entries[cmd_index].copy_cmd = NULL;
-                       /* nor is the duplicated part of the command */
                        kfree(txq->entries[cmd_index].free_buf);
                        txq->entries[cmd_index].free_buf = NULL;
                }
index 8e9e321..8595c16 100644 (file)
@@ -191,12 +191,9 @@ static void iwl_pcie_txq_stuck_timer(unsigned long data)
        }
 
        for (i = q->read_ptr; i != q->write_ptr;
-            i = iwl_queue_inc_wrap(i, q->n_bd)) {
-               struct iwl_tx_cmd *tx_cmd =
-                       (struct iwl_tx_cmd *)txq->entries[i].cmd->payload;
+            i = iwl_queue_inc_wrap(i, q->n_bd))
                IWL_ERR(trans, "scratch %d = 0x%08x\n", i,
-                       get_unaligned_le32(&tx_cmd->scratch));
-       }
+                       le32_to_cpu(txq->scratchbufs[i].scratch));
 
        iwl_op_mode_nic_error(trans->op_mode);
 }
@@ -367,8 +364,8 @@ static inline u8 iwl_pcie_tfd_get_num_tbs(struct iwl_tfd *tfd)
 }
 
 static void iwl_pcie_tfd_unmap(struct iwl_trans *trans,
-                              struct iwl_cmd_meta *meta, struct iwl_tfd *tfd,
-                              enum dma_data_direction dma_dir)
+                              struct iwl_cmd_meta *meta,
+                              struct iwl_tfd *tfd)
 {
        int i;
        int num_tbs;
@@ -382,17 +379,12 @@ static void iwl_pcie_tfd_unmap(struct iwl_trans *trans,
                return;
        }
 
-       /* Unmap tx_cmd */
-       if (num_tbs)
-               dma_unmap_single(trans->dev,
-                               dma_unmap_addr(meta, mapping),
-                               dma_unmap_len(meta, len),
-                               DMA_BIDIRECTIONAL);
+       /* first TB is never freed - it's the scratchbuf data */
 
-       /* Unmap chunks, if any. */
        for (i = 1; i < num_tbs; i++)
                dma_unmap_single(trans->dev, iwl_pcie_tfd_tb_get_addr(tfd, i),
-                                iwl_pcie_tfd_tb_get_len(tfd, i), dma_dir);
+                                iwl_pcie_tfd_tb_get_len(tfd, i),
+                                DMA_TO_DEVICE);
 
        tfd->num_tbs = 0;
 }
@@ -406,8 +398,7 @@ static void iwl_pcie_tfd_unmap(struct iwl_trans *trans,
  * Does NOT advance any TFD circular buffer read/write indexes
  * Does NOT free the TFD itself (which is within circular buffer)
  */
-static void iwl_pcie_txq_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq,
-                                 enum dma_data_direction dma_dir)
+static void iwl_pcie_txq_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq)
 {
        struct iwl_tfd *tfd_tmp = txq->tfds;
 
@@ -418,8 +409,7 @@ static void iwl_pcie_txq_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq,
        lockdep_assert_held(&txq->lock);
 
        /* We have only q->n_window txq->entries, but we use q->n_bd tfds */
-       iwl_pcie_tfd_unmap(trans, &txq->entries[idx].meta, &tfd_tmp[rd_ptr],
-                          dma_dir);
+       iwl_pcie_tfd_unmap(trans, &txq->entries[idx].meta, &tfd_tmp[rd_ptr]);
 
        /* free SKB */
        if (txq->entries) {
@@ -479,6 +469,7 @@ static int iwl_pcie_txq_alloc(struct iwl_trans *trans,
 {
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
        size_t tfd_sz = sizeof(struct iwl_tfd) * TFD_QUEUE_SIZE_MAX;
+       size_t scratchbuf_sz;
        int i;
 
        if (WARN_ON(txq->entries || txq->tfds))
@@ -514,9 +505,25 @@ static int iwl_pcie_txq_alloc(struct iwl_trans *trans,
                IWL_ERR(trans, "dma_alloc_coherent(%zd) failed\n", tfd_sz);
                goto error;
        }
+
+       BUILD_BUG_ON(IWL_HCMD_SCRATCHBUF_SIZE != sizeof(*txq->scratchbufs));
+       BUILD_BUG_ON(offsetof(struct iwl_pcie_txq_scratch_buf, scratch) !=
+                       sizeof(struct iwl_cmd_header) +
+                       offsetof(struct iwl_tx_cmd, scratch));
+
+       scratchbuf_sz = sizeof(*txq->scratchbufs) * slots_num;
+
+       txq->scratchbufs = dma_alloc_coherent(trans->dev, scratchbuf_sz,
+                                             &txq->scratchbufs_dma,
+                                             GFP_KERNEL);
+       if (!txq->scratchbufs)
+               goto err_free_tfds;
+
        txq->q.id = txq_id;
 
        return 0;
+err_free_tfds:
+       dma_free_coherent(trans->dev, tfd_sz, txq->tfds, txq->q.dma_addr);
 error:
        if (txq->entries && txq_id == trans_pcie->cmd_queue)
                for (i = 0; i < slots_num; i++)
@@ -565,22 +572,13 @@ static void iwl_pcie_txq_unmap(struct iwl_trans *trans, int txq_id)
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
        struct iwl_txq *txq = &trans_pcie->txq[txq_id];
        struct iwl_queue *q = &txq->q;
-       enum dma_data_direction dma_dir;
 
        if (!q->n_bd)
                return;
 
-       /* In the command queue, all the TBs are mapped as BIDI
-        * so unmap them as such.
-        */
-       if (txq_id == trans_pcie->cmd_queue)
-               dma_dir = DMA_BIDIRECTIONAL;
-       else
-               dma_dir = DMA_TO_DEVICE;
-
        spin_lock_bh(&txq->lock);
        while (q->write_ptr != q->read_ptr) {
-               iwl_pcie_txq_free_tfd(trans, txq, dma_dir);
+               iwl_pcie_txq_free_tfd(trans, txq);
                q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd);
        }
        spin_unlock_bh(&txq->lock);
@@ -610,7 +608,6 @@ static void iwl_pcie_txq_free(struct iwl_trans *trans, int txq_id)
        if (txq_id == trans_pcie->cmd_queue)
                for (i = 0; i < txq->q.n_window; i++) {
                        kfree(txq->entries[i].cmd);
-                       kfree(txq->entries[i].copy_cmd);
                        kfree(txq->entries[i].free_buf);
                }
 
@@ -619,6 +616,10 @@ static void iwl_pcie_txq_free(struct iwl_trans *trans, int txq_id)
                dma_free_coherent(dev, sizeof(struct iwl_tfd) *
                                  txq->q.n_bd, txq->tfds, txq->q.dma_addr);
                txq->q.dma_addr = 0;
+
+               dma_free_coherent(dev,
+                                 sizeof(*txq->scratchbufs) * txq->q.n_window,
+                                 txq->scratchbufs, txq->scratchbufs_dma);
        }
 
        kfree(txq->entries);
@@ -962,7 +963,7 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
 
                iwl_pcie_txq_inval_byte_cnt_tbl(trans, txq);
 
-               iwl_pcie_txq_free_tfd(trans, txq, DMA_TO_DEVICE);
+               iwl_pcie_txq_free_tfd(trans, txq);
        }
 
        iwl_pcie_txq_progress(trans_pcie, txq);
@@ -1152,20 +1153,37 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
        void *dup_buf = NULL;
        dma_addr_t phys_addr;
        int idx;
-       u16 copy_size, cmd_size;
+       u16 copy_size, cmd_size, scratch_size;
        bool had_nocopy = false;
        int i;
        u32 cmd_pos;
+       const u8 *cmddata[IWL_MAX_CMD_TBS_PER_TFD];
+       u16 cmdlen[IWL_MAX_CMD_TBS_PER_TFD];
 
        copy_size = sizeof(out_cmd->hdr);
        cmd_size = sizeof(out_cmd->hdr);
 
        /* need one for the header if the first is NOCOPY */
-       BUILD_BUG_ON(IWL_MAX_CMD_TFDS > IWL_NUM_OF_TBS - 1);
+       BUILD_BUG_ON(IWL_MAX_CMD_TBS_PER_TFD > IWL_NUM_OF_TBS - 1);
+
+       for (i = 0; i < IWL_MAX_CMD_TBS_PER_TFD; i++) {
+               cmddata[i] = cmd->data[i];
+               cmdlen[i] = cmd->len[i];
 
-       for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
                if (!cmd->len[i])
                        continue;
+
+               /* need at least IWL_HCMD_SCRATCHBUF_SIZE copied */
+               if (copy_size < IWL_HCMD_SCRATCHBUF_SIZE) {
+                       int copy = IWL_HCMD_SCRATCHBUF_SIZE - copy_size;
+
+                       if (copy > cmdlen[i])
+                               copy = cmdlen[i];
+                       cmdlen[i] -= copy;
+                       cmddata[i] += copy;
+                       copy_size += copy;
+               }
+
                if (cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY) {
                        had_nocopy = true;
                        if (WARN_ON(cmd->dataflags[i] & IWL_HCMD_DFL_DUP)) {
@@ -1185,7 +1203,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
                                goto free_dup_buf;
                        }
 
-                       dup_buf = kmemdup(cmd->data[i], cmd->len[i],
+                       dup_buf = kmemdup(cmddata[i], cmdlen[i],
                                          GFP_ATOMIC);
                        if (!dup_buf)
                                return -ENOMEM;
@@ -1195,7 +1213,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
                                idx = -EINVAL;
                                goto free_dup_buf;
                        }
-                       copy_size += cmd->len[i];
+                       copy_size += cmdlen[i];
                }
                cmd_size += cmd->len[i];
        }
@@ -1242,30 +1260,30 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
 
        /* and copy the data that needs to be copied */
        cmd_pos = offsetof(struct iwl_device_cmd, payload);
-       for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
-               if (!cmd->len[i])
+       copy_size = sizeof(out_cmd->hdr);
+       for (i = 0; i < IWL_MAX_CMD_TBS_PER_TFD; i++) {
+               int copy = 0;
+
+               if (!cmd->len)
                        continue;
-               if (cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY |
-                                        IWL_HCMD_DFL_DUP))
-                       break;
-               memcpy((u8 *)out_cmd + cmd_pos, cmd->data[i], cmd->len[i]);
-               cmd_pos += cmd->len[i];
-       }
 
-       WARN_ON_ONCE(txq->entries[idx].copy_cmd);
+               /* need at least IWL_HCMD_SCRATCHBUF_SIZE copied */
+               if (copy_size < IWL_HCMD_SCRATCHBUF_SIZE) {
+                       copy = IWL_HCMD_SCRATCHBUF_SIZE - copy_size;
 
-       /*
-        * since out_cmd will be the source address of the FH, it will write
-        * the retry count there. So when the user needs to receivce the HCMD
-        * that corresponds to the response in the response handler, it needs
-        * to set CMD_WANT_HCMD.
-        */
-       if (cmd->flags & CMD_WANT_HCMD) {
-               txq->entries[idx].copy_cmd =
-                       kmemdup(out_cmd, cmd_pos, GFP_ATOMIC);
-               if (unlikely(!txq->entries[idx].copy_cmd)) {
-                       idx = -ENOMEM;
-                       goto out;
+                       if (copy > cmd->len[i])
+                               copy = cmd->len[i];
+               }
+
+               /* copy everything if not nocopy/dup */
+               if (!(cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY |
+                                          IWL_HCMD_DFL_DUP)))
+                       copy = cmd->len[i];
+
+               if (copy) {
+                       memcpy((u8 *)out_cmd + cmd_pos, cmd->data[i], copy);
+                       cmd_pos += copy;
+                       copy_size += copy;
                }
        }
 
@@ -1275,22 +1293,35 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
                     out_cmd->hdr.cmd, le16_to_cpu(out_cmd->hdr.sequence),
                     cmd_size, q->write_ptr, idx, trans_pcie->cmd_queue);
 
-       phys_addr = dma_map_single(trans->dev, &out_cmd->hdr, copy_size,
-                                  DMA_BIDIRECTIONAL);
-       if (unlikely(dma_mapping_error(trans->dev, phys_addr))) {
-               idx = -ENOMEM;
-               goto out;
-       }
-
-       dma_unmap_addr_set(out_meta, mapping, phys_addr);
-       dma_unmap_len_set(out_meta, len, copy_size);
+       /* start the TFD with the scratchbuf */
+       scratch_size = min_t(int, copy_size, IWL_HCMD_SCRATCHBUF_SIZE);
+       memcpy(&txq->scratchbufs[q->write_ptr], &out_cmd->hdr, scratch_size);
+       iwl_pcie_txq_build_tfd(trans, txq,
+                              iwl_pcie_get_scratchbuf_dma(txq, q->write_ptr),
+                              scratch_size, 1);
+
+       /* map first command fragment, if any remains */
+       if (copy_size > scratch_size) {
+               phys_addr = dma_map_single(trans->dev,
+                                          ((u8 *)&out_cmd->hdr) + scratch_size,
+                                          copy_size - scratch_size,
+                                          DMA_TO_DEVICE);
+               if (dma_mapping_error(trans->dev, phys_addr)) {
+                       iwl_pcie_tfd_unmap(trans, out_meta,
+                                          &txq->tfds[q->write_ptr]);
+                       idx = -ENOMEM;
+                       goto out;
+               }
 
-       iwl_pcie_txq_build_tfd(trans, txq, phys_addr, copy_size, 1);
+               iwl_pcie_txq_build_tfd(trans, txq, phys_addr,
+                                      copy_size - scratch_size, 0);
+       }
 
-       for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
-               const void *data = cmd->data[i];
+       /* map the remaining (adjusted) nocopy/dup fragments */
+       for (i = 0; i < IWL_MAX_CMD_TBS_PER_TFD; i++) {
+               const void *data = cmddata[i];
 
-               if (!cmd->len[i])
+               if (!cmdlen[i])
                        continue;
                if (!(cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY |
                                           IWL_HCMD_DFL_DUP)))
@@ -1298,16 +1329,15 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
                if (cmd->dataflags[i] & IWL_HCMD_DFL_DUP)
                        data = dup_buf;
                phys_addr = dma_map_single(trans->dev, (void *)data,
-                                          cmd->len[i], DMA_BIDIRECTIONAL);
+                                          cmdlen[i], DMA_TO_DEVICE);
                if (dma_mapping_error(trans->dev, phys_addr)) {
                        iwl_pcie_tfd_unmap(trans, out_meta,
-                                          &txq->tfds[q->write_ptr],
-                                          DMA_BIDIRECTIONAL);
+                                          &txq->tfds[q->write_ptr]);
                        idx = -ENOMEM;
                        goto out;
                }
 
-               iwl_pcie_txq_build_tfd(trans, txq, phys_addr, cmd->len[i], 0);
+               iwl_pcie_txq_build_tfd(trans, txq, phys_addr, cmdlen[i], 0);
        }
 
        out_meta->flags = cmd->flags;
@@ -1317,8 +1347,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
 
        txq->need_update = 1;
 
-       trace_iwlwifi_dev_hcmd(trans->dev, cmd, cmd_size,
-                              &out_cmd->hdr, copy_size);
+       trace_iwlwifi_dev_hcmd(trans->dev, cmd, cmd_size, &out_cmd->hdr);
 
        /* start timer if queue currently empty */
        if (q->read_ptr == q->write_ptr && trans_pcie->wd_timeout)
@@ -1377,7 +1406,7 @@ void iwl_pcie_hcmd_complete(struct iwl_trans *trans,
        cmd = txq->entries[cmd_index].cmd;
        meta = &txq->entries[cmd_index].meta;
 
-       iwl_pcie_tfd_unmap(trans, meta, &txq->tfds[index], DMA_BIDIRECTIONAL);
+       iwl_pcie_tfd_unmap(trans, meta, &txq->tfds[index]);
 
        /* Input error checking is done when commands are added to queue. */
        if (meta->flags & CMD_WANT_SKB) {
@@ -1556,10 +1585,9 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
        struct iwl_cmd_meta *out_meta;
        struct iwl_txq *txq;
        struct iwl_queue *q;
-       dma_addr_t phys_addr = 0;
-       dma_addr_t txcmd_phys;
-       dma_addr_t scratch_phys;
-       u16 len, firstlen, secondlen;
+       dma_addr_t tb0_phys, tb1_phys, scratch_phys;
+       void *tb1_addr;
+       u16 len, tb1_len, tb2_len;
        u8 wait_write_ptr = 0;
        __le16 fc = hdr->frame_control;
        u8 hdr_len = ieee80211_hdrlen(fc);
@@ -1597,85 +1625,80 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
                cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) |
                            INDEX_TO_SEQ(q->write_ptr)));
 
+       tb0_phys = iwl_pcie_get_scratchbuf_dma(txq, q->write_ptr);
+       scratch_phys = tb0_phys + sizeof(struct iwl_cmd_header) +
+                      offsetof(struct iwl_tx_cmd, scratch);
+
+       tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys);
+       tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys);
+
        /* Set up first empty entry in queue's array of Tx/cmd buffers */
        out_meta = &txq->entries[q->write_ptr].meta;
 
        /*
-        * Use the first empty entry in this queue's command buffer array
-        * to contain the Tx command and MAC header concatenated together
-        * (payload data will be in another buffer).
-        * Size of this varies, due to varying MAC header length.
-        * If end is not dword aligned, we'll have 2 extra bytes at the end
-        * of the MAC header (device reads on dword boundaries).
-        * We'll tell device about this padding later.
+        * The second TB (tb1) points to the remainder of the TX command
+        * and the 802.11 header - dword aligned size
+        * (This calculation modifies the TX command, so do it before the
+        * setup of the first TB)
         */
-       len = sizeof(struct iwl_tx_cmd) +
-               sizeof(struct iwl_cmd_header) + hdr_len;
-       firstlen = (len + 3) & ~3;
+       len = sizeof(struct iwl_tx_cmd) + sizeof(struct iwl_cmd_header) +
+             hdr_len - IWL_HCMD_SCRATCHBUF_SIZE;
+       tb1_len = (len + 3) & ~3;
 
        /* Tell NIC about any 2-byte padding after MAC header */
-       if (firstlen != len)
+       if (tb1_len != len)
                tx_cmd->tx_flags |= TX_CMD_FLG_MH_PAD_MSK;
 
-       /* Physical address of this Tx command's header (not MAC header!),
-        * within command buffer array. */
-       txcmd_phys = dma_map_single(trans->dev,
-                                   &dev_cmd->hdr, firstlen,
-                                   DMA_BIDIRECTIONAL);
-       if (unlikely(dma_mapping_error(trans->dev, txcmd_phys)))
-               goto out_err;
-       dma_unmap_addr_set(out_meta, mapping, txcmd_phys);
-       dma_unmap_len_set(out_meta, len, firstlen);
+       /* The first TB points to the scratchbuf data - min_copy bytes */
+       memcpy(&txq->scratchbufs[q->write_ptr], &dev_cmd->hdr,
+              IWL_HCMD_SCRATCHBUF_SIZE);
+       iwl_pcie_txq_build_tfd(trans, txq, tb0_phys,
+                              IWL_HCMD_SCRATCHBUF_SIZE, 1);
 
-       if (!ieee80211_has_morefrags(fc)) {
-               txq->need_update = 1;
-       } else {
-               wait_write_ptr = 1;
-               txq->need_update = 0;
-       }
+       /* there must be data left over for TB1 or this code must be changed */
+       BUILD_BUG_ON(sizeof(struct iwl_tx_cmd) < IWL_HCMD_SCRATCHBUF_SIZE);
+
+       /* map the data for TB1 */
+       tb1_addr = ((u8 *)&dev_cmd->hdr) + IWL_HCMD_SCRATCHBUF_SIZE;
+       tb1_phys = dma_map_single(trans->dev, tb1_addr, tb1_len, DMA_TO_DEVICE);
+       if (unlikely(dma_mapping_error(trans->dev, tb1_phys)))
+               goto out_err;
+       iwl_pcie_txq_build_tfd(trans, txq, tb1_phys, tb1_len, 0);
 
-       /* Set up TFD's 2nd entry to point directly to remainder of skb,
-        * if any (802.11 null frames have no payload). */
-       secondlen = skb->len - hdr_len;
-       if (secondlen > 0) {
-               phys_addr = dma_map_single(trans->dev, skb->data + hdr_len,
-                                          secondlen, DMA_TO_DEVICE);
-               if (unlikely(dma_mapping_error(trans->dev, phys_addr))) {
-                       dma_unmap_single(trans->dev,
-                                        dma_unmap_addr(out_meta, mapping),
-                                        dma_unmap_len(out_meta, len),
-                                        DMA_BIDIRECTIONAL);
+       /*
+        * Set up TFD's third entry to point directly to remainder
+        * of skb, if any (802.11 null frames have no payload).
+        */
+       tb2_len = skb->len - hdr_len;
+       if (tb2_len > 0) {
+               dma_addr_t tb2_phys = dma_map_single(trans->dev,
+                                                    skb->data + hdr_len,
+                                                    tb2_len, DMA_TO_DEVICE);
+               if (unlikely(dma_mapping_error(trans->dev, tb2_phys))) {
+                       iwl_pcie_tfd_unmap(trans, out_meta,
+                                          &txq->tfds[q->write_ptr]);
                        goto out_err;
                }
+               iwl_pcie_txq_build_tfd(trans, txq, tb2_phys, tb2_len, 0);
        }
 
-       /* Attach buffers to TFD */
-       iwl_pcie_txq_build_tfd(trans, txq, txcmd_phys, firstlen, 1);
-       if (secondlen > 0)
-               iwl_pcie_txq_build_tfd(trans, txq, phys_addr, secondlen, 0);
-
-       scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) +
-                               offsetof(struct iwl_tx_cmd, scratch);
-
-       /* take back ownership of DMA buffer to enable update */
-       dma_sync_single_for_cpu(trans->dev, txcmd_phys, firstlen,
-                               DMA_BIDIRECTIONAL);
-       tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys);
-       tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys);
-
        /* Set up entry for this TFD in Tx byte-count array */
        iwl_pcie_txq_update_byte_cnt_tbl(trans, txq, le16_to_cpu(tx_cmd->len));
 
-       dma_sync_single_for_device(trans->dev, txcmd_phys, firstlen,
-                                  DMA_BIDIRECTIONAL);
-
        trace_iwlwifi_dev_tx(trans->dev, skb,
                             &txq->tfds[txq->q.write_ptr],
                             sizeof(struct iwl_tfd),
-                            &dev_cmd->hdr, firstlen,
-                            skb->data + hdr_len, secondlen);
+                            &dev_cmd->hdr, IWL_HCMD_SCRATCHBUF_SIZE + tb1_len,
+                            skb->data + hdr_len, tb2_len);
        trace_iwlwifi_dev_tx_data(trans->dev, skb,
-                                 skb->data + hdr_len, secondlen);
+                                 skb->data + hdr_len, tb2_len);
+
+       if (!ieee80211_has_morefrags(fc)) {
+               txq->need_update = 1;
+       } else {
+               wait_write_ptr = 1;
+               txq->need_update = 0;
+       }
 
        /* start timer if queue currently empty */
        if (txq->need_update && q->read_ptr == q->write_ptr &&
index 739309e..4557833 100644 (file)
@@ -825,6 +825,11 @@ static void if_sdio_finish_power_on(struct if_sdio_card *card)
 
        sdio_release_host(func);
 
+       /* Set fw_ready before queuing any commands so that
+        * lbs_thread won't block from sending them to firmware.
+        */
+       priv->fw_ready = 1;
+
        /*
         * FUNC_INIT is required for SD8688 WLAN/BT multiple functions
         */
@@ -839,7 +844,6 @@ static void if_sdio_finish_power_on(struct if_sdio_card *card)
                        netdev_alert(priv->dev, "CMD_FUNC_INIT cmd failed\n");
        }
 
-       priv->fw_ready = 1;
        wake_up(&card->pwron_waitq);
 
        if (!card->started) {
index 35c7972..5c395e2 100644 (file)
@@ -302,7 +302,7 @@ static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter)
                i++;
                usleep_range(10, 20);
                /* 50ms max wait */
-               if (i == 50000)
+               if (i == 5000)
                        break;
        }
 
index 1031db6..189744d 100644 (file)
@@ -1236,8 +1236,10 @@ static inline void rt2x00lib_set_if_combinations(struct rt2x00_dev *rt2x00dev)
         */
        if_limit = &rt2x00dev->if_limits_ap;
        if_limit->max = rt2x00dev->ops->max_ap_intf;
-       if_limit->types = BIT(NL80211_IFTYPE_AP) |
-                       BIT(NL80211_IFTYPE_MESH_POINT);
+       if_limit->types = BIT(NL80211_IFTYPE_AP);
+#ifdef CONFIG_MAC80211_MESH
+       if_limit->types |= BIT(NL80211_IFTYPE_MESH_POINT);
+#endif
 
        /*
         * Build up AP interface combinations structure.
@@ -1309,7 +1311,9 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
                rt2x00dev->hw->wiphy->interface_modes |=
                    BIT(NL80211_IFTYPE_ADHOC) |
                    BIT(NL80211_IFTYPE_AP) |
+#ifdef CONFIG_MAC80211_MESH
                    BIT(NL80211_IFTYPE_MESH_POINT) |
+#endif
                    BIT(NL80211_IFTYPE_WDS);
 
        rt2x00dev->hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
index 445ffda..7c12d9c 100644 (file)
@@ -276,6 +276,7 @@ static struct file_system_type oprofilefs_type = {
        .mount          = oprofilefs_mount,
        .kill_sb        = kill_litter_super,
 };
+MODULE_ALIAS_FS("oprofilefs");
 
 
 int __init oprofilefs_register(void)
index 39c937f..dee5ddd 100644 (file)
@@ -331,8 +331,14 @@ static void pci_acpi_cleanup(struct device *dev)
        }
 }
 
+static bool pci_acpi_bus_match(struct device *dev)
+{
+       return dev->bus == &pci_bus_type;
+}
+
 static struct acpi_bus_type acpi_pci_bus = {
-       .bus = &pci_bus_type,
+       .name = "PCI",
+       .match = pci_acpi_bus_match,
        .find_device = acpi_pci_find_device,
        .setup = pci_acpi_setup,
        .cleanup = pci_acpi_cleanup,
index 93d6680..3e5b449 100644 (file)
@@ -23,6 +23,9 @@
 
 #include <linux/dmi.h>
 #include <linux/i2c.h>
+#include <linux/i2c/atmel_mxt_ts.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
 #include <linux/module.h>
 
 #define ATMEL_TP_I2C_ADDR      0x4b
@@ -67,15 +70,49 @@ static struct i2c_board_info __initdata tsl2563_als_device = {
        I2C_BOARD_INFO("tsl2563", TAOS_ALS_I2C_ADDR),
 };
 
+static struct mxt_platform_data atmel_224s_tp_platform_data = {
+       .x_line                 = 18,
+       .y_line                 = 12,
+       .x_size                 = 102*20,
+       .y_size                 = 68*20,
+       .blen                   = 0x80, /* Gain setting is in upper 4 bits */
+       .threshold              = 0x32,
+       .voltage                = 0,    /* 3.3V */
+       .orient                 = MXT_VERTICAL_FLIP,
+       .irqflags               = IRQF_TRIGGER_FALLING,
+       .is_tp                  = true,
+       .key_map                = { KEY_RESERVED,
+                                   KEY_RESERVED,
+                                   KEY_RESERVED,
+                                   BTN_LEFT },
+       .config                 = NULL,
+       .config_length          = 0,
+};
+
 static struct i2c_board_info __initdata atmel_224s_tp_device = {
        I2C_BOARD_INFO("atmel_mxt_tp", ATMEL_TP_I2C_ADDR),
-       .platform_data = NULL,
+       .platform_data = &atmel_224s_tp_platform_data,
        .flags          = I2C_CLIENT_WAKE,
 };
 
+static struct mxt_platform_data atmel_1664s_platform_data = {
+       .x_line                 = 32,
+       .y_line                 = 50,
+       .x_size                 = 1700,
+       .y_size                 = 2560,
+       .blen                   = 0x89, /* Gain setting is in upper 4 bits */
+       .threshold              = 0x28,
+       .voltage                = 0,    /* 3.3V */
+       .orient                 = MXT_ROTATED_90_COUNTER,
+       .irqflags               = IRQF_TRIGGER_FALLING,
+       .is_tp                  = false,
+       .config                 = NULL,
+       .config_length          = 0,
+};
+
 static struct i2c_board_info __initdata atmel_1664s_device = {
        I2C_BOARD_INFO("atmel_mxt_ts", ATMEL_TS_I2C_ADDR),
-       .platform_data = NULL,
+       .platform_data = &atmel_1664s_platform_data,
        .flags          = I2C_CLIENT_WAKE,
 };
 
index 8813fc0..55cd459 100644 (file)
@@ -353,8 +353,14 @@ static int __init acpi_pnp_find_device(struct device *dev, acpi_handle * handle)
 /* complete initialization of a PNPACPI device includes having
  * pnpdev->dev.archdata.acpi_handle point to its ACPI sibling.
  */
+static bool acpi_pnp_bus_match(struct device *dev)
+{
+       return dev->bus == &pnp_bus_type;
+}
+
 static struct acpi_bus_type __initdata acpi_pnp_bus = {
-       .bus         = &pnp_bus_type,
+       .name        = "PNP",
+       .match       = acpi_pnp_bus_match,
        .find_device = acpi_pnp_find_device,
 };
 
index da9782b..e3661c2 100644 (file)
@@ -2830,7 +2830,7 @@ EXPORT_SYMBOL_GPL(regulator_get_bypass_regmap);
  * regulator_allow_bypass - allow the regulator to go into bypass mode
  *
  * @regulator: Regulator to configure
- * @allow: enable or disable bypass mode
+ * @enable: enable or disable bypass mode
  *
  * Allow the regulator to go into bypass mode if all other consumers
  * for the regulator also enable bypass mode and the machine
@@ -3057,9 +3057,13 @@ int regulator_bulk_enable(int num_consumers,
        return 0;
 
 err:
-       pr_err("Failed to enable %s: %d\n", consumers[i].supply, ret);
-       while (--i >= 0)
-               regulator_disable(consumers[i].consumer);
+       for (i = 0; i < num_consumers; i++) {
+               if (consumers[i].ret < 0)
+                       pr_err("Failed to enable %s: %d\n", consumers[i].supply,
+                              consumers[i].ret);
+               else
+                       regulator_disable(consumers[i].consumer);
+       }
 
        return ret;
 }
index 219d162..a53c11a 100644 (file)
@@ -528,7 +528,7 @@ static int db8500_regulator_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __exit db8500_regulator_remove(struct platform_device *pdev)
+static int db8500_regulator_remove(struct platform_device *pdev)
 {
        int i;
 
@@ -553,7 +553,7 @@ static struct platform_driver db8500_regulator_driver = {
                .owner = THIS_MODULE,
        },
        .probe = db8500_regulator_probe,
-       .remove = __exit_p(db8500_regulator_remove),
+       .remove = db8500_regulator_remove,
 };
 
 static int __init db8500_regulator_init(void)
index cde13bb..39cf146 100644 (file)
@@ -4,6 +4,7 @@
  * Copyright 2011-2012 Texas Instruments Inc.
  *
  * Author: Graeme Gregory <gg@slimlogic.co.uk>
+ * Author: Ian Lartey <ian@slimlogic.co.uk>
  *
  *  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
@@ -156,7 +157,7 @@ static const struct regs_info palmas_regs_info[] = {
  *
  * So they are basically (maxV-minV)/stepV
  */
-#define PALMAS_SMPS_NUM_VOLTAGES       116
+#define PALMAS_SMPS_NUM_VOLTAGES       117
 #define PALMAS_SMPS10_NUM_VOLTAGES     2
 #define PALMAS_LDO_NUM_VOLTAGES                50
 
index 74508cc..f705d25 100644 (file)
@@ -471,24 +471,23 @@ twl4030ldo_set_voltage_sel(struct regulator_dev *rdev, unsigned selector)
                            selector);
 }
 
-static int twl4030ldo_get_voltage(struct regulator_dev *rdev)
+static int twl4030ldo_get_voltage_sel(struct regulator_dev *rdev)
 {
        struct twlreg_info      *info = rdev_get_drvdata(rdev);
-       int             vsel = twlreg_read(info, TWL_MODULE_PM_RECEIVER,
-                                                               VREG_VOLTAGE);
+       int vsel = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE);
 
        if (vsel < 0)
                return vsel;
 
        vsel &= info->table_len - 1;
-       return LDO_MV(info->table[vsel]) * 1000;
+       return vsel;
 }
 
 static struct regulator_ops twl4030ldo_ops = {
        .list_voltage   = twl4030ldo_list_voltage,
 
        .set_voltage_sel = twl4030ldo_set_voltage_sel,
-       .get_voltage    = twl4030ldo_get_voltage,
+       .get_voltage_sel = twl4030ldo_get_voltage_sel,
 
        .enable         = twl4030reg_enable,
        .disable        = twl4030reg_disable,
index 57233c8..8f87fec 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/platform_device.h>
 #include <linux/of.h>
 #include <linux/delay.h>
+#include <linux/clk.h>
 #include <linux/gfp.h>
 #include <linux/module.h>
 
@@ -41,6 +42,7 @@ struct rtc_plat_data {
        struct rtc_device *rtc;
        void __iomem *ioaddr;
        int             irq;
+       struct clk      *clk;
 };
 
 static int mv_rtc_set_time(struct device *dev, struct rtc_time *tm)
@@ -221,6 +223,7 @@ static int mv_rtc_probe(struct platform_device *pdev)
        struct rtc_plat_data *pdata;
        resource_size_t size;
        u32 rtc_time;
+       int ret = 0;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res)
@@ -239,11 +242,17 @@ static int mv_rtc_probe(struct platform_device *pdev)
        if (!pdata->ioaddr)
                return -ENOMEM;
 
+       pdata->clk = devm_clk_get(&pdev->dev, NULL);
+       /* Not all SoCs require a clock.*/
+       if (!IS_ERR(pdata->clk))
+               clk_prepare_enable(pdata->clk);
+
        /* make sure the 24 hours mode is enabled */
        rtc_time = readl(pdata->ioaddr + RTC_TIME_REG_OFFS);
        if (rtc_time & RTC_HOURS_12H_MODE) {
                dev_err(&pdev->dev, "24 Hours mode not supported.\n");
-               return -EINVAL;
+               ret = -EINVAL;
+               goto out;
        }
 
        /* make sure it is actually functional */
@@ -252,7 +261,8 @@ static int mv_rtc_probe(struct platform_device *pdev)
                rtc_time = readl(pdata->ioaddr + RTC_TIME_REG_OFFS);
                if (rtc_time == 0x01000000) {
                        dev_err(&pdev->dev, "internal RTC not ticking\n");
-                       return -ENODEV;
+                       ret = -ENODEV;
+                       goto out;
                }
        }
 
@@ -268,8 +278,10 @@ static int mv_rtc_probe(struct platform_device *pdev)
        } else
                pdata->rtc = rtc_device_register(pdev->name, &pdev->dev,
                                                 &mv_rtc_ops, THIS_MODULE);
-       if (IS_ERR(pdata->rtc))
-               return PTR_ERR(pdata->rtc);
+       if (IS_ERR(pdata->rtc)) {
+               ret = PTR_ERR(pdata->rtc);
+               goto out;
+       }
 
        if (pdata->irq >= 0) {
                writel(0, pdata->ioaddr + RTC_ALARM_INTERRUPT_MASK_REG_OFFS);
@@ -282,6 +294,11 @@ static int mv_rtc_probe(struct platform_device *pdev)
        }
 
        return 0;
+out:
+       if (!IS_ERR(pdata->clk))
+               clk_disable_unprepare(pdata->clk);
+
+       return ret;
 }
 
 static int __exit mv_rtc_remove(struct platform_device *pdev)
@@ -292,6 +309,9 @@ static int __exit mv_rtc_remove(struct platform_device *pdev)
                device_init_wakeup(&pdev->dev, 0);
 
        rtc_device_unregister(pdata->rtc);
+       if (!IS_ERR(pdata->clk))
+               clk_disable_unprepare(pdata->clk);
+
        return 0;
 }
 
index 765398c..c31187d 100644 (file)
@@ -71,9 +71,14 @@ struct kmem_cache *scsi_sdb_cache;
 #ifdef CONFIG_ACPI
 #include <acpi/acpi_bus.h>
 
+static bool acpi_scsi_bus_match(struct device *dev)
+{
+       return dev->bus == &scsi_bus_type;
+}
+
 int scsi_register_acpi_bus_type(struct acpi_bus_type *bus)
 {
-        bus->bus = &scsi_bus_type;
+        bus->match = acpi_scsi_bus_match;
         return register_acpi_bus_type(bus);
 }
 EXPORT_SYMBOL_GPL(scsi_register_acpi_bus_type);
index 8adc79d..f6373da 100644 (file)
@@ -1223,6 +1223,7 @@ static struct file_system_type ffs_fs_type = {
        .mount          = ffs_fs_mount,
        .kill_sb        = ffs_fs_kill_sb,
 };
+MODULE_ALIAS_FS("functionfs");
 
 
 /* Driver's main init/cleanup functions *************************************/
index 192cf08..57b4519 100644 (file)
@@ -947,12 +947,13 @@ static int dt9812_di_rinsn(struct comedi_device *dev,
                           unsigned int *data)
 {
        struct comedi_dt9812 *devpriv = dev->private;
+       unsigned int channel = CR_CHAN(insn->chanspec);
        int n;
        u8 bits = 0;
 
        dt9812_digital_in(devpriv->slot, &bits);
        for (n = 0; n < insn->n; n++)
-               data[n] = ((1 << insn->chanspec) & bits) != 0;
+               data[n] = ((1 << channel) & bits) != 0;
        return n;
 }
 
@@ -961,12 +962,13 @@ static int dt9812_do_winsn(struct comedi_device *dev,
                           unsigned int *data)
 {
        struct comedi_dt9812 *devpriv = dev->private;
+       unsigned int channel = CR_CHAN(insn->chanspec);
        int n;
        u8 bits = 0;
 
        dt9812_digital_out_shadow(devpriv->slot, &bits);
        for (n = 0; n < insn->n; n++) {
-               u8 mask = 1 << insn->chanspec;
+               u8 mask = 1 << channel;
 
                bits &= ~mask;
                if (data[n])
@@ -981,13 +983,13 @@ static int dt9812_ai_rinsn(struct comedi_device *dev,
                           unsigned int *data)
 {
        struct comedi_dt9812 *devpriv = dev->private;
+       unsigned int channel = CR_CHAN(insn->chanspec);
        int n;
 
        for (n = 0; n < insn->n; n++) {
                u16 value = 0;
 
-               dt9812_analog_in(devpriv->slot, insn->chanspec, &value,
-                                DT9812_GAIN_1);
+               dt9812_analog_in(devpriv->slot, channel, &value, DT9812_GAIN_1);
                data[n] = value;
        }
        return n;
@@ -998,12 +1000,13 @@ static int dt9812_ao_rinsn(struct comedi_device *dev,
                           unsigned int *data)
 {
        struct comedi_dt9812 *devpriv = dev->private;
+       unsigned int channel = CR_CHAN(insn->chanspec);
        int n;
        u16 value;
 
        for (n = 0; n < insn->n; n++) {
                value = 0;
-               dt9812_analog_out_shadow(devpriv->slot, insn->chanspec, &value);
+               dt9812_analog_out_shadow(devpriv->slot, channel, &value);
                data[n] = value;
        }
        return n;
@@ -1014,10 +1017,11 @@ static int dt9812_ao_winsn(struct comedi_device *dev,
                           unsigned int *data)
 {
        struct comedi_dt9812 *devpriv = dev->private;
+       unsigned int channel = CR_CHAN(insn->chanspec);
        int n;
 
        for (n = 0; n < insn->n; n++)
-               dt9812_analog_out(devpriv->slot, insn->chanspec, data[n]);
+               dt9812_analog_out(devpriv->slot, channel, data[n]);
        return n;
 }
 
index 1a0062a..6aac1f6 100644 (file)
@@ -730,10 +730,14 @@ static void usbduxsub_ao_IsocIrq(struct urb *urb)
 static int usbduxsub_start(struct usbduxsub *usbduxsub)
 {
        int errcode = 0;
-       uint8_t local_transfer_buffer[16];
+       uint8_t *local_transfer_buffer;
+
+       local_transfer_buffer = kmalloc(1, GFP_KERNEL);
+       if (!local_transfer_buffer)
+               return -ENOMEM;
 
        /* 7f92 to zero */
-       local_transfer_buffer[0] = 0;
+       *local_transfer_buffer = 0;
        errcode = usb_control_msg(usbduxsub->usbdev,
                                  /* create a pipe for a control transfer */
                                  usb_sndctrlpipe(usbduxsub->usbdev, 0),
@@ -751,22 +755,25 @@ static int usbduxsub_start(struct usbduxsub *usbduxsub)
                                  1,
                                  /* Timeout */
                                  BULK_TIMEOUT);
-       if (errcode < 0) {
+       if (errcode < 0)
                dev_err(&usbduxsub->interface->dev,
                        "comedi_: control msg failed (start)\n");
-               return errcode;
-       }
-       return 0;
+
+       kfree(local_transfer_buffer);
+       return errcode;
 }
 
 static int usbduxsub_stop(struct usbduxsub *usbduxsub)
 {
        int errcode = 0;
+       uint8_t *local_transfer_buffer;
 
-       uint8_t local_transfer_buffer[16];
+       local_transfer_buffer = kmalloc(1, GFP_KERNEL);
+       if (!local_transfer_buffer)
+               return -ENOMEM;
 
        /* 7f92 to one */
-       local_transfer_buffer[0] = 1;
+       *local_transfer_buffer = 1;
        errcode = usb_control_msg(usbduxsub->usbdev,
                                  usb_sndctrlpipe(usbduxsub->usbdev, 0),
                                  /* bRequest, "Firmware" */
@@ -781,12 +788,12 @@ static int usbduxsub_stop(struct usbduxsub *usbduxsub)
                                  1,
                                  /* Timeout */
                                  BULK_TIMEOUT);
-       if (errcode < 0) {
+       if (errcode < 0)
                dev_err(&usbduxsub->interface->dev,
                        "comedi_: control msg failed (stop)\n");
-               return errcode;
-       }
-       return 0;
+
+       kfree(local_transfer_buffer);
+       return errcode;
 }
 
 static int usbduxsub_upload(struct usbduxsub *usbduxsub,
index 4bf5dd0..1ba0e3d 100644 (file)
@@ -436,10 +436,14 @@ static void usbduxfastsub_ai_Irq(struct urb *urb)
 static int usbduxfastsub_start(struct usbduxfastsub_s *udfs)
 {
        int ret;
-       unsigned char local_transfer_buffer[16];
+       unsigned char *local_transfer_buffer;
+
+       local_transfer_buffer = kmalloc(1, GFP_KERNEL);
+       if (!local_transfer_buffer)
+               return -ENOMEM;
 
        /* 7f92 to zero */
-       local_transfer_buffer[0] = 0;
+       *local_transfer_buffer = 0;
        /* bRequest, "Firmware" */
        ret = usb_control_msg(udfs->usbdev, usb_sndctrlpipe(udfs->usbdev, 0),
                              USBDUXFASTSUB_FIRMWARE,
@@ -450,22 +454,25 @@ static int usbduxfastsub_start(struct usbduxfastsub_s *udfs)
                              local_transfer_buffer,
                              1,      /* Length */
                              EZTIMEOUT);    /* Timeout */
-       if (ret < 0) {
+       if (ret < 0)
                dev_err(&udfs->interface->dev,
                        "control msg failed (start)\n");
-               return ret;
-       }
 
-       return 0;
+       kfree(local_transfer_buffer);
+       return ret;
 }
 
 static int usbduxfastsub_stop(struct usbduxfastsub_s *udfs)
 {
        int ret;
-       unsigned char local_transfer_buffer[16];
+       unsigned char *local_transfer_buffer;
+
+       local_transfer_buffer = kmalloc(1, GFP_KERNEL);
+       if (!local_transfer_buffer)
+               return -ENOMEM;
 
        /* 7f92 to one */
-       local_transfer_buffer[0] = 1;
+       *local_transfer_buffer = 1;
        /* bRequest, "Firmware" */
        ret = usb_control_msg(udfs->usbdev, usb_sndctrlpipe(udfs->usbdev, 0),
                              USBDUXFASTSUB_FIRMWARE,
@@ -474,13 +481,12 @@ static int usbduxfastsub_stop(struct usbduxfastsub_s *udfs)
                              0x0000,   /* Index */
                              local_transfer_buffer, 1, /* Length */
                              EZTIMEOUT);       /* Timeout */
-       if (ret < 0) {
+       if (ret < 0)
                dev_err(&udfs->interface->dev,
                        "control msg failed (stop)\n");
-               return ret;
-       }
 
-       return 0;
+       kfree(local_transfer_buffer);
+       return ret;
 }
 
 static int usbduxfastsub_upload(struct usbduxfastsub_s *udfs,
index d066351..a728c8f 100644 (file)
@@ -681,7 +681,11 @@ static void usbduxsub_ao_IsocIrq(struct urb *urb)
 static int usbduxsub_start(struct usbduxsub *usbduxsub)
 {
        int errcode = 0;
-       uint8_t local_transfer_buffer[16];
+       uint8_t *local_transfer_buffer;
+
+       local_transfer_buffer = kmalloc(16, GFP_KERNEL);
+       if (!local_transfer_buffer)
+               return -ENOMEM;
 
        /* 7f92 to zero */
        local_transfer_buffer[0] = 0;
@@ -702,19 +706,22 @@ static int usbduxsub_start(struct usbduxsub *usbduxsub)
                                  1,
                                  /* Timeout */
                                  BULK_TIMEOUT);
-       if (errcode < 0) {
+       if (errcode < 0)
                dev_err(&usbduxsub->interface->dev,
                        "comedi_: control msg failed (start)\n");
-               return errcode;
-       }
-       return 0;
+
+       kfree(local_transfer_buffer);
+       return errcode;
 }
 
 static int usbduxsub_stop(struct usbduxsub *usbduxsub)
 {
        int errcode = 0;
+       uint8_t *local_transfer_buffer;
 
-       uint8_t local_transfer_buffer[16];
+       local_transfer_buffer = kmalloc(16, GFP_KERNEL);
+       if (!local_transfer_buffer)
+               return -ENOMEM;
 
        /* 7f92 to one */
        local_transfer_buffer[0] = 1;
@@ -732,12 +739,12 @@ static int usbduxsub_stop(struct usbduxsub *usbduxsub)
                                  1,
                                  /* Timeout */
                                  BULK_TIMEOUT);
-       if (errcode < 0) {
+       if (errcode < 0)
                dev_err(&usbduxsub->interface->dev,
                        "comedi_: control msg failed (stop)\n");
-               return errcode;
-       }
-       return 0;
+
+       kfree(local_transfer_buffer);
+       return errcode;
 }
 
 static int usbduxsub_upload(struct usbduxsub *usbduxsub,
index 4b3a019..b028b0d 100644 (file)
@@ -483,17 +483,6 @@ static int ipu_get_resources(struct ipu_crtc *ipu_crtc,
                goto err_out;
        }
 
-       ipu_crtc->irq = ipu_idmac_channel_irq(ipu, ipu_crtc->ipu_ch,
-                       IPU_IRQ_EOF);
-       ret = devm_request_irq(ipu_crtc->dev, ipu_crtc->irq, ipu_irq_handler, 0,
-                       "imx_drm", ipu_crtc);
-       if (ret < 0) {
-               dev_err(ipu_crtc->dev, "irq request failed with %d.\n", ret);
-               goto err_out;
-       }
-
-       disable_irq(ipu_crtc->irq);
-
        return 0;
 err_out:
        ipu_put_resources(ipu_crtc);
@@ -504,6 +493,7 @@ err_out:
 static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
                struct ipu_client_platformdata *pdata)
 {
+       struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent);
        int ret;
 
        ret = ipu_get_resources(ipu_crtc, pdata);
@@ -522,6 +512,17 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
                goto err_put_resources;
        }
 
+       ipu_crtc->irq = ipu_idmac_channel_irq(ipu, ipu_crtc->ipu_ch,
+                       IPU_IRQ_EOF);
+       ret = devm_request_irq(ipu_crtc->dev, ipu_crtc->irq, ipu_irq_handler, 0,
+                       "imx_drm", ipu_crtc);
+       if (ret < 0) {
+               dev_err(ipu_crtc->dev, "irq request failed with %d.\n", ret);
+               goto err_put_resources;
+       }
+
+       disable_irq(ipu_crtc->irq);
+
        return 0;
 
 err_put_resources:
index db1da28..be26917 100644 (file)
@@ -76,37 +76,28 @@ int drv_insert_node_res_element(void *hnode, void *node_resource,
        struct node_res_object **node_res_obj =
            (struct node_res_object **)node_resource;
        struct process_context *ctxt = (struct process_context *)process_ctxt;
-       int status = 0;
        int retval;
 
        *node_res_obj = kzalloc(sizeof(struct node_res_object), GFP_KERNEL);
-       if (!*node_res_obj) {
-               status = -ENOMEM;
-               goto func_end;
-       }
+       if (!*node_res_obj)
+               return -ENOMEM;
 
        (*node_res_obj)->node = hnode;
-       retval = idr_get_new(ctxt->node_id, *node_res_obj,
-                                               &(*node_res_obj)->id);
-       if (retval == -EAGAIN) {
-               if (!idr_pre_get(ctxt->node_id, GFP_KERNEL)) {
-                       pr_err("%s: OUT OF MEMORY\n", __func__);
-                       status = -ENOMEM;
-                       goto func_end;
-               }
-
-               retval = idr_get_new(ctxt->node_id, *node_res_obj,
-                                               &(*node_res_obj)->id);
+       retval = idr_alloc(ctxt->node_id, *node_res_obj, 0, 0, GFP_KERNEL);
+       if (retval >= 0) {
+               (*node_res_obj)->id = retval;
+               return 0;
        }
-       if (retval) {
+
+       kfree(*node_res_obj);
+
+       if (retval == -ENOSPC) {
                pr_err("%s: FAILED, IDR is FULL\n", __func__);
-               status = -EFAULT;
+               return -EFAULT;
+       } else {
+               pr_err("%s: OUT OF MEMORY\n", __func__);
+               return -ENOMEM;
        }
-func_end:
-       if (status)
-               kfree(*node_res_obj);
-
-       return status;
 }
 
 /* Release all Node resources and its context
@@ -201,35 +192,26 @@ int drv_proc_insert_strm_res_element(void *stream_obj,
        struct strm_res_object **pstrm_res =
            (struct strm_res_object **)strm_res;
        struct process_context *ctxt = (struct process_context *)process_ctxt;
-       int status = 0;
        int retval;
 
        *pstrm_res = kzalloc(sizeof(struct strm_res_object), GFP_KERNEL);
-       if (*pstrm_res == NULL) {
-               status = -EFAULT;
-               goto func_end;
-       }
+       if (*pstrm_res == NULL)
+               return -EFAULT;
 
        (*pstrm_res)->stream = stream_obj;
-       retval = idr_get_new(ctxt->stream_id, *pstrm_res,
-                                               &(*pstrm_res)->id);
-       if (retval == -EAGAIN) {
-               if (!idr_pre_get(ctxt->stream_id, GFP_KERNEL)) {
-                       pr_err("%s: OUT OF MEMORY\n", __func__);
-                       status = -ENOMEM;
-                       goto func_end;
-               }
-
-               retval = idr_get_new(ctxt->stream_id, *pstrm_res,
-                                               &(*pstrm_res)->id);
+       retval = idr_alloc(ctxt->stream_id, *pstrm_res, 0, 0, GFP_KERNEL);
+       if (retval >= 0) {
+               (*pstrm_res)->id = retval;
+               return 0;
        }
-       if (retval) {
+
+       if (retval == -ENOSPC) {
                pr_err("%s: FAILED, IDR is FULL\n", __func__);
-               status = -EPERM;
+               return -EPERM;
+       } else {
+               pr_err("%s: OUT OF MEMORY\n", __func__);
+               return -ENOMEM;
        }
-
-func_end:
-       return status;
 }
 
 static int drv_proc_free_strm_res(int id, void *p, void *process_ctxt)
index 22918a1..d2479b7 100644 (file)
@@ -790,7 +790,7 @@ u64 CARDqGetNextTBTT(u64 qwTSF, WORD wBeaconInterval)
        if ((~uLowNextTBTT) < uLowRemain)
                qwTSF = ((qwTSF >> 32) + 1) << 32;
 
-       qwTSF = (qwTSF & 0xffffffff00000000UL) |
+       qwTSF = (qwTSF & 0xffffffff00000000ULL) |
                (u64)(uLowNextTBTT + uLowRemain);
 
     return (qwTSF);
index d5f53e1..a5063a6 100644 (file)
@@ -669,8 +669,6 @@ static int vt6656_suspend(struct usb_interface *intf, pm_message_t message)
        if (device->flags & DEVICE_FLAGS_OPENED)
                device_close(device->dev);
 
-       usb_put_dev(interface_to_usbdev(intf));
-
        return 0;
 }
 
@@ -681,8 +679,6 @@ static int vt6656_resume(struct usb_interface *intf)
        if (!device || !device->dev)
                return -ENODEV;
 
-       usb_get_dev(interface_to_usbdev(intf));
-
        if (!(device->flags & DEVICE_FLAGS_OPENED))
                device_open(device->dev);
 
index aa2a1a7..f6e1e52 100644 (file)
@@ -300,27 +300,22 @@ static u8 r2net_num_from_nn(struct r2net_node *nn)
 
 static int r2net_prep_nsw(struct r2net_node *nn, struct r2net_status_wait *nsw)
 {
-       int ret = 0;
+       int ret;
 
-       do {
-               if (!idr_pre_get(&nn->nn_status_idr, GFP_ATOMIC)) {
-                       ret = -EAGAIN;
-                       break;
-               }
-               spin_lock(&nn->nn_lock);
-               ret = idr_get_new(&nn->nn_status_idr, nsw, &nsw->ns_id);
-               if (ret == 0)
-                       list_add_tail(&nsw->ns_node_item,
-                                     &nn->nn_status_list);
-               spin_unlock(&nn->nn_lock);
-       } while (ret == -EAGAIN);
+       spin_lock(&nn->nn_lock);
+       ret = idr_alloc(&nn->nn_status_idr, nsw, 0, 0, GFP_ATOMIC);
+       if (ret >= 0) {
+               nsw->ns_id = ret;
+               list_add_tail(&nsw->ns_node_item, &nn->nn_status_list);
+       }
+       spin_unlock(&nn->nn_lock);
 
-       if (ret == 0)  {
+       if (ret >= 0) {
                init_waitqueue_head(&nsw->ns_wq);
                nsw->ns_sys_status = R2NET_ERR_NONE;
                nsw->ns_status = 0;
+               return 0;
        }
-
        return ret;
 }
 
index 1956593..81e939e 100644 (file)
@@ -881,17 +881,12 @@ static struct vio_driver hvcs_vio_driver = {
 /* Only called from hvcs_get_pi please */
 static void hvcs_set_pi(struct hvcs_partner_info *pi, struct hvcs_struct *hvcsd)
 {
-       int clclength;
-
        hvcsd->p_unit_address = pi->unit_address;
        hvcsd->p_partition_ID  = pi->partition_ID;
-       clclength = strlen(&pi->location_code[0]);
-       if (clclength > HVCS_CLC_LENGTH)
-               clclength = HVCS_CLC_LENGTH;
 
        /* copy the null-term char too */
-       strncpy(&hvcsd->p_location_code[0],
-                       &pi->location_code[0], clclength + 1);
+       strlcpy(&hvcsd->p_location_code[0],
+                       &pi->location_code[0], sizeof(hvcsd->p_location_code));
 }
 
 /*
index 0efc815..cf6a538 100644 (file)
@@ -301,7 +301,28 @@ static const struct serial8250_config uart_config[] = {
        },
        [PORT_8250_CIR] = {
                .name           = "CIR port"
-       }
+       },
+       [PORT_ALTR_16550_F32] = {
+               .name           = "Altera 16550 FIFO32",
+               .fifo_size      = 32,
+               .tx_loadsz      = 32,
+               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+               .flags          = UART_CAP_FIFO | UART_CAP_AFE,
+       },
+       [PORT_ALTR_16550_F64] = {
+               .name           = "Altera 16550 FIFO64",
+               .fifo_size      = 64,
+               .tx_loadsz      = 64,
+               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+               .flags          = UART_CAP_FIFO | UART_CAP_AFE,
+       },
+       [PORT_ALTR_16550_F128] = {
+               .name           = "Altera 16550 FIFO128",
+               .fifo_size      = 128,
+               .tx_loadsz      = 128,
+               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+               .flags          = UART_CAP_FIFO | UART_CAP_AFE,
+       },
 };
 
 /* Uart divisor latch read */
@@ -3396,3 +3417,32 @@ module_param_array(probe_rsa, ulong, &probe_rsa_count, 0444);
 MODULE_PARM_DESC(probe_rsa, "Probe I/O ports for RSA");
 #endif
 MODULE_ALIAS_CHARDEV_MAJOR(TTY_MAJOR);
+
+#ifndef MODULE
+/* This module was renamed to 8250_core in 3.7.  Keep the old "8250" name
+ * working as well for the module options so we don't break people.  We
+ * need to keep the names identical and the convenient macros will happily
+ * refuse to let us do that by failing the build with redefinition errors
+ * of global variables.  So we stick them inside a dummy function to avoid
+ * those conflicts.  The options still get parsed, and the redefined
+ * MODULE_PARAM_PREFIX lets us keep the "8250." syntax alive.
+ *
+ * This is hacky.  I'm sorry.
+ */
+static void __used s8250_options(void)
+{
+#undef MODULE_PARAM_PREFIX
+#define MODULE_PARAM_PREFIX "8250."
+
+       module_param_cb(share_irqs, &param_ops_uint, &share_irqs, 0644);
+       module_param_cb(nr_uarts, &param_ops_uint, &nr_uarts, 0644);
+       module_param_cb(skip_txen_test, &param_ops_uint, &skip_txen_test, 0644);
+#ifdef CONFIG_SERIAL_8250_RSA
+       __module_param_call(MODULE_PARAM_PREFIX, probe_rsa,
+               &param_array_ops, .arr = &__param_arr_probe_rsa,
+               0444, -1);
+#endif
+}
+#else
+MODULE_ALIAS("8250");
+#endif
index 791c5a7..aa76825 100644 (file)
@@ -1571,6 +1571,7 @@ pci_wch_ch353_setup(struct serial_private *priv,
 
 /* Unknown vendors/cards - this should not be in linux/pci_ids.h */
 #define PCI_SUBDEVICE_ID_UNKNOWN_0x1584        0x1584
+#define PCI_SUBDEVICE_ID_UNKNOWN_0x1588        0x1588
 
 /*
  * Master list of serial port init/setup/exit quirks.
@@ -1852,15 +1853,6 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
        },
        {
                .vendor         = PCI_VENDOR_ID_PLX,
-               .device         = PCI_DEVICE_ID_PLX_9050,
-               .subvendor      = PCI_VENDOR_ID_PLX,
-               .subdevice      = PCI_SUBDEVICE_ID_UNKNOWN_0x1584,
-               .init           = pci_plx9050_init,
-               .setup          = pci_default_setup,
-               .exit           = pci_plx9050_exit,
-       },
-       {
-               .vendor         = PCI_VENDOR_ID_PLX,
                .device         = PCI_DEVICE_ID_PLX_ROMULUS,
                .subvendor      = PCI_VENDOR_ID_PLX,
                .subdevice      = PCI_DEVICE_ID_PLX_ROMULUS,
@@ -3733,7 +3725,12 @@ static struct pci_device_id serial_pci_tbl[] = {
        {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
                PCI_VENDOR_ID_PLX,
                PCI_SUBDEVICE_ID_UNKNOWN_0x1584, 0, 0,
-               pbn_b0_4_115200 },
+               pbn_b2_4_115200 },
+       /* Unknown card - subdevice 0x1588 */
+       {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
+               PCI_VENDOR_ID_PLX,
+               PCI_SUBDEVICE_ID_UNKNOWN_0x1588, 0, 0,
+               pbn_b2_8_115200 },
        {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
                PCI_SUBVENDOR_ID_KEYSPAN,
                PCI_SUBDEVICE_ID_KEYSPAN_SX2, 0, 0,
@@ -4791,6 +4788,10 @@ static struct pci_device_id serial_pci_tbl[] = {
                PCI_VENDOR_ID_IBM, 0x0299,
                0, 0, pbn_b0_bt_2_115200 },
 
+       {       PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9835,
+               0x1000, 0x0012,
+               0, 0, pbn_b0_bt_2_115200 },
+
        {       PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9901,
                0xA000, 0x1000,
                0, 0, pbn_b0_1_115200 },
index 35d9ab9..b3455a9 100644 (file)
@@ -429,6 +429,7 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
 {
        struct uart_8250_port uart;
        int ret, line, flags = dev_id->driver_data;
+       struct resource *res = NULL;
 
        if (flags & UNKNOWN_DEV) {
                ret = serial_pnp_guess_board(dev);
@@ -439,11 +440,12 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
        memset(&uart, 0, sizeof(uart));
        if (pnp_irq_valid(dev, 0))
                uart.port.irq = pnp_irq(dev, 0);
-       if ((flags & CIR_PORT) && pnp_port_valid(dev, 2)) {
-               uart.port.iobase = pnp_port_start(dev, 2);
-               uart.port.iotype = UPIO_PORT;
-       } else if (pnp_port_valid(dev, 0)) {
-               uart.port.iobase = pnp_port_start(dev, 0);
+       if ((flags & CIR_PORT) && pnp_port_valid(dev, 2))
+               res = pnp_get_resource(dev, IORESOURCE_IO, 2);
+       else if (pnp_port_valid(dev, 0))
+               res = pnp_get_resource(dev, IORESOURCE_IO, 0);
+       if (pnp_resource_enabled(res)) {
+               uart.port.iobase = res->start;
                uart.port.iotype = UPIO_PORT;
        } else if (pnp_mem_valid(dev, 0)) {
                uart.port.mapbase = pnp_mem_start(dev, 0);
index cf9210d..7e7006f 100644 (file)
@@ -211,14 +211,14 @@ config SERIAL_SAMSUNG
 config SERIAL_SAMSUNG_UARTS_4
        bool
        depends on PLAT_SAMSUNG
-       default y if !(CPU_S3C2410 || SERIAL_S3C2412 || CPU_S3C2440 || CPU_S3C2442)
+       default y if !(CPU_S3C2410 || CPU_S3C2412 || CPU_S3C2440 || CPU_S3C2442)
        help
          Internal node for the common case of 4 Samsung compatible UARTs
 
 config SERIAL_SAMSUNG_UARTS
        int
        depends on PLAT_SAMSUNG
-       default 6 if ARCH_S5P6450
+       default 6 if CPU_S5P6450
        default 4 if SERIAL_SAMSUNG_UARTS_4 || CPU_S3C2416
        default 3
        help
index 719594e..52a3ecd 100644 (file)
@@ -235,7 +235,7 @@ static const char *bcm_uart_type(struct uart_port *port)
  */
 static void bcm_uart_do_rx(struct uart_port *port)
 {
-       struct tty_port *port = &port->state->port;
+       struct tty_port *tty_port = &port->state->port;
        unsigned int max_count;
 
        /* limit number of char read in interrupt, should not be
@@ -260,7 +260,7 @@ static void bcm_uart_do_rx(struct uart_port *port)
                        bcm_uart_writel(port, val, UART_CTL_REG);
 
                        port->icount.overrun++;
-                       tty_insert_flip_char(port, 0, TTY_OVERRUN);
+                       tty_insert_flip_char(tty_port, 0, TTY_OVERRUN);
                }
 
                if (!(iestat & UART_IR_STAT(UART_IR_RXNOTEMPTY)))
@@ -299,11 +299,11 @@ static void bcm_uart_do_rx(struct uart_port *port)
 
 
                if ((cstat & port->ignore_status_mask) == 0)
-                       tty_insert_flip_char(port, c, flag);
+                       tty_insert_flip_char(tty_port, c, flag);
 
        } while (--max_count);
 
-       tty_flip_buffer_push(port);
+       tty_flip_buffer_push(tty_port);
 }
 
 /*
index c0e1fad..018bad9 100644 (file)
@@ -550,7 +550,7 @@ static int mpc512x_psc_clock(struct uart_port *port, int enable)
                return 0;
 
        psc_num = (port->mapbase & 0xf00) >> 8;
-       snprintf(clk_name, sizeof(clk_name), "psc%d_clk", psc_num);
+       snprintf(clk_name, sizeof(clk_name), "psc%d_mclk", psc_num);
        psc_clk = clk_get(port->dev, clk_name);
        if (IS_ERR(psc_clk)) {
                dev_err(port->dev, "Failed to get PSC clock entry!\n");
index d587460..b025d54 100644 (file)
@@ -241,6 +241,12 @@ static struct of_device_id of_platform_serial_table[] = {
        { .compatible = "ns16850",  .data = (void *)PORT_16850, },
        { .compatible = "nvidia,tegra20-uart", .data = (void *)PORT_TEGRA, },
        { .compatible = "nxp,lpc3220-uart", .data = (void *)PORT_LPC3220, },
+       { .compatible = "altr,16550-FIFO32",
+               .data = (void *)PORT_ALTR_16550_F32, },
+       { .compatible = "altr,16550-FIFO64",
+               .data = (void *)PORT_ALTR_16550_F64, },
+       { .compatible = "altr,16550-FIFO128",
+               .data = (void *)PORT_ALTR_16550_F128, },
 #ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL
        { .compatible = "ibm,qpace-nwp-serial",
                .data = (void *)PORT_NWPSERIAL, },
index a3f9dd5..705240e 100644 (file)
@@ -611,14 +611,7 @@ static int vt8500_serial_probe(struct platform_device *pdev)
        vt8500_port->uart.dev = &pdev->dev;
        vt8500_port->uart.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF;
 
-       vt8500_port->clk = of_clk_get(pdev->dev.of_node, 0);
-       if (!IS_ERR(vt8500_port->clk)) {
-               vt8500_port->uart.uartclk = clk_get_rate(vt8500_port->clk);
-       } else {
-               /* use the default of 24Mhz if not specified and warn */
-               pr_warn("%s: serial clock source not specified\n", __func__);
-               vt8500_port->uart.uartclk = 24000000;
-       }
+       vt8500_port->uart.uartclk = clk_get_rate(vt8500_port->clk);
 
        snprintf(vt8500_port->name, sizeof(vt8500_port->name),
                 "VT8500 UART%d", pdev->id);
index bb11993..578aa75 100644 (file)
@@ -425,7 +425,7 @@ static void flush_to_ldisc(struct work_struct *work)
        struct tty_ldisc *disc;
 
        tty = port->itty;
-       if (WARN_RATELIMIT(tty == NULL, "tty is NULL\n"))
+       if (tty == NULL)
                return;
 
        disc = tty_ldisc_ref(tty);
index f5ed3d7..8f5ebce 100644 (file)
@@ -46,7 +46,7 @@ obj-$(CONFIG_USB_MICROTEK)    += image/
 obj-$(CONFIG_USB_SERIAL)       += serial/
 
 obj-$(CONFIG_USB)              += misc/
-obj-$(CONFIG_USB_COMMON)       += phy/
+obj-$(CONFIG_USB_OTG_UTILS)    += phy/
 obj-$(CONFIG_EARLY_PRINTK_DBGP)        += early/
 
 obj-$(CONFIG_USB_ATM)          += atm/
index a03fbc1..aa49162 100644 (file)
@@ -100,7 +100,7 @@ struct c67x00_urb_priv {
 #define TD_PIDEP_OFFSET                0x04
 #define TD_PIDEPMASK_PID       0xF0
 #define TD_PIDEPMASK_EP                0x0F
-#define TD_PORTLENMASK_DL      0x02FF
+#define TD_PORTLENMASK_DL      0x03FF
 #define TD_PORTLENMASK_PN      0xC000
 
 #define TD_STATUS_OFFSET       0x07
@@ -590,7 +590,7 @@ static int c67x00_create_td(struct c67x00_hcd *c67x00, struct urb *urb,
 {
        struct c67x00_td *td;
        struct c67x00_urb_priv *urbp = urb->hcpriv;
-       const __u8 active_flag = 1, retry_cnt = 1;
+       const __u8 active_flag = 1, retry_cnt = 3;
        __u8 cmd = 0;
        int tt = 0;
 
index 2f45bba..f64fbea 100644 (file)
@@ -1767,7 +1767,7 @@ static int udc_start(struct ci13xxx *ci)
                goto put_transceiver;
        }
 
-       retval = dbg_create_files(&ci->gadget.dev);
+       retval = dbg_create_files(ci->dev);
        if (retval)
                goto unreg_device;
 
@@ -1796,7 +1796,7 @@ remove_trans:
 
        dev_err(dev, "error = %i\n", retval);
 remove_dbg:
-       dbg_remove_files(&ci->gadget.dev);
+       dbg_remove_files(ci->dev);
 unreg_device:
        device_unregister(&ci->gadget.dev);
 put_transceiver:
@@ -1836,7 +1836,7 @@ static void udc_stop(struct ci13xxx *ci)
                if (ci->global_phy)
                        usb_put_phy(ci->transceiver);
        }
-       dbg_remove_files(&ci->gadget.dev);
+       dbg_remove_files(ci->dev);
        device_unregister(&ci->gadget.dev);
        /* my kobject is dynamic, I swear! */
        memset(&ci->gadget, 0, sizeof(ci->gadget));
index 5f0cb41..122d056 100644 (file)
@@ -56,6 +56,7 @@ MODULE_DEVICE_TABLE (usb, wdm_ids);
 #define WDM_RESPONDING         7
 #define WDM_SUSPENDING         8
 #define WDM_RESETTING          9
+#define WDM_OVERFLOW           10
 
 #define WDM_MAX                        16
 
@@ -155,6 +156,7 @@ static void wdm_in_callback(struct urb *urb)
 {
        struct wdm_device *desc = urb->context;
        int status = urb->status;
+       int length = urb->actual_length;
 
        spin_lock(&desc->iuspin);
        clear_bit(WDM_RESPONDING, &desc->flags);
@@ -185,9 +187,17 @@ static void wdm_in_callback(struct urb *urb)
        }
 
        desc->rerr = status;
-       desc->reslength = urb->actual_length;
-       memmove(desc->ubuf + desc->length, desc->inbuf, desc->reslength);
-       desc->length += desc->reslength;
+       if (length + desc->length > desc->wMaxCommand) {
+               /* The buffer would overflow */
+               set_bit(WDM_OVERFLOW, &desc->flags);
+       } else {
+               /* we may already be in overflow */
+               if (!test_bit(WDM_OVERFLOW, &desc->flags)) {
+                       memmove(desc->ubuf + desc->length, desc->inbuf, length);
+                       desc->length += length;
+                       desc->reslength = length;
+               }
+       }
 skip_error:
        wake_up(&desc->wait);
 
@@ -435,6 +445,11 @@ retry:
                        rv = -ENODEV;
                        goto err;
                }
+               if (test_bit(WDM_OVERFLOW, &desc->flags)) {
+                       clear_bit(WDM_OVERFLOW, &desc->flags);
+                       rv = -ENOBUFS;
+                       goto err;
+               }
                i++;
                if (file->f_flags & O_NONBLOCK) {
                        if (!test_bit(WDM_READ, &desc->flags)) {
@@ -478,6 +493,7 @@ retry:
                        spin_unlock_irq(&desc->iuspin);
                        goto retry;
                }
+
                if (!desc->reslength) { /* zero length read */
                        dev_dbg(&desc->intf->dev, "%s: zero length - clearing WDM_READ\n", __func__);
                        clear_bit(WDM_READ, &desc->flags);
@@ -1004,6 +1020,7 @@ static int wdm_post_reset(struct usb_interface *intf)
        struct wdm_device *desc = wdm_find_device(intf);
        int rv;
 
+       clear_bit(WDM_OVERFLOW, &desc->flags);
        clear_bit(WDM_RESETTING, &desc->flags);
        rv = recover_from_urb_loss(desc);
        mutex_unlock(&desc->wlock);
index cef4252..b6f4bad 100644 (file)
@@ -210,9 +210,14 @@ static int usb_acpi_find_device(struct device *dev, acpi_handle *handle)
        return 0;
 }
 
+static bool usb_acpi_bus_match(struct device *dev)
+{
+       return is_usb_device(dev) || is_usb_port(dev);
+}
+
 static struct acpi_bus_type usb_acpi_bus = {
-       .bus = &usb_bus_type,
-       .find_bridge = usb_acpi_find_device,
+       .name = "USB",
+       .match = usb_acpi_bus_match,
        .find_device = usb_acpi_find_device,
 };
 
index 9999094..ffa6b00 100644 (file)
@@ -583,6 +583,7 @@ static int dwc3_remove(struct platform_device *pdev)
                break;
        }
 
+       dwc3_free_event_buffers(dwc);
        dwc3_core_exit(dwc);
 
        return 0;
index b50da53..b082bec 100644 (file)
@@ -23,8 +23,6 @@
 #include <linux/usb/nop-usb-xceiv.h>
 #include <linux/of.h>
 
-#include "core.h"
-
 struct dwc3_exynos {
        struct platform_device  *dwc3;
        struct platform_device  *usb2_phy;
index 22f337f..afa05e3 100644 (file)
@@ -54,8 +54,6 @@
 #include <linux/usb/otg.h>
 #include <linux/usb/nop-usb-xceiv.h>
 
-#include "core.h"
-
 /*
  * All these registers belong to OMAP's Wrapper around the
  * DesignWare USB3 Core.
@@ -465,20 +463,20 @@ static int dwc3_omap_remove(struct platform_device *pdev)
        return 0;
 }
 
-static const struct of_device_id of_dwc3_matach[] = {
+static const struct of_device_id of_dwc3_match[] = {
        {
                "ti,dwc3",
        },
        { },
 };
-MODULE_DEVICE_TABLE(of, of_dwc3_matach);
+MODULE_DEVICE_TABLE(of, of_dwc3_match);
 
 static struct platform_driver dwc3_omap_driver = {
        .probe          = dwc3_omap_probe,
        .remove         = dwc3_omap_remove,
        .driver         = {
                .name   = "omap-dwc3",
-               .of_match_table = of_dwc3_matach,
+               .of_match_table = of_dwc3_match,
        },
 };
 
index 7d70f44..e8d7768 100644 (file)
@@ -45,8 +45,6 @@
 #include <linux/usb/otg.h>
 #include <linux/usb/nop-usb-xceiv.h>
 
-#include "core.h"
-
 /* FIXME define these in <linux/pci_ids.h> */
 #define PCI_VENDOR_ID_SYNOPSYS         0x16c3
 #define PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3        0xabcd
index d7da073..1d139ca 100644 (file)
@@ -891,7 +891,8 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
                                DWC3_TRBCTL_CONTROL_DATA);
        } else if (!IS_ALIGNED(req->request.length, dep->endpoint.maxpacket)
                        && (dep->number == 0)) {
-               u32             transfer_size;
+               u32     transfer_size;
+               u32     maxpacket;
 
                ret = usb_gadget_map_request(&dwc->gadget, &req->request,
                                dep->number);
@@ -902,8 +903,8 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
 
                WARN_ON(req->request.length > DWC3_EP0_BOUNCE_SIZE);
 
-               transfer_size = roundup(req->request.length,
-                               (u32) dep->endpoint.maxpacket);
+               maxpacket = dep->endpoint.maxpacket;
+               transfer_size = roundup(req->request.length, maxpacket);
 
                dwc->ep0_bounced = true;
 
index a04342f..82e160e 100644 (file)
@@ -2159,7 +2159,6 @@ static void dwc3_gadget_phy_suspend(struct dwc3 *dwc, u8 speed)
 
 static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc)
 {
-       struct dwc3_gadget_ep_cmd_params params;
        struct dwc3_ep          *dep;
        int                     ret;
        u32                     reg;
@@ -2167,8 +2166,6 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc)
 
        dev_vdbg(dwc->dev, "%s\n", __func__);
 
-       memset(&params, 0x00, sizeof(params));
-
        reg = dwc3_readl(dwc->regs, DWC3_DSTS);
        speed = reg & DWC3_DSTS_CONNECTSPD;
        dwc->speed = speed;
index 97a13c3..82fb225 100644 (file)
@@ -35,6 +35,12 @@ mv_udc-y                     := mv_udc_core.o
 obj-$(CONFIG_USB_FUSB300)      += fusb300_udc.o
 obj-$(CONFIG_USB_MV_U3D)       += mv_u3d_core.o
 
+# USB Functions
+obj-$(CONFIG_USB_F_ACM)                += f_acm.o
+f_ss_lb-y                      := f_loopback.o f_sourcesink.o
+obj-$(CONFIG_USB_F_SS_LB)      += f_ss_lb.o
+obj-$(CONFIG_USB_U_SERIAL)     += u_serial.o
+
 #
 # USB gadget drivers
 #
@@ -74,9 +80,3 @@ obj-$(CONFIG_USB_G_WEBCAM)    += g_webcam.o
 obj-$(CONFIG_USB_G_NCM)                += g_ncm.o
 obj-$(CONFIG_USB_G_ACM_MS)     += g_acm_ms.o
 obj-$(CONFIG_USB_GADGET_TARGET)        += tcm_usb_gadget.o
-
-# USB Functions
-obj-$(CONFIG_USB_F_ACM)                += f_acm.o
-f_ss_lb-y                      := f_loopback.o f_sourcesink.o
-obj-$(CONFIG_USB_F_SS_LB)      += f_ss_lb.o
-obj-$(CONFIG_USB_U_SERIAL)     += u_serial.o
index 7c821de..c0d62b2 100644 (file)
@@ -1757,10 +1757,7 @@ static const struct usb_gadget_driver composite_driver_template = {
 /**
  * usb_composite_probe() - register a composite driver
  * @driver: the driver to register
- * @bind: the callback used to allocate resources that are shared across the
- *     whole device, such as string IDs, and add its configurations using
- *     @usb_add_config().  This may fail by returning a negative errno
- *     value; it should return zero on successful initialization.
+ *
  * Context: single threaded during gadget setup
  *
  * This function is used to register drivers using the composite driver
index 38388d7..c377ff8 100644 (file)
@@ -1235,6 +1235,7 @@ static struct file_system_type ffs_fs_type = {
        .mount          = ffs_fs_mount,
        .kill_sb        = ffs_fs_kill_sb,
 };
+MODULE_ALIAS_FS("functionfs");
 
 
 /* Driver's main init/cleanup functions *************************************/
index f570e66..fa8ea4e 100644 (file)
@@ -418,6 +418,7 @@ static int audio_get_intf_req(struct usb_function *f,
 
        req->context = audio;
        req->complete = f_audio_complete;
+       len = min_t(size_t, sizeof(value), len);
        memcpy(req->buf, &value, len);
 
        return len;
index 8efd755..5bd930d 100644 (file)
@@ -1334,27 +1334,18 @@ static int imx_udc_start(struct usb_gadget *gadget,
                struct usb_gadget_driver *driver)
 {
        struct imx_udc_struct *imx_usb;
-       int retval;
 
        imx_usb = container_of(gadget, struct imx_udc_struct, gadget);
        /* first hook up the driver ... */
        imx_usb->driver = driver;
        imx_usb->gadget.dev.driver = &driver->driver;
 
-       retval = device_add(&imx_usb->gadget.dev);
-       if (retval)
-               goto fail;
-
        D_INI(imx_usb->dev, "<%s> registered gadget driver '%s'\n",
                __func__, driver->driver.name);
 
        imx_udc_enable(imx_usb);
 
        return 0;
-fail:
-       imx_usb->driver = NULL;
-       imx_usb->gadget.dev.driver = NULL;
-       return retval;
 }
 
 static int imx_udc_stop(struct usb_gadget *gadget,
@@ -1370,8 +1361,6 @@ static int imx_udc_stop(struct usb_gadget *gadget,
        imx_usb->gadget.dev.driver = NULL;
        imx_usb->driver = NULL;
 
-       device_del(&imx_usb->gadget.dev);
-
        D_INI(imx_usb->dev, "<%s> unregistered gadget driver '%s'\n",
                __func__, driver->driver.name);
 
@@ -1477,6 +1466,10 @@ static int __init imx_udc_probe(struct platform_device *pdev)
        imx_usb->gadget.dev.parent = &pdev->dev;
        imx_usb->gadget.dev.dma_mask = pdev->dev.dma_mask;
 
+       ret = device_add(&imx_usb->gadget.dev);
+       if (retval)
+               goto fail4;
+
        platform_set_drvdata(pdev, imx_usb);
 
        usb_init_data(imx_usb);
@@ -1488,9 +1481,11 @@ static int __init imx_udc_probe(struct platform_device *pdev)
 
        ret = usb_add_gadget_udc(&pdev->dev, &imx_usb->gadget);
        if (ret)
-               goto fail4;
+               goto fail5;
 
        return 0;
+fail5:
+       device_unregister(&imx_usb->gadget.dev);
 fail4:
        for (i = 0; i < IMX_USB_NB_EP + 1; i++)
                free_irq(imx_usb->usbd_int[i], imx_usb);
@@ -1514,6 +1509,7 @@ static int __exit imx_udc_remove(struct platform_device *pdev)
        int i;
 
        usb_del_gadget_udc(&imx_usb->gadget);
+       device_unregister(&imx_usb->gadget.dev);
        imx_udc_disable(imx_usb);
        del_timer(&imx_usb->timer);
 
index 8ac840f..e2b2e9c 100644 (file)
@@ -2105,6 +2105,7 @@ static struct file_system_type gadgetfs_type = {
        .mount          = gadgetfs_mount,
        .kill_sb        = gadgetfs_kill_sb,
 };
+MODULE_ALIAS_FS("gadgetfs");
 
 /*----------------------------------------------------------------------*/
 
index 06be85c..f844565 100644 (file)
@@ -62,6 +62,7 @@
 #define        DRIVER_VERSION  "4 October 2004"
 
 #define OMAP_DMA_USB_W2FC_TX0          29
+#define OMAP_DMA_USB_W2FC_RX0          26
 
 /*
  * The OMAP UDC needs _very_ early endpoint setup:  before enabling the
@@ -1310,7 +1311,7 @@ static int omap_pullup(struct usb_gadget *gadget, int is_on)
 }
 
 static int omap_udc_start(struct usb_gadget *g,
-               struct usb_gadget_driver *driver)
+               struct usb_gadget_driver *driver);
 static int omap_udc_stop(struct usb_gadget *g,
                struct usb_gadget_driver *driver);
 
index 2bbcdce..d0f3748 100644 (file)
@@ -1266,13 +1266,6 @@ static int pxa25x_udc_start(struct usb_gadget *g,
        dev->gadget.dev.driver = &driver->driver;
        dev->pullup = 1;
 
-       retval = device_add (&dev->gadget.dev);
-       if (retval) {
-               dev->driver = NULL;
-               dev->gadget.dev.driver = NULL;
-               return retval;
-       }
-
        /* ... then enable host detection and ep0; and we're ready
         * for set_configuration as well as eventual disconnect.
         */
@@ -1310,6 +1303,10 @@ stop_activity(struct pxa25x_udc *dev, struct usb_gadget_driver *driver)
        }
        del_timer_sync(&dev->timer);
 
+       /* report disconnect; the driver is already quiesced */
+       if (driver)
+               driver->disconnect(&dev->gadget);
+
        /* re-init driver-visible data structures */
        udc_reinit(dev);
 }
@@ -1331,7 +1328,6 @@ static int pxa25x_udc_stop(struct usb_gadget*g,
        dev->gadget.dev.driver = NULL;
        dev->driver = NULL;
 
-       device_del (&dev->gadget.dev);
        dump_state(dev);
 
        return 0;
@@ -2146,6 +2142,13 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev)
        dev->gadget.dev.parent = &pdev->dev;
        dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
 
+       retval = device_add(&dev->gadget.dev);
+       if (retval) {
+               dev->driver = NULL;
+               dev->gadget.dev.driver = NULL;
+               goto err_device_add;
+       }
+
        the_controller = dev;
        platform_set_drvdata(pdev, dev);
 
@@ -2196,6 +2199,8 @@ lubbock_fail0:
        free_irq(irq, dev);
 #endif
  err_irq1:
+       device_unregister(&dev->gadget.dev);
+ err_device_add:
        if (gpio_is_valid(dev->mach->gpio_pullup))
                gpio_free(dev->mach->gpio_pullup);
  err_gpio_pullup:
@@ -2217,10 +2222,11 @@ static int __exit pxa25x_udc_remove(struct platform_device *pdev)
 {
        struct pxa25x_udc *dev = platform_get_drvdata(pdev);
 
-       usb_del_gadget_udc(&dev->gadget);
        if (dev->driver)
                return -EBUSY;
 
+       usb_del_gadget_udc(&dev->gadget);
+       device_unregister(&dev->gadget.dev);
        dev->pullup = 0;
        pullup(dev);
 
index f7d2579..2fc8676 100644 (file)
@@ -1814,11 +1814,6 @@ static int pxa27x_udc_start(struct usb_gadget *g,
        udc->gadget.dev.driver = &driver->driver;
        dplus_pullup(udc, 1);
 
-       retval = device_add(&udc->gadget.dev);
-       if (retval) {
-               dev_err(udc->dev, "device_add error %d\n", retval);
-               goto fail;
-       }
        if (!IS_ERR_OR_NULL(udc->transceiver)) {
                retval = otg_set_peripheral(udc->transceiver->otg,
                                                &udc->gadget);
@@ -1876,7 +1871,6 @@ static int pxa27x_udc_stop(struct usb_gadget *g,
 
        udc->driver = NULL;
 
-       device_del(&udc->gadget.dev);
 
        if (!IS_ERR_OR_NULL(udc->transceiver))
                return otg_set_peripheral(udc->transceiver->otg, NULL);
@@ -2480,13 +2474,24 @@ static int __init pxa_udc_probe(struct platform_device *pdev)
                        driver_name, udc->irq, retval);
                goto err_irq;
        }
+
+       retval = device_add(&udc->gadget.dev);
+       if (retval) {
+               dev_err(udc->dev, "device_add error %d\n", retval);
+               goto err_dev_add;
+       }
+
        retval = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
        if (retval)
                goto err_add_udc;
 
        pxa_init_debugfs(udc);
+
        return 0;
+
 err_add_udc:
+       device_unregister(&udc->gadget.dev);
+err_dev_add:
        free_irq(udc->irq, udc);
 err_irq:
        iounmap(udc->regs);
@@ -2507,6 +2512,7 @@ static int __exit pxa_udc_remove(struct platform_device *_dev)
        int gpio = udc->mach->gpio_pullup;
 
        usb_del_gadget_udc(&udc->gadget);
+       device_del(&udc->gadget.dev);
        usb_gadget_unregister_driver(udc->driver);
        free_irq(udc->irq, udc);
        pxa_cleanup_debugfs(udc);
index fc07b43..08f8965 100644 (file)
@@ -1668,8 +1668,7 @@ static void s3c2410_udc_enable(struct s3c2410_udc *dev)
 static int s3c2410_udc_start(struct usb_gadget *g,
                struct usb_gadget_driver *driver)
 {
-       struct s3c2410_udc *udc = to_s3c2410(g)
-       int             retval;
+       struct s3c2410_udc *udc = to_s3c2410(g);
 
        dprintk(DEBUG_NORMAL, "%s() '%s'\n", __func__, driver->driver.name);
 
@@ -1677,22 +1676,10 @@ static int s3c2410_udc_start(struct usb_gadget *g,
        udc->driver = driver;
        udc->gadget.dev.driver = &driver->driver;
 
-       /* Bind the driver */
-       retval = device_add(&udc->gadget.dev);
-       if (retval) {
-               dev_err(&udc->gadget.dev, "Error in device_add() : %d\n", retval);
-               goto register_error;
-       }
-
        /* Enable udc */
        s3c2410_udc_enable(udc);
 
        return 0;
-
-register_error:
-       udc->driver = NULL;
-       udc->gadget.dev.driver = NULL;
-       return retval;
 }
 
 static int s3c2410_udc_stop(struct usb_gadget *g,
@@ -1700,7 +1687,6 @@ static int s3c2410_udc_stop(struct usb_gadget *g,
 {
        struct s3c2410_udc *udc = to_s3c2410(g);
 
-       device_del(&udc->gadget.dev);
        udc->driver = NULL;
 
        /* Disable udc */
@@ -1842,6 +1828,13 @@ static int s3c2410_udc_probe(struct platform_device *pdev)
        udc->gadget.dev.parent = &pdev->dev;
        udc->gadget.dev.dma_mask = pdev->dev.dma_mask;
 
+       /* Bind the driver */
+       retval = device_add(&udc->gadget.dev);
+       if (retval) {
+               dev_err(&udc->gadget.dev, "Error in device_add() : %d\n", retval);
+               goto err_device_add;
+       }
+
        the_controller = udc;
        platform_set_drvdata(pdev, udc);
 
@@ -1930,6 +1923,8 @@ err_gpio_claim:
 err_int:
        free_irq(IRQ_USBD, udc);
 err_map:
+       device_unregister(&udc->gadget.dev);
+err_device_add:
        iounmap(base_addr);
 err_mem:
        release_mem_region(rsrc_start, rsrc_len);
@@ -1947,10 +1942,11 @@ static int s3c2410_udc_remove(struct platform_device *pdev)
 
        dev_dbg(&pdev->dev, "%s()\n", __func__);
 
-       usb_del_gadget_udc(&udc->gadget);
        if (udc->driver)
                return -EBUSY;
 
+       usb_del_gadget_udc(&udc->gadget);
+       device_unregister(&udc->gadget.dev);
        debugfs_remove(udc->regs_info);
 
        if (udc_info && !udc_info->udc_command &&
index e0c5e88..c7d460f 100644 (file)
@@ -240,8 +240,11 @@ static int gaudio_open_snd_dev(struct gaudio *card)
        snd = &card->playback;
        snd->filp = filp_open(fn_play, O_WRONLY, 0);
        if (IS_ERR(snd->filp)) {
+               int ret = PTR_ERR(snd->filp);
+
                ERROR(card, "No such PCM playback device: %s\n", fn_play);
                snd->filp = NULL;
+               return ret;
        }
        pcm_file = snd->filp->private_data;
        snd->substream = pcm_file->substream;
index b416a3f..5726cb1 100644 (file)
@@ -748,11 +748,9 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
                /* guard against (alleged) silicon errata */
                if (cmd & CMD_IAAD)
                        ehci_dbg(ehci, "IAA with IAAD still set?\n");
-               if (ehci->async_iaa) {
+               if (ehci->async_iaa)
                        COUNT(ehci->stats.iaa);
-                       end_unlink_async(ehci);
-               } else
-                       ehci_dbg(ehci, "IAA with nothing unlinked?\n");
+               end_unlink_async(ehci);
        }
 
        /* remote wakeup [4.3.1] */
index fd252f0..5464665 100644 (file)
@@ -135,7 +135,7 @@ qh_refresh (struct ehci_hcd *ehci, struct ehci_qh *qh)
                 * qtd is updated in qh_completions(). Update the QH
                 * overlay here.
                 */
-               if (cpu_to_hc32(ehci, qtd->qtd_dma) == qh->hw->hw_current) {
+               if (qh->hw->hw_token & ACTIVE_BIT(ehci)) {
                        qh->hw->hw_qtd_next = qtd->hw_next;
                        qtd = NULL;
                }
@@ -449,11 +449,19 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
                        else if (last_status == -EINPROGRESS && !urb->unlinked)
                                continue;
 
-                       /* qh unlinked; token in overlay may be most current */
-                       if (state == QH_STATE_IDLE
-                                       && cpu_to_hc32(ehci, qtd->qtd_dma)
-                                               == hw->hw_current) {
+                       /*
+                        * If this was the active qtd when the qh was unlinked
+                        * and the overlay's token is active, then the overlay
+                        * hasn't been written back to the qtd yet so use its
+                        * token instead of the qtd's.  After the qtd is
+                        * processed and removed, the overlay won't be valid
+                        * any more.
+                        */
+                       if (state == QH_STATE_IDLE &&
+                                       qh->qtd_list.next == &qtd->qtd_list &&
+                                       (hw->hw_token & ACTIVE_BIT(ehci))) {
                                token = hc32_to_cpu(ehci, hw->hw_token);
+                               hw->hw_token &= ~ACTIVE_BIT(ehci);
 
                                /* An unlink may leave an incomplete
                                 * async transaction in the TT buffer.
@@ -1170,7 +1178,7 @@ static void single_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh)
        struct ehci_qh          *prev;
 
        /* Add to the end of the list of QHs waiting for the next IAAD */
-       qh->qh_state = QH_STATE_UNLINK;
+       qh->qh_state = QH_STATE_UNLINK_WAIT;
        if (ehci->async_unlink)
                ehci->async_unlink_last->unlink_next = qh;
        else
@@ -1213,9 +1221,19 @@ static void start_iaa_cycle(struct ehci_hcd *ehci, bool nested)
 
                /* Do only the first waiting QH (nVidia bug?) */
                qh = ehci->async_unlink;
-               ehci->async_iaa = qh;
-               ehci->async_unlink = qh->unlink_next;
-               qh->unlink_next = NULL;
+
+               /*
+                * Intel (?) bug: The HC can write back the overlay region
+                * even after the IAA interrupt occurs.  In self-defense,
+                * always go through two IAA cycles for each QH.
+                */
+               if (qh->qh_state == QH_STATE_UNLINK_WAIT) {
+                       qh->qh_state = QH_STATE_UNLINK;
+               } else {
+                       ehci->async_iaa = qh;
+                       ehci->async_unlink = qh->unlink_next;
+                       qh->unlink_next = NULL;
+               }
 
                /* Make sure the unlinks are all visible to the hardware */
                wmb();
index 45b19e2..05e5143 100644 (file)
@@ -7,11 +7,6 @@
 config USB_MUSB_HDRC
        tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)'
        depends on USB && USB_GADGET
-       select NOP_USB_XCEIV if (ARCH_DAVINCI || MACH_OMAP3EVM || BLACKFIN)
-       select NOP_USB_XCEIV if (SOC_TI81XX || SOC_AM33XX)
-       select TWL4030_USB if MACH_OMAP_3430SDP
-       select TWL6030_USB if MACH_OMAP_4430SDP || MACH_OMAP4_PANDA
-       select OMAP_CONTROL_USB if MACH_OMAP_4430SDP || MACH_OMAP4_PANDA
        select USB_OTG_UTILS
        help
          Say Y here if your system has a dual role high speed USB
index 60b41cc..daec6e0 100644 (file)
@@ -1624,8 +1624,6 @@ EXPORT_SYMBOL_GPL(musb_dma_completion);
 
 /*-------------------------------------------------------------------------*/
 
-#ifdef CONFIG_SYSFS
-
 static ssize_t
 musb_mode_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
@@ -1742,8 +1740,6 @@ static const struct attribute_group musb_attr_group = {
        .attrs = musb_attributes,
 };
 
-#endif /* sysfs */
-
 /* Only used to provide driver mode change events */
 static void musb_irq_work(struct work_struct *data)
 {
@@ -1968,11 +1964,9 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
        if (status < 0)
                goto fail4;
 
-#ifdef CONFIG_SYSFS
        status = sysfs_create_group(&musb->controller->kobj, &musb_attr_group);
        if (status)
                goto fail5;
-#endif
 
        pm_runtime_put(musb->controller);
 
index 1762354..1a42a45 100644 (file)
@@ -51,7 +51,7 @@ struct omap2430_glue {
 };
 #define glue_to_musb(g)                platform_get_drvdata(g->musb)
 
-struct omap2430_glue           *_glue;
+static struct omap2430_glue    *_glue;
 
 static struct timer_list musb_idle_timer;
 
@@ -237,9 +237,13 @@ void omap_musb_mailbox(enum omap_musb_vbus_id_status status)
 {
        struct omap2430_glue    *glue = _glue;
 
-       if (glue && glue_to_musb(glue)) {
-               glue->status = status;
-       } else {
+       if (!glue) {
+               pr_err("%s: musb core is not yet initialized\n", __func__);
+               return;
+       }
+       glue->status = status;
+
+       if (!glue_to_musb(glue)) {
                pr_err("%s: musb core is not yet ready\n", __func__);
                return;
        }
index e181439..2bd03d2 100644 (file)
@@ -130,7 +130,7 @@ struct usb_phy *usb_get_phy(enum usb_phy_type type)
        spin_lock_irqsave(&phy_lock, flags);
 
        phy = __usb_find_phy(&phy_list, type);
-       if (IS_ERR(phy)) {
+       if (IS_ERR(phy) || !try_module_get(phy->dev->driver->owner)) {
                pr_err("unable to find transceiver of type %s\n",
                        usb_phy_type_string(type));
                goto err0;
@@ -228,7 +228,7 @@ struct usb_phy *usb_get_phy_dev(struct device *dev, u8 index)
        spin_lock_irqsave(&phy_lock, flags);
 
        phy = __usb_find_phy_dev(dev, &phy_bind_list, index);
-       if (IS_ERR(phy)) {
+       if (IS_ERR(phy) || !try_module_get(phy->dev->driver->owner)) {
                pr_err("unable to find transceiver\n");
                goto err0;
        }
@@ -301,8 +301,12 @@ EXPORT_SYMBOL(devm_usb_put_phy);
  */
 void usb_put_phy(struct usb_phy *x)
 {
-       if (x)
+       if (x) {
+               struct module *owner = x->dev->driver->owner;
+
                put_device(x->dev);
+               module_put(owner);
+       }
 }
 EXPORT_SYMBOL(usb_put_phy);
 
index 5323b71..1419ced 100644 (file)
@@ -219,32 +219,26 @@ static int omap_control_usb_probe(struct platform_device *pdev)
 
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
                "control_dev_conf");
-       control_usb->dev_conf = devm_request_and_ioremap(&pdev->dev, res);
-       if (!control_usb->dev_conf) {
-               dev_err(&pdev->dev, "Failed to obtain io memory\n");
-               return -EADDRNOTAVAIL;
-       }
+       control_usb->dev_conf = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(control_usb->dev_conf))
+               return PTR_ERR(control_usb->dev_conf);
 
        if (control_usb->type == OMAP_CTRL_DEV_TYPE1) {
                res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
                        "otghs_control");
-               control_usb->otghs_control = devm_request_and_ioremap(
+               control_usb->otghs_control = devm_ioremap_resource(
                        &pdev->dev, res);
-               if (!control_usb->otghs_control) {
-                       dev_err(&pdev->dev, "Failed to obtain io memory\n");
-                       return -EADDRNOTAVAIL;
-               }
+               if (IS_ERR(control_usb->otghs_control))
+                       return PTR_ERR(control_usb->otghs_control);
        }
 
        if (control_usb->type == OMAP_CTRL_DEV_TYPE2) {
                res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
                        "phy_power_usb");
-               control_usb->phy_power = devm_request_and_ioremap(
+               control_usb->phy_power = devm_ioremap_resource(
                        &pdev->dev, res);
-               if (!control_usb->phy_power) {
-                       dev_dbg(&pdev->dev, "Failed to obtain io memory\n");
-                       return -EADDRNOTAVAIL;
-               }
+               if (IS_ERR(control_usb->phy_power))
+                       return PTR_ERR(control_usb->phy_power);
 
                control_usb->sys_clk = devm_clk_get(control_usb->dev,
                        "sys_clkin");
index fadc0c2..a6e60b1 100644 (file)
@@ -212,11 +212,9 @@ static int omap_usb3_probe(struct platform_device *pdev)
        }
 
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pll_ctrl");
-       phy->pll_ctrl_base = devm_request_and_ioremap(&pdev->dev, res);
-       if (!phy->pll_ctrl_base) {
-               dev_err(&pdev->dev, "ioremap of pll_ctrl failed\n");
-               return -ENOMEM;
-       }
+       phy->pll_ctrl_base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(phy->pll_ctrl_base))
+               return PTR_ERR(phy->pll_ctrl_base);
 
        phy->dev                = &pdev->dev;
 
index 6ea5537..967101e 100644 (file)
@@ -787,11 +787,9 @@ static int samsung_usbphy_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
-       phy_base = devm_request_and_ioremap(dev, phy_mem);
-       if (!phy_base) {
-               dev_err(dev, "%s: register mapping failed\n", __func__);
-               return -ENXIO;
-       }
+       phy_base = devm_ioremap_resource(dev, phy_mem);
+       if (IS_ERR(phy_base))
+               return PTR_ERR(phy_base);
 
        sphy = devm_kzalloc(dev, sizeof(*sphy), GFP_KERNEL);
        if (!sphy)
index edc0f0d..4747d1c 100644 (file)
@@ -85,6 +85,7 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(0x10C4, 0x813F) }, /* Tams Master Easy Control */
        { USB_DEVICE(0x10C4, 0x814A) }, /* West Mountain Radio RIGblaster P&P */
        { USB_DEVICE(0x10C4, 0x814B) }, /* West Mountain Radio RIGtalk */
+       { USB_DEVICE(0x2405, 0x0003) }, /* West Mountain Radio RIGblaster Advantage */
        { USB_DEVICE(0x10C4, 0x8156) }, /* B&G H3000 link cable */
        { USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */
        { USB_DEVICE(0x10C4, 0x815F) }, /* Timewave HamLinkUSB */
@@ -150,6 +151,25 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(0x1BE3, 0x07A6) }, /* WAGO 750-923 USB Service Cable */
        { USB_DEVICE(0x1E29, 0x0102) }, /* Festo CPX-USB */
        { USB_DEVICE(0x1E29, 0x0501) }, /* Festo CMSP */
+       { USB_DEVICE(0x1FB9, 0x0100) }, /* Lake Shore Model 121 Current Source */
+       { USB_DEVICE(0x1FB9, 0x0200) }, /* Lake Shore Model 218A Temperature Monitor */
+       { USB_DEVICE(0x1FB9, 0x0201) }, /* Lake Shore Model 219 Temperature Monitor */
+       { USB_DEVICE(0x1FB9, 0x0202) }, /* Lake Shore Model 233 Temperature Transmitter */
+       { USB_DEVICE(0x1FB9, 0x0203) }, /* Lake Shore Model 235 Temperature Transmitter */
+       { USB_DEVICE(0x1FB9, 0x0300) }, /* Lake Shore Model 335 Temperature Controller */
+       { USB_DEVICE(0x1FB9, 0x0301) }, /* Lake Shore Model 336 Temperature Controller */
+       { USB_DEVICE(0x1FB9, 0x0302) }, /* Lake Shore Model 350 Temperature Controller */
+       { USB_DEVICE(0x1FB9, 0x0303) }, /* Lake Shore Model 371 AC Bridge */
+       { USB_DEVICE(0x1FB9, 0x0400) }, /* Lake Shore Model 411 Handheld Gaussmeter */
+       { USB_DEVICE(0x1FB9, 0x0401) }, /* Lake Shore Model 425 Gaussmeter */
+       { USB_DEVICE(0x1FB9, 0x0402) }, /* Lake Shore Model 455A Gaussmeter */
+       { USB_DEVICE(0x1FB9, 0x0403) }, /* Lake Shore Model 475A Gaussmeter */
+       { USB_DEVICE(0x1FB9, 0x0404) }, /* Lake Shore Model 465 Three Axis Gaussmeter */
+       { USB_DEVICE(0x1FB9, 0x0600) }, /* Lake Shore Model 625A Superconducting MPS */
+       { USB_DEVICE(0x1FB9, 0x0601) }, /* Lake Shore Model 642A Magnet Power Supply */
+       { USB_DEVICE(0x1FB9, 0x0602) }, /* Lake Shore Model 648 Magnet Power Supply */
+       { USB_DEVICE(0x1FB9, 0x0700) }, /* Lake Shore Model 737 VSM Controller */
+       { USB_DEVICE(0x1FB9, 0x0701) }, /* Lake Shore Model 776 Hall Matrix */
        { USB_DEVICE(0x3195, 0xF190) }, /* Link Instruments MSO-19 */
        { USB_DEVICE(0x3195, 0xF280) }, /* Link Instruments MSO-28 */
        { USB_DEVICE(0x3195, 0xF281) }, /* Link Instruments MSO-28 */
index f7d339d..558adfc 100644 (file)
@@ -341,6 +341,8 @@ static void option_instat_callback(struct urb *urb);
 #define CINTERION_PRODUCT_EU3_E                        0x0051
 #define CINTERION_PRODUCT_EU3_P                        0x0052
 #define CINTERION_PRODUCT_PH8                  0x0053
+#define CINTERION_PRODUCT_AH6                  0x0055
+#define CINTERION_PRODUCT_PLS8                 0x0060
 
 /* Olivetti products */
 #define OLIVETTI_VENDOR_ID                     0x0b3c
@@ -579,6 +581,7 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(QUANTA_VENDOR_ID, 0xea42),
                .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1c05, USB_CLASS_COMM, 0x02, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1c1f, USB_CLASS_COMM, 0x02, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1c23, USB_CLASS_COMM, 0x02, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E173, 0xff, 0xff, 0xff),
                .driver_info = (kernel_ulong_t) &net_intf1_blacklist },
@@ -1260,6 +1263,8 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_E) },
        { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_P) },
        { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PH8) },
+       { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_AH6) },
+       { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PLS8) },
        { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_HC28_MDM) }, 
        { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_HC28_MDMNET) },
        { USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC25_MDM) },
index 9b1b96f..31f81c3 100644 (file)
@@ -69,6 +69,7 @@ static struct usb_device_id id_table[] = {
        { USB_VENDOR_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, 0xff, 0xfd, 0xff) },  /* NMEA */
        { USB_VENDOR_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, 0xff, 0xfe, 0xff) },  /* WMC */
        { USB_VENDOR_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, 0xff, 0xff, 0xff) },  /* DIAG */
+       { USB_DEVICE_AND_INTERFACE_INFO(0x1fac, 0x0151, 0xff, 0xff, 0xff) },
        { },
 };
 MODULE_DEVICE_TABLE(usb, id_table);
index 2466254..59b32b7 100644 (file)
@@ -197,12 +197,15 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
 
        if (is_gobi1k) {
                /* Gobi 1K USB layout:
-                * 0: serial port (doesn't respond)
+                * 0: DM/DIAG (use libqcdm from ModemManager for communication)
                 * 1: serial port (doesn't respond)
                 * 2: AT-capable modem port
                 * 3: QMI/net
                 */
-               if (ifnum == 2)
+               if (ifnum == 0) {
+                       dev_dbg(dev, "Gobi 1K DM/DIAG interface found\n");
+                       altsetting = 1;
+               } else if (ifnum == 2)
                        dev_dbg(dev, "Modem port found\n");
                else
                        altsetting = -1;
index 00e6c9b..d643a4d 100644 (file)
@@ -661,7 +661,9 @@ void qt2_process_read_urb(struct urb *urb)
                                                 __func__);
                                        break;
                                }
-                               tty_flip_buffer_push(&port->port);
+
+                               if (port_priv->is_open)
+                                       tty_flip_buffer_push(&port->port);
 
                                newport = *(ch + 3);
 
@@ -704,7 +706,8 @@ void qt2_process_read_urb(struct urb *urb)
                tty_insert_flip_string(&port->port, ch, 1);
        }
 
-       tty_flip_buffer_push(&port->port);
+       if (port_priv->is_open)
+               tty_flip_buffer_push(&port->port);
 }
 
 static void qt2_write_bulk_callback(struct urb *urb)
index 7ab9046..105d900 100644 (file)
@@ -92,8 +92,8 @@ int usb_stor_ucr61s2b_init(struct us_data *us)
        return 0;
 }
 
-/* This places the HUAWEI usb dongles in multi-port mode */
-static int usb_stor_huawei_feature_init(struct us_data *us)
+/* This places the HUAWEI E220 devices in multi-port mode */
+int usb_stor_huawei_e220_init(struct us_data *us)
 {
        int result;
 
@@ -104,75 +104,3 @@ static int usb_stor_huawei_feature_init(struct us_data *us)
        US_DEBUGP("Huawei mode set result is %d\n", result);
        return 0;
 }
-
-/*
- * It will send a scsi switch command called rewind' to huawei dongle.
- * When the dongle receives this command at the first time,
- * it will reboot immediately. After rebooted, it will ignore this command.
- * So it is  unnecessary to read its response.
- */
-static int usb_stor_huawei_scsi_init(struct us_data *us)
-{
-       int result = 0;
-       int act_len = 0;
-       struct bulk_cb_wrap *bcbw = (struct bulk_cb_wrap *) us->iobuf;
-       char rewind_cmd[] = {0x11, 0x06, 0x20, 0x00, 0x00, 0x01, 0x01, 0x00,
-                       0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-
-       bcbw->Signature = cpu_to_le32(US_BULK_CB_SIGN);
-       bcbw->Tag = 0;
-       bcbw->DataTransferLength = 0;
-       bcbw->Flags = bcbw->Lun = 0;
-       bcbw->Length = sizeof(rewind_cmd);
-       memset(bcbw->CDB, 0, sizeof(bcbw->CDB));
-       memcpy(bcbw->CDB, rewind_cmd, sizeof(rewind_cmd));
-
-       result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, bcbw,
-                                       US_BULK_CB_WRAP_LEN, &act_len);
-       US_DEBUGP("transfer actual length=%d, result=%d\n", act_len, result);
-       return result;
-}
-
-/*
- * It tries to find the supported Huawei USB dongles.
- * In Huawei, they assign the following product IDs
- * for all of their mobile broadband dongles,
- * including the new dongles in the future.
- * So if the product ID is not included in this list,
- * it means it is not Huawei's mobile broadband dongles.
- */
-static int usb_stor_huawei_dongles_pid(struct us_data *us)
-{
-       struct usb_interface_descriptor *idesc;
-       int idProduct;
-
-       idesc = &us->pusb_intf->cur_altsetting->desc;
-       idProduct = le16_to_cpu(us->pusb_dev->descriptor.idProduct);
-       /* The first port is CDROM,
-        * means the dongle in the single port mode,
-        * and a switch command is required to be sent. */
-       if (idesc && idesc->bInterfaceNumber == 0) {
-               if ((idProduct == 0x1001)
-                       || (idProduct == 0x1003)
-                       || (idProduct == 0x1004)
-                       || (idProduct >= 0x1401 && idProduct <= 0x1500)
-                       || (idProduct >= 0x1505 && idProduct <= 0x1600)
-                       || (idProduct >= 0x1c02 && idProduct <= 0x2202)) {
-                       return 1;
-               }
-       }
-       return 0;
-}
-
-int usb_stor_huawei_init(struct us_data *us)
-{
-       int result = 0;
-
-       if (usb_stor_huawei_dongles_pid(us)) {
-               if (le16_to_cpu(us->pusb_dev->descriptor.idProduct) >= 0x1446)
-                       result = usb_stor_huawei_scsi_init(us);
-               else
-                       result = usb_stor_huawei_feature_init(us);
-       }
-       return result;
-}
index 5376d4f..529327f 100644 (file)
@@ -46,5 +46,5 @@ int usb_stor_euscsi_init(struct us_data *us);
  * flash reader */
 int usb_stor_ucr61s2b_init(struct us_data *us);
 
-/* This places the HUAWEI usb dongles in multi-port mode */
-int usb_stor_huawei_init(struct us_data *us);
+/* This places the HUAWEI E220 devices in multi-port mode */
+int usb_stor_huawei_e220_init(struct us_data *us);
index 72923b5..da04a07 100644 (file)
  * as opposed to devices that do something strangely or wrongly.
  */
 
+/* In-kernel mode switching is deprecated.  Do not add new devices to
+ * this list for the sole purpose of switching them to a different
+ * mode.  Existing userspace solutions are superior.
+ *
+ * New mode switching devices should instead be added to the database
+ * maintained at http://www.draisberghof.de/usb_modeswitch/
+ */
+
 #if !defined(CONFIG_USB_STORAGE_SDDR09) && \
                !defined(CONFIG_USB_STORAGE_SDDR09_MODULE)
 #define NO_SDDR09
@@ -1527,10 +1535,335 @@ UNUSUAL_DEV(  0x1210, 0x0003, 0x0100, 0x0100,
 /* Reported by fangxiaozhi <huananhu@huawei.com>
  * This brings the HUAWEI data card devices into multi-port mode
  */
-UNUSUAL_VENDOR_INTF(0x12d1, 0x08, 0x06, 0x50,
+UNUSUAL_DEV(  0x12d1, 0x1001, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1003, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1004, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1401, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1402, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1403, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1404, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1405, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1406, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1407, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1408, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1409, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x140A, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x140B, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x140C, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x140D, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x140E, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x140F, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1410, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1411, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1412, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1413, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1414, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1415, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1416, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1417, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1418, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1419, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x141A, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x141B, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x141C, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x141D, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x141E, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x141F, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1420, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1421, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1422, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1423, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1424, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1425, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1426, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1427, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1428, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1429, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x142A, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x142B, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x142C, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x142D, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x142E, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x142F, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1430, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1431, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1432, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1433, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1434, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1435, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1436, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1437, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1438, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1439, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x143A, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x143B, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x143C, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x143D, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x143E, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x143F, 0x0000, 0x0000,
                "HUAWEI MOBILE",
                "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_init,
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
                0),
 
 /* Reported by Vilius Bilinkevicius <vilisas AT xxx DOT lt) */
index ed4cad8..4a5f2cd 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/lcd.h>
 #include <linux/gpio.h>
 
+#include <mach/hardware.h>
 #include <mach/board-ams-delta.h>
 
 #include "omapfb.h"
index 3aa62da..7fbe04b 100644 (file)
 #include <linux/platform_device.h>
 
 #include <asm/gpio.h>
+
+#include <mach/hardware.h>
 #include <mach/mux.h>
+
 #include "omapfb.h"
 
 static int osk_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
index d39dfa4..46d9701 100644 (file)
@@ -47,11 +47,13 @@ static u8 w1_gpio_read_bit(void *data)
        return gpio_get_value(pdata->pin) ? 1 : 0;
 }
 
+#if defined(CONFIG_OF)
 static struct of_device_id w1_gpio_dt_ids[] = {
        { .compatible = "w1-gpio" },
        {}
 };
 MODULE_DEVICE_TABLE(of, w1_gpio_dt_ids);
+#endif
 
 static int w1_gpio_probe_dt(struct platform_device *pdev)
 {
@@ -158,7 +160,7 @@ static int w1_gpio_probe(struct platform_device *pdev)
        return err;
 }
 
-static int __exit w1_gpio_remove(struct platform_device *pdev)
+static int w1_gpio_remove(struct platform_device *pdev)
 {
        struct w1_bus_master *master = platform_get_drvdata(pdev);
        struct w1_gpio_platform_data *pdata = pdev->dev.platform_data;
@@ -210,7 +212,7 @@ static struct platform_driver w1_gpio_driver = {
                .of_match_table = of_match_ptr(w1_gpio_dt_ids),
        },
        .probe = w1_gpio_probe,
-       .remove = __exit_p(w1_gpio_remove),
+       .remove = w1_gpio_remove,
        .suspend = w1_gpio_suspend,
        .resume = w1_gpio_resume,
 };
index 7994d93..7ce277d 100644 (file)
@@ -924,7 +924,8 @@ void w1_search(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb
                        tmp64 = (triplet_ret >> 2);
                        rn |= (tmp64 << i);
 
-                       if (kthread_should_stop()) {
+                       /* ensure we're called from kthread and not by netlink callback */
+                       if (!dev->priv && kthread_should_stop()) {
                                mutex_unlock(&dev->bus_mutex);
                                dev_dbg(&dev->dev, "Abort w1_search\n");
                                return;
index 316df65..f3278a6 100644 (file)
@@ -500,16 +500,16 @@ static int __init xen_acpi_processor_init(void)
        (void)acpi_processor_preregister_performance(acpi_perf_data);
 
        for_each_possible_cpu(i) {
+               struct acpi_processor *pr;
                struct acpi_processor_performance *perf;
 
+               pr = per_cpu(processors, i);
                perf = per_cpu_ptr(acpi_perf_data, i);
-               rc = acpi_processor_register_performance(perf, i);
+               pr->performance = perf;
+               rc = acpi_processor_get_performance_info(pr);
                if (rc)
                        goto err_out;
        }
-       rc = acpi_processor_notify_smm(THIS_MODULE);
-       if (rc)
-               goto err_unregister;
 
        for_each_possible_cpu(i) {
                struct acpi_processor *_pr;
index 37c1f82..b98cf0c 100644 (file)
@@ -113,7 +113,8 @@ void xen_pcibk_reset_device(struct pci_dev *dev)
                if (dev->msi_enabled)
                        pci_disable_msi(dev);
 #endif
-               pci_disable_device(dev);
+               if (pci_is_enabled(dev))
+                       pci_disable_device(dev);
 
                pci_write_config_word(dev, PCI_COMMAND, 0);
 
index d85e411..bbef194 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/export.h>
 #include <linux/types.h>
 #include <linux/acpi.h>
-#include <acpi/acpi_drivers.h>
 #include <xen/acpi.h>
 
 #ifdef CONFIG_ACPI
index ec0abb6..7167987 100644 (file)
@@ -75,6 +75,7 @@ static struct file_system_type xenfs_type = {
        .mount =        xenfs_mount,
        .kill_sb =      kill_litter_super,
 };
+MODULE_ALIAS_FS("xenfs");
 
 static int __init xenfs_init(void)
 {
index 91dad63..2756dcd 100644 (file)
@@ -365,3 +365,4 @@ struct file_system_type v9fs_fs_type = {
        .owner = THIS_MODULE,
        .fs_flags = FS_RENAME_DOES_D_MOVE,
 };
+MODULE_ALIAS_FS("9p");
index d571229..0ff4bae 100644 (file)
@@ -524,6 +524,7 @@ static struct file_system_type adfs_fs_type = {
        .kill_sb        = kill_block_super,
        .fs_flags       = FS_REQUIRES_DEV,
 };
+MODULE_ALIAS_FS("adfs");
 
 static int __init init_adfs_fs(void)
 {
index b84dc73..45161a8 100644 (file)
@@ -622,6 +622,7 @@ static struct file_system_type affs_fs_type = {
        .kill_sb        = kill_block_super,
        .fs_flags       = FS_REQUIRES_DEV,
 };
+MODULE_ALIAS_FS("affs");
 
 static int __init init_affs_fs(void)
 {
index 7c31ec3..c486155 100644 (file)
@@ -45,6 +45,7 @@ struct file_system_type afs_fs_type = {
        .kill_sb        = afs_kill_super,
        .fs_flags       = 0,
 };
+MODULE_ALIAS_FS("afs");
 
 static const struct super_operations afs_super_ops = {
        .statfs         = afs_statfs,
index cddc74b..b3db517 100644 (file)
@@ -26,6 +26,7 @@ static struct file_system_type autofs_fs_type = {
        .mount          = autofs_mount,
        .kill_sb        = autofs4_kill_sb,
 };
+MODULE_ALIAS_FS("autofs");
 
 static int __init init_autofs4_fs(void)
 {
index c8f4e25..8615ee8 100644 (file)
@@ -951,6 +951,7 @@ static struct file_system_type befs_fs_type = {
        .kill_sb        = kill_block_super,
        .fs_flags       = FS_REQUIRES_DEV,      
 };
+MODULE_ALIAS_FS("befs");
 
 static int __init
 init_befs_fs(void)
index 737aaa3..5e376bb 100644 (file)
@@ -473,6 +473,7 @@ static struct file_system_type bfs_fs_type = {
        .kill_sb        = kill_block_super,
        .fs_flags       = FS_REQUIRES_DEV,
 };
+MODULE_ALIAS_FS("bfs");
 
 static int __init init_bfs_fs(void)
 {
index fecbbf3..751df5e 100644 (file)
@@ -720,6 +720,7 @@ static struct file_system_type bm_fs_type = {
        .mount          = bm_mount,
        .kill_sb        = kill_litter_super,
 };
+MODULE_ALIAS_FS("binfmt_misc");
 
 static int __init init_misc_binfmt(void)
 {
index 0b278b1..14fce27 100644 (file)
@@ -22,8 +22,9 @@
 #include "disk-io.h"
 #include "transaction.h"
 
-#define BTRFS_DELAYED_WRITEBACK                400
-#define BTRFS_DELAYED_BACKGROUND       100
+#define BTRFS_DELAYED_WRITEBACK                512
+#define BTRFS_DELAYED_BACKGROUND       128
+#define BTRFS_DELAYED_BATCH            16
 
 static struct kmem_cache *delayed_node_cache;
 
@@ -494,6 +495,15 @@ static int __btrfs_add_delayed_deletion_item(struct btrfs_delayed_node *node,
                                        BTRFS_DELAYED_DELETION_ITEM);
 }
 
+static void finish_one_item(struct btrfs_delayed_root *delayed_root)
+{
+       int seq = atomic_inc_return(&delayed_root->items_seq);
+       if ((atomic_dec_return(&delayed_root->items) <
+           BTRFS_DELAYED_BACKGROUND || seq % BTRFS_DELAYED_BATCH == 0) &&
+           waitqueue_active(&delayed_root->wait))
+               wake_up(&delayed_root->wait);
+}
+
 static void __btrfs_remove_delayed_item(struct btrfs_delayed_item *delayed_item)
 {
        struct rb_root *root;
@@ -512,10 +522,8 @@ static void __btrfs_remove_delayed_item(struct btrfs_delayed_item *delayed_item)
 
        rb_erase(&delayed_item->rb_node, root);
        delayed_item->delayed_node->count--;
-       if (atomic_dec_return(&delayed_root->items) <
-           BTRFS_DELAYED_BACKGROUND &&
-           waitqueue_active(&delayed_root->wait))
-               wake_up(&delayed_root->wait);
+
+       finish_one_item(delayed_root);
 }
 
 static void btrfs_release_delayed_item(struct btrfs_delayed_item *item)
@@ -1056,10 +1064,7 @@ static void btrfs_release_delayed_inode(struct btrfs_delayed_node *delayed_node)
                delayed_node->count--;
 
                delayed_root = delayed_node->root->fs_info->delayed_root;
-               if (atomic_dec_return(&delayed_root->items) <
-                   BTRFS_DELAYED_BACKGROUND &&
-                   waitqueue_active(&delayed_root->wait))
-                       wake_up(&delayed_root->wait);
+               finish_one_item(delayed_root);
        }
 }
 
@@ -1304,35 +1309,44 @@ void btrfs_remove_delayed_node(struct inode *inode)
        btrfs_release_delayed_node(delayed_node);
 }
 
-struct btrfs_async_delayed_node {
-       struct btrfs_root *root;
-       struct btrfs_delayed_node *delayed_node;
+struct btrfs_async_delayed_work {
+       struct btrfs_delayed_root *delayed_root;
+       int nr;
        struct btrfs_work work;
 };
 
-static void btrfs_async_run_delayed_node_done(struct btrfs_work *work)
+static void btrfs_async_run_delayed_root(struct btrfs_work *work)
 {
-       struct btrfs_async_delayed_node *async_node;
+       struct btrfs_async_delayed_work *async_work;
+       struct btrfs_delayed_root *delayed_root;
        struct btrfs_trans_handle *trans;
        struct btrfs_path *path;
        struct btrfs_delayed_node *delayed_node = NULL;
        struct btrfs_root *root;
        struct btrfs_block_rsv *block_rsv;
-       int need_requeue = 0;
+       int total_done = 0;
 
-       async_node = container_of(work, struct btrfs_async_delayed_node, work);
+       async_work = container_of(work, struct btrfs_async_delayed_work, work);
+       delayed_root = async_work->delayed_root;
 
        path = btrfs_alloc_path();
        if (!path)
                goto out;
-       path->leave_spinning = 1;
 
-       delayed_node = async_node->delayed_node;
+again:
+       if (atomic_read(&delayed_root->items) < BTRFS_DELAYED_BACKGROUND / 2)
+               goto free_path;
+
+       delayed_node = btrfs_first_prepared_delayed_node(delayed_root);
+       if (!delayed_node)
+               goto free_path;
+
+       path->leave_spinning = 1;
        root = delayed_node->root;
 
        trans = btrfs_join_transaction(root);
        if (IS_ERR(trans))
-               goto free_path;
+               goto release_path;
 
        block_rsv = trans->block_rsv;
        trans->block_rsv = &root->fs_info->delayed_block_rsv;
@@ -1363,57 +1377,47 @@ static void btrfs_async_run_delayed_node_done(struct btrfs_work *work)
         * Task1 will sleep until the transaction is commited.
         */
        mutex_lock(&delayed_node->mutex);
-       if (delayed_node->count)
-               need_requeue = 1;
-       else
-               btrfs_dequeue_delayed_node(root->fs_info->delayed_root,
-                                          delayed_node);
+       btrfs_dequeue_delayed_node(root->fs_info->delayed_root, delayed_node);
        mutex_unlock(&delayed_node->mutex);
 
        trans->block_rsv = block_rsv;
        btrfs_end_transaction_dmeta(trans, root);
        btrfs_btree_balance_dirty_nodelay(root);
+
+release_path:
+       btrfs_release_path(path);
+       total_done++;
+
+       btrfs_release_prepared_delayed_node(delayed_node);
+       if (async_work->nr == 0 || total_done < async_work->nr)
+               goto again;
+
 free_path:
        btrfs_free_path(path);
 out:
-       if (need_requeue)
-               btrfs_requeue_work(&async_node->work);
-       else {
-               btrfs_release_prepared_delayed_node(delayed_node);
-               kfree(async_node);
-       }
+       wake_up(&delayed_root->wait);
+       kfree(async_work);
 }
 
+
 static int btrfs_wq_run_delayed_node(struct btrfs_delayed_root *delayed_root,
-                                    struct btrfs_root *root, int all)
+                                    struct btrfs_root *root, int nr)
 {
-       struct btrfs_async_delayed_node *async_node;
-       struct btrfs_delayed_node *curr;
-       int count = 0;
+       struct btrfs_async_delayed_work *async_work;
 
-again:
-       curr = btrfs_first_prepared_delayed_node(delayed_root);
-       if (!curr)
+       if (atomic_read(&delayed_root->items) < BTRFS_DELAYED_BACKGROUND)
                return 0;
 
-       async_node = kmalloc(sizeof(*async_node), GFP_NOFS);
-       if (!async_node) {
-               btrfs_release_prepared_delayed_node(curr);
+       async_work = kmalloc(sizeof(*async_work), GFP_NOFS);
+       if (!async_work)
                return -ENOMEM;
-       }
-
-       async_node->root = root;
-       async_node->delayed_node = curr;
-
-       async_node->work.func = btrfs_async_run_delayed_node_done;
-       async_node->work.flags = 0;
 
-       btrfs_queue_worker(&root->fs_info->delayed_workers, &async_node->work);
-       count++;
-
-       if (all || count < 4)
-               goto again;
+       async_work->delayed_root = delayed_root;
+       async_work->work.func = btrfs_async_run_delayed_root;
+       async_work->work.flags = 0;
+       async_work->nr = nr;
 
+       btrfs_queue_worker(&root->fs_info->delayed_workers, &async_work->work);
        return 0;
 }
 
@@ -1424,30 +1428,55 @@ void btrfs_assert_delayed_root_empty(struct btrfs_root *root)
        WARN_ON(btrfs_first_delayed_node(delayed_root));
 }
 
+static int refs_newer(struct btrfs_delayed_root *delayed_root,
+                     int seq, int count)
+{
+       int val = atomic_read(&delayed_root->items_seq);
+
+       if (val < seq || val >= seq + count)
+               return 1;
+       return 0;
+}
+
 void btrfs_balance_delayed_items(struct btrfs_root *root)
 {
        struct btrfs_delayed_root *delayed_root;
+       int seq;
 
        delayed_root = btrfs_get_delayed_root(root);
 
        if (atomic_read(&delayed_root->items) < BTRFS_DELAYED_BACKGROUND)
                return;
 
+       seq = atomic_read(&delayed_root->items_seq);
+
        if (atomic_read(&delayed_root->items) >= BTRFS_DELAYED_WRITEBACK) {
                int ret;
-               ret = btrfs_wq_run_delayed_node(delayed_root, root, 1);
+               DEFINE_WAIT(__wait);
+
+               ret = btrfs_wq_run_delayed_node(delayed_root, root, 0);
                if (ret)
                        return;
 
-               wait_event_interruptible_timeout(
-                               delayed_root->wait,
-                               (atomic_read(&delayed_root->items) <
-                                BTRFS_DELAYED_BACKGROUND),
-                               HZ);
-               return;
+               while (1) {
+                       prepare_to_wait(&delayed_root->wait, &__wait,
+                                       TASK_INTERRUPTIBLE);
+
+                       if (refs_newer(delayed_root, seq,
+                                      BTRFS_DELAYED_BATCH) ||
+                           atomic_read(&delayed_root->items) <
+                           BTRFS_DELAYED_BACKGROUND) {
+                               break;
+                       }
+                       if (!signal_pending(current))
+                               schedule();
+                       else
+                               break;
+               }
+               finish_wait(&delayed_root->wait, &__wait);
        }
 
-       btrfs_wq_run_delayed_node(delayed_root, root, 0);
+       btrfs_wq_run_delayed_node(delayed_root, root, BTRFS_DELAYED_BATCH);
 }
 
 /* Will return 0 or -ENOMEM */
index 78b6ad0..1d5c5f7 100644 (file)
@@ -43,6 +43,7 @@ struct btrfs_delayed_root {
         */
        struct list_head prepare_list;
        atomic_t items;         /* for delayed items */
+       atomic_t items_seq;     /* for delayed items */
        int nodes;              /* for delayed nodes */
        wait_queue_head_t wait;
 };
@@ -86,6 +87,7 @@ static inline void btrfs_init_delayed_root(
                                struct btrfs_delayed_root *delayed_root)
 {
        atomic_set(&delayed_root->items, 0);
+       atomic_set(&delayed_root->items_seq, 0);
        delayed_root->nodes = 0;
        spin_lock_init(&delayed_root->lock);
        init_waitqueue_head(&delayed_root->wait);
index 02369a3..7d84651 100644 (file)
@@ -62,7 +62,7 @@ static void btrfs_destroy_ordered_operations(struct btrfs_transaction *t,
 static void btrfs_destroy_ordered_extents(struct btrfs_root *root);
 static int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans,
                                      struct btrfs_root *root);
-static void btrfs_destroy_pending_snapshots(struct btrfs_transaction *t);
+static void btrfs_evict_pending_snapshots(struct btrfs_transaction *t);
 static void btrfs_destroy_delalloc_inodes(struct btrfs_root *root);
 static int btrfs_destroy_marked_extents(struct btrfs_root *root,
                                        struct extent_io_tree *dirty_pages,
@@ -3687,7 +3687,7 @@ int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans,
        return ret;
 }
 
-static void btrfs_destroy_pending_snapshots(struct btrfs_transaction *t)
+static void btrfs_evict_pending_snapshots(struct btrfs_transaction *t)
 {
        struct btrfs_pending_snapshot *snapshot;
        struct list_head splice;
@@ -3700,10 +3700,8 @@ static void btrfs_destroy_pending_snapshots(struct btrfs_transaction *t)
                snapshot = list_entry(splice.next,
                                      struct btrfs_pending_snapshot,
                                      list);
-
+               snapshot->error = -ECANCELED;
                list_del_init(&snapshot->list);
-
-               kfree(snapshot);
        }
 }
 
@@ -3840,6 +3838,8 @@ void btrfs_cleanup_one_transaction(struct btrfs_transaction *cur_trans,
        cur_trans->blocked = 1;
        wake_up(&root->fs_info->transaction_blocked_wait);
 
+       btrfs_evict_pending_snapshots(cur_trans);
+
        cur_trans->blocked = 0;
        wake_up(&root->fs_info->transaction_wait);
 
@@ -3849,8 +3849,6 @@ void btrfs_cleanup_one_transaction(struct btrfs_transaction *cur_trans,
        btrfs_destroy_delayed_inodes(root);
        btrfs_assert_delayed_root_empty(root);
 
-       btrfs_destroy_pending_snapshots(cur_trans);
-
        btrfs_destroy_marked_extents(root, &cur_trans->dirty_pages,
                                     EXTENT_DIRTY);
        btrfs_destroy_pinned_extent(root,
@@ -3894,6 +3892,8 @@ int btrfs_cleanup_transaction(struct btrfs_root *root)
                if (waitqueue_active(&root->fs_info->transaction_blocked_wait))
                        wake_up(&root->fs_info->transaction_blocked_wait);
 
+               btrfs_evict_pending_snapshots(t);
+
                t->blocked = 0;
                smp_mb();
                if (waitqueue_active(&root->fs_info->transaction_wait))
@@ -3907,8 +3907,6 @@ int btrfs_cleanup_transaction(struct btrfs_root *root)
                btrfs_destroy_delayed_inodes(root);
                btrfs_assert_delayed_root_empty(root);
 
-               btrfs_destroy_pending_snapshots(t);
-
                btrfs_destroy_delalloc_inodes(root);
 
                spin_lock(&root->fs_info->trans_lock);
index 3e074da..9ac2eca 100644 (file)
@@ -1467,8 +1467,11 @@ int lookup_inline_extent_backref(struct btrfs_trans_handle *trans,
        if (ret && !insert) {
                err = -ENOENT;
                goto out;
+       } else if (ret) {
+               err = -EIO;
+               WARN_ON(1);
+               goto out;
        }
-       BUG_ON(ret); /* Corruption */
 
        leaf = path->nodes[0];
        item_size = btrfs_item_size_nr(leaf, path->slots[0]);
index af1d060..5b4ea5f 100644 (file)
@@ -591,6 +591,7 @@ void btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end,
                }
                compressed = test_bit(EXTENT_FLAG_COMPRESSED, &em->flags);
                clear_bit(EXTENT_FLAG_PINNED, &em->flags);
+               clear_bit(EXTENT_FLAG_LOGGING, &flags);
                remove_extent_mapping(em_tree, em);
                if (no_splits)
                        goto next;
index c226dae..ca1b767 100644 (file)
@@ -2312,6 +2312,7 @@ again:
        key.type = BTRFS_EXTENT_DATA_KEY;
        key.offset = start;
 
+       path->leave_spinning = 1;
        if (merge) {
                struct btrfs_file_extent_item *fi;
                u64 extent_len;
@@ -2368,6 +2369,7 @@ again:
 
        btrfs_mark_buffer_dirty(leaf);
        inode_add_bytes(inode, len);
+       btrfs_release_path(path);
 
        ret = btrfs_inc_extent_ref(trans, root, new->bytenr,
                        new->disk_len, 0,
@@ -2381,6 +2383,7 @@ again:
        ret = 1;
 out_free_path:
        btrfs_release_path(path);
+       path->leave_spinning = 0;
        btrfs_end_transaction(trans, root);
 out_unlock:
        unlock_extent_cached(&BTRFS_I(inode)->io_tree, lock_start, lock_end,
@@ -8502,6 +8505,7 @@ static int __btrfs_prealloc_file_range(struct inode *inode, int mode,
        struct btrfs_key ins;
        u64 cur_offset = start;
        u64 i_size;
+       u64 cur_bytes;
        int ret = 0;
        bool own_trans = true;
 
@@ -8516,8 +8520,9 @@ static int __btrfs_prealloc_file_range(struct inode *inode, int mode,
                        }
                }
 
-               ret = btrfs_reserve_extent(trans, root,
-                                          min(num_bytes, 256ULL * 1024 * 1024),
+               cur_bytes = min(num_bytes, 256ULL * 1024 * 1024);
+               cur_bytes = max(cur_bytes, min_size);
+               ret = btrfs_reserve_extent(trans, root, cur_bytes,
                                           min_size, 0, *alloc_hint, &ins, 1);
                if (ret) {
                        if (own_trans)
index c83086f..2c02310 100644 (file)
@@ -527,6 +527,8 @@ fail:
        if (async_transid) {
                *async_transid = trans->transid;
                err = btrfs_commit_transaction_async(trans, root, 1);
+               if (err)
+                       err = btrfs_commit_transaction(trans, root);
        } else {
                err = btrfs_commit_transaction(trans, root);
        }
@@ -592,16 +594,14 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir,
                *async_transid = trans->transid;
                ret = btrfs_commit_transaction_async(trans,
                                     root->fs_info->extent_root, 1);
+               if (ret)
+                       ret = btrfs_commit_transaction(trans, root);
        } else {
                ret = btrfs_commit_transaction(trans,
                                               root->fs_info->extent_root);
        }
-       if (ret) {
-               /* cleanup_transaction has freed this for us */
-               if (trans->aborted)
-                       pending_snapshot = NULL;
+       if (ret)
                goto fail;
-       }
 
        ret = pending_snapshot->error;
        if (ret)
@@ -2245,13 +2245,6 @@ static int btrfs_ioctl_defrag(struct file *file, void __user *argp)
        if (ret)
                return ret;
 
-       if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running,
-                       1)) {
-               pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n");
-               mnt_drop_write_file(file);
-               return -EINVAL;
-       }
-
        if (btrfs_root_readonly(root)) {
                ret = -EROFS;
                goto out;
@@ -2306,7 +2299,6 @@ static int btrfs_ioctl_defrag(struct file *file, void __user *argp)
                ret = -EINVAL;
        }
 out:
-       atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0);
        mnt_drop_write_file(file);
        return ret;
 }
index ca52681..b81e0e9 100644 (file)
@@ -26,7 +26,6 @@
 
 void btrfs_tree_lock(struct extent_buffer *eb);
 void btrfs_tree_unlock(struct extent_buffer *eb);
-int btrfs_try_spin_lock(struct extent_buffer *eb);
 
 void btrfs_tree_read_lock(struct extent_buffer *eb);
 void btrfs_tree_read_unlock(struct extent_buffer *eb);
index aee4b1c..5471e47 100644 (file)
@@ -1525,21 +1525,23 @@ int btrfs_qgroup_reserve(struct btrfs_root *root, u64 num_bytes)
 
                if ((qg->lim_flags & BTRFS_QGROUP_LIMIT_MAX_RFER) &&
                    qg->reserved + qg->rfer + num_bytes >
-                   qg->max_rfer)
+                   qg->max_rfer) {
                        ret = -EDQUOT;
+                       goto out;
+               }
 
                if ((qg->lim_flags & BTRFS_QGROUP_LIMIT_MAX_EXCL) &&
                    qg->reserved + qg->excl + num_bytes >
-                   qg->max_excl)
+                   qg->max_excl) {
                        ret = -EDQUOT;
+                       goto out;
+               }
 
                list_for_each_entry(glist, &qg->groups, next_group) {
                        ulist_add(ulist, glist->group->qgroupid,
                                  (uintptr_t)glist->group, GFP_ATOMIC);
                }
        }
-       if (ret)
-               goto out;
 
        /*
         * no limits exceeded, now record the reservation into all qgroups
index 50695dc..b67171e 100644 (file)
@@ -1269,6 +1269,8 @@ static int __update_reloc_root(struct btrfs_root *root, int del)
        }
        spin_unlock(&rc->reloc_root_tree.lock);
 
+       if (!node)
+               return 0;
        BUG_ON((struct btrfs_root *)node->data != root);
 
        if (!del) {
@@ -2238,13 +2240,28 @@ again:
 }
 
 static noinline_for_stack
+void free_reloc_roots(struct list_head *list)
+{
+       struct btrfs_root *reloc_root;
+
+       while (!list_empty(list)) {
+               reloc_root = list_entry(list->next, struct btrfs_root,
+                                       root_list);
+               __update_reloc_root(reloc_root, 1);
+               free_extent_buffer(reloc_root->node);
+               free_extent_buffer(reloc_root->commit_root);
+               kfree(reloc_root);
+       }
+}
+
+static noinline_for_stack
 int merge_reloc_roots(struct reloc_control *rc)
 {
        struct btrfs_root *root;
        struct btrfs_root *reloc_root;
        LIST_HEAD(reloc_roots);
        int found = 0;
-       int ret;
+       int ret = 0;
 again:
        root = rc->extent_root;
 
@@ -2270,20 +2287,33 @@ again:
                        BUG_ON(root->reloc_root != reloc_root);
 
                        ret = merge_reloc_root(rc, root);
-                       BUG_ON(ret);
+                       if (ret)
+                               goto out;
                } else {
                        list_del_init(&reloc_root->root_list);
                }
                ret = btrfs_drop_snapshot(reloc_root, rc->block_rsv, 0, 1);
-               BUG_ON(ret < 0);
+               if (ret < 0) {
+                       if (list_empty(&reloc_root->root_list))
+                               list_add_tail(&reloc_root->root_list,
+                                             &reloc_roots);
+                       goto out;
+               }
        }
 
        if (found) {
                found = 0;
                goto again;
        }
+out:
+       if (ret) {
+               btrfs_std_error(root->fs_info, ret);
+               if (!list_empty(&reloc_roots))
+                       free_reloc_roots(&reloc_roots);
+       }
+
        BUG_ON(!RB_EMPTY_ROOT(&rc->reloc_root_tree.rb_root));
-       return 0;
+       return ret;
 }
 
 static void free_block_list(struct rb_root *blocks)
@@ -2818,8 +2848,10 @@ int relocate_tree_blocks(struct btrfs_trans_handle *trans,
        int err = 0;
 
        path = btrfs_alloc_path();
-       if (!path)
-               return -ENOMEM;
+       if (!path) {
+               err = -ENOMEM;
+               goto out_path;
+       }
 
        rb_node = rb_first(blocks);
        while (rb_node) {
@@ -2858,10 +2890,11 @@ int relocate_tree_blocks(struct btrfs_trans_handle *trans,
                rb_node = rb_next(rb_node);
        }
 out:
-       free_block_list(blocks);
        err = finish_pending_nodes(trans, rc, path, err);
 
        btrfs_free_path(path);
+out_path:
+       free_block_list(blocks);
        return err;
 }
 
@@ -3698,7 +3731,15 @@ int prepare_to_relocate(struct reloc_control *rc)
        set_reloc_control(rc);
 
        trans = btrfs_join_transaction(rc->extent_root);
-       BUG_ON(IS_ERR(trans));
+       if (IS_ERR(trans)) {
+               unset_reloc_control(rc);
+               /*
+                * extent tree is not a ref_cow tree and has no reloc_root to
+                * cleanup.  And callers are responsible to free the above
+                * block rsv.
+                */
+               return PTR_ERR(trans);
+       }
        btrfs_commit_transaction(trans, rc->extent_root);
        return 0;
 }
@@ -3730,7 +3771,11 @@ static noinline_for_stack int relocate_block_group(struct reloc_control *rc)
        while (1) {
                progress++;
                trans = btrfs_start_transaction(rc->extent_root, 0);
-               BUG_ON(IS_ERR(trans));
+               if (IS_ERR(trans)) {
+                       err = PTR_ERR(trans);
+                       trans = NULL;
+                       break;
+               }
 restart:
                if (update_backref_cache(trans, &rc->backref_cache)) {
                        btrfs_end_transaction(trans, rc->extent_root);
@@ -4264,14 +4309,9 @@ int btrfs_recover_relocation(struct btrfs_root *root)
 out_free:
        kfree(rc);
 out:
-       while (!list_empty(&reloc_roots)) {
-               reloc_root = list_entry(reloc_roots.next,
-                                       struct btrfs_root, root_list);
-               list_del(&reloc_root->root_list);
-               free_extent_buffer(reloc_root->node);
-               free_extent_buffer(reloc_root->commit_root);
-               kfree(reloc_root);
-       }
+       if (!list_empty(&reloc_roots))
+               free_reloc_roots(&reloc_roots);
+
        btrfs_free_path(path);
 
        if (err == 0) {
index 68a29a1..f6b8859 100644 (file)
@@ -1558,6 +1558,7 @@ static struct file_system_type btrfs_fs_type = {
        .kill_sb        = btrfs_kill_super,
        .fs_flags       = FS_REQUIRES_DEV,
 };
+MODULE_ALIAS_FS("btrfs");
 
 /*
  * used by btrfsctl to scan devices when no FS is mounted
index e52da6f..50767bb 100644 (file)
@@ -625,14 +625,13 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
 
        btrfs_trans_release_metadata(trans, root);
        trans->block_rsv = NULL;
-       /*
-        * the same root has to be passed to start_transaction and
-        * end_transaction. Subvolume quota depends on this.
-        */
-       WARN_ON(trans->root != root);
 
        if (trans->qgroup_reserved) {
-               btrfs_qgroup_free(root, trans->qgroup_reserved);
+               /*
+                * the same root has to be passed here between start_transaction
+                * and end_transaction. Subvolume quota depends on this.
+                */
+               btrfs_qgroup_free(trans->root, trans->qgroup_reserved);
                trans->qgroup_reserved = 0;
        }
 
@@ -1052,7 +1051,12 @@ int btrfs_defrag_root(struct btrfs_root *root)
 
 /*
  * new snapshots need to be created at a very specific time in the
- * transaction commit.  This does the actual creation
+ * transaction commit.  This does the actual creation.
+ *
+ * Note:
+ * If the error which may affect the commitment of the current transaction
+ * happens, we should return the error number. If the error which just affect
+ * the creation of the pending snapshots, just return 0.
  */
 static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
                                   struct btrfs_fs_info *fs_info,
@@ -1071,7 +1075,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
        struct extent_buffer *tmp;
        struct extent_buffer *old;
        struct timespec cur_time = CURRENT_TIME;
-       int ret;
+       int ret = 0;
        u64 to_reserve = 0;
        u64 index = 0;
        u64 objectid;
@@ -1080,40 +1084,36 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
 
        path = btrfs_alloc_path();
        if (!path) {
-               ret = pending->error = -ENOMEM;
-               return ret;
+               pending->error = -ENOMEM;
+               return 0;
        }
 
        new_root_item = kmalloc(sizeof(*new_root_item), GFP_NOFS);
        if (!new_root_item) {
-               ret = pending->error = -ENOMEM;
+               pending->error = -ENOMEM;
                goto root_item_alloc_fail;
        }
 
-       ret = btrfs_find_free_objectid(tree_root, &objectid);
-       if (ret) {
-               pending->error = ret;
+       pending->error = btrfs_find_free_objectid(tree_root, &objectid);
+       if (pending->error)
                goto no_free_objectid;
-       }
 
        btrfs_reloc_pre_snapshot(trans, pending, &to_reserve);
 
        if (to_reserve > 0) {
-               ret = btrfs_block_rsv_add(root, &pending->block_rsv,
-                                         to_reserve,
-                                         BTRFS_RESERVE_NO_FLUSH);
-               if (ret) {
-                       pending->error = ret;
+               pending->error = btrfs_block_rsv_add(root,
+                                                    &pending->block_rsv,
+                                                    to_reserve,
+                                                    BTRFS_RESERVE_NO_FLUSH);
+               if (pending->error)
                        goto no_free_objectid;
-               }
        }
 
-       ret = btrfs_qgroup_inherit(trans, fs_info, root->root_key.objectid,
-                                  objectid, pending->inherit);
-       if (ret) {
-               pending->error = ret;
+       pending->error = btrfs_qgroup_inherit(trans, fs_info,
+                                             root->root_key.objectid,
+                                             objectid, pending->inherit);
+       if (pending->error)
                goto no_free_objectid;
-       }
 
        key.objectid = objectid;
        key.offset = (u64)-1;
@@ -1141,7 +1141,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
                                         dentry->d_name.len, 0);
        if (dir_item != NULL && !IS_ERR(dir_item)) {
                pending->error = -EEXIST;
-               goto fail;
+               goto dir_item_existed;
        } else if (IS_ERR(dir_item)) {
                ret = PTR_ERR(dir_item);
                btrfs_abort_transaction(trans, root, ret);
@@ -1272,6 +1272,8 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
        if (ret)
                btrfs_abort_transaction(trans, root, ret);
 fail:
+       pending->error = ret;
+dir_item_existed:
        trans->block_rsv = rsv;
        trans->bytes_reserved = 0;
 no_free_objectid:
@@ -1287,12 +1289,17 @@ root_item_alloc_fail:
 static noinline int create_pending_snapshots(struct btrfs_trans_handle *trans,
                                             struct btrfs_fs_info *fs_info)
 {
-       struct btrfs_pending_snapshot *pending;
+       struct btrfs_pending_snapshot *pending, *next;
        struct list_head *head = &trans->transaction->pending_snapshots;
+       int ret = 0;
 
-       list_for_each_entry(pending, head, list)
-               create_pending_snapshot(trans, fs_info, pending);
-       return 0;
+       list_for_each_entry_safe(pending, next, head, list) {
+               list_del(&pending->list);
+               ret = create_pending_snapshot(trans, fs_info, pending);
+               if (ret)
+                       break;
+       }
+       return ret;
 }
 
 static void update_super_roots(struct btrfs_root *root)
@@ -1448,6 +1455,13 @@ static void cleanup_transaction(struct btrfs_trans_handle *trans,
        btrfs_abort_transaction(trans, root, err);
 
        spin_lock(&root->fs_info->trans_lock);
+
+       if (list_empty(&cur_trans->list)) {
+               spin_unlock(&root->fs_info->trans_lock);
+               btrfs_end_transaction(trans, root);
+               return;
+       }
+
        list_del_init(&cur_trans->list);
        if (cur_trans == root->fs_info->running_transaction) {
                root->fs_info->trans_no_join = 1;
index c7ef569..451fad9 100644 (file)
@@ -1382,7 +1382,10 @@ static noinline int link_to_fixup_dir(struct btrfs_trans_handle *trans,
 
        btrfs_release_path(path);
        if (ret == 0) {
-               btrfs_inc_nlink(inode);
+               if (!inode->i_nlink)
+                       set_nlink(inode, 1);
+               else
+                       btrfs_inc_nlink(inode);
                ret = btrfs_update_inode(trans, root, inode);
        } else if (ret == -EEXIST) {
                ret = 0;
index 35bb2d4..5989a92 100644 (file)
@@ -684,6 +684,12 @@ int btrfs_close_devices(struct btrfs_fs_devices *fs_devices)
                __btrfs_close_devices(fs_devices);
                free_fs_devices(fs_devices);
        }
+       /*
+        * Wait for rcu kworkers under __btrfs_close_devices
+        * to finish all blkdev_puts so device is really
+        * free when umount is done.
+        */
+       rcu_barrier();
        return ret;
 }
 
@@ -2379,7 +2385,11 @@ static int btrfs_relocate_chunk(struct btrfs_root *root,
                return ret;
 
        trans = btrfs_start_transaction(root, 0);
-       BUG_ON(IS_ERR(trans));
+       if (IS_ERR(trans)) {
+               ret = PTR_ERR(trans);
+               btrfs_std_error(root->fs_info, ret);
+               return ret;
+       }
 
        lock_chunks(root);
 
@@ -3050,7 +3060,8 @@ static void __cancel_balance(struct btrfs_fs_info *fs_info)
 
        unset_balance_control(fs_info);
        ret = del_balance_item(fs_info->tree_root);
-       BUG_ON(ret);
+       if (ret)
+               btrfs_std_error(fs_info, ret);
 
        atomic_set(&fs_info->mutually_exclusive_operation_running, 0);
 }
@@ -3230,6 +3241,11 @@ int btrfs_balance(struct btrfs_balance_control *bctl,
                update_ioctl_balance_args(fs_info, 0, bargs);
        }
 
+       if ((ret && ret != -ECANCELED && ret != -ENOSPC) ||
+           balance_need_close(fs_info)) {
+               __cancel_balance(fs_info);
+       }
+
        wake_up(&fs_info->balance_wait_q);
 
        return ret;
index 9fe17c6..6ddc0bc 100644 (file)
@@ -952,6 +952,7 @@ static struct file_system_type ceph_fs_type = {
        .kill_sb        = ceph_kill_sb,
        .fs_flags       = FS_RENAME_DOES_D_MOVE,
 };
+MODULE_ALIAS_FS("ceph");
 
 #define _STRINGIFY(x) #x
 #define STRINGIFY(x) _STRINGIFY(x)
index 1a052c0..3cf8a15 100644 (file)
@@ -777,6 +777,7 @@ struct file_system_type cifs_fs_type = {
        .kill_sb = cifs_kill_sb,
        /*  .fs_flags */
 };
+MODULE_ALIAS_FS("cifs");
 const struct inode_operations cifs_dir_inode_ops = {
        .create = cifs_create,
        .atomic_open = cifs_atomic_open,
index 7353bc5..8e2e799 100644 (file)
@@ -1909,12 +1909,12 @@ cifs_writev_requeue(struct cifs_writedata *wdata)
        } while (rc == -EAGAIN);
 
        for (i = 0; i < wdata->nr_pages; i++) {
+               unlock_page(wdata->pages[i]);
                if (rc != 0) {
                        SetPageError(wdata->pages[i]);
                        end_page_writeback(wdata->pages[i]);
                        page_cache_release(wdata->pages[i]);
                }
-               unlock_page(wdata->pages[i]);
        }
 
        mapping_set_error(inode->i_mapping, rc);
index 54125e0..991c63c 100644 (file)
@@ -97,7 +97,7 @@ enum {
        Opt_user, Opt_pass, Opt_ip,
        Opt_unc, Opt_domain,
        Opt_srcaddr, Opt_prefixpath,
-       Opt_iocharset, Opt_sockopt,
+       Opt_iocharset,
        Opt_netbiosname, Opt_servern,
        Opt_ver, Opt_vers, Opt_sec, Opt_cache,
 
@@ -202,7 +202,6 @@ static const match_table_t cifs_mount_option_tokens = {
        { Opt_srcaddr, "srcaddr=%s" },
        { Opt_prefixpath, "prefixpath=%s" },
        { Opt_iocharset, "iocharset=%s" },
-       { Opt_sockopt, "sockopt=%s" },
        { Opt_netbiosname, "netbiosname=%s" },
        { Opt_servern, "servern=%s" },
        { Opt_ver, "ver=%s" },
@@ -1752,19 +1751,6 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
                         */
                        cFYI(1, "iocharset set to %s", string);
                        break;
-               case Opt_sockopt:
-                       string = match_strdup(args);
-                       if (string == NULL)
-                               goto out_nomem;
-
-                       if (strnicmp(string, "TCP_NODELAY", 11) == 0) {
-                               printk(KERN_WARNING "CIFS: the "
-                                       "sockopt=TCP_NODELAY option has been "
-                                       "deprecated and will be removed "
-                                       "in 3.9\n");
-                               vol->sockopt_tcp_nodelay = 1;
-                       }
-                       break;
                case Opt_netbiosname:
                        string = match_strdup(args);
                        if (string == NULL)
index 83f2606..0079696 100644 (file)
@@ -995,6 +995,15 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
                return PTR_ERR(tlink);
        tcon = tlink_tcon(tlink);
 
+       /*
+        * We cannot rename the file if the server doesn't support
+        * CAP_INFOLEVEL_PASSTHRU
+        */
+       if (!(tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)) {
+               rc = -EBUSY;
+               goto out;
+       }
+
        rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN,
                         DELETE|FILE_WRITE_ATTRIBUTES, CREATE_NOT_DIR,
                         &netfid, &oplock, NULL, cifs_sb->local_nls,
@@ -1023,7 +1032,7 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
                                        current->tgid);
                /* although we would like to mark the file hidden
                   if that fails we will still try to rename it */
-               if (rc != 0)
+               if (!rc)
                        cifsInode->cifsAttrs = dosattr;
                else
                        dosattr = origattr; /* since not able to change them */
index c9c7aa7..bceffe7 100644 (file)
@@ -744,4 +744,5 @@ struct smb_version_values smb30_values = {
        .cap_unix = 0,
        .cap_nt_find = SMB2_NT_FIND,
        .cap_large_files = SMB2_LARGE_FILES,
+       .oplock_read = SMB2_OPLOCK_LEVEL_II,
 };
index dada9d0..4dcc0d8 100644 (file)
@@ -329,4 +329,5 @@ struct file_system_type coda_fs_type = {
        .kill_sb        = kill_anon_super,
        .fs_flags       = FS_BINARY_MOUNTDATA,
 };
+MODULE_ALIAS_FS("coda");
 
index fe40fde..d487985 100644 (file)
@@ -558,6 +558,10 @@ ssize_t compat_rw_copy_check_uvector(int type,
        }
        *ret_pointer = iov;
 
+       ret = -EFAULT;
+       if (!access_ok(VERIFY_READ, uvector, nr_segs*sizeof(*uvector)))
+               goto out;
+
        /*
         * Single unix specification:
         * We should -EINVAL if an element length is not >= 0 and fitting an
@@ -1080,17 +1084,12 @@ static ssize_t compat_do_readv_writev(int type, struct file *file,
        if (!file->f_op)
                goto out;
 
-       ret = -EFAULT;
-       if (!access_ok(VERIFY_READ, uvector, nr_segs*sizeof(*uvector)))
-               goto out;
-
-       tot_len = compat_rw_copy_check_uvector(type, uvector, nr_segs,
+       ret = compat_rw_copy_check_uvector(type, uvector, nr_segs,
                                               UIO_FASTIOV, iovstack, &iov);
-       if (tot_len == 0) {
-               ret = 0;
+       if (ret <= 0)
                goto out;
-       }
 
+       tot_len = ret;
        ret = rw_verify_area(type, file, pos, tot_len);
        if (ret < 0)
                goto out;
index aee0a7e..7f26c3c 100644 (file)
@@ -114,6 +114,7 @@ static struct file_system_type configfs_fs_type = {
        .mount          = configfs_do_mount,
        .kill_sb        = kill_litter_super,
 };
+MODULE_ALIAS_FS("configfs");
 
 struct dentry *configfs_pin_fs(void)
 {
index 3ceb9ec..35b1c7b 100644 (file)
@@ -573,6 +573,7 @@ static struct file_system_type cramfs_fs_type = {
        .kill_sb        = kill_block_super,
        .fs_flags       = FS_REQUIRES_DEV,
 };
+MODULE_ALIAS_FS("cramfs");
 
 static int __init init_cramfs_fs(void)
 {
index 0c4f80b..4888cb3 100644 (file)
@@ -299,6 +299,7 @@ static struct file_system_type debug_fs_type = {
        .mount =        debug_mount,
        .kill_sb =      kill_litter_super,
 };
+MODULE_ALIAS_FS("debugfs");
 
 static struct dentry *__create_file(const char *name, umode_t mode,
                                    struct dentry *parent, void *data,
index e15ef38..434aa31 100644 (file)
@@ -12,3 +12,11 @@ config ECRYPT_FS
 
          To compile this file system support as a module, choose M here: the
          module will be called ecryptfs.
+
+config ECRYPT_FS_MESSAGING
+       bool "Enable notifications for userspace key wrap/unwrap"
+       depends on ECRYPT_FS
+       help
+         Enables the /dev/ecryptfs entry for use by ecryptfsd. This allows
+         for userspace to wrap/unwrap file encryption keys by other
+         backends, like OpenSSL.
index 2cc9ee4..49678a6 100644 (file)
@@ -1,7 +1,10 @@
 #
-# Makefile for the Linux 2.6 eCryptfs
+# Makefile for the Linux eCryptfs
 #
 
 obj-$(CONFIG_ECRYPT_FS) += ecryptfs.o
 
-ecryptfs-objs := dentry.o file.o inode.o main.o super.o mmap.o read_write.o crypto.o keystore.o messaging.o miscdev.o kthread.o debug.o
+ecryptfs-y := dentry.o file.o inode.o main.o super.o mmap.o read_write.o \
+             crypto.o keystore.o kthread.o debug.o
+
+ecryptfs-$(CONFIG_ECRYPT_FS_MESSAGING) += messaging.o miscdev.o
index a7b0c2d..d5c25db 100644 (file)
@@ -301,17 +301,14 @@ int virt_to_scatterlist(const void *addr, int size, struct scatterlist *sg,
        while (size > 0 && i < sg_size) {
                pg = virt_to_page(addr);
                offset = offset_in_page(addr);
-               if (sg)
-                       sg_set_page(&sg[i], pg, 0, offset);
+               sg_set_page(&sg[i], pg, 0, offset);
                remainder_of_page = PAGE_CACHE_SIZE - offset;
                if (size >= remainder_of_page) {
-                       if (sg)
-                               sg[i].length = remainder_of_page;
+                       sg[i].length = remainder_of_page;
                        addr += remainder_of_page;
                        size -= remainder_of_page;
                } else {
-                       if (sg)
-                               sg[i].length = size;
+                       sg[i].length = size;
                        addr += size;
                        size = 0;
                }
index 1b5d9af..bf12ba5 100644 (file)
 static int ecryptfs_d_revalidate(struct dentry *dentry, unsigned int flags)
 {
        struct dentry *lower_dentry;
-       struct vfsmount *lower_mnt;
        int rc = 1;
 
        if (flags & LOOKUP_RCU)
                return -ECHILD;
 
        lower_dentry = ecryptfs_dentry_to_lower(dentry);
-       lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
        if (!lower_dentry->d_op || !lower_dentry->d_op->d_revalidate)
                goto out;
        rc = lower_dentry->d_op->d_revalidate(lower_dentry, flags);
index 7e2c6f5..dd299b3 100644 (file)
@@ -172,6 +172,19 @@ ecryptfs_get_key_payload_data(struct key *key)
 #define ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE 24
 #define ECRYPTFS_ENCRYPTED_DENTRY_NAME_LEN (18 + 1 + 4 + 1 + 32)
 
+#ifdef CONFIG_ECRYPT_FS_MESSAGING
+# define ECRYPTFS_VERSIONING_MASK_MESSAGING (ECRYPTFS_VERSIONING_DEVMISC \
+                                            | ECRYPTFS_VERSIONING_PUBKEY)
+#else
+# define ECRYPTFS_VERSIONING_MASK_MESSAGING 0
+#endif
+
+#define ECRYPTFS_VERSIONING_MASK (ECRYPTFS_VERSIONING_PASSPHRASE \
+                                 | ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH \
+                                 | ECRYPTFS_VERSIONING_XATTR \
+                                 | ECRYPTFS_VERSIONING_MULTKEY \
+                                 | ECRYPTFS_VERSIONING_MASK_MESSAGING \
+                                 | ECRYPTFS_VERSIONING_FILENAME_ENCRYPTION)
 struct ecryptfs_key_sig {
        struct list_head crypt_stat_list;
        char keysig[ECRYPTFS_SIG_SIZE_HEX + 1];
@@ -399,7 +412,9 @@ struct ecryptfs_daemon {
        struct hlist_node euid_chain;
 };
 
+#ifdef CONFIG_ECRYPT_FS_MESSAGING
 extern struct mutex ecryptfs_daemon_hash_mux;
+#endif
 
 static inline size_t
 ecryptfs_lower_header_size(struct ecryptfs_crypt_stat *crypt_stat)
@@ -610,6 +625,7 @@ int
 ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value,
                  size_t size, int flags);
 int ecryptfs_read_xattr_region(char *page_virt, struct inode *ecryptfs_inode);
+#ifdef CONFIG_ECRYPT_FS_MESSAGING
 int ecryptfs_process_response(struct ecryptfs_daemon *daemon,
                              struct ecryptfs_message *msg, u32 seq);
 int ecryptfs_send_message(char *data, int data_len,
@@ -618,6 +634,24 @@ int ecryptfs_wait_for_response(struct ecryptfs_msg_ctx *msg_ctx,
                               struct ecryptfs_message **emsg);
 int ecryptfs_init_messaging(void);
 void ecryptfs_release_messaging(void);
+#else
+static inline int ecryptfs_init_messaging(void)
+{
+       return 0;
+}
+static inline void ecryptfs_release_messaging(void)
+{ }
+static inline int ecryptfs_send_message(char *data, int data_len,
+                                       struct ecryptfs_msg_ctx **msg_ctx)
+{
+       return -ENOTCONN;
+}
+static inline int ecryptfs_wait_for_response(struct ecryptfs_msg_ctx *msg_ctx,
+                                            struct ecryptfs_message **emsg)
+{
+       return -ENOMSG;
+}
+#endif
 
 void
 ecryptfs_write_header_metadata(char *virt,
@@ -655,12 +689,11 @@ int ecryptfs_read_lower_page_segment(struct page *page_for_ecryptfs,
                                     size_t offset_in_page, size_t size,
                                     struct inode *ecryptfs_inode);
 struct page *ecryptfs_get_locked_page(struct inode *inode, loff_t index);
-int ecryptfs_exorcise_daemon(struct ecryptfs_daemon *daemon);
-int ecryptfs_find_daemon_by_euid(struct ecryptfs_daemon **daemon);
 int ecryptfs_parse_packet_length(unsigned char *data, size_t *size,
                                 size_t *length_size);
 int ecryptfs_write_packet_length(char *dest, size_t size,
                                 size_t *packet_size_length);
+#ifdef CONFIG_ECRYPT_FS_MESSAGING
 int ecryptfs_init_ecryptfs_miscdev(void);
 void ecryptfs_destroy_ecryptfs_miscdev(void);
 int ecryptfs_send_miscdev(char *data, size_t data_size,
@@ -669,6 +702,9 @@ int ecryptfs_send_miscdev(char *data, size_t data_size,
 void ecryptfs_msg_ctx_alloc_to_free(struct ecryptfs_msg_ctx *msg_ctx);
 int
 ecryptfs_spawn_daemon(struct ecryptfs_daemon **daemon, struct file *file);
+int ecryptfs_exorcise_daemon(struct ecryptfs_daemon *daemon);
+int ecryptfs_find_daemon_by_euid(struct ecryptfs_daemon **daemon);
+#endif
 int ecryptfs_init_kthread(void);
 void ecryptfs_destroy_kthread(void);
 int ecryptfs_privileged_open(struct file **lower_file,
index 53acc9d..63b1f54 100644 (file)
@@ -199,7 +199,6 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
        struct dentry *ecryptfs_dentry = file->f_path.dentry;
        /* Private value of ecryptfs_dentry allocated in
         * ecryptfs_lookup() */
-       struct dentry *lower_dentry;
        struct ecryptfs_file_info *file_info;
 
        mount_crypt_stat = &ecryptfs_superblock_to_private(
@@ -222,7 +221,6 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
                rc = -ENOMEM;
                goto out;
        }
-       lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
        crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat;
        mutex_lock(&crypt_stat->cs_mutex);
        if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED)) {
index e0f07fb..5eab400 100644 (file)
@@ -999,8 +999,8 @@ out:
        return rc;
 }
 
-int ecryptfs_getattr_link(struct vfsmount *mnt, struct dentry *dentry,
-                         struct kstat *stat)
+static int ecryptfs_getattr_link(struct vfsmount *mnt, struct dentry *dentry,
+                                struct kstat *stat)
 {
        struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
        int rc = 0;
@@ -1021,8 +1021,8 @@ int ecryptfs_getattr_link(struct vfsmount *mnt, struct dentry *dentry,
        return rc;
 }
 
-int ecryptfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
-                    struct kstat *stat)
+static int ecryptfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
+                           struct kstat *stat)
 {
        struct kstat lower_stat;
        int rc;
index 2333203..7d52806 100644 (file)
@@ -1150,7 +1150,7 @@ decrypt_pki_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok,
        struct ecryptfs_message *msg = NULL;
        char *auth_tok_sig;
        char *payload;
-       size_t payload_len;
+       size_t payload_len = 0;
        int rc;
 
        rc = ecryptfs_get_auth_tok_sig(&auth_tok_sig, auth_tok);
@@ -1168,7 +1168,7 @@ decrypt_pki_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok,
        rc = ecryptfs_send_message(payload, payload_len, &msg_ctx);
        if (rc) {
                ecryptfs_printk(KERN_ERR, "Error sending message to "
-                               "ecryptfsd\n");
+                               "ecryptfsd: %d\n", rc);
                goto out;
        }
        rc = ecryptfs_wait_for_response(msg_ctx, &msg);
@@ -1202,8 +1202,7 @@ decrypt_pki_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok,
                                  crypt_stat->key_size);
        }
 out:
-       if (msg)
-               kfree(msg);
+       kfree(msg);
        return rc;
 }
 
@@ -1989,7 +1988,7 @@ pki_encrypt_session_key(struct key *auth_tok_key,
        rc = ecryptfs_send_message(payload, payload_len, &msg_ctx);
        if (rc) {
                ecryptfs_printk(KERN_ERR, "Error sending message to "
-                               "ecryptfsd\n");
+                               "ecryptfsd: %d\n", rc);
                goto out;
        }
        rc = ecryptfs_wait_for_response(msg_ctx, &msg);
index 4e0886c..e924cf4 100644 (file)
@@ -629,6 +629,7 @@ static struct file_system_type ecryptfs_fs_type = {
        .kill_sb = ecryptfs_kill_block_super,
        .fs_flags = 0
 };
+MODULE_ALIAS_FS("ecryptfs");
 
 /**
  * inode_info_init_once
index 8d7a577..49ff8ea 100644 (file)
@@ -97,8 +97,7 @@ static void ecryptfs_msg_ctx_free_to_alloc(struct ecryptfs_msg_ctx *msg_ctx)
 void ecryptfs_msg_ctx_alloc_to_free(struct ecryptfs_msg_ctx *msg_ctx)
 {
        list_move(&(msg_ctx->node), &ecryptfs_msg_ctx_free_list);
-       if (msg_ctx->msg)
-               kfree(msg_ctx->msg);
+       kfree(msg_ctx->msg);
        msg_ctx->msg = NULL;
        msg_ctx->state = ECRYPTFS_MSG_CTX_STATE_FREE;
 }
@@ -283,7 +282,7 @@ ecryptfs_send_message_locked(char *data, int data_len, u8 msg_type,
        int rc;
 
        rc = ecryptfs_find_daemon_by_euid(&daemon);
-       if (rc || !daemon) {
+       if (rc) {
                rc = -ENOTCONN;
                goto out;
        }
index 2002431..c6f57a7 100644 (file)
@@ -33,6 +33,7 @@ static struct file_system_type efs_fs_type = {
        .kill_sb        = kill_block_super,
        .fs_flags       = FS_REQUIRES_DEV,
 };
+MODULE_ALIAS_FS("efs");
 
 static struct pt_types sgi_pt_types[] = {
        {0x00,          "SGI vh"},
index 5e59280..9d97633 100644 (file)
@@ -1010,6 +1010,7 @@ static struct file_system_type exofs_type = {
        .mount          = exofs_mount,
        .kill_sb        = generic_shutdown_super,
 };
+MODULE_ALIAS_FS("exofs");
 
 static int __init init_exofs(void)
 {
index 8f370e0..7cadd82 100644 (file)
@@ -118,7 +118,6 @@ void ext2_free_inode (struct inode * inode)
         * as writing the quota to disk may need the lock as well.
         */
        /* Quota is already initialized in iput() */
-       ext2_xattr_delete_inode(inode);
        dquot_free_inode(inode);
        dquot_drop(inode);
 
index c3881e5..fe60cc1 100644 (file)
@@ -34,6 +34,7 @@
 #include "ext2.h"
 #include "acl.h"
 #include "xip.h"
+#include "xattr.h"
 
 static int __ext2_write_inode(struct inode *inode, int do_sync);
 
@@ -88,6 +89,7 @@ void ext2_evict_inode(struct inode * inode)
                inode->i_size = 0;
                if (inode->i_blocks)
                        ext2_truncate_blocks(inode, 0);
+               ext2_xattr_delete_inode(inode);
        }
 
        invalidate_inode_buffers(inode);
index 7f68c81..2885349 100644 (file)
@@ -1536,6 +1536,7 @@ static struct file_system_type ext2_fs_type = {
        .kill_sb        = kill_block_super,
        .fs_flags       = FS_REQUIRES_DEV,
 };
+MODULE_ALIAS_FS("ext2");
 
 static int __init init_ext2_fs(void)
 {
index 5546ca2..fb5120a 100644 (file)
@@ -353,7 +353,7 @@ static struct block_device *ext3_blkdev_get(dev_t dev, struct super_block *sb)
        return bdev;
 
 fail:
-       ext3_msg(sb, "error: failed to open journal device %s: %ld",
+       ext3_msg(sb, KERN_ERR, "error: failed to open journal device %s: %ld",
                __bdevname(dev, b), PTR_ERR(bdev));
 
        return NULL;
@@ -887,7 +887,7 @@ static ext3_fsblk_t get_sb_block(void **data, struct super_block *sb)
        /*todo: use simple_strtoll with >32bit ext3 */
        sb_block = simple_strtoul(options, &options, 0);
        if (*options && *options != ',') {
-               ext3_msg(sb, "error: invalid sb specification: %s",
+               ext3_msg(sb, KERN_ERR, "error: invalid sb specification: %s",
                       (char *) *data);
                return 1;
        }
@@ -3068,6 +3068,7 @@ static struct file_system_type ext3_fs_type = {
        .kill_sb        = kill_block_super,
        .fs_flags       = FS_REQUIRES_DEV,
 };
+MODULE_ALIAS_FS("ext3");
 
 static int __init init_ext3_fs(void)
 {
index 5e6c878..b3818b4 100644 (file)
@@ -90,6 +90,8 @@ static struct file_system_type ext2_fs_type = {
        .kill_sb        = kill_block_super,
        .fs_flags       = FS_REQUIRES_DEV,
 };
+MODULE_ALIAS_FS("ext2");
+MODULE_ALIAS("ext2");
 #define IS_EXT2_SB(sb) ((sb)->s_bdev->bd_holder == &ext2_fs_type)
 #else
 #define IS_EXT2_SB(sb) (0)
@@ -104,6 +106,8 @@ static struct file_system_type ext3_fs_type = {
        .kill_sb        = kill_block_super,
        .fs_flags       = FS_REQUIRES_DEV,
 };
+MODULE_ALIAS_FS("ext3");
+MODULE_ALIAS("ext3");
 #define IS_EXT3_SB(sb) ((sb)->s_bdev->bd_holder == &ext3_fs_type)
 #else
 #define IS_EXT3_SB(sb) (0)
@@ -5152,7 +5156,6 @@ static inline int ext2_feature_set_ok(struct super_block *sb)
                return 0;
        return 1;
 }
-MODULE_ALIAS("ext2");
 #else
 static inline void register_as_ext2(void) { }
 static inline void unregister_as_ext2(void) { }
@@ -5185,7 +5188,6 @@ static inline int ext3_feature_set_ok(struct super_block *sb)
                return 0;
        return 1;
 }
-MODULE_ALIAS("ext3");
 #else
 static inline void register_as_ext3(void) { }
 static inline void unregister_as_ext3(void) { }
@@ -5199,6 +5201,7 @@ static struct file_system_type ext4_fs_type = {
        .kill_sb        = kill_block_super,
        .fs_flags       = FS_REQUIRES_DEV,
 };
+MODULE_ALIAS_FS("ext4");
 
 static int __init ext4_init_feat_adverts(void)
 {
index 8c11764..fea6e58 100644 (file)
@@ -687,6 +687,7 @@ static struct file_system_type f2fs_fs_type = {
        .kill_sb        = kill_block_super,
        .fs_flags       = FS_REQUIRES_DEV,
 };
+MODULE_ALIAS_FS("f2fs");
 
 static int __init init_inodecache(void)
 {
index e2cfda9..081b759 100644 (file)
@@ -668,6 +668,7 @@ static struct file_system_type msdos_fs_type = {
        .kill_sb        = kill_block_super,
        .fs_flags       = FS_REQUIRES_DEV,
 };
+MODULE_ALIAS_FS("msdos");
 
 static int __init init_msdos_fs(void)
 {
index ac959d6..2da9520 100644 (file)
@@ -1073,6 +1073,7 @@ static struct file_system_type vfat_fs_type = {
        .kill_sb        = kill_block_super,
        .fs_flags       = FS_REQUIRES_DEV,
 };
+MODULE_ALIAS_FS("vfat");
 
 static int __init init_vfat_fs(void)
 {
index da165f6..92567d9 100644 (file)
@@ -273,7 +273,7 @@ struct file_system_type *get_fs_type(const char *name)
        int len = dot ? dot - name : strlen(name);
 
        fs = __get_fs_type(name, len);
-       if (!fs && (request_module("%.*s", len, name) == 0))
+       if (!fs && (request_module("fs-%.*s", len, name) == 0))
                fs = __get_fs_type(name, len);
 
        if (dot && fs && !(fs->fs_flags & FS_HAS_SUBTYPE)) {
index fed2c8a..e37eb27 100644 (file)
@@ -52,7 +52,6 @@ MODULE_AUTHOR("Christoph Hellwig");
 MODULE_DESCRIPTION("Veritas Filesystem (VxFS) driver");
 MODULE_LICENSE("Dual BSD/GPL");
 
-MODULE_ALIAS("vxfs"); /* makes mount -t vxfs autoload the module */
 
 
 static void            vxfs_put_super(struct super_block *);
@@ -258,6 +257,8 @@ static struct file_system_type vxfs_fs_type = {
        .kill_sb        = kill_block_super,
        .fs_flags       = FS_REQUIRES_DEV,
 };
+MODULE_ALIAS_FS("vxfs"); /* makes mount -t vxfs autoload the module */
+MODULE_ALIAS("vxfs");
 
 static int __init
 vxfs_init(void)
index b7978b9..a0b0855 100644 (file)
@@ -341,6 +341,7 @@ static struct file_system_type fuse_ctl_fs_type = {
        .mount          = fuse_ctl_mount,
        .kill_sb        = fuse_ctl_kill_sb,
 };
+MODULE_ALIAS_FS("fusectl");
 
 int __init fuse_ctl_init(void)
 {
index df00993..137185c 100644 (file)
@@ -1117,6 +1117,7 @@ static struct file_system_type fuse_fs_type = {
        .mount          = fuse_mount,
        .kill_sb        = fuse_kill_sb_anon,
 };
+MODULE_ALIAS_FS("fuse");
 
 #ifdef CONFIG_BLOCK
 static struct dentry *fuse_mount_blk(struct file_system_type *fs_type,
@@ -1146,6 +1147,7 @@ static struct file_system_type fuseblk_fs_type = {
        .kill_sb        = fuse_kill_sb_blk,
        .fs_flags       = FS_REQUIRES_DEV | FS_HAS_SUBTYPE,
 };
+MODULE_ALIAS_FS("fuseblk");
 
 static inline int register_fuseblk(void)
 {
index 1b612be..60ede2a 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/gfs2_ondisk.h>
 #include <linux/quotaops.h>
 #include <linux/lockdep.h>
+#include <linux/module.h>
 
 #include "gfs2.h"
 #include "incore.h"
@@ -1425,6 +1426,7 @@ struct file_system_type gfs2_fs_type = {
        .kill_sb = gfs2_kill_sb,
        .owner = THIS_MODULE,
 };
+MODULE_ALIAS_FS("gfs2");
 
 struct file_system_type gfs2meta_fs_type = {
        .name = "gfs2meta",
@@ -1432,4 +1434,4 @@ struct file_system_type gfs2meta_fs_type = {
        .mount = gfs2_mount_meta,
        .owner = THIS_MODULE,
 };
-
+MODULE_ALIAS_FS("gfs2meta");
index e93ddaa..bbaaa8a 100644 (file)
@@ -466,6 +466,7 @@ static struct file_system_type hfs_fs_type = {
        .kill_sb        = kill_block_super,
        .fs_flags       = FS_REQUIRES_DEV,
 };
+MODULE_ALIAS_FS("hfs");
 
 static void hfs_init_once(void *p)
 {
index 974c26f..7b87284 100644 (file)
@@ -654,6 +654,7 @@ static struct file_system_type hfsplus_fs_type = {
        .kill_sb        = kill_block_super,
        .fs_flags       = FS_REQUIRES_DEV,
 };
+MODULE_ALIAS_FS("hfsplus");
 
 static void hfsplus_init_once(void *p)
 {
index fbabb90..0f6e52d 100644 (file)
@@ -845,15 +845,8 @@ int hostfs_setattr(struct dentry *dentry, struct iattr *attr)
                return err;
 
        if ((attr->ia_valid & ATTR_SIZE) &&
-           attr->ia_size != i_size_read(inode)) {
-               int error;
-
-               error = inode_newsize_ok(inode, attr->ia_size);
-               if (error)
-                       return error;
-
+           attr->ia_size != i_size_read(inode))
                truncate_setsize(inode, attr->ia_size);
-       }
 
        setattr_copy(inode, attr);
        mark_inode_dirty(inode);
@@ -993,6 +986,7 @@ static struct file_system_type hostfs_type = {
        .kill_sb        = hostfs_kill_sb,
        .fs_flags       = 0,
 };
+MODULE_ALIAS_FS("hostfs");
 
 static int __init init_hostfs(void)
 {
index a307622..a0617e7 100644 (file)
@@ -688,6 +688,7 @@ static struct file_system_type hpfs_fs_type = {
        .kill_sb        = kill_block_super,
        .fs_flags       = FS_REQUIRES_DEV,
 };
+MODULE_ALIAS_FS("hpfs");
 
 static int __init init_hpfs_fs(void)
 {
index 74f5570..126d3c2 100644 (file)
@@ -748,6 +748,7 @@ static struct file_system_type hppfs_type = {
        .kill_sb        = kill_anon_super,
        .fs_flags       = 0,
 };
+MODULE_ALIAS_FS("hppfs");
 
 static int __init init_hppfs(void)
 {
index 7f94e0c..84e3d85 100644 (file)
@@ -896,6 +896,7 @@ static struct file_system_type hugetlbfs_fs_type = {
        .mount          = hugetlbfs_mount,
        .kill_sb        = kill_litter_super,
 };
+MODULE_ALIAS_FS("hugetlbfs");
 
 static struct vfsmount *hugetlbfs_vfsmount[HUGE_MAX_HSTATE];
 
index 67ce525..d9b8aeb 100644 (file)
@@ -1556,6 +1556,8 @@ static struct file_system_type iso9660_fs_type = {
        .kill_sb        = kill_block_super,
        .fs_flags       = FS_REQUIRES_DEV,
 };
+MODULE_ALIAS_FS("iso9660");
+MODULE_ALIAS("iso9660");
 
 static int __init init_iso9660_fs(void)
 {
@@ -1593,5 +1595,3 @@ static void __exit exit_iso9660_fs(void)
 module_init(init_iso9660_fs)
 module_exit(exit_iso9660_fs)
 MODULE_LICENSE("GPL");
-/* Actual filesystem name is iso9660, as requested in filesystems.c */
-MODULE_ALIAS("iso9660");
index d3d8799..0defb1c 100644 (file)
@@ -356,6 +356,7 @@ static struct file_system_type jffs2_fs_type = {
        .mount =        jffs2_mount,
        .kill_sb =      jffs2_kill_sb,
 };
+MODULE_ALIAS_FS("jffs2");
 
 static int __init init_jffs2_fs(void)
 {
index 060ba63..2003e83 100644 (file)
@@ -833,6 +833,7 @@ static struct file_system_type jfs_fs_type = {
        .kill_sb        = kill_block_super,
        .fs_flags       = FS_REQUIRES_DEV,
 };
+MODULE_ALIAS_FS("jfs");
 
 static void init_once(void *foo)
 {
index 345c24b..5436029 100644 (file)
@@ -608,6 +608,7 @@ static struct file_system_type logfs_fs_type = {
        .fs_flags       = FS_REQUIRES_DEV,
 
 };
+MODULE_ALIAS_FS("logfs");
 
 static int __init logfs_init(void)
 {
index 99541cc..df12249 100644 (file)
@@ -660,6 +660,7 @@ static struct file_system_type minix_fs_type = {
        .kill_sb        = kill_block_super,
        .fs_flags       = FS_REQUIRES_DEV,
 };
+MODULE_ALIAS_FS("minix");
 
 static int __init init_minix_fs(void)
 {
index 961bc12..57ae9c8 100644 (file)
@@ -689,8 +689,6 @@ void nd_jump_link(struct nameidata *nd, struct path *path)
        nd->path = *path;
        nd->inode = nd->path.dentry->d_inode;
        nd->flags |= LOOKUP_JUMPED;
-
-       BUG_ON(nd->inode->i_op->follow_link);
 }
 
 static inline void put_link(struct nameidata *nd, struct path *link, void *cookie)
index 7dafd68..26910c8 100644 (file)
@@ -1051,6 +1051,7 @@ static struct file_system_type ncp_fs_type = {
        .kill_sb        = kill_anon_super,
        .fs_flags       = FS_BINARY_MOUNTDATA,
 };
+MODULE_ALIAS_FS("ncpfs");
 
 static int __init init_ncp_fs(void)
 {
index 3bb8318..eb494f6 100644 (file)
@@ -294,6 +294,7 @@ struct file_system_type nfs_fs_type = {
        .kill_sb        = nfs_kill_super,
        .fs_flags       = FS_RENAME_DOES_D_MOVE|FS_BINARY_MOUNTDATA,
 };
+MODULE_ALIAS_FS("nfs");
 EXPORT_SYMBOL_GPL(nfs_fs_type);
 
 struct file_system_type nfs_xdev_fs_type = {
@@ -333,6 +334,8 @@ struct file_system_type nfs4_fs_type = {
        .kill_sb        = nfs_kill_super,
        .fs_flags       = FS_RENAME_DOES_D_MOVE|FS_BINARY_MOUNTDATA,
 };
+MODULE_ALIAS_FS("nfs4");
+MODULE_ALIAS("nfs4");
 EXPORT_SYMBOL_GPL(nfs4_fs_type);
 
 static int __init register_nfs4_fs(void)
@@ -2721,6 +2724,5 @@ module_param(send_implementation_id, ushort, 0644);
 MODULE_PARM_DESC(send_implementation_id,
                "Send implementation ID with NFSv4.1 exchange_id");
 MODULE_PARM_DESC(nfs4_unique_id, "nfs_client_id4 uniquifier string");
-MODULE_ALIAS("nfs4");
 
 #endif /* CONFIG_NFS_V4 */
index 87fd141..d5c5b3e 100644 (file)
@@ -82,6 +82,7 @@ int   nfsd_reply_cache_init(void);
 void   nfsd_reply_cache_shutdown(void);
 int    nfsd_cache_lookup(struct svc_rqst *);
 void   nfsd_cache_update(struct svc_rqst *, int, __be32 *);
+int    nfsd_reply_cache_stats_open(struct inode *, struct file *);
 
 #ifdef CONFIG_NFSD_V4
 void   nfsd4_set_statp(struct svc_rqst *rqstp, __be32 *statp);
index 1051beb..849a7c3 100644 (file)
@@ -80,6 +80,7 @@ struct nfsd_net {
         */
        struct list_head client_lru;
        struct list_head close_lru;
+       struct list_head del_recall_lru;
 
        struct delayed_work laundromat_work;
 
index 99bc85f..7f05cd1 100644 (file)
@@ -37,6 +37,7 @@
 #include "nfsd.h"
 #include "state.h"
 #include "netns.h"
+#include "xdr4cb.h"
 
 #define NFSDDBG_FACILITY                NFSDDBG_PROC
 
@@ -53,30 +54,6 @@ enum {
        NFSPROC4_CLNT_CB_SEQUENCE,
 };
 
-#define NFS4_MAXTAGLEN         20
-
-#define NFS4_enc_cb_null_sz            0
-#define NFS4_dec_cb_null_sz            0
-#define cb_compound_enc_hdr_sz         4
-#define cb_compound_dec_hdr_sz         (3 + (NFS4_MAXTAGLEN >> 2))
-#define sessionid_sz                   (NFS4_MAX_SESSIONID_LEN >> 2)
-#define cb_sequence_enc_sz             (sessionid_sz + 4 +             \
-                                       1 /* no referring calls list yet */)
-#define cb_sequence_dec_sz             (op_dec_sz + sessionid_sz + 4)
-
-#define op_enc_sz                      1
-#define op_dec_sz                      2
-#define enc_nfs4_fh_sz                 (1 + (NFS4_FHSIZE >> 2))
-#define enc_stateid_sz                 (NFS4_STATEID_SIZE >> 2)
-#define NFS4_enc_cb_recall_sz          (cb_compound_enc_hdr_sz +       \
-                                       cb_sequence_enc_sz +            \
-                                       1 + enc_stateid_sz +            \
-                                       enc_nfs4_fh_sz)
-
-#define NFS4_dec_cb_recall_sz          (cb_compound_dec_hdr_sz  +      \
-                                       cb_sequence_dec_sz +            \
-                                       op_dec_sz)
-
 struct nfs4_cb_compound_hdr {
        /* args */
        u32             ident;  /* minorversion 0 only */
@@ -817,8 +794,7 @@ static bool nfsd41_cb_get_slot(struct nfs4_client *clp, struct rpc_task *task)
 static void nfsd4_cb_prepare(struct rpc_task *task, void *calldata)
 {
        struct nfsd4_callback *cb = calldata;
-       struct nfs4_delegation *dp = container_of(cb, struct nfs4_delegation, dl_recall);
-       struct nfs4_client *clp = dp->dl_stid.sc_client;
+       struct nfs4_client *clp = cb->cb_clp;
        u32 minorversion = clp->cl_minorversion;
 
        cb->cb_minorversion = minorversion;
@@ -839,8 +815,7 @@ static void nfsd4_cb_prepare(struct rpc_task *task, void *calldata)
 static void nfsd4_cb_done(struct rpc_task *task, void *calldata)
 {
        struct nfsd4_callback *cb = calldata;
-       struct nfs4_delegation *dp = container_of(cb, struct nfs4_delegation, dl_recall);
-       struct nfs4_client *clp = dp->dl_stid.sc_client;
+       struct nfs4_client *clp = cb->cb_clp;
 
        dprintk("%s: minorversion=%d\n", __func__,
                clp->cl_minorversion);
@@ -863,7 +838,7 @@ static void nfsd4_cb_recall_done(struct rpc_task *task, void *calldata)
 {
        struct nfsd4_callback *cb = calldata;
        struct nfs4_delegation *dp = container_of(cb, struct nfs4_delegation, dl_recall);
-       struct nfs4_client *clp = dp->dl_stid.sc_client;
+       struct nfs4_client *clp = cb->cb_clp;
        struct rpc_clnt *current_rpc_client = clp->cl_cb_client;
 
        nfsd4_cb_done(task, calldata);
index ae73175..5dee811 100644 (file)
@@ -191,9 +191,18 @@ static __be32 nfsd_check_obj_isreg(struct svc_fh *fh)
        return nfserr_symlink;
 }
 
+static void nfsd4_set_open_owner_reply_cache(struct nfsd4_compound_state *cstate, struct nfsd4_open *open, struct svc_fh *resfh)
+{
+       if (nfsd4_has_session(cstate))
+               return;
+       fh_copy_shallow(&open->op_openowner->oo_owner.so_replay.rp_openfh,
+                       &resfh->fh_handle);
+}
+
 static __be32
-do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
+do_open_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_open *open)
 {
+       struct svc_fh *current_fh = &cstate->current_fh;
        struct svc_fh *resfh;
        int accmode;
        __be32 status;
@@ -252,9 +261,7 @@ do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_o
        if (is_create_with_attrs(open) && open->op_acl != NULL)
                do_set_nfs4_acl(rqstp, resfh, open->op_acl, open->op_bmval);
 
-       /* set reply cache */
-       fh_copy_shallow(&open->op_openowner->oo_owner.so_replay.rp_openfh,
-                       &resfh->fh_handle);
+       nfsd4_set_open_owner_reply_cache(cstate, open, resfh);
        accmode = NFSD_MAY_NOP;
        if (open->op_created)
                accmode |= NFSD_MAY_OWNER_OVERRIDE;
@@ -268,8 +275,9 @@ out:
 }
 
 static __be32
-do_open_fhandle(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
+do_open_fhandle(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_open *open)
 {
+       struct svc_fh *current_fh = &cstate->current_fh;
        __be32 status;
 
        /* We don't know the target directory, and therefore can not
@@ -278,9 +286,7 @@ do_open_fhandle(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_
 
        memset(&open->op_cinfo, 0, sizeof(struct nfsd4_change_info));
 
-       /* set replay cache */
-       fh_copy_shallow(&open->op_openowner->oo_owner.so_replay.rp_openfh,
-                       &current_fh->fh_handle);
+       nfsd4_set_open_owner_reply_cache(cstate, open, current_fh);
 
        open->op_truncate = (open->op_iattr.ia_valid & ATTR_SIZE) &&
                (open->op_iattr.ia_size == 0);
@@ -351,6 +357,10 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        }
        if (status)
                goto out;
+       if (open->op_xdr_error) {
+               status = open->op_xdr_error;
+               goto out;
+       }
 
        status = nfsd4_check_open_attributes(rqstp, cstate, open);
        if (status)
@@ -368,8 +378,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        switch (open->op_claim_type) {
                case NFS4_OPEN_CLAIM_DELEGATE_CUR:
                case NFS4_OPEN_CLAIM_NULL:
-                       status = do_open_lookup(rqstp, &cstate->current_fh,
-                                               open);
+                       status = do_open_lookup(rqstp, cstate, open);
                        if (status)
                                goto out;
                        break;
@@ -382,8 +391,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
                                goto out;
                case NFS4_OPEN_CLAIM_FH:
                case NFS4_OPEN_CLAIM_DELEG_CUR_FH:
-                       status = do_open_fhandle(rqstp, &cstate->current_fh,
-                                                open);
+                       status = do_open_fhandle(rqstp, cstate, open);
                        if (status)
                                goto out;
                        break;
@@ -409,14 +417,33 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        WARN_ON(status && open->op_created);
 out:
        nfsd4_cleanup_open_state(open, status);
-       if (open->op_openowner)
+       if (open->op_openowner && !nfsd4_has_session(cstate))
                cstate->replay_owner = &open->op_openowner->oo_owner;
-       else
+       nfsd4_bump_seqid(cstate, status);
+       if (!cstate->replay_owner)
                nfs4_unlock_state();
        return status;
 }
 
 /*
+ * OPEN is the only seqid-mutating operation whose decoding can fail
+ * with a seqid-mutating error (specifically, decoding of user names in
+ * the attributes).  Therefore we have to do some processing to look up
+ * the stateowner so that we can bump the seqid.
+ */
+static __be32 nfsd4_open_omfg(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_op *op)
+{
+       struct nfsd4_open *open = (struct nfsd4_open *)&op->u;
+
+       if (!seqid_mutating_err(ntohl(op->status)))
+               return op->status;
+       if (nfsd4_has_session(cstate))
+               return op->status;
+       open->op_xdr_error = op->status;
+       return nfsd4_open(rqstp, cstate, open);
+}
+
+/*
  * filehandle-manipulating ops.
  */
 static __be32
@@ -931,14 +958,14 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        nfs4_lock_state();
        status = nfs4_preprocess_stateid_op(SVC_NET(rqstp),
                                        cstate, stateid, WR_STATE, &filp);
-       if (filp)
-               get_file(filp);
-       nfs4_unlock_state();
-
        if (status) {
+               nfs4_unlock_state();
                dprintk("NFSD: nfsd4_write: couldn't process stateid!\n");
                return status;
        }
+       if (filp)
+               get_file(filp);
+       nfs4_unlock_state();
 
        cnt = write->wr_buflen;
        write->wr_how_written = write->wr_stable_how;
@@ -1244,8 +1271,11 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
                 * for example, if there is a miscellaneous XDR error
                 * it will be set to nfserr_bad_xdr.
                 */
-               if (op->status)
+               if (op->status) {
+                       if (op->opnum == OP_OPEN)
+                               op->status = nfsd4_open_omfg(rqstp, cstate, op);
                        goto encode_op;
+               }
 
                /* We must be able to encode a successful response to
                 * this operation, with enough room left over to encode a
@@ -1282,12 +1312,9 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
                if (op->status)
                        goto encode_op;
 
-               if (opdesc->op_func) {
-                       if (opdesc->op_get_currentstateid)
-                               opdesc->op_get_currentstateid(cstate, &op->u);
-                       op->status = opdesc->op_func(rqstp, cstate, &op->u);
-               } else
-                       BUG_ON(op->status == nfs_ok);
+               if (opdesc->op_get_currentstateid)
+                       opdesc->op_get_currentstateid(cstate, &op->u);
+               op->status = opdesc->op_func(rqstp, cstate, &op->u);
 
                if (!op->status) {
                        if (opdesc->op_set_currentstateid)
index 16d39c6..a964a17 100644 (file)
@@ -42,6 +42,7 @@
 #include <linux/sunrpc/svcauth_gss.h>
 #include <linux/sunrpc/addr.h>
 #include "xdr4.h"
+#include "xdr4cb.h"
 #include "vfs.h"
 #include "current_stateid.h"
 
@@ -94,17 +95,32 @@ nfs4_lock_state(void)
        mutex_lock(&client_mutex);
 }
 
-static void free_session(struct kref *);
+static void free_session(struct nfsd4_session *);
 
-/* Must be called under the client_lock */
-static void nfsd4_put_session_locked(struct nfsd4_session *ses)
+void nfsd4_put_session(struct nfsd4_session *ses)
+{
+       atomic_dec(&ses->se_ref);
+}
+
+static bool is_session_dead(struct nfsd4_session *ses)
+{
+       return ses->se_flags & NFS4_SESSION_DEAD;
+}
+
+static __be32 mark_session_dead_locked(struct nfsd4_session *ses)
 {
-       kref_put(&ses->se_ref, free_session);
+       if (atomic_read(&ses->se_ref))
+               return nfserr_jukebox;
+       ses->se_flags |= NFS4_SESSION_DEAD;
+       return nfs_ok;
 }
 
-static void nfsd4_get_session(struct nfsd4_session *ses)
+static __be32 nfsd4_get_session_locked(struct nfsd4_session *ses)
 {
-       kref_get(&ses->se_ref);
+       if (is_session_dead(ses))
+               return nfserr_badsession;
+       atomic_inc(&ses->se_ref);
+       return nfs_ok;
 }
 
 void
@@ -113,6 +129,90 @@ nfs4_unlock_state(void)
        mutex_unlock(&client_mutex);
 }
 
+static bool is_client_expired(struct nfs4_client *clp)
+{
+       return clp->cl_time == 0;
+}
+
+static __be32 mark_client_expired_locked(struct nfs4_client *clp)
+{
+       if (atomic_read(&clp->cl_refcount))
+               return nfserr_jukebox;
+       clp->cl_time = 0;
+       return nfs_ok;
+}
+
+static __be32 mark_client_expired(struct nfs4_client *clp)
+{
+       struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
+       __be32 ret;
+
+       spin_lock(&nn->client_lock);
+       ret = mark_client_expired_locked(clp);
+       spin_unlock(&nn->client_lock);
+       return ret;
+}
+
+static __be32 get_client_locked(struct nfs4_client *clp)
+{
+       if (is_client_expired(clp))
+               return nfserr_expired;
+       atomic_inc(&clp->cl_refcount);
+       return nfs_ok;
+}
+
+/* must be called under the client_lock */
+static inline void
+renew_client_locked(struct nfs4_client *clp)
+{
+       struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
+
+       if (is_client_expired(clp)) {
+               WARN_ON(1);
+               printk("%s: client (clientid %08x/%08x) already expired\n",
+                       __func__,
+                       clp->cl_clientid.cl_boot,
+                       clp->cl_clientid.cl_id);
+               return;
+       }
+
+       dprintk("renewing client (clientid %08x/%08x)\n",
+                       clp->cl_clientid.cl_boot,
+                       clp->cl_clientid.cl_id);
+       list_move_tail(&clp->cl_lru, &nn->client_lru);
+       clp->cl_time = get_seconds();
+}
+
+static inline void
+renew_client(struct nfs4_client *clp)
+{
+       struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
+
+       spin_lock(&nn->client_lock);
+       renew_client_locked(clp);
+       spin_unlock(&nn->client_lock);
+}
+
+static void put_client_renew_locked(struct nfs4_client *clp)
+{
+       if (!atomic_dec_and_test(&clp->cl_refcount))
+               return;
+       if (!is_client_expired(clp))
+               renew_client_locked(clp);
+}
+
+void put_client_renew(struct nfs4_client *clp)
+{
+       struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
+
+       if (!atomic_dec_and_lock(&clp->cl_refcount, &nn->client_lock))
+               return;
+       if (!is_client_expired(clp))
+               renew_client_locked(clp);
+       spin_unlock(&nn->client_lock);
+}
+
+
 static inline u32
 opaque_hashval(const void *ptr, int nbytes)
 {
@@ -126,8 +226,6 @@ opaque_hashval(const void *ptr, int nbytes)
        return x;
 }
 
-static struct list_head del_recall_lru;
-
 static void nfsd4_free_file(struct nfs4_file *f)
 {
        kmem_cache_free(file_slab, f);
@@ -137,7 +235,7 @@ static inline void
 put_nfs4_file(struct nfs4_file *fi)
 {
        if (atomic_dec_and_lock(&fi->fi_ref, &recall_lock)) {
-               list_del(&fi->fi_hash);
+               hlist_del(&fi->fi_hash);
                spin_unlock(&recall_lock);
                iput(fi->fi_inode);
                nfsd4_free_file(fi);
@@ -181,7 +279,7 @@ static unsigned int file_hashval(struct inode *ino)
        return hash_ptr(ino, FILE_HASH_BITS);
 }
 
-static struct list_head file_hashtbl[FILE_HASH_SIZE];
+static struct hlist_head file_hashtbl[FILE_HASH_SIZE];
 
 static void __nfs4_file_get_access(struct nfs4_file *fp, int oflag)
 {
@@ -210,13 +308,7 @@ static void __nfs4_file_put_access(struct nfs4_file *fp, int oflag)
 {
        if (atomic_dec_and_test(&fp->fi_access[oflag])) {
                nfs4_file_put_fd(fp, oflag);
-               /*
-                * It's also safe to get rid of the RDWR open *if*
-                * we no longer have need of the other kind of access
-                * or if we already have the other kind of open:
-                */
-               if (fp->fi_fds[1-oflag]
-                       || atomic_read(&fp->fi_access[1 - oflag]) == 0)
+               if (atomic_read(&fp->fi_access[1 - oflag]) == 0)
                        nfs4_file_put_fd(fp, O_RDWR);
        }
 }
@@ -230,37 +322,6 @@ static void nfs4_file_put_access(struct nfs4_file *fp, int oflag)
                __nfs4_file_put_access(fp, oflag);
 }
 
-static inline int get_new_stid(struct nfs4_stid *stid)
-{
-       static int min_stateid = 0;
-       struct idr *stateids = &stid->sc_client->cl_stateids;
-       int new_stid;
-       int error;
-
-       error = idr_get_new_above(stateids, stid, min_stateid, &new_stid);
-       /*
-        * Note: the necessary preallocation was done in
-        * nfs4_alloc_stateid().  The idr code caps the number of
-        * preallocations that can exist at a time, but the state lock
-        * prevents anyone from using ours before we get here:
-        */
-       WARN_ON_ONCE(error);
-       /*
-        * It shouldn't be a problem to reuse an opaque stateid value.
-        * I don't think it is for 4.1.  But with 4.0 I worry that, for
-        * example, a stray write retransmission could be accepted by
-        * the server when it should have been rejected.  Therefore,
-        * adopt a trick from the sctp code to attempt to maximize the
-        * amount of time until an id is reused, by ensuring they always
-        * "increase" (mod INT_MAX):
-        */
-
-       min_stateid = new_stid+1;
-       if (min_stateid == INT_MAX)
-               min_stateid = 0;
-       return new_stid;
-}
-
 static struct nfs4_stid *nfs4_alloc_stid(struct nfs4_client *cl, struct
 kmem_cache *slab)
 {
@@ -273,9 +334,8 @@ kmem_cache *slab)
        if (!stid)
                return NULL;
 
-       if (!idr_pre_get(stateids, GFP_KERNEL))
-               goto out_free;
-       if (idr_get_new_above(stateids, stid, min_stateid, &new_id))
+       new_id = idr_alloc(stateids, stid, min_stateid, 0, GFP_KERNEL);
+       if (new_id < 0)
                goto out_free;
        stid->sc_client = cl;
        stid->sc_type = 0;
@@ -299,7 +359,7 @@ kmem_cache *slab)
                min_stateid = 0;
        return stid;
 out_free:
-       kfree(stid);
+       kmem_cache_free(slab, stid);
        return NULL;
 }
 
@@ -350,21 +410,18 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_ol_stateid *stp, struct sv
        return dp;
 }
 
-static void free_stid(struct nfs4_stid *s, struct kmem_cache *slab)
+static void remove_stid(struct nfs4_stid *s)
 {
        struct idr *stateids = &s->sc_client->cl_stateids;
 
        idr_remove(stateids, s->sc_stateid.si_opaque.so_id);
-       kmem_cache_free(slab, s);
 }
 
 void
 nfs4_put_delegation(struct nfs4_delegation *dp)
 {
        if (atomic_dec_and_test(&dp->dl_count)) {
-               dprintk("NFSD: freeing dp %p\n",dp);
-               put_nfs4_file(dp->dl_file);
-               free_stid(&dp->dl_stid, deleg_slab);
+               kmem_cache_free(deleg_slab, dp);
                num_delegations--;
        }
 }
@@ -388,16 +445,45 @@ static void unhash_stid(struct nfs4_stid *s)
 static void
 unhash_delegation(struct nfs4_delegation *dp)
 {
-       unhash_stid(&dp->dl_stid);
        list_del_init(&dp->dl_perclnt);
        spin_lock(&recall_lock);
        list_del_init(&dp->dl_perfile);
        list_del_init(&dp->dl_recall_lru);
        spin_unlock(&recall_lock);
        nfs4_put_deleg_lease(dp->dl_file);
+       put_nfs4_file(dp->dl_file);
+       dp->dl_file = NULL;
+}
+
+
+
+static void destroy_revoked_delegation(struct nfs4_delegation *dp)
+{
+       list_del_init(&dp->dl_recall_lru);
+       remove_stid(&dp->dl_stid);
+       nfs4_put_delegation(dp);
+}
+
+static void destroy_delegation(struct nfs4_delegation *dp)
+{
+       unhash_delegation(dp);
+       remove_stid(&dp->dl_stid);
        nfs4_put_delegation(dp);
 }
 
+static void revoke_delegation(struct nfs4_delegation *dp)
+{
+       struct nfs4_client *clp = dp->dl_stid.sc_client;
+
+       if (clp->cl_minorversion == 0)
+               destroy_delegation(dp);
+       else {
+               unhash_delegation(dp);
+               dp->dl_stid.sc_type = NFS4_REVOKED_DELEG_STID;
+               list_add(&dp->dl_recall_lru, &clp->cl_revoked);
+       }
+}
+
 /* 
  * SETCLIENTID state 
  */
@@ -538,7 +624,8 @@ static void close_generic_stateid(struct nfs4_ol_stateid *stp)
 
 static void free_generic_stateid(struct nfs4_ol_stateid *stp)
 {
-       free_stid(&stp->st_stid, stateid_slab);
+       remove_stid(&stp->st_stid);
+       kmem_cache_free(stateid_slab, stp);
 }
 
 static void release_lock_stateid(struct nfs4_ol_stateid *stp)
@@ -654,6 +741,28 @@ dump_sessionid(const char *fn, struct nfs4_sessionid *sessionid)
 }
 #endif
 
+/*
+ * Bump the seqid on cstate->replay_owner, and clear replay_owner if it
+ * won't be used for replay.
+ */
+void nfsd4_bump_seqid(struct nfsd4_compound_state *cstate, __be32 nfserr)
+{
+       struct nfs4_stateowner *so = cstate->replay_owner;
+
+       if (nfserr == nfserr_replay_me)
+               return;
+
+       if (!seqid_mutating_err(ntohl(nfserr))) {
+               cstate->replay_owner = NULL;
+               return;
+       }
+       if (!so)
+               return;
+       if (so->so_is_open_owner)
+               release_last_closed_stateid(openowner(so));
+       so->so_seqid++;
+       return;
+}
 
 static void
 gen_sessionid(struct nfsd4_session *ses)
@@ -694,17 +803,15 @@ free_session_slots(struct nfsd4_session *ses)
  * We don't actually need to cache the rpc and session headers, so we
  * can allocate a little less for each slot:
  */
-static inline int slot_bytes(struct nfsd4_channel_attrs *ca)
+static inline u32 slot_bytes(struct nfsd4_channel_attrs *ca)
 {
-       return ca->maxresp_cached - NFSD_MIN_HDR_SEQ_SZ;
-}
-
-static int nfsd4_sanitize_slot_size(u32 size)
-{
-       size -= NFSD_MIN_HDR_SEQ_SZ; /* We don't cache the rpc header */
-       size = min_t(u32, size, NFSD_SLOT_CACHE_SIZE);
+       u32 size;
 
-       return size;
+       if (ca->maxresp_cached < NFSD_MIN_HDR_SEQ_SZ)
+               size = 0;
+       else
+               size = ca->maxresp_cached - NFSD_MIN_HDR_SEQ_SZ;
+       return size + sizeof(struct nfsd4_slot);
 }
 
 /*
@@ -712,12 +819,12 @@ static int nfsd4_sanitize_slot_size(u32 size)
  * re-negotiate active sessions and reduce their slot usage to make
  * room for new connections. For now we just fail the create session.
  */
-static int nfsd4_get_drc_mem(int slotsize, u32 num)
+static u32 nfsd4_get_drc_mem(struct nfsd4_channel_attrs *ca)
 {
+       u32 slotsize = slot_bytes(ca);
+       u32 num = ca->maxreqs;
        int avail;
 
-       num = min_t(u32, num, NFSD_MAX_SLOTS_PER_SESSION);
-
        spin_lock(&nfsd_drc_lock);
        avail = min((unsigned long)NFSD_MAX_MEM_PER_SESSION,
                    nfsd_drc_max_mem - nfsd_drc_mem_used);
@@ -728,15 +835,19 @@ static int nfsd4_get_drc_mem(int slotsize, u32 num)
        return num;
 }
 
-static void nfsd4_put_drc_mem(int slotsize, int num)
+static void nfsd4_put_drc_mem(struct nfsd4_channel_attrs *ca)
 {
+       int slotsize = slot_bytes(ca);
+
        spin_lock(&nfsd_drc_lock);
-       nfsd_drc_mem_used -= slotsize * num;
+       nfsd_drc_mem_used -= slotsize * ca->maxreqs;
        spin_unlock(&nfsd_drc_lock);
 }
 
-static struct nfsd4_session *__alloc_session(int slotsize, int numslots)
+static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *attrs)
 {
+       int numslots = attrs->maxreqs;
+       int slotsize = slot_bytes(attrs);
        struct nfsd4_session *new;
        int mem, i;
 
@@ -749,8 +860,7 @@ static struct nfsd4_session *__alloc_session(int slotsize, int numslots)
                return NULL;
        /* allocate each struct nfsd4_slot and data cache in one piece */
        for (i = 0; i < numslots; i++) {
-               mem = sizeof(struct nfsd4_slot) + slotsize;
-               new->se_slots[i] = kzalloc(mem, GFP_KERNEL);
+               new->se_slots[i] = kzalloc(slotsize, GFP_KERNEL);
                if (!new->se_slots[i])
                        goto out_free;
        }
@@ -762,21 +872,6 @@ out_free:
        return NULL;
 }
 
-static void init_forechannel_attrs(struct nfsd4_channel_attrs *new,
-                                  struct nfsd4_channel_attrs *req,
-                                  int numslots, int slotsize,
-                                  struct nfsd_net *nn)
-{
-       u32 maxrpc = nn->nfsd_serv->sv_max_mesg;
-
-       new->maxreqs = numslots;
-       new->maxresp_cached = min_t(u32, req->maxresp_cached,
-                                       slotsize + NFSD_MIN_HDR_SEQ_SZ);
-       new->maxreq_sz = min_t(u32, req->maxreq_sz, maxrpc);
-       new->maxresp_sz = min_t(u32, req->maxresp_sz, maxrpc);
-       new->maxops = min_t(u32, req->maxops, NFSD_MAX_OPS_PER_COMPOUND);
-}
-
 static void free_conn(struct nfsd4_conn *c)
 {
        svc_xprt_put(c->cn_xprt);
@@ -793,8 +888,8 @@ static void nfsd4_conn_lost(struct svc_xpt_user *u)
                list_del(&c->cn_persession);
                free_conn(c);
        }
-       spin_unlock(&clp->cl_lock);
        nfsd4_probe_callback(clp);
+       spin_unlock(&clp->cl_lock);
 }
 
 static struct nfsd4_conn *alloc_conn(struct svc_rqst *rqstp, u32 flags)
@@ -878,59 +973,20 @@ static void nfsd4_del_conns(struct nfsd4_session *s)
 
 static void __free_session(struct nfsd4_session *ses)
 {
-       nfsd4_put_drc_mem(slot_bytes(&ses->se_fchannel), ses->se_fchannel.maxreqs);
        free_session_slots(ses);
        kfree(ses);
 }
 
-static void free_session(struct kref *kref)
+static void free_session(struct nfsd4_session *ses)
 {
-       struct nfsd4_session *ses;
-       struct nfsd_net *nn;
-
-       ses = container_of(kref, struct nfsd4_session, se_ref);
-       nn = net_generic(ses->se_client->net, nfsd_net_id);
+       struct nfsd_net *nn = net_generic(ses->se_client->net, nfsd_net_id);
 
        lockdep_assert_held(&nn->client_lock);
        nfsd4_del_conns(ses);
+       nfsd4_put_drc_mem(&ses->se_fchannel);
        __free_session(ses);
 }
 
-void nfsd4_put_session(struct nfsd4_session *ses)
-{
-       struct nfsd_net *nn = net_generic(ses->se_client->net, nfsd_net_id);
-
-       spin_lock(&nn->client_lock);
-       nfsd4_put_session_locked(ses);
-       spin_unlock(&nn->client_lock);
-}
-
-static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *fchan,
-                                          struct nfsd_net *nn)
-{
-       struct nfsd4_session *new;
-       int numslots, slotsize;
-       /*
-        * Note decreasing slot size below client's request may
-        * make it difficult for client to function correctly, whereas
-        * decreasing the number of slots will (just?) affect
-        * performance.  When short on memory we therefore prefer to
-        * decrease number of slots instead of their size.
-        */
-       slotsize = nfsd4_sanitize_slot_size(fchan->maxresp_cached);
-       numslots = nfsd4_get_drc_mem(slotsize, fchan->maxreqs);
-       if (numslots < 1)
-               return NULL;
-
-       new = __alloc_session(slotsize, numslots);
-       if (!new) {
-               nfsd4_put_drc_mem(slotsize, numslots);
-               return NULL;
-       }
-       init_forechannel_attrs(&new->se_fchannel, fchan, numslots, slotsize, nn);
-       return new;
-}
-
 static void init_session(struct svc_rqst *rqstp, struct nfsd4_session *new, struct nfs4_client *clp, struct nfsd4_create_session *cses)
 {
        int idx;
@@ -945,7 +1001,7 @@ static void init_session(struct svc_rqst *rqstp, struct nfsd4_session *new, stru
        new->se_flags = cses->flags;
        new->se_cb_prog = cses->callback_prog;
        new->se_cb_sec = cses->cb_sec;
-       kref_init(&new->se_ref);
+       atomic_set(&new->se_ref, 0);
        idx = hash_sessionid(&new->se_sessionid);
        spin_lock(&nn->client_lock);
        list_add(&new->se_hash, &nn->sessionid_hashtbl[idx]);
@@ -953,7 +1009,8 @@ static void init_session(struct svc_rqst *rqstp, struct nfsd4_session *new, stru
        list_add(&new->se_perclnt, &clp->cl_sessions);
        spin_unlock(&clp->cl_lock);
        spin_unlock(&nn->client_lock);
-
+       memcpy(&new->se_fchannel, &cses->fore_channel,
+                       sizeof(struct nfsd4_channel_attrs));
        if (cses->flags & SESSION4_BACK_CHAN) {
                struct sockaddr *sa = svc_addr(rqstp);
                /*
@@ -1000,38 +1057,6 @@ unhash_session(struct nfsd4_session *ses)
        spin_unlock(&ses->se_client->cl_lock);
 }
 
-/* must be called under the client_lock */
-static inline void
-renew_client_locked(struct nfs4_client *clp)
-{
-       struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
-
-       if (is_client_expired(clp)) {
-               WARN_ON(1);
-               printk("%s: client (clientid %08x/%08x) already expired\n",
-                       __func__,
-                       clp->cl_clientid.cl_boot,
-                       clp->cl_clientid.cl_id);
-               return;
-       }
-
-       dprintk("renewing client (clientid %08x/%08x)\n", 
-                       clp->cl_clientid.cl_boot, 
-                       clp->cl_clientid.cl_id);
-       list_move_tail(&clp->cl_lru, &nn->client_lru);
-       clp->cl_time = get_seconds();
-}
-
-static inline void
-renew_client(struct nfs4_client *clp)
-{
-       struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
-
-       spin_lock(&nn->client_lock);
-       renew_client_locked(clp);
-       spin_unlock(&nn->client_lock);
-}
-
 /* SETCLIENTID and SETCLIENTID_CONFIRM Helper functions */
 static int
 STALE_CLIENTID(clientid_t *clid, struct nfsd_net *nn)
@@ -1075,7 +1100,8 @@ free_client(struct nfs4_client *clp)
                ses = list_entry(clp->cl_sessions.next, struct nfsd4_session,
                                se_perclnt);
                list_del(&ses->se_perclnt);
-               nfsd4_put_session_locked(ses);
+               WARN_ON_ONCE(atomic_read(&ses->se_ref));
+               free_session(ses);
        }
        free_svc_cred(&clp->cl_cred);
        kfree(clp->cl_name.data);
@@ -1083,29 +1109,12 @@ free_client(struct nfs4_client *clp)
        kfree(clp);
 }
 
-void
-release_session_client(struct nfsd4_session *session)
-{
-       struct nfs4_client *clp = session->se_client;
-       struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
-
-       if (!atomic_dec_and_lock(&clp->cl_refcount, &nn->client_lock))
-               return;
-       if (is_client_expired(clp)) {
-               free_client(clp);
-               session->se_client = NULL;
-       } else
-               renew_client_locked(clp);
-       spin_unlock(&nn->client_lock);
-}
-
 /* must be called under the client_lock */
 static inline void
 unhash_client_locked(struct nfs4_client *clp)
 {
        struct nfsd4_session *ses;
 
-       mark_client_expired(clp);
        list_del(&clp->cl_lru);
        spin_lock(&clp->cl_lock);
        list_for_each_entry(ses, &clp->cl_sessions, se_perclnt)
@@ -1131,7 +1140,7 @@ destroy_client(struct nfs4_client *clp)
        spin_unlock(&recall_lock);
        while (!list_empty(&reaplist)) {
                dp = list_entry(reaplist.next, struct nfs4_delegation, dl_recall_lru);
-               unhash_delegation(dp);
+               destroy_delegation(dp);
        }
        while (!list_empty(&clp->cl_openowners)) {
                oo = list_entry(clp->cl_openowners.next, struct nfs4_openowner, oo_perclient);
@@ -1147,8 +1156,8 @@ destroy_client(struct nfs4_client *clp)
                rb_erase(&clp->cl_namenode, &nn->unconf_name_tree);
        spin_lock(&nn->client_lock);
        unhash_client_locked(clp);
-       if (atomic_read(&clp->cl_refcount) == 0)
-               free_client(clp);
+       WARN_ON_ONCE(atomic_read(&clp->cl_refcount));
+       free_client(clp);
        spin_unlock(&nn->client_lock);
 }
 
@@ -1327,6 +1336,7 @@ static struct nfs4_client *create_client(struct xdr_netobj name,
        INIT_LIST_HEAD(&clp->cl_delegations);
        INIT_LIST_HEAD(&clp->cl_lru);
        INIT_LIST_HEAD(&clp->cl_callbacks);
+       INIT_LIST_HEAD(&clp->cl_revoked);
        spin_lock_init(&clp->cl_lock);
        nfsd4_init_callback(&clp->cl_cb_null);
        clp->cl_time = get_seconds();
@@ -1408,12 +1418,12 @@ move_to_confirmed(struct nfs4_client *clp)
 }
 
 static struct nfs4_client *
-find_confirmed_client(clientid_t *clid, bool sessions, struct nfsd_net *nn)
+find_client_in_id_table(struct list_head *tbl, clientid_t *clid, bool sessions)
 {
        struct nfs4_client *clp;
        unsigned int idhashval = clientid_hashval(clid->cl_id);
 
-       list_for_each_entry(clp, &nn->conf_id_hashtbl[idhashval], cl_idhash) {
+       list_for_each_entry(clp, &tbl[idhashval], cl_idhash) {
                if (same_clid(&clp->cl_clientid, clid)) {
                        if ((bool)clp->cl_minorversion != sessions)
                                return NULL;
@@ -1425,19 +1435,19 @@ find_confirmed_client(clientid_t *clid, bool sessions, struct nfsd_net *nn)
 }
 
 static struct nfs4_client *
+find_confirmed_client(clientid_t *clid, bool sessions, struct nfsd_net *nn)
+{
+       struct list_head *tbl = nn->conf_id_hashtbl;
+
+       return find_client_in_id_table(tbl, clid, sessions);
+}
+
+static struct nfs4_client *
 find_unconfirmed_client(clientid_t *clid, bool sessions, struct nfsd_net *nn)
 {
-       struct nfs4_client *clp;
-       unsigned int idhashval = clientid_hashval(clid->cl_id);
+       struct list_head *tbl = nn->unconf_id_hashtbl;
 
-       list_for_each_entry(clp, &nn->unconf_id_hashtbl[idhashval], cl_idhash) {
-               if (same_clid(&clp->cl_clientid, clid)) {
-                       if ((bool)clp->cl_minorversion != sessions)
-                               return NULL;
-                       return clp;
-               }
-       }
-       return NULL;
+       return find_client_in_id_table(tbl, clid, sessions);
 }
 
 static bool clp_used_exchangeid(struct nfs4_client *clp)
@@ -1641,6 +1651,7 @@ nfsd4_exchange_id(struct svc_rqst *rqstp,
        default:                                /* checked by xdr code */
                WARN_ON_ONCE(1);
        case SP4_SSV:
+               return nfserr_encr_alg_unsupp;
        case SP4_MACH_CRED:
                return nfserr_serverfault;      /* no excuse :-/ */
        }
@@ -1782,10 +1793,55 @@ nfsd4_replay_create_session(struct nfsd4_create_session *cr_ses,
                                /* seqid, slotID, slotID, slotID, status */ \
                        5 ) * sizeof(__be32))
 
-static bool check_forechannel_attrs(struct nfsd4_channel_attrs fchannel)
+static __be32 check_forechannel_attrs(struct nfsd4_channel_attrs *ca, struct nfsd_net *nn)
 {
-       return fchannel.maxreq_sz < NFSD_MIN_REQ_HDR_SEQ_SZ
-               || fchannel.maxresp_sz < NFSD_MIN_RESP_HDR_SEQ_SZ;
+       u32 maxrpc = nn->nfsd_serv->sv_max_mesg;
+
+       if (ca->maxreq_sz < NFSD_MIN_REQ_HDR_SEQ_SZ)
+               return nfserr_toosmall;
+       if (ca->maxresp_sz < NFSD_MIN_RESP_HDR_SEQ_SZ)
+               return nfserr_toosmall;
+       ca->headerpadsz = 0;
+       ca->maxreq_sz = min_t(u32, ca->maxreq_sz, maxrpc);
+       ca->maxresp_sz = min_t(u32, ca->maxresp_sz, maxrpc);
+       ca->maxops = min_t(u32, ca->maxops, NFSD_MAX_OPS_PER_COMPOUND);
+       ca->maxresp_cached = min_t(u32, ca->maxresp_cached,
+                       NFSD_SLOT_CACHE_SIZE + NFSD_MIN_HDR_SEQ_SZ);
+       ca->maxreqs = min_t(u32, ca->maxreqs, NFSD_MAX_SLOTS_PER_SESSION);
+       /*
+        * Note decreasing slot size below client's request may make it
+        * difficult for client to function correctly, whereas
+        * decreasing the number of slots will (just?) affect
+        * performance.  When short on memory we therefore prefer to
+        * decrease number of slots instead of their size.  Clients that
+        * request larger slots than they need will get poor results:
+        */
+       ca->maxreqs = nfsd4_get_drc_mem(ca);
+       if (!ca->maxreqs)
+               return nfserr_jukebox;
+
+       return nfs_ok;
+}
+
+static __be32 check_backchannel_attrs(struct nfsd4_channel_attrs *ca)
+{
+       ca->headerpadsz = 0;
+
+       /*
+        * These RPC_MAX_HEADER macros are overkill, especially since we
+        * don't even do gss on the backchannel yet.  But this is still
+        * less than 1k.  Tighten up this estimate in the unlikely event
+        * it turns out to be a problem for some client:
+        */
+       if (ca->maxreq_sz < NFS4_enc_cb_recall_sz + RPC_MAX_HEADER_WITH_AUTH)
+               return nfserr_toosmall;
+       if (ca->maxresp_sz < NFS4_dec_cb_recall_sz + RPC_MAX_REPHEADER_WITH_AUTH)
+               return nfserr_toosmall;
+       ca->maxresp_cached = 0;
+       if (ca->maxops < 2)
+               return nfserr_toosmall;
+
+       return nfs_ok;
 }
 
 __be32
@@ -1803,12 +1859,16 @@ nfsd4_create_session(struct svc_rqst *rqstp,
 
        if (cr_ses->flags & ~SESSION4_FLAG_MASK_A)
                return nfserr_inval;
-       if (check_forechannel_attrs(cr_ses->fore_channel))
-               return nfserr_toosmall;
-       new = alloc_session(&cr_ses->fore_channel, nn);
-       if (!new)
-               return nfserr_jukebox;
+       status = check_forechannel_attrs(&cr_ses->fore_channel, nn);
+       if (status)
+               return status;
+       status = check_backchannel_attrs(&cr_ses->back_channel);
+       if (status)
+               return status;
        status = nfserr_jukebox;
+       new = alloc_session(&cr_ses->fore_channel);
+       if (!new)
+               goto out_release_drc_mem;
        conn = alloc_conn_from_crses(rqstp, cr_ses);
        if (!conn)
                goto out_free_session;
@@ -1816,6 +1876,7 @@ nfsd4_create_session(struct svc_rqst *rqstp,
        nfs4_lock_state();
        unconf = find_unconfirmed_client(&cr_ses->clientid, true, nn);
        conf = find_confirmed_client(&cr_ses->clientid, true, nn);
+       WARN_ON_ONCE(conf && unconf);
 
        if (conf) {
                cs_slot = &conf->cl_cs_slot;
@@ -1842,8 +1903,12 @@ nfsd4_create_session(struct svc_rqst *rqstp,
                        goto out_free_conn;
                }
                old = find_confirmed_client_by_name(&unconf->cl_name, nn);
-               if (old)
+               if (old) {
+                       status = mark_client_expired(old);
+                       if (status)
+                               goto out_free_conn;
                        expire_client(old);
+               }
                move_to_confirmed(unconf);
                conf = unconf;
        } else {
@@ -1862,23 +1927,21 @@ nfsd4_create_session(struct svc_rqst *rqstp,
 
        memcpy(cr_ses->sessionid.data, new->se_sessionid.data,
               NFS4_MAX_SESSIONID_LEN);
-       memcpy(&cr_ses->fore_channel, &new->se_fchannel,
-               sizeof(struct nfsd4_channel_attrs));
        cs_slot->sl_seqid++;
        cr_ses->seqid = cs_slot->sl_seqid;
 
        /* cache solo and embedded create sessions under the state lock */
        nfsd4_cache_create_session(cr_ses, cs_slot, status);
        nfs4_unlock_state();
-out:
-       dprintk("%s returns %d\n", __func__, ntohl(status));
        return status;
 out_free_conn:
        nfs4_unlock_state();
        free_conn(conn);
 out_free_session:
        __free_session(new);
-       goto out;
+out_release_drc_mem:
+       nfsd4_put_drc_mem(&cr_ses->fore_channel);
+       return status;
 }
 
 static __be32 nfsd4_map_bcts_dir(u32 *dir)
@@ -1916,30 +1979,30 @@ __be32 nfsd4_bind_conn_to_session(struct svc_rqst *rqstp,
 {
        __be32 status;
        struct nfsd4_conn *conn;
+       struct nfsd4_session *session;
        struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
 
        if (!nfsd4_last_compound_op(rqstp))
                return nfserr_not_only_op;
+       nfs4_lock_state();
        spin_lock(&nn->client_lock);
-       cstate->session = find_in_sessionid_hashtbl(&bcts->sessionid, SVC_NET(rqstp));
-       /* Sorta weird: we only need the refcnt'ing because new_conn acquires
-        * client_lock iself: */
-       if (cstate->session) {
-               nfsd4_get_session(cstate->session);
-               atomic_inc(&cstate->session->se_client->cl_refcount);
-       }
+       session = find_in_sessionid_hashtbl(&bcts->sessionid, SVC_NET(rqstp));
        spin_unlock(&nn->client_lock);
-       if (!cstate->session)
-               return nfserr_badsession;
-
+       status = nfserr_badsession;
+       if (!session)
+               goto out;
        status = nfsd4_map_bcts_dir(&bcts->dir);
        if (status)
-               return status;
+               goto out;
        conn = alloc_conn(rqstp, bcts->dir);
+       status = nfserr_jukebox;
        if (!conn)
-               return nfserr_jukebox;
-       nfsd4_init_conn(rqstp, conn, cstate->session);
-       return nfs_ok;
+               goto out;
+       nfsd4_init_conn(rqstp, conn, session);
+       status = nfs_ok;
+out:
+       nfs4_unlock_state();
+       return status;
 }
 
 static bool nfsd4_compound_in_session(struct nfsd4_session *session, struct nfs4_sessionid *sid)
@@ -1955,42 +2018,36 @@ nfsd4_destroy_session(struct svc_rqst *r,
                      struct nfsd4_destroy_session *sessionid)
 {
        struct nfsd4_session *ses;
-       __be32 status = nfserr_badsession;
+       __be32 status;
        struct nfsd_net *nn = net_generic(SVC_NET(r), nfsd_net_id);
 
-       /* Notes:
-        * - The confirmed nfs4_client->cl_sessionid holds destroyed sessinid
-        * - Should we return nfserr_back_chan_busy if waiting for
-        *   callbacks on to-be-destroyed session?
-        * - Do we need to clear any callback info from previous session?
-        */
-
+       nfs4_lock_state();
+       status = nfserr_not_only_op;
        if (nfsd4_compound_in_session(cstate->session, &sessionid->sessionid)) {
                if (!nfsd4_last_compound_op(r))
-                       return nfserr_not_only_op;
+                       goto out;
        }
        dump_sessionid(__func__, &sessionid->sessionid);
        spin_lock(&nn->client_lock);
        ses = find_in_sessionid_hashtbl(&sessionid->sessionid, SVC_NET(r));
-       if (!ses) {
-               spin_unlock(&nn->client_lock);
-               goto out;
-       }
-
+       status = nfserr_badsession;
+       if (!ses)
+               goto out_client_lock;
+       status = mark_session_dead_locked(ses);
+       if (status)
+               goto out_client_lock;
        unhash_session(ses);
        spin_unlock(&nn->client_lock);
 
-       nfs4_lock_state();
        nfsd4_probe_callback_sync(ses->se_client);
-       nfs4_unlock_state();
 
        spin_lock(&nn->client_lock);
-       nfsd4_del_conns(ses);
-       nfsd4_put_session_locked(ses);
-       spin_unlock(&nn->client_lock);
+       free_session(ses);
        status = nfs_ok;
+out_client_lock:
+       spin_unlock(&nn->client_lock);
 out:
-       dprintk("%s returns %d\n", __func__, ntohl(status));
+       nfs4_unlock_state();
        return status;
 }
 
@@ -2050,6 +2107,7 @@ nfsd4_sequence(struct svc_rqst *rqstp,
 {
        struct nfsd4_compoundres *resp = rqstp->rq_resp;
        struct nfsd4_session *session;
+       struct nfs4_client *clp;
        struct nfsd4_slot *slot;
        struct nfsd4_conn *conn;
        __be32 status;
@@ -2070,19 +2128,26 @@ nfsd4_sequence(struct svc_rqst *rqstp,
        status = nfserr_badsession;
        session = find_in_sessionid_hashtbl(&seq->sessionid, SVC_NET(rqstp));
        if (!session)
-               goto out;
+               goto out_no_session;
+       clp = session->se_client;
+       status = get_client_locked(clp);
+       if (status)
+               goto out_no_session;
+       status = nfsd4_get_session_locked(session);
+       if (status)
+               goto out_put_client;
 
        status = nfserr_too_many_ops;
        if (nfsd4_session_too_many_ops(rqstp, session))
-               goto out;
+               goto out_put_session;
 
        status = nfserr_req_too_big;
        if (nfsd4_request_too_big(rqstp, session))
-               goto out;
+               goto out_put_session;
 
        status = nfserr_badslot;
        if (seq->slotid >= session->se_fchannel.maxreqs)
-               goto out;
+               goto out_put_session;
 
        slot = session->se_slots[seq->slotid];
        dprintk("%s: slotid %d\n", __func__, seq->slotid);
@@ -2097,7 +2162,7 @@ nfsd4_sequence(struct svc_rqst *rqstp,
        if (status == nfserr_replay_cache) {
                status = nfserr_seq_misordered;
                if (!(slot->sl_flags & NFSD4_SLOT_INITIALIZED))
-                       goto out;
+                       goto out_put_session;
                cstate->slot = slot;
                cstate->session = session;
                /* Return the cached reply status and set cstate->status
@@ -2107,7 +2172,7 @@ nfsd4_sequence(struct svc_rqst *rqstp,
                goto out;
        }
        if (status)
-               goto out;
+               goto out_put_session;
 
        nfsd4_sequence_check_conn(conn, session);
        conn = NULL;
@@ -2124,27 +2189,27 @@ nfsd4_sequence(struct svc_rqst *rqstp,
        cstate->session = session;
 
 out:
-       /* Hold a session reference until done processing the compound. */
-       if (cstate->session) {
-               struct nfs4_client *clp = session->se_client;
-
-               nfsd4_get_session(cstate->session);
-               atomic_inc(&clp->cl_refcount);
-               switch (clp->cl_cb_state) {
-               case NFSD4_CB_DOWN:
-                       seq->status_flags = SEQ4_STATUS_CB_PATH_DOWN;
-                       break;
-               case NFSD4_CB_FAULT:
-                       seq->status_flags = SEQ4_STATUS_BACKCHANNEL_FAULT;
-                       break;
-               default:
-                       seq->status_flags = 0;
-               }
+       switch (clp->cl_cb_state) {
+       case NFSD4_CB_DOWN:
+               seq->status_flags = SEQ4_STATUS_CB_PATH_DOWN;
+               break;
+       case NFSD4_CB_FAULT:
+               seq->status_flags = SEQ4_STATUS_BACKCHANNEL_FAULT;
+               break;
+       default:
+               seq->status_flags = 0;
        }
+       if (!list_empty(&clp->cl_revoked))
+               seq->status_flags |= SEQ4_STATUS_RECALLABLE_STATE_REVOKED;
+out_no_session:
        kfree(conn);
        spin_unlock(&nn->client_lock);
-       dprintk("%s: return %d\n", __func__, ntohl(status));
        return status;
+out_put_session:
+       nfsd4_put_session(session);
+out_put_client:
+       put_client_renew_locked(clp);
+       goto out_no_session;
 }
 
 __be32
@@ -2157,17 +2222,12 @@ nfsd4_destroy_clientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *csta
        nfs4_lock_state();
        unconf = find_unconfirmed_client(&dc->clientid, true, nn);
        conf = find_confirmed_client(&dc->clientid, true, nn);
+       WARN_ON_ONCE(conf && unconf);
 
        if (conf) {
                clp = conf;
 
-               if (!is_client_expired(conf) && client_has_state(conf)) {
-                       status = nfserr_clientid_busy;
-                       goto out;
-               }
-
-               /* rfc5661 18.50.3 */
-               if (cstate->session && conf == cstate->session->se_client) {
+               if (client_has_state(conf)) {
                        status = nfserr_clientid_busy;
                        goto out;
                }
@@ -2181,7 +2241,6 @@ nfsd4_destroy_clientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *csta
        expire_client(clp);
 out:
        nfs4_unlock_state();
-       dprintk("%s return %d\n", __func__, ntohl(status));
        return status;
 }
 
@@ -2319,8 +2378,12 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
                expire_client(unconf);
        } else { /* case 3: normal case; new or rebooted client */
                conf = find_confirmed_client_by_name(&unconf->cl_name, nn);
-               if (conf)
+               if (conf) {
+                       status = mark_client_expired(conf);
+                       if (status)
+                               goto out;
                        expire_client(conf);
+               }
                move_to_confirmed(unconf);
                nfsd4_probe_callback(unconf);
        }
@@ -2340,7 +2403,6 @@ static void nfsd4_init_file(struct nfs4_file *fp, struct inode *ino)
        unsigned int hashval = file_hashval(ino);
 
        atomic_set(&fp->fi_ref, 1);
-       INIT_LIST_HEAD(&fp->fi_hash);
        INIT_LIST_HEAD(&fp->fi_stateids);
        INIT_LIST_HEAD(&fp->fi_delegations);
        fp->fi_inode = igrab(ino);
@@ -2349,7 +2411,7 @@ static void nfsd4_init_file(struct nfs4_file *fp, struct inode *ino)
        memset(fp->fi_fds, 0, sizeof(fp->fi_fds));
        memset(fp->fi_access, 0, sizeof(fp->fi_access));
        spin_lock(&recall_lock);
-       list_add(&fp->fi_hash, &file_hashtbl[hashval]);
+       hlist_add_head(&fp->fi_hash, &file_hashtbl[hashval]);
        spin_unlock(&recall_lock);
 }
 
@@ -2535,7 +2597,7 @@ find_file(struct inode *ino)
        struct nfs4_file *fp;
 
        spin_lock(&recall_lock);
-       list_for_each_entry(fp, &file_hashtbl[hashval], fi_hash) {
+       hlist_for_each_entry(fp, &file_hashtbl[hashval], fi_hash) {
                if (fp->fi_inode == ino) {
                        get_nfs4_file(fp);
                        spin_unlock(&recall_lock);
@@ -2558,8 +2620,6 @@ nfs4_share_conflict(struct svc_fh *current_fh, unsigned int deny_type)
        struct nfs4_ol_stateid *stp;
        __be32 ret;
 
-       dprintk("NFSD: nfs4_share_conflict\n");
-
        fp = find_file(ino);
        if (!fp)
                return nfs_ok;
@@ -2578,6 +2638,9 @@ out:
 
 static void nfsd_break_one_deleg(struct nfs4_delegation *dp)
 {
+       struct nfs4_client *clp = dp->dl_stid.sc_client;
+       struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
+
        /* We're assuming the state code never drops its reference
         * without first removing the lease.  Since we're in this lease
         * callback (and since the lease code is serialized by the kernel
@@ -2585,7 +2648,7 @@ static void nfsd_break_one_deleg(struct nfs4_delegation *dp)
         * it's safe to take a reference: */
        atomic_inc(&dp->dl_count);
 
-       list_add_tail(&dp->dl_recall_lru, &del_recall_lru);
+       list_add_tail(&dp->dl_recall_lru, &nn->del_recall_lru);
 
        /* only place dl_time is set. protected by lock_flocks*/
        dp->dl_time = get_seconds();
@@ -2731,7 +2794,7 @@ static bool nfsd4_is_deleg_cur(struct nfsd4_open *open)
 }
 
 static __be32
-nfs4_check_deleg(struct nfs4_client *cl, struct nfs4_file *fp, struct nfsd4_open *open,
+nfs4_check_deleg(struct nfs4_client *cl, struct nfsd4_open *open,
                struct nfs4_delegation **dp)
 {
        int flags;
@@ -3056,7 +3119,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
        if (fp) {
                if ((status = nfs4_check_open(fp, open, &stp)))
                        goto out;
-               status = nfs4_check_deleg(cl, fp, open, &dp);
+               status = nfs4_check_deleg(cl, open, &dp);
                if (status)
                        goto out;
        } else {
@@ -3234,13 +3297,12 @@ nfs4_laundromat(struct nfsd_net *nn)
                                clientid_val = t;
                        break;
                }
-               if (atomic_read(&clp->cl_refcount)) {
+               if (mark_client_expired_locked(clp)) {
                        dprintk("NFSD: client in use (clientid %08x)\n",
                                clp->cl_clientid.cl_id);
                        continue;
                }
-               unhash_client_locked(clp);
-               list_add(&clp->cl_lru, &reaplist);
+               list_move(&clp->cl_lru, &reaplist);
        }
        spin_unlock(&nn->client_lock);
        list_for_each_safe(pos, next, &reaplist) {
@@ -3250,7 +3312,7 @@ nfs4_laundromat(struct nfsd_net *nn)
                expire_client(clp);
        }
        spin_lock(&recall_lock);
-       list_for_each_safe(pos, next, &del_recall_lru) {
+       list_for_each_safe(pos, next, &nn->del_recall_lru) {
                dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru);
                if (net_generic(dp->dl_stid.sc_client->net, nfsd_net_id) != nn)
                        continue;
@@ -3265,7 +3327,7 @@ nfs4_laundromat(struct nfsd_net *nn)
        spin_unlock(&recall_lock);
        list_for_each_safe(pos, next, &reaplist) {
                dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru);
-               unhash_delegation(dp);
+               revoke_delegation(dp);
        }
        test_val = nn->nfsd4_lease;
        list_for_each_safe(pos, next, &nn->close_lru) {
@@ -3308,16 +3370,6 @@ static inline __be32 nfs4_check_fh(struct svc_fh *fhp, struct nfs4_ol_stateid *s
        return nfs_ok;
 }
 
-static int
-STALE_STATEID(stateid_t *stateid, struct nfsd_net *nn)
-{
-       if (stateid->si_opaque.so_clid.cl_boot == nn->boot_time)
-               return 0;
-       dprintk("NFSD: stale stateid " STATEID_FMT "!\n",
-               STATEID_VAL(stateid));
-       return 1;
-}
-
 static inline int
 access_permit_read(struct nfs4_ol_stateid *stp)
 {
@@ -3434,13 +3486,24 @@ static __be32 nfsd4_validate_stateid(struct nfs4_client *cl, stateid_t *stateid)
        status = check_stateid_generation(stateid, &s->sc_stateid, 1);
        if (status)
                return status;
-       if (!(s->sc_type & (NFS4_OPEN_STID | NFS4_LOCK_STID)))
+       switch (s->sc_type) {
+       case NFS4_DELEG_STID:
+               return nfs_ok;
+       case NFS4_REVOKED_DELEG_STID:
+               return nfserr_deleg_revoked;
+       case NFS4_OPEN_STID:
+       case NFS4_LOCK_STID:
+               ols = openlockstateid(s);
+               if (ols->st_stateowner->so_is_open_owner
+                               && !(openowner(ols->st_stateowner)->oo_flags
+                                               & NFS4_OO_CONFIRMED))
+                       return nfserr_bad_stateid;
                return nfs_ok;
-       ols = openlockstateid(s);
-       if (ols->st_stateowner->so_is_open_owner
-           && !(openowner(ols->st_stateowner)->oo_flags & NFS4_OO_CONFIRMED))
+       default:
+               printk("unknown stateid type %x\n", s->sc_type);
+       case NFS4_CLOSED_STID:
                return nfserr_bad_stateid;
-       return nfs_ok;
+       }
 }
 
 static __be32 nfsd4_lookup_stateid(stateid_t *stateid, unsigned char typemask,
@@ -3448,19 +3511,20 @@ static __be32 nfsd4_lookup_stateid(stateid_t *stateid, unsigned char typemask,
                                   struct nfsd_net *nn)
 {
        struct nfs4_client *cl;
+       __be32 status;
 
        if (ZERO_STATEID(stateid) || ONE_STATEID(stateid))
                return nfserr_bad_stateid;
-       if (STALE_STATEID(stateid, nn))
+       status = lookup_clientid(&stateid->si_opaque.so_clid, sessions,
+                                                       nn, &cl);
+       if (status == nfserr_stale_clientid)
                return nfserr_stale_stateid;
-       cl = find_confirmed_client(&stateid->si_opaque.so_clid, sessions, nn);
-       if (!cl)
-               return nfserr_expired;
+       if (status)
+               return status;
        *s = find_stateid_by_type(cl, stateid, typemask);
        if (!*s)
                return nfserr_bad_stateid;
        return nfs_ok;
-
 }
 
 /*
@@ -3570,6 +3634,7 @@ nfsd4_free_stateid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 {
        stateid_t *stateid = &free_stateid->fr_stateid;
        struct nfs4_stid *s;
+       struct nfs4_delegation *dp;
        struct nfs4_client *cl = cstate->session->se_client;
        __be32 ret = nfserr_bad_stateid;
 
@@ -3591,6 +3656,11 @@ nfsd4_free_stateid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
                else
                        ret = nfserr_locks_held;
                break;
+       case NFS4_REVOKED_DELEG_STID:
+               dp = delegstateid(s);
+               destroy_revoked_delegation(dp);
+               ret = nfs_ok;
+               break;
        default:
                ret = nfserr_bad_stateid;
        }
@@ -3615,10 +3685,12 @@ static __be32 nfs4_seqid_op_checks(struct nfsd4_compound_state *cstate, stateid_
        status = nfsd4_check_seqid(cstate, sop, seqid);
        if (status)
                return status;
-       if (stp->st_stid.sc_type == NFS4_CLOSED_STID)
+       if (stp->st_stid.sc_type == NFS4_CLOSED_STID
+               || stp->st_stid.sc_type == NFS4_REVOKED_DELEG_STID)
                /*
                 * "Closed" stateid's exist *only* to return
-                * nfserr_replay_me from the previous step.
+                * nfserr_replay_me from the previous step, and
+                * revoked delegations are kept only for free_stateid.
                 */
                return nfserr_bad_stateid;
        status = check_stateid_generation(stateid, &stp->st_stid.sc_stateid, nfsd4_has_session(cstate));
@@ -3648,7 +3720,8 @@ nfs4_preprocess_seqid_op(struct nfsd4_compound_state *cstate, u32 seqid,
        if (status)
                return status;
        *stpp = openlockstateid(s);
-       cstate->replay_owner = (*stpp)->st_stateowner;
+       if (!nfsd4_has_session(cstate))
+               cstate->replay_owner = (*stpp)->st_stateowner;
 
        return nfs4_seqid_op_checks(cstate, stateid, seqid, *stpp);
 }
@@ -3706,6 +3779,7 @@ nfsd4_open_confirm(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        nfsd4_client_record_create(oo->oo_owner.so_client);
        status = nfs_ok;
 out:
+       nfsd4_bump_seqid(cstate, status);
        if (!cstate->replay_owner)
                nfs4_unlock_state();
        return status;
@@ -3789,31 +3863,12 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp,
        memcpy(&od->od_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t));
        status = nfs_ok;
 out:
+       nfsd4_bump_seqid(cstate, status);
        if (!cstate->replay_owner)
                nfs4_unlock_state();
        return status;
 }
 
-void nfsd4_purge_closed_stateid(struct nfs4_stateowner *so)
-{
-       struct nfs4_openowner *oo;
-       struct nfs4_ol_stateid *s;
-
-       if (!so->so_is_open_owner)
-               return;
-       oo = openowner(so);
-       s = oo->oo_last_closed_stid;
-       if (!s)
-               return;
-       if (!(oo->oo_flags & NFS4_OO_PURGE_CLOSE)) {
-               /* Release the last_closed_stid on the next seqid bump: */
-               oo->oo_flags |= NFS4_OO_PURGE_CLOSE;
-               return;
-       }
-       oo->oo_flags &= ~NFS4_OO_PURGE_CLOSE;
-       release_last_closed_stateid(oo);
-}
-
 static void nfsd4_close_open_stateid(struct nfs4_ol_stateid *s)
 {
        unhash_open_stateid(s);
@@ -3842,28 +3897,30 @@ nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
                                        &close->cl_stateid,
                                        NFS4_OPEN_STID|NFS4_CLOSED_STID,
                                        &stp, nn);
+       nfsd4_bump_seqid(cstate, status);
        if (status)
                goto out; 
        oo = openowner(stp->st_stateowner);
-       status = nfs_ok;
        update_stateid(&stp->st_stid.sc_stateid);
        memcpy(&close->cl_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t));
 
        nfsd4_close_open_stateid(stp);
-       release_last_closed_stateid(oo);
-       oo->oo_last_closed_stid = stp;
+
+       if (cstate->minorversion) {
+               unhash_stid(&stp->st_stid);
+               free_generic_stateid(stp);
+       } else
+               oo->oo_last_closed_stid = stp;
 
        if (list_empty(&oo->oo_owner.so_stateids)) {
-               if (cstate->minorversion) {
+               if (cstate->minorversion)
                        release_openowner(oo);
-                       cstate->replay_owner = NULL;
-               } else {
+               else {
                        /*
                         * In the 4.0 case we need to keep the owners around a
                         * little while to handle CLOSE replay.
                         */
-                       if (list_empty(&oo->oo_owner.so_stateids))
-                               move_to_close_lru(oo, SVC_NET(rqstp));
+                       move_to_close_lru(oo, SVC_NET(rqstp));
                }
        }
 out:
@@ -3895,7 +3952,7 @@ nfsd4_delegreturn(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        if (status)
                goto out;
 
-       unhash_delegation(dp);
+       destroy_delegation(dp);
 out:
        nfs4_unlock_state();
 
@@ -4273,6 +4330,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 out:
        if (status && new_state)
                release_lockowner(lock_sop);
+       nfsd4_bump_seqid(cstate, status);
        if (!cstate->replay_owner)
                nfs4_unlock_state();
        if (file_lock)
@@ -4382,6 +4440,7 @@ __be32
 nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
            struct nfsd4_locku *locku)
 {
+       struct nfs4_lockowner *lo;
        struct nfs4_ol_stateid *stp;
        struct file *filp = NULL;
        struct file_lock *file_lock = NULL;
@@ -4414,9 +4473,10 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
                status = nfserr_jukebox;
                goto out;
        }
+       lo = lockowner(stp->st_stateowner);
        locks_init_lock(file_lock);
        file_lock->fl_type = F_UNLCK;
-       file_lock->fl_owner = (fl_owner_t)lockowner(stp->st_stateowner);
+       file_lock->fl_owner = (fl_owner_t)lo;
        file_lock->fl_pid = current->tgid;
        file_lock->fl_file = filp;
        file_lock->fl_flags = FL_POSIX;
@@ -4427,21 +4487,21 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
                                                locku->lu_length);
        nfs4_transform_lock_offset(file_lock);
 
-       /*
-       *  Try to unlock the file in the VFS.
-       */
        err = vfs_lock_file(filp, F_SETLK, file_lock, NULL);
        if (err) {
                dprintk("NFSD: nfs4_locku: vfs_lock_file failed!\n");
                goto out_nfserr;
        }
-       /*
-       * OK, unlock succeeded; the only thing left to do is update the stateid.
-       */
        update_stateid(&stp->st_stid.sc_stateid);
        memcpy(&locku->lu_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t));
 
+       if (nfsd4_has_session(cstate) && !check_for_locks(stp->st_file, lo)) {
+               WARN_ON_ONCE(cstate->replay_owner);
+               release_lockowner(lo);
+       }
+
 out:
+       nfsd4_bump_seqid(cstate, status);
        if (!cstate->replay_owner)
                nfs4_unlock_state();
        if (file_lock)
@@ -4634,6 +4694,8 @@ nfs4_check_open_reclaim(clientid_t *clid, bool sessions, struct nfsd_net *nn)
 
 u64 nfsd_forget_client(struct nfs4_client *clp, u64 max)
 {
+       if (mark_client_expired(clp))
+               return 0;
        expire_client(clp);
        return 1;
 }
@@ -4740,7 +4802,7 @@ u64 nfsd_forget_client_delegations(struct nfs4_client *clp, u64 max)
        spin_unlock(&recall_lock);
 
        list_for_each_entry_safe(dp, next, &victims, dl_recall_lru)
-               unhash_delegation(dp);
+               revoke_delegation(dp);
 
        return count;
 }
@@ -4812,12 +4874,6 @@ struct nfs4_client *nfsd_find_client(struct sockaddr_storage *addr, size_t addr_
 void
 nfs4_state_init(void)
 {
-       int i;
-
-       for (i = 0; i < FILE_HASH_SIZE; i++) {
-               INIT_LIST_HEAD(&file_hashtbl[i]);
-       }
-       INIT_LIST_HEAD(&del_recall_lru);
 }
 
 /*
@@ -4881,6 +4937,7 @@ static int nfs4_state_create_net(struct net *net)
        nn->unconf_name_tree = RB_ROOT;
        INIT_LIST_HEAD(&nn->client_lru);
        INIT_LIST_HEAD(&nn->close_lru);
+       INIT_LIST_HEAD(&nn->del_recall_lru);
        spin_lock_init(&nn->client_lock);
 
        INIT_DELAYED_WORK(&nn->laundromat_work, laundromat_main);
@@ -4993,16 +5050,14 @@ nfs4_state_shutdown_net(struct net *net)
 
        INIT_LIST_HEAD(&reaplist);
        spin_lock(&recall_lock);
-       list_for_each_safe(pos, next, &del_recall_lru) {
+       list_for_each_safe(pos, next, &nn->del_recall_lru) {
                dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru);
-               if (dp->dl_stid.sc_client->net != net)
-                       continue;
                list_move(&dp->dl_recall_lru, &reaplist);
        }
        spin_unlock(&recall_lock);
        list_for_each_safe(pos, next, &reaplist) {
                dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru);
-               unhash_delegation(dp);
+               destroy_delegation(dp);
        }
 
        nfsd4_client_tracking_exit(net);
index 2a27456..7827218 100644 (file)
@@ -264,7 +264,7 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
                iattr->ia_valid |= ATTR_SIZE;
        }
        if (bmval[0] & FATTR4_WORD0_ACL) {
-               int nace;
+               u32 nace;
                struct nfs4_ace *ace;
 
                READ_BUF(4); len += 4;
@@ -344,10 +344,7 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
                           all 32 bits of 'nseconds'. */
                        READ_BUF(12);
                        len += 12;
-                       READ32(dummy32);
-                       if (dummy32)
-                               return nfserr_inval;
-                       READ32(iattr->ia_atime.tv_sec);
+                       READ64(iattr->ia_atime.tv_sec);
                        READ32(iattr->ia_atime.tv_nsec);
                        if (iattr->ia_atime.tv_nsec >= (u32)1000000000)
                                return nfserr_inval;
@@ -370,10 +367,7 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
                           all 32 bits of 'nseconds'. */
                        READ_BUF(12);
                        len += 12;
-                       READ32(dummy32);
-                       if (dummy32)
-                               return nfserr_inval;
-                       READ32(iattr->ia_mtime.tv_sec);
+                       READ64(iattr->ia_mtime.tv_sec);
                        READ32(iattr->ia_mtime.tv_nsec);
                        if (iattr->ia_mtime.tv_nsec >= (u32)1000000000)
                                return nfserr_inval;
@@ -804,6 +798,7 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
        open->op_iattr.ia_valid = 0;
        open->op_openowner = NULL;
 
+       open->op_xdr_error = 0;
        /* seqid, share_access, share_deny, clientid, ownerlen */
        READ_BUF(4);
        READ32(open->op_seqid);
@@ -1692,36 +1687,6 @@ static void write_cinfo(__be32 **p, struct nfsd4_change_info *c)
 } while (0)
 #define ADJUST_ARGS()          resp->p = p
 
-/*
- * Header routine to setup seqid operation replay cache
- */
-#define ENCODE_SEQID_OP_HEAD                                   \
-       __be32 *save;                                           \
-                                                               \
-       save = resp->p;
-
-/*
- * Routine for encoding the result of a "seqid-mutating" NFSv4 operation.  This
- * is where sequence id's are incremented, and the replay cache is filled.
- * Note that we increment sequence id's here, at the last moment, so we're sure
- * we know whether the error to be returned is a sequence id mutating error.
- */
-
-static void encode_seqid_op_tail(struct nfsd4_compoundres *resp, __be32 *save, __be32 nfserr)
-{
-       struct nfs4_stateowner *stateowner = resp->cstate.replay_owner;
-
-       if (seqid_mutating_err(ntohl(nfserr)) && stateowner) {
-               stateowner->so_seqid++;
-               stateowner->so_replay.rp_status = nfserr;
-               stateowner->so_replay.rp_buflen =
-                         (char *)resp->p - (char *)save;
-               memcpy(stateowner->so_replay.rp_buf, save,
-                       stateowner->so_replay.rp_buflen);
-               nfsd4_purge_closed_stateid(stateowner);
-       }
-}
-
 /* Encode as an array of strings the string given with components
  * separated @sep, escaped with esc_enter and esc_exit.
  */
@@ -2401,8 +2366,7 @@ out_acl:
        if (bmval1 & FATTR4_WORD1_TIME_ACCESS) {
                if ((buflen -= 12) < 0)
                        goto out_resource;
-               WRITE32(0);
-               WRITE32(stat.atime.tv_sec);
+               WRITE64((s64)stat.atime.tv_sec);
                WRITE32(stat.atime.tv_nsec);
        }
        if (bmval1 & FATTR4_WORD1_TIME_DELTA) {
@@ -2415,15 +2379,13 @@ out_acl:
        if (bmval1 & FATTR4_WORD1_TIME_METADATA) {
                if ((buflen -= 12) < 0)
                        goto out_resource;
-               WRITE32(0);
-               WRITE32(stat.ctime.tv_sec);
+               WRITE64((s64)stat.ctime.tv_sec);
                WRITE32(stat.ctime.tv_nsec);
        }
        if (bmval1 & FATTR4_WORD1_TIME_MODIFY) {
                if ((buflen -= 12) < 0)
                        goto out_resource;
-               WRITE32(0);
-               WRITE32(stat.mtime.tv_sec);
+               WRITE64((s64)stat.mtime.tv_sec);
                WRITE32(stat.mtime.tv_nsec);
        }
        if (bmval1 & FATTR4_WORD1_MOUNTED_ON_FILEID) {
@@ -2661,12 +2623,9 @@ static __be32 nfsd4_encode_bind_conn_to_session(struct nfsd4_compoundres *resp,
 static __be32
 nfsd4_encode_close(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_close *close)
 {
-       ENCODE_SEQID_OP_HEAD;
-
        if (!nfserr)
                nfsd4_encode_stateid(resp, &close->cl_stateid);
 
-       encode_seqid_op_tail(resp, save, nfserr);
        return nfserr;
 }
 
@@ -2762,14 +2721,11 @@ nfsd4_encode_lock_denied(struct nfsd4_compoundres *resp, struct nfsd4_lock_denie
 static __be32
 nfsd4_encode_lock(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_lock *lock)
 {
-       ENCODE_SEQID_OP_HEAD;
-
        if (!nfserr)
                nfsd4_encode_stateid(resp, &lock->lk_resp_stateid);
        else if (nfserr == nfserr_denied)
                nfsd4_encode_lock_denied(resp, &lock->lk_denied);
 
-       encode_seqid_op_tail(resp, save, nfserr);
        return nfserr;
 }
 
@@ -2784,12 +2740,9 @@ nfsd4_encode_lockt(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_l
 static __be32
 nfsd4_encode_locku(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_locku *locku)
 {
-       ENCODE_SEQID_OP_HEAD;
-
        if (!nfserr)
                nfsd4_encode_stateid(resp, &locku->lu_stateid);
 
-       encode_seqid_op_tail(resp, save, nfserr);
        return nfserr;
 }
 
@@ -2812,7 +2765,6 @@ static __be32
 nfsd4_encode_open(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open *open)
 {
        __be32 *p;
-       ENCODE_SEQID_OP_HEAD;
 
        if (nfserr)
                goto out;
@@ -2884,31 +2836,24 @@ nfsd4_encode_open(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_op
        }
        /* XXX save filehandle here */
 out:
-       encode_seqid_op_tail(resp, save, nfserr);
        return nfserr;
 }
 
 static __be32
 nfsd4_encode_open_confirm(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open_confirm *oc)
 {
-       ENCODE_SEQID_OP_HEAD;
-
        if (!nfserr)
                nfsd4_encode_stateid(resp, &oc->oc_resp_stateid);
 
-       encode_seqid_op_tail(resp, save, nfserr);
        return nfserr;
 }
 
 static __be32
 nfsd4_encode_open_downgrade(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open_downgrade *od)
 {
-       ENCODE_SEQID_OP_HEAD;
-
        if (!nfserr)
                nfsd4_encode_stateid(resp, &od->od_stateid);
 
-       encode_seqid_op_tail(resp, save, nfserr);
        return nfserr;
 }
 
@@ -3564,6 +3509,7 @@ __be32 nfsd4_check_resp_size(struct nfsd4_compoundres *resp, u32 pad)
 void
 nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
 {
+       struct nfs4_stateowner *so = resp->cstate.replay_owner;
        __be32 *statp;
        __be32 *p;
 
@@ -3580,6 +3526,11 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
        /* nfsd4_check_drc_limit guarantees enough room for error status */
        if (!op->status)
                op->status = nfsd4_check_resp_size(resp, 0);
+       if (so) {
+               so->so_replay.rp_status = op->status;
+               so->so_replay.rp_buflen = (char *)resp->p - (char *)(statp+1);
+               memcpy(so->so_replay.rp_buf, statp+1, so->so_replay.rp_buflen);
+       }
 status:
        /*
         * Note: We write the status directly, instead of using WRITE32(),
@@ -3681,7 +3632,7 @@ nfs4svc_encode_compoundres(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compo
                        cs->slot->sl_flags &= ~NFSD4_SLOT_INUSE;
                }
                /* Renew the clientid on success and on replay */
-               release_session_client(cs->session);
+               put_client_renew(cs->session->se_client);
                nfsd4_put_session(cs->session);
        }
        return 1;
index 62c1ee1..eb25877 100644 (file)
@@ -11,6 +11,8 @@
 #include <linux/slab.h>
 #include <linux/sunrpc/addr.h>
 #include <linux/highmem.h>
+#include <linux/log2.h>
+#include <linux/hash.h>
 #include <net/checksum.h>
 
 #include "nfsd.h"
 
 #define NFSDDBG_FACILITY       NFSDDBG_REPCACHE
 
-#define HASHSIZE               64
+/*
+ * We use this value to determine the number of hash buckets from the max
+ * cache size, the idea being that when the cache is at its maximum number
+ * of entries, then this should be the average number of entries per bucket.
+ */
+#define TARGET_BUCKET_SIZE     64
 
 static struct hlist_head *     cache_hash;
 static struct list_head        lru_head;
 static struct kmem_cache       *drc_slab;
-static unsigned int            num_drc_entries;
+
+/* max number of entries allowed in the cache */
 static unsigned int            max_drc_entries;
 
+/* number of significant bits in the hash value */
+static unsigned int            maskbits;
+
 /*
- * Calculate the hash index from an XID.
+ * Stats and other tracking of on the duplicate reply cache. All of these and
+ * the "rc" fields in nfsdstats are protected by the cache_lock
  */
-static inline u32 request_hash(u32 xid)
-{
-       u32 h = xid;
-       h ^= (xid >> 24);
-       return h & (HASHSIZE-1);
-}
+
+/* total number of entries */
+static unsigned int            num_drc_entries;
+
+/* cache misses due only to checksum comparison failures */
+static unsigned int            payload_misses;
+
+/* amount of memory (in bytes) currently consumed by the DRC */
+static unsigned int            drc_mem_usage;
+
+/* longest hash chain seen */
+static unsigned int            longest_chain;
+
+/* size of cache when we saw the longest hash chain */
+static unsigned int            longest_chain_cachesize;
 
 static int     nfsd_cache_append(struct svc_rqst *rqstp, struct kvec *vec);
 static void    cache_cleaner_func(struct work_struct *unused);
@@ -82,6 +103,16 @@ nfsd_cache_size_limit(void)
        return min_t(unsigned int, limit, 256*1024);
 }
 
+/*
+ * Compute the number of hash buckets we need. Divide the max cachesize by
+ * the "target" max bucket size, and round up to next power of two.
+ */
+static unsigned int
+nfsd_hashsize(unsigned int limit)
+{
+       return roundup_pow_of_two(limit / TARGET_BUCKET_SIZE);
+}
+
 static struct svc_cacherep *
 nfsd_reply_cache_alloc(void)
 {
@@ -100,11 +131,15 @@ nfsd_reply_cache_alloc(void)
 static void
 nfsd_reply_cache_free_locked(struct svc_cacherep *rp)
 {
-       if (rp->c_type == RC_REPLBUFF)
+       if (rp->c_type == RC_REPLBUFF && rp->c_replvec.iov_base) {
+               drc_mem_usage -= rp->c_replvec.iov_len;
                kfree(rp->c_replvec.iov_base);
-       hlist_del(&rp->c_hash);
+       }
+       if (!hlist_unhashed(&rp->c_hash))
+               hlist_del(&rp->c_hash);
        list_del(&rp->c_lru);
        --num_drc_entries;
+       drc_mem_usage -= sizeof(*rp);
        kmem_cache_free(drc_slab, rp);
 }
 
@@ -118,20 +153,24 @@ nfsd_reply_cache_free(struct svc_cacherep *rp)
 
 int nfsd_reply_cache_init(void)
 {
+       unsigned int hashsize;
+
+       INIT_LIST_HEAD(&lru_head);
+       max_drc_entries = nfsd_cache_size_limit();
+       num_drc_entries = 0;
+       hashsize = nfsd_hashsize(max_drc_entries);
+       maskbits = ilog2(hashsize);
+
        register_shrinker(&nfsd_reply_cache_shrinker);
        drc_slab = kmem_cache_create("nfsd_drc", sizeof(struct svc_cacherep),
                                        0, 0, NULL);
        if (!drc_slab)
                goto out_nomem;
 
-       cache_hash = kcalloc(HASHSIZE, sizeof(struct hlist_head), GFP_KERNEL);
+       cache_hash = kcalloc(hashsize, sizeof(struct hlist_head), GFP_KERNEL);
        if (!cache_hash)
                goto out_nomem;
 
-       INIT_LIST_HEAD(&lru_head);
-       max_drc_entries = nfsd_cache_size_limit();
-       num_drc_entries = 0;
-
        return 0;
 out_nomem:
        printk(KERN_ERR "nfsd: failed to allocate reply cache\n");
@@ -179,7 +218,7 @@ static void
 hash_refile(struct svc_cacherep *rp)
 {
        hlist_del_init(&rp->c_hash);
-       hlist_add_head(&rp->c_hash, cache_hash + request_hash(rp->c_xid));
+       hlist_add_head(&rp->c_hash, cache_hash + hash_32(rp->c_xid, maskbits));
 }
 
 static inline bool
@@ -272,6 +311,26 @@ nfsd_cache_csum(struct svc_rqst *rqstp)
        return csum;
 }
 
+static bool
+nfsd_cache_match(struct svc_rqst *rqstp, __wsum csum, struct svc_cacherep *rp)
+{
+       /* Check RPC header info first */
+       if (rqstp->rq_xid != rp->c_xid || rqstp->rq_proc != rp->c_proc ||
+           rqstp->rq_prot != rp->c_prot || rqstp->rq_vers != rp->c_vers ||
+           rqstp->rq_arg.len != rp->c_len ||
+           !rpc_cmp_addr(svc_addr(rqstp), (struct sockaddr *)&rp->c_addr) ||
+           rpc_get_port(svc_addr(rqstp)) != rpc_get_port((struct sockaddr *)&rp->c_addr))
+               return false;
+
+       /* compare checksum of NFS data */
+       if (csum != rp->c_csum) {
+               ++payload_misses;
+               return false;
+       }
+
+       return true;
+}
+
 /*
  * Search the request hash for an entry that matches the given rqstp.
  * Must be called with cache_lock held. Returns the found entry or
@@ -280,23 +339,30 @@ nfsd_cache_csum(struct svc_rqst *rqstp)
 static struct svc_cacherep *
 nfsd_cache_search(struct svc_rqst *rqstp, __wsum csum)
 {
-       struct svc_cacherep     *rp;
+       struct svc_cacherep     *rp, *ret = NULL;
        struct hlist_head       *rh;
-       __be32                  xid = rqstp->rq_xid;
-       u32                     proto =  rqstp->rq_prot,
-                               vers = rqstp->rq_vers,
-                               proc = rqstp->rq_proc;
+       unsigned int            entries = 0;
 
-       rh = &cache_hash[request_hash(xid)];
+       rh = &cache_hash[hash_32(rqstp->rq_xid, maskbits)];
        hlist_for_each_entry(rp, rh, c_hash) {
-               if (xid == rp->c_xid && proc == rp->c_proc &&
-                   proto == rp->c_prot && vers == rp->c_vers &&
-                   rqstp->rq_arg.len == rp->c_len && csum == rp->c_csum &&
-                   rpc_cmp_addr(svc_addr(rqstp), (struct sockaddr *)&rp->c_addr) &&
-                   rpc_get_port(svc_addr(rqstp)) == rpc_get_port((struct sockaddr *)&rp->c_addr))
-                       return rp;
+               ++entries;
+               if (nfsd_cache_match(rqstp, csum, rp)) {
+                       ret = rp;
+                       break;
+               }
        }
-       return NULL;
+
+       /* tally hash chain length stats */
+       if (entries > longest_chain) {
+               longest_chain = entries;
+               longest_chain_cachesize = num_drc_entries;
+       } else if (entries == longest_chain) {
+               /* prefer to keep the smallest cachesize possible here */
+               longest_chain_cachesize = min(longest_chain_cachesize,
+                                               num_drc_entries);
+       }
+
+       return ret;
 }
 
 /*
@@ -317,55 +383,55 @@ nfsd_cache_lookup(struct svc_rqst *rqstp)
        __wsum                  csum;
        unsigned long           age;
        int type = rqstp->rq_cachetype;
-       int rtn;
+       int rtn = RC_DOIT;
 
        rqstp->rq_cacherep = NULL;
        if (type == RC_NOCACHE) {
                nfsdstats.rcnocache++;
-               return RC_DOIT;
+               return rtn;
        }
 
        csum = nfsd_cache_csum(rqstp);
 
+       /*
+        * Since the common case is a cache miss followed by an insert,
+        * preallocate an entry. First, try to reuse the first entry on the LRU
+        * if it works, then go ahead and prune the LRU list.
+        */
        spin_lock(&cache_lock);
-       rtn = RC_DOIT;
-
-       rp = nfsd_cache_search(rqstp, csum);
-       if (rp)
-               goto found_entry;
-
-       /* Try to use the first entry on the LRU */
        if (!list_empty(&lru_head)) {
                rp = list_first_entry(&lru_head, struct svc_cacherep, c_lru);
                if (nfsd_cache_entry_expired(rp) ||
                    num_drc_entries >= max_drc_entries) {
                        lru_put_end(rp);
                        prune_cache_entries();
-                       goto setup_entry;
+                       goto search_cache;
                }
        }
 
-       /* Drop the lock and allocate a new entry */
+       /* No expired ones available, allocate a new one. */
        spin_unlock(&cache_lock);
        rp = nfsd_reply_cache_alloc();
-       if (!rp) {
-               dprintk("nfsd: unable to allocate DRC entry!\n");
-               return RC_DOIT;
-       }
        spin_lock(&cache_lock);
-       ++num_drc_entries;
+       if (likely(rp)) {
+               ++num_drc_entries;
+               drc_mem_usage += sizeof(*rp);
+       }
 
-       /*
-        * Must search again just in case someone inserted one
-        * after we dropped the lock above.
-        */
+search_cache:
        found = nfsd_cache_search(rqstp, csum);
        if (found) {
-               nfsd_reply_cache_free_locked(rp);
+               if (likely(rp))
+                       nfsd_reply_cache_free_locked(rp);
                rp = found;
                goto found_entry;
        }
 
+       if (!rp) {
+               dprintk("nfsd: unable to allocate DRC entry!\n");
+               goto out;
+       }
+
        /*
         * We're keeping the one we just allocated. Are we now over the
         * limit? Prune one off the tip of the LRU in trade for the one we
@@ -375,7 +441,6 @@ nfsd_cache_lookup(struct svc_rqst *rqstp)
                nfsd_reply_cache_free_locked(list_first_entry(&lru_head,
                                                struct svc_cacherep, c_lru));
 
-setup_entry:
        nfsdstats.rcmisses++;
        rqstp->rq_cacherep = rp;
        rp->c_state = RC_INPROG;
@@ -393,6 +458,7 @@ setup_entry:
 
        /* release any buffer */
        if (rp->c_type == RC_REPLBUFF) {
+               drc_mem_usage -= rp->c_replvec.iov_len;
                kfree(rp->c_replvec.iov_base);
                rp->c_replvec.iov_base = NULL;
        }
@@ -461,6 +527,7 @@ nfsd_cache_update(struct svc_rqst *rqstp, int cachetype, __be32 *statp)
        struct svc_cacherep *rp = rqstp->rq_cacherep;
        struct kvec     *resv = &rqstp->rq_res.head[0], *cachv;
        int             len;
+       size_t          bufsize = 0;
 
        if (!rp)
                return;
@@ -482,19 +549,21 @@ nfsd_cache_update(struct svc_rqst *rqstp, int cachetype, __be32 *statp)
                break;
        case RC_REPLBUFF:
                cachv = &rp->c_replvec;
-               cachv->iov_base = kmalloc(len << 2, GFP_KERNEL);
+               bufsize = len << 2;
+               cachv->iov_base = kmalloc(bufsize, GFP_KERNEL);
                if (!cachv->iov_base) {
                        nfsd_reply_cache_free(rp);
                        return;
                }
-               cachv->iov_len = len << 2;
-               memcpy(cachv->iov_base, statp, len << 2);
+               cachv->iov_len = bufsize;
+               memcpy(cachv->iov_base, statp, bufsize);
                break;
        case RC_NOCACHE:
                nfsd_reply_cache_free(rp);
                return;
        }
        spin_lock(&cache_lock);
+       drc_mem_usage += bufsize;
        lru_put_end(rp);
        rp->c_secure = rqstp->rq_secure;
        rp->c_type = cachetype;
@@ -522,3 +591,30 @@ nfsd_cache_append(struct svc_rqst *rqstp, struct kvec *data)
        vec->iov_len += data->iov_len;
        return 1;
 }
+
+/*
+ * Note that fields may be added, removed or reordered in the future. Programs
+ * scraping this file for info should test the labels to ensure they're
+ * getting the correct field.
+ */
+static int nfsd_reply_cache_stats_show(struct seq_file *m, void *v)
+{
+       spin_lock(&cache_lock);
+       seq_printf(m, "max entries:           %u\n", max_drc_entries);
+       seq_printf(m, "num entries:           %u\n", num_drc_entries);
+       seq_printf(m, "hash buckets:          %u\n", 1 << maskbits);
+       seq_printf(m, "mem usage:             %u\n", drc_mem_usage);
+       seq_printf(m, "cache hits:            %u\n", nfsdstats.rchits);
+       seq_printf(m, "cache misses:          %u\n", nfsdstats.rcmisses);
+       seq_printf(m, "not cached:            %u\n", nfsdstats.rcnocache);
+       seq_printf(m, "payload misses:        %u\n", payload_misses);
+       seq_printf(m, "longest chain len:     %u\n", longest_chain);
+       seq_printf(m, "cachesize at longest:  %u\n", longest_chain_cachesize);
+       spin_unlock(&cache_lock);
+       return 0;
+}
+
+int nfsd_reply_cache_stats_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, nfsd_reply_cache_stats_show, NULL);
+}
index 13a21c8..68a4d32 100644 (file)
@@ -35,6 +35,7 @@ enum {
        NFSD_Threads,
        NFSD_Pool_Threads,
        NFSD_Pool_Stats,
+       NFSD_Reply_Cache_Stats,
        NFSD_Versions,
        NFSD_Ports,
        NFSD_MaxBlkSize,
@@ -212,6 +213,13 @@ static const struct file_operations pool_stats_operations = {
        .owner          = THIS_MODULE,
 };
 
+static struct file_operations reply_cache_stats_operations = {
+       .open           = nfsd_reply_cache_stats_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
 /*----------------------------------------------------------------------------*/
 /*
  * payload - write methods
@@ -1047,6 +1055,7 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
                [NFSD_Threads] = {"threads", &transaction_ops, S_IWUSR|S_IRUSR},
                [NFSD_Pool_Threads] = {"pool_threads", &transaction_ops, S_IWUSR|S_IRUSR},
                [NFSD_Pool_Stats] = {"pool_stats", &pool_stats_operations, S_IRUGO},
+               [NFSD_Reply_Cache_Stats] = {"reply_cache_stats", &reply_cache_stats_operations, S_IRUGO},
                [NFSD_Versions] = {"versions", &transaction_ops, S_IWUSR|S_IRUSR},
                [NFSD_Ports] = {"portlist", &transaction_ops, S_IWUSR|S_IRUGO},
                [NFSD_MaxBlkSize] = {"max_block_size", &transaction_ops, S_IWUSR|S_IRUGO},
@@ -1090,6 +1099,7 @@ static struct file_system_type nfsd_fs_type = {
        .mount          = nfsd_mount,
        .kill_sb        = nfsd_umount,
 };
+MODULE_ALIAS_FS("nfsd");
 
 #ifdef CONFIG_PROC_FS
 static int create_proc_exports_entry(void)
@@ -1101,8 +1111,10 @@ static int create_proc_exports_entry(void)
                return -ENOMEM;
        entry = proc_create("exports", 0, entry,
                                 &exports_proc_operations);
-       if (!entry)
+       if (!entry) {
+               remove_proc_entry("fs/nfs", NULL);
                return -ENOMEM;
+       }
        return 0;
 }
 #else /* CONFIG_PROC_FS */
index 1a8c739..274e2a1 100644 (file)
@@ -79,6 +79,8 @@ struct nfs4_stid {
 #define NFS4_DELEG_STID 4
 /* For an open stateid kept around *only* to process close replays: */
 #define NFS4_CLOSED_STID 8
+/* For a deleg stateid kept around only to process free_stateid's: */
+#define NFS4_REVOKED_DELEG_STID 16
        unsigned char sc_type;
        stateid_t sc_stateid;
        struct nfs4_client *sc_client;
@@ -194,9 +196,11 @@ struct nfsd4_conn {
 };
 
 struct nfsd4_session {
-       struct kref             se_ref;
+       atomic_t                se_ref;
        struct list_head        se_hash;        /* hash by sessionid */
        struct list_head        se_perclnt;
+/* See SESSION4_PERSIST, etc. for standard flags; this is internal-only: */
+#define NFS4_SESSION_DEAD      0x010
        u32                     se_flags;
        struct nfs4_client      *se_client;
        struct nfs4_sessionid   se_sessionid;
@@ -236,6 +240,7 @@ struct nfs4_client {
        struct list_head        cl_openowners;
        struct idr              cl_stateids;    /* stateid lookup */
        struct list_head        cl_delegations;
+       struct list_head        cl_revoked;     /* unacknowledged, revoked 4.1 state */
        struct list_head        cl_lru;         /* tail queue */
        struct xdr_netobj       cl_name;        /* id generated by client */
        nfs4_verifier           cl_verifier;    /* generated by client */
@@ -286,18 +291,6 @@ struct nfs4_client {
        struct net              *net;
 };
 
-static inline void
-mark_client_expired(struct nfs4_client *clp)
-{
-       clp->cl_time = 0;
-}
-
-static inline bool
-is_client_expired(struct nfs4_client *clp)
-{
-       return clp->cl_time == 0;
-}
-
 /* struct nfs4_client_reset
  * one per old client. Populates reset_str_hashtbl. Filled from conf_id_hashtbl
  * upon lease reset, or from upcall to state_daemon (to read in state
@@ -365,7 +358,6 @@ struct nfs4_openowner {
        struct nfs4_ol_stateid *oo_last_closed_stid;
        time_t                  oo_time; /* time of placement on so_close_lru */
 #define NFS4_OO_CONFIRMED   1
-#define NFS4_OO_PURGE_CLOSE 2
 #define NFS4_OO_NEW         4
        unsigned char           oo_flags;
 };
@@ -373,7 +365,7 @@ struct nfs4_openowner {
 struct nfs4_lockowner {
        struct nfs4_stateowner  lo_owner; /* must be first element */
        struct list_head        lo_owner_ino_hash; /* hash by owner,file */
-       struct list_head        lo_perstateid; /* for lockowners only */
+       struct list_head        lo_perstateid;
        struct list_head        lo_list; /* for temporary uses */
 };
 
@@ -390,7 +382,7 @@ static inline struct nfs4_lockowner * lockowner(struct nfs4_stateowner *so)
 /* nfs4_file: a file opened by some number of (open) nfs4_stateowners. */
 struct nfs4_file {
        atomic_t                fi_ref;
-       struct list_head        fi_hash;    /* hash by "struct inode *" */
+       struct hlist_node       fi_hash;    /* hash by "struct inode *" */
        struct list_head        fi_stateids;
        struct list_head        fi_delegations;
        /* One each for O_RDONLY, O_WRONLY, O_RDWR: */
@@ -486,8 +478,7 @@ extern void nfs4_put_delegation(struct nfs4_delegation *dp);
 extern struct nfs4_client_reclaim *nfs4_client_to_reclaim(const char *name,
                                                        struct nfsd_net *nn);
 extern bool nfs4_has_reclaimed_state(const char *name, struct nfsd_net *nn);
-extern void release_session_client(struct nfsd4_session *);
-extern void nfsd4_purge_closed_stateid(struct nfs4_stateowner *);
+extern void put_client_renew(struct nfs4_client *clp);
 
 /* nfs4recover operations */
 extern int nfsd4_client_tracking_init(struct net *net);
index 2a7eb53..84ce601 100644 (file)
@@ -1013,6 +1013,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
        int                     host_err;
        int                     stable = *stablep;
        int                     use_wgather;
+       loff_t                  pos = offset;
 
        dentry = file->f_path.dentry;
        inode = dentry->d_inode;
@@ -1025,7 +1026,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
 
        /* Write the data. */
        oldfs = get_fs(); set_fs(KERNEL_DS);
-       host_err = vfs_writev(file, (struct iovec __user *)vec, vlen, &offset);
+       host_err = vfs_writev(file, (struct iovec __user *)vec, vlen, &pos);
        set_fs(oldfs);
        if (host_err < 0)
                goto out_nfserr;
@@ -1757,10 +1758,6 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
        tdentry = tfhp->fh_dentry;
        tdir = tdentry->d_inode;
 
-       err = (rqstp->rq_vers == 2) ? nfserr_acces : nfserr_xdev;
-       if (ffhp->fh_export != tfhp->fh_export)
-               goto out;
-
        err = nfserr_perm;
        if (!flen || isdotent(fname, flen) || !tlen || isdotent(tname, tlen))
                goto out;
@@ -1801,6 +1798,8 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
        host_err = -EXDEV;
        if (ffhp->fh_export->ex_path.mnt != tfhp->fh_export->ex_path.mnt)
                goto out_dput_new;
+       if (ffhp->fh_export->ex_path.dentry != tfhp->fh_export->ex_path.dentry)
+               goto out_dput_new;
 
        host_err = nfsd_break_lease(odentry->d_inode);
        if (host_err)
index 546f898..3b271d2 100644 (file)
@@ -184,7 +184,6 @@ struct nfsd4_lock {
 #define lk_old_lock_stateid     v.old.lock_stateid
 #define lk_old_lock_seqid       v.old.lock_seqid
 
-#define lk_rflags       u.ok.rflags
 #define lk_resp_stateid u.ok.stateid
 #define lk_denied       u.denied
 
@@ -237,6 +236,7 @@ struct nfsd4_open {
        u32             op_share_deny;      /* request */
        u32             op_deleg_want;      /* request */
        stateid_t       op_stateid;         /* response */
+       __be32          op_xdr_error;       /* see nfsd4_open_omfg() */
        u32             op_recall;          /* recall */
        struct nfsd4_change_info  op_cinfo; /* response */
        u32             op_rflags;          /* response */
@@ -623,6 +623,7 @@ extern __be32 nfsd4_test_stateid(struct svc_rqst *rqstp,
                struct nfsd4_compound_state *, struct nfsd4_test_stateid *test_stateid);
 extern __be32 nfsd4_free_stateid(struct svc_rqst *rqstp,
                struct nfsd4_compound_state *, struct nfsd4_free_stateid *free_stateid);
+extern void nfsd4_bump_seqid(struct nfsd4_compound_state *, __be32 nfserr);
 #endif
 
 /*
diff --git a/fs/nfsd/xdr4cb.h b/fs/nfsd/xdr4cb.h
new file mode 100644 (file)
index 0000000..c5c55df
--- /dev/null
@@ -0,0 +1,23 @@
+#define NFS4_MAXTAGLEN         20
+
+#define NFS4_enc_cb_null_sz            0
+#define NFS4_dec_cb_null_sz            0
+#define cb_compound_enc_hdr_sz         4
+#define cb_compound_dec_hdr_sz         (3 + (NFS4_MAXTAGLEN >> 2))
+#define sessionid_sz                   (NFS4_MAX_SESSIONID_LEN >> 2)
+#define cb_sequence_enc_sz             (sessionid_sz + 4 +             \
+                                       1 /* no referring calls list yet */)
+#define cb_sequence_dec_sz             (op_dec_sz + sessionid_sz + 4)
+
+#define op_enc_sz                      1
+#define op_dec_sz                      2
+#define enc_nfs4_fh_sz                 (1 + (NFS4_FHSIZE >> 2))
+#define enc_stateid_sz                 (NFS4_STATEID_SIZE >> 2)
+#define NFS4_enc_cb_recall_sz          (cb_compound_enc_hdr_sz +       \
+                                       cb_sequence_enc_sz +            \
+                                       1 + enc_stateid_sz +            \
+                                       enc_nfs4_fh_sz)
+
+#define NFS4_dec_cb_recall_sz          (cb_compound_dec_hdr_sz  +      \
+                                       cb_sequence_dec_sz +            \
+                                       op_dec_sz)
index 3c991dc..c7d1f9f 100644 (file)
@@ -1361,6 +1361,7 @@ struct file_system_type nilfs_fs_type = {
        .kill_sb  = kill_block_super,
        .fs_flags = FS_REQUIRES_DEV,
 };
+MODULE_ALIAS_FS("nilfs2");
 
 static void nilfs_inode_init_once(void *obj)
 {
index 4a8289f..82650d5 100644 (file)
@@ -3079,6 +3079,7 @@ static struct file_system_type ntfs_fs_type = {
        .kill_sb        = kill_block_super,
        .fs_flags       = FS_REQUIRES_DEV,
 };
+MODULE_ALIAS_FS("ntfs");
 
 /* Stable names for the slab caches. */
 static const char ntfs_index_ctx_cache_name[] = "ntfs_index_ctx_cache";
index 4c5fc8d..12bafb7 100644 (file)
@@ -640,6 +640,7 @@ static struct file_system_type dlmfs_fs_type = {
        .mount          = dlmfs_mount,
        .kill_sb        = kill_litter_super,
 };
+MODULE_ALIAS_FS("ocfs2_dlmfs");
 
 static int __init init_dlmfs_fs(void)
 {
index 9b6910d..01b8516 100644 (file)
@@ -1266,6 +1266,7 @@ static struct file_system_type ocfs2_fs_type = {
        .fs_flags       = FS_REQUIRES_DEV|FS_RENAME_DOES_D_MOVE,
        .next           = NULL
 };
+MODULE_ALIAS_FS("ocfs2");
 
 static int ocfs2_check_set_options(struct super_block *sb,
                                   struct mount_options *options)
index 25d715c..d8b0afd 100644 (file)
@@ -572,6 +572,7 @@ static struct file_system_type omfs_fs_type = {
        .kill_sb = kill_block_super,
        .fs_flags = FS_REQUIRES_DEV,
 };
+MODULE_ALIAS_FS("omfs");
 
 static int __init init_omfs_fs(void)
 {
index ae47fa7..75885ff 100644 (file)
@@ -432,6 +432,7 @@ static struct file_system_type openprom_fs_type = {
        .mount          = openprom_mount,
        .kill_sb        = kill_anon_super,
 };
+MODULE_ALIAS_FS("openpromfs");
 
 static void op_inode_init_once(void *data)
 {
index 64a494c..2234f3f 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -863,6 +863,9 @@ pipe_rdwr_open(struct inode *inode, struct file *filp)
 {
        int ret = -ENOENT;
 
+       if (!(filp->f_mode & (FMODE_READ|FMODE_WRITE)))
+               return -EINVAL;
+
        mutex_lock(&inode->i_mutex);
 
        if (inode->i_pipe) {
index b7a4719..66b51c0 100644 (file)
@@ -118,7 +118,7 @@ static void *proc_ns_follow_link(struct dentry *dentry, struct nameidata *nd)
        struct super_block *sb = inode->i_sb;
        struct proc_inode *ei = PROC_I(inode);
        struct task_struct *task;
-       struct dentry *ns_dentry;
+       struct path ns_path;
        void *error = ERR_PTR(-EACCES);
 
        task = get_proc_task(inode);
@@ -128,14 +128,14 @@ static void *proc_ns_follow_link(struct dentry *dentry, struct nameidata *nd)
        if (!ptrace_may_access(task, PTRACE_MODE_READ))
                goto out_put_task;
 
-       ns_dentry = proc_ns_get_dentry(sb, task, ei->ns_ops);
-       if (IS_ERR(ns_dentry)) {
-               error = ERR_CAST(ns_dentry);
+       ns_path.dentry = proc_ns_get_dentry(sb, task, ei->ns_ops);
+       if (IS_ERR(ns_path.dentry)) {
+               error = ERR_CAST(ns_path.dentry);
                goto out_put_task;
        }
 
-       dput(nd->path.dentry);
-       nd->path.dentry = ns_dentry;
+       ns_path.mnt = mntget(nd->path.mnt);
+       nd_jump_link(nd, &ns_path);
        error = NULL;
 
 out_put_task:
index 43098bb..2e8caa6 100644 (file)
@@ -412,6 +412,7 @@ static struct file_system_type qnx4_fs_type = {
        .kill_sb        = kill_block_super,
        .fs_flags       = FS_REQUIRES_DEV,
 };
+MODULE_ALIAS_FS("qnx4");
 
 static int __init init_qnx4_fs(void)
 {
index 57199a5..8d941ed 100644 (file)
@@ -672,6 +672,7 @@ static struct file_system_type qnx6_fs_type = {
        .kill_sb        = kill_block_super,
        .fs_flags       = FS_REQUIRES_DEV,
 };
+MODULE_ALIAS_FS("qnx6");
 
 static int __init init_qnx6_fs(void)
 {
index 05ae3c9..3e64169 100644 (file)
@@ -1439,8 +1439,11 @@ static void __dquot_initialize(struct inode *inode, int type)
                         * did a write before quota was turned on
                         */
                        rsv = inode_get_rsv_space(inode);
-                       if (unlikely(rsv))
+                       if (unlikely(rsv)) {
+                               spin_lock(&dq_data_lock);
                                dquot_resv_space(inode->i_dquot[cnt], rsv);
+                               spin_unlock(&dq_data_lock);
+                       }
                }
        }
 out_err:
index 418bdc3..f8a23c3 100644 (file)
@@ -1147,8 +1147,7 @@ static int reiserfs_parse_options(struct super_block *s, char *options,   /* strin
                                                         "on filesystem root.");
                                        return 0;
                                }
-                               qf_names[qtype] =
-                                   kmalloc(strlen(arg) + 1, GFP_KERNEL);
+                               qf_names[qtype] = kstrdup(arg, GFP_KERNEL);
                                if (!qf_names[qtype]) {
                                        reiserfs_warning(s, "reiserfs-2502",
                                                         "not enough memory "
@@ -1156,7 +1155,6 @@ static int reiserfs_parse_options(struct super_block *s, char *options,   /* strin
                                                         "quotafile name.");
                                        return 0;
                                }
-                               strcpy(qf_names[qtype], arg);
                                if (qtype == USRQUOTA)
                                        *mount_options |= 1 << REISERFS_USRQUOTA;
                                else
@@ -2434,6 +2432,7 @@ struct file_system_type reiserfs_fs_type = {
        .kill_sb = reiserfs_kill_sb,
        .fs_flags = FS_REQUIRES_DEV,
 };
+MODULE_ALIAS_FS("reiserfs");
 
 MODULE_DESCRIPTION("ReiserFS journaled filesystem");
 MODULE_AUTHOR("Hans Reiser <reiser@namesys.com>");
index 7e8d3a8..15cbc41 100644 (file)
@@ -599,6 +599,7 @@ static struct file_system_type romfs_fs_type = {
        .kill_sb        = romfs_kill_sb,
        .fs_flags       = FS_REQUIRES_DEV,
 };
+MODULE_ALIAS_FS("romfs");
 
 /*
  * inode storage initialiser
index 260e392..60553a9 100644 (file)
@@ -489,6 +489,7 @@ static struct file_system_type squashfs_fs_type = {
        .kill_sb = kill_block_super,
        .fs_flags = FS_REQUIRES_DEV
 };
+MODULE_ALIAS_FS("squashfs");
 
 static const struct super_operations squashfs_super_ops = {
        .alloc_inode = squashfs_alloc_inode,
index a38e87b..d0c6a00 100644 (file)
@@ -545,6 +545,7 @@ static struct file_system_type sysv_fs_type = {
        .kill_sb        = kill_block_super,
        .fs_flags       = FS_REQUIRES_DEV,
 };
+MODULE_ALIAS_FS("sysv");
 
 static struct file_system_type v7_fs_type = {
        .owner          = THIS_MODULE,
@@ -553,6 +554,8 @@ static struct file_system_type v7_fs_type = {
        .kill_sb        = kill_block_super,
        .fs_flags       = FS_REQUIRES_DEV,
 };
+MODULE_ALIAS_FS("v7");
+MODULE_ALIAS("v7");
 
 static int __init init_sysv_fs(void)
 {
@@ -586,5 +589,4 @@ static void __exit exit_sysv_fs(void)
 
 module_init(init_sysv_fs)
 module_exit(exit_sysv_fs)
-MODULE_ALIAS("v7");
 MODULE_LICENSE("GPL");
index ddc0f6a..ac838b8 100644 (file)
@@ -2174,6 +2174,7 @@ static struct file_system_type ubifs_fs_type = {
        .mount   = ubifs_mount,
        .kill_sb = kill_ubifs_super,
 };
+MODULE_ALIAS_FS("ubifs");
 
 /*
  * Inode slab cache constructor.
index bc5b30a..9ac4057 100644 (file)
@@ -118,6 +118,7 @@ static struct file_system_type udf_fstype = {
        .kill_sb        = kill_block_super,
        .fs_flags       = FS_REQUIRES_DEV,
 };
+MODULE_ALIAS_FS("udf");
 
 static struct kmem_cache *udf_inode_cachep;
 
index dc8e3a8..329f2f5 100644 (file)
@@ -1500,6 +1500,7 @@ static struct file_system_type ufs_fs_type = {
        .kill_sb        = kill_block_super,
        .fs_flags       = FS_REQUIRES_DEV,
 };
+MODULE_ALIAS_FS("ufs");
 
 static int __init init_ufs_fs(void)
 {
index c407121..ea341ce 100644 (file)
@@ -1561,6 +1561,7 @@ static struct file_system_type xfs_fs_type = {
        .kill_sb                = kill_block_super,
        .fs_flags               = FS_REQUIRES_DEV,
 };
+MODULE_ALIAS_FS("xfs");
 
 STATIC int __init
 xfs_init_zones(void)
index e65278f..22ba56e 100644 (file)
@@ -437,11 +437,9 @@ void acpi_remove_dir(struct acpi_device *);
  */
 struct acpi_bus_type {
        struct list_head list;
-       struct bus_type *bus;
-       /* For general devices under the bus */
+       const char *name;
+       bool (*match)(struct device *dev);
        int (*find_device) (struct device *, acpi_handle *);
-       /* For bridges, such as PCI root bridge, IDE controller */
-       int (*find_bridge) (struct device *, acpi_handle *);
        void (*setup)(struct device *);
        void (*cleanup)(struct device *);
 };
index 555d033..b327b5a 100644 (file)
@@ -235,6 +235,9 @@ extern void acpi_processor_unregister_performance(struct
          if a _PPC object exists, rmmod is disallowed then */
 int acpi_processor_notify_smm(struct module *calling_module);
 
+/* parsing the _P* objects. */
+extern int acpi_processor_get_performance_info(struct acpi_processor *pr);
+
 /* for communication between multiple parts of the processor kernel module */
 DECLARE_PER_CPU(struct acpi_processor *, processors);
 extern struct acpi_processor_errata errata;
index 1ced641..33bd2de 100644 (file)
@@ -136,12 +136,6 @@ static inline void atomic_dec(atomic_t *v)
 #define atomic_xchg(ptr, v)            (xchg(&(ptr)->counter, (v)))
 #define atomic_cmpxchg(v, old, new)    (cmpxchg(&((v)->counter), (old), (new)))
 
-#define cmpxchg_local(ptr, o, n)                                              \
-       ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
-                       (unsigned long)(n), sizeof(*(ptr))))
-
-#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
-
 static inline int __atomic_add_unless(atomic_t *v, int a, int u)
 {
   int c, old;
index 1488302..811fb1e 100644 (file)
@@ -92,6 +92,16 @@ unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
  */
 #include <asm-generic/cmpxchg-local.h>
 
+#ifndef cmpxchg_local
+#define cmpxchg_local(ptr, o, n)                                              \
+       ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
+                       (unsigned long)(n), sizeof(*(ptr))))
+#endif
+
+#ifndef cmpxchg64_local
+#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
+#endif
+
 #define cmpxchg(ptr, o, n)     cmpxchg_local((ptr), (o), (n))
 #define cmpxchg64(ptr, o, n)   cmpxchg64_local((ptr), (o), (n))
 
index 8839b3a..e3e0d65 100644 (file)
@@ -443,12 +443,12 @@ struct drm_crtc {
  * @dpms: set power state (see drm_crtc_funcs above)
  * @save: save connector state
  * @restore: restore connector state
- * @reset: reset connector after state has been invalidate (e.g. resume)
+ * @reset: reset connector after state has been invalidated (e.g. resume)
  * @detect: is this connector active?
  * @fill_modes: fill mode list for this connector
- * @set_property: property for this connector may need update
+ * @set_property: property for this connector may need an update
  * @destroy: make object go away
- * @force: notify the driver the connector is forced on
+ * @force: notify the driver that the connector is forced on
  *
  * Each CRTC may have one or more connectors attached to it.  The functions
  * below allow the core DRM code to control connectors, enumerate available modes,
index 2224a8c..8d5ab99 100644 (file)
@@ -6,9 +6,8 @@
 #define ECRYPTFS_VERSION_MINOR 0x04
 #define ECRYPTFS_SUPPORTED_FILE_VERSION 0x03
 /* These flags indicate which features are supported by the kernel
- * module; userspace tools such as the mount helper read
- * ECRYPTFS_VERSIONING_MASK from a sysfs handle in order to determine
- * how to behave. */
+ * module; userspace tools such as the mount helper read the feature
+ * bits from a sysfs handle in order to determine how to behave. */
 #define ECRYPTFS_VERSIONING_PASSPHRASE            0x00000001
 #define ECRYPTFS_VERSIONING_PUBKEY                0x00000002
 #define ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH 0x00000004
 #define ECRYPTFS_VERSIONING_HMAC                  0x00000080
 #define ECRYPTFS_VERSIONING_FILENAME_ENCRYPTION   0x00000100
 #define ECRYPTFS_VERSIONING_GCM                   0x00000200
-#define ECRYPTFS_VERSIONING_MASK (ECRYPTFS_VERSIONING_PASSPHRASE \
-                                 | ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH \
-                                 | ECRYPTFS_VERSIONING_PUBKEY \
-                                 | ECRYPTFS_VERSIONING_XATTR \
-                                 | ECRYPTFS_VERSIONING_MULTKEY \
-                                 | ECRYPTFS_VERSIONING_DEVMISC \
-                                 | ECRYPTFS_VERSIONING_FILENAME_ENCRYPTION)
 #define ECRYPTFS_MAX_PASSWORD_LENGTH 64
 #define ECRYPTFS_MAX_PASSPHRASE_BYTES ECRYPTFS_MAX_PASSWORD_LENGTH
 #define ECRYPTFS_SALT_SIZE 8
index 74a907b..2c28271 100644 (file)
@@ -1825,6 +1825,8 @@ struct file_system_type {
        struct lock_class_key i_mutex_dir_key;
 };
 
+#define MODULE_ALIAS_FS(NAME) MODULE_ALIAS("fs-" NAME)
+
 extern struct dentry *mount_ns(struct file_system_type *fs_type, int flags,
        void *data, int (*fill_super)(struct super_block *, void *, int));
 extern struct dentry *mount_bdev(struct file_system_type *fs_type,
index 29eb805..c1d6555 100644 (file)
 
 #ifdef CONFIG_PREEMPT_COUNT
 # define preemptible() (preempt_count() == 0 && !irqs_disabled())
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
 #else
 # define preemptible() 0
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
 #endif
 
 #if defined(CONFIG_SMP) || defined(CONFIG_GENERIC_HARDIRQS)
index f027f7a..99e379b 100644 (file)
@@ -15,6 +15,9 @@
 
 #include <linux/types.h>
 
+/* For key_map array */
+#define MXT_NUM_GPIO           4
+
 /* Orient */
 #define MXT_NORMAL             0x0
 #define MXT_DIAGONAL           0x1
@@ -39,6 +42,8 @@ struct mxt_platform_data {
        unsigned int voltage;
        unsigned char orient;
        unsigned long irqflags;
+       bool is_tp;
+       const unsigned int key_map[MXT_NUM_GPIO];
 };
 
 #endif /* __LINUX_ATMEL_MXT_TS_H */
index a6f38b5..2640c7e 100644 (file)
@@ -73,8 +73,6 @@ struct idr {
  */
 
 void *idr_find_slowpath(struct idr *idp, int id);
-int idr_pre_get(struct idr *idp, gfp_t gfp_mask);
-int idr_get_new_above(struct idr *idp, void *ptr, int starting_id, int *id);
 void idr_preload(gfp_t gfp_mask);
 int idr_alloc(struct idr *idp, void *ptr, int start, int end, gfp_t gfp_mask);
 int idr_for_each(struct idr *idp,
@@ -99,7 +97,7 @@ static inline void idr_preload_end(void)
 
 /**
  * idr_find - return pointer for given id
- * @idp: idr handle
+ * @idr: idr handle
  * @id: lookup key
  *
  * Return the pointer given the id it has been registered with.  A %NULL
@@ -120,19 +118,6 @@ static inline void *idr_find(struct idr *idr, int id)
 }
 
 /**
- * idr_get_new - allocate new idr entry
- * @idp: idr handle
- * @ptr: pointer you want associated with the id
- * @id: pointer to the allocated handle
- *
- * Simple wrapper around idr_get_new_above() w/ @starting_id of zero.
- */
-static inline int idr_get_new(struct idr *idp, void *ptr, int *id)
-{
-       return idr_get_new_above(idp, ptr, 0, id);
-}
-
-/**
  * idr_for_each_entry - iterate over an idr's elements of a given type
  * @idp:     idr handle
  * @entry:   the type * to use as cursor
@@ -143,7 +128,56 @@ static inline int idr_get_new(struct idr *idp, void *ptr, int *id)
             entry != NULL;                                             \
             ++id, entry = (typeof(entry))idr_get_next((idp), &(id)))
 
-void __idr_remove_all(struct idr *idp);        /* don't use */
+/*
+ * Don't use the following functions.  These exist only to suppress
+ * deprecated warnings on EXPORT_SYMBOL()s.
+ */
+int __idr_pre_get(struct idr *idp, gfp_t gfp_mask);
+int __idr_get_new_above(struct idr *idp, void *ptr, int starting_id, int *id);
+void __idr_remove_all(struct idr *idp);
+
+/**
+ * idr_pre_get - reserve resources for idr allocation
+ * @idp:       idr handle
+ * @gfp_mask:  memory allocation flags
+ *
+ * Part of old alloc interface.  This is going away.  Use
+ * idr_preload[_end]() and idr_alloc() instead.
+ */
+static inline int __deprecated idr_pre_get(struct idr *idp, gfp_t gfp_mask)
+{
+       return __idr_pre_get(idp, gfp_mask);
+}
+
+/**
+ * idr_get_new_above - allocate new idr entry above or equal to a start id
+ * @idp: idr handle
+ * @ptr: pointer you want associated with the id
+ * @starting_id: id to start search at
+ * @id: pointer to the allocated handle
+ *
+ * Part of old alloc interface.  This is going away.  Use
+ * idr_preload[_end]() and idr_alloc() instead.
+ */
+static inline int __deprecated idr_get_new_above(struct idr *idp, void *ptr,
+                                                int starting_id, int *id)
+{
+       return __idr_get_new_above(idp, ptr, starting_id, id);
+}
+
+/**
+ * idr_get_new - allocate new idr entry
+ * @idp: idr handle
+ * @ptr: pointer you want associated with the id
+ * @id: pointer to the allocated handle
+ *
+ * Part of old alloc interface.  This is going away.  Use
+ * idr_preload[_end]() and idr_alloc() instead.
+ */
+static inline int __deprecated idr_get_new(struct idr *idp, void *ptr, int *id)
+{
+       return __idr_get_new_above(idp, ptr, 0, id);
+}
 
 /**
  * idr_remove_all - remove all ids from the given idr tree
index 1f86a97..8bd12be 100644 (file)
@@ -227,14 +227,17 @@ struct st_sensor_data {
 };
 
 #ifdef CONFIG_IIO_BUFFER
+irqreturn_t st_sensors_trigger_handler(int irq, void *p);
+
+int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf);
+#endif
+
+#ifdef CONFIG_IIO_TRIGGER
 int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
                                const struct iio_trigger_ops *trigger_ops);
 
 void st_sensors_deallocate_trigger(struct iio_dev *indio_dev);
 
-irqreturn_t st_sensors_trigger_handler(int irq, void *p);
-
-int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf);
 #else
 static inline int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
                                const struct iio_trigger_ops *trigger_ops)
index d991cc1..6a1f8df 100644 (file)
@@ -667,7 +667,9 @@ static inline void hlist_move_list(struct hlist_head *old,
             pos = n)
 
 #define hlist_entry_safe(ptr, type, member) \
-       (ptr) ? hlist_entry(ptr, type, member) : NULL
+       ({ typeof(ptr) ____ptr = (ptr); \
+          ____ptr ? hlist_entry(____ptr, type, member) : NULL; \
+       })
 
 /**
  * hlist_for_each_entry        - iterate over list of given type
index a4d13d7..3bbda22 100644 (file)
@@ -221,6 +221,7 @@ struct palmas_clk_platform_data {
 };
 
 struct palmas_platform_data {
+       int irq_flags;
        int gpio_base;
 
        /* bit value to be loaded to the POWER_CTRL register */
index aaceab4..6d30903 100644 (file)
@@ -323,5 +323,6 @@ int tps65912_device_init(struct tps65912 *tps65912);
 void tps65912_device_exit(struct tps65912 *tps65912);
 int tps65912_irq_init(struct tps65912 *tps65912, int irq,
                        struct tps65912_platform_data *pdata);
+int tps65912_irq_exit(struct tps65912 *tps65912);
 
 #endif /*  __LINUX_MFD_TPS65912_H */
index b132067..867aa23 100644 (file)
@@ -15,6 +15,8 @@
 #ifndef __MFD_WM831X_AUXADC_H__
 #define __MFD_WM831X_AUXADC_H__
 
+struct wm831x;
+
 /*
  * R16429 (0x402D) - AuxADC Data
  */
index 4a3b83a..76c2264 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/irqdomain.h>
 #include <linux/list.h>
 #include <linux/regmap.h>
+#include <linux/mfd/wm831x/auxadc.h>
 
 /*
  * Register values.
@@ -355,7 +356,6 @@ enum wm831x_parent {
 };
 
 struct wm831x;
-enum wm831x_auxadc;
 
 typedef int (*wm831x_auxadc_read_fn)(struct wm831x *wm831x,
                                     enum wm831x_auxadc input);
index ef9acd3..01d25e6 100644 (file)
@@ -854,6 +854,8 @@ type_pf_tresize(struct ip_set *set, bool retried)
 retry:
        ret = 0;
        htable_bits++;
+       pr_debug("attempt to resize set %s from %u to %u, t %p\n",
+                set->name, orig->htable_bits, htable_bits, orig);
        if (!htable_bits) {
                /* In case we have plenty of memory :-) */
                pr_warning("Cannot increase the hashsize of set %s further\n",
@@ -873,7 +875,7 @@ retry:
                        data = ahash_tdata(n, j);
                        m = hbucket(t, HKEY(data, h->initval, htable_bits));
                        ret = type_pf_elem_tadd(m, data, AHASH_MAX(h), 0,
-                                               type_pf_data_timeout(data));
+                                               ip_set_timeout_get(type_pf_data_timeout(data)));
                        if (ret < 0) {
                                read_unlock_bh(&set->lock);
                                ahash_destroy(t);
index e47ee46..1d795df 100644 (file)
@@ -799,6 +799,12 @@ static inline int __perf_event_disable(void *info)                 { return -1; }
 static inline void perf_event_task_tick(void)                          { }
 #endif
 
+#if defined(CONFIG_PERF_EVENTS) && defined(CONFIG_CPU_SUP_INTEL)
+extern void perf_restore_debug_store(void);
+#else
+static inline void perf_restore_debug_store(void)                      { }
+#endif
+
 #define perf_output_put(handle, x) perf_output_copy((handle), &(x), sizeof(x))
 
 /*
index 23070fd..7df93f5 100644 (file)
@@ -199,6 +199,8 @@ enum regulator_type {
  *                output when using regulator_set_voltage_sel_regmap
  * @enable_reg: Register for control when using regmap enable/disable ops
  * @enable_mask: Mask for control when using regmap enable/disable ops
+ * @bypass_reg: Register for control when using regmap set_bypass
+ * @bypass_mask: Mask for control when using regmap set_bypass
  *
  * @enable_time: Time taken for initial enable of regulator (in uS).
  */
index 5ae8456..c230994 100644 (file)
@@ -14,6 +14,7 @@
  */
 
 #include <linux/cgroup.h>
+#include <linux/errno.h>
 
 /*
  * The core object. the cgroup that wishes to account for some
index c65dee0..13e9296 100644 (file)
@@ -24,6 +24,9 @@ struct smpboot_thread_data;
  *                     parked (cpu offline)
  * @unpark:            Optional unpark function, called when the thread is
  *                     unparked (cpu online)
+ * @pre_unpark:                Optional unpark function, called before the thread is
+ *                     unparked (cpu online). This is not guaranteed to be
+ *                     called on the target cpu of the thread. Careful!
  * @selfparking:       Thread is not parked by the park function.
  * @thread_comm:       The base name of the thread
  */
@@ -37,6 +40,7 @@ struct smp_hotplug_thread {
        void                            (*cleanup)(unsigned int cpu, bool online);
        void                            (*park)(unsigned int cpu);
        void                            (*unpark)(unsigned int cpu);
+       void                            (*pre_unpark)(unsigned int cpu);
        bool                            selfparking;
        const char                      *thread_comm;
 };
index e7d492c..bfe11be 100644 (file)
@@ -125,6 +125,7 @@ struct rpc_create_args {
 #define RPC_CLNT_CREATE_DISCRTRY       (1UL << 5)
 #define RPC_CLNT_CREATE_QUIET          (1UL << 6)
 #define RPC_CLNT_CREATE_INFINITE_SLOTS (1UL << 7)
+#define RPC_CLNT_CREATE_NO_IDLE_TIMEOUT        (1UL << 8)
 
 struct rpc_clnt *rpc_create(struct rpc_create_args *args);
 struct rpc_clnt        *rpc_bind_new_program(struct rpc_clnt *,
index f32b7a4..161463e 100644 (file)
@@ -48,6 +48,7 @@ int gss_import_sec_context(
                size_t                  bufsize,
                struct gss_api_mech     *mech,
                struct gss_ctx          **ctx_id,
+               time_t                  *endtime,
                gfp_t                   gfp_mask);
 u32 gss_get_mic(
                struct gss_ctx          *ctx_id,
@@ -105,6 +106,7 @@ struct gss_api_ops {
                        const void              *input_token,
                        size_t                  bufsize,
                        struct gss_ctx          *ctx_id,
+                       time_t                  *endtime,
                        gfp_t                   gfp_mask);
        u32 (*gss_get_mic)(
                        struct gss_ctx          *ctx_id,
@@ -130,6 +132,10 @@ struct gss_api_ops {
 int gss_mech_register(struct gss_api_mech *);
 void gss_mech_unregister(struct gss_api_mech *);
 
+/* returns a mechanism descriptor given an OID, and increments the mechanism's
+ * reference count. */
+struct gss_api_mech * gss_mech_get_by_OID(struct rpcsec_gss_oid *);
+
 /* Given a GSS security tuple, look up a pseudoflavor */
 rpc_authflavor_t gss_mech_info2flavor(struct rpcsec_gss_info *);
 
index c68a147..aadc6a0 100644 (file)
@@ -138,6 +138,9 @@ typedef __be32      rpc_fraghdr;
 #define RPC_MAX_HEADER_WITH_AUTH \
        (RPC_CALLHDRSIZE + 2*(2+RPC_MAX_AUTH_SIZE/4))
 
+#define RPC_MAX_REPHEADER_WITH_AUTH \
+       (RPC_REPHDRSIZE + (2 + RPC_MAX_AUTH_SIZE/4))
+
 /*
  * RFC1833/RFC3530 rpcbind (v3+) well-known netid's.
  */
index ff53924..cec7b9b 100644 (file)
@@ -256,6 +256,7 @@ static inline int bc_prealloc(struct rpc_rqst *req)
 #endif /* CONFIG_SUNRPC_BACKCHANNEL */
 
 #define XPRT_CREATE_INFINITE_SLOTS     (1U)
+#define XPRT_CREATE_NO_IDLE_TIMEOUT    (1U << 1)
 
 struct xprt_create {
        int                     ident;          /* XPRT_TRANSPORT identifier */
index 3c671c1..8860594 100644 (file)
@@ -60,7 +60,7 @@ struct usb_configuration;
  * @name: For diagnostics, identifies the function.
  * @strings: tables of strings, keyed by identifiers assigned during bind()
  *     and by language IDs provided in control requests
- * @descriptors: Table of full (or low) speed descriptors, using interface and
+ * @fs_descriptors: Table of full (or low) speed descriptors, using interface and
  *     string identifiers assigned during @bind().  If this pointer is null,
  *     the function will not be available at full speed (or at low speed).
  * @hs_descriptors: Table of high speed descriptors, using interface and
@@ -290,6 +290,7 @@ enum {
  *     after function notifications
  * @resume: Notifies configuration when the host restarts USB traffic,
  *     before function notifications
+ * @gadget_driver: Gadget driver controlling this driver
  *
  * Devices default to reporting self powered operation.  Devices which rely
  * on bus powered operation should report this in their @bind method.
index 23f2e98..cf0694d 100644 (file)
@@ -1045,6 +1045,10 @@ static inline bool tcp_prequeue(struct sock *sk, struct sk_buff *skb)
        if (sysctl_tcp_low_latency || !tp->ucopy.task)
                return false;
 
+       if (skb->len <= tcp_hdrlen(skb) &&
+           skb_queue_len(&tp->ucopy.prequeue) == 0)
+               return false;
+
        __skb_queue_tail(&tp->ucopy.prequeue, skb);
        tp->ucopy.memory += skb->truesize;
        if (tp->ucopy.memory > sk->sk_rcvbuf) {
index 11b6ca3..df2f9a0 100644 (file)
@@ -107,10 +107,12 @@ struct acct_v3
 #define ACORE          0x08    /* ... dumped core */
 #define AXSIG          0x10    /* ... was killed by a signal */
 
-#ifdef __BIG_ENDIAN
+#if defined(__BYTE_ORDER) ? __BYTE_ORDER == __BIG_ENDIAN : defined(__BIG_ENDIAN)
 #define ACCT_BYTEORDER 0x80    /* accounting file is big endian */
-#else
+#elif defined(__BYTE_ORDER) ? __BYTE_ORDER == __LITTLE_ENDIAN : defined(__LITTLE_ENDIAN)
 #define ACCT_BYTEORDER 0x00    /* accounting file is little endian */
+#else
+#error unspecified endianness
 #endif
 
 #ifndef __KERNEL__
index 86fa7a7..bb2554f 100644 (file)
@@ -62,9 +62,9 @@ struct io_event {
        __s64           res2;           /* secondary result */
 };
 
-#if defined(__LITTLE_ENDIAN)
+#if defined(__BYTE_ORDER) ? __BYTE_ORDER == __LITTLE_ENDIAN : defined(__LITTLE_ENDIAN)
 #define PADDED(x,y)    x, y
-#elif defined(__BIG_ENDIAN)
+#elif defined(__BYTE_ORDER) ? __BYTE_ORDER == __BIG_ENDIAN : defined(__BIG_ENDIAN)
 #define PADDED(x,y)    y, x
 #else
 #error edit for your odd byteorder.
index ee75353..fe1a540 100644 (file)
@@ -145,16 +145,18 @@ typedef struct mdp_superblock_s {
        __u32 failed_disks;     /*  4 Number of failed disks                  */
        __u32 spare_disks;      /*  5 Number of spare disks                   */
        __u32 sb_csum;          /*  6 checksum of the whole superblock        */
-#ifdef __BIG_ENDIAN
+#if defined(__BYTE_ORDER) ? __BYTE_ORDER == __BIG_ENDIAN : defined(__BIG_ENDIAN)
        __u32 events_hi;        /*  7 high-order of superblock update count   */
        __u32 events_lo;        /*  8 low-order of superblock update count    */
        __u32 cp_events_hi;     /*  9 high-order of checkpoint update count   */
        __u32 cp_events_lo;     /* 10 low-order of checkpoint update count    */
-#else
+#elif defined(__BYTE_ORDER) ? __BYTE_ORDER == __LITTLE_ENDIAN : defined(__LITTLE_ENDIAN)
        __u32 events_lo;        /*  7 low-order of superblock update count    */
        __u32 events_hi;        /*  8 high-order of superblock update count   */
        __u32 cp_events_lo;     /*  9 low-order of checkpoint update count    */
        __u32 cp_events_hi;     /* 10 high-order of checkpoint update count   */
+#else
+#error unspecified endianness
 #endif
        __u32 recovery_cp;      /* 11 recovery checkpoint sector count        */
        /* There are only valid for minor_version > 90 */
index b6a23a4..74c2bf7 100644 (file)
 #define PORT_8250_CIR  23      /* CIR infrared port, has its own driver */
 #define PORT_XR17V35X  24      /* Exar XR17V35x UARTs */
 #define PORT_BRCM_TRUMANAGE    25
-#define PORT_MAX_8250  25      /* max port ID */
+#define PORT_ALTR_16550_F32 26 /* Altera 16550 UART with 32 FIFOs */
+#define PORT_ALTR_16550_F64 27 /* Altera 16550 UART with 64 FIFOs */
+#define PORT_ALTR_16550_F128 28 /* Altera 16550 UART with 128 FIFOs */
+#define PORT_MAX_8250  28      /* max port ID */
 
 /*
  * ARM specific type numbers.  These are not currently guaranteed
index 22616cd..5341d72 100644 (file)
@@ -28,10 +28,6 @@ config BUILDTIME_EXTABLE_SORT
 
 menu "General setup"
 
-config EXPERIMENTAL
-       bool
-       default y
-
 config BROKEN
        bool
 
index 950572f..31cd1bf 100644 (file)
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -820,15 +820,17 @@ long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp,
        struct msg_msg *copy = NULL;
        unsigned long copy_number = 0;
 
+       ns = current->nsproxy->ipc_ns;
+
        if (msqid < 0 || (long) bufsz < 0)
                return -EINVAL;
        if (msgflg & MSG_COPY) {
-               copy = prepare_copy(buf, bufsz, msgflg, &msgtyp, &copy_number);
+               copy = prepare_copy(buf, min_t(size_t, bufsz, ns->msg_ctlmax),
+                                   msgflg, &msgtyp, &copy_number);
                if (IS_ERR(copy))
                        return PTR_ERR(copy);
        }
        mode = convert_mode(&msgtyp, msgflg);
-       ns = current->nsproxy->ipc_ns;
 
        msq = msg_lock_check(ns, msqid);
        if (IS_ERR(msq)) {
index ebfcbfa..5df8e4b 100644 (file)
@@ -117,9 +117,6 @@ struct msg_msg *copy_msg(struct msg_msg *src, struct msg_msg *dst)
        if (alen > DATALEN_MSG)
                alen = DATALEN_MSG;
 
-       dst->next = NULL;
-       dst->security = NULL;
-
        memcpy(dst + 1, src + 1, alen);
 
        len -= alen;
index 8d932b1..1766d32 100644 (file)
@@ -1141,6 +1141,9 @@ static struct task_struct *copy_process(unsigned long clone_flags,
        if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS))
                return ERR_PTR(-EINVAL);
 
+       if ((clone_flags & (CLONE_NEWUSER|CLONE_FS)) == (CLONE_NEWUSER|CLONE_FS))
+               return ERR_PTR(-EINVAL);
+
        /*
         * Thread groups must share signals as well, and detached threads
         * can only be started up within the thread group.
@@ -1807,7 +1810,7 @@ SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags)
         * If unsharing a user namespace must also unshare the thread.
         */
        if (unshare_flags & CLONE_NEWUSER)
-               unshare_flags |= CLONE_THREAD;
+               unshare_flags |= CLONE_THREAD | CLONE_FS;
        /*
         * If unsharing a pid namespace must also unshare the thread.
         */
index f0090a9..b26dcfc 100644 (file)
@@ -223,7 +223,8 @@ static void drop_futex_key_refs(union futex_key *key)
  * @rw:                mapping needs to be read/write (values: VERIFY_READ,
  *              VERIFY_WRITE)
  *
- * Returns a negative error code or 0
+ * Return: a negative error code or 0
+ *
  * The key words are stored in *key on success.
  *
  * For shared mappings, it's (page->index, file_inode(vma->vm_file),
@@ -705,9 +706,9 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb,
  *                     be "current" except in the case of requeue pi.
  * @set_waiters:       force setting the FUTEX_WAITERS bit (1) or not (0)
  *
- * Returns:
- *  0 - ready to wait
- *  1 - acquired the lock
+ * Return:
+ *  0 - ready to wait;
+ *  1 - acquired the lock;
  * <0 - error
  *
  * The hb->lock and futex_key refs shall be held by the caller.
@@ -1191,9 +1192,9 @@ void requeue_pi_wake_futex(struct futex_q *q, union futex_key *key,
  * then direct futex_lock_pi_atomic() to force setting the FUTEX_WAITERS bit.
  * hb1 and hb2 must be held by the caller.
  *
- * Returns:
- *  0 - failed to acquire the lock atomicly
- *  1 - acquired the lock
+ * Return:
+ *  0 - failed to acquire the lock atomically;
+ *  1 - acquired the lock;
  * <0 - error
  */
 static int futex_proxy_trylock_atomic(u32 __user *pifutex,
@@ -1254,8 +1255,8 @@ static int futex_proxy_trylock_atomic(u32 __user *pifutex,
  * Requeue waiters on uaddr1 to uaddr2. In the requeue_pi case, try to acquire
  * uaddr2 atomically on behalf of the top waiter.
  *
- * Returns:
- * >=0 - on success, the number of tasks requeued or woken
+ * Return:
+ * >=0 - on success, the number of tasks requeued or woken;
  *  <0 - on error
  */
 static int futex_requeue(u32 __user *uaddr1, unsigned int flags,
@@ -1536,8 +1537,8 @@ static inline void queue_me(struct futex_q *q, struct futex_hash_bucket *hb)
  * The q->lock_ptr must not be held by the caller. A call to unqueue_me() must
  * be paired with exactly one earlier call to queue_me().
  *
- * Returns:
- *   1 - if the futex_q was still queued (and we removed unqueued it)
+ * Return:
+ *   1 - if the futex_q was still queued (and we removed unqueued it);
  *   0 - if the futex_q was already removed by the waking thread
  */
 static int unqueue_me(struct futex_q *q)
@@ -1707,9 +1708,9 @@ static long futex_wait_restart(struct restart_block *restart);
  * the pi_state owner as well as handle race conditions that may allow us to
  * acquire the lock. Must be called with the hb lock held.
  *
- * Returns:
- *  1 - success, lock taken
- *  0 - success, lock not taken
+ * Return:
+ *  1 - success, lock taken;
+ *  0 - success, lock not taken;
  * <0 - on error (-EFAULT)
  */
 static int fixup_owner(u32 __user *uaddr, struct futex_q *q, int locked)
@@ -1824,8 +1825,8 @@ static void futex_wait_queue_me(struct futex_hash_bucket *hb, struct futex_q *q,
  * Return with the hb lock held and a q.key reference on success, and unlocked
  * with no q.key reference on failure.
  *
- * Returns:
- *  0 - uaddr contains val and hb has been locked
+ * Return:
+ *  0 - uaddr contains val and hb has been locked;
  * <1 - -EFAULT or -EWOULDBLOCK (uaddr does not contain val) and hb is unlocked
  */
 static int futex_wait_setup(u32 __user *uaddr, u32 val, unsigned int flags,
@@ -2203,9 +2204,9 @@ pi_faulted:
  * the wakeup and return the appropriate error code to the caller.  Must be
  * called with the hb lock held.
  *
- * Returns
- *  0 - no early wakeup detected
- * <0 - -ETIMEDOUT or -ERESTARTNOINTR
+ * Return:
+ *  0 = no early wakeup detected;
+ * <0 = -ETIMEDOUT or -ERESTARTNOINTR
  */
 static inline
 int handle_early_requeue_pi_wakeup(struct futex_hash_bucket *hb,
@@ -2247,7 +2248,6 @@ int handle_early_requeue_pi_wakeup(struct futex_hash_bucket *hb,
  * @val:       the expected value of uaddr
  * @abs_time:  absolute timeout
  * @bitset:    32 bit wakeup bitset set by userspace, defaults to all
- * @clockrt:   whether to use CLOCK_REALTIME (1) or CLOCK_MONOTONIC (0)
  * @uaddr2:    the pi futex we will take prior to returning to user-space
  *
  * The caller will wait on uaddr and will be requeued by futex_requeue() to
@@ -2258,7 +2258,7 @@ int handle_early_requeue_pi_wakeup(struct futex_hash_bucket *hb,
  * there was a need to.
  *
  * We call schedule in futex_wait_queue_me() when we enqueue and return there
- * via the following:
+ * via the following--
  * 1) wakeup on uaddr2 after an atomic lock acquisition by futex_requeue()
  * 2) wakeup on uaddr2 after a requeue
  * 3) signal
@@ -2276,8 +2276,8 @@ int handle_early_requeue_pi_wakeup(struct futex_hash_bucket *hb,
  *
  * If 4 or 7, we cleanup and return with -ETIMEDOUT.
  *
- * Returns:
- *  0 - On success
+ * Return:
+ *  0 - On success;
  * <0 - On error
  */
 static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
index 2ec870a..dd72567 100644 (file)
@@ -485,6 +485,9 @@ flush_signal_handlers(struct task_struct *t, int force_default)
                if (force_default || ka->sa.sa_handler != SIG_IGN)
                        ka->sa.sa_handler = SIG_DFL;
                ka->sa.sa_flags = 0;
+#ifdef __ARCH_HAS_SA_RESTORER
+               ka->sa.sa_restorer = NULL;
+#endif
                sigemptyset(&ka->sa.sa_mask);
                ka++;
        }
@@ -2682,7 +2685,7 @@ static int do_sigpending(void *set, unsigned long sigsetsize)
 /**
  *  sys_rt_sigpending - examine a pending signal that has been raised
  *                     while blocked
- *  @set: stores pending signals
+ *  @uset: stores pending signals
  *  @sigsetsize: size of sigset_t type or larger
  */
 SYSCALL_DEFINE2(rt_sigpending, sigset_t __user *, uset, size_t, sigsetsize)
index b9bde57..8eaed9a 100644 (file)
@@ -131,7 +131,7 @@ static int smpboot_thread_fn(void *data)
                        continue;
                }
 
-               //BUG_ON(td->cpu != smp_processor_id());
+               BUG_ON(td->cpu != smp_processor_id());
 
                /* Check for state change setup */
                switch (td->status) {
@@ -209,6 +209,8 @@ static void smpboot_unpark_thread(struct smp_hotplug_thread *ht, unsigned int cp
 {
        struct task_struct *tsk = *per_cpu_ptr(ht->store, cpu);
 
+       if (ht->pre_unpark)
+               ht->pre_unpark(cpu);
        kthread_unpark(tsk);
 }
 
index b4d252f..14d7758 100644 (file)
@@ -323,18 +323,10 @@ void irq_enter(void)
 
 static inline void invoke_softirq(void)
 {
-       if (!force_irqthreads) {
-#ifdef __ARCH_IRQ_EXIT_IRQS_DISABLED
+       if (!force_irqthreads)
                __do_softirq();
-#else
-               do_softirq();
-#endif
-       } else {
-               __local_bh_disable((unsigned long)__builtin_return_address(0),
-                               SOFTIRQ_OFFSET);
+       else
                wakeup_softirqd();
-               __local_bh_enable(SOFTIRQ_OFFSET);
-       }
 }
 
 /*
@@ -342,9 +334,15 @@ static inline void invoke_softirq(void)
  */
 void irq_exit(void)
 {
+#ifndef __ARCH_IRQ_EXIT_IRQS_DISABLED
+       local_irq_disable();
+#else
+       WARN_ON_ONCE(!irqs_disabled());
+#endif
+
        account_irq_exit_time(current);
        trace_hardirq_exit();
-       sub_preempt_count(IRQ_EXIT_OFFSET);
+       sub_preempt_count(HARDIRQ_OFFSET);
        if (!in_interrupt() && local_softirq_pending())
                invoke_softirq();
 
@@ -354,7 +352,6 @@ void irq_exit(void)
                tick_nohz_irq_exit();
 #endif
        rcu_irq_exit();
-       sched_preempt_enable_no_resched();
 }
 
 /*
index 95d178c..c09f295 100644 (file)
@@ -336,7 +336,7 @@ static struct smp_hotplug_thread cpu_stop_threads = {
        .create                 = cpu_stop_create,
        .setup                  = cpu_stop_unpark,
        .park                   = cpu_stop_park,
-       .unpark                 = cpu_stop_unpark,
+       .pre_unpark             = cpu_stop_unpark,
        .selfparking            = true,
 };
 
index 192473b..fc382d6 100644 (file)
@@ -414,24 +414,28 @@ config PROBE_EVENTS
        def_bool n
 
 config DYNAMIC_FTRACE
-       bool "enable/disable ftrace tracepoints dynamically"
+       bool "enable/disable function tracing dynamically"
        depends on FUNCTION_TRACER
        depends on HAVE_DYNAMIC_FTRACE
        default y
        help
-          This option will modify all the calls to ftrace dynamically
-         (will patch them out of the binary image and replace them
-         with a No-Op instruction) as they are called. A table is
-         created to dynamically enable them again.
+         This option will modify all the calls to function tracing
+         dynamically (will patch them out of the binary image and
+         replace them with a No-Op instruction) on boot up. During
+         compile time, a table is made of all the locations that ftrace
+         can function trace, and this table is linked into the kernel
+         image. When this is enabled, functions can be individually
+         enabled, and the functions not enabled will not affect
+         performance of the system.
+
+         See the files in /sys/kernel/debug/tracing:
+           available_filter_functions
+           set_ftrace_filter
+           set_ftrace_notrace
 
          This way a CONFIG_FUNCTION_TRACER kernel is slightly larger, but
          otherwise has native performance as long as no tracing is active.
 
-         The changes to the code are done by a kernel thread that
-         wakes up once a second and checks to see if any ftrace calls
-         were made. If so, it runs stop_machine (stops all CPUS)
-         and modifies the code to jump over the call to ftrace.
-
 config DYNAMIC_FTRACE_WITH_REGS
        def_bool y
        depends on DYNAMIC_FTRACE
index c2e2c23..1f835a8 100644 (file)
@@ -2400,6 +2400,27 @@ static void test_ftrace_alive(struct seq_file *m)
        seq_printf(m, "#          MAY BE MISSING FUNCTION EVENTS\n");
 }
 
+#ifdef CONFIG_TRACER_MAX_TRACE
+static void print_snapshot_help(struct seq_file *m, struct trace_iterator *iter)
+{
+       if (iter->trace->allocated_snapshot)
+               seq_printf(m, "#\n# * Snapshot is allocated *\n#\n");
+       else
+               seq_printf(m, "#\n# * Snapshot is freed *\n#\n");
+
+       seq_printf(m, "# Snapshot commands:\n");
+       seq_printf(m, "# echo 0 > snapshot : Clears and frees snapshot buffer\n");
+       seq_printf(m, "# echo 1 > snapshot : Allocates snapshot buffer, if not already allocated.\n");
+       seq_printf(m, "#                      Takes a snapshot of the main buffer.\n");
+       seq_printf(m, "# echo 2 > snapshot : Clears snapshot buffer (but does not allocate)\n");
+       seq_printf(m, "#                      (Doesn't have to be '2' works with any number that\n");
+       seq_printf(m, "#                       is not a '0' or '1')\n");
+}
+#else
+/* Should never be called */
+static inline void print_snapshot_help(struct seq_file *m, struct trace_iterator *iter) { }
+#endif
+
 static int s_show(struct seq_file *m, void *v)
 {
        struct trace_iterator *iter = v;
@@ -2411,7 +2432,9 @@ static int s_show(struct seq_file *m, void *v)
                        seq_puts(m, "#\n");
                        test_ftrace_alive(m);
                }
-               if (iter->trace && iter->trace->print_header)
+               if (iter->snapshot && trace_empty(iter))
+                       print_snapshot_help(m, iter);
+               else if (iter->trace && iter->trace->print_header)
                        iter->trace->print_header(m);
                else
                        trace_default_header(m);
@@ -4144,8 +4167,6 @@ tracing_snapshot_write(struct file *filp, const char __user *ubuf, size_t cnt,
        default:
                if (current_trace->allocated_snapshot)
                        tracing_reset_online_cpus(&max_tr);
-               else
-                       ret = -EINVAL;
                break;
        }
 
index 8b65083..b14f4d3 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/uaccess.h>
 #include <linux/ctype.h>
 #include <linux/projid.h>
+#include <linux/fs_struct.h>
 
 static struct kmem_cache *user_ns_cachep __read_mostly;
 
@@ -837,6 +838,9 @@ static int userns_install(struct nsproxy *nsproxy, void *ns)
        if (atomic_read(&current->mm->mm_users) > 1)
                return -EINVAL;
 
+       if (current->fs->users != 1)
+               return -EINVAL;
+
        if (!ns_capable(user_ns, CAP_SYS_ADMIN))
                return -EPERM;
 
index 81f2457..55fac5b 100644 (file)
@@ -457,11 +457,12 @@ static int worker_pool_assign_id(struct worker_pool *pool)
        int ret;
 
        mutex_lock(&worker_pool_idr_mutex);
-       idr_pre_get(&worker_pool_idr, GFP_KERNEL);
-       ret = idr_get_new(&worker_pool_idr, pool, &pool->id);
+       ret = idr_alloc(&worker_pool_idr, pool, 0, 0, GFP_KERNEL);
+       if (ret >= 0)
+               pool->id = ret;
        mutex_unlock(&worker_pool_idr_mutex);
 
-       return ret;
+       return ret < 0 ? ret : 0;
 }
 
 /*
index 73f4d53..322e281 100644 (file)
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -106,8 +106,14 @@ static struct idr_layer *idr_layer_alloc(gfp_t gfp_mask, struct idr *layer_idr)
        if (layer_idr)
                return get_from_free_list(layer_idr);
 
-       /* try to allocate directly from kmem_cache */
-       new = kmem_cache_zalloc(idr_layer_cache, gfp_mask);
+       /*
+        * Try to allocate directly from kmem_cache.  We want to try this
+        * before preload buffer; otherwise, non-preloading idr_alloc()
+        * users will end up taking advantage of preloading ones.  As the
+        * following is allowed to fail for preloaded cases, suppress
+        * warning this time.
+        */
+       new = kmem_cache_zalloc(idr_layer_cache, gfp_mask | __GFP_NOWARN);
        if (new)
                return new;
 
@@ -115,18 +121,24 @@ static struct idr_layer *idr_layer_alloc(gfp_t gfp_mask, struct idr *layer_idr)
         * Try to fetch one from the per-cpu preload buffer if in process
         * context.  See idr_preload() for details.
         */
-       if (in_interrupt())
-               return NULL;
-
-       preempt_disable();
-       new = __this_cpu_read(idr_preload_head);
-       if (new) {
-               __this_cpu_write(idr_preload_head, new->ary[0]);
-               __this_cpu_dec(idr_preload_cnt);
-               new->ary[0] = NULL;
+       if (!in_interrupt()) {
+               preempt_disable();
+               new = __this_cpu_read(idr_preload_head);
+               if (new) {
+                       __this_cpu_write(idr_preload_head, new->ary[0]);
+                       __this_cpu_dec(idr_preload_cnt);
+                       new->ary[0] = NULL;
+               }
+               preempt_enable();
+               if (new)
+                       return new;
        }
-       preempt_enable();
-       return new;
+
+       /*
+        * Both failed.  Try kmem_cache again w/o adding __GFP_NOWARN so
+        * that memory allocation failure warning is printed as intended.
+        */
+       return kmem_cache_zalloc(idr_layer_cache, gfp_mask);
 }
 
 static void idr_layer_rcu_free(struct rcu_head *head)
@@ -184,20 +196,7 @@ static void idr_mark_full(struct idr_layer **pa, int id)
        }
 }
 
-/**
- * idr_pre_get - reserve resources for idr allocation
- * @idp:       idr handle
- * @gfp_mask:  memory allocation flags
- *
- * This function should be called prior to calling the idr_get_new* functions.
- * It preallocates enough memory to satisfy the worst possible allocation. The
- * caller should pass in GFP_KERNEL if possible.  This of course requires that
- * no spinning locks be held.
- *
- * If the system is REALLY out of memory this function returns %0,
- * otherwise %1.
- */
-int idr_pre_get(struct idr *idp, gfp_t gfp_mask)
+int __idr_pre_get(struct idr *idp, gfp_t gfp_mask)
 {
        while (idp->id_free_cnt < MAX_IDR_FREE) {
                struct idr_layer *new;
@@ -208,13 +207,12 @@ int idr_pre_get(struct idr *idp, gfp_t gfp_mask)
        }
        return 1;
 }
-EXPORT_SYMBOL(idr_pre_get);
+EXPORT_SYMBOL(__idr_pre_get);
 
 /**
  * sub_alloc - try to allocate an id without growing the tree depth
  * @idp: idr handle
  * @starting_id: id to start search at
- * @id: pointer to the allocated handle
  * @pa: idr_layer[MAX_IDR_LEVEL] used as backtrack buffer
  * @gfp_mask: allocation mask for idr_layer_alloc()
  * @layer_idr: optional idr passed to idr_layer_alloc()
@@ -376,25 +374,7 @@ static void idr_fill_slot(struct idr *idr, void *ptr, int id,
        idr_mark_full(pa, id);
 }
 
-/**
- * idr_get_new_above - allocate new idr entry above or equal to a start id
- * @idp: idr handle
- * @ptr: pointer you want associated with the id
- * @starting_id: id to start search at
- * @id: pointer to the allocated handle
- *
- * This is the allocate id function.  It should be called with any
- * required locks.
- *
- * If allocation from IDR's private freelist fails, idr_get_new_above() will
- * return %-EAGAIN.  The caller should retry the idr_pre_get() call to refill
- * IDR's preallocation and then retry the idr_get_new_above() call.
- *
- * If the idr is full idr_get_new_above() will return %-ENOSPC.
- *
- * @id returns a value in the range @starting_id ... %0x7fffffff
- */
-int idr_get_new_above(struct idr *idp, void *ptr, int starting_id, int *id)
+int __idr_get_new_above(struct idr *idp, void *ptr, int starting_id, int *id)
 {
        struct idr_layer *pa[MAX_IDR_LEVEL + 1];
        int rv;
@@ -407,7 +387,7 @@ int idr_get_new_above(struct idr *idp, void *ptr, int starting_id, int *id)
        *id = rv;
        return 0;
 }
-EXPORT_SYMBOL(idr_get_new_above);
+EXPORT_SYMBOL(__idr_get_new_above);
 
 /**
  * idr_preload - preload for idr_alloc()
@@ -569,8 +549,7 @@ void idr_remove(struct idr *idp, int id)
        struct idr_layer *p;
        struct idr_layer *to_free;
 
-       /* see comment in idr_find_slowpath() */
-       if (WARN_ON_ONCE(id < 0))
+       if (id < 0)
                return;
 
        sub_remove(idp, (idp->layers - 1) * IDR_BITS, id);
@@ -667,15 +646,7 @@ void *idr_find_slowpath(struct idr *idp, int id)
        int n;
        struct idr_layer *p;
 
-       /*
-        * If @id is negative, idr_find() used to ignore the sign bit and
-        * performed lookup with the rest of bits, which is weird and can
-        * lead to very obscure bugs.  We're now returning NULL for all
-        * negative IDs but just in case somebody was depending on the sign
-        * bit being ignored, let's trigger WARN_ON_ONCE() so that they can
-        * be detected and fixed.  WARN_ON_ONCE() can later be removed.
-        */
-       if (WARN_ON_ONCE(id < 0))
+       if (id < 0)
                return NULL;
 
        p = rcu_dereference_raw(idp->top);
@@ -824,8 +795,7 @@ void *idr_replace(struct idr *idp, void *ptr, int id)
        int n;
        struct idr_layer *p, *old_p;
 
-       /* see comment in idr_find_slowpath() */
-       if (WARN_ON_ONCE(id < 0))
+       if (id < 0)
                return ERR_PTR(-EINVAL);
 
        p = idp->top;
@@ -918,7 +888,7 @@ static void free_bitmap(struct ida *ida, struct ida_bitmap *bitmap)
 int ida_pre_get(struct ida *ida, gfp_t gfp_mask)
 {
        /* allocate idr_layers */
-       if (!idr_pre_get(&ida->idr, gfp_mask))
+       if (!__idr_pre_get(&ida->idr, gfp_mask))
                return 0;
 
        /* allocate free_bitmap */
index 82a04d7..08837db 100644 (file)
@@ -15,7 +15,7 @@ config XZ_DEC_X86
 
 config XZ_DEC_POWERPC
        bool "PowerPC BCJ filter decoder"
-       default y if POWERPC
+       default y if PPC
        select XZ_DEC_BCJ
 
 config XZ_DEC_IA64
index ae55c1e..3bea74f 100644 (file)
@@ -286,8 +286,12 @@ config NR_QUICK
        default "1"
 
 config VIRT_TO_BUS
-       def_bool y
-       depends on HAVE_VIRT_TO_BUS
+       bool
+       help
+         An architecture should select this if it implements the
+         deprecated interface virt_to_bus().  All new architectures
+         should probably not select this.
+
 
 config MMU_NOTIFIER
        bool
index 0cd4c11..4723ac8 100644 (file)
@@ -129,7 +129,7 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size,
        struct vm_area_struct *vma;
        int err = -EINVAL;
        int has_write_lock = 0;
-       vm_flags_t vm_flags;
+       vm_flags_t vm_flags = 0;
 
        if (prot)
                return err;
@@ -254,7 +254,8 @@ get_write_lock:
         */
 
 out:
-       vm_flags = vma->vm_flags;
+       if (vma)
+               vm_flags = vma->vm_flags;
        if (likely(!has_write_lock))
                up_read(&mm->mmap_sem);
        else
index 85bfd4c..b6afe0c 100644 (file)
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -489,7 +489,7 @@ out:                page = NULL;
  */
 static inline int get_kpfn_nid(unsigned long kpfn)
 {
-       return ksm_merge_across_nodes ? 0 : pfn_to_nid(kpfn);
+       return ksm_merge_across_nodes ? 0 : NUMA(pfn_to_nid(kpfn));
 }
 
 static void remove_node_from_stable_tree(struct stable_node *stable_node)
index 53b8201..2b55222 100644 (file)
@@ -3012,6 +3012,8 @@ void memcg_update_array_size(int num)
                memcg_limited_groups_array_size = memcg_caches_array_size(num);
 }
 
+static void kmem_cache_destroy_work_func(struct work_struct *w);
+
 int memcg_update_cache_size(struct kmem_cache *s, int num_groups)
 {
        struct memcg_cache_params *cur_params = s->memcg_params;
@@ -3031,6 +3033,8 @@ int memcg_update_cache_size(struct kmem_cache *s, int num_groups)
                        return -ENOMEM;
                }
 
+               INIT_WORK(&s->memcg_params->destroy,
+                               kmem_cache_destroy_work_func);
                s->memcg_params->is_root_cache = true;
 
                /*
@@ -3078,6 +3082,8 @@ int memcg_register_cache(struct mem_cgroup *memcg, struct kmem_cache *s,
        if (!s->memcg_params)
                return -ENOMEM;
 
+       INIT_WORK(&s->memcg_params->destroy,
+                       kmem_cache_destroy_work_func);
        if (memcg) {
                s->memcg_params->memcg = memcg;
                s->memcg_params->root_cache = root_cache;
@@ -3358,8 +3364,6 @@ static void mem_cgroup_destroy_all_caches(struct mem_cgroup *memcg)
        list_for_each_entry(params, &memcg->memcg_slab_caches, list) {
                cachep = memcg_params_to_cache(params);
                cachep->memcg_params->dead = true;
-               INIT_WORK(&cachep->memcg_params->destroy,
-                                 kmem_cache_destroy_work_func);
                schedule_work(&cachep->memcg_params->destroy);
        }
        mutex_unlock(&memcg->slab_caches_mutex);
index b81a367..9597eec 100644 (file)
@@ -1801,7 +1801,7 @@ int __ref remove_memory(int nid, u64 start, u64 size)
        int retry = 1;
 
        start_pfn = PFN_DOWN(start);
-       end_pfn = start_pfn + PFN_DOWN(size);
+       end_pfn = PFN_UP(start + size - 1);
 
        /*
         * When CONFIG_MEMCG is on, one memory block may be used by other
index 31d2663..7431001 100644 (file)
@@ -2390,9 +2390,9 @@ restart:
 
                                *mpol_new = *n->policy;
                                atomic_set(&mpol_new->refcnt, 1);
-                               sp_node_init(n_new, n->end, end, mpol_new);
-                               sp_insert(sp, n_new);
+                               sp_node_init(n_new, end, n->end, mpol_new);
                                n->end = start;
+                               sp_insert(sp, n_new);
                                n_new = NULL;
                                mpol_new = NULL;
                                break;
index 926b466..fd26d04 100644 (file)
@@ -429,12 +429,6 @@ compat_process_vm_rw(compat_pid_t pid,
        if (flags != 0)
                return -EINVAL;
 
-       if (!access_ok(VERIFY_READ, lvec, liovcnt * sizeof(*lvec)))
-               goto out;
-
-       if (!access_ok(VERIFY_READ, rvec, riovcnt * sizeof(*rvec)))
-               goto out;
-
        if (vm_write)
                rc = compat_rw_copy_check_uvector(WRITE, lvec, liovcnt,
                                                  UIO_FASTIOV, iovstack_l,
@@ -459,8 +453,6 @@ free_iovecs:
                kfree(iov_r);
        if (iov_l != iovstack_l)
                kfree(iov_l);
-
-out:
        return rc;
 }
 
index 74dea37..de2e950 100644 (file)
@@ -655,7 +655,7 @@ static struct p9_trans_module p9_virtio_trans = {
        .create = p9_virtio_create,
        .close = p9_virtio_close,
        .request = p9_virtio_request,
-       //.zc_request = p9_virtio_zc_request,
+       .zc_request = p9_virtio_zc_request,
        .cancel = p9_virtio_cancel,
        /*
         * We leave one entry for input and one entry for response
index d5f1d3f..314c73e 100644 (file)
@@ -66,7 +66,7 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
                        goto out;
                }
 
-               mdst = br_mdb_get(br, skb);
+               mdst = br_mdb_get(br, skb, vid);
                if (mdst || BR_INPUT_SKB_CB_MROUTERS_ONLY(skb))
                        br_multicast_deliver(mdst, skb);
                else
index 4803301..828e2bc 100644 (file)
@@ -97,7 +97,7 @@ int br_handle_frame_finish(struct sk_buff *skb)
        if (is_broadcast_ether_addr(dest))
                skb2 = skb;
        else if (is_multicast_ether_addr(dest)) {
-               mdst = br_mdb_get(br, skb);
+               mdst = br_mdb_get(br, skb, vid);
                if (mdst || BR_INPUT_SKB_CB_MROUTERS_ONLY(skb)) {
                        if ((mdst && mdst->mglist) ||
                            br_multicast_is_router(br))
index 9f97b85..ee79f3f 100644 (file)
@@ -80,6 +80,7 @@ static int br_mdb_fill_info(struct sk_buff *skb, struct netlink_callback *cb,
                                port = p->port;
                                if (port) {
                                        struct br_mdb_entry e;
+                                       memset(&e, 0, sizeof(e));
                                        e.ifindex = port->dev->ifindex;
                                        e.state = p->state;
                                        if (p->addr.proto == htons(ETH_P_IP))
@@ -136,6 +137,7 @@ static int br_mdb_dump(struct sk_buff *skb, struct netlink_callback *cb)
                                break;
 
                        bpm = nlmsg_data(nlh);
+                       memset(bpm, 0, sizeof(*bpm));
                        bpm->ifindex = dev->ifindex;
                        if (br_mdb_fill_info(skb, cb, dev) < 0)
                                goto out;
@@ -171,6 +173,7 @@ static int nlmsg_populate_mdb_fill(struct sk_buff *skb,
                return -EMSGSIZE;
 
        bpm = nlmsg_data(nlh);
+       memset(bpm, 0, sizeof(*bpm));
        bpm->family  = AF_BRIDGE;
        bpm->ifindex = dev->ifindex;
        nest = nla_nest_start(skb, MDBA_MDB);
@@ -228,6 +231,7 @@ void br_mdb_notify(struct net_device *dev, struct net_bridge_port *port,
 {
        struct br_mdb_entry entry;
 
+       memset(&entry, 0, sizeof(entry));
        entry.ifindex = port->dev->ifindex;
        entry.addr.proto = group->proto;
        entry.addr.u.ip4 = group->u.ip4;
index 10e6fce..923fbea 100644 (file)
@@ -132,7 +132,7 @@ static struct net_bridge_mdb_entry *br_mdb_ip6_get(
 #endif
 
 struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br,
-                                       struct sk_buff *skb)
+                                       struct sk_buff *skb, u16 vid)
 {
        struct net_bridge_mdb_htable *mdb = rcu_dereference(br->mdb);
        struct br_ip ip;
@@ -144,6 +144,7 @@ struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br,
                return NULL;
 
        ip.proto = skb->protocol;
+       ip.vid = vid;
 
        switch (skb->protocol) {
        case htons(ETH_P_IP):
index 6d314c4..3cbf5be 100644 (file)
@@ -442,7 +442,7 @@ extern int br_multicast_rcv(struct net_bridge *br,
                            struct net_bridge_port *port,
                            struct sk_buff *skb);
 extern struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br,
-                                              struct sk_buff *skb);
+                                              struct sk_buff *skb, u16 vid);
 extern void br_multicast_add_port(struct net_bridge_port *port);
 extern void br_multicast_del_port(struct net_bridge_port *port);
 extern void br_multicast_enable_port(struct net_bridge_port *port);
@@ -504,7 +504,7 @@ static inline int br_multicast_rcv(struct net_bridge *br,
 }
 
 static inline struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br,
-                                                     struct sk_buff *skb)
+                                                     struct sk_buff *skb, u16 vid)
 {
        return NULL;
 }
index 1ae1d9c..21760f0 100644 (file)
@@ -118,7 +118,7 @@ static struct caif_device_entry *caif_get(struct net_device *dev)
        return NULL;
 }
 
-void caif_flow_cb(struct sk_buff *skb)
+static void caif_flow_cb(struct sk_buff *skb)
 {
        struct caif_device_entry *caifd;
        void (*dtor)(struct sk_buff *skb) = NULL;
index 3ebc8cb..ef8ebaa 100644 (file)
@@ -81,8 +81,8 @@ static void cfusbl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
                layr->up->ctrlcmd(layr->up, ctrl, layr->id);
 }
 
-struct cflayer *cfusbl_create(int phyid, u8 ethaddr[ETH_ALEN],
-                                       u8 braddr[ETH_ALEN])
+static struct cflayer *cfusbl_create(int phyid, u8 ethaddr[ETH_ALEN],
+                                     u8 braddr[ETH_ALEN])
 {
        struct cfusbl *this = kmalloc(sizeof(struct cfusbl), GFP_ATOMIC);
 
index 69bc4bf..4543b9a 100644 (file)
@@ -654,6 +654,24 @@ static int osdmap_set_max_osd(struct ceph_osdmap *map, int max)
        return 0;
 }
 
+static int __decode_pgid(void **p, void *end, struct ceph_pg *pg)
+{
+       u8 v;
+
+       ceph_decode_need(p, end, 1+8+4+4, bad);
+       v = ceph_decode_8(p);
+       if (v != 1)
+               goto bad;
+       pg->pool = ceph_decode_64(p);
+       pg->seed = ceph_decode_32(p);
+       *p += 4; /* skip preferred */
+       return 0;
+
+bad:
+       dout("error decoding pgid\n");
+       return -EINVAL;
+}
+
 /*
  * decode a full map.
  */
@@ -745,13 +763,12 @@ struct ceph_osdmap *osdmap_decode(void **p, void *end)
        for (i = 0; i < len; i++) {
                int n, j;
                struct ceph_pg pgid;
-               struct ceph_pg_v1 pgid_v1;
                struct ceph_pg_mapping *pg;
 
-               ceph_decode_need(p, end, sizeof(u32) + sizeof(u64), bad);
-               ceph_decode_copy(p, &pgid_v1, sizeof(pgid_v1));
-               pgid.pool = le32_to_cpu(pgid_v1.pool);
-               pgid.seed = le16_to_cpu(pgid_v1.ps);
+               err = __decode_pgid(p, end, &pgid);
+               if (err)
+                       goto bad;
+               ceph_decode_need(p, end, sizeof(u32), bad);
                n = ceph_decode_32(p);
                err = -EINVAL;
                if (n > (UINT_MAX - sizeof(*pg)) / sizeof(u32))
@@ -818,8 +835,8 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end,
        u16 version;
 
        ceph_decode_16_safe(p, end, version, bad);
-       if (version > 6) {
-               pr_warning("got unknown v %d > %d of inc osdmap\n", version, 6);
+       if (version != 6) {
+               pr_warning("got unknown v %d != 6 of inc osdmap\n", version);
                goto bad;
        }
 
@@ -963,15 +980,14 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end,
        while (len--) {
                struct ceph_pg_mapping *pg;
                int j;
-               struct ceph_pg_v1 pgid_v1;
                struct ceph_pg pgid;
                u32 pglen;
-               ceph_decode_need(p, end, sizeof(u64) + sizeof(u32), bad);
-               ceph_decode_copy(p, &pgid_v1, sizeof(pgid_v1));
-               pgid.pool = le32_to_cpu(pgid_v1.pool);
-               pgid.seed = le16_to_cpu(pgid_v1.ps);
-               pglen = ceph_decode_32(p);
 
+               err = __decode_pgid(p, end, &pgid);
+               if (err)
+                       goto bad;
+               ceph_decode_need(p, end, sizeof(u32), bad);
+               pglen = ceph_decode_32(p);
                if (pglen) {
                        ceph_decode_need(p, end, pglen*sizeof(u32), bad);
 
index a06a7a5..dffbef7 100644 (file)
@@ -3444,6 +3444,7 @@ ncls:
                }
                switch (rx_handler(&skb)) {
                case RX_HANDLER_CONSUMED:
+                       ret = NET_RX_SUCCESS;
                        goto unlock;
                case RX_HANDLER_ANOTHER:
                        goto another_round;
@@ -4103,7 +4104,7 @@ static void net_rx_action(struct softirq_action *h)
                 * Allow this to run for 2 jiffies since which will allow
                 * an average latency of 1.5/HZ.
                 */
-               if (unlikely(budget <= 0 || time_after(jiffies, time_limit)))
+               if (unlikely(budget <= 0 || time_after_eq(jiffies, time_limit)))
                        goto softnet_break;
 
                local_irq_enable();
@@ -4780,7 +4781,7 @@ EXPORT_SYMBOL(dev_set_mac_address);
 /**
  *     dev_change_carrier - Change device carrier
  *     @dev: device
- *     @new_carries: new value
+ *     @new_carrier: new value
  *
  *     Change device carrier
  */
index b376410..a585d45 100644 (file)
@@ -979,6 +979,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
                         * report anything.
                         */
                        ivi.spoofchk = -1;
+                       memset(ivi.mac, 0, sizeof(ivi.mac));
                        if (dev->netdev_ops->ndo_get_vf_config(dev, i, &ivi))
                                break;
                        vf_mac.vf =
index 1b588e2..21291f1 100644 (file)
@@ -284,6 +284,7 @@ static int dcbnl_getperm_hwaddr(struct net_device *netdev, struct nlmsghdr *nlh,
        if (!netdev->dcbnl_ops->getpermhwaddr)
                return -EOPNOTSUPP;
 
+       memset(perm_addr, 0, sizeof(perm_addr));
        netdev->dcbnl_ops->getpermhwaddr(netdev, perm_addr);
 
        return nla_put(skb, DCB_ATTR_PERM_HWADDR, sizeof(perm_addr), perm_addr);
@@ -1042,6 +1043,7 @@ static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev)
 
        if (ops->ieee_getets) {
                struct ieee_ets ets;
+               memset(&ets, 0, sizeof(ets));
                err = ops->ieee_getets(netdev, &ets);
                if (!err &&
                    nla_put(skb, DCB_ATTR_IEEE_ETS, sizeof(ets), &ets))
@@ -1050,6 +1052,7 @@ static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev)
 
        if (ops->ieee_getmaxrate) {
                struct ieee_maxrate maxrate;
+               memset(&maxrate, 0, sizeof(maxrate));
                err = ops->ieee_getmaxrate(netdev, &maxrate);
                if (!err) {
                        err = nla_put(skb, DCB_ATTR_IEEE_MAXRATE,
@@ -1061,6 +1064,7 @@ static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev)
 
        if (ops->ieee_getpfc) {
                struct ieee_pfc pfc;
+               memset(&pfc, 0, sizeof(pfc));
                err = ops->ieee_getpfc(netdev, &pfc);
                if (!err &&
                    nla_put(skb, DCB_ATTR_IEEE_PFC, sizeof(pfc), &pfc))
@@ -1094,6 +1098,7 @@ static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev)
        /* get peer info if available */
        if (ops->ieee_peer_getets) {
                struct ieee_ets ets;
+               memset(&ets, 0, sizeof(ets));
                err = ops->ieee_peer_getets(netdev, &ets);
                if (!err &&
                    nla_put(skb, DCB_ATTR_IEEE_PEER_ETS, sizeof(ets), &ets))
@@ -1102,6 +1107,7 @@ static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev)
 
        if (ops->ieee_peer_getpfc) {
                struct ieee_pfc pfc;
+               memset(&pfc, 0, sizeof(pfc));
                err = ops->ieee_peer_getpfc(netdev, &pfc);
                if (!err &&
                    nla_put(skb, DCB_ATTR_IEEE_PEER_PFC, sizeof(pfc), &pfc))
@@ -1280,6 +1286,7 @@ static int dcbnl_cee_fill(struct sk_buff *skb, struct net_device *netdev)
        /* peer info if available */
        if (ops->cee_peer_getpg) {
                struct cee_pg pg;
+               memset(&pg, 0, sizeof(pg));
                err = ops->cee_peer_getpg(netdev, &pg);
                if (!err &&
                    nla_put(skb, DCB_ATTR_CEE_PEER_PG, sizeof(pg), &pg))
@@ -1288,6 +1295,7 @@ static int dcbnl_cee_fill(struct sk_buff *skb, struct net_device *netdev)
 
        if (ops->cee_peer_getpfc) {
                struct cee_pfc pfc;
+               memset(&pfc, 0, sizeof(pfc));
                err = ops->cee_peer_getpfc(netdev, &pfc);
                if (!err &&
                    nla_put(skb, DCB_ATTR_CEE_PEER_PFC, sizeof(pfc), &pfc))
index 8c2251f..bba5f83 100644 (file)
@@ -84,7 +84,7 @@
        (memcmp(addr1, addr2, length >> 3) == 0)
 
 /* local link, i.e. FE80::/10 */
-#define is_addr_link_local(a) (((a)->s6_addr16[0]) == 0x80FE)
+#define is_addr_link_local(a) (((a)->s6_addr16[0]) == htons(0xFE80))
 
 /*
  * check whether we can compress the IID to 16 bits,
index 7d1874b..786d97a 100644 (file)
@@ -735,6 +735,7 @@ EXPORT_SYMBOL(inet_csk_destroy_sock);
  * tcp/dccp_create_openreq_child().
  */
 void inet_csk_prepare_forced_close(struct sock *sk)
+       __releases(&sk->sk_lock.slock)
 {
        /* sk_clone_lock locked the socket and set refcnt to 2 */
        bh_unlock_sock(sk);
index 87abd3e..2bdf802 100644 (file)
@@ -228,9 +228,11 @@ static int ip_local_deliver_finish(struct sk_buff *skb)
                                        icmp_send(skb, ICMP_DEST_UNREACH,
                                                  ICMP_PROT_UNREACH, 0);
                                }
-                       } else
+                               kfree_skb(skb);
+                       } else {
                                IP_INC_STATS_BH(net, IPSTATS_MIB_INDELIVERS);
-                       kfree_skb(skb);
+                               consume_skb(skb);
+                       }
                }
        }
  out:
index f6289bf..310a364 100644 (file)
@@ -423,7 +423,7 @@ int ip_options_compile(struct net *net,
                                        put_unaligned_be32(midtime, timeptr);
                                        opt->is_changed = 1;
                                }
-                       } else {
+                       } else if ((optptr[3]&0xF) != IPOPT_TS_PRESPEC) {
                                unsigned int overflow = optptr[3]>>4;
                                if (overflow == 15) {
                                        pp_ptr = optptr + 3;
index a759e19..0d9bdac 100644 (file)
@@ -5485,6 +5485,9 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb,
                                if (tcp_checksum_complete_user(sk, skb))
                                        goto csum_error;
 
+                               if ((int)skb->truesize > sk->sk_forward_alloc)
+                                       goto step5;
+
                                /* Predicted packet is in window by definition.
                                 * seq == rcv_nxt and rcv_wup <= rcv_nxt.
                                 * Hence, check seq<=rcv_wup reduces to:
@@ -5496,9 +5499,6 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb,
 
                                tcp_rcv_rtt_measure_ts(sk, skb);
 
-                               if ((int)skb->truesize > sk->sk_forward_alloc)
-                                       goto step5;
-
                                NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPHPHITS);
 
                                /* Bulk data transfer: receiver */
index 5b10414..e33fe0a 100644 (file)
@@ -241,9 +241,11 @@ resubmit:
                                icmpv6_send(skb, ICMPV6_PARAMPROB,
                                            ICMPV6_UNK_NEXTHDR, nhoff);
                        }
-               } else
+                       kfree_skb(skb);
+               } else {
                        IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INDELIVERS);
-               kfree_skb(skb);
+                       consume_skb(skb);
+               }
        }
        rcu_read_unlock();
        return 0;
@@ -279,7 +281,8 @@ int ip6_mc_input(struct sk_buff *skb)
         *      IPv6 multicast router mode is now supported ;)
         */
        if (dev_net(skb->dev)->ipv6.devconf_all->mc_forwarding &&
-           !(ipv6_addr_type(&hdr->daddr) & IPV6_ADDR_LINKLOCAL) &&
+           !(ipv6_addr_type(&hdr->daddr) &
+             (IPV6_ADDR_LOOPBACK|IPV6_ADDR_LINKLOCAL)) &&
            likely(!(IP6CB(skb)->flags & IP6SKB_FORWARDED))) {
                /*
                 * Okay, we try to forward - split and duplicate
index 9282665..e5fe004 100644 (file)
@@ -1915,7 +1915,8 @@ void rt6_purge_dflt_routers(struct net *net)
 restart:
        read_lock_bh(&table->tb6_lock);
        for (rt = table->tb6_root.leaf; rt; rt = rt->dst.rt6_next) {
-               if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) {
+               if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF) &&
+                   (!rt->rt6i_idev || rt->rt6i_idev->cnf.accept_ra != 2)) {
                        dst_hold(&rt->dst);
                        read_unlock_bh(&table->tb6_lock);
                        ip6_del_rt(rt);
index 9a5fd3c..362ba47 100644 (file)
@@ -280,7 +280,7 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,
        struct tty_port *port = &self->port;
        DECLARE_WAITQUEUE(wait, current);
        int             retval;
-       int             do_clocal = 0, extra_count = 0;
+       int             do_clocal = 0;
        unsigned long   flags;
 
        IRDA_DEBUG(2, "%s()\n", __func__ );
@@ -289,8 +289,15 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,
         * If non-blocking mode is set, or the port is not enabled,
         * then make the check up front and then exit.
         */
-       if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){
-               /* nonblock mode is set or port is not enabled */
+       if (test_bit(TTY_IO_ERROR, &tty->flags)) {
+               port->flags |= ASYNC_NORMAL_ACTIVE;
+               return 0;
+       }
+
+       if (filp->f_flags & O_NONBLOCK) {
+               /* nonblock mode is set */
+               if (tty->termios.c_cflag & CBAUD)
+                       tty_port_raise_dtr_rts(port);
                port->flags |= ASYNC_NORMAL_ACTIVE;
                IRDA_DEBUG(1, "%s(), O_NONBLOCK requested!\n", __func__ );
                return 0;
@@ -315,18 +322,16 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,
              __FILE__, __LINE__, tty->driver->name, port->count);
 
        spin_lock_irqsave(&port->lock, flags);
-       if (!tty_hung_up_p(filp)) {
-               extra_count = 1;
+       if (!tty_hung_up_p(filp))
                port->count--;
-       }
-       spin_unlock_irqrestore(&port->lock, flags);
        port->blocked_open++;
+       spin_unlock_irqrestore(&port->lock, flags);
 
        while (1) {
                if (tty->termios.c_cflag & CBAUD)
                        tty_port_raise_dtr_rts(port);
 
-               current->state = TASK_INTERRUPTIBLE;
+               set_current_state(TASK_INTERRUPTIBLE);
 
                if (tty_hung_up_p(filp) ||
                    !test_bit(ASYNCB_INITIALIZED, &port->flags)) {
@@ -361,13 +366,11 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,
        __set_current_state(TASK_RUNNING);
        remove_wait_queue(&port->open_wait, &wait);
 
-       if (extra_count) {
-               /* ++ is not atomic, so this should be protected - Jean II */
-               spin_lock_irqsave(&port->lock, flags);
+       spin_lock_irqsave(&port->lock, flags);
+       if (!tty_hung_up_p(filp))
                port->count++;
-               spin_unlock_irqrestore(&port->lock, flags);
-       }
        port->blocked_open--;
+       spin_unlock_irqrestore(&port->lock, flags);
 
        IRDA_DEBUG(1, "%s(%d):block_til_ready after blocking on %s open_count=%d\n",
              __FILE__, __LINE__, tty->driver->name, port->count);
index e71e85b..29340a9 100644 (file)
@@ -495,8 +495,11 @@ static void iriap_getvaluebyclass_confirm(struct iriap_cb *self,
 /*             case CS_ISO_8859_9: */
 /*             case CS_UNICODE: */
                default:
-                       IRDA_DEBUG(0, "%s(), charset %s, not supported\n",
-                                  __func__, ias_charset_types[charset]);
+                       IRDA_DEBUG(0, "%s(), charset [%d] %s, not supported\n",
+                                  __func__, charset,
+                                  charset < ARRAY_SIZE(ias_charset_types) ?
+                                       ias_charset_types[charset] :
+                                       "(unknown)");
 
                        /* Aborting, close connection! */
                        iriap_disconnect_request(self);
index 556fdaf..8555f33 100644 (file)
@@ -2201,7 +2201,7 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, const struct sadb_
                      XFRM_POLICY_BLOCK : XFRM_POLICY_ALLOW);
        xp->priority = pol->sadb_x_policy_priority;
 
-       sa = ext_hdrs[SADB_EXT_ADDRESS_SRC-1],
+       sa = ext_hdrs[SADB_EXT_ADDRESS_SRC-1];
        xp->family = pfkey_sadb_addr2xfrm_addr(sa, &xp->selector.saddr);
        if (!xp->family) {
                err = -EINVAL;
@@ -2214,7 +2214,7 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, const struct sadb_
        if (xp->selector.sport)
                xp->selector.sport_mask = htons(0xffff);
 
-       sa = ext_hdrs[SADB_EXT_ADDRESS_DST-1],
+       sa = ext_hdrs[SADB_EXT_ADDRESS_DST-1];
        pfkey_sadb_addr2xfrm_addr(sa, &xp->selector.daddr);
        xp->selector.prefixlen_d = sa->sadb_address_prefixlen;
 
@@ -2315,7 +2315,7 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, const struct sa
 
        memset(&sel, 0, sizeof(sel));
 
-       sa = ext_hdrs[SADB_EXT_ADDRESS_SRC-1],
+       sa = ext_hdrs[SADB_EXT_ADDRESS_SRC-1];
        sel.family = pfkey_sadb_addr2xfrm_addr(sa, &sel.saddr);
        sel.prefixlen_s = sa->sadb_address_prefixlen;
        sel.proto = pfkey_proto_to_xfrm(sa->sadb_address_proto);
@@ -2323,7 +2323,7 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, const struct sa
        if (sel.sport)
                sel.sport_mask = htons(0xffff);
 
-       sa = ext_hdrs[SADB_EXT_ADDRESS_DST-1],
+       sa = ext_hdrs[SADB_EXT_ADDRESS_DST-1];
        pfkey_sadb_addr2xfrm_addr(sa, &sel.daddr);
        sel.prefixlen_d = sa->sadb_address_prefixlen;
        sel.proto = pfkey_proto_to_xfrm(sa->sadb_address_proto);
index 3f4e3af..6a53371 100644 (file)
@@ -355,6 +355,7 @@ static int pppol2tp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msgh
        l2tp_xmit_skb(session, skb, session->hdr_len);
 
        sock_put(ps->tunnel_sock);
+       sock_put(sk);
 
        return error;
 
index 09d96a8..fb30681 100644 (file)
@@ -3285,6 +3285,7 @@ static int ieee80211_cfg_get_channel(struct wiphy *wiphy,
                                     struct cfg80211_chan_def *chandef)
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
+       struct ieee80211_local *local = wiphy_priv(wiphy);
        struct ieee80211_chanctx_conf *chanctx_conf;
        int ret = -ENODATA;
 
@@ -3293,6 +3294,16 @@ static int ieee80211_cfg_get_channel(struct wiphy *wiphy,
        if (chanctx_conf) {
                *chandef = chanctx_conf->def;
                ret = 0;
+       } else if (local->open_count > 0 &&
+                  local->open_count == local->monitors &&
+                  sdata->vif.type == NL80211_IFTYPE_MONITOR) {
+               if (local->use_chanctx)
+                       *chandef = local->monitor_chandef;
+               else
+                       cfg80211_chandef_create(chandef,
+                                               local->_oper_channel,
+                                               local->_oper_channel_type);
+               ret = 0;
        }
        rcu_read_unlock();
 
index 2c059e5..baaa860 100644 (file)
@@ -107,7 +107,7 @@ void ieee80211_recalc_idle(struct ieee80211_local *local)
 
        lockdep_assert_held(&local->mtx);
 
-       active = !list_empty(&local->chanctx_list);
+       active = !list_empty(&local->chanctx_list) || local->monitors;
 
        if (!local->ops->remain_on_channel) {
                list_for_each_entry(roc, &local->roc_list, list) {
@@ -541,6 +541,9 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
 
                ieee80211_adjust_monitor_flags(sdata, 1);
                ieee80211_configure_filter(local);
+               mutex_lock(&local->mtx);
+               ieee80211_recalc_idle(local);
+               mutex_unlock(&local->mtx);
 
                netif_carrier_on(dev);
                break;
@@ -812,6 +815,9 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
 
                ieee80211_adjust_monitor_flags(sdata, -1);
                ieee80211_configure_filter(local);
+               mutex_lock(&local->mtx);
+               ieee80211_recalc_idle(local);
+               mutex_unlock(&local->mtx);
                break;
        case NL80211_IFTYPE_P2P_DEVICE:
                /* relies on synchronize_rcu() below */
index 9f6464f..1415774 100644 (file)
@@ -647,6 +647,9 @@ static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata,
                our_mcs = (le16_to_cpu(vht_cap.vht_mcs.rx_mcs_map) &
                                                                mask) >> shift;
 
+               if (our_mcs == IEEE80211_VHT_MCS_NOT_SUPPORTED)
+                       continue;
+
                switch (ap_mcs) {
                default:
                        if (our_mcs <= ap_mcs)
@@ -3503,6 +3506,14 @@ void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata)
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 
        /*
+        * Stop timers before deleting work items, as timers
+        * could race and re-add the work-items. They will be
+        * re-established on connection.
+        */
+       del_timer_sync(&ifmgd->conn_mon_timer);
+       del_timer_sync(&ifmgd->bcn_mon_timer);
+
+       /*
         * we need to use atomic bitops for the running bits
         * only because both timers might fire at the same
         * time -- the code here is properly synchronised.
@@ -3516,13 +3527,9 @@ void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata)
        if (del_timer_sync(&ifmgd->timer))
                set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running);
 
-       cancel_work_sync(&ifmgd->chswitch_work);
        if (del_timer_sync(&ifmgd->chswitch_timer))
                set_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running);
-
-       /* these will just be re-established on connection */
-       del_timer_sync(&ifmgd->conn_mon_timer);
-       del_timer_sync(&ifmgd->bcn_mon_timer);
+       cancel_work_sync(&ifmgd->chswitch_work);
 }
 
 void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata)
@@ -4315,6 +4322,17 @@ void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata)
 {
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 
+       /*
+        * Make sure some work items will not run after this,
+        * they will not do anything but might not have been
+        * cancelled when disconnecting.
+        */
+       cancel_work_sync(&ifmgd->monitor_work);
+       cancel_work_sync(&ifmgd->beacon_connection_loss_work);
+       cancel_work_sync(&ifmgd->request_smps_work);
+       cancel_work_sync(&ifmgd->csa_connection_drop_work);
+       cancel_work_sync(&ifmgd->chswitch_work);
+
        mutex_lock(&ifmgd->mtx);
        if (ifmgd->assoc_data)
                ieee80211_destroy_assoc_data(sdata, false);
index de8548b..8914d2d 100644 (file)
@@ -1231,34 +1231,40 @@ static bool ieee80211_tx_frags(struct ieee80211_local *local,
                if (local->queue_stop_reasons[q] ||
                    (!txpending && !skb_queue_empty(&local->pending[q]))) {
                        if (unlikely(info->flags &
-                                       IEEE80211_TX_INTFL_OFFCHAN_TX_OK &&
-                                    local->queue_stop_reasons[q] &
-                                       ~BIT(IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL))) {
+                                    IEEE80211_TX_INTFL_OFFCHAN_TX_OK)) {
+                               if (local->queue_stop_reasons[q] &
+                                   ~BIT(IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL)) {
+                                       /*
+                                        * Drop off-channel frames if queues
+                                        * are stopped for any reason other
+                                        * than off-channel operation. Never
+                                        * queue them.
+                                        */
+                                       spin_unlock_irqrestore(
+                                               &local->queue_stop_reason_lock,
+                                               flags);
+                                       ieee80211_purge_tx_queue(&local->hw,
+                                                                skbs);
+                                       return true;
+                               }
+                       } else {
+
                                /*
-                                * Drop off-channel frames if queues are stopped
-                                * for any reason other than off-channel
-                                * operation. Never queue them.
+                                * Since queue is stopped, queue up frames for
+                                * later transmission from the tx-pending
+                                * tasklet when the queue is woken again.
                                 */
-                               spin_unlock_irqrestore(
-                                       &local->queue_stop_reason_lock, flags);
-                               ieee80211_purge_tx_queue(&local->hw, skbs);
-                               return true;
+                               if (txpending)
+                                       skb_queue_splice_init(skbs,
+                                                             &local->pending[q]);
+                               else
+                                       skb_queue_splice_tail_init(skbs,
+                                                                  &local->pending[q]);
+
+                               spin_unlock_irqrestore(&local->queue_stop_reason_lock,
+                                                      flags);
+                               return false;
                        }
-
-                       /*
-                        * Since queue is stopped, queue up frames for later
-                        * transmission from the tx-pending tasklet when the
-                        * queue is woken again.
-                        */
-                       if (txpending)
-                               skb_queue_splice_init(skbs, &local->pending[q]);
-                       else
-                               skb_queue_splice_tail_init(skbs,
-                                                          &local->pending[q]);
-
-                       spin_unlock_irqrestore(&local->queue_stop_reason_lock,
-                                              flags);
-                       return false;
                }
                spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
 
@@ -1844,9 +1850,24 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
                }
 
                if (!is_multicast_ether_addr(skb->data)) {
+                       struct sta_info *next_hop;
+                       bool mpp_lookup = true;
+
                        mpath = mesh_path_lookup(sdata, skb->data);
-                       if (!mpath)
+                       if (mpath) {
+                               mpp_lookup = false;
+                               next_hop = rcu_dereference(mpath->next_hop);
+                               if (!next_hop ||
+                                   !(mpath->flags & (MESH_PATH_ACTIVE |
+                                                     MESH_PATH_RESOLVING)))
+                                       mpp_lookup = true;
+                       }
+
+                       if (mpp_lookup)
                                mppath = mpp_path_lookup(sdata, skb->data);
+
+                       if (mppath && mpath)
+                               mesh_path_del(mpath->sdata, mpath->dst);
                }
 
                /*
@@ -2350,9 +2371,9 @@ static int ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,
        if (local->tim_in_locked_section) {
                __ieee80211_beacon_add_tim(sdata, ps, skb);
        } else {
-               spin_lock(&local->tim_lock);
+               spin_lock_bh(&local->tim_lock);
                __ieee80211_beacon_add_tim(sdata, ps, skb);
-               spin_unlock(&local->tim_lock);
+               spin_unlock_bh(&local->tim_lock);
        }
 
        return 0;
@@ -2724,7 +2745,8 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw,
                                cpu_to_le16(IEEE80211_FCTL_MOREDATA);
                }
 
-               sdata = IEEE80211_DEV_TO_SUB_IF(skb->dev);
+               if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+                       sdata = IEEE80211_DEV_TO_SUB_IF(skb->dev);
                if (!ieee80211_tx_prepare(sdata, &tx, skb))
                        break;
                dev_kfree_skb_any(skb);
index f82b2e6..1ba9dbc 100644 (file)
@@ -1470,7 +1470,8 @@ ip_set_utest(struct sock *ctnl, struct sk_buff *skb,
        if (ret == -EAGAIN)
                ret = 1;
 
-       return ret < 0 ? ret : ret > 0 ? 0 : -IPSET_ERR_EXIST;
+       return (ret < 0 && ret != -ENOTEMPTY) ? ret :
+               ret > 0 ? 0 : -IPSET_ERR_EXIST;
 }
 
 /* Get headed data of a set */
index a9740bd..94b4b98 100644 (file)
@@ -339,6 +339,13 @@ void nf_ct_helper_log(struct sk_buff *skb, const struct nf_conn *ct,
 {
        const struct nf_conn_help *help;
        const struct nf_conntrack_helper *helper;
+       struct va_format vaf;
+       va_list args;
+
+       va_start(args, fmt);
+
+       vaf.fmt = fmt;
+       vaf.va = &args;
 
        /* Called from the helper function, this call never fails */
        help = nfct_help(ct);
@@ -347,7 +354,9 @@ void nf_ct_helper_log(struct sk_buff *skb, const struct nf_conn *ct,
        helper = rcu_dereference(help->helper);
 
        nf_log_packet(nf_ct_l3num(ct), 0, skb, NULL, NULL, NULL,
-                     "nf_ct_%s: dropping packet: %s ", helper->name, fmt);
+                     "nf_ct_%s: dropping packet: %pV ", helper->name, &vaf);
+
+       va_end(args);
 }
 EXPORT_SYMBOL_GPL(nf_ct_helper_log);
 
index d578ec2..0b1b32c 100644 (file)
@@ -62,11 +62,6 @@ void nfnl_unlock(__u8 subsys_id)
 }
 EXPORT_SYMBOL_GPL(nfnl_unlock);
 
-static struct mutex *nfnl_get_lock(__u8 subsys_id)
-{
-       return &table[subsys_id].mutex;
-}
-
 int nfnetlink_subsys_register(const struct nfnetlink_subsystem *n)
 {
        nfnl_lock(n->subsys_id);
@@ -199,7 +194,7 @@ replay:
                        rcu_read_unlock();
                        nfnl_lock(subsys_id);
                        if (rcu_dereference_protected(table[subsys_id].subsys,
-                               lockdep_is_held(nfnl_get_lock(subsys_id))) != ss ||
+                               lockdep_is_held(&table[subsys_id].mutex)) != ss ||
                            nfnetlink_find_client(type, ss) != nc)
                                err = -EAGAIN;
                        else if (nc->call)
index ba92824..3228d7f 100644 (file)
@@ -124,6 +124,9 @@ audit_tg(struct sk_buff *skb, const struct xt_action_param *par)
        const struct xt_audit_info *info = par->targinfo;
        struct audit_buffer *ab;
 
+       if (audit_enabled == 0)
+               goto errout;
+
        ab = audit_log_start(NULL, GFP_ATOMIC, AUDIT_NETFILTER_PKT);
        if (ab == NULL)
                goto errout;
index 847d495..8a6c6ea 100644 (file)
@@ -1189,8 +1189,6 @@ static int netlbl_unlabel_staticlist(struct sk_buff *skb,
        struct netlbl_unlhsh_walk_arg cb_arg;
        u32 skip_bkt = cb->args[0];
        u32 skip_chain = cb->args[1];
-       u32 skip_addr4 = cb->args[2];
-       u32 skip_addr6 = cb->args[3];
        u32 iter_bkt;
        u32 iter_chain = 0, iter_addr4 = 0, iter_addr6 = 0;
        struct netlbl_unlhsh_iface *iface;
@@ -1215,7 +1213,7 @@ static int netlbl_unlabel_staticlist(struct sk_buff *skb,
                                continue;
                        netlbl_af4list_foreach_rcu(addr4,
                                                   &iface->addr4_list) {
-                               if (iter_addr4++ < skip_addr4)
+                               if (iter_addr4++ < cb->args[2])
                                        continue;
                                if (netlbl_unlabel_staticlist_gen(
                                              NLBL_UNLABEL_C_STATICLIST,
@@ -1231,7 +1229,7 @@ static int netlbl_unlabel_staticlist(struct sk_buff *skb,
 #if IS_ENABLED(CONFIG_IPV6)
                        netlbl_af6list_foreach_rcu(addr6,
                                                   &iface->addr6_list) {
-                               if (iter_addr6++ < skip_addr6)
+                               if (iter_addr6++ < cb->args[3])
                                        continue;
                                if (netlbl_unlabel_staticlist_gen(
                                              NLBL_UNLABEL_C_STATICLIST,
@@ -1250,10 +1248,10 @@ static int netlbl_unlabel_staticlist(struct sk_buff *skb,
 
 unlabel_staticlist_return:
        rcu_read_unlock();
-       cb->args[0] = skip_bkt;
-       cb->args[1] = skip_chain;
-       cb->args[2] = skip_addr4;
-       cb->args[3] = skip_addr6;
+       cb->args[0] = iter_bkt;
+       cb->args[1] = iter_chain;
+       cb->args[2] = iter_addr4;
+       cb->args[3] = iter_addr6;
        return skb->len;
 }
 
@@ -1273,12 +1271,9 @@ static int netlbl_unlabel_staticlistdef(struct sk_buff *skb,
 {
        struct netlbl_unlhsh_walk_arg cb_arg;
        struct netlbl_unlhsh_iface *iface;
-       u32 skip_addr4 = cb->args[0];
-       u32 skip_addr6 = cb->args[1];
-       u32 iter_addr4 = 0;
+       u32 iter_addr4 = 0, iter_addr6 = 0;
        struct netlbl_af4list *addr4;
 #if IS_ENABLED(CONFIG_IPV6)
-       u32 iter_addr6 = 0;
        struct netlbl_af6list *addr6;
 #endif
 
@@ -1292,7 +1287,7 @@ static int netlbl_unlabel_staticlistdef(struct sk_buff *skb,
                goto unlabel_staticlistdef_return;
 
        netlbl_af4list_foreach_rcu(addr4, &iface->addr4_list) {
-               if (iter_addr4++ < skip_addr4)
+               if (iter_addr4++ < cb->args[0])
                        continue;
                if (netlbl_unlabel_staticlist_gen(NLBL_UNLABEL_C_STATICLISTDEF,
                                              iface,
@@ -1305,7 +1300,7 @@ static int netlbl_unlabel_staticlistdef(struct sk_buff *skb,
        }
 #if IS_ENABLED(CONFIG_IPV6)
        netlbl_af6list_foreach_rcu(addr6, &iface->addr6_list) {
-               if (iter_addr6++ < skip_addr6)
+               if (iter_addr6++ < cb->args[1])
                        continue;
                if (netlbl_unlabel_staticlist_gen(NLBL_UNLABEL_C_STATICLISTDEF,
                                              iface,
@@ -1320,8 +1315,8 @@ static int netlbl_unlabel_staticlistdef(struct sk_buff *skb,
 
 unlabel_staticlistdef_return:
        rcu_read_unlock();
-       cb->args[0] = skip_addr4;
-       cb->args[1] = skip_addr6;
+       cb->args[0] = iter_addr4;
+       cb->args[1] = iter_addr6;
        return skb->len;
 }
 
index f0a4658..aba232f 100644 (file)
@@ -82,10 +82,7 @@ static void rds_message_purge(struct rds_message *rm)
 void rds_message_put(struct rds_message *rm)
 {
        rdsdebug("put rm %p ref %d\n", rm, atomic_read(&rm->m_refcount));
-       if (atomic_read(&rm->m_refcount) == 0) {
-printk(KERN_CRIT "danger refcount zero on %p\n", rm);
-WARN_ON(1);
-       }
+       WARN(!atomic_read(&rm->m_refcount), "danger refcount zero on %p\n", rm);
        if (atomic_dec_and_test(&rm->m_refcount)) {
                BUG_ON(!list_empty(&rm->m_sock_item));
                BUG_ON(!list_empty(&rm->m_conn_item));
@@ -197,6 +194,9 @@ struct rds_message *rds_message_alloc(unsigned int extra_len, gfp_t gfp)
 {
        struct rds_message *rm;
 
+       if (extra_len > KMALLOC_MAX_SIZE - sizeof(struct rds_message))
+               return NULL;
+
        rm = kzalloc(sizeof(struct rds_message) + extra_len, gfp);
        if (!rm)
                goto out;
index 7be790d..73be187 100644 (file)
@@ -87,6 +87,7 @@ void rds_stats_info_copy(struct rds_info_iterator *iter,
        for (i = 0; i < nr; i++) {
                BUG_ON(strlen(names[i]) >= sizeof(ctr.name));
                strncpy(ctr.name, names[i], sizeof(ctr.name) - 1);
+               ctr.name[sizeof(ctr.name) - 1] = '\0';
                ctr.value = values[i];
 
                rds_info_copy(iter, &ctr, sizeof(ctr));
index e9a77f6..d51852b 100644 (file)
@@ -298,6 +298,10 @@ static void qfq_update_agg(struct qfq_sched *q, struct qfq_aggregate *agg,
            new_num_classes == q->max_agg_classes - 1) /* agg no more full */
                hlist_add_head(&agg->nonfull_next, &q->nonfull_aggs);
 
+       /* The next assignment may let
+        * agg->initial_budget > agg->budgetmax
+        * hold, we will take it into account in charge_actual_service().
+        */
        agg->budgetmax = new_num_classes * agg->lmax;
        new_agg_weight = agg->class_weight * new_num_classes;
        agg->inv_w = ONE_FP/new_agg_weight;
@@ -817,7 +821,7 @@ static void qfq_make_eligible(struct qfq_sched *q)
        unsigned long old_vslot = q->oldV >> q->min_slot_shift;
 
        if (vslot != old_vslot) {
-               unsigned long mask = (1UL << fls(vslot ^ old_vslot)) - 1;
+               unsigned long mask = (1ULL << fls(vslot ^ old_vslot)) - 1;
                qfq_move_groups(q, mask, IR, ER);
                qfq_move_groups(q, mask, IB, EB);
        }
@@ -988,12 +992,23 @@ static inline struct sk_buff *qfq_peek_skb(struct qfq_aggregate *agg,
 /* Update F according to the actual service received by the aggregate. */
 static inline void charge_actual_service(struct qfq_aggregate *agg)
 {
-       /* compute the service received by the aggregate */
-       u32 service_received = agg->initial_budget - agg->budget;
+       /* Compute the service received by the aggregate, taking into
+        * account that, after decreasing the number of classes in
+        * agg, it may happen that
+        * agg->initial_budget - agg->budget > agg->bugdetmax
+        */
+       u32 service_received = min(agg->budgetmax,
+                                  agg->initial_budget - agg->budget);
 
        agg->F = agg->S + (u64)service_received * agg->inv_w;
 }
 
+static inline void qfq_update_agg_ts(struct qfq_sched *q,
+                                    struct qfq_aggregate *agg,
+                                    enum update_reason reason);
+
+static void qfq_schedule_agg(struct qfq_sched *q, struct qfq_aggregate *agg);
+
 static struct sk_buff *qfq_dequeue(struct Qdisc *sch)
 {
        struct qfq_sched *q = qdisc_priv(sch);
@@ -1021,7 +1036,7 @@ static struct sk_buff *qfq_dequeue(struct Qdisc *sch)
                in_serv_agg->initial_budget = in_serv_agg->budget =
                        in_serv_agg->budgetmax;
 
-               if (!list_empty(&in_serv_agg->active))
+               if (!list_empty(&in_serv_agg->active)) {
                        /*
                         * Still active: reschedule for
                         * service. Possible optimization: if no other
@@ -1032,8 +1047,9 @@ static struct sk_buff *qfq_dequeue(struct Qdisc *sch)
                         * handle it, we would need to maintain an
                         * extra num_active_aggs field.
                        */
-                       qfq_activate_agg(q, in_serv_agg, requeue);
-               else if (sch->q.qlen == 0) { /* no aggregate to serve */
+                       qfq_update_agg_ts(q, in_serv_agg, requeue);
+                       qfq_schedule_agg(q, in_serv_agg);
+               } else if (sch->q.qlen == 0) { /* no aggregate to serve */
                        q->in_serv_agg = NULL;
                        return NULL;
                }
@@ -1052,7 +1068,15 @@ static struct sk_buff *qfq_dequeue(struct Qdisc *sch)
        qdisc_bstats_update(sch, skb);
 
        agg_dequeue(in_serv_agg, cl, len);
-       in_serv_agg->budget -= len;
+       /* If lmax is lowered, through qfq_change_class, for a class
+        * owning pending packets with larger size than the new value
+        * of lmax, then the following condition may hold.
+        */
+       if (unlikely(in_serv_agg->budget < len))
+               in_serv_agg->budget = 0;
+       else
+               in_serv_agg->budget -= len;
+
        q->V += (u64)len * IWSUM;
        pr_debug("qfq dequeue: len %u F %lld now %lld\n",
                 len, (unsigned long long) in_serv_agg->F,
@@ -1217,17 +1241,11 @@ static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch)
        cl->deficit = agg->lmax;
        list_add_tail(&cl->alist, &agg->active);
 
-       if (list_first_entry(&agg->active, struct qfq_class, alist) != cl)
-               return err; /* aggregate was not empty, nothing else to do */
+       if (list_first_entry(&agg->active, struct qfq_class, alist) != cl ||
+           q->in_serv_agg == agg)
+               return err; /* non-empty or in service, nothing else to do */
 
-       /* recharge budget */
-       agg->initial_budget = agg->budget = agg->budgetmax;
-
-       qfq_update_agg_ts(q, agg, enqueue);
-       if (q->in_serv_agg == NULL)
-               q->in_serv_agg = agg;
-       else if (agg != q->in_serv_agg)
-               qfq_schedule_agg(q, agg);
+       qfq_activate_agg(q, agg, enqueue);
 
        return err;
 }
@@ -1261,7 +1279,8 @@ static void qfq_schedule_agg(struct qfq_sched *q, struct qfq_aggregate *agg)
                /* group was surely ineligible, remove */
                __clear_bit(grp->index, &q->bitmaps[IR]);
                __clear_bit(grp->index, &q->bitmaps[IB]);
-       } else if (!q->bitmaps[ER] && qfq_gt(roundedS, q->V))
+       } else if (!q->bitmaps[ER] && qfq_gt(roundedS, q->V) &&
+                  q->in_serv_agg == NULL)
                q->V = roundedS;
 
        grp->S = roundedS;
@@ -1284,8 +1303,15 @@ skip_update:
 static void qfq_activate_agg(struct qfq_sched *q, struct qfq_aggregate *agg,
                             enum update_reason reason)
 {
+       agg->initial_budget = agg->budget = agg->budgetmax; /* recharge budg. */
+
        qfq_update_agg_ts(q, agg, reason);
-       qfq_schedule_agg(q, agg);
+       if (q->in_serv_agg == NULL) { /* no aggr. in service or scheduled */
+               q->in_serv_agg = agg; /* start serving this aggregate */
+                /* update V: to be in service, agg must be eligible */
+               q->oldV = q->V = agg->S;
+       } else if (agg != q->in_serv_agg)
+               qfq_schedule_agg(q, agg);
 }
 
 static void qfq_slot_remove(struct qfq_sched *q, struct qfq_group *grp,
@@ -1357,8 +1383,6 @@ static void qfq_deactivate_agg(struct qfq_sched *q, struct qfq_aggregate *agg)
                        __set_bit(grp->index, &q->bitmaps[s]);
                }
        }
-
-       qfq_update_eligible(q);
 }
 
 static void qfq_qlen_notify(struct Qdisc *sch, unsigned long arg)
index 2b3ef03..12ed45d 100644 (file)
@@ -155,7 +155,7 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
 
        /* SCTP-AUTH extensions*/
        INIT_LIST_HEAD(&ep->endpoint_shared_keys);
-       null_key = sctp_auth_shkey_create(0, GFP_KERNEL);
+       null_key = sctp_auth_shkey_create(0, gfp);
        if (!null_key)
                goto nomem;
 
index c99458d..b907073 100644 (file)
@@ -5653,6 +5653,9 @@ static int sctp_getsockopt_assoc_stats(struct sock *sk, int len,
        if (len < sizeof(sctp_assoc_t))
                return -EINVAL;
 
+       /* Allow the struct to grow and fill in as much as possible */
+       len = min_t(size_t, len, sizeof(sas));
+
        if (copy_from_user(&sas, optval, len))
                return -EFAULT;
 
@@ -5686,9 +5689,6 @@ static int sctp_getsockopt_assoc_stats(struct sock *sk, int len,
        /* Mark beginning of a new observation period */
        asoc->stats.max_obs_rto = asoc->rto_min;
 
-       /* Allow the struct to grow and fill in as much as possible */
-       len = min_t(size_t, len, sizeof(sas));
-
        if (put_user(len, optlen))
                return -EFAULT;
 
index 442ad4e..825ea94 100644 (file)
@@ -41,8 +41,6 @@
 #include <net/sctp/sctp.h>
 #include <net/sctp/sm.h>
 
-#define MAX_KMALLOC_SIZE       131072
-
 static struct sctp_ssnmap *sctp_ssnmap_init(struct sctp_ssnmap *map, __u16 in,
                                            __u16 out);
 
@@ -65,7 +63,7 @@ struct sctp_ssnmap *sctp_ssnmap_new(__u16 in, __u16 out,
        int size;
 
        size = sctp_ssnmap_size(in, out);
-       if (size <= MAX_KMALLOC_SIZE)
+       if (size <= KMALLOC_MAX_SIZE)
                retval = kmalloc(size, gfp);
        else
                retval = (struct sctp_ssnmap *)
@@ -82,7 +80,7 @@ struct sctp_ssnmap *sctp_ssnmap_new(__u16 in, __u16 out,
        return retval;
 
 fail_map:
-       if (size <= MAX_KMALLOC_SIZE)
+       if (size <= KMALLOC_MAX_SIZE)
                kfree(retval);
        else
                free_pages((unsigned long)retval, get_order(size));
@@ -124,7 +122,7 @@ void sctp_ssnmap_free(struct sctp_ssnmap *map)
                int size;
 
                size = sctp_ssnmap_size(map->in.len, map->out.len);
-               if (size <= MAX_KMALLOC_SIZE)
+               if (size <= KMALLOC_MAX_SIZE)
                        kfree(map);
                else
                        free_pages((unsigned long)map, get_order(size));
index 5f25e0c..396c451 100644 (file)
@@ -51,7 +51,7 @@
 static void sctp_tsnmap_update(struct sctp_tsnmap *map);
 static void sctp_tsnmap_find_gap_ack(unsigned long *map, __u16 off,
                                     __u16 len, __u16 *start, __u16 *end);
-static int sctp_tsnmap_grow(struct sctp_tsnmap *map, u16 gap);
+static int sctp_tsnmap_grow(struct sctp_tsnmap *map, u16 size);
 
 /* Initialize a block of memory as a tsnmap.  */
 struct sctp_tsnmap *sctp_tsnmap_init(struct sctp_tsnmap *map, __u16 len,
@@ -124,7 +124,7 @@ int sctp_tsnmap_mark(struct sctp_tsnmap *map, __u32 tsn,
 
        gap = tsn - map->base_tsn;
 
-       if (gap >= map->len && !sctp_tsnmap_grow(map, gap))
+       if (gap >= map->len && !sctp_tsnmap_grow(map, gap + 1))
                return -ENOMEM;
 
        if (!sctp_tsnmap_has_gap(map) && gap == 0) {
@@ -360,23 +360,24 @@ __u16 sctp_tsnmap_num_gabs(struct sctp_tsnmap *map,
        return ngaps;
 }
 
-static int sctp_tsnmap_grow(struct sctp_tsnmap *map, u16 gap)
+static int sctp_tsnmap_grow(struct sctp_tsnmap *map, u16 size)
 {
        unsigned long *new;
        unsigned long inc;
        u16  len;
 
-       if (gap >= SCTP_TSN_MAP_SIZE)
+       if (size > SCTP_TSN_MAP_SIZE)
                return 0;
 
-       inc = ALIGN((gap - map->len),BITS_PER_LONG) + SCTP_TSN_MAP_INCREMENT;
+       inc = ALIGN((size - map->len), BITS_PER_LONG) + SCTP_TSN_MAP_INCREMENT;
        len = min_t(u16, map->len + inc, SCTP_TSN_MAP_SIZE);
 
        new = kzalloc(len>>3, GFP_ATOMIC);
        if (!new)
                return 0;
 
-       bitmap_copy(new, map->tsn_map, map->max_tsn_seen - map->base_tsn);
+       bitmap_copy(new, map->tsn_map,
+               map->max_tsn_seen - map->cumulative_tsn_ack_point);
        kfree(map->tsn_map);
        map->tsn_map = new;
        map->len = len;
index ada1746..0fd5b3d 100644 (file)
@@ -106,6 +106,7 @@ int sctp_ulpq_tail_data(struct sctp_ulpq *ulpq, struct sctp_chunk *chunk,
 {
        struct sk_buff_head temp;
        struct sctp_ulpevent *event;
+       int event_eor = 0;
 
        /* Create an event from the incoming chunk. */
        event = sctp_ulpevent_make_rcvmsg(chunk->asoc, chunk, gfp);
@@ -127,10 +128,12 @@ int sctp_ulpq_tail_data(struct sctp_ulpq *ulpq, struct sctp_chunk *chunk,
        /* Send event to the ULP.  'event' is the sctp_ulpevent for
         * very first SKB on the 'temp' list.
         */
-       if (event)
+       if (event) {
+               event_eor = (event->msg_flags & MSG_EOR) ? 1 : 0;
                sctp_ulpq_tail_event(ulpq, event);
+       }
 
-       return 0;
+       return event_eor;
 }
 
 /* Add a new event for propagation to the ULP.  */
@@ -540,14 +543,19 @@ static struct sctp_ulpevent *sctp_ulpq_retrieve_partial(struct sctp_ulpq *ulpq)
                ctsn = cevent->tsn;
 
                switch (cevent->msg_flags & SCTP_DATA_FRAG_MASK) {
+               case SCTP_DATA_FIRST_FRAG:
+                       if (!first_frag)
+                               return NULL;
+                       goto done;
                case SCTP_DATA_MIDDLE_FRAG:
                        if (!first_frag) {
                                first_frag = pos;
                                next_tsn = ctsn + 1;
                                last_frag = pos;
-                       } else if (next_tsn == ctsn)
+                       } else if (next_tsn == ctsn) {
                                next_tsn++;
-                       else
+                               last_frag = pos;
+                       } else
                                goto done;
                        break;
                case SCTP_DATA_LAST_FRAG:
@@ -651,6 +659,14 @@ static struct sctp_ulpevent *sctp_ulpq_retrieve_first(struct sctp_ulpq *ulpq)
                        } else
                                goto done;
                        break;
+
+               case SCTP_DATA_LAST_FRAG:
+                       if (!first_frag)
+                               return NULL;
+                       else
+                               goto done;
+                       break;
+
                default:
                        return NULL;
                }
@@ -962,20 +978,43 @@ static __u16 sctp_ulpq_renege_list(struct sctp_ulpq *ulpq,
                struct sk_buff_head *list, __u16 needed)
 {
        __u16 freed = 0;
-       __u32 tsn;
-       struct sk_buff *skb;
+       __u32 tsn, last_tsn;
+       struct sk_buff *skb, *flist, *last;
        struct sctp_ulpevent *event;
        struct sctp_tsnmap *tsnmap;
 
        tsnmap = &ulpq->asoc->peer.tsn_map;
 
-       while ((skb = __skb_dequeue_tail(list)) != NULL) {
-               freed += skb_headlen(skb);
+       while ((skb = skb_peek_tail(list)) != NULL) {
                event = sctp_skb2event(skb);
                tsn = event->tsn;
 
+               /* Don't renege below the Cumulative TSN ACK Point. */
+               if (TSN_lte(tsn, sctp_tsnmap_get_ctsn(tsnmap)))
+                       break;
+
+               /* Events in ordering queue may have multiple fragments
+                * corresponding to additional TSNs.  Sum the total
+                * freed space; find the last TSN.
+                */
+               freed += skb_headlen(skb);
+               flist = skb_shinfo(skb)->frag_list;
+               for (last = flist; flist; flist = flist->next) {
+                       last = flist;
+                       freed += skb_headlen(last);
+               }
+               if (last)
+                       last_tsn = sctp_skb2event(last)->tsn;
+               else
+                       last_tsn = tsn;
+
+               /* Unlink the event, then renege all applicable TSNs. */
+               __skb_unlink(skb, list);
                sctp_ulpevent_free(event);
-               sctp_tsnmap_renege(tsnmap, tsn);
+               while (TSN_lte(tsn, last_tsn)) {
+                       sctp_tsnmap_renege(tsnmap, tsn);
+                       tsn++;
+               }
                if (freed >= needed)
                        return freed;
        }
@@ -1002,16 +1041,28 @@ void sctp_ulpq_partial_delivery(struct sctp_ulpq *ulpq,
        struct sctp_ulpevent *event;
        struct sctp_association *asoc;
        struct sctp_sock *sp;
+       __u32 ctsn;
+       struct sk_buff *skb;
 
        asoc = ulpq->asoc;
        sp = sctp_sk(asoc->base.sk);
 
        /* If the association is already in Partial Delivery mode
-        * we have noting to do.
+        * we have nothing to do.
         */
        if (ulpq->pd_mode)
                return;
 
+       /* Data must be at or below the Cumulative TSN ACK Point to
+        * start partial delivery.
+        */
+       skb = skb_peek(&asoc->ulpq.reasm);
+       if (skb != NULL) {
+               ctsn = sctp_skb2event(skb)->tsn;
+               if (!TSN_lte(ctsn, sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map)))
+                       return;
+       }
+
        /* If the user enabled fragment interleave socket option,
         * multiple associations can enter partial delivery.
         * Otherwise, we can only enter partial delivery if the
@@ -1054,12 +1105,16 @@ void sctp_ulpq_renege(struct sctp_ulpq *ulpq, struct sctp_chunk *chunk,
        }
        /* If able to free enough room, accept this chunk. */
        if (chunk && (freed >= needed)) {
-               __u32 tsn;
-               tsn = ntohl(chunk->subh.data_hdr->tsn);
-               sctp_tsnmap_mark(&asoc->peer.tsn_map, tsn, chunk->transport);
-               sctp_ulpq_tail_data(ulpq, chunk, gfp);
-
-               sctp_ulpq_partial_delivery(ulpq, gfp);
+               int retval;
+               retval = sctp_ulpq_tail_data(ulpq, chunk, gfp);
+               /*
+                * Enter partial delivery if chunk has not been
+                * delivered; otherwise, drain the reassembly queue.
+                */
+               if (retval <= 0)
+                       sctp_ulpq_partial_delivery(ulpq, gfp);
+               else if (retval == 1)
+                       sctp_ulpq_reasm_drain(ulpq);
        }
 
        sk_mem_reclaim(asoc->base.sk);
index 9e4cb59..14e9e53 100644 (file)
@@ -5,7 +5,8 @@
 obj-$(CONFIG_SUNRPC_GSS) += auth_rpcgss.o
 
 auth_rpcgss-y := auth_gss.o gss_generic_token.o \
-       gss_mech_switch.o svcauth_gss.o
+       gss_mech_switch.o svcauth_gss.o \
+       gss_rpc_upcall.o gss_rpc_xdr.o
 
 obj-$(CONFIG_RPCSEC_GSS_KRB5) += rpcsec_gss_krb5.o
 
index 51415b0..a764e22 100644 (file)
@@ -238,7 +238,7 @@ gss_fill_context(const void *p, const void *end, struct gss_cl_ctx *ctx, struct
                p = ERR_PTR(-EFAULT);
                goto err;
        }
-       ret = gss_import_sec_context(p, seclen, gm, &ctx->gc_gss_ctx, GFP_NOFS);
+       ret = gss_import_sec_context(p, seclen, gm, &ctx->gc_gss_ctx, NULL, GFP_NOFS);
        if (ret < 0) {
                p = ERR_PTR(ret);
                goto err;
index 33255ff..0d3c158 100644 (file)
@@ -679,6 +679,7 @@ out_err:
 static int
 gss_import_sec_context_kerberos(const void *p, size_t len,
                                struct gss_ctx *ctx_id,
+                               time_t *endtime,
                                gfp_t gfp_mask)
 {
        const void *end = (const void *)((const char *)p + len);
@@ -694,9 +695,11 @@ gss_import_sec_context_kerberos(const void *p, size_t len,
        else
                ret = gss_import_v2_context(p, end, ctx, gfp_mask);
 
-       if (ret == 0)
+       if (ret == 0) {
                ctx_id->internal_ctx_id = ctx;
-       else
+               if (endtime)
+                       *endtime = ctx->endtime;
+       } else
                kfree(ctx);
 
        dprintk("RPC:       %s: returning %d\n", __func__, ret);
index 79881d6..defa9d3 100644 (file)
@@ -175,7 +175,7 @@ struct gss_api_mech * gss_mech_get_by_name(const char *name)
        return gm;
 }
 
-static struct gss_api_mech *gss_mech_get_by_OID(struct rpcsec_gss_oid *obj)
+struct gss_api_mech *gss_mech_get_by_OID(struct rpcsec_gss_oid *obj)
 {
        struct gss_api_mech     *pos, *gm = NULL;
        char buf[32];
@@ -386,14 +386,15 @@ int
 gss_import_sec_context(const void *input_token, size_t bufsize,
                       struct gss_api_mech      *mech,
                       struct gss_ctx           **ctx_id,
+                      time_t                   *endtime,
                       gfp_t gfp_mask)
 {
        if (!(*ctx_id = kzalloc(sizeof(**ctx_id), gfp_mask)))
                return -ENOMEM;
        (*ctx_id)->mech_type = gss_mech_get(mech);
 
-       return mech->gm_ops
-               ->gss_import_sec_context(input_token, bufsize, *ctx_id, gfp_mask);
+       return mech->gm_ops->gss_import_sec_context(input_token, bufsize,
+                                               *ctx_id, endtime, gfp_mask);
 }
 
 /* gss_get_mic: compute a mic over message and return mic_token. */
diff --git a/net/sunrpc/auth_gss/gss_rpc_upcall.c b/net/sunrpc/auth_gss/gss_rpc_upcall.c
new file mode 100644 (file)
index 0000000..c632736
--- /dev/null
@@ -0,0 +1,358 @@
+/*
+ *  linux/net/sunrpc/gss_rpc_upcall.c
+ *
+ *  Copyright (C) 2012 Simo Sorce <simo@redhat.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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/types.h>
+#include <linux/un.h>
+
+#include <linux/sunrpc/svcauth.h>
+#include "gss_rpc_upcall.h"
+
+#define GSSPROXY_SOCK_PATHNAME "/var/run/gssproxy.sock"
+
+#define GSSPROXY_PROGRAM       (400112u)
+#define GSSPROXY_VERS_1                (1u)
+
+/*
+ * Encoding/Decoding functions
+ */
+
+enum {
+       GSSX_NULL = 0,  /* Unused */
+        GSSX_INDICATE_MECHS = 1,
+        GSSX_GET_CALL_CONTEXT = 2,
+        GSSX_IMPORT_AND_CANON_NAME = 3,
+        GSSX_EXPORT_CRED = 4,
+        GSSX_IMPORT_CRED = 5,
+        GSSX_ACQUIRE_CRED = 6,
+        GSSX_STORE_CRED = 7,
+        GSSX_INIT_SEC_CONTEXT = 8,
+        GSSX_ACCEPT_SEC_CONTEXT = 9,
+        GSSX_RELEASE_HANDLE = 10,
+        GSSX_GET_MIC = 11,
+        GSSX_VERIFY = 12,
+        GSSX_WRAP = 13,
+        GSSX_UNWRAP = 14,
+        GSSX_WRAP_SIZE_LIMIT = 15,
+};
+
+#define PROC(proc, name)                               \
+[GSSX_##proc] = {                                      \
+       .p_proc   = GSSX_##proc,                        \
+       .p_encode = (kxdreproc_t)gssx_enc_##name,       \
+       .p_decode = (kxdrdproc_t)gssx_dec_##name,       \
+       .p_arglen = GSSX_ARG_##name##_sz,               \
+       .p_replen = GSSX_RES_##name##_sz,               \
+       .p_statidx = GSSX_##proc,                       \
+       .p_name   = #proc,                              \
+}
+
+struct rpc_procinfo gssp_procedures[] = {
+       PROC(INDICATE_MECHS, indicate_mechs),
+        PROC(GET_CALL_CONTEXT, get_call_context),
+        PROC(IMPORT_AND_CANON_NAME, import_and_canon_name),
+        PROC(EXPORT_CRED, export_cred),
+        PROC(IMPORT_CRED, import_cred),
+        PROC(ACQUIRE_CRED, acquire_cred),
+        PROC(STORE_CRED, store_cred),
+        PROC(INIT_SEC_CONTEXT, init_sec_context),
+        PROC(ACCEPT_SEC_CONTEXT, accept_sec_context),
+        PROC(RELEASE_HANDLE, release_handle),
+        PROC(GET_MIC, get_mic),
+        PROC(VERIFY, verify),
+        PROC(WRAP, wrap),
+        PROC(UNWRAP, unwrap),
+        PROC(WRAP_SIZE_LIMIT, wrap_size_limit),
+};
+
+
+
+/*
+ * Common transport functions
+ */
+
+static const struct rpc_program gssp_program;
+
+static int gssp_rpc_create(struct net *net, struct rpc_clnt **_clnt)
+{
+       static const struct sockaddr_un gssp_localaddr = {
+               .sun_family             = AF_LOCAL,
+               .sun_path               = GSSPROXY_SOCK_PATHNAME,
+       };
+       struct rpc_create_args args = {
+               .net            = net,
+               .protocol       = XPRT_TRANSPORT_LOCAL,
+               .address        = (struct sockaddr *)&gssp_localaddr,
+               .addrsize       = sizeof(gssp_localaddr),
+               .servername     = "localhost",
+               .program        = &gssp_program,
+               .version        = GSSPROXY_VERS_1,
+               .authflavor     = RPC_AUTH_NULL,
+               /*
+                * Note we want connection to be done in the caller's
+                * filesystem namespace.  We therefore turn off the idle
+                * timeout, which would result in reconnections being
+                * done without the correct namespace:
+                */
+               .flags          = RPC_CLNT_CREATE_NOPING |
+                                 RPC_CLNT_CREATE_NO_IDLE_TIMEOUT
+       };
+       struct rpc_clnt *clnt;
+       int result = 0;
+
+       clnt = rpc_create(&args);
+       if (IS_ERR(clnt)) {
+               dprintk("RPC:       failed to create AF_LOCAL gssproxy "
+                               "client (errno %ld).\n", PTR_ERR(clnt));
+               result = -PTR_ERR(clnt);
+               *_clnt = NULL;
+               goto out;
+       }
+
+       dprintk("RPC:       created new gssp local client (gssp_local_clnt: "
+                       "%p)\n", clnt);
+       *_clnt = clnt;
+
+out:
+       return result;
+}
+
+void init_gssp_clnt(struct sunrpc_net *sn)
+{
+       mutex_init(&sn->gssp_lock);
+       sn->gssp_clnt = NULL;
+       init_waitqueue_head(&sn->gssp_wq);
+}
+
+int set_gssp_clnt(struct net *net)
+{
+       struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
+       struct rpc_clnt *clnt;
+       int ret;
+
+       mutex_lock(&sn->gssp_lock);
+       ret = gssp_rpc_create(net, &clnt);
+       if (!ret) {
+               if (sn->gssp_clnt)
+                       rpc_shutdown_client(sn->gssp_clnt);
+               sn->gssp_clnt = clnt;
+       }
+       mutex_unlock(&sn->gssp_lock);
+       wake_up(&sn->gssp_wq);
+       return ret;
+}
+
+void clear_gssp_clnt(struct sunrpc_net *sn)
+{
+       mutex_lock(&sn->gssp_lock);
+       if (sn->gssp_clnt) {
+               rpc_shutdown_client(sn->gssp_clnt);
+               sn->gssp_clnt = NULL;
+       }
+       mutex_unlock(&sn->gssp_lock);
+}
+
+static struct rpc_clnt *get_gssp_clnt(struct sunrpc_net *sn)
+{
+       struct rpc_clnt *clnt;
+
+       mutex_lock(&sn->gssp_lock);
+       clnt = sn->gssp_clnt;
+       if (clnt)
+               atomic_inc(&clnt->cl_count);
+       mutex_unlock(&sn->gssp_lock);
+       return clnt;
+}
+
+static int gssp_call(struct net *net, struct rpc_message *msg)
+{
+       struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
+       struct rpc_clnt *clnt;
+       int status;
+
+       clnt = get_gssp_clnt(sn);
+       if (!clnt)
+               return -EIO;
+       status = rpc_call_sync(clnt, msg, 0);
+       if (status < 0) {
+               dprintk("gssp: rpc_call returned error %d\n", -status);
+               switch (status) {
+               case -EPROTONOSUPPORT:
+                       status = -EINVAL;
+                       break;
+               case -ECONNREFUSED:
+               case -ETIMEDOUT:
+               case -ENOTCONN:
+                       status = -EAGAIN;
+                       break;
+               case -ERESTARTSYS:
+                       if (signalled ())
+                               status = -EINTR;
+                       break;
+               default:
+                       break;
+               }
+       }
+       rpc_release_client(clnt);
+       return status;
+}
+
+
+/*
+ * Public functions
+ */
+
+/* numbers somewhat arbitrary but large enough for current needs */
+#define GSSX_MAX_OUT_HANDLE    128
+#define GSSX_MAX_SRC_PRINC     256
+#define GSSX_KMEMBUF (GSSX_max_output_handle_sz + \
+                       GSSX_max_oid_sz + \
+                       GSSX_max_princ_sz + \
+                       sizeof(struct svc_cred))
+
+int gssp_accept_sec_context_upcall(struct net *net,
+                               struct gssp_upcall_data *data)
+{
+       struct gssx_ctx ctxh = {
+               .state = data->in_handle
+       };
+       struct gssx_arg_accept_sec_context arg = {
+               .input_token = data->in_token,
+       };
+       struct gssx_ctx rctxh = {
+               /*
+                * pass in the max length we expect for each of these
+                * buffers but let the xdr code kmalloc them:
+                */
+               .exported_context_token.len = GSSX_max_output_handle_sz,
+               .mech.len = GSS_OID_MAX_LEN,
+               .src_name.display_name.len = GSSX_max_princ_sz
+       };
+       struct gssx_res_accept_sec_context res = {
+               .context_handle = &rctxh,
+               .output_token = &data->out_token
+       };
+       struct rpc_message msg = {
+               .rpc_proc = &gssp_procedures[GSSX_ACCEPT_SEC_CONTEXT],
+               .rpc_argp = &arg,
+               .rpc_resp = &res,
+               .rpc_cred = NULL, /* FIXME ? */
+       };
+       struct xdr_netobj client_name = { 0 , NULL };
+       int ret;
+
+       if (data->in_handle.len != 0)
+               arg.context_handle = &ctxh;
+       res.output_token->len = GSSX_max_output_token_sz;
+
+       /* use nfs/ for targ_name ? */
+
+       ret = gssp_call(net, &msg);
+
+       /* we need to fetch all data even in case of error so
+        * that we can free special strctures is they have been allocated */
+       data->major_status = res.status.major_status;
+       data->minor_status = res.status.minor_status;
+       if (res.context_handle) {
+               data->out_handle = rctxh.exported_context_token;
+               data->mech_oid.len = rctxh.mech.len;
+               memcpy(data->mech_oid.data, rctxh.mech.data,
+                                               data->mech_oid.len);
+               client_name = rctxh.src_name.display_name;
+       }
+
+       if (res.options.count == 1) {
+               gssx_buffer *value = &res.options.data[0].value;
+               /* Currently we only decode CREDS_VALUE, if we add
+                * anything else we'll have to loop and match on the
+                * option name */
+               if (value->len == 1) {
+                       /* steal group info from struct svc_cred */
+                       data->creds = *(struct svc_cred *)value->data;
+                       data->found_creds = 1;
+               }
+               /* whether we use it or not, free data */
+               kfree(value->data);
+       }
+
+       if (res.options.count != 0) {
+               kfree(res.options.data);
+       }
+
+       /* convert to GSS_NT_HOSTBASED_SERVICE form and set into creds */
+       if (data->found_creds && client_name.data != NULL) {
+               char *c;
+
+               data->creds.cr_principal = kstrndup(client_name.data,
+                                               client_name.len, GFP_KERNEL);
+               if (data->creds.cr_principal) {
+                       /* terminate and remove realm part */
+                       c = strchr(data->creds.cr_principal, '@');
+                       if (c) {
+                               *c = '\0';
+
+                               /* change service-hostname delimiter */
+                               c = strchr(data->creds.cr_principal, '/');
+                               if (c) *c = '@';
+                       }
+                       if (!c) {
+                               /* not a service principal */
+                               kfree(data->creds.cr_principal);
+                               data->creds.cr_principal = NULL;
+                       }
+               }
+       }
+       kfree(client_name.data);
+
+       return ret;
+}
+
+void gssp_free_upcall_data(struct gssp_upcall_data *data)
+{
+       kfree(data->in_handle.data);
+       kfree(data->out_handle.data);
+       kfree(data->out_token.data);
+       kfree(data->mech_oid.data);
+       free_svc_cred(&data->creds);
+}
+
+/*
+ * Initialization stuff
+ */
+
+static const struct rpc_version gssp_version1 = {
+       .number         = GSSPROXY_VERS_1,
+       .nrprocs        = ARRAY_SIZE(gssp_procedures),
+       .procs          = gssp_procedures,
+};
+
+static const struct rpc_version *gssp_version[] = {
+       NULL,
+       &gssp_version1,
+};
+
+static struct rpc_stat gssp_stats;
+
+static const struct rpc_program gssp_program = {
+       .name           = "gssproxy",
+       .number         = GSSPROXY_PROGRAM,
+       .nrvers         = ARRAY_SIZE(gssp_version),
+       .version        = gssp_version,
+       .stats          = &gssp_stats,
+};
diff --git a/net/sunrpc/auth_gss/gss_rpc_upcall.h b/net/sunrpc/auth_gss/gss_rpc_upcall.h
new file mode 100644 (file)
index 0000000..1e542ad
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ *  linux/net/sunrpc/gss_rpc_upcall.h
+ *
+ *  Copyright (C) 2012 Simo Sorce <simo@redhat.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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _GSS_RPC_UPCALL_H
+#define _GSS_RPC_UPCALL_H
+
+#include <linux/sunrpc/gss_api.h>
+#include <linux/sunrpc/auth_gss.h>
+#include "gss_rpc_xdr.h"
+#include "../netns.h"
+
+struct gssp_upcall_data {
+       struct xdr_netobj in_handle;
+       struct gssp_in_token in_token;
+       struct xdr_netobj out_handle;
+       struct xdr_netobj out_token;
+       struct rpcsec_gss_oid mech_oid;
+       struct svc_cred creds;
+       int found_creds;
+       int major_status;
+       int minor_status;
+};
+
+int gssp_accept_sec_context_upcall(struct net *net,
+                               struct gssp_upcall_data *data);
+void gssp_free_upcall_data(struct gssp_upcall_data *data);
+
+void init_gssp_clnt(struct sunrpc_net *);
+int set_gssp_clnt(struct net *);
+void clear_gssp_clnt(struct sunrpc_net *);
+#endif /* _GSS_RPC_UPCALL_H */
diff --git a/net/sunrpc/auth_gss/gss_rpc_xdr.c b/net/sunrpc/auth_gss/gss_rpc_xdr.c
new file mode 100644 (file)
index 0000000..d0ccdff
--- /dev/null
@@ -0,0 +1,832 @@
+/*
+ * GSS Proxy upcall module
+ *
+ *  Copyright (C) 2012 Simo Sorce <simo@redhat.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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/sunrpc/svcauth.h>
+#include "gss_rpc_xdr.h"
+
+static bool gssx_check_pointer(struct xdr_stream *xdr)
+{
+       __be32 *p;
+
+       p = xdr_reserve_space(xdr, 4);
+       if (unlikely(p == NULL))
+               return -ENOSPC;
+       return *p?true:false;
+}
+
+static int gssx_enc_bool(struct xdr_stream *xdr, int v)
+{
+       __be32 *p;
+
+       p = xdr_reserve_space(xdr, 4);
+       if (unlikely(p == NULL))
+               return -ENOSPC;
+       *p = v ? xdr_one : xdr_zero;
+       return 0;
+}
+
+static int gssx_dec_bool(struct xdr_stream *xdr, u32 *v)
+{
+       __be32 *p;
+
+       p = xdr_inline_decode(xdr, 4);
+       if (unlikely(p == NULL))
+               return -ENOSPC;
+       *v = be32_to_cpu(*p);
+       return 0;
+}
+
+static int gssx_enc_buffer(struct xdr_stream *xdr,
+                          gssx_buffer *buf)
+{
+       __be32 *p;
+
+       p = xdr_reserve_space(xdr, sizeof(u32) + buf->len);
+       if (!p)
+               return -ENOSPC;
+       xdr_encode_opaque(p, buf->data, buf->len);
+       return 0;
+}
+
+static int gssx_enc_in_token(struct xdr_stream *xdr,
+                            struct gssp_in_token *in)
+{
+       __be32 *p;
+
+       p = xdr_reserve_space(xdr, 4);
+       if (!p)
+               return -ENOSPC;
+       *p = cpu_to_be32(in->page_len);
+
+       /* all we need to do is to write pages */
+       xdr_write_pages(xdr, in->pages, in->page_base, in->page_len);
+
+       return 0;
+}
+
+
+static int gssx_dec_buffer(struct xdr_stream *xdr,
+                          gssx_buffer *buf)
+{
+       u32 length;
+       __be32 *p;
+
+       p = xdr_inline_decode(xdr, 4);
+       if (unlikely(p == NULL))
+               return -ENOSPC;
+
+       length = be32_to_cpup(p);
+       p = xdr_inline_decode(xdr, length);
+       if (unlikely(p == NULL))
+               return -ENOSPC;
+
+       if (buf->len == 0) {
+               /* we intentionally are not interested in this buffer */
+               return 0;
+       }
+       if (length > buf->len)
+               return -ENOSPC;
+
+       if (!buf->data) {
+               buf->data = kmemdup(p, length, GFP_KERNEL);
+               if (!buf->data)
+                       return -ENOMEM;
+       } else {
+               memcpy(buf->data, p, length);
+       }
+       buf->len = length;
+       return 0;
+}
+
+static int gssx_enc_option(struct xdr_stream *xdr,
+                          struct gssx_option *opt)
+{
+       int err;
+
+       err = gssx_enc_buffer(xdr, &opt->option);
+       if (err)
+               return err;
+       err = gssx_enc_buffer(xdr, &opt->value);
+       return err;
+}
+
+static int gssx_dec_option(struct xdr_stream *xdr,
+                          struct gssx_option *opt)
+{
+       int err;
+
+       err = gssx_dec_buffer(xdr, &opt->option);
+       if (err)
+               return err;
+       err = gssx_dec_buffer(xdr, &opt->value);
+       return err;
+}
+
+static int dummy_enc_opt_array(struct xdr_stream *xdr,
+                               struct gssx_option_array *oa)
+{
+       __be32 *p;
+
+       if (oa->count != 0)
+               return -EINVAL;
+
+       p = xdr_reserve_space(xdr, 4);
+       if (!p)
+               return -ENOSPC;
+       *p = 0;
+
+       return 0;
+}
+
+static int dummy_dec_opt_array(struct xdr_stream *xdr,
+                               struct gssx_option_array *oa)
+{
+       struct gssx_option dummy;
+       u32 count, i;
+       __be32 *p;
+
+       p = xdr_inline_decode(xdr, 4);
+       if (unlikely(p == NULL))
+               return -ENOSPC;
+       count = be32_to_cpup(p++);
+       memset(&dummy, 0, sizeof(dummy));
+       for (i = 0; i < count; i++) {
+               gssx_dec_option(xdr, &dummy);
+       }
+
+       oa->count = 0;
+       oa->data = NULL;
+       return 0;
+}
+
+static int get_s32(void **p, void *max, s32 *res)
+{
+       void *base = *p;
+       void *next = (void *)((char *)base + sizeof(s32));
+       if (unlikely(next > max || next < base))
+               return -EINVAL;
+       memcpy(res, base, sizeof(s32));
+       *p = next;
+       return 0;
+}
+
+static int gssx_dec_linux_creds(struct xdr_stream *xdr,
+                               struct svc_cred *creds)
+{
+       u32 length;
+       __be32 *p;
+       void *q, *end;
+       s32 tmp;
+       int N, i, err;
+
+       p = xdr_inline_decode(xdr, 4);
+       if (unlikely(p == NULL))
+               return -ENOSPC;
+
+       length = be32_to_cpup(p);
+
+       /* FIXME: we do not want to use the scratch buffer for this one
+        * may need to use functions that allows us to access an io vector
+        * directly */
+       p = xdr_inline_decode(xdr, length);
+       if (unlikely(p == NULL))
+               return -ENOSPC;
+
+       q = p;
+       end = q + length;
+
+       /* uid */
+       err = get_s32(&q, end, &tmp);
+       if (err)
+               return err;
+       creds->cr_uid = tmp;
+
+       /* gid */
+       err = get_s32(&q, end, &tmp);
+       if (err)
+               return err;
+       creds->cr_gid = tmp;
+
+       /* number of additional gid's */
+       err = get_s32(&q, end, &tmp);
+       if (err)
+               return err;
+       N = tmp;
+       creds->cr_group_info = groups_alloc(N);
+       if (creds->cr_group_info == NULL)
+               return -ENOMEM;
+
+       /* gid's */
+       for (i = 0; i < N; i++) {
+               err = get_s32(&q, end, &tmp);
+               if (err) {
+                       groups_free(creds->cr_group_info);
+                       return err;
+               }
+               GROUP_AT(creds->cr_group_info, i) = tmp;
+       }
+
+       return 0;
+}
+
+static int gssx_dec_option_array(struct xdr_stream *xdr,
+                                struct gssx_option_array *oa)
+{
+       struct svc_cred *creds;
+       u32 count, i;
+       __be32 *p;
+       int err;
+
+       p = xdr_inline_decode(xdr, 4);
+       if (unlikely(p == NULL))
+               return -ENOSPC;
+       count = be32_to_cpup(p++);
+       if (count != 0) {
+               /* we recognize only 1 currently: CREDS_VALUE */
+               oa->count = 1;
+
+               oa->data = kmalloc(sizeof(struct gssx_option), GFP_KERNEL);
+               if (!oa->data)
+                       return -ENOMEM;
+
+               creds = kmalloc(sizeof(struct svc_cred), GFP_KERNEL);
+               if (!creds) {
+                       kfree(oa->data);
+                       return -ENOMEM;
+               }
+
+               oa->data[0].option.data = CREDS_VALUE;
+               oa->data[0].option.len = sizeof(CREDS_VALUE);
+               oa->data[0].value.data = (void *)creds;
+               oa->data[0].value.len = 0;
+       }
+       for (i = 0; i < count; i++) {
+               gssx_buffer dummy = { 0, NULL };
+               u32 length;
+
+               /* option buffer */
+               p = xdr_inline_decode(xdr, 4);
+               if (unlikely(p == NULL))
+                       return -ENOSPC;
+
+               length = be32_to_cpup(p);
+               p = xdr_inline_decode(xdr, length);
+               if (unlikely(p == NULL))
+                       return -ENOSPC;
+
+               if (length == sizeof(CREDS_VALUE) &&
+                   memcmp(p, CREDS_VALUE, sizeof(CREDS_VALUE)) == 0) {
+                       /* We have creds here. parse them */
+                       err = gssx_dec_linux_creds(xdr, creds);
+                       if (err)
+                               return err;
+                       oa->data[0].value.len = 1; /* presence */
+               } else {
+                       /* consume uninteresting buffer */
+                       err = gssx_dec_buffer(xdr, &dummy);
+                       if (err)
+                               return err;
+               }
+       }
+       return 0;
+}
+
+static int gssx_dec_status(struct xdr_stream *xdr,
+                          struct gssx_status *status)
+{
+       __be32 *p;
+       int err;
+
+       /* status->major_status */
+       p = xdr_inline_decode(xdr, 8);
+       if (unlikely(p == NULL))
+               return -ENOSPC;
+       p = xdr_decode_hyper(p, &status->major_status);
+
+       /* status->mech */
+       err = gssx_dec_buffer(xdr, &status->mech);
+       if (err)
+               return err;
+
+       /* status->minor_status */
+       p = xdr_inline_decode(xdr, 8);
+       if (unlikely(p == NULL))
+               return -ENOSPC;
+       p = xdr_decode_hyper(p, &status->minor_status);
+
+       /* status->major_status_string */
+       err = gssx_dec_buffer(xdr, &status->major_status_string);
+       if (err)
+               return err;
+
+       /* status->minor_status_string */
+       err = gssx_dec_buffer(xdr, &status->minor_status_string);
+       if (err)
+               return err;
+
+       /* status->server_ctx */
+       err = gssx_dec_buffer(xdr, &status->server_ctx);
+       if (err)
+               return err;
+
+       /* we assume we have no options for now, so simply consume them */
+       /* status->options */
+       err = dummy_dec_opt_array(xdr, &status->options);
+
+       return err;
+}
+
+static int gssx_enc_call_ctx(struct xdr_stream *xdr,
+                            struct gssx_call_ctx *ctx)
+{
+       struct gssx_option opt;
+       __be32 *p;
+       int err;
+
+       /* ctx->locale */
+       err = gssx_enc_buffer(xdr, &ctx->locale);
+       if (err)
+               return err;
+
+       /* ctx->server_ctx */
+       err = gssx_enc_buffer(xdr, &ctx->server_ctx);
+       if (err)
+               return err;
+
+       /* we always want to ask for lucid contexts */
+       /* ctx->options */
+       p = xdr_reserve_space(xdr, 4);
+       *p = cpu_to_be32(2);
+
+       /* we want a lucid_v1 context */
+       opt.option.data = LUCID_OPTION;
+       opt.option.len = sizeof(LUCID_OPTION);
+       opt.value.data = LUCID_VALUE;
+       opt.value.len = sizeof(LUCID_VALUE);
+       err = gssx_enc_option(xdr, &opt);
+
+       /* ..and user creds */
+       opt.option.data = CREDS_OPTION;
+       opt.option.len = sizeof(CREDS_OPTION);
+       opt.value.data = CREDS_VALUE;
+       opt.value.len = sizeof(CREDS_VALUE);
+       err = gssx_enc_option(xdr, &opt);
+
+       return err;
+}
+
+static int gssx_dec_name_attr(struct xdr_stream *xdr,
+                            struct gssx_name_attr *attr)
+{
+       int err;
+
+       /* attr->attr */
+       err = gssx_dec_buffer(xdr, &attr->attr);
+       if (err)
+               return err;
+
+       /* attr->value */
+       err = gssx_dec_buffer(xdr, &attr->value);
+       if (err)
+               return err;
+
+       /* attr->extensions */
+       err = dummy_dec_opt_array(xdr, &attr->extensions);
+
+       return err;
+}
+
+static int dummy_enc_nameattr_array(struct xdr_stream *xdr,
+                                   struct gssx_name_attr_array *naa)
+{
+       __be32 *p;
+
+       if (naa->count != 0)
+               return -EINVAL;
+
+       p = xdr_reserve_space(xdr, 4);
+       if (!p)
+               return -ENOSPC;
+       *p = 0;
+
+       return 0;
+}
+
+static int dummy_dec_nameattr_array(struct xdr_stream *xdr,
+                                   struct gssx_name_attr_array *naa)
+{
+       struct gssx_name_attr dummy;
+       u32 count, i;
+       __be32 *p;
+
+       p = xdr_inline_decode(xdr, 4);
+       if (unlikely(p == NULL))
+               return -ENOSPC;
+       count = be32_to_cpup(p++);
+       for (i = 0; i < count; i++) {
+               gssx_dec_name_attr(xdr, &dummy);
+       }
+
+       naa->count = 0;
+       naa->data = NULL;
+       return 0;
+}
+
+static struct xdr_netobj zero_netobj = {};
+
+static struct gssx_name_attr_array zero_name_attr_array = {};
+
+static struct gssx_option_array zero_option_array = {};
+
+static int gssx_enc_name(struct xdr_stream *xdr,
+                        struct gssx_name *name)
+{
+       int err;
+
+       /* name->display_name */
+       err = gssx_enc_buffer(xdr, &name->display_name);
+       if (err)
+               return err;
+
+       /* name->name_type */
+       err = gssx_enc_buffer(xdr, &zero_netobj);
+       if (err)
+               return err;
+
+       /* name->exported_name */
+       err = gssx_enc_buffer(xdr, &zero_netobj);
+       if (err)
+               return err;
+
+       /* name->exported_composite_name */
+       err = gssx_enc_buffer(xdr, &zero_netobj);
+       if (err)
+               return err;
+
+       /* leave name_attributes empty for now, will add once we have any
+        * to pass up at all */
+       /* name->name_attributes */
+       err = dummy_enc_nameattr_array(xdr, &zero_name_attr_array);
+       if (err)
+               return err;
+
+       /* leave options empty for now, will add once we have any options
+        * to pass up at all */
+       /* name->extensions */
+       err = dummy_enc_opt_array(xdr, &zero_option_array);
+
+       return err;
+}
+
+static int gssx_dec_name(struct xdr_stream *xdr,
+                        struct gssx_name *name)
+{
+       struct xdr_netobj dummy_netobj;
+       struct gssx_name_attr_array dummy_name_attr_array;
+       struct gssx_option_array dummy_option_array;
+       int err;
+
+       /* name->display_name */
+       err = gssx_dec_buffer(xdr, &name->display_name);
+       if (err)
+               return err;
+
+       /* name->name_type */
+       err = gssx_dec_buffer(xdr, &dummy_netobj);
+       if (err)
+               return err;
+
+       /* name->exported_name */
+       err = gssx_dec_buffer(xdr, &dummy_netobj);
+       if (err)
+               return err;
+
+       /* name->exported_composite_name */
+       err = gssx_dec_buffer(xdr, &dummy_netobj);
+       if (err)
+               return err;
+
+       /* we assume we have no attributes for now, so simply consume them */
+       /* name->name_attributes */
+       err = dummy_dec_nameattr_array(xdr, &dummy_name_attr_array);
+       if (err)
+               return err;
+
+       /* we assume we have no options for now, so simply consume them */
+       /* name->extensions */
+       err = dummy_dec_opt_array(xdr, &dummy_option_array);
+
+       return err;
+}
+
+static int dummy_enc_credel_array(struct xdr_stream *xdr,
+                                 struct gssx_cred_element_array *cea)
+{
+       __be32 *p;
+
+       if (cea->count != 0)
+               return -EINVAL;
+
+       p = xdr_reserve_space(xdr, 4);
+       if (!p)
+               return -ENOSPC;
+       *p = 0;
+
+       return 0;
+}
+
+static int gssx_enc_cred(struct xdr_stream *xdr,
+                        struct gssx_cred *cred)
+{
+       int err;
+
+       /* cred->desired_name */
+       err = gssx_enc_name(xdr, &cred->desired_name);
+       if (err)
+               return err;
+
+       /* cred->elements */
+       err = dummy_enc_credel_array(xdr, &cred->elements);
+
+       /* cred->cred_handle_reference */
+       err = gssx_enc_buffer(xdr, &cred->cred_handle_reference);
+       if (err)
+               return err;
+
+       /* cred->needs_release */
+       err = gssx_enc_bool(xdr, cred->needs_release);
+
+       return err;
+}
+
+static int gssx_enc_ctx(struct xdr_stream *xdr,
+                       struct gssx_ctx *ctx)
+{
+       __be32 *p;
+       int err;
+
+       /* ctx->exported_context_token */
+       err = gssx_enc_buffer(xdr, &ctx->exported_context_token);
+       if (err)
+               return err;
+
+       /* ctx->state */
+       err = gssx_enc_buffer(xdr, &ctx->state);
+       if (err)
+               return err;
+
+       /* ctx->need_release */
+       err = gssx_enc_bool(xdr, ctx->need_release);
+       if (err)
+               return err;
+
+       /* ctx->mech */
+       err = gssx_enc_buffer(xdr, &ctx->mech);
+       if (err)
+               return err;
+
+       /* ctx->src_name */
+       err = gssx_enc_name(xdr, &ctx->src_name);
+       if (err)
+               return err;
+
+       /* ctx->targ_name */
+       err = gssx_enc_name(xdr, &ctx->targ_name);
+       if (err)
+               return err;
+
+       /* ctx->lifetime */
+       p = xdr_reserve_space(xdr, 8+8);
+       if (!p)
+               return -ENOSPC;
+       p = xdr_encode_hyper(p, ctx->lifetime);
+
+       /* ctx->ctx_flags */
+       p = xdr_encode_hyper(p, ctx->ctx_flags);
+
+       /* ctx->locally_initiated */
+       err = gssx_enc_bool(xdr, ctx->locally_initiated);
+       if (err)
+               return err;
+
+       /* ctx->open */
+       err = gssx_enc_bool(xdr, ctx->open);
+       if (err)
+               return err;
+
+       /* leave options empty for now, will add once we have any options
+        * to pass up at all */
+       /* ctx->options */
+       err = dummy_enc_opt_array(xdr, &ctx->options);
+
+       return err;
+}
+
+static int gssx_dec_ctx(struct xdr_stream *xdr,
+                       struct gssx_ctx *ctx)
+{
+       __be32 *p;
+       int err;
+
+       /* ctx->exported_context_token */
+       err = gssx_dec_buffer(xdr, &ctx->exported_context_token);
+       if (err)
+               return err;
+
+       /* ctx->state */
+       err = gssx_dec_buffer(xdr, &ctx->state);
+       if (err)
+               return err;
+
+       /* ctx->need_release */
+       err = gssx_dec_bool(xdr, &ctx->need_release);
+       if (err)
+               return err;
+
+       /* ctx->mech */
+       err = gssx_dec_buffer(xdr, &ctx->mech);
+       if (err)
+               return err;
+
+       /* ctx->src_name */
+       err = gssx_dec_name(xdr, &ctx->src_name);
+       if (err)
+               return err;
+
+       /* ctx->targ_name */
+       err = gssx_dec_name(xdr, &ctx->targ_name);
+       if (err)
+               return err;
+
+       /* ctx->lifetime */
+       p = xdr_inline_decode(xdr, 8+8);
+       if (unlikely(p == NULL))
+               return -ENOSPC;
+       p = xdr_decode_hyper(p, &ctx->lifetime);
+
+       /* ctx->ctx_flags */
+       p = xdr_decode_hyper(p, &ctx->ctx_flags);
+
+       /* ctx->locally_initiated */
+       err = gssx_dec_bool(xdr, &ctx->locally_initiated);
+       if (err)
+               return err;
+
+       /* ctx->open */
+       err = gssx_dec_bool(xdr, &ctx->open);
+       if (err)
+               return err;
+
+       /* we assume we have no options for now, so simply consume them */
+       /* ctx->options */
+       err = dummy_dec_opt_array(xdr, &ctx->options);
+
+       return err;
+}
+
+static int gssx_enc_cb(struct xdr_stream *xdr, struct gssx_cb *cb)
+{
+       __be32 *p;
+       int err;
+
+       /* cb->initiator_addrtype */
+       p = xdr_reserve_space(xdr, 8);
+       if (!p)
+               return -ENOSPC;
+       p = xdr_encode_hyper(p, cb->initiator_addrtype);
+
+       /* cb->initiator_address */
+       err = gssx_enc_buffer(xdr, &cb->initiator_address);
+       if (err)
+               return err;
+
+       /* cb->acceptor_addrtype */
+       p = xdr_reserve_space(xdr, 8);
+       if (!p)
+               return -ENOSPC;
+       p = xdr_encode_hyper(p, cb->acceptor_addrtype);
+
+       /* cb->acceptor_address */
+       err = gssx_enc_buffer(xdr, &cb->acceptor_address);
+       if (err)
+               return err;
+
+       /* cb->application_data */
+       err = gssx_enc_buffer(xdr, &cb->application_data);
+
+       return err;
+}
+
+void gssx_enc_accept_sec_context(struct rpc_rqst *req,
+                                struct xdr_stream *xdr,
+                                struct gssx_arg_accept_sec_context *arg)
+{
+       int err;
+
+       err = gssx_enc_call_ctx(xdr, &arg->call_ctx);
+       if (err)
+               goto done;
+
+       /* arg->context_handle */
+       if (arg->context_handle) {
+               err = gssx_enc_ctx(xdr, arg->context_handle);
+               if (err)
+                       goto done;
+       } else {
+               err = gssx_enc_bool(xdr, 0);
+       }
+
+       /* arg->cred_handle */
+       if (arg->cred_handle) {
+               err = gssx_enc_cred(xdr, arg->cred_handle);
+               if (err)
+                       goto done;
+       } else {
+               err = gssx_enc_bool(xdr, 0);
+       }
+
+       /* arg->input_token */
+       err = gssx_enc_in_token(xdr, &arg->input_token);
+       if (err)
+               goto done;
+
+       /* arg->input_cb */
+       if (arg->input_cb) {
+               err = gssx_enc_cb(xdr, arg->input_cb);
+               if (err)
+                       goto done;
+       } else {
+               err = gssx_enc_bool(xdr, 0);
+       }
+
+       err = gssx_enc_bool(xdr, arg->ret_deleg_cred);
+       if (err)
+               goto done;
+
+       /* leave options empty for now, will add once we have any options
+        * to pass up at all */
+       /* arg->options */
+       err = dummy_enc_opt_array(xdr, &arg->options);
+
+done:
+       if (err)
+               dprintk("RPC:       gssx_enc_accept_sec_context: %d\n", err);
+}
+
+int gssx_dec_accept_sec_context(struct rpc_rqst *rqstp,
+                               struct xdr_stream *xdr,
+                               struct gssx_res_accept_sec_context *res)
+{
+       int err;
+
+       /* res->status */
+       err = gssx_dec_status(xdr, &res->status);
+       if (err)
+               return err;
+
+       /* res->context_handle */
+       if (gssx_check_pointer(xdr)) {
+               err = gssx_dec_ctx(xdr, res->context_handle);
+               if (err)
+                       return err;
+       } else {
+               res->context_handle = NULL;
+       }
+
+       /* res->output_token */
+       if (gssx_check_pointer(xdr)) {
+               err = gssx_dec_buffer(xdr, res->output_token);
+               if (err)
+                       return err;
+       } else {
+               res->output_token = NULL;
+       }
+
+       /* res->delegated_cred_handle */
+       if (gssx_check_pointer(xdr)) {
+               /* we do not support upcall servers sending this data. */
+               return -EINVAL;
+       }
+
+       /* res->options */
+       err = gssx_dec_option_array(xdr, &res->options);
+
+       return err;
+}
diff --git a/net/sunrpc/auth_gss/gss_rpc_xdr.h b/net/sunrpc/auth_gss/gss_rpc_xdr.h
new file mode 100644 (file)
index 0000000..1c98b27
--- /dev/null
@@ -0,0 +1,264 @@
+/*
+ * GSS Proxy upcall module
+ *
+ *  Copyright (C) 2012 Simo Sorce <simo@redhat.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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _LINUX_GSS_RPC_XDR_H
+#define _LINUX_GSS_RPC_XDR_H
+
+#include <linux/sunrpc/xdr.h>
+#include <linux/sunrpc/clnt.h>
+#include <linux/sunrpc/xprtsock.h>
+
+#ifdef RPC_DEBUG
+# define RPCDBG_FACILITY       RPCDBG_AUTH
+#endif
+
+#define LUCID_OPTION "exported_context_type"
+#define LUCID_VALUE  "linux_lucid_v1"
+#define CREDS_OPTION "exported_creds_type"
+#define CREDS_VALUE  "linux_creds_v1"
+
+typedef struct xdr_netobj gssx_buffer;
+typedef struct xdr_netobj utf8string;
+typedef struct xdr_netobj gssx_OID;
+
+enum gssx_cred_usage {
+       GSSX_C_INITIATE = 1,
+       GSSX_C_ACCEPT = 2,
+       GSSX_C_BOTH = 3,
+};
+
+struct gssx_option {
+       gssx_buffer option;
+       gssx_buffer value;
+};
+
+struct gssx_option_array {
+       u32 count;
+       struct gssx_option *data;
+};
+
+struct gssx_status {
+       u64 major_status;
+       gssx_OID mech;
+       u64 minor_status;
+       utf8string major_status_string;
+       utf8string minor_status_string;
+       gssx_buffer server_ctx;
+       struct gssx_option_array options;
+};
+
+struct gssx_call_ctx {
+       utf8string locale;
+       gssx_buffer server_ctx;
+       struct gssx_option_array options;
+};
+
+struct gssx_name_attr {
+       gssx_buffer attr;
+       gssx_buffer value;
+       struct gssx_option_array extensions;
+};
+
+struct gssx_name_attr_array {
+       u32 count;
+       struct gssx_name_attr *data;
+};
+
+struct gssx_name {
+       gssx_buffer display_name;
+};
+typedef struct gssx_name gssx_name;
+
+struct gssx_cred_element {
+       gssx_name MN;
+       gssx_OID mech;
+       u32 cred_usage;
+       u64 initiator_time_rec;
+       u64 acceptor_time_rec;
+       struct gssx_option_array options;
+};
+
+struct gssx_cred_element_array {
+       u32 count;
+       struct gssx_cred_element *data;
+};
+
+struct gssx_cred {
+       gssx_name desired_name;
+       struct gssx_cred_element_array elements;
+       gssx_buffer cred_handle_reference;
+       u32 needs_release;
+};
+
+struct gssx_ctx {
+       gssx_buffer exported_context_token;
+       gssx_buffer state;
+       u32 need_release;
+       gssx_OID mech;
+       gssx_name src_name;
+       gssx_name targ_name;
+       u64 lifetime;
+       u64 ctx_flags;
+       u32 locally_initiated;
+       u32 open;
+       struct gssx_option_array options;
+};
+
+struct gssx_cb {
+       u64 initiator_addrtype;
+       gssx_buffer initiator_address;
+       u64 acceptor_addrtype;
+       gssx_buffer acceptor_address;
+       gssx_buffer application_data;
+};
+
+
+/* This structure is not defined in the protocol.
+ * It is used in the kernel to carry around a big buffer
+ * as a set of pages */
+struct gssp_in_token {
+       struct page **pages;    /* Array of contiguous pages */
+       unsigned int page_base; /* Start of page data */
+       unsigned int page_len;  /* Length of page data */
+};
+
+struct gssx_arg_accept_sec_context {
+       struct gssx_call_ctx call_ctx;
+       struct gssx_ctx *context_handle;
+       struct gssx_cred *cred_handle;
+       struct gssp_in_token input_token;
+       struct gssx_cb *input_cb;
+       u32 ret_deleg_cred;
+       struct gssx_option_array options;
+};
+
+struct gssx_res_accept_sec_context {
+       struct gssx_status status;
+       struct gssx_ctx *context_handle;
+       gssx_buffer *output_token;
+       /* struct gssx_cred *delegated_cred_handle; not used in kernel */
+       struct gssx_option_array options;
+};
+
+
+
+#define gssx_enc_indicate_mechs NULL
+#define gssx_dec_indicate_mechs NULL
+#define gssx_enc_get_call_context NULL
+#define gssx_dec_get_call_context NULL
+#define gssx_enc_import_and_canon_name NULL
+#define gssx_dec_import_and_canon_name NULL
+#define gssx_enc_export_cred NULL
+#define gssx_dec_export_cred NULL
+#define gssx_enc_import_cred NULL
+#define gssx_dec_import_cred NULL
+#define gssx_enc_acquire_cred NULL
+#define gssx_dec_acquire_cred NULL
+#define gssx_enc_store_cred NULL
+#define gssx_dec_store_cred NULL
+#define gssx_enc_init_sec_context NULL
+#define gssx_dec_init_sec_context NULL
+void gssx_enc_accept_sec_context(struct rpc_rqst *req,
+                                struct xdr_stream *xdr,
+                                struct gssx_arg_accept_sec_context *args);
+int gssx_dec_accept_sec_context(struct rpc_rqst *rqstp,
+                               struct xdr_stream *xdr,
+                               struct gssx_res_accept_sec_context *res);
+#define gssx_enc_release_handle NULL
+#define gssx_dec_release_handle NULL
+#define gssx_enc_get_mic NULL
+#define gssx_dec_get_mic NULL
+#define gssx_enc_verify NULL
+#define gssx_dec_verify NULL
+#define gssx_enc_wrap NULL
+#define gssx_dec_wrap NULL
+#define gssx_enc_unwrap NULL
+#define gssx_dec_unwrap NULL
+#define gssx_enc_wrap_size_limit NULL
+#define gssx_dec_wrap_size_limit NULL
+
+/* non implemented calls are set to 0 size */
+#define GSSX_ARG_indicate_mechs_sz 0
+#define GSSX_RES_indicate_mechs_sz 0
+#define GSSX_ARG_get_call_context_sz 0
+#define GSSX_RES_get_call_context_sz 0
+#define GSSX_ARG_import_and_canon_name_sz 0
+#define GSSX_RES_import_and_canon_name_sz 0
+#define GSSX_ARG_export_cred_sz 0
+#define GSSX_RES_export_cred_sz 0
+#define GSSX_ARG_import_cred_sz 0
+#define GSSX_RES_import_cred_sz 0
+#define GSSX_ARG_acquire_cred_sz 0
+#define GSSX_RES_acquire_cred_sz 0
+#define GSSX_ARG_store_cred_sz 0
+#define GSSX_RES_store_cred_sz 0
+#define GSSX_ARG_init_sec_context_sz 0
+#define GSSX_RES_init_sec_context_sz 0
+
+#define GSSX_default_in_call_ctx_sz (4 + 4 + 4 + \
+                       8 + sizeof(LUCID_OPTION) + sizeof(LUCID_VALUE) + \
+                       8 + sizeof(CREDS_OPTION) + sizeof(CREDS_VALUE))
+#define GSSX_default_in_ctx_hndl_sz (4 + 4+8 + 4 + 4 + 6*4 + 6*4 + 8 + 8 + \
+                                       4 + 4 + 4)
+#define GSSX_default_in_cred_sz 4 /* we send in no cred_handle */
+#define GSSX_default_in_token_sz 4 /* does *not* include token data */
+#define GSSX_default_in_cb_sz 4 /* we do not use channel bindings */
+#define GSSX_ARG_accept_sec_context_sz (GSSX_default_in_call_ctx_sz + \
+                                       GSSX_default_in_ctx_hndl_sz + \
+                                       GSSX_default_in_cred_sz + \
+                                       GSSX_default_in_token_sz + \
+                                       GSSX_default_in_cb_sz + \
+                                       4 /* no deleg creds boolean */ + \
+                                       4) /* empty options */
+
+/* somewhat arbitrary numbers but large enough (we ignore some of the data
+ * sent down, but it is part of the protocol so we need enough space to take
+ * it in) */
+#define GSSX_default_status_sz 8 + 24 + 8 + 256 + 256 + 16 + 4
+#define GSSX_max_output_handle_sz 128
+#define GSSX_max_oid_sz 16
+#define GSSX_max_princ_sz 256
+#define GSSX_default_ctx_sz (GSSX_max_output_handle_sz + \
+                            16 + 4 + GSSX_max_oid_sz + \
+                            2 * GSSX_max_princ_sz + \
+                            8 + 8 + 4 + 4 + 4)
+#define GSSX_max_output_token_sz 1024
+#define GSSX_max_creds_sz (4 + 4 + 4 + NGROUPS_MAX * 4)
+#define GSSX_RES_accept_sec_context_sz (GSSX_default_status_sz + \
+                                       GSSX_default_ctx_sz + \
+                                       GSSX_max_output_token_sz + \
+                                       4 + GSSX_max_creds_sz)
+
+#define GSSX_ARG_release_handle_sz 0
+#define GSSX_RES_release_handle_sz 0
+#define GSSX_ARG_get_mic_sz 0
+#define GSSX_RES_get_mic_sz 0
+#define GSSX_ARG_verify_sz 0
+#define GSSX_RES_verify_sz 0
+#define GSSX_ARG_wrap_sz 0
+#define GSSX_RES_wrap_sz 0
+#define GSSX_ARG_unwrap_sz 0
+#define GSSX_RES_unwrap_sz 0
+#define GSSX_ARG_wrap_size_limit_sz 0
+#define GSSX_RES_wrap_size_limit_sz 0
+
+
+
+#endif /* _LINUX_GSS_RPC_XDR_H */
index 74f6d30..1c66a3b 100644 (file)
@@ -48,8 +48,8 @@
 #include <linux/sunrpc/svcauth.h>
 #include <linux/sunrpc/svcauth_gss.h>
 #include <linux/sunrpc/cache.h>
+#include "gss_rpc_upcall.h"
 
-#include "../netns.h"
 
 #ifdef RPC_DEBUG
 # define RPCDBG_FACILITY       RPCDBG_AUTH
@@ -447,17 +447,21 @@ static int rsc_parse(struct cache_detail *cd,
        else {
                int N, i;
 
+               /*
+                * NOTE: we skip uid_valid()/gid_valid() checks here:
+                * instead, * -1 id's are later mapped to the
+                * (export-specific) anonymous id by nfsd_setuser.
+                *
+                * (But supplementary gid's get no such special
+                * treatment so are checked for validity here.)
+                */
                /* uid */
                rsci.cred.cr_uid = make_kuid(&init_user_ns, id);
-               if (!uid_valid(rsci.cred.cr_uid))
-                       goto out;
 
                /* gid */
                if (get_int(&mesg, &id))
                        goto out;
                rsci.cred.cr_gid = make_kgid(&init_user_ns, id);
-               if (!gid_valid(rsci.cred.cr_gid))
-                       goto out;
 
                /* number of additional gid's */
                if (get_int(&mesg, &N))
@@ -493,7 +497,8 @@ static int rsc_parse(struct cache_detail *cd,
                len = qword_get(&mesg, buf, mlen);
                if (len < 0)
                        goto out;
-               status = gss_import_sec_context(buf, len, gm, &rsci.mechctx, GFP_KERNEL);
+               status = gss_import_sec_context(buf, len, gm, &rsci.mechctx,
+                                               NULL, GFP_KERNEL);
                if (status)
                        goto out;
 
@@ -983,13 +988,10 @@ gss_write_init_verf(struct cache_detail *cd, struct svc_rqst *rqstp,
 }
 
 static inline int
-gss_read_verf(struct rpc_gss_wire_cred *gc,
-             struct kvec *argv, __be32 *authp,
-             struct xdr_netobj *in_handle,
-             struct xdr_netobj *in_token)
+gss_read_common_verf(struct rpc_gss_wire_cred *gc,
+                    struct kvec *argv, __be32 *authp,
+                    struct xdr_netobj *in_handle)
 {
-       struct xdr_netobj tmpobj;
-
        /* Read the verifier; should be NULL: */
        *authp = rpc_autherr_badverf;
        if (argv->iov_len < 2 * 4)
@@ -1005,6 +1007,23 @@ gss_read_verf(struct rpc_gss_wire_cred *gc,
        if (dup_netobj(in_handle, &gc->gc_ctx))
                return SVC_CLOSE;
        *authp = rpc_autherr_badverf;
+
+       return 0;
+}
+
+static inline int
+gss_read_verf(struct rpc_gss_wire_cred *gc,
+             struct kvec *argv, __be32 *authp,
+             struct xdr_netobj *in_handle,
+             struct xdr_netobj *in_token)
+{
+       struct xdr_netobj tmpobj;
+       int res;
+
+       res = gss_read_common_verf(gc, argv, authp, in_handle);
+       if (res)
+               return res;
+
        if (svc_safe_getnetobj(argv, &tmpobj)) {
                kfree(in_handle->data);
                return SVC_DENIED;
@@ -1017,6 +1036,40 @@ gss_read_verf(struct rpc_gss_wire_cred *gc,
        return 0;
 }
 
+/* Ok this is really heavily depending on a set of semantics in
+ * how rqstp is set up by svc_recv and pages laid down by the
+ * server when reading a request. We are basically guaranteed that
+ * the token lays all down linearly across a set of pages, starting
+ * at iov_base in rq_arg.head[0] which happens to be the first of a
+ * set of pages stored in rq_pages[].
+ * rq_arg.head[0].iov_base will provide us the page_base to pass
+ * to the upcall.
+ */
+static inline int
+gss_read_proxy_verf(struct svc_rqst *rqstp,
+                   struct rpc_gss_wire_cred *gc, __be32 *authp,
+                   struct xdr_netobj *in_handle,
+                   struct gssp_in_token *in_token)
+{
+       struct kvec *argv = &rqstp->rq_arg.head[0];
+       u32 inlen;
+       int res;
+
+       res = gss_read_common_verf(gc, argv, authp, in_handle);
+       if (res)
+               return res;
+
+       inlen = svc_getnl(argv);
+       if (inlen > (argv->iov_len + rqstp->rq_arg.page_len))
+               return SVC_DENIED;
+
+       in_token->pages = rqstp->rq_pages;
+       in_token->page_base = (ulong)argv->iov_base & ~PAGE_MASK;
+       in_token->page_len = inlen;
+
+       return 0;
+}
+
 static inline int
 gss_write_resv(struct kvec *resv, size_t size_limit,
               struct xdr_netobj *out_handle, struct xdr_netobj *out_token,
@@ -1044,7 +1097,7 @@ gss_write_resv(struct kvec *resv, size_t size_limit,
  * the upcall results are available, write the verifier and result.
  * Otherwise, drop the request pending an answer to the upcall.
  */
-static int svcauth_gss_handle_init(struct svc_rqst *rqstp,
+static int svcauth_gss_legacy_init(struct svc_rqst *rqstp,
                        struct rpc_gss_wire_cred *gc, __be32 *authp)
 {
        struct kvec *argv = &rqstp->rq_arg.head[0];
@@ -1084,6 +1137,278 @@ out:
        return ret;
 }
 
+static int gss_proxy_save_rsc(struct cache_detail *cd,
+                               struct gssp_upcall_data *ud,
+                               uint64_t *handle)
+{
+       struct rsc rsci, *rscp = NULL;
+       static atomic64_t ctxhctr;
+       long long ctxh;
+       struct gss_api_mech *gm = NULL;
+       time_t expiry;
+       int status = -EINVAL;
+
+       memset(&rsci, 0, sizeof(rsci));
+       /* context handle */
+       status = -ENOMEM;
+       /* the handle needs to be just a unique id,
+        * use a static counter */
+       ctxh = atomic64_inc_return(&ctxhctr);
+
+       /* make a copy for the caller */
+       *handle = ctxh;
+
+       /* make a copy for the rsc cache */
+       if (dup_to_netobj(&rsci.handle, (char *)handle, sizeof(uint64_t)))
+               goto out;
+       rscp = rsc_lookup(cd, &rsci);
+       if (!rscp)
+               goto out;
+
+       /* creds */
+       if (!ud->found_creds) {
+               /* userspace seem buggy, we should always get at least a
+                * mapping to nobody */
+               dprintk("RPC:       No creds found, marking Negative!\n");
+               set_bit(CACHE_NEGATIVE, &rsci.h.flags);
+       } else {
+
+               /* steal creds */
+               rsci.cred = ud->creds;
+               memset(&ud->creds, 0, sizeof(struct svc_cred));
+
+               status = -EOPNOTSUPP;
+               /* get mech handle from OID */
+               gm = gss_mech_get_by_OID(&ud->mech_oid);
+               if (!gm)
+                       goto out;
+
+               status = -EINVAL;
+               /* mech-specific data: */
+               status = gss_import_sec_context(ud->out_handle.data,
+                                               ud->out_handle.len,
+                                               gm, &rsci.mechctx,
+                                               &expiry, GFP_KERNEL);
+               if (status)
+                       goto out;
+       }
+
+       rsci.h.expiry_time = expiry;
+       rscp = rsc_update(cd, &rsci, rscp);
+       status = 0;
+out:
+       gss_mech_put(gm);
+       rsc_free(&rsci);
+       if (rscp)
+               cache_put(&rscp->h, cd);
+       else
+               status = -ENOMEM;
+       return status;
+}
+
+static int svcauth_gss_proxy_init(struct svc_rqst *rqstp,
+                       struct rpc_gss_wire_cred *gc, __be32 *authp)
+{
+       struct kvec *resv = &rqstp->rq_res.head[0];
+       struct xdr_netobj cli_handle;
+       struct gssp_upcall_data ud;
+       uint64_t handle;
+       int status;
+       int ret;
+       struct net *net = rqstp->rq_xprt->xpt_net;
+       struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
+
+       memset(&ud, 0, sizeof(ud));
+       ret = gss_read_proxy_verf(rqstp, gc, authp,
+                                 &ud.in_handle, &ud.in_token);
+       if (ret)
+               return ret;
+
+       ret = SVC_CLOSE;
+
+       /* Perform synchronous upcall to gss-proxy */
+       status = gssp_accept_sec_context_upcall(net, &ud);
+       if (status)
+               goto out;
+
+       dprintk("RPC:       svcauth_gss: gss major status = %d\n",
+                       ud.major_status);
+
+       switch (ud.major_status) {
+       case GSS_S_CONTINUE_NEEDED:
+               cli_handle = ud.out_handle;
+               break;
+       case GSS_S_COMPLETE:
+               status = gss_proxy_save_rsc(sn->rsc_cache, &ud, &handle);
+               if (status)
+                       goto out;
+               cli_handle.data = (u8 *)&handle;
+               cli_handle.len = sizeof(handle);
+               break;
+       default:
+               ret = SVC_CLOSE;
+               goto out;
+       }
+
+       /* Got an answer to the upcall; use it: */
+       if (gss_write_init_verf(sn->rsc_cache, rqstp,
+                               &cli_handle, &ud.major_status))
+               goto out;
+       if (gss_write_resv(resv, PAGE_SIZE,
+                          &cli_handle, &ud.out_token,
+                          ud.major_status, ud.minor_status))
+               goto out;
+
+       ret = SVC_COMPLETE;
+out:
+       gssp_free_upcall_data(&ud);
+       return ret;
+}
+
+DEFINE_SPINLOCK(use_gssp_lock);
+
+static bool use_gss_proxy(struct net *net)
+{
+       struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
+
+       if (sn->use_gss_proxy != -1)
+               return sn->use_gss_proxy;
+       spin_lock(&use_gssp_lock);
+       /*
+        * If you wanted gss-proxy, you should have said so before
+        * starting to accept requests:
+        */
+       sn->use_gss_proxy = 0;
+       spin_unlock(&use_gssp_lock);
+       return 0;
+}
+
+static bool set_gss_proxy(struct net *net, int type)
+{
+       struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
+       int ret = 0;
+
+       WARN_ON_ONCE(type != 0 && type != 1);
+       spin_lock(&use_gssp_lock);
+       if (sn->use_gss_proxy == -1 || sn->use_gss_proxy == type)
+               sn->use_gss_proxy = type;
+       else
+               ret = -EBUSY;
+       spin_unlock(&use_gssp_lock);
+       wake_up(&sn->gssp_wq);
+       return ret;
+}
+
+static inline bool gssp_ready(struct sunrpc_net *sn)
+{
+       switch (sn->use_gss_proxy) {
+               case -1:
+                       return false;
+               case 0:
+                       return true;
+               case 1:
+                       return sn->gssp_clnt;
+       }
+       WARN_ON_ONCE(1);
+       return false;
+}
+
+static int wait_for_gss_proxy(struct net *net)
+{
+       struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
+
+       return wait_event_interruptible(sn->gssp_wq, gssp_ready(sn));
+}
+
+#ifdef CONFIG_PROC_FS
+
+static ssize_t write_gssp(struct file *file, const char __user *buf,
+                        size_t count, loff_t *ppos)
+{
+       struct net *net = PDE(file->f_path.dentry->d_inode)->data;
+       char tbuf[20];
+       unsigned long i;
+       int res;
+
+       if (*ppos || count > sizeof(tbuf)-1)
+               return -EINVAL;
+       if (copy_from_user(tbuf, buf, count))
+               return -EFAULT;
+
+       tbuf[count] = 0;
+       res = kstrtoul(tbuf, 0, &i);
+       if (res)
+               return res;
+       if (i != 1)
+               return -EINVAL;
+       res = set_gss_proxy(net, 1);
+       if (res)
+               return res;
+       res = set_gssp_clnt(net);
+       if (res)
+               return res;
+       return count;
+}
+
+static ssize_t read_gssp(struct file *file, char __user *buf,
+                        size_t count, loff_t *ppos)
+{
+       struct net *net = PDE(file->f_path.dentry->d_inode)->data;
+       unsigned long p = *ppos;
+       char tbuf[10];
+       size_t len;
+       int ret;
+
+       ret = wait_for_gss_proxy(net);
+       if (ret)
+               return ret;
+
+       snprintf(tbuf, sizeof(tbuf), "%d\n", use_gss_proxy(net));
+       len = strlen(tbuf);
+       if (p >= len)
+               return 0;
+       len -= p;
+       if (len > count)
+               len = count;
+       if (copy_to_user(buf, (void *)(tbuf+p), len))
+               return -EFAULT;
+       *ppos += len;
+       return len;
+}
+
+static const struct file_operations use_gss_proxy_ops = {
+       .open = nonseekable_open,
+       .write = write_gssp,
+       .read = read_gssp,
+};
+
+static int create_use_gss_proxy_proc_entry(struct net *net)
+{
+       struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
+       struct proc_dir_entry **p = &sn->use_gssp_proc;
+
+       sn->use_gss_proxy = -1;
+       *p = proc_create_data("use-gss-proxy", S_IFREG|S_IRUSR|S_IWUSR,
+                             sn->proc_net_rpc,
+                             &use_gss_proxy_ops, net);
+       if (!*p)
+               return -ENOMEM;
+       init_gssp_clnt(sn);
+       return 0;
+}
+
+static void destroy_use_gss_proxy_proc_entry(struct net *net)
+{
+       struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
+
+       if (sn->use_gssp_proc) {
+               remove_proc_entry("use-gss-proxy", sn->proc_net_rpc); 
+               clear_gssp_clnt(sn);
+       }
+}
+
+#endif /* CONFIG_PROC_FS */
+
 /*
  * Accept an rpcsec packet.
  * If context establishment, punt to user space
@@ -1150,7 +1475,10 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
        switch (gc->gc_proc) {
        case RPC_GSS_PROC_INIT:
        case RPC_GSS_PROC_CONTINUE_INIT:
-               return svcauth_gss_handle_init(rqstp, gc, authp);
+               if (use_gss_proxy(SVC_NET(rqstp)))
+                       return svcauth_gss_proxy_init(rqstp, gc, authp);
+               else
+                       return svcauth_gss_legacy_init(rqstp, gc, authp);
        case RPC_GSS_PROC_DATA:
        case RPC_GSS_PROC_DESTROY:
                /* Look up the context, and check the verifier: */
@@ -1527,7 +1855,12 @@ gss_svc_init_net(struct net *net)
        rv = rsi_cache_create_net(net);
        if (rv)
                goto out1;
+       rv = create_use_gss_proxy_proc_entry(net);
+       if (rv)
+               goto out2;
        return 0;
+out2:
+       destroy_use_gss_proxy_proc_entry(net);
 out1:
        rsc_cache_destroy_net(net);
        return rv;
@@ -1536,6 +1869,7 @@ out1:
 void
 gss_svc_shutdown_net(struct net *net)
 {
+       destroy_use_gss_proxy_proc_entry(net);
        rsi_cache_destroy_net(net);
        rsc_cache_destroy_net(net);
 }
index 25d58e7..1d3c514 100644 (file)
@@ -986,8 +986,10 @@ static int cache_open(struct inode *inode, struct file *filp,
        nonseekable_open(inode, filp);
        if (filp->f_mode & FMODE_READ) {
                rp = kmalloc(sizeof(*rp), GFP_KERNEL);
-               if (!rp)
+               if (!rp) {
+                       module_put(cd->owner);
                        return -ENOMEM;
+               }
                rp->offset = 0;
                rp->q.reader = 1;
                atomic_inc(&cd->readers);
index d259fa9..3f7930f 100644 (file)
@@ -413,6 +413,8 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args)
 
        if (args->flags & RPC_CLNT_CREATE_INFINITE_SLOTS)
                xprtargs.flags |= XPRT_CREATE_INFINITE_SLOTS;
+       if (args->flags & RPC_CLNT_CREATE_NO_IDLE_TIMEOUT)
+               xprtargs.flags |= XPRT_CREATE_NO_IDLE_TIMEOUT;
        /*
         * If the caller chooses not to specify a hostname, whip
         * up a string representation of the passed-in address.
@@ -681,6 +683,7 @@ rpc_release_client(struct rpc_clnt *clnt)
        if (atomic_dec_and_test(&clnt->cl_count))
                rpc_free_auth(clnt);
 }
+EXPORT_SYMBOL_GPL(rpc_release_client);
 
 /**
  * rpc_bind_new_program - bind a new RPC program to an existing client
index ce7bd44..7111a4c 100644 (file)
@@ -23,6 +23,12 @@ struct sunrpc_net {
        struct rpc_clnt *rpcb_local_clnt4;
        spinlock_t rpcb_clnt_lock;
        unsigned int rpcb_users;
+
+       struct mutex gssp_lock;
+       wait_queue_head_t gssp_wq;
+       struct rpc_clnt *gssp_clnt;
+       int use_gss_proxy;
+       struct proc_dir_entry *use_gssp_proc;
 };
 
 extern int sunrpc_net_id;
index 7b9b402..a9129f8 100644 (file)
@@ -1174,6 +1174,8 @@ static struct file_system_type rpc_pipe_fs_type = {
        .mount          = rpc_mount,
        .kill_sb        = rpc_kill_sb,
 };
+MODULE_ALIAS_FS("rpc_pipefs");
+MODULE_ALIAS("rpc_pipefs");
 
 static void
 init_once(void *foo)
@@ -1218,6 +1220,3 @@ void unregister_rpc_pipefs(void)
        kmem_cache_destroy(rpc_inode_cachep);
        unregister_filesystem(&rpc_pipe_fs_type);
 }
-
-/* Make 'mount -t rpc_pipefs ...' autoload this module. */
-MODULE_ALIAS("rpc_pipefs");
index 745fca3..095363e 100644 (file)
@@ -1300,6 +1300,8 @@ found:
                                -PTR_ERR(xprt));
                goto out;
        }
+       if (args->flags & XPRT_CREATE_NO_IDLE_TIMEOUT)
+               xprt->idle_timeout = 0;
        INIT_WORK(&xprt->task_cleanup, xprt_autoclose);
        if (xprt_has_timer(xprt))
                setup_timer(&xprt->timer, xprt_init_autodisconnect,
index 726e702..ffd5034 100644 (file)
@@ -849,6 +849,14 @@ static void xs_tcp_close(struct rpc_xprt *xprt)
                xs_tcp_shutdown(xprt);
 }
 
+static void xs_local_destroy(struct rpc_xprt *xprt)
+{
+       xs_close(xprt);
+       xs_free_peer_addresses(xprt);
+       xprt_free(xprt);
+       module_put(THIS_MODULE);
+}
+
 /**
  * xs_destroy - prepare to shutdown a transport
  * @xprt: doomed transport
@@ -862,10 +870,7 @@ static void xs_destroy(struct rpc_xprt *xprt)
 
        cancel_delayed_work_sync(&transport->connect_worker);
 
-       xs_close(xprt);
-       xs_free_peer_addresses(xprt);
-       xprt_free(xprt);
-       module_put(THIS_MODULE);
+       xs_local_destroy(xprt);
 }
 
 static inline struct rpc_xprt *xprt_from_sock(struct sock *sk)
@@ -2482,7 +2487,7 @@ static struct rpc_xprt_ops xs_local_ops = {
        .send_request           = xs_local_send_request,
        .set_retrans_timeout    = xprt_set_retrans_timeout_def,
        .close                  = xs_close,
-       .destroy                = xs_destroy,
+       .destroy                = xs_local_destroy,
        .print_stats            = xs_local_print_stats,
 };
 
@@ -2650,6 +2655,9 @@ static struct rpc_xprt *xs_setup_local(struct xprt_create *args)
                }
                xprt_set_bound(xprt);
                xs_format_peer_addresses(xprt, "local", RPCBIND_NETID_LOCAL);
+               ret = ERR_PTR(xs_local_setup_socket(transport));
+               if (ret)
+                       goto out_err;
                break;
        default:
                ret = ERR_PTR(-EAFNOSUPPORT);
index 5ffff03..ea4155f 100644 (file)
@@ -367,8 +367,7 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
        rdev->wiphy.rts_threshold = (u32) -1;
        rdev->wiphy.coverage_class = 0;
 
-       rdev->wiphy.features = NL80211_FEATURE_SCAN_FLUSH |
-                              NL80211_FEATURE_ADVERTISE_CHAN_LIMITS;
+       rdev->wiphy.features = NL80211_FEATURE_SCAN_FLUSH;
 
        return &rdev->wiphy;
 }
index 35545cc..d44ab21 100644 (file)
@@ -554,27 +554,8 @@ static int nl80211_msg_put_channel(struct sk_buff *msg,
        if ((chan->flags & IEEE80211_CHAN_NO_IBSS) &&
            nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_IBSS))
                goto nla_put_failure;
-       if (chan->flags & IEEE80211_CHAN_RADAR) {
-               u32 time = elapsed_jiffies_msecs(chan->dfs_state_entered);
-               if (nla_put_flag(msg, NL80211_FREQUENCY_ATTR_RADAR))
-                       goto nla_put_failure;
-               if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_STATE,
-                               chan->dfs_state))
-                       goto nla_put_failure;
-               if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_TIME, time))
-                       goto nla_put_failure;
-       }
-       if ((chan->flags & IEEE80211_CHAN_NO_HT40MINUS) &&
-           nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HT40_MINUS))
-               goto nla_put_failure;
-       if ((chan->flags & IEEE80211_CHAN_NO_HT40PLUS) &&
-           nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HT40_PLUS))
-               goto nla_put_failure;
-       if ((chan->flags & IEEE80211_CHAN_NO_80MHZ) &&
-           nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_80MHZ))
-               goto nla_put_failure;
-       if ((chan->flags & IEEE80211_CHAN_NO_160MHZ) &&
-           nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_160MHZ))
+       if ((chan->flags & IEEE80211_CHAN_RADAR) &&
+           nla_put_flag(msg, NL80211_FREQUENCY_ATTR_RADAR))
                goto nla_put_failure;
 
        if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER,
@@ -900,9 +881,6 @@ static int nl80211_put_iface_combinations(struct wiphy *wiphy,
                    nla_put_u32(msg, NL80211_IFACE_COMB_MAXNUM,
                                c->max_interfaces))
                        goto nla_put_failure;
-               if (nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS,
-                               c->radar_detect_widths))
-                       goto nla_put_failure;
 
                nla_nest_end(msg, nl_combi);
        }
@@ -914,48 +892,6 @@ nla_put_failure:
        return -ENOBUFS;
 }
 
-#ifdef CONFIG_PM
-static int nl80211_send_wowlan_tcp_caps(struct cfg80211_registered_device *rdev,
-                                       struct sk_buff *msg)
-{
-       const struct wiphy_wowlan_tcp_support *tcp = rdev->wiphy.wowlan.tcp;
-       struct nlattr *nl_tcp;
-
-       if (!tcp)
-               return 0;
-
-       nl_tcp = nla_nest_start(msg, NL80211_WOWLAN_TRIG_TCP_CONNECTION);
-       if (!nl_tcp)
-               return -ENOBUFS;
-
-       if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD,
-                       tcp->data_payload_max))
-               return -ENOBUFS;
-
-       if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD,
-                       tcp->data_payload_max))
-               return -ENOBUFS;
-
-       if (tcp->seq && nla_put_flag(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ))
-               return -ENOBUFS;
-
-       if (tcp->tok && nla_put(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN,
-                               sizeof(*tcp->tok), tcp->tok))
-               return -ENOBUFS;
-
-       if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_INTERVAL,
-                       tcp->data_interval_max))
-               return -ENOBUFS;
-
-       if (nla_put_u32(msg, NL80211_WOWLAN_TCP_WAKE_PAYLOAD,
-                       tcp->wake_payload_max))
-               return -ENOBUFS;
-
-       nla_nest_end(msg, nl_tcp);
-       return 0;
-}
-#endif
-
 static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flags,
                              struct cfg80211_registered_device *dev)
 {
@@ -1330,9 +1266,6 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flag
                                goto nla_put_failure;
                }
 
-               if (nl80211_send_wowlan_tcp_caps(dev, msg))
-                       goto nla_put_failure;
-
                nla_nest_end(msg, nl_wowlan);
        }
 #endif
@@ -1365,15 +1298,6 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flag
                        dev->wiphy.max_acl_mac_addrs))
                goto nla_put_failure;
 
-       if (dev->wiphy.extended_capabilities &&
-           (nla_put(msg, NL80211_ATTR_EXT_CAPA,
-                    dev->wiphy.extended_capabilities_len,
-                    dev->wiphy.extended_capabilities) ||
-            nla_put(msg, NL80211_ATTR_EXT_CAPA_MASK,
-                    dev->wiphy.extended_capabilities_len,
-                    dev->wiphy.extended_capabilities_mask)))
-               goto nla_put_failure;
-
        return genlmsg_end(msg, hdr);
 
  nla_put_failure:
@@ -1383,7 +1307,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flag
 
 static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
 {
-       int idx = 0;
+       int idx = 0, ret;
        int start = cb->args[0];
        struct cfg80211_registered_device *dev;
 
@@ -1393,9 +1317,29 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
                        continue;
                if (++idx <= start)
                        continue;
-               if (nl80211_send_wiphy(skb, NETLINK_CB(cb->skb).portid,
-                                      cb->nlh->nlmsg_seq, NLM_F_MULTI,
-                                      dev) < 0) {
+               ret = nl80211_send_wiphy(skb, NETLINK_CB(cb->skb).portid,
+                                        cb->nlh->nlmsg_seq, NLM_F_MULTI,
+                                        dev);
+               if (ret < 0) {
+                       /*
+                        * If sending the wiphy data didn't fit (ENOBUFS or
+                        * EMSGSIZE returned), this SKB is still empty (so
+                        * it's not too big because another wiphy dataset is
+                        * already in the skb) and we've not tried to adjust
+                        * the dump allocation yet ... then adjust the alloc
+                        * size to be bigger, and return 1 but with the empty
+                        * skb. This results in an empty message being RX'ed
+                        * in userspace, but that is ignored.
+                        *
+                        * We can then retry with the larger buffer.
+                        */
+                       if ((ret == -ENOBUFS || ret == -EMSGSIZE) &&
+                           !skb->len &&
+                           cb->min_dump_alloc < 4096) {
+                               cb->min_dump_alloc = 4096;
+                               mutex_unlock(&cfg80211_mutex);
+                               return 1;
+                       }
                        idx--;
                        break;
                }
@@ -1412,7 +1356,7 @@ static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info)
        struct sk_buff *msg;
        struct cfg80211_registered_device *dev = info->user_ptr[0];
 
-       msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+       msg = nlmsg_new(4096, GFP_KERNEL);
        if (!msg)
                return -ENOMEM;
 
index 25f216a..477d137 100644 (file)
@@ -14,7 +14,7 @@ kbuild-file := $(srctree)/$(obj)/Kbuild
 include $(kbuild-file)
 
 # called may set destination dir (when installing to asm/)
-_dst := $(or $(destination-y),$(dst),$(obj))
+_dst := $(if $(destination-y),$(destination-y),$(if $(dst),$(dst),$(obj)))
 
 old-kbuild-file := $(srctree)/$(subst uapi/,,$(obj))/Kbuild
 ifneq ($(wildcard $(old-kbuild-file)),)
@@ -48,13 +48,14 @@ all-files     := $(header-y) $(genhdr-y) $(wrapper-files)
 output-files  := $(addprefix $(installdir)/, $(all-files))
 
 input-files   := $(foreach hdr, $(header-y), \
-                  $(or \
+                  $(if $(wildcard $(srcdir)/$(hdr)), \
                        $(wildcard $(srcdir)/$(hdr)), \
-                       $(wildcard $(oldsrcdir)/$(hdr)), \
-                       $(error Missing UAPI file $(srcdir)/$(hdr)) \
+                       $(if $(wildcard $(oldsrcdir)/$(hdr)), \
+                               $(wildcard $(oldsrcdir)/$(hdr)), \
+                               $(error Missing UAPI file $(srcdir)/$(hdr))) \
                   )) \
                 $(foreach hdr, $(genhdr-y), \
-                  $(or \
+                  $(if $(wildcard $(gendir)/$(hdr)), \
                        $(wildcard $(gendir)/$(hdr)), \
                        $(error Missing generated UAPI file $(gendir)/$(hdr)) \
                   ))
index 1c26176..d65fa7f 100644 (file)
@@ -40,12 +40,12 @@ static long compat_keyctl_instantiate_key_iov(
                                           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;
index 58dfe08..42defae 100644 (file)
@@ -57,7 +57,7 @@ int install_user_keyrings(void)
 
        kenter("%p{%u}", user, uid);
 
-       if (user->uid_keyring) {
+       if (user->uid_keyring && user->session_keyring) {
                kleave(" = 0 [exist]");
                return 0;
        }
@@ -839,7 +839,7 @@ void key_change_session_keyring(struct callback_head *twork)
        new-> sgid      = old-> sgid;
        new->fsgid      = old->fsgid;
        new->user       = get_uid(old->user);
-       new->user_ns    = get_user_ns(new->user_ns);
+       new->user_ns    = get_user_ns(old->user_ns);
        new->group_info = get_group_info(old->group_info);
 
        new->securebits = old->securebits;
index 066f5f3..c390886 100644 (file)
@@ -285,7 +285,12 @@ local_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev
 static int
 note_on_event(struct seq_oss_devinfo *dp, int dev, int ch, int note, int vel, struct snd_seq_event *ev)
 {
-       struct seq_oss_synthinfo *info = &dp->synths[dev];
+       struct seq_oss_synthinfo *info;
+
+       if (!snd_seq_oss_synth_is_valid(dp, dev))
+               return -ENXIO;
+
+       info = &dp->synths[dev];
        switch (info->arg.event_passing) {
        case SNDRV_SEQ_OSS_PROCESS_EVENTS:
                if (! info->ch || ch < 0 || ch >= info->nr_voices) {
@@ -340,7 +345,12 @@ note_on_event(struct seq_oss_devinfo *dp, int dev, int ch, int note, int vel, st
 static int
 note_off_event(struct seq_oss_devinfo *dp, int dev, int ch, int note, int vel, struct snd_seq_event *ev)
 {
-       struct seq_oss_synthinfo *info = &dp->synths[dev];
+       struct seq_oss_synthinfo *info;
+
+       if (!snd_seq_oss_synth_is_valid(dp, dev))
+               return -ENXIO;
+
+       info = &dp->synths[dev];
        switch (info->arg.event_passing) {
        case SNDRV_SEQ_OSS_PROCESS_EVENTS:
                if (! info->ch || ch < 0 || ch >= info->nr_voices) {
index 160b1bd..24d44b2 100644 (file)
@@ -290,10 +290,10 @@ int snd_seq_timer_open(struct snd_seq_queue *q)
                        tid.device = SNDRV_TIMER_GLOBAL_SYSTEM;
                        err = snd_timer_open(&t, str, &tid, q->queue);
                }
-               if (err < 0) {
-                       snd_printk(KERN_ERR "seq fatal error: cannot create timer (%i)\n", err);
-                       return err;
-               }
+       }
+       if (err < 0) {
+               snd_printk(KERN_ERR "seq fatal error: cannot create timer (%i)\n", err);
+               return err;
        }
        t->callback = snd_seq_timer_interrupt;
        t->callback_data = q;
index 8575861..0097f36 100644 (file)
@@ -213,7 +213,10 @@ static int slave_put(struct snd_kcontrol *kcontrol,
        }
        if (!changed)
                return 0;
-       return slave_put_val(slave, ucontrol);
+       err = slave_put_val(slave, ucontrol);
+       if (err < 0)
+               return err;
+       return 1;
 }
 
 static int slave_tlv_cmd(struct snd_kcontrol *kcontrol,
index 30bcfe4..4ff60a6 100644 (file)
@@ -545,6 +545,9 @@ static void seq_chn_common_event(unsigned char *event_rec)
                case MIDI_PGM_CHANGE:
                        if (seq_mode == SEQ_2)
                        {
+                               if (chn > 15)
+                                       break;
+
                                synth_devs[dev]->chn_info[chn].pgm_num = p1;
                                if ((int) dev >= num_synths)
                                        synth_devs[dev]->set_instr(dev, chn, p1);
@@ -596,6 +599,9 @@ static void seq_chn_common_event(unsigned char *event_rec)
                case MIDI_PITCH_BEND:
                        if (seq_mode == SEQ_2)
                        {
+                               if (chn > 15)
+                                       break;
+
                                synth_devs[dev]->chn_info[chn].bender_value = w14;
 
                                if ((int) dev < num_synths)
index 3536b07..0aabfed 100644 (file)
@@ -2549,7 +2549,7 @@ static int snd_asihpi_sampleclock_add(struct snd_card_asihpi *asihpi,
 
 static int snd_card_asihpi_mixer_new(struct snd_card_asihpi *asihpi)
 {
-       struct snd_card *card = asihpi->card;
+       struct snd_card *card;
        unsigned int idx = 0;
        unsigned int subindex = 0;
        int err;
@@ -2557,6 +2557,7 @@ static int snd_card_asihpi_mixer_new(struct snd_card_asihpi *asihpi)
 
        if (snd_BUG_ON(!asihpi))
                return -EINVAL;
+       card = asihpi->card;
        strcpy(card->mixername, "Asihpi Mixer");
 
        err =
index 04b5738..a9ebcf9 100644 (file)
@@ -494,7 +494,7 @@ static unsigned int get_num_conns(struct hda_codec *codec, hda_nid_t nid)
 
 int snd_hda_get_num_raw_conns(struct hda_codec *codec, hda_nid_t nid)
 {
-       return get_num_conns(codec, nid) & AC_CLIST_LENGTH;
+       return snd_hda_get_raw_connections(codec, nid, NULL, 0);
 }
 
 /**
@@ -517,9 +517,6 @@ int snd_hda_get_raw_connections(struct hda_codec *codec, hda_nid_t nid,
        hda_nid_t prev_nid;
        int null_count = 0;
 
-       if (snd_BUG_ON(!conn_list || max_conns <= 0))
-               return -EINVAL;
-
        parm = get_num_conns(codec, nid);
        if (!parm)
                return 0;
@@ -545,7 +542,8 @@ int snd_hda_get_raw_connections(struct hda_codec *codec, hda_nid_t nid,
                                          AC_VERB_GET_CONNECT_LIST, 0);
                if (parm == -1 && codec->bus->rirb_error)
                        return -EIO;
-               conn_list[0] = parm & mask;
+               if (conn_list)
+                       conn_list[0] = parm & mask;
                return 1;
        }
 
@@ -580,14 +578,20 @@ int snd_hda_get_raw_connections(struct hda_codec *codec, hda_nid_t nid,
                                continue;
                        }
                        for (n = prev_nid + 1; n <= val; n++) {
+                               if (conn_list) {
+                                       if (conns >= max_conns)
+                                               return -ENOSPC;
+                                       conn_list[conns] = n;
+                               }
+                               conns++;
+                       }
+               } else {
+                       if (conn_list) {
                                if (conns >= max_conns)
                                        return -ENOSPC;
-                               conn_list[conns++] = n;
+                               conn_list[conns] = val;
                        }
-               } else {
-                       if (conns >= max_conns)
-                               return -ENOSPC;
-                       conn_list[conns++] = val;
+                       conns++;
                }
                prev_nid = val;
        }
@@ -3334,6 +3338,8 @@ int snd_hda_create_dig_out_ctls(struct hda_codec *codec,
                return -EBUSY;
        }
        spdif = snd_array_new(&codec->spdif_out);
+       if (!spdif)
+               return -ENOMEM;
        for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) {
                kctl = snd_ctl_new1(dig_mix, codec);
                if (!kctl)
@@ -3431,11 +3437,16 @@ static struct snd_kcontrol_new spdif_share_sw = {
 int snd_hda_create_spdif_share_sw(struct hda_codec *codec,
                                  struct hda_multi_out *mout)
 {
+       struct snd_kcontrol *kctl;
+
        if (!mout->dig_out_nid)
                return 0;
+
+       kctl = snd_ctl_new1(&spdif_share_sw, mout);
+       if (!kctl)
+               return -ENOMEM;
        /* ATTENTION: here mout is passed as private_data, instead of codec */
-       return snd_hda_ctl_add(codec, mout->dig_out_nid,
-                             snd_ctl_new1(&spdif_share_sw, mout));
+       return snd_hda_ctl_add(codec, mout->dig_out_nid, kctl);
 }
 EXPORT_SYMBOL_HDA(snd_hda_create_spdif_share_sw);
 
index db02c1e..0792b57 100644 (file)
@@ -2298,6 +2298,11 @@ static int dspxfr_one_seg(struct hda_codec *codec,
        hda_frame_size_words = ((sample_rate_div == 0) ? 0 :
                        (num_chans * sample_rate_mul / sample_rate_div));
 
+       if (hda_frame_size_words == 0) {
+               snd_printdd(KERN_ERR "frmsz zero\n");
+               return -EINVAL;
+       }
+
        buffer_size_words = min(buffer_size_words,
                                (unsigned int)(UC_RANGE(chip_addx, 1) ?
                                65536 : 32768));
@@ -2308,8 +2313,7 @@ static int dspxfr_one_seg(struct hda_codec *codec,
                   chip_addx, hda_frame_size_words, num_chans,
                   sample_rate_mul, sample_rate_div, buffer_size_words);
 
-       if ((buffer_addx == NULL) || (hda_frame_size_words == 0) ||
-           (buffer_size_words < hda_frame_size_words)) {
+       if (buffer_size_words < hda_frame_size_words) {
                snd_printdd(KERN_ERR "dspxfr_one_seg:failed\n");
                return -EINVAL;
        }
@@ -3235,7 +3239,7 @@ static int ca0132_set_vipsource(struct hda_codec *codec, int val)
        struct ca0132_spec *spec = codec->spec;
        unsigned int tmp;
 
-       if (!dspload_is_loaded(codec))
+       if (spec->dsp_state != DSP_DOWNLOADED)
                return 0;
 
        /* if CrystalVoice if off, vipsource should be 0 */
@@ -4263,11 +4267,12 @@ static void ca0132_refresh_widget_caps(struct hda_codec *codec)
  */
 static void ca0132_setup_defaults(struct hda_codec *codec)
 {
+       struct ca0132_spec *spec = codec->spec;
        unsigned int tmp;
        int num_fx;
        int idx, i;
 
-       if (!dspload_is_loaded(codec))
+       if (spec->dsp_state != DSP_DOWNLOADED)
                return;
 
        /* out, in effects + voicefx */
@@ -4347,12 +4352,16 @@ static bool ca0132_download_dsp_images(struct hda_codec *codec)
                return false;
 
        dsp_os_image = (struct dsp_image_seg *)(fw_entry->data);
-       dspload_image(codec, dsp_os_image, 0, 0, true, 0);
+       if (dspload_image(codec, dsp_os_image, 0, 0, true, 0)) {
+               pr_err("ca0132 dspload_image failed.\n");
+               goto exit_download;
+       }
+
        dsp_loaded = dspload_wait_loaded(codec);
 
+exit_download:
        release_firmware(fw_entry);
 
-
        return dsp_loaded;
 }
 
@@ -4363,16 +4372,13 @@ static void ca0132_download_dsp(struct hda_codec *codec)
 #ifndef CONFIG_SND_HDA_CODEC_CA0132_DSP
        return; /* NOP */
 #endif
-       spec->dsp_state = DSP_DOWNLOAD_INIT;
 
-       if (spec->dsp_state == DSP_DOWNLOAD_INIT) {
-               chipio_enable_clocks(codec);
-               spec->dsp_state = DSP_DOWNLOADING;
-               if (!ca0132_download_dsp_images(codec))
-                       spec->dsp_state = DSP_DOWNLOAD_FAILED;
-               else
-                       spec->dsp_state = DSP_DOWNLOADED;
-       }
+       chipio_enable_clocks(codec);
+       spec->dsp_state = DSP_DOWNLOADING;
+       if (!ca0132_download_dsp_images(codec))
+               spec->dsp_state = DSP_DOWNLOAD_FAILED;
+       else
+               spec->dsp_state = DSP_DOWNLOADED;
 
        if (spec->dsp_state == DSP_DOWNLOADED)
                ca0132_set_dsp_msr(codec, true);
index 72ebb8a..60d08f6 100644 (file)
@@ -506,6 +506,8 @@ static int patch_cs420x(struct hda_codec *codec)
        if (!spec)
                return -ENOMEM;
 
+       spec->gen.automute_hook = cs_automute;
+
        snd_hda_pick_fixup(codec, cs420x_models, cs420x_fixup_tbl,
                           cs420x_fixups);
        snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
@@ -893,6 +895,8 @@ static int patch_cs4210(struct hda_codec *codec)
        if (!spec)
                return -ENOMEM;
 
+       spec->gen.automute_hook = cs_automute;
+
        snd_hda_pick_fixup(codec, cs421x_models, cs421x_fixup_tbl,
                           cs421x_fixups);
        snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
index 2d4237b..563c24d 100644 (file)
@@ -3163,6 +3163,7 @@ static int patch_alc269(struct hda_codec *codec)
        case 0x10ec0290:
                spec->codec_variant = ALC269_TYPE_ALC280;
                break;
+       case 0x10ec0233:
        case 0x10ec0282:
        case 0x10ec0283:
                spec->codec_variant = ALC269_TYPE_ALC282;
@@ -3862,6 +3863,7 @@ static int patch_alc680(struct hda_codec *codec)
  */
 static const struct hda_codec_preset snd_hda_preset_realtek[] = {
        { .id = 0x10ec0221, .name = "ALC221", .patch = patch_alc269 },
+       { .id = 0x10ec0233, .name = "ALC233", .patch = patch_alc269 },
        { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 },
        { .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 },
        { .id = 0x10ec0267, .name = "ALC267", .patch = patch_alc268 },
index 83d5335..dafe04a 100644 (file)
@@ -815,6 +815,29 @@ static int find_mute_led_cfg(struct hda_codec *codec, int default_polarity)
        return 0;
 }
 
+/* check whether a built-in speaker is included in parsed pins */
+static bool has_builtin_speaker(struct hda_codec *codec)
+{
+       struct sigmatel_spec *spec = codec->spec;
+       hda_nid_t *nid_pin;
+       int nids, i;
+
+       if (spec->gen.autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT) {
+               nid_pin = spec->gen.autocfg.line_out_pins;
+               nids = spec->gen.autocfg.line_outs;
+       } else {
+               nid_pin = spec->gen.autocfg.speaker_pins;
+               nids = spec->gen.autocfg.speaker_outs;
+       }
+
+       for (i = 0; i < nids; i++) {
+               unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid_pin[i]);
+               if (snd_hda_get_input_pin_attr(def_conf) == INPUT_PIN_ATTR_INT)
+                       return true;
+       }
+       return false;
+}
+
 /*
  * PC beep controls
  */
@@ -3890,6 +3913,12 @@ static int patch_stac92hd73xx(struct hda_codec *codec)
                return err;
        }
 
+       /* Don't GPIO-mute speakers if there are no internal speakers, because
+        * the GPIO might be necessary for Headphone
+        */
+       if (spec->eapd_switch && !has_builtin_speaker(codec))
+               spec->eapd_switch = 0;
+
        codec->proc_widget_hook = stac92hd7x_proc_hook;
 
        snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
index 2ffdc35..806407a 100644 (file)
@@ -2594,6 +2594,8 @@ static int snd_ice1712_create(struct snd_card *card,
        snd_ice1712_proc_init(ice);
        synchronize_irq(pci->irq);
 
+       card->private_data = ice;
+
        err = pci_request_regions(pci, "ICE1712");
        if (err < 0) {
                kfree(ice);
index b8d461d..b82bbf5 100644 (file)
@@ -573,6 +573,13 @@ static const struct reg_default wm5102_sysclk_reva_patch[] = {
        { 0x025e, 0x0112 },
 };
 
+static const struct reg_default wm5102_sysclk_revb_patch[] = {
+       { 0x3081, 0x08FE },
+       { 0x3083, 0x00ED },
+       { 0x30C1, 0x08FE },
+       { 0x30C3, 0x00ED },
+};
+
 static int wm5102_sysclk_ev(struct snd_soc_dapm_widget *w,
                            struct snd_kcontrol *kcontrol, int event)
 {
@@ -587,6 +594,10 @@ static int wm5102_sysclk_ev(struct snd_soc_dapm_widget *w,
                patch = wm5102_sysclk_reva_patch;
                patch_size = ARRAY_SIZE(wm5102_sysclk_reva_patch);
                break;
+       default:
+               patch = wm5102_sysclk_revb_patch;
+               patch_size = ARRAY_SIZE(wm5102_sysclk_revb_patch);
+               break;
        }
 
        switch (event) {
@@ -755,7 +766,7 @@ SOC_SINGLE("SPKDAT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_5L,
 
 SOC_DOUBLE_R("HPOUT1 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_1L,
             ARIZONA_DAC_DIGITAL_VOLUME_1R, ARIZONA_OUT1L_MUTE_SHIFT, 1, 1),
-SOC_DOUBLE_R("OUT2 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_2L,
+SOC_DOUBLE_R("HPOUT2 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_2L,
             ARIZONA_DAC_DIGITAL_VOLUME_2R, ARIZONA_OUT2L_MUTE_SHIFT, 1, 1),
 SOC_SINGLE("EPOUT Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_3L,
           ARIZONA_OUT3L_MUTE_SHIFT, 1, 1),
@@ -767,7 +778,7 @@ SOC_DOUBLE_R("SPKDAT1 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_5L,
 SOC_DOUBLE_R_TLV("HPOUT1 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_1L,
                 ARIZONA_DAC_DIGITAL_VOLUME_1R, ARIZONA_OUT1L_VOL_SHIFT,
                 0xbf, 0, digital_tlv),
-SOC_DOUBLE_R_TLV("OUT2 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_2L,
+SOC_DOUBLE_R_TLV("HPOUT2 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_2L,
                 ARIZONA_DAC_DIGITAL_VOLUME_2R, ARIZONA_OUT2L_VOL_SHIFT,
                 0xbf, 0, digital_tlv),
 SOC_SINGLE_TLV("EPOUT Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_3L,
index cd17b47..cdeb301 100644 (file)
@@ -213,9 +213,9 @@ ARIZONA_MIXER_CONTROLS("SPKDAT2R", ARIZONA_OUT6RMIX_INPUT_1_SOURCE),
 
 SOC_SINGLE("HPOUT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_1L,
           ARIZONA_OUT1_OSR_SHIFT, 1, 0),
-SOC_SINGLE("OUT2 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_2L,
+SOC_SINGLE("HPOUT2 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_2L,
           ARIZONA_OUT2_OSR_SHIFT, 1, 0),
-SOC_SINGLE("OUT3 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_3L,
+SOC_SINGLE("HPOUT3 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_3L,
           ARIZONA_OUT3_OSR_SHIFT, 1, 0),
 SOC_SINGLE("Speaker High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_4L,
           ARIZONA_OUT4_OSR_SHIFT, 1, 0),
@@ -226,9 +226,9 @@ SOC_SINGLE("SPKDAT2 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_6L,
 
 SOC_DOUBLE_R("HPOUT1 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_1L,
             ARIZONA_DAC_DIGITAL_VOLUME_1R, ARIZONA_OUT1L_MUTE_SHIFT, 1, 1),
-SOC_DOUBLE_R("OUT2 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_2L,
+SOC_DOUBLE_R("HPOUT2 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_2L,
             ARIZONA_DAC_DIGITAL_VOLUME_2R, ARIZONA_OUT2L_MUTE_SHIFT, 1, 1),
-SOC_DOUBLE_R("OUT3 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_3L,
+SOC_DOUBLE_R("HPOUT3 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_3L,
             ARIZONA_DAC_DIGITAL_VOLUME_3R, ARIZONA_OUT3L_MUTE_SHIFT, 1, 1),
 SOC_DOUBLE_R("Speaker Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_4L,
             ARIZONA_DAC_DIGITAL_VOLUME_4R, ARIZONA_OUT4L_MUTE_SHIFT, 1, 1),
@@ -240,10 +240,10 @@ SOC_DOUBLE_R("SPKDAT2 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_6L,
 SOC_DOUBLE_R_TLV("HPOUT1 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_1L,
                 ARIZONA_DAC_DIGITAL_VOLUME_1R, ARIZONA_OUT1L_VOL_SHIFT,
                 0xbf, 0, digital_tlv),
-SOC_DOUBLE_R_TLV("OUT2 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_2L,
+SOC_DOUBLE_R_TLV("HPOUT2 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_2L,
                 ARIZONA_DAC_DIGITAL_VOLUME_2R, ARIZONA_OUT2L_VOL_SHIFT,
                 0xbf, 0, digital_tlv),
-SOC_DOUBLE_R_TLV("OUT3 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_3L,
+SOC_DOUBLE_R_TLV("HPOUT3 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_3L,
                 ARIZONA_DAC_DIGITAL_VOLUME_3R, ARIZONA_OUT3L_VOL_SHIFT,
                 0xbf, 0, digital_tlv),
 SOC_DOUBLE_R_TLV("Speaker Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_4L,
@@ -260,11 +260,11 @@ SOC_DOUBLE_R_RANGE_TLV("HPOUT1 Volume", ARIZONA_OUTPUT_PATH_CONFIG_1L,
                       ARIZONA_OUTPUT_PATH_CONFIG_1R,
                       ARIZONA_OUT1L_PGA_VOL_SHIFT,
                       0x34, 0x40, 0, ana_tlv),
-SOC_DOUBLE_R_RANGE_TLV("OUT2 Volume", ARIZONA_OUTPUT_PATH_CONFIG_2L,
+SOC_DOUBLE_R_RANGE_TLV("HPOUT2 Volume", ARIZONA_OUTPUT_PATH_CONFIG_2L,
                       ARIZONA_OUTPUT_PATH_CONFIG_2R,
                       ARIZONA_OUT2L_PGA_VOL_SHIFT,
                       0x34, 0x40, 0, ana_tlv),
-SOC_DOUBLE_R_RANGE_TLV("OUT3 Volume", ARIZONA_OUTPUT_PATH_CONFIG_3L,
+SOC_DOUBLE_R_RANGE_TLV("HPOUT3 Volume", ARIZONA_OUTPUT_PATH_CONFIG_3L,
                       ARIZONA_OUTPUT_PATH_CONFIG_3R,
                       ARIZONA_OUT3L_PGA_VOL_SHIFT, 0x34, 0x40, 0, ana_tlv),
 
index ec0efc1..0e8b3aa 100644 (file)
@@ -1301,7 +1301,7 @@ static irqreturn_t wm8350_hpl_jack_handler(int irq, void *data)
        if (device_may_wakeup(wm8350->dev))
                pm_wakeup_event(wm8350->dev, 250);
 
-       schedule_delayed_work(&priv->hpl.work, 200);
+       schedule_delayed_work(&priv->hpl.work, msecs_to_jiffies(200));
 
        return IRQ_HANDLED;
 }
@@ -1318,7 +1318,7 @@ static irqreturn_t wm8350_hpr_jack_handler(int irq, void *data)
        if (device_may_wakeup(wm8350->dev))
                pm_wakeup_event(wm8350->dev, 250);
 
-       schedule_delayed_work(&priv->hpr.work, 200);
+       schedule_delayed_work(&priv->hpr.work, msecs_to_jiffies(200));
 
        return IRQ_HANDLED;
 }
index 9bb9273..a64b934 100644 (file)
@@ -53,8 +53,8 @@
  * using 2 wire for device control, so we cache them instead.
  */
 static const struct reg_default wm8960_reg_defaults[] = {
-       {  0x0, 0x0097 },
-       {  0x1, 0x0097 },
+       {  0x0, 0x00a7 },
+       {  0x1, 0x00a7 },
        {  0x2, 0x0000 },
        {  0x3, 0x0000 },
        {  0x4, 0x0000 },
@@ -323,8 +323,8 @@ SND_SOC_DAPM_MIXER("Left Input Mixer", WM8960_POWER3, 5, 0,
 SND_SOC_DAPM_MIXER("Right Input Mixer", WM8960_POWER3, 4, 0,
                   wm8960_rin, ARRAY_SIZE(wm8960_rin)),
 
-SND_SOC_DAPM_ADC("Left ADC", "Capture", WM8960_POWER2, 3, 0),
-SND_SOC_DAPM_ADC("Right ADC", "Capture", WM8960_POWER2, 2, 0),
+SND_SOC_DAPM_ADC("Left ADC", "Capture", WM8960_POWER1, 3, 0),
+SND_SOC_DAPM_ADC("Right ADC", "Capture", WM8960_POWER1, 2, 0),
 
 SND_SOC_DAPM_DAC("Left DAC", "Playback", WM8960_POWER2, 8, 0),
 SND_SOC_DAPM_DAC("Right DAC", "Playback", WM8960_POWER2, 7, 0),
index c27069d..7299587 100644 (file)
 
 #define TEGRA20_I2S_TIMING_NON_SYM_ENABLE              (1 << 12)
 #define TEGRA20_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT     0
-#define TEGRA20_I2S_TIMING_CHANNEL_BIT_COUNT_MASK_US   0x7fff
+#define TEGRA20_I2S_TIMING_CHANNEL_BIT_COUNT_MASK_US   0x7ff
 #define TEGRA20_I2S_TIMING_CHANNEL_BIT_COUNT_MASK      (TEGRA20_I2S_TIMING_CHANNEL_BIT_COUNT_MASK_US << TEGRA20_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT)
 
 /* Fields in TEGRA20_I2S_FIFO_SCR */
index 34dc47b..a294d94 100644 (file)
 
 #define TEGRA30_I2S_TIMING_NON_SYM_ENABLE              (1 << 12)
 #define TEGRA30_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT     0
-#define TEGRA30_I2S_TIMING_CHANNEL_BIT_COUNT_MASK_US   0x7fff
+#define TEGRA30_I2S_TIMING_CHANNEL_BIT_COUNT_MASK_US   0x7ff
 #define TEGRA30_I2S_TIMING_CHANNEL_BIT_COUNT_MASK      (TEGRA30_I2S_TIMING_CHANNEL_BIT_COUNT_MASK_US << TEGRA30_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT)
 
 /* Fields in TEGRA30_I2S_OFFSET */
index 803953a..2da8ad7 100644 (file)
@@ -244,6 +244,21 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif)
                        usb_ifnum_to_if(dev, ctrlif)->intf_assoc;
 
                if (!assoc) {
+                       /*
+                        * Firmware writers cannot count to three.  So to find
+                        * the IAD on the NuForce UDH-100, also check the next
+                        * interface.
+                        */
+                       struct usb_interface *iface =
+                               usb_ifnum_to_if(dev, ctrlif + 1);
+                       if (iface &&
+                           iface->intf_assoc &&
+                           iface->intf_assoc->bFunctionClass == USB_CLASS_AUDIO &&
+                           iface->intf_assoc->bFunctionProtocol == UAC_VERSION_2)
+                               assoc = iface->intf_assoc;
+               }
+
+               if (!assoc) {
                        snd_printk(KERN_ERR "Audio class v2 interfaces need an interface association\n");
                        return -EINVAL;
                }
index 880cdd5..77edcdc 100644 (file)
@@ -125,6 +125,63 @@ test_open_unlink()
        ./open-unlink $file
 }
 
+# test that we can create a range of filenames
+test_valid_filenames()
+{
+       local attrs='\x07\x00\x00\x00'
+       local ret=0
+
+       local file_list="abc dump-type0-11-1-1362436005 1234 -"
+       for f in $file_list; do
+               local file=$efivarfs_mount/$f-$test_guid
+
+               printf "$attrs\x00" > $file
+
+               if [ ! -e $file ]; then
+                       echo "$file could not be created" >&2
+                       ret=1
+               else
+                       rm $file
+               fi
+       done
+
+       exit $ret
+}
+
+test_invalid_filenames()
+{
+       local attrs='\x07\x00\x00\x00'
+       local ret=0
+
+       local file_list="
+               -1234-1234-1234-123456789abc
+               foo
+               foo-bar
+               -foo-
+               foo-barbazba-foob-foob-foob-foobarbazfoo
+               foo-------------------------------------
+               -12345678-1234-1234-1234-123456789abc
+               a-12345678=1234-1234-1234-123456789abc
+               a-12345678-1234=1234-1234-123456789abc
+               a-12345678-1234-1234=1234-123456789abc
+               a-12345678-1234-1234-1234=123456789abc
+               1112345678-1234-1234-1234-123456789abc"
+
+       for f in $file_list; do
+               local file=$efivarfs_mount/$f
+
+               printf "$attrs\x00" 2>/dev/null > $file
+
+               if [ -e $file ]; then
+                       echo "Creating $file should have failed" >&2
+                       rm $file
+                       ret=1
+               fi
+       done
+
+       exit $ret
+}
+
 check_prereqs
 
 rc=0
@@ -135,5 +192,7 @@ run_test test_create_read
 run_test test_delete
 run_test test_zero_size_delete
 run_test test_open_unlink
+run_test test_valid_filenames
+run_test test_invalid_filenames
 
 exit $rc
index 8674b9e..fe1e66b 100644 (file)
@@ -38,7 +38,7 @@
 #include <unistd.h>
 #include <tools/le_byteshift.h>
 
-#include "../../include/linux/usb/functionfs.h"
+#include "../../include/uapi/linux/usb/functionfs.h"
 
 
 /******************** Little Endian Handling ********************************/